mirror of
https://github.com/electron/electron.git
synced 2026-04-10 03:01:51 -04:00
Compare commits
6 Commits
remove-dec
...
fix/codesi
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
9c045e97a7 | ||
|
|
6a87d47e83 | ||
|
|
c05faa7bad | ||
|
|
5b6403eb11 | ||
|
|
1c6bb418bd | ||
|
|
ed27a77558 |
@@ -7,20 +7,19 @@ description: Guide for performing Chromium version upgrades in the Electron proj
|
||||
|
||||
## Summary
|
||||
|
||||
Run `e sync --3` repeatedly, fixing patch conflicts as they arise, until it succeeds. Then export patches and commit changes atomically.
|
||||
Run `e sync --3` repeatedly, fixing patch conflicts as they arise, until it succeeds. Then run `e patches all` 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
|
||||
- `e patches all` has been run to export all changes
|
||||
- All changes are committed per the commit guidelines below
|
||||
|
||||
Do not stop until these criteria are met.
|
||||
|
||||
**CRITICAL** Do not delete or skip patches unless 100% certain the patch is no longer needed. 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/chromium/main` branch is created by automation to update Electron's Chromium dependency SHA. No work has been done to handle breaking changes between the old and new versions.
|
||||
@@ -31,18 +30,12 @@ The `roller/chromium/main` branch is created by automation to update Electron's
|
||||
- `patches/`: Patch files organized by target
|
||||
- `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 `..` 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:
|
||||
1. Delete the `.git/rr-cache` in both the `electron` and `..` folder to ensure no accidental rerere replays occur from before this upgrade phase attempt started
|
||||
2. Run `e sync --3` (the `--3` flag enables 3-way merge, always required)
|
||||
3. If succeeds → skip to step 6
|
||||
4. If patch fails:
|
||||
- Identify target repo and patch from error output
|
||||
- Analyze failure (see references/patch-analysis.md)
|
||||
- Fix conflict in target repo's working directory
|
||||
@@ -50,8 +43,10 @@ Run these once at the start of each upgrade session:
|
||||
- Repeat until all patches for that repo apply
|
||||
- IMPORTANT: Once `git am --continue` succeeds you MUST run `e patches {target}` 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.
|
||||
5. When `e sync --3` succeeds, run `e patches all`
|
||||
6. **Read `references/phase-one-commit-guidelines.md` NOW**, then commit changes following those instructions exactly.
|
||||
|
||||
Before committing any Phase One changes, you MUST read `references/phase-one-commit-guidelines.md` and follow its instructions exactly.
|
||||
|
||||
## Commands Reference
|
||||
|
||||
@@ -61,7 +56,6 @@ Run these once at the start of each upgrade session:
|
||||
| `git am --continue` | Continue after resolving conflict (run in target repo) |
|
||||
| `e patches {target}` | Export commits from target repo to patch files |
|
||||
| `e patches all` | Export all patches from all targets |
|
||||
| `e patches {target} --commit-updates` | Export patches and auto-commit trivial changes |
|
||||
| `e patches --list-targets` | List targets and config paths |
|
||||
|
||||
## Patch System Mental Model
|
||||
@@ -86,22 +80,25 @@ Fix existing patches 99% of the time rather than creating new ones.
|
||||
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 (e.g., `DCHECK` → `CHECK_IS_TEST`), 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.
|
||||
|
||||
## Final Deliverable
|
||||
|
||||
After Phase One, write a summary of every change: what was fixed, why, reasoning, and Chromium CL links.
|
||||
|
||||
# Electron Chromium 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 `e build -k 999` 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 build -k 999` 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
|
||||
- All changes are committed per the commit guidelines below
|
||||
|
||||
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.
|
||||
|
||||
@@ -115,7 +112,8 @@ The `roller/chromium/main` branch is created by automation to update Electron's
|
||||
|
||||
## Workflow
|
||||
|
||||
1. Run `e build -k 999 -- --quiet` (the `--quiet` flag suppresses per-target status lines, showing only errors and the final result)
|
||||
1. Run `e build -k 999` (the `-k 999` flag is a flag to ninja to say "do not stop until you find that many errors" it is an attempt to get as much error
|
||||
context as possible for each time we run build)
|
||||
2. If succeeds → skip to step 6
|
||||
3. If build fails:
|
||||
- Identify underlying file in "electron" from the compilation error message
|
||||
@@ -128,17 +126,27 @@ The `roller/chromium/main` branch is created by automation to update Electron's
|
||||
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)"`
|
||||
- Commit them immediately with: `git commit -am "chore: update patch hunk headers"`
|
||||
- This prevents losing track of necessary updates
|
||||
5. Return to step 1
|
||||
6. When `e build` succeeds, run `e start --version`
|
||||
7. Check if you have any pending changes in the Chromium repo by running `git status`
|
||||
- If you have changes follow the instructions below in "A. Patch Fixes" to correctly commit those modifications into the appropriate patch file
|
||||
|
||||
Before committing any Phase Two changes, you MUST read `references/phase-two-commit-guidelines.md` and follow its instructions exactly.
|
||||
|
||||
## Build Error Detection
|
||||
|
||||
When monitoring `e build -k 999` output, filter for errors using this regex pattern:
|
||||
error:|FAILED:|fatal:|subcommand failed|build finished
|
||||
|
||||
The build output is extremely verbose. Filtering is essential to catch errors quickly.
|
||||
|
||||
## Commands Reference
|
||||
|
||||
| Command | Purpose |
|
||||
|---------|---------|
|
||||
| `e build -k 999 -- --quiet` | Build Electron, continue on errors, suppress status lines |
|
||||
| `e build -k 999` | Builds Electron and won't stop until either all targets attempted or 999 errors found |
|
||||
| `e build -t {target}.o` | Build just one specific target to verify a fix |
|
||||
| `e start --version` | Validate Electron launches after successful build |
|
||||
|
||||
@@ -155,21 +163,28 @@ When the error is in a file that Electron patches (check with `grep -l "filename
|
||||
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 chromium`
|
||||
4. Commit the updated patch file following `references/phase-one-commit-guidelines.md`.
|
||||
3. Export the updated patch: e patches chromium
|
||||
4. Commit the updated patch file in the electron repo following the `references/phase-one-commit-guidelines.md`, then commit changes following those instructions exactly. **READ THESE GUIDELINES BEFORE COMMITTING THESE CHANGES**
|
||||
|
||||
To find the original patch commit to fixup: `git log --oneline | grep -i "keyword from patch name"`
|
||||
|
||||
The base commit for rebase is the Chromium 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.)
|
||||
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)
|
||||
|
||||
Dependent Patch Updates
|
||||
|
||||
IMPORTANT: When you modify a patch, other patches that apply to the same file may have their hunk headers invalidated. After committing a patch fix:
|
||||
|
||||
1. Run git status in the electron repo
|
||||
2. Look for other modified .patch files with just index/hunk header changes
|
||||
3. Commit these with: git commit -m "chore: update patch hunk headers"
|
||||
|
||||
# Critical: Read Before Committing
|
||||
|
||||
- Before ANY Phase One commits: Read `references/phase-one-commit-guidelines.md`
|
||||
@@ -181,4 +196,4 @@ This skill has additional reference files in `references/`:
|
||||
- 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.
|
||||
Read these when referenced in the workflow steps.
|
||||
@@ -17,56 +17,6 @@
|
||||
Reviewed-on: https://chromium-review.googlesource.com/c/chromium/src/+/{CL_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 CL'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 a feature flag guard", add only the guard — don't also
|
||||
restore old code inside the guard 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 CL, 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.
|
||||
- **Evidence:** An upstream CL removed a `HeadlessModeWindow` struct from a
|
||||
header, but the conflict was only in a `.mm` file. Mechanically keeping the
|
||||
patch's old line (`headless_mode_window_ = ...`) produced code referencing
|
||||
a nonexistent type — caught only on review, not at patch-apply time.
|
||||
|
||||
### 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.
|
||||
- **Evidence:** An occlusion patch needed only a feature flag check, but the
|
||||
old patch also contained a version check that upstream intentionally removed.
|
||||
Mechanically preserving the old patch code re-added the removed check.
|
||||
|
||||
### 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.
|
||||
- **Evidence:** A safestorage patch conflicted because Chromium removed Keychain V1.
|
||||
The conflict was resolved by removing V1 hunks, but the remaining code still
|
||||
called V1 methods (`FindGenericPassword` with 3 args, `ItemDelete` with
|
||||
`SecKeychainItemRef`). These should have been adapted to V2 APIs in the same
|
||||
commit, not deferred.
|
||||
|
||||
## Common Failure Patterns
|
||||
|
||||
| Pattern | Cause | Solution |
|
||||
|
||||
@@ -4,65 +4,19 @@ Only follow these instructions if there are uncommitted changes to `patches/` af
|
||||
|
||||
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: {Chromium CL 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): constant moved to header`
|
||||
- `fix(patch): headless mode refactor upstream`
|
||||
- `fix(patch): V1 Keychain removal`
|
||||
|
||||
### 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
|
||||
```
|
||||
|
||||
If the patch file did NOT contain a `Reviewed-on: https://chromium-review.googlesource.com/c/chromium/...` link, add a `Ref:` in the commit. If it did (i.e. cherry-picks), no `Ref:` is needed.
|
||||
|
||||
### 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.
|
||||
For each fix made to a patch, create a separate commit:
|
||||
|
||||
```
|
||||
fix(patch-conflict): {concise title}
|
||||
|
||||
{Brief explanation, 1-2 paragraphs max}
|
||||
|
||||
Ref: {Chromium CL link}
|
||||
```
|
||||
|
||||
IMPORTANT: Ensure that any changes made to patch content as a result of a change in Chromium is committed individually. Each change should have it's own commit message and it's own REF.
|
||||
|
||||
IMPORTANT: Try really hard to find the CL reference per the instructions below. Each change you made should in theory have been in response to a change made in Chromium 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.
|
||||
|
||||
@@ -76,27 +30,23 @@ Reviewed-on: https://chromium-review.googlesource.com/c/chromium/src/+/XXXXXXX
|
||||
|
||||
If no CL found after searching: `Ref: Unable to locate CL`
|
||||
|
||||
## Example Commits
|
||||
## Final Cleanup
|
||||
|
||||
### Patch conflict fix (simple — title is sufficient)
|
||||
After all fix commits, stage remaining changes:
|
||||
|
||||
```
|
||||
fix(patch): constant moved to header
|
||||
|
||||
Ref: https://chromium-review.googlesource.com/c/chromium/src/+/7536483
|
||||
|
||||
Co-Authored-By: <AI model attribution>
|
||||
```bash
|
||||
git add patches
|
||||
git commit -m "chore: update patch hunk headers"
|
||||
```
|
||||
|
||||
### Patch conflict fix (complex — description adds value)
|
||||
## Example Commit
|
||||
|
||||
```
|
||||
fix(patch): V1 Keychain removal
|
||||
fix(patch-conflict): update web_contents_impl.cc context for navigation refactor
|
||||
|
||||
Upstream deleted the V1 Keychain API. Removed V1 hunks and adapted
|
||||
keychain_password_mac.mm to use KeychainV2 APIs.
|
||||
The upstream navigation code was refactored to use NavigationRequest directly
|
||||
instead of going through NavigationController. Updated surrounding context
|
||||
to match new code structure.
|
||||
|
||||
Ref: https://chromium-review.googlesource.com/c/chromium/src/+/7540447
|
||||
|
||||
Co-Authored-By: <AI model attribution>
|
||||
```
|
||||
Ref: https://chromium-review.googlesource.com/c/chromium/src/+/1234567
|
||||
```
|
||||
@@ -4,37 +4,41 @@ Only follow these instructions if there are uncommitted changes in the Electron
|
||||
|
||||
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 Chromium CL 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.)
|
||||
|
||||
```
|
||||
{CL-Number}: {upstream CL's original title}
|
||||
{CL-Number}: {concise description of API change}
|
||||
|
||||
{Brief explanation of what upstream changed and how Electron was adapted}
|
||||
|
||||
Ref: {Chromium CL link}
|
||||
|
||||
Co-Authored-By: <AI model attribution>
|
||||
```
|
||||
|
||||
Use the **upstream CL's original commit title** — do not paraphrase or rewrite it. To find it: `git log -1 --format=%s <chromium-commit-hash>`.
|
||||
IMPORTANT: Ensure that any change made to electron as a result of a change in Chromium is committed individually. Each change should have it's own commit message and it's own REF. Logically grouped into commits that make sense rather than one giant commit.
|
||||
|
||||
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.
|
||||
IMPORTANT: Try really hard to find the CL reference per the instructions below. Each change you made should in theory have been in response to a change made in Chromium 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.
|
||||
|
||||
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.
|
||||
You may include multiple "Ref" links if required.
|
||||
|
||||
For a CL link in the format `https://chromium-review.googlesource.com/c/chromium/src/+/2958369` the "CL-Number" is `2958369`.
|
||||
|
||||
IMPORTANT: Try really hard to find the CL reference. Each change you made should in theory have been in response to a change in Chromium. Do not give up easily.
|
||||
For a CL link in the format `https://chromium-review.googlesource.com/c/chromium/src/+/2958369` the "CL-Number" is `2958369`
|
||||
|
||||
### For Patch Updates (patches/chromium/*.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).
|
||||
Use the same fixup workflow as Phase One:
|
||||
1. Fix in Chromium source tree
|
||||
2. Fixup commit + rebase
|
||||
3. Export with `e patches chromium`
|
||||
4. Commit the patch file:
|
||||
|
||||
```
|
||||
fix(patch-update): {concise description}
|
||||
|
||||
{Brief explanation}
|
||||
|
||||
Ref: {Chromium CL link}
|
||||
```
|
||||
|
||||
## Dependent Patch Header Updates
|
||||
|
||||
@@ -42,43 +46,37 @@ 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:
|
||||
# If other .patch files show as modified with only hunk header changes:
|
||||
git add patches/
|
||||
git commit -m "chore: update patches (trivial only)"
|
||||
git commit -m "chore: update patch hunk headers"
|
||||
```
|
||||
|
||||
## Finding CL References
|
||||
|
||||
Use git log or git blame on Chromium source files. Look for:
|
||||
|
||||
```
|
||||
Reviewed-on: https://chromium-review.googlesource.com/c/chromium/src/+/XXXXXXX
|
||||
```
|
||||
|
||||
If no CL found after searching: `Ref: Unable to locate CL`
|
||||
If no CL found after searching: Ref: Unable to locate CL
|
||||
|
||||
## Example Commits
|
||||
|
||||
### Electron Source Fix (simple — title is self-explanatory)
|
||||
### Electron Source Fix
|
||||
|
||||
```
|
||||
7535923: Rename ozone buildflags
|
||||
fix: update GetPlugins to GetPluginsAsync for API change
|
||||
|
||||
Ref: https://chromium-review.googlesource.com/c/chromium/src/+/7535923
|
||||
The upstream Chromium API changed:
|
||||
- Old: GetPlugins(callback) - took a callback
|
||||
- New: GetPluginsAsync(callback) - async version takes a callback
|
||||
|
||||
Co-Authored-By: <AI model attribution>
|
||||
```
|
||||
Ref: https://chromium-review.googlesource.com/c/chromium/src/+/1234567
|
||||
|
||||
### Electron Source Fix (complex — description adds value)
|
||||
### Patch Fix
|
||||
|
||||
```
|
||||
7534194: Convert some functions in ui::Clipboard to async
|
||||
fix(patch-conflict): update picture-in-picture for gesture handling refactor
|
||||
|
||||
Adapted ExtractCustomPlatformNames calls to use RunLoop pattern
|
||||
consistent with existing ReadImage implementation, since upstream
|
||||
converted the API from synchronous return to callback-based.
|
||||
Upstream added new gesture handling code that accesses live caption dialog.
|
||||
The live caption functionality is disabled in Electron's patch, so wrapped
|
||||
the new code in #if 0 guards to match existing pattern.
|
||||
|
||||
Ref: https://chromium-review.googlesource.com/c/chromium/src/+/7534194
|
||||
|
||||
Co-Authored-By: <AI model attribution>
|
||||
```
|
||||
Ref: https://chromium-review.googlesource.com/c/chromium/src/+/7654321
|
||||
|
||||
@@ -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"
|
||||
],
|
||||
|
||||
@@ -2,7 +2,7 @@ version: '3'
|
||||
|
||||
services:
|
||||
buildtools:
|
||||
image: ghcr.io/electron/devcontainer:eac3529546ea8f3aa356d31e345715eef342233b
|
||||
image: ghcr.io/electron/devcontainer:a82b87d7a4f5ff0cab61405f8151ac4cf4942aeb
|
||||
|
||||
volumes:
|
||||
- ..:/workspaces/gclient/src/electron:cached
|
||||
|
||||
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
|
||||
|
||||
66
.github/actions/build-electron/action.yml
vendored
66
.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
|
||||
} 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: |
|
||||
@@ -148,9 +128,6 @@ runs:
|
||||
fi
|
||||
sed $SEDOPTION '/.*builtins-pgo/d' out/Default/mksnapshot_args
|
||||
sed $SEDOPTION '/--turbo-profiling-input/d' out/Default/mksnapshot_args
|
||||
sed $SEDOPTION '/--reorder-builtins/d' out/Default/mksnapshot_args
|
||||
sed $SEDOPTION '/--warn-about-builtin-profile-data/d' out/Default/mksnapshot_args
|
||||
sed $SEDOPTION '/--abort-on-bad-builtin-profile-data/d' out/Default/mksnapshot_args
|
||||
|
||||
if [ "${{ inputs.target-platform }}" = "win" ]; then
|
||||
cd out/Default
|
||||
@@ -228,17 +205,7 @@ runs:
|
||||
if: ${{ inputs.is-release == 'true' }}
|
||||
run: |
|
||||
cd src
|
||||
# Reuse the hermetic mac_sdk_path that `e build` wrote for out/Default so
|
||||
# out/ffmpeg builds against the same SDK instead of the runner's system Xcode.
|
||||
# The path has to live under root_build_dir, so copy the symlink tree and
|
||||
# rewrite Default -> ffmpeg.
|
||||
MAC_SDK_ARG=""
|
||||
if [ "$(uname)" = "Darwin" ]; then
|
||||
mkdir -p out/ffmpeg
|
||||
cp -a out/Default/xcode_links out/ffmpeg/
|
||||
MAC_SDK_ARG=$(sed -n 's|^\(mac_sdk_path = "//out/\)Default/|\1ffmpeg/|p' out/Default/args.gn)
|
||||
fi
|
||||
gn gen out/ffmpeg --args="import(\"//electron/build/args/ffmpeg.gn\") use_remoteexec=true use_siso=true $MAC_SDK_ARG $GN_EXTRA_ARGS"
|
||||
gn gen out/ffmpeg --args="import(\"//electron/build/args/ffmpeg.gn\") use_remoteexec=true use_siso=true $GN_EXTRA_ARGS"
|
||||
e build --target electron:electron_ffmpeg_zip -C ../../out/ffmpeg
|
||||
- name: Remove Clang problem matcher
|
||||
shell: bash
|
||||
@@ -307,25 +274,18 @@ runs:
|
||||
run: ./src/electron/script/actions/move-artifacts.sh
|
||||
- name: Upload Generated Artifacts ${{ inputs.step-suffix }}
|
||||
if: always() && !cancelled()
|
||||
uses: actions/upload-artifact@bbbca2ddaa5d8feaa63e36b76fdaad77386f024f #v7.0.0
|
||||
uses: actions/upload-artifact@65462800fd760344b1a7b4382951275a0abb4808
|
||||
with:
|
||||
name: generated_artifacts_${{ env.ARTIFACT_KEY }}
|
||||
path: ./generated_artifacts_${{ inputs.artifact-platform }}_${{ inputs.target-arch }}
|
||||
- name: Upload Src Artifacts ${{ inputs.step-suffix }}
|
||||
uses: actions/upload-artifact@bbbca2ddaa5d8feaa63e36b76fdaad77386f024f #v7.0.0
|
||||
uses: actions/upload-artifact@65462800fd760344b1a7b4382951275a0abb4808
|
||||
with:
|
||||
name: src_artifacts_${{ env.ARTIFACT_KEY }}
|
||||
path: ./src_artifacts_${{ inputs.artifact-platform }}_${{ inputs.target-arch }}
|
||||
- name: Upload Out Gen Artifacts ${{ inputs.step-suffix }}
|
||||
if: ${{ inputs.upload-out-gen-artifacts == 'true' }}
|
||||
uses: actions/upload-artifact@bbbca2ddaa5d8feaa63e36b76fdaad77386f024f #v7.0.0
|
||||
uses: actions/upload-artifact@65462800fd760344b1a7b4382951275a0abb4808
|
||||
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);
|
||||
});
|
||||
30
.github/actions/checkout/action.yml
vendored
30
.github/actions/checkout/action.yml
vendored
@@ -28,7 +28,7 @@ runs:
|
||||
shell: bash
|
||||
run: |
|
||||
node src/electron/script/generate-deps-hash.js
|
||||
DEPSHASH="v2-src-cache-$(cat src/electron/.depshash)"
|
||||
DEPSHASH="v1-src-cache-$(cat src/electron/.depshash)"
|
||||
echo "DEPSHASH=$DEPSHASH" >> $GITHUB_ENV
|
||||
echo "CACHE_FILE=$DEPSHASH.tar" >> $GITHUB_ENV
|
||||
if [ "${{ inputs.target-platform }}" = "win" ]; then
|
||||
@@ -43,7 +43,7 @@ runs:
|
||||
curl --unix-socket /var/run/sas/sas.sock --fail "http://foo/$CACHE_FILE?platform=${{ inputs.target-platform }}&getAccountName=true" > sas-token
|
||||
- name: Save SAS Key
|
||||
if: ${{ inputs.generate-sas-token == 'true' }}
|
||||
uses: actions/cache/save@668228422ae6a00e4ad889ee87cd7109ec5666a7 # v5.0.4
|
||||
uses: actions/cache/save@5a3ec84eff668545956fd18022155c47e93e2684 # v4.2.3
|
||||
with:
|
||||
path: sas-token
|
||||
key: sas-key-${{ inputs.target-platform }}-${{ github.run_number }}-${{ github.run_attempt }}
|
||||
@@ -109,7 +109,7 @@ runs:
|
||||
echo "target_os=['$TARGET_OS']" >> ./.gclient
|
||||
fi
|
||||
|
||||
ELECTRON_DEPOT_TOOLS_WIN_TOOLCHAIN=0 DEPOT_TOOLS_WIN_TOOLCHAIN=0 ELECTRON_USE_THREE_WAY_MERGE_FOR_PATCHES=1 e d gclient sync --with_branch_heads --with_tags
|
||||
ELECTRON_USE_THREE_WAY_MERGE_FOR_PATCHES=1 e d gclient sync --with_branch_heads --with_tags -vv
|
||||
if [[ "${{ inputs.is-release }}" != "true" ]]; then
|
||||
# Re-export all the patches to check if there were changes.
|
||||
python3 src/electron/script/export_all_patches.py src/electron/patches/config.json
|
||||
@@ -187,35 +187,21 @@ runs:
|
||||
shell: bash
|
||||
run: |
|
||||
echo "Uncompressed src size: $(du -sh src | cut -f1 -d' ')"
|
||||
# Named .tar but zstd-compressed; the sas-sidecar's filename allowlist
|
||||
# only permits .tar/.tgz so we keep the extension and decode on restore.
|
||||
tar -cf - src | zstd -T0 --long=30 -f -o $CACHE_FILE
|
||||
tar -cf $CACHE_FILE src
|
||||
echo "Compressed src to $(du -sh $CACHE_FILE | cut -f1 -d' ')"
|
||||
cp ./$CACHE_FILE $CACHE_DRIVE/
|
||||
- name: Persist Src Cache
|
||||
if: ${{ steps.check-cache.outputs.cache_exists == 'false' && inputs.use-cache == 'true' }}
|
||||
shell: bash
|
||||
run: |
|
||||
final_cache_path=$CACHE_DRIVE/$CACHE_FILE
|
||||
# Upload to a run-unique temp name first so concurrent readers never
|
||||
# observe a partially-written file, and an interrupted copy can't leave
|
||||
# a truncated file at the final path. Orphaned temp files get swept by
|
||||
# the clean-orphaned-cache-uploads workflow.
|
||||
tmp_cache_path=$final_cache_path.upload-${GITHUB_RUN_ID}-${GITHUB_RUN_ATTEMPT}
|
||||
echo "Uploading to temp path: $tmp_cache_path"
|
||||
cp ./$CACHE_FILE $tmp_cache_path
|
||||
|
||||
echo "Using cache key: $DEPSHASH"
|
||||
if [ -f "$final_cache_path" ]; then
|
||||
echo "Cache already persisted at $final_cache_path by a concurrent run; discarding ours"
|
||||
rm -f $tmp_cache_path
|
||||
else
|
||||
mv -f $tmp_cache_path $final_cache_path
|
||||
echo "Cache key persisted in $final_cache_path"
|
||||
fi
|
||||
|
||||
echo "Checking path: $final_cache_path"
|
||||
if [ ! -f "$final_cache_path" ]; then
|
||||
echo "Cache key not found"
|
||||
exit 1
|
||||
else
|
||||
echo "Cache key persisted in $final_cache_path"
|
||||
fi
|
||||
- name: Wait for active SSH sessions
|
||||
shell: bash
|
||||
|
||||
38
.github/actions/cipd-install/action.yml
vendored
38
.github/actions/cipd-install/action.yml
vendored
@@ -22,50 +22,30 @@ runs:
|
||||
steps:
|
||||
- name: Delete wrong ${{ inputs.dependency }}
|
||||
shell: bash
|
||||
env:
|
||||
CIPD_ROOT_PREFIX: ${{ inputs.cipd-root-prefix-path }}
|
||||
INSTALLATION_DIR: ${{ inputs.installation-dir }}
|
||||
run : |
|
||||
rm -rf "${CIPD_ROOT_PREFIX}${INSTALLATION_DIR}"
|
||||
rm -rf ${{ inputs.cipd-root-prefix-path }}${{ inputs.installation-dir }}
|
||||
- name: Create ensure file for ${{ inputs.dependency }}
|
||||
if: ${{ inputs.dependency-version == '' }}
|
||||
shell: bash
|
||||
env:
|
||||
PACKAGE: ${{ inputs.package }}
|
||||
DEPS_FILE: ${{ inputs.deps-file }}
|
||||
INSTALLATION_DIR: ${{ inputs.installation-dir }}
|
||||
DEPENDENCY: ${{ inputs.dependency }}
|
||||
run: |
|
||||
echo "$PACKAGE" $(e d gclient getdep --deps-file="$DEPS_FILE" -r "${INSTALLATION_DIR}:${PACKAGE}") > "${DEPENDENCY}_ensure_file"
|
||||
cat "${DEPENDENCY}_ensure_file"
|
||||
echo '${{ inputs.package }}' `e d gclient getdep --deps-file=${{ inputs.deps-file }} -r '${{ inputs.installation-dir }}:${{ inputs.package }}'` > ${{ inputs.dependency }}_ensure_file
|
||||
cat ${{ inputs.dependency }}_ensure_file
|
||||
|
||||
- name: Create ensure file for ${{ inputs.dependency }} from dependency-version
|
||||
if: ${{ inputs.dependency-version != '' }}
|
||||
shell: bash
|
||||
env:
|
||||
PACKAGE: ${{ inputs.package }}
|
||||
DEPENDENCY_VERSION: ${{ inputs.dependency-version }}
|
||||
DEPENDENCY: ${{ inputs.dependency }}
|
||||
run: |
|
||||
echo "$PACKAGE $DEPENDENCY_VERSION" > "${DEPENDENCY}_ensure_file"
|
||||
cat "${DEPENDENCY}_ensure_file"
|
||||
echo '${{ inputs.package }} ${{ inputs.dependency-version }}' > ${{ inputs.dependency }}_ensure_file
|
||||
cat ${{ inputs.dependency }}_ensure_file
|
||||
- name: CIPD installation of ${{ inputs.dependency }} (macOS)
|
||||
if: ${{ inputs.target-platform != 'win' }}
|
||||
shell: bash
|
||||
env:
|
||||
CIPD_ROOT_PREFIX: ${{ inputs.cipd-root-prefix-path }}
|
||||
INSTALLATION_DIR: ${{ inputs.installation-dir }}
|
||||
DEPENDENCY: ${{ inputs.dependency }}
|
||||
run: |
|
||||
echo "ensuring $DEPENDENCY"
|
||||
e d cipd ensure --root "${CIPD_ROOT_PREFIX}${INSTALLATION_DIR}" -ensure-file "${DEPENDENCY}_ensure_file"
|
||||
echo "ensuring ${{ inputs.dependency }}"
|
||||
e d cipd ensure --root ${{ inputs.cipd-root-prefix-path }}${{ inputs.installation-dir }} -ensure-file ${{ inputs.dependency }}_ensure_file
|
||||
- name: CIPD installation of ${{ inputs.dependency }} (Windows)
|
||||
if: ${{ inputs.target-platform == 'win' }}
|
||||
shell: powershell
|
||||
env:
|
||||
CIPD_ROOT_PREFIX: ${{ inputs.cipd-root-prefix-path }}
|
||||
INSTALLATION_DIR: ${{ inputs.installation-dir }}
|
||||
DEPENDENCY: ${{ inputs.dependency }}
|
||||
run: |
|
||||
echo "ensuring $env:DEPENDENCY on Windows"
|
||||
e d cipd ensure --root "$env:CIPD_ROOT_PREFIX$env:INSTALLATION_DIR" -ensure-file "$($env:DEPENDENCY)_ensure_file"
|
||||
echo "ensuring ${{ inputs.dependency }} on Windows"
|
||||
e d cipd ensure --root ${{ inputs.cipd-root-prefix-path }}${{ inputs.installation-dir }} -ensure-file ${{ inputs.dependency }}_ensure_file
|
||||
|
||||
1
.github/actions/fix-sync/action.yml
vendored
1
.github/actions/fix-sync/action.yml
vendored
@@ -27,7 +27,6 @@ runs:
|
||||
python3 src/tools/clang/scripts/update.py
|
||||
# Refs https://chromium-review.googlesource.com/c/chromium/src/+/6667681
|
||||
python3 src/tools/clang/scripts/update.py --package objdump
|
||||
python3 src/tools/clang/scripts/update.py --package clang-tidy
|
||||
- name: Fix esbuild
|
||||
if: ${{ inputs.target-platform != 'linux' }}
|
||||
uses: ./src/electron/.github/actions/cipd-install
|
||||
|
||||
@@ -15,7 +15,7 @@ runs:
|
||||
git config --global core.preloadindex true
|
||||
git config --global core.longpaths true
|
||||
fi
|
||||
export BUILD_TOOLS_SHA=1b7bd25dae4a780bb3170fff56c9327b53aaf7eb
|
||||
export BUILD_TOOLS_SHA=4430e4a505e0f4fa2a41b707a10a36f780bbdd26
|
||||
npm i -g @electron/build-tools
|
||||
# Update depot_tools to ensure python
|
||||
e d update_depot_tools
|
||||
@@ -29,4 +29,4 @@ runs:
|
||||
else
|
||||
echo "$HOME/.electron_build_tools/third_party/depot_tools" >> $GITHUB_PATH
|
||||
echo "$HOME/.electron_build_tools/third_party/depot_tools/python-bin" >> $GITHUB_PATH
|
||||
fi
|
||||
fi
|
||||
@@ -7,7 +7,7 @@ runs:
|
||||
shell: bash
|
||||
id: yarn-cache-dir-path
|
||||
run: echo "dir=$(node src/electron/script/yarn.js config get cacheFolder)" >> $GITHUB_OUTPUT
|
||||
- uses: actions/cache@668228422ae6a00e4ad889ee87cd7109ec5666a7 # v5.0.4
|
||||
- uses: actions/cache@5a3ec84eff668545956fd18022155c47e93e2684 # v4.2.3
|
||||
id: yarn-cache
|
||||
with:
|
||||
path: ${{ steps.yarn-cache-dir-path.outputs.dir }}
|
||||
|
||||
2
.github/actions/restore-cache-aks/action.yml
vendored
2
.github/actions/restore-cache-aks/action.yml
vendored
@@ -31,7 +31,7 @@ runs:
|
||||
fi
|
||||
|
||||
mkdir temp-cache
|
||||
zstd -d --long=30 -c $cache_path | tar -xf - -C temp-cache
|
||||
tar -xf $cache_path -C temp-cache
|
||||
echo "Unzipped cache is $(du -sh temp-cache/src | cut -f1)"
|
||||
|
||||
if [ -d "temp-cache/src" ]; then
|
||||
|
||||
33
.github/actions/restore-cache-azcopy/action.yml
vendored
33
.github/actions/restore-cache-azcopy/action.yml
vendored
@@ -8,14 +8,14 @@ runs:
|
||||
steps:
|
||||
- name: Obtain SAS Key
|
||||
continue-on-error: true
|
||||
uses: actions/cache/restore@668228422ae6a00e4ad889ee87cd7109ec5666a7 # v5.0.4
|
||||
uses: actions/cache/restore@5a3ec84eff668545956fd18022155c47e93e2684 # v4.2.3
|
||||
with:
|
||||
path: sas-token
|
||||
key: sas-key-${{ inputs.target-platform }}-${{ github.run_number }}-1
|
||||
enableCrossOsArchive: true
|
||||
- name: Obtain SAS Key
|
||||
continue-on-error: true
|
||||
uses: actions/cache/restore@668228422ae6a00e4ad889ee87cd7109ec5666a7 # v5.0.4
|
||||
uses: actions/cache/restore@5a3ec84eff668545956fd18022155c47e93e2684 # v4.2.3
|
||||
with:
|
||||
path: sas-token
|
||||
key: sas-key-${{ inputs.target-platform }}-${{ github.run_number }}-${{ github.run_attempt }}
|
||||
@@ -24,7 +24,7 @@ runs:
|
||||
# The cache will always exist here as a result of the checkout job
|
||||
# Either it was uploaded to Azure in the checkout job for this commit
|
||||
# or it was uploaded in the checkout job for a previous commit.
|
||||
uses: nick-fields/retry@ad984534de44a9489a53aefd81eb77f87c70dc60 # v4.0.0
|
||||
uses: nick-fields/retry@7152eba30c6575329ac0576536151aca5a72780e # v3.0.0
|
||||
with:
|
||||
timeout_minutes: 30
|
||||
max_attempts: 3
|
||||
@@ -61,9 +61,9 @@ runs:
|
||||
echo "Cache is empty - exiting"
|
||||
exit 1
|
||||
fi
|
||||
|
||||
|
||||
mkdir temp-cache
|
||||
zstd -d --long=30 -c $DEPSHASH.tar | tar -xf - -C temp-cache
|
||||
tar -xf $DEPSHASH.tar -C temp-cache
|
||||
echo "Unzipped cache is $(du -sh temp-cache/src | cut -f1)"
|
||||
|
||||
if [ -d "temp-cache/src" ]; then
|
||||
@@ -85,21 +85,23 @@ runs:
|
||||
|
||||
- name: Unzip and Ensure Src Cache (Windows)
|
||||
if: ${{ inputs.target-platform == 'win' }}
|
||||
shell: bash
|
||||
shell: powershell
|
||||
run: |
|
||||
echo "Downloaded cache is $(du -sh $DEPSHASH.tar | cut -f1)"
|
||||
if [ `du $DEPSHASH.tar | cut -f1` = "0" ]; then
|
||||
echo "Cache is empty - exiting"
|
||||
$src_cache = "$env:DEPSHASH.tar"
|
||||
$cache_size = $(Get-Item $src_cache).length
|
||||
Write-Host "Downloaded cache is $cache_size"
|
||||
if ($cache_size -eq 0) {
|
||||
Write-Host "Cache is empty - exiting"
|
||||
exit 1
|
||||
fi
|
||||
}
|
||||
|
||||
mkdir temp-cache
|
||||
zstd -d --long=30 -c $DEPSHASH.tar | tar -xf - -C temp-cache
|
||||
rm -f $DEPSHASH.tar
|
||||
$TEMP_DIR=New-Item -ItemType Directory -Path temp-cache
|
||||
$TEMP_DIR_PATH = $TEMP_DIR.FullName
|
||||
C:\ProgramData\Chocolatey\bin\7z.exe -y -snld20 x $src_cache -o"$TEMP_DIR_PATH"
|
||||
|
||||
- name: Move Src Cache (Windows)
|
||||
if: ${{ inputs.target-platform == 'win' }}
|
||||
uses: nick-fields/retry@ad984534de44a9489a53aefd81eb77f87c70dc60 # v4.0.0
|
||||
uses: nick-fields/retry@7152eba30c6575329ac0576536151aca5a72780e # v3.0.0
|
||||
with:
|
||||
timeout_minutes: 30
|
||||
max_attempts: 3
|
||||
@@ -110,6 +112,9 @@ runs:
|
||||
Write-Host "Relocating Cache"
|
||||
Remove-Item -Recurse -Force src
|
||||
Move-Item temp-cache\src src
|
||||
|
||||
Write-Host "Deleting zip file"
|
||||
Remove-Item -Force $src_cache
|
||||
}
|
||||
if (-Not (Test-Path "src\third_party\blink")) {
|
||||
Write-Host "Cache was not correctly restored - exiting"
|
||||
|
||||
@@ -7,7 +7,7 @@ runs:
|
||||
if: ${{ runner.os != 'Windows' }}
|
||||
shell: bash
|
||||
run: |
|
||||
if [[ -z "$CHROMIUM_GIT_COOKIE" ]]; then
|
||||
if [[ -z "${{ env.CHROMIUM_GIT_COOKIE }}" ]]; then
|
||||
echo "CHROMIUM_GIT_COOKIE is not set - cannot authenticate."
|
||||
exit 0
|
||||
fi
|
||||
@@ -18,7 +18,9 @@ runs:
|
||||
|
||||
git config --global http.cookiefile ~/.gitcookies
|
||||
|
||||
echo "$CHROMIUM_GIT_COOKIE" | tr , \\t >>~/.gitcookies
|
||||
tr , \\t <<\__END__ >>~/.gitcookies
|
||||
${{ env.CHROMIUM_GIT_COOKIE }}
|
||||
__END__
|
||||
eval 'set -o history' 2>/dev/null || unsetopt HIST_IGNORE_SPACE 2>/dev/null
|
||||
|
||||
RESPONSE=$(curl -s -b ~/.gitcookies https://chromium-review.googlesource.com/a/accounts/self)
|
||||
@@ -40,7 +42,7 @@ runs:
|
||||
)
|
||||
|
||||
git config --global http.cookiefile "%USERPROFILE%\.gitcookies"
|
||||
powershell -noprofile -nologo -command Write-Output $env:CHROMIUM_GIT_COOKIE_WINDOWS_STRING >>"%USERPROFILE%\.gitcookies"
|
||||
powershell -noprofile -nologo -command Write-Output "${{ env.CHROMIUM_GIT_COOKIE_WINDOWS_STRING }}" >>"%USERPROFILE%\.gitcookies"
|
||||
|
||||
curl -s -b "%USERPROFILE%\.gitcookies" https://chromium-review.googlesource.com/a/accounts/self > response.txt
|
||||
|
||||
|
||||
122
.github/copilot-instructions.md
vendored
122
.github/copilot-instructions.md
vendored
@@ -1,122 +0,0 @@
|
||||
# Copilot Instructions for Electron
|
||||
|
||||
## Build System
|
||||
|
||||
Electron uses `@electron/build-tools` (`e` CLI). Install with `npm i -g @electron/build-tools`.
|
||||
|
||||
```bash
|
||||
e sync # Fetch sources and apply patches
|
||||
e build # Build Electron (GN + Ninja)
|
||||
e build -k 999 # Build, continuing through errors
|
||||
e start # Run built Electron
|
||||
e start --version # Verify Electron launches
|
||||
e test # Run full test suite
|
||||
e debug # Run in debugger (lldb on macOS, gdb on Linux)
|
||||
```
|
||||
|
||||
### Linting
|
||||
|
||||
```bash
|
||||
npm run lint # Run all linters (JS, C++, Python, GN, docs)
|
||||
npm run lint:js # JavaScript/TypeScript only
|
||||
npm run lint:clang-format # C++ formatting only
|
||||
npm run lint:cpp # C++ linting only
|
||||
npm run lint:docs # Documentation only
|
||||
```
|
||||
|
||||
### Running a Single Test
|
||||
|
||||
```bash
|
||||
npm run test -- -g "pattern" # Run tests matching a regex pattern
|
||||
# Example: npm run test -- -g "ipc"
|
||||
```
|
||||
|
||||
### Running a Single Node.js Test
|
||||
|
||||
```bash
|
||||
node script/node-spec-runner.js parallel/test-crypto-keygen
|
||||
```
|
||||
|
||||
## Architecture
|
||||
|
||||
Electron embeds Chromium (rendering) and Node.js (backend) to enable desktop apps with web technologies. The parent directory (`../`) is the Chromium source tree.
|
||||
|
||||
### Process Model
|
||||
|
||||
Electron has two primary process types, mirroring Chromium:
|
||||
|
||||
- **Main process** (`shell/browser/` + `lib/browser/`): Controls app lifecycle, creates windows, system APIs
|
||||
- **Renderer process** (`shell/renderer/` + `lib/renderer/`): Runs web content in BrowserWindows
|
||||
|
||||
### Native ↔ JavaScript Bridge
|
||||
|
||||
Each API is implemented as a C++/JS pair:
|
||||
|
||||
- C++ side: `shell/browser/api/electron_api_{name}.cc/.h` — uses `gin::Wrappable` and `ObjectTemplateBuilder`
|
||||
- JS side: `lib/browser/api/{name}.ts` — exports the module, registered in `lib/browser/api/module-list.ts`
|
||||
- Binding: `NODE_LINKED_BINDING_CONTEXT_AWARE(electron_browser_{name}, Initialize)` in C++ and registered in `shell/common/node_bindings.cc`
|
||||
- Type declaration: `typings/internal-ambient.d.ts` maps `process._linkedBinding('electron_browser_{name}')`
|
||||
|
||||
### Patches System
|
||||
|
||||
Electron patches upstream dependencies (Chromium, Node.js, V8, etc.) rather than forking them. Patches live in `patches/` organized by target, with `patches/config.json` mapping directories to repos.
|
||||
|
||||
```text
|
||||
patches/{target}/*.patch → [e sync] → target repo commits
|
||||
← [e patches] ←
|
||||
```
|
||||
|
||||
Key rules:
|
||||
|
||||
- Fix existing patches rather than creating new ones
|
||||
- Preserve original authorship in TODO comments — never change `TODO(name)` assignees
|
||||
- Each patch commit message must explain why the patch exists
|
||||
- After modifying patches, run `e patches {target}` to export
|
||||
|
||||
When working on the `roller/chromium/main` branch for Chromium upgrades, use `e sync --3` for 3-way merge conflict resolution.
|
||||
|
||||
## Conventions
|
||||
|
||||
### File Naming
|
||||
|
||||
- JS/TS files: kebab-case (`file-name.ts`)
|
||||
- C++ files: snake_case with `electron_api_` prefix (`electron_api_safe_storage.cc`)
|
||||
- Test files: `api-{module-name}-spec.ts` in `spec/`
|
||||
- Source file lists are maintained in `filenames.gni` (with platform-specific sections)
|
||||
|
||||
### JavaScript/TypeScript
|
||||
|
||||
- Semicolons required (`"semi": ["error", "always"]`)
|
||||
- `const` and `let` only (no `var`)
|
||||
- Arrow functions preferred
|
||||
- Import order enforced: `@electron/internal` → `@electron` → `electron` → external → builtin → relative
|
||||
- API naming: `PascalCase` for classes (`BrowserWindow`), `camelCase` for module APIs (`globalShortcut`)
|
||||
- Prefer getters/setters over jQuery-style `.text([text])` patterns
|
||||
|
||||
### C++
|
||||
|
||||
- Follows Chromium coding style, enforced by `clang-format` and `clang-tidy`
|
||||
- Uses Chromium abstractions (`base::`, `content::`, etc.)
|
||||
- Header guards: `#ifndef ELECTRON_SHELL_BROWSER_API_ELECTRON_API_{NAME}_H_`
|
||||
- Platform-specific files: `_mac.mm`, `_win.cc`, `_linux.cc`
|
||||
|
||||
### Testing
|
||||
|
||||
- Framework: Mocha + Chai + Sinon
|
||||
- Test helpers in `spec/lib/` (e.g., `spec-helpers.ts`, `window-helpers.ts`)
|
||||
- Use `defer()` from spec-helpers for cleanup, `closeAllWindows()` for window teardown
|
||||
- Tests import from `electron/main` or `electron/renderer`
|
||||
|
||||
### Documentation
|
||||
|
||||
- API docs in `docs/api/` as Markdown, parsed by `@electron/docs-parser` to generate `electron.d.ts`
|
||||
- API history tracked via YAML blocks in HTML comments within doc files
|
||||
- Docs must pass `npm run lint:docs`
|
||||
|
||||
### Build Configuration
|
||||
|
||||
- `BUILD.gn`: Main GN build config
|
||||
- `buildflags/buildflags.gni`: Feature flags (PDF viewer, extensions, spellchecker)
|
||||
- `build/args/`: Build argument profiles (`testing.gn`, `release.gn`, `all.gn`)
|
||||
- `DEPS`: Dependency versions and checkout paths
|
||||
- `chromium_src/`: Chromium source file overrides (compiled instead of originals)
|
||||
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
|
||||
}
|
||||
]
|
||||
}
|
||||
]
|
||||
}
|
||||
16
.github/problem-matchers/markdownlint.json
vendored
16
.github/problem-matchers/markdownlint.json
vendored
@@ -1,16 +0,0 @@
|
||||
{
|
||||
"problemMatcher": [
|
||||
{
|
||||
"owner": "markdownlint",
|
||||
"pattern": [
|
||||
{
|
||||
"regexp": "^(.+):(\\d+):(\\d+)\\s+(.*)$",
|
||||
"file": 1,
|
||||
"line": 2,
|
||||
"column": 3,
|
||||
"message": 4
|
||||
}
|
||||
]
|
||||
}
|
||||
]
|
||||
}
|
||||
12
.github/workflows/apply-patches.yml
vendored
12
.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: |
|
||||
@@ -41,7 +41,7 @@ jobs:
|
||||
permissions:
|
||||
contents: read
|
||||
container:
|
||||
image: ghcr.io/electron/build:eac3529546ea8f3aa356d31e345715eef342233b
|
||||
image: ghcr.io/electron/build:a82b87d7a4f5ff0cab61405f8151ac4cf4942aeb
|
||||
options: --user root
|
||||
volumes:
|
||||
- /mnt/cross-instance-cache:/mnt/cross-instance-cache
|
||||
@@ -71,11 +71,3 @@ jobs:
|
||||
uses: ./src/electron/.github/actions/checkout
|
||||
with:
|
||||
target-platform: linux
|
||||
- name: Upload Patch Conflict Fix
|
||||
if: ${{ failure() }}
|
||||
uses: actions/upload-artifact@bbbca2ddaa5d8feaa63e36b76fdaad77386f024f # v7.0.0
|
||||
with:
|
||||
name: update-patches
|
||||
path: patches/update-patches.patch
|
||||
if-no-files-found: ignore
|
||||
archive: false
|
||||
|
||||
24
.github/workflows/archaeologist-dig.yml
vendored
24
.github/workflows/archaeologist-dig.yml
vendored
@@ -17,25 +17,21 @@ jobs:
|
||||
with:
|
||||
fetch-depth: 0
|
||||
- name: Setup Node.js/npm
|
||||
uses: actions/setup-node@53b83947a5a98c8d113130e565377fae1a50d02f
|
||||
uses: actions/setup-node@6044e13b5dc448c55e2357c09f80417699197238
|
||||
with:
|
||||
node-version: 24.12.x
|
||||
- name: Setting Up Dig Site
|
||||
env:
|
||||
CLONE_URL: ${{ github.event.pull_request.head.repo.clone_url }}
|
||||
HEAD_SHA: ${{ github.event.pull_request.head.sha }}
|
||||
BASE_REF: ${{ github.event.pull_request.base.ref }}
|
||||
run: |
|
||||
echo "remote: $CLONE_URL"
|
||||
echo "sha $HEAD_SHA"
|
||||
echo "base ref $BASE_REF"
|
||||
git clone https://github.com/electron/electron.git electron
|
||||
echo "remote: ${{ github.event.pull_request.head.repo.clone_url }}"
|
||||
echo "sha ${{ github.event.pull_request.head.sha }}"
|
||||
echo "base ref ${{ github.event.pull_request.base.ref }}"
|
||||
git clone https://github.com/electron/electron.git electron
|
||||
cd electron
|
||||
mkdir -p artifacts
|
||||
git remote add fork "$CLONE_URL" && git fetch fork
|
||||
git checkout "$HEAD_SHA"
|
||||
git merge-base "origin/$BASE_REF" HEAD > .dig-old
|
||||
echo "$HEAD_SHA" > .dig-new
|
||||
git remote add fork ${{ github.event.pull_request.head.repo.clone_url }} && git fetch fork
|
||||
git checkout ${{ github.event.pull_request.head.sha }}
|
||||
git merge-base origin/${{ github.event.pull_request.base.ref }} HEAD > .dig-old
|
||||
echo ${{ github.event.pull_request.head.sha }} > .dig-new
|
||||
cp .dig-old artifacts
|
||||
|
||||
- name: Generating Types for SHA in .dig-new
|
||||
@@ -49,7 +45,7 @@ jobs:
|
||||
sha-file: .dig-old
|
||||
filename: electron.old.d.ts
|
||||
- name: Upload artifacts
|
||||
uses: actions/upload-artifact@bbbca2ddaa5d8feaa63e36b76fdaad77386f024f #v7.0.0
|
||||
uses: actions/upload-artifact@b7c566a772e6b6bfb58ed0dc250532a479d7789f #v6.0.0
|
||||
with:
|
||||
name: artifacts
|
||||
path: electron/artifacts
|
||||
|
||||
5
.github/workflows/audit-branch-ci.yml
vendored
5
.github/workflows/audit-branch-ci.yml
vendored
@@ -17,7 +17,7 @@ jobs:
|
||||
contents: read
|
||||
steps:
|
||||
- name: Setup Node.js
|
||||
uses: actions/setup-node@53b83947a5a98c8d113130e565377fae1a50d02f # v6.3.0
|
||||
uses: actions/setup-node@6044e13b5dc448c55e2357c09f80417699197238 # v6.2.0
|
||||
with:
|
||||
node-version: 22.17.x
|
||||
- name: Sparse checkout repository
|
||||
@@ -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 }}"
|
||||
|
||||
75
.github/workflows/branch-created.yml
vendored
75
.github/workflows/branch-created.yml
vendored
@@ -31,46 +31,16 @@ jobs:
|
||||
else
|
||||
echo "Not a release branch: $BRANCH_NAME"
|
||||
fi
|
||||
- name: Determine Next Unsupported Major Version
|
||||
id: determine-next-unsupported-major
|
||||
if: ${{ steps.check-major-version.outputs.MAJOR }}
|
||||
env:
|
||||
MAJOR: ${{ steps.check-major-version.outputs.MAJOR }}
|
||||
run: |
|
||||
# Fetch the release schedule
|
||||
SCHEDULE=$(curl -s https://releases.electronjs.org/schedule.json)
|
||||
|
||||
# Get the stableDate for the current major version
|
||||
STABLE_DATE=$(echo "$SCHEDULE" | jq -r --arg major "${MAJOR}.0.0" '.[] | select(.version == $major) | .stableDate')
|
||||
|
||||
if [[ -z "$STABLE_DATE" || "$STABLE_DATE" == "null" ]]; then
|
||||
echo "Could not find stableDate for version $MAJOR"
|
||||
exit 1
|
||||
fi
|
||||
|
||||
# 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" '
|
||||
[.[] | 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
|
||||
echo "Could not determine oldest supported version"
|
||||
exit 1
|
||||
fi
|
||||
|
||||
echo "SCHEDULE=$SCHEDULE" >> "$GITHUB_OUTPUT"
|
||||
echo "NEXT_UNSUPPORTED_MAJOR=$NEXT_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 }}
|
||||
NUM_SUPPORTED_VERSIONS: 3
|
||||
run: |
|
||||
PREVIOUS_MAJOR=$((MAJOR - 1))
|
||||
UNSUPPORTED_MAJOR=$((NEXT_UNSUPPORTED_MAJOR - 1))
|
||||
UNSUPPORTED_MAJOR=$((MAJOR - NUM_SUPPORTED_VERSIONS - 1))
|
||||
|
||||
# Create new labels
|
||||
gh label create $MAJOR-x-y --color 8d9ee8 || true
|
||||
@@ -107,36 +77,12 @@ jobs:
|
||||
if: ${{ steps.check-major-version.outputs.MAJOR }}
|
||||
uses: actions/github-script@ed597411d8f924073f98dfc5c65a23a2325f34cd # v8.0.0
|
||||
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 }}
|
||||
with:
|
||||
script: |
|
||||
const schedule = JSON.parse(process.env.SCHEDULE)
|
||||
|
||||
const major = parseInt(process.env.MAJOR)
|
||||
const major = ${{ steps.check-major-version.outputs.MAJOR }}
|
||||
const nextMajor = major + 1
|
||||
const prevMajor = major - 1
|
||||
|
||||
const { betaDate, stableDate } = schedule.find(v => v.version === `${major}.0.0`)
|
||||
|
||||
const betaPrepWeek = new Date(betaDate)
|
||||
betaPrepWeek.setDate(betaPrepWeek.getDate() - 8)
|
||||
const betaPrepWeekEnd = new Date(betaPrepWeek)
|
||||
betaPrepWeekEnd.setDate(betaPrepWeekEnd.getDate() + 4)
|
||||
|
||||
const stablePrepWeek = new Date(stableDate)
|
||||
stablePrepWeek.setDate(stablePrepWeek.getDate() - 8)
|
||||
const stablePrepWeekEnd = new Date(stablePrepWeek)
|
||||
stablePrepWeekEnd.setDate(stablePrepWeekEnd.getDate() + 4)
|
||||
|
||||
const stableWeek = new Date(stableDate)
|
||||
stableWeek.setDate(stableWeek.getDate() - 1)
|
||||
|
||||
const nextAlphaDate = new Date(stableDate)
|
||||
nextAlphaDate.setDate(nextAlphaDate.getDate() + 2)
|
||||
|
||||
core.setOutput("major", major)
|
||||
core.setOutput("next-major", nextMajor)
|
||||
core.setOutput("prev-major", prevMajor)
|
||||
@@ -145,19 +91,10 @@ jobs:
|
||||
major,
|
||||
"next-major": nextMajor,
|
||||
"prev-major": prevMajor,
|
||||
"ending-support-major": parseInt(process.env.NEXT_UNSUPPORTED_MAJOR),
|
||||
"beta-date": betaDate,
|
||||
"beta-prep-week": betaPrepWeek.toISOString().split('T')[0],
|
||||
"beta-prep-week-end": betaPrepWeekEnd.toISOString().split('T')[0],
|
||||
"stable-week": stableWeek.toISOString().split('T')[0],
|
||||
"stable-prep-week": stablePrepWeek.toISOString().split('T')[0],
|
||||
"stable-prep-week-end": stablePrepWeekEnd.toISOString().split('T')[0],
|
||||
"stable-date": stableDate,
|
||||
"next-alpha-date": nextAlphaDate.toISOString().split('T')[0],
|
||||
}))
|
||||
- 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 +114,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 +122,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 }}
|
||||
|
||||
6
.github/workflows/build-git-cache.yml
vendored
6
.github/workflows/build-git-cache.yml
vendored
@@ -15,7 +15,7 @@ jobs:
|
||||
permissions:
|
||||
contents: read
|
||||
container:
|
||||
image: ghcr.io/electron/build:eac3529546ea8f3aa356d31e345715eef342233b
|
||||
image: ghcr.io/electron/build:a82b87d7a4f5ff0cab61405f8151ac4cf4942aeb
|
||||
options: --user root
|
||||
volumes:
|
||||
- /mnt/cross-instance-cache:/mnt/cross-instance-cache
|
||||
@@ -39,7 +39,7 @@ jobs:
|
||||
permissions:
|
||||
contents: read
|
||||
container:
|
||||
image: ghcr.io/electron/build:eac3529546ea8f3aa356d31e345715eef342233b
|
||||
image: ghcr.io/electron/build:a82b87d7a4f5ff0cab61405f8151ac4cf4942aeb
|
||||
options: --user root --device /dev/fuse --cap-add SYS_ADMIN
|
||||
volumes:
|
||||
- /mnt/win-cache:/mnt/win-cache
|
||||
@@ -66,7 +66,7 @@ jobs:
|
||||
# This job updates the same git cache as linux, so it needs to run after the linux one.
|
||||
needs: build-git-cache-linux
|
||||
container:
|
||||
image: ghcr.io/electron/build:eac3529546ea8f3aa356d31e345715eef342233b
|
||||
image: ghcr.io/electron/build:a82b87d7a4f5ff0cab61405f8151ac4cf4942aeb
|
||||
options: --user root
|
||||
volumes:
|
||||
- /mnt/cross-instance-cache:/mnt/cross-instance-cache
|
||||
|
||||
20
.github/workflows/build.yml
vendored
20
.github/workflows/build.yml
vendored
@@ -6,7 +6,7 @@ on:
|
||||
build-image-sha:
|
||||
type: string
|
||||
description: 'SHA for electron/build image'
|
||||
default: 'eac3529546ea8f3aa356d31e345715eef342233b'
|
||||
default: 'a82b87d7a4f5ff0cab61405f8151ac4cf4942aeb'
|
||||
required: true
|
||||
skip-macos:
|
||||
type: boolean
|
||||
@@ -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: |
|
||||
@@ -77,7 +77,7 @@ jobs:
|
||||
id: set-output
|
||||
run: |
|
||||
if [ -z "${{ inputs.build-image-sha }}" ]; then
|
||||
echo "build-image-sha=eac3529546ea8f3aa356d31e345715eef342233b" >> "$GITHUB_OUTPUT"
|
||||
echo "build-image-sha=a82b87d7a4f5ff0cab61405f8151ac4cf4942aeb" >> "$GITHUB_OUTPUT"
|
||||
else
|
||||
echo "build-image-sha=${{ inputs.build-image-sha }}" >> "$GITHUB_OUTPUT"
|
||||
fi
|
||||
@@ -365,18 +365,6 @@ jobs:
|
||||
generate-symbols: false
|
||||
upload-to-storage: '0'
|
||||
secrets: inherit
|
||||
|
||||
test-linux-arm64-64k:
|
||||
uses: ./.github/workflows/pipeline-segment-electron-test-64k.yml
|
||||
permissions:
|
||||
contents: read
|
||||
issues: read
|
||||
pull-requests: read
|
||||
needs: [checkout-linux, linux-arm64]
|
||||
with:
|
||||
test-runs-on: ubuntu-22.04-arm
|
||||
test-container: '{"image":"ghcr.io/electron/test:arm64v8-${{ needs.checkout-linux.outputs.build-image-sha }}","options":"--user root --privileged --init"}'
|
||||
secrets: inherit
|
||||
|
||||
windows-x64:
|
||||
permissions:
|
||||
@@ -442,7 +430,7 @@ jobs:
|
||||
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')
|
||||
steps:
|
||||
steps:
|
||||
- name: GitHub Actions Jobs Done
|
||||
run: |
|
||||
echo "All GitHub Actions Jobs are done"
|
||||
|
||||
@@ -1,32 +0,0 @@
|
||||
name: Clean Orphaned Cache Uploads
|
||||
|
||||
# Description:
|
||||
# Sweeps orphaned in-flight upload temp files left on the src-cache volumes
|
||||
# by checkout/action.yml when its cp-to-share step dies before the rename.
|
||||
# A successful upload finishes in minutes, so anything older than 4h is dead.
|
||||
|
||||
on:
|
||||
schedule:
|
||||
- cron: "0 */4 * * *"
|
||||
workflow_dispatch:
|
||||
|
||||
permissions: {}
|
||||
|
||||
jobs:
|
||||
clean-orphaned-uploads:
|
||||
if: github.repository == 'electron/electron'
|
||||
runs-on: electron-arc-centralus-linux-amd64-32core
|
||||
permissions:
|
||||
contents: read
|
||||
container:
|
||||
image: ghcr.io/electron/build:bc2f48b2415a670de18d13605b1cf0eb5fdbaae1
|
||||
options: --user root
|
||||
volumes:
|
||||
- /mnt/cross-instance-cache:/mnt/cross-instance-cache
|
||||
- /mnt/win-cache:/mnt/win-cache
|
||||
steps:
|
||||
- name: Remove Orphaned Upload Temp Files
|
||||
shell: bash
|
||||
run: |
|
||||
find /mnt/cross-instance-cache -maxdepth 1 -type f -name '*.tar.upload-*' -mmin +240 -print -delete
|
||||
find /mnt/win-cache -maxdepth 1 -type f -name '*.tar.upload-*' -mmin +240 -print -delete
|
||||
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
|
||||
|
||||
63
.github/workflows/issue-commented.yml
vendored
63
.github/workflows/issue-commented.yml
vendored
@@ -1,4 +1,4 @@
|
||||
name: Issue / Pull Request Commented
|
||||
name: Issue Commented
|
||||
|
||||
on:
|
||||
issue_comment:
|
||||
@@ -8,16 +8,16 @@ on:
|
||||
permissions: {}
|
||||
|
||||
jobs:
|
||||
blocked-issue-commented:
|
||||
issue-commented:
|
||||
name: Remove blocked/{need-info,need-repro} on comment
|
||||
if: ${{ !github.event.issue.pull_request && (contains(github.event.issue.labels.*.name, 'blocked/need-repro') || contains(github.event.issue.labels.*.name, 'blocked/need-info ❌')) && github.event.comment.user.type != 'Bot' }}
|
||||
runs-on: ubuntu-slim
|
||||
if: ${{ (contains(github.event.issue.labels.*.name, 'blocked/need-repro') || contains(github.event.issue.labels.*.name, 'blocked/need-info ❌')) && github.event.comment.user.type != 'Bot' }}
|
||||
runs-on: ubuntu-latest
|
||||
steps:
|
||||
- name: Get author association
|
||||
id: get-author-association
|
||||
env:
|
||||
GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}
|
||||
run: &get-author-association |
|
||||
run: |
|
||||
AUTHOR_ASSOCIATION=$(gh api /repos/electron/electron/issues/comments/${{ github.event.comment.id }} --jq '.author_association')
|
||||
echo "author_association=$AUTHOR_ASSOCIATION" >> "$GITHUB_OUTPUT"
|
||||
- name: Generate GitHub App token
|
||||
@@ -33,56 +33,3 @@ jobs:
|
||||
ISSUE_URL: ${{ github.event.issue.html_url }}
|
||||
run: |
|
||||
gh issue edit $ISSUE_URL --remove-label 'blocked/need-repro','blocked/need-info ❌'
|
||||
|
||||
pr-reviewer-requested:
|
||||
name: Maintainer requested reviewer on PR
|
||||
if: ${{ github.event.issue.pull_request && startsWith(github.event.comment.body, '/request-review') && github.event.comment.user.type != 'Bot' }}
|
||||
runs-on: ubuntu-slim
|
||||
steps:
|
||||
- name: Get author association
|
||||
id: get-author-association
|
||||
env:
|
||||
GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}
|
||||
run: *get-author-association
|
||||
- name: Generate GitHub App token
|
||||
uses: electron/github-app-auth-action@e14e47722ed120360649d0789e25b9baece12725 # v2.0.0
|
||||
if: ${{ contains(fromJSON('["MEMBER", "OWNER"]'), steps.get-author-association.outputs.author_association) }}
|
||||
id: generate-token
|
||||
with:
|
||||
creds: ${{ secrets.ISSUE_TRIAGE_GH_APP_CREDS }}
|
||||
- name: Request reviewer
|
||||
if: ${{ contains(fromJSON('["MEMBER", "OWNER"]'), steps.get-author-association.outputs.author_association) }}
|
||||
env:
|
||||
GITHUB_TOKEN: ${{ steps.generate-token.outputs.token }}
|
||||
PR_URL: ${{ github.event.issue.html_url }}
|
||||
COMMENT_BODY: ${{ github.event.comment.body }}
|
||||
run: |
|
||||
RAW=$(echo "$COMMENT_BODY" | head -n 1 | sed 's|/request-review\s*||' | xargs)
|
||||
|
||||
if [ -z "$RAW" ]; then
|
||||
echo "::warning::No username provided. Usage: /request-review <username>[,<username>,...]"
|
||||
exit 0
|
||||
fi
|
||||
|
||||
IFS=',' read -ra USERS <<< "$RAW"
|
||||
for USER in "${USERS[@]}"; do
|
||||
NAME=$(echo "$USER" | sed 's/@//g' | xargs)
|
||||
if [ -z "$NAME" ]; then
|
||||
continue
|
||||
fi
|
||||
|
||||
# Strip "electron/" prefix if present to get the bare name
|
||||
BARE_NAME=$(echo "$NAME" | sed 's|^electron/||')
|
||||
|
||||
# If the original name contained "electron/" or looks like a team slug, treat as team
|
||||
if [ "$NAME" != "$BARE_NAME" ]; then
|
||||
gh pr edit $PR_URL --add-reviewer "electron/$BARE_NAME"
|
||||
else
|
||||
if ! gh api /orgs/electron/public_members/$BARE_NAME --silent > /dev/null 2>&1; then
|
||||
echo "::warning::$BARE_NAME is not a public member of the electron organization."
|
||||
continue
|
||||
fi
|
||||
|
||||
gh pr edit $PR_URL --add-reviewer "$BARE_NAME"
|
||||
fi
|
||||
done
|
||||
|
||||
9
.github/workflows/issue-labeled.yml
vendored
9
.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
|
||||
@@ -61,10 +61,9 @@ jobs:
|
||||
env:
|
||||
GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}
|
||||
GH_REPO: electron/electron
|
||||
ISSUE_NUMBER: ${{ github.event.issue.number }}
|
||||
run: |
|
||||
set -eo pipefail
|
||||
COMMENT_COUNT=$(gh issue view "$ISSUE_NUMBER" --comments --json comments | jq '[ .comments[] | select(.author.login == "electron-issue-triage" or .authorAssociation == "OWNER" or .authorAssociation == "MEMBER") | select(.body | startswith("<!-- blocked/need-repro -->")) ] | length')
|
||||
COMMENT_COUNT=$(gh issue view ${{ github.event.issue.number }} --comments --json comments | jq '[ .comments[] | select(.author.login == "electron-issue-triage" or .authorAssociation == "OWNER" or .authorAssociation == "MEMBER") | select(.body | startswith("<!-- blocked/need-repro -->")) ] | length')
|
||||
if [[ $COMMENT_COUNT -eq 0 ]]; then
|
||||
echo "SHOULD_COMMENT=1" >> "$GITHUB_OUTPUT"
|
||||
fi
|
||||
@@ -76,7 +75,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@e2ff99831a4f13625d35064e2b3dfe65c07a0396 # v3.7.5
|
||||
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@e2ff99831a4f13625d35064e2b3dfe65c07a0396 # v3.7.5
|
||||
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
|
||||
|
||||
6
.github/workflows/issue-unlabeled.yml
vendored
6
.github/workflows/issue-unlabeled.yml
vendored
@@ -16,11 +16,9 @@ jobs:
|
||||
steps:
|
||||
- name: Check for any blocked labels
|
||||
id: check-for-blocked-labels
|
||||
env:
|
||||
LABELS_JSON: ${{ toJSON(github.event.issue.labels.*.name) }}
|
||||
run: |
|
||||
set -eo pipefail
|
||||
BLOCKED_LABEL_COUNT=$(echo "$LABELS_JSON" | jq '[ .[] | select(startswith("blocked/")) ] | length')
|
||||
BLOCKED_LABEL_COUNT=$(echo '${{ toJSON(github.event.issue.labels.*.name) }}' | jq '[ .[] | select(startswith("blocked/")) ] | length')
|
||||
if [[ $BLOCKED_LABEL_COUNT -eq 0 ]]; then
|
||||
echo "NOT_BLOCKED=1" >> "$GITHUB_OUTPUT"
|
||||
fi
|
||||
@@ -33,7 +31,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
|
||||
|
||||
5
.github/workflows/linux-publish.yml
vendored
5
.github/workflows/linux-publish.yml
vendored
@@ -6,7 +6,7 @@ on:
|
||||
build-image-sha:
|
||||
type: string
|
||||
description: 'SHA for electron/build image'
|
||||
default: 'eac3529546ea8f3aa356d31e345715eef342233b'
|
||||
default: 'a82b87d7a4f5ff0cab61405f8151ac4cf4942aeb'
|
||||
upload-to-storage:
|
||||
description: 'Uploads to Azure storage'
|
||||
required: false
|
||||
@@ -46,7 +46,6 @@ jobs:
|
||||
publish-x64:
|
||||
uses: ./.github/workflows/pipeline-segment-electron-publish.yml
|
||||
permissions:
|
||||
artifact-metadata: write
|
||||
attestations: write
|
||||
contents: read
|
||||
id-token: write
|
||||
@@ -66,7 +65,6 @@ jobs:
|
||||
publish-arm:
|
||||
uses: ./.github/workflows/pipeline-segment-electron-publish.yml
|
||||
permissions:
|
||||
artifact-metadata: write
|
||||
attestations: write
|
||||
contents: read
|
||||
id-token: write
|
||||
@@ -86,7 +84,6 @@ jobs:
|
||||
publish-arm64:
|
||||
uses: ./.github/workflows/pipeline-segment-electron-publish.yml
|
||||
permissions:
|
||||
artifact-metadata: write
|
||||
attestations: write
|
||||
contents: read
|
||||
id-token: write
|
||||
|
||||
6
.github/workflows/macos-publish.yml
vendored
6
.github/workflows/macos-publish.yml
vendored
@@ -6,7 +6,7 @@ on:
|
||||
build-image-sha:
|
||||
type: string
|
||||
description: 'SHA for electron/build image'
|
||||
default: 'eac3529546ea8f3aa356d31e345715eef342233b'
|
||||
default: 'a82b87d7a4f5ff0cab61405f8151ac4cf4942aeb'
|
||||
required: true
|
||||
upload-to-storage:
|
||||
description: 'Uploads to Azure storage'
|
||||
@@ -50,7 +50,6 @@ jobs:
|
||||
publish-x64-darwin:
|
||||
uses: ./.github/workflows/pipeline-segment-electron-publish.yml
|
||||
permissions:
|
||||
artifact-metadata: write
|
||||
attestations: write
|
||||
contents: read
|
||||
id-token: write
|
||||
@@ -70,7 +69,6 @@ jobs:
|
||||
publish-x64-mas:
|
||||
uses: ./.github/workflows/pipeline-segment-electron-publish.yml
|
||||
permissions:
|
||||
artifact-metadata: write
|
||||
attestations: write
|
||||
contents: read
|
||||
id-token: write
|
||||
@@ -90,7 +88,6 @@ jobs:
|
||||
publish-arm64-darwin:
|
||||
uses: ./.github/workflows/pipeline-segment-electron-publish.yml
|
||||
permissions:
|
||||
artifact-metadata: write
|
||||
attestations: write
|
||||
contents: read
|
||||
id-token: write
|
||||
@@ -110,7 +107,6 @@ jobs:
|
||||
publish-arm64-mas:
|
||||
uses: ./.github/workflows/pipeline-segment-electron-publish.yml
|
||||
permissions:
|
||||
artifact-metadata: write
|
||||
attestations: write
|
||||
contents: read
|
||||
id-token: write
|
||||
|
||||
@@ -10,10 +10,6 @@ on:
|
||||
- '.yarn/**'
|
||||
- '.yarnrc.yml'
|
||||
|
||||
# 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:
|
||||
@@ -49,23 +45,5 @@ jobs:
|
||||
env:
|
||||
GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}
|
||||
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 @${{ github.event.pull_request.user.login }}! 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=-
|
||||
|
||||
@@ -110,21 +110,6 @@ jobs:
|
||||
test-runs-on: ${{ inputs.test-runs-on }}
|
||||
test-container: ${{ inputs.test-container }}
|
||||
secrets: inherit
|
||||
test-wayland:
|
||||
uses: ./.github/workflows/pipeline-segment-electron-test.yml
|
||||
permissions:
|
||||
contents: read
|
||||
issues: read
|
||||
pull-requests: read
|
||||
needs: build
|
||||
if: ${{ inputs.target-platform == 'linux' && inputs.target-arch == 'x64' && !inputs.is-asan }}
|
||||
with:
|
||||
target-arch: ${{ inputs.target-arch }}
|
||||
target-platform: ${{ inputs.target-platform }}
|
||||
test-runs-on: ${{ inputs.test-runs-on }}
|
||||
test-container: ${{ inputs.test-container }}
|
||||
display-server: wayland
|
||||
secrets: inherit
|
||||
nn-test:
|
||||
uses: ./.github/workflows/pipeline-segment-node-nan-test.yml
|
||||
permissions:
|
||||
|
||||
@@ -35,7 +35,7 @@ jobs:
|
||||
- name: Generate DEPS Hash
|
||||
run: |
|
||||
node src/electron/script/generate-deps-hash.js
|
||||
DEPSHASH=v2-src-cache-$(cat src/electron/.depshash)
|
||||
DEPSHASH=v1-src-cache-$(cat src/electron/.depshash)
|
||||
echo "DEPSHASH=$DEPSHASH" >> $GITHUB_ENV
|
||||
echo "CACHE_PATH=$DEPSHASH.tar" >> $GITHUB_ENV
|
||||
- name: Restore src cache via AKS
|
||||
|
||||
17
.github/workflows/pipeline-electron-lint.yml
vendored
17
.github/workflows/pipeline-electron-lint.yml
vendored
@@ -46,11 +46,7 @@ jobs:
|
||||
shell: bash
|
||||
run: |
|
||||
chromium_revision="$(grep -A1 chromium_version src/electron/DEPS | tr -d '\n' | cut -d\' -f4)"
|
||||
if [[ ! "$chromium_revision" =~ ^[a-zA-Z0-9._-]+$ ]]; then
|
||||
echo "::error::Invalid chromium_revision: $chromium_revision"
|
||||
exit 1
|
||||
fi
|
||||
gn_version="$(curl -sL "https://raw.githubusercontent.com/chromium/chromium/refs/tags/${chromium_revision}/DEPS" | grep gn_version | head -n1 | cut -d\' -f4)"
|
||||
gn_version="$(curl -sL "https://chromium.googlesource.com/chromium/src/+/${chromium_revision}/DEPS?format=TEXT" | base64 -d | grep gn_version | head -n1 | cut -d\' -f4)"
|
||||
|
||||
cipd ensure -ensure-file - -root . <<-CIPD
|
||||
\$ServiceURL https://chrome-infra-packages.appspot.com/
|
||||
@@ -64,19 +60,14 @@ jobs:
|
||||
shell: bash
|
||||
run: |
|
||||
chromium_revision="$(grep -A1 chromium_version src/electron/DEPS | tr -d '\n' | cut -d\' -f4)"
|
||||
if [[ ! "$chromium_revision" =~ ^[a-zA-Z0-9._-]+$ ]]; then
|
||||
echo "::error::Invalid chromium_revision: $chromium_revision"
|
||||
exit 1
|
||||
fi
|
||||
|
||||
mkdir -p src/buildtools
|
||||
curl -sL "https://raw.githubusercontent.com/chromium/chromium/refs/tags/${chromium_revision}/buildtools/DEPS" > src/buildtools/DEPS
|
||||
curl -sL "https://chromium.googlesource.com/chromium/src/+/${chromium_revision}/buildtools/DEPS?format=TEXT" | base64 -d > src/buildtools/DEPS
|
||||
|
||||
gclient sync --spec="solutions=[{'name':'src/buildtools','url':None,'deps_file':'DEPS','custom_vars':{'process_deps':True},'managed':False}]"
|
||||
- name: Add problem matchers
|
||||
- name: Add ESLint problem matcher
|
||||
shell: bash
|
||||
run: |
|
||||
echo "::add-matcher::src/electron/.github/problem-matchers/markdownlint.json"
|
||||
run: echo "::add-matcher::src/electron/.github/problem-matchers/eslint-stylish.json"
|
||||
- name: Run Lint
|
||||
shell: bash
|
||||
run: |
|
||||
|
||||
@@ -124,7 +124,7 @@ jobs:
|
||||
run: df -h
|
||||
- name: Setup Node.js/npm
|
||||
if: ${{ inputs.target-platform == 'macos' }}
|
||||
uses: actions/setup-node@53b83947a5a98c8d113130e565377fae1a50d02f
|
||||
uses: actions/setup-node@6044e13b5dc448c55e2357c09f80417699197238
|
||||
with:
|
||||
node-version: 22.21.x
|
||||
cache: yarn
|
||||
@@ -156,7 +156,7 @@ jobs:
|
||||
- name: Generate DEPS Hash
|
||||
run: |
|
||||
node src/electron/script/generate-deps-hash.js
|
||||
DEPSHASH=v2-src-cache-$(cat src/electron/.depshash)
|
||||
DEPSHASH=v1-src-cache-$(cat src/electron/.depshash)
|
||||
echo "DEPSHASH=$DEPSHASH" >> $GITHUB_ENV
|
||||
echo "CACHE_PATH=$DEPSHASH.tar" >> $GITHUB_ENV
|
||||
- name: Restore src cache via AZCopy
|
||||
|
||||
@@ -80,7 +80,7 @@ jobs:
|
||||
- name: Generate DEPS Hash
|
||||
run: |
|
||||
node src/electron/script/generate-deps-hash.js
|
||||
DEPSHASH=v2-src-cache-$(cat src/electron/.depshash)
|
||||
DEPSHASH=v1-src-cache-$(cat src/electron/.depshash)
|
||||
echo "DEPSHASH=$DEPSHASH" >> $GITHUB_ENV
|
||||
echo "CACHE_PATH=$DEPSHASH.tar" >> $GITHUB_ENV
|
||||
- name: Restore src cache via AZCopy
|
||||
@@ -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@37930b1c2abaa49bbe596cd826c3c89aef350131
|
||||
with:
|
||||
name: out_gen_artifacts_${{ env.ARTIFACT_KEY }}
|
||||
path: ./src/out/${{ env.ELECTRON_OUT_DIR }}/gen
|
||||
|
||||
@@ -81,7 +81,7 @@ jobs:
|
||||
- name: Generate DEPS Hash
|
||||
run: |
|
||||
node src/electron/script/generate-deps-hash.js
|
||||
DEPSHASH=v2-src-cache-$(cat src/electron/.depshash)
|
||||
DEPSHASH=v1-src-cache-$(cat src/electron/.depshash)
|
||||
echo "DEPSHASH=$DEPSHASH" >> $GITHUB_ENV
|
||||
echo "CACHE_PATH=$DEPSHASH.tar" >> $GITHUB_ENV
|
||||
- name: Restore src cache via AZCopy
|
||||
|
||||
@@ -93,7 +93,6 @@ jobs:
|
||||
shell: bash
|
||||
runs-on: ${{ inputs.build-runs-on }}
|
||||
permissions:
|
||||
artifact-metadata: write
|
||||
attestations: write
|
||||
contents: read
|
||||
id-token: write
|
||||
@@ -132,7 +131,7 @@ jobs:
|
||||
run: df -h
|
||||
- name: Setup Node.js/npm
|
||||
if: ${{ inputs.target-platform == 'macos' }}
|
||||
uses: actions/setup-node@53b83947a5a98c8d113130e565377fae1a50d02f
|
||||
uses: actions/setup-node@6044e13b5dc448c55e2357c09f80417699197238
|
||||
with:
|
||||
node-version: 22.21.x
|
||||
cache: yarn
|
||||
@@ -165,7 +164,7 @@ jobs:
|
||||
- name: Generate DEPS Hash
|
||||
run: |
|
||||
node src/electron/script/generate-deps-hash.js
|
||||
DEPSHASH=v2-src-cache-$(cat src/electron/.depshash)
|
||||
DEPSHASH=v1-src-cache-$(cat src/electron/.depshash)
|
||||
echo "DEPSHASH=$DEPSHASH" >> $GITHUB_ENV
|
||||
echo "CACHE_PATH=$DEPSHASH.tar" >> $GITHUB_ENV
|
||||
- name: Restore src cache via AZCopy
|
||||
|
||||
@@ -1,67 +0,0 @@
|
||||
name: Pipeline Segment - Electron Test on Linux ARM64 64k
|
||||
|
||||
on:
|
||||
workflow_call:
|
||||
inputs:
|
||||
test-runs-on:
|
||||
type: string
|
||||
description: 'What host to run the tests on'
|
||||
required: true
|
||||
test-container:
|
||||
type: string
|
||||
description: 'JSON container information for aks runs-on'
|
||||
required: false
|
||||
default: '{"image":null}'
|
||||
|
||||
concurrency:
|
||||
group: electron-test-linux-64k-${{ github.ref_protected == true && github.run_id || github.ref }}
|
||||
cancel-in-progress: ${{ github.ref_protected != true }}
|
||||
|
||||
permissions: {}
|
||||
|
||||
env:
|
||||
ELECTRON_OUT_DIR: Default
|
||||
|
||||
jobs:
|
||||
test-linux-arm64-64k:
|
||||
env:
|
||||
BUILD_TYPE: linux
|
||||
TARGET_ARCH: arm64
|
||||
defaults:
|
||||
run:
|
||||
shell: bash
|
||||
runs-on: ${{ inputs.test-runs-on }}
|
||||
permissions:
|
||||
contents: read
|
||||
issues: read
|
||||
pull-requests: read
|
||||
steps:
|
||||
- name: Checkout Electron
|
||||
uses: actions/checkout@de0fac2e4500dabe0009e67214ff5f5447ce83dd
|
||||
with:
|
||||
path: src/electron
|
||||
fetch-depth: 0
|
||||
ref: ${{ github.event.pull_request.head.sha }}
|
||||
- name: Download Generated Artifacts
|
||||
uses: actions/download-artifact@3e5f45b2cfb9172054b4087a40e8e0b5a5461e7c
|
||||
with:
|
||||
name: generated_artifacts_linux_arm64
|
||||
path: ./generated_artifacts_linux_arm64
|
||||
- name: Restore Generated Artifacts
|
||||
run: ./src/electron/script/actions/restore-artifacts.sh
|
||||
- name: Unzip Dist
|
||||
run: |
|
||||
cd src/out/Default
|
||||
unzip -:o dist.zip
|
||||
|
||||
- name: Run Electron Tests in QEMU 64k Container
|
||||
shell: bash
|
||||
env:
|
||||
MOCHA_REPORTER: mocha-multi-reporters
|
||||
MOCHA_MULTI_REPORTERS: mocha-junit-reporter, tap
|
||||
ELECTRON_DISABLE_SECURITY_WARNINGS: 1
|
||||
DISPLAY: ':99.0'
|
||||
run: |
|
||||
container=$(echo '${{ inputs.test-container }}' | jq -r '.image')
|
||||
src/electron/script/run-qemu-64k.sh --container $container --testfiles "`pwd`/src"
|
||||
|
||||
@@ -30,14 +30,9 @@ on:
|
||||
required: false
|
||||
type: boolean
|
||||
default: false
|
||||
display-server:
|
||||
description: 'Display backend for Linux tests: x11 or wayland'
|
||||
required: false
|
||||
type: string
|
||||
default: x11
|
||||
|
||||
concurrency:
|
||||
group: electron-test-${{ inputs.target-platform }}-${{ inputs.target-arch }}-${{ inputs.is-asan }}-${{ inputs.display-server }}-${{ github.ref_protected == true && github.run_id || github.ref }}
|
||||
group: electron-test-${{ inputs.target-platform }}-${{ inputs.target-arch }}-${{ inputs.is-asan }}-${{ github.ref_protected == true && github.run_id || github.ref }}
|
||||
cancel-in-progress: ${{ github.ref_protected != true }}
|
||||
|
||||
permissions: {}
|
||||
@@ -48,8 +43,6 @@ env:
|
||||
ELECTRON_OUT_DIR: Default
|
||||
ELECTRON_RBE_JWT: ${{ secrets.ELECTRON_RBE_JWT }}
|
||||
ACTIONS_STEP_DEBUG: ${{ secrets.ACTIONS_STEP_DEBUG }}
|
||||
# @sentry/cli is only needed by release upload-symbols.py; skip the ~17MB CDN download on test jobs
|
||||
SENTRYCLI_SKIP_DOWNLOAD: 1
|
||||
|
||||
jobs:
|
||||
test:
|
||||
@@ -66,7 +59,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: ${{ inputs.target-platform == 'linux' && fromJSON('[1, 2, 3]') || fromJSON('[1, 2]') }}
|
||||
env:
|
||||
BUILD_TYPE: ${{ matrix.build-type }}
|
||||
TARGET_ARCH: ${{ inputs.target-arch }}
|
||||
@@ -79,7 +72,7 @@ jobs:
|
||||
cp $(which node) /mnt/runner-externals/node24/bin/
|
||||
- name: Setup Node.js/npm
|
||||
if: ${{ inputs.target-platform == 'win' }}
|
||||
uses: actions/setup-node@53b83947a5a98c8d113130e565377fae1a50d02f
|
||||
uses: actions/setup-node@6044e13b5dc448c55e2357c09f80417699197238
|
||||
with:
|
||||
node-version: 22.21.x
|
||||
- name: Add TCC permissions on macOS
|
||||
@@ -175,12 +168,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@37930b1c2abaa49bbe596cd826c3c89aef350131
|
||||
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@37930b1c2abaa49bbe596cd826c3c89aef350131
|
||||
with:
|
||||
name: src_artifacts_${{ env.ARTIFACT_KEY }}
|
||||
path: ./src_artifacts_${{ matrix.build-type }}_${{ inputs.target-arch }}
|
||||
@@ -203,9 +196,6 @@ jobs:
|
||||
run: |
|
||||
cd src/electron
|
||||
./script/codesign/generate-identity.sh
|
||||
# Sign with our self-signed cert so that macOS system integrations
|
||||
# (UNNotifications, dock bounce, etc.) work in tests on both architectures.
|
||||
# Autoupdater tests sign their own fixture copies via signApp().
|
||||
- name: Sign Electron.app for macOS tests
|
||||
if: ${{ inputs.target-platform == 'macos' }}
|
||||
run: |
|
||||
@@ -216,7 +206,6 @@ jobs:
|
||||
|
||||
- name: Run Electron Tests
|
||||
shell: bash
|
||||
timeout-minutes: 60
|
||||
env:
|
||||
MOCHA_REPORTER: mocha-multi-reporters
|
||||
MOCHA_MULTI_REPORTERS: mocha-junit-reporter, tap
|
||||
@@ -227,22 +216,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) }})
|
||||
if [ "${{ inputs.display-server }}" = "wayland" ]; then
|
||||
allowlist_file=script/wayland-test-allowlist.txt
|
||||
filtered_tests=""
|
||||
for test_file in $tests_files; do
|
||||
if grep -Fxq "$test_file" "$allowlist_file"; then
|
||||
filtered_tests="$filtered_tests $test_file"
|
||||
fi
|
||||
done
|
||||
tests_files="${filtered_tests# }"
|
||||
|
||||
if [ -z "$tests_files" ]; then
|
||||
echo "No tests matched Wayland filter, skipping."
|
||||
exit 0
|
||||
fi
|
||||
fi
|
||||
tests_files=$(node script/split-tests ${{ matrix.shard }} ${{ inputs.target-platform == 'linux' && 3 || 2 }})
|
||||
|
||||
# Run tests
|
||||
if [ "${{ inputs.target-platform }}" != "linux" ]; then
|
||||
@@ -277,28 +251,11 @@ jobs:
|
||||
if [ "${{ inputs.target-arch }}" = "arm" ]; then
|
||||
runuser -u builduser -- xvfb-run script/actions/run-tests.sh script/yarn.js test --skipYarnInstall --runners=main --enableRerun=3 --trace-uncaught --enable-logging --files $tests_files
|
||||
else
|
||||
if [ "${{ inputs.display-server }}" = "wayland" ]; then
|
||||
runuser -u builduser -- script/actions/run-tests-wayland.sh script/yarn.js test --runners=main --enableRerun=3 --trace-uncaught --enable-logging --files $tests_files
|
||||
else
|
||||
runuser -u builduser -- xvfb-run script/actions/run-tests.sh script/yarn.js test --runners=main --enableRerun=3 --trace-uncaught --enable-logging --files $tests_files
|
||||
fi
|
||||
runuser -u builduser -- xvfb-run script/actions/run-tests.sh script/yarn.js test --runners=main --enableRerun=3 --trace-uncaught --enable-logging --files $tests_files
|
||||
fi
|
||||
|
||||
fi
|
||||
fi
|
||||
- name: Take screenshot on timeout or cancellation
|
||||
if: ${{ inputs.target-platform != 'linux' && (cancelled() || failure()) }}
|
||||
shell: bash
|
||||
run: |
|
||||
screenshot_dir="src/electron/spec/artifacts"
|
||||
mkdir -p "$screenshot_dir"
|
||||
screenshot_file="$screenshot_dir/screenshot-timeout-$(date +%Y%m%d%H%M%S).png"
|
||||
if [ "${{ inputs.target-platform }}" = "macos" ]; then
|
||||
screencapture -x "$screenshot_file" || true
|
||||
elif [ "${{ inputs.target-platform }}" = "win" ]; then
|
||||
powershell -command "Add-Type -AssemblyName System.Windows.Forms; \$screen = [System.Windows.Forms.Screen]::PrimaryScreen.Bounds; \$bitmap = New-Object System.Drawing.Bitmap(\$screen.Width, \$screen.Height); \$graphics = [System.Drawing.Graphics]::FromImage(\$bitmap); \$graphics.CopyFromScreen(\$screen.Location, [System.Drawing.Point]::Empty, \$screen.Size); \$bitmap.Save('$screenshot_file')" || true
|
||||
fi
|
||||
|
||||
- name: Upload Test results to Datadog
|
||||
env:
|
||||
DD_ENV: ci
|
||||
@@ -314,10 +271,10 @@ jobs:
|
||||
fi
|
||||
if: always() && !cancelled()
|
||||
- name: Upload Test Artifacts
|
||||
if: always()
|
||||
uses: actions/upload-artifact@bbbca2ddaa5d8feaa63e36b76fdaad77386f024f #v7.0.0
|
||||
if: always() && !cancelled()
|
||||
uses: actions/upload-artifact@b7c566a772e6b6bfb58ed0dc250532a479d7789f
|
||||
with:
|
||||
name: ${{ inputs.target-platform == 'linux' && format('test_artifacts_{0}_{1}_{2}', env.ARTIFACT_KEY, inputs.display-server, matrix.shard) || format('test_artifacts_{0}_{1}', env.ARTIFACT_KEY, matrix.shard) }}
|
||||
name: test_artifacts_${{ env.ARTIFACT_KEY }}_${{ matrix.shard }}
|
||||
path: src/electron/spec/artifacts
|
||||
if-no-files-found: ignore
|
||||
- name: Wait for active SSH sessions
|
||||
|
||||
@@ -36,8 +36,6 @@ env:
|
||||
CHROMIUM_GIT_COOKIE: ${{ secrets.CHROMIUM_GIT_COOKIE }}
|
||||
ELECTRON_OUT_DIR: Default
|
||||
ELECTRON_RBE_JWT: ${{ secrets.ELECTRON_RBE_JWT }}
|
||||
# @sentry/cli is only needed by release upload-symbols.py; skip the ~17MB CDN download on test jobs
|
||||
SENTRYCLI_SKIP_DOWNLOAD: 1
|
||||
|
||||
jobs:
|
||||
node-tests:
|
||||
@@ -67,12 +65,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@37930b1c2abaa49bbe596cd826c3c89aef350131
|
||||
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@37930b1c2abaa49bbe596cd826c3c89aef350131
|
||||
with:
|
||||
name: src_artifacts_linux_${{ env.TARGET_ARCH }}
|
||||
path: ./src_artifacts_linux_${{ env.TARGET_ARCH }}
|
||||
@@ -123,12 +121,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@37930b1c2abaa49bbe596cd826c3c89aef350131
|
||||
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@37930b1c2abaa49bbe596cd826c3c89aef350131
|
||||
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
|
||||
14
.github/workflows/pull-request-labeled.yml
vendored
14
.github/workflows/pull-request-labeled.yml
vendored
@@ -4,10 +4,6 @@ on:
|
||||
pull_request_target:
|
||||
types: [labeled]
|
||||
|
||||
# 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:
|
||||
@@ -18,7 +14,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 +38,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 +46,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 +56,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@e2ff99831a4f13625d35064e2b3dfe65c07a0396 # v3.7.5
|
||||
with:
|
||||
actions: 'create-comment'
|
||||
token: ${{ steps.generate-token.outputs.token }}
|
||||
@@ -72,7 +68,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 }}
|
||||
|
||||
@@ -1,46 +0,0 @@
|
||||
name: Pull Request Opened/Synchronized
|
||||
|
||||
on:
|
||||
pull_request_target:
|
||||
types: [opened, synchronize]
|
||||
|
||||
# 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-signed-commits:
|
||||
name: Check signed commits in PR
|
||||
runs-on: ubuntu-slim
|
||||
permissions:
|
||||
contents: read
|
||||
pull-requests: write
|
||||
steps:
|
||||
- name: Check signed commits in PR
|
||||
uses: 1Password/check-signed-commits-action@ed2885f3ed2577a4f5d3c3fe895432a557d23d52 # v1
|
||||
with:
|
||||
comment: |
|
||||
⚠️ This PR contains unsigned commits. This repository enforces [commit signatures](https://docs.github.com/en/authentication/managing-commit-signature-verification)
|
||||
for all incoming PRs. To get your PR merged, please sign those commits
|
||||
(`git rebase --exec 'git commit -S --amend --no-edit -n' @{upstream}`) and force push them to this branch
|
||||
(`git push --force-with-lease`)
|
||||
|
||||
For more information on signing commits, see GitHub's documentation on [Telling Git about your signing key](https://docs.github.com/en/authentication/managing-commit-signature-verification/telling-git-about-your-signing-key).
|
||||
|
||||
- name: Add needs-signed-commits label
|
||||
if: ${{ failure() }}
|
||||
env:
|
||||
GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}
|
||||
PR_URL: ${{ github.event.pull_request.html_url }}
|
||||
run: |
|
||||
gh pr edit $PR_URL --add-label needs-signed-commits
|
||||
|
||||
- name: Remove needs-signed-commits label
|
||||
if: ${{ success() && contains(github.event.pull_request.labels.*.name, 'needs-signed-commits') }}
|
||||
env:
|
||||
GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}
|
||||
PR_URL: ${{ github.event.pull_request.html_url }}
|
||||
run: |
|
||||
gh pr edit $PR_URL --remove-label needs-signed-commits
|
||||
4
.github/workflows/scorecards.yml
vendored
4
.github/workflows/scorecards.yml
vendored
@@ -43,7 +43,7 @@ jobs:
|
||||
# Upload the results as artifacts (optional). Commenting out will disable uploads of run results in SARIF
|
||||
# format to the repository Actions tab.
|
||||
- name: "Upload artifact"
|
||||
uses: actions/upload-artifact@bbbca2ddaa5d8feaa63e36b76fdaad77386f024f # v7.0.0
|
||||
uses: actions/upload-artifact@b7c566a772e6b6bfb58ed0dc250532a479d7789f # v6.0.0
|
||||
with:
|
||||
name: SARIF file
|
||||
path: results.sarif
|
||||
@@ -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@45cbd0c69e560cd9e7cd7f8c32362050c9b7ded2 # 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
|
||||
|
||||
4
.github/workflows/stale.yml
vendored
4
.github/workflows/stale.yml
vendored
@@ -18,7 +18,7 @@ jobs:
|
||||
id: generate-token
|
||||
with:
|
||||
creds: ${{ secrets.ISSUE_TRIAGE_GH_APP_CREDS }}
|
||||
- uses: actions/stale@b5d41d4e1d5dceea10e7104786b73624c18a190f # tag: v10.2.0
|
||||
- uses: actions/stale@997185467fa4f803885201cee163a9f38240193d # tag: v10.1.1
|
||||
with:
|
||||
repo-token: ${{ steps.generate-token.outputs.token }}
|
||||
days-before-stale: 90
|
||||
@@ -42,7 +42,7 @@ jobs:
|
||||
id: generate-token
|
||||
with:
|
||||
creds: ${{ secrets.ISSUE_TRIAGE_GH_APP_CREDS }}
|
||||
- uses: actions/stale@b5d41d4e1d5dceea10e7104786b73624c18a190f # tag: v10.2.0
|
||||
- uses: actions/stale@997185467fa4f803885201cee163a9f38240193d # tag: v10.1.1
|
||||
with:
|
||||
repo-token: ${{ steps.generate-token.outputs.token }}
|
||||
days-before-stale: -1
|
||||
|
||||
2
.github/workflows/update-website-docs.yml
vendored
2
.github/workflows/update-website-docs.yml
vendored
@@ -31,7 +31,7 @@ jobs:
|
||||
echo "isLatestRelease=false" >> $GITHUB_OUTPUT
|
||||
fi
|
||||
- name: Trigger website docs update
|
||||
if: ${{ steps.check-if-latest-release.outputs.isLatestRelease == 'true' }}
|
||||
if: ${{ steps.check-if-latest-release.outputs.isLatestRelease }}
|
||||
env:
|
||||
GH_REPO: electron/website
|
||||
GH_TOKEN: ${{ fromJSON(steps.secret-service.outputs.secrets).WEBSITE_DOCS_UPDATER_APP_TOKEN }}
|
||||
|
||||
5
.github/workflows/windows-publish.yml
vendored
5
.github/workflows/windows-publish.yml
vendored
@@ -6,7 +6,7 @@ on:
|
||||
build-image-sha:
|
||||
type: string
|
||||
description: 'SHA for electron/build image'
|
||||
default: 'eac3529546ea8f3aa356d31e345715eef342233b'
|
||||
default: 'a82b87d7a4f5ff0cab61405f8151ac4cf4942aeb'
|
||||
required: true
|
||||
upload-to-storage:
|
||||
description: 'Uploads to Azure storage'
|
||||
@@ -54,7 +54,6 @@ jobs:
|
||||
publish-x64-win:
|
||||
uses: ./.github/workflows/pipeline-segment-electron-publish.yml
|
||||
permissions:
|
||||
artifact-metadata: write
|
||||
attestations: write
|
||||
contents: read
|
||||
id-token: write
|
||||
@@ -73,7 +72,6 @@ jobs:
|
||||
publish-arm64-win:
|
||||
uses: ./.github/workflows/pipeline-segment-electron-publish.yml
|
||||
permissions:
|
||||
artifact-metadata: write
|
||||
attestations: write
|
||||
contents: read
|
||||
id-token: write
|
||||
@@ -92,7 +90,6 @@ jobs:
|
||||
publish-x86-win:
|
||||
uses: ./.github/workflows/pipeline-segment-electron-publish.yml
|
||||
permissions:
|
||||
artifact-metadata: write
|
||||
attestations: write
|
||||
contents: read
|
||||
id-token: write
|
||||
|
||||
1
.gitignore
vendored
1
.gitignore
vendored
@@ -42,7 +42,6 @@ spec/.hash
|
||||
|
||||
# Generated native addon files
|
||||
/spec/fixtures/native-addon/echo/build/
|
||||
/spec/fixtures/native-addon/dialog-helper/build/
|
||||
|
||||
# If someone runs tsc this is where stuff will end up
|
||||
ts-gen
|
||||
|
||||
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"
|
||||
}
|
||||
}
|
||||
]
|
||||
}
|
||||
6
.remarkrc
Normal file
6
.remarkrc
Normal file
@@ -0,0 +1,6 @@
|
||||
{
|
||||
"plugins": [
|
||||
["remark-lint-code-block-style", "fenced"],
|
||||
["remark-lint-fenced-code-flag"]
|
||||
]
|
||||
}
|
||||
@@ -9,8 +9,4 @@ npmMinimalAgeGate: 10080
|
||||
npmPreapprovedPackages:
|
||||
- "@electron/*"
|
||||
|
||||
httpProxy: "${HTTP_PROXY:-}"
|
||||
|
||||
httpsProxy: "${HTTPS_PROXY:-}"
|
||||
|
||||
yarnPath: .yarn/releases/yarn-4.12.0.cjs
|
||||
|
||||
24
BUILD.gn
24
BUILD.gn
@@ -618,7 +618,6 @@ source_set("electron_lib") {
|
||||
use_libcxx_modules = false
|
||||
|
||||
deps += [
|
||||
"//components/os_crypt/async/browser:keychain_key_provider",
|
||||
"//components/os_crypt/common:keychain_password_mac",
|
||||
"//components/remote_cocoa/app_shim",
|
||||
"//components/remote_cocoa/browser",
|
||||
@@ -682,9 +681,6 @@ source_set("electron_lib") {
|
||||
":libnotify_loader",
|
||||
"//build/config/linux/gtk",
|
||||
"//components/crash/content/browser",
|
||||
"//components/os_crypt/async/browser:freedesktop_secret_key_provider",
|
||||
"//components/os_crypt/async/browser:posix_key_provider",
|
||||
"//components/os_crypt/async/browser:secret_portal_key_provider",
|
||||
"//dbus",
|
||||
"//device/bluetooth",
|
||||
"//third_party/crashpad/crashpad/client",
|
||||
@@ -725,7 +721,6 @@ source_set("electron_lib") {
|
||||
deps += [
|
||||
"//components/app_launch_prefetch",
|
||||
"//components/crash/core/app:crash_export_thunks",
|
||||
"//components/os_crypt/async/browser:dpapi_key_provider",
|
||||
"//third_party/libxml:xml_writer",
|
||||
"//ui/wm",
|
||||
"//ui/wm/public",
|
||||
@@ -775,7 +770,6 @@ source_set("electron_lib") {
|
||||
"//components/zoom",
|
||||
"//extensions/browser",
|
||||
"//extensions/browser/api:api_provider",
|
||||
"//extensions/browser/mime_handler:stream_info",
|
||||
"//extensions/browser/updater",
|
||||
"//extensions/common",
|
||||
"//extensions/common:core_api_provider",
|
||||
@@ -1018,17 +1012,7 @@ if (is_mac) {
|
||||
}
|
||||
}
|
||||
|
||||
# Electron defines its own plugin helper (using CHILD_EMBEDDER_FIRST + 1) to
|
||||
# allow loading of unsigned or third-party-signed libraries.
|
||||
_electron_plugin_helper_params = [
|
||||
"plugin",
|
||||
".plugin",
|
||||
" (Plugin)",
|
||||
]
|
||||
electron_mac_helpers =
|
||||
content_mac_helpers + [ _electron_plugin_helper_params ]
|
||||
|
||||
foreach(helper_params, electron_mac_helpers) {
|
||||
foreach(helper_params, content_mac_helpers) {
|
||||
_helper_target = helper_params[0]
|
||||
_helper_bundle_id = helper_params[1]
|
||||
_helper_suffix = helper_params[2]
|
||||
@@ -1081,7 +1065,7 @@ if (is_mac) {
|
||||
":stripped_squirrel_framework",
|
||||
]
|
||||
|
||||
foreach(helper_params, electron_mac_helpers) {
|
||||
foreach(helper_params, content_mac_helpers) {
|
||||
sources +=
|
||||
[ "$root_out_dir/${electron_helper_name}${helper_params[2]}.app" ]
|
||||
public_deps += [ ":electron_helper_app_${helper_params[0]}" ]
|
||||
@@ -1185,7 +1169,7 @@ if (is_mac) {
|
||||
deps = [ ":electron_framework" ]
|
||||
}
|
||||
|
||||
foreach(helper_params, electron_mac_helpers) {
|
||||
foreach(helper_params, content_mac_helpers) {
|
||||
_helper_target = helper_params[0]
|
||||
_helper_bundle_id = helper_params[1]
|
||||
_helper_suffix = helper_params[2]
|
||||
@@ -1237,7 +1221,7 @@ if (is_mac) {
|
||||
deps += [ ":crashpad_handler_syms" ]
|
||||
}
|
||||
|
||||
foreach(helper_params, electron_mac_helpers) {
|
||||
foreach(helper_params, content_mac_helpers) {
|
||||
_helper_target = helper_params[0]
|
||||
deps += [ ":electron_helper_syms_${_helper_target}" ]
|
||||
}
|
||||
|
||||
56
CLAUDE.md
56
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.
|
||||
@@ -136,22 +127,6 @@ patches/{target}/*.patch → [e sync --3] → target repo commits
|
||||
2. Create a git commit
|
||||
3. Run `e patches <target>` to export
|
||||
|
||||
**Fixing patch conflicts on an existing PR:**
|
||||
|
||||
If asked to fix a patch conflict on a branch that already has an open PR, check the PR's failed **Apply Patches** CI run for an `update-patches` artifact before running `e sync` locally. CI has already performed the 3-way merge and exported the resolved patch diff — applying it is much faster than a full local sync.
|
||||
|
||||
```bash
|
||||
# Find the failed Apply Patches run for the PR and download the artifact
|
||||
gh run list --repo electron/electron --branch <pr-branch> --workflow "Apply Patches" --limit 1
|
||||
gh run download <run-id> --repo electron/electron --name update-patches
|
||||
|
||||
# Apply the CI-generated fix, then push
|
||||
git am update-patches.patch
|
||||
git push
|
||||
```
|
||||
|
||||
If no artifact exists (e.g. the 3-way merge itself failed), fall back to `e sync --3` and resolve manually.
|
||||
|
||||
## Testing
|
||||
|
||||
**Test location:** `spec/` directory
|
||||
@@ -180,45 +155,16 @@ e test # Run full test suite
|
||||
|
||||
When working on the `roller/chromium/main` branch to upgrade Chromium activate the "Electron Chromium 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.
|
||||
|
||||
### PR Labeling (write-access only)
|
||||
|
||||
When the user has write access to `electron/electron`, add these labels when creating PRs:
|
||||
|
||||
**Semver label** — one of:
|
||||
|
||||
- `semver/none` — build changes, refactors, CI, or anything with no end-user impact
|
||||
- `semver/patch` — backwards-compatible bug fixes
|
||||
- `semver/minor` — backwards-compatible new functionality
|
||||
- `semver/major` — incompatible API changes
|
||||
|
||||
**Backport target labels** — add `target/{N}-x-y` for each supported release branch the change should land on. Default policy:
|
||||
|
||||
- **Bug fixes** — backport to all active release lines _except the oldest_
|
||||
- **Security fixes** — backport to all active release lines _including the oldest_
|
||||
- **Features (semver/minor) and breaking changes (semver/major)** — no backport labels; main-only by default
|
||||
|
||||
To find which release branches are active, check label colors — active `target/*` labels use color `#ad244f`, older/EOL ones use `#ededed`:
|
||||
|
||||
```bash
|
||||
gh label list --repo electron/electron --search target/ --json name,color --jq '.[] | select(.color == "ad244f") | .name'
|
||||
```
|
||||
|
||||
## 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
|
||||
```
|
||||
|
||||
## Key Files
|
||||
|
||||
4
DEPS
4
DEPS
@@ -2,9 +2,9 @@ gclient_gn_args_from = 'src'
|
||||
|
||||
vars = {
|
||||
'chromium_version':
|
||||
'148.0.7778.0',
|
||||
'146.0.7650.0',
|
||||
'node_version':
|
||||
'v24.14.1',
|
||||
'v24.13.0',
|
||||
'nan_version':
|
||||
'675cefebca42410733da8a454c8d9391fcebfbc2',
|
||||
'squirrel.mac_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"]
|
||||
}
|
||||
}
|
||||
@@ -2,7 +2,7 @@ is_electron_build = true
|
||||
root_extra_deps = [ "//electron" ]
|
||||
|
||||
# Registry of NMVs --> https://github.com/nodejs/node/blob/main/doc/abi_version_registry.json
|
||||
node_module_version = 146
|
||||
node_module_version = 145
|
||||
|
||||
v8_promise_internal_field_count = 1
|
||||
v8_embedder_string = "-electron.0"
|
||||
@@ -51,6 +51,9 @@ is_cfi = false
|
||||
use_qt5 = false
|
||||
use_qt6 = false
|
||||
|
||||
# Disables the builtins PGO for V8
|
||||
v8_builtins_profiling_log_file = ""
|
||||
|
||||
# https://chromium.googlesource.com/chromium/src/+/main/docs/dangling_ptr.md
|
||||
# TODO(vertedinde): hunt down dangling pointers on Linux
|
||||
enable_dangling_raw_ptr_checks = false
|
||||
|
||||
@@ -9,6 +9,5 @@
|
||||
"embedded_asar_integrity_validation": "0",
|
||||
"only_load_app_from_asar": "0",
|
||||
"load_browser_process_specific_v8_snapshot": "0",
|
||||
"grant_file_protocol_extra_privileges": "1",
|
||||
"wasm_trap_handlers": "1"
|
||||
"grant_file_protocol_extra_privileges": "1"
|
||||
}
|
||||
|
||||
21
build/siso/backend.star
Normal file
21
build/siso/backend.star
Normal file
@@ -0,0 +1,21 @@
|
||||
# -*- bazel-starlark -*-
|
||||
|
||||
load("@builtin//struct.star", "module")
|
||||
|
||||
def __platform_properties(ctx):
|
||||
container_image = "docker://gcr.io/chops-public-images-prod/rbe/siso-chromium/linux@sha256:d7cb1ab14a0f20aa669c23f22c15a9dead761dcac19f43985bf9dd5f41fbef3a"
|
||||
return {
|
||||
"default": {
|
||||
"OSFamily": "Linux",
|
||||
"container-image": container_image,
|
||||
},
|
||||
"large": {
|
||||
"OSFamily": "Linux",
|
||||
"container-image": container_image,
|
||||
},
|
||||
}
|
||||
|
||||
backend = module(
|
||||
"backend",
|
||||
platform_properties = __platform_properties,
|
||||
)
|
||||
66
build/siso/main.star
Normal file
66
build/siso/main.star
Normal file
@@ -0,0 +1,66 @@
|
||||
load("@builtin//encoding.star", "json")
|
||||
load("@builtin//path.star", "path")
|
||||
load("@builtin//runtime.star", "runtime")
|
||||
load("@builtin//struct.star", "module")
|
||||
load("@config//main.star", upstream_init = "init")
|
||||
load("@config//win_sdk.star", "win_sdk")
|
||||
load("@config//gn_logs.star", "gn_logs")
|
||||
|
||||
def init(ctx):
|
||||
mod = upstream_init(ctx)
|
||||
step_config = json.decode(mod.step_config)
|
||||
|
||||
# Buildbarn doesn't support input_root_absolute_path so disable that
|
||||
for rule in step_config["rules"]:
|
||||
input_root_absolute_path = rule.get("input_root_absolute_path", False)
|
||||
if input_root_absolute_path:
|
||||
rule.pop("input_root_absolute_path", None)
|
||||
|
||||
# Only wrap clang rules with a remote wrapper if not on Linux. These are currently only
|
||||
# needed for X-Compile builds, which run on Windows and Mac.
|
||||
if runtime.os != "linux":
|
||||
for rule in step_config["rules"]:
|
||||
if rule["name"].startswith("clang/") or rule["name"].startswith("clang-cl/"):
|
||||
rule["remote_wrapper"] = "../../buildtools/reclient_cfgs/chromium-browser-clang/clang_remote_wrapper"
|
||||
if "inputs" not in rule:
|
||||
rule["inputs"] = []
|
||||
rule["inputs"].append("buildtools/reclient_cfgs/chromium-browser-clang/clang_remote_wrapper")
|
||||
rule["inputs"].append("third_party/llvm-build/Release+Asserts_linux/bin/clang")
|
||||
|
||||
if "executables" not in step_config:
|
||||
step_config["executables"] = []
|
||||
step_config["executables"].append("buildtools/reclient_cfgs/chromium-browser-clang/clang_remote_wrapper")
|
||||
step_config["executables"].append("third_party/llvm-build/Release+Asserts_linux/bin/clang")
|
||||
|
||||
if runtime.os == "darwin":
|
||||
# Update platforms to match our default siso config instead of reclient configs.
|
||||
step_config["platforms"].update({
|
||||
"clang": step_config["platforms"]["default"],
|
||||
"clang_large": step_config["platforms"]["default"],
|
||||
})
|
||||
|
||||
if runtime.os == "windows":
|
||||
# Add additional Windows SDK headers needed by Electron
|
||||
win_toolchain_dir = win_sdk.toolchain_dir(ctx)
|
||||
if win_toolchain_dir:
|
||||
sdk_version = gn_logs.read(ctx).get("windows_sdk_version")
|
||||
step_config["input_deps"][win_toolchain_dir + ":headers"].extend([
|
||||
# third_party/electron_node/deps/uv/include/uv/win.h includes mswsock.h
|
||||
path.join(win_toolchain_dir, "Windows Kits/10/Include", sdk_version, "um/mswsock.h"),
|
||||
# third_party/electron_node/src/debug_utils.cc includes lm.h
|
||||
path.join(win_toolchain_dir, "Windows Kits/10/Include", sdk_version, "um/Lm.h"),
|
||||
])
|
||||
|
||||
# Update platforms to match our default siso config instead of reclient configs.
|
||||
step_config["platforms"].update({
|
||||
"clang-cl": step_config["platforms"]["default"],
|
||||
"clang-cl_large": step_config["platforms"]["default"],
|
||||
"lld-link": step_config["platforms"]["default"],
|
||||
})
|
||||
|
||||
return module(
|
||||
"config",
|
||||
step_config = json.encode(step_config),
|
||||
filegroups = mod.filegroups,
|
||||
handlers = mod.handlers,
|
||||
)
|
||||
@@ -122,8 +122,8 @@ if ((globalThis.process || binding.process).argv.includes("--profile-electron-in
|
||||
'electron/renderer$': electronAPIFile,
|
||||
'electron/common$': electronAPIFile,
|
||||
'electron/utility$': electronAPIFile,
|
||||
// Force timers to resolve to our own shim that doesn't use window.postMessage
|
||||
timers: path.resolve(electronRoot, 'lib', 'common', 'timers-shim.ts')
|
||||
// Force timers to resolve to our dependency that doesn't use window.postMessage
|
||||
timers: path.resolve(electronRoot, 'node_modules', 'timers-browserify', 'main.js')
|
||||
},
|
||||
extensions: ['.ts', '.js'],
|
||||
fallback: {
|
||||
|
||||
@@ -144,8 +144,6 @@ static_library("chrome") {
|
||||
"//chrome/browser/ui/views/overlay/toggle_camera_button.h",
|
||||
"//chrome/browser/ui/views/overlay/toggle_microphone_button.cc",
|
||||
"//chrome/browser/ui/views/overlay/toggle_microphone_button.h",
|
||||
"//chrome/browser/ui/views/overlay/toggle_mute_button.cc",
|
||||
"//chrome/browser/ui/views/overlay/toggle_mute_button.h",
|
||||
"//chrome/browser/ui/views/overlay/video_overlay_window_views.cc",
|
||||
"//chrome/browser/ui/views/overlay/video_overlay_window_views.h",
|
||||
"//chrome/browser/ui/views/picture_in_picture/picture_in_picture_bounds_change_animation.cc",
|
||||
@@ -205,7 +203,7 @@ static_library("chrome") {
|
||||
|
||||
deps = [
|
||||
"//chrome/app/vector_icons",
|
||||
"//chrome/browser/predictors:resource_prefetch_predictor_proto",
|
||||
"//chrome/browser:resource_prefetch_predictor_proto",
|
||||
"//chrome/browser/resource_coordinator:mojo_bindings",
|
||||
"//chrome/browser/task_manager/common:impl",
|
||||
"//chrome/browser/ui/webui/tab_search:mojo_bindings",
|
||||
@@ -247,10 +245,6 @@ static_library("chrome") {
|
||||
"//chrome/browser/ui/views/dark_mode_manager_linux.cc",
|
||||
"//chrome/browser/ui/views/dark_mode_manager_linux.h",
|
||||
]
|
||||
sources += [
|
||||
"//chrome/browser/ui/views/frame/browser_frame_view_paint_utils_linux.cc",
|
||||
"//chrome/browser/ui/views/frame/browser_frame_view_paint_utils_linux.h",
|
||||
]
|
||||
public_deps += [ "//components/dbus" ]
|
||||
}
|
||||
|
||||
|
||||
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"]
|
||||
}
|
||||
}
|
||||
@@ -11,6 +11,13 @@ app.on('window-all-closed', () => {
|
||||
app.quit();
|
||||
});
|
||||
|
||||
function decorateURL (url: string) {
|
||||
// safely add `?utm_source=default_app
|
||||
const parsedUrl = new URL(url);
|
||||
parsedUrl.searchParams.append('utm_source', 'default_app');
|
||||
return parsedUrl.toString();
|
||||
}
|
||||
|
||||
// Find the shortest path to the electron binary
|
||||
const absoluteElectronPath = process.execPath;
|
||||
const relativeElectronPath = path.relative(process.cwd(), absoluteElectronPath);
|
||||
@@ -62,7 +69,7 @@ async function createWindow (backgroundColor?: string) {
|
||||
mainWindow.on('ready-to-show', () => mainWindow!.show());
|
||||
|
||||
mainWindow.webContents.setWindowOpenHandler(details => {
|
||||
shell.openExternal(details.url);
|
||||
shell.openExternal(decorateURL(details.url));
|
||||
return { action: 'deny' };
|
||||
});
|
||||
|
||||
|
||||
@@ -111,10 +111,7 @@ async function loadApplicationPackage (packagePath: string) {
|
||||
app.name = packageJson.name;
|
||||
}
|
||||
|
||||
// Set application's desktop name (Linux). These usually match the executable name,
|
||||
// so use it as the default to ensure the app gets the correct icon in the taskbar and application switcher.
|
||||
const desktopName = packageJson.desktopName || `${path.basename(process.execPath)}.desktop`;
|
||||
app.setDesktopName(desktopName);
|
||||
app.setDesktopName(packageJson.desktopName || `${app.name}.desktop`);
|
||||
|
||||
// Set v8 flags, deliberately lazy load so that apps that do not use this
|
||||
// feature do not pay the price
|
||||
@@ -256,7 +253,7 @@ async function startRepl () {
|
||||
if (option.file && !option.webdriver) {
|
||||
const file = option.file;
|
||||
// eslint-disable-next-line n/no-deprecated-api
|
||||
const protocol = URL.canParse(file) ? new URL(file).protocol : null;
|
||||
const protocol = url.parse(file).protocol;
|
||||
const extension = path.extname(file);
|
||||
if (protocol === 'http:' || protocol === 'https:' || protocol === 'file:' || protocol === 'chrome:') {
|
||||
await loadApplicationByURL(file);
|
||||
|
||||
@@ -41,7 +41,7 @@ h4 {
|
||||
transform-origin: 50% 50%;
|
||||
}
|
||||
|
||||
.hero-icon.loop-3 {
|
||||
hero-icon.loop-3 {
|
||||
transform: translate(79px, 21px);
|
||||
opacity: 1;
|
||||
}
|
||||
|
||||
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"]
|
||||
}
|
||||
}
|
||||
@@ -1,58 +0,0 @@
|
||||
# Electron Documentation Guide
|
||||
|
||||
## API History Migration
|
||||
|
||||
Guide: `docs/development/api-history-migration-guide.md`
|
||||
Style rules: `docs/development/style-guide.md` (see "API History" section)
|
||||
Schema: `docs/api-history.schema.json`
|
||||
Lint: `npm run lint:api-history`
|
||||
|
||||
### Format
|
||||
|
||||
Place YAML history block directly after the Markdown header, before parameters:
|
||||
|
||||
````md
|
||||
### `module.method(args)`
|
||||
|
||||
<!--
|
||||
```YAML history
|
||||
added:
|
||||
- pr-url: https://github.com/electron/electron/pull/XXXXX
|
||||
```
|
||||
-->
|
||||
|
||||
* `arg` type - Description.
|
||||
````
|
||||
|
||||
### Finding when an API was added
|
||||
|
||||
- `git log --all --reverse --oneline -S "methodName" -- docs/api/file.md` — find first commit adding a method name
|
||||
- `git log --reverse -L :FunctionName:path/to/source.cc` — trace C++ implementation history
|
||||
- `git log --grep="keyword" --oneline` — find merge commits referencing PRs
|
||||
- `gh pr view <number> --repo electron/electron --json baseRefName` — verify PR targets main (not a backport)
|
||||
- Always use the main-branch PR URL in history blocks, not backport PRs
|
||||
|
||||
### Cross-referencing breaking changes
|
||||
|
||||
- Search `docs/breaking-changes.md` for the API name to find deprecations/removals
|
||||
- Use `git blame` on the breaking-changes entry to find the associated PR
|
||||
- Add `breaking-changes-header` field using the heading ID from breaking-changes.md
|
||||
|
||||
### Placement rules
|
||||
|
||||
- Only add blocks to actual API entries (methods, events, properties with backtick signatures)
|
||||
- Do NOT add blocks to section headers like `## Methods`, `### Instance Methods`, `## Events`
|
||||
- Module-level blocks go after the `# moduleName` heading, before the module description quote
|
||||
- For changes affecting multiple APIs, add a block under each affected top-level heading (see style guide "Change affecting multiple APIs")
|
||||
|
||||
### Key details
|
||||
|
||||
- `added` and `deprecated` arrays have `maxItems: 1`; `changes` can have multiple items
|
||||
- `changes` entries require a `description` field; `added`/`deprecated` do not
|
||||
- Wrap descriptions in double quotes to avoid YAML parsing issues with special characters
|
||||
- Early Electron APIs (pre-2015) use merge-commit PRs (e.g., `Merge pull request #534`)
|
||||
- Very early APIs (2013-2014, e.g., `ipcMain.on`, `ipcRenderer.send`) predate GitHub PRs — skip history blocks for these
|
||||
- When multiple APIs were added in the same PR, they all reference the same PR URL
|
||||
- Promisification PRs (e.g., #17355) count as `changes` entries with a description
|
||||
- These PRs are breaking changes and should have their notes as "This method now returns a Promise instead of using a callback function."
|
||||
- APIs that were deprecated and then removed from docs don't need history blocks (the removal is in `breaking-changes.md`)
|
||||
@@ -250,9 +250,7 @@ Returns:
|
||||
|
||||
Emitted when the user clicks the native macOS new tab button. The new
|
||||
tab button is only visible if the current `BrowserWindow` has a
|
||||
`tabbingIdentifier`.
|
||||
|
||||
You must create a window in this handler in order for macOS tabbing to work as expected.
|
||||
`tabbingIdentifier`
|
||||
|
||||
### Event: 'browser-window-blur'
|
||||
|
||||
@@ -573,10 +571,6 @@ focus but may instead show a notification or flash the app icon (Wayland).
|
||||
|
||||
You should seek to use the `steal` option as sparingly as possible.
|
||||
|
||||
### `app.isActive()` _macOS_
|
||||
|
||||
Returns `boolean` - `true` if the application is active (i.e. focused).
|
||||
|
||||
### `app.hide()` _macOS_
|
||||
|
||||
Hides all application windows without minimizing them.
|
||||
@@ -615,11 +609,7 @@ Returns `string` - The current application directory.
|
||||
by default is the `appData` directory appended with your app's name. By
|
||||
convention files storing user data should be written to this directory, and
|
||||
it is not recommended to write large files here because some environments
|
||||
may backup this directory to cloud storage. It is recommended to store
|
||||
app-specific files within a subdirectory of `userData` (e.g.,
|
||||
`path.join(app.getPath('userData'), 'my-app-data')`) rather than directly
|
||||
in `userData` itself, to avoid naming conflicts with Chromium's own
|
||||
subdirectories (such as `Cache`, `GPUCache`, and `Local Storage`).
|
||||
may backup this directory to cloud storage.
|
||||
* `sessionData` The directory for storing data generated by `Session`, such
|
||||
as localStorage, cookies, disk cache, downloaded dictionaries, network
|
||||
state, DevTools files. By default this points to `userData`. Chromium may
|
||||
@@ -643,7 +633,7 @@ Returns `string` - The current application directory.
|
||||
Returns `string` - A path to a special directory or file associated with `name`. On
|
||||
failure, an `Error` is thrown.
|
||||
|
||||
If `app.getPath('logs')` is called without calling `app.setAppLogsPath()` being called first, a default log directory will be created equivalent to calling `app.setAppLogsPath()` without a `path` parameter.
|
||||
If `app.getPath('logs')` is called without called `app.setAppLogsPath()` being called first, a default log directory will be created equivalent to calling `app.setAppLogsPath()` without a `path` parameter.
|
||||
|
||||
### `app.getFileIcon(path[, options])`
|
||||
|
||||
@@ -658,7 +648,7 @@ Returns `Promise<NativeImage>` - fulfilled with the app's icon, which is a [Nati
|
||||
|
||||
Fetches a path's associated icon.
|
||||
|
||||
On _Windows_, there are 2 kinds of icons:
|
||||
On _Windows_, there a 2 kinds of icons:
|
||||
|
||||
* Icons associated with certain file extensions, like `.mp3`, `.png`, etc.
|
||||
* Icons inside the file itself, like `.exe`, `.dll`, `.ico`.
|
||||
@@ -774,7 +764,7 @@ app.getPreferredSystemLanguages() // ['fr-CA', 'en-US', 'zh-Hans-FI', 'es-419']
|
||||
|
||||
Both the available languages and regions and the possible return values differ between the two operating systems.
|
||||
|
||||
As can be seen with the example above, on Windows, it is possible that a preferred system language has no country code, and that one of the preferred system languages corresponds with the language used for the regional format. On macOS, the region serves more as a default country code: the user doesn't need to have Finnish as a preferred language to use Finland as the region, and the country code `FI` is used as the country code for preferred system languages that do not have associated countries in the language name.
|
||||
As can be seen with the example above, on Windows, it is possible that a preferred system language has no country code, and that one of the preferred system languages corresponds with the language used for the regional format. On macOS, the region serves more as a default country code: the user doesn't need to have Finnish as a preferred language to use Finland as the region,and the country code `FI` is used as the country code for preferred system languages that do not have associated countries in the language name.
|
||||
|
||||
### `app.addRecentDocument(path)` _macOS_ _Windows_
|
||||
|
||||
@@ -1132,19 +1122,6 @@ Updates the current activity if its type matches `type`, merging the entries fro
|
||||
|
||||
Changes the [Application User Model ID][app-user-model-id] to `id`.
|
||||
|
||||
### `app.setToastActivatorCLSID(id)` _Windows_
|
||||
|
||||
* `id` string
|
||||
|
||||
Changes the [Toast Activator CLSID][toast-activator-clsid] to `id`. If one is not set via this method, it will be randomly generated for the app.
|
||||
|
||||
* The value must be a valid GUID/CLSID in one of the following forms:
|
||||
* Canonical brace-wrapped: `{XXXXXXXX-XXXX-XXXX-XXXX-XXXXXXXXXXXX}` (preferred)
|
||||
* Canonical without braces: `XXXXXXXX-XXXX-XXXX-XXXX-XXXXXXXXXXXX` (braces will be added automatically)
|
||||
* Hex digits are case-insensitive.
|
||||
|
||||
This method should be called early (before showing notifications) so the value is baked into the registration/shortcut. Supplying an empty string or an unparsable value throws and leaves the existing (or generated) CLSID unchanged. If this method is never called, a random CLSID is generated once per run and exposed via `app.toastActivatorCLSID`.
|
||||
|
||||
### `app.setActivationPolicy(policy)` _macOS_
|
||||
|
||||
* `policy` string - Can be 'regular', 'accessory', or 'prohibited'.
|
||||
@@ -1249,7 +1226,7 @@ Returns `boolean` - whether hardware acceleration is currently enabled.
|
||||
### `app.disableDomainBlockingFor3DAPIs()`
|
||||
|
||||
By default, Chromium disables 3D APIs (e.g. WebGL) until restart on a per
|
||||
domain basis if the GPU process crashes too frequently. This function
|
||||
domain basis if the GPU processes crashes too frequently. This function
|
||||
disables that behavior.
|
||||
|
||||
This method can only be called before app is ready.
|
||||
@@ -1340,7 +1317,7 @@ Returns `boolean` - Whether the current desktop environment is Unity launcher.
|
||||
### `app.getLoginItemSettings([options])` _macOS_ _Windows_
|
||||
|
||||
* `options` Object (optional)
|
||||
* `type` string (optional) _macOS_ - Can be `mainAppService`, `agentService`, `daemonService`, or `loginItemService`. Defaults to `mainAppService`. Only available on macOS 13 and up. See [app.setLoginItemSettings](app.md#appsetloginitemsettingssettings-macos-windows) for more information about each type.
|
||||
* `type` string (optional) _macOS_ - Can be one of `mainAppService`, `agentService`, `daemonService`, or `loginItemService`. Defaults to `mainAppService`. Only available on macOS 13 and up. See [app.setLoginItemSettings](app.md#appsetloginitemsettingssettings-macos-windows) for more information about each type.
|
||||
* `serviceName` string (optional) _macOS_ - The name of the service. Required if `type` is non-default. Only available on macOS 13 and up.
|
||||
* `path` string (optional) _Windows_ - The executable path to compare against. Defaults to `process.execPath`.
|
||||
* `args` string[] (optional) _Windows_ - The command-line arguments to compare against. Defaults to an empty array.
|
||||
@@ -1355,13 +1332,13 @@ Returns `Object`:
|
||||
* `wasOpenedAtLogin` boolean _macOS_ - `true` if the app was opened at login automatically.
|
||||
* `wasOpenedAsHidden` boolean _macOS_ _Deprecated_ - `true` if the app was opened as a hidden login item. This indicates that the app should not open any windows at startup. This setting is not available on [MAS builds][mas-builds] or on macOS 13 and up.
|
||||
* `restoreState` boolean _macOS_ _Deprecated_ - `true` if the app was opened as a login item that should restore the state from the previous session. This indicates that the app should restore the windows that were open the last time the app was closed. This setting is not available on [MAS builds][mas-builds] or on macOS 13 and up.
|
||||
* `status` string _macOS_ - can be `not-registered`, `enabled`, `requires-approval`, or `not-found`.
|
||||
* `status` string _macOS_ - can be one of `not-registered`, `enabled`, `requires-approval`, or `not-found`.
|
||||
* `executableWillLaunchAtLogin` boolean _Windows_ - `true` if app is set to open at login and its run key is not deactivated. This differs from `openAtLogin` as it ignores the `args` option, this property will be true if the given executable would be launched at login with **any** arguments.
|
||||
* `launchItems` Object[] _Windows_
|
||||
* `name` string _Windows_ - name value of a registry entry.
|
||||
* `path` string _Windows_ - The executable to an app that corresponds to a registry entry.
|
||||
* `args` string[] _Windows_ - the command-line arguments to pass to the executable.
|
||||
* `scope` string _Windows_ - can be `user` or `machine`. Indicates whether the registry entry is under `HKEY_CURRENT USER` or `HKEY_LOCAL_MACHINE`.
|
||||
* `scope` string _Windows_ - one of `user` or `machine`. Indicates whether the registry entry is under `HKEY_CURRENT USER` or `HKEY_LOCAL_MACHINE`.
|
||||
* `enabled` boolean _Windows_ - `true` if the app registry key is startup approved and therefore shows as `enabled` in Task Manager and Windows settings.
|
||||
|
||||
### `app.setLoginItemSettings(settings)` _macOS_ _Windows_
|
||||
@@ -1727,13 +1704,8 @@ platforms) that allows you to perform actions on your app icon in the user's doc
|
||||
|
||||
A `boolean` property that returns `true` if the app is packaged, `false` otherwise. For many apps, this property can be used to distinguish development and production environments.
|
||||
|
||||
### `app.toastActivatorCLSID` _Windows_ _Readonly_
|
||||
|
||||
A `string` property that returns the app's [Toast Activator CLSID][toast-activator-clsid].
|
||||
|
||||
[tasks]:https://learn.microsoft.com/en-us/windows/win32/shell/taskbar-extensions#tasks
|
||||
[app-user-model-id]: https://learn.microsoft.com/en-us/windows/win32/shell/appids
|
||||
[toast-activator-clsid]: https://learn.microsoft.com/en-us/windows/win32/properties/props-system-appusermodel-toastactivatorclsid
|
||||
[electron-forge]: https://www.electronforge.io/
|
||||
[electron-packager]: https://github.com/electron/packager
|
||||
[CFBundleURLTypes]: https://developer.apple.com/library/ios/documentation/General/Reference/InfoPlistKeyReference/Articles/CoreFoundationKeys.html#//apple_ref/doc/uid/TP40009249-102207-TPXREF115
|
||||
|
||||
@@ -351,11 +351,7 @@ Emitted when the window has closed a sheet.
|
||||
|
||||
#### Event: 'new-window-for-tab' _macOS_
|
||||
|
||||
Emitted when the user clicks the native macOS new tab button. The new
|
||||
tab button is only visible if the current `BrowserWindow` has a
|
||||
`tabbingIdentifier`.
|
||||
|
||||
You must create a window in this handler in order for macOS tabbing to work as expected.
|
||||
Emitted when the native new tab button is clicked.
|
||||
|
||||
#### Event: 'system-context-menu' _Windows_ _Linux_
|
||||
|
||||
@@ -1053,7 +1049,7 @@ under this mode apps can choose to optimize their UI for tablets, such as
|
||||
enlarging the titlebar and hiding titlebar buttons.
|
||||
|
||||
This API returns whether the window is in tablet mode, and the `resize` event
|
||||
can be used to listen to changes to tablet mode.
|
||||
can be be used to listen to changes to tablet mode.
|
||||
|
||||
#### `win.getMediaSourceId()`
|
||||
|
||||
|
||||
@@ -435,11 +435,7 @@ Emitted when the window has closed a sheet.
|
||||
|
||||
#### Event: 'new-window-for-tab' _macOS_
|
||||
|
||||
Emitted when the user clicks the native macOS new tab button. The new
|
||||
tab button is only visible if the current `BrowserWindow` has a
|
||||
`tabbingIdentifier`.
|
||||
|
||||
You must create a window in this handler in order for macOS tabbing to work as expected.
|
||||
Emitted when the native new tab button is clicked.
|
||||
|
||||
#### Event: 'system-context-menu' _Windows_ _Linux_
|
||||
|
||||
@@ -1169,7 +1165,7 @@ under this mode apps can choose to optimize their UI for tablets, such as
|
||||
enlarging the titlebar and hiding titlebar buttons.
|
||||
|
||||
This API returns whether the window is in tablet mode, and the `resize` event
|
||||
can be used to listen to changes to tablet mode.
|
||||
can be be used to listen to changes to tablet mode.
|
||||
|
||||
#### `win.getMediaSourceId()`
|
||||
|
||||
|
||||
@@ -264,7 +264,7 @@ will not be allowed. The `finish` event is emitted just after the end operation.
|
||||
Cancels an ongoing HTTP transaction. If the request has already emitted the
|
||||
`close` event, the abort operation will have no effect. Otherwise an ongoing
|
||||
event will emit `abort` and `close` events. Additionally, if there is an ongoing
|
||||
response object, it will emit the `aborted` event.
|
||||
response object,it will emit the `aborted` event.
|
||||
|
||||
#### `request.followRedirect()`
|
||||
|
||||
|
||||
@@ -1,20 +1,11 @@
|
||||
# clipboard
|
||||
|
||||
<!--
|
||||
```YAML history
|
||||
deprecated:
|
||||
- pr-url: https://github.com/electron/electron/pull/48877
|
||||
description: "Using the `clipboard` API directly in the renderer process is deprecated."
|
||||
breaking-changes-header: deprecated-clipboard-api-access-from-renderer-processes
|
||||
```
|
||||
-->
|
||||
|
||||
> Perform copy and paste operations on the system clipboard.
|
||||
|
||||
Process: [Main](../glossary.md#main-process), [Renderer](../glossary.md#renderer-process) _Deprecated_ (non-sandboxed only)
|
||||
|
||||
> [!NOTE]
|
||||
> Using the `clipboard` API from the renderer process is deprecated.
|
||||
> Using the `clipoard` API from the renderer process is deprecated.
|
||||
|
||||
> [!IMPORTANT]
|
||||
> If you want to call this API from a renderer process,
|
||||
|
||||
@@ -172,7 +172,7 @@ Enables net log events to be saved and writes them to `path`.
|
||||
Sets the verbosity of logging when used together with `--enable-logging`.
|
||||
`N` should be one of [Chrome's LogSeverities][severities].
|
||||
|
||||
Note that two complementary logging mechanisms in Chromium -- `LOG()`
|
||||
Note that two complimentary logging mechanisms in Chromium -- `LOG()`
|
||||
and `VLOG()` -- are controlled by different switches. `--log-level`
|
||||
controls `LOG()` messages, while `--v` and `--vmodule` control `VLOG()`
|
||||
messages. So you may want to use a combination of these three switches
|
||||
@@ -354,11 +354,6 @@ Affects the default output directory of [v8.setHeapSnapshotNearHeapLimit](https:
|
||||
|
||||
Disable exposition of [Navigator API][] on the global scope from Node.js.
|
||||
|
||||
### `--experimental-transform-types`
|
||||
|
||||
Enables the [transformation](https://nodejs.org/api/typescript.html#type-stripping)
|
||||
of TypeScript-only syntax into JavaScript code.
|
||||
|
||||
## Chromium Flags
|
||||
|
||||
There isn't a documented list of all Chromium switches, but there are a few ways to find them.
|
||||
@@ -375,13 +370,6 @@ Keep in mind that standalone switches can sometimes be split into individual fea
|
||||
|
||||
Finally, you'll need to ensure that the version of Chromium in Electron matches the version of the browser you're using to cross-reference the switches.
|
||||
|
||||
### Chromium features relevant to Electron apps
|
||||
|
||||
* `AlwaysLogLOAFURL`: enables script attribution for
|
||||
[`long-animation-frame`](https://developer.mozilla.org/en-US/docs/Web/API/Performance_API/Long_animation_frame_timing)
|
||||
`PerformanceObserver` events for non-http(s), non-data, non-blob URLs (such as `file:` or custom
|
||||
protocol URLs).
|
||||
|
||||
[app]: app.md
|
||||
[append-switch]: command-line.md#commandlineappendswitchswitch-value
|
||||
[debugging-main-process]: ../tutorial/debugging-main-process.md
|
||||
|
||||
@@ -33,15 +33,6 @@ The `contentTracing` module has the following methods:
|
||||
|
||||
### `contentTracing.getCategories()`
|
||||
|
||||
<!--
|
||||
```YAML history
|
||||
changes:
|
||||
- pr-url: https://github.com/electron/electron/pull/16583
|
||||
description: "This method now returns a Promise instead of using a callback function."
|
||||
breaking-changes-header: api-changed-callback-based-versions-of-promisified-apis
|
||||
```
|
||||
-->
|
||||
|
||||
Returns `Promise<string[]>` - resolves with an array of category groups once all child processes have acknowledged the `getCategories` request
|
||||
|
||||
Get a set of category groups. The category groups can change as new code paths
|
||||
@@ -53,17 +44,6 @@ are reached. See also the
|
||||
|
||||
### `contentTracing.startRecording(options)`
|
||||
|
||||
<!--
|
||||
```YAML history
|
||||
changes:
|
||||
- pr-url: https://github.com/electron/electron/pull/13914
|
||||
description: "The `options` parameter now accepts `TraceConfig` in addition to `TraceCategoriesAndOptions`."
|
||||
- pr-url: https://github.com/electron/electron/pull/16584
|
||||
description: "This function now returns a callback`Promise<void>`."
|
||||
breaking-changes-header: api-changed-callback-based-versions-of-promisified-apis
|
||||
```
|
||||
-->
|
||||
|
||||
* `options` ([TraceConfig](structures/trace-config.md) | [TraceCategoriesAndOptions](structures/trace-categories-and-options.md))
|
||||
|
||||
Returns `Promise<void>` - resolved once all child processes have acknowledged the `startRecording` request.
|
||||
@@ -78,17 +58,6 @@ only one trace operation can be in progress at a time.
|
||||
|
||||
### `contentTracing.stopRecording([resultFilePath])`
|
||||
|
||||
<!--
|
||||
```YAML history
|
||||
changes:
|
||||
- pr-url: https://github.com/electron/electron/pull/16584
|
||||
description: "This method now returns a Promise instead of using a callback function."
|
||||
breaking-changes-header: api-changed-callback-based-versions-of-promisified-apis
|
||||
- pr-url: https://github.com/electron/electron/pull/18411
|
||||
description: "The `resultFilePath` parameter is now optional."
|
||||
```
|
||||
-->
|
||||
|
||||
* `resultFilePath` string (optional)
|
||||
|
||||
Returns `Promise<string>` - resolves with a path to a file that contains the traced data once all child processes have acknowledged the `stopRecording` request
|
||||
@@ -107,15 +76,6 @@ will be returned in the promise.
|
||||
|
||||
### `contentTracing.getTraceBufferUsage()`
|
||||
|
||||
<!--
|
||||
```YAML history
|
||||
changes:
|
||||
- pr-url: https://github.com/electron/electron/pull/16600
|
||||
description: "This method now returns a Promise instead of using a callback function."
|
||||
breaking-changes-header: api-changed-callback-based-versions-of-promisified-apis
|
||||
```
|
||||
-->
|
||||
|
||||
Returns `Promise<Object>` - Resolves with an object containing the `value` and `percentage` of trace buffer maximum usage
|
||||
|
||||
* `value` number
|
||||
|
||||
@@ -107,7 +107,7 @@ the response.
|
||||
cookie and will not be retained between sessions.
|
||||
* `sameSite` string (optional) - The [Same Site](https://developer.mozilla.org/en-US/docs/Web/HTTP/Cookies#SameSite_cookies) policy to apply to this cookie. Can be `unspecified`, `no_restriction`, `lax` or `strict`. Default is `lax`.
|
||||
|
||||
Returns `Promise<void>` - A promise which resolves when the cookie has been set.
|
||||
Returns `Promise<void>` - A promise which resolves when the cookie has been set
|
||||
|
||||
Sets a cookie with `details`.
|
||||
|
||||
@@ -116,16 +116,16 @@ Sets a cookie with `details`.
|
||||
* `url` string - The URL associated with the cookie.
|
||||
* `name` string - The name of cookie to remove.
|
||||
|
||||
Returns `Promise<void>` - A promise which resolves when the cookie has been removed.
|
||||
Returns `Promise<void>` - A promise which resolves when the cookie has been removed
|
||||
|
||||
Removes the cookies matching `url` and `name`.
|
||||
Removes the cookies matching `url` and `name`
|
||||
|
||||
#### `cookies.flushStore()`
|
||||
|
||||
Returns `Promise<void>` - A promise which resolves when the cookie store has been flushed.
|
||||
Returns `Promise<void>` - A promise which resolves when the cookie store has been flushed
|
||||
|
||||
Writes any unwritten cookies data to disk.
|
||||
Writes any unwritten cookies data to disk
|
||||
|
||||
Cookies written by any method will not be written to disk immediately, but will be written every 30 seconds or 512 operations.
|
||||
Cookies written by any method will not be written to disk immediately, but will be written every 30 seconds or 512 operations
|
||||
|
||||
Calling this method can cause the cookie to be written to disk immediately.
|
||||
|
||||
@@ -49,7 +49,7 @@ Use the `system-ui` keyword to match the smoothness to the OS design language.
|
||||
| Value: | `60%` | `0%` |
|
||||
| Example: |  |  |
|
||||
|
||||
### Controlling availability
|
||||
### Controlling availibility
|
||||
|
||||
This CSS rule can be disabled using the Blink feature flag `ElectronCSSCornerSmoothing`.
|
||||
|
||||
|
||||
@@ -50,22 +50,6 @@ The `crashReporter` module has the following methods:
|
||||
|
||||
### `crashReporter.start(options)`
|
||||
|
||||
<!--
|
||||
```YAML history
|
||||
changes:
|
||||
- pr-url: https://github.com/electron/electron/pull/23062
|
||||
description: "Added `rateLimit` and `compress` options."
|
||||
- pr-url: https://github.com/electron/electron/pull/23265
|
||||
description: "Deprecated calling this method in the renderer process."
|
||||
breaking-changes-header: deprecated-crashreporter-methods-in-the-renderer-process
|
||||
- pr-url: https://github.com/electron/electron/pull/25288
|
||||
description: "Default value of `compress` option changed from `false` to `true`."
|
||||
breaking-changes-header: default-changed-crashreporterstart-compress-true-
|
||||
- pr-url: https://github.com/electron/electron/pull/28105
|
||||
description: "The `submitURL` parameter is now optional when `uploadToServer` is `false`."
|
||||
```
|
||||
-->
|
||||
|
||||
* `options` Object
|
||||
* `submitURL` string (optional) - URL that crash reports will be sent to as
|
||||
POST. Required unless `uploadToServer` is `false`.
|
||||
@@ -127,15 +111,6 @@ by the crash reporter.
|
||||
|
||||
### `crashReporter.getLastCrashReport()`
|
||||
|
||||
<!--
|
||||
```YAML history
|
||||
changes:
|
||||
- pr-url: https://github.com/electron/electron/pull/23265
|
||||
description: "Deprecated calling this method in the renderer process."
|
||||
breaking-changes-header: deprecated-crashreporter-methods-in-the-renderer-process
|
||||
```
|
||||
-->
|
||||
|
||||
Returns [`CrashReport | null`](structures/crash-report.md) - The date and ID of the
|
||||
last crash report. Only crash reports that have been uploaded will be returned;
|
||||
even if a crash report is present on disk it will not be returned until it is
|
||||
@@ -146,15 +121,6 @@ uploaded. In the case that there are no uploaded reports, `null` is returned.
|
||||
|
||||
### `crashReporter.getUploadedReports()`
|
||||
|
||||
<!--
|
||||
```YAML history
|
||||
changes:
|
||||
- pr-url: https://github.com/electron/electron/pull/23265
|
||||
description: "Deprecated calling this method in the renderer process."
|
||||
breaking-changes-header: deprecated-crashreporter-methods-in-the-renderer-process
|
||||
```
|
||||
-->
|
||||
|
||||
Returns [`CrashReport[]`](structures/crash-report.md):
|
||||
|
||||
Returns all uploaded crash reports. Each report contains the date and uploaded
|
||||
@@ -165,15 +131,6 @@ ID.
|
||||
|
||||
### `crashReporter.getUploadToServer()`
|
||||
|
||||
<!--
|
||||
```YAML history
|
||||
changes:
|
||||
- pr-url: https://github.com/electron/electron/pull/23265
|
||||
description: "Deprecated calling this method in the renderer process."
|
||||
breaking-changes-header: deprecated-crashreporter-methods-in-the-renderer-process
|
||||
```
|
||||
-->
|
||||
|
||||
Returns `boolean` - Whether reports should be submitted to the server. Set through
|
||||
the `start` method or `setUploadToServer`.
|
||||
|
||||
@@ -182,15 +139,6 @@ the `start` method or `setUploadToServer`.
|
||||
|
||||
### `crashReporter.setUploadToServer(uploadToServer)`
|
||||
|
||||
<!--
|
||||
```YAML history
|
||||
changes:
|
||||
- pr-url: https://github.com/electron/electron/pull/23265
|
||||
description: "Deprecated calling this method in the renderer process."
|
||||
breaking-changes-header: deprecated-crashreporter-methods-in-the-renderer-process
|
||||
```
|
||||
-->
|
||||
|
||||
* `uploadToServer` boolean - Whether reports should be submitted to the server.
|
||||
|
||||
This would normally be controlled by user preferences. This has no effect if
|
||||
|
||||
@@ -80,17 +80,6 @@ The `desktopCapturer` module has the following methods:
|
||||
|
||||
### `desktopCapturer.getSources(options)`
|
||||
|
||||
<!--
|
||||
```YAML history
|
||||
added:
|
||||
- pr-url: https://github.com/electron/electron/pull/2963
|
||||
changes:
|
||||
- pr-url: https://github.com/electron/electron/pull/16427
|
||||
description: "This method now returns a Promise instead of using a callback function."
|
||||
breaking-changes-header: api-changed-callback-based-versions-of-promisified-apis
|
||||
```
|
||||
-->
|
||||
|
||||
* `options` Object
|
||||
* `types` string[] - An array of strings that lists the types of desktop sources
|
||||
to be captured, available types can be `screen` and `window`.
|
||||
@@ -105,7 +94,7 @@ changes:
|
||||
Returns `Promise<DesktopCapturerSource[]>` - Resolves with an array of [`DesktopCapturerSource`](structures/desktop-capturer-source.md) objects, each `DesktopCapturerSource` represents a screen or an individual window that can be captured.
|
||||
|
||||
> [!NOTE]
|
||||
<!-- markdownlint-disable-next-line MD032 -->
|
||||
|
||||
> * Capturing audio requires `NSAudioCaptureUsageDescription` Info.plist key on macOS 14.2 Sonoma and higher - [read more](#macos-versions-142-or-higher).
|
||||
> * Capturing the screen contents requires user consent on macOS 10.15 Catalina or higher, which can detected by [`systemPreferences.getMediaAccessStatus`][].
|
||||
|
||||
@@ -120,41 +109,30 @@ Returns `Promise<DesktopCapturerSource[]>` - Resolves with an array of [`Desktop
|
||||
|
||||
PipeWire supports a single capture for both screens and windows. If you request the window and screen type, the selected source will be returned as a window capture.
|
||||
|
||||
### macOS versions 14.2 or higher
|
||||
---
|
||||
|
||||
`NSAudioCaptureUsageDescription` Info.plist key must be added in order for audio to be captured by
|
||||
`desktopCapturer`. If instead you are running Electron from another program like a terminal or IDE
|
||||
then that parent program must contain the Info.plist key.
|
||||
### MacOS versions 14.2 or higher
|
||||
|
||||
`NSAudioCaptureUsageDescription` Info.plist key must be added in-order for audio to be captured by `desktopCapturer`. If instead you are running electron from another program like a terminal or IDE then that parent program must contain the Info.plist key.
|
||||
|
||||
This is in order to facillitate use of Apple's new [CoreAudio Tap API](https://developer.apple.com/documentation/CoreAudio/capturing-system-audio-with-core-audio-taps#Configure-the-sample-code-project) by Chromium.
|
||||
|
||||
> [!WARNING]
|
||||
> Failure of `desktopCapturer` to start an audio stream due to `NSAudioCaptureUsageDescription`
|
||||
> permission not present will still create a dead audio stream however no warnings or errors are
|
||||
> displayed.
|
||||
> Failure of `desktopCapturer` to start an audio stream due to `NSAudioCaptureUsageDescription` permission not present will still create a dead audio stream however no warnings or errors are displayed.
|
||||
|
||||
As of Electron `v39.0.0-beta.4`, Chromium [made Apple's new `CoreAudio Tap API` the default](https://source.chromium.org/chromium/chromium/src/+/ad17e8f8b93d5f34891b06085d373a668918255e)
|
||||
for desktop audio capture. There is no fallback to the older `Screen & System Audio Recording`
|
||||
permissions system even if [CoreAudio Tap API](https://developer.apple.com/documentation/CoreAudio/capturing-system-audio-with-core-audio-taps) stream creation fails.
|
||||
As of electron `v39.0.0-beta.4` Chromium [made Apple's new `CoreAudio Tap API` the default](https://source.chromium.org/chromium/chromium/src/+/ad17e8f8b93d5f34891b06085d373a668918255e) for desktop audio capture. There is no fallback to the older `Screen & System Audio Recording` permissions system even if [CoreAudio Tap API](https://developer.apple.com/documentation/CoreAudio/capturing-system-audio-with-core-audio-taps) stream creation fails.
|
||||
|
||||
If you need to continue using `Screen & System Audio Recording` permissions for `desktopCapturer`
|
||||
on macOS versions 14.2 and later, you can apply a Chromium feature flag to force use of that older
|
||||
permissions system:
|
||||
If you need to continue using `Screen & System Audio Recording` permissions for `desktopCapturer` on macOS versions 14.2 and later, you can apply a chromium feature flag to force use of that older permissions system:
|
||||
|
||||
```js
|
||||
// main.js (right beneath your require/import statments)
|
||||
app.commandLine.appendSwitch('disable-features', 'MacCatapLoopbackAudioForScreenShare')
|
||||
```
|
||||
|
||||
### macOS versions 12.7.6 or lower
|
||||
---
|
||||
|
||||
`navigator.mediaDevices.getUserMedia` does not work on macOS versions 12.7.6 and prior for audio
|
||||
capture due to a fundamental limitation whereby apps that want to access the system's audio require
|
||||
a [signed kernel extension](https://developer.apple.com/library/archive/documentation/Security/Conceptual/System_Integrity_Protection_Guide/KernelExtensions/KernelExtensions.html).
|
||||
Chromium, and by extension Electron, does not provide this. Only in macOS 13 and onwards does Apple
|
||||
provide APIs to capture desktop audio without the need for a signed kernel extension.
|
||||
### MacOS versions 12.7.6 or lower
|
||||
|
||||
It is possible to circumvent this limitation by capturing system audio with another macOS app like
|
||||
[BlackHole](https://existential.audio/blackhole/) or [Soundflower](https://rogueamoeba.com/freebies/soundflower/)
|
||||
and passing it through a virtual audio input device. This virtual device can then be queried
|
||||
with `navigator.mediaDevices.getUserMedia`.
|
||||
`navigator.mediaDevices.getUserMedia` does not work on macOS versions 12.7.6 and prior for audio capture due to a fundamental limitation whereby apps that want to access the system's audio require a [signed kernel extension](https://developer.apple.com/library/archive/documentation/Security/Conceptual/System_Integrity_Protection_Guide/KernelExtensions/KernelExtensions.html). Chromium, and by extension Electron, does not provide this. Only in macOS 13 and onwards does Apple provide APIs to capture desktop audio without the need for a signed kernel extension.
|
||||
|
||||
It is possible to circumvent this limitation by capturing system audio with another macOS app like [BlackHole](https://existential.audio/blackhole/) or [Soundflower](https://rogueamoeba.com/freebies/soundflower/) and passing it through a virtual audio input device. This virtual device can then be queried with `navigator.mediaDevices.getUserMedia`.
|
||||
|
||||
@@ -18,20 +18,10 @@ The `dialog` module has the following methods:
|
||||
|
||||
### `dialog.showOpenDialogSync([window, ]options)`
|
||||
|
||||
<!--
|
||||
```YAML history
|
||||
added:
|
||||
- pr-url: https://github.com/electron/electron/pull/16973
|
||||
```
|
||||
-->
|
||||
|
||||
* `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)
|
||||
@@ -40,7 +30,7 @@ added:
|
||||
* `openFile` - Allow files to be selected.
|
||||
* `openDirectory` - Allow directories to be selected.
|
||||
* `multiSelections` - Allow multiple paths to be selected.
|
||||
* `showHiddenFiles` _macOS_ _Windows_ _Deprecated_ - Show hidden files in dialog. Deprecated on Linux.
|
||||
* `showHiddenFiles` - Show hidden files in dialog.
|
||||
* `createDirectory` _macOS_ - Allow creating new directories from dialog.
|
||||
* `promptToCreate` _Windows_ - Prompt for creation if the file path entered
|
||||
in the dialog does not exist. This does not actually create the file at
|
||||
@@ -100,22 +90,10 @@ dialog.showOpenDialogSync(mainWindow, {
|
||||
|
||||
### `dialog.showOpenDialog([window, ]options)`
|
||||
|
||||
<!--
|
||||
```YAML history
|
||||
changes:
|
||||
- pr-url: https://github.com/electron/electron/pull/16973
|
||||
description: "This method now returns a Promise instead of using a callback function."
|
||||
breaking-changes-header: api-changed-callback-based-versions-of-promisified-apis
|
||||
```
|
||||
-->
|
||||
|
||||
* `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)
|
||||
@@ -124,7 +102,7 @@ changes:
|
||||
* `openFile` - Allow files to be selected.
|
||||
* `openDirectory` - Allow directories to be selected.
|
||||
* `multiSelections` - Allow multiple paths to be selected.
|
||||
* `showHiddenFiles` _macOS_ _Windows_ _Deprecated_ - Show hidden files in dialog. Deprecated on Linux.
|
||||
* `showHiddenFiles` - Show hidden files in dialog.
|
||||
* `createDirectory` _macOS_ - Allow creating new directories from dialog.
|
||||
* `promptToCreate` _Windows_ - Prompt for creation if the file path entered
|
||||
in the dialog does not exist. This does not actually create the file at
|
||||
@@ -193,20 +171,11 @@ dialog.showOpenDialog(mainWindow, {
|
||||
|
||||
### `dialog.showSaveDialogSync([window, ]options)`
|
||||
|
||||
<!--
|
||||
```YAML history
|
||||
added:
|
||||
- pr-url: https://github.com/electron/electron/pull/17054
|
||||
```
|
||||
-->
|
||||
|
||||
* `window` [BaseWindow](base-window.md) (optional)
|
||||
* `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)
|
||||
@@ -216,7 +185,7 @@ added:
|
||||
* `showsTagField` boolean (optional) _macOS_ - Show the tags input box,
|
||||
defaults to `true`.
|
||||
* `properties` string[] (optional)
|
||||
* `showHiddenFiles` _macOS_ _Windows_ _Deprecated_ - Show hidden files in dialog. Deprecated on Linux.
|
||||
* `showHiddenFiles` - Show hidden files in dialog.
|
||||
* `createDirectory` _macOS_ - Allow creating new directories from dialog.
|
||||
* `treatPackageAsDirectory` _macOS_ - Treat packages, such as `.app` folders,
|
||||
as a directory instead of a file.
|
||||
@@ -233,22 +202,11 @@ The `filters` specifies an array of file types that can be displayed, see
|
||||
|
||||
### `dialog.showSaveDialog([window, ]options)`
|
||||
|
||||
<!--
|
||||
```YAML history
|
||||
changes:
|
||||
- pr-url: https://github.com/electron/electron/pull/17054
|
||||
description: "This method now returns a Promise instead of using a callback function."
|
||||
breaking-changes-header: api-changed-callback-based-versions-of-promisified-apis
|
||||
```
|
||||
-->
|
||||
|
||||
* `window` [BaseWindow](base-window.md) (optional)
|
||||
* `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)
|
||||
@@ -257,7 +215,7 @@ changes:
|
||||
displayed in front of the filename text field.
|
||||
* `showsTagField` boolean (optional) _macOS_ - Show the tags input box, defaults to `true`.
|
||||
* `properties` string[] (optional)
|
||||
* `showHiddenFiles` _macOS_ _Windows_ _Deprecated_ - Show hidden files in dialog. Deprecated on Linux.
|
||||
* `showHiddenFiles` - Show hidden files in dialog.
|
||||
* `createDirectory` _macOS_ - Allow creating new directories from dialog.
|
||||
* `treatPackageAsDirectory` _macOS_ - Treat packages, such as `.app` folders,
|
||||
as a directory instead of a file.
|
||||
@@ -282,13 +240,6 @@ The `filters` specifies an array of file types that can be displayed, see
|
||||
|
||||
### `dialog.showMessageBoxSync([window, ]options)`
|
||||
|
||||
<!--
|
||||
```YAML history
|
||||
added:
|
||||
- pr-url: https://github.com/electron/electron/pull/17298
|
||||
```
|
||||
-->
|
||||
|
||||
* `window` [BaseWindow](base-window.md) (optional)
|
||||
* `options` Object
|
||||
* `message` string - Content of the message box.
|
||||
@@ -332,19 +283,6 @@ If `window` is not shown dialog will not be attached to it. In such case it will
|
||||
|
||||
### `dialog.showMessageBox([window, ]options)`
|
||||
|
||||
<!--
|
||||
```YAML history
|
||||
changes:
|
||||
- pr-url: https://github.com/electron/electron/pull/17298
|
||||
description: "This method now returns a Promise instead of using a callback function."
|
||||
breaking-changes-header: api-changed-callback-based-versions-of-promisified-apis
|
||||
- pr-url: https://github.com/electron/electron/pull/26102
|
||||
description: "Added the `signal` option."
|
||||
- pr-url: https://github.com/electron/electron/pull/30474
|
||||
description: "Added the `textWidth` option."
|
||||
```
|
||||
-->
|
||||
|
||||
* `window` [BaseWindow](base-window.md) (optional)
|
||||
* `options` Object
|
||||
* `message` string - Content of the message box.
|
||||
@@ -406,22 +344,11 @@ Displays a modal dialog that shows an error message.
|
||||
|
||||
This API can be called safely before the `ready` event the `app` module emits,
|
||||
it is usually used to report errors in early stage of startup. If called
|
||||
before the app `ready` event on Linux, the message will be emitted to stderr,
|
||||
before the app `ready`event on Linux, the message will be emitted to stderr,
|
||||
and no GUI dialog will appear.
|
||||
|
||||
### `dialog.showCertificateTrustDialog([window, ]options)` _macOS_ _Windows_
|
||||
|
||||
<!--
|
||||
```YAML history
|
||||
added:
|
||||
- pr-url: https://github.com/electron/electron/pull/9099
|
||||
changes:
|
||||
- pr-url: https://github.com/electron/electron/pull/17181
|
||||
description: "This method now returns a Promise instead of using a callback function."
|
||||
breaking-changes-header: api-changed-callback-based-versions-of-promisified-apis
|
||||
```
|
||||
-->
|
||||
|
||||
* `window` [BaseWindow](base-window.md) (optional)
|
||||
* `options` Object
|
||||
* `certificate` [Certificate](structures/certificate.md) - The certificate to trust/import.
|
||||
|
||||
@@ -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.
|
||||
|
||||
@@ -55,13 +55,6 @@ The `globalShortcut` module has the following methods:
|
||||
|
||||
### `globalShortcut.register(accelerator, callback)`
|
||||
|
||||
<!--
|
||||
```YAML history
|
||||
added:
|
||||
- pr-url: https://github.com/electron/electron/pull/534
|
||||
```
|
||||
-->
|
||||
|
||||
* `accelerator` string - An [accelerator](../tutorial/keyboard-shortcuts.md#accelerators) shortcut.
|
||||
* `callback` Function
|
||||
|
||||
@@ -84,13 +77,6 @@ the app has been authorized as a [trusted accessibility client](https://develope
|
||||
|
||||
### `globalShortcut.registerAll(accelerators, callback)`
|
||||
|
||||
<!--
|
||||
```YAML history
|
||||
added:
|
||||
- pr-url: https://github.com/electron/electron/pull/15542
|
||||
```
|
||||
-->
|
||||
|
||||
* `accelerators` string[] - An array of [accelerator](../tutorial/keyboard-shortcuts.md#accelerators) shortcuts.
|
||||
* `callback` Function
|
||||
|
||||
@@ -110,13 +96,6 @@ the app has been authorized as a [trusted accessibility client](https://develope
|
||||
|
||||
### `globalShortcut.isRegistered(accelerator)`
|
||||
|
||||
<!--
|
||||
```YAML history
|
||||
added:
|
||||
- pr-url: https://github.com/electron/electron/pull/534
|
||||
```
|
||||
-->
|
||||
|
||||
* `accelerator` string - An [accelerator](../tutorial/keyboard-shortcuts.md#accelerators) shortcut.
|
||||
|
||||
Returns `boolean` - Whether this application has registered `accelerator`.
|
||||
@@ -127,55 +106,10 @@ don't want applications to fight for global shortcuts.
|
||||
|
||||
### `globalShortcut.unregister(accelerator)`
|
||||
|
||||
<!--
|
||||
```YAML history
|
||||
added:
|
||||
- pr-url: https://github.com/electron/electron/pull/534
|
||||
```
|
||||
-->
|
||||
|
||||
* `accelerator` string - An [accelerator](../tutorial/keyboard-shortcuts.md#accelerators) shortcut.
|
||||
|
||||
Unregisters the global shortcut of `accelerator`.
|
||||
|
||||
### `globalShortcut.unregisterAll()`
|
||||
|
||||
<!--
|
||||
```YAML history
|
||||
added:
|
||||
- pr-url: https://github.com/electron/electron/pull/534
|
||||
```
|
||||
-->
|
||||
|
||||
Unregisters all of the global shortcuts.
|
||||
|
||||
### `globalShortcut.setSuspended(suspended)`
|
||||
|
||||
<!--
|
||||
```YAML history
|
||||
added:
|
||||
- pr-url: https://github.com/electron/electron/pull/50425
|
||||
```
|
||||
-->
|
||||
|
||||
* `suspended` boolean - Whether global shortcut handling should be suspended.
|
||||
|
||||
Suspends or resumes global shortcut handling. When suspended, all registered
|
||||
global shortcuts will stop listening for key presses. When resumed, all
|
||||
previously registered shortcuts will begin listening again. New shortcut
|
||||
registrations will fail while handling is suspended.
|
||||
|
||||
This can be useful when you want to temporarily allow the user to press key
|
||||
combinations without your application intercepting them, for example while
|
||||
displaying a UI to rebind shortcuts.
|
||||
|
||||
### `globalShortcut.isSuspended()`
|
||||
|
||||
<!--
|
||||
```YAML history
|
||||
added:
|
||||
- pr-url: https://github.com/electron/electron/pull/50425
|
||||
```
|
||||
-->
|
||||
|
||||
Returns `boolean` - Whether global shortcut handling is currently suspended.
|
||||
|
||||
@@ -35,13 +35,6 @@ webContentsView.webContents.loadURL('https://electronjs.org')
|
||||
|
||||
## Class: ImageView extends `View`
|
||||
|
||||
<!--
|
||||
```YAML history
|
||||
added:
|
||||
- pr-url: https://github.com/electron/electron/pull/46760
|
||||
```
|
||||
-->
|
||||
|
||||
> A View that displays an image.
|
||||
|
||||
Process: [Main](../glossary.md#main-process)
|
||||
@@ -56,13 +49,6 @@ Process: [Main](../glossary.md#main-process)
|
||||
|
||||
### `new ImageView()` _Experimental_
|
||||
|
||||
<!--
|
||||
```YAML history
|
||||
added:
|
||||
- pr-url: https://github.com/electron/electron/pull/46760
|
||||
```
|
||||
-->
|
||||
|
||||
Creates an ImageView.
|
||||
|
||||
### Instance Methods
|
||||
@@ -72,13 +58,6 @@ addition to those inherited from [View](view.md):
|
||||
|
||||
#### `image.setImage(image)` _Experimental_
|
||||
|
||||
<!--
|
||||
```YAML history
|
||||
added:
|
||||
- pr-url: https://github.com/electron/electron/pull/46760
|
||||
```
|
||||
-->
|
||||
|
||||
* `image` NativeImage
|
||||
|
||||
Sets the image for this `ImageView`. Note that only image formats supported by
|
||||
|
||||
@@ -1,12 +1,5 @@
|
||||
# inAppPurchase
|
||||
|
||||
<!--
|
||||
```YAML history
|
||||
added:
|
||||
- pr-url: https://github.com/electron/electron/pull/11292
|
||||
```
|
||||
-->
|
||||
|
||||
> In-app purchases on Mac App Store.
|
||||
|
||||
Process: [Main](../glossary.md#main-process)
|
||||
@@ -17,13 +10,6 @@ The `inAppPurchase` module emits the following events:
|
||||
|
||||
### Event: 'transactions-updated'
|
||||
|
||||
<!--
|
||||
```YAML history
|
||||
added:
|
||||
- pr-url: https://github.com/electron/electron/pull/11292
|
||||
```
|
||||
-->
|
||||
|
||||
Returns:
|
||||
|
||||
* `event` Event
|
||||
@@ -37,19 +23,6 @@ The `inAppPurchase` module has the following methods:
|
||||
|
||||
### `inAppPurchase.purchaseProduct(productID[, opts])`
|
||||
|
||||
<!--
|
||||
```YAML history
|
||||
added:
|
||||
- pr-url: https://github.com/electron/electron/pull/11292
|
||||
changes:
|
||||
- pr-url: https://github.com/electron/electron/pull/17355
|
||||
description: "This method now returns a Promise instead of using a callback function."
|
||||
breaking-changes-header: api-changed-callback-based-versions-of-promisified-apis
|
||||
- pr-url: https://github.com/electron/electron/pull/35902
|
||||
description: "Added `username` option to `opts` parameter."
|
||||
```
|
||||
-->
|
||||
|
||||
* `productID` string
|
||||
* `opts` Integer | Object (optional) - If specified as an integer, defines the quantity.
|
||||
* `quantity` Integer (optional) - The number of items the user wants to purchase.
|
||||
@@ -61,17 +34,6 @@ You should listen for the `transactions-updated` event as soon as possible and c
|
||||
|
||||
### `inAppPurchase.getProducts(productIDs)`
|
||||
|
||||
<!--
|
||||
```YAML history
|
||||
added:
|
||||
- pr-url: https://github.com/electron/electron/pull/12464
|
||||
changes:
|
||||
- pr-url: https://github.com/electron/electron/pull/17355
|
||||
description: "This method now returns a Promise instead of using a callback function."
|
||||
breaking-changes-header: api-changed-callback-based-versions-of-promisified-apis
|
||||
```
|
||||
-->
|
||||
|
||||
* `productIDs` string[] - The identifiers of the products to get.
|
||||
|
||||
Returns `Promise<Product[]>` - Resolves with an array of [`Product`](structures/product.md) objects.
|
||||
@@ -80,59 +42,24 @@ Retrieves the product descriptions.
|
||||
|
||||
### `inAppPurchase.canMakePayments()`
|
||||
|
||||
<!--
|
||||
```YAML history
|
||||
added:
|
||||
- pr-url: https://github.com/electron/electron/pull/11292
|
||||
```
|
||||
-->
|
||||
|
||||
Returns `boolean` - whether a user can make a payment.
|
||||
|
||||
### `inAppPurchase.restoreCompletedTransactions()`
|
||||
|
||||
<!--
|
||||
```YAML history
|
||||
added:
|
||||
- pr-url: https://github.com/electron/electron/pull/21461
|
||||
```
|
||||
-->
|
||||
|
||||
Restores finished transactions. This method can be called either to install purchases on additional devices, or to restore purchases for an application that the user deleted and reinstalled.
|
||||
|
||||
[The payment queue](https://developer.apple.com/documentation/storekit/skpaymentqueue?language=objc) delivers a new transaction for each previously completed transaction that can be restored. Each transaction includes a copy of the original transaction.
|
||||
|
||||
### `inAppPurchase.getReceiptURL()`
|
||||
|
||||
<!--
|
||||
```YAML history
|
||||
added:
|
||||
- pr-url: https://github.com/electron/electron/pull/11292
|
||||
```
|
||||
-->
|
||||
|
||||
Returns `string` - the path to the receipt.
|
||||
|
||||
### `inAppPurchase.finishAllTransactions()`
|
||||
|
||||
<!--
|
||||
```YAML history
|
||||
added:
|
||||
- pr-url: https://github.com/electron/electron/pull/12464
|
||||
```
|
||||
-->
|
||||
|
||||
Completes all pending transactions.
|
||||
|
||||
### `inAppPurchase.finishTransactionByDate(date)`
|
||||
|
||||
<!--
|
||||
```YAML history
|
||||
added:
|
||||
- pr-url: https://github.com/electron/electron/pull/12464
|
||||
```
|
||||
-->
|
||||
|
||||
* `date` string - The ISO formatted date of the transaction to finish.
|
||||
|
||||
Completes the pending transactions corresponding to the date.
|
||||
|
||||
@@ -34,7 +34,7 @@ Returns:
|
||||
* `error` Error - Typically holds an error string identifying failure root cause.
|
||||
|
||||
Emitted when an error was encountered while streaming response data events. For
|
||||
instance, if the server closes the underlying connection while the response is still
|
||||
instance, if the server closes the underlying while the response is still
|
||||
streaming, an `error` event will be emitted on the response object and a `close`
|
||||
event will subsequently follow on the request object.
|
||||
|
||||
|
||||
@@ -46,13 +46,6 @@ Listens to `channel`, when a new message arrives `listener` would be called with
|
||||
|
||||
### `ipcMain.off(channel, listener)`
|
||||
|
||||
<!--
|
||||
```YAML history
|
||||
added:
|
||||
- pr-url: https://github.com/electron/electron/pull/44651
|
||||
```
|
||||
-->
|
||||
|
||||
* `channel` string
|
||||
* `listener` Function
|
||||
* `event` [IpcMainEvent][ipc-main-event]
|
||||
@@ -96,13 +89,6 @@ Removes all listeners from the specified `channel`. Removes all listeners from a
|
||||
|
||||
### `ipcMain.handle(channel, listener)`
|
||||
|
||||
<!--
|
||||
```YAML history
|
||||
added:
|
||||
- pr-url: https://github.com/electron/electron/pull/18449
|
||||
```
|
||||
-->
|
||||
|
||||
* `channel` string
|
||||
* `listener` Function\<Promise\<any\> | any\>
|
||||
* `event` [IpcMainInvokeEvent][ipc-main-invoke-event]
|
||||
@@ -140,13 +126,6 @@ provided to the renderer process. Please refer to
|
||||
|
||||
### `ipcMain.handleOnce(channel, listener)`
|
||||
|
||||
<!--
|
||||
```YAML history
|
||||
added:
|
||||
- pr-url: https://github.com/electron/electron/pull/18449
|
||||
```
|
||||
-->
|
||||
|
||||
* `channel` string
|
||||
* `listener` Function\<Promise\<any\> | any\>
|
||||
* `event` [IpcMainInvokeEvent][ipc-main-invoke-event]
|
||||
@@ -157,13 +136,6 @@ Handles a single `invoke`able IPC message, then removes the listener. See
|
||||
|
||||
### `ipcMain.removeHandler(channel)`
|
||||
|
||||
<!--
|
||||
```YAML history
|
||||
added:
|
||||
- pr-url: https://github.com/electron/electron/pull/18449
|
||||
```
|
||||
-->
|
||||
|
||||
* `channel` string
|
||||
|
||||
Removes any handler for `channel`, if present.
|
||||
|
||||
@@ -59,13 +59,6 @@ for more info.
|
||||
|
||||
### `ipcRenderer.off(channel, listener)`
|
||||
|
||||
<!--
|
||||
```YAML history
|
||||
added:
|
||||
- pr-url: https://github.com/electron/electron/pull/39816
|
||||
```
|
||||
-->
|
||||
|
||||
* `channel` string
|
||||
* `listener` Function
|
||||
* `event` [IpcRendererEvent][ipc-renderer-event]
|
||||
@@ -86,13 +79,6 @@ only the next time a message is sent to `channel`, after which it is removed.
|
||||
|
||||
### `ipcRenderer.addListener(channel, listener)`
|
||||
|
||||
<!--
|
||||
```YAML history
|
||||
added:
|
||||
- pr-url: https://github.com/electron/electron/pull/39816
|
||||
```
|
||||
-->
|
||||
|
||||
* `channel` string
|
||||
* `listener` Function
|
||||
* `event` [IpcRendererEvent][ipc-renderer-event]
|
||||
@@ -143,13 +129,6 @@ If you want to receive a single response from the main process, like the result
|
||||
|
||||
### `ipcRenderer.invoke(channel, ...args)`
|
||||
|
||||
<!--
|
||||
```YAML history
|
||||
added:
|
||||
- pr-url: https://github.com/electron/electron/pull/18449
|
||||
```
|
||||
-->
|
||||
|
||||
* `channel` string
|
||||
* `...args` any[]
|
||||
|
||||
@@ -230,13 +209,6 @@ and replies by setting `event.returnValue`.
|
||||
|
||||
### `ipcRenderer.postMessage(channel, message, [transfer])`
|
||||
|
||||
<!--
|
||||
```YAML history
|
||||
added:
|
||||
- pr-url: https://github.com/electron/electron/pull/22404
|
||||
```
|
||||
-->
|
||||
|
||||
* `channel` string
|
||||
* `message` any
|
||||
* `transfer` MessagePort[] (optional)
|
||||
|
||||
@@ -44,8 +44,8 @@ See [`Menu`](menu.md) for examples.
|
||||
menu items.
|
||||
* `registerAccelerator` boolean (optional) _Linux_ _Windows_ - If false, the accelerator won't be registered
|
||||
with the system, but it will still be displayed. Defaults to true.
|
||||
* `sharingItem` [SharingItem](structures/sharing-item.md) (optional) _macOS_ - The item to share when the `role` is `shareMenu`.
|
||||
* `submenu` ([MenuItemConstructorOptions](#new-menuitemoptions)[] | [Menu](menu.md)) (optional) - Should be specified
|
||||
* `sharingItem` SharingItem (optional) _macOS_ - The item to share when the `role` is `shareMenu`.
|
||||
* `submenu` (MenuItemConstructorOptions[] | [Menu](menu.md)) (optional) - Should be specified
|
||||
for `submenu` type menu items. If `submenu` is specified, the `type: 'submenu'` can be omitted.
|
||||
If the value is not a [`Menu`](menu.md) then it will be automatically converted to one using
|
||||
`Menu.buildFromTemplate`.
|
||||
@@ -73,23 +73,20 @@ The following properties are available on instances of `MenuItem`:
|
||||
|
||||
#### `menuItem.id`
|
||||
|
||||
A `string` indicating the item's unique id.
|
||||
|
||||
This property can be dynamically changed.
|
||||
A `string` indicating the item's unique id. This property can be
|
||||
dynamically changed.
|
||||
|
||||
#### `menuItem.label`
|
||||
|
||||
A `string` indicating the item's visible label.
|
||||
|
||||
This property can be dynamically changed.
|
||||
|
||||
#### `menuItem.click`
|
||||
|
||||
A `Function` that is fired when the MenuItem receives a click event.
|
||||
It can be called with `menuItem.click(event, focusedWindow, focusedWebContents)`.
|
||||
|
||||
* `event` [KeyboardEvent](structures/keyboard-event.md)
|
||||
* `focusedWindow` [BaseWindow](base-window.md)
|
||||
* `focusedWindow` [BaseWindow](browser-window.md)
|
||||
* `focusedWebContents` [WebContents](web-contents.md)
|
||||
|
||||
#### `menuItem.submenu`
|
||||
@@ -110,48 +107,42 @@ A `string` (optional) indicating the item's role, if set. Can be `undo`, `redo`,
|
||||
|
||||
#### `menuItem.accelerator`
|
||||
|
||||
An [`Accelerator | null`](../tutorial/keyboard-shortcuts.md#accelerators) indicating the item's accelerator, if set.
|
||||
An `Accelerator | null` indicating the item's accelerator, if set.
|
||||
|
||||
#### `menuItem.userAccelerator` _Readonly_ _macOS_
|
||||
|
||||
An [`Accelerator | null`](../tutorial/keyboard-shortcuts.md#accelerators) indicating the item's [user-assigned accelerator](https://developer.apple.com/documentation/appkit/nsmenuitem/1514850-userkeyequivalent?language=objc) for the menu item.
|
||||
An `Accelerator | null` indicating the item's [user-assigned accelerator](https://developer.apple.com/documentation/appkit/nsmenuitem/1514850-userkeyequivalent?language=objc) for the menu item.
|
||||
|
||||
> [!NOTE]
|
||||
> This property is only initialized after the `MenuItem` has been added to a `Menu`. Either via `Menu.buildFromTemplate` or via `Menu.append()/insert()`. Accessing before initialization will just return `null`.
|
||||
|
||||
#### `menuItem.icon`
|
||||
|
||||
A `NativeImage | string` (optional) indicating the item's icon, if set.
|
||||
|
||||
This property can be dynamically changed.
|
||||
A `NativeImage | string` (optional) indicating the
|
||||
item's icon, if set.
|
||||
|
||||
#### `menuItem.sublabel`
|
||||
|
||||
A `string` indicating the item's sublabel.
|
||||
|
||||
This property can be dynamically changed.
|
||||
|
||||
#### `menuItem.toolTip` _macOS_
|
||||
|
||||
A `string` indicating the item's hover text.
|
||||
|
||||
#### `menuItem.enabled`
|
||||
|
||||
A `boolean` indicating whether the item is enabled.
|
||||
|
||||
This property can be dynamically changed.
|
||||
A `boolean` indicating whether the item is enabled. This property can be
|
||||
dynamically changed.
|
||||
|
||||
#### `menuItem.visible`
|
||||
|
||||
A `boolean` indicating whether the item is visible.
|
||||
|
||||
This property can be dynamically changed.
|
||||
A `boolean` indicating whether the item is visible. This property can be
|
||||
dynamically changed.
|
||||
|
||||
#### `menuItem.checked`
|
||||
|
||||
A `boolean` indicating whether the item is checked.
|
||||
|
||||
This property can be dynamically changed.
|
||||
A `boolean` indicating whether the item is checked. This property can be
|
||||
dynamically changed.
|
||||
|
||||
A `checkbox` menu item will toggle the `checked` property on and off when
|
||||
selected.
|
||||
@@ -170,7 +161,7 @@ This property can be dynamically changed.
|
||||
|
||||
#### `menuItem.sharingItem` _macOS_
|
||||
|
||||
A [`SharingItem`](structures/sharing-item.md) indicating the item to share when the `role` is `shareMenu`.
|
||||
A `SharingItem` indicating the item to share when the `role` is `shareMenu`.
|
||||
|
||||
This property can be dynamically changed.
|
||||
|
||||
|
||||
@@ -39,7 +39,7 @@ indicate which letter should get a generated accelerator. For example, using
|
||||
opens the associated menu. The indicated character in the button label then gets an
|
||||
underline, and the `&` character is not displayed on the button label.
|
||||
|
||||
In order to escape the `&` character in an item name, add a preceding `&`. For example, `&&File` would result in `&File` displayed on the button label.
|
||||
In order to escape the `&` character in an item name, add a proceeding `&`. For example, `&&File` would result in `&File` displayed on the button label.
|
||||
|
||||
Passing `null` will suppress the default menu. On Windows and Linux,
|
||||
this has the additional effect of removing the menu bar from the window.
|
||||
@@ -70,7 +70,7 @@ for more information on macOS' native actions.
|
||||
|
||||
#### `Menu.buildFromTemplate(template)`
|
||||
|
||||
- `template` ([MenuItemConstructorOptions](menu-item.md#new-menuitemoptions) | [MenuItem](menu-item.md))[]
|
||||
- `template` (MenuItemConstructorOptions | [MenuItem](menu-item.md))[]
|
||||
|
||||
Returns [`Menu`](menu.md)
|
||||
|
||||
@@ -162,7 +162,7 @@ Emitted when a popup is closed either manually or with `menu.closePopup()`.
|
||||
|
||||
#### `menu.items`
|
||||
|
||||
A [`MenuItem[]`](menu-item.md) array containing the menu's items.
|
||||
A `MenuItem[]` array containing the menu's items.
|
||||
|
||||
Each `Menu` consists of multiple [`MenuItem`](menu-item.md) instances and each `MenuItem`
|
||||
can nest a `Menu` into its `submenu` property.
|
||||
|
||||
@@ -83,8 +83,4 @@ Currently, Windows high contrast is the only system setting that triggers forced
|
||||
|
||||
### `nativeTheme.prefersReducedTransparency` _Readonly_
|
||||
|
||||
A `boolean` that indicates whether the user has chosen via system accessibility settings to reduce transparency at the OS level.
|
||||
|
||||
### `nativeTheme.shouldDifferentiateWithoutColor` _macOS_ _Readonly_
|
||||
|
||||
A `boolean` that indicates whether the user prefers UI that differentiates items using something other than color alone (e.g. shapes or labels). This maps to [NSWorkspace.accessibilityDisplayShouldDifferentiateWithoutColor](https://developer.apple.com/documentation/appkit/nsworkspace/accessibilitydisplayshoulddifferentiatewithoutcolor).
|
||||
A `boolean` that indicates the whether the user has chosen via system accessibility settings to reduce transparency at the OS level.
|
||||
|
||||
@@ -8,12 +8,6 @@ Process: [Main](../glossary.md#main-process)
|
||||
> If you want to show notifications from a renderer process you should use the
|
||||
> [web Notifications API](../tutorial/notifications.md)
|
||||
|
||||
> [!NOTE]
|
||||
> On MacOS, notifications use the UNNotification API as their underlying framework.
|
||||
> This API requires an application to be code-signed in order for notifications
|
||||
> to appear. Unsigned binaries will emit a `failed` event when notifications
|
||||
> are called.
|
||||
|
||||
## Class: Notification
|
||||
|
||||
> Create OS desktop notifications
|
||||
@@ -36,69 +30,23 @@ The `Notification` class has the following static methods:
|
||||
|
||||
Returns `boolean` - Whether or not desktop notifications are supported on the current system
|
||||
|
||||
#### `Notification.handleActivation(callback)` _Windows_
|
||||
|
||||
* `callback` Function
|
||||
* `details` [ActivationArguments](structures/activation-arguments.md) - Details about the notification activation.
|
||||
|
||||
Registers a callback to handle all notification activations. The callback is invoked whenever a
|
||||
notification is clicked, replied to, or has an action button pressed - regardless of whether
|
||||
the original `Notification` object is still in memory.
|
||||
|
||||
This method handles timing automatically:
|
||||
|
||||
* If an activation already occurred before calling this method, the callback is invoked immediately
|
||||
with those details.
|
||||
* For all subsequent activations, the callback is invoked when they occur.
|
||||
|
||||
The callback remains registered until replaced by another call to `handleActivation`.
|
||||
|
||||
This provides a centralized way to handle notification interactions that works in all scenarios:
|
||||
|
||||
* Cold start (app launched from notification click)
|
||||
* Notifications persisted in AC that have no in-memory representation after app re-start
|
||||
* Notification object was garbage collected
|
||||
* Notification object is still in memory (callback is invoked in addition to instance events)
|
||||
|
||||
```js
|
||||
const { Notification, app } = require('electron')
|
||||
|
||||
app.whenReady().then(() => {
|
||||
// Register handler for all notification activations
|
||||
Notification.handleActivation((details) => {
|
||||
console.log('Notification activated:', details.type)
|
||||
if (details.type === 'reply') {
|
||||
console.log('User reply:', details.reply)
|
||||
} else if (details.type === 'action') {
|
||||
console.log('Action index:', details.actionIndex)
|
||||
}
|
||||
})
|
||||
})
|
||||
```
|
||||
|
||||
### `new Notification([options])`
|
||||
|
||||
* `options` Object (optional)
|
||||
* `id` string (optional) _macOS_ - A unique identifier for the notification, mapping to `UNNotificationRequest`'s [`identifier`](https://developer.apple.com/documentation/usernotifications/unnotificationrequest/identifier) property. Defaults to a random UUID if not provided or if an empty string is passed. This can be used to remove or update previously delivered notifications.
|
||||
* `groupId` string (optional) _macOS_ - A string identifier used to visually group notifications together in Notification Center. Maps to `UNNotificationContent`'s [`threadIdentifier`](https://developer.apple.com/documentation/usernotifications/unnotificationcontent/threadidentifier) property.
|
||||
* `title` string (optional) - A title for the notification, which will be displayed at the top of the notification window when it is shown.
|
||||
* `subtitle` string (optional) _macOS_ - A subtitle for the notification, which will be displayed below the title.
|
||||
* `body` string (optional) - The body text of the notification, which will be displayed below the title or subtitle.
|
||||
* `silent` boolean (optional) - Whether or not to suppress the OS notification noise when showing the notification.
|
||||
* `icon` (string | [NativeImage](native-image.md)) (optional) - An icon to use in the notification. If a string is passed, it must be a valid path to a local icon file.
|
||||
* `hasReply` boolean (optional) _macOS_ _Windows_ - Whether or not to add an inline reply option to the notification.
|
||||
* `hasReply` boolean (optional) _macOS_ - Whether or not to add an inline reply option to the notification.
|
||||
* `timeoutType` string (optional) _Linux_ _Windows_ - The timeout duration of the notification. Can be 'default' or 'never'.
|
||||
* `replyPlaceholder` string (optional) _macOS_ _Windows_ - The placeholder to write in the inline reply input field.
|
||||
* `replyPlaceholder` string (optional) _macOS_ - The placeholder to write in the inline reply input field.
|
||||
* `sound` string (optional) _macOS_ - The name of the sound file to play when the notification is shown.
|
||||
* `urgency` string (optional) _Linux_ _Windows_ - The urgency level of the notification. Can be 'normal', 'critical', or 'low'.
|
||||
* `actions` [NotificationAction[]](structures/notification-action.md) (optional) _macOS_ _Windows_ - Actions to add to the notification. Please read the available actions and limitations in the `NotificationAction` documentation.
|
||||
* `urgency` string (optional) _Linux_ - The urgency level of the notification. Can be 'normal', 'critical', or 'low'.
|
||||
* `actions` [NotificationAction[]](structures/notification-action.md) (optional) _macOS_ - Actions to add to the notification. Please read the available actions and limitations in the `NotificationAction` documentation.
|
||||
* `closeButtonText` string (optional) _macOS_ - A custom title for the close button of an alert. An empty string will cause the default localized text to be used.
|
||||
* `toastXml` string (optional) _Windows_ - A custom description of the Notification on Windows superseding all properties above. Provides full customization of design and behavior of the notification.
|
||||
|
||||
> [!NOTE]
|
||||
> On Windows, `urgency` type 'critical' sorts the notification higher in Action Center (above default priority notifications), but does not prevent auto-dismissal. To prevent auto-dismissal, you should also set
|
||||
> `timeoutType` to 'never'.
|
||||
|
||||
### Instance Events
|
||||
|
||||
Objects created with `new Notification` emit the following events:
|
||||
@@ -119,22 +67,6 @@ Emitted when the notification is shown to the user. Note that this event can be
|
||||
multiple times as a notification can be shown multiple times through the
|
||||
`show()` method.
|
||||
|
||||
```js
|
||||
const { Notification, app } = require('electron')
|
||||
|
||||
app.whenReady().then(() => {
|
||||
const n = new Notification({
|
||||
title: 'Title!',
|
||||
subtitle: 'Subtitle!',
|
||||
body: 'Body!'
|
||||
})
|
||||
|
||||
n.on('show', () => console.log('Notification shown!'))
|
||||
|
||||
n.show()
|
||||
})
|
||||
```
|
||||
|
||||
#### Event: 'click'
|
||||
|
||||
Returns:
|
||||
@@ -143,28 +75,11 @@ Returns:
|
||||
|
||||
Emitted when the notification is clicked by the user.
|
||||
|
||||
```js
|
||||
const { Notification, app } = require('electron')
|
||||
|
||||
app.whenReady().then(() => {
|
||||
const n = new Notification({
|
||||
title: 'Title!',
|
||||
subtitle: 'Subtitle!',
|
||||
body: 'Body!'
|
||||
})
|
||||
|
||||
n.on('click', () => console.log('Notification clicked!'))
|
||||
|
||||
n.show()
|
||||
})
|
||||
```
|
||||
|
||||
#### Event: 'close'
|
||||
|
||||
Returns:
|
||||
|
||||
* `details` Event\<\>
|
||||
* `reason` _Windows_ string (optional) - The reason the notification was closed. This can be 'userCanceled', 'applicationHidden', or 'timedOut'.
|
||||
* `event` Event
|
||||
|
||||
Emitted when the notification is closed by manual intervention from the user.
|
||||
|
||||
@@ -173,85 +88,21 @@ is closed.
|
||||
|
||||
On Windows, the `close` event can be emitted in one of three ways: programmatic dismissal with `notification.close()`, by the user closing the notification, or via system timeout. If a notification is in the Action Center after the initial `close` event is emitted, a call to `notification.close()` will remove the notification from the action center but the `close` event will not be emitted again.
|
||||
|
||||
```js
|
||||
const { Notification, app } = require('electron')
|
||||
|
||||
app.whenReady().then(() => {
|
||||
const n = new Notification({
|
||||
title: 'Title!',
|
||||
subtitle: 'Subtitle!',
|
||||
body: 'Body!'
|
||||
})
|
||||
|
||||
n.on('close', () => console.log('Notification closed!'))
|
||||
|
||||
n.show()
|
||||
})
|
||||
```
|
||||
|
||||
#### Event: 'reply' _macOS_ _Windows_
|
||||
#### Event: 'reply' _macOS_
|
||||
|
||||
Returns:
|
||||
|
||||
* `details` Event\<\>
|
||||
* `reply` string - The string the user entered into the inline reply field.
|
||||
* `reply` string _Deprecated_
|
||||
* `event` Event
|
||||
* `reply` string - The string the user entered into the inline reply field.
|
||||
|
||||
Emitted when the user clicks the "Reply" button on a notification with `hasReply: true`.
|
||||
|
||||
```js
|
||||
const { Notification, app } = require('electron')
|
||||
|
||||
app.whenReady().then(() => {
|
||||
const n = new Notification({
|
||||
title: 'Send a Message',
|
||||
body: 'Body Text',
|
||||
hasReply: true,
|
||||
replyPlaceholder: 'Message text...'
|
||||
})
|
||||
|
||||
n.on('reply', (e, reply) => console.log(`User replied: ${reply}`))
|
||||
n.on('click', () => console.log('Notification clicked'))
|
||||
|
||||
n.show()
|
||||
})
|
||||
```
|
||||
|
||||
#### Event: 'action' _macOS_ _Windows_
|
||||
#### Event: 'action' _macOS_
|
||||
|
||||
Returns:
|
||||
|
||||
* `details` Event\<\>
|
||||
* `actionIndex` number - The index of the action that was activated.
|
||||
* `selectionIndex` number _Windows_ - The index of the selected item, if one was chosen. -1 if none was chosen.
|
||||
* `actionIndex` number _Deprecated_
|
||||
* `selectionIndex` number _Windows_ _Deprecated_
|
||||
|
||||
```js
|
||||
const { Notification, app } = require('electron')
|
||||
|
||||
app.whenReady().then(() => {
|
||||
const items = ['One', 'Two', 'Three']
|
||||
const n = new Notification({
|
||||
title: 'Choose an Action!',
|
||||
actions: [
|
||||
{ type: 'button', text: 'Action 1' },
|
||||
{ type: 'button', text: 'Action 2' },
|
||||
{ type: 'selection', text: 'Apply', items }
|
||||
]
|
||||
})
|
||||
|
||||
n.on('click', () => console.log('Notification clicked'))
|
||||
n.on('action', (e) => {
|
||||
console.log(`User triggered action at index: ${e.actionIndex}`)
|
||||
if (e.selectionIndex > -1) {
|
||||
console.log(`User chose selection item '${items[e.selectionIndex]}'`)
|
||||
}
|
||||
})
|
||||
|
||||
n.show()
|
||||
})
|
||||
```
|
||||
* `event` Event
|
||||
* `index` number - The index of the action that was activated.
|
||||
|
||||
#### Event: 'failed' _Windows_
|
||||
|
||||
@@ -262,22 +113,6 @@ Returns:
|
||||
|
||||
Emitted when an error is encountered while creating and showing the native notification.
|
||||
|
||||
```js
|
||||
const { Notification, app } = require('electron')
|
||||
|
||||
app.whenReady().then(() => {
|
||||
const n = new Notification({
|
||||
title: 'Bad Action'
|
||||
})
|
||||
|
||||
n.on('failed', (e, err) => {
|
||||
console.log('Notification failed: ', err)
|
||||
})
|
||||
|
||||
n.show()
|
||||
})
|
||||
```
|
||||
|
||||
### Instance Methods
|
||||
|
||||
Objects created with the `new Notification()` constructor have the following instance methods:
|
||||
@@ -291,52 +126,14 @@ call this method before the OS will display it.
|
||||
If the notification has been shown before, this method will dismiss the previously
|
||||
shown notification and create a new one with identical properties.
|
||||
|
||||
```js
|
||||
const { Notification, app } = require('electron')
|
||||
|
||||
app.whenReady().then(() => {
|
||||
const n = new Notification({
|
||||
title: 'Title!',
|
||||
subtitle: 'Subtitle!',
|
||||
body: 'Body!'
|
||||
})
|
||||
|
||||
n.show()
|
||||
})
|
||||
```
|
||||
|
||||
#### `notification.close()`
|
||||
|
||||
Dismisses the notification.
|
||||
|
||||
On Windows, calling `notification.close()` while the notification is visible on screen will dismiss the notification and remove it from the Action Center. If `notification.close()` is called after the notification is no longer visible on screen, calling `notification.close()` will try remove it from the Action Center.
|
||||
|
||||
```js
|
||||
const { Notification, app } = require('electron')
|
||||
|
||||
app.whenReady().then(() => {
|
||||
const n = new Notification({
|
||||
title: 'Title!',
|
||||
subtitle: 'Subtitle!',
|
||||
body: 'Body!'
|
||||
})
|
||||
|
||||
n.show()
|
||||
|
||||
setTimeout(() => n.close(), 5000)
|
||||
})
|
||||
```
|
||||
|
||||
### Instance Properties
|
||||
|
||||
#### `notification.id` _macOS_ _Readonly_
|
||||
|
||||
A `string` property representing the unique identifier of the notification. This is set at construction time — either from the `id` option or as a generated UUID if none was provided.
|
||||
|
||||
#### `notification.groupId` _macOS_ _Readonly_
|
||||
|
||||
A `string` property representing the group identifier of the notification. Notifications with the same `groupId` will be visually grouped together in Notification Center.
|
||||
|
||||
#### `notification.title`
|
||||
|
||||
A `string` property representing the title of the notification.
|
||||
|
||||
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user