mirror of
https://github.com/electron/electron.git
synced 2026-04-10 03:01:51 -04:00
Compare commits
39 Commits
menu-item-
...
build-win-
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
3e7cbfee95 | ||
|
|
44b0789530 | ||
|
|
038f610ef8 | ||
|
|
9f58248ac5 | ||
|
|
1f6c061d0e | ||
|
|
76a4adbe1c | ||
|
|
695b375cc9 | ||
|
|
cab27faeee | ||
|
|
ed8cdca6c7 | ||
|
|
f87cbacea4 | ||
|
|
0e93e65759 | ||
|
|
aa74829cea | ||
|
|
d4b50302c6 | ||
|
|
44c52506b9 | ||
|
|
4ade686dc0 | ||
|
|
f7fdbbdf36 | ||
|
|
d2f0ebc159 | ||
|
|
ac4307d32a | ||
|
|
ef368f377f | ||
|
|
df4a22eae4 | ||
|
|
34fba75af3 | ||
|
|
613434c18e | ||
|
|
4718534f22 | ||
|
|
1fb9fd3810 | ||
|
|
f9f25e4d48 | ||
|
|
3079b0c606 | ||
|
|
25de3bb0b5 | ||
|
|
400cb880aa | ||
|
|
71f792cf35 | ||
|
|
c947680085 | ||
|
|
f1c425650a | ||
|
|
f61a5b1889 | ||
|
|
5491b80c48 | ||
|
|
165a675b8a | ||
|
|
b7461579db | ||
|
|
19816f5f3e | ||
|
|
12f9b97955 | ||
|
|
8d7db38344 | ||
|
|
57892e93c0 |
175
.github/actions/build-electron/action.yml
vendored
175
.github/actions/build-electron/action.yml
vendored
@@ -40,10 +40,113 @@ runs:
|
||||
echo "GN_EXTRA_ARGS=$GN_APPENDED_ARGS" >> $GITHUB_ENV
|
||||
- name: Set GN_EXTRA_ARGS for Windows
|
||||
shell: bash
|
||||
if: ${{inputs.target-arch != 'x64' && inputs.target-platform == 'win' }}
|
||||
if: ${{ inputs.target-platform == 'win' }}
|
||||
run: |
|
||||
GN_APPENDED_ARGS="$GN_EXTRA_ARGS target_cpu=\"${{ inputs.target-arch }}\""
|
||||
GN_APPENDED_ARGS="$GN_EXTRA_ARGS target_cpu=\"${{ inputs.target-arch }}\" use_v8_context_snapshot=true v8_win_cross_compile_using_wine=true target_os=\"win\""
|
||||
echo "GN_EXTRA_ARGS=$GN_APPENDED_ARGS" >> $GITHUB_ENV
|
||||
echo "ELECTRON_BUILD_TOOLS_MAIN_STAR=`pwd`/src/electron/build/siso/main.star" >> $GITHUB_ENV
|
||||
- name: Install wine for Windows builds on non-Windows hosts
|
||||
shell: bash
|
||||
if: ${{ inputs.target-platform == 'win' && runner.os != 'Windows' }}
|
||||
run: |
|
||||
sudo mkdir -pm755 /etc/apt/keyrings
|
||||
wget -O - https://dl.winehq.org/wine-builds/winehq.key | sudo gpg --dearmor -o /etc/apt/keyrings/winehq-archive.key -
|
||||
sudo dpkg --add-architecture i386
|
||||
sudo wget -NP /etc/apt/sources.list.d/ https://dl.winehq.org/wine-builds/ubuntu/dists/jammy/winehq-jammy.sources
|
||||
sudo apt-get update
|
||||
sudo apt install -y --install-recommends winehq-stable libgcc-s1:i386 libgcc-s1
|
||||
# Increase virtual memory limits for Wine's VirtualAlloc (V8 sandbox
|
||||
# reserves a very large contiguous region that fails under default limits)
|
||||
sudo sysctl vm.mmap_min_addr
|
||||
sudo sysctl -w vm.mmap_min_addr=65536
|
||||
sudo sysctl -w vm.max_map_count=1048576
|
||||
sudo sysctl -w vm.overcommit_memory=1
|
||||
sudo sysctl -w kernel.randomize_va_space=0
|
||||
if [ -x /usr/bin/wine ]; then
|
||||
WINE_PATH=/usr/bin/wine
|
||||
elif command -v wine >/dev/null 2>&1; then
|
||||
WINE_PATH=$(command -v wine)
|
||||
fi
|
||||
if [ -z "$WINE_PATH" ] || [ ! -x "$WINE_PATH" ]; then
|
||||
echo "ERROR: wine binary not found anywhere after install"
|
||||
exit 1
|
||||
fi
|
||||
echo "Found wine at: $WINE_PATH"
|
||||
export WINEPREFIX="$HOME/.wine"
|
||||
mkdir -p "$WINEPREFIX"
|
||||
echo "WINEPREFIX=$WINEPREFIX" >> $GITHUB_ENV
|
||||
# Start a persistent Xvfb server for wine (xvfb-run per-invocation hangs
|
||||
# because wineserver keeps the X connection alive)
|
||||
export DISPLAY=:99.0
|
||||
echo "DISPLAY=:99.0" >> $GITHUB_ENV
|
||||
export XDG_RUNTIME_DIR=/tmp/runtime-$(whoami)
|
||||
echo "XDG_RUNTIME_DIR=$XDG_RUNTIME_DIR" >> $GITHUB_ENV
|
||||
mkdir -p "$XDG_RUNTIME_DIR"
|
||||
echo "Starting Xvfb on :99 with 1024x768x24 resolution"
|
||||
Xvfb :99 -screen 0 1024x768x24 &
|
||||
echo "Wait for Xvfb to be ready"
|
||||
# Wait for Xvfb to be ready (up to 5 seconds)
|
||||
for i in $(seq 1 10); do
|
||||
if xdpyinfo -display :99 >/dev/null 2>&1; then
|
||||
echo "Xvfb is running on :99"
|
||||
break
|
||||
fi
|
||||
echo "xvfb not ready yet, waiting..."
|
||||
sleep 0.5
|
||||
done
|
||||
if ! xdpyinfo -display :99 >/dev/null 2>&1; then
|
||||
echo "ERROR: Xvfb failed to start"
|
||||
exit 1
|
||||
fi
|
||||
echo "Xvfb is ready; about to run wineboot"
|
||||
|
||||
export WINEDEBUG=-all
|
||||
echo "WINEDEBUG=$WINEDEBUG" >> $GITHUB_ENV
|
||||
export WINEARCH=win64
|
||||
echo "WINEARCH=$WINEARCH" >> $GITHUB_ENV
|
||||
WINEDLLOVERRIDES="mscoree,mshtml=" wineboot --init
|
||||
echo "Done running wineboot"
|
||||
# Initialize wine prefix to avoid first-run delays during build
|
||||
#"$WINE_PATH" wineboot --init 2>/dev/null || true
|
||||
WINE_WRAPPER="/usr/local/bin/xvfb-wine"
|
||||
printf '#!/bin/sh\nsetarch x86_64 -R %s "$@"\n' "$WINE_PATH" | sudo tee "$WINE_WRAPPER" > /dev/null
|
||||
sudo chmod +x "$WINE_WRAPPER"
|
||||
GN_APPENDED_ARGS="$GN_EXTRA_ARGS v8_wine_path=\"$WINE_WRAPPER\""
|
||||
|
||||
# Pass wine path to GN so siso can find it regardless of PATH
|
||||
GN_APPENDED_ARGS="$GN_EXTRA_ARGS v8_wine_path=\"$WINE_PATH\""
|
||||
echo "GN_EXTRA_ARGS=$GN_APPENDED_ARGS" >> $GITHUB_ENV
|
||||
echo "GN APPENDED_ARGS set with wine path: $GN_APPENDED_ARGS"
|
||||
echo "Wine setup complete"
|
||||
# - name: Download mksnapshot.zip
|
||||
# shell: bash
|
||||
# if: ${{ inputs.target-platform == 'win' }}
|
||||
# run: |
|
||||
# # Download mksnapshot.zip from https://electronbuildtools.blob.core.windows.net/windows-toolchains/mksnapshot.zip
|
||||
# curl -L -o mksnapshot.zip https://electronbuildtools.blob.core.windows.net/windows-toolchains/mksnapshot.zip
|
||||
# if [ $? -ne 0 ]; then
|
||||
# echo "Failed to download mksnapshot.zip"
|
||||
# exit 1
|
||||
# fi
|
||||
# if [ -f mksnapshot.zip ]; then
|
||||
# echo "Successfully downloaded mksnapshot.zip"
|
||||
# else
|
||||
# echo "mksnapshot.zip not found after download"
|
||||
# exit 1
|
||||
# fi
|
||||
# if [ -f mksnapshot.zip ]; then
|
||||
# unzip mksnapshot.zip -d mksnapshot || true
|
||||
# PREBUILT_MKSNAPSHOT="$(pwd)/mksnapshot/mksnapshot.exe"
|
||||
# if [ -f "$PREBUILT_MKSNAPSHOT" ]; then
|
||||
# GN_APPENDED_ARGS="$GN_EXTRA_ARGS v8_prebuilt_mksnapshot=\"$PREBUILT_MKSNAPSHOT\""
|
||||
# echo "GN_EXTRA_ARGS=$GN_APPENDED_ARGS" >> $GITHUB_ENV
|
||||
# echo "Using pre-built mksnapshot at $PREBUILT_MKSNAPSHOT"
|
||||
# else
|
||||
# echo "mksnapshot binary not found in mksnapshot.zip, will build from source"
|
||||
# fi
|
||||
# else
|
||||
# echo "mksnapshot.zip not found, skipping unzip and PATH update"
|
||||
# fi
|
||||
- name: Add Clang problem matcher
|
||||
shell: bash
|
||||
run: echo "::add-matcher::src/electron/.github/problem-matchers/clang.json"
|
||||
@@ -58,7 +161,6 @@ runs:
|
||||
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
|
||||
run: |
|
||||
rm -rf "src/out/Default/Electron Framework.framework"
|
||||
@@ -83,7 +185,11 @@ runs:
|
||||
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 [ "$TARGET_PLATFORM" = "win" ]; then
|
||||
BUILD_STATS_ARGS="out/Default/siso.exe.INFO --out-dir out/Default --output-object-checksums object-checksums.${{ inputs.artifact-platform }}_${{ inputs.target-arch }}.json"
|
||||
else
|
||||
BUILD_STATS_ARGS="out/Default/siso.INFO --out-dir out/Default --output-object-checksums object-checksums.${{ inputs.artifact-platform }}_${{ inputs.target-arch }}.json"
|
||||
fi
|
||||
if [ -f previous-object-checksums.json ]; then
|
||||
BUILD_STATS_ARGS="$BUILD_STATS_ARGS --input-object-checksums previous-object-checksums.json"
|
||||
fi
|
||||
@@ -93,38 +199,6 @@ runs:
|
||||
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
|
||||
run: |
|
||||
cd src\electron
|
||||
git pack-refs
|
||||
cd ..
|
||||
|
||||
$env:NINJA_SUMMARIZE_BUILD = 1
|
||||
if ("${{ inputs.is-release }}" -eq "true") {
|
||||
e build --target electron:release_build
|
||||
} else {
|
||||
e build --target electron:testing_build
|
||||
}
|
||||
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")
|
||||
}
|
||||
if ($env:DD_API_KEY) {
|
||||
$statsArgs += "--upload-stats"
|
||||
} 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: |
|
||||
@@ -152,15 +226,7 @@ runs:
|
||||
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
|
||||
powershell Compress-Archive -update mksnapshot_args mksnapshot.zip
|
||||
powershell mkdir mktmp\\gen\\v8
|
||||
powershell Copy-Item gen\\v8\\embedded.S mktmp\\gen\\v8
|
||||
powershell Compress-Archive -update -Path mktmp\\gen mksnapshot.zip
|
||||
else
|
||||
(cd out/Default; zip mksnapshot.zip mksnapshot_args gen/v8/embedded.S)
|
||||
fi
|
||||
(cd out/Default; zip mksnapshot.zip mksnapshot_args gen/v8/embedded.S)
|
||||
- name: Generate Cross-Arch Snapshot (arm/arm64) ${{ inputs.step-suffix }}
|
||||
shell: bash
|
||||
if: ${{ (inputs.target-arch == 'arm' || inputs.target-arch == 'arm64') && inputs.target-platform == 'linux' }}
|
||||
@@ -194,12 +260,6 @@ runs:
|
||||
fi
|
||||
electron/script/zip_manifests/check-zip-manifest.py out/Default/chromedriver.zip electron/script/zip_manifests/chromedriver_zip.$target_os.${{ inputs.target-arch }}.manifest
|
||||
fi
|
||||
- name: Create installed_software.json ${{ inputs.step-suffix }}
|
||||
shell: powershell
|
||||
if: ${{ inputs.is-release == 'true' && inputs.target-platform == 'win' }}
|
||||
run: |
|
||||
cd src
|
||||
Get-CimInstance -Namespace root\cimv2 -Class Win32_product | Select vendor, description, @{l='install_location';e='InstallLocation'}, @{l='install_date';e='InstallDate'}, @{l='install_date_2';e='InstallDate2'}, caption, version, name, @{l='sku_number';e='SKUNumber'} | ConvertTo-Json | Out-File -Encoding utf8 -FilePath .\installed_software.json
|
||||
- name: Profile Windows Toolchain ${{ inputs.step-suffix }}
|
||||
shell: bash
|
||||
if: ${{ inputs.is-release == 'true' && inputs.target-platform == 'win' }}
|
||||
@@ -269,7 +329,7 @@ runs:
|
||||
with:
|
||||
subject-path: ${{ steps.github-upload.outputs.UPLOADED_PATHS }}
|
||||
- name: Generate siso report
|
||||
if: ${{ inputs.target-platform != 'win' && !cancelled() }}
|
||||
if: ${{ !cancelled() }}
|
||||
shell: bash
|
||||
run: |
|
||||
cd src
|
||||
@@ -278,17 +338,6 @@ runs:
|
||||
echo "SISO_REPORT_PATH=$SISO_REPORT_PATH" >> $GITHUB_ENV
|
||||
cat siso_report.txt
|
||||
echo "SISO REPORT AT $SISO_REPORT_PATH"
|
||||
- name: Generate siso report (Windows)
|
||||
if: ${{ inputs.target-platform == 'win' && !cancelled() }}
|
||||
shell: powershell
|
||||
run: |
|
||||
cd src
|
||||
e d siso report -C out\Default > siso_report.txt
|
||||
$SISO_REPORT_PATH = Get-Content "siso_report.txt" | Select-String "report file:\s*(.+)" | ForEach-Object {
|
||||
$_.Matches.Groups[1].Value.Trim()
|
||||
}
|
||||
echo "SISO_REPORT_PATH=$SISO_REPORT_PATH"
|
||||
echo "SISO_REPORT_PATH=$SISO_REPORT_PATH" >> $env:GITHUB_ENV
|
||||
- name: Generate Artifact Key
|
||||
if: always() && !cancelled()
|
||||
shell: bash
|
||||
|
||||
@@ -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=1aa9dce0b3fa9353c38a6c3d4aac0249f0f68973
|
||||
npm i -g @electron/build-tools
|
||||
# Update depot_tools to ensure python
|
||||
e d update_depot_tools
|
||||
@@ -29,4 +29,4 @@ runs:
|
||||
else
|
||||
echo "$HOME/.electron_build_tools/third_party/depot_tools" >> $GITHUB_PATH
|
||||
echo "$HOME/.electron_build_tools/third_party/depot_tools/python-bin" >> $GITHUB_PATH
|
||||
fi
|
||||
fi
|
||||
17
.github/workflows/build.yml
vendored
17
.github/workflows/build.yml
vendored
@@ -11,12 +11,12 @@ on:
|
||||
skip-macos:
|
||||
type: boolean
|
||||
description: 'Skip macOS builds'
|
||||
default: false
|
||||
default: true
|
||||
required: false
|
||||
skip-linux:
|
||||
type: boolean
|
||||
description: 'Skip Linux builds'
|
||||
default: false
|
||||
default: true
|
||||
required: false
|
||||
skip-windows:
|
||||
type: boolean
|
||||
@@ -108,7 +108,7 @@ jobs:
|
||||
# Checkout Jobs
|
||||
checkout-macos:
|
||||
needs: setup
|
||||
if: ${{ needs.setup.outputs.src == 'true' && !inputs.skip-macos}}
|
||||
if: ${{ needs.setup.outputs.src == 'true' && inputs.skip-macos == 'false'}}
|
||||
runs-on: electron-arc-centralus-linux-amd64-32core
|
||||
permissions:
|
||||
contents: read
|
||||
@@ -138,7 +138,7 @@ jobs:
|
||||
|
||||
checkout-linux:
|
||||
needs: setup
|
||||
if: ${{ !inputs.skip-linux}}
|
||||
if: ${{ inputs.skip-linux == 'false' }}
|
||||
runs-on: electron-arc-centralus-linux-amd64-32core
|
||||
permissions:
|
||||
contents: read
|
||||
@@ -387,8 +387,9 @@ jobs:
|
||||
needs: checkout-windows
|
||||
if: ${{ needs.setup.outputs.src == 'true' && !inputs.skip-windows }}
|
||||
with:
|
||||
build-runs-on: electron-arc-centralus-windows-amd64-16core
|
||||
build-runs-on: electron-arc-centralus-linux-amd64-32core
|
||||
test-runs-on: windows-latest
|
||||
build-container: '{"image":"ghcr.io/electron/build:${{ needs.checkout-windows.outputs.build-image-sha }}","options":"--user root --device /dev/fuse --cap-add SYS_ADMIN","volumes":["/mnt/win-cache:/mnt/win-cache"]}'
|
||||
target-platform: win
|
||||
target-arch: x64
|
||||
is-release: false
|
||||
@@ -406,8 +407,9 @@ jobs:
|
||||
needs: checkout-windows
|
||||
if: ${{ needs.setup.outputs.src == 'true' && !inputs.skip-windows }}
|
||||
with:
|
||||
build-runs-on: electron-arc-centralus-windows-amd64-16core
|
||||
build-runs-on: electron-arc-centralus-linux-amd64-32core
|
||||
test-runs-on: windows-latest
|
||||
build-container: '{"image":"ghcr.io/electron/build:${{ needs.checkout-windows.outputs.build-image-sha }}","options":"--user root --device /dev/fuse --cap-add SYS_ADMIN","volumes":["/mnt/win-cache:/mnt/win-cache"]}'
|
||||
target-platform: win
|
||||
target-arch: x86
|
||||
is-release: false
|
||||
@@ -425,8 +427,9 @@ jobs:
|
||||
needs: checkout-windows
|
||||
if: ${{ needs.setup.outputs.src == 'true' && !inputs.skip-windows }}
|
||||
with:
|
||||
build-runs-on: electron-arc-centralus-windows-amd64-16core
|
||||
build-runs-on: electron-arc-centralus-linux-amd64-32core
|
||||
test-runs-on: windows-11-arm
|
||||
build-container: '{"image":"ghcr.io/electron/build:${{ needs.checkout-windows.outputs.build-image-sha }}","options":"--user root --device /dev/fuse --cap-add SYS_ADMIN","volumes":["/mnt/win-cache:/mnt/win-cache"]}'
|
||||
target-platform: win
|
||||
target-arch: arm64
|
||||
is-release: false
|
||||
|
||||
@@ -134,6 +134,10 @@ jobs:
|
||||
- name: Install AZCopy
|
||||
if: ${{ inputs.target-platform == 'macos' }}
|
||||
run: brew install azcopy
|
||||
- name: Enable windows toolchain
|
||||
if: ${{ inputs.target-platform == 'win' }}
|
||||
run: |
|
||||
echo "ELECTRON_DEPOT_TOOLS_WIN_TOOLCHAIN=1" >> $GITHUB_ENV
|
||||
- name: Set GN_EXTRA_ARGS for Linux
|
||||
if: ${{ inputs.target-platform == 'linux' }}
|
||||
run: |
|
||||
@@ -160,13 +164,15 @@ jobs:
|
||||
echo "DEPSHASH=$DEPSHASH" >> $GITHUB_ENV
|
||||
echo "CACHE_PATH=$DEPSHASH.tar" >> $GITHUB_ENV
|
||||
- name: Restore src cache via AZCopy
|
||||
if: ${{ inputs.target-platform != 'linux' }}
|
||||
if: ${{ inputs.target-platform == 'macos' }}
|
||||
uses: ./src/electron/.github/actions/restore-cache-azcopy
|
||||
with:
|
||||
target-platform: ${{ inputs.target-platform }}
|
||||
- name: Restore src cache via AKS
|
||||
if: ${{ inputs.target-platform == 'linux' }}
|
||||
if: ${{ inputs.target-platform != 'macos' }}
|
||||
uses: ./src/electron/.github/actions/restore-cache-aks
|
||||
with:
|
||||
target-platform: ${{ inputs.target-platform }}
|
||||
- name: Checkout Electron
|
||||
uses: actions/checkout@de0fac2e4500dabe0009e67214ff5f5447ce83dd
|
||||
with:
|
||||
@@ -174,7 +180,7 @@ jobs:
|
||||
fetch-depth: 0
|
||||
ref: ${{ github.event.pull_request.head.sha }}
|
||||
- name: Fix Sync
|
||||
if: ${{ inputs.target-platform != 'linux' }}
|
||||
if: ${{ inputs.target-platform == 'macos' }}
|
||||
uses: ./src/electron/.github/actions/fix-sync
|
||||
with:
|
||||
target-platform: ${{ inputs.target-platform }}
|
||||
@@ -183,9 +189,21 @@ jobs:
|
||||
- name: Init Build Tools
|
||||
run: |
|
||||
e init -f --root=$(pwd) --out=Default ${{ inputs.gn-build-type }} --import ${{ inputs.gn-build-type }} --target-cpu ${{ inputs.target-arch }} --remote-build siso
|
||||
e sanitize-config
|
||||
- name: Run Electron Only Hooks
|
||||
run: |
|
||||
e d gclient runhooks --spec="solutions=[{'name':'src/electron','url':None,'deps_file':'DEPS','custom_vars':{'process_deps':False},'managed':False}]"
|
||||
if [ "${{ inputs.target-platform }}" = "win" ]; then
|
||||
rm -rf src/third_party/depot_tools/win_toolchain/vs_files*
|
||||
fi
|
||||
echo "solutions=[{'name':'src/electron','url':None,'deps_file':'DEPS','custom_vars':{'process_deps':False},'managed':False}]" > tmpgclient
|
||||
if [ "${{ inputs.target-platform }}" = "win" ]; then
|
||||
echo "target_os=['win']" >> tmpgclient
|
||||
fi
|
||||
gclient runhooks --gclientfile=tmpgclient
|
||||
# Fix VS Toolchain
|
||||
if [ "${{ inputs.target-platform }}" = "win" ]; then
|
||||
e d python3 src/build/vs_toolchain.py update --force
|
||||
fi
|
||||
- name: Regenerate DEPS Hash
|
||||
run: |
|
||||
(cd src/electron && git checkout .) && node src/electron/script/generate-deps-hash.js
|
||||
@@ -224,3 +242,11 @@ jobs:
|
||||
generate-symbols: '${{ inputs.generate-symbols }}'
|
||||
upload-to-storage: '${{ inputs.upload-to-storage }}'
|
||||
step-suffix: '(mas)'
|
||||
- name: Wait for active SSH sessions
|
||||
shell: bash
|
||||
if: always() && !cancelled()
|
||||
run: |
|
||||
while [ -f /var/.ssh-lock ]
|
||||
do
|
||||
sleep 60
|
||||
done
|
||||
|
||||
2
.github/workflows/pull-request-labeled.yml
vendored
2
.github/workflows/pull-request-labeled.yml
vendored
@@ -50,7 +50,7 @@ jobs:
|
||||
field-value: ✅ Reviewed
|
||||
pull-request-labeled-ai-pr:
|
||||
name: ai-pr label added
|
||||
if: github.event.label.name == 'ai-pr' && github.event.pull_request.state != 'closed'
|
||||
if: github.event.label.name == 'ai-pr'
|
||||
runs-on: ubuntu-latest
|
||||
permissions: {}
|
||||
steps:
|
||||
|
||||
103
build/siso/main.star
Normal file
103
build/siso/main.star
Normal file
@@ -0,0 +1,103 @@
|
||||
load("@builtin//encoding.star", "json")
|
||||
load("@builtin//lib/gn.star", "gn")
|
||||
load("@builtin//path.star", "path")
|
||||
load("@builtin//runtime.star", "runtime")
|
||||
load("@builtin//struct.star", "module")
|
||||
load("@config//main.star", upstream_init = "init")
|
||||
load("@config//win_sdk.star", "win_sdk")
|
||||
load("@config//gn_logs.star", "gn_logs")
|
||||
|
||||
def init(ctx):
|
||||
mod = upstream_init(ctx)
|
||||
step_config = json.decode(mod.step_config)
|
||||
|
||||
# Buildbarn doesn't support input_root_absolute_path so disable that
|
||||
for rule in step_config["rules"]:
|
||||
input_root_absolute_path = rule.get("input_root_absolute_path", False)
|
||||
if input_root_absolute_path:
|
||||
rule.pop("input_root_absolute_path", None)
|
||||
|
||||
# Only wrap clang rules with a remote wrapper if not on Linux. These are currently only
|
||||
# needed for X-Compile builds, which run on Windows and Mac.
|
||||
if runtime.os != "linux":
|
||||
for rule in step_config["rules"]:
|
||||
if rule["name"].startswith("clang/") or rule["name"].startswith("clang-cl/"):
|
||||
rule["remote_wrapper"] = "../../buildtools/reclient_cfgs/chromium-browser-clang/clang_remote_wrapper"
|
||||
if "inputs" not in rule:
|
||||
rule["inputs"] = []
|
||||
rule["inputs"].append("buildtools/reclient_cfgs/chromium-browser-clang/clang_remote_wrapper")
|
||||
rule["inputs"].append("third_party/llvm-build/Release+Asserts_linux/bin/clang")
|
||||
|
||||
if "executables" not in step_config:
|
||||
step_config["executables"] = []
|
||||
step_config["executables"].append("buildtools/reclient_cfgs/chromium-browser-clang/clang_remote_wrapper")
|
||||
step_config["executables"].append("third_party/llvm-build/Release+Asserts_linux/bin/clang")
|
||||
|
||||
if runtime.os == "darwin":
|
||||
# Update platforms to match our default siso config instead of reclient configs.
|
||||
step_config["platforms"].update({
|
||||
"clang": step_config["platforms"]["default"],
|
||||
"clang_large": step_config["platforms"]["default"],
|
||||
})
|
||||
|
||||
# Add additional Windows SDK headers needed by Electron
|
||||
win_toolchain_dir = win_sdk.toolchain_dir(ctx)
|
||||
if win_toolchain_dir:
|
||||
sdk_version = gn_logs.read(ctx).get("windows_sdk_version")
|
||||
step_config["input_deps"][win_toolchain_dir + ":headers"].extend([
|
||||
# third_party/electron_node/deps/uv/include/uv/win.h includes mswsock.h
|
||||
path.join(win_toolchain_dir, "Windows Kits", "10/Include", sdk_version, "um/mswsock.h"),
|
||||
# third_party/electron_node/src/debug_utils.cc includes lm.h
|
||||
path.join(win_toolchain_dir, "Windows Kits", "10/Include", sdk_version, "um/Lm.h"),
|
||||
])
|
||||
|
||||
if runtime.os == "windows":
|
||||
# Update platforms to match our default siso config instead of reclient configs.
|
||||
step_config["platforms"].update({
|
||||
"clang-cl": step_config["platforms"]["default"],
|
||||
"clang-cl_large": step_config["platforms"]["default"],
|
||||
"lld-link": step_config["platforms"]["default"],
|
||||
})
|
||||
|
||||
# When cross-compiling for Windows using wine, mksnapshot.exe is run via
|
||||
# wine64 on the local machine. The remote execution service cannot handle
|
||||
# this, so force mksnapshot to run locally. The wine64 prefix also changes
|
||||
# the command so the upstream v8/mksnapshot rule's command_prefix won't
|
||||
# match — add an explicit rule for the wine-prefixed command.
|
||||
if "args.gn" in ctx.metadata:
|
||||
gn_args = gn.args(ctx)
|
||||
if gn_args.get("v8_win_cross_compile_using_wine", "").strip('"') == "true":
|
||||
# Force the existing v8/mksnapshot rule to run locally
|
||||
for rule in step_config["rules"]:
|
||||
if rule.get("name") == "v8/mksnapshot":
|
||||
rule["remote"] = False
|
||||
|
||||
# Add a rule that matches the wine64-prefixed mksnapshot command.
|
||||
# With wine, GN emits: python3 ../../v8/tools/run.py <wine_path> ./mksnapshot.exe
|
||||
# The upstream command_prefix ("python3 ...run.py ./mksnapshot") won't
|
||||
# match because wine_path appears before ./mksnapshot.exe.
|
||||
wine_path = gn_args.get("v8_wine_path", "").strip('"')
|
||||
if wine_path:
|
||||
step_config["rules"].insert(0, {
|
||||
"name": "v8/mksnapshot_wine",
|
||||
"command_prefix": "python3 ../../v8/tools/run.py " + wine_path,
|
||||
"remote": False,
|
||||
"timeout": "2m",
|
||||
"output_local": True,
|
||||
})
|
||||
# Same treatment for v8_context_snapshot_generator which uses
|
||||
# gn_run_binary.py instead of v8/tools/run.py.
|
||||
step_config["rules"].insert(0, {
|
||||
"name": "v8/context_snapshot_wine",
|
||||
"command_prefix": "python3 ../../build/gn_run_binary.py " + wine_path,
|
||||
"remote": False,
|
||||
"timeout": "2m",
|
||||
"output_local": True,
|
||||
})
|
||||
|
||||
return module(
|
||||
"config",
|
||||
step_config = json.encode(step_config),
|
||||
filegroups = mod.filegroups,
|
||||
handlers = mod.handlers,
|
||||
)
|
||||
@@ -63,17 +63,10 @@ See [`Menu`](menu.md) for examples.
|
||||
* `afterGroupContaining` string[] (optional) - Provides a means for a single context menu to declare
|
||||
the placement of their containing group after the containing group of the item
|
||||
with the specified id.
|
||||
* `badge` Object (optional) _macOS_ - Only available on macOS 14 and up.
|
||||
* `type` string (optional) - Can be one of `alerts`, `updates`, `new-items` or `none`. Default is `none`.
|
||||
* `count` number (optional) - The number of items the badge displays. Cannot be used with `type: 'none'`.
|
||||
* `content` string (optional) - A custom string to display in the badge. Only usable with `type: 'none'`.
|
||||
|
||||
> [!NOTE]
|
||||
> `acceleratorWorksWhenHidden` is specified as being macOS-only because accelerators always work when items are hidden on Windows and Linux. The option is exposed to users to give them the option to turn it off, as this is possible in native macOS development.
|
||||
|
||||
> [!NOTE]
|
||||
> If you use one of the predefined badge types on macOS (not 'none'), the system localizes and pluralizes the string for you. If you create your own custom badge string, you need to localize and pluralize that string yourself.
|
||||
|
||||
### Instance Properties
|
||||
|
||||
The following properties are available on instances of `MenuItem`:
|
||||
@@ -188,9 +181,3 @@ A `number` indicating an item's sequential unique id.
|
||||
#### `menuItem.menu`
|
||||
|
||||
A [`Menu`](menu.md) that the item is a part of.
|
||||
|
||||
#### `menuItem.badge` _macOS_
|
||||
|
||||
An [`MenuItemBadge`](structures/menu-item-badge.md) indicating the badge for the menu item.
|
||||
|
||||
This property can be dynamically changed. Only available on macOS 14 and up.
|
||||
|
||||
@@ -1,5 +0,0 @@
|
||||
# MenuItemBadge Object
|
||||
|
||||
* `type` string (optional) - Can be one of `alerts`, `updates`, `new-items` or `none`. Default is `none`.
|
||||
* `count` number (optional) - The number of items the badge displays. Cannot be used with `type: 'none'`.
|
||||
* `content` string (optional) - A custom string to display in the badge. Only usable with `type: 'none'`.
|
||||
@@ -111,7 +111,6 @@ auto_filenames = {
|
||||
"docs/api/structures/media-access-permission-request.md",
|
||||
"docs/api/structures/memory-info.md",
|
||||
"docs/api/structures/memory-usage-details.md",
|
||||
"docs/api/structures/menu-item-badge.md",
|
||||
"docs/api/structures/mime-typed-buffer.md",
|
||||
"docs/api/structures/mouse-input-event.md",
|
||||
"docs/api/structures/mouse-wheel-input-event.md",
|
||||
|
||||
@@ -38,24 +38,6 @@ const MenuItem = function (this: any, options: any) {
|
||||
this.overrideProperty('acceleratorWorksWhenHidden', true);
|
||||
this.overrideProperty('registerAccelerator', roles.shouldRegisterAccelerator(this.role));
|
||||
|
||||
if (process.platform === 'darwin') {
|
||||
let badgeValue = options.badge;
|
||||
Object.defineProperty(this, 'badge', {
|
||||
get: () => badgeValue,
|
||||
set: (newValue) => {
|
||||
badgeValue = newValue;
|
||||
// Update native badge if this item is already in a menu
|
||||
if (this.menu) {
|
||||
const index = this.menu.getIndexOfCommandId(this.commandId);
|
||||
if (index !== -1 && badgeValue) {
|
||||
this.menu.setBadge(index, badgeValue);
|
||||
}
|
||||
}
|
||||
},
|
||||
enumerable: true
|
||||
});
|
||||
}
|
||||
|
||||
if (!MenuItem.types.includes(this.type)) {
|
||||
throw new Error(`Unknown menu item type: ${this.type}`);
|
||||
}
|
||||
|
||||
@@ -176,9 +176,6 @@ Menu.prototype.insert = function (pos, item) {
|
||||
if (item.type === 'palette' || item.type === 'header') {
|
||||
this.setCustomType(pos, item.type);
|
||||
}
|
||||
if (process.platform === 'darwin' && item.badge) {
|
||||
this.setBadge(pos, item.badge);
|
||||
}
|
||||
|
||||
// Make menu accessible to items.
|
||||
item.overrideReadOnlyProperty('menu', this);
|
||||
|
||||
@@ -150,3 +150,4 @@ 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
|
||||
chore_run_v8_context_snapshot_generator_through_wine_when.patch
|
||||
|
||||
@@ -0,0 +1,49 @@
|
||||
From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001
|
||||
From: John Kleinschmidt <kleinschmidtorama@gmail.com>
|
||||
Date: Tue, 7 Apr 2026 14:05:09 -0400
|
||||
Subject: chore: run v8_context_snapshot_generator through Wine when
|
||||
cross-compiling
|
||||
|
||||
When cross-compiling for Windows on Linux with Wine, the
|
||||
v8_context_snapshot_generator binary is a Windows PE executable (.exe)
|
||||
that cannot be run directly. Prepend the wine path to args and append
|
||||
.exe to the binary name, matching the approach used for mksnapshot.
|
||||
|
||||
diff --git a/tools/v8_context_snapshot/BUILD.gn b/tools/v8_context_snapshot/BUILD.gn
|
||||
index ec2357139826613e8b295cb01be341acb03b4737..6c4171dbaf7a76cfc89d71871b73058747675811 100644
|
||||
--- a/tools/v8_context_snapshot/BUILD.gn
|
||||
+++ b/tools/v8_context_snapshot/BUILD.gn
|
||||
@@ -50,12 +50,27 @@ if (use_v8_context_snapshot) {
|
||||
output_file = "$root_build_dir/$v8_context_snapshot_filename"
|
||||
output_path = rebase_path(output_file, root_build_dir)
|
||||
|
||||
- args = [
|
||||
- "./" + rebase_path(
|
||||
- get_label_info(
|
||||
- ":v8_context_snapshot_generator($v8_snapshot_toolchain)",
|
||||
- "root_out_dir") + "/v8_context_snapshot_generator",
|
||||
- root_build_dir),
|
||||
+ _generator_dir = get_label_info(
|
||||
+ ":v8_context_snapshot_generator($v8_snapshot_toolchain)",
|
||||
+ "root_out_dir")
|
||||
+ if (v8_win_cross_compile_using_wine) {
|
||||
+ _generator_bin = "./" + rebase_path(
|
||||
+ _generator_dir + "/v8_context_snapshot_generator.exe",
|
||||
+ root_build_dir)
|
||||
+ } else {
|
||||
+ _generator_bin = "./" + rebase_path(
|
||||
+ _generator_dir + "/v8_context_snapshot_generator",
|
||||
+ root_build_dir)
|
||||
+ }
|
||||
+
|
||||
+ args = []
|
||||
+ if (v8_win_cross_compile_using_wine) {
|
||||
+ assert(v8_wine_path != "",
|
||||
+ "v8_wine_path must be set when v8_win_cross_compile_using_wine is true")
|
||||
+ args += [ v8_wine_path ]
|
||||
+ }
|
||||
+ args += [
|
||||
+ _generator_bin,
|
||||
"--snapshot_blob=$snapshot_blob_path",
|
||||
"--output_file=$output_path",
|
||||
]
|
||||
@@ -1,2 +1,3 @@
|
||||
chore_allow_customizing_microtask_policy_per_context.patch
|
||||
build_warn_instead_of_abort_on_builtin_pgo_profile_mismatch.patch
|
||||
feat_support_running_mksnapshot_exe_via_wine_for_windows.patch
|
||||
|
||||
@@ -0,0 +1,113 @@
|
||||
From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001
|
||||
From: John Kleinschmidt <kleinschmidtorama@gmail.com>
|
||||
Date: Tue, 24 Mar 2026 16:29:55 -0400
|
||||
Subject: feat: support running mksnapshot.exe via Wine for Windows
|
||||
cross-compile
|
||||
|
||||
When v8_win_cross_compile_using_wine=true is set, mksnapshot is built as a
|
||||
Windows .exe using the target toolchain and executed via Wine on the Linux
|
||||
host. This avoids needing source-level cross-compile patches for the
|
||||
unwinding info code paths.
|
||||
|
||||
diff --git a/BUILD.gn b/BUILD.gn
|
||||
index 751265ba83c04f0c545248a71b35e46034bfc90a..9ca41b06b569c729496abde7cba085518a9f0d71 100644
|
||||
--- a/BUILD.gn
|
||||
+++ b/BUILD.gn
|
||||
@@ -2699,7 +2699,11 @@ template("run_mksnapshot") {
|
||||
suffix = "_$name"
|
||||
}
|
||||
action("run_mksnapshot_" + name) {
|
||||
- deps = [ ":mksnapshot($v8_snapshot_toolchain)" ]
|
||||
+ if (v8_prebuilt_mksnapshot != "") {
|
||||
+ deps = []
|
||||
+ } else {
|
||||
+ deps = [ ":mksnapshot($v8_snapshot_toolchain)" ]
|
||||
+ }
|
||||
if (v8_verify_deterministic_mksnapshot) {
|
||||
# We archive the snapshot executable when verifying snapshot
|
||||
# determinism to ease debugging.
|
||||
@@ -2753,10 +2757,26 @@ template("run_mksnapshot") {
|
||||
data += [ "$root_out_dir/mksnapshot_output${suffix}.log" ]
|
||||
}
|
||||
|
||||
+ if (v8_prebuilt_mksnapshot != "") {
|
||||
+ _mksnapshot_bin = v8_prebuilt_mksnapshot
|
||||
+ } else {
|
||||
+ _mksnapshot_dir =
|
||||
+ get_label_info(":mksnapshot($v8_snapshot_toolchain)", "root_out_dir")
|
||||
+ if (v8_win_cross_compile_using_wine) {
|
||||
+ _mksnapshot_bin = _mksnapshot_dir + "/mksnapshot.exe"
|
||||
+ } else {
|
||||
+ _mksnapshot_bin = _mksnapshot_dir + "/mksnapshot"
|
||||
+ }
|
||||
+ }
|
||||
+
|
||||
+ if (v8_win_cross_compile_using_wine) {
|
||||
+ assert(
|
||||
+ v8_wine_path != "",
|
||||
+ "v8_wine_path must be set when v8_win_cross_compile_using_wine is true")
|
||||
+ args += [ v8_wine_path ]
|
||||
+ }
|
||||
args += [
|
||||
- "./" + rebase_path(get_label_info(":mksnapshot($v8_snapshot_toolchain)",
|
||||
- "root_out_dir") + "/mksnapshot",
|
||||
- root_build_dir),
|
||||
+ "./" + rebase_path(_mksnapshot_bin, root_build_dir),
|
||||
"--turbo_instruction_scheduling",
|
||||
"--turbo-always-optimize-spills",
|
||||
|
||||
diff --git a/gni/snapshot_toolchain.gni b/gni/snapshot_toolchain.gni
|
||||
index 37ed262640d048a6fa5923279ae0388c1c0ae766..d9830914f0abd919143f0cf8b3069c5a3f70516e 100644
|
||||
--- a/gni/snapshot_toolchain.gni
|
||||
+++ b/gni/snapshot_toolchain.gni
|
||||
@@ -32,6 +32,21 @@ declare_args() {
|
||||
# toolchain that matches the bit-width of the target CPU, but runs on
|
||||
# the host.
|
||||
v8_snapshot_toolchain = ""
|
||||
+
|
||||
+ # When cross-compiling for Windows on a non-Windows host, build mksnapshot
|
||||
+ # as a Windows .exe and run it via Wine instead of building a host-native
|
||||
+ # mksnapshot with cross-compile patches.
|
||||
+ v8_win_cross_compile_using_wine = false
|
||||
+
|
||||
+ # Absolute path to the wine64 binary. Required when
|
||||
+ # v8_win_cross_compile_using_wine is true.
|
||||
+ v8_wine_path = ""
|
||||
+
|
||||
+ # Path to a pre-built mksnapshot binary to use instead of building one from
|
||||
+ # source. When set, run_mksnapshot will use this binary directly and skip
|
||||
+ # building the mksnapshot target. The path should be absolute or relative
|
||||
+ # to the source root.
|
||||
+ v8_prebuilt_mksnapshot = ""
|
||||
}
|
||||
|
||||
# Try to infer the appropriate snapshot toolchain for the v8_current_cpu
|
||||
@@ -69,7 +84,12 @@ if (v8_snapshot_toolchain == "") {
|
||||
# Cross-build from same ISA on one OS to another. For example:
|
||||
# * targeting win/x64 on a linux/x64 host
|
||||
# * targeting win/arm64 on a mac/arm64 host
|
||||
- v8_snapshot_toolchain = host_toolchain
|
||||
+ if (v8_win_cross_compile_using_wine && is_win && host_os != "win") {
|
||||
+ # Build mksnapshot as a Windows .exe and run it via Wine.
|
||||
+ v8_snapshot_toolchain = current_toolchain
|
||||
+ } else {
|
||||
+ v8_snapshot_toolchain = host_toolchain
|
||||
+ }
|
||||
} else if (host_cpu == "arm64" && current_cpu == "x64") {
|
||||
# Cross-build from arm64 to intel (likely on an Apple Silicon mac).
|
||||
v8_snapshot_toolchain =
|
||||
@@ -119,7 +139,13 @@ assert(v8_snapshot_toolchain != "",
|
||||
# We reuse the snapshot toolchain for building torque and other generators to
|
||||
# avoid building v8_libbase on the host more than once. On mips with big endian,
|
||||
# the snapshot toolchain is the target toolchain and, hence, can't be used.
|
||||
-v8_generator_toolchain = v8_snapshot_toolchain
|
||||
+# When using Wine for cross-compilation, mksnapshot is built as a Windows .exe
|
||||
+# but other generators (torque, etc.) must still be host-native binaries.
|
||||
+if (v8_win_cross_compile_using_wine && is_win && host_os != "win") {
|
||||
+ v8_generator_toolchain = host_toolchain
|
||||
+} else {
|
||||
+ v8_generator_toolchain = v8_snapshot_toolchain
|
||||
+}
|
||||
if (host_cpu == "x64" && v8_current_cpu == "mips64") {
|
||||
v8_generator_toolchain = "//build/toolchain/linux:clang_x64"
|
||||
}
|
||||
@@ -9,7 +9,11 @@ elif [ "`uname`" == "Darwin" ]; then
|
||||
BUILD_TYPE="mas"
|
||||
fi
|
||||
elif [ "`uname`" == "Linux" ]; then
|
||||
BUILD_TYPE="linux"
|
||||
if [ "$ELECTRON_DEPOT_TOOLS_WIN_TOOLCHAIN" == "1" ]; then
|
||||
BUILD_TYPE="win"
|
||||
else
|
||||
BUILD_TYPE="linux"
|
||||
fi
|
||||
else
|
||||
echo "Unsupported platform"
|
||||
exit 1
|
||||
|
||||
@@ -18,6 +18,7 @@
|
||||
#include "shell/common/gin_converters/gurl_converter.h"
|
||||
#include "shell/common/gin_converters/image_converter.h"
|
||||
#include "shell/common/gin_converters/optional_converter.h"
|
||||
#include "shell/common/gin_helper/dictionary.h"
|
||||
#include "shell/common/gin_helper/object_template_builder.h"
|
||||
#include "shell/common/node_includes.h"
|
||||
#include "ui/base/models/image_model.h"
|
||||
@@ -27,7 +28,6 @@
|
||||
namespace gin {
|
||||
|
||||
using SharingItem = electron::ElectronMenuModel::SharingItem;
|
||||
using Badge = electron::ElectronMenuModel::Badge;
|
||||
|
||||
template <>
|
||||
struct Converter<SharingItem> {
|
||||
@@ -44,28 +44,6 @@ struct Converter<SharingItem> {
|
||||
}
|
||||
};
|
||||
|
||||
template <>
|
||||
struct Converter<Badge> {
|
||||
static bool FromV8(v8::Isolate* isolate,
|
||||
v8::Local<v8::Value> val,
|
||||
Badge* out) {
|
||||
gin_helper::Dictionary dict;
|
||||
if (!ConvertFromV8(isolate, val, &dict))
|
||||
return false;
|
||||
|
||||
std::string type_str;
|
||||
if (dict.Get("type", &type_str)) {
|
||||
out->type = base::UTF8ToUTF16(type_str);
|
||||
} else {
|
||||
out->type = u"none";
|
||||
}
|
||||
|
||||
dict.GetOptional("count", &(out->count));
|
||||
dict.GetOptional("content", &(out->content));
|
||||
return true;
|
||||
}
|
||||
};
|
||||
|
||||
} // namespace gin
|
||||
|
||||
#endif
|
||||
@@ -274,21 +252,6 @@ void Menu::SetCustomType(int index, const std::u16string& customType) {
|
||||
model_->SetCustomType(index, customType);
|
||||
}
|
||||
|
||||
#if BUILDFLAG(IS_MAC)
|
||||
void Menu::SetBadge(int index, const gin_helper::Dictionary& badge_dict) {
|
||||
ElectronMenuModel::Badge badge;
|
||||
std::string type_str;
|
||||
if (badge_dict.Get("type", &type_str)) {
|
||||
badge.type = base::UTF8ToUTF16(type_str);
|
||||
} else {
|
||||
badge.type = u"none";
|
||||
}
|
||||
badge_dict.GetOptional("count", &badge.count);
|
||||
badge_dict.GetOptional("content", &badge.content);
|
||||
model_->SetBadge(index, std::move(badge));
|
||||
}
|
||||
#endif
|
||||
|
||||
void Menu::Clear() {
|
||||
model_->Clear();
|
||||
}
|
||||
@@ -329,12 +292,8 @@ void Menu::FillObjectTemplate(v8::Isolate* isolate,
|
||||
.SetMethod("setToolTip", &Menu::SetToolTip)
|
||||
.SetMethod("setRole", &Menu::SetRole)
|
||||
.SetMethod("setCustomType", &Menu::SetCustomType)
|
||||
#if BUILDFLAG(IS_MAC)
|
||||
.SetMethod("setBadge", &Menu::SetBadge)
|
||||
#endif
|
||||
.SetMethod("clear", &Menu::Clear)
|
||||
.SetMethod("getItemCount", &Menu::GetItemCount)
|
||||
.SetMethod("getIndexOfCommandId", &Menu::GetIndexOfCommandId)
|
||||
.SetMethod("popupAt", &Menu::PopupAt)
|
||||
.SetMethod("closePopupAt", &Menu::ClosePopupAt)
|
||||
.SetMethod("_getAcceleratorTextAt", &Menu::GetAcceleratorTextAtForTesting)
|
||||
|
||||
@@ -13,7 +13,6 @@
|
||||
#include "shell/browser/event_emitter_mixin.h"
|
||||
#include "shell/browser/ui/electron_menu_model.h"
|
||||
#include "shell/common/gin_helper/constructible.h"
|
||||
#include "shell/common/gin_helper/dictionary.h"
|
||||
#include "shell/common/gin_helper/self_keep_alive.h"
|
||||
#include "ui/base/mojom/menu_source_type.mojom-forward.h"
|
||||
|
||||
@@ -129,9 +128,6 @@ class Menu : public gin::Wrappable<Menu>,
|
||||
void SetToolTip(int index, const std::u16string& toolTip);
|
||||
void SetRole(int index, const std::u16string& role);
|
||||
void SetCustomType(int index, const std::u16string& customType);
|
||||
#if BUILDFLAG(IS_MAC)
|
||||
void SetBadge(int index, const gin_helper::Dictionary& badge);
|
||||
#endif
|
||||
void Clear();
|
||||
int GetIndexOfCommandId(int command_id) const;
|
||||
int GetItemCount() const;
|
||||
|
||||
@@ -550,7 +550,8 @@ gin::WrapperInfo Session::kWrapperInfo = {{gin::kEmbedderNativeGin},
|
||||
Session::Session(v8::Isolate* isolate, ElectronBrowserContext* browser_context)
|
||||
: isolate_(isolate),
|
||||
network_emulation_token_(base::UnguessableToken::Create()),
|
||||
browser_context_{browser_context} {
|
||||
browser_context_{
|
||||
raw_ref<ElectronBrowserContext>::from_ptr(browser_context)} {
|
||||
gin::PerIsolateData* data = gin::PerIsolateData::From(isolate);
|
||||
data->AddDisposeObserver(this);
|
||||
// Observe DownloadManager to get download notifications.
|
||||
@@ -583,21 +584,16 @@ Session::~Session() {
|
||||
}
|
||||
|
||||
void Session::Dispose() {
|
||||
if (!keep_alive_)
|
||||
return;
|
||||
|
||||
ElectronBrowserContext* const browser_context = this->browser_context();
|
||||
if (!browser_context)
|
||||
return;
|
||||
|
||||
browser_context->GetDownloadManager()->RemoveObserver(this);
|
||||
if (keep_alive_) {
|
||||
browser_context()->GetDownloadManager()->RemoveObserver(this);
|
||||
|
||||
#if BUILDFLAG(ENABLE_BUILTIN_SPELLCHECKER)
|
||||
if (auto* service =
|
||||
SpellcheckServiceFactory::GetForContext(browser_context)) {
|
||||
service->SetHunspellObserver(nullptr);
|
||||
}
|
||||
if (auto* service =
|
||||
SpellcheckServiceFactory::GetForContext(browser_context())) {
|
||||
service->SetHunspellObserver(nullptr);
|
||||
}
|
||||
#endif
|
||||
}
|
||||
}
|
||||
|
||||
void Session::OnDownloadCreated(content::DownloadManager* manager,
|
||||
@@ -1879,7 +1875,6 @@ void Session::OnBeforeMicrotasksRunnerDispose(v8::Isolate* isolate) {
|
||||
data->RemoveDisposeObserver(this);
|
||||
Dispose();
|
||||
weak_factory_.Invalidate();
|
||||
browser_context_ = nullptr;
|
||||
keep_alive_.Clear();
|
||||
}
|
||||
|
||||
|
||||
@@ -10,6 +10,7 @@
|
||||
#include <vector>
|
||||
|
||||
#include "base/memory/raw_ptr.h"
|
||||
#include "base/memory/raw_ref.h"
|
||||
#include "base/memory/weak_ptr.h"
|
||||
#include "base/values.h"
|
||||
#include "content/public/browser/download_manager.h"
|
||||
@@ -102,8 +103,8 @@ class Session final : public gin::Wrappable<Session>,
|
||||
Session(v8::Isolate* isolate, ElectronBrowserContext* browser_context);
|
||||
~Session() override;
|
||||
|
||||
[[nodiscard]] ElectronBrowserContext* browser_context() const {
|
||||
return browser_context_;
|
||||
ElectronBrowserContext* browser_context() const {
|
||||
return &browser_context_.get();
|
||||
}
|
||||
|
||||
// gin::Wrappable
|
||||
@@ -224,7 +225,7 @@ class Session final : public gin::Wrappable<Session>,
|
||||
// The client id to enable the network throttler.
|
||||
base::UnguessableToken network_emulation_token_;
|
||||
|
||||
raw_ptr<ElectronBrowserContext> browser_context_;
|
||||
const raw_ref<ElectronBrowserContext> browser_context_;
|
||||
|
||||
gin::WeakCellFactory<Session> weak_factory_{this};
|
||||
|
||||
|
||||
@@ -910,15 +910,14 @@ WebContents::WebContents(v8::Isolate* isolate,
|
||||
session = Session::FromPartition(isolate, "");
|
||||
}
|
||||
session_ = session;
|
||||
ElectronBrowserContext* const browser_context = session->browser_context();
|
||||
DCHECK(browser_context != nullptr);
|
||||
|
||||
std::unique_ptr<content::WebContents> web_contents;
|
||||
if (is_guest()) {
|
||||
scoped_refptr<content::SiteInstance> site_instance =
|
||||
content::SiteInstance::CreateForURL(browser_context,
|
||||
content::SiteInstance::CreateForURL(session->browser_context(),
|
||||
GURL("chrome-guest://fake-host"));
|
||||
content::WebContents::CreateParams params{browser_context, site_instance};
|
||||
content::WebContents::CreateParams params(session->browser_context(),
|
||||
site_instance);
|
||||
guest_delegate_ =
|
||||
std::make_unique<WebViewGuestDelegate>(embedder_->web_contents(), this);
|
||||
params.guest_delegate = guest_delegate_.get();
|
||||
@@ -946,7 +945,7 @@ WebContents::WebContents(v8::Isolate* isolate,
|
||||
SkColor bc = ParseCSSColor(background_color_str).value_or(SK_ColorWHITE);
|
||||
bool transparent = bc == SK_ColorTRANSPARENT;
|
||||
|
||||
content::WebContents::CreateParams params{browser_context};
|
||||
content::WebContents::CreateParams params(session->browser_context());
|
||||
auto* view = new OffScreenWebContentsView(
|
||||
transparent, offscreen_use_shared_texture_,
|
||||
offscreen_shared_texture_pixel_format_, offscreen_device_scale_factor_,
|
||||
@@ -957,13 +956,13 @@ WebContents::WebContents(v8::Isolate* isolate,
|
||||
web_contents = content::WebContents::Create(params);
|
||||
view->SetWebContents(web_contents.get());
|
||||
} else {
|
||||
content::WebContents::CreateParams params{browser_context};
|
||||
content::WebContents::CreateParams params(session->browser_context());
|
||||
params.initially_hidden = !initially_shown;
|
||||
web_contents = content::WebContents::Create(params);
|
||||
}
|
||||
|
||||
InitWithSessionAndOptions(isolate, std::move(web_contents), browser_context,
|
||||
options);
|
||||
InitWithSessionAndOptions(isolate, std::move(web_contents),
|
||||
session->browser_context(), options);
|
||||
}
|
||||
|
||||
void WebContents::InitZoomController(content::WebContents* web_contents,
|
||||
|
||||
@@ -626,9 +626,6 @@ void ElectronBrowserMainParts::PostMainMessageLoopRun() {
|
||||
#if BUILDFLAG(IS_LINUX)
|
||||
ui::OzonePlatform::GetInstance()->PostMainMessageLoopRun();
|
||||
#endif
|
||||
|
||||
browser_.reset();
|
||||
js_env_.reset();
|
||||
}
|
||||
|
||||
#if !BUILDFLAG(IS_MAC)
|
||||
|
||||
@@ -116,6 +116,10 @@ class FileSystemAccessPermissionContext
|
||||
content::GlobalRenderFrameHostId frame_id,
|
||||
EntriesAllowedByEnterprisePolicyCallback callback) override;
|
||||
|
||||
enum class Access { kRead, kWrite, kReadWrite };
|
||||
|
||||
enum class RequestType { kNewPermission, kRestorePermissions };
|
||||
|
||||
void RevokeActiveGrants(const url::Origin& origin,
|
||||
const base::FilePath& file_path = base::FilePath());
|
||||
|
||||
|
||||
@@ -117,30 +117,6 @@ NSArray* ConvertSharingItemToNS(const SharingItem& item) {
|
||||
return result;
|
||||
}
|
||||
|
||||
// Convert a Badge to an NSMenuItemBadge.
|
||||
NSMenuItemBadge* CreateBadge(const electron::ElectronMenuModel::Badge& badge)
|
||||
API_AVAILABLE(macos(14.0)) {
|
||||
NSString* badgeType = base::SysUTF16ToNSString(badge.type);
|
||||
|
||||
if ([badgeType isEqualToString:@"alerts"]) {
|
||||
if (badge.count.has_value())
|
||||
return [NSMenuItemBadge alertsWithCount:badge.count.value()];
|
||||
} else if ([badgeType isEqualToString:@"updates"]) {
|
||||
if (badge.count.has_value())
|
||||
return [NSMenuItemBadge updatesWithCount:badge.count.value()];
|
||||
} else if ([badgeType isEqualToString:@"new-items"]) {
|
||||
if (badge.count.has_value())
|
||||
return [NSMenuItemBadge newItemsWithCount:badge.count.value()];
|
||||
} else if ([badgeType isEqualToString:@"none"]) {
|
||||
if (badge.content.has_value()) {
|
||||
NSString* content = base::SysUTF8ToNSString(badge.content.value());
|
||||
return [[NSMenuItemBadge alloc] initWithString:content];
|
||||
}
|
||||
}
|
||||
|
||||
return nil;
|
||||
}
|
||||
|
||||
} // namespace
|
||||
|
||||
// This class stores a base::WeakPtr<electron::ElectronMenuModel> as an
|
||||
@@ -365,12 +341,14 @@ NSMenuItemBadge* CreateBadge(const electron::ElectronMenuModel::Badge& badge)
|
||||
electron::ElectronMenuModel::ItemType type = model->GetTypeAt(index);
|
||||
std::u16string customType = model->GetCustomTypeAt(index);
|
||||
|
||||
// The sectionHeaderWithTitle menu item is only available in macOS 14.0+.
|
||||
if (@available(macOS 14, *)) {
|
||||
if (customType == u"header") {
|
||||
item = [NSMenuItem sectionHeaderWithTitle:label];
|
||||
}
|
||||
}
|
||||
|
||||
// If the menu item has an icon, set it.
|
||||
ui::ImageModel icon = model->GetIconAt(index);
|
||||
if (icon.IsImage())
|
||||
item.image = icon.GetImage().ToNSImage();
|
||||
@@ -378,15 +356,6 @@ NSMenuItemBadge* CreateBadge(const electron::ElectronMenuModel::Badge& badge)
|
||||
std::u16string toolTip = model->GetToolTipAt(index);
|
||||
item.toolTip = base::SysUTF16ToNSString(toolTip);
|
||||
|
||||
if (@available(macOS 14, *)) {
|
||||
electron::ElectronMenuModel::Badge badge;
|
||||
if (model->GetBadgeAt(index, &badge)) {
|
||||
NSMenuItemBadge* nsBadge = CreateBadge(badge);
|
||||
if (nsBadge)
|
||||
item.badge = nsBadge;
|
||||
}
|
||||
}
|
||||
|
||||
if (role == u"services") {
|
||||
std::u16string title = u"Services";
|
||||
NSString* sub_label = l10n_util::FixUpWindowsStyleLabel(title);
|
||||
@@ -548,15 +517,6 @@ NSMenuItemBadge* CreateBadge(const electron::ElectronMenuModel::Badge& badge)
|
||||
} else {
|
||||
item.image = nil;
|
||||
}
|
||||
|
||||
if (@available(macOS 14, *)) {
|
||||
electron::ElectronMenuModel::Badge badge;
|
||||
if (model->GetBadgeAt(index, &badge)) {
|
||||
item.badge = CreateBadge(badge);
|
||||
} else {
|
||||
item.badge = nil;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
- (void)refreshMenuTree:(NSMenu*)menu {
|
||||
|
||||
@@ -12,15 +12,6 @@ namespace electron {
|
||||
ElectronMenuModel::SharingItem::SharingItem() = default;
|
||||
ElectronMenuModel::SharingItem::SharingItem(SharingItem&&) = default;
|
||||
ElectronMenuModel::SharingItem::~SharingItem() = default;
|
||||
|
||||
ElectronMenuModel::Badge::Badge() = default;
|
||||
ElectronMenuModel::Badge::Badge(Badge&&) = default;
|
||||
ElectronMenuModel::Badge::Badge(const Badge&) = default;
|
||||
ElectronMenuModel::Badge& ElectronMenuModel::Badge::operator=(const Badge&) =
|
||||
default;
|
||||
ElectronMenuModel::Badge& ElectronMenuModel::Badge::operator=(Badge&&) =
|
||||
default;
|
||||
ElectronMenuModel::Badge::~Badge() = default;
|
||||
#endif
|
||||
|
||||
bool ElectronMenuModel::Delegate::GetAcceleratorForCommandId(
|
||||
@@ -124,21 +115,6 @@ bool ElectronMenuModel::GetSharingItemAt(size_t index,
|
||||
void ElectronMenuModel::SetSharingItem(SharingItem item) {
|
||||
sharing_item_.emplace(std::move(item));
|
||||
}
|
||||
|
||||
void ElectronMenuModel::SetBadge(size_t index, Badge badge) {
|
||||
int command_id = GetCommandIdAt(index);
|
||||
badges_[command_id] = std::move(badge);
|
||||
}
|
||||
|
||||
bool ElectronMenuModel::GetBadgeAt(size_t index, Badge* badge) const {
|
||||
int command_id = GetCommandIdAt(index);
|
||||
const auto iter = badges_.find(command_id);
|
||||
if (iter != badges_.end()) {
|
||||
*badge = iter->second;
|
||||
return true;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
#endif
|
||||
|
||||
void ElectronMenuModel::MenuWillClose() {
|
||||
|
||||
@@ -33,19 +33,6 @@ class ElectronMenuModel : public ui::SimpleMenuModel {
|
||||
std::optional<std::vector<GURL>> urls;
|
||||
std::optional<std::vector<base::FilePath>> file_paths;
|
||||
};
|
||||
|
||||
struct Badge {
|
||||
Badge();
|
||||
Badge(Badge&&);
|
||||
Badge(const Badge&);
|
||||
Badge& operator=(const Badge&);
|
||||
Badge& operator=(Badge&&);
|
||||
~Badge();
|
||||
|
||||
std::u16string type; // "alerts", "updates", "new-items", or "none"
|
||||
std::optional<int> count;
|
||||
std::optional<std::string> content;
|
||||
};
|
||||
#endif
|
||||
|
||||
class Delegate : public ui::SimpleMenuModel::Delegate {
|
||||
@@ -118,9 +105,6 @@ class ElectronMenuModel : public ui::SimpleMenuModel {
|
||||
return sharing_item_;
|
||||
}
|
||||
|
||||
// Set/Get the Badge of a menu item.
|
||||
void SetBadge(size_t index, Badge badge);
|
||||
bool GetBadgeAt(size_t index, Badge* badge) const;
|
||||
#endif
|
||||
|
||||
// ui::SimpleMenuModel:
|
||||
@@ -139,7 +123,6 @@ class ElectronMenuModel : public ui::SimpleMenuModel {
|
||||
|
||||
#if BUILDFLAG(IS_MAC)
|
||||
std::optional<SharingItem> sharing_item_;
|
||||
base::flat_map<int, Badge> badges_; // command id -> badge
|
||||
#endif
|
||||
|
||||
base::flat_map<int, std::u16string> toolTips_; // command id -> tooltip
|
||||
|
||||
@@ -705,10 +705,8 @@ gin_helper::Handle<SimpleURLLoaderWrapper> SimpleURLLoaderWrapper::Create(
|
||||
else // default session
|
||||
session = Session::FromPartition(args->isolate(), "");
|
||||
}
|
||||
if (session) {
|
||||
if (session)
|
||||
browser_context = session->browser_context();
|
||||
DCHECK(browser_context != nullptr);
|
||||
}
|
||||
}
|
||||
|
||||
auto ret = gin_helper::CreateHandle(
|
||||
|
||||
@@ -10,7 +10,7 @@
|
||||
#include <vector>
|
||||
|
||||
#include "base/containers/span.h"
|
||||
#include "base/memory/memory_pressure_listener_registry.h"
|
||||
#include "base/memory/memory_pressure_listener.h"
|
||||
#include "base/no_destructor.h"
|
||||
#include "base/strings/strcat.h"
|
||||
#include "base/strings/utf_string_conversions.h"
|
||||
@@ -810,7 +810,7 @@ class WebFrameRenderer final
|
||||
|
||||
void ClearCache(v8::Isolate* isolate) {
|
||||
blink::WebCache::Clear();
|
||||
base::MemoryPressureListenerRegistry::NotifyMemoryPressure(
|
||||
base::MemoryPressureListener::NotifyMemoryPressure(
|
||||
base::MEMORY_PRESSURE_LEVEL_CRITICAL);
|
||||
}
|
||||
|
||||
|
||||
@@ -59,6 +59,7 @@ const startServer = async () => {
|
||||
function waitForCrash (): Promise<CrashInfo> {
|
||||
return new Promise(resolve => {
|
||||
emitter.once('crash', (crash) => {
|
||||
console.log('crash fired', crash);
|
||||
resolve(crash);
|
||||
});
|
||||
});
|
||||
@@ -69,6 +70,7 @@ const startServer = async () => {
|
||||
const fields = {} as Record<string, any>;
|
||||
const files = {} as Record<string, Buffer>;
|
||||
busboy.on('file', (fieldname, file) => {
|
||||
console.log('Receiving file for :', fieldname);
|
||||
const chunks = [] as Array<Buffer>;
|
||||
file.on('data', (chunk) => {
|
||||
chunks.push(chunk);
|
||||
@@ -81,10 +83,12 @@ const startServer = async () => {
|
||||
fields[fieldname] = val;
|
||||
});
|
||||
busboy.on('finish', () => {
|
||||
console.log('On finish');
|
||||
// breakpad id must be 16 hex digits.
|
||||
const reportId = Math.random().toString(16).split('.')[1].padStart(16, '0');
|
||||
res.end(reportId, async () => {
|
||||
req.socket.destroy();
|
||||
console.log('Emmitting crash:', fields);
|
||||
emitter.emit('crash', { ...fields, ...files });
|
||||
});
|
||||
});
|
||||
@@ -138,10 +142,15 @@ function waitForNewFileInDir (dir: string): Promise<string[]> {
|
||||
ifdescribe(!isLinuxOnArm && !process.mas && !process.env.DISABLE_CRASH_REPORTER_TESTS)('crashReporter module', function () {
|
||||
describe('should send minidump', () => {
|
||||
it('when renderer crashes', async () => {
|
||||
console.log('starting server for renderer crash test');
|
||||
const { port, waitForCrash } = await startServer();
|
||||
console.log('Done starting server for renderer crash test');
|
||||
runCrashApp('renderer', port);
|
||||
console.log('Waiting for renderer crash');
|
||||
const crash = await waitForCrash();
|
||||
console.log('Renderer crash received');
|
||||
checkCrash('renderer', crash);
|
||||
console.log('Renderer crash checked');
|
||||
expect(crash.mainProcessSpecific).to.be.undefined();
|
||||
});
|
||||
|
||||
|
||||
@@ -1,6 +1,5 @@
|
||||
import { expect } from 'chai';
|
||||
|
||||
import { once } from 'node:events';
|
||||
import * as path from 'node:path';
|
||||
|
||||
import { ifdescribe, isTestingBindingAvailable, startRemoteControlApp } from './lib/spec-helpers';
|
||||
@@ -40,33 +39,6 @@ describe('cpp heap', () => {
|
||||
});
|
||||
|
||||
describe('session module', () => {
|
||||
it('does not crash on exit with live session wrappers', async () => {
|
||||
const rc = await startRemoteControlApp();
|
||||
await rc.remotely(async () => {
|
||||
const { app, session } = require('electron');
|
||||
|
||||
const sessions = [
|
||||
session.defaultSession,
|
||||
session.fromPartition('cppheap-exit'),
|
||||
session.fromPartition('persist:cppheap-exit-persist')
|
||||
];
|
||||
|
||||
// We want to test GC on shutdown, so add a global reference
|
||||
// to these sessions to prevent pre-shutdown GC.
|
||||
(globalThis as any).sessionRefs = sessions;
|
||||
|
||||
// We want to test CppGC-traced references during shutdown.
|
||||
// The CppGC-managed cookies will do that; but since they're
|
||||
// lazy-created, access them here to ensure they're live.
|
||||
sessions.forEach(ses => ses.cookies);
|
||||
|
||||
setTimeout(() => app.quit());
|
||||
});
|
||||
|
||||
const [code] = await once(rc.process, 'exit');
|
||||
expect(code).to.equal(0);
|
||||
});
|
||||
|
||||
it('should record as node in heap snapshot', async () => {
|
||||
const { remotely } = await startRemoteControlApp(['--expose-internals']);
|
||||
const result = await remotely(async (heap: string, snapshotHelper: string) => {
|
||||
|
||||
2
typings/internal-electron.d.ts
vendored
2
typings/internal-electron.d.ts
vendored
@@ -166,7 +166,6 @@ declare namespace Electron {
|
||||
commandsMap: Record<string, MenuItem>;
|
||||
groupsMap: Record<string, MenuItem[]>;
|
||||
getItemCount(): number;
|
||||
getIndexOfCommandId(commandId: number): number;
|
||||
popupAt(window: BaseWindow, frame: WebFrameMain | undefined, x: number, y: number, positioning: number, sourceType: Required<Electron.PopupOptions>['sourceType'], callback: () => void): void;
|
||||
closePopupAt(id: number): void;
|
||||
setSublabel(index: number, label: string): void;
|
||||
@@ -174,7 +173,6 @@ declare namespace Electron {
|
||||
setIcon(index: number, image: string | NativeImage): void;
|
||||
setRole(index: number, role: string): void;
|
||||
setCustomType(index: number, customType: string): void;
|
||||
setBadge(index: number, badge: MenuItemBadge): void;
|
||||
insertItem(index: number, commandId: number, label: string): void;
|
||||
insertCheckItem(index: number, commandId: number, label: string): void;
|
||||
insertRadioItem(index: number, commandId: number, label: string, groupId: number): void;
|
||||
|
||||
Reference in New Issue
Block a user