mirror of
https://github.com/electron/electron.git
synced 2026-05-02 03:00:22 -04:00
Compare commits
163 Commits
fix/autofi
...
v42.0.0-be
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
b38c88664e | ||
|
|
687bd0a1f0 | ||
|
|
9d194e28ab | ||
|
|
b6de8acc8a | ||
|
|
b51e62e560 | ||
|
|
f1958d838c | ||
|
|
8b2dba3726 | ||
|
|
4ac50292d5 | ||
|
|
81e76165ae | ||
|
|
acf615229d | ||
|
|
d5cea60ac7 | ||
|
|
60ec7cd0fb | ||
|
|
3d7d676bee | ||
|
|
c5b0ee8a9b | ||
|
|
3ea2c9c760 | ||
|
|
067fe3d1f1 | ||
|
|
75a7ebc7c0 | ||
|
|
64055f27e7 | ||
|
|
09156151c4 | ||
|
|
b07503d468 | ||
|
|
ef664710a0 | ||
|
|
61954b457b | ||
|
|
b9c4e815ef | ||
|
|
48cc1126bd | ||
|
|
d146c4f019 | ||
|
|
5f3c30b8e5 | ||
|
|
1a67d03b0b | ||
|
|
043377523a | ||
|
|
d1c3b41f24 | ||
|
|
3bde2f38a8 | ||
|
|
c39e3d5687 | ||
|
|
316351f673 | ||
|
|
ad5b435f43 | ||
|
|
9c1e9e0237 | ||
|
|
844bbf8484 | ||
|
|
a9f2f95d64 | ||
|
|
30cf3882de | ||
|
|
ec57a84297 | ||
|
|
a078ed77c5 | ||
|
|
10fb5b39c5 | ||
|
|
4bd7aa8d98 | ||
|
|
70a321634c | ||
|
|
aa7a81deb9 | ||
|
|
9ecc0670fe | ||
|
|
4affacb4e1 | ||
|
|
63d2c9c9d1 | ||
|
|
3c8256cdcc | ||
|
|
6e035d36e1 | ||
|
|
45bc6435ce | ||
|
|
b0b7a70f69 | ||
|
|
64554bcc13 | ||
|
|
5c1bb7126d | ||
|
|
3087643c9c | ||
|
|
8e5e775e84 | ||
|
|
2a1790e0ef | ||
|
|
be93d72e82 | ||
|
|
4cc29c25e5 | ||
|
|
acdabe464e | ||
|
|
d74660fb3a | ||
|
|
b8daf0b57d | ||
|
|
95af3a7e78 | ||
|
|
1b5f3ea40e | ||
|
|
eb19030912 | ||
|
|
bc02cdf5b3 | ||
|
|
f9de33b79f | ||
|
|
670b87c7ee | ||
|
|
c4addb7f13 | ||
|
|
a0f9ff4cc0 | ||
|
|
b31c3efb29 | ||
|
|
4604c78c88 | ||
|
|
7bd5de006e | ||
|
|
b861998db0 | ||
|
|
786bf64a09 | ||
|
|
32fd562a6f | ||
|
|
8bca9a0a7c | ||
|
|
e258e0735d | ||
|
|
7e84164ed9 | ||
|
|
1e43451d08 | ||
|
|
a0f042f8d3 | ||
|
|
b5fdb985f5 | ||
|
|
487c29b3e2 | ||
|
|
b5f2375eb6 | ||
|
|
0d74dce4ee | ||
|
|
7e09a452a8 | ||
|
|
fd717ad03e | ||
|
|
3cb947d1b9 | ||
|
|
1f167f66f2 | ||
|
|
6fc19a017f | ||
|
|
cba85c0983 | ||
|
|
2067d3a414 | ||
|
|
d298f4be88 | ||
|
|
be53e0a470 | ||
|
|
5b6b1c1641 | ||
|
|
1f51bf66fb | ||
|
|
1686aa37f2 | ||
|
|
ef8c983ccb | ||
|
|
28f46a967e | ||
|
|
04614eed17 | ||
|
|
964cf07e19 | ||
|
|
cd495e20a7 | ||
|
|
d73eaf83f5 | ||
|
|
65f97115f1 | ||
|
|
3aa89f7ff1 | ||
|
|
efb7477305 | ||
|
|
4323fa4b06 | ||
|
|
5c61e826c8 | ||
|
|
bba4374952 | ||
|
|
eb80b7c889 | ||
|
|
199588ff02 | ||
|
|
510576fcd7 | ||
|
|
0c09677949 | ||
|
|
7356c75ca3 | ||
|
|
e1e3ecee75 | ||
|
|
d1b34d76a8 | ||
|
|
d456259da4 | ||
|
|
e21a1b8cd1 | ||
|
|
7f8e35c8c8 | ||
|
|
2da7d8dadb | ||
|
|
d2e0d19985 | ||
|
|
d074963b30 | ||
|
|
ef7f35e15c | ||
|
|
5559ffa184 | ||
|
|
4ede07538d | ||
|
|
b310e26059 | ||
|
|
ad4dc5045f | ||
|
|
a45f5dbcba | ||
|
|
ba46942463 | ||
|
|
602119ea25 | ||
|
|
8f0f8401f2 | ||
|
|
f90dd8d6bd | ||
|
|
6dfb19210b | ||
|
|
119127b23a | ||
|
|
a806e3890f | ||
|
|
e48835e4e0 | ||
|
|
7dfd55b8ea | ||
|
|
e02471eba0 | ||
|
|
83615377dc | ||
|
|
f8eb1b2a31 | ||
|
|
d23fbd5c71 | ||
|
|
e7d473337f | ||
|
|
1766e229eb | ||
|
|
0d0a58cbd4 | ||
|
|
99a6230d6b | ||
|
|
49a9efa764 | ||
|
|
1b080d4097 | ||
|
|
191f673246 | ||
|
|
636e0e26f3 | ||
|
|
a7744df592 | ||
|
|
b0d5b63477 | ||
|
|
0f54cb1d8b | ||
|
|
4ed6809aaa | ||
|
|
44ebbc11ed | ||
|
|
d1b5d7c9ed | ||
|
|
d5ac7d3f33 | ||
|
|
17ddcbf01f | ||
|
|
3b3e1e8ef6 | ||
|
|
045516d598 | ||
|
|
1fffaeb481 | ||
|
|
88e666f210 | ||
|
|
90f7796adb | ||
|
|
e6925bef1f | ||
|
|
6a5e9fe677 | ||
|
|
270c9e7ce9 |
@@ -11,6 +11,7 @@
|
||||
"Bash(e patches:*)",
|
||||
"Bash(e sync:*)",
|
||||
"Skill(electron-chromium-upgrade)",
|
||||
"Skill(electron-node-upgrade)",
|
||||
"Read(*)",
|
||||
"Bash(echo:*)",
|
||||
"Bash(e build:*)",
|
||||
|
||||
205
.claude/skills/electron-node-upgrade/SKILL.md
Normal file
205
.claude/skills/electron-node-upgrade/SKILL.md
Normal file
@@ -0,0 +1,205 @@
|
||||
---
|
||||
name: electron-node-upgrade
|
||||
description: Guide for performing Node.js version upgrades in the Electron project. Use when working on the roller/node/main branch to fix patch conflicts during `e sync --3`. Covers the patch application workflow, conflict resolution, analyzing upstream Node.js changes, and proper commit formatting for patch fixes.
|
||||
---
|
||||
|
||||
# Electron Node.js Upgrade: Phase One
|
||||
|
||||
## Summary
|
||||
|
||||
Run `e sync --3` repeatedly, fixing patch conflicts as they arise, until it succeeds. Then export patches and commit changes atomically.
|
||||
|
||||
## Success Criteria
|
||||
|
||||
Phase One is complete when:
|
||||
- `e sync --3` exits with code 0 (no patch failures)
|
||||
- All changes are committed per the commit guidelines
|
||||
|
||||
Do not stop until these criteria are met.
|
||||
|
||||
**CRITICAL** Do not delete or skip patches unless 100% certain the patch is no longer needed. For major version upgrades, patches that shim deprecated V8 APIs or backport upstream changes are often deletable because the new Node.js version already incorporates them — but verify before removing. Complicated conflicts or hard to resolve issues should be presented to the user after you have exhausted all other options. Do not delete the patch just because you can't solve it.
|
||||
|
||||
**CRITICAL** Never use `git am --skip` and then manually recreate a patch by making a new commit. This destroys the original patch's authorship, commit message, and position in the series. If `git am --continue` reports "No changes", investigate why — the changes were likely absorbed by a prior conflict resolution's 3-way merge. Present this situation to the user rather than skipping and recreating.
|
||||
|
||||
## Context
|
||||
|
||||
The `roller/node/main` branch is created by automation to update Electron's Node.js dependency version in `DEPS`. No work has been done to handle breaking changes between the old and new versions.
|
||||
|
||||
There are two types of Node.js version updates:
|
||||
- **Bumps** (patch/minor): Automated by `electron-roller[bot]` with commit title `chore: bump node to v{version}`. Trivial patch index updates are handled automatically by `patchup[bot]`. These often land cleanly, but may require manual patch fixes.
|
||||
- **Major upgrades** (e.g., v22 → v24): Manual, large PRs with commit title `chore: upgrade Node.js to v{X}.{Y}.{Z}`. These typically involve deleting obsolete patches, adapting many others, and updating `@types/node` in `package.json`.
|
||||
|
||||
**Key directories:**
|
||||
- Current directory: Electron repo (always run `e` commands here)
|
||||
- `../third_party/electron_node`: Node.js repo (where patches apply)
|
||||
- `patches/node/`: Patch files for Node.js
|
||||
- `docs/development/patches.md`: Patch system documentation
|
||||
|
||||
## Pre-flight Checks
|
||||
|
||||
Run these once at the start of each upgrade session:
|
||||
|
||||
1. **Clear rerere cache** (if enabled): `git rerere clear` in both the electron and `../third_party/electron_node` repos. Stale recorded resolutions from a prior attempt can silently apply wrong merges.
|
||||
2. **Ensure pre-commit hooks are installed**: Check that `.git/hooks/pre-commit` exists. If not, run `yarn husky` to install it. The hook runs `lint-staged` which handles clang-format for C++ files.
|
||||
|
||||
## Workflow
|
||||
|
||||
1. Run `e sync --3` (the `--3` flag enables 3-way merge, always required)
|
||||
2. If succeeds → skip to step 5
|
||||
3. If patch fails:
|
||||
- Identify target repo and patch from error output
|
||||
- Analyze failure (see references/patch-analysis.md)
|
||||
- Fix conflict in `../third_party/electron_node` working directory
|
||||
- Run `git am --continue` in `../third_party/electron_node`
|
||||
- Repeat until all patches for that repo apply
|
||||
- IMPORTANT: Once `git am --continue` succeeds you MUST run `e patches node` to export fixes
|
||||
- Return to step 1
|
||||
4. When `e sync --3` succeeds, run `e patches all`
|
||||
5. **Read `references/phase-one-commit-guidelines.md` NOW**, then commit changes following those instructions exactly.
|
||||
|
||||
## Commands Reference
|
||||
|
||||
| Command | Purpose |
|
||||
|---------|---------|
|
||||
| `e sync --3` | Clone deps and apply patches with 3-way merge |
|
||||
| `git am --continue` | Continue after resolving conflict (run in node repo) |
|
||||
| `e patches node` | Export commits from node repo to patch files |
|
||||
| `e patches all` | Export all patches from all targets |
|
||||
| `e patches node --commit-updates` | Export patches and auto-commit trivial changes |
|
||||
| `e patches --list-targets` | List targets and config paths |
|
||||
|
||||
## Patch System Mental Model
|
||||
|
||||
```
|
||||
patches/node/*.patch → [e sync --3] → ../third_party/electron_node commits
|
||||
← [e patches] ←
|
||||
```
|
||||
|
||||
## When to Edit Patches
|
||||
|
||||
| Situation | Action |
|
||||
|-----------|--------|
|
||||
| During active `git am` conflict | Fix in node repo, then `git am --continue` |
|
||||
| Modifying patch outside conflict | Edit `.patch` file directly |
|
||||
| Creating new patch (rare, avoid) | Commit in node repo, then `e patches node` |
|
||||
|
||||
Fix existing patches 99% of the time rather than creating new ones.
|
||||
|
||||
## Patch Fixing Rules
|
||||
|
||||
1. **Preserve authorship**: Keep original author in TODO comments (from patch `From:` field)
|
||||
2. **Never change TODO assignees**: `TODO(name)` must retain original name
|
||||
3. **Update descriptions**: If upstream changed APIs or macros, update patch commit message to reflect current state
|
||||
4. **Never skip-and-recreate a patch**: If `git am --continue` says "No changes — did you forget to use 'git add'?", do NOT run `git am --skip` and create a replacement commit. The patch's changes were already absorbed by a prior 3-way merge resolution. This means an earlier conflict resolution pulled in too many changes. Present the situation to the user for guidance — the correct fix may require re-doing an earlier resolution more carefully to keep each patch's changes separate.
|
||||
|
||||
# Electron Node.js Upgrade: Phase Two
|
||||
|
||||
## Summary
|
||||
|
||||
Run `e build -k 999 -- --quiet` repeatedly, fixing build issues as they arise, until it succeeds. Then run `e start --version` to validate Electron launches and commit changes atomically.
|
||||
|
||||
Run Phase Two immediately after Phase One is complete.
|
||||
|
||||
## Success Criteria
|
||||
|
||||
Phase Two is complete when:
|
||||
- `e build -k 999 -- --quiet` exits with code 0 (no build failures)
|
||||
- `e start --version` has been run to check Electron launches
|
||||
- All changes are committed per the commit guidelines
|
||||
|
||||
Do not stop until these criteria are met. Do not delete code or features, never comment out code in order to take short cut. Make all existing code, logic and intention work.
|
||||
|
||||
## Context
|
||||
|
||||
The `roller/node/main` branch is created by automation to update Electron's Node.js dependency version in `DEPS`. No work has been done to handle breaking changes between the old and new versions. Node.js APIs (especially internal V8 integration, OpenSSL/BoringSSL compatibility, and build system files) frequently change between versions. In every case the code in Electron must be updated to account for the change in Node.js, strongly avoid making changes to the code in Node.js to fix Electron's build.
|
||||
|
||||
**Key directories:**
|
||||
- Current directory: Electron repo (always run `e` commands here)
|
||||
- `../third_party/electron_node`: Node.js repo (do not touch this code to fix build issues, just read it to obtain context)
|
||||
|
||||
## Workflow
|
||||
|
||||
1. Run `e build -k 999 -- --quiet` (the `--quiet` flag suppresses per-target status lines, showing only errors and the final result)
|
||||
2. If succeeds → skip to step 6
|
||||
3. If build fails:
|
||||
- Identify underlying file in "electron" from the compilation error message
|
||||
- Analyze failure
|
||||
- Fix build issue by adapting Electron's code for the change in Node.js
|
||||
- Run `e build -t {target_that_failed}.o` to build just the failed target we were specifically fixing
|
||||
- You can identify the target_that_failed from the failure line in the build log. E.g. `FAILED: 2e506007-8d5d-4f38-bdd1-b5cd77999a77 "./obj/electron/shell/browser/api/electron_api_utility_process.o" CXX obj/electron/shell/browser/api/electron_api_utility_process.o` the target name is `obj/electron/shell/browser/api/electron_api_utility_process.o`
|
||||
- **Read `references/phase-two-commit-guidelines.md` NOW**, then commit changes following those instructions exactly.
|
||||
- Return to step 1
|
||||
4. **CRITICAL**: After ANY commit (especially patch commits), immediately run `git status` in the electron repo
|
||||
- Look for other modified `.patch` files that only have index/hunk header changes
|
||||
- These are dependent patches affected by your fix
|
||||
- Commit them immediately with: `git commit -am "chore: update patches (trivial only)"`
|
||||
5. Return to step 1
|
||||
6. When `e build` succeeds, run `e start --version`
|
||||
7. Check if you have any pending changes in the Node.js repo by running `git status` in `../third_party/electron_node`
|
||||
- If you have changes follow the instructions below in "A. Patch Fixes" to correctly commit those modifications into the appropriate patch file
|
||||
|
||||
## Commands Reference
|
||||
|
||||
| Command | Purpose |
|
||||
|---------|---------|
|
||||
| `e build -k 999 -- --quiet` | Build Electron, continue on errors, suppress status lines |
|
||||
| `e build -t {target}.o` | Build just one specific target to verify a fix |
|
||||
| `e start --version` | Validate Electron launches after successful build |
|
||||
|
||||
## Two Types of Build Fixes
|
||||
|
||||
### A. Patch Fixes (for files in patched Node.js files)
|
||||
|
||||
When the error is in a file that Electron patches (check with `grep -l "filename" patches/node/*.patch`):
|
||||
|
||||
1. Edit the file in the Node.js source tree (`../third_party/electron_node/...`)
|
||||
2. Create a fixup commit targeting the original patch commit:
|
||||
```bash
|
||||
cd ../third_party/electron_node
|
||||
git add <modified-file>
|
||||
git commit --fixup=<original-patch-commit-hash>
|
||||
GIT_SEQUENCE_EDITOR=: git rebase --autosquash --autostash -i <commit>^
|
||||
```
|
||||
3. Export the updated patch: `e patches node`
|
||||
4. Commit the updated patch file following `references/phase-one-commit-guidelines.md`.
|
||||
|
||||
To find the original patch commit to fixup: `git log --oneline | grep -i "keyword from patch name"`
|
||||
|
||||
The base commit for rebase is the Node.js commit before patches were applied. Find it by checking the `refs/patches/upstream-head` ref.
|
||||
|
||||
### B. Electron Code Fixes (for files in shell/, electron/, etc.)
|
||||
|
||||
When the error is in Electron's own source code:
|
||||
|
||||
1. Edit files directly in the electron repo
|
||||
2. Commit directly (no patch export needed)
|
||||
|
||||
# Critical: Read Before Committing
|
||||
|
||||
- Before ANY Phase One commits: Read `references/phase-one-commit-guidelines.md`
|
||||
- Before ANY Phase Two commits: Read `references/phase-two-commit-guidelines.md`
|
||||
|
||||
# High-Churn Patches
|
||||
|
||||
These patches consistently require the most work during Node.js upgrades:
|
||||
|
||||
- **`fix_handle_boringssl_and_openssl_incompatibilities.patch`** — Electron uses BoringSSL (via Chromium) while Node.js expects OpenSSL. This patch is large and complex, and upstream OpenSSL API changes frequently break it.
|
||||
- **`fix_crypto_tests_to_run_with_bssl.patch`** — Companion to the above; adapts Node.js crypto tests for BoringSSL. Can grow significantly during major upgrades.
|
||||
- **`support_v8_sandboxed_pointers.patch`** — V8 sandbox pointer support requires careful adaptation when V8 APIs change.
|
||||
- **`build_add_gn_build_files.patch`** — The GN build file patch is large and touches many build targets. Upstream build system changes frequently conflict.
|
||||
|
||||
# Major Version Upgrades
|
||||
|
||||
Major Node.js version transitions (e.g., v22 → v24) are significantly more involved than patch bumps:
|
||||
|
||||
1. **Expect patch deletions.** Electron uses Chromium's V8, which is often ahead of the V8 version bundled in Node.js. Many patches exist to bridge this gap — shimming newer V8 APIs that Chromium's V8 has but Node.js' older V8 doesn't. When Node.js bumps to a newer major version, its V8 catches up to Chromium's, and those bridge patches can be deleted. In the v22 → v24 upgrade, 17 patches were deleted for this reason.
|
||||
2. **Update `@types/node`** in `package.json` to match the new major version.
|
||||
3. **Post-upgrade regressions are expected.** Even after the upgrade lands, follow-up fix PRs for edge cases (ESM path handling, certificate loading, platform-specific issues) are normal.
|
||||
|
||||
# Skill Directory Structure
|
||||
This skill has additional reference files in `references/`:
|
||||
- patch-analysis.md - How to analyze patch failures
|
||||
- phase-one-commit-guidelines.md - Commit format for Phase One
|
||||
- phase-two-commit-guidelines.md - Commit format for Phase Two
|
||||
|
||||
Read these when referenced in the workflow steps.
|
||||
@@ -0,0 +1,112 @@
|
||||
# Analyzing Patch Failures
|
||||
|
||||
## Investigation Steps
|
||||
|
||||
1. **Read the patch file** at `patches/node/{patch_name}.patch`
|
||||
|
||||
2. **Examine current state** of the file in the Node.js repo at mentioned line numbers
|
||||
|
||||
3. **Check recent upstream changes:**
|
||||
```bash
|
||||
cd ../third_party/electron_node
|
||||
git log --oneline -10 -- {file}
|
||||
```
|
||||
|
||||
4. **Find Node.js PR** in commit messages:
|
||||
```
|
||||
PR-URL: https://github.com/nodejs/node/pull/{PR_NUMBER}
|
||||
```
|
||||
|
||||
## Critical: Resolve by Intent, Not by Mechanical Merge
|
||||
|
||||
When resolving a patch conflict, do NOT blindly preserve the patch's old code. Instead:
|
||||
|
||||
1. **Understand the upstream commit's full scope** — not just the conflicting hunk.
|
||||
Run `git show <commit> --stat` and read diffs for all affected files.
|
||||
Upstream may have removed structs, members, or methods that the patch
|
||||
references in other hunks or files.
|
||||
|
||||
2. **Re-read the patch commit message** to understand its *intent* — what
|
||||
behavior does it need to preserve or add?
|
||||
|
||||
3. **Implement the intent against the new upstream code.** If the patch's
|
||||
purpose is "add BoringSSL compatibility", add only the compatibility
|
||||
layer — don't also restore old code that upstream separately removed.
|
||||
|
||||
### Lesson: Upstream Removals Break Patch References
|
||||
|
||||
- **Trigger:** Patch conflict involves an upstream refactor (not just context drift)
|
||||
- **Strategy:** After identifying the upstream commit, check its full diff for
|
||||
removed types, members, and methods. If the patch's old code references
|
||||
something removed, the resolution must use the new upstream mechanism.
|
||||
|
||||
### Lesson: Separate Patch Purpose from Patch Implementation
|
||||
|
||||
- **Trigger:** Conflict between "upstream simplified code" vs "patch has older code"
|
||||
- **Strategy:** Identify the *minimal* change the patch needs. If the patch
|
||||
wraps code in a conditional, only add the conditional — don't restore old
|
||||
code that was inside the conditional but was separately cleaned up upstream.
|
||||
|
||||
### Lesson: Finish the Adaptation at Conflict Time
|
||||
|
||||
- **Trigger:** A patch conflict involves an upstream API removal or replacement
|
||||
- **Strategy:** When resolving the conflict, fully adapt the patch to use the
|
||||
new API in the same commit. Don't remove the old code and leave behind stale
|
||||
references that will "be fixed in Phase Two." Each patch fix commit should be
|
||||
a complete resolution.
|
||||
|
||||
## Common Failure Patterns
|
||||
|
||||
| Pattern | Cause | Solution |
|
||||
|---------|-------|----------|
|
||||
| Context lines don't match | Surrounding code changed | Update context in patch |
|
||||
| File not found | File renamed/moved | Update patch target path |
|
||||
| Function not found | Refactored upstream | Find new function name |
|
||||
| OpenSSL → BoringSSL mismatch | Crypto API change | Update to BoringSSL-compatible API |
|
||||
| GYP/GN build change | Build system refactor | Adapt build patch to new structure |
|
||||
| Deleted code | Feature removed | Verify patch still needed |
|
||||
| V8 API bridge patch conflicts | Node.js caught up to Chromium's V8 | Patch may be deletable — verify the API is now in Node.js' V8 natively |
|
||||
|
||||
## Using Git Blame
|
||||
|
||||
To find the commit that changed specific lines:
|
||||
|
||||
```bash
|
||||
cd ../third_party/electron_node
|
||||
git blame -L {start},{end} -- {file}
|
||||
git log -1 {commit_sha} # Look for PR-URL: line
|
||||
```
|
||||
|
||||
## Verifying Patch Necessity
|
||||
|
||||
Before deleting a patch, verify:
|
||||
1. The patched functionality was intentionally removed upstream
|
||||
2. Electron doesn't need the patch for other reasons
|
||||
3. No other code depends on the patched behavior
|
||||
|
||||
**V8 bridge patches:** Electron uses Chromium's V8, which is often ahead of the V8 bundled in Node.js. Many patches exist to bridge this version gap — adapting Node.js code to work with newer V8 APIs that Chromium's V8 exposes. During major Node.js upgrades, Node.js' V8 catches up to Chromium's, and these bridge patches often become unnecessary. Check whether the API the patch shims is now available natively in the new Node.js version's V8.
|
||||
|
||||
When in doubt, keep the patch and adapt it.
|
||||
|
||||
## Phase Two: Build-Time Patch Issues
|
||||
|
||||
Sometimes patches that applied successfully in Phase One cause build errors in Phase Two. This can happen when:
|
||||
|
||||
1. **Incomplete types**: A patch disables a header include, but new upstream code uses the type
|
||||
2. **Missing members**: A patch modifies a class, but upstream added new code referencing the original
|
||||
|
||||
### Finding Which Patch Affects a File
|
||||
|
||||
```bash
|
||||
grep -l "filename.cc" patches/node/*.patch
|
||||
```
|
||||
|
||||
### Matching Existing Patch Patterns
|
||||
|
||||
When fixing build errors in patched files, examine the existing patch to understand its style:
|
||||
- Does it use `#if 0` / `#endif` guards?
|
||||
- Does it use `#if BUILDFLAG(...)` conditionals?
|
||||
- Does it use `#ifndef` / `#ifdef` guards for BoringSSL vs OpenSSL?
|
||||
- What's the pattern for disabled functionality?
|
||||
|
||||
Apply fixes consistent with the existing patch style.
|
||||
@@ -0,0 +1,111 @@
|
||||
# Phase One Commit Guidelines
|
||||
|
||||
Only follow these instructions if there are uncommitted changes to `patches/` after Phase One succeeds.
|
||||
|
||||
Ignore other instructions about making commit messages, our guidelines are CRITICALLY IMPORTANT and must be followed.
|
||||
|
||||
## Each Commit Must Be Complete
|
||||
|
||||
When resolving a patch conflict, fully adapt the patch to the new upstream code in the same commit. If the upstream change removes an API the patch uses, update the patch to use the replacement API now — don't leave stale references knowing they'll need fixing later. The goal is that each commit represents a finished resolution, not a partial one that defers known work to a future phase.
|
||||
|
||||
## Commit Message Style
|
||||
|
||||
**Titles** follow the 60/80-character guideline: simple changes fit within 60 characters, otherwise the limit is 80 characters.
|
||||
|
||||
Always include a `Co-Authored-By` trailer identifying the AI model that assisted (e.g., `Co-Authored-By: <AI model attribution>`).
|
||||
|
||||
### Patch conflict fixes
|
||||
|
||||
Use `fix(patch):` prefix. The title should name the upstream change, not your response to it:
|
||||
|
||||
```
|
||||
fix(patch): {topic headline}
|
||||
|
||||
Ref: {Node.js commit or issue link}
|
||||
|
||||
Co-Authored-By: <AI model attribution>
|
||||
```
|
||||
|
||||
Only add a description body if it provides clarity beyond the title. For straightforward context drift or simple API renames, the title + Ref is sufficient.
|
||||
|
||||
Examples:
|
||||
- `fix(patch): stop using v8::PropertyCallbackInfo<T>::This()`
|
||||
- `fix(patch): BoringSSL and OpenSSL incompatibilities`
|
||||
- `fix(patch): refactor module_wrap.cc FixedArray::Get params`
|
||||
|
||||
### Upstreamed patch removal
|
||||
|
||||
When patches are no longer needed (applied cleanly with "already applied" or confirmed upstreamed), group ALL removals into a single commit:
|
||||
|
||||
```
|
||||
chore: remove upstreamed patch
|
||||
```
|
||||
|
||||
or (if multiple):
|
||||
|
||||
```
|
||||
chore: remove upstreamed patches
|
||||
```
|
||||
|
||||
Most Node.js patches in Electron are Electron-authored (no upstream `PR-URL:`). If the patch originated from an upstream Node.js PR, no extra `Ref:` is needed. Otherwise, add a `Ref:` pointing to the relevant Node.js issue or commit if one exists.
|
||||
|
||||
### Trivial patch updates
|
||||
|
||||
After all fix commits, stage remaining trivial changes (index, line numbers, context only):
|
||||
|
||||
```bash
|
||||
git add patches
|
||||
git commit -m "chore: update patches (trivial only)"
|
||||
```
|
||||
|
||||
**Conflict resolution can produce trivial results.** A `git am` conflict doesn't always mean the patch content changed — context drift alone can cause a conflict. After resolving and exporting, inspect the patch diff: if only index hashes, line numbers, and context lines changed (not the patch's own `+`/`-` lines), it's trivial and belongs here, not in a `fix(patch):` commit.
|
||||
|
||||
## Atomic Commits
|
||||
|
||||
Each patch conflict fix gets its own commit with its own Ref.
|
||||
|
||||
IMPORTANT: Try really hard to find the PR or commit reference per the instructions below. Each change you made should in theory have been in response to a change made in Node.js that you identified or can identify. Try for a while to identify and include the ref in the commit message. Do not give up easily.
|
||||
|
||||
## Finding Commit/Issue References
|
||||
|
||||
Use `git log` or `git blame` on Node.js source files in `../third_party/electron_node`. Look for:
|
||||
|
||||
```
|
||||
PR-URL: https://github.com/nodejs/node/pull/XXXXX
|
||||
```
|
||||
|
||||
or issue references in the patch itself:
|
||||
|
||||
```
|
||||
Refs: https://github.com/nodejs/node/issues/XXXXX
|
||||
```
|
||||
|
||||
Note: Most Node.js patches in Electron are Electron-authored and won't have upstream references. In that case, check `git log` in the Node.js repo to find which upstream commit caused the conflict.
|
||||
|
||||
If no reference found after searching: `Ref: Unable to locate reference`
|
||||
|
||||
## Example Commits
|
||||
|
||||
### Patch conflict fix (simple — title is sufficient)
|
||||
|
||||
```
|
||||
fix(patch): stop using v8::PropertyCallbackInfo<T>::This()
|
||||
|
||||
Ref: https://github.com/nodejs/node/issues/60616
|
||||
|
||||
Co-Authored-By: <AI model attribution>
|
||||
```
|
||||
|
||||
### Patch conflict fix (complex — description adds value)
|
||||
|
||||
```
|
||||
fix(patch): BoringSSL and OpenSSL incompatibilities
|
||||
|
||||
Upstream updated OpenSSL APIs that diverge from BoringSSL. Adapted
|
||||
the compatibility shims in crypto patches to use the BoringSSL
|
||||
equivalents.
|
||||
|
||||
Ref: Unable to locate reference
|
||||
|
||||
Co-Authored-By: <AI model attribution>
|
||||
```
|
||||
@@ -0,0 +1,96 @@
|
||||
# Phase Two Commit Guidelines
|
||||
|
||||
Only follow these instructions if there are uncommitted changes in the Electron repo after any fixes are made during Phase Two that result a target that was failing, successfully building.
|
||||
|
||||
Ignore other instructions about making commit messages, our guidelines are CRITICALLY IMPORTANT and must be followed.
|
||||
|
||||
## Commit Message Style
|
||||
|
||||
**Titles** follow the 60/80-character guideline: simple changes fit within 60 characters, otherwise the limit is 80 characters. Exception: upstream Node.js PR titles are used verbatim even if longer.
|
||||
|
||||
Always include a `Co-Authored-By` trailer identifying the AI model that assisted (e.g., `Co-Authored-By: <AI model attribution>`).
|
||||
|
||||
## Two Commit Types
|
||||
|
||||
### For Electron Source Changes (shell/, electron/, etc.)
|
||||
|
||||
When the upstream Node.js commit has a `PR-URL:`:
|
||||
|
||||
```
|
||||
node#{PR-Number}: {upstream PR's original title}
|
||||
|
||||
Ref: {Node.js PR link}
|
||||
|
||||
Co-Authored-By: <AI model attribution>
|
||||
```
|
||||
|
||||
When there is no `PR-URL:` but there is an issue reference or commit:
|
||||
|
||||
```
|
||||
fix: {description of the adaptation}
|
||||
|
||||
Ref: {Node.js issue or commit link}
|
||||
|
||||
Co-Authored-By: <AI model attribution>
|
||||
```
|
||||
|
||||
Use the **upstream commit's original title** when available — do not paraphrase or rewrite it. To find it: check the commit message in `../third_party/electron_node` for `PR-URL:` or `Refs:` lines.
|
||||
|
||||
Only add a description body if it provides clarity beyond what the title already says (e.g., when Electron's adaptation is non-obvious). For simple renames, method additions, or straightforward API updates, the title + Ref link is sufficient.
|
||||
|
||||
Each change should have its own commit and its own Ref. Logically group into commits that make sense rather than one giant commit. You may include multiple "Ref" links if required.
|
||||
|
||||
IMPORTANT: Try really hard to find a reference. Each change you made should in theory have been in response to a change in Node.js. Check `git log` and `git blame` in the Node.js repo. Do not give up easily.
|
||||
|
||||
### For Patch Updates (patches/node/*.patch)
|
||||
|
||||
Use the same fixup workflow as Phase One and follow `references/phase-one-commit-guidelines.md` for the commit message format (`fix(patch):` prefix, topic style).
|
||||
|
||||
## Dependent Patch Header Updates
|
||||
|
||||
After any patch modification, check for other affected patches:
|
||||
|
||||
```bash
|
||||
git status
|
||||
# If other .patch files show as modified with only index, line number, and context changes:
|
||||
git add patches/
|
||||
git commit -m "chore: update patches (trivial only)"
|
||||
```
|
||||
|
||||
## Finding References
|
||||
|
||||
Use `git log` or `git blame` on Node.js source files in `../third_party/electron_node`. Look for:
|
||||
|
||||
```
|
||||
PR-URL: https://github.com/nodejs/node/pull/XXXXX
|
||||
Refs: https://github.com/nodejs/node/issues/XXXXX
|
||||
```
|
||||
|
||||
Note: Many Node.js patches in Electron are Electron-authored and won't have upstream `PR-URL:` lines. Check the patch's own commit message for `Refs:` lines, or use `git log` in the Node.js repo to find which upstream commit caused the build break.
|
||||
|
||||
If no reference found after searching: `Ref: Unable to locate reference`
|
||||
|
||||
## Example Commits
|
||||
|
||||
### Electron Source Fix (with upstream PR)
|
||||
|
||||
```
|
||||
node#61898: src: stop using v8::PropertyCallbackInfo<T>::This()
|
||||
|
||||
Ref: https://github.com/nodejs/node/pull/61898
|
||||
|
||||
Co-Authored-By: <AI model attribution>
|
||||
```
|
||||
|
||||
### Electron Source Fix (with issue reference, no PR)
|
||||
|
||||
```
|
||||
fix: adapt to v8::PropertyCallbackInfo<T>::This() removal
|
||||
|
||||
Updated NodeBindings to use HolderV2() after upstream Node.js
|
||||
stopped using the deprecated This() API.
|
||||
|
||||
Ref: https://github.com/nodejs/node/issues/60616
|
||||
|
||||
Co-Authored-By: <AI model attribution>
|
||||
```
|
||||
@@ -35,7 +35,7 @@
|
||||
"ms-vscode.cpptools",
|
||||
"mutantdino.resourcemonitor",
|
||||
"dsanders11.vscode-electron-build-tools",
|
||||
"oxc.oxc-vscode",
|
||||
"dbaeumer.vscode-eslint",
|
||||
"shakram02.bash-beautify",
|
||||
"marshallofsound.gnls-electron"
|
||||
],
|
||||
|
||||
79
.eslintrc.json
Normal file
79
.eslintrc.json
Normal file
@@ -0,0 +1,79 @@
|
||||
{
|
||||
"root": true,
|
||||
"extends": "standard",
|
||||
"parser": "@typescript-eslint/parser",
|
||||
"plugins": ["@typescript-eslint"],
|
||||
"env": {
|
||||
"browser": true
|
||||
},
|
||||
"rules": {
|
||||
"semi": ["error", "always"],
|
||||
"no-var": "error",
|
||||
"no-unused-vars": "off",
|
||||
"guard-for-in": "error",
|
||||
"@typescript-eslint/no-unused-vars": ["error", {
|
||||
"vars": "all",
|
||||
"args": "after-used",
|
||||
"ignoreRestSiblings": true
|
||||
}],
|
||||
"prefer-const": ["error", {
|
||||
"destructuring": "all"
|
||||
}],
|
||||
"n/no-callback-literal": "off",
|
||||
"import/newline-after-import": "error",
|
||||
"import/order": ["error", {
|
||||
"alphabetize": {
|
||||
"order": "asc"
|
||||
},
|
||||
"newlines-between": "always",
|
||||
"pathGroups": [
|
||||
{
|
||||
"pattern": "@electron/internal/**",
|
||||
"group": "external",
|
||||
"position": "before"
|
||||
},
|
||||
{
|
||||
"pattern": "@electron/**",
|
||||
"group": "external",
|
||||
"position": "before"
|
||||
},
|
||||
{
|
||||
"pattern": "{electron,electron/**}",
|
||||
"group": "external",
|
||||
"position": "before"
|
||||
}
|
||||
],
|
||||
"pathGroupsExcludedImportTypes": [],
|
||||
"distinctGroup": true,
|
||||
"groups": [
|
||||
"external",
|
||||
"builtin",
|
||||
["sibling", "parent"],
|
||||
"index",
|
||||
"type"
|
||||
]
|
||||
}]
|
||||
},
|
||||
"parserOptions": {
|
||||
"ecmaVersion": 6,
|
||||
"sourceType": "module"
|
||||
},
|
||||
"overrides": [
|
||||
{
|
||||
"files": "*.ts",
|
||||
"rules": {
|
||||
"no-undef": "off",
|
||||
"no-redeclare": "off",
|
||||
"@typescript-eslint/no-redeclare": ["error"],
|
||||
"no-use-before-define": "off"
|
||||
}
|
||||
},
|
||||
{
|
||||
"files": "*.d.ts",
|
||||
"rules": {
|
||||
"no-useless-constructor": "off",
|
||||
"@typescript-eslint/no-unused-vars": "off"
|
||||
}
|
||||
}
|
||||
]
|
||||
}
|
||||
1
.github/CODEOWNERS
vendored
1
.github/CODEOWNERS
vendored
@@ -19,7 +19,6 @@ DEPS @electron/wg-upgrades
|
||||
/lib/renderer/security-warnings.ts @electron/wg-security
|
||||
|
||||
# Infra WG
|
||||
/.claude/ @electron/wg-infra
|
||||
/.github/actions/ @electron/wg-infra
|
||||
/.github/workflows/*-publish.yml @electron/wg-infra
|
||||
/.github/workflows/build.yml @electron/wg-infra
|
||||
|
||||
2
.github/PULL_REQUEST_TEMPLATE.md
vendored
2
.github/PULL_REQUEST_TEMPLATE.md
vendored
@@ -5,8 +5,6 @@ Thank you for your Pull Request. Please provide a description above and review
|
||||
the requirements below.
|
||||
|
||||
Contributors guide: https://github.com/electron/electron/blob/main/CONTRIBUTING.md
|
||||
|
||||
NOTE: PRS submitted without this template will be automatically closed.
|
||||
-->
|
||||
|
||||
#### Checklist
|
||||
|
||||
45
.github/actions/build-electron/action.yml
vendored
45
.github/actions/build-electron/action.yml
vendored
@@ -47,16 +47,6 @@ runs:
|
||||
- name: Add Clang problem matcher
|
||||
shell: bash
|
||||
run: echo "::add-matcher::src/electron/.github/problem-matchers/clang.json"
|
||||
- name: Download previous object checksums
|
||||
shell: bash
|
||||
if: ${{ (github.event_name == 'push' || github.event_name == 'pull_request') && inputs.is-asan != 'true' }}
|
||||
env:
|
||||
GITHUB_TOKEN: ${{ github.token }}
|
||||
ARTIFACT_NAME: object-checksums.${{ inputs.artifact-platform }}_${{ inputs.target-arch }}.json
|
||||
SEARCH_BRANCH: ${{ case(github.event_name == 'push', github.ref_name, github.event.pull_request.base.ref) }}
|
||||
REPO: ${{ github.repository }}
|
||||
OUTPUT_PATH: src/previous-object-checksums.json
|
||||
run: node src/electron/.github/actions/build-electron/download-previous-object-checksums.mjs
|
||||
- name: Build Electron ${{ inputs.step-suffix }}
|
||||
if: ${{ inputs.target-platform != 'win' }}
|
||||
shell: bash
|
||||
@@ -82,17 +72,12 @@ runs:
|
||||
cp out/Default/.ninja_log out/electron_ninja_log
|
||||
node electron/script/check-symlinks.js
|
||||
|
||||
# Build stats and object checksums
|
||||
BUILD_STATS_ARGS="out/Default/siso.INFO --out-dir out/Default --output-object-checksums object-checksums.${{ inputs.artifact-platform }}_${{ inputs.target-arch }}.json"
|
||||
if [ -f previous-object-checksums.json ]; then
|
||||
BUILD_STATS_ARGS="$BUILD_STATS_ARGS --input-object-checksums previous-object-checksums.json"
|
||||
fi
|
||||
if ! [ -z "$DD_API_KEY" ]; then
|
||||
BUILD_STATS_ARGS="$BUILD_STATS_ARGS --upload-stats"
|
||||
# Upload build stats to Datadog
|
||||
if ! [ -z $DD_API_KEY ]; then
|
||||
npx node electron/script/build-stats.mjs out/Default/siso.INFO --upload-stats || true
|
||||
else
|
||||
echo "Skipping build-stats.mjs upload because DD_API_KEY is not set"
|
||||
fi
|
||||
node electron/script/build-stats.mjs $BUILD_STATS_ARGS || true
|
||||
- name: Build Electron (Windows) ${{ inputs.step-suffix }}
|
||||
if: ${{ inputs.target-platform == 'win' }}
|
||||
shell: powershell
|
||||
@@ -110,21 +95,16 @@ runs:
|
||||
Copy-Item out\Default\.ninja_log out\electron_ninja_log
|
||||
node electron\script\check-symlinks.js
|
||||
|
||||
# Build stats and object checksums
|
||||
$statsArgs = @("out\Default\siso.exe.INFO", "--out-dir", "out\Default", "--output-object-checksums", "object-checksums.${{ inputs.artifact-platform }}_${{ inputs.target-arch }}.json")
|
||||
if (Test-Path previous-object-checksums.json) {
|
||||
$statsArgs += @("--input-object-checksums", "previous-object-checksums.json")
|
||||
}
|
||||
# Upload build stats to Datadog
|
||||
if ($env:DD_API_KEY) {
|
||||
$statsArgs += "--upload-stats"
|
||||
try {
|
||||
npx node electron\script\build-stats.mjs out\Default\siso.exe.INFO --upload-stats ; $LASTEXITCODE = 0
|
||||
} catch {
|
||||
Write-Host "Build stats upload failed, continuing..."
|
||||
}
|
||||
} else {
|
||||
Write-Host "Skipping build-stats.mjs upload because DD_API_KEY is not set"
|
||||
}
|
||||
try {
|
||||
& node electron\script\build-stats.mjs @statsArgs ; $LASTEXITCODE = 0
|
||||
} catch {
|
||||
Write-Host "Build stats failed, continuing..."
|
||||
}
|
||||
- name: Verify dist.zip ${{ inputs.step-suffix }}
|
||||
shell: bash
|
||||
run: |
|
||||
@@ -322,10 +302,3 @@ runs:
|
||||
with:
|
||||
name: out_gen_artifacts_${{ env.ARTIFACT_KEY }}
|
||||
path: ./src/out/Default/gen
|
||||
- name: Upload Object Checksums ${{ inputs.step-suffix }}
|
||||
if: ${{ always() && !cancelled() && inputs.is-asan != 'true' }}
|
||||
uses: actions/upload-artifact@bbbca2ddaa5d8feaa63e36b76fdaad77386f024f # v7.0.0
|
||||
with:
|
||||
name: object_checksums_${{ inputs.artifact-platform }}_${{ inputs.target-arch }}
|
||||
path: ./src/object-checksums.${{ inputs.artifact-platform }}_${{ inputs.target-arch }}.json
|
||||
archive: false
|
||||
|
||||
@@ -1,82 +0,0 @@
|
||||
import { Octokit } from '@octokit/rest';
|
||||
|
||||
import { writeFileSync } from 'node:fs';
|
||||
|
||||
const token = process.env.GITHUB_TOKEN;
|
||||
const repo = process.env.REPO;
|
||||
const artifactName = process.env.ARTIFACT_NAME;
|
||||
const branch = process.env.SEARCH_BRANCH;
|
||||
const outputPath = process.env.OUTPUT_PATH;
|
||||
|
||||
const required = { GITHUB_TOKEN: token, REPO: repo, ARTIFACT_NAME: artifactName, SEARCH_BRANCH: branch, OUTPUT_PATH: outputPath };
|
||||
const missing = Object.entries(required).filter(([, v]) => !v).map(([k]) => k);
|
||||
if (missing.length > 0) {
|
||||
console.error(`Missing required environment variables: ${missing.join(', ')}`);
|
||||
process.exit(1);
|
||||
}
|
||||
|
||||
const [owner, repoName] = repo.split('/');
|
||||
const octokit = new Octokit({ auth: token });
|
||||
|
||||
async function main () {
|
||||
console.log(`Searching for artifact '${artifactName}' on branch '${branch}'...`);
|
||||
|
||||
// Resolve the "Build" workflow name to an ID, mirroring how `gh run list --workflow` works
|
||||
// under the hood (it uses /repos/{owner}/{repo}/actions/workflows/{id}/runs).
|
||||
const { data: workflows } = await octokit.actions.listRepoWorkflows({ owner, repo: repoName });
|
||||
const buildWorkflow = workflows.workflows.find((w) => w.name === 'Build');
|
||||
if (!buildWorkflow) {
|
||||
console.log('Could not find "Build" workflow, continuing without previous checksums');
|
||||
return;
|
||||
}
|
||||
|
||||
const { data: runs } = await octokit.actions.listWorkflowRuns({
|
||||
owner,
|
||||
repo: repoName,
|
||||
workflow_id: buildWorkflow.id,
|
||||
branch,
|
||||
status: 'completed',
|
||||
event: 'push',
|
||||
per_page: 20,
|
||||
exclude_pull_requests: true
|
||||
});
|
||||
|
||||
for (const run of runs.workflow_runs) {
|
||||
const { data: artifacts } = await octokit.actions.listWorkflowRunArtifacts({
|
||||
owner,
|
||||
repo: repoName,
|
||||
run_id: run.id,
|
||||
name: artifactName
|
||||
});
|
||||
|
||||
if (artifacts.artifacts.length > 0) {
|
||||
const artifact = artifacts.artifacts[0];
|
||||
console.log(`Found artifact in run ${run.id} (artifact ID: ${artifact.id}), downloading...`);
|
||||
|
||||
// Non-archived artifacts are still downloaded from the /zip endpoint
|
||||
const response = await octokit.actions.downloadArtifact({
|
||||
owner,
|
||||
repo: repoName,
|
||||
artifact_id: artifact.id,
|
||||
archive_format: 'zip'
|
||||
});
|
||||
|
||||
if (response.headers['content-type'] !== 'application/json') {
|
||||
console.error(`Unexpected content type for artifact download: ${response.headers['content-type']}`);
|
||||
console.error('Expected application/json, continuing without previous checksums');
|
||||
return;
|
||||
}
|
||||
|
||||
writeFileSync(outputPath, JSON.stringify(response.data));
|
||||
console.log('Downloaded previous object checksums successfully');
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
console.log(`No previous object checksums found in last ${runs.workflow_runs.length} runs, continuing without them`);
|
||||
}
|
||||
|
||||
main().catch((err) => {
|
||||
console.error('Failed to download previous object checksums, continuing without them:', err.message);
|
||||
process.exit(0);
|
||||
});
|
||||
2
.github/problem-matchers/clang.json
vendored
2
.github/problem-matchers/clang.json
vendored
@@ -5,7 +5,7 @@
|
||||
"fromPath": "src/out/Default/args.gn",
|
||||
"pattern": [
|
||||
{
|
||||
"regexp": "^(.+)[(:](\\d+)[:,](\\d+)\\)?:\\s+(warning|error):\\s+(.*)$",
|
||||
"regexp": "^(.+)[(:](\\d+)[:,](\\d+)\\)?:\\s+(warning|fatal error|error):\\s+(.*)$",
|
||||
"file": 1,
|
||||
"line": 2,
|
||||
"column": 3,
|
||||
|
||||
22
.github/problem-matchers/eslint-stylish.json
vendored
Normal file
22
.github/problem-matchers/eslint-stylish.json
vendored
Normal file
@@ -0,0 +1,22 @@
|
||||
{
|
||||
"problemMatcher": [
|
||||
{
|
||||
"owner": "eslint-stylish",
|
||||
"pattern": [
|
||||
{
|
||||
"regexp": "^\\s*([^\\s].*)$",
|
||||
"file": 1
|
||||
},
|
||||
{
|
||||
"regexp": "^\\s+(\\d+):(\\d+)\\s+(error|warning|info)\\s+(.*)\\s\\s+(.*)$",
|
||||
"line": 1,
|
||||
"column": 2,
|
||||
"severity": 3,
|
||||
"message": 4,
|
||||
"code": 5,
|
||||
"loop": true
|
||||
}
|
||||
]
|
||||
}
|
||||
]
|
||||
}
|
||||
47
.github/siso-patches/0001-siso-reuse-the-outer-os.File-for-chunked-ReadAt-in-f.patch
vendored
Normal file
47
.github/siso-patches/0001-siso-reuse-the-outer-os.File-for-chunked-ReadAt-in-f.patch
vendored
Normal file
@@ -0,0 +1,47 @@
|
||||
From 85b561ea4dbc76ba98af020b970f3aa6b20fdb9e Mon Sep 17 00:00:00 2001
|
||||
From: Samuel Attard <sam@electronjs.org>
|
||||
Date: Wed, 8 Apr 2026 23:24:15 -0700
|
||||
Subject: [PATCH] siso: reuse the outer *os.File for chunked ReadAt in
|
||||
fileParser.readFile
|
||||
MIME-Version: 1.0
|
||||
Content-Type: text/plain; charset=UTF-8
|
||||
Content-Transfer-Encoding: 8bit
|
||||
|
||||
The per-chunk goroutine currently re-opens fname to get its own handle
|
||||
for ReadAt. (*os.File).ReadAt is documented as safe for concurrent
|
||||
calls on the same File (on Windows it is ReadFile with an OVERLAPPED
|
||||
offset, so there is no shared seek state), so the extra open is
|
||||
redundant — the goroutines can share the outer f.
|
||||
|
||||
Besides halving the CreateFileW calls per subninja, this avoids an
|
||||
intermittent 'The parameter is incorrect.' (ERROR_INVALID_PARAMETER)
|
||||
from bindflt.sys when out/ is a mapped directory inside a Windows
|
||||
container: bindflt's handle-relative NtCreateFile path races when a
|
||||
second relative open arrives while the first handle to the same target
|
||||
is still being set up. Absolute paths and single opens do not trigger
|
||||
it; see microsoft/Windows-Containers#<tbd>.
|
||||
---
|
||||
siso/toolsupport/ninjautil/file_parser.go | 7 -------
|
||||
1 file changed, 7 deletions(-)
|
||||
|
||||
diff --git a/siso/toolsupport/ninjautil/file_parser.go b/siso/toolsupport/ninjautil/file_parser.go
|
||||
index 8c18d084..63116662 100644
|
||||
--- a/siso/toolsupport/ninjautil/file_parser.go
|
||||
+++ b/siso/toolsupport/ninjautil/file_parser.go
|
||||
@@ -111,13 +111,6 @@ func (p *fileParser) readFile(ctx context.Context, fname string) ([]byte, error)
|
||||
eg.Go(func() error {
|
||||
p.sema <- struct{}{}
|
||||
defer func() { <-p.sema }()
|
||||
- f, err := os.Open(fname)
|
||||
- if err != nil {
|
||||
- return err
|
||||
- }
|
||||
- defer func() {
|
||||
- _ = f.Close()
|
||||
- }()
|
||||
for len(chunkBuf) > 0 {
|
||||
n, err := f.ReadAt(chunkBuf, pos)
|
||||
if err != nil {
|
||||
--
|
||||
2.53.0
|
||||
|
||||
2
.github/workflows/apply-patches.yml
vendored
2
.github/workflows/apply-patches.yml
vendored
@@ -26,7 +26,7 @@ jobs:
|
||||
# Use dorny/paths-filter instead of the path filter under the on: pull_request: block
|
||||
# so that the output can be used to conditionally run the apply-patches job, which lets
|
||||
# the job be marked as a required status check (conditional skip counts as a success).
|
||||
- uses: dorny/paths-filter@fbd0ab8f3e69293af611ebaee6363fc25e6d187d # v4.0.1
|
||||
- uses: dorny/paths-filter@de90cc6fb38fc0963ad72b210f1f284cd68cea36 # v3.0.2
|
||||
id: filter
|
||||
with:
|
||||
filters: |
|
||||
|
||||
3
.github/workflows/audit-branch-ci.yml
vendored
3
.github/workflows/audit-branch-ci.yml
vendored
@@ -86,7 +86,6 @@ jobs:
|
||||
!message.startsWith("Response status code does not indicate success") &&
|
||||
!message.startsWith("The hosted runner lost communication with the server") &&
|
||||
!message.startsWith("Dependabot encountered an error performing the update") &&
|
||||
!message.startsWith("The action 'Run Electron Tests' has timed out") &&
|
||||
!/Unable to make request/.test(message) &&
|
||||
!/The requested URL returned error/.test(message),
|
||||
)
|
||||
@@ -155,7 +154,7 @@ jobs:
|
||||
await core.summary.write();
|
||||
- name: Send Slack message if errors
|
||||
if: ${{ always() && steps.audit-errors.outputs.errorsFound && github.ref == 'refs/heads/main' }}
|
||||
uses: slackapi/slack-github-action@af78098f536edbc4de71162a307590698245be95 # v3.0.1
|
||||
uses: slackapi/slack-github-action@91efab103c0de0a537f72a35f6b8cda0ee76bf0a # v2.1.1
|
||||
with:
|
||||
payload: |
|
||||
link: "https://github.com/${{ github.repository }}/actions/runs/${{ github.run_id }}"
|
||||
|
||||
25
.github/workflows/branch-created.yml
vendored
25
.github/workflows/branch-created.yml
vendored
@@ -31,8 +31,8 @@ jobs:
|
||||
else
|
||||
echo "Not a release branch: $BRANCH_NAME"
|
||||
fi
|
||||
- name: Determine Next Unsupported Major Version
|
||||
id: determine-next-unsupported-major
|
||||
- name: Determine Unsupported Major Version
|
||||
id: determine-unsupported-major
|
||||
if: ${{ steps.check-major-version.outputs.MAJOR }}
|
||||
env:
|
||||
MAJOR: ${{ steps.check-major-version.outputs.MAJOR }}
|
||||
@@ -50,27 +50,26 @@ jobs:
|
||||
|
||||
# Find the oldest version where eolDate >= stableDate of the new major
|
||||
# This gives us the oldest supported version when the new major goes stable
|
||||
NEXT_UNSUPPORTED_MAJOR=$(echo "$SCHEDULE" | jq -r --arg stableDate "$STABLE_DATE" '
|
||||
UNSUPPORTED_MAJOR=$(echo "$SCHEDULE" | jq -r --arg stableDate "$STABLE_DATE" '
|
||||
[.[] | select(.eolDate != null and .eolDate >= $stableDate)] | sort_by(.version | split(".")[0] | tonumber) | first | .version | split(".")[0]
|
||||
')
|
||||
|
||||
if [[ -z "$NEXT_UNSUPPORTED_MAJOR" || "$NEXT_UNSUPPORTED_MAJOR" == "null" ]]; then
|
||||
if [[ -z "$UNSUPPORTED_MAJOR" || "$UNSUPPORTED_MAJOR" == "null" ]]; then
|
||||
echo "Could not determine oldest supported version"
|
||||
exit 1
|
||||
fi
|
||||
|
||||
echo "SCHEDULE=$SCHEDULE" >> "$GITHUB_OUTPUT"
|
||||
echo "NEXT_UNSUPPORTED_MAJOR=$NEXT_UNSUPPORTED_MAJOR" >> "$GITHUB_OUTPUT"
|
||||
echo "UNSUPPORTED_MAJOR=$UNSUPPORTED_MAJOR" >> "$GITHUB_OUTPUT"
|
||||
- name: New Release Branch Tasks
|
||||
if: ${{ steps.check-major-version.outputs.MAJOR }}
|
||||
env:
|
||||
GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}
|
||||
GH_REPO: electron/electron
|
||||
MAJOR: ${{ steps.check-major-version.outputs.MAJOR }}
|
||||
NEXT_UNSUPPORTED_MAJOR: ${{ steps.determine-next-unsupported-major.outputs.NEXT_UNSUPPORTED_MAJOR }}
|
||||
UNSUPPORTED_MAJOR: ${{ steps.determine-unsupported-major.outputs.UNSUPPORTED_MAJOR }}
|
||||
run: |
|
||||
PREVIOUS_MAJOR=$((MAJOR - 1))
|
||||
UNSUPPORTED_MAJOR=$((NEXT_UNSUPPORTED_MAJOR - 1))
|
||||
|
||||
# Create new labels
|
||||
gh label create $MAJOR-x-y --color 8d9ee8 || true
|
||||
@@ -109,8 +108,8 @@ jobs:
|
||||
id: generate-project-metadata
|
||||
env:
|
||||
MAJOR: ${{ steps.check-major-version.outputs.MAJOR }}
|
||||
NEXT_UNSUPPORTED_MAJOR: ${{ steps.determine-next-unsupported-major.outputs.NEXT_UNSUPPORTED_MAJOR }}
|
||||
SCHEDULE: ${{ steps.determine-next-unsupported-major.outputs.SCHEDULE }}
|
||||
UNSUPPORTED_MAJOR: ${{ steps.determine-unsupported-major.outputs.UNSUPPORTED_MAJOR }}
|
||||
SCHEDULE: ${{ steps.determine-unsupported-major.outputs.SCHEDULE }}
|
||||
with:
|
||||
script: |
|
||||
const schedule = JSON.parse(process.env.SCHEDULE)
|
||||
@@ -145,7 +144,7 @@ jobs:
|
||||
major,
|
||||
"next-major": nextMajor,
|
||||
"prev-major": prevMajor,
|
||||
"ending-support-major": parseInt(process.env.NEXT_UNSUPPORTED_MAJOR),
|
||||
"ending-support-major": parseInt(process.env.UNSUPPORTED_MAJOR),
|
||||
"beta-date": betaDate,
|
||||
"beta-prep-week": betaPrepWeek.toISOString().split('T')[0],
|
||||
"beta-prep-week-end": betaPrepWeekEnd.toISOString().split('T')[0],
|
||||
@@ -157,7 +156,7 @@ jobs:
|
||||
}))
|
||||
- name: Create Release Project Board
|
||||
if: ${{ steps.check-major-version.outputs.MAJOR }}
|
||||
uses: dsanders11/project-actions/copy-project@5767984408ccc6742f83acc8b8d8ea5e09f329af # v2.0.0
|
||||
uses: dsanders11/project-actions/copy-project@2134fe7cc71c58b7ae259c82a8e63c6058255678 # v1.7.0
|
||||
id: create-release-board
|
||||
with:
|
||||
drafts: true
|
||||
@@ -177,7 +176,7 @@ jobs:
|
||||
GITHUB_TOKEN: ${{ steps.generate-token.outputs.token }}
|
||||
- name: Find Previous Release Project Board
|
||||
if: ${{ steps.check-major-version.outputs.MAJOR }}
|
||||
uses: dsanders11/project-actions/find-project@5767984408ccc6742f83acc8b8d8ea5e09f329af # v2.0.0
|
||||
uses: dsanders11/project-actions/find-project@2134fe7cc71c58b7ae259c82a8e63c6058255678 # v1.7.0
|
||||
id: find-prev-release-board
|
||||
with:
|
||||
fail-if-project-not-found: false
|
||||
@@ -185,7 +184,7 @@ jobs:
|
||||
token: ${{ steps.generate-token.outputs.token }}
|
||||
- name: Close Previous Release Project Board
|
||||
if: ${{ steps.find-prev-release-board.outputs.number }}
|
||||
uses: dsanders11/project-actions/close-project@5767984408ccc6742f83acc8b8d8ea5e09f329af # v2.0.0
|
||||
uses: dsanders11/project-actions/close-project@2134fe7cc71c58b7ae259c82a8e63c6058255678 # v1.7.0
|
||||
with:
|
||||
project-number: ${{ steps.find-prev-release-board.outputs.number }}
|
||||
token: ${{ steps.generate-token.outputs.token }}
|
||||
|
||||
24
.github/workflows/build.yml
vendored
24
.github/workflows/build.yml
vendored
@@ -61,7 +61,7 @@ jobs:
|
||||
- uses: actions/checkout@de0fac2e4500dabe0009e67214ff5f5447ce83dd
|
||||
with:
|
||||
ref: ${{ github.event.pull_request.head.sha }}
|
||||
- uses: dorny/paths-filter@fbd0ab8f3e69293af611ebaee6363fc25e6d187d # v4.0.1
|
||||
- uses: dorny/paths-filter@de90cc6fb38fc0963ad72b210f1f284cd68cea36 # v3.0.2
|
||||
id: filter
|
||||
with:
|
||||
filters: |
|
||||
@@ -200,6 +200,15 @@ jobs:
|
||||
generate-sas-token: 'true'
|
||||
target-platform: win
|
||||
|
||||
# Build a patched siso binary for Windows CI in parallel with checkout-windows.
|
||||
# The Windows build jobs download the resulting artifact and use it via SISO_PATH.
|
||||
build-siso-windows:
|
||||
needs: setup
|
||||
if: ${{ needs.setup.outputs.src == 'true' && !inputs.skip-windows }}
|
||||
uses: ./.github/workflows/pipeline-segment-build-siso-windows.yml
|
||||
permissions:
|
||||
contents: read
|
||||
|
||||
# GN Check Jobs
|
||||
macos-gn-check:
|
||||
uses: ./.github/workflows/pipeline-segment-electron-gn-check.yml
|
||||
@@ -384,7 +393,7 @@ jobs:
|
||||
issues: read
|
||||
pull-requests: read
|
||||
uses: ./.github/workflows/pipeline-electron-build-and-test.yml
|
||||
needs: checkout-windows
|
||||
needs: [checkout-windows, build-siso-windows]
|
||||
if: ${{ needs.setup.outputs.src == 'true' && !inputs.skip-windows }}
|
||||
with:
|
||||
build-runs-on: electron-arc-centralus-windows-amd64-16core
|
||||
@@ -403,7 +412,7 @@ jobs:
|
||||
issues: read
|
||||
pull-requests: read
|
||||
uses: ./.github/workflows/pipeline-electron-build-and-test.yml
|
||||
needs: checkout-windows
|
||||
needs: [checkout-windows, build-siso-windows]
|
||||
if: ${{ needs.setup.outputs.src == 'true' && !inputs.skip-windows }}
|
||||
with:
|
||||
build-runs-on: electron-arc-centralus-windows-amd64-16core
|
||||
@@ -422,7 +431,7 @@ jobs:
|
||||
issues: read
|
||||
pull-requests: read
|
||||
uses: ./.github/workflows/pipeline-electron-build-and-test.yml
|
||||
needs: checkout-windows
|
||||
needs: [checkout-windows, build-siso-windows]
|
||||
if: ${{ needs.setup.outputs.src == 'true' && !inputs.skip-windows }}
|
||||
with:
|
||||
build-runs-on: electron-arc-centralus-windows-amd64-16core
|
||||
@@ -440,9 +449,12 @@ jobs:
|
||||
runs-on: ubuntu-latest
|
||||
permissions:
|
||||
contents: read
|
||||
needs: [docs-only, macos-x64, macos-arm64, linux-x64, linux-x64-asan, linux-arm, linux-arm64, windows-x64, windows-x86, windows-arm64]
|
||||
if: always() && github.repository == 'electron/electron' && !contains(needs.*.result, 'failure')
|
||||
needs: [docs-only, macos-x64, macos-arm64, linux-x64, linux-x64-asan, linux-arm, linux-arm64, build-siso-windows, windows-x64, windows-x86, windows-arm64]
|
||||
if: always() && github.repository == 'electron/electron'
|
||||
steps:
|
||||
- name: Fail if any needed job failed or was cancelled
|
||||
if: contains(needs.*.result, 'failure') || contains(needs.*.result, 'cancelled')
|
||||
run: exit 1
|
||||
- name: GitHub Actions Jobs Done
|
||||
run: |
|
||||
echo "All GitHub Actions Jobs are done"
|
||||
|
||||
127
.github/workflows/clean-src-cache.yml
vendored
127
.github/workflows/clean-src-cache.yml
vendored
@@ -7,7 +7,6 @@ name: Clean Source Cache
|
||||
on:
|
||||
schedule:
|
||||
- cron: "0 0 * * *"
|
||||
workflow_dispatch:
|
||||
|
||||
permissions: {}
|
||||
|
||||
@@ -17,8 +16,6 @@ jobs:
|
||||
runs-on: electron-arc-centralus-linux-amd64-32core
|
||||
permissions:
|
||||
contents: read
|
||||
env:
|
||||
DD_API_KEY: ${{ secrets.DD_API_KEY }}
|
||||
container:
|
||||
image: ghcr.io/electron/build:bc2f48b2415a670de18d13605b1cf0eb5fdbaae1
|
||||
options: --user root
|
||||
@@ -26,130 +23,12 @@ jobs:
|
||||
- /mnt/cross-instance-cache:/mnt/cross-instance-cache
|
||||
- /mnt/win-cache:/mnt/win-cache
|
||||
steps:
|
||||
- name: Get Disk Space Before Cleanup
|
||||
id: disk-before
|
||||
shell: bash
|
||||
run: |
|
||||
echo "Disk space before cleanup:"
|
||||
df -h /mnt/cross-instance-cache
|
||||
df -h /mnt/win-cache
|
||||
CROSS_FREE_BEFORE=$(df -k /mnt/cross-instance-cache | tail -1 | awk '{print $4}')
|
||||
CROSS_TOTAL=$(df -k /mnt/cross-instance-cache | tail -1 | awk '{print $2}')
|
||||
WIN_FREE_BEFORE=$(df -k /mnt/win-cache | tail -1 | awk '{print $4}')
|
||||
WIN_TOTAL=$(df -k /mnt/win-cache | tail -1 | awk '{print $2}')
|
||||
echo "cross_free_kb=$CROSS_FREE_BEFORE" >> $GITHUB_OUTPUT
|
||||
echo "cross_total_kb=$CROSS_TOTAL" >> $GITHUB_OUTPUT
|
||||
echo "win_free_kb=$WIN_FREE_BEFORE" >> $GITHUB_OUTPUT
|
||||
echo "win_total_kb=$WIN_TOTAL" >> $GITHUB_OUTPUT
|
||||
|
||||
- name: Cleanup Source Cache
|
||||
shell: bash
|
||||
run: |
|
||||
df -h /mnt/cross-instance-cache
|
||||
find /mnt/cross-instance-cache -type f -mtime +15 -delete
|
||||
find /mnt/win-cache -type f -mtime +15 -delete
|
||||
|
||||
- name: Get Disk Space After Cleanup
|
||||
id: disk-after
|
||||
shell: bash
|
||||
run: |
|
||||
echo "Disk space after cleanup:"
|
||||
df -h /mnt/cross-instance-cache
|
||||
df -h /mnt/win-cache
|
||||
CROSS_FREE_AFTER=$(df -k /mnt/cross-instance-cache | tail -1 | awk '{print $4}')
|
||||
WIN_FREE_AFTER=$(df -k /mnt/win-cache | tail -1 | awk '{print $4}')
|
||||
echo "cross_free_kb=$CROSS_FREE_AFTER" >> $GITHUB_OUTPUT
|
||||
echo "win_free_kb=$WIN_FREE_AFTER" >> $GITHUB_OUTPUT
|
||||
|
||||
- name: Log Disk Space to Datadog
|
||||
if: ${{ env.DD_API_KEY != '' }}
|
||||
shell: bash
|
||||
env:
|
||||
CROSS_FREE_BEFORE: ${{ steps.disk-before.outputs.cross_free_kb }}
|
||||
CROSS_FREE_AFTER: ${{ steps.disk-after.outputs.cross_free_kb }}
|
||||
CROSS_TOTAL: ${{ steps.disk-before.outputs.cross_total_kb }}
|
||||
WIN_FREE_BEFORE: ${{ steps.disk-before.outputs.win_free_kb }}
|
||||
WIN_FREE_AFTER: ${{ steps.disk-after.outputs.win_free_kb }}
|
||||
WIN_TOTAL: ${{ steps.disk-before.outputs.win_total_kb }}
|
||||
run: |
|
||||
TIMESTAMP=$(date +%s)
|
||||
|
||||
CROSS_FREE_BEFORE_GB=$(awk "BEGIN {printf \"%.2f\", $CROSS_FREE_BEFORE / 1024 / 1024}")
|
||||
CROSS_FREE_AFTER_GB=$(awk "BEGIN {printf \"%.2f\", $CROSS_FREE_AFTER / 1024 / 1024}")
|
||||
CROSS_FREED_GB=$(awk "BEGIN {printf \"%.2f\", ($CROSS_FREE_AFTER - $CROSS_FREE_BEFORE) / 1024 / 1024}")
|
||||
CROSS_TOTAL_GB=$(awk "BEGIN {printf \"%.2f\", $CROSS_TOTAL / 1024 / 1024}")
|
||||
|
||||
WIN_FREE_BEFORE_GB=$(awk "BEGIN {printf \"%.2f\", $WIN_FREE_BEFORE / 1024 / 1024}")
|
||||
WIN_FREE_AFTER_GB=$(awk "BEGIN {printf \"%.2f\", $WIN_FREE_AFTER / 1024 / 1024}")
|
||||
WIN_FREED_GB=$(awk "BEGIN {printf \"%.2f\", ($WIN_FREE_AFTER - $WIN_FREE_BEFORE) / 1024 / 1024}")
|
||||
WIN_TOTAL_GB=$(awk "BEGIN {printf \"%.2f\", $WIN_TOTAL / 1024 / 1024}")
|
||||
|
||||
echo "cross-instance-cache: free before=${CROSS_FREE_BEFORE_GB}GB, after=${CROSS_FREE_AFTER_GB}GB, freed=${CROSS_FREED_GB}GB, total=${CROSS_TOTAL_GB}GB"
|
||||
echo "win-cache: free before=${WIN_FREE_BEFORE_GB}GB, after=${WIN_FREE_AFTER_GB}GB, freed=${WIN_FREED_GB}GB, total=${WIN_TOTAL_GB}GB"
|
||||
|
||||
curl -s -X POST "https://api.datadoghq.com/api/v2/series" \
|
||||
-H "Content-Type: application/json" \
|
||||
-H "DD-API-KEY: ${DD_API_KEY}" \
|
||||
-d @- << EOF
|
||||
{
|
||||
"series": [
|
||||
{
|
||||
"metric": "electron.src_cache.disk.free_space_before_cleanup_gb",
|
||||
"points": [{"timestamp": ${TIMESTAMP}, "value": ${CROSS_FREE_BEFORE_GB}}],
|
||||
"type": 3,
|
||||
"unit": "gigabyte",
|
||||
"tags": ["volume:cross-instance-cache", "platform:linux"]
|
||||
},
|
||||
{
|
||||
"metric": "electron.src_cache.disk.free_space_after_cleanup_gb",
|
||||
"points": [{"timestamp": ${TIMESTAMP}, "value": ${CROSS_FREE_AFTER_GB}}],
|
||||
"type": 3,
|
||||
"unit": "gigabyte",
|
||||
"tags": ["volume:cross-instance-cache", "platform:linux"]
|
||||
},
|
||||
{
|
||||
"metric": "electron.src_cache.disk.space_freed_gb",
|
||||
"points": [{"timestamp": ${TIMESTAMP}, "value": ${CROSS_FREED_GB}}],
|
||||
"type": 3,
|
||||
"unit": "gigabyte",
|
||||
"tags": ["volume:cross-instance-cache", "platform:linux"]
|
||||
},
|
||||
{
|
||||
"metric": "electron.src_cache.disk.total_space_gb",
|
||||
"points": [{"timestamp": ${TIMESTAMP}, "value": ${CROSS_TOTAL_GB}}],
|
||||
"type": 3,
|
||||
"unit": "gigabyte",
|
||||
"tags": ["volume:cross-instance-cache", "platform:linux"]
|
||||
},
|
||||
{
|
||||
"metric": "electron.src_cache.disk.free_space_before_cleanup_gb",
|
||||
"points": [{"timestamp": ${TIMESTAMP}, "value": ${WIN_FREE_BEFORE_GB}}],
|
||||
"type": 3,
|
||||
"unit": "gigabyte",
|
||||
"tags": ["volume:win-cache", "platform:linux"]
|
||||
},
|
||||
{
|
||||
"metric": "electron.src_cache.disk.free_space_after_cleanup_gb",
|
||||
"points": [{"timestamp": ${TIMESTAMP}, "value": ${WIN_FREE_AFTER_GB}}],
|
||||
"type": 3,
|
||||
"unit": "gigabyte",
|
||||
"tags": ["volume:win-cache", "platform:linux"]
|
||||
},
|
||||
{
|
||||
"metric": "electron.src_cache.disk.space_freed_gb",
|
||||
"points": [{"timestamp": ${TIMESTAMP}, "value": ${WIN_FREED_GB}}],
|
||||
"type": 3,
|
||||
"unit": "gigabyte",
|
||||
"tags": ["volume:win-cache", "platform:linux"]
|
||||
},
|
||||
{
|
||||
"metric": "electron.src_cache.disk.total_space_gb",
|
||||
"points": [{"timestamp": ${TIMESTAMP}, "value": ${WIN_TOTAL_GB}}],
|
||||
"type": 3,
|
||||
"unit": "gigabyte",
|
||||
"tags": ["volume:win-cache", "platform:linux"]
|
||||
}
|
||||
]
|
||||
}
|
||||
EOF
|
||||
|
||||
echo "Disk space metrics logged to Datadog"
|
||||
find /mnt/win-cache -type f -mtime +15 -delete
|
||||
df -h /mnt/win-cache
|
||||
|
||||
6
.github/workflows/issue-labeled.yml
vendored
6
.github/workflows/issue-labeled.yml
vendored
@@ -21,7 +21,7 @@ jobs:
|
||||
creds: ${{ secrets.ISSUE_TRIAGE_GH_APP_CREDS }}
|
||||
org: electron
|
||||
- name: Set status
|
||||
uses: dsanders11/project-actions/edit-item@5767984408ccc6742f83acc8b8d8ea5e09f329af # v2.0.0
|
||||
uses: dsanders11/project-actions/edit-item@2134fe7cc71c58b7ae259c82a8e63c6058255678 # v1.7.0
|
||||
with:
|
||||
token: ${{ steps.generate-token.outputs.token }}
|
||||
project-number: 90
|
||||
@@ -42,7 +42,7 @@ jobs:
|
||||
creds: ${{ secrets.ISSUE_TRIAGE_GH_APP_CREDS }}
|
||||
org: electron
|
||||
- name: Set status
|
||||
uses: dsanders11/project-actions/edit-item@5767984408ccc6742f83acc8b8d8ea5e09f329af # v2.0.0
|
||||
uses: dsanders11/project-actions/edit-item@2134fe7cc71c58b7ae259c82a8e63c6058255678 # v1.7.0
|
||||
with:
|
||||
token: ${{ steps.generate-token.outputs.token }}
|
||||
project-number: 90
|
||||
@@ -76,7 +76,7 @@ jobs:
|
||||
creds: ${{ secrets.ISSUE_TRIAGE_GH_APP_CREDS }}
|
||||
- name: Create comment
|
||||
if: ${{ steps.check-for-comment.outputs.SHOULD_COMMENT }}
|
||||
uses: actions-cool/issues-helper@200c78641dbf33838311e5a1e0c31bbdb92d7cf0 # v3.8.0
|
||||
uses: actions-cool/issues-helper@71b62d7da76e59ff7b193904feb6e77d4dbb2777 # v3.7.6
|
||||
with:
|
||||
actions: 'create-comment'
|
||||
token: ${{ steps.generate-token.outputs.token }}
|
||||
|
||||
4
.github/workflows/issue-opened.yml
vendored
4
.github/workflows/issue-opened.yml
vendored
@@ -20,7 +20,7 @@ jobs:
|
||||
creds: ${{ secrets.ISSUE_TRIAGE_GH_APP_CREDS }}
|
||||
org: electron
|
||||
- name: Add to Issue Triage
|
||||
uses: dsanders11/project-actions/add-item@5767984408ccc6742f83acc8b8d8ea5e09f329af # v2.0.0
|
||||
uses: dsanders11/project-actions/add-item@2134fe7cc71c58b7ae259c82a8e63c6058255678 # v1.7.0
|
||||
with:
|
||||
field: Reporter
|
||||
field-value: ${{ github.event.issue.user.login }}
|
||||
@@ -146,7 +146,7 @@ jobs:
|
||||
}
|
||||
- name: Create unsupported major comment
|
||||
if: ${{ steps.add-labels.outputs.unsupportedMajor }}
|
||||
uses: actions-cool/issues-helper@200c78641dbf33838311e5a1e0c31bbdb92d7cf0 # v3.8.0
|
||||
uses: actions-cool/issues-helper@71b62d7da76e59ff7b193904feb6e77d4dbb2777 # v3.7.6
|
||||
with:
|
||||
actions: 'create-comment'
|
||||
token: ${{ steps.generate-token.outputs.token }}
|
||||
|
||||
2
.github/workflows/issue-transferred.yml
vendored
2
.github/workflows/issue-transferred.yml
vendored
@@ -20,7 +20,7 @@ jobs:
|
||||
creds: ${{ secrets.ISSUE_TRIAGE_GH_APP_CREDS }}
|
||||
org: electron
|
||||
- name: Remove from issue triage
|
||||
uses: dsanders11/project-actions/delete-item@5767984408ccc6742f83acc8b8d8ea5e09f329af # v2.0.0
|
||||
uses: dsanders11/project-actions/delete-item@2134fe7cc71c58b7ae259c82a8e63c6058255678 # v1.7.0
|
||||
with:
|
||||
token: ${{ steps.generate-token.outputs.token }}
|
||||
project-number: 90
|
||||
|
||||
2
.github/workflows/issue-unlabeled.yml
vendored
2
.github/workflows/issue-unlabeled.yml
vendored
@@ -33,7 +33,7 @@ jobs:
|
||||
org: electron
|
||||
- name: Set status
|
||||
if: ${{ steps.check-for-blocked-labels.outputs.NOT_BLOCKED }}
|
||||
uses: dsanders11/project-actions/edit-item@5767984408ccc6742f83acc8b8d8ea5e09f329af # v2.0.0
|
||||
uses: dsanders11/project-actions/edit-item@2134fe7cc71c58b7ae259c82a8e63c6058255678 # v1.7.0
|
||||
with:
|
||||
token: ${{ steps.generate-token.outputs.token }}
|
||||
project-number: 90
|
||||
|
||||
@@ -51,21 +51,4 @@ jobs:
|
||||
PR_URL: ${{ github.event.pull_request.html_url }}
|
||||
PR_AUTHOR: ${{ github.event.pull_request.user.login }}
|
||||
run: |
|
||||
cat <<'REVIEW_EOF' | sed "s/%AUTHOR%/$PR_AUTHOR/g" | gh pr review $PR_URL -r --body-file=-
|
||||
<!-- disallowed-non-maintainer-change -->
|
||||
|
||||
Hello @%AUTHOR%! It looks like this pull request touches one of our dependency or CI files, and per [our contribution policy](https://github.com/electron/electron/blob/main/CONTRIBUTING.md#dependencies-upgrades-policy) we do not accept these types of changes in PRs.
|
||||
|
||||
To move this PR forward, please:
|
||||
|
||||
1. Revert the dependency/CI file changes from your branch. (e.g. `yarn.lock`, `.yarn/`, `.yarnrc.yml`, `.github/workflows/`, `.github/actions/`)
|
||||
2. Ensure your branch [allows maintainer commits](https://docs.github.com/en/pull-requests/collaborating-with-pull-requests/working-with-forks/allowing-changes-to-a-pull-request-branch-created-from-a-fork) so a maintainer can push the necessary dependency changes on your behalf.
|
||||
3. Leave a comment letting reviewers know the dependency change is still needed.
|
||||
|
||||
<details>
|
||||
<summary>For maintainers</summary>
|
||||
|
||||
To land this PR, push a verified commit to the contributor's branch with the required dependency/CI changes, then dismiss this review.
|
||||
|
||||
</details>
|
||||
REVIEW_EOF
|
||||
printf "<!-- disallowed-non-maintainer-change -->\n\nHello @${PR_AUTHOR}! It looks like this pull request touches one of our dependency or CI files, and per [our contribution policy](https://github.com/electron/electron/blob/main/CONTRIBUTING.md#dependencies-upgrades-policy) we do not accept these types of changes in PRs." | gh pr review $PR_URL -r --body-file=-
|
||||
|
||||
1
.github/workflows/pipeline-electron-lint.yml
vendored
1
.github/workflows/pipeline-electron-lint.yml
vendored
@@ -76,6 +76,7 @@ jobs:
|
||||
- name: Add problem matchers
|
||||
shell: bash
|
||||
run: |
|
||||
echo "::add-matcher::src/electron/.github/problem-matchers/eslint-stylish.json"
|
||||
echo "::add-matcher::src/electron/.github/problem-matchers/markdownlint.json"
|
||||
- name: Run Lint
|
||||
shell: bash
|
||||
|
||||
98
.github/workflows/pipeline-segment-build-siso-windows.yml
vendored
Normal file
98
.github/workflows/pipeline-segment-build-siso-windows.yml
vendored
Normal file
@@ -0,0 +1,98 @@
|
||||
name: Pipeline Segment - Build Siso (Windows)
|
||||
|
||||
# Builds a patched siso binary for Windows CI. Reads the siso revision from
|
||||
# the Chromium DEPS file at the pinned chromium_version, shallow-clones
|
||||
# chromium.googlesource.com/build at that revision, applies the patches under
|
||||
# .github/siso-patches/, cross-compiles siso.exe for windows/amd64, and
|
||||
# publishes it as the `siso-windows-amd64` artifact. The Windows build jobs
|
||||
# download it and use it via SISO_PATH. The built binary is cached keyed on
|
||||
# the siso revision + sha256 of the patch contents, so subsequent runs just
|
||||
# restore it.
|
||||
|
||||
on:
|
||||
workflow_call: {}
|
||||
|
||||
permissions: {}
|
||||
|
||||
jobs:
|
||||
build:
|
||||
runs-on: ubuntu-latest
|
||||
permissions:
|
||||
contents: read
|
||||
steps:
|
||||
- name: Checkout Electron
|
||||
uses: actions/checkout@de0fac2e4500dabe0009e67214ff5f5447ce83dd # v6.0.2
|
||||
with:
|
||||
fetch-depth: 1
|
||||
ref: ${{ github.event.pull_request.head.sha }}
|
||||
sparse-checkout: |
|
||||
DEPS
|
||||
.github/siso-patches
|
||||
- name: Resolve siso revision from Chromium DEPS
|
||||
id: resolve
|
||||
run: |
|
||||
set -euo pipefail
|
||||
CHROMIUM_VERSION=$(python3 -c "import re; print(re.search(r\"'chromium_version':\s*\n\s*'([^']+)'\", open('DEPS').read()).group(1))")
|
||||
if ! [[ "$CHROMIUM_VERSION" =~ ^[0-9]+(\.[0-9]+){1,3}$ ]]; then
|
||||
echo "error: unexpected chromium_version format: $CHROMIUM_VERSION" >&2
|
||||
exit 1
|
||||
fi
|
||||
curl -sfL "https://raw.githubusercontent.com/chromium/chromium/${CHROMIUM_VERSION}/DEPS" -o /tmp/chromium-DEPS
|
||||
SISO_SHA=$(python3 -c "import re; print(re.search(r\"'siso_version':\s*'git_revision:([0-9a-f]+)'\", open('/tmp/chromium-DEPS').read()).group(1))")
|
||||
if ! [[ "$SISO_SHA" =~ ^[0-9a-f]{40}$ ]]; then
|
||||
echo "error: unexpected siso_version SHA: $SISO_SHA" >&2
|
||||
exit 1
|
||||
fi
|
||||
PATCHES_HASH=$(find .github/siso-patches -type f -name '*.patch' | sort | xargs sha256sum | sha256sum | awk '{print $1}')
|
||||
echo "siso-sha=${SISO_SHA}" >> "$GITHUB_OUTPUT"
|
||||
echo "patches-hash=${PATCHES_HASH}" >> "$GITHUB_OUTPUT"
|
||||
echo "Chromium ${CHROMIUM_VERSION} pins siso at ${SISO_SHA}"
|
||||
echo "Patches hash: ${PATCHES_HASH}"
|
||||
- name: Restore cached siso binary
|
||||
id: cache-siso
|
||||
uses: actions/cache@27d5ce7f107fe9357f9df03efb73ab90386fccae # v5.0.5
|
||||
with:
|
||||
path: siso-out/siso.exe
|
||||
key: siso-windows-amd64-${{ steps.resolve.outputs.siso-sha }}-${{ steps.resolve.outputs.patches-hash }}
|
||||
- name: Shallow clone chromium build repo at pinned revision
|
||||
if: steps.cache-siso.outputs.cache-hit != 'true'
|
||||
env:
|
||||
SISO_SHA: ${{ steps.resolve.outputs.siso-sha }}
|
||||
run: |
|
||||
set -euo pipefail
|
||||
mkdir chromium-build
|
||||
cd chromium-build
|
||||
git init -q
|
||||
git remote add origin https://chromium.googlesource.com/build
|
||||
git -c protocol.version=2 fetch --depth=1 origin "$SISO_SHA"
|
||||
git checkout --detach FETCH_HEAD
|
||||
- name: Apply in-tree siso patches
|
||||
if: steps.cache-siso.outputs.cache-hit != 'true'
|
||||
run: |
|
||||
set -euo pipefail
|
||||
cd chromium-build
|
||||
git -c user.name=electron-ci -c user.email=ci@electronjs.org \
|
||||
am --3way "${GITHUB_WORKSPACE}/.github/siso-patches"/*.patch
|
||||
- name: Set up Go
|
||||
if: steps.cache-siso.outputs.cache-hit != 'true'
|
||||
uses: actions/setup-go@4a3601121dd01d1626a1e23e37211e3254c1c06c # v6.4.0
|
||||
with:
|
||||
go-version-file: chromium-build/siso/go.mod
|
||||
cache: false
|
||||
- name: Build siso (windows/amd64)
|
||||
if: steps.cache-siso.outputs.cache-hit != 'true'
|
||||
working-directory: chromium-build/siso
|
||||
env:
|
||||
CGO_ENABLED: '0'
|
||||
GOOS: windows
|
||||
GOARCH: amd64
|
||||
run: |
|
||||
mkdir -p "${GITHUB_WORKSPACE}/siso-out"
|
||||
go build -trimpath -o "${GITHUB_WORKSPACE}/siso-out/siso.exe" .
|
||||
- name: Upload siso artifact
|
||||
uses: actions/upload-artifact@043fb46d1a93c77aae656e7c1c64a875d1fc6a0a # v7.0.1
|
||||
with:
|
||||
name: siso-windows-amd64
|
||||
path: siso-out/siso.exe
|
||||
if-no-files-found: error
|
||||
retention-days: 1
|
||||
@@ -77,7 +77,6 @@ env:
|
||||
ELECTRON_ARTIFACTS_BLOB_STORAGE: ${{ secrets.ELECTRON_ARTIFACTS_BLOB_STORAGE }}
|
||||
ELECTRON_RBE_JWT: ${{ secrets.ELECTRON_RBE_JWT }}
|
||||
SUDOWOODO_EXCHANGE_URL: ${{ secrets.SUDOWOODO_EXCHANGE_URL }}
|
||||
SUDOWOODO_EXCHANGE_TOKEN: ${{ secrets.SUDOWOODO_EXCHANGE_TOKEN }}
|
||||
GCLIENT_EXTRA_ARGS: ${{ inputs.target-platform == 'macos' && '--custom-var=checkout_mac=True --custom-var=host_os=mac' || inputs.target-platform == 'win' && '--custom-var=checkout_win=True' || '--custom-var=checkout_arm=True --custom-var=checkout_arm64=True' }}
|
||||
ELECTRON_OUT_DIR: Default
|
||||
ACTIONS_STEP_DEBUG: ${{ secrets.ACTIONS_STEP_DEBUG }}
|
||||
@@ -195,6 +194,22 @@ jobs:
|
||||
- name: Free up space (macOS)
|
||||
if: ${{ inputs.target-platform == 'macos' }}
|
||||
uses: ./src/electron/.github/actions/free-space-macos
|
||||
- name: Download custom siso binary (Windows)
|
||||
if: ${{ inputs.target-platform == 'win' }}
|
||||
uses: actions/download-artifact@3e5f45b2cfb9172054b4087a40e8e0b5a5461e7c # v8.0.1
|
||||
with:
|
||||
name: siso-windows-amd64
|
||||
path: ${{ runner.temp }}/siso
|
||||
- name: Set SISO_PATH (Windows)
|
||||
if: ${{ inputs.target-platform == 'win' }}
|
||||
run: |
|
||||
SISO_BIN="${RUNNER_TEMP}/siso/siso.exe"
|
||||
if [ ! -f "$SISO_BIN" ]; then
|
||||
echo "error: expected siso binary at $SISO_BIN" >&2
|
||||
exit 1
|
||||
fi
|
||||
echo "SISO_PATH=$SISO_BIN" >> "$GITHUB_ENV"
|
||||
echo "Using custom siso binary at $SISO_BIN"
|
||||
- name: Build Electron
|
||||
if: ${{ inputs.target-platform != 'macos' || (inputs.target-variant == 'all' || inputs.target-variant == 'darwin') }}
|
||||
uses: ./src/electron/.github/actions/build-electron
|
||||
|
||||
@@ -126,7 +126,7 @@ jobs:
|
||||
cd src/electron
|
||||
git pack-refs
|
||||
- name: Download Out Gen Artifacts
|
||||
uses: actions/download-artifact@3e5f45b2cfb9172054b4087a40e8e0b5a5461e7c
|
||||
uses: actions/download-artifact@70fc10c6e5e1ce46ad2ea6f2b72d43f7d47b13c3
|
||||
with:
|
||||
name: out_gen_artifacts_${{ env.ARTIFACT_KEY }}
|
||||
path: ./src/out/${{ env.ELECTRON_OUT_DIR }}/gen
|
||||
@@ -135,7 +135,7 @@ jobs:
|
||||
run: echo "::add-matcher::src/electron/.github/problem-matchers/clang.json"
|
||||
- name: Run Clang-Tidy
|
||||
run: |
|
||||
e init -f --root=$(pwd) --out=${ELECTRON_OUT_DIR} testing --target-cpu ${TARGET_ARCH}
|
||||
e init -f --root=$(pwd) --out=${ELECTRON_OUT_DIR} testing --target-cpu ${TARGET_ARCH} --remote-build none
|
||||
|
||||
export GN_EXTRA_ARGS="target_cpu=\"${TARGET_ARCH}\""
|
||||
if [ "${{ inputs.target-platform }}" = "win" ]; then
|
||||
|
||||
@@ -130,7 +130,7 @@ jobs:
|
||||
run: |
|
||||
for target_cpu in ${{ inputs.target-archs }}
|
||||
do
|
||||
e init -f --root=$(pwd) --out=Default ${{ inputs.gn-build-type }} --import ${{ inputs.gn-build-type }} --target-cpu $target_cpu
|
||||
e init -f --root=$(pwd) --out=Default ${{ inputs.gn-build-type }} --import ${{ inputs.gn-build-type }} --target-cpu $target_cpu --remote-build none
|
||||
cd src
|
||||
export GN_EXTRA_ARGS="target_cpu=\"$target_cpu\""
|
||||
if [ "${{ inputs.target-platform }}" = "linux" ]; then
|
||||
|
||||
@@ -79,7 +79,6 @@ env:
|
||||
ELECTRON_ARTIFACTS_BLOB_STORAGE: ${{ secrets.ELECTRON_ARTIFACTS_BLOB_STORAGE }}
|
||||
ELECTRON_RBE_JWT: ${{ secrets.ELECTRON_RBE_JWT }}
|
||||
SUDOWOODO_EXCHANGE_URL: ${{ secrets.SUDOWOODO_EXCHANGE_URL }}
|
||||
SUDOWOODO_EXCHANGE_TOKEN: ${{ secrets.SUDOWOODO_EXCHANGE_TOKEN }}
|
||||
GCLIENT_EXTRA_ARGS: ${{ inputs.target-platform == 'macos' &&
|
||||
'--custom-var=checkout_mac=True --custom-var=host_os=mac' ||
|
||||
inputs.target-platform == 'win' && '--custom-var=checkout_win=True' ||
|
||||
@@ -208,6 +207,22 @@ jobs:
|
||||
- name: Free up space (macOS)
|
||||
if: ${{ inputs.target-platform == 'macos' }}
|
||||
uses: ./src/electron/.github/actions/free-space-macos
|
||||
- name: Download custom siso binary (Windows)
|
||||
if: ${{ inputs.target-platform == 'win' }}
|
||||
uses: actions/download-artifact@3e5f45b2cfb9172054b4087a40e8e0b5a5461e7c
|
||||
with:
|
||||
name: siso-windows-amd64
|
||||
path: ${{ runner.temp }}/siso
|
||||
- name: Set SISO_PATH (Windows)
|
||||
if: ${{ inputs.target-platform == 'win' }}
|
||||
run: |
|
||||
SISO_BIN="${RUNNER_TEMP}/siso/siso.exe"
|
||||
if [ ! -f "$SISO_BIN" ]; then
|
||||
echo "error: expected siso binary at $SISO_BIN" >&2
|
||||
exit 1
|
||||
fi
|
||||
echo "SISO_PATH=$SISO_BIN" >> "$GITHUB_ENV"
|
||||
echo "Using custom siso binary at $SISO_BIN"
|
||||
- name: Build Electron
|
||||
if: ${{ inputs.target-platform != 'macos' || (inputs.target-variant == 'all' ||
|
||||
inputs.target-variant == 'darwin') }}
|
||||
|
||||
@@ -43,7 +43,7 @@ jobs:
|
||||
fetch-depth: 0
|
||||
ref: ${{ github.event.pull_request.head.sha }}
|
||||
- name: Download Generated Artifacts
|
||||
uses: actions/download-artifact@3e5f45b2cfb9172054b4087a40e8e0b5a5461e7c
|
||||
uses: actions/download-artifact@37930b1c2abaa49bbe596cd826c3c89aef350131
|
||||
with:
|
||||
name: generated_artifacts_linux_arm64
|
||||
path: ./generated_artifacts_linux_arm64
|
||||
|
||||
@@ -66,7 +66,7 @@ jobs:
|
||||
fail-fast: false
|
||||
matrix:
|
||||
build-type: ${{ inputs.target-platform == 'macos' && fromJSON('["darwin","mas"]') || (inputs.target-platform == 'win' && fromJSON('["win"]') || fromJSON('["linux"]')) }}
|
||||
shard: ${{ case(inputs.display-server == 'wayland', fromJSON('[1]'), inputs.target-platform == 'linux', fromJSON('[1, 2, 3]'), fromJSON('[1, 2]')) }}
|
||||
shard: ${{ case(inputs.display-server == 'wayland', fromJSON('[1]'), inputs.target-platform == 'linux', fromJSON('[1, 2, 3]'), inputs.target-platform == 'macos' && inputs.target-arch == 'x64', fromJSON('[1, 2, 3]'), fromJSON('[1, 2]')) }}
|
||||
env:
|
||||
BUILD_TYPE: ${{ matrix.build-type }}
|
||||
TARGET_ARCH: ${{ inputs.target-arch }}
|
||||
@@ -175,12 +175,12 @@ jobs:
|
||||
echo "DISABLE_CRASH_REPORTER_TESTS=true" >> $GITHUB_ENV
|
||||
echo "IS_ASAN=true" >> $GITHUB_ENV
|
||||
- name: Download Generated Artifacts
|
||||
uses: actions/download-artifact@3e5f45b2cfb9172054b4087a40e8e0b5a5461e7c
|
||||
uses: actions/download-artifact@70fc10c6e5e1ce46ad2ea6f2b72d43f7d47b13c3
|
||||
with:
|
||||
name: generated_artifacts_${{ env.ARTIFACT_KEY }}
|
||||
path: ./generated_artifacts_${{ matrix.build-type }}_${{ inputs.target-arch }}
|
||||
- name: Download Src Artifacts
|
||||
uses: actions/download-artifact@3e5f45b2cfb9172054b4087a40e8e0b5a5461e7c
|
||||
uses: actions/download-artifact@70fc10c6e5e1ce46ad2ea6f2b72d43f7d47b13c3
|
||||
with:
|
||||
name: src_artifacts_${{ env.ARTIFACT_KEY }}
|
||||
path: ./src_artifacts_${{ matrix.build-type }}_${{ inputs.target-arch }}
|
||||
@@ -227,7 +227,7 @@ jobs:
|
||||
cd src/electron
|
||||
export ELECTRON_TEST_RESULTS_DIR=`pwd`/junit
|
||||
# Get which tests are on this shard
|
||||
tests_files=$(node script/split-tests ${{ matrix.shard }} ${{ case(inputs.display-server == 'wayland', 1, inputs.target-platform == 'linux', 3, 2) }})
|
||||
tests_files=$(node script/split-tests ${{ matrix.shard }} ${{ case(inputs.display-server == 'wayland', 1, inputs.target-platform == 'linux', 3, inputs.target-platform == 'macos' && inputs.target-arch == 'x64', 3, 2) }})
|
||||
if [ "${{ inputs.display-server }}" = "wayland" ]; then
|
||||
allowlist_file=script/wayland-test-allowlist.txt
|
||||
filtered_tests=""
|
||||
|
||||
@@ -67,12 +67,12 @@ jobs:
|
||||
- name: Install Dependencies
|
||||
uses: ./src/electron/.github/actions/install-dependencies
|
||||
- name: Download Generated Artifacts
|
||||
uses: actions/download-artifact@3e5f45b2cfb9172054b4087a40e8e0b5a5461e7c
|
||||
uses: actions/download-artifact@70fc10c6e5e1ce46ad2ea6f2b72d43f7d47b13c3
|
||||
with:
|
||||
name: generated_artifacts_${{ env.BUILD_TYPE }}_${{ env.TARGET_ARCH }}
|
||||
path: ./generated_artifacts_${{ env.BUILD_TYPE }}_${{ env.TARGET_ARCH }}
|
||||
- name: Download Src Artifacts
|
||||
uses: actions/download-artifact@3e5f45b2cfb9172054b4087a40e8e0b5a5461e7c
|
||||
uses: actions/download-artifact@70fc10c6e5e1ce46ad2ea6f2b72d43f7d47b13c3
|
||||
with:
|
||||
name: src_artifacts_linux_${{ env.TARGET_ARCH }}
|
||||
path: ./src_artifacts_linux_${{ env.TARGET_ARCH }}
|
||||
@@ -123,12 +123,12 @@ jobs:
|
||||
- name: Install Dependencies
|
||||
uses: ./src/electron/.github/actions/install-dependencies
|
||||
- name: Download Generated Artifacts
|
||||
uses: actions/download-artifact@3e5f45b2cfb9172054b4087a40e8e0b5a5461e7c
|
||||
uses: actions/download-artifact@70fc10c6e5e1ce46ad2ea6f2b72d43f7d47b13c3
|
||||
with:
|
||||
name: generated_artifacts_${{ env.BUILD_TYPE }}_${{ env.TARGET_ARCH }}
|
||||
path: ./generated_artifacts_${{ env.BUILD_TYPE }}_${{ env.TARGET_ARCH }}
|
||||
- name: Download Src Artifacts
|
||||
uses: actions/download-artifact@3e5f45b2cfb9172054b4087a40e8e0b5a5461e7c
|
||||
uses: actions/download-artifact@70fc10c6e5e1ce46ad2ea6f2b72d43f7d47b13c3
|
||||
with:
|
||||
name: src_artifacts_linux_${{ env.TARGET_ARCH }}
|
||||
path: ./src_artifacts_linux_${{ env.TARGET_ARCH }}
|
||||
|
||||
58
.github/workflows/pr-template-check.yml
vendored
58
.github/workflows/pr-template-check.yml
vendored
@@ -1,58 +0,0 @@
|
||||
name: PR Template Check
|
||||
|
||||
on:
|
||||
pull_request_target:
|
||||
types: [opened, ready_for_review]
|
||||
|
||||
# SECURITY: This workflow uses pull_request_target and has access to secrets.
|
||||
# Do NOT checkout or run code from the PR head. All code execution must use
|
||||
# the base branch only. Adding a ref to PR head would expose secrets to
|
||||
# untrusted code.
|
||||
permissions: {}
|
||||
|
||||
jobs:
|
||||
check-pr-template:
|
||||
if: ${{ github.event.pull_request.head.repo.fork && !github.event.pull_request.draft && !startsWith(github.head_ref, 'roller/') }}
|
||||
name: Check PR Template
|
||||
runs-on: ubuntu-slim
|
||||
permissions:
|
||||
contents: read
|
||||
pull-requests: write
|
||||
steps:
|
||||
- name: Checkout
|
||||
uses: actions/checkout@de0fac2e4500dabe0009e67214ff5f5447ce83dd
|
||||
with:
|
||||
sparse-checkout: .github/PULL_REQUEST_TEMPLATE.md
|
||||
sparse-checkout-cone-mode: false
|
||||
- name: Check for required sections
|
||||
uses: actions/github-script@ed597411d8f924073f98dfc5c65a23a2325f34cd # v8.0.0
|
||||
with:
|
||||
script: |
|
||||
const fs = require('fs');
|
||||
const template = fs.readFileSync('.github/PULL_REQUEST_TEMPLATE.md', 'utf8');
|
||||
const requiredSections = [...template.matchAll(/^(#{1,4} .+)$/gm)].map(
|
||||
(m) => m[1],
|
||||
);
|
||||
if (requiredSections.length === 0) {
|
||||
console.log('No heading sections found in PR template');
|
||||
return;
|
||||
}
|
||||
const body = context.payload.pull_request.body || '';
|
||||
const missingSections = requiredSections.filter(
|
||||
(section) => !body.includes(section),
|
||||
);
|
||||
if (missingSections.length > 0) {
|
||||
const list = missingSections.map((s) => `- \`${s}\``).join('\n');
|
||||
await github.rest.issues.createComment({
|
||||
owner: context.repo.owner,
|
||||
repo: context.repo.repo,
|
||||
issue_number: context.payload.pull_request.number,
|
||||
body: `This PR was automatically closed because the PR template was not properly filled out. The following required sections are missing:\n\n${list}\n\nPlease update your PR description to include all required sections and reopen the PR.`,
|
||||
});
|
||||
await github.rest.pulls.update({
|
||||
owner: context.repo.owner,
|
||||
repo: context.repo.repo,
|
||||
pull_number: context.payload.pull_request.number,
|
||||
state: 'closed',
|
||||
});
|
||||
}
|
||||
46
.github/workflows/pr-triage-automation.yml
vendored
46
.github/workflows/pr-triage-automation.yml
vendored
@@ -1,46 +0,0 @@
|
||||
name: PR Triage Automation
|
||||
|
||||
on:
|
||||
pull_request_target:
|
||||
types: [synchronize, review_requested]
|
||||
issue_comment:
|
||||
types: [created]
|
||||
|
||||
# SECURITY: This workflow uses pull_request_target and has access to secrets.
|
||||
# Do NOT checkout or run code from the PR head. All code execution must use
|
||||
# the base branch only. Adding a ref to PR head would expose secrets to
|
||||
# untrusted code.
|
||||
permissions: {}
|
||||
|
||||
jobs:
|
||||
set-needs-review:
|
||||
name: Set status to Needs Review
|
||||
if: >-
|
||||
(github.event_name == 'pull_request_target'
|
||||
&& github.event.pull_request.state == 'open'
|
||||
&& github.event.pull_request.draft != true
|
||||
&& !contains(github.event.pull_request.labels.*.name, 'wip ⚒')
|
||||
&& (github.event.action == 'synchronize' || github.event.action == 'review_requested'))
|
||||
|| (github.event_name == 'issue_comment'
|
||||
&& github.event.issue.pull_request
|
||||
&& github.event.issue.state == 'open'
|
||||
&& !contains(github.event.issue.labels.*.name, 'wip ⚒')
|
||||
&& github.event.comment.user.login == github.event.issue.user.login)
|
||||
runs-on: ubuntu-slim
|
||||
permissions:
|
||||
contents: read
|
||||
steps:
|
||||
- name: Generate GitHub App token
|
||||
uses: electron/github-app-auth-action@e14e47722ed120360649d0789e25b9baece12725 # v2.0.0
|
||||
id: generate-token
|
||||
with:
|
||||
creds: ${{ secrets.ISSUE_TRIAGE_GH_APP_CREDS }}
|
||||
org: electron
|
||||
- name: Set status to Needs Review
|
||||
uses: dsanders11/project-actions/edit-item@5767984408ccc6742f83acc8b8d8ea5e09f329af # v2.0.0
|
||||
with:
|
||||
token: ${{ steps.generate-token.outputs.token }}
|
||||
project-number: 118
|
||||
field: Status
|
||||
field-value: 🌀 Needs Review
|
||||
fail-if-item-not-found: false
|
||||
10
.github/workflows/pull-request-labeled.yml
vendored
10
.github/workflows/pull-request-labeled.yml
vendored
@@ -18,7 +18,7 @@ jobs:
|
||||
permissions: {}
|
||||
steps:
|
||||
- name: Trigger Slack workflow
|
||||
uses: slackapi/slack-github-action@af78098f536edbc4de71162a307590698245be95 # v3.0.1
|
||||
uses: slackapi/slack-github-action@91efab103c0de0a537f72a35f6b8cda0ee76bf0a # v2.1.1
|
||||
with:
|
||||
webhook: ${{ secrets.BACKPORT_REQUESTED_SLACK_WEBHOOK_URL }}
|
||||
webhook-type: webhook-trigger
|
||||
@@ -42,7 +42,7 @@ jobs:
|
||||
creds: ${{ secrets.RELEASE_BOARD_GH_APP_CREDS }}
|
||||
org: electron
|
||||
- name: Set status
|
||||
uses: dsanders11/project-actions/edit-item@5767984408ccc6742f83acc8b8d8ea5e09f329af # v2.0.0
|
||||
uses: dsanders11/project-actions/edit-item@2134fe7cc71c58b7ae259c82a8e63c6058255678 # v1.7.0
|
||||
with:
|
||||
token: ${{ steps.generate-token.outputs.token }}
|
||||
project-number: 94
|
||||
@@ -50,7 +50,7 @@ jobs:
|
||||
field-value: ✅ Reviewed
|
||||
pull-request-labeled-ai-pr:
|
||||
name: ai-pr label added
|
||||
if: github.event.label.name == 'ai-pr' && github.event.pull_request.state != 'closed'
|
||||
if: github.event.label.name == 'ai-pr'
|
||||
runs-on: ubuntu-latest
|
||||
permissions: {}
|
||||
steps:
|
||||
@@ -60,7 +60,7 @@ jobs:
|
||||
with:
|
||||
creds: ${{ secrets.ISSUE_TRIAGE_GH_APP_CREDS }}
|
||||
- name: Create comment
|
||||
uses: actions-cool/issues-helper@200c78641dbf33838311e5a1e0c31bbdb92d7cf0 # v3.8.0
|
||||
uses: actions-cool/issues-helper@71b62d7da76e59ff7b193904feb6e77d4dbb2777 # v3.7.6
|
||||
with:
|
||||
actions: 'create-comment'
|
||||
token: ${{ steps.generate-token.outputs.token }}
|
||||
@@ -72,7 +72,7 @@ jobs:
|
||||
|
||||
Hello @${{ github.event.pull_request.user.login }}. Due to the high amount of AI spam PRs we receive, if a PR is detected to be majority AI-generated without disclosure and untested, we will automatically close the PR.
|
||||
|
||||
We welcome the use of AI tools, as long as the PR meets our quality standards and has clearly been built and tested. If you believe your PR was closed in error, we welcome you to resubmit. However, please read our [CONTRIBUTING.md](https://github.com/electron/electron/blob/main/CONTRIBUTING.md) and [AI Tool Policy](https://github.com/electron/governance/blob/main/policy/ai.md) carefully before reopening. Thanks for your contribution.
|
||||
We welcome the use of AI tools, as long as the PR meets our quality standards and has clearly been built and tested. If you believe your PR was closed in error, we welcome you to resubmit. However, please read our [CONTRIBUTING.md](http://contributing.md/) carefully before reopening. Thanks for your contribution.
|
||||
- name: Close the pull request
|
||||
env:
|
||||
GITHUB_TOKEN: ${{ steps.generate-token.outputs.token }}
|
||||
|
||||
2
.github/workflows/scorecards.yml
vendored
2
.github/workflows/scorecards.yml
vendored
@@ -51,6 +51,6 @@ jobs:
|
||||
|
||||
# Upload the results to GitHub's code scanning dashboard.
|
||||
- name: "Upload to code-scanning"
|
||||
uses: github/codeql-action/upload-sarif@c10b8064de6f491fea524254123dbe5e09572f13 # v3.29.5
|
||||
uses: github/codeql-action/upload-sarif@0d579ffd059c29b07949a3cce3983f0780820c98 # v3.29.5
|
||||
with:
|
||||
sarif_file: results.sarif
|
||||
|
||||
2
.github/workflows/stable-prep-items.yml
vendored
2
.github/workflows/stable-prep-items.yml
vendored
@@ -29,7 +29,7 @@ jobs:
|
||||
PROJECT_NUMBER=$(gh project list --owner electron --format json | jq -r '.projects | map(select(.title | test("^[0-9]+-x-y$"))) | max_by(.number) | .number')
|
||||
echo "PROJECT_NUMBER=$PROJECT_NUMBER" >> "$GITHUB_OUTPUT"
|
||||
- name: Update Completed Stable Prep Items
|
||||
uses: dsanders11/project-actions/completed-by@5767984408ccc6742f83acc8b8d8ea5e09f329af # v2.0.0
|
||||
uses: dsanders11/project-actions/completed-by@2134fe7cc71c58b7ae259c82a8e63c6058255678 # v1.7.0
|
||||
with:
|
||||
field: Prep Status
|
||||
field-value: ✅ Complete
|
||||
|
||||
14
.github/workflows/windows-publish.yml
vendored
14
.github/workflows/windows-publish.yml
vendored
@@ -51,6 +51,14 @@ jobs:
|
||||
generate-sas-token: 'true'
|
||||
target-platform: win
|
||||
|
||||
# Build the patched siso binary in parallel with checkout-windows; the
|
||||
# publish-*-win jobs consume it via SISO_PATH.
|
||||
build-siso-windows:
|
||||
if: github.repository == 'electron/electron'
|
||||
uses: ./.github/workflows/pipeline-segment-build-siso-windows.yml
|
||||
permissions:
|
||||
contents: read
|
||||
|
||||
publish-x64-win:
|
||||
uses: ./.github/workflows/pipeline-segment-electron-publish.yml
|
||||
permissions:
|
||||
@@ -58,7 +66,7 @@ jobs:
|
||||
attestations: write
|
||||
contents: read
|
||||
id-token: write
|
||||
needs: checkout-windows
|
||||
needs: [checkout-windows, build-siso-windows]
|
||||
with:
|
||||
environment: production-release
|
||||
build-runs-on: electron-arc-centralus-windows-amd64-16core
|
||||
@@ -77,7 +85,7 @@ jobs:
|
||||
attestations: write
|
||||
contents: read
|
||||
id-token: write
|
||||
needs: checkout-windows
|
||||
needs: [checkout-windows, build-siso-windows]
|
||||
with:
|
||||
environment: production-release
|
||||
build-runs-on: electron-arc-centralus-windows-amd64-16core
|
||||
@@ -96,7 +104,7 @@ jobs:
|
||||
attestations: write
|
||||
contents: read
|
||||
id-token: write
|
||||
needs: checkout-windows
|
||||
needs: [checkout-windows, build-siso-windows]
|
||||
with:
|
||||
environment: production-release
|
||||
build-runs-on: electron-arc-centralus-windows-amd64-16core
|
||||
|
||||
329
.oxlintrc.json
329
.oxlintrc.json
@@ -1,329 +0,0 @@
|
||||
{
|
||||
"$schema": "./node_modules/oxlint/configuration_schema.json",
|
||||
"plugins": [
|
||||
"typescript",
|
||||
"import",
|
||||
"node",
|
||||
"promise",
|
||||
"unicorn"
|
||||
],
|
||||
"jsPlugins": [
|
||||
{
|
||||
"name": "no-only-tests",
|
||||
"specifier": "./script/lint-plugins/no-only-tests.mjs"
|
||||
}
|
||||
],
|
||||
"categories": {
|
||||
"correctness": "off"
|
||||
},
|
||||
"options": {
|
||||
"typeAware": false
|
||||
},
|
||||
"env": {
|
||||
"builtin": true,
|
||||
"browser": true
|
||||
},
|
||||
"ignorePatterns": [
|
||||
".github/workflows/node_modules",
|
||||
"spec/node_modules",
|
||||
"spec/fixtures/native-addon",
|
||||
"shell/browser/resources/win/resource.h",
|
||||
"shell/common/node_includes.h",
|
||||
"spec/fixtures/pages/jquery-3.6.0.min.js"
|
||||
],
|
||||
"rules": {
|
||||
"no-var": "error",
|
||||
"accessor-pairs": [
|
||||
"error",
|
||||
{
|
||||
"setWithoutGet": true,
|
||||
"enforceForClassMembers": true
|
||||
}
|
||||
],
|
||||
"array-callback-return": [
|
||||
"error",
|
||||
{
|
||||
"allowImplicit": false,
|
||||
"checkForEach": false
|
||||
}
|
||||
],
|
||||
"constructor-super": "error",
|
||||
"curly": [
|
||||
"error",
|
||||
"multi-line"
|
||||
],
|
||||
"default-case-last": "error",
|
||||
"eqeqeq": [
|
||||
"error",
|
||||
"always",
|
||||
{
|
||||
"null": "ignore"
|
||||
}
|
||||
],
|
||||
"new-cap": [
|
||||
"error",
|
||||
{
|
||||
"newIsCap": true,
|
||||
"capIsNew": false,
|
||||
"properties": true
|
||||
}
|
||||
],
|
||||
"no-array-constructor": "error",
|
||||
"no-async-promise-executor": "error",
|
||||
"no-caller": "error",
|
||||
"no-case-declarations": "error",
|
||||
"no-class-assign": "error",
|
||||
"no-compare-neg-zero": "error",
|
||||
"no-cond-assign": "error",
|
||||
"no-const-assign": "error",
|
||||
"no-constant-condition": [
|
||||
"error",
|
||||
{
|
||||
"checkLoops": false
|
||||
}
|
||||
],
|
||||
"no-control-regex": "error",
|
||||
"no-debugger": "error",
|
||||
"no-delete-var": "error",
|
||||
"no-dupe-class-members": "error",
|
||||
"no-dupe-keys": "error",
|
||||
"no-duplicate-case": "error",
|
||||
"no-useless-backreference": "error",
|
||||
"no-empty": [
|
||||
"error",
|
||||
{
|
||||
"allowEmptyCatch": true
|
||||
}
|
||||
],
|
||||
"no-empty-character-class": "error",
|
||||
"no-empty-pattern": "error",
|
||||
"no-eval": "error",
|
||||
"no-ex-assign": "error",
|
||||
"no-extend-native": "error",
|
||||
"no-extra-bind": "error",
|
||||
"no-extra-boolean-cast": "error",
|
||||
"no-fallthrough": "error",
|
||||
"no-func-assign": "error",
|
||||
"no-global-assign": "error",
|
||||
"no-import-assign": "error",
|
||||
"no-invalid-regexp": "error",
|
||||
"no-irregular-whitespace": "error",
|
||||
"no-iterator": "error",
|
||||
"no-labels": [
|
||||
"error",
|
||||
{
|
||||
"allowLoop": false,
|
||||
"allowSwitch": false
|
||||
}
|
||||
],
|
||||
"no-lone-blocks": "error",
|
||||
"no-loss-of-precision": "error",
|
||||
"no-misleading-character-class": "error",
|
||||
"no-prototype-builtins": "error",
|
||||
"no-useless-catch": "error",
|
||||
"no-useless-constructor": "error",
|
||||
"no-use-before-define": [
|
||||
"error",
|
||||
{
|
||||
"functions": false,
|
||||
"classes": false,
|
||||
"variables": false
|
||||
}
|
||||
],
|
||||
"no-multi-str": "error",
|
||||
"no-new": "error",
|
||||
"no-new-func": "error",
|
||||
"no-new-wrappers": "error",
|
||||
"no-obj-calls": "error",
|
||||
"no-proto": "error",
|
||||
"no-redeclare": [
|
||||
"error"
|
||||
],
|
||||
"no-regex-spaces": "error",
|
||||
"no-return-assign": [
|
||||
"error",
|
||||
"except-parens"
|
||||
],
|
||||
"no-self-assign": [
|
||||
"error",
|
||||
{
|
||||
"props": true
|
||||
}
|
||||
],
|
||||
"no-self-compare": "error",
|
||||
"no-sequences": "error",
|
||||
"no-shadow-restricted-names": "error",
|
||||
"no-sparse-arrays": "error",
|
||||
"no-template-curly-in-string": "error",
|
||||
"no-this-before-super": "error",
|
||||
"no-throw-literal": "error",
|
||||
"no-unexpected-multiline": "error",
|
||||
"no-unmodified-loop-condition": "error",
|
||||
"no-unneeded-ternary": [
|
||||
"error",
|
||||
{
|
||||
"defaultAssignment": false
|
||||
}
|
||||
],
|
||||
"no-unreachable": "error",
|
||||
"no-unsafe-finally": "error",
|
||||
"no-unsafe-negation": "error",
|
||||
"no-unused-vars": [
|
||||
"error",
|
||||
{
|
||||
"vars": "all",
|
||||
"args": "after-used",
|
||||
"argsIgnorePattern": "^_",
|
||||
"ignoreRestSiblings": true
|
||||
}
|
||||
],
|
||||
"no-useless-call": "error",
|
||||
"no-useless-computed-key": "error",
|
||||
"no-useless-escape": "error",
|
||||
"no-useless-rename": "error",
|
||||
"no-useless-return": "error",
|
||||
"no-void": "error",
|
||||
"no-with": "error",
|
||||
"prefer-const": [
|
||||
"error",
|
||||
{
|
||||
"destructuring": "all"
|
||||
}
|
||||
],
|
||||
"prefer-promise-reject-errors": "error",
|
||||
"symbol-description": "error",
|
||||
"unicode-bom": [
|
||||
"error",
|
||||
"never"
|
||||
],
|
||||
"use-isnan": [
|
||||
"error",
|
||||
{
|
||||
"enforceForSwitchCase": true,
|
||||
"enforceForIndexOf": true
|
||||
}
|
||||
],
|
||||
"valid-typeof": [
|
||||
"error",
|
||||
{
|
||||
"requireStringLiterals": true
|
||||
}
|
||||
],
|
||||
"yoda": [
|
||||
"error",
|
||||
"never"
|
||||
],
|
||||
"import/export": "error",
|
||||
"import/first": "error",
|
||||
"import/no-absolute-path": [
|
||||
"error",
|
||||
{
|
||||
"esmodule": true,
|
||||
"commonjs": true,
|
||||
"amd": false
|
||||
}
|
||||
],
|
||||
"import/no-duplicates": "error",
|
||||
"import/no-named-default": "error",
|
||||
"import/no-webpack-loader-syntax": "error",
|
||||
"promise/param-names": "error",
|
||||
"guard-for-in": "error",
|
||||
"node/handle-callback-err": [
|
||||
"error",
|
||||
"^(err|error)$"
|
||||
],
|
||||
"node/no-exports-assign": "error",
|
||||
"node/no-new-require": "error",
|
||||
"node/no-path-concat": "error"
|
||||
},
|
||||
"overrides": [
|
||||
{
|
||||
"files": ["**/*.ts", "**/*.tsx", "**/*.mts", "**/*.cts"],
|
||||
"rules": {
|
||||
"no-use-before-define": "off"
|
||||
}
|
||||
},
|
||||
{
|
||||
"files": ["lib/browser/**", "lib/utility/**"],
|
||||
"rules": {
|
||||
"no-restricted-imports": [
|
||||
"error",
|
||||
{
|
||||
"paths": ["electron", "electron/renderer"],
|
||||
"patterns": [
|
||||
"./*",
|
||||
"../*",
|
||||
"@electron/internal/isolated_renderer/*",
|
||||
"@electron/internal/renderer/*",
|
||||
"@electron/internal/sandboxed_worker/*",
|
||||
"@electron/internal/worker/*"
|
||||
]
|
||||
}
|
||||
]
|
||||
}
|
||||
},
|
||||
{
|
||||
"files": [
|
||||
"lib/renderer/**",
|
||||
"lib/worker/**",
|
||||
"lib/preload_realm/**",
|
||||
"lib/sandboxed_renderer/**",
|
||||
"lib/isolated_renderer/**"
|
||||
],
|
||||
"rules": {
|
||||
"no-restricted-imports": [
|
||||
"error",
|
||||
{
|
||||
"paths": ["electron", "electron/main"],
|
||||
"patterns": ["./*", "../*", "@electron/internal/browser/*"]
|
||||
}
|
||||
]
|
||||
}
|
||||
},
|
||||
{
|
||||
"files": ["lib/common/**"],
|
||||
"rules": {
|
||||
"no-restricted-imports": [
|
||||
"error",
|
||||
{
|
||||
"paths": ["electron", "electron/main", "electron/renderer"],
|
||||
"patterns": [
|
||||
"./*",
|
||||
"../*",
|
||||
"@electron/internal/browser/*",
|
||||
"@electron/internal/isolated_renderer/*",
|
||||
"@electron/internal/renderer/*",
|
||||
"@electron/internal/sandboxed_worker/*",
|
||||
"@electron/internal/worker/*"
|
||||
]
|
||||
}
|
||||
]
|
||||
}
|
||||
},
|
||||
{
|
||||
"files": [
|
||||
"build/**",
|
||||
"script/**",
|
||||
"docs/**",
|
||||
"default_app/**",
|
||||
"spec/**"
|
||||
],
|
||||
"rules": {
|
||||
"unicorn/prefer-node-protocol": "error"
|
||||
}
|
||||
},
|
||||
{
|
||||
"files": ["spec/**/*.ts", "spec/**/*.js", "spec/**/*.mjs"],
|
||||
"rules": {
|
||||
"no-only-tests/no-only-tests": "error"
|
||||
}
|
||||
},
|
||||
{
|
||||
"files": ["**/*.d.ts"],
|
||||
"rules": {
|
||||
"no-useless-constructor": "off",
|
||||
"no-unused-vars": "off"
|
||||
}
|
||||
}
|
||||
]
|
||||
}
|
||||
20
BUILD.gn
20
BUILD.gn
@@ -147,25 +147,6 @@ config("branding") {
|
||||
|
||||
config("electron_lib_config") {
|
||||
include_dirs = [ "." ]
|
||||
cflags = []
|
||||
if (is_clang && clang_use_chrome_plugins) {
|
||||
# The plugin is built directly into clang, so there's no need to load it
|
||||
# dynamically.
|
||||
cflags += [
|
||||
"-Xclang",
|
||||
"-add-plugin",
|
||||
"-Xclang",
|
||||
"blink-gc-plugin",
|
||||
"-Xclang",
|
||||
"-plugin-arg-blink-gc-plugin",
|
||||
"-Xclang",
|
||||
"check-directory=electron/shell/",
|
||||
"-Xclang",
|
||||
"-plugin-arg-blink-gc-plugin",
|
||||
"-Xclang",
|
||||
"check-directory=gin/",
|
||||
]
|
||||
}
|
||||
}
|
||||
|
||||
# We generate the definitions twice here, once in //electron/electron.d.ts
|
||||
@@ -509,6 +490,7 @@ source_set("electron_lib") {
|
||||
"//components/pref_registry",
|
||||
"//components/prefs",
|
||||
"//components/security_state/content",
|
||||
"//components/tracing:tracing_metrics",
|
||||
"//components/upload_list",
|
||||
"//components/user_prefs",
|
||||
"//components/viz/host",
|
||||
|
||||
16
CLAUDE.md
16
CLAUDE.md
@@ -1,14 +1,5 @@
|
||||
# Electron Development Guide
|
||||
|
||||
## Running node_modules binaries
|
||||
|
||||
**Never use `npx`.** It is considered dangerous because it can silently fetch and execute arbitrary packages from the registry. Always run binaries through one of these safer mechanisms instead:
|
||||
|
||||
1. **Preferred** — spawn the executable directly from `node_modules/.bin/<tool>` (or the platform equivalent on Windows). This is what `script/lint.js` does for `oxlint`.
|
||||
2. **Acceptable** — invoke via `yarn <tool>` or `yarn run <tool>`, which resolves to the locally installed version without the registry fallback that `npx` performs.
|
||||
|
||||
This rule applies to shell commands you run yourself and to any scripts you author or modify in this repo.
|
||||
|
||||
## Project Overview
|
||||
|
||||
Electron is a framework for building cross-platform desktop applications using web technologies. It embeds Chromium for rendering and Node.js for backend functionality.
|
||||
@@ -180,6 +171,10 @@ e test # Run full test suite
|
||||
|
||||
When working on the `roller/chromium/main` branch to upgrade Chromium activate the "Electron Chromium Upgrade" skill.
|
||||
|
||||
## Node.js Upgrade Workflow
|
||||
|
||||
When working on the `roller/node/main` branch to upgrade Node.js activate the "Electron Node.js Upgrade" skill.
|
||||
|
||||
## Pull Requests
|
||||
|
||||
PR bodies must always include a `Notes:` section as the **last line** of the body. This is a consumer-facing release note for Electron app developers — describe the user-visible fix or change, not internal implementation details. Use `Notes: none` if there is no user-facing change.
|
||||
@@ -210,13 +205,12 @@ gh label list --repo electron/electron --search target/ --json name,color --jq '
|
||||
## Code Style
|
||||
|
||||
**C++:** Follows Chromium style, enforced by clang-format
|
||||
**TypeScript/JavaScript:** [oxlint](https://oxc.rs/docs/guide/usage/linter) configuration in `.oxlintrc.json`
|
||||
**TypeScript/JavaScript:** ESLint configuration in `.eslintrc.json`
|
||||
|
||||
**Linting:**
|
||||
|
||||
```bash
|
||||
npm run lint # Run all linters
|
||||
npm run lint:js # Run oxlint over all JS/TS/MJS sources
|
||||
npm run lint:clang-format # C++ formatting
|
||||
npm run lint:api-history # Validate API history YAML blocks in docs
|
||||
```
|
||||
|
||||
2
DEPS
2
DEPS
@@ -2,7 +2,7 @@ gclient_gn_args_from = 'src'
|
||||
|
||||
vars = {
|
||||
'chromium_version':
|
||||
'148.0.7778.0',
|
||||
'148.0.7778.5',
|
||||
'node_version':
|
||||
'v24.14.1',
|
||||
'nan_version':
|
||||
|
||||
8
build/.eslintrc.json
Normal file
8
build/.eslintrc.json
Normal file
@@ -0,0 +1,8 @@
|
||||
{
|
||||
"plugins": [
|
||||
"import"
|
||||
],
|
||||
"rules": {
|
||||
"import/enforce-node-protocol-usage": ["error", "always"]
|
||||
}
|
||||
}
|
||||
8
default_app/.eslintrc.json
Normal file
8
default_app/.eslintrc.json
Normal file
@@ -0,0 +1,8 @@
|
||||
{
|
||||
"plugins": [
|
||||
"import"
|
||||
],
|
||||
"rules": {
|
||||
"import/enforce-node-protocol-usage": ["error", "always"]
|
||||
}
|
||||
}
|
||||
35
docs/.eslintrc.json
Normal file
35
docs/.eslintrc.json
Normal file
@@ -0,0 +1,35 @@
|
||||
{
|
||||
"extends": "standard",
|
||||
"plugins": [
|
||||
"import",
|
||||
"markdown"
|
||||
],
|
||||
"overrides": [
|
||||
{
|
||||
"files": ["*.md", "**/*.md"],
|
||||
"processor": "markdown/markdown"
|
||||
}
|
||||
],
|
||||
"rules": {
|
||||
"@typescript-eslint/no-unused-vars": "off",
|
||||
"import/order": ["error", {
|
||||
"alphabetize": {
|
||||
"order": "asc"
|
||||
},
|
||||
"newlines-between": "always",
|
||||
"pathGroups": [
|
||||
{
|
||||
"pattern": "{electron,electron/**}",
|
||||
"group": "builtin",
|
||||
"position": "before"
|
||||
}
|
||||
],
|
||||
"pathGroupsExcludedImportTypes": []
|
||||
}],
|
||||
"n/no-callback-literal": "off",
|
||||
"no-undef": "off",
|
||||
"no-unused-expressions": "off",
|
||||
"no-unused-vars": "off",
|
||||
"import/enforce-node-protocol-usage": ["error", "always"]
|
||||
}
|
||||
}
|
||||
@@ -28,10 +28,7 @@ added:
|
||||
* `window` [BaseWindow](base-window.md) (optional)
|
||||
* `options` Object
|
||||
* `title` string (optional)
|
||||
* `defaultPath` string (optional) - Absolute directory path, absolute file
|
||||
path, or file name to use by default. If not provided, the dialog will
|
||||
default to the user's Downloads folder, or their home directory if Downloads
|
||||
doesn't exist.
|
||||
* `defaultPath` string (optional)
|
||||
* `buttonLabel` string (optional) - Custom label for the confirmation button, when
|
||||
left empty the default label will be used.
|
||||
* `filters` [FileFilter[]](structures/file-filter.md) (optional)
|
||||
@@ -112,10 +109,7 @@ changes:
|
||||
* `window` [BaseWindow](base-window.md) (optional)
|
||||
* `options` Object
|
||||
* `title` string (optional)
|
||||
* `defaultPath` string (optional) - Absolute directory path, absolute file
|
||||
path, or file name to use by default. If not provided, the dialog will
|
||||
default to the user's Downloads folder, or their home directory if Downloads
|
||||
doesn't exist.
|
||||
* `defaultPath` string (optional)
|
||||
* `buttonLabel` string (optional) - Custom label for the confirmation button, when
|
||||
left empty the default label will be used.
|
||||
* `filters` [FileFilter[]](structures/file-filter.md) (optional)
|
||||
@@ -204,9 +198,7 @@ added:
|
||||
* `options` Object
|
||||
* `title` string (optional) - The dialog title. Cannot be displayed on some _Linux_ desktop environments.
|
||||
* `defaultPath` string (optional) - Absolute directory path, absolute file
|
||||
path, or file name to use by default. If not provided, the dialog will
|
||||
default to the user's Downloads folder, or their home directory if Downloads
|
||||
doesn't exist.
|
||||
path, or file name to use by default.
|
||||
* `buttonLabel` string (optional) - Custom label for the confirmation button, when
|
||||
left empty the default label will be used.
|
||||
* `filters` [FileFilter[]](structures/file-filter.md) (optional)
|
||||
@@ -246,9 +238,7 @@ changes:
|
||||
* `options` Object
|
||||
* `title` string (optional) - The dialog title. Cannot be displayed on some _Linux_ desktop environments.
|
||||
* `defaultPath` string (optional) - Absolute directory path, absolute file
|
||||
path, or file name to use by default. If not provided, the dialog will
|
||||
default to the user's Downloads folder, or their home directory if Downloads
|
||||
doesn't exist.
|
||||
path, or file name to use by default.
|
||||
* `buttonLabel` string (optional) - Custom label for the confirmation button, when
|
||||
left empty the default label will be used.
|
||||
* `filters` [FileFilter[]](structures/file-filter.md) (optional)
|
||||
|
||||
@@ -56,9 +56,6 @@ Returns `string` - The badge string of the dock.
|
||||
|
||||
Hides the dock icon.
|
||||
|
||||
> [!IMPORTANT]
|
||||
> **Known issue:** Calling `dock.hide()` within one second of a previous call will have no effect. As a workaround, ensure at least one second has elapsed between calls — for example, by deferring with a `setTimeout` of 1100ms or more after a previous call.
|
||||
|
||||
#### `dock.show()` _macOS_
|
||||
|
||||
Returns `Promise<void>` - Resolves when the dock icon is shown.
|
||||
|
||||
@@ -59,12 +59,7 @@ On Windows, returns true once the app has emitted the `ready` event.
|
||||
|
||||
### `safeStorage.isAsyncEncryptionAvailable()`
|
||||
|
||||
Returns `Promise<boolean>` - Resolves with whether encryption is available for
|
||||
asynchronous safeStorage operations.
|
||||
|
||||
The asynchronous encryptor is initialized lazily the first time this method,
|
||||
`encryptStringAsync`, or `decryptStringAsync` is called after the app is ready.
|
||||
The returned promise resolves once initialization completes.
|
||||
Returns `Promise<Boolean>` - Whether encryption is available for asynchronous safeStorage operations.
|
||||
|
||||
### `safeStorage.encryptString(plainText)`
|
||||
|
||||
|
||||
@@ -94,7 +94,6 @@
|
||||
The actual output pixel format and color space of the texture should refer to [`OffscreenSharedTexture`](../structures/offscreen-shared-texture.md) object in the `paint` event.
|
||||
* `argb` - The requested output texture format is 8-bit unorm RGBA, with SRGB SDR color space.
|
||||
* `rgbaf16` - The requested output texture format is 16-bit float RGBA, with scRGB HDR color space.
|
||||
* `nv12` - The requested output texture format is 12bpp with Y plane followed by a 2x2 interleaved UV plane, with REC709 color space.
|
||||
* `deviceScaleFactor` number (optional) _Experimental_ - The device scale factor of the offscreen rendering output. If not set, will use `1` as default.
|
||||
* `contextIsolation` boolean (optional) - Whether to run Electron APIs and
|
||||
the specified `preload` script in a separate JavaScript context. Defaults
|
||||
|
||||
@@ -1585,20 +1585,6 @@ Centers the current text selection in web page.
|
||||
|
||||
Copy the image at the given position to the clipboard.
|
||||
|
||||
#### `contents.copyVideoFrameAt(x, y)`
|
||||
|
||||
* `x` Integer
|
||||
* `y` Integer
|
||||
|
||||
When executed on a video media element, copies the frame at (x, y) to the clipboard.
|
||||
|
||||
#### `contents.saveVideoFrameAs(x, y)`
|
||||
|
||||
* `x` Integer
|
||||
* `y` Integer
|
||||
|
||||
When executed on a video media element, shows a save dialog and saves the frame at (x, y) to disk.
|
||||
|
||||
#### `contents.paste()`
|
||||
|
||||
Executes the editing command `paste` in web page.
|
||||
|
||||
@@ -175,20 +175,6 @@ app.on('web-contents-created', (_, webContents) => {
|
||||
})
|
||||
```
|
||||
|
||||
#### `frame.copyVideoFrameAt(x, y)`
|
||||
|
||||
* `x` Integer
|
||||
* `y` Integer
|
||||
|
||||
When executed on a video media element, copies the frame at (x, y) to the clipboard.
|
||||
|
||||
#### `frame.saveVideoFrameAs(x, y)`
|
||||
|
||||
* `x` Integer
|
||||
* `y` Integer
|
||||
|
||||
When executed on a video media element, shows a save dialog and saves the frame at (x, y) to disk.
|
||||
|
||||
### Instance Properties
|
||||
|
||||
#### `frame.ipc` _Readonly_
|
||||
|
||||
@@ -12,34 +12,6 @@ This document uses the following convention to categorize breaking changes:
|
||||
* **Deprecated:** An API was marked as deprecated. The API will continue to function, but will emit a deprecation warning, and will be removed in a future release.
|
||||
* **Removed:** An API or feature was removed, and is no longer supported by Electron.
|
||||
|
||||
## Planned Breaking API Changes (43.0)
|
||||
|
||||
### Behavior Changed: Dialog methods default to Downloads directory
|
||||
|
||||
The `defaultPath` option for the following methods now defaults to the user's Downloads folder (or their home directory if Downloads doesn't exist) when not explicitly provided:
|
||||
|
||||
* `dialog.showOpenDialog`
|
||||
* `dialog.showOpenDialogSync`
|
||||
* `dialog.showSaveDialog`
|
||||
* `dialog.showSaveDialogSync`
|
||||
|
||||
Previously, when no `defaultPath` was provided, the underlying OS file dialog would determine the initial directory — typically remembering the last directory the user navigated to, or falling back to an OS-specific default. Now, Electron explicitly sets the initial directory to Downloads, which also means the OS will no longer track and restore the last-used directory between dialog invocations.
|
||||
|
||||
To preserve the old behavior, you can track the last-used directory yourself and pass it as `defaultPath`:
|
||||
|
||||
```js
|
||||
const path = require('node:path')
|
||||
|
||||
let lastUsedPath
|
||||
const result = await dialog.showOpenDialog({
|
||||
defaultPath: lastUsedPath
|
||||
})
|
||||
|
||||
if (!result.canceled && result.filePaths.length > 0) {
|
||||
lastUsedPath = path.dirname(result.filePaths[0])
|
||||
}
|
||||
```
|
||||
|
||||
## Planned Breaking API Changes (42.0)
|
||||
|
||||
### Behavior Changed: macOS notifications now use `UNNotification` API
|
||||
|
||||
@@ -3,7 +3,7 @@
|
||||
These are the style guidelines for coding in Electron.
|
||||
|
||||
You can run `npm run lint` to show any style issues detected by `cpplint` and
|
||||
`oxlint`.
|
||||
`eslint`.
|
||||
|
||||
## General Code
|
||||
|
||||
|
||||
@@ -25,6 +25,27 @@ included in the `electron` package:
|
||||
npx install-electron --no
|
||||
```
|
||||
|
||||
## Installing prereleases
|
||||
|
||||
Electron [distributes experimental releases of future major versions](./electron-timelines.md)
|
||||
via npm as well.
|
||||
|
||||
Nightly builds contain the latest changes from the `main` branch:
|
||||
|
||||
```sh
|
||||
npm install electron-nightly --save-dev
|
||||
```
|
||||
|
||||
Alpha and beta builds contain changes slated for the next major version:
|
||||
|
||||
```sh
|
||||
npm install electron@alpha --save-dev
|
||||
npm install electron@beta --save-dev
|
||||
```
|
||||
|
||||
> [!TIP]
|
||||
> For more information on available Electron releases, see the [Release Status dashboard](https://releases.electronjs.org).
|
||||
|
||||
## Running Electron ad-hoc
|
||||
|
||||
If you're in a pinch and would prefer to not use `npm install` in your local
|
||||
|
||||
@@ -87,13 +87,6 @@ if (!gotTheLock) {
|
||||
// Create mainWindow, load the rest of the app, etc...
|
||||
app.whenReady().then(() => {
|
||||
createWindow()
|
||||
// Check for deep link on cold start
|
||||
if (process.argv.length >= 2) {
|
||||
const lastArg = process.argv[process.argv.length - 1]
|
||||
if (lastArg.startsWith('electron-fiddle://')) {
|
||||
dialog.showErrorBox('Welcome Back', `You arrived from: ${lastArg}`)
|
||||
}
|
||||
}
|
||||
})
|
||||
}
|
||||
```
|
||||
|
||||
@@ -179,7 +179,6 @@ auto_filenames = {
|
||||
"lib/common/define-properties.ts",
|
||||
"lib/common/deprecate.ts",
|
||||
"lib/common/ipc-messages.ts",
|
||||
"lib/common/timers-shim.ts",
|
||||
"lib/common/web-view-methods.ts",
|
||||
"lib/common/webpack-globals-provider.ts",
|
||||
"lib/renderer/api/context-bridge.ts",
|
||||
|
||||
@@ -432,6 +432,10 @@ filenames = {
|
||||
"shell/browser/media/media_capture_devices_dispatcher.h",
|
||||
"shell/browser/media/media_device_id_salt.cc",
|
||||
"shell/browser/media/media_device_id_salt.h",
|
||||
"shell/browser/metrics/electron_metrics_log_uploader.cc",
|
||||
"shell/browser/metrics/electron_metrics_log_uploader.h",
|
||||
"shell/browser/metrics/electron_metrics_service_client.cc",
|
||||
"shell/browser/metrics/electron_metrics_service_client.h",
|
||||
"shell/browser/microtasks_runner.cc",
|
||||
"shell/browser/microtasks_runner.h",
|
||||
"shell/browser/native_window.cc",
|
||||
@@ -508,6 +512,10 @@ filenames = {
|
||||
"shell/browser/session_preferences.h",
|
||||
"shell/browser/special_storage_policy.cc",
|
||||
"shell/browser/special_storage_policy.h",
|
||||
"shell/browser/tracing/electron_background_tracing_metrics_provider.cc",
|
||||
"shell/browser/tracing/electron_background_tracing_metrics_provider.h",
|
||||
"shell/browser/tracing/electron_tracing_delegate.cc",
|
||||
"shell/browser/tracing/electron_tracing_delegate.h",
|
||||
"shell/browser/ui/accelerator_util.cc",
|
||||
"shell/browser/ui/accelerator_util.h",
|
||||
"shell/browser/ui/autofill_popup.cc",
|
||||
@@ -734,8 +742,6 @@ filenames = {
|
||||
"shell/renderer/electron_sandboxed_renderer_client.h",
|
||||
"shell/renderer/electron_smooth_round_rect.cc",
|
||||
"shell/renderer/electron_smooth_round_rect.h",
|
||||
"shell/renderer/oom_stack_trace.cc",
|
||||
"shell/renderer/oom_stack_trace.h",
|
||||
"shell/renderer/preload_realm_context.cc",
|
||||
"shell/renderer/preload_realm_context.h",
|
||||
"shell/renderer/preload_utils.cc",
|
||||
@@ -797,6 +803,8 @@ filenames = {
|
||||
"shell/browser/extensions/electron_kiosk_delegate.h",
|
||||
"shell/browser/extensions/electron_messaging_delegate.cc",
|
||||
"shell/browser/extensions/electron_messaging_delegate.h",
|
||||
"shell/browser/extensions/electron_navigation_ui_data.cc",
|
||||
"shell/browser/extensions/electron_navigation_ui_data.h",
|
||||
"shell/browser/extensions/electron_process_manager_delegate.cc",
|
||||
"shell/browser/extensions/electron_process_manager_delegate.h",
|
||||
"shell/common/extensions/electron_extensions_api_provider.cc",
|
||||
|
||||
21
lib/browser/.eslintrc.json
Normal file
21
lib/browser/.eslintrc.json
Normal file
@@ -0,0 +1,21 @@
|
||||
{
|
||||
"rules": {
|
||||
"no-restricted-imports": [
|
||||
"error",
|
||||
{
|
||||
"paths": [
|
||||
"electron",
|
||||
"electron/renderer"
|
||||
],
|
||||
"patterns": [
|
||||
"./*",
|
||||
"../*",
|
||||
"@electron/internal/isolated_renderer/*",
|
||||
"@electron/internal/renderer/*",
|
||||
"@electron/internal/sandboxed_worker/*",
|
||||
"@electron/internal/worker/*"
|
||||
]
|
||||
}
|
||||
]
|
||||
}
|
||||
}
|
||||
@@ -73,7 +73,6 @@ export async function getSources (args: Electron.SourcesOptions) {
|
||||
|
||||
capturer._onerror = (error: string) => {
|
||||
stopRunning();
|
||||
// eslint-disable-next-line prefer-promise-reject-errors
|
||||
reject(error);
|
||||
};
|
||||
|
||||
|
||||
@@ -437,14 +437,6 @@ WebContents.prototype.loadURL = function (url, options) {
|
||||
return p;
|
||||
};
|
||||
|
||||
WebContents.prototype.copyVideoFrameAt = function (x: number, y: number) {
|
||||
this.mainFrame.copyVideoFrameAt(x, y);
|
||||
};
|
||||
|
||||
WebContents.prototype.saveVideoFrameAs = function (x: number, y: number) {
|
||||
this.mainFrame.saveVideoFrameAs(x, y);
|
||||
};
|
||||
|
||||
WebContents.prototype.setWindowOpenHandler = function (handler: (details: Electron.HandlerDetails) => Electron.WindowOpenHandlerResponse) {
|
||||
this._windowOpenHandler = handler;
|
||||
};
|
||||
|
||||
23
lib/common/.eslintrc.json
Normal file
23
lib/common/.eslintrc.json
Normal file
@@ -0,0 +1,23 @@
|
||||
{
|
||||
"rules": {
|
||||
"no-restricted-imports": [
|
||||
"error",
|
||||
{
|
||||
"paths": [
|
||||
"electron",
|
||||
"electron/main",
|
||||
"electron/renderer"
|
||||
],
|
||||
"patterns": [
|
||||
"./*",
|
||||
"../*",
|
||||
"@electron/internal/browser/*",
|
||||
"@electron/internal/isolated_renderer/*",
|
||||
"@electron/internal/renderer/*",
|
||||
"@electron/internal/sandboxed_worker/*",
|
||||
"@electron/internal/worker/*"
|
||||
]
|
||||
}
|
||||
]
|
||||
}
|
||||
}
|
||||
18
lib/isolated_renderer/.eslintrc.json
Normal file
18
lib/isolated_renderer/.eslintrc.json
Normal file
@@ -0,0 +1,18 @@
|
||||
{
|
||||
"rules": {
|
||||
"no-restricted-imports": [
|
||||
"error",
|
||||
{
|
||||
"paths": [
|
||||
"electron",
|
||||
"electron/main"
|
||||
],
|
||||
"patterns": [
|
||||
"./*",
|
||||
"../*",
|
||||
"@electron/internal/browser/*"
|
||||
]
|
||||
}
|
||||
]
|
||||
}
|
||||
}
|
||||
18
lib/preload_realm/.eslintrc.json
Normal file
18
lib/preload_realm/.eslintrc.json
Normal file
@@ -0,0 +1,18 @@
|
||||
{
|
||||
"rules": {
|
||||
"no-restricted-imports": [
|
||||
"error",
|
||||
{
|
||||
"paths": [
|
||||
"electron",
|
||||
"electron/main"
|
||||
],
|
||||
"patterns": [
|
||||
"./*",
|
||||
"../*",
|
||||
"@electron/internal/browser/*"
|
||||
]
|
||||
}
|
||||
]
|
||||
}
|
||||
}
|
||||
18
lib/renderer/.eslintrc.json
Normal file
18
lib/renderer/.eslintrc.json
Normal file
@@ -0,0 +1,18 @@
|
||||
{
|
||||
"rules": {
|
||||
"no-restricted-imports": [
|
||||
"error",
|
||||
{
|
||||
"paths": [
|
||||
"electron",
|
||||
"electron/main"
|
||||
],
|
||||
"patterns": [
|
||||
"./*",
|
||||
"../*",
|
||||
"@electron/internal/browser/*"
|
||||
]
|
||||
}
|
||||
]
|
||||
}
|
||||
}
|
||||
@@ -124,9 +124,7 @@ if (nodeIntegration) {
|
||||
delete (global as any).setImmediate;
|
||||
delete (global as any).clearImmediate;
|
||||
delete (global as any).global;
|
||||
// eslint-disable-next-line n/no-deprecated-api
|
||||
delete (global as any).root;
|
||||
// eslint-disable-next-line n/no-deprecated-api
|
||||
delete (global as any).GLOBAL;
|
||||
});
|
||||
}
|
||||
|
||||
18
lib/sandboxed_renderer/.eslintrc.json
Normal file
18
lib/sandboxed_renderer/.eslintrc.json
Normal file
@@ -0,0 +1,18 @@
|
||||
{
|
||||
"rules": {
|
||||
"no-restricted-imports": [
|
||||
"error",
|
||||
{
|
||||
"paths": [
|
||||
"electron",
|
||||
"electron/main"
|
||||
],
|
||||
"patterns": [
|
||||
"./*",
|
||||
"../*",
|
||||
"@electron/internal/browser/*"
|
||||
]
|
||||
}
|
||||
]
|
||||
}
|
||||
}
|
||||
@@ -90,7 +90,6 @@ export function executeSandboxedPreloadScripts (context: PreloadContext, preload
|
||||
if (contents) {
|
||||
runPreloadScript(context, contents);
|
||||
} else if (error) {
|
||||
// eslint-disable-next-line no-throw-literal
|
||||
throw error;
|
||||
}
|
||||
} catch (error) {
|
||||
|
||||
21
lib/utility/.eslintrc.json
Normal file
21
lib/utility/.eslintrc.json
Normal file
@@ -0,0 +1,21 @@
|
||||
{
|
||||
"rules": {
|
||||
"no-restricted-imports": [
|
||||
"error",
|
||||
{
|
||||
"paths": [
|
||||
"electron",
|
||||
"electron/renderer"
|
||||
],
|
||||
"patterns": [
|
||||
"./*",
|
||||
"../*",
|
||||
"@electron/internal/isolated_renderer/*",
|
||||
"@electron/internal/renderer/*",
|
||||
"@electron/internal/sandboxed_worker/*",
|
||||
"@electron/internal/worker/*"
|
||||
]
|
||||
}
|
||||
]
|
||||
}
|
||||
}
|
||||
18
lib/worker/.eslintrc.json
Normal file
18
lib/worker/.eslintrc.json
Normal file
@@ -0,0 +1,18 @@
|
||||
{
|
||||
"rules": {
|
||||
"no-restricted-imports": [
|
||||
"error",
|
||||
{
|
||||
"paths": [
|
||||
"electron",
|
||||
"electron/main"
|
||||
],
|
||||
"patterns": [
|
||||
"./*",
|
||||
"../*",
|
||||
"@electron/internal/browser/*"
|
||||
]
|
||||
}
|
||||
]
|
||||
}
|
||||
}
|
||||
@@ -6,7 +6,7 @@
|
||||
"install-electron": "install.js"
|
||||
},
|
||||
"dependencies": {
|
||||
"@electron/get": "^4.0.3",
|
||||
"@electron/get": "^2.0.0",
|
||||
"@types/node": "^24.9.0",
|
||||
"extract-zip": "^2.0.1"
|
||||
},
|
||||
|
||||
19
package.json
19
package.json
@@ -5,7 +5,7 @@
|
||||
"description": "Build cross platform desktop apps with JavaScript, HTML, and CSS",
|
||||
"devDependencies": {
|
||||
"@azure/storage-blob": "^12.28.0",
|
||||
"@datadog/datadog-ci": "^5.9.1",
|
||||
"@datadog/datadog-ci": "^4.1.2",
|
||||
"@electron/asar": "^4.0.1",
|
||||
"@electron/docs-parser": "^2.0.0",
|
||||
"@electron/fiddle-core": "^1.3.4",
|
||||
@@ -13,7 +13,7 @@
|
||||
"@electron/lint-roller": "^3.2.0",
|
||||
"@electron/typescript-definitions": "^9.1.5",
|
||||
"@hurdlegroup/robotjs": "^0.12.3",
|
||||
"@octokit/rest": "^22.0.1",
|
||||
"@octokit/rest": "^20.1.2",
|
||||
"@primer/octicons": "^10.0.0",
|
||||
"@sentry/cli": "1.72.0",
|
||||
"@types/minimist": "^1.2.5",
|
||||
@@ -21,12 +21,22 @@
|
||||
"@types/semver": "^7.5.8",
|
||||
"@types/stream-json": "^1.7.8",
|
||||
"@types/temp": "^0.9.4",
|
||||
"@xmldom/xmldom": "^0.8.12",
|
||||
"@typescript-eslint/eslint-plugin": "^8.32.1",
|
||||
"@typescript-eslint/parser": "^8.7.0",
|
||||
"@xmldom/xmldom": "^0.8.11",
|
||||
"buffer": "^6.0.3",
|
||||
"chalk": "^4.1.0",
|
||||
"check-for-leaks": "^1.2.1",
|
||||
"eslint": "^8.57.1",
|
||||
"eslint-config-standard": "^17.1.0",
|
||||
"eslint-plugin-import": "^2.32.0",
|
||||
"eslint-plugin-markdown": "^5.1.0",
|
||||
"eslint-plugin-mocha": "^10.5.0",
|
||||
"eslint-plugin-n": "^16.6.2",
|
||||
"eslint-plugin-node": "^11.1.0",
|
||||
"eslint-plugin-promise": "^6.6.0",
|
||||
"events": "^3.2.0",
|
||||
"folder-hash": "^4.1.2",
|
||||
"folder-hash": "^4.1.1",
|
||||
"got": "^11.8.5",
|
||||
"husky": "^9.1.7",
|
||||
"lint-staged": "^16.1.0",
|
||||
@@ -34,7 +44,6 @@
|
||||
"minimist": "^1.2.8",
|
||||
"node-gyp": "^11.4.2",
|
||||
"null-loader": "^4.0.1",
|
||||
"oxlint": "^1.57.0",
|
||||
"pre-flight": "^2.0.0",
|
||||
"process": "^0.11.10",
|
||||
"semver": "^7.6.3",
|
||||
|
||||
@@ -145,10 +145,6 @@ fix_set_correct_app_id_on_linux.patch
|
||||
fix_pass_trigger_for_global_shortcuts_on_wayland.patch
|
||||
feat_plumb_node_integration_in_worker_through_workersettings.patch
|
||||
fix_restore_sdk_inputs_cross-toolchain_deps_for_macos.patch
|
||||
fix_use_fresh_lazynow_for_onendworkitemimpl_after_didruntask.patch
|
||||
fix_pulseaudio_stream_and_icon_names.patch
|
||||
fix_fire_menu_popup_start_for_dynamically_created_aria_menus.patch
|
||||
feat_allow_enabling_extensions_on_custom_protocols.patch
|
||||
fix_initialize_com_on_desktopmedialistcapturethread_on_windows.patch
|
||||
chore_register_node_as_a_dynamic_trace_category_prefix.patch
|
||||
gin_mark_argumentholder_as_cppgc_stack_allocated.patch
|
||||
|
||||
@@ -6,79 +6,6 @@ Subject: chore: provide IsWebContentsCreationOverridden with full params
|
||||
Pending upstream patch, this gives us fuller access to the window.open params
|
||||
so that we will be able to decide whether to cancel it or not.
|
||||
|
||||
diff --git a/chrome/browser/media/offscreen_tab.cc b/chrome/browser/media/offscreen_tab.cc
|
||||
index 047f1258f951f763df2ca0ba355b19d19337826b..9fc7114312212fbe38ddec740b4aebbcd72cb0f8 100644
|
||||
--- a/chrome/browser/media/offscreen_tab.cc
|
||||
+++ b/chrome/browser/media/offscreen_tab.cc
|
||||
@@ -285,8 +285,7 @@ bool OffscreenTab::IsWebContentsCreationOverridden(
|
||||
content::SiteInstance* source_site_instance,
|
||||
content::mojom::WindowContainerType window_container_type,
|
||||
const GURL& opener_url,
|
||||
- const std::string& frame_name,
|
||||
- const GURL& target_url) {
|
||||
+ const content::mojom::CreateNewWindowParams& params) {
|
||||
// Disallow creating separate WebContentses. The WebContents implementation
|
||||
// uses this to spawn new windows/tabs, which is also not allowed for
|
||||
// offscreen tabs.
|
||||
diff --git a/chrome/browser/media/offscreen_tab.h b/chrome/browser/media/offscreen_tab.h
|
||||
index 231e3595f218aeebe28d0b13ce6182e7a4d6f4e1..609bd205d1cd0404cab3471765bef8b0e053d061 100644
|
||||
--- a/chrome/browser/media/offscreen_tab.h
|
||||
+++ b/chrome/browser/media/offscreen_tab.h
|
||||
@@ -108,8 +108,7 @@ class OffscreenTab final : public ProfileObserver,
|
||||
content::SiteInstance* source_site_instance,
|
||||
content::mojom::WindowContainerType window_container_type,
|
||||
const GURL& opener_url,
|
||||
- const std::string& frame_name,
|
||||
- const GURL& target_url) final;
|
||||
+ const content::mojom::CreateNewWindowParams& params) override;
|
||||
void EnterFullscreenModeForTab(
|
||||
content::RenderFrameHost* requesting_frame,
|
||||
const blink::mojom::FullscreenOptions& options) final;
|
||||
diff --git a/chrome/browser/ui/ash/keyboard/chrome_keyboard_web_contents.cc b/chrome/browser/ui/ash/keyboard/chrome_keyboard_web_contents.cc
|
||||
index 33edb0a90d886dd44956046e03fcc182a0f6bc8e..5b5edd3da3d9f7a248ea3affd195c36bfd64a38e 100644
|
||||
--- a/chrome/browser/ui/ash/keyboard/chrome_keyboard_web_contents.cc
|
||||
+++ b/chrome/browser/ui/ash/keyboard/chrome_keyboard_web_contents.cc
|
||||
@@ -80,8 +80,7 @@ class ChromeKeyboardContentsDelegate : public content::WebContentsDelegate,
|
||||
content::SiteInstance* source_site_instance,
|
||||
content::mojom::WindowContainerType window_container_type,
|
||||
const GURL& opener_url,
|
||||
- const std::string& frame_name,
|
||||
- const GURL& target_url) override {
|
||||
+ const content::mojom::CreateNewWindowParams& params) override {
|
||||
return true;
|
||||
}
|
||||
|
||||
diff --git a/chrome/browser/ui/ash/web_view/ash_web_view_impl.cc b/chrome/browser/ui/ash/web_view/ash_web_view_impl.cc
|
||||
index e4e42249c476ccae58f0ba42e7dbae299f1e36bd..670c30ed4b7f1a07eb4b8abaa95e5a8a9d94bd8d 100644
|
||||
--- a/chrome/browser/ui/ash/web_view/ash_web_view_impl.cc
|
||||
+++ b/chrome/browser/ui/ash/web_view/ash_web_view_impl.cc
|
||||
@@ -121,10 +121,9 @@ bool AshWebViewImpl::IsWebContentsCreationOverridden(
|
||||
content::SiteInstance* source_site_instance,
|
||||
content::mojom::WindowContainerType window_container_type,
|
||||
const GURL& opener_url,
|
||||
- const std::string& frame_name,
|
||||
- const GURL& target_url) {
|
||||
+ const content::mojom::CreateNewWindowParams& params) {
|
||||
if (params_.suppress_navigation) {
|
||||
- NotifyDidSuppressNavigation(target_url,
|
||||
+ NotifyDidSuppressNavigation(params.target_url,
|
||||
WindowOpenDisposition::NEW_FOREGROUND_TAB,
|
||||
/*from_user_gesture=*/true);
|
||||
return true;
|
||||
diff --git a/chrome/browser/ui/ash/web_view/ash_web_view_impl.h b/chrome/browser/ui/ash/web_view/ash_web_view_impl.h
|
||||
index 39fa45f0a0f9076bd7ac0be6f455dd540a276512..3d0381d463eed73470b28085830f2a23751659a7 100644
|
||||
--- a/chrome/browser/ui/ash/web_view/ash_web_view_impl.h
|
||||
+++ b/chrome/browser/ui/ash/web_view/ash_web_view_impl.h
|
||||
@@ -60,8 +60,7 @@ class AshWebViewImpl : public ash::AshWebView,
|
||||
content::SiteInstance* source_site_instance,
|
||||
content::mojom::WindowContainerType window_container_type,
|
||||
const GURL& opener_url,
|
||||
- const std::string& frame_name,
|
||||
- const GURL& target_url) override;
|
||||
+ const content::mojom::CreateNewWindowParams& params) override;
|
||||
content::WebContents* OpenURLFromTab(
|
||||
content::WebContents* source,
|
||||
const content::OpenURLParams& params,
|
||||
diff --git a/chrome/browser/ui/browser.cc b/chrome/browser/ui/browser.cc
|
||||
index 8f8852b2af1acfa4ec985fd1c8b50563b991b12a..c2f2903545b191c5ab13462bf330efce37d7d08c 100644
|
||||
--- a/chrome/browser/ui/browser.cc
|
||||
@@ -116,112 +43,6 @@ index acdb28d61badaf549c47e107f4795e1e2adc37c9..b6aca0bf802f2146d09d2a872ff9e091
|
||||
content::WebContents* CreateCustomWebContents(
|
||||
content::RenderFrameHost* opener,
|
||||
content::SiteInstance* source_site_instance,
|
||||
diff --git a/chrome/browser/ui/media_router/presentation_receiver_window_controller.cc b/chrome/browser/ui/media_router/presentation_receiver_window_controller.cc
|
||||
index a05510eadf5c9ff24bb7999aa76229946319280f..a80ecc46f8a6b84de83d608257d45ae61ccc2170 100644
|
||||
--- a/chrome/browser/ui/media_router/presentation_receiver_window_controller.cc
|
||||
+++ b/chrome/browser/ui/media_router/presentation_receiver_window_controller.cc
|
||||
@@ -206,8 +206,7 @@ bool PresentationReceiverWindowController::IsWebContentsCreationOverridden(
|
||||
content::SiteInstance* source_site_instance,
|
||||
content::mojom::WindowContainerType window_container_type,
|
||||
const GURL& opener_url,
|
||||
- const std::string& frame_name,
|
||||
- const GURL& target_url) {
|
||||
+ const content::mojom::CreateNewWindowParams& params) {
|
||||
// Disallow creating separate WebContentses. The WebContents implementation
|
||||
// uses this to spawn new windows/tabs, which is also not allowed for
|
||||
// local presentations.
|
||||
diff --git a/chrome/browser/ui/media_router/presentation_receiver_window_controller.h b/chrome/browser/ui/media_router/presentation_receiver_window_controller.h
|
||||
index 3fc06be01f20e8cd314d95d73a3f58c2f0742fe9..c07910ae59a185442f37ea6e7b96fdf3a33aba82 100644
|
||||
--- a/chrome/browser/ui/media_router/presentation_receiver_window_controller.h
|
||||
+++ b/chrome/browser/ui/media_router/presentation_receiver_window_controller.h
|
||||
@@ -106,8 +106,7 @@ class PresentationReceiverWindowController final
|
||||
content::SiteInstance* source_site_instance,
|
||||
content::mojom::WindowContainerType window_container_type,
|
||||
const GURL& opener_url,
|
||||
- const std::string& frame_name,
|
||||
- const GURL& target_url) override;
|
||||
+ const content::mojom::CreateNewWindowParams& params) override;
|
||||
|
||||
// The profile used for the presentation.
|
||||
raw_ptr<Profile, DanglingUntriaged> otr_profile_;
|
||||
diff --git a/chrome/browser/ui/views/hats/hats_next_web_dialog.cc b/chrome/browser/ui/views/hats/hats_next_web_dialog.cc
|
||||
index 783d05c39ecbe5e556af2e5fd8b4f30fb5aa1196..e1895bcf9d3c6818aa64b1479774a143dae74d53 100644
|
||||
--- a/chrome/browser/ui/views/hats/hats_next_web_dialog.cc
|
||||
+++ b/chrome/browser/ui/views/hats/hats_next_web_dialog.cc
|
||||
@@ -104,8 +104,7 @@ class HatsNextWebDialog::HatsWebView : public views::WebView {
|
||||
content::SiteInstance* source_site_instance,
|
||||
content::mojom::WindowContainerType window_container_type,
|
||||
const GURL& opener_url,
|
||||
- const std::string& frame_name,
|
||||
- const GURL& target_url) override {
|
||||
+ const content::mojom::CreateNewWindowParams& params) override {
|
||||
return true;
|
||||
}
|
||||
content::WebContents* CreateCustomWebContents(
|
||||
diff --git a/components/embedder_support/android/delegate/web_contents_delegate_android.cc b/components/embedder_support/android/delegate/web_contents_delegate_android.cc
|
||||
index a82c39208a2709d9e292dac5c89bd2c9bf529a98..d578299501e15815ac615528610889d270aaf6ad 100644
|
||||
--- a/components/embedder_support/android/delegate/web_contents_delegate_android.cc
|
||||
+++ b/components/embedder_support/android/delegate/web_contents_delegate_android.cc
|
||||
@@ -214,15 +214,14 @@ bool WebContentsDelegateAndroid::IsWebContentsCreationOverridden(
|
||||
content::SiteInstance* source_site_instance,
|
||||
content::mojom::WindowContainerType window_container_type,
|
||||
const GURL& opener_url,
|
||||
- const std::string& frame_name,
|
||||
- const GURL& target_url) {
|
||||
+ const content::mojom::CreateNewWindowParams& params) {
|
||||
JNIEnv* env = AttachCurrentThread();
|
||||
ScopedJavaLocalRef<jobject> obj = GetJavaDelegate(env);
|
||||
if (obj.is_null()) {
|
||||
return false;
|
||||
}
|
||||
ScopedJavaLocalRef<jobject> java_gurl =
|
||||
- url::GURLAndroid::FromNativeGURL(env, target_url);
|
||||
+ url::GURLAndroid::FromNativeGURL(env, params.target_url.spec());
|
||||
return !Java_WebContentsDelegateAndroid_shouldCreateWebContents(env, obj,
|
||||
java_gurl);
|
||||
}
|
||||
diff --git a/components/embedder_support/android/delegate/web_contents_delegate_android.h b/components/embedder_support/android/delegate/web_contents_delegate_android.h
|
||||
index 5754a774852d53a99d34568d0b98aa19171add2a..a75d85c97a75fffa5dba6ac427d7608e345c02ef 100644
|
||||
--- a/components/embedder_support/android/delegate/web_contents_delegate_android.h
|
||||
+++ b/components/embedder_support/android/delegate/web_contents_delegate_android.h
|
||||
@@ -82,8 +82,7 @@ class WebContentsDelegateAndroid : public content::WebContentsDelegate {
|
||||
content::SiteInstance* source_site_instance,
|
||||
content::mojom::WindowContainerType window_container_type,
|
||||
const GURL& opener_url,
|
||||
- const std::string& frame_name,
|
||||
- const GURL& target_url) override;
|
||||
+ const content::mojom::CreateNewWindowParams& params) override;
|
||||
void CloseContents(content::WebContents* source) override;
|
||||
bool DidAddMessageToConsole(content::WebContents* source,
|
||||
blink::mojom::ConsoleMessageLevel log_level,
|
||||
diff --git a/components/offline_pages/content/background_loader/background_loader_contents.cc b/components/offline_pages/content/background_loader/background_loader_contents.cc
|
||||
index 12b38ddee62e3af915083830703a4c2e8e249f00..bf4e8dcbdecd46712c48107cfee554b7bb1e0277 100644
|
||||
--- a/components/offline_pages/content/background_loader/background_loader_contents.cc
|
||||
+++ b/components/offline_pages/content/background_loader/background_loader_contents.cc
|
||||
@@ -85,8 +85,7 @@ bool BackgroundLoaderContents::IsWebContentsCreationOverridden(
|
||||
content::SiteInstance* source_site_instance,
|
||||
content::mojom::WindowContainerType window_container_type,
|
||||
const GURL& opener_url,
|
||||
- const std::string& frame_name,
|
||||
- const GURL& target_url) {
|
||||
+ const content::mojom::CreateNewWindowParams& params) {
|
||||
// Background pages should not create other webcontents/tabs.
|
||||
return true;
|
||||
}
|
||||
diff --git a/components/offline_pages/content/background_loader/background_loader_contents.h b/components/offline_pages/content/background_loader/background_loader_contents.h
|
||||
index b969f1d97b7e3396119b579cfbe61e19ff7d2dd4..b8d6169652da28266a514938b45b39c58df53573 100644
|
||||
--- a/components/offline_pages/content/background_loader/background_loader_contents.h
|
||||
+++ b/components/offline_pages/content/background_loader/background_loader_contents.h
|
||||
@@ -66,8 +66,7 @@ class BackgroundLoaderContents : public content::WebContentsDelegate {
|
||||
content::SiteInstance* source_site_instance,
|
||||
content::mojom::WindowContainerType window_container_type,
|
||||
const GURL& opener_url,
|
||||
- const std::string& frame_name,
|
||||
- const GURL& target_url) override;
|
||||
+ const content::mojom::CreateNewWindowParams& params) override;
|
||||
|
||||
content::WebContents* AddNewContents(
|
||||
content::WebContents* source,
|
||||
diff --git a/content/browser/web_contents/web_contents_impl.cc b/content/browser/web_contents/web_contents_impl.cc
|
||||
index d43e75c20aca09080f4223d339c88381f030c504..8cd59445bae73ff0193e4512d7c36740cbad847f 100644
|
||||
--- a/content/browser/web_contents/web_contents_impl.cc
|
||||
@@ -356,48 +177,6 @@ index f459dddeb3f8f3a33ffead0e96fba791d18a0108..f7a229b186774ca3a01f2d747eab139a
|
||||
content::WebContents* CreateCustomWebContents(
|
||||
content::RenderFrameHost* opener,
|
||||
content::SiteInstance* source_site_instance,
|
||||
diff --git a/fuchsia_web/webengine/browser/frame_impl.cc b/fuchsia_web/webengine/browser/frame_impl.cc
|
||||
index 9c1fb0b2ed4f013ef6108a9844b22f6bfe697621..ef4991adc766d53b03d280395630b83ced38c2e8 100644
|
||||
--- a/fuchsia_web/webengine/browser/frame_impl.cc
|
||||
+++ b/fuchsia_web/webengine/browser/frame_impl.cc
|
||||
@@ -585,8 +585,7 @@ bool FrameImpl::IsWebContentsCreationOverridden(
|
||||
content::SiteInstance* source_site_instance,
|
||||
content::mojom::WindowContainerType window_container_type,
|
||||
const GURL& opener_url,
|
||||
- const std::string& frame_name,
|
||||
- const GURL& target_url) {
|
||||
+ const content::mojom::CreateNewWindowParams& params) {
|
||||
// Specify a generous upper bound for unacknowledged popup windows, so that we
|
||||
// can catch bad client behavior while not interfering with normal operation.
|
||||
constexpr size_t kMaxPendingWebContentsCount = 10;
|
||||
diff --git a/fuchsia_web/webengine/browser/frame_impl.h b/fuchsia_web/webengine/browser/frame_impl.h
|
||||
index 756d4192271d6a65cfe8e1511737c565b543cb1f..5688f6f745056565c3c01947f741c4d13e27b6ae 100644
|
||||
--- a/fuchsia_web/webengine/browser/frame_impl.h
|
||||
+++ b/fuchsia_web/webengine/browser/frame_impl.h
|
||||
@@ -308,8 +308,7 @@ class WEB_ENGINE_EXPORT FrameImpl : public fuchsia::web::Frame,
|
||||
content::SiteInstance* source_site_instance,
|
||||
content::mojom::WindowContainerType window_container_type,
|
||||
const GURL& opener_url,
|
||||
- const std::string& frame_name,
|
||||
- const GURL& target_url) override;
|
||||
+ const content::mojom::CreateNewWindowParams& params) override;
|
||||
void WebContentsCreated(content::WebContents* source_contents,
|
||||
int opener_render_process_id,
|
||||
int opener_render_frame_id,
|
||||
diff --git a/headless/lib/browser/headless_web_contents_impl.cc b/headless/lib/browser/headless_web_contents_impl.cc
|
||||
index ae616fa9c352413e23fb509b3e12e0e4fab5a094..0efa65f7d4346cfe78d2f27ba55a0526202315ff 100644
|
||||
--- a/headless/lib/browser/headless_web_contents_impl.cc
|
||||
+++ b/headless/lib/browser/headless_web_contents_impl.cc
|
||||
@@ -232,8 +232,7 @@ class HeadlessWebContentsImpl::Delegate : public content::WebContentsDelegate {
|
||||
content::SiteInstance* source_site_instance,
|
||||
content::mojom::WindowContainerType window_container_type,
|
||||
const GURL& opener_url,
|
||||
- const std::string& frame_name,
|
||||
- const GURL& target_url) override {
|
||||
+ const content::mojom::CreateNewWindowParams& params) override {
|
||||
return headless_web_contents_->browser_context()
|
||||
->options()
|
||||
->block_new_web_contents();
|
||||
diff --git a/ui/views/controls/webview/web_dialog_view.cc b/ui/views/controls/webview/web_dialog_view.cc
|
||||
index a7d370220136f2c31afd70644ada26f1768b2e0d..e08dd61b20c68398b0532f5ae74e0ffd5968c19b 100644
|
||||
--- a/ui/views/controls/webview/web_dialog_view.cc
|
||||
|
||||
@@ -1,27 +0,0 @@
|
||||
From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001
|
||||
From: deepak1556 <hop2deep@gmail.com>
|
||||
Date: Tue, 31 Mar 2026 09:03:39 +0900
|
||||
Subject: chore: register node as a dynamic trace category prefix
|
||||
|
||||
This allows Node.js trace categories to be treated as dynamic Perfetto
|
||||
categories in the Chromium build. Without this, the categories
|
||||
must be registered in the static registry base/trace_event/builtin_categories.h
|
||||
which is backed by constexpr function ValidateCategories() that
|
||||
recursively validates to a depth of index + longest_category_name_length,
|
||||
adding the node categories exceeds the current constexpr recursion depth
|
||||
of 512 and requires additional patching to add `-fconstexpr-depth` to //base
|
||||
target. Given neither the static nor the dynamic registration can be
|
||||
upstreamed, the minimal of the two changes is chosen here.
|
||||
|
||||
diff --git a/base/trace_event/builtin_categories.h b/base/trace_event/builtin_categories.h
|
||||
index 85c6f973788938b6a48a7a89e9fa803dc1030580..ae25a8188d57ff4c15e9a20e91629d585314db87 100644
|
||||
--- a/base/trace_event/builtin_categories.h
|
||||
+++ b/base/trace_event/builtin_categories.h
|
||||
@@ -14,6 +14,7 @@ PERFETTO_DEFINE_TEST_CATEGORY_PREFIXES("cat",
|
||||
"foo",
|
||||
"test",
|
||||
"kTest",
|
||||
+ "node",
|
||||
"noise",
|
||||
"Testing",
|
||||
"NotTesting",
|
||||
@@ -53,34 +53,6 @@ index de56c9b94f92e9abf69b1d4894e5d386cad6d3cd..f8955ef7cc43b1854b29841ed65260a1
|
||||
int GetSourceCount() const override;
|
||||
const Source& GetSource(int index) const override;
|
||||
DesktopMediaList::Type GetMediaListType() const override;
|
||||
diff --git a/chrome/browser/media/webrtc/fake_desktop_media_list.cc b/chrome/browser/media/webrtc/fake_desktop_media_list.cc
|
||||
index cea6af048e682e33b5d93e4a3bfb4072840ca4fe..1c98d2275fa73a9e105bbd8928e05b48a4a05c14 100644
|
||||
--- a/chrome/browser/media/webrtc/fake_desktop_media_list.cc
|
||||
+++ b/chrome/browser/media/webrtc/fake_desktop_media_list.cc
|
||||
@@ -79,7 +79,8 @@ void FakeDesktopMediaList::StartUpdating(DesktopMediaListObserver* observer) {
|
||||
thumbnail_ = gfx::ImageSkia::CreateFrom1xBitmap(bitmap);
|
||||
}
|
||||
|
||||
-void FakeDesktopMediaList::Update(UpdateCallback callback) {
|
||||
+void FakeDesktopMediaList::Update(UpdateCallback callback,
|
||||
+ bool refresh_thumbnails) {
|
||||
std::move(callback).Run();
|
||||
}
|
||||
|
||||
diff --git a/chrome/browser/media/webrtc/fake_desktop_media_list.h b/chrome/browser/media/webrtc/fake_desktop_media_list.h
|
||||
index 786c526588d81b8b5b1b5dd3760719a53e005995..f66b7d0b4dfcbb8ed3dde5a9ff463ae2c8818d27 100644
|
||||
--- a/chrome/browser/media/webrtc/fake_desktop_media_list.h
|
||||
+++ b/chrome/browser/media/webrtc/fake_desktop_media_list.h
|
||||
@@ -40,7 +40,8 @@ class FakeDesktopMediaList : public DesktopMediaList {
|
||||
void SetThumbnailSize(const gfx::Size& thumbnail_size) override;
|
||||
void SetViewDialogWindowId(content::DesktopMediaID dialog_id) override;
|
||||
void StartUpdating(DesktopMediaListObserver* observer) override;
|
||||
- void Update(UpdateCallback callback) override;
|
||||
+ void Update(UpdateCallback callback,
|
||||
+ bool refresh_thumbnails = false) override;
|
||||
int GetSourceCount() const override;
|
||||
const Source& GetSource(int index) const override;
|
||||
DesktopMediaList::Type GetMediaListType() const override;
|
||||
diff --git a/chrome/browser/media/webrtc/native_desktop_media_list.cc b/chrome/browser/media/webrtc/native_desktop_media_list.cc
|
||||
index 2b745dbb254c714756a953ac0a32c1430af2c91d..9a8ebb4edfb92d9fe28ae4b87463a68547ea1ab3 100644
|
||||
--- a/chrome/browser/media/webrtc/native_desktop_media_list.cc
|
||||
|
||||
@@ -34,6 +34,48 @@ index 7ea6daec53a497bf867d799e041bf6ae7191ef7b..15940624940d5c629c40319f45c59282
|
||||
agent_group_scheduler_compositor_task_runner =
|
||||
execution_context->GetScheduler()
|
||||
->ToFrameScheduler()
|
||||
diff --git a/third_party/blink/renderer/core/workers/threaded_worklet_messaging_proxy.cc b/third_party/blink/renderer/core/workers/threaded_worklet_messaging_proxy.cc
|
||||
index 936f5ebe28caa993ed5de0f7de3613fa338e263f..961ac8091aa82128e1cfb8800a7efcb80d100a05 100644
|
||||
--- a/third_party/blink/renderer/core/workers/threaded_worklet_messaging_proxy.cc
|
||||
+++ b/third_party/blink/renderer/core/workers/threaded_worklet_messaging_proxy.cc
|
||||
@@ -13,10 +13,12 @@
|
||||
#include "third_party/blink/public/platform/task_type.h"
|
||||
#include "third_party/blink/renderer/core/dom/document.h"
|
||||
#include "third_party/blink/renderer/core/execution_context/security_context.h"
|
||||
+#include "third_party/blink/renderer/core/exported/web_view_impl.h"
|
||||
#include "third_party/blink/renderer/core/frame/csp/content_security_policy.h"
|
||||
#include "third_party/blink/renderer/core/frame/local_dom_window.h"
|
||||
#include "third_party/blink/renderer/core/frame/local_frame.h"
|
||||
#include "third_party/blink/renderer/core/frame/local_frame_client.h"
|
||||
+#include "third_party/blink/renderer/core/frame/web_local_frame_impl.h"
|
||||
#include "third_party/blink/renderer/core/inspector/thread_debugger_common_impl.h"
|
||||
#include "third_party/blink/renderer/core/loader/worker_fetch_context.h"
|
||||
#include "third_party/blink/renderer/core/origin_trials/origin_trial_context.h"
|
||||
@@ -135,6 +137,14 @@ void ThreadedWorkletMessagingProxy::Initialize(
|
||||
DCHECK(csp);
|
||||
|
||||
LocalFrameClient* frame_client = window->GetFrame()->Client();
|
||||
+ auto worklet_settings =
|
||||
+ std::make_unique<WorkerSettings>(window->GetFrame()->GetSettings());
|
||||
+ if (auto* web_local_frame = WebLocalFrameImpl::FromFrame(window->GetFrame())) {
|
||||
+ if (auto* web_view = web_local_frame->ViewImpl()) {
|
||||
+ worklet_settings->SetNodeIntegrationInWorker(
|
||||
+ web_view->GetWebPreferences().node_integration_in_worker);
|
||||
+ }
|
||||
+ }
|
||||
auto global_scope_creation_params =
|
||||
std::make_unique<GlobalScopeCreationParams>(
|
||||
window->Url(), mojom::blink::ScriptType::kModule, global_scope_name,
|
||||
@@ -147,8 +157,7 @@ void ThreadedWorkletMessagingProxy::Initialize(
|
||||
window->GetHttpsState(), worker_clients,
|
||||
frame_client->CreateWorkerContentSettingsClient(),
|
||||
OriginTrialContext::GetInheritedTrialFeatures(window).get(),
|
||||
- base::UnguessableToken::Create(),
|
||||
- std::make_unique<WorkerSettings>(window->GetFrame()->GetSettings()),
|
||||
+ base::UnguessableToken::Create(), std::move(worklet_settings),
|
||||
mojom::blink::V8CacheOptions::kDefault, module_responses_map,
|
||||
mojo::NullRemote() /* browser_interface_broker */,
|
||||
window->GetFrame()->Loader().CreateWorkerCodeCacheHost(),
|
||||
diff --git a/third_party/blink/renderer/core/workers/worker_settings.cc b/third_party/blink/renderer/core/workers/worker_settings.cc
|
||||
index 45680c5f6ea0c7e89ccf43eb88f8a11e3318c02e..3fa3af62f4e7ba8186441c5e3184b1c04fe32d12 100644
|
||||
--- a/third_party/blink/renderer/core/workers/worker_settings.cc
|
||||
@@ -71,3 +113,56 @@ index 45c60dd2c44b05fdd279f759069383479823c7f2..33a2a0337efb9a46293e11d0d09b3fc1
|
||||
|
||||
GenericFontFamilySettings generic_font_family_settings_;
|
||||
};
|
||||
diff --git a/third_party/blink/renderer/core/workers/worklet_global_scope.cc b/third_party/blink/renderer/core/workers/worklet_global_scope.cc
|
||||
index b5300dea97f20d72a807543a6da0baf61d21955f..a7030c1ba6851b26c765c7b05cd26e1453866719 100644
|
||||
--- a/third_party/blink/renderer/core/workers/worklet_global_scope.cc
|
||||
+++ b/third_party/blink/renderer/core/workers/worklet_global_scope.cc
|
||||
@@ -32,6 +32,7 @@
|
||||
#include "third_party/blink/renderer/core/script/modulator.h"
|
||||
#include "third_party/blink/renderer/core/workers/global_scope_creation_params.h"
|
||||
#include "third_party/blink/renderer/core/workers/worker_reporting_proxy.h"
|
||||
+#include "third_party/blink/renderer/core/workers/worker_settings.h"
|
||||
#include "third_party/blink/renderer/core/workers/worker_thread.h"
|
||||
#include "third_party/blink/renderer/core/workers/worklet_module_responses_map.h"
|
||||
#include "third_party/blink/renderer/core/workers/worklet_module_tree_client.h"
|
||||
@@ -110,6 +111,10 @@ WorkletGlobalScope::WorkletGlobalScope(
|
||||
parent_cross_origin_isolated_capability_(
|
||||
creation_params->cross_origin_isolated_capability),
|
||||
parent_is_isolated_context_(creation_params->parent_is_isolated_context),
|
||||
+ node_integration_in_worker_(
|
||||
+ creation_params->worker_settings
|
||||
+ ? creation_params->worker_settings->NodeIntegrationInWorker()
|
||||
+ : false),
|
||||
browser_interface_broker_proxy_(this) {
|
||||
DCHECK((thread_type_ == ThreadType::kMainThread && frame_) ||
|
||||
(thread_type_ == ThreadType::kOffMainThread && worker_thread_));
|
||||
diff --git a/third_party/blink/renderer/core/workers/worklet_global_scope.h b/third_party/blink/renderer/core/workers/worklet_global_scope.h
|
||||
index c7dd62900f0de48ab992a7c99058f5b6d98212cf..47ceea11ec9db6b67cef6945d165f46c868f4ca5 100644
|
||||
--- a/third_party/blink/renderer/core/workers/worklet_global_scope.h
|
||||
+++ b/third_party/blink/renderer/core/workers/worklet_global_scope.h
|
||||
@@ -140,6 +140,13 @@ class CORE_EXPORT WorkletGlobalScope : public WorkerOrWorkletGlobalScope {
|
||||
// Returns the WorkletToken that uniquely identifies this worklet.
|
||||
virtual WorkletToken GetWorkletToken() const = 0;
|
||||
|
||||
+ // Electron: returns whether the creator frame had the
|
||||
+ // `nodeIntegrationInWorker` web preference enabled. Copied from
|
||||
+ // GlobalScopeCreationParams::worker_settings at construction time so the
|
||||
+ // value is readable on the worker thread without crossing back to the
|
||||
+ // main thread.
|
||||
+ bool NodeIntegrationInWorker() const { return node_integration_in_worker_; }
|
||||
+
|
||||
// Returns the ExecutionContextToken that uniquely identifies the parent
|
||||
// context that created this worklet. Note that this will always be a
|
||||
// LocalFrameToken.
|
||||
@@ -207,6 +214,11 @@ class CORE_EXPORT WorkletGlobalScope : public WorkerOrWorkletGlobalScope {
|
||||
// TODO(crbug.com/1206150): We need a spec for this capability.
|
||||
const bool parent_is_isolated_context_;
|
||||
|
||||
+ // Electron: snapshot of the creator frame's nodeIntegrationInWorker
|
||||
+ // WebPreference, copied out of GlobalScopeCreationParams::worker_settings
|
||||
+ // at construction time.
|
||||
+ const bool node_integration_in_worker_;
|
||||
+
|
||||
// This is the interface that handles generated code cache
|
||||
// requests both to fetch code cache when loading resources
|
||||
// and to store generated code cache to disk.
|
||||
|
||||
@@ -23,10 +23,10 @@ additional headless changes from breaking macOS window behavior.
|
||||
https://chromium-review.googlesource.com/c/chromium/src/+/7487666
|
||||
|
||||
diff --git a/components/remote_cocoa/app_shim/native_widget_mac_nswindow.mm b/components/remote_cocoa/app_shim/native_widget_mac_nswindow.mm
|
||||
index 94bd32ce1ddd3f8b4315cd06be59d7550b591891..ad005e0a19a7763da089fccc659d93c8815dc860 100644
|
||||
index b4554165e3c5344c7ff0b21ccc3986c3e5edf593..4a9e866b57333cbaf8f8e9b415572e9da953e9a8 100644
|
||||
--- a/components/remote_cocoa/app_shim/native_widget_mac_nswindow.mm
|
||||
+++ b/components/remote_cocoa/app_shim/native_widget_mac_nswindow.mm
|
||||
@@ -231,6 +231,7 @@ @implementation NativeWidgetMacNSWindow {
|
||||
@@ -251,6 +251,7 @@ @implementation NativeWidgetMacNSWindow {
|
||||
BOOL _isEnforcingNeverMadeVisible;
|
||||
BOOL _activationIndependence;
|
||||
BOOL _isTooltip;
|
||||
@@ -34,7 +34,7 @@ index 94bd32ce1ddd3f8b4315cd06be59d7550b591891..ad005e0a19a7763da089fccc659d93c8
|
||||
BOOL _isShufflingForOrdering;
|
||||
BOOL _miniaturizationInProgress;
|
||||
std::unique_ptr<NativeWidgetMacNSWindowHeadlessInfo> _headless_info;
|
||||
@@ -238,6 +239,7 @@ @implementation NativeWidgetMacNSWindow {
|
||||
@@ -258,6 +259,7 @@ @implementation NativeWidgetMacNSWindow {
|
||||
@synthesize bridgedNativeWidgetId = _bridgedNativeWidgetId;
|
||||
@synthesize bridge = _bridge;
|
||||
@synthesize isTooltip = _isTooltip;
|
||||
@@ -42,7 +42,7 @@ index 94bd32ce1ddd3f8b4315cd06be59d7550b591891..ad005e0a19a7763da089fccc659d93c8
|
||||
@synthesize isShufflingForOrdering = _isShufflingForOrdering;
|
||||
@synthesize preventKeyWindow = _preventKeyWindow;
|
||||
@synthesize childWindowAddedHandler = _childWindowAddedHandler;
|
||||
@@ -259,23 +261,6 @@ - (instancetype)initWithContentRect:(NSRect)contentRect
|
||||
@@ -279,23 +281,6 @@ - (instancetype)initWithContentRect:(NSRect)contentRect
|
||||
return self;
|
||||
}
|
||||
|
||||
|
||||
@@ -1,120 +0,0 @@
|
||||
From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001
|
||||
From: Damglador <vse.stopchanskyi@gmail.com>
|
||||
Date: Fri, 26 Dec 2025 21:26:43 +0100
|
||||
Subject: fix: pulseaudio stream and icon names
|
||||
|
||||
Use platform_util::GetXdgAppId() with fallback to argv0 as PA_PROP_APPLICATION_ICON_NAME.
|
||||
Use electron::GetPossiblyOverriddenApplicationName()
|
||||
to set environment variable "ELECTRON_PA_APP_NAME" in audio_service.cc,
|
||||
to use it in pulse_util.cc for setting input/output pa_context name.
|
||||
|
||||
This replaces hard-codded kBrowserDisplayName that was used for PA_PROP_APPLICATION_ICON_NAME,
|
||||
and PRODUCT_STRING that was used for pa_context names.
|
||||
|
||||
This is done to make audio streams recognizable in tools like qpwgrapth and general audio managers,
|
||||
instead of having 20 "Chromium" outputs and "Chromium input" inputs, that are actually coming from
|
||||
completely different applications.
|
||||
|
||||
This patch can be removed when upstream starts using AudioManager::SetGlobalAppName()
|
||||
for all pa_context names (and when actually works with AudioServiceOutOfProcess).
|
||||
|
||||
diff --git a/content/browser/audio/audio_service.cc b/content/browser/audio/audio_service.cc
|
||||
index 70615782c50d18606c3baa42a223e54f8619bc07..fb67e69f9ff46b432236b46913a1b10dd8302887 100644
|
||||
--- a/content/browser/audio/audio_service.cc
|
||||
+++ b/content/browser/audio/audio_service.cc
|
||||
@@ -29,6 +29,9 @@
|
||||
#include "services/audio/public/mojom/audio_service.mojom.h"
|
||||
#include "services/audio/service.h"
|
||||
#include "services/audio/service_factory.h"
|
||||
+#if BUILDFLAG(IS_LINUX)
|
||||
+#include "electron/shell/common/application_info.h"
|
||||
+#endif
|
||||
|
||||
#if BUILDFLAG(ENABLE_PASSTHROUGH_AUDIO_CODECS) && BUILDFLAG(IS_WIN)
|
||||
#define PASS_EDID_ON_COMMAND_LINE 1
|
||||
@@ -109,6 +112,10 @@ void LaunchAudioServiceOutOfProcess(
|
||||
mojo::PendingReceiver<audio::mojom::AudioService> receiver,
|
||||
uint32_t codec_bitmask) {
|
||||
std::vector<std::string> switches;
|
||||
+#if BUILDFLAG(IS_LINUX)
|
||||
+ // Set ELECTRON_PA_APP_NAME variable for pulse_util to grab and set pa_context name
|
||||
+ setenv("ELECTRON_PA_APP_NAME", electron::GetPossiblyOverriddenApplicationName().c_str(), 1);
|
||||
+#endif
|
||||
#if BUILDFLAG(IS_MAC)
|
||||
// On Mac, the audio service requires a CFRunLoop provided by a
|
||||
// UI MessageLoop type, to run AVFoundation and CoreAudio code.
|
||||
diff --git a/media/audio/pulse/pulse_util.cc b/media/audio/pulse/pulse_util.cc
|
||||
index a08e42a464a3894cbf2b8e3cf8a320a33423b719..e5d69506e1585710a2540c91ca51cba7a4692575 100644
|
||||
--- a/media/audio/pulse/pulse_util.cc
|
||||
+++ b/media/audio/pulse/pulse_util.cc
|
||||
@@ -10,6 +10,7 @@
|
||||
#include <memory>
|
||||
#include <type_traits>
|
||||
|
||||
+#include "base/command_line.h"
|
||||
#include "base/files/file_path.h"
|
||||
#include "base/logging.h"
|
||||
#include "base/memory/ptr_util.h"
|
||||
@@ -20,6 +21,7 @@
|
||||
#include "build/branding_buildflags.h"
|
||||
#include "media/audio/audio_device_description.h"
|
||||
#include "media/base/audio_timestamp_helper.h"
|
||||
+#include "electron/shell/common/platform_util.h"
|
||||
|
||||
#if defined(DLOPEN_PULSEAUDIO)
|
||||
#include "media/audio/pulse/pulse_stubs.h"
|
||||
@@ -36,10 +38,8 @@ namespace pulse {
|
||||
namespace {
|
||||
|
||||
#if BUILDFLAG(GOOGLE_CHROME_BRANDING)
|
||||
-constexpr char kBrowserDisplayName[] = "google-chrome";
|
||||
#define PRODUCT_STRING "Google Chrome"
|
||||
#else
|
||||
-constexpr char kBrowserDisplayName[] = "chromium-browser";
|
||||
#define PRODUCT_STRING "Chromium"
|
||||
#endif
|
||||
|
||||
@@ -236,7 +236,7 @@ bool InitPulse(pa_threaded_mainloop** mainloop, pa_context** context) {
|
||||
|
||||
pa_mainloop_api* pa_mainloop_api = pa_threaded_mainloop_get_api(pa_mainloop);
|
||||
pa_context* pa_context =
|
||||
- pa_context_new(pa_mainloop_api, PRODUCT_STRING " input");
|
||||
+ pa_context_new(pa_mainloop_api, getenv("ELECTRON_PA_APP_NAME"));
|
||||
if (!pa_context) {
|
||||
pa_threaded_mainloop_free(pa_mainloop);
|
||||
return false;
|
||||
@@ -464,8 +464,11 @@ bool CreateInputStream(pa_threaded_mainloop* mainloop,
|
||||
// Create a new recording stream and
|
||||
// tells PulseAudio what the stream icon should be.
|
||||
ScopedPropertyList property_list;
|
||||
+ const std::string cmd_name =
|
||||
+ base::CommandLine::ForCurrentProcess()->GetProgram().BaseName().value();
|
||||
+ const std::string app_id = platform_util::GetXdgAppId().value_or(cmd_name);
|
||||
pa_proplist_sets(property_list.get(), PA_PROP_APPLICATION_ICON_NAME,
|
||||
- kBrowserDisplayName);
|
||||
+ app_id.c_str());
|
||||
*stream = pa_stream_new_with_proplist(context, "RecordStream",
|
||||
&sample_specifications, map,
|
||||
property_list.get());
|
||||
@@ -526,7 +529,7 @@ bool CreateOutputStream(raw_ptr<pa_threaded_mainloop>* mainloop,
|
||||
|
||||
pa_mainloop_api* pa_mainloop_api = pa_threaded_mainloop_get_api(*mainloop);
|
||||
*context = pa_context_new(
|
||||
- pa_mainloop_api, app_name.empty() ? PRODUCT_STRING : app_name.c_str());
|
||||
+ pa_mainloop_api, getenv("ELECTRON_PA_APP_NAME"));
|
||||
RETURN_ON_FAILURE(*context, "Failed to create PulseAudio context.");
|
||||
|
||||
// A state callback must be set before calling pa_threaded_mainloop_lock() or
|
||||
@@ -574,8 +577,11 @@ bool CreateOutputStream(raw_ptr<pa_threaded_mainloop>* mainloop,
|
||||
// Open playback stream and
|
||||
// tell PulseAudio what the stream icon should be.
|
||||
ScopedPropertyList property_list;
|
||||
+ const std::string cmd_name =
|
||||
+ base::CommandLine::ForCurrentProcess()->GetProgram().BaseName().value();
|
||||
+ const std::string app_id = platform_util::GetXdgAppId().value_or(cmd_name);
|
||||
pa_proplist_sets(property_list.get(), PA_PROP_APPLICATION_ICON_NAME,
|
||||
- kBrowserDisplayName);
|
||||
+ app_id.c_str());
|
||||
*stream = pa_stream_new_with_proplist(
|
||||
*context, "Playback", &sample_specifications, map, property_list.get());
|
||||
RETURN_ON_FAILURE(*stream, "failed to create PA playback stream");
|
||||
@@ -1,52 +0,0 @@
|
||||
From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001
|
||||
From: Sam Attard <sattard@anthropic.com>
|
||||
Date: Sun, 22 Mar 2026 19:21:45 +0000
|
||||
Subject: fix: use fresh LazyNow for OnEndWorkItemImpl after DidRunTask
|
||||
|
||||
DidRunTask can cache the LazyNow early (via RecordTaskEnd in
|
||||
BrowserUIThreadScheduler::OnTaskCompleted) before running task observers.
|
||||
If a task observer's DidProcessTask triggers nested pump activity (nested
|
||||
RunLoop, sync IPC, etc.), TimeKeeper's last_phase_end_ advances past the
|
||||
cached value. The subsequent OnEndWorkItemImpl then computes a negative
|
||||
delta and hits DCHECK(!delta.is_negative()) in RecordTimeInPhase.
|
||||
|
||||
Using a fresh LazyNow for OnEndWorkItemImpl samples the time after all
|
||||
observers have run, which matches the existing comment's intent that
|
||||
microtasks are extensions of the RunTask and the work item ends after them.
|
||||
|
||||
This is upstreamable: the bug exists whenever any TaskObserver::DidProcessTask
|
||||
triggers nested pump activity, which is not forbidden by the contract.
|
||||
|
||||
diff --git a/base/task/sequence_manager/thread_controller_with_message_pump_impl.cc b/base/task/sequence_manager/thread_controller_with_message_pump_impl.cc
|
||||
index bb09c99ea0b37a139440d0fe98c7f2f5e9c147e0..d27c34f8090ff54d20d8339c0ad56d37d6d61ab2 100644
|
||||
--- a/base/task/sequence_manager/thread_controller_with_message_pump_impl.cc
|
||||
+++ b/base/task/sequence_manager/thread_controller_with_message_pump_impl.cc
|
||||
@@ -481,15 +481,22 @@ std::optional<WakeUp> ThreadControllerWithMessagePumpImpl::DoWorkImpl(
|
||||
// `PendingTask` reference dangling.
|
||||
selected_task.reset();
|
||||
|
||||
- LazyNow lazy_now_after_run_task(time_source_);
|
||||
- main_thread_only().task_source->DidRunTask(lazy_now_after_run_task);
|
||||
+ {
|
||||
+ LazyNow lazy_now_did_run_task(time_source_);
|
||||
+ main_thread_only().task_source->DidRunTask(lazy_now_did_run_task);
|
||||
+ }
|
||||
// End the work item scope after DidRunTask() as it can process microtasks
|
||||
- // (which are extensions of the RunTask).
|
||||
+ // (which are extensions of the RunTask). Use a fresh LazyNow here because
|
||||
+ // DidRunTask may cache the LazyNow (via RecordTaskEnd) before running task
|
||||
+ // observers, and those observers may trigger nested pump activity that
|
||||
+ // advances TimeKeeper's last_phase_end_ past the cached value, resulting
|
||||
+ // in a negative delta in RecordTimeInPhase.
|
||||
+ LazyNow lazy_now_after_run_task(time_source_);
|
||||
OnEndWorkItemImpl(lazy_now_after_run_task, run_depth);
|
||||
|
||||
- // If DidRunTask() read the clock (lazy_now_after_run_task.has_value()) or
|
||||
- // if |batch_duration| > 0, store the clock value in `recent_time` so it can
|
||||
- // be reused by SelectNextTask() at the next loop iteration.
|
||||
+ // If OnEndWorkItemImpl() read the clock (lazy_now_after_run_task.has_value())
|
||||
+ // or if |batch_duration| > 0, store the clock value in `recent_time` so it
|
||||
+ // can be reused by SelectNextTask() at the next loop iteration.
|
||||
if (lazy_now_after_run_task.has_value() || !batch_duration.is_zero()) {
|
||||
recent_time = lazy_now_after_run_task.Now();
|
||||
} else {
|
||||
@@ -1,48 +0,0 @@
|
||||
From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001
|
||||
From: deepak1556 <hop2deep@gmail.com>
|
||||
Date: Tue, 7 Apr 2026 02:34:49 +0900
|
||||
Subject: [gin] Mark ArgumentHolder as CPPGC_STACK_ALLOCATED
|
||||
|
||||
ArgumentHolder is always stack-allocated from Invoker.
|
||||
When ArgType is a pointer to a cppgc-managed type, the blink-gc plugin
|
||||
reports an error for the raw pointer `value` field:
|
||||
|
||||
[blink-gc] Class 'ArgumentHolder<0, T*>' contains invalid fields.
|
||||
[blink-gc] Raw pointer field 'value' to a GC managed class.
|
||||
|
||||
Disallow any heap allocations and make the lifetime explicit.
|
||||
|
||||
Backports https://chromium-review.googlesource.com/c/chromium/src/+/7728865
|
||||
|
||||
diff --git a/gin/function_template.h b/gin/function_template.h
|
||||
index 873015289db9709c00c32080e5387d9cdfea1f69..bc84040952b79f02df783833005cc9583f3378a5 100644
|
||||
--- a/gin/function_template.h
|
||||
+++ b/gin/function_template.h
|
||||
@@ -20,6 +20,7 @@
|
||||
#include "gin/gin_export.h"
|
||||
#include "gin/per_isolate_data.h"
|
||||
#include "gin/public/gin_embedders.h"
|
||||
+#include "v8/include/cppgc/macros.h"
|
||||
#include "v8/include/v8-external.h"
|
||||
#include "v8/include/v8-forward.h"
|
||||
#include "v8/include/v8-persistent-handle.h"
|
||||
@@ -162,6 +163,9 @@ GIN_EXPORT void ThrowConversionError(Arguments* args,
|
||||
// at position |index|.
|
||||
template <size_t index, typename ArgType, typename = void>
|
||||
struct ArgumentHolder {
|
||||
+ CPPGC_STACK_ALLOCATED();
|
||||
+
|
||||
+ public:
|
||||
using ArgLocalType = typename CallbackParamTraits<ArgType>::LocalType;
|
||||
|
||||
ArgLocalType value;
|
||||
@@ -184,6 +188,9 @@ template <size_t index, typename ArgType>
|
||||
std::is_constructible_v<typename CallbackParamTraits<ArgType>::LocalType,
|
||||
v8::Isolate*>)
|
||||
struct ArgumentHolder<index, ArgType> {
|
||||
+ CPPGC_STACK_ALLOCATED();
|
||||
+
|
||||
+ public:
|
||||
using ArgLocalType = typename CallbackParamTraits<ArgType>::LocalType;
|
||||
|
||||
ArgLocalType value;
|
||||
@@ -640,7 +640,7 @@ index 48f47bf3eeb8464d1c3925f0f73f62c790cac2f0..b7b2b7c1b7e99927012ce1676cc753b2
|
||||
// The NSWindow used by BridgedNativeWidget. Provides hooks into AppKit that
|
||||
// can only be accomplished by overriding methods.
|
||||
diff --git a/components/remote_cocoa/app_shim/native_widget_mac_nswindow.mm b/components/remote_cocoa/app_shim/native_widget_mac_nswindow.mm
|
||||
index a5fc9193711a7cc2eee45171178c070321177ca2..94bd32ce1ddd3f8b4315cd06be59d7550b591891 100644
|
||||
index a5fc9193711a7cc2eee45171178c070321177ca2..b4554165e3c5344c7ff0b21ccc3986c3e5edf593 100644
|
||||
--- a/components/remote_cocoa/app_shim/native_widget_mac_nswindow.mm
|
||||
+++ b/components/remote_cocoa/app_shim/native_widget_mac_nswindow.mm
|
||||
@@ -22,6 +22,7 @@
|
||||
@@ -677,7 +677,7 @@ index a5fc9193711a7cc2eee45171178c070321177ca2..94bd32ce1ddd3f8b4315cd06be59d755
|
||||
@end
|
||||
|
||||
struct NSEdgeAndCornerThicknesses {
|
||||
@@ -159,13 +164,30 @@ - (void)cr_mouseDownOnFrameView:(NSEvent*)event;
|
||||
@@ -159,13 +164,50 @@ - (void)cr_mouseDownOnFrameView:(NSEvent*)event;
|
||||
@implementation NSView (CRFrameViewAdditions)
|
||||
// If a mouseDown: falls through to the frame view, turn it into a window drag.
|
||||
- (void)cr_mouseDownOnFrameView:(NSEvent*)event {
|
||||
@@ -688,13 +688,33 @@ index a5fc9193711a7cc2eee45171178c070321177ca2..94bd32ce1ddd3f8b4315cd06be59d755
|
||||
+#else
|
||||
+ // For MAS builds, approximate the resize direction check.
|
||||
+ if (self.window.styleMask & NSWindowStyleMaskResizable) {
|
||||
+ constexpr CGFloat kResizeThreshold = 5.0;
|
||||
+ // Match Electron's frameless resize affordances:
|
||||
+ // - 5pt resize handles along edges
|
||||
+ // - 16pt resize hot-zone at corners
|
||||
+ //
|
||||
+ // If we misclassify a resize as a drag, we can end up with a window that
|
||||
+ // moves while it is being resized (most noticeable near corners).
|
||||
+ constexpr CGFloat kResizeInsideBoundsSize = 5.0;
|
||||
+ constexpr CGFloat kResizeAreaCornerSize = 16.0;
|
||||
+ NSPoint location = event.locationInWindow;
|
||||
+ NSRect frame = self.window.frame;
|
||||
+ CGFloat width = NSWidth(frame);
|
||||
+ CGFloat height = NSHeight(frame);
|
||||
+ if (location.x < kResizeThreshold || location.x > width - kResizeThreshold ||
|
||||
+ location.y < kResizeThreshold || location.y > height - kResizeThreshold) {
|
||||
+
|
||||
+ const bool in_left_edge = location.x < kResizeInsideBoundsSize;
|
||||
+ const bool in_right_edge = location.x > width - kResizeInsideBoundsSize;
|
||||
+ const bool in_bottom_edge = location.y < kResizeInsideBoundsSize;
|
||||
+ const bool in_top_edge = location.y > height - kResizeInsideBoundsSize;
|
||||
+
|
||||
+ const bool in_left_corner_zone = location.x < kResizeAreaCornerSize;
|
||||
+ const bool in_right_corner_zone = location.x > width - kResizeAreaCornerSize;
|
||||
+ const bool in_bottom_corner_zone = location.y < kResizeAreaCornerSize;
|
||||
+ const bool in_top_corner_zone = location.y > height - kResizeAreaCornerSize;
|
||||
+ const bool in_corner = (in_left_corner_zone || in_right_corner_zone) &&
|
||||
+ (in_bottom_corner_zone || in_top_corner_zone);
|
||||
+
|
||||
+ if (in_left_edge || in_right_edge || in_bottom_edge || in_top_edge ||
|
||||
+ in_corner) {
|
||||
+ return;
|
||||
+ }
|
||||
+ }
|
||||
@@ -708,7 +728,7 @@ index a5fc9193711a7cc2eee45171178c070321177ca2..94bd32ce1ddd3f8b4315cd06be59d755
|
||||
@implementation NativeWidgetMacNSWindowTitledFrame
|
||||
- (void)mouseDown:(NSEvent*)event {
|
||||
if (self.window.isMovable)
|
||||
@@ -193,6 +215,8 @@ - (BOOL)usesCustomDrawing {
|
||||
@@ -193,6 +235,8 @@ - (BOOL)usesCustomDrawing {
|
||||
}
|
||||
@end
|
||||
|
||||
@@ -717,7 +737,7 @@ index a5fc9193711a7cc2eee45171178c070321177ca2..94bd32ce1ddd3f8b4315cd06be59d755
|
||||
@implementation NativeWidgetMacNSWindow {
|
||||
@private
|
||||
CommandDispatcher* __strong _commandDispatcher;
|
||||
@@ -268,6 +292,7 @@ - (BOOL)invokeOriginalIsVisibleForTesting {
|
||||
@@ -268,6 +312,7 @@ - (BOOL)invokeOriginalIsVisibleForTesting {
|
||||
// bubbles and the find bar, but these should not be movable.
|
||||
// Instead, let's push this up to the parent window which should be
|
||||
// the browser.
|
||||
@@ -725,7 +745,7 @@ index a5fc9193711a7cc2eee45171178c070321177ca2..94bd32ce1ddd3f8b4315cd06be59d755
|
||||
- (void)_zoomToScreenEdge:(NSUInteger)edge {
|
||||
if (self.parentWindow) {
|
||||
[self.parentWindow _zoomToScreenEdge:edge];
|
||||
@@ -275,6 +300,7 @@ - (void)_zoomToScreenEdge:(NSUInteger)edge {
|
||||
@@ -275,6 +320,7 @@ - (void)_zoomToScreenEdge:(NSUInteger)edge {
|
||||
[super _zoomToScreenEdge:edge];
|
||||
}
|
||||
}
|
||||
@@ -733,7 +753,7 @@ index a5fc9193711a7cc2eee45171178c070321177ca2..94bd32ce1ddd3f8b4315cd06be59d755
|
||||
|
||||
// This override helps diagnose lifetime issues in crash stacktraces by
|
||||
// inserting a symbol on NativeWidgetMacNSWindow and should be kept even if it
|
||||
@@ -407,6 +433,8 @@ - (NSAccessibilityRole)accessibilityRole {
|
||||
@@ -407,6 +453,8 @@ - (NSAccessibilityRole)accessibilityRole {
|
||||
|
||||
// NSWindow overrides.
|
||||
|
||||
@@ -742,7 +762,7 @@ index a5fc9193711a7cc2eee45171178c070321177ca2..94bd32ce1ddd3f8b4315cd06be59d755
|
||||
+ (Class)frameViewClassForStyleMask:(NSWindowStyleMask)windowStyle {
|
||||
if (windowStyle & NSWindowStyleMaskTitled) {
|
||||
if (Class customFrame = [NativeWidgetMacNSWindowTitledFrame class])
|
||||
@@ -418,6 +446,8 @@ + (Class)frameViewClassForStyleMask:(NSWindowStyleMask)windowStyle {
|
||||
@@ -418,6 +466,8 @@ + (Class)frameViewClassForStyleMask:(NSWindowStyleMask)windowStyle {
|
||||
return [super frameViewClassForStyleMask:windowStyle];
|
||||
}
|
||||
|
||||
@@ -751,7 +771,7 @@ index a5fc9193711a7cc2eee45171178c070321177ca2..94bd32ce1ddd3f8b4315cd06be59d755
|
||||
- (NSRect)constrainFrameRect:(NSRect)frameRect toScreen:(NSScreen*)screen {
|
||||
if (self.isHeadless || self.parentWindow) {
|
||||
// AppKit's default implementation moves child windows down to avoid
|
||||
@@ -455,12 +485,14 @@ - (BOOL)_usesCustomDrawing {
|
||||
@@ -455,12 +505,14 @@ - (BOOL)_usesCustomDrawing {
|
||||
// if it were valid to set that style for windows, setting the window style
|
||||
// recalculates and re-caches a bunch of stuff, so a surgical override is the
|
||||
// cleanest approach.
|
||||
@@ -766,7 +786,7 @@ index a5fc9193711a7cc2eee45171178c070321177ca2..94bd32ce1ddd3f8b4315cd06be59d755
|
||||
|
||||
+ (void)_getExteriorResizeEdgeThicknesses:
|
||||
(NSEdgeAndCornerThicknesses*)outThicknesses
|
||||
@@ -714,9 +746,11 @@ - (id)archiver:(NSKeyedArchiver*)archiver willEncodeObject:(id)object {
|
||||
@@ -714,9 +766,11 @@ - (id)archiver:(NSKeyedArchiver*)archiver willEncodeObject:(id)object {
|
||||
}
|
||||
|
||||
- (void)saveRestorableState {
|
||||
@@ -778,7 +798,7 @@ index a5fc9193711a7cc2eee45171178c070321177ca2..94bd32ce1ddd3f8b4315cd06be59d755
|
||||
|
||||
// Certain conditions, such as in the Speedometer 3 benchmark, can trigger a
|
||||
// rapid succession of calls to saveRestorableState. If there's no pending
|
||||
@@ -783,6 +817,7 @@ - (void)reallySaveRestorableState {
|
||||
@@ -783,6 +837,7 @@ - (void)reallySaveRestorableState {
|
||||
// affects its restorable state changes.
|
||||
- (void)invalidateRestorableState {
|
||||
[super invalidateRestorableState];
|
||||
@@ -786,7 +806,7 @@ index a5fc9193711a7cc2eee45171178c070321177ca2..94bd32ce1ddd3f8b4315cd06be59d755
|
||||
if ([self _isConsideredOpenForPersistentState]) {
|
||||
if (_willUpdateRestorableState)
|
||||
return;
|
||||
@@ -795,6 +830,7 @@ - (void)invalidateRestorableState {
|
||||
@@ -795,6 +850,7 @@ - (void)invalidateRestorableState {
|
||||
_willUpdateRestorableState = NO;
|
||||
[NSObject cancelPreviousPerformRequestsWithTarget:self];
|
||||
}
|
||||
@@ -794,7 +814,7 @@ index a5fc9193711a7cc2eee45171178c070321177ca2..94bd32ce1ddd3f8b4315cd06be59d755
|
||||
}
|
||||
|
||||
// On newer SDKs, _canMiniaturize respects NSWindowStyleMaskMiniaturizable in
|
||||
@@ -971,6 +1007,7 @@ - (void)maybeRemoveTreeFromOrderingGroups {
|
||||
@@ -971,6 +1027,7 @@ - (void)maybeRemoveTreeFromOrderingGroups {
|
||||
// Since _removeFromGroups: is not documented it could go away in newer
|
||||
// versions of macOS. If the selector does not exist, DumpWithoutCrashing() so
|
||||
// we hear about the change.
|
||||
@@ -802,7 +822,7 @@ index a5fc9193711a7cc2eee45171178c070321177ca2..94bd32ce1ddd3f8b4315cd06be59d755
|
||||
if (![NSWindow instancesRespondToSelector:@selector(_removeFromGroups:)]) {
|
||||
base::debug::DumpWithoutCrashing();
|
||||
return;
|
||||
@@ -988,6 +1025,7 @@ - (void)maybeRemoveTreeFromOrderingGroups {
|
||||
@@ -988,6 +1045,7 @@ - (void)maybeRemoveTreeFromOrderingGroups {
|
||||
[currentWindow _removeFromGroups:child];
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1,2 +1,3 @@
|
||||
chore_expose_ui_to_allow_electron_to_set_dock_side.patch
|
||||
feat_allow_enabling_extension_panels_on_custom_protocols.patch
|
||||
fix_context_selector_not_showing_execution_contexts.patch
|
||||
|
||||
@@ -0,0 +1,25 @@
|
||||
From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001
|
||||
From: Fedor Indutny <indutny@signal.org>
|
||||
Date: Tue, 14 Apr 2026 19:33:23 -0700
|
||||
Subject: Fix context selector not showing execution contexts
|
||||
|
||||
When execution context's origin is `file://` - the `url.domain()` is an
|
||||
empty string and the item's subtitle becomes falsy. Since we predicated
|
||||
rendering of an item on presence of both title and subtitle - the items
|
||||
were not rendered while still taking space in the dropdown.
|
||||
|
||||
Pending CL: https://chromium-review.googlesource.com/c/devtools/devtools-frontend/+/7761316
|
||||
|
||||
diff --git a/front_end/panels/console/ConsoleContextSelector.ts b/front_end/panels/console/ConsoleContextSelector.ts
|
||||
index f933dbd6dbdfadd2ea8b78e473d9506350825037..d8aa3f9811f1857a9b30231ed8ff59e709e3383c 100644
|
||||
--- a/front_end/panels/console/ConsoleContextSelector.ts
|
||||
+++ b/front_end/panels/console/ConsoleContextSelector.ts
|
||||
@@ -303,7 +303,7 @@ interface ViewInput {
|
||||
type View = (input: ViewInput, output: undefined, target: HTMLElement) => void;
|
||||
|
||||
const DEFAULT_VIEW: View = (input, _output, target): void => {
|
||||
- if (!input.title || !input.subtitle) {
|
||||
+ if (!input.title) {
|
||||
render(nothing, target);
|
||||
return;
|
||||
}
|
||||
@@ -133,10 +133,10 @@ index 6fe4f0492dc1f3eaf576c8ff7866080a54cb81c1..41e8e052ff81df78ece87163b0499966
|
||||
// Recreate the buffer in the constructor.
|
||||
InternalFieldInfo* casted_info = static_cast<InternalFieldInfo*>(info);
|
||||
diff --git a/src/env.cc b/src/env.cc
|
||||
index 57a46c8be2e052b298ed841eed6f291d62711750..e4ffaa465a4ffe21334496c52334fcb1404f67a9 100644
|
||||
index b5cf58cc953590493beb52abf249e33e486ffc46..347ec5c42e098186ff489dff199ac5989961f6e3 100644
|
||||
--- a/src/env.cc
|
||||
+++ b/src/env.cc
|
||||
@@ -1764,10 +1764,10 @@ void AsyncHooks::Deserialize(Local<Context> context) {
|
||||
@@ -1765,10 +1765,10 @@ void AsyncHooks::Deserialize(Local<Context> context) {
|
||||
context->GetDataFromSnapshotOnce<Array>(
|
||||
info_->js_execution_async_resources).ToLocalChecked();
|
||||
} else {
|
||||
@@ -149,7 +149,7 @@ index 57a46c8be2e052b298ed841eed6f291d62711750..e4ffaa465a4ffe21334496c52334fcb1
|
||||
|
||||
// The native_execution_async_resources_ field requires v8::Local<> instances
|
||||
// for async calls whose resources were on the stack as JS objects when they
|
||||
@@ -1807,7 +1807,7 @@ AsyncHooks::SerializeInfo AsyncHooks::Serialize(Local<Context> context,
|
||||
@@ -1808,7 +1808,7 @@ AsyncHooks::SerializeInfo AsyncHooks::Serialize(Local<Context> context,
|
||||
info.async_id_fields = async_id_fields_.Serialize(context, creator);
|
||||
if (!js_execution_async_resources_.IsEmpty()) {
|
||||
info.js_execution_async_resources = creator->AddData(
|
||||
@@ -458,7 +458,7 @@ index fea0426496978c0003fe1481afcf93fc9c23edca..c9588880d05435ab9f4e23fcff74c933
|
||||
|
||||
CHECK(
|
||||
diff --git a/src/node_contextify.cc b/src/node_contextify.cc
|
||||
index 986a2d8da7fd04b5d4060d9c8d44c61a231dcce6..9f11d32c70366524cf3b7c1cfdfd24f31e438e7b 100644
|
||||
index 3c234205e89be7e976dae5c3fcc73ca67953e034..e66d4fcb0c064f96cdb819c783027d864fe88d12 100644
|
||||
--- a/src/node_contextify.cc
|
||||
+++ b/src/node_contextify.cc
|
||||
@@ -113,7 +113,7 @@ namespace {
|
||||
@@ -479,7 +479,7 @@ index 986a2d8da7fd04b5d4060d9c8d44c61a231dcce6..9f11d32c70366524cf3b7c1cfdfd24f3
|
||||
|
||||
PropertyAttribute attributes = PropertyAttribute::None;
|
||||
bool is_declared =
|
||||
@@ -1665,7 +1665,7 @@ static MaybeLocal<Function> CompileFunctionForCJSLoader(
|
||||
@@ -1666,7 +1666,7 @@ static MaybeLocal<Function> CompileFunctionForCJSLoader(
|
||||
bool* cache_rejected,
|
||||
bool is_cjs_scope,
|
||||
ScriptCompiler::CachedData* cached_data) {
|
||||
@@ -533,10 +533,10 @@ index 55a0c986c5b6989ee9ce277bb6a9778abb2ad2ee..809d88f21e5572807e38132d40ee7587
|
||||
READONLY_PROPERTY(target, "exitCodes", exit_codes);
|
||||
|
||||
diff --git a/src/node_file.cc b/src/node_file.cc
|
||||
index c7a9648b0f83e910190dc620f4b72577ffde6c44..46cd16b535d9bd651ef733ca52ea58db7d39b09f 100644
|
||||
index 96aac2d86695732bf6805f2ad2168a62241b5045..547455bb5011677719a8de1f98cb447561bce6aa 100644
|
||||
--- a/src/node_file.cc
|
||||
+++ b/src/node_file.cc
|
||||
@@ -3857,7 +3857,7 @@ void BindingData::Deserialize(Local<Context> context,
|
||||
@@ -3850,7 +3850,7 @@ void BindingData::Deserialize(Local<Context> context,
|
||||
int index,
|
||||
InternalFieldInfoBase* info) {
|
||||
DCHECK_IS_SNAPSHOT_SLOT(index);
|
||||
|
||||
@@ -14,10 +14,10 @@ We don't need to do this for zlib, as the existing gn workflow uses the same
|
||||
Upstreamed at https://github.com/nodejs/node/pull/55903
|
||||
|
||||
diff --git a/unofficial.gni b/unofficial.gni
|
||||
index a773152813376bef1fa227c331241a1d944c9317..43f09d1e68c88d3ba3b862a1a74769f73c370894 100644
|
||||
index bff7b0650cfe8578a044e45d0f9e352859909695..4ab316e45bd84e43a53335df60f847b17fe6c2fa 100644
|
||||
--- a/unofficial.gni
|
||||
+++ b/unofficial.gni
|
||||
@@ -203,7 +203,17 @@ template("node_gn_build") {
|
||||
@@ -199,7 +199,17 @@ template("node_gn_build") {
|
||||
configs -= [ "//build/config/gcc:symbol_visibility_hidden" ]
|
||||
configs += [ "//build/config/gcc:symbol_visibility_default" ]
|
||||
}
|
||||
@@ -36,7 +36,7 @@ index a773152813376bef1fa227c331241a1d944c9317..43f09d1e68c88d3ba3b862a1a74769f7
|
||||
if (v8_enable_i18n_support) {
|
||||
deps += [ "//third_party/icu" ]
|
||||
}
|
||||
@@ -236,6 +246,19 @@ template("node_gn_build") {
|
||||
@@ -232,6 +242,19 @@ template("node_gn_build") {
|
||||
sources += node_inspector.node_inspector_sources +
|
||||
node_inspector.node_inspector_generated_sources
|
||||
}
|
||||
|
||||
@@ -3,14 +3,20 @@ From: Shelley Vohr <shelley.vohr@gmail.com>
|
||||
Date: Wed, 17 Apr 2024 08:17:49 -0400
|
||||
Subject: build: enable perfetto
|
||||
|
||||
Enable perfetto by default in Node.js and wire track events
|
||||
through legacy shim.
|
||||
Enable perfetto by default in Node.js. Node.js disables perfetto by
|
||||
default but is broken on build - they don't currently add guards for
|
||||
`V8_USE_PERFETTO` and upstream only defines certain functions
|
||||
on `v8::TracingController` if perfetto is disabled. Electron already
|
||||
had minimal to no support for Node.js trace events, so the impact of
|
||||
adding associated guards there should be relatively small.
|
||||
|
||||
We should upstream this as it will eventually impact Node.js as well.
|
||||
|
||||
diff --git a/lib/internal/constants.js b/lib/internal/constants.js
|
||||
index 8d7204f6cb48f783adc4d1c1eb2de0c83b7fffe2..8061013fcfe3c3b02aabaca0447069423ac853b2 100644
|
||||
index 8d7204f6cb48f783adc4d1c1eb2de0c83b7fffe2..a154559a56bf383d3c26af523c9bb07b564ef600 100644
|
||||
--- a/lib/internal/constants.js
|
||||
+++ b/lib/internal/constants.js
|
||||
@@ -5,12 +5,16 @@ const isWindows = process.platform === 'win32';
|
||||
@@ -5,12 +5,15 @@ const isWindows = process.platform === 'win32';
|
||||
module.exports = {
|
||||
// Alphabet chars.
|
||||
CHAR_UPPERCASE_A: 65, /* A */
|
||||
@@ -22,216 +28,61 @@ index 8d7204f6cb48f783adc4d1c1eb2de0c83b7fffe2..8061013fcfe3c3b02aabaca044706942
|
||||
CHAR_LOWERCASE_B: 98, /* b */
|
||||
+ CHAR_UPPERCASE_E: 69, /* E */
|
||||
CHAR_LOWERCASE_E: 101, /* e */
|
||||
+ CHAR_UPPERCASE_I: 73, /* I */
|
||||
+
|
||||
CHAR_LOWERCASE_N: 110, /* n */
|
||||
|
||||
// Non-alphabetic chars.
|
||||
diff --git a/lib/internal/http.js b/lib/internal/http.js
|
||||
index f8b4fd7c4ca5a0907806c7e804de8c951675a36a..0f924a5cc6718415226ffef5f8bc40a51043be04 100644
|
||||
index f8b4fd7c4ca5a0907806c7e804de8c951675a36a..209e3bcf8be5a23ac528dcd673bed82cbad709ca 100644
|
||||
--- a/lib/internal/http.js
|
||||
+++ b/lib/internal/http.js
|
||||
@@ -9,7 +9,7 @@ const {
|
||||
} = primordials;
|
||||
|
||||
@@ -11,8 +11,8 @@ const {
|
||||
const { setUnrefTimeout } = require('internal/timers');
|
||||
-const { getCategoryEnabledBuffer, trace } = internalBinding('trace_events');
|
||||
+const { isTraceCategoryEnabled, trace } = internalBinding('trace_events');
|
||||
const { getCategoryEnabledBuffer, trace } = internalBinding('trace_events');
|
||||
const {
|
||||
CHAR_LOWERCASE_B,
|
||||
CHAR_LOWERCASE_E,
|
||||
@@ -42,13 +42,11 @@ function getNextTraceEventId() {
|
||||
return ++traceEventId;
|
||||
}
|
||||
- CHAR_LOWERCASE_B,
|
||||
- CHAR_LOWERCASE_E,
|
||||
+ CHAR_UPPERCASE_B,
|
||||
+ CHAR_UPPERCASE_E,
|
||||
} = require('internal/constants');
|
||||
|
||||
-const httpEnabled = getCategoryEnabledBuffer('node.http');
|
||||
-
|
||||
function isTraceHTTPEnabled() {
|
||||
- return httpEnabled[0] > 0;
|
||||
+ return isTraceCategoryEnabled('node.http');
|
||||
}
|
||||
|
||||
-const traceEventCategory = 'node,node.http';
|
||||
+const traceEventCategory = 'node.http';
|
||||
const { URL } = require('internal/url');
|
||||
@@ -51,11 +51,13 @@ function isTraceHTTPEnabled() {
|
||||
const traceEventCategory = 'node,node.http';
|
||||
|
||||
function traceBegin(...args) {
|
||||
trace(CHAR_LOWERCASE_B, traceEventCategory, ...args);
|
||||
diff --git a/lib/internal/perf/usertiming.js b/lib/internal/perf/usertiming.js
|
||||
index 88bb63ead2d3d620dea6b54db043a404b484ead9..a37386bbf51b55b26a140cd81fbaf26d78015f21 100644
|
||||
--- a/lib/internal/perf/usertiming.js
|
||||
+++ b/lib/internal/perf/usertiming.js
|
||||
@@ -13,6 +13,12 @@ const { PerformanceEntry, kSkipThrow } = require('internal/perf/performance_entr
|
||||
const { now } = require('internal/perf/utils');
|
||||
const { enqueue, bufferUserTiming } = require('internal/perf/observe');
|
||||
const nodeTiming = require('internal/perf/nodetiming');
|
||||
+const { isTraceCategoryEnabled, trace } = internalBinding('trace_events');
|
||||
+const {
|
||||
+ CHAR_LOWERCASE_B,
|
||||
+ CHAR_LOWERCASE_E,
|
||||
+ CHAR_UPPERCASE_I
|
||||
+} = require('internal/constants');
|
||||
|
||||
const {
|
||||
validateNumber,
|
||||
@@ -41,6 +47,9 @@ const kDetail = Symbol('kDetail');
|
||||
|
||||
const markTimings = new SafeMap();
|
||||
|
||||
+const traceEventCategory = 'node.perf.usertiming';
|
||||
+let traceEventId = 0;
|
||||
+
|
||||
const nodeTimingReadOnlyAttributes = new SafeSet(new SafeArrayIterator([
|
||||
'nodeStart',
|
||||
'v8Start',
|
||||
@@ -168,6 +177,10 @@ function mark(name, options) {
|
||||
const mark = new PerformanceMark(name, options);
|
||||
enqueue(mark);
|
||||
bufferUserTiming(mark);
|
||||
+ if (isTraceCategoryEnabled(traceEventCategory)) {
|
||||
+ trace(CHAR_UPPERCASE_I, traceEventCategory, name, undefined,
|
||||
+ { startTime: mark.startTime });
|
||||
+ }
|
||||
return mark;
|
||||
- trace(CHAR_LOWERCASE_B, traceEventCategory, ...args);
|
||||
+ // See v8/src/builtins/builtins-trace.cc - must be uppercase for perfetto
|
||||
+ trace(CHAR_UPPERCASE_B, traceEventCategory, ...args);
|
||||
}
|
||||
|
||||
@@ -233,6 +246,13 @@ function measure(name, startOrMeasureOptions, endMark) {
|
||||
const measure = createPerformanceMeasure(name, start, duration, detail);
|
||||
enqueue(measure);
|
||||
bufferUserTiming(measure);
|
||||
+ if (isTraceCategoryEnabled(traceEventCategory)) {
|
||||
+ const id = ++traceEventId;
|
||||
+ trace(CHAR_LOWERCASE_B, traceEventCategory, name, id,
|
||||
+ { startTime: start });
|
||||
+ trace(CHAR_LOWERCASE_E, traceEventCategory, name, id,
|
||||
+ { startTime: start, duration });
|
||||
+ }
|
||||
return measure;
|
||||
function traceEnd(...args) {
|
||||
- trace(CHAR_LOWERCASE_E, traceEventCategory, ...args);
|
||||
+ // See v8/src/builtins/builtins-trace.cc - must be uppercase for perfetto
|
||||
+ trace(CHAR_UPPERCASE_E, traceEventCategory, ...args);
|
||||
}
|
||||
|
||||
diff --git a/lib/internal/trace_events_async_hooks.js b/lib/internal/trace_events_async_hooks.js
|
||||
index a9f517ffc9e4eea5bc68997ffadc85d43dde2a52..e85bcd2f500ff3f5bbd2b25922c13cb29de50993 100644
|
||||
--- a/lib/internal/trace_events_async_hooks.js
|
||||
+++ b/lib/internal/trace_events_async_hooks.js
|
||||
@@ -20,7 +20,7 @@ const {
|
||||
// the specific C++ macros.
|
||||
const kBeforeEvent = CHAR_LOWERCASE_B;
|
||||
const kEndEvent = CHAR_LOWERCASE_E;
|
||||
-const kTraceEventCategory = 'node,node.async_hooks';
|
||||
+const kTraceEventCategory = 'node.async_hooks';
|
||||
|
||||
const kEnabled = Symbol('enabled');
|
||||
|
||||
diff --git a/lib/internal/util/debuglog.js b/lib/internal/util/debuglog.js
|
||||
index 06a4f8a239855571dcc67cd81e7da7a255a9ebfd..1fa9e314ad796cdf74f718f0eb2a15530f5833d3 100644
|
||||
--- a/lib/internal/util/debuglog.js
|
||||
+++ b/lib/internal/util/debuglog.js
|
||||
@@ -20,7 +20,7 @@ const {
|
||||
CHAR_LOWERCASE_N: kTraceInstant,
|
||||
} = require('internal/constants');
|
||||
const { inspect, format, formatWithOptions } = require('internal/util/inspect');
|
||||
-const { getCategoryEnabledBuffer, trace } = internalBinding('trace_events');
|
||||
+const { isTraceCategoryEnabled, trace } = internalBinding('trace_events');
|
||||
|
||||
// `debugImpls` and `testEnabled` are deliberately not initialized so any call
|
||||
// to `debuglog()` before `initializeDebugEnv()` is called will throw.
|
||||
@@ -386,14 +386,13 @@ function debugWithTimer(set, cb) {
|
||||
}
|
||||
|
||||
const traceCategory = `node,node.${StringPrototypeToLowerCase(set)}`;
|
||||
- let traceCategoryBuffer;
|
||||
let debugLogCategoryEnabled = false;
|
||||
let timerFlags = kNone;
|
||||
|
||||
function ensureTimerFlagsAreUpdated() {
|
||||
timerFlags &= ~kSkipTrace;
|
||||
|
||||
- if (traceCategoryBuffer[0] === 0) {
|
||||
+ if (!isTraceCategoryEnabled(traceCategory)) {
|
||||
timerFlags |= kSkipTrace;
|
||||
}
|
||||
}
|
||||
@@ -467,7 +466,6 @@ function debugWithTimer(set, cb) {
|
||||
}
|
||||
emitWarningIfNeeded(set);
|
||||
debugLogCategoryEnabled = testEnabled(set);
|
||||
- traceCategoryBuffer = getCategoryEnabledBuffer(traceCategory);
|
||||
|
||||
timerFlags = kNone;
|
||||
|
||||
@@ -475,7 +473,7 @@ function debugWithTimer(set, cb) {
|
||||
timerFlags |= kSkipLog;
|
||||
}
|
||||
|
||||
- if (traceCategoryBuffer[0] === 0) {
|
||||
+ if (!isTraceCategoryEnabled(traceCategory)) {
|
||||
timerFlags |= kSkipTrace;
|
||||
}
|
||||
|
||||
function ipToInt(ip) {
|
||||
diff --git a/node.gyp b/node.gyp
|
||||
index f5cd416b5fe7a51084bc4af9a4427a8e62599fd8..b7072ce74354495bec49357f962f4ef2999bf727 100644
|
||||
index f5cd416b5fe7a51084bc4af9a4427a8e62599fd8..5eb70ce3820f2b82121bc102c5182ab768cbef36 100644
|
||||
--- a/node.gyp
|
||||
+++ b/node.gyp
|
||||
@@ -182,9 +182,9 @@
|
||||
@@ -182,7 +182,6 @@
|
||||
'src/timers.cc',
|
||||
'src/timer_wrap.cc',
|
||||
'src/tracing/agent.cc',
|
||||
- 'src/tracing/node_trace_buffer.cc',
|
||||
'src/tracing/node_trace_writer.cc',
|
||||
'src/tracing/trace_event.cc',
|
||||
+ 'src/tracing/trace_categories.cc',
|
||||
'src/tracing/traced_value.cc',
|
||||
'src/tty_wrap.cc',
|
||||
'src/udp_wrap.cc',
|
||||
@@ -314,9 +314,9 @@
|
||||
@@ -314,7 +313,6 @@
|
||||
'src/tcp_wrap.h',
|
||||
'src/timers.h',
|
||||
'src/tracing/agent.h',
|
||||
- 'src/tracing/node_trace_buffer.h',
|
||||
'src/tracing/node_trace_writer.h',
|
||||
'src/tracing/trace_event.h',
|
||||
+ 'src/tracing/trace_categories.h',
|
||||
'src/tracing/trace_event_common.h',
|
||||
'src/tracing/traced_value.h',
|
||||
'src/timer_wrap.h',
|
||||
diff --git a/src/async_wrap.cc b/src/async_wrap.cc
|
||||
index 301f77c419f178c4eea258e0896327f69389dda7..d5068a18392a6128ceee7f0146f8f9c77f9924bb 100644
|
||||
--- a/src/async_wrap.cc
|
||||
+++ b/src/async_wrap.cc
|
||||
@@ -110,8 +110,7 @@ void AsyncWrap::EmitPromiseResolve(Environment* env, double async_id) {
|
||||
}
|
||||
|
||||
void AsyncWrap::EmitTraceAsyncStart() const {
|
||||
- if (*TRACE_EVENT_API_GET_CATEGORY_GROUP_ENABLED(
|
||||
- TRACING_CATEGORY_NODE1(async_hooks))) {
|
||||
+ if (NODE_TRACE_CATEGORY_ENABLED(TRACING_CATEGORY_NODE1(async_hooks))) {
|
||||
tracing::AsyncWrapArgs data(env()->execution_async_id(),
|
||||
get_trigger_async_id());
|
||||
TRACE_EVENT_NESTABLE_ASYNC_BEGIN1(TRACING_CATEGORY_NODE1(async_hooks),
|
||||
diff --git a/src/env.cc b/src/env.cc
|
||||
index fdabe48dd7776c59298f7d972286d0d2ed062752..c185d822b29c0b691bbf5f724f71f59638c6184d 100644
|
||||
--- a/src/env.cc
|
||||
+++ b/src/env.cc
|
||||
@@ -650,8 +650,8 @@ void TrackingTraceStateObserver::UpdateTraceCategoryState() {
|
||||
return;
|
||||
}
|
||||
|
||||
- bool async_hooks_enabled = (*(TRACE_EVENT_API_GET_CATEGORY_GROUP_ENABLED(
|
||||
- TRACING_CATEGORY_NODE1(async_hooks)))) != 0;
|
||||
+ bool async_hooks_enabled =
|
||||
+ NODE_TRACE_CATEGORY_ENABLED(TRACING_CATEGORY_NODE1(async_hooks));
|
||||
|
||||
Isolate* isolate = env_->isolate();
|
||||
HandleScope handle_scope(isolate);
|
||||
@@ -893,8 +893,7 @@ Environment::Environment(IsolateData* isolate_data,
|
||||
time_origin_timestamp_,
|
||||
MAYBE_FIELD_PTR(env_info, performance_state));
|
||||
|
||||
- if (*TRACE_EVENT_API_GET_CATEGORY_GROUP_ENABLED(
|
||||
- TRACING_CATEGORY_NODE1(environment)) != 0) {
|
||||
+ if (NODE_TRACE_CATEGORY_ENABLED(TRACING_CATEGORY_NODE1(environment))) {
|
||||
tracing::EnvironmentArgs traced_value(args, exec_args);
|
||||
TRACE_EVENT_NESTABLE_ASYNC_BEGIN1(TRACING_CATEGORY_NODE1(environment),
|
||||
"Environment",
|
||||
diff --git a/src/inspector/tracing_agent.cc b/src/inspector/tracing_agent.cc
|
||||
index 40c8aea35c931c46fc62b717c978eab0659645fd..348cdfb0b42aa18f352c220cea0b896c09f67753 100644
|
||||
--- a/src/inspector/tracing_agent.cc
|
||||
@@ -253,156 +104,6 @@ index 40c8aea35c931c46fc62b717c978eab0659645fd..348cdfb0b42aa18f352c220cea0b896c
|
||||
void Flush(bool) override {
|
||||
if (!json_writer_)
|
||||
return;
|
||||
diff --git a/src/node.cc b/src/node.cc
|
||||
index 0bc086ccd1ff449c0f3fb08a972a0c45d3178f1c..ca74e83ef6f7b0e8b8496457af3813f07f52eb37 100644
|
||||
--- a/src/node.cc
|
||||
+++ b/src/node.cc
|
||||
@@ -78,6 +78,11 @@
|
||||
|
||||
#include "large_pages/node_large_page.h"
|
||||
|
||||
+#if defined(V8_USE_PERFETTO)
|
||||
+#include "perfetto/tracing/tracing.h"
|
||||
+#include "tracing/trace_categories.h"
|
||||
+#endif
|
||||
+
|
||||
#if defined(__APPLE__) || defined(__linux__) || defined(_WIN32)
|
||||
#define NODE_USE_V8_WASM_TRAP_HANDLER 1
|
||||
#else
|
||||
@@ -1261,6 +1266,14 @@ InitializeOncePerProcessInternal(const std::vector<std::string>& args,
|
||||
absl::SetMutexDeadlockDetectionMode(absl::OnDeadlockCycle::kIgnore);
|
||||
}
|
||||
|
||||
+#if defined(V8_USE_PERFETTO)
|
||||
+ // Register Node's Perfetto TrackEvent data source so that trace
|
||||
+ // categories are available.
|
||||
+ if (perfetto::Tracing::IsInitialized()) {
|
||||
+ node::perfetto_track_event::TrackEvent::Register();
|
||||
+ }
|
||||
+#endif
|
||||
+
|
||||
#if NODE_USE_V8_WASM_TRAP_HANDLER
|
||||
bool use_wasm_trap_handler =
|
||||
!per_process::cli_options->disable_wasm_trap_handler;
|
||||
diff --git a/src/node_contextify.cc b/src/node_contextify.cc
|
||||
index 3c234205e89be7e976dae5c3fcc73ca67953e034..986a2d8da7fd04b5d4060d9c8d44c61a231dcce6 100644
|
||||
--- a/src/node_contextify.cc
|
||||
+++ b/src/node_contextify.cc
|
||||
@@ -1026,8 +1026,7 @@ void ContextifyScript::New(const FunctionCallbackInfo<Value>& args) {
|
||||
|
||||
ContextifyScript* contextify_script = New(env, args.This());
|
||||
|
||||
- if (*TRACE_EVENT_API_GET_CATEGORY_GROUP_ENABLED(
|
||||
- TRACING_CATEGORY_NODE2(vm, script)) != 0) {
|
||||
+ if (NODE_TRACE_CATEGORY_ENABLED(TRACING_CATEGORY_NODE2(vm, script))) {
|
||||
Utf8Value fn(isolate, filename);
|
||||
TRACE_EVENT_BEGIN1(TRACING_CATEGORY_NODE2(vm, script),
|
||||
"ContextifyScript::New",
|
||||
diff --git a/src/node_dir.cc b/src/node_dir.cc
|
||||
index c9173d404c79a69743fc75ddb6bba0ac9579c1ef..8ffac047a69b3900f37d712334c504a1c65c83fd 100644
|
||||
--- a/src/node_dir.cc
|
||||
+++ b/src/node_dir.cc
|
||||
@@ -61,18 +61,25 @@ static const char* get_dir_func_name_by_type(uv_fs_type req_type) {
|
||||
|
||||
#define TRACE_NAME(name) "fs_dir.sync." #name
|
||||
#define GET_TRACE_ENABLED \
|
||||
- (*TRACE_EVENT_API_GET_CATEGORY_GROUP_ENABLED( \
|
||||
- TRACING_CATEGORY_NODE2(fs_dir, sync)) != 0)
|
||||
+ NODE_TRACE_CATEGORY_ENABLED(TRACING_CATEGORY_NODE2(fs_dir, sync))
|
||||
#define FS_DIR_SYNC_TRACE_BEGIN(syscall, ...) \
|
||||
if (GET_TRACE_ENABLED) \
|
||||
TRACE_EVENT_BEGIN(TRACING_CATEGORY_NODE2(fs_dir, sync), \
|
||||
TRACE_NAME(syscall), \
|
||||
##__VA_ARGS__);
|
||||
+#if defined(V8_USE_PERFETTO)
|
||||
+// Perfetto's TRACE_EVENT_END does not accept a name; it matches the prior
|
||||
+// TRACE_EVENT_BEGIN on the same thread.
|
||||
+#define FS_DIR_SYNC_TRACE_END(syscall, ...) \
|
||||
+ if (GET_TRACE_ENABLED) \
|
||||
+ TRACE_EVENT_END(TRACING_CATEGORY_NODE2(fs_dir, sync), ##__VA_ARGS__);
|
||||
+#else
|
||||
#define FS_DIR_SYNC_TRACE_END(syscall, ...) \
|
||||
if (GET_TRACE_ENABLED) \
|
||||
TRACE_EVENT_END(TRACING_CATEGORY_NODE2(fs_dir, sync), \
|
||||
TRACE_NAME(syscall), \
|
||||
##__VA_ARGS__);
|
||||
+#endif
|
||||
|
||||
#define FS_DIR_ASYNC_TRACE_BEGIN0(fs_type, id) \
|
||||
TRACE_EVENT_NESTABLE_ASYNC_BEGIN0(TRACING_CATEGORY_NODE2(fs_dir, async), \
|
||||
diff --git a/src/node_file.cc b/src/node_file.cc
|
||||
index 96aac2d86695732bf6805f2ad2168a62241b5045..c7a9648b0f83e910190dc620f4b72577ffde6c44 100644
|
||||
--- a/src/node_file.cc
|
||||
+++ b/src/node_file.cc
|
||||
@@ -147,16 +147,23 @@ static const char* get_fs_func_name_by_type(uv_fs_type req_type) {
|
||||
|
||||
#define TRACE_NAME(name) "fs.sync." #name
|
||||
#define GET_TRACE_ENABLED \
|
||||
- (*TRACE_EVENT_API_GET_CATEGORY_GROUP_ENABLED( \
|
||||
- TRACING_CATEGORY_NODE2(fs, sync)) != 0)
|
||||
+ NODE_TRACE_CATEGORY_ENABLED(TRACING_CATEGORY_NODE2(fs, sync))
|
||||
#define FS_SYNC_TRACE_BEGIN(syscall, ...) \
|
||||
if (GET_TRACE_ENABLED) \
|
||||
TRACE_EVENT_BEGIN( \
|
||||
TRACING_CATEGORY_NODE2(fs, sync), TRACE_NAME(syscall), ##__VA_ARGS__);
|
||||
+#if defined(V8_USE_PERFETTO)
|
||||
+// Perfetto's TRACE_EVENT_END does not accept a name; it matches the prior
|
||||
+// TRACE_EVENT_BEGIN on the same thread.
|
||||
+#define FS_SYNC_TRACE_END(syscall, ...) \
|
||||
+ if (GET_TRACE_ENABLED) \
|
||||
+ TRACE_EVENT_END(TRACING_CATEGORY_NODE2(fs, sync), ##__VA_ARGS__);
|
||||
+#else
|
||||
#define FS_SYNC_TRACE_END(syscall, ...) \
|
||||
if (GET_TRACE_ENABLED) \
|
||||
TRACE_EVENT_END( \
|
||||
TRACING_CATEGORY_NODE2(fs, sync), TRACE_NAME(syscall), ##__VA_ARGS__);
|
||||
+#endif
|
||||
|
||||
#define FS_ASYNC_TRACE_BEGIN0(fs_type, id) \
|
||||
TRACE_EVENT_NESTABLE_ASYNC_BEGIN0(TRACING_CATEGORY_NODE2(fs, async), \
|
||||
diff --git a/src/node_internals.h b/src/node_internals.h
|
||||
index 8e930a6fecd6589b858293d91b2454ea14ae7c73..a95dd02d4149a02ff40c759010e130c89ad1d848 100644
|
||||
--- a/src/node_internals.h
|
||||
+++ b/src/node_internals.h
|
||||
@@ -315,6 +315,14 @@ class ThreadPoolWork {
|
||||
const char* type_;
|
||||
};
|
||||
|
||||
+#if defined(V8_USE_PERFETTO)
|
||||
+// Perfetto categories must be single strings (not comma-separated).
|
||||
+#define TRACING_CATEGORY_NODE "node"
|
||||
+#define TRACING_CATEGORY_NODE1(one) "node." #one
|
||||
+#define TRACING_CATEGORY_NODE2(one, two) "node." #one "." #two
|
||||
+#define NODE_TRACE_CATEGORY_ENABLED(category) \
|
||||
+ TRACE_EVENT_CATEGORY_ENABLED(category)
|
||||
+#else
|
||||
#define TRACING_CATEGORY_NODE "node"
|
||||
#define TRACING_CATEGORY_NODE1(one) \
|
||||
TRACING_CATEGORY_NODE "," \
|
||||
@@ -323,6 +331,9 @@ class ThreadPoolWork {
|
||||
TRACING_CATEGORY_NODE "," \
|
||||
TRACING_CATEGORY_NODE "." #one "," \
|
||||
TRACING_CATEGORY_NODE "." #one "." #two
|
||||
+#define NODE_TRACE_CATEGORY_ENABLED(category) \
|
||||
+ (*TRACE_EVENT_API_GET_CATEGORY_GROUP_ENABLED(category) != 0)
|
||||
+#endif
|
||||
|
||||
// Functions defined in node.cc that are exposed via the bootstrapper object
|
||||
|
||||
diff --git a/src/node_trace_events.cc b/src/node_trace_events.cc
|
||||
index 225b1465b7c97d972a38968faf6d685017a80bf0..4a53a07f4d5e79354e647ba3ff6e2e1095a5b684 100644
|
||||
--- a/src/node_trace_events.cc
|
||||
+++ b/src/node_trace_events.cc
|
||||
@@ -127,7 +127,8 @@ static void GetCategoryEnabledBuffer(const FunctionCallbackInfo<Value>& args) {
|
||||
node::Utf8Value category_name(isolate, args[0]);
|
||||
|
||||
const uint8_t* enabled_pointer =
|
||||
- TRACE_EVENT_API_GET_CATEGORY_GROUP_ENABLED(category_name.out());
|
||||
+ tracing::TraceEventHelper::GetCategoryGroupEnabled(
|
||||
+ category_name.out());
|
||||
uint8_t* enabled_pointer_cast = const_cast<uint8_t*>(enabled_pointer);
|
||||
uint8_t size = sizeof(*enabled_pointer_cast);
|
||||
|
||||
diff --git a/src/tracing/agent.cc b/src/tracing/agent.cc
|
||||
index eddcf6c3bf91b730d6ca72960e3048ceed7e7844..184e8647b2148bc597d9d3eb63f86ae99917c642 100644
|
||||
--- a/src/tracing/agent.cc
|
||||
@@ -596,138 +297,48 @@ index cd965d77b7859ff2edcf781a934594b5a9b6d251..fe1714ba77fddef693d37eeb8c7a196d
|
||||
void Flush(bool blocking) override;
|
||||
|
||||
static const int kTracesPerFile = 1 << 19;
|
||||
diff --git a/src/tracing/trace_categories.cc b/src/tracing/trace_categories.cc
|
||||
new file mode 100644
|
||||
index 0000000000000000000000000000000000000000..4abc4dc5d9ef9c2a9b2e3d85d858f4bbf5ac6432
|
||||
--- /dev/null
|
||||
+++ b/src/tracing/trace_categories.cc
|
||||
@@ -0,0 +1,5 @@
|
||||
+#include "tracing/trace_categories.h"
|
||||
+
|
||||
+#if defined(V8_USE_PERFETTO)
|
||||
+PERFETTO_TRACK_EVENT_STATIC_STORAGE_IN_NAMESPACE(node);
|
||||
+#endif
|
||||
diff --git a/src/tracing/trace_categories.h b/src/tracing/trace_categories.h
|
||||
new file mode 100644
|
||||
index 0000000000000000000000000000000000000000..b28d4baa7bf766301c9281b80e0d29729ef9832e
|
||||
--- /dev/null
|
||||
+++ b/src/tracing/trace_categories.h
|
||||
@@ -0,0 +1,66 @@
|
||||
+#ifndef SRC_TRACING_TRACE_CATEGORIES_H_
|
||||
+#define SRC_TRACING_TRACE_CATEGORIES_H_
|
||||
+
|
||||
+#if defined(V8_USE_PERFETTO)
|
||||
+
|
||||
+#ifdef BASE_TRACE_EVENT_BUILTIN_CATEGORIES_H_
|
||||
+// Compiling mode where Chromium's Perfetto TrackEvent
|
||||
+// is already set up (via PERFETTO_USE_CATEGORIES_FROM_NAMESPACE(base)).
|
||||
+// Node trace categories (node.perf, node.async_hooks, etc.) will be treated
|
||||
+// as dynamic categories.
|
||||
+#else
|
||||
+// Set up Node's own Perfetto TrackEvent data source with its trace categories,
|
||||
+// following the same pattern V8 uses (PERFETTO_DEFINE_CATEGORIES_IN_NAMESPACE).
|
||||
+#define PERFETTO_ENABLE_LEGACY_TRACE_EVENTS 1
|
||||
+
|
||||
+#include "perfetto/tracing/track_event.h"
|
||||
+#include "perfetto/tracing/track_event_legacy.h"
|
||||
+
|
||||
+// Register Node.js trace categories as static Perfetto categories in the
|
||||
+// 'node' namespace.
|
||||
+PERFETTO_DEFINE_CATEGORIES_IN_NAMESPACE(
|
||||
+ node,
|
||||
+ perfetto::Category("__metadata"),
|
||||
+ perfetto::Category("node"),
|
||||
+ perfetto::Category("node.perf"),
|
||||
+ perfetto::Category("node.perf.timerify"),
|
||||
+ perfetto::Category("node.perf.usertiming"),
|
||||
+ perfetto::Category("node.perf.event_loop"),
|
||||
+ perfetto::Category("node.async_hooks"),
|
||||
+ perfetto::Category("node.bootstrap"),
|
||||
+ perfetto::Category("node.dns.native"),
|
||||
+ perfetto::Category("node.environment"),
|
||||
+ perfetto::Category("node.fs.async"),
|
||||
+ perfetto::Category("node.fs.sync"),
|
||||
+ perfetto::Category("node.fs_dir.async"),
|
||||
+ perfetto::Category("node.fs_dir.sync"),
|
||||
+ perfetto::Category("node.http"),
|
||||
+ perfetto::Category("node.net.native"),
|
||||
+ perfetto::Category("node.promises.rejections"),
|
||||
+ perfetto::Category("node.realm"),
|
||||
+ perfetto::Category("node.threadpoolwork.async"),
|
||||
+ perfetto::Category("node.threadpoolwork.sync"),
|
||||
+ perfetto::Category("node.vm.script"),
|
||||
+ perfetto::Category("v8"));
|
||||
+
|
||||
+// Make Node's categories available through the default TrackEvent namespace
|
||||
+// so that TRACE_EVENT macros work without qualification.
|
||||
+PERFETTO_USE_CATEGORIES_FROM_NAMESPACE(node);
|
||||
+
|
||||
+// These deprecated phase constants are not defined by Perfetto's legacy shim
|
||||
+// but are still exported to JavaScript by node_constants.cc.
|
||||
+#ifndef TRACE_EVENT_PHASE_ENTER_CONTEXT
|
||||
+#define TRACE_EVENT_PHASE_ENTER_CONTEXT ('(')
|
||||
+#endif
|
||||
+#ifndef TRACE_EVENT_PHASE_LEAVE_CONTEXT
|
||||
+#define TRACE_EVENT_PHASE_LEAVE_CONTEXT (')')
|
||||
+#endif
|
||||
+#ifndef TRACE_EVENT_PHASE_LINK_IDS
|
||||
+#define TRACE_EVENT_PHASE_LINK_IDS ('=')
|
||||
+#endif
|
||||
+
|
||||
+#endif // BASE_TRACE_EVENT_BUILTIN_CATEGORIES_H_
|
||||
+
|
||||
+#endif // defined(V8_USE_PERFETTO)
|
||||
+
|
||||
+#endif // SRC_TRACING_TRACE_CATEGORIES_H_
|
||||
diff --git a/src/tracing/trace_event.h b/src/tracing/trace_event.h
|
||||
index a662a081dc3bf356bf93e4063fcb043e4d8df07b..a7d0363e15a260feaaa5c7826a3b3137be531934 100644
|
||||
index a662a081dc3bf356bf93e4063fcb043e4d8df07b..c89cdfe2b2681fbf9946200a03d7d1f7bad21226 100644
|
||||
--- a/src/tracing/trace_event.h
|
||||
+++ b/src/tracing/trace_event.h
|
||||
@@ -7,13 +7,23 @@
|
||||
|
||||
#include "v8-platform.h"
|
||||
#include "tracing/agent.h"
|
||||
-#include "trace_event_common.h"
|
||||
#include <atomic>
|
||||
|
||||
+#if defined(V8_USE_PERFETTO)
|
||||
+#include "tracing/trace_categories.h"
|
||||
@@ -69,8 +69,16 @@ enum CategoryGroupEnabledFlags {
|
||||
// for best performance when tracing is disabled.
|
||||
// const uint8_t*
|
||||
// TRACE_EVENT_API_GET_CATEGORY_GROUP_ENABLED(const char* category_group)
|
||||
+#ifndef V8_USE_PERFETTO
|
||||
#define TRACE_EVENT_API_GET_CATEGORY_GROUP_ENABLED \
|
||||
node::tracing::TraceEventHelper::GetCategoryGroupEnabled
|
||||
+#else
|
||||
+#include "trace_event_common.h"
|
||||
+#define TRACE_EVENT_API_GET_CATEGORY_GROUP_ENABLED(category_group) \
|
||||
+ ([](const char*) -> const uint8_t* { \
|
||||
+ static uint8_t no = 0; \
|
||||
+ return &no; \
|
||||
+ })(category_group)
|
||||
+#endif
|
||||
+
|
||||
// This header file defines implementation details of how the trace macros in
|
||||
// trace_event_common.h collect and store trace events. Anything not
|
||||
// implementation-specific should go in trace_macros_common.h instead of here.
|
||||
|
||||
+#if !defined(V8_USE_PERFETTO)
|
||||
+// When Perfetto is enabled, all trace event macros and their internal
|
||||
+// implementation are provided by Perfetto's track event legacy shim
|
||||
+// (included via trace_categories.h). The following definitions are only
|
||||
+// needed for the non-Perfetto tracing backend.
|
||||
// Get the number of times traces have been recorded. This is used to implement
|
||||
// the TRACE_EVENT_IS_NEW_TRACE facility.
|
||||
@@ -114,10 +122,15 @@ enum CategoryGroupEnabledFlags {
|
||||
// const uint8_t* category_group_enabled,
|
||||
// const char* name,
|
||||
// uint64_t id)
|
||||
+#ifndef V8_USE_PERFETTO
|
||||
#define TRACE_EVENT_API_UPDATE_TRACE_EVENT_DURATION \
|
||||
if (auto controller = \
|
||||
node::tracing::TraceEventHelper::GetTracingController()) \
|
||||
controller->UpdateTraceEventDuration
|
||||
+#else
|
||||
+#define TRACE_EVENT_API_UPDATE_TRACE_EVENT_DURATION(category_group_enabled, name, event_handle) \
|
||||
+ (void)(category_group_enabled), (void)(name), (void)(event_handle)
|
||||
+#endif
|
||||
|
||||
// The pointer returned from GetCategoryGroupEnabled() points to a
|
||||
// value with zero or more of the following bits. Used in this class only.
|
||||
@@ -301,6 +311,8 @@ enum CategoryGroupEnabledFlags {
|
||||
INTERNAL_TRACE_EVENT_UID(ScopedContext) \
|
||||
INTERNAL_TRACE_EVENT_UID(scoped_context)(context);
|
||||
|
||||
+#endif // !defined(V8_USE_PERFETTO)
|
||||
+
|
||||
namespace node {
|
||||
namespace tracing {
|
||||
|
||||
@@ -319,15 +331,24 @@ class TraceEventHelper {
|
||||
// Adds a metadata event to the trace log. The |AppendValueAsTraceFormat| method
|
||||
// on the convertable value will be called at flush time.
|
||||
@@ -319,12 +332,15 @@ class TraceEventHelper {
|
||||
static void SetAgent(Agent* agent);
|
||||
|
||||
static inline const uint8_t* GetCategoryGroupEnabled(const char* group) {
|
||||
+#if defined(V8_USE_PERFETTO)
|
||||
+ // Under Perfetto, callers should use TRACE_EVENT_CATEGORY_ENABLED()
|
||||
+ // instead. This function exists only for backward compatibility with
|
||||
+ // non-Perfetto builds.
|
||||
+ static const uint8_t disabled = 0;
|
||||
+ return &disabled;
|
||||
+#else
|
||||
+#ifndef V8_USE_PERFETTO
|
||||
v8::TracingController* controller = GetTracingController();
|
||||
static const uint8_t disabled = 0;
|
||||
if (controller == nullptr) [[unlikely]] {
|
||||
@@ -735,90 +346,56 @@ index a662a081dc3bf356bf93e4063fcb043e4d8df07b..a7d0363e15a260feaaa5c7826a3b3137
|
||||
}
|
||||
return controller->GetCategoryGroupEnabled(group);
|
||||
+#endif
|
||||
+ return 0;
|
||||
}
|
||||
};
|
||||
|
||||
+#if !defined(V8_USE_PERFETTO)
|
||||
// TraceID encapsulates an ID that can either be an integer or pointer. Pointers
|
||||
// are by default mangled with the Process ID so that they are unlikely to
|
||||
// collide when the same pointer is used on different processes.
|
||||
@@ -478,6 +499,7 @@ static inline uint64_t AddTraceEventImpl(
|
||||
@@ -462,6 +478,7 @@ static inline uint64_t AddTraceEventImpl(
|
||||
const char* scope, uint64_t id, uint64_t bind_id, int32_t num_args,
|
||||
const char** arg_names, const uint8_t* arg_types,
|
||||
const uint64_t* arg_values, unsigned int flags) {
|
||||
+#ifndef V8_USE_PERFETTO
|
||||
std::unique_ptr<v8::ConvertableToTraceFormat> arg_convertibles[2];
|
||||
if (num_args > 0 && arg_types[0] == TRACE_VALUE_TYPE_CONVERTABLE) {
|
||||
arg_convertibles[0].reset(reinterpret_cast<v8::ConvertableToTraceFormat*>(
|
||||
@@ -478,6 +495,8 @@ static inline uint64_t AddTraceEventImpl(
|
||||
return controller->AddTraceEvent(phase, category_group_enabled, name, scope, id,
|
||||
bind_id, num_args, arg_names, arg_types,
|
||||
arg_values, arg_convertibles, flags);
|
||||
+#endif
|
||||
+ return 0;
|
||||
}
|
||||
|
||||
static V8_INLINE uint64_t AddTraceEventWithTimestampImpl(
|
||||
@@ -501,6 +523,7 @@ static V8_INLINE uint64_t AddTraceEventWithTimestampImpl(
|
||||
@@ -485,6 +504,7 @@ static V8_INLINE uint64_t AddTraceEventWithTimestampImpl(
|
||||
const char* scope, uint64_t id, uint64_t bind_id, int32_t num_args,
|
||||
const char** arg_names, const uint8_t* arg_types,
|
||||
const uint64_t* arg_values, unsigned int flags, int64_t timestamp) {
|
||||
+#ifndef V8_USE_PERFETTO
|
||||
std::unique_ptr<v8::ConvertableToTraceFormat> arg_convertibles[2];
|
||||
if (num_args > 0 && arg_types[0] == TRACE_VALUE_TYPE_CONVERTABLE) {
|
||||
arg_convertibles[0].reset(reinterpret_cast<v8::ConvertableToTraceFormat*>(
|
||||
@@ -501,12 +521,15 @@ static V8_INLINE uint64_t AddTraceEventWithTimestampImpl(
|
||||
return controller->AddTraceEventWithTimestamp(
|
||||
phase, category_group_enabled, name, scope, id, bind_id, num_args,
|
||||
arg_names, arg_types, arg_values, arg_convertibles, flags, timestamp);
|
||||
+#endif
|
||||
+ return 0;
|
||||
}
|
||||
|
||||
static V8_INLINE void AddMetadataEventImpl(
|
||||
@@ -716,6 +739,8 @@ class ScopedTracer {
|
||||
Data data_;
|
||||
};
|
||||
const uint8_t* category_group_enabled, const char* name, int32_t num_args,
|
||||
const char** arg_names, const uint8_t* arg_types,
|
||||
const uint64_t* arg_values, unsigned int flags) {
|
||||
+#ifndef V8_USE_PERFETTO
|
||||
std::unique_ptr<v8::ConvertableToTraceFormat> arg_convertibles[2];
|
||||
if (num_args > 0 && arg_types[0] == TRACE_VALUE_TYPE_CONVERTABLE) {
|
||||
arg_convertibles[0].reset(reinterpret_cast<v8::ConvertableToTraceFormat*>(
|
||||
@@ -522,6 +545,7 @@ static V8_INLINE void AddMetadataEventImpl(
|
||||
return agent->GetTracingController()->AddMetadataEvent(
|
||||
category_group_enabled, name, num_args, arg_names, arg_types, arg_values,
|
||||
arg_convertibles, flags);
|
||||
+#endif
|
||||
}
|
||||
|
||||
+#endif // !defined(V8_USE_PERFETTO)
|
||||
+
|
||||
} // namespace tracing
|
||||
} // namespace node
|
||||
|
||||
diff --git a/src/tracing/traced_value.h b/src/tracing/traced_value.h
|
||||
index 0bc9df81d87562243817a6618641a49b602654e3..b6dd8b9a9c21051f3d385d5ecea9c50c8b8b1629 100644
|
||||
--- a/src/tracing/traced_value.h
|
||||
+++ b/src/tracing/traced_value.h
|
||||
@@ -11,6 +11,26 @@
|
||||
#include <span>
|
||||
#include <string>
|
||||
|
||||
+#if defined(V8_USE_PERFETTO)
|
||||
+#include "perfetto/tracing/traced_value.h"
|
||||
+
|
||||
+namespace perfetto {
|
||||
+
|
||||
+template <>
|
||||
+struct TraceFormatTraits<
|
||||
+ std::unique_ptr<v8::ConvertableToTraceFormat>> {
|
||||
+ static void WriteIntoTrace(
|
||||
+ TracedValue context,
|
||||
+ const std::unique_ptr<v8::ConvertableToTraceFormat>& value) {
|
||||
+ std::string json;
|
||||
+ value->AppendAsTraceFormat(&json);
|
||||
+ std::move(context).WriteString(json);
|
||||
+ }
|
||||
+};
|
||||
+
|
||||
+} // namespace perfetto
|
||||
+#endif // defined(V8_USE_PERFETTO)
|
||||
+
|
||||
namespace node {
|
||||
namespace tracing {
|
||||
|
||||
diff --git a/unofficial.gni b/unofficial.gni
|
||||
index bff7b0650cfe8578a044e45d0f9e352859909695..a773152813376bef1fa227c331241a1d944c9317 100644
|
||||
--- a/unofficial.gni
|
||||
+++ b/unofficial.gni
|
||||
@@ -143,7 +143,10 @@ template("node_gn_build") {
|
||||
[ "node.gyp" ])
|
||||
|
||||
source_set("libnode") {
|
||||
- configs += [ ":node_internal_config" ]
|
||||
+ configs += [
|
||||
+ ":node_internal_config",
|
||||
+ "$node_v8_path:v8_tracing_config",
|
||||
+ ]
|
||||
public_configs = [
|
||||
":node_external_config",
|
||||
"deps/googletest:googletest_config",
|
||||
@@ -173,6 +176,7 @@ template("node_gn_build") {
|
||||
"//third_party/zstd:headers",
|
||||
"$node_simdutf_path",
|
||||
"$node_v8_path:v8_libplatform",
|
||||
+ "$node_v8_path:v8_tracing",
|
||||
]
|
||||
|
||||
cflags_cc = [
|
||||
// Define SetTraceValue for each allowed type. It stores the type and
|
||||
|
||||
@@ -20,18 +20,22 @@ index ab7dc27de3e304f6d912d5834da47e3b4eb25495..b6c0fd4ceee989dac55c7d54e52fef18
|
||||
}
|
||||
}
|
||||
diff --git a/unofficial.gni b/unofficial.gni
|
||||
index 43f09d1e68c88d3ba3b862a1a74769f73c370894..cedd2b0a0941fe66bdae479c4fc768ce3d7bc6ac 100644
|
||||
index 4ab316e45bd84e43a53335df60f847b17fe6c2fa..def9a302830e493e51cc2b3588816fcbd3a1bb51 100644
|
||||
--- a/unofficial.gni
|
||||
+++ b/unofficial.gni
|
||||
@@ -146,6 +146,7 @@ template("node_gn_build") {
|
||||
configs += [
|
||||
":node_internal_config",
|
||||
"$node_v8_path:v8_tracing_config",
|
||||
@@ -143,7 +143,10 @@ template("node_gn_build") {
|
||||
[ "node.gyp" ])
|
||||
|
||||
source_set("libnode") {
|
||||
- configs += [ ":node_internal_config" ]
|
||||
+ configs += [
|
||||
+ ":node_internal_config",
|
||||
+ "//build/config/compiler:no_exit_time_destructors"
|
||||
]
|
||||
+ ]
|
||||
public_configs = [
|
||||
":node_external_config",
|
||||
@@ -368,6 +369,7 @@ template("node_gn_build") {
|
||||
"deps/googletest:googletest_config",
|
||||
@@ -364,6 +367,7 @@ template("node_gn_build") {
|
||||
"src/embedded_data.h",
|
||||
]
|
||||
include_dirs = [ "src", "tools" ]
|
||||
|
||||
@@ -18,10 +18,10 @@ Stage 3.
|
||||
Upstreamed in https://github.com/nodejs/node/pull/60364
|
||||
|
||||
diff --git a/src/node.cc b/src/node.cc
|
||||
index 6e7df97bfdb3bb2ff9fcbb0eba6118239018d632..2b221e84bb5e84829af8193b38eec31b57668e75 100644
|
||||
index b9d35e60f39d1edd910cd0fc1e57157458db93f5..4421ddd05f69e32f38d074a4cc04e4e7eac89e76 100644
|
||||
--- a/src/node.cc
|
||||
+++ b/src/node.cc
|
||||
@@ -783,7 +783,7 @@ static ExitCode ProcessGlobalArgsInternal(std::vector<std::string>* args,
|
||||
@@ -778,7 +778,7 @@ static ExitCode ProcessGlobalArgsInternal(std::vector<std::string>* args,
|
||||
|
||||
if (std::ranges::find(v8_args, "--no-js-source-phase-imports") ==
|
||||
v8_args.end()) {
|
||||
|
||||
@@ -12,10 +12,10 @@ This can be removed/refactored once Node.js upgrades to a version of V8
|
||||
containing the above CL.
|
||||
|
||||
diff --git a/src/node.cc b/src/node.cc
|
||||
index ca74e83ef6f7b0e8b8496457af3813f07f52eb37..6e7df97bfdb3bb2ff9fcbb0eba6118239018d632 100644
|
||||
index 0bc086ccd1ff449c0f3fb08a972a0c45d3178f1c..b9d35e60f39d1edd910cd0fc1e57157458db93f5 100644
|
||||
--- a/src/node.cc
|
||||
+++ b/src/node.cc
|
||||
@@ -1249,7 +1249,7 @@ InitializeOncePerProcessInternal(const std::vector<std::string>& args,
|
||||
@@ -1244,7 +1244,7 @@ InitializeOncePerProcessInternal(const std::vector<std::string>& args,
|
||||
result->platform_ = per_process::v8_platform.Platform();
|
||||
}
|
||||
|
||||
|
||||
@@ -10,10 +10,10 @@ change, it seems to introduce an incompatibility when compiling
|
||||
using clang modules. Disabling them resolves the issue.
|
||||
|
||||
diff --git a/unofficial.gni b/unofficial.gni
|
||||
index cedd2b0a0941fe66bdae479c4fc768ce3d7bc6ac..86bd7d18ca299d0866c872b52fb0508174c148d9 100644
|
||||
index def9a302830e493e51cc2b3588816fcbd3a1bb51..900c5e4d8a48d0725420518c923c7024518158b8 100644
|
||||
--- a/unofficial.gni
|
||||
+++ b/unofficial.gni
|
||||
@@ -199,6 +199,10 @@ template("node_gn_build") {
|
||||
@@ -197,6 +197,10 @@ template("node_gn_build") {
|
||||
"CoreFoundation.framework",
|
||||
"Security.framework",
|
||||
]
|
||||
@@ -24,7 +24,7 @@ index cedd2b0a0941fe66bdae479c4fc768ce3d7bc6ac..86bd7d18ca299d0866c872b52fb05081
|
||||
}
|
||||
if (is_posix) {
|
||||
configs -= [ "//build/config/gcc:symbol_visibility_hidden" ]
|
||||
@@ -371,6 +375,12 @@ template("node_gn_build") {
|
||||
@@ -369,6 +373,12 @@ template("node_gn_build") {
|
||||
include_dirs = [ "src", "tools" ]
|
||||
configs += [ "//build/config/compiler:no_exit_time_destructors" ]
|
||||
|
||||
|
||||
@@ -7,10 +7,10 @@ libc++ added [[nodiscard]] to std::filesystem::copy_options operator|=
|
||||
which causes build failures with -Werror.
|
||||
|
||||
diff --git a/src/node_file.cc b/src/node_file.cc
|
||||
index 46cd16b535d9bd651ef733ca52ea58db7d39b09f..7a7c71a0fcbb71e1c3dfcac7a00da207c4c3bf56 100644
|
||||
index 547455bb5011677719a8de1f98cb447561bce6aa..385db5fd6fe5db6bb7ff17e98309b6cd605a82d3 100644
|
||||
--- a/src/node_file.cc
|
||||
+++ b/src/node_file.cc
|
||||
@@ -3467,11 +3467,11 @@ static void CpSyncCopyDir(const FunctionCallbackInfo<Value>& args) {
|
||||
@@ -3460,11 +3460,11 @@ static void CpSyncCopyDir(const FunctionCallbackInfo<Value>& args) {
|
||||
|
||||
auto file_copy_opts = std::filesystem::copy_options::recursive;
|
||||
if (force) {
|
||||
|
||||
@@ -89,7 +89,7 @@ index fb2af584a4ae777022c9ef8c20ada1edcbbbefdc..fe6300a5d5d2d6602a84cbd33736c213
|
||||
#endif // defined(NODE_WANT_INTERNALS) && NODE_WANT_INTERNALS
|
||||
|
||||
diff --git a/src/env.cc b/src/env.cc
|
||||
index c185d822b29c0b691bbf5f724f71f59638c6184d..57a46c8be2e052b298ed841eed6f291d62711750 100644
|
||||
index fdabe48dd7776c59298f7d972286d0d2ed062752..b5cf58cc953590493beb52abf249e33e486ffc46 100644
|
||||
--- a/src/env.cc
|
||||
+++ b/src/env.cc
|
||||
@@ -611,7 +611,7 @@ IsolateData::~IsolateData() {}
|
||||
|
||||
@@ -19,7 +19,7 @@ index 2c95ac99be70b0750372e9c858753bf519498e3d..5ab30502fd232196739ca2b450e35cc9
|
||||
Local<Module> module = obj->module_.Get(isolate);
|
||||
if (module->GetStatus() < Module::kInstantiated) {
|
||||
diff --git a/src/node_contextify.cc b/src/node_contextify.cc
|
||||
index 9f11d32c70366524cf3b7c1cfdfd24f31e438e7b..3f1772b62aa0300540d25fb93012c49bce9d8134 100644
|
||||
index e66d4fcb0c064f96cdb819c783027d864fe88d12..619980b36db457ef7e476eacd446e3bf2a9a71d2 100644
|
||||
--- a/src/node_contextify.cc
|
||||
+++ b/src/node_contextify.cc
|
||||
@@ -460,7 +460,7 @@ ContextifyContext* ContextifyContext::Get(const PropertyCallbackInfo<T>& args) {
|
||||
|
||||
@@ -12,3 +12,4 @@ use_uttype_class_instead_of_deprecated_uttypeconformsto.patch
|
||||
fix_clean_up_orphaned_staged_updates_before_downloading_new_update.patch
|
||||
fix_add_explicit_json_property_mappings_for_shipit_request_model.patch
|
||||
fix_resolve_target_bundle_path_once_at_start_of_install.patch
|
||||
fix_remove_vestigial_machservices_from_shipit_launchd_job.patch
|
||||
|
||||
@@ -0,0 +1,49 @@
|
||||
From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001
|
||||
From: Keeley Hammond <vertedinde@electronjs.org>
|
||||
Date: Tue, 14 Apr 2026 10:00:00 -0700
|
||||
Subject: fix: remove vestigial MachServices from ShipIt launchd job
|
||||
|
||||
The MachServices key in the ShipIt launchd job dictionary is a leftover
|
||||
from when ShipIt was an XPC service (removed in Squirrel/Squirrel.Mac@d6ca1c2
|
||||
":fire: XPC :fire:" in October 2013). Since then, nothing connects to
|
||||
the registered Mach port.
|
||||
|
||||
When a macOS system update is pending, launchd puts the user domain into
|
||||
"on-demand-only mode", where only jobs with an on-demand trigger (like a
|
||||
MachServices connection) are started. Since nothing connects to ShipIt's
|
||||
Mach port, launchd pends the spawn indefinitely with:
|
||||
|
||||
"pending spawn, domain in on-demand-only mode"
|
||||
|
||||
This prevents ShipIt from running, causing Electron auto-updates to fail
|
||||
whenever a macOS update is staged. By the time the domain exits
|
||||
on-demand-only mode (after reboot/update completion), the staged update
|
||||
bundle is often stale, leading to "Too many attempts to install" errors.
|
||||
|
||||
Removing the MachServices key eliminates the on-demand trigger, so
|
||||
launchd falls back to evaluating KeepAlive.SuccessfulExit which
|
||||
correctly starts ShipIt immediately on submission.
|
||||
|
||||
Also removes the stale "service name" comment on the jobLabel argument,
|
||||
since ShipIt is no longer a Mach service.
|
||||
|
||||
diff --git a/Squirrel/SQRLShipItLauncher.m b/Squirrel/SQRLShipItLauncher.m
|
||||
index 6a9151d92f399184fff9854eb00ea506165bbbe2..0ebd2a23d62424c41e15413edeab360bef87ecc4 100644
|
||||
--- a/Squirrel/SQRLShipItLauncher.m
|
||||
+++ b/Squirrel/SQRLShipItLauncher.m
|
||||
@@ -50,14 +50,10 @@ + (RACSignal *)shipItJobDictionary {
|
||||
@(LAUNCH_JOBKEY_KEEPALIVE_SUCCESSFULEXIT): @NO
|
||||
};
|
||||
|
||||
- jobDict[@(LAUNCH_JOBKEY_MACHSERVICES)] = @{
|
||||
- jobLabel: @YES
|
||||
- };
|
||||
-
|
||||
NSMutableArray *arguments = [[NSMutableArray alloc] init];
|
||||
[arguments addObject:[squirrelBundle URLForResource:@"ShipIt" withExtension:nil].path];
|
||||
|
||||
- // Pass in the service name so ShipIt knows how to broadcast itself.
|
||||
+ // Pass in the job label so ShipIt can identify itself.
|
||||
[arguments addObject:jobLabel];
|
||||
|
||||
// We need to pass the path to ShipIt rather than having ShipIt
|
||||
@@ -1,3 +1,2 @@
|
||||
chore_allow_customizing_microtask_policy_per_context.patch
|
||||
build_warn_instead_of_abort_on_builtin_pgo_profile_mismatch.patch
|
||||
src_use_legacy_trace_macros_in_perfetto_to_support_all_phases.patch
|
||||
|
||||
@@ -1,98 +0,0 @@
|
||||
From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001
|
||||
From: deepak1556 <hop2deep@gmail.com>
|
||||
Date: Tue, 31 Mar 2026 07:05:17 +0900
|
||||
Subject: src: use legacy trace macros in perfetto to support all phases
|
||||
|
||||
Replace the phase-specific SDK macros with the INTERNAL_TRACE_EVENT_ADD
|
||||
and INTERNAL_TRACE_EVENT_ADD_WITH_ID legacy shim macros, which accept an
|
||||
arbitrary phase character and forward it through Perfetto's legacy
|
||||
compatibility layer. This supports nestable async ('b'/'e'/'n')
|
||||
and counter ('C') trace event phases needed for Node.js.
|
||||
|
||||
Additionally:
|
||||
|
||||
1. Clear TRACE_EVENT_FLAG_COPY before calling Perfetto macros. Perfetto
|
||||
manages string lifetimes internally via DynamicString and
|
||||
TRACE_STR_COPY; passing FLAG_COPY triggers a CHECK failure in
|
||||
Perfetto's legacy shim.
|
||||
|
||||
2. Default instant events (phase 'I') with GLOBAL scope to THREAD scope.
|
||||
Under Perfetto, global-scope instant events land on Track::Global(0),
|
||||
producing pid:0/tid:0 in the trace output, making them effectively
|
||||
invisible in trace viewers.
|
||||
|
||||
diff --git a/src/builtins/builtins-trace.cc b/src/builtins/builtins-trace.cc
|
||||
index c17d72d477d4c28d25e3f385d8af3c5b7024f7f7..5990e6cee1d08ba0e86059cb7f3affc878dcc632 100644
|
||||
--- a/src/builtins/builtins-trace.cc
|
||||
+++ b/src/builtins/builtins-trace.cc
|
||||
@@ -181,37 +181,44 @@ BUILTIN(Trace) {
|
||||
}
|
||||
|
||||
#if defined(V8_USE_PERFETTO)
|
||||
- // TODO(skyostil): Use interned names to reduce trace size.
|
||||
- auto trace_args = [&](perfetto::EventContext ctx) {
|
||||
+ // Perfetto handles string lifetimes internally (via DynamicString and
|
||||
+ // TRACE_STR_COPY), so TRACE_EVENT_FLAG_COPY must not be set — Perfetto's
|
||||
+ // legacy shim CHECKs against it.
|
||||
+ flags &= ~TRACE_EVENT_FLAG_COPY;
|
||||
+
|
||||
+ // Default instant events to thread scope under Perfetto. Without this,
|
||||
+ // scope bits are 0 (GLOBAL), which puts events on Track::Global(0)
|
||||
+ // resulting in pid:0/tid:0 in the trace output.
|
||||
+ if (phase == TRACE_EVENT_PHASE_INSTANT) {
|
||||
+ auto scope = flags & TRACE_EVENT_FLAG_SCOPE_MASK;
|
||||
+ if (scope == TRACE_EVENT_SCOPE_GLOBAL) {
|
||||
+ flags = (flags & ~TRACE_EVENT_FLAG_SCOPE_MASK) | TRACE_EVENT_SCOPE_THREAD;
|
||||
+ }
|
||||
+ }
|
||||
+
|
||||
+ // Use the legacy trace event macros which support all phase types
|
||||
+ // (including nestable async 'b'/'e'/'n' and counter 'C' used by Node.js)
|
||||
+ if (flags & TRACE_EVENT_FLAG_HAS_ID) {
|
||||
if (num_args) {
|
||||
MaybeUtf8 arg_contents(isolate, Cast<String>(arg_json));
|
||||
- auto annotation = ctx.event()->add_debug_annotations();
|
||||
- annotation->set_name(arg_name);
|
||||
- annotation->set_legacy_json_value(*arg_contents);
|
||||
+ INTERNAL_TRACE_EVENT_ADD_WITH_ID(
|
||||
+ phase, dynamic_category, perfetto::DynamicString(*name), id, flags,
|
||||
+ arg_name, TRACE_STR_COPY(*arg_contents));
|
||||
+ } else {
|
||||
+ INTERNAL_TRACE_EVENT_ADD_WITH_ID(
|
||||
+ phase, dynamic_category, perfetto::DynamicString(*name), id, flags);
|
||||
}
|
||||
- if (flags & TRACE_EVENT_FLAG_HAS_ID) {
|
||||
- auto legacy_event = ctx.event()->set_legacy_event();
|
||||
- legacy_event->set_global_id(id);
|
||||
+ } else {
|
||||
+ if (num_args) {
|
||||
+ MaybeUtf8 arg_contents(isolate, Cast<String>(arg_json));
|
||||
+ INTERNAL_TRACE_EVENT_ADD(
|
||||
+ phase, dynamic_category, perfetto::DynamicString(*name), flags,
|
||||
+ arg_name, TRACE_STR_COPY(*arg_contents));
|
||||
+ } else {
|
||||
+ INTERNAL_TRACE_EVENT_ADD(phase, dynamic_category,
|
||||
+ perfetto::DynamicString(*name), flags);
|
||||
}
|
||||
- };
|
||||
-
|
||||
- switch (phase) {
|
||||
- case TRACE_EVENT_PHASE_BEGIN:
|
||||
- TRACE_EVENT_BEGIN(dynamic_category, perfetto::DynamicString(*name),
|
||||
- trace_args);
|
||||
- break;
|
||||
- case TRACE_EVENT_PHASE_END:
|
||||
- TRACE_EVENT_END(dynamic_category, trace_args);
|
||||
- break;
|
||||
- case TRACE_EVENT_PHASE_INSTANT:
|
||||
- TRACE_EVENT_INSTANT(dynamic_category, perfetto::DynamicString(*name),
|
||||
- trace_args);
|
||||
- break;
|
||||
- default:
|
||||
- THROW_NEW_ERROR_RETURN_FAILURE(
|
||||
- isolate, NewTypeError(MessageTemplate::kTraceEventPhaseError));
|
||||
}
|
||||
-
|
||||
#else // !defined(V8_USE_PERFETTO)
|
||||
uint8_t arg_type;
|
||||
uint64_t arg_value;
|
||||
8
script/.eslintrc.json
Normal file
8
script/.eslintrc.json
Normal file
@@ -0,0 +1,8 @@
|
||||
{
|
||||
"plugins": [
|
||||
"import"
|
||||
],
|
||||
"rules": {
|
||||
"import/enforce-node-protocol-usage": ["error", "always"]
|
||||
}
|
||||
}
|
||||
@@ -1,16 +1,13 @@
|
||||
#!/usr/bin/env python3
|
||||
|
||||
import argparse
|
||||
import concurrent.futures
|
||||
import json
|
||||
import os
|
||||
import subprocess
|
||||
import warnings
|
||||
|
||||
from lib import git
|
||||
from lib.patches import patch_from_dir
|
||||
|
||||
ELECTRON_DIR = os.path.dirname(os.path.dirname(os.path.abspath(__file__)))
|
||||
THREEWAY = "ELECTRON_USE_THREE_WAY_MERGE_FOR_PATCHES" in os.environ
|
||||
|
||||
def apply_patches(target):
|
||||
@@ -22,43 +19,14 @@ def apply_patches(target):
|
||||
git.import_patches(
|
||||
committer_email="scripts@electron",
|
||||
committer_name="Electron Scripts",
|
||||
output_prefix=f'[{os.path.basename(patch_dir)}] ',
|
||||
patch_data=patch_from_dir(patch_dir),
|
||||
repo=repo,
|
||||
threeway=THREEWAY,
|
||||
)
|
||||
|
||||
def is_roller_branch():
|
||||
try:
|
||||
branch = subprocess.check_output(
|
||||
['git', '-C', ELECTRON_DIR, 'rev-parse', '--abbrev-ref', 'HEAD'],
|
||||
stderr=subprocess.DEVNULL,
|
||||
).decode('utf-8').strip()
|
||||
return branch.startswith('roller/')
|
||||
except subprocess.CalledProcessError:
|
||||
return False
|
||||
|
||||
def apply_config(config):
|
||||
# Targets are independent git repos, so apply in parallel. The work is
|
||||
# subprocess-bound (git am), so threads are sufficient. On roller/
|
||||
# branches, patch conflicts are expected and interleaved failure output
|
||||
# from multiple repos is hard to read, so force sequential there.
|
||||
if is_roller_branch():
|
||||
max_workers = 1
|
||||
else:
|
||||
max_workers = max(1, (os.cpu_count() or 4) - 2)
|
||||
with concurrent.futures.ThreadPoolExecutor(max_workers=max_workers) as pool:
|
||||
futures = {pool.submit(apply_patches, t): t for t in config}
|
||||
failed = []
|
||||
for f in concurrent.futures.as_completed(futures):
|
||||
try:
|
||||
f.result()
|
||||
except Exception as e: # pylint: disable=broad-except
|
||||
failed.append((futures[f].get('repo'), e))
|
||||
if failed:
|
||||
for repo, e in failed:
|
||||
print(f'ERROR applying patches to {repo}: {e}')
|
||||
raise failed[0][1]
|
||||
for target in config:
|
||||
apply_patches(target)
|
||||
|
||||
def parse_args():
|
||||
parser = argparse.ArgumentParser(description='Apply Electron patches')
|
||||
|
||||
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user