Compare commits

..

4 Commits

Author SHA1 Message Date
chen jing
d06db5f30c test: skip webFrameMain.copyVideoFrameAt on win32 CI due Chromium DCHECK 2026-03-19 14:02:07 +08:00
dodola
67eec6ceb3 Merge branch 'electron:main' into videoframe 2026-03-17 19:27:30 +08:00
dodola
ea6da976eb Merge branch 'electron:main' into videoframe 2026-02-24 10:57:39 +08:00
chenjing
b568504d8d feat: add copyVideoFrameAt and saveVideoFrameAs Method on Webcontent
chore: change the description of savevideoframe api

chore: add the description of the restrictive elements for using the APIs.

move to webframemain

fixed mediaPlayerAction to kSaveVideoFrameAs

Update spec/api-web-frame-main-spec.ts

Co-authored-by: John Kleinschmidt <kleinschmidtorama@gmail.com>

Update spec/api-web-frame-main-spec.ts

Co-authored-by: John Kleinschmidt <kleinschmidtorama@gmail.com>

fixed clipboard tests for video frame copying

fixed test for copying video frame to clipboard. check video loaded before copy video frame in test.

chore: try non-proprietary video format

Revert "chore: try non-proprietary video format"

This reverts commit ef085f88a1af53b6408a7af695cc60b8681398cf.

fix: format video as file url
2025-12-10 18:25:52 +08:00
401 changed files with 5655 additions and 8707 deletions

View File

@@ -35,7 +35,7 @@
"ms-vscode.cpptools",
"mutantdino.resourcemonitor",
"dsanders11.vscode-electron-build-tools",
"oxc.oxc-vscode",
"dbaeumer.vscode-eslint",
"shakram02.bash-beautify",
"marshallofsound.gnls-electron"
],

79
.eslintrc.json Normal file
View 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
View File

@@ -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

View File

@@ -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

View File

@@ -47,16 +47,6 @@ runs:
- name: Add Clang problem matcher
shell: bash
run: echo "::add-matcher::src/electron/.github/problem-matchers/clang.json"
- name: Download previous object checksums
shell: bash
if: ${{ (github.event_name == 'push' || github.event_name == 'pull_request') && inputs.is-asan != 'true' }}
env:
GITHUB_TOKEN: ${{ github.token }}
ARTIFACT_NAME: object-checksums.${{ inputs.artifact-platform }}_${{ inputs.target-arch }}.json
SEARCH_BRANCH: ${{ case(github.event_name == 'push', github.ref_name, github.event.pull_request.base.ref) }}
REPO: ${{ github.repository }}
OUTPUT_PATH: src/previous-object-checksums.json
run: node src/electron/.github/actions/build-electron/download-previous-object-checksums.mjs
- name: Build Electron ${{ inputs.step-suffix }}
if: ${{ inputs.target-platform != 'win' }}
shell: bash
@@ -82,17 +72,12 @@ runs:
cp out/Default/.ninja_log out/electron_ninja_log
node electron/script/check-symlinks.js
# Build stats and object checksums
BUILD_STATS_ARGS="out/Default/siso.INFO --out-dir out/Default --output-object-checksums object-checksums.${{ inputs.artifact-platform }}_${{ inputs.target-arch }}.json"
if [ -f previous-object-checksums.json ]; then
BUILD_STATS_ARGS="$BUILD_STATS_ARGS --input-object-checksums previous-object-checksums.json"
fi
if ! [ -z "$DD_API_KEY" ]; then
BUILD_STATS_ARGS="$BUILD_STATS_ARGS --upload-stats"
# Upload build stats to Datadog
if ! [ -z $DD_API_KEY ]; then
npx node electron/script/build-stats.mjs out/Default/siso.INFO --upload-stats || true
else
echo "Skipping build-stats.mjs upload because DD_API_KEY is not set"
fi
node electron/script/build-stats.mjs $BUILD_STATS_ARGS || true
- name: Build Electron (Windows) ${{ inputs.step-suffix }}
if: ${{ inputs.target-platform == 'win' }}
shell: powershell
@@ -110,21 +95,16 @@ runs:
Copy-Item out\Default\.ninja_log out\electron_ninja_log
node electron\script\check-symlinks.js
# Build stats and object checksums
$statsArgs = @("out\Default\siso.exe.INFO", "--out-dir", "out\Default", "--output-object-checksums", "object-checksums.${{ inputs.artifact-platform }}_${{ inputs.target-arch }}.json")
if (Test-Path previous-object-checksums.json) {
$statsArgs += @("--input-object-checksums", "previous-object-checksums.json")
}
# Upload build stats to Datadog
if ($env:DD_API_KEY) {
$statsArgs += "--upload-stats"
try {
npx node electron\script\build-stats.mjs out\Default\siso.exe.INFO --upload-stats ; $LASTEXITCODE = 0
} catch {
Write-Host "Build stats upload failed, continuing..."
}
} else {
Write-Host "Skipping build-stats.mjs upload because DD_API_KEY is not set"
}
try {
& node electron\script\build-stats.mjs @statsArgs ; $LASTEXITCODE = 0
} catch {
Write-Host "Build stats failed, continuing..."
}
- name: Verify dist.zip ${{ inputs.step-suffix }}
shell: bash
run: |
@@ -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

View File

@@ -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);
});

View File

@@ -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@cdf6c1fa76f9f475f3d7449005a359c84ca0f306 # v5.0.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

View File

@@ -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

View File

@@ -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

View File

@@ -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=a0cc95a1884a631559bcca0c948465b725d9295a
npm i -g @electron/build-tools
# Update depot_tools to ensure python
e d update_depot_tools
@@ -29,20 +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
- name: Install patched siso (Windows)
# Overrides the CIPD siso with a build from electron/siso that carries a
# retry for transient ERROR_INVALID_PARAMETER during the subninja scan on
# container bind-mounted out/ directories. Remove once the fix has rolled
# into Chromium's siso_version.
if: ${{ runner.os == 'Windows' }}
shell: bash
env:
ELECTRON_SISO_URL: https://github.com/electron/siso/releases/download/v1.5.7-electron.2/siso-windows-amd64.exe
ELECTRON_SISO_SHA256: 0e6b754820be3324d5ea4ca3af3634b4cfcf806d89140d78fec4e2a8ef636c9d
run: |
set -eo pipefail
mkdir -p /c/electron-siso
curl --fail --retry 3 -sSL "$ELECTRON_SISO_URL" -o /c/electron-siso/siso.exe
echo "$ELECTRON_SISO_SHA256 /c/electron-siso/siso.exe" | sha256sum --check --strict -
echo "SISO_PATH=C:\\electron-siso\\siso.exe" >> "$GITHUB_ENV"
fi

View File

@@ -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@cdf6c1fa76f9f475f3d7449005a359c84ca0f306 # v5.0.3
id: yarn-cache
with:
path: ${{ steps.yarn-cache-dir-path.outputs.dir }}

View File

@@ -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

View File

@@ -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"

View File

@@ -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

View 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
}
]
}
]
}

View File

@@ -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: |

View File

@@ -21,21 +21,17 @@ jobs:
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

View File

@@ -157,7 +157,7 @@ jobs:
}))
- name: Create Release Project Board
if: ${{ steps.check-major-version.outputs.MAJOR }}
uses: dsanders11/project-actions/copy-project@5767984408ccc6742f83acc8b8d8ea5e09f329af # v2.0.0
uses: dsanders11/project-actions/copy-project@2134fe7cc71c58b7ae259c82a8e63c6058255678 # v1.7.0
id: create-release-board
with:
drafts: true
@@ -177,7 +177,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 +185,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 }}

View File

@@ -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: |
@@ -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:
@@ -387,7 +375,7 @@ jobs:
needs: checkout-windows
if: ${{ needs.setup.outputs.src == 'true' && !inputs.skip-windows }}
with:
build-runs-on: electron-arc-centralus-windows-amd64-32core
build-runs-on: electron-arc-centralus-windows-amd64-16core
test-runs-on: windows-latest
target-platform: win
target-arch: x64
@@ -406,7 +394,7 @@ jobs:
needs: checkout-windows
if: ${{ needs.setup.outputs.src == 'true' && !inputs.skip-windows }}
with:
build-runs-on: electron-arc-centralus-windows-amd64-32core
build-runs-on: electron-arc-centralus-windows-amd64-16core
test-runs-on: windows-latest
target-platform: win
target-arch: x86
@@ -425,7 +413,7 @@ jobs:
needs: checkout-windows
if: ${{ needs.setup.outputs.src == 'true' && !inputs.skip-windows }}
with:
build-runs-on: electron-arc-centralus-windows-amd64-32core
build-runs-on: electron-arc-centralus-windows-amd64-16core
test-runs-on: windows-11-arm
target-platform: win
target-arch: arm64
@@ -446,30 +434,3 @@ jobs:
- name: GitHub Actions Jobs Done
run: |
echo "All GitHub Actions Jobs are done"
check-signed-commits:
name: Check signed commits in green PR
needs: gha-done
if: ${{ contains(github.event.pull_request.labels.*.name, 'needs-signed-commits')}}
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: Remove needs-signed-commits label
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

View File

@@ -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

View File

@@ -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

View File

@@ -34,6 +34,30 @@ jobs:
run: |
gh issue edit $ISSUE_URL --remove-label 'blocked/need-repro','blocked/need-info ❌'
pr-needs-signed-commits-commented:
name: Remove needs-signed-commits on comment
if: ${{ github.event.issue.pull_request && (contains(github.event.issue.labels.*.name, 'needs-signed-commits')) && (github.event.comment.user.login == github.event.issue.user.login) }}
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", "COLLABORATOR"]'), steps.get-author-association.outputs.author_association) }}
id: generate-token
with:
creds: ${{ secrets.ISSUE_TRIAGE_GH_APP_CREDS }}
- name: Remove label
if: ${{ !contains(fromJSON('["MEMBER", "OWNER", "COLLABORATOR"]'), steps.get-author-association.outputs.author_association) }}
env:
GITHUB_TOKEN: ${{ steps.generate-token.outputs.token }}
ISSUE_URL: ${{ github.event.issue.html_url }}
run: |
gh issue edit $ISSUE_URL --remove-label 'needs-signed-commits'
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' }}

View File

@@ -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@71b62d7da76e59ff7b193904feb6e77d4dbb2777 # v3.7.6
with:
actions: 'create-comment'
token: ${{ steps.generate-token.outputs.token }}

View File

@@ -20,7 +20,7 @@ jobs:
creds: ${{ secrets.ISSUE_TRIAGE_GH_APP_CREDS }}
org: electron
- name: Add to Issue Triage
uses: dsanders11/project-actions/add-item@5767984408ccc6742f83acc8b8d8ea5e09f329af # v2.0.0
uses: dsanders11/project-actions/add-item@2134fe7cc71c58b7ae259c82a8e63c6058255678 # v1.7.0
with:
field: Reporter
field-value: ${{ github.event.issue.user.login }}
@@ -146,7 +146,7 @@ jobs:
}
- name: Create unsupported major comment
if: ${{ steps.add-labels.outputs.unsupportedMajor }}
uses: actions-cool/issues-helper@200c78641dbf33838311e5a1e0c31bbdb92d7cf0 # v3.8.0
uses: actions-cool/issues-helper@71b62d7da76e59ff7b193904feb6e77d4dbb2777 # v3.7.6
with:
actions: 'create-comment'
token: ${{ steps.generate-token.outputs.token }}

View File

@@ -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

View File

@@ -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

View File

@@ -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=-

View File

@@ -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

View File

@@ -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 -b ~/.gitcookies "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,18 +60,15 @@ 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 -b ~/.gitcookies "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
shell: bash
run: |
echo "::add-matcher::src/electron/.github/problem-matchers/eslint-stylish.json"
echo "::add-matcher::src/electron/.github/problem-matchers/markdownlint.json"
- name: Run Lint
shell: bash

View File

@@ -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

View File

@@ -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@70fc10c6e5e1ce46ad2ea6f2b72d43f7d47b13c3
with:
name: out_gen_artifacts_${{ env.ARTIFACT_KEY }}
path: ./src/out/${{ env.ELECTRON_OUT_DIR }}/gen

View File

@@ -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

View File

@@ -165,7 +165,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

View File

@@ -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"

View File

@@ -48,8 +48,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:
@@ -175,12 +173,12 @@ jobs:
echo "DISABLE_CRASH_REPORTER_TESTS=true" >> $GITHUB_ENV
echo "IS_ASAN=true" >> $GITHUB_ENV
- name: Download Generated Artifacts
uses: actions/download-artifact@3e5f45b2cfb9172054b4087a40e8e0b5a5461e7c
uses: actions/download-artifact@70fc10c6e5e1ce46ad2ea6f2b72d43f7d47b13c3
with:
name: generated_artifacts_${{ env.ARTIFACT_KEY }}
path: ./generated_artifacts_${{ matrix.build-type }}_${{ inputs.target-arch }}
- name: Download Src Artifacts
uses: actions/download-artifact@3e5f45b2cfb9172054b4087a40e8e0b5a5461e7c
uses: actions/download-artifact@70fc10c6e5e1ce46ad2ea6f2b72d43f7d47b13c3
with:
name: src_artifacts_${{ env.ARTIFACT_KEY }}
path: ./src_artifacts_${{ matrix.build-type }}_${{ inputs.target-arch }}
@@ -216,7 +214,7 @@ jobs:
- name: Run Electron Tests
shell: bash
timeout-minutes: 60
timeout-minutes: 40
env:
MOCHA_REPORTER: mocha-multi-reporters
MOCHA_MULTI_REPORTERS: mocha-junit-reporter, tap
@@ -315,7 +313,7 @@ jobs:
if: always() && !cancelled()
- name: Upload Test Artifacts
if: always()
uses: actions/upload-artifact@bbbca2ddaa5d8feaa63e36b76fdaad77386f024f #v7.0.0
uses: actions/upload-artifact@bbbca2ddaa5d8feaa63e36b76fdaad77386f024f
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) }}
path: src/electron/spec/artifacts

View File

@@ -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@70fc10c6e5e1ce46ad2ea6f2b72d43f7d47b13c3
with:
name: generated_artifacts_${{ env.BUILD_TYPE }}_${{ env.TARGET_ARCH }}
path: ./generated_artifacts_${{ env.BUILD_TYPE }}_${{ env.TARGET_ARCH }}
- name: Download Src Artifacts
uses: actions/download-artifact@3e5f45b2cfb9172054b4087a40e8e0b5a5461e7c
uses: actions/download-artifact@70fc10c6e5e1ce46ad2ea6f2b72d43f7d47b13c3
with:
name: src_artifacts_linux_${{ env.TARGET_ARCH }}
path: ./src_artifacts_linux_${{ env.TARGET_ARCH }}
@@ -123,12 +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@70fc10c6e5e1ce46ad2ea6f2b72d43f7d47b13c3
with:
name: generated_artifacts_${{ env.BUILD_TYPE }}_${{ env.TARGET_ARCH }}
path: ./generated_artifacts_${{ env.BUILD_TYPE }}_${{ env.TARGET_ARCH }}
- name: Download Src Artifacts
uses: actions/download-artifact@3e5f45b2cfb9172054b4087a40e8e0b5a5461e7c
uses: actions/download-artifact@70fc10c6e5e1ce46ad2ea6f2b72d43f7d47b13c3
with:
name: src_artifacts_linux_${{ env.TARGET_ARCH }}
path: ./src_artifacts_linux_${{ env.TARGET_ARCH }}

View File

@@ -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',
});
}

View File

@@ -6,25 +6,16 @@ on:
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 == 'pull_request_target' && github.event.action == 'synchronize')
|| (github.event_name == 'pull_request_target' && 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:
@@ -37,7 +28,7 @@ jobs:
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
uses: dsanders11/project-actions/edit-item@2134fe7cc71c58b7ae259c82a8e63c6058255678 # v1.7.0
with:
token: ${{ steps.generate-token.outputs.token }}
project-number: 118

View File

@@ -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:
@@ -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@71b62d7da76e59ff7b193904feb6e77d4dbb2777 # v3.7.6
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 }}

View File

@@ -1,39 +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
if: ${{ !contains(github.event.pull_request.labels.*.name, 'needs-signed-commits')}}
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

View File

@@ -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@b1bff81932f5cdfc8695c7752dcee935dcd061c8 # v3.29.5
with:
sarif_file: results.sarif

View File

@@ -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

View File

@@ -61,7 +61,7 @@ jobs:
needs: checkout-windows
with:
environment: production-release
build-runs-on: electron-arc-centralus-windows-amd64-32core
build-runs-on: electron-arc-centralus-windows-amd64-16core
target-platform: win
target-arch: x64
is-release: true
@@ -80,7 +80,7 @@ jobs:
needs: checkout-windows
with:
environment: production-release
build-runs-on: electron-arc-centralus-windows-amd64-32core
build-runs-on: electron-arc-centralus-windows-amd64-16core
target-platform: win
target-arch: arm64
is-release: true
@@ -99,7 +99,7 @@ jobs:
needs: checkout-windows
with:
environment: production-release
build-runs-on: electron-arc-centralus-windows-amd64-32core
build-runs-on: electron-arc-centralus-windows-amd64-16core
target-platform: win
target-arch: x86
is-release: true

1
.gitignore vendored
View File

@@ -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

View File

@@ -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"
}
}
]
}

View File

@@ -9,8 +9,4 @@ npmMinimalAgeGate: 10080
npmPreapprovedPackages:
- "@electron/*"
httpProxy: "${HTTP_PROXY:-}"
httpsProxy: "${HTTPS_PROXY:-}"
yarnPath: .yarn/releases/yarn-4.12.0.cjs

View File

@@ -775,7 +775,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 +1017,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 +1070,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 +1174,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 +1226,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}" ]
}

View File

@@ -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.
@@ -210,13 +201,12 @@ gh label list --repo electron/electron --search target/ --json name,color --jq '
## Code Style
**C++:** Follows Chromium style, enforced by clang-format
**TypeScript/JavaScript:** [oxlint](https://oxc.rs/docs/guide/usage/linter) configuration in `.oxlintrc.json`
**TypeScript/JavaScript:** ESLint configuration in `.eslintrc.json`
**Linting:**
```bash
npm run lint # Run all linters
npm run lint:js # Run oxlint over all JS/TS/MJS sources
npm run lint:clang-format # C++ formatting
npm run lint:api-history # Validate API history YAML blocks in docs
```

4
DEPS
View File

@@ -2,9 +2,9 @@ gclient_gn_args_from = 'src'
vars = {
'chromium_version':
'148.0.7778.0',
'148.0.7733.0',
'node_version':
'v24.14.1',
'v24.14.0',
'nan_version':
'675cefebca42410733da8a454c8d9391fcebfbc2',
'squirrel.mac_version':

8
build/.eslintrc.json Normal file
View File

@@ -0,0 +1,8 @@
{
"plugins": [
"import"
],
"rules": {
"import/enforce-node-protocol-usage": ["error", "always"]
}
}

View File

@@ -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

View File

@@ -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",

View File

@@ -0,0 +1,8 @@
{
"plugins": [
"import"
],
"rules": {
"import/enforce-node-protocol-usage": ["error", "always"]
}
}

35
docs/.eslintrc.json Normal file
View 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"]
}
}

View File

@@ -615,11 +615,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

View File

@@ -28,10 +28,7 @@ added:
* `window` [BaseWindow](base-window.md) (optional)
* `options` Object
* `title` string (optional)
* `defaultPath` string (optional) - Absolute directory path, absolute file
path, or file name to use by default. If not provided, the dialog will
default to the user's Downloads folder, or their home directory if Downloads
doesn't exist.
* `defaultPath` string (optional)
* `buttonLabel` string (optional) - Custom label for the confirmation button, when
left empty the default label will be used.
* `filters` [FileFilter[]](structures/file-filter.md) (optional)
@@ -112,10 +109,7 @@ changes:
* `window` [BaseWindow](base-window.md) (optional)
* `options` Object
* `title` string (optional)
* `defaultPath` string (optional) - Absolute directory path, absolute file
path, or file name to use by default. If not provided, the dialog will
default to the user's Downloads folder, or their home directory if Downloads
doesn't exist.
* `defaultPath` string (optional)
* `buttonLabel` string (optional) - Custom label for the confirmation button, when
left empty the default label will be used.
* `filters` [FileFilter[]](structures/file-filter.md) (optional)
@@ -204,9 +198,7 @@ added:
* `options` Object
* `title` string (optional) - The dialog title. Cannot be displayed on some _Linux_ desktop environments.
* `defaultPath` string (optional) - Absolute directory path, absolute file
path, or file name to use by default. If not provided, the dialog will
default to the user's Downloads folder, or their home directory if Downloads
doesn't exist.
path, or file name to use by default.
* `buttonLabel` string (optional) - Custom label for the confirmation button, when
left empty the default label will be used.
* `filters` [FileFilter[]](structures/file-filter.md) (optional)
@@ -246,9 +238,7 @@ changes:
* `options` Object
* `title` string (optional) - The dialog title. Cannot be displayed on some _Linux_ desktop environments.
* `defaultPath` string (optional) - Absolute directory path, absolute file
path, or file name to use by default. If not provided, the dialog will
default to the user's Downloads folder, or their home directory if Downloads
doesn't exist.
path, or file name to use by default.
* `buttonLabel` string (optional) - Custom label for the confirmation button, when
left empty the default label will be used.
* `filters` [FileFilter[]](structures/file-filter.md) (optional)

View File

@@ -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.

View File

@@ -148,34 +148,3 @@ added:
-->
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.

View File

@@ -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`.
@@ -89,7 +89,7 @@ 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,11 +110,11 @@ 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`.
@@ -170,7 +170,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.

View File

@@ -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.

View File

@@ -84,7 +84,3 @@ 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).

View File

@@ -86,19 +86,15 @@ app.whenReady().then(() => {
* `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:

View File

@@ -56,15 +56,6 @@ app.whenReady().then(() => {
})
```
## Protocol names
[RFC 3986](https://www.rfc-editor.org/rfc/rfc3986#section-3.1) defines what a valid
protocol name is:
> Scheme names consist of a sequence of characters beginning with a letter and followed
> by any combination of letters, digits, plus ("+"), period ("."), or hyphen ("-").
> Although schemes are case-insensitive, the canonical form is lowercase […].
## Methods
The `protocol` module has the following methods:

View File

@@ -59,12 +59,7 @@ On Windows, returns true once the app has emitted the `ready` event.
### `safeStorage.isAsyncEncryptionAvailable()`
Returns `Promise<boolean>` - Resolves with whether encryption is available for
asynchronous safeStorage operations.
The asynchronous encryptor is initialized lazily the first time this method,
`encryptStringAsync`, or `decryptStringAsync` is called after the app is ready.
The returned promise resolves once initialization completes.
Returns `Promise<Boolean>` - Whether encryption is available for asynchronous safeStorage operations.
### `safeStorage.encryptString(plainText)`

View File

@@ -11,5 +11,3 @@
* `stream` boolean (optional) - Default false.
* `codeCache` boolean (optional) - Enable V8 code cache for the scheme, only
works when `standard` is also set to true. Default false.
* `allowExtensions` boolean (optional) - Allow Chrome extensions to be used
on pages served over this protocol. Default false.

View File

@@ -94,7 +94,6 @@
The actual output pixel format and color space of the texture should refer to [`OffscreenSharedTexture`](../structures/offscreen-shared-texture.md) object in the `paint` event.
* `argb` - The requested output texture format is 8-bit unorm RGBA, with SRGB SDR color space.
* `rgbaf16` - The requested output texture format is 16-bit float RGBA, with scRGB HDR color space.
* `nv12` - The requested output texture format is 12bpp with Y plane followed by a 2x2 interleaved UV plane, with REC709 color space.
* `deviceScaleFactor` number (optional) _Experimental_ - The device scale factor of the offscreen rendering output. If not set, will use `1` as default.
* `contextIsolation` boolean (optional) - Whether to run Electron APIs and
the specified `preload` script in a separate JavaScript context. Defaults

View File

@@ -12,34 +12,6 @@ This document uses the following convention to categorize breaking changes:
* **Deprecated:** An API was marked as deprecated. The API will continue to function, but will emit a deprecation warning, and will be removed in a future release.
* **Removed:** An API or feature was removed, and is no longer supported by Electron.
## Planned Breaking API Changes (43.0)
### Behavior Changed: Dialog methods default to Downloads directory
The `defaultPath` option for the following methods now defaults to the user's Downloads folder (or their home directory if Downloads doesn't exist) when not explicitly provided:
* `dialog.showOpenDialog`
* `dialog.showOpenDialogSync`
* `dialog.showSaveDialog`
* `dialog.showSaveDialogSync`
Previously, when no `defaultPath` was provided, the underlying OS file dialog would determine the initial directory — typically remembering the last directory the user navigated to, or falling back to an OS-specific default. Now, Electron explicitly sets the initial directory to Downloads, which also means the OS will no longer track and restore the last-used directory between dialog invocations.
To preserve the old behavior, you can track the last-used directory yourself and pass it as `defaultPath`:
```js
const path = require('node:path')
let lastUsedPath
const result = await dialog.showOpenDialog({
defaultPath: lastUsedPath
})
if (!result.canceled && result.filePaths.length > 0) {
lastUsedPath = path.dirname(result.filePaths[0])
}
```
## Planned Breaking API Changes (42.0)
### Behavior Changed: macOS notifications now use `UNNotification` API
@@ -98,9 +70,6 @@ npm install electron --save-dev
ELECTRON_INSTALL_PLATFORM=mas npx electron . --no
```
This also means the `ELECTRON_SKIP_BINARY_DOWNLOAD` environment variable is no
longer supported, as its primary purpose was to prevent the `postinstall` script from running.
### Removed: `quotas` object from `Session.clearStorageData(options)`
When calling `Session.clearStorageData(options)`, the `options.quotas` object is no longer supported because it has been

View File

@@ -3,7 +3,7 @@
These are the style guidelines for coding in Electron.
You can run `npm run lint` to show any style issues detected by `cpplint` and
`oxlint`.
`eslint`.
## General Code

View File

@@ -79,7 +79,7 @@ $ ../../electron/script/git-import-patches ../../electron/patches/node
$ ../../electron/script/git-export-patches -o ../../electron/patches/node
```
Note that `git-import-patches` will mark the commit that was `HEAD` when it was run as `refs/patches/upstream-head` (and a checkout-specific `refs/patches/upstream-head-<hash>` so that gclient worktrees sharing a `.git/refs` directory don't clobber each other). This lets you keep track of which commits are from Electron patches (those that come after `refs/patches/upstream-head`) and which commits are in upstream (those before `refs/patches/upstream-head`).
Note that `git-import-patches` will mark the commit that was `HEAD` when it was run as `refs/patches/upstream-head`. This lets you keep track of which commits are from Electron patches (those that come after `refs/patches/upstream-head`) and which commits are in upstream (those before `refs/patches/upstream-head`).
#### Resolving conflicts

View File

@@ -146,15 +146,13 @@ The extra privileges granted to the `file://` protocol by this fuse are incomple
The `wasmTrapHandlers` fuse controls whether V8 will use signal handlers to trap Out of Bounds memory
access from WebAssembly. The feature works by surrounding the WebAssembly memory with large guard regions
and then installing a signal handler that traps attempt to access memory in the guard region. The feature
is only supported on the following 64-bit systems:
is only supported on the following 64-bit systems.
* Linux, macOS, Windows - x86_64
* Linux, macOS - aarch64
Linux. MacOS, Windows - x86_64
Linux, MacOS - aarch64
```text
| Guard Pages | WASM heap | Guard Pages |
|-----8GB-----| |-----8GB-----|
```
When the fuse is disabled V8 will use explicit bound checks in the generated WebAssembly code to ensure
memory safety. However, this method has some downsides

View File

@@ -25,6 +25,16 @@ included in the `electron` package:
npx install-electron --no
```
If you want to install your project's dependencies but don't need to use
Electron functionality, you can set the `ELECTRON_SKIP_BINARY_DOWNLOAD` environment
variable to prevent the binary from being downloaded. For instance, this feature can
be useful in continuous integration environments when running unit tests that mock
out the `electron` module.
```sh
ELECTRON_SKIP_BINARY_DOWNLOAD=1 npm install
```
## Running Electron ad-hoc
If you're in a pinch and would prefer to not use `npm install` in your local

View File

@@ -87,13 +87,6 @@ if (!gotTheLock) {
// Create mainWindow, load the rest of the app, etc...
app.whenReady().then(() => {
createWindow()
// Check for deep link on cold start
if (process.argv.length >= 2) {
const lastArg = process.argv[process.argv.length - 1]
if (lastArg.startsWith('electron-fiddle://')) {
dialog.showErrorBox('Welcome Back', `You arrived from: ${lastArg}`)
}
}
})
}
```

View File

@@ -1097,8 +1097,7 @@ public:
Napi::Function func = DefineClass(env, "CppLinuxAddon", {
InstanceMethod("helloWorld", &CppAddon::HelloWorld),
InstanceMethod("helloGui", &CppAddon::HelloGui),
InstanceMethod("on", &CppAddon::On),
InstanceMethod("destroy", &CppAddon::Destroy)
InstanceMethod("on", &CppAddon::On)
});
Napi::FunctionReference *constructor = new Napi::FunctionReference();
@@ -1140,12 +1139,11 @@ private:
Here, we create a C++ class that inherits from `Napi::ObjectWrap<CppAddon>`:
`static Napi::Object Init` defines our JavaScript interface with four methods:
`static Napi::Object Init` defines our JavaScript interface with three methods:
* `helloWorld`: A simple function to test the bridge
* `helloGui`: The function to launch our GTK3 UI
* `on`: A method to register event callbacks
* `destroy`: A method to release all persistent references before app quit
The constructor initializes:
@@ -1356,8 +1354,7 @@ public:
Napi::Function func = DefineClass(env, "CppLinuxAddon", {
InstanceMethod("helloWorld", &CppAddon::HelloWorld),
InstanceMethod("helloGui", &CppAddon::HelloGui),
InstanceMethod("on", &CppAddon::On),
InstanceMethod("destroy", &CppAddon::Destroy)
InstanceMethod("on", &CppAddon::On)
});
Napi::FunctionReference *constructor = new Napi::FunctionReference();
@@ -1500,20 +1497,6 @@ private:
callbacks.Value().Set(info[0].As<Napi::String>(), info[1].As<Napi::Function>());
return env.Undefined();
}
Napi::Value Destroy(const Napi::CallbackInfo &info)
{
callbacks.Reset();
emitter.Reset();
if (tsfn_ != nullptr)
{
napi_release_threadsafe_function(tsfn_, napi_tsfn_abort);
tsfn_ = nullptr;
}
return info.Env().Undefined();
}
};
Napi::Object Init(Napi::Env env, Napi::Object exports)
@@ -1564,10 +1547,6 @@ class CppLinuxAddon extends EventEmitter {
return this.addon.helloGui()
}
destroy() {
this.addon.destroy()
}
// Parse JSON and convert date to JavaScript Date object
parse(payload) {
const parsed = JSON.parse(payload)
@@ -1590,12 +1569,8 @@ This wrapper:
* Only loads on Linux platforms
* Forwards events from C++ to JavaScript
* Provides clean methods to call into C++
* Provides a `destroy()` method to release native resources
* Converts JSON data into proper JavaScript objects
> [!IMPORTANT]
> You must call `destroy()` before the app quits (e.g. in the `will-quit` or `before-quit` event handler). Without this, persistent references to callbacks and the threadsafe function will prevent the native addon's destructor from running, causing Electron to hang on quit.
## 7) Building and testing the addon
With all files in place, you can build the addon:

View File

@@ -1099,8 +1099,7 @@ static Napi::Object Init(Napi::Env env, Napi::Object exports) {
Napi::Function func = DefineClass(env, "CppWin32Addon", {
InstanceMethod("helloWorld", &CppAddon::HelloWorld),
InstanceMethod("helloGui", &CppAddon::HelloGui),
InstanceMethod("on", &CppAddon::On),
InstanceMethod("destroy", &CppAddon::Destroy)
InstanceMethod("on", &CppAddon::On)
});
// ... rest of Init function
@@ -1118,21 +1117,9 @@ Napi::Value On(const Napi::CallbackInfo& info) {
callbacks.Value().Set(info[0].As<Napi::String>(), info[1].As<Napi::Function>());
return env.Undefined();
}
Napi::Value Destroy(const Napi::CallbackInfo& info) {
callbacks.Reset();
emitter.Reset();
if (tsfn_ != nullptr) {
napi_release_threadsafe_function(tsfn_, napi_tsfn_abort);
tsfn_ = nullptr;
}
return info.Env().Undefined();
}
```
This allows JavaScript to register callbacks for specific event types. The `Destroy` method releases all persistent references and aborts the threadsafe function, which must be called before the app quits to prevent the process from hanging.
This allows JavaScript to register callbacks for specific event types.
### Putting the bridge together
@@ -1274,18 +1261,6 @@ private:
callbacks.Value().Set(info[0].As<Napi::String>(), info[1].As<Napi::Function>());
return env.Undefined();
}
Napi::Value Destroy(const Napi::CallbackInfo& info) {
callbacks.Reset();
emitter.Reset();
if (tsfn_ != nullptr) {
napi_release_threadsafe_function(tsfn_, napi_tsfn_abort);
tsfn_ = nullptr;
}
return info.Env().Undefined();
}
};
Napi::Object Init(Napi::Env env, Napi::Object exports) {
@@ -1334,10 +1309,6 @@ class CppWin32Addon extends EventEmitter {
this.addon.helloGui()
}
destroy() {
this.addon.destroy()
}
#parse(payload) {
const parsed = JSON.parse(payload)
@@ -1352,9 +1323,6 @@ if (process.platform === 'win32') {
}
```
> [!IMPORTANT]
> You must call `destroy()` before the app quits (e.g. in the `will-quit` or `before-quit` event handler). Without this, persistent references to callbacks and the threadsafe function will prevent the native addon's destructor from running, causing Electron to hang on quit.
## 7) Building and Testing the Addon
With all files in place, you can build the addon:

View File

@@ -753,8 +753,7 @@ public:
Napi::Function func = DefineClass(env, "ObjcMacosAddon", {
InstanceMethod("helloWorld", &ObjcAddon::HelloWorld),
InstanceMethod("helloGui", &ObjcAddon::HelloGui),
InstanceMethod("on", &ObjcAddon::On),
InstanceMethod("destroy", &ObjcAddon::Destroy)
InstanceMethod("on", &ObjcAddon::On)
});
Napi::FunctionReference* constructor = new Napi::FunctionReference();
@@ -916,18 +915,6 @@ Napi::Value On(const Napi::CallbackInfo& info) {
callbacks.Value().Set(info[0].As<Napi::String>(), info[1].As<Napi::Function>());
return env.Undefined();
}
Napi::Value Destroy(const Napi::CallbackInfo& info) {
callbacks.Reset();
emitter.Reset();
if (tsfn_ != nullptr) {
napi_release_threadsafe_function(tsfn_, napi_tsfn_abort);
tsfn_ = nullptr;
}
return info.Env().Undefined();
}
```
Let's take a look at what we've added in this step:
@@ -935,11 +922,10 @@ Let's take a look at what we've added in this step:
* `HelloWorld()`: Takes a string input, calls our Objective-C function, and returns the result
* `HelloGui()`: A simple wrapper around the Objective-C `hello_gui` function
* `On`: Allows JavaScript to register event listeners that will be called when native events occur
* `Destroy`: Releases all persistent references (callbacks and emitter) and aborts the threadsafe function, allowing the addon to be properly cleaned up on quit
The `On` method is particularly important as it creates the event system that our JavaScript code will use to receive notifications from the native UI.
Together, these four components form a complete bridge between our Objective-C code and the JavaScript world, allowing bidirectional communication. Here's what the finished file should look like:
Together, these three components form a complete bridge between our Objective-C code and the JavaScript world, allowing bidirectional communication. Here's what the finished file should look like:
```objc title='src/objc_addon.mm'
#include <napi.h>
@@ -952,8 +938,7 @@ public:
Napi::Function func = DefineClass(env, "ObjcMacosAddon", {
InstanceMethod("helloWorld", &ObjcAddon::HelloWorld),
InstanceMethod("helloGui", &ObjcAddon::HelloGui),
InstanceMethod("on", &ObjcAddon::On),
InstanceMethod("destroy", &ObjcAddon::Destroy)
InstanceMethod("on", &ObjcAddon::On)
});
Napi::FunctionReference* constructor = new Napi::FunctionReference();
@@ -1076,18 +1061,6 @@ private:
callbacks.Value().Set(info[0].As<Napi::String>(), info[1].As<Napi::Function>());
return env.Undefined();
}
Napi::Value Destroy(const Napi::CallbackInfo& info) {
callbacks.Reset();
emitter.Reset();
if (tsfn_ != nullptr) {
napi_release_threadsafe_function(tsfn_, napi_tsfn_abort);
tsfn_ = nullptr;
}
return info.Env().Undefined();
}
};
Napi::Object Init(Napi::Env env, Napi::Object exports) {
@@ -1128,10 +1101,6 @@ class ObjcMacosAddon extends EventEmitter {
this.addon.helloGui()
}
destroy () {
this.addon.destroy()
}
parse (payload) {
const parsed = JSON.parse(payload)
@@ -1153,11 +1122,7 @@ This wrapper:
3. Loads the native addon
4. Sets up event listeners and forwards them
5. Provides a clean API for our functions
6. Provides a `destroy()` method to release native resources
7. Parses JSON payloads and converts timestamps to JavaScript Date objects
> [!IMPORTANT]
> You must call `destroy()` before the app quits (e.g. in the `will-quit` or `before-quit` event handler). Without this, persistent references to callbacks and the threadsafe function will prevent the native addon's destructor from running, causing Electron to hang on quit.
6. Parses JSON payloads and converts timestamps to JavaScript Date objects
## 7) Building and Testing the Addon

View File

@@ -752,8 +752,7 @@ public:
Napi::Function func = DefineClass(env, "SwiftAddon", {
InstanceMethod("helloWorld", &SwiftAddon::HelloWorld),
InstanceMethod("helloGui", &SwiftAddon::HelloGui),
InstanceMethod("on", &SwiftAddon::On),
InstanceMethod("destroy", &SwiftAddon::Destroy)
InstanceMethod("on", &SwiftAddon::On)
});
Napi::FunctionReference* constructor = new Napi::FunctionReference();
@@ -771,7 +770,7 @@ This first part:
1. Defines a C++ class that inherits from `Napi::ObjectWrap`
2. Creates a static `Init` method to register our class with Node.js
3. Defines four methods: `helloWorld`, `helloGui`, `on`, and `destroy`
3. Defines three methods: `helloWorld`, `helloGui`, and `on`
### Callback Mechanism
@@ -920,18 +919,6 @@ private:
callbacks.Value().Set(info[0].As<Napi::String>(), info[1].As<Napi::Function>());
return env.Undefined();
}
Napi::Value Destroy(const Napi::CallbackInfo& info) {
callbacks.Reset();
emitter.Reset();
if (tsfn_ != nullptr) {
napi_release_threadsafe_function(tsfn_, napi_tsfn_abort);
tsfn_ = nullptr;
}
return info.Env().Undefined();
}
};
Napi::Object Init(Napi::Env env, Napi::Object exports) {
@@ -947,8 +934,7 @@ This final part does multiple things:
2. The HelloWorld method implementation takes a string input from JavaScript, passes it to the Swift code, and returns the processed result back to the JavaScript environment.
3. The `HelloGui` method implementation provides a simple wrapper that calls the Swift UI creation function to display the native macOS window.
4. The `On` method implementation allows JavaScript code to register callback functions that will be invoked when specific events occur in the native Swift code.
5. The `Destroy` method releases all persistent references (callbacks and emitter) and aborts the threadsafe function. This must be called before the app quits to allow the destructor to run and prevent the process from hanging.
6. The code sets up the module initialization process that registers the addon with Node.js and makes its functionality available to JavaScript.
5. The code sets up the module initialization process that registers the addon with Node.js and makes its functionality available to JavaScript.
The final and full `src/swift_addon.mm` should look like:
@@ -963,8 +949,7 @@ public:
Napi::Function func = DefineClass(env, "SwiftAddon", {
InstanceMethod("helloWorld", &SwiftAddon::HelloWorld),
InstanceMethod("helloGui", &SwiftAddon::HelloGui),
InstanceMethod("on", &SwiftAddon::On),
InstanceMethod("destroy", &SwiftAddon::Destroy)
InstanceMethod("on", &SwiftAddon::On)
});
Napi::FunctionReference* constructor = new Napi::FunctionReference();
@@ -1089,18 +1074,6 @@ private:
callbacks.Value().Set(info[0].As<Napi::String>(), info[1].As<Napi::Function>());
return env.Undefined();
}
Napi::Value Destroy(const Napi::CallbackInfo& info) {
callbacks.Reset();
emitter.Reset();
if (tsfn_ != nullptr) {
napi_release_threadsafe_function(tsfn_, napi_tsfn_abort);
tsfn_ = nullptr;
}
return info.Env().Undefined();
}
};
Napi::Object Init(Napi::Env env, Napi::Object exports) {
@@ -1149,10 +1122,6 @@ class SwiftAddon extends EventEmitter {
this.addon.helloGui()
}
destroy () {
this.addon.destroy()
}
parse (payload) {
const parsed = JSON.parse(payload)
@@ -1174,11 +1143,7 @@ This wrapper:
3. Loads the native addon
4. Sets up event listeners and forwards them
5. Provides a clean API for our functions
6. Provides a `destroy()` method to release native resources
7. Parses JSON payloads and converts timestamps to JavaScript Date objects
> [!IMPORTANT]
> You must call `destroy()` before the app quits (e.g. in the `will-quit` or `before-quit` event handler). Without this, persistent references to callbacks and the threadsafe function will prevent the native addon's destructor from running, causing Electron to hang on quit.
6. Parses JSON payloads and converts timestamps to JavaScript Date objects
## 7) Building and Testing the Addon

View File

@@ -83,6 +83,17 @@ dependency.
npm install electron --save-dev
```
:::warning
In order to correctly install Electron, you need to ensure that its `postinstall` lifecycle
script is able to run. This means avoiding the `--ignore-scripts` flag on npm and allowlisting
`electron` to run build scripts on other package managers.
This is likely to change in a future version of Electron. See
[electron/rfcs#22](https://github.com/electron/rfcs/pull/22) for more details.
:::
Your package.json file should look something like this after initializing your package
and installing Electron. You should also now have a `node_modules` folder containing
the Electron executable, as well as a `package-lock.json` lockfile that specifies

View File

@@ -793,6 +793,8 @@ filenames = {
"shell/browser/extensions/electron_kiosk_delegate.h",
"shell/browser/extensions/electron_messaging_delegate.cc",
"shell/browser/extensions/electron_messaging_delegate.h",
"shell/browser/extensions/electron_navigation_ui_data.cc",
"shell/browser/extensions/electron_navigation_ui_data.h",
"shell/browser/extensions/electron_process_manager_delegate.cc",
"shell/browser/extensions/electron_process_manager_delegate.h",
"shell/common/extensions/electron_extensions_api_provider.cc",

View File

@@ -0,0 +1,21 @@
{
"rules": {
"no-restricted-imports": [
"error",
{
"paths": [
"electron",
"electron/renderer"
],
"patterns": [
"./*",
"../*",
"@electron/internal/isolated_renderer/*",
"@electron/internal/renderer/*",
"@electron/internal/sandboxed_worker/*",
"@electron/internal/worker/*"
]
}
]
}
}

View File

@@ -73,7 +73,6 @@ export async function getSources (args: Electron.SourcesOptions) {
capturer._onerror = (error: string) => {
stopRunning();
// eslint-disable-next-line prefer-promise-reject-errors
reject(error);
};

View File

@@ -790,7 +790,8 @@ WebContents.prototype._init = function () {
const originCounts = new Map<string, number>();
const openDialogs = new Set<AbortController>();
this.on('-run-dialog', async (info, callback) => {
const origin = info.frame.origin === 'file://' ? info.frame.url : info.frame.origin;
const originUrl = new URL(info.frame.url);
const origin = originUrl.protocol === 'file:' ? originUrl.href : originUrl.origin;
if ((originCounts.get(origin) ?? 0) < 0) return callback(false, '');
const prefs = this.getLastWebPreferences();

View File

@@ -17,6 +17,11 @@ export type WindowOpenArgs = {
features: string,
}
const frameNamesToWindow = new Map<string, WebContents>();
const registerFrameNameToGuestWindow = (name: string, webContents: WebContents) => frameNamesToWindow.set(name, webContents);
const unregisterFrameName = (name: string) => frameNamesToWindow.delete(name);
const getGuestWebContentsByFrameName = (name: string) => frameNamesToWindow.get(name);
/**
* `openGuestWindow` is called to create and setup event handling for the new
* window.
@@ -42,6 +47,20 @@ export function openGuestWindow ({ embedder, guest, referrer, disposition, postD
...overrideBrowserWindowOptions
};
// To spec, subsequent window.open calls with the same frame name (`target` in
// spec parlance) will reuse the previous window.
// https://html.spec.whatwg.org/multipage/window-object.html#apis-for-creating-and-navigating-browsing-contexts-by-name
const existingWebContents = getGuestWebContentsByFrameName(frameName);
if (existingWebContents) {
if (existingWebContents.isDestroyed()) {
// FIXME(t57ser): The webContents is destroyed for some reason, unregister the frame name
unregisterFrameName(frameName);
} else {
existingWebContents.loadURL(url);
return;
}
}
if (createWindow) {
const webContents = createWindow({
webContents: guest,
@@ -53,7 +72,7 @@ export function openGuestWindow ({ embedder, guest, referrer, disposition, postD
throw new Error('Invalid webContents. Created window should be connected to webContents passed with options object.');
}
handleWindowLifecycleEvents({ embedder, guest, outlivesOpener });
handleWindowLifecycleEvents({ embedder, frameName, guest, outlivesOpener });
}
return;
@@ -77,7 +96,7 @@ export function openGuestWindow ({ embedder, guest, referrer, disposition, postD
});
}
handleWindowLifecycleEvents({ embedder, guest: window.webContents, outlivesOpener });
handleWindowLifecycleEvents({ embedder, frameName, guest: window.webContents, outlivesOpener });
embedder.emit('did-create-window', window, { url, frameName, options: browserWindowOptions, disposition, referrer, postData });
}
@@ -88,9 +107,10 @@ export function openGuestWindow ({ embedder, guest, referrer, disposition, postD
* too is the guest destroyed; this is Electron convention and isn't based in
* browser behavior.
*/
const handleWindowLifecycleEvents = function ({ embedder, guest, outlivesOpener }: {
const handleWindowLifecycleEvents = function ({ embedder, guest, frameName, outlivesOpener }: {
embedder: WebContents,
guest: WebContents,
frameName: string,
outlivesOpener: boolean
}) {
const closedByEmbedder = function () {
@@ -108,6 +128,13 @@ const handleWindowLifecycleEvents = function ({ embedder, guest, outlivesOpener
embedder.once('current-render-view-deleted' as any, closedByEmbedder);
}
guest.once('destroyed', closedByUser);
if (frameName) {
registerFrameNameToGuestWindow(frameName, guest);
guest.once('destroyed', function () {
unregisterFrameName(frameName);
});
}
};
// Security options that child windows will always inherit from parent windows

23
lib/common/.eslintrc.json Normal file
View File

@@ -0,0 +1,23 @@
{
"rules": {
"no-restricted-imports": [
"error",
{
"paths": [
"electron",
"electron/main",
"electron/renderer"
],
"patterns": [
"./*",
"../*",
"@electron/internal/browser/*",
"@electron/internal/isolated_renderer/*",
"@electron/internal/renderer/*",
"@electron/internal/sandboxed_worker/*",
"@electron/internal/worker/*"
]
}
]
}
}

View File

@@ -0,0 +1,18 @@
{
"rules": {
"no-restricted-imports": [
"error",
{
"paths": [
"electron",
"electron/main"
],
"patterns": [
"./*",
"../*",
"@electron/internal/browser/*"
]
}
]
}
}

View File

@@ -0,0 +1,18 @@
{
"rules": {
"no-restricted-imports": [
"error",
{
"paths": [
"electron",
"electron/main"
],
"patterns": [
"./*",
"../*",
"@electron/internal/browser/*"
]
}
]
}
}

View File

@@ -0,0 +1,18 @@
{
"rules": {
"no-restricted-imports": [
"error",
{
"paths": [
"electron",
"electron/main"
],
"patterns": [
"./*",
"../*",
"@electron/internal/browser/*"
]
}
]
}
}

View File

@@ -124,9 +124,7 @@ if (nodeIntegration) {
delete (global as any).setImmediate;
delete (global as any).clearImmediate;
delete (global as any).global;
// eslint-disable-next-line n/no-deprecated-api
delete (global as any).root;
// eslint-disable-next-line n/no-deprecated-api
delete (global as any).GLOBAL;
});
}

View File

@@ -0,0 +1,18 @@
{
"rules": {
"no-restricted-imports": [
"error",
{
"paths": [
"electron",
"electron/main"
],
"patterns": [
"./*",
"../*",
"@electron/internal/browser/*"
]
}
]
}
}

View File

@@ -90,7 +90,6 @@ export function executeSandboxedPreloadScripts (context: PreloadContext, preload
if (contents) {
runPreloadScript(context, contents);
} else if (error) {
// eslint-disable-next-line no-throw-literal
throw error;
}
} catch (error) {

View File

@@ -0,0 +1,21 @@
{
"rules": {
"no-restricted-imports": [
"error",
{
"paths": [
"electron",
"electron/renderer"
],
"patterns": [
"./*",
"../*",
"@electron/internal/isolated_renderer/*",
"@electron/internal/renderer/*",
"@electron/internal/sandboxed_worker/*",
"@electron/internal/worker/*"
]
}
]
}
}

18
lib/worker/.eslintrc.json Normal file
View File

@@ -0,0 +1,18 @@
{
"rules": {
"no-restricted-imports": [
"error",
{
"paths": [
"electron",
"electron/main"
],
"patterns": [
"./*",
"../*",
"@electron/internal/browser/*"
]
}
]
}
}

View File

@@ -11,6 +11,10 @@ const path = require('path');
const { version } = require('./package');
if (process.env.ELECTRON_SKIP_BINARY_DOWNLOAD) {
process.exit(0);
}
const platformPath = getPlatformPath();
if (isInstalled()) {

View File

@@ -6,7 +6,7 @@
"install-electron": "install.js"
},
"dependencies": {
"@electron/get": "^4.0.3",
"@electron/get": "^2.0.0",
"@types/node": "^24.9.0",
"extract-zip": "^2.0.1"
},

View File

@@ -5,7 +5,7 @@
"description": "Build cross platform desktop apps with JavaScript, HTML, and CSS",
"devDependencies": {
"@azure/storage-blob": "^12.28.0",
"@datadog/datadog-ci": "^5.9.1",
"@datadog/datadog-ci": "^4.1.2",
"@electron/asar": "^4.0.1",
"@electron/docs-parser": "^2.0.0",
"@electron/fiddle-core": "^1.3.4",
@@ -13,18 +13,27 @@
"@electron/lint-roller": "^3.2.0",
"@electron/typescript-definitions": "^9.1.5",
"@hurdlegroup/robotjs": "^0.12.3",
"@octokit/rest": "^22.0.1",
"@octokit/rest": "^20.1.2",
"@primer/octicons": "^10.0.0",
"@sentry/cli": "1.72.0",
"@types/minimist": "^1.2.5",
"@types/node": "^24.9.0",
"@types/semver": "^7.5.8",
"@types/stream-json": "^1.7.8",
"@types/temp": "^0.9.4",
"@typescript-eslint/eslint-plugin": "^8.32.1",
"@typescript-eslint/parser": "^8.7.0",
"@xmldom/xmldom": "^0.8.11",
"buffer": "^6.0.3",
"chalk": "^4.1.0",
"check-for-leaks": "^1.2.1",
"eslint": "^8.57.1",
"eslint-config-standard": "^17.1.0",
"eslint-plugin-import": "^2.32.0",
"eslint-plugin-markdown": "^5.1.0",
"eslint-plugin-mocha": "^10.5.0",
"eslint-plugin-n": "^16.6.2",
"eslint-plugin-node": "^11.1.0",
"eslint-plugin-promise": "^6.6.0",
"events": "^3.2.0",
"folder-hash": "^4.1.2",
"got": "^11.8.5",
@@ -34,7 +43,6 @@
"minimist": "^1.2.8",
"node-gyp": "^11.4.2",
"null-loader": "^4.0.1",
"oxlint": "^1.57.0",
"pre-flight": "^2.0.0",
"process": "^0.11.10",
"semver": "^7.6.3",
@@ -145,9 +153,6 @@
"spec/fixtures/native-addon/*"
],
"dependenciesMeta": {
"@sentry/cli": {
"built": true
},
"abstract-socket": {
"built": true
}

View File

@@ -10,10 +10,10 @@ this patch is required to provide ripemd160 support in the nodejs crypto
module.
diff --git a/crypto/digest/digest_extra.cc b/crypto/digest/digest_extra.cc
index d38e0c1132da60ec96c3a5c2416ff07589f03b80..cd60baaf22a8d5dc20544d861d36b7d74d986e7b 100644
index 17961ba6bd9de78b5b1b1008eb1f73babd49d0e7..6a870dce37df8f49106c24b183308a2c7a03fd7d 100644
--- a/crypto/digest/digest_extra.cc
+++ b/crypto/digest/digest_extra.cc
@@ -48,6 +48,7 @@ static const struct nid_to_digest nid_to_digest_mapping[] = {
@@ -47,6 +47,7 @@ static const struct nid_to_digest nid_to_digest_mapping[] = {
{NID_sha512, EVP_sha512, SN_sha512, LN_sha512},
{NID_sha512_256, EVP_sha512_256, SN_sha512_256, LN_sha512_256},
{NID_md5_sha1, EVP_md5_sha1, SN_md5_sha1, LN_md5_sha1},
@@ -62,10 +62,10 @@ index a246a51103701e0ac8a0722324350a462f95bcc9..ddf0a90337d4e40de09bc345cf959dff
+
#undef CHECK
diff --git a/decrepit/evp/evp_do_all.cc b/decrepit/evp/evp_do_all.cc
index 584b1390a841cc1b1dcb69e16d8242a88e4bb9cb..637aeccb8de8d793eabc38e32bef6834ac0e6ad3 100644
index feaf17c72cecb8099bc11ac10747fbad719ddca9..891a73f229e3f0838cb2fa99b8fb24fdeac1962b 100644
--- a/decrepit/evp/evp_do_all.cc
+++ b/decrepit/evp/evp_do_all.cc
@@ -82,6 +82,7 @@ void EVP_MD_do_all_sorted(void (*callback)(const EVP_MD *md,
@@ -79,6 +79,7 @@ void EVP_MD_do_all_sorted(void (*callback)(const EVP_MD *cipher,
callback(EVP_sha384(), "SHA384", nullptr, arg);
callback(EVP_sha512(), "SHA512", nullptr, arg);
callback(EVP_sha512_256(), "SHA512-256", nullptr, arg);
@@ -73,16 +73,16 @@ index 584b1390a841cc1b1dcb69e16d8242a88e4bb9cb..637aeccb8de8d793eabc38e32bef6834
callback(EVP_md4(), "md4", nullptr, arg);
callback(EVP_md5(), "md5", nullptr, arg);
@@ -91,6 +92,7 @@ void EVP_MD_do_all_sorted(void (*callback)(const EVP_MD *md,
@@ -88,6 +89,7 @@ void EVP_MD_do_all_sorted(void (*callback)(const EVP_MD *cipher,
callback(EVP_sha384(), "sha384", nullptr, arg);
callback(EVP_sha512(), "sha512", nullptr, arg);
callback(EVP_sha512_256(), "sha512-256", nullptr, arg);
+ callback(EVP_ripemd160(), "ripemd160", nullptr, arg);
}
void EVP_MD_do_all(void (*callback)(const EVP_MD *md, const char *name,
void EVP_MD_do_all(void (*callback)(const EVP_MD *cipher, const char *name,
diff --git a/include/openssl/digest.h b/include/openssl/digest.h
index 62ad57368cb3059ee25df08bb07876fef499de2e..322daef194b3c7b73011419bb74bccb311eb03a5 100644
index 40670234682ac00dec268dea43f0ee1e39e8684f..293fbc9faf01ea0ca4e58b0a65b14597fe4916a6 100644
--- a/include/openssl/digest.h
+++ b/include/openssl/digest.h
@@ -48,6 +48,9 @@ OPENSSL_EXPORT const EVP_MD *EVP_blake2b256(void);

View File

@@ -64,10 +64,10 @@ index dabc54aa13745600a62e57ecbb427e48a4565282..ce213e00573102ce9405a794d3c140d9
const EVP_CIPHER *EVP_get_cipherbynid(int nid) {
diff --git a/decrepit/evp/evp_do_all.cc b/decrepit/evp/evp_do_all.cc
index 637aeccb8de8d793eabc38e32bef6834ac0e6ad3..c5dd0b18d7338457e47ae47088d9822472b24212 100644
index 891a73f229e3f0838cb2fa99b8fb24fdeac1962b..f7d0c5dc66f016eb9338c15e7f5ef59e6de2969d 100644
--- a/decrepit/evp/evp_do_all.cc
+++ b/decrepit/evp/evp_do_all.cc
@@ -23,8 +23,10 @@ void EVP_CIPHER_do_all_sorted(void (*callback)(const EVP_CIPHER *cipher,
@@ -20,8 +20,10 @@ void EVP_CIPHER_do_all_sorted(void (*callback)(const EVP_CIPHER *cipher,
const char *unused, void *arg),
void *arg) {
callback(EVP_aes_128_cbc(), "AES-128-CBC", nullptr, arg);
@@ -78,7 +78,7 @@ index 637aeccb8de8d793eabc38e32bef6834ac0e6ad3..c5dd0b18d7338457e47ae47088d98224
callback(EVP_aes_128_ctr(), "AES-128-CTR", nullptr, arg);
callback(EVP_aes_192_ctr(), "AES-192-CTR", nullptr, arg);
callback(EVP_aes_256_ctr(), "AES-256-CTR", nullptr, arg);
@@ -37,9 +39,13 @@ void EVP_CIPHER_do_all_sorted(void (*callback)(const EVP_CIPHER *cipher,
@@ -34,9 +36,13 @@ void EVP_CIPHER_do_all_sorted(void (*callback)(const EVP_CIPHER *cipher,
callback(EVP_aes_128_gcm(), "AES-128-GCM", nullptr, arg);
callback(EVP_aes_192_gcm(), "AES-192-GCM", nullptr, arg);
callback(EVP_aes_256_gcm(), "AES-256-GCM", nullptr, arg);
@@ -92,7 +92,7 @@ index 637aeccb8de8d793eabc38e32bef6834ac0e6ad3..c5dd0b18d7338457e47ae47088d98224
callback(EVP_des_ede_cbc(), "DES-EDE-CBC", nullptr, arg);
callback(EVP_des_ede3_cbc(), "DES-EDE3-CBC", nullptr, arg);
callback(EVP_rc2_cbc(), "RC2-CBC", nullptr, arg);
@@ -47,8 +53,10 @@ void EVP_CIPHER_do_all_sorted(void (*callback)(const EVP_CIPHER *cipher,
@@ -44,8 +50,10 @@ void EVP_CIPHER_do_all_sorted(void (*callback)(const EVP_CIPHER *cipher,
// OpenSSL returns everything twice, the second time in lower case.
callback(EVP_aes_128_cbc(), "aes-128-cbc", nullptr, arg);
@@ -103,7 +103,7 @@ index 637aeccb8de8d793eabc38e32bef6834ac0e6ad3..c5dd0b18d7338457e47ae47088d98224
callback(EVP_aes_128_ctr(), "aes-128-ctr", nullptr, arg);
callback(EVP_aes_192_ctr(), "aes-192-ctr", nullptr, arg);
callback(EVP_aes_256_ctr(), "aes-256-ctr", nullptr, arg);
@@ -61,9 +69,13 @@ void EVP_CIPHER_do_all_sorted(void (*callback)(const EVP_CIPHER *cipher,
@@ -58,9 +66,13 @@ void EVP_CIPHER_do_all_sorted(void (*callback)(const EVP_CIPHER *cipher,
callback(EVP_aes_128_gcm(), "aes-128-gcm", nullptr, arg);
callback(EVP_aes_192_gcm(), "aes-192-gcm", nullptr, arg);
callback(EVP_aes_256_gcm(), "aes-256-gcm", nullptr, arg);

View File

@@ -52,6 +52,7 @@ adjust_accessibility_ui_for_electron.patch
worker_feat_add_hook_to_notify_script_ready.patch
chore_provide_iswebcontentscreationoverridden_with_full_params.patch
fix_properly_honor_printing_page_ranges.patch
export_gin_v8platform_pageallocator_for_usage_outside_of_the_gin.patch
fix_export_zlib_symbols.patch
web_contents.patch
webview_fullscreen.patch
@@ -103,6 +104,7 @@ chore_remove_check_is_test_on_script_injection_tracker.patch
fix_restore_original_resize_performance_on_macos.patch
feat_allow_code_cache_in_custom_schemes.patch
build_run_reclient_cfg_generator_after_chrome.patch
fix_getcursorscreenpoint_wrongly_returns_0_0.patch
fix_add_support_for_skipping_first_2_no-op_refreshes_in_thumb_cap.patch
refactor_expose_file_system_access_blocklist.patch
feat_add_support_for_missing_dialog_features_to_shell_dialogs.patch
@@ -119,13 +121,14 @@ build_disable_thin_lto_mac.patch
feat_corner_smoothing_css_rule_and_blink_painting.patch
build_add_public_config_simdutf_config.patch
fix_multiple_scopedpumpmessagesinprivatemodes_instances.patch
fix_handle_embedder_windows_shown_after_webcontentsviewcocoa_attach.patch
revert_code_health_clean_up_stale_macwebcontentsocclusion.patch
feat_add_signals_when_embedder_cleanup_callbacks_run_for.patch
feat_separate_content_settings_callback_for_sync_and_async_clipboard.patch
fix_win32_synchronous_spellcheck.patch
chore_grandfather_in_electron_views_and_delegates.patch
refactor_patch_electron_permissiontypes_into_blink.patch
revert_views_remove_desktopwindowtreehostwin_window_enlargement.patch
build_partial_revert_mac_fullscreen_top_chrome_mouse_events.patch
fix_add_macos_memory_query_fallback_to_avoid_crash.patch
fix_resolve_dynamic_background_material_update_issue_on_windows_11.patch
feat_add_support_for_embedder_snapshot_validation.patch
@@ -145,9 +148,5 @@ fix_wayland_test_crash_on_teardown.patch
fix_set_correct_app_id_on_linux.patch
fix_pass_trigger_for_global_shortcuts_on_wayland.patch
feat_plumb_node_integration_in_worker_through_workersettings.patch
feat_restore_macos_child_plugin_process.patch
fix_restore_sdk_inputs_cross-toolchain_deps_for_macos.patch
fix_use_fresh_lazynow_for_onendworkitemimpl_after_didruntask.patch
fix_pulseaudio_stream_and_icon_names.patch
fix_fire_menu_popup_start_for_dynamically_created_aria_menus.patch
feat_allow_enabling_extensions_on_custom_protocols.patch
fix_initialize_com_on_desktopmedialistcapturethread_on_windows.patch

View File

@@ -10,10 +10,10 @@ Allows Electron to restore WER when ELECTRON_DEFAULT_ERROR_MODE is set.
This should be upstreamed.
diff --git a/content/gpu/gpu_main.cc b/content/gpu/gpu_main.cc
index 26619daf25f3cc455d2dba7b5f16c9449e6103c1..387fca1b54b818a5af435e96bf8f435e2963fe39 100644
index 7265019647734154f64108efd7e6376b7a9fc1ba..398aaff3af5bff791f114e4023d0e07be86dd79a 100644
--- a/content/gpu/gpu_main.cc
+++ b/content/gpu/gpu_main.cc
@@ -277,6 +277,10 @@ int GpuMain(MainFunctionParams parameters) {
@@ -272,6 +272,10 @@ int GpuMain(MainFunctionParams parameters) {
// to the GpuProcessHost once the GpuServiceImpl has started.
viz::GpuLogMessageManager::GetInstance()->InstallPreInitializeLogHandler();
@@ -24,7 +24,7 @@ index 26619daf25f3cc455d2dba7b5f16c9449e6103c1..387fca1b54b818a5af435e96bf8f435e
// We are experiencing what appear to be memory-stomp issues in the GPU
// process. These issues seem to be impacting the task executor and listeners
// registered to it. Create the task executor on the heap to guard against
@@ -385,7 +389,6 @@ int GpuMain(MainFunctionParams parameters) {
@@ -380,7 +384,6 @@ int GpuMain(MainFunctionParams parameters) {
#endif
const bool dead_on_arrival = !init_success;
@@ -33,7 +33,7 @@ index 26619daf25f3cc455d2dba7b5f16c9449e6103c1..387fca1b54b818a5af435e96bf8f435e
client->PostSandboxInitialized();
}
diff --git a/content/public/gpu/content_gpu_client.h b/content/public/gpu/content_gpu_client.h
index ad511f0966c29e46a1e4c07e09c3172b38c7c906..ca3a35d213147c6fcb9fbbbe118c15a3075875fa 100644
index e5389b44df98ab1a5c976524a66a26c763e5c436..4a183b4959fae18e6875440e6570b8ada6823d81 100644
--- a/content/public/gpu/content_gpu_client.h
+++ b/content/public/gpu/content_gpu_client.h
@@ -36,6 +36,10 @@ class CONTENT_EXPORT ContentGpuClient {

View File

@@ -10,7 +10,7 @@ DidCreateScriptContext is called, not all JS APIs are available in the
context, which can cause some preload scripts to trip.
diff --git a/content/public/renderer/render_frame_observer.h b/content/public/renderer/render_frame_observer.h
index 3f8cf4edc7448e6b584adae8fcbb872d27377126..1d03dc809d4c18f24314d94811e0bf527aa7b5b4 100644
index 8077ed85e45e56d6cccb691223216c1f6a94b5ee..dd4cee346f16df703d414bf206bbe6c9f4b1f796 100644
--- a/content/public/renderer/render_frame_observer.h
+++ b/content/public/renderer/render_frame_observer.h
@@ -141,6 +141,8 @@ class CONTENT_EXPORT RenderFrameObserver {
@@ -23,10 +23,10 @@ index 3f8cf4edc7448e6b584adae8fcbb872d27377126..1d03dc809d4c18f24314d94811e0bf52
int32_t world_id) {}
virtual void DidClearWindowObject() {}
diff --git a/content/renderer/render_frame_impl.cc b/content/renderer/render_frame_impl.cc
index ab959e66f8841d7367863bb13d6c7a0854d0df23..5279ba15f45bd7634b5f24553ad64c0069318cc0 100644
index 42a0a7e5be01fe346cc2ad83d3395425a41e1699..40d1f104794795dba6cd59518819e98a4cdbfc44 100644
--- a/content/renderer/render_frame_impl.cc
+++ b/content/renderer/render_frame_impl.cc
@@ -4733,6 +4733,12 @@ void RenderFrameImpl::DidCreateScriptContext(v8::Local<v8::Context> context,
@@ -4769,6 +4769,12 @@ void RenderFrameImpl::DidCreateScriptContext(v8::Local<v8::Context> context,
observer.DidCreateScriptContext(context, world_id);
}
@@ -40,10 +40,10 @@ index ab959e66f8841d7367863bb13d6c7a0854d0df23..5279ba15f45bd7634b5f24553ad64c00
int world_id) {
for (auto& observer : observers_)
diff --git a/content/renderer/render_frame_impl.h b/content/renderer/render_frame_impl.h
index 1733f28e69b331b33f36084391f1d3ddb47c8e14..2ce05bce0a02338aba018c18f0a808a4eb392ff4 100644
index c803bf1d93bb9aabf0f9098c4d58aa7528d18d79..ced097d57cec93b3d3062a6d7d9f7d037a355e6c 100644
--- a/content/renderer/render_frame_impl.h
+++ b/content/renderer/render_frame_impl.h
@@ -607,6 +607,8 @@ class CONTENT_EXPORT RenderFrameImpl
@@ -606,6 +606,8 @@ class CONTENT_EXPORT RenderFrameImpl
void DidObserveLayoutShift(double score, bool after_input_or_scroll) override;
void DidCreateScriptContext(v8::Local<v8::Context> context,
int world_id) override;
@@ -53,10 +53,10 @@ index 1733f28e69b331b33f36084391f1d3ddb47c8e14..2ce05bce0a02338aba018c18f0a808a4
int world_id) override;
void DidChangeScrollOffset() override;
diff --git a/third_party/blink/public/web/web_local_frame_client.h b/third_party/blink/public/web/web_local_frame_client.h
index 0f218d3f96f0c3a3a5773937e50ba9e8d7df0498..27b21f02d2dbfd60cb64f09be393b0e50928756f 100644
index 7e5f1d80ff5395ea11eb558acabe63ccc3e5a17e..d241042fc37ffe4a2afecbc3c02e89f18e990929 100644
--- a/third_party/blink/public/web/web_local_frame_client.h
+++ b/third_party/blink/public/web/web_local_frame_client.h
@@ -675,6 +675,9 @@ class BLINK_EXPORT WebLocalFrameClient {
@@ -674,6 +674,9 @@ class BLINK_EXPORT WebLocalFrameClient {
virtual void DidCreateScriptContext(v8::Local<v8::Context>,
int32_t world_id) {}
@@ -79,10 +79,10 @@ index d293c49e6774de889fa9959234c82b41a4b1efe1..0787bc8a602c60e5b42933813baa6b9d
if (World().IsMainWorld()) {
probe::DidCreateMainWorldContext(GetFrame());
diff --git a/third_party/blink/renderer/core/frame/local_frame_client.h b/third_party/blink/renderer/core/frame/local_frame_client.h
index a68832975b5d359f7eddaf2326bd47ff1e7e18df..ae565a4d3fdc2d02e2c7a27312d8296bbdf61e0b 100644
index 52cc48e0099ded3686c6fc056514b6446afcae5d..a6331653b0aaf30cedba6ff6df787aa944142ac4 100644
--- a/third_party/blink/renderer/core/frame/local_frame_client.h
+++ b/third_party/blink/renderer/core/frame/local_frame_client.h
@@ -310,6 +310,8 @@ class CORE_EXPORT LocalFrameClient : public FrameClient {
@@ -309,6 +309,8 @@ class CORE_EXPORT LocalFrameClient : public FrameClient {
virtual void DidCreateScriptContext(v8::Local<v8::Context>,
int32_t world_id) = 0;
@@ -92,7 +92,7 @@ index a68832975b5d359f7eddaf2326bd47ff1e7e18df..ae565a4d3fdc2d02e2c7a27312d8296b
int32_t world_id) = 0;
virtual bool AllowScriptExtensions() = 0;
diff --git a/third_party/blink/renderer/core/frame/local_frame_client_impl.cc b/third_party/blink/renderer/core/frame/local_frame_client_impl.cc
index 5e5e43e204f006989a859a6077dcb56c81a08e60..aaf03855e53d5529bb51d70cd9b4355d68fed48c 100644
index ebf1c82da02efbe73f1bb7b20cb1011c1bd7a335..26410fc221baf1fadb6220eb653c651b47fb3da7 100644
--- a/third_party/blink/renderer/core/frame/local_frame_client_impl.cc
+++ b/third_party/blink/renderer/core/frame/local_frame_client_impl.cc
@@ -301,6 +301,13 @@ void LocalFrameClientImpl::DidCreateScriptContext(
@@ -110,7 +110,7 @@ index 5e5e43e204f006989a859a6077dcb56c81a08e60..aaf03855e53d5529bb51d70cd9b4355d
v8::Local<v8::Context> context,
int32_t world_id) {
diff --git a/third_party/blink/renderer/core/frame/local_frame_client_impl.h b/third_party/blink/renderer/core/frame/local_frame_client_impl.h
index b00211cf215fb820b3fe49139b8ef95be6a10d21..cc593168947e469b599794260692e1deb9b5f1a5 100644
index 9bdfacfc0270bf4ac3a965f6308e4cfc19193f4f..ea9e16b6dd6c96333c653fc602edfbd84cd9e5de 100644
--- a/third_party/blink/renderer/core/frame/local_frame_client_impl.h
+++ b/third_party/blink/renderer/core/frame/local_frame_client_impl.h
@@ -78,6 +78,8 @@ class CORE_EXPORT LocalFrameClientImpl final : public LocalFrameClient {
@@ -123,10 +123,10 @@ index b00211cf215fb820b3fe49139b8ef95be6a10d21..cc593168947e469b599794260692e1de
int32_t world_id) override;
diff --git a/third_party/blink/renderer/core/loader/empty_clients.h b/third_party/blink/renderer/core/loader/empty_clients.h
index bcdcc5f04edaf06d89375b05eb2d5f6bfa3d3237..5a0f42b4b7e5eb67d476c948caa201ee6fc7b3ca 100644
index 1f9061d660d7395a6a9e32d783228fc5ae85c898..f762722e2e2a27db2488aae25d78e79598f6a4b4 100644
--- a/third_party/blink/renderer/core/loader/empty_clients.h
+++ b/third_party/blink/renderer/core/loader/empty_clients.h
@@ -425,6 +425,8 @@ class CORE_EXPORT EmptyLocalFrameClient : public LocalFrameClient {
@@ -422,6 +422,8 @@ class CORE_EXPORT EmptyLocalFrameClient : public LocalFrameClient {
void DidCreateScriptContext(v8::Local<v8::Context>,
int32_t world_id) override {}

View File

@@ -7,10 +7,10 @@ Ensure that licenses for the dependencies introduced by Electron
are included in `LICENSES.chromium.html`
diff --git a/tools/licenses/licenses.py b/tools/licenses/licenses.py
index 4272e2ab96c64b1970e1cf035a3385893b1f2f0c..387fa19ca4ea8aace08bfef67d4b7c0870ad1d23 100755
index f87d1ffc90ba5bd6da87a90c6dd904c01ae42e23..9987b33124cfec689502f991b92c0b05d0433106 100755
--- a/tools/licenses/licenses.py
+++ b/tools/licenses/licenses.py
@@ -354,6 +354,31 @@ SPECIAL_CASES = {
@@ -355,6 +355,31 @@ SPECIAL_CASES = {
"License": "Apache 2.0",
"License File": ["//third_party/sample3/the_license"],
},

Some files were not shown because too many files have changed in this diff Show More