mirror of
https://github.com/electron/electron.git
synced 2026-02-26 03:01:17 -05:00
Compare commits
74 Commits
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
87badb84f8 | ||
|
|
2f3a1ca461 | ||
|
|
81ae20905c | ||
|
|
da4a808af7 | ||
|
|
71579e4749 | ||
|
|
06fdee87b3 | ||
|
|
6ce52ad792 | ||
|
|
7784d25821 | ||
|
|
126a32c5d2 | ||
|
|
811b1d6326 | ||
|
|
50fc493ae6 | ||
|
|
9453e8bfe1 | ||
|
|
a4eb213a04 | ||
|
|
81c08e80f6 | ||
|
|
5f630c7de7 | ||
|
|
2dc82ea1f3 | ||
|
|
f57d6f92b6 | ||
|
|
744142fe54 | ||
|
|
b200b8d6c0 | ||
|
|
cdaf0e96b6 | ||
|
|
981df181c1 | ||
|
|
218300e57f | ||
|
|
6ccee512e4 | ||
|
|
b6e4f514d8 | ||
|
|
ade4c00984 | ||
|
|
d8687cfc9d | ||
|
|
2ab4489447 | ||
|
|
ab9b156113 | ||
|
|
35a531953b | ||
|
|
4d18062d0f | ||
|
|
832ffb2330 | ||
|
|
03121eeaef | ||
|
|
8282c07a0f | ||
|
|
f2d1cb21b0 | ||
|
|
ef9b4162af | ||
|
|
6e97bca80d | ||
|
|
c511fc5c3f | ||
|
|
22dfbb0822 | ||
|
|
85913a38da | ||
|
|
a327629ca2 | ||
|
|
7deed2b980 | ||
|
|
65fc06a9f7 | ||
|
|
245e70aedd | ||
|
|
2a8164f499 | ||
|
|
2f7024dbcc | ||
|
|
d53d3bb99e | ||
|
|
c2c1d40294 | ||
|
|
0e9decd459 | ||
|
|
b2e73d28e2 | ||
|
|
aeb5af803f | ||
|
|
53819a8a2a | ||
|
|
14565211f7 | ||
|
|
00646c9db6 | ||
|
|
d9c33a951a | ||
|
|
8b02e33187 | ||
|
|
eecca2cb19 | ||
|
|
08b5ef556c | ||
|
|
ab85f2c2f7 | ||
|
|
1936243ce1 | ||
|
|
e7e052f5b1 | ||
|
|
349a9b6398 | ||
|
|
b5f19ce974 | ||
|
|
bb930b887b | ||
|
|
e962bc3743 | ||
|
|
895cf006e7 | ||
|
|
bc1ca72dc7 | ||
|
|
a9a4c77353 | ||
|
|
0f613246d9 | ||
|
|
a77b92adf2 | ||
|
|
d62c324567 | ||
|
|
108a26a0f9 | ||
|
|
331f8cca47 | ||
|
|
215128715a | ||
|
|
efcab52714 |
@@ -2,7 +2,7 @@ version: '3'
|
||||
|
||||
services:
|
||||
buildtools:
|
||||
image: ghcr.io/electron/devcontainer:933c7d6ff6802706875270bec2e3c891cf8add3f
|
||||
image: ghcr.io/electron/devcontainer:a82b87d7a4f5ff0cab61405f8151ac4cf4942aeb
|
||||
|
||||
volumes:
|
||||
- ..:/workspaces/gclient/src/electron:cached
|
||||
|
||||
2
.github/actions/build-electron/action.yml
vendored
2
.github/actions/build-electron/action.yml
vendored
@@ -184,7 +184,7 @@ runs:
|
||||
shell: bash
|
||||
run: |
|
||||
cd src/electron
|
||||
node script/yarn create-typescript-definitions
|
||||
node script/yarn.js create-typescript-definitions
|
||||
- name: Publish Electron Dist ${{ inputs.step-suffix }}
|
||||
if: ${{ inputs.is-release == 'true' }}
|
||||
shell: bash
|
||||
|
||||
5
.github/actions/checkout/action.yml
vendored
5
.github/actions/checkout/action.yml
vendored
@@ -143,16 +143,17 @@ runs:
|
||||
echo "No changes to patches detected"
|
||||
fi
|
||||
fi
|
||||
- name: Remove patch conflict problem matcher
|
||||
- name: Remove patch conflict problem matchers
|
||||
shell: bash
|
||||
run: |
|
||||
echo "::remove-matcher owner=merge-conflict::"
|
||||
echo "::remove-matcher owner=patch-conflict::"
|
||||
echo "::remove-matcher owner=patch-needs-update::"
|
||||
- name: Upload patches stats
|
||||
if: ${{ inputs.target-platform == 'linux' && github.ref == 'refs/heads/main' }}
|
||||
shell: bash
|
||||
run: |
|
||||
npx node src/electron/script/patches-stats.mjs --upload-stats || true
|
||||
node src/electron/script/patches-stats.mjs --upload-stats || true
|
||||
# delete all .git directories under src/ except for
|
||||
# third_party/angle/ and third_party/dawn/ because of build time generation of files
|
||||
# gen/angle/commit.h depends on third_party/angle/.git/HEAD
|
||||
|
||||
11
.github/actions/free-space-macos/action.yml
vendored
11
.github/actions/free-space-macos/action.yml
vendored
@@ -64,15 +64,24 @@ runs:
|
||||
sudo rm -rf /Applications/Xcode_16.1.app
|
||||
sudo rm -rf /Applications/Xcode_16.2.app
|
||||
sudo rm -rf /Applications/Xcode_16.3.app
|
||||
sudo rm -rf /Applications/Xcode_26*
|
||||
sudo rm -rf /Applications/Google Chrome.app
|
||||
sudo rm -rf /Applications/Google Chrome for Testing.app
|
||||
sudo rm -rf /Applications/Firefox.app
|
||||
sudo rm -rf /Applications/Firefox.app
|
||||
sudo rm -rf /Applications/Microsoft Edge.app
|
||||
sudo rm -rf ~/project/src/third_party/catapult/tracing/test_data
|
||||
sudo rm -rf ~/project/src/third_party/angle/third_party/VK-GL-CTS
|
||||
sudo rm -rf /Users/runner/Library/Android
|
||||
sudo rm -rf $JAVA_HOME_11_arm64
|
||||
sudo rm -rf $JAVA_HOME_17_arm64
|
||||
sudo rm -rf $JAVA_HOME_21_arm64
|
||||
sudo rm -rf $JAVA_HOME_25_arm64
|
||||
sudo rm -rf /Users/runner/.dotnet/
|
||||
sudo rm -rf /Users/runner/.rustup
|
||||
|
||||
# remove homebrew packages we don't need
|
||||
brew uninstall -f --zap aws-sam-cli session-manager-plugin gcc gcc@13 gcc@14 llvm@18 gradle maven ant azure-cli
|
||||
brew autoremove
|
||||
|
||||
# lipo off some huge binaries arm64 versions to save space
|
||||
strip_universal_deep $(xcode-select -p)/../SharedFrameworks
|
||||
|
||||
14
.github/actions/generate-types/action.yml
vendored
14
.github/actions/generate-types/action.yml
vendored
@@ -13,12 +13,16 @@ runs:
|
||||
- name: Generating Types for SHA in ${{ inputs.sha-file }}
|
||||
shell: bash
|
||||
run: |
|
||||
git checkout $(cat ${{ inputs.sha-file }})
|
||||
rm -rf node_modules
|
||||
yarn install --frozen-lockfile --ignore-scripts
|
||||
export ELECTRON_DIR=$(pwd)
|
||||
if [ "${{ inputs.sha-file }}" == ".dig-old" ]; then
|
||||
cd /tmp
|
||||
git clone https://github.com/electron/electron.git
|
||||
cd electron
|
||||
fi
|
||||
git checkout $(cat $ELECTRON_DIR/${{ inputs.sha-file }})
|
||||
node script/yarn.js install --immutable
|
||||
echo "#!/usr/bin/env node\nglobal.x=1" > node_modules/typescript/bin/tsc
|
||||
node node_modules/.bin/electron-docs-parser --dir=./ --outDir=./ --moduleVersion=0.0.0-development
|
||||
node node_modules/.bin/electron-typescript-definitions --api=electron-api.json --outDir=artifacts
|
||||
mv artifacts/electron.d.ts artifacts/${{ inputs.filename }}
|
||||
git checkout .
|
||||
mv artifacts/electron.d.ts $ELECTRON_DIR/artifacts/${{ inputs.filename }}
|
||||
working-directory: ./electron
|
||||
|
||||
@@ -15,7 +15,7 @@ runs:
|
||||
git config --global core.preloadindex true
|
||||
git config --global core.longpaths true
|
||||
fi
|
||||
export BUILD_TOOLS_SHA=a5d9f9052dcc36ee88bef5c8b13acbefd87b7d8d
|
||||
export BUILD_TOOLS_SHA=4430e4a505e0f4fa2a41b707a10a36f780bbdd26
|
||||
npm i -g @electron/build-tools
|
||||
# Update depot_tools to ensure python
|
||||
e d update_depot_tools
|
||||
|
||||
14
.github/actions/install-dependencies/action.yml
vendored
14
.github/actions/install-dependencies/action.yml
vendored
@@ -6,7 +6,7 @@ runs:
|
||||
- name: Get yarn cache directory path
|
||||
shell: bash
|
||||
id: yarn-cache-dir-path
|
||||
run: echo "dir=$(node src/electron/script/yarn cache dir)" >> $GITHUB_OUTPUT
|
||||
run: echo "dir=$(node src/electron/script/yarn.js config get cacheFolder)" >> $GITHUB_OUTPUT
|
||||
- uses: actions/cache@5a3ec84eff668545956fd18022155c47e93e2684 # v4.2.3
|
||||
id: yarn-cache
|
||||
with:
|
||||
@@ -18,4 +18,14 @@ runs:
|
||||
shell: bash
|
||||
run: |
|
||||
cd src/electron
|
||||
node script/yarn install --frozen-lockfile --prefer-offline
|
||||
if [ "$TARGET_ARCH" = "x86" ]; then
|
||||
export npm_config_arch="ia32"
|
||||
fi
|
||||
# if running on linux arm skip yarn Builds
|
||||
ARCH=$(uname -m)
|
||||
if [ "$ARCH" = "armv7l" ]; then
|
||||
echo "Skipping yarn build on linux arm"
|
||||
node script/yarn.js install --immutable --mode=skip-build
|
||||
else
|
||||
node script/yarn.js install --immutable
|
||||
fi
|
||||
|
||||
10
.github/problem-matchers/patch-conflict.json
vendored
10
.github/problem-matchers/patch-conflict.json
vendored
@@ -19,6 +19,16 @@
|
||||
"line": 3
|
||||
}
|
||||
]
|
||||
},
|
||||
{
|
||||
"owner": "patch-needs-update",
|
||||
"pattern": [
|
||||
{
|
||||
"regexp": "^((patches\/.*): needs update)$",
|
||||
"message": 1,
|
||||
"file": 2
|
||||
}
|
||||
]
|
||||
}
|
||||
]
|
||||
}
|
||||
|
||||
4
.github/workflows/archaeologist-dig.yml
vendored
4
.github/workflows/archaeologist-dig.yml
vendored
@@ -3,10 +3,14 @@ name: Archaeologist
|
||||
on:
|
||||
pull_request:
|
||||
|
||||
permissions: {}
|
||||
|
||||
jobs:
|
||||
archaeologist-dig:
|
||||
name: Archaeologist Dig
|
||||
runs-on: ubuntu-latest
|
||||
permissions:
|
||||
contents: read
|
||||
steps:
|
||||
- name: Checkout Electron
|
||||
uses: actions/checkout@11bd71901bbe5b1630ceea73d27597364c9af683 #v4.0.2
|
||||
|
||||
14
.github/workflows/build-git-cache.yml
vendored
14
.github/workflows/build-git-cache.yml
vendored
@@ -6,11 +6,15 @@ on:
|
||||
schedule:
|
||||
- cron: "0 0 * * *"
|
||||
|
||||
permissions: {}
|
||||
|
||||
jobs:
|
||||
build-git-cache-linux:
|
||||
runs-on: electron-arc-centralus-linux-amd64-32core
|
||||
permissions:
|
||||
contents: read
|
||||
container:
|
||||
image: ghcr.io/electron/build:bc2f48b2415a670de18d13605b1cf0eb5fdbaae1
|
||||
image: ghcr.io/electron/build:a82b87d7a4f5ff0cab61405f8151ac4cf4942aeb
|
||||
options: --user root
|
||||
volumes:
|
||||
- /mnt/cross-instance-cache:/mnt/cross-instance-cache
|
||||
@@ -30,8 +34,10 @@ jobs:
|
||||
|
||||
build-git-cache-windows:
|
||||
runs-on: electron-arc-centralus-linux-amd64-32core
|
||||
permissions:
|
||||
contents: read
|
||||
container:
|
||||
image: ghcr.io/electron/build:bc2f48b2415a670de18d13605b1cf0eb5fdbaae1
|
||||
image: ghcr.io/electron/build:a82b87d7a4f5ff0cab61405f8151ac4cf4942aeb
|
||||
options: --user root --device /dev/fuse --cap-add SYS_ADMIN
|
||||
volumes:
|
||||
- /mnt/win-cache:/mnt/win-cache
|
||||
@@ -52,10 +58,12 @@ jobs:
|
||||
|
||||
build-git-cache-macos:
|
||||
runs-on: electron-arc-centralus-linux-amd64-32core
|
||||
permissions:
|
||||
contents: read
|
||||
# This job updates the same git cache as linux, so it needs to run after the linux one.
|
||||
needs: build-git-cache-linux
|
||||
container:
|
||||
image: ghcr.io/electron/build:bc2f48b2415a670de18d13605b1cf0eb5fdbaae1
|
||||
image: ghcr.io/electron/build:a82b87d7a4f5ff0cab61405f8151ac4cf4942aeb
|
||||
options: --user root
|
||||
volumes:
|
||||
- /mnt/cross-instance-cache:/mnt/cross-instance-cache
|
||||
|
||||
70
.github/workflows/build.yml
vendored
70
.github/workflows/build.yml
vendored
@@ -6,7 +6,7 @@ on:
|
||||
build-image-sha:
|
||||
type: string
|
||||
description: 'SHA for electron/build image'
|
||||
default: '933c7d6ff6802706875270bec2e3c891cf8add3f'
|
||||
default: 'a82b87d7a4f5ff0cab61405f8151ac4cf4942aeb'
|
||||
required: true
|
||||
skip-macos:
|
||||
type: boolean
|
||||
@@ -43,16 +43,20 @@ defaults:
|
||||
run:
|
||||
shell: bash
|
||||
|
||||
permissions: {}
|
||||
|
||||
jobs:
|
||||
setup:
|
||||
runs-on: ubuntu-latest
|
||||
permissions:
|
||||
contents: read
|
||||
pull-requests: read
|
||||
outputs:
|
||||
docs: ${{ steps.filter.outputs.docs }}
|
||||
src: ${{ steps.filter.outputs.src }}
|
||||
build-image-sha: ${{ steps.set-output.outputs.build-image-sha }}
|
||||
docs-only: ${{ steps.set-output.outputs.docs-only }}
|
||||
has-patches: ${{ steps.filter.outputs.patches }}
|
||||
steps:
|
||||
- uses: actions/checkout@11bd71901bbe5b1630ceea73d27597364c9af683 #v4.0.2
|
||||
with:
|
||||
@@ -63,13 +67,20 @@ jobs:
|
||||
filters: |
|
||||
docs:
|
||||
- 'docs/**'
|
||||
- README.md
|
||||
- SECURITY.md
|
||||
- CONTRIBUTING.md
|
||||
- CODE_OF_CONDUCT.md
|
||||
src:
|
||||
- '!docs/**'
|
||||
patches:
|
||||
- DEPS
|
||||
- 'patches/**'
|
||||
- name: Set Outputs for Build Image SHA & Docs Only
|
||||
id: set-output
|
||||
run: |
|
||||
if [ -z "${{ inputs.build-image-sha }}" ]; then
|
||||
echo "build-image-sha=933c7d6ff6802706875270bec2e3c891cf8add3f" >> "$GITHUB_OUTPUT"
|
||||
echo "build-image-sha=a82b87d7a4f5ff0cab61405f8151ac4cf4942aeb" >> "$GITHUB_OUTPUT"
|
||||
else
|
||||
echo "build-image-sha=${{ inputs.build-image-sha }}" >> "$GITHUB_OUTPUT"
|
||||
fi
|
||||
@@ -80,6 +91,8 @@ jobs:
|
||||
needs: setup
|
||||
if: ${{ !inputs.skip-lint }}
|
||||
uses: ./.github/workflows/pipeline-electron-lint.yml
|
||||
permissions:
|
||||
contents: read
|
||||
with:
|
||||
container: '{"image":"ghcr.io/electron/build:${{ needs.setup.outputs.build-image-sha }}","options":"--user root"}'
|
||||
secrets: inherit
|
||||
@@ -89,15 +102,54 @@ jobs:
|
||||
needs: [setup, checkout-linux]
|
||||
if: ${{ needs.setup.outputs.docs-only == 'true' }}
|
||||
uses: ./.github/workflows/pipeline-electron-docs-only.yml
|
||||
permissions:
|
||||
contents: read
|
||||
with:
|
||||
container: '{"image":"ghcr.io/electron/build:${{ needs.checkout-linux.outputs.build-image-sha }}","options":"--user root","volumes":["/mnt/cross-instance-cache:/mnt/cross-instance-cache"]}'
|
||||
secrets: inherit
|
||||
|
||||
# Apply Patches Job
|
||||
apply-patches:
|
||||
needs: setup
|
||||
if: ${{ needs.setup.outputs.has-patches == 'true' }}
|
||||
runs-on: electron-arc-centralus-linux-amd64-32core
|
||||
permissions:
|
||||
contents: read
|
||||
container:
|
||||
image: ghcr.io/electron/build:${{ needs.setup.outputs.build-image-sha }}
|
||||
options: --user root
|
||||
volumes:
|
||||
- /mnt/cross-instance-cache:/mnt/cross-instance-cache
|
||||
- /var/run/sas:/var/run/sas
|
||||
env:
|
||||
CHROMIUM_GIT_COOKIE: ${{ secrets.CHROMIUM_GIT_COOKIE }}
|
||||
GCLIENT_EXTRA_ARGS: '--custom-var=checkout_arm=True --custom-var=checkout_arm64=True'
|
||||
steps:
|
||||
- name: Checkout Electron
|
||||
uses: actions/checkout@8e8c483db84b4bee98b60c0593521ed34d9990e8
|
||||
with:
|
||||
path: src/electron
|
||||
fetch-depth: 0
|
||||
ref: ${{ github.event.pull_request.head.sha }}
|
||||
- name: Rebase onto Base Branch
|
||||
working-directory: src/electron
|
||||
run: |
|
||||
git config user.email "electron@github.com"
|
||||
git config user.name "Electron Bot"
|
||||
git fetch origin ${{ github.event.pull_request.base.ref }}
|
||||
git rebase origin/${{ github.event.pull_request.base.ref }}
|
||||
- name: Checkout & Sync & Save
|
||||
uses: ./src/electron/.github/actions/checkout
|
||||
with:
|
||||
target-platform: linux
|
||||
|
||||
# Checkout Jobs
|
||||
checkout-macos:
|
||||
needs: setup
|
||||
if: ${{ needs.setup.outputs.src == 'true' && !inputs.skip-macos}}
|
||||
runs-on: electron-arc-centralus-linux-amd64-32core
|
||||
permissions:
|
||||
contents: read
|
||||
container:
|
||||
image: ghcr.io/electron/build:${{ needs.setup.outputs.build-image-sha }}
|
||||
options: --user root
|
||||
@@ -126,6 +178,8 @@ jobs:
|
||||
needs: setup
|
||||
if: ${{ !inputs.skip-linux}}
|
||||
runs-on: electron-arc-centralus-linux-amd64-32core
|
||||
permissions:
|
||||
contents: read
|
||||
container:
|
||||
image: ghcr.io/electron/build:${{ needs.setup.outputs.build-image-sha }}
|
||||
options: --user root
|
||||
@@ -155,6 +209,8 @@ jobs:
|
||||
needs: setup
|
||||
if: ${{ needs.setup.outputs.src == 'true' && !inputs.skip-windows }}
|
||||
runs-on: electron-arc-centralus-linux-amd64-32core
|
||||
permissions:
|
||||
contents: read
|
||||
container:
|
||||
image: ghcr.io/electron/build:${{ needs.setup.outputs.build-image-sha }}
|
||||
options: --user root --device /dev/fuse --cap-add SYS_ADMIN
|
||||
@@ -185,6 +241,8 @@ jobs:
|
||||
# GN Check Jobs
|
||||
macos-gn-check:
|
||||
uses: ./.github/workflows/pipeline-segment-electron-gn-check.yml
|
||||
permissions:
|
||||
contents: read
|
||||
needs: checkout-macos
|
||||
with:
|
||||
target-platform: macos
|
||||
@@ -195,6 +253,8 @@ jobs:
|
||||
|
||||
linux-gn-check:
|
||||
uses: ./.github/workflows/pipeline-segment-electron-gn-check.yml
|
||||
permissions:
|
||||
contents: read
|
||||
needs: checkout-linux
|
||||
if: ${{ needs.setup.outputs.src == 'true' }}
|
||||
with:
|
||||
@@ -207,6 +267,8 @@ jobs:
|
||||
|
||||
windows-gn-check:
|
||||
uses: ./.github/workflows/pipeline-segment-electron-gn-check.yml
|
||||
permissions:
|
||||
contents: read
|
||||
needs: checkout-windows
|
||||
with:
|
||||
target-platform: win
|
||||
@@ -310,7 +372,7 @@ jobs:
|
||||
build-runs-on: electron-arc-centralus-linux-amd64-32core
|
||||
test-runs-on: electron-arc-centralus-linux-arm64-4core
|
||||
build-container: '{"image":"ghcr.io/electron/build:${{ needs.checkout-linux.outputs.build-image-sha }}","options":"--user root","volumes":["/mnt/cross-instance-cache:/mnt/cross-instance-cache"]}'
|
||||
test-container: '{"image":"ghcr.io/electron/test:arm32v7-${{ needs.checkout-linux.outputs.build-image-sha }}","options":"--user root --privileged --init","volumes":["/home/runner/externals:/mnt/runner-externals"]}'
|
||||
test-container: '{"image":"ghcr.io/electron/test:arm32v7-${{ needs.checkout-linux.outputs.build-image-sha }}","options":"--user root --privileged --init --memory=12g","volumes":["/home/runner/externals:/mnt/runner-externals"]}'
|
||||
target-platform: linux
|
||||
target-arch: arm
|
||||
is-release: false
|
||||
@@ -400,6 +462,8 @@ jobs:
|
||||
gha-done:
|
||||
name: GitHub Actions Completed
|
||||
runs-on: ubuntu-latest
|
||||
permissions:
|
||||
contents: read
|
||||
needs: [docs-only, macos-x64, macos-arm64, linux-x64, linux-x64-asan, linux-arm, linux-arm64, windows-x64, windows-x86, windows-arm64]
|
||||
if: always() && !contains(needs.*.result, 'failure')
|
||||
steps:
|
||||
|
||||
10
.github/workflows/clean-src-cache.yml
vendored
10
.github/workflows/clean-src-cache.yml
vendored
@@ -1,16 +1,20 @@
|
||||
name: Clean Source Cache
|
||||
|
||||
description: |
|
||||
This workflow cleans up the source cache on the cross-instance cache volume
|
||||
to free up space. It runs daily at midnight and clears files older than 15 days.
|
||||
# Description:
|
||||
# This workflow cleans up the source cache on the cross-instance cache volume
|
||||
# to free up space. It runs daily at midnight and clears files older than 15 days.
|
||||
|
||||
on:
|
||||
schedule:
|
||||
- cron: "0 0 * * *"
|
||||
|
||||
permissions: {}
|
||||
|
||||
jobs:
|
||||
clean-src-cache:
|
||||
runs-on: electron-arc-centralus-linux-amd64-32core
|
||||
permissions:
|
||||
contents: read
|
||||
container:
|
||||
image: ghcr.io/electron/build:bc2f48b2415a670de18d13605b1cf0eb5fdbaae1
|
||||
options: --user root
|
||||
|
||||
7
.github/workflows/issue-labeled.yml
vendored
7
.github/workflows/issue-labeled.yml
vendored
@@ -4,14 +4,15 @@ on:
|
||||
issues:
|
||||
types: [labeled]
|
||||
|
||||
permissions: # added using https://github.com/step-security/secure-workflows
|
||||
contents: read
|
||||
permissions: {}
|
||||
|
||||
jobs:
|
||||
issue-labeled-with-status:
|
||||
name: status/{confirmed,reviewed} label added
|
||||
if: github.event.label.name == 'status/confirmed' || github.event.label.name == 'status/reviewed'
|
||||
runs-on: ubuntu-latest
|
||||
permissions:
|
||||
contents: read
|
||||
steps:
|
||||
- name: Generate GitHub App token
|
||||
uses: electron/github-app-auth-action@384fd19694fe7b6dcc9a684746c6976ad78228ae # v1.1.1
|
||||
@@ -31,6 +32,8 @@ jobs:
|
||||
name: blocked/* label added
|
||||
if: startsWith(github.event.label.name, 'blocked/')
|
||||
runs-on: ubuntu-latest
|
||||
permissions:
|
||||
contents: read
|
||||
steps:
|
||||
- name: Generate GitHub App token
|
||||
uses: electron/github-app-auth-action@384fd19694fe7b6dcc9a684746c6976ad78228ae # v1.1.1
|
||||
|
||||
2
.github/workflows/issue-opened.yml
vendored
2
.github/workflows/issue-opened.yml
vendored
@@ -11,6 +11,7 @@ jobs:
|
||||
add-to-issue-triage:
|
||||
if: ${{ contains(github.event.issue.labels.*.name, 'bug :beetle:') }}
|
||||
runs-on: ubuntu-latest
|
||||
permissions: {}
|
||||
steps:
|
||||
- name: Generate GitHub App token
|
||||
uses: electron/github-app-auth-action@384fd19694fe7b6dcc9a684746c6976ad78228ae # v1.1.1
|
||||
@@ -28,6 +29,7 @@ jobs:
|
||||
set-labels:
|
||||
if: ${{ contains(github.event.issue.labels.*.name, 'bug :beetle:') }}
|
||||
runs-on: ubuntu-latest
|
||||
permissions: {}
|
||||
steps:
|
||||
- name: Generate GitHub App token
|
||||
uses: electron/github-app-auth-action@384fd19694fe7b6dcc9a684746c6976ad78228ae # v1.1.1
|
||||
|
||||
1
.github/workflows/issue-transferred.yml
vendored
1
.github/workflows/issue-transferred.yml
vendored
@@ -10,6 +10,7 @@ jobs:
|
||||
issue-transferred:
|
||||
name: Issue Transferred
|
||||
runs-on: ubuntu-latest
|
||||
permissions: {}
|
||||
if: ${{ !github.event.changes.new_repository.private }}
|
||||
steps:
|
||||
- name: Generate GitHub App token
|
||||
|
||||
5
.github/workflows/issue-unlabeled.yml
vendored
5
.github/workflows/issue-unlabeled.yml
vendored
@@ -4,14 +4,15 @@ on:
|
||||
issues:
|
||||
types: [unlabeled]
|
||||
|
||||
permissions:
|
||||
contents: read
|
||||
permissions: {}
|
||||
|
||||
jobs:
|
||||
issue-unlabeled-blocked:
|
||||
name: All blocked/* labels removed
|
||||
if: startsWith(github.event.label.name, 'blocked/') && github.event.issue.state == 'open'
|
||||
runs-on: ubuntu-latest
|
||||
permissions:
|
||||
contents: read
|
||||
steps:
|
||||
- name: Check for any blocked labels
|
||||
id: check-for-blocked-labels
|
||||
|
||||
12
.github/workflows/linux-publish.yml
vendored
12
.github/workflows/linux-publish.yml
vendored
@@ -6,7 +6,7 @@ on:
|
||||
build-image-sha:
|
||||
type: string
|
||||
description: 'SHA for electron/build image'
|
||||
default: '933c7d6ff6802706875270bec2e3c891cf8add3f'
|
||||
default: 'a82b87d7a4f5ff0cab61405f8151ac4cf4942aeb'
|
||||
upload-to-storage:
|
||||
description: 'Uploads to Azure storage'
|
||||
required: false
|
||||
@@ -17,9 +17,13 @@ on:
|
||||
type: boolean
|
||||
default: false
|
||||
|
||||
permissions: {}
|
||||
|
||||
jobs:
|
||||
checkout-linux:
|
||||
runs-on: electron-arc-centralus-linux-amd64-32core
|
||||
permissions:
|
||||
contents: read
|
||||
container:
|
||||
image: ghcr.io/electron/build:${{ inputs.build-image-sha }}
|
||||
options: --user root
|
||||
@@ -40,6 +44,8 @@ jobs:
|
||||
|
||||
publish-x64:
|
||||
uses: ./.github/workflows/pipeline-segment-electron-build.yml
|
||||
permissions:
|
||||
contents: read
|
||||
needs: checkout-linux
|
||||
with:
|
||||
environment: production-release
|
||||
@@ -55,6 +61,8 @@ jobs:
|
||||
|
||||
publish-arm:
|
||||
uses: ./.github/workflows/pipeline-segment-electron-build.yml
|
||||
permissions:
|
||||
contents: read
|
||||
needs: checkout-linux
|
||||
with:
|
||||
environment: production-release
|
||||
@@ -70,6 +78,8 @@ jobs:
|
||||
|
||||
publish-arm64:
|
||||
uses: ./.github/workflows/pipeline-segment-electron-build.yml
|
||||
permissions:
|
||||
contents: read
|
||||
needs: checkout-linux
|
||||
with:
|
||||
environment: production-release
|
||||
|
||||
14
.github/workflows/macos-publish.yml
vendored
14
.github/workflows/macos-publish.yml
vendored
@@ -6,7 +6,7 @@ on:
|
||||
build-image-sha:
|
||||
type: string
|
||||
description: 'SHA for electron/build image'
|
||||
default: '933c7d6ff6802706875270bec2e3c891cf8add3f'
|
||||
default: 'a82b87d7a4f5ff0cab61405f8151ac4cf4942aeb'
|
||||
required: true
|
||||
upload-to-storage:
|
||||
description: 'Uploads to Azure storage'
|
||||
@@ -18,9 +18,13 @@ on:
|
||||
type: boolean
|
||||
default: false
|
||||
|
||||
permissions: {}
|
||||
|
||||
jobs:
|
||||
checkout-macos:
|
||||
runs-on: electron-arc-centralus-linux-amd64-32core
|
||||
permissions:
|
||||
contents: read
|
||||
container:
|
||||
image: ghcr.io/electron/build:${{ inputs.build-image-sha }}
|
||||
options: --user root
|
||||
@@ -44,6 +48,8 @@ jobs:
|
||||
|
||||
publish-x64-darwin:
|
||||
uses: ./.github/workflows/pipeline-segment-electron-build.yml
|
||||
permissions:
|
||||
contents: read
|
||||
needs: checkout-macos
|
||||
with:
|
||||
environment: production-release
|
||||
@@ -59,6 +65,8 @@ jobs:
|
||||
|
||||
publish-x64-mas:
|
||||
uses: ./.github/workflows/pipeline-segment-electron-build.yml
|
||||
permissions:
|
||||
contents: read
|
||||
needs: checkout-macos
|
||||
with:
|
||||
environment: production-release
|
||||
@@ -74,6 +82,8 @@ jobs:
|
||||
|
||||
publish-arm64-darwin:
|
||||
uses: ./.github/workflows/pipeline-segment-electron-build.yml
|
||||
permissions:
|
||||
contents: read
|
||||
needs: checkout-macos
|
||||
with:
|
||||
environment: production-release
|
||||
@@ -89,6 +99,8 @@ jobs:
|
||||
|
||||
publish-arm64-mas:
|
||||
uses: ./.github/workflows/pipeline-segment-electron-build.yml
|
||||
permissions:
|
||||
contents: read
|
||||
needs: checkout-macos
|
||||
with:
|
||||
environment: production-release
|
||||
|
||||
@@ -7,6 +7,8 @@ on:
|
||||
- 'spec/yarn.lock'
|
||||
- '.github/workflows/**'
|
||||
- '.github/actions/**'
|
||||
- '.yarn/**'
|
||||
- '.yarnrc.yml'
|
||||
|
||||
permissions: {}
|
||||
|
||||
|
||||
@@ -55,6 +55,8 @@ on:
|
||||
type: boolean
|
||||
default: false
|
||||
|
||||
permissions: {}
|
||||
|
||||
concurrency:
|
||||
group: electron-build-and-test-and-nan-${{ inputs.target-platform }}-${{ inputs.target-arch }}-${{ github.ref_protected == true && github.run_id || github.ref }}
|
||||
cancel-in-progress: ${{ github.ref_protected != true }}
|
||||
@@ -62,6 +64,8 @@ concurrency:
|
||||
jobs:
|
||||
build:
|
||||
uses: ./.github/workflows/pipeline-segment-electron-build.yml
|
||||
permissions:
|
||||
contents: read
|
||||
with:
|
||||
build-runs-on: ${{ inputs.build-runs-on }}
|
||||
build-container: ${{ inputs.build-container }}
|
||||
@@ -74,6 +78,10 @@ jobs:
|
||||
secrets: inherit
|
||||
test:
|
||||
uses: ./.github/workflows/pipeline-segment-electron-test.yml
|
||||
permissions:
|
||||
contents: read
|
||||
issues: read
|
||||
pull-requests: read
|
||||
needs: build
|
||||
with:
|
||||
target-arch: ${{ inputs.target-arch }}
|
||||
@@ -83,6 +91,8 @@ jobs:
|
||||
secrets: inherit
|
||||
nn-test:
|
||||
uses: ./.github/workflows/pipeline-segment-node-nan-test.yml
|
||||
permissions:
|
||||
contents: read
|
||||
needs: build
|
||||
with:
|
||||
target-arch: ${{ inputs.target-arch }}
|
||||
|
||||
@@ -64,14 +64,13 @@ concurrency:
|
||||
group: electron-build-and-test-${{ inputs.target-platform }}-${{ inputs.target-arch }}-${{ github.ref_protected == true && github.run_id || github.ref }}
|
||||
cancel-in-progress: ${{ github.ref_protected != true }}
|
||||
|
||||
permissions:
|
||||
contents: read
|
||||
issues: read
|
||||
pull-requests: read
|
||||
permissions: {}
|
||||
|
||||
jobs:
|
||||
build:
|
||||
uses: ./.github/workflows/pipeline-segment-electron-build.yml
|
||||
permissions:
|
||||
contents: read
|
||||
with:
|
||||
build-runs-on: ${{ inputs.build-runs-on }}
|
||||
build-container: ${{ inputs.build-container }}
|
||||
@@ -86,6 +85,10 @@ jobs:
|
||||
secrets: inherit
|
||||
test:
|
||||
uses: ./.github/workflows/pipeline-segment-electron-test.yml
|
||||
permissions:
|
||||
contents: read
|
||||
issues: read
|
||||
pull-requests: read
|
||||
needs: build
|
||||
with:
|
||||
target-arch: ${{ inputs.target-arch }}
|
||||
|
||||
@@ -8,6 +8,8 @@ on:
|
||||
description: 'Container to run the docs-only ts compile in'
|
||||
type: string
|
||||
|
||||
permissions: {}
|
||||
|
||||
concurrency:
|
||||
group: electron-docs-only-${{ github.ref }}
|
||||
cancel-in-progress: true
|
||||
@@ -19,6 +21,8 @@ jobs:
|
||||
docs-only:
|
||||
name: Docs Only Compile
|
||||
runs-on: electron-arc-centralus-linux-amd64-4core
|
||||
permissions:
|
||||
contents: read
|
||||
timeout-minutes: 20
|
||||
container: ${{ fromJSON(inputs.container) }}
|
||||
steps:
|
||||
@@ -50,12 +54,12 @@ jobs:
|
||||
shell: bash
|
||||
run: |
|
||||
cd src/electron
|
||||
node script/yarn create-typescript-definitions
|
||||
node script/yarn tsc -p tsconfig.default_app.json --noEmit
|
||||
node script/yarn.js create-typescript-definitions
|
||||
node script/yarn.js tsc -p tsconfig.default_app.json --noEmit
|
||||
for f in build/webpack/*.js
|
||||
do
|
||||
out="${f:29}"
|
||||
if [ "$out" != "base.js" ]; then
|
||||
node script/yarn webpack --config $f --output-filename=$out --output-path=./.tmp --env mode=development
|
||||
node script/yarn.js webpack --config $f --output-filename=$out --output-path=./.tmp --env mode=development
|
||||
fi
|
||||
done
|
||||
|
||||
10
.github/workflows/pipeline-electron-lint.yml
vendored
10
.github/workflows/pipeline-electron-lint.yml
vendored
@@ -8,6 +8,8 @@ on:
|
||||
description: 'Container to run lint in'
|
||||
type: string
|
||||
|
||||
permissions: {}
|
||||
|
||||
concurrency:
|
||||
group: electron-lint-${{ github.ref_protected == true && github.run_id || github.ref }}
|
||||
cancel-in-progress: ${{ github.ref_protected != true }}
|
||||
@@ -19,6 +21,8 @@ jobs:
|
||||
lint:
|
||||
name: Lint
|
||||
runs-on: electron-arc-centralus-linux-amd64-4core
|
||||
permissions:
|
||||
contents: read
|
||||
timeout-minutes: 20
|
||||
container: ${{ fromJSON(inputs.container) }}
|
||||
steps:
|
||||
@@ -74,11 +78,11 @@ jobs:
|
||||
# but then we would lint its contents (at least gn format), and it doesn't pass it.
|
||||
|
||||
cd src/electron
|
||||
node script/yarn install --frozen-lockfile
|
||||
node script/yarn lint
|
||||
node script/yarn.js install --immutable
|
||||
node script/yarn.js lint
|
||||
- name: Run Script Typechecker
|
||||
shell: bash
|
||||
run: |
|
||||
cd src/electron
|
||||
node script/yarn tsc -p tsconfig.script.json
|
||||
node script/yarn.js tsc -p tsconfig.script.json
|
||||
|
||||
|
||||
@@ -59,6 +59,8 @@ on:
|
||||
type: boolean
|
||||
default: false
|
||||
|
||||
permissions: {}
|
||||
|
||||
concurrency:
|
||||
group: electron-build-${{ inputs.target-platform }}-${{ inputs.target-arch }}-${{ inputs.target-variant }}-${{ inputs.is-asan }}-${{ github.ref_protected == true && github.run_id || github.ref }}
|
||||
cancel-in-progress: ${{ github.ref_protected != true }}
|
||||
@@ -81,6 +83,8 @@ jobs:
|
||||
run:
|
||||
shell: bash
|
||||
runs-on: ${{ inputs.build-runs-on }}
|
||||
permissions:
|
||||
contents: read
|
||||
container: ${{ fromJSON(inputs.build-container) }}
|
||||
environment: ${{ inputs.environment }}
|
||||
env:
|
||||
|
||||
@@ -26,6 +26,8 @@ on:
|
||||
type: string
|
||||
default: testing
|
||||
|
||||
permissions: {}
|
||||
|
||||
concurrency:
|
||||
group: electron-gn-check-${{ inputs.target-platform }}-${{ github.ref }}
|
||||
cancel-in-progress: true
|
||||
@@ -41,6 +43,8 @@ jobs:
|
||||
run:
|
||||
shell: bash
|
||||
runs-on: ${{ inputs.check-runs-on }}
|
||||
permissions:
|
||||
contents: read
|
||||
container: ${{ fromJSON(inputs.check-container) }}
|
||||
steps:
|
||||
- name: Checkout Electron
|
||||
|
||||
@@ -35,10 +35,7 @@ concurrency:
|
||||
group: electron-test-${{ inputs.target-platform }}-${{ inputs.target-arch }}-${{ inputs.is-asan }}-${{ github.ref_protected == true && github.run_id || github.ref }}
|
||||
cancel-in-progress: ${{ github.ref_protected != true }}
|
||||
|
||||
permissions:
|
||||
contents: read
|
||||
issues: read
|
||||
pull-requests: read
|
||||
permissions: {}
|
||||
|
||||
env:
|
||||
CHROMIUM_GIT_COOKIE: ${{ secrets.CHROMIUM_GIT_COOKIE }}
|
||||
@@ -53,6 +50,10 @@ jobs:
|
||||
run:
|
||||
shell: bash
|
||||
runs-on: ${{ inputs.test-runs-on }}
|
||||
permissions:
|
||||
contents: read
|
||||
issues: read
|
||||
pull-requests: read
|
||||
container: ${{ fromJSON(inputs.test-container) }}
|
||||
strategy:
|
||||
fail-fast: false
|
||||
@@ -195,10 +196,7 @@ jobs:
|
||||
# sudo security authorizationdb write com.apple.trust-settings.admin allow
|
||||
# cd src/electron
|
||||
# ./script/codesign/generate-identity.sh
|
||||
- name: Install Datadog CLI
|
||||
run: |
|
||||
cd src/electron
|
||||
node script/yarn global add @datadog/datadog-ci
|
||||
|
||||
- name: Run Electron Tests
|
||||
shell: bash
|
||||
env:
|
||||
@@ -224,7 +222,7 @@ jobs:
|
||||
export ELECTRON_FORCE_TEST_SUITE_EXIT="true"
|
||||
fi
|
||||
fi
|
||||
node script/yarn test --runners=main --enableRerun=3 --trace-uncaught --enable-logging --files $tests_files
|
||||
node script/yarn.js test --runners=main --enableRerun=3 --trace-uncaught --enable-logging --files $tests_files
|
||||
else
|
||||
chown :builduser .. && chmod g+w ..
|
||||
chown -R :builduser . && chmod -R g+w .
|
||||
@@ -241,9 +239,14 @@ jobs:
|
||||
export MOCHA_TIMEOUT=180000
|
||||
echo "Piping output to ASAN_SYMBOLIZE ($ASAN_SYMBOLIZE)"
|
||||
cd electron
|
||||
runuser -u builduser -- xvfb-run script/actions/run-tests.sh script/yarn test --runners=main --trace-uncaught --enable-logging --files $tests_files | $ASAN_SYMBOLIZE
|
||||
runuser -u builduser -- xvfb-run script/actions/run-tests.sh script/yarn.js test --runners=main --trace-uncaught --enable-logging --files $tests_files | $ASAN_SYMBOLIZE
|
||||
else
|
||||
runuser -u builduser -- xvfb-run script/actions/run-tests.sh script/yarn test --runners=main --trace-uncaught --enable-logging --files $tests_files
|
||||
if [ "${{ inputs.target-arch }}" = "arm" ]; then
|
||||
runuser -u builduser -- xvfb-run script/actions/run-tests.sh script/yarn.js test --skipYarnInstall --runners=main --enableRerun=3 --trace-uncaught --enable-logging --files $tests_files
|
||||
else
|
||||
runuser -u builduser -- xvfb-run script/actions/run-tests.sh script/yarn.js test --runners=main --enableRerun=3 --trace-uncaught --enable-logging --files $tests_files
|
||||
fi
|
||||
|
||||
fi
|
||||
fi
|
||||
- name: Upload Test results to Datadog
|
||||
@@ -255,9 +258,10 @@ jobs:
|
||||
DD_TAGS: "os.architecture:${{ inputs.target-arch }},os.family:${{ inputs.target-platform }},os.platform:${{ inputs.target-platform }},asan:${{ inputs.is-asan }}"
|
||||
run: |
|
||||
if ! [ -z $DD_API_KEY ] && [ -f src/electron/junit/test-results-main.xml ]; then
|
||||
export DATADOG_PATH=`node src/electron/script/yarn global bin`
|
||||
$DATADOG_PATH/datadog-ci junit upload src/electron/junit/test-results-main.xml
|
||||
fi
|
||||
cd src/electron
|
||||
export DATADOG_PATH=`node script/yarn.js bin datadog-ci`
|
||||
$DATADOG_PATH junit upload junit/test-results-main.xml
|
||||
fi
|
||||
if: always() && !cancelled()
|
||||
- name: Upload Test Artifacts
|
||||
if: always() && !cancelled()
|
||||
|
||||
@@ -26,6 +26,8 @@ on:
|
||||
type: string
|
||||
default: testing
|
||||
|
||||
permissions: {}
|
||||
|
||||
concurrency:
|
||||
group: electron-node-nan-test-${{ inputs.target-platform }}-${{ inputs.target-arch }}-${{ github.ref_protected == true && github.run_id || github.ref }}
|
||||
cancel-in-progress: ${{ github.ref_protected != true }}
|
||||
@@ -39,6 +41,8 @@ jobs:
|
||||
node-tests:
|
||||
name: Run Node.js Tests
|
||||
runs-on: electron-arc-centralus-linux-amd64-8core
|
||||
permissions:
|
||||
contents: read
|
||||
timeout-minutes: 30
|
||||
env:
|
||||
TARGET_ARCH: ${{ inputs.target-arch }}
|
||||
@@ -93,6 +97,8 @@ jobs:
|
||||
nan-tests:
|
||||
name: Run Nan Tests
|
||||
runs-on: electron-arc-centralus-linux-amd64-4core
|
||||
permissions:
|
||||
contents: read
|
||||
timeout-minutes: 30
|
||||
env:
|
||||
TARGET_ARCH: ${{ inputs.target-arch }}
|
||||
@@ -132,10 +138,16 @@ jobs:
|
||||
unzip -:o dist.zip
|
||||
- name: Setup Linux for Headless Testing
|
||||
run: sh -e /etc/init.d/xvfb start
|
||||
- name: Add Clang problem matcher
|
||||
shell: bash
|
||||
run: echo "::add-matcher::src/electron/.github/problem-matchers/clang.json"
|
||||
- name: Run Nan Tests
|
||||
run: |
|
||||
cd src
|
||||
node electron/script/nan-spec-runner.js
|
||||
- name: Remove Clang problem matcher
|
||||
shell: bash
|
||||
run: echo "::remove-matcher owner=clang::"
|
||||
- name: Wait for active SSH sessions
|
||||
shell: bash
|
||||
if: always() && !cancelled()
|
||||
|
||||
2
.github/workflows/pull-request-labeled.yml
vendored
2
.github/workflows/pull-request-labeled.yml
vendored
@@ -11,6 +11,7 @@ jobs:
|
||||
name: backport/requested label added
|
||||
if: github.event.label.name == 'backport/requested 🗳'
|
||||
runs-on: ubuntu-latest
|
||||
permissions: {}
|
||||
steps:
|
||||
- name: Trigger Slack workflow
|
||||
uses: slackapi/slack-github-action@91efab103c0de0a537f72a35f6b8cda0ee76bf0a # v2.1.1
|
||||
@@ -28,6 +29,7 @@ jobs:
|
||||
name: deprecation-review/complete label added
|
||||
if: github.event.label.name == 'deprecation-review/complete ✅'
|
||||
runs-on: ubuntu-latest
|
||||
permissions: {}
|
||||
steps:
|
||||
- name: Generate GitHub App token
|
||||
uses: electron/github-app-auth-action@384fd19694fe7b6dcc9a684746c6976ad78228ae # v1.1.1
|
||||
|
||||
69
.github/workflows/rerun-apply-patches.yml
vendored
Normal file
69
.github/workflows/rerun-apply-patches.yml
vendored
Normal file
@@ -0,0 +1,69 @@
|
||||
name: Rerun PR Apply Patches
|
||||
|
||||
on:
|
||||
push:
|
||||
branches:
|
||||
- main
|
||||
- '[1-9][0-9]-x-y'
|
||||
paths:
|
||||
- 'DEPS'
|
||||
- 'patches/**'
|
||||
|
||||
permissions: {}
|
||||
|
||||
jobs:
|
||||
rerun-apply-patches:
|
||||
runs-on: ubuntu-latest
|
||||
permissions:
|
||||
contents: read
|
||||
actions: write
|
||||
pull-requests: read
|
||||
steps:
|
||||
- name: Find PRs and Rerun Apply Patches
|
||||
env:
|
||||
GH_REPO: ${{ github.repository }}
|
||||
GH_TOKEN: ${{ github.token }}
|
||||
run: |
|
||||
BRANCH="${GITHUB_REF#refs/heads/}"
|
||||
|
||||
# Find all open PRs targeting this branch
|
||||
PRS=$(gh pr list --base "$BRANCH" --state open --limit 250 --json number)
|
||||
|
||||
echo "$PRS" | jq -c '.[]' | while read -r pr; do
|
||||
PR_NUMBER=$(echo "$pr" | jq -r '.number')
|
||||
echo "Processing PR #${PR_NUMBER}"
|
||||
|
||||
# Find the apply-patches job check for this PR
|
||||
CHECK=$(gh pr checks "$PR_NUMBER" --json link,name,state,workflow --jq '[.[] | select(.workflow == "Build" and .name == "apply-patches")] | first')
|
||||
|
||||
if [ -z "$CHECK" ] || [ "$CHECK" = "null" ]; then
|
||||
echo " No apply-patches job found for PR #${PR_NUMBER}"
|
||||
continue
|
||||
fi
|
||||
|
||||
STATE=$(echo "$CHECK" | jq -r '.state')
|
||||
if [ "$STATE" = "SKIPPED" ]; then
|
||||
echo " apply-patches job was skipped for PR #${PR_NUMBER} (no patches)"
|
||||
continue
|
||||
fi
|
||||
|
||||
LINK=$(echo "$CHECK" | jq -r '.link')
|
||||
|
||||
# Extract the run ID from the link (format: .../runs/RUN_ID/job/JOB_ID)
|
||||
RUN_ID=$(echo "$LINK" | grep -oE 'runs/[0-9]+' | cut -d'/' -f2)
|
||||
|
||||
if [ -z "$RUN_ID" ]; then
|
||||
echo " Could not extract run ID from link: ${LINK}"
|
||||
continue
|
||||
fi
|
||||
|
||||
# Get the job database ID for the apply-patches job
|
||||
JOB_ID=$(gh run view "$RUN_ID" --json jobs --jq '.jobs[] | select(.name == "apply-patches") | .databaseId')
|
||||
|
||||
if [ -z "$JOB_ID" ]; then
|
||||
echo " Could not find apply-patches job ID for run: ${RUN_ID}"
|
||||
continue
|
||||
fi
|
||||
|
||||
gh run rerun "$RUN_ID" --job "$JOB_ID"
|
||||
done
|
||||
3
.github/workflows/semantic.yml
vendored
3
.github/workflows/semantic.yml
vendored
@@ -7,8 +7,7 @@ on:
|
||||
- edited
|
||||
- synchronize
|
||||
|
||||
permissions:
|
||||
contents: read
|
||||
permissions: {}
|
||||
|
||||
jobs:
|
||||
main:
|
||||
|
||||
1
.github/workflows/stable-prep-items.yml
vendored
1
.github/workflows/stable-prep-items.yml
vendored
@@ -11,6 +11,7 @@ jobs:
|
||||
check-stable-prep-items:
|
||||
name: Check Stable Prep Items
|
||||
runs-on: ubuntu-latest
|
||||
permissions: {}
|
||||
steps:
|
||||
- name: Generate GitHub App token
|
||||
uses: electron/github-app-auth-action@384fd19694fe7b6dcc9a684746c6976ad78228ae # v1.1.1
|
||||
|
||||
2
.github/workflows/stale.yml
vendored
2
.github/workflows/stale.yml
vendored
@@ -10,6 +10,7 @@ permissions: {}
|
||||
jobs:
|
||||
stale:
|
||||
runs-on: ubuntu-latest
|
||||
permissions: {}
|
||||
steps:
|
||||
- name: Generate GitHub App token
|
||||
uses: electron/github-app-auth-action@384fd19694fe7b6dcc9a684746c6976ad78228ae # v1.1.1
|
||||
@@ -31,6 +32,7 @@ jobs:
|
||||
only-pr-labels: not-a-real-label
|
||||
pending-repro:
|
||||
runs-on: ubuntu-latest
|
||||
permissions: {}
|
||||
if: ${{ always() }}
|
||||
needs: stale
|
||||
steps:
|
||||
|
||||
12
.github/workflows/windows-publish.yml
vendored
12
.github/workflows/windows-publish.yml
vendored
@@ -6,7 +6,7 @@ on:
|
||||
build-image-sha:
|
||||
type: string
|
||||
description: 'SHA for electron/build image'
|
||||
default: '933c7d6ff6802706875270bec2e3c891cf8add3f'
|
||||
default: 'a82b87d7a4f5ff0cab61405f8151ac4cf4942aeb'
|
||||
required: true
|
||||
upload-to-storage:
|
||||
description: 'Uploads to Azure storage'
|
||||
@@ -18,9 +18,13 @@ on:
|
||||
type: boolean
|
||||
default: false
|
||||
|
||||
permissions: {}
|
||||
|
||||
jobs:
|
||||
checkout-windows:
|
||||
runs-on: electron-arc-centralus-linux-amd64-32core
|
||||
permissions:
|
||||
contents: read
|
||||
container:
|
||||
image: ghcr.io/electron/build:${{ inputs.build-image-sha }}
|
||||
options: --user root --device /dev/fuse --cap-add SYS_ADMIN
|
||||
@@ -48,6 +52,8 @@ jobs:
|
||||
|
||||
publish-x64-win:
|
||||
uses: ./.github/workflows/pipeline-segment-electron-build.yml
|
||||
permissions:
|
||||
contents: read
|
||||
needs: checkout-windows
|
||||
with:
|
||||
environment: production-release
|
||||
@@ -62,6 +68,8 @@ jobs:
|
||||
|
||||
publish-arm64-win:
|
||||
uses: ./.github/workflows/pipeline-segment-electron-build.yml
|
||||
permissions:
|
||||
contents: read
|
||||
needs: checkout-windows
|
||||
with:
|
||||
environment: production-release
|
||||
@@ -76,6 +84,8 @@ jobs:
|
||||
|
||||
publish-x86-win:
|
||||
uses: ./.github/workflows/pipeline-segment-electron-build.yml
|
||||
permissions:
|
||||
contents: read
|
||||
needs: checkout-windows
|
||||
with:
|
||||
environment: production-release
|
||||
|
||||
2
.gitignore
vendored
2
.gitignore
vendored
@@ -53,3 +53,5 @@ ts-gen
|
||||
patches/mtime-cache.json
|
||||
|
||||
spec/fixtures/logo.png
|
||||
|
||||
.yarn/install-state.gz
|
||||
942
.yarn/releases/yarn-4.12.0.cjs
vendored
Executable file
942
.yarn/releases/yarn-4.12.0.cjs
vendored
Executable file
File diff suppressed because one or more lines are too long
12
.yarnrc.yml
Normal file
12
.yarnrc.yml
Normal file
@@ -0,0 +1,12 @@
|
||||
enableScripts: false
|
||||
|
||||
nmHoistingLimits: workspaces
|
||||
|
||||
nodeLinker: node-modules
|
||||
|
||||
npmMinimalAgeGate: 10080
|
||||
|
||||
npmPreapprovedPackages:
|
||||
- "@electron/*"
|
||||
|
||||
yarnPath: .yarn/releases/yarn-4.12.0.cjs
|
||||
9
DEPS
9
DEPS
@@ -2,9 +2,9 @@ gclient_gn_args_from = 'src'
|
||||
|
||||
vars = {
|
||||
'chromium_version':
|
||||
'142.0.7444.134',
|
||||
'142.0.7444.265',
|
||||
'node_version':
|
||||
'v22.21.1',
|
||||
'v22.22.0',
|
||||
'nan_version':
|
||||
'e14bdcd1f72d62bca1d541b66da43130384ec213',
|
||||
'squirrel.mac_version':
|
||||
@@ -30,9 +30,6 @@ vars = {
|
||||
# The path of the sysroots.json file.
|
||||
'sysroots_json_path': 'electron/script/sysroots.json',
|
||||
|
||||
# KEEP IN SYNC WITH utils.js FILE
|
||||
'yarn_version': '1.22.22',
|
||||
|
||||
# To be able to build clean Chromium from sources.
|
||||
'apply_patches': True,
|
||||
|
||||
@@ -155,7 +152,7 @@ hooks = [
|
||||
'action': [
|
||||
'python3',
|
||||
'-c',
|
||||
'import os, subprocess; os.chdir(os.path.join("src", "electron")); subprocess.check_call(["python3", "script/lib/npx.py", "yarn@' + (Var("yarn_version")) + '", "install", "--frozen-lockfile"]);',
|
||||
'import os, subprocess; os.chdir(os.path.join("src", "electron")); subprocess.check_call(["node", ".yarn/releases/yarn-4.12.0.cjs", "install", "--immutable"]);',
|
||||
],
|
||||
},
|
||||
{
|
||||
|
||||
@@ -1216,6 +1216,13 @@ Disables hardware acceleration for current app.
|
||||
|
||||
This method can only be called before app is ready.
|
||||
|
||||
### `app.isHardwareAccelerationEnabled()`
|
||||
|
||||
Returns `boolean` - whether hardware acceleration is currently enabled.
|
||||
|
||||
> [!NOTE]
|
||||
> This information is only usable after the `gpu-info-update` event is emitted.
|
||||
|
||||
### `app.disableDomainBlockingFor3DAPIs()`
|
||||
|
||||
By default, Chromium disables 3D APIs (e.g. WebGL) until restart on a per
|
||||
|
||||
@@ -1262,15 +1262,16 @@ Sets the properties for the window's taskbar button.
|
||||
|
||||
#### `win.setAccentColor(accentColor)` _Windows_
|
||||
|
||||
* `accentColor` boolean | string - The accent color for the window. By default, follows user preference in System Settings.
|
||||
* `accentColor` boolean | string | null - The accent color for the window. By default, follows user preference in System Settings. To reset to system default, pass `null`.
|
||||
|
||||
Sets the system accent color and highlighting of active window border.
|
||||
|
||||
The `accentColor` parameter accepts the following values:
|
||||
|
||||
* **Color string** - Sets a custom accent color using standard CSS color formats (Hex, RGB, RGBA, HSL, HSLA, or named colors). Alpha values in RGBA/HSLA formats are ignored and the color is treated as fully opaque.
|
||||
* **`true`** - Uses the system's default accent color from user preferences in System Settings.
|
||||
* **`false`** - Explicitly disables accent color highlighting for the window.
|
||||
* **Color string** - Like `true`, but sets a custom accent color using standard CSS color formats (Hex, RGB, RGBA, HSL, HSLA, or named colors). Alpha values in RGBA/HSLA formats are ignored and the color is treated as fully opaque.
|
||||
* **`true`** - Enable accent color highlighting for the window with the system accent color regardless of whether accent colors are enabled for windows in System `Settings.`
|
||||
* **`false`** - Disable accent color highlighting for the window regardless of whether accent colors are currently enabled for windows in System Settings.
|
||||
* **`null`** - Reset window accent color behavior to follow behavior set in System Settings.
|
||||
|
||||
Examples:
|
||||
|
||||
@@ -1283,11 +1284,14 @@ win.setAccentColor('#ff0000')
|
||||
// RGB format (alpha ignored if present).
|
||||
win.setAccentColor('rgba(255,0,0,0.5)')
|
||||
|
||||
// Use system accent color.
|
||||
// Enable accent color, using the color specified in System Settings.
|
||||
win.setAccentColor(true)
|
||||
|
||||
// Disable accent color.
|
||||
win.setAccentColor(false)
|
||||
|
||||
// Reset window accent color behavior to follow behavior set in System Settings.
|
||||
win.setAccentColor(null)
|
||||
```
|
||||
|
||||
#### `win.getAccentColor()` _Windows_
|
||||
|
||||
@@ -1252,7 +1252,8 @@ Captures a snapshot of the page within `rect`. Omitting `rect` will capture the
|
||||
|
||||
Returns `Promise<void>` - the promise will resolve when the page has finished loading
|
||||
(see [`did-finish-load`](web-contents.md#event-did-finish-load)), and rejects
|
||||
if the page fails to load (see [`did-fail-load`](web-contents.md#event-did-fail-load)).
|
||||
if the page fails to load (see
|
||||
[`did-fail-load`](web-contents.md#event-did-fail-load)). A noop rejection handler is already attached, which avoids unhandled rejection errors. If the existing page has a beforeUnload handler, [`did-fail-load`](web-contents.md#event-did-fail-load) will be called unless [`will-prevent-unload`](web-contents.md#event-did-fail-load) is handled.
|
||||
|
||||
Same as [`webContents.loadURL(url[, options])`](web-contents.md#contentsloadurlurl-options).
|
||||
|
||||
@@ -1467,15 +1468,16 @@ Sets the properties for the window's taskbar button.
|
||||
|
||||
#### `win.setAccentColor(accentColor)` _Windows_
|
||||
|
||||
* `accentColor` boolean | string - The accent color for the window. By default, follows user preference in System Settings.
|
||||
* `accentColor` boolean | string | null - The accent color for the window. By default, follows user preference in System Settings. To reset to system default, pass `null`.
|
||||
|
||||
Sets the system accent color and highlighting of active window border.
|
||||
|
||||
The `accentColor` parameter accepts the following values:
|
||||
|
||||
* **Color string** - Sets a custom accent color using standard CSS color formats (Hex, RGB, RGBA, HSL, HSLA, or named colors). Alpha values in RGBA/HSLA formats are ignored and the color is treated as fully opaque.
|
||||
* **`true`** - Uses the system's default accent color from user preferences in System Settings.
|
||||
* **`false`** - Explicitly disables accent color highlighting for the window.
|
||||
* **Color string** - Like `true`, but sets a custom accent color using standard CSS color formats (Hex, RGB, RGBA, HSL, HSLA, or named colors). Alpha values in RGBA/HSLA formats are ignored and the color is treated as fully opaque.
|
||||
* **`true`** - Enable accent color highlighting for the window with the system accent color regardless of whether accent colors are enabled for windows in System `Settings.`
|
||||
* **`false`** - Disable accent color highlighting for the window regardless of whether accent colors are currently enabled for windows in System Settings.
|
||||
* **`null`** - Reset window accent color behavior to follow behavior set in System Settings.
|
||||
|
||||
Examples:
|
||||
|
||||
@@ -1488,11 +1490,14 @@ win.setAccentColor('#ff0000')
|
||||
// RGB format (alpha ignored if present).
|
||||
win.setAccentColor('rgba(255,0,0,0.5)')
|
||||
|
||||
// Use system accent color.
|
||||
// Enable accent color, using the color specified in System Settings.
|
||||
win.setAccentColor(true)
|
||||
|
||||
// Disable accent color.
|
||||
win.setAccentColor(false)
|
||||
|
||||
// Reset window accent color behavior to follow behavior set in System Settings.
|
||||
win.setAccentColor(null)
|
||||
```
|
||||
|
||||
#### `win.getAccentColor()` _Windows_
|
||||
|
||||
@@ -25,6 +25,11 @@ following properties:
|
||||
with which the request is associated. Defaults to the empty string. The
|
||||
`session` option supersedes `partition`. Thus if a `session` is explicitly
|
||||
specified, `partition` is ignored.
|
||||
* `bypassCustomProtocolHandlers` boolean (optional) - When set to `true`,
|
||||
custom protocol handlers registered for the request's URL scheme will not be
|
||||
called. This allows forwarding an intercepted request to the built-in
|
||||
handler. [webRequest](web-request.md) handlers will still be triggered
|
||||
when bypassing custom protocols. Defaults to `false`.
|
||||
* `credentials` string (optional) - Can be `include`, `omit` or
|
||||
`same-origin`. Whether to send
|
||||
[credentials](https://fetch.spec.whatwg.org/#credentials) with this
|
||||
|
||||
@@ -34,7 +34,8 @@ See [`Menu`](menu.md) for examples.
|
||||
* `sublabel` string (optional) _macOS_ - Available in macOS >= 14.4
|
||||
* `toolTip` string (optional) _macOS_ - Hover text for this menu item.
|
||||
* `accelerator` string (optional) - An [Accelerator](../tutorial/keyboard-shortcuts.md#accelerators) string.
|
||||
* `icon` ([NativeImage](native-image.md) | string) (optional)
|
||||
* `icon` ([NativeImage](native-image.md) | string) (optional) - Can be a
|
||||
[NativeImage](native-image.md) or the file path of an icon.
|
||||
* `enabled` boolean (optional) - If false, the menu item will be greyed out and
|
||||
unclickable.
|
||||
* `acceleratorWorksWhenHidden` boolean (optional) _macOS_ - default is `true`, and when `false` will prevent the accelerator from triggering the item if the item is not visible.
|
||||
|
||||
@@ -202,8 +202,7 @@ Creates a new `NativeImage` instance from `dataUrl`, a base 64 encoded [Data URL
|
||||
Returns `NativeImage`
|
||||
|
||||
Creates a new `NativeImage` instance from the `NSImage` that maps to the
|
||||
given image name. See Apple's [`NSImageName`](https://developer.apple.com/documentation/appkit/nsimagename#2901388)
|
||||
documentation for a list of possible values.
|
||||
given image name. See Apple's [`NSImageName`](https://developer.apple.com/documentation/appkit/nsimagename#2901388) documentation and [SF Symbols](https://developer.apple.com/sf-symbols/) for a list of possible values.
|
||||
|
||||
The `hslShift` is applied to the image with the following rules:
|
||||
|
||||
@@ -231,6 +230,15 @@ echo -e '#import <Cocoa/Cocoa.h>\nint main() { NSLog(@"%@", SYSTEM_IMAGE_NAME);
|
||||
|
||||
where `SYSTEM_IMAGE_NAME` should be replaced with any value from [this list](https://developer.apple.com/documentation/appkit/nsimagename?language=objc).
|
||||
|
||||
For SF Symbols, usage looks as follows:
|
||||
|
||||
```js
|
||||
const image = nativeImage.createFromNamedImage('square.and.pencil')
|
||||
```
|
||||
|
||||
where `'square.and.pencil'` is the symbol name from the
|
||||
[SF Symbols app](https://developer.apple.com/sf-symbols/).
|
||||
|
||||
## Class: NativeImage
|
||||
|
||||
> Natively wrap images such as tray, dock, and application icons.
|
||||
|
||||
@@ -71,7 +71,7 @@ will disable the support for `asar` archives in Node's built-in modules.
|
||||
|
||||
### `process.noDeprecation`
|
||||
|
||||
A `boolean` that controls whether or not deprecation warnings are printed to `stderr`.
|
||||
A `boolean` (optional) that controls whether or not deprecation warnings are printed to `stderr`.
|
||||
Setting this to `true` will silence deprecation warnings. This property is used
|
||||
instead of the `--no-deprecation` command line flag.
|
||||
|
||||
|
||||
@@ -58,6 +58,10 @@ Rejects if there was an error while deleting the requested item.
|
||||
This moves a path to the OS-specific trash location (Trash on macOS, Recycle
|
||||
Bin on Windows, and a desktop-environment-specific location on Linux).
|
||||
|
||||
The path must use the default path separator for the platform (backslash on
|
||||
Windows). Use `path.resolve()` from the `node:path` module to ensure correct
|
||||
handling on all filesystems.
|
||||
|
||||
### `shell.beep()`
|
||||
|
||||
Play the beep sound.
|
||||
|
||||
@@ -72,6 +72,9 @@
|
||||
some GTK+3 desktop environments. Default is `false`.
|
||||
* `transparent` boolean (optional) - Makes the window [transparent](../../tutorial/custom-window-styles.md#transparent-windows).
|
||||
Default is `false`. On Windows, does not work unless the window is frameless.
|
||||
When you add a [`View`](../view.md) to a `BaseWindow`, you'll need to call
|
||||
[`view.setBackgroundColor`](../view.md#viewsetbackgroundcolorcolor) with a transparent
|
||||
background color on that view to make its background transparent as well.
|
||||
* `type` string (optional) - The type of window, default is normal window. See more about
|
||||
this below.
|
||||
* `visualEffectState` string (optional) _macOS_ - Specify how the material
|
||||
@@ -99,9 +102,9 @@
|
||||
* `trafficLightPosition` [Point](point.md) (optional) _macOS_ -
|
||||
Set a custom position for the traffic light buttons in frameless windows.
|
||||
* `roundedCorners` boolean (optional) _macOS_ _Windows_ - Whether frameless window
|
||||
should have rounded corners. Default is `true`. Setting this property
|
||||
to `false` will prevent the window from being fullscreenable on macOS.
|
||||
On Windows versions older than Windows 11 Build 22000 this property has no effect, and frameless windows will not have rounded corners.
|
||||
should have rounded corners. Default is `true`. On Windows versions older than
|
||||
Windows 11 Build 22000 this property has no effect, and frameless windows will
|
||||
not have rounded corners.
|
||||
* `thickFrame` boolean (optional) _Windows_ - Use `WS_THICKFRAME` style for
|
||||
frameless windows on Windows, which adds the standard window frame. Setting it
|
||||
to `false` will remove window shadow and window animations, and disable window
|
||||
|
||||
@@ -1079,7 +1079,7 @@ Emitted when the [mainFrame](web-contents.md#contentsmainframe-readonly), an `<i
|
||||
Returns `Promise<void>` - the promise will resolve when the page has finished loading
|
||||
(see [`did-finish-load`](web-contents.md#event-did-finish-load)), and rejects
|
||||
if the page fails to load (see
|
||||
[`did-fail-load`](web-contents.md#event-did-fail-load)). A noop rejection handler is already attached, which avoids unhandled rejection errors.
|
||||
[`did-fail-load`](web-contents.md#event-did-fail-load)). A noop rejection handler is already attached, which avoids unhandled rejection errors. If the existing page has a beforeUnload handler, [`did-fail-load`](web-contents.md#event-did-fail-load) will be called unless [`will-prevent-unload`](web-contents.md#event-did-fail-load) is handled.
|
||||
|
||||
Loads the `url` in the window. The `url` must contain the protocol prefix,
|
||||
e.g. the `http://` or `file://`. If the load should bypass http cache then
|
||||
@@ -2410,7 +2410,8 @@ A [`NavigationHistory`](navigation-history.md) used by this webContents.
|
||||
|
||||
#### `contents.hostWebContents` _Readonly_
|
||||
|
||||
A [`WebContents`](web-contents.md) instance that might own this `WebContents`.
|
||||
A `WebContents | null` property that represents a [`WebContents`](web-contents.md)
|
||||
instance that might own this `WebContents`.
|
||||
|
||||
#### `contents.devToolsWebContents` _Readonly_
|
||||
|
||||
|
||||
@@ -6,77 +6,17 @@ Follow the guidelines below for building **Electron itself** on Linux, for the p
|
||||
|
||||
## Prerequisites
|
||||
|
||||
* At least 25GB disk space and 8GB RAM.
|
||||
* Python >= 3.9.
|
||||
* [Node.js](https://nodejs.org/download/) >= 22.12.0
|
||||
* [clang](https://clang.llvm.org/get_started.html) 3.4 or later.
|
||||
* Development headers of GTK 3 and libnotify.
|
||||
Due to Electron's dependency on Chromium, prerequisites and dependencies for Electron change over time. [Chromium's documentation on building on Linux](https://chromium.googlesource.com/chromium/src/+/HEAD/docs/linux/build_instructions.md) has up to date information for building Chromium on Linux. This documentation can generally
|
||||
be followed for building Electron on Linux as well.
|
||||
|
||||
On Ubuntu >= 20.04, install the following libraries:
|
||||
|
||||
```sh
|
||||
$ sudo apt-get install build-essential clang libdbus-1-dev libgtk-3-dev \
|
||||
libnotify-dev libasound2-dev libcap-dev \
|
||||
libcups2-dev libxtst-dev \
|
||||
libxss1 libnss3-dev gcc-multilib g++-multilib curl \
|
||||
gperf bison python3-dbusmock openjdk-8-jre
|
||||
```
|
||||
|
||||
On Ubuntu < 20.04, install the following libraries:
|
||||
|
||||
```sh
|
||||
$ sudo apt-get install build-essential clang libdbus-1-dev libgtk-3-dev \
|
||||
libnotify-dev libgnome-keyring-dev \
|
||||
libasound2-dev libcap-dev libcups2-dev libxtst-dev \
|
||||
libxss1 libnss3-dev gcc-multilib g++-multilib curl \
|
||||
gperf bison python-dbusmock openjdk-8-jre
|
||||
```
|
||||
|
||||
On RHEL / CentOS, install the following libraries:
|
||||
|
||||
```sh
|
||||
$ sudo yum install clang dbus-devel gtk3-devel libnotify-devel \
|
||||
libgnome-keyring-devel xorg-x11-server-utils libcap-devel \
|
||||
cups-devel libXtst-devel alsa-lib-devel libXrandr-devel \
|
||||
nss-devel python-dbusmock openjdk-8-jre
|
||||
```
|
||||
|
||||
On Fedora, install the following libraries:
|
||||
|
||||
```sh
|
||||
$ sudo dnf install clang dbus-devel gperf gtk3-devel \
|
||||
libnotify-devel libgnome-keyring-devel libcap-devel \
|
||||
cups-devel libXtst-devel alsa-lib-devel libXrandr-devel \
|
||||
nss-devel python-dbusmock
|
||||
```
|
||||
|
||||
On Arch Linux / Manjaro, install the following libraries:
|
||||
|
||||
```sh
|
||||
$ sudo pacman -Syu base-devel clang libdbus gtk2 libnotify \
|
||||
libgnome-keyring alsa-lib libcap libcups libxtst \
|
||||
libxss nss gcc-multilib curl gperf bison \
|
||||
python2 python-dbusmock jdk8-openjdk
|
||||
```
|
||||
|
||||
Other distributions may offer similar packages for installation via package
|
||||
managers such as pacman. Or one can compile from source code.
|
||||
Additionally, Electron's [Linux dependency installer](https://github.com/electron/build-images/blob/main/tools/install-deps.sh) can be referenced to get the current dependencies that Electron requires in addition to what Chromium installs via [build/install-deps.sh](https://chromium.googlesource.com/chromium/src/+/HEAD/build/install-build-deps.sh).
|
||||
|
||||
### Cross compilation
|
||||
|
||||
If you want to build for an `arm` target you should also install the following
|
||||
dependencies:
|
||||
If you want to build for an `arm` target, you can use Electron's [Linux dependency installer](https://github.com/electron/build-images/blob/main/tools/install-deps.sh) to install the additional dependencies by passing the `--arm argument`:
|
||||
|
||||
```sh
|
||||
$ sudo apt-get install libc6-dev-armhf-cross linux-libc-dev-armhf-cross \
|
||||
g++-arm-linux-gnueabihf
|
||||
```
|
||||
|
||||
Similarly for `arm64`, install the following:
|
||||
|
||||
```sh
|
||||
$ sudo apt-get install libc6-dev-arm64-cross linux-libc-dev-arm64-cross \
|
||||
g++-aarch64-linux-gnu
|
||||
$ sudo install-deps.sh --arm
|
||||
```
|
||||
|
||||
And to cross-compile for `arm` or targets, you should pass the
|
||||
|
||||
@@ -9,7 +9,7 @@ check out our [Electron Versioning](./electron-versioning.md) doc.
|
||||
|
||||
| Electron | Alpha | Beta | Stable | EOL | Chrome | Node | Supported |
|
||||
| ------- | ----- | ------- | ------ | ------ | ---- | ---- | ---- |
|
||||
| 40.0.0 | 2025-Oct-30 | 2025-Dec-03 | 2025-Oct-28 | 2026-Jun-30 | M144 | TBD | ✅ |
|
||||
| 40.0.0 | 2025-Oct-30 | 2025-Dec-03 | 2026-Jan-13 | 2026-Jun-30 | M144 | TBD | ✅ |
|
||||
| 39.0.0 | 2025-Sep-04 | 2025-Oct-01 | 2025-Oct-28 | 2026-May-05 | M142 | v22.20 | ✅ |
|
||||
| 38.0.0 | 2025-Jun-26 | 2025-Aug-06 | 2025-Sep-02 | 2026-Mar-10 | M140 | v22.18 | ✅ |
|
||||
| 37.0.0 | 2025-May-01 | 2025-May-28 | 2025-Jun-24 | 2026-Jan-13 | M138 | v22.16 | ✅ |
|
||||
|
||||
@@ -118,13 +118,6 @@ You should at least follow these steps to improve the security of your applicati
|
||||
19. [Check which fuses you can change](#19-check-which-fuses-you-can-change)
|
||||
20. [Do not expose Electron APIs to untrusted web content](#20-do-not-expose-electron-apis-to-untrusted-web-content)
|
||||
|
||||
To automate the detection of misconfigurations and insecure patterns, it is
|
||||
possible to use
|
||||
[Electronegativity](https://github.com/doyensec/electronegativity). For
|
||||
additional details on potential weaknesses and implementation bugs when
|
||||
developing applications using Electron, please refer to this
|
||||
[guide for developers and auditors](https://doyensec.com/resources/us-17-Carettoni-Electronegativity-A-Study-Of-Electron-Security-wp.pdf).
|
||||
|
||||
### 1. Only load secure content
|
||||
|
||||
Any resources not included with your application should be loaded using a
|
||||
|
||||
@@ -119,7 +119,10 @@ export function fetchWithSession (input: RequestInfo, init: (RequestInit & {bypa
|
||||
p.reject(err);
|
||||
});
|
||||
|
||||
if (!req.body?.pipeTo(Writable.toWeb(r as unknown as Writable)).then(() => r.end())) { r.end(); }
|
||||
// pipeTo expects a WritableStream<Uint8Array>. Node.js' Writable.toWeb returns WritableStream<any>,
|
||||
// which causes a TS structural mismatch.
|
||||
const writable = Writable.toWeb(r as unknown as Writable) as unknown as WritableStream<Uint8Array>;
|
||||
if (!req.body?.pipeTo(writable).then(() => r.end())) { r.end(); }
|
||||
|
||||
return p.promise;
|
||||
}
|
||||
|
||||
@@ -4,6 +4,8 @@ import { createReadStream } from 'fs';
|
||||
import { Readable } from 'stream';
|
||||
import { ReadableStream } from 'stream/web';
|
||||
|
||||
import type { ReadableStreamDefaultReader } from 'stream/web';
|
||||
|
||||
// Global protocol APIs.
|
||||
const { registerSchemesAsPrivileged, getStandardSchemes, Protocol } = process._linkedBinding('electron_browser_protocol');
|
||||
|
||||
@@ -12,7 +14,7 @@ const ERR_UNEXPECTED = -9;
|
||||
|
||||
const isBuiltInScheme = (scheme: string) => ['http', 'https', 'file'].includes(scheme);
|
||||
|
||||
function makeStreamFromPipe (pipe: any): ReadableStream {
|
||||
function makeStreamFromPipe (pipe: any): ReadableStream<Uint8Array> {
|
||||
const buf = new Uint8Array(1024 * 1024 /* 1 MB */);
|
||||
return new ReadableStream({
|
||||
async pull (controller) {
|
||||
@@ -38,21 +40,26 @@ function makeStreamFromFileInfo ({
|
||||
filePath: string;
|
||||
offset?: number;
|
||||
length?: number;
|
||||
}): ReadableStream {
|
||||
}): ReadableStream<Uint8Array> {
|
||||
// Node's Readable.toWeb produces a WHATWG ReadableStream whose chunks are Uint8Array.
|
||||
return Readable.toWeb(createReadStream(filePath, {
|
||||
start: offset,
|
||||
end: length >= 0 ? offset + length : undefined
|
||||
}));
|
||||
})) as ReadableStream<Uint8Array>;
|
||||
}
|
||||
|
||||
function convertToRequestBody (uploadData: ProtocolRequest['uploadData']): RequestInit['body'] {
|
||||
if (!uploadData) return null;
|
||||
// Optimization: skip creating a stream if the request is just a single buffer.
|
||||
if (uploadData.length === 1 && (uploadData[0] as any).type === 'rawData') return uploadData[0].bytes;
|
||||
if (uploadData.length === 1 && (uploadData[0] as any).type === 'rawData') {
|
||||
return uploadData[0].bytes as any;
|
||||
}
|
||||
|
||||
const chunks = [...uploadData] as any[]; // TODO: types are wrong
|
||||
let current: ReadableStreamDefaultReader | null = null;
|
||||
return new ReadableStream({
|
||||
const chunks = [...uploadData] as any[]; // TODO: refine ProtocolRequest types
|
||||
// Use Node's web stream types explicitly to avoid DOM lib vs Node lib structural mismatches.
|
||||
// Generic <Uint8Array> ensures reader.read() returns value?: Uint8Array consistent with enqueue.
|
||||
let current: ReadableStreamDefaultReader<Uint8Array> | null = null;
|
||||
return new ReadableStream<Uint8Array>({
|
||||
async pull (controller) {
|
||||
if (current) {
|
||||
const { done, value } = await current.read();
|
||||
@@ -67,7 +74,7 @@ function convertToRequestBody (uploadData: ProtocolRequest['uploadData']): Reque
|
||||
if (!chunks.length) { return controller.close(); }
|
||||
const chunk = chunks.shift()!;
|
||||
if (chunk.type === 'rawData') {
|
||||
controller.enqueue(chunk.bytes);
|
||||
controller.enqueue(chunk.bytes as Uint8Array);
|
||||
} else if (chunk.type === 'file') {
|
||||
current = makeStreamFromFileInfo(chunk).getReader();
|
||||
return this.pull!(controller);
|
||||
|
||||
@@ -40,7 +40,7 @@ process.on('uncaughtException', function (error) {
|
||||
// Emit 'exit' event on quit.
|
||||
const { app } = require('electron');
|
||||
|
||||
app.on('quit', (_event, exitCode) => {
|
||||
app.on('quit', (_event: any, exitCode: number) => {
|
||||
process.emit('exit', exitCode);
|
||||
});
|
||||
|
||||
|
||||
@@ -289,7 +289,8 @@ function parseOptions (optionsIn: ClientRequestConstructorOptions | string): Nod
|
||||
referrerPolicy: options.referrerPolicy,
|
||||
cache: options.cache,
|
||||
allowNonHttpProtocols: Object.hasOwn(options, kAllowNonHttpProtocols),
|
||||
priority: options.priority
|
||||
priority: options.priority,
|
||||
bypassCustomProtocolHandlers: options.bypassCustomProtocolHandlers
|
||||
};
|
||||
if ('priorityIncremental' in options) {
|
||||
urlLoaderOptions.priorityIncremental = options.priorityIncremental;
|
||||
|
||||
@@ -11,12 +11,14 @@ const { contextIsolationEnabled } = internalContextBridge;
|
||||
* 1) Use menu API to show context menu.
|
||||
*/
|
||||
window.onload = function () {
|
||||
if (contextIsolationEnabled) {
|
||||
internalContextBridge.overrideGlobalValueFromIsolatedWorld([
|
||||
'InspectorFrontendHost', 'showContextMenuAtPoint'
|
||||
], createMenu);
|
||||
} else {
|
||||
window.InspectorFrontendHost!.showContextMenuAtPoint = createMenu;
|
||||
if (window.InspectorFrontendHost) {
|
||||
if (contextIsolationEnabled) {
|
||||
internalContextBridge.overrideGlobalValueFromIsolatedWorld([
|
||||
'InspectorFrontendHost', 'showContextMenuAtPoint'
|
||||
], createMenu);
|
||||
} else {
|
||||
window.InspectorFrontendHost.showContextMenuAtPoint = createMenu;
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
|
||||
21
package.json
21
package.json
@@ -1,14 +1,15 @@
|
||||
{
|
||||
"name": "electron",
|
||||
"name": "@electron-ci/dev-root",
|
||||
"version": "0.0.0-development",
|
||||
"repository": "https://github.com/electron/electron",
|
||||
"description": "Build cross platform desktop apps with JavaScript, HTML, and CSS",
|
||||
"devDependencies": {
|
||||
"@azure/storage-blob": "^12.28.0",
|
||||
"@datadog/datadog-ci": "^4.1.2",
|
||||
"@electron/asar": "^3.2.13",
|
||||
"@electron/docs-parser": "^2.0.0",
|
||||
"@electron/fiddle-core": "^1.3.4",
|
||||
"@electron/github-app-auth": "^2.2.1",
|
||||
"@electron/github-app-auth": "^3.2.0",
|
||||
"@electron/lint-roller": "^3.1.2",
|
||||
"@electron/typescript-definitions": "^9.1.2",
|
||||
"@octokit/rest": "^20.1.2",
|
||||
@@ -24,7 +25,6 @@
|
||||
"buffer": "^6.0.3",
|
||||
"chalk": "^4.1.0",
|
||||
"check-for-leaks": "^1.2.1",
|
||||
"dugite": "^2.7.1",
|
||||
"eslint": "^8.57.1",
|
||||
"eslint-config-standard": "^17.1.0",
|
||||
"eslint-plugin-import": "^2.32.0",
|
||||
@@ -40,6 +40,7 @@
|
||||
"lint-staged": "^16.1.0",
|
||||
"markdownlint-cli2": "^0.18.0",
|
||||
"minimist": "^1.2.8",
|
||||
"node-gyp": "^11.4.2",
|
||||
"null-loader": "^4.0.1",
|
||||
"pre-flight": "^2.0.0",
|
||||
"process": "^0.11.10",
|
||||
@@ -134,6 +135,18 @@
|
||||
]
|
||||
},
|
||||
"resolutions": {
|
||||
"nan": "nodejs/nan#e14bdcd1f72d62bca1d541b66da43130384ec213"
|
||||
"dbus-native/xml2js": "0.5.0",
|
||||
"abstract-socket": "github:deepak1556/node-abstractsocket#928cc591decd12aff7dad96449da8afc29832c19",
|
||||
"minimist@npm:~0.0.1": "0.2.4"
|
||||
},
|
||||
"packageManager": "yarn@4.12.0",
|
||||
"workspaces": [
|
||||
"spec",
|
||||
"spec/fixtures/native-addon/*"
|
||||
],
|
||||
"dependenciesMeta": {
|
||||
"abstract-socket": {
|
||||
"built": true
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -143,3 +143,7 @@ allow_electron_to_depend_on_components_os_crypt_sync.patch
|
||||
expose_referrerscriptinfo_hostdefinedoptionsindex.patch
|
||||
chore_disable_protocol_handler_dcheck.patch
|
||||
fix_release_mouse_buttons_on_focus_loss_on_wayland.patch
|
||||
viz_fix_visual_artifacts_due_to_resizing_root_render_pass_with_dcomp.patch
|
||||
viz_do_not_overallocate_surface_on_initial_render.patch
|
||||
viz_create_isbufferqueuesupportedandenabled.patch
|
||||
viz_fix_visual_artifacts_while_resizing_window_with_dcomp.patch
|
||||
|
||||
@@ -46,7 +46,7 @@ index 7280ef29b85c1b16b11dd9e4d628a9eb579bb4dd..ab56e29d402a400a8c91aa97b6e82ad7
|
||||
# than here in :chrome_dll.
|
||||
deps += [ "//chrome:packed_resources_integrity_header" ]
|
||||
diff --git a/chrome/test/BUILD.gn b/chrome/test/BUILD.gn
|
||||
index 15cfa64348e80a3507fc83c3819e9abdb238bffb..4650080f45da4e321d4b0f0dabd98f2bf097c7c2 100644
|
||||
index d8978eb678048850cc0e629d0c978f23417b5be9..219c9ae3dde4f2239b5c1331b99c8f2e9a170628 100644
|
||||
--- a/chrome/test/BUILD.gn
|
||||
+++ b/chrome/test/BUILD.gn
|
||||
@@ -7571,9 +7571,12 @@ test("unit_tests") {
|
||||
|
||||
@@ -312,7 +312,7 @@ index 7e3d46902fbf736b4240eb3fcb89975a7b222197..57fdc89fc265ad70cb0bff8443cc1026
|
||||
|
||||
auto DrawAsSinglePath = [&]() {
|
||||
diff --git a/third_party/blink/renderer/platform/runtime_enabled_features.json5 b/third_party/blink/renderer/platform/runtime_enabled_features.json5
|
||||
index 6f47f1f484ffbc107f454fb2b23a9adda68ff7c0..10a13a986bb5d39323bf25ecba1b3935b1b0a081 100644
|
||||
index 2e464ef7bbfd7e0d84df348d012e8020d4758726..b59eceacbd4143ef183bb67c39f9ccccc7582adb 100644
|
||||
--- a/third_party/blink/renderer/platform/runtime_enabled_features.json5
|
||||
+++ b/third_party/blink/renderer/platform/runtime_enabled_features.json5
|
||||
@@ -214,6 +214,10 @@
|
||||
|
||||
@@ -0,0 +1,93 @@
|
||||
From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001
|
||||
From: Niklas Wenzel <dev@nikwen.de>
|
||||
Date: Wed, 3 Dec 2025 17:10:02 +0100
|
||||
Subject: viz: Create IsBufferQueueSupportedAndEnabled()
|
||||
|
||||
Manual backport of crrev.com/c/7210913
|
||||
|
||||
Bug: 457463689
|
||||
Change-Id: I31bbaa6b5d79697c6bb5e1fc6738f6ea5a937b4f
|
||||
Reviewed-on: https://chromium-review.googlesource.com/c/chromium/src/+/7210913
|
||||
Reviewed-by: Michael Tang <tangm@microsoft.com>
|
||||
Commit-Queue: David Sanders <dsanders11@ucsbalum.com>
|
||||
Reviewed-by: Vasiliy Telezhnikov <vasilyt@chromium.org>
|
||||
Cr-Commit-Position: refs/heads/main@{#1553190}
|
||||
|
||||
diff --git a/components/viz/service/display/output_surface.cc b/components/viz/service/display/output_surface.cc
|
||||
index ff795eb057ac64f40aa842fec8e053d12f57f538..71287614c627d39f8d019889498205ab3eff2a69 100644
|
||||
--- a/components/viz/service/display/output_surface.cc
|
||||
+++ b/components/viz/service/display/output_surface.cc
|
||||
@@ -21,6 +21,16 @@
|
||||
|
||||
namespace viz {
|
||||
|
||||
+namespace {
|
||||
+
|
||||
+#if BUILDFLAG(IS_WIN)
|
||||
+// Use BufferQueue for the primary plane instead of a DXGI swap chain or DComp
|
||||
+// surface.
|
||||
+BASE_FEATURE(kBufferQueue, base::FEATURE_DISABLED_BY_DEFAULT);
|
||||
+#endif
|
||||
+
|
||||
+} // namespace
|
||||
+
|
||||
OutputSurface::Capabilities::Capabilities() = default;
|
||||
OutputSurface::Capabilities::~Capabilities() = default;
|
||||
OutputSurface::Capabilities::Capabilities(const Capabilities& capabilities) =
|
||||
@@ -94,6 +104,12 @@ bool IsDelegatedCompositingSupportedAndEnabled(
|
||||
// Ensure we check the feature flag iff the feature is supported.
|
||||
return features::IsDelegatedCompositingEnabled();
|
||||
}
|
||||
+
|
||||
+bool IsBufferQueueSupportedAndEnabled(
|
||||
+ OutputSurface::DCSupportLevel support_level) {
|
||||
+ return support_level >= OutputSurface::DCSupportLevel::kDCompDynamicTexture &&
|
||||
+ base::FeatureList::IsEnabled(kBufferQueue);
|
||||
+}
|
||||
#endif
|
||||
|
||||
} // namespace viz
|
||||
diff --git a/components/viz/service/display/output_surface.h b/components/viz/service/display/output_surface.h
|
||||
index 25306ab6e18a266efdc329e4ddd81f5303033f4c..589f4c10dad9c807c9e3ce7baba63795b629435b 100644
|
||||
--- a/components/viz/service/display/output_surface.h
|
||||
+++ b/components/viz/service/display/output_surface.h
|
||||
@@ -307,6 +307,9 @@ class VIZ_SERVICE_EXPORT OutputSurface {
|
||||
// `features::IsDelegatedCompositingEnabled()`.
|
||||
bool IsDelegatedCompositingSupportedAndEnabled(
|
||||
OutputSurface::DCSupportLevel support_level);
|
||||
+
|
||||
+bool IsBufferQueueSupportedAndEnabled(
|
||||
+ OutputSurface::DCSupportLevel support_level);
|
||||
#endif
|
||||
|
||||
} // namespace viz
|
||||
diff --git a/components/viz/service/display/skia_renderer.cc b/components/viz/service/display/skia_renderer.cc
|
||||
index e34e15dda13a183568fc3e186d3b89da1e828ad4..9b9a4c02c975799fe42b04f0d5b680274d28b09e 100644
|
||||
--- a/components/viz/service/display/skia_renderer.cc
|
||||
+++ b/components/viz/service/display/skia_renderer.cc
|
||||
@@ -121,12 +121,6 @@ namespace {
|
||||
BASE_FEATURE(kDumpWithoutCrashingOnMissingRenderPassBacking,
|
||||
base::FEATURE_ENABLED_BY_DEFAULT);
|
||||
|
||||
-#if BUILDFLAG(IS_WIN)
|
||||
-// Use BufferQueue for the primary plane instead of a DXGI swap chain or DComp
|
||||
-// surface.
|
||||
-BASE_FEATURE(kBufferQueue, base::FEATURE_DISABLED_BY_DEFAULT);
|
||||
-#endif
|
||||
-
|
||||
// Smallest unit that impacts anti-aliasing output. We use this to determine
|
||||
// when an exterior edge (with AA) has been clipped (no AA). The specific value
|
||||
// was chosen to match that used by gl_renderer.
|
||||
@@ -992,10 +986,8 @@ SkiaRenderer::SkiaRenderer(const RendererSettings* settings,
|
||||
|
||||
// It's possible to use BufferQueue with DComp textures, so we can optionally
|
||||
// enable it behind a feature flag.
|
||||
- const bool want_buffer_queue =
|
||||
- output_surface_->capabilities().dc_support_level >=
|
||||
- OutputSurface::DCSupportLevel::kDCompDynamicTexture &&
|
||||
- base::FeatureList::IsEnabled(kBufferQueue);
|
||||
+ const bool want_buffer_queue = IsBufferQueueSupportedAndEnabled(
|
||||
+ output_surface_->capabilities().dc_support_level);
|
||||
#else
|
||||
const bool want_buffer_queue = true;
|
||||
#endif
|
||||
@@ -0,0 +1,45 @@
|
||||
From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001
|
||||
From: Niklas Wenzel <dev@nikwen.de>
|
||||
Date: Wed, 3 Dec 2025 17:08:55 +0100
|
||||
Subject: viz: Do not overallocate surface on initial render
|
||||
|
||||
Manual backport of crrev.com/c/7129658
|
||||
|
||||
Change-Id: I0baa5865dbe66efc7b0f3f793c8e89cdc6aaa0b6
|
||||
Reviewed-on: https://chromium-review.googlesource.com/c/chromium/src/+/7129658
|
||||
Commit-Queue: Vasiliy Telezhnikov <vasilyt@chromium.org>
|
||||
Reviewed-by: Vasiliy Telezhnikov <vasilyt@chromium.org>
|
||||
Reviewed-by: Michael Tang <tangm@microsoft.com>
|
||||
Cr-Commit-Position: refs/heads/main@{#1544293}
|
||||
|
||||
diff --git a/components/viz/service/display/direct_renderer.cc b/components/viz/service/display/direct_renderer.cc
|
||||
index c03a4b3db61371021a94128f698126b5fef2f577..01abf5d36e2e117acf6f9cdc91307c9ac5616453 100644
|
||||
--- a/components/viz/service/display/direct_renderer.cc
|
||||
+++ b/components/viz/service/display/direct_renderer.cc
|
||||
@@ -1081,10 +1081,13 @@ gfx::Size DirectRenderer::CalculateTextureSizeForRenderPass(
|
||||
// buffer area and number of reallocations to quantify the trade-off.
|
||||
gfx::Size DirectRenderer::CalculateSizeForOutputSurface(
|
||||
const gfx::Size& requested_viewport_size) {
|
||||
+ const gfx::Size surface_size = surface_size_for_swap_buffers();
|
||||
+
|
||||
// We're not able to clip back buffers if output surface does not support
|
||||
- // clipping.
|
||||
- if (requested_viewport_size == surface_size_for_swap_buffers() ||
|
||||
+ // clipping. We don't round on the initial frame when a window is first shown.
|
||||
+ if (requested_viewport_size == surface_size ||
|
||||
!output_surface_->capabilities().supports_viewporter ||
|
||||
+ surface_size.IsZero() ||
|
||||
settings_->dont_round_texture_sizes_for_pixel_tests) {
|
||||
device_viewport_size_ = requested_viewport_size;
|
||||
return requested_viewport_size;
|
||||
@@ -1102,8 +1105,8 @@ gfx::Size DirectRenderer::CalculateSizeForOutputSurface(
|
||||
// allows backings to be more easily reused during a resize operation.
|
||||
const int request_width = requested_viewport_size.width();
|
||||
const int request_height = requested_viewport_size.height();
|
||||
- int surface_width = surface_size_for_swap_buffers().width();
|
||||
- int surface_height = surface_size_for_swap_buffers().height();
|
||||
+ int surface_width = surface_size.width();
|
||||
+ int surface_height = surface_size.height();
|
||||
constexpr int multiple = 256;
|
||||
|
||||
// If |request_width| or |request_height| is already a multiple of |multiple|,
|
||||
@@ -0,0 +1,43 @@
|
||||
From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001
|
||||
From: Niklas Wenzel <dev@nikwen.de>
|
||||
Date: Thu, 20 Nov 2025 11:51:44 -0800
|
||||
Subject: viz: Fix visual artifacts due to resizing root render pass with DComp
|
||||
|
||||
Backport of crrev.com/c/7156576
|
||||
|
||||
Refs https://github.com/electron/electron/issues/36280#issuecomment-3560964534
|
||||
|
||||
Bug: 457463689
|
||||
Change-Id: I7e00eadb2a1c3b44d64939d1a870d89befee158b
|
||||
Reviewed-on: https://chromium-review.googlesource.com/c/chromium/src/+/7156576
|
||||
Reviewed-by: Vasiliy Telezhnikov <vasilyt@chromium.org>
|
||||
Reviewed-by: Jonathan Ross <jonross@chromium.org>
|
||||
Commit-Queue: Jonathan Ross <jonross@chromium.org>
|
||||
Reviewed-by: Michael Tang <tangm@microsoft.com>
|
||||
Cr-Commit-Position: refs/heads/main@{#1547987}
|
||||
|
||||
diff --git a/components/viz/service/display_embedder/skia_output_device_dcomp.cc b/components/viz/service/display_embedder/skia_output_device_dcomp.cc
|
||||
index 81649eb59eb71ac950779af0f521a1f2a02e3add..7ac9ea1cdc4416a7af8dc2a75404cbc15be6cfad 100644
|
||||
--- a/components/viz/service/display_embedder/skia_output_device_dcomp.cc
|
||||
+++ b/components/viz/service/display_embedder/skia_output_device_dcomp.cc
|
||||
@@ -39,6 +39,11 @@
|
||||
namespace viz {
|
||||
|
||||
namespace {
|
||||
+// With DirectComposition, resize surface based on root render pass size to
|
||||
+// avoid gutter which shows stale pixels.
|
||||
+BASE_FEATURE(kDirectCompositionResizeBasedOnRootSurface,
|
||||
+ base::FEATURE_ENABLED_BY_DEFAULT);
|
||||
+
|
||||
base::TimeTicks g_last_reshape_failure = base::TimeTicks();
|
||||
|
||||
NOINLINE void CheckForLoopFailures() {
|
||||
@@ -155,6 +160,8 @@ SkiaOutputDeviceDComp::SkiaOutputDeviceDComp(
|
||||
capabilities_.renderer_allocates_images = true;
|
||||
capabilities_.supports_viewporter = presenter_->SupportsViewporter();
|
||||
capabilities_.supports_non_backed_solid_color_overlays = true;
|
||||
+ capabilities_.resize_based_on_root_surface =
|
||||
+ base::FeatureList::IsEnabled(kDirectCompositionResizeBasedOnRootSurface);
|
||||
|
||||
DCHECK(context_state_);
|
||||
DCHECK(context_state_->gr_context() ||
|
||||
@@ -0,0 +1,122 @@
|
||||
From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001
|
||||
From: Niklas Wenzel <dev@nikwen.de>
|
||||
Date: Wed, 3 Dec 2025 17:42:58 +0100
|
||||
Subject: viz: Fix visual artifacts while resizing window with DComp
|
||||
|
||||
Manual backport of crrev.com/c/7115438
|
||||
|
||||
Bug: 457463689
|
||||
Change-Id: I9c684effe15e0b112ae533faa243e5a035e9c875
|
||||
Reviewed-on: https://chromium-review.googlesource.com/c/chromium/src/+/7115438
|
||||
Commit-Queue: David Sanders <dsanders11@ucsbalum.com>
|
||||
Reviewed-by: Michael Tang <tangm@microsoft.com>
|
||||
Reviewed-by: Vasiliy Telezhnikov <vasilyt@chromium.org>
|
||||
Cr-Commit-Position: refs/heads/main@{#1553192}
|
||||
|
||||
diff --git a/components/viz/service/display/direct_renderer.cc b/components/viz/service/display/direct_renderer.cc
|
||||
index 01abf5d36e2e117acf6f9cdc91307c9ac5616453..7e45d9ea46d0d4095169daf748e20c98db21969d 100644
|
||||
--- a/components/viz/service/display/direct_renderer.cc
|
||||
+++ b/components/viz/service/display/direct_renderer.cc
|
||||
@@ -243,6 +243,31 @@ void DirectRenderer::DrawFrame(
|
||||
current_frame()->device_viewport_size = device_viewport_size;
|
||||
current_frame()->display_color_spaces = display_color_spaces;
|
||||
|
||||
+ gfx::Size surface_resource_size =
|
||||
+ CalculateSizeForOutputSurface(device_viewport_size);
|
||||
+
|
||||
+#if BUILDFLAG(IS_WIN)
|
||||
+ if (output_surface_->capabilities().clear_drawn_areas_outside_viewport &&
|
||||
+ device_viewport_size != surface_resource_size) {
|
||||
+ // On Windows with DirectComposition, we cannot synchronize the swap chain
|
||||
+ // |Present| and the DComp |Commit| calls to take effect at the same time.
|
||||
+ // (Both take effect asynchronously.) Hence, presenting a frame and changing
|
||||
+ // the DComp layer clip rect can happen at different times. This can lead to
|
||||
+ // ugly visual artifacts while resizing the window because it can reveal
|
||||
+ // areas of the surface that are outside the viewport (crbug.com/457463689).
|
||||
+ // To prevent those artifacts, we clear areas outside of the viewport with a
|
||||
+ // transparent color. Transparency is expensive, so we use it only while
|
||||
+ // resizing.
|
||||
+ // This line gives us a transparent image format and triggers the background
|
||||
+ // to be cleared in |SkiaRenderer::ClearFramebuffer|.
|
||||
+ root_render_pass->has_transparent_background = true;
|
||||
+ // Redraw and swap the whole surface.
|
||||
+ root_render_pass->output_rect = gfx::Rect(surface_resource_size);
|
||||
+ current_frame()->root_damage_rect = gfx::Rect(surface_resource_size);
|
||||
+ current_frame()->device_viewport_size = surface_resource_size;
|
||||
+ }
|
||||
+#endif
|
||||
+
|
||||
output_surface_->SetNeedsMeasureNextDrawLatency();
|
||||
BeginDrawingFrame();
|
||||
|
||||
@@ -274,8 +299,6 @@ void DirectRenderer::DrawFrame(
|
||||
current_frame()->display_color_spaces.GetOutputBufferFormat(
|
||||
current_frame()->root_render_pass->content_color_usage,
|
||||
frame_has_alpha));
|
||||
- gfx::Size surface_resource_size =
|
||||
- CalculateSizeForOutputSurface(device_viewport_size);
|
||||
if (overlay_processor_) {
|
||||
// Display transform and viewport size are needed for overlay validator on
|
||||
// Android SurfaceControl, and viewport size is need on Windows. These need
|
||||
@@ -397,8 +420,10 @@ void DirectRenderer::DrawFrame(
|
||||
|
||||
// If we need to redraw the frame, the whole output should be considered
|
||||
// damaged.
|
||||
- if (needs_full_frame_redraw)
|
||||
- current_frame()->root_damage_rect = gfx::Rect(device_viewport_size);
|
||||
+ if (needs_full_frame_redraw) {
|
||||
+ current_frame()->root_damage_rect =
|
||||
+ gfx::Rect(current_frame()->device_viewport_size);
|
||||
+ }
|
||||
|
||||
if (!skip_drawing_root_render_pass) {
|
||||
DrawRenderPassAndExecuteCopyRequests(root_render_pass);
|
||||
diff --git a/components/viz/service/display/output_surface.h b/components/viz/service/display/output_surface.h
|
||||
index 589f4c10dad9c807c9e3ce7baba63795b629435b..641bbfc732c88141ddd929a4c334360462259ee4 100644
|
||||
--- a/components/viz/service/display/output_surface.h
|
||||
+++ b/components/viz/service/display/output_surface.h
|
||||
@@ -106,6 +106,11 @@ class VIZ_SERVICE_EXPORT OutputSurface {
|
||||
#if BUILDFLAG(IS_WIN)
|
||||
// Whether this OutputSurface supports direct composition layers.
|
||||
DCSupportLevel dc_support_level = DCSupportLevel::kNone;
|
||||
+ // Whether to 1) clear all drawn areas outside the viewport with a
|
||||
+ // transparent background color when drawing a frame and 2) swap them. This
|
||||
+ // is necessary if the surface clip rect can get out of sync with the
|
||||
+ // viewport size (e.g., due to a race condition).
|
||||
+ bool clear_drawn_areas_outside_viewport = false;
|
||||
#endif
|
||||
// Whether this OutputSurface should skip DrawAndSwap(). This is true for
|
||||
// the unified display on Chrome OS. All drawing is handled by the physical
|
||||
diff --git a/components/viz/service/display_embedder/skia_output_device_dcomp.cc b/components/viz/service/display_embedder/skia_output_device_dcomp.cc
|
||||
index 7ac9ea1cdc4416a7af8dc2a75404cbc15be6cfad..8e027d1382c5d639c1e114b8e25b6cea3af3445d 100644
|
||||
--- a/components/viz/service/display_embedder/skia_output_device_dcomp.cc
|
||||
+++ b/components/viz/service/display_embedder/skia_output_device_dcomp.cc
|
||||
@@ -39,10 +39,8 @@
|
||||
namespace viz {
|
||||
|
||||
namespace {
|
||||
-// With DirectComposition, resize surface based on root render pass size to
|
||||
-// avoid gutter which shows stale pixels.
|
||||
-BASE_FEATURE(kDirectCompositionResizeBasedOnRootSurface,
|
||||
- base::FEATURE_ENABLED_BY_DEFAULT);
|
||||
+// Apply fixes for crbug.com/457463689.
|
||||
+BASE_FEATURE(kDirectCompositionResizeFixes, base::FEATURE_ENABLED_BY_DEFAULT);
|
||||
|
||||
base::TimeTicks g_last_reshape_failure = base::TimeTicks();
|
||||
|
||||
@@ -161,7 +159,14 @@ SkiaOutputDeviceDComp::SkiaOutputDeviceDComp(
|
||||
capabilities_.supports_viewporter = presenter_->SupportsViewporter();
|
||||
capabilities_.supports_non_backed_solid_color_overlays = true;
|
||||
capabilities_.resize_based_on_root_surface =
|
||||
- base::FeatureList::IsEnabled(kDirectCompositionResizeBasedOnRootSurface);
|
||||
+ base::FeatureList::IsEnabled(kDirectCompositionResizeFixes);
|
||||
+ // With delegated compositing or a buffer queue, |Present| and |Commit| are
|
||||
+ // synchronized and the clear is not needed.
|
||||
+ capabilities_.clear_drawn_areas_outside_viewport =
|
||||
+ base::FeatureList::IsEnabled(kDirectCompositionResizeFixes) &&
|
||||
+ !IsDelegatedCompositingSupportedAndEnabled(
|
||||
+ capabilities_.dc_support_level) &&
|
||||
+ !IsBufferQueueSupportedAndEnabled(capabilities_.dc_support_level);
|
||||
|
||||
DCHECK(context_state_);
|
||||
DCHECK(context_state_->gr_context() ||
|
||||
@@ -1 +1,2 @@
|
||||
chore_expose_ui_to_allow_electron_to_set_dock_side.patch
|
||||
fix_element_tree_flickering_with_node_inspection.patch
|
||||
|
||||
@@ -0,0 +1,107 @@
|
||||
From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001
|
||||
From: Alex Rudenko <alexrudenko@chromium.org>
|
||||
Date: Thu, 20 Nov 2025 11:18:30 +0100
|
||||
Subject: Fix element tree flickering with node inspection
|
||||
|
||||
Regressed in https://crrev.com/c/6888910. The highlighting in the tree
|
||||
outline emits the INSPECT_MODE_WILL_BE_TOGGLED on the overlay model
|
||||
causing the tree to clear the highlight immediately. This CL
|
||||
recovers the logic missed in the https://crrev.com/c/6888910
|
||||
to prevent re-entrancy during highlighting.
|
||||
|
||||
Fixed: 462120622
|
||||
Change-Id: I08af098f7a142085c2fb16511031855623e07c4b
|
||||
Reviewed-on: https://chromium-review.googlesource.com/c/devtools/devtools-frontend/+/7170551
|
||||
Reviewed-by: Philip Pfaffe <pfaffe@chromium.org>
|
||||
Commit-Queue: Philip Pfaffe <pfaffe@chromium.org>
|
||||
Auto-Submit: Alex Rudenko <alexrudenko@chromium.org>
|
||||
|
||||
diff --git a/front_end/panels/elements/DOMTreeWidget.test.ts b/front_end/panels/elements/DOMTreeWidget.test.ts
|
||||
index 43ae133087a61c47c84349c7550485bd52b23847..d83fddd7afc1871b8064631d63c1b6b1e5357b70 100644
|
||||
--- a/front_end/panels/elements/DOMTreeWidget.test.ts
|
||||
+++ b/front_end/panels/elements/DOMTreeWidget.test.ts
|
||||
@@ -24,6 +24,7 @@ describeWithMockConnection('DOMTreeWidget', () => {
|
||||
elementsTreeOutline,
|
||||
alreadyExpandedParentTreeElement: null,
|
||||
highlightedTreeElement: null,
|
||||
+ isUpdatingHighlights: false,
|
||||
});
|
||||
const domTree = new Elements.ElementsTreeOutline.DOMTreeWidget(undefined, view);
|
||||
domTree.performUpdate();
|
||||
diff --git a/front_end/panels/elements/ElementsTreeOutline.ts b/front_end/panels/elements/ElementsTreeOutline.ts
|
||||
index bd8093e1c0961648e782234ed5826273d6ace6d9..c6c8d9d29a84f872126ca0b7c847dffe08c285ad 100644
|
||||
--- a/front_end/panels/elements/ElementsTreeOutline.ts
|
||||
+++ b/front_end/panels/elements/ElementsTreeOutline.ts
|
||||
@@ -105,6 +105,7 @@ interface ViewInput {
|
||||
interface ViewOutput {
|
||||
elementsTreeOutline?: ElementsTreeOutline;
|
||||
highlightedTreeElement: ElementsTreeElement|null;
|
||||
+ isUpdatingHighlights: boolean;
|
||||
alreadyExpandedParentTreeElement: ElementsTreeElement|null;
|
||||
}
|
||||
|
||||
@@ -136,6 +137,7 @@ export const DEFAULT_VIEW = (input: ViewInput, output: ViewOutput, target: HTMLE
|
||||
// Node highlighting logic. FIXME: express as a lit template.
|
||||
const previousHighlightedNode = output.highlightedTreeElement?.node() ?? null;
|
||||
if (previousHighlightedNode !== input.currentHighlightedNode) {
|
||||
+ output.isUpdatingHighlights = true;
|
||||
let treeElement: ElementsTreeElement|null = null;
|
||||
|
||||
if (output.highlightedTreeElement) {
|
||||
@@ -173,6 +175,7 @@ export const DEFAULT_VIEW = (input: ViewInput, output: ViewOutput, target: HTMLE
|
||||
output.highlightedTreeElement = treeElement;
|
||||
output.elementsTreeOutline.setHoverEffect(treeElement);
|
||||
treeElement?.reveal(true);
|
||||
+ output.isUpdatingHighlights = false;
|
||||
}
|
||||
};
|
||||
|
||||
@@ -225,6 +228,7 @@ export class DOMTreeWidget extends UI.Widget.Widget {
|
||||
#viewOutput: ViewOutput = {
|
||||
highlightedTreeElement: null,
|
||||
alreadyExpandedParentTreeElement: null,
|
||||
+ isUpdatingHighlights: false,
|
||||
};
|
||||
#highlightThrottler = new Common.Throttler.Throttler(100);
|
||||
|
||||
@@ -239,8 +243,8 @@ export class DOMTreeWidget extends UI.Widget.Widget {
|
||||
SDK.OverlayModel.OverlayModel, SDK.OverlayModel.Events.HIGHLIGHT_NODE_REQUESTED, this.#highlightNode, this,
|
||||
{scoped: true});
|
||||
SDK.TargetManager.TargetManager.instance().addModelListener(
|
||||
- SDK.OverlayModel.OverlayModel, SDK.OverlayModel.Events.INSPECT_MODE_WILL_BE_TOGGLED, this.#clearState, this,
|
||||
- {scoped: true});
|
||||
+ SDK.OverlayModel.OverlayModel, SDK.OverlayModel.Events.INSPECT_MODE_WILL_BE_TOGGLED,
|
||||
+ this.#clearHighlightedNode, this, {scoped: true});
|
||||
}
|
||||
}
|
||||
|
||||
@@ -251,7 +255,13 @@ export class DOMTreeWidget extends UI.Widget.Widget {
|
||||
});
|
||||
}
|
||||
|
||||
- #clearState(): void {
|
||||
+ #clearHighlightedNode(): void {
|
||||
+ // Highlighting an element via tree outline will emit the
|
||||
+ // INSPECT_MODE_WILL_BE_TOGGLED event, therefore, we skip it if the view
|
||||
+ // informed us that it is updating the element.
|
||||
+ if (this.#viewOutput.isUpdatingHighlights) {
|
||||
+ return;
|
||||
+ }
|
||||
this.#currentHighlightedNode = null;
|
||||
this.requestUpdate();
|
||||
}
|
||||
@@ -305,11 +315,11 @@ export class DOMTreeWidget extends UI.Widget.Widget {
|
||||
currentHighlightedNode: this.#currentHighlightedNode,
|
||||
onElementsTreeUpdated: this.onElementsTreeUpdated.bind(this),
|
||||
onSelectedNodeChanged: event => {
|
||||
- this.#clearState();
|
||||
+ this.#clearHighlightedNode();
|
||||
this.onSelectedNodeChanged(event);
|
||||
},
|
||||
- onElementCollapsed: this.#clearState.bind(this),
|
||||
- onElementExpanded: this.#clearState.bind(this),
|
||||
+ onElementCollapsed: this.#clearHighlightedNode.bind(this),
|
||||
+ onElementExpanded: this.#clearHighlightedNode.bind(this),
|
||||
},
|
||||
this.#viewOutput, this.contentElement);
|
||||
}
|
||||
@@ -7,3 +7,4 @@ fix_support_new_variant_of_namedpropertyhandlerconfiguration_and.patch
|
||||
fix_correct_usages_of_v8_returnvalue_void_set_nonempty_for_new.patch
|
||||
chore_remove_deprecated_functioncallbackinfo_holder.patch
|
||||
fix_replace_deprecated_get_setprototype.patch
|
||||
chore_add_yarnrc_yml_and_yarn_lock_file_to_use_yarn_v4.patch
|
||||
|
||||
File diff suppressed because it is too large
Load Diff
@@ -39,7 +39,6 @@ build_change_crdtp_protocoltypetraits_signatures_to_avoid_conflict.patch
|
||||
fix_adjust_wpt_and_webidl_tests_for_enabled_float16array.patch
|
||||
chore_add_createexternalizabletwobytestring_to_globals.patch
|
||||
refactor_attach_cppgc_heap_on_v8_isolate_creation.patch
|
||||
fix_ensure_traverseparent_bails_on_resource_path_exit.patch
|
||||
cli_move_--trace-atomics-wait_to_eol.patch
|
||||
fix_cppgc_initializing_twice.patch
|
||||
fix_task_starvation_in_inspector_context_test.patch
|
||||
@@ -53,3 +52,8 @@ src_switch_from_get_setprototype_to_get_setprototypev2.patch
|
||||
fix_replace_deprecated_setprototype.patch
|
||||
fix_redefined_macos_sdk_header_symbols.patch
|
||||
src_use_cp_utf8_for_wide_file_names_on_win32.patch
|
||||
fix_ensure_traverseparent_bails_on_resource_path_exit.patch
|
||||
src_handle_der_decoding_errors_from_system_certificates.patch
|
||||
remove_obsolete_noarraybufferzerofillscope.patch
|
||||
src_prepare_for_v8_sandboxing.patch
|
||||
test_correct_conditional_secure_heap_flags_test.patch
|
||||
|
||||
@@ -6,10 +6,10 @@ Subject: Remove deprecated `GetIsolate`
|
||||
https://chromium-review.googlesource.com/c/v8/v8/+/6905244
|
||||
|
||||
diff --git a/src/api/environment.cc b/src/api/environment.cc
|
||||
index 8e227ddd1be50c046a8cf2895a31d607eb7d31de..82f53bba29613de212f64be440ca20d7c630fddf 100644
|
||||
index ceac508418f489a8077c1bc85a2feaf85bf60480..33827edce63c9fe08b52aea59571391a83853443 100644
|
||||
--- a/src/api/environment.cc
|
||||
+++ b/src/api/environment.cc
|
||||
@@ -654,7 +654,7 @@ std::unique_ptr<MultiIsolatePlatform> MultiIsolatePlatform::Create(
|
||||
@@ -646,7 +646,7 @@ std::unique_ptr<MultiIsolatePlatform> MultiIsolatePlatform::Create(
|
||||
|
||||
MaybeLocal<Object> GetPerContextExports(Local<Context> context,
|
||||
IsolateData* isolate_data) {
|
||||
@@ -18,7 +18,7 @@ index 8e227ddd1be50c046a8cf2895a31d607eb7d31de..82f53bba29613de212f64be440ca20d7
|
||||
EscapableHandleScope handle_scope(isolate);
|
||||
|
||||
Local<Object> global = context->Global();
|
||||
@@ -700,7 +700,7 @@ void ProtoThrower(const FunctionCallbackInfo<Value>& info) {
|
||||
@@ -692,7 +692,7 @@ void ProtoThrower(const FunctionCallbackInfo<Value>& info) {
|
||||
// This runs at runtime, regardless of whether the context
|
||||
// is created from a snapshot.
|
||||
Maybe<void> InitializeContextRuntime(Local<Context> context) {
|
||||
@@ -27,7 +27,7 @@ index 8e227ddd1be50c046a8cf2895a31d607eb7d31de..82f53bba29613de212f64be440ca20d7
|
||||
HandleScope handle_scope(isolate);
|
||||
|
||||
// When `IsCodeGenerationFromStringsAllowed` is true, V8 takes the fast path
|
||||
@@ -779,7 +779,7 @@ Maybe<void> InitializeContextRuntime(Local<Context> context) {
|
||||
@@ -771,7 +771,7 @@ Maybe<void> InitializeContextRuntime(Local<Context> context) {
|
||||
}
|
||||
|
||||
Maybe<void> InitializeBaseContextForSnapshot(Local<Context> context) {
|
||||
@@ -36,7 +36,7 @@ index 8e227ddd1be50c046a8cf2895a31d607eb7d31de..82f53bba29613de212f64be440ca20d7
|
||||
HandleScope handle_scope(isolate);
|
||||
|
||||
// Delete `Intl.v8BreakIterator`
|
||||
@@ -804,7 +804,7 @@ Maybe<void> InitializeBaseContextForSnapshot(Local<Context> context) {
|
||||
@@ -796,7 +796,7 @@ Maybe<void> InitializeBaseContextForSnapshot(Local<Context> context) {
|
||||
}
|
||||
|
||||
Maybe<void> InitializeMainContextForSnapshot(Local<Context> context) {
|
||||
@@ -45,7 +45,7 @@ index 8e227ddd1be50c046a8cf2895a31d607eb7d31de..82f53bba29613de212f64be440ca20d7
|
||||
HandleScope handle_scope(isolate);
|
||||
|
||||
// Initialize the default values.
|
||||
@@ -822,7 +822,7 @@ Maybe<void> InitializeMainContextForSnapshot(Local<Context> context) {
|
||||
@@ -814,7 +814,7 @@ Maybe<void> InitializeMainContextForSnapshot(Local<Context> context) {
|
||||
MaybeLocal<Object> InitializePrivateSymbols(Local<Context> context,
|
||||
IsolateData* isolate_data) {
|
||||
CHECK(isolate_data);
|
||||
@@ -54,7 +54,7 @@ index 8e227ddd1be50c046a8cf2895a31d607eb7d31de..82f53bba29613de212f64be440ca20d7
|
||||
EscapableHandleScope scope(isolate);
|
||||
Context::Scope context_scope(context);
|
||||
|
||||
@@ -846,7 +846,7 @@ MaybeLocal<Object> InitializePrivateSymbols(Local<Context> context,
|
||||
@@ -838,7 +838,7 @@ MaybeLocal<Object> InitializePrivateSymbols(Local<Context> context,
|
||||
MaybeLocal<Object> InitializePerIsolateSymbols(Local<Context> context,
|
||||
IsolateData* isolate_data) {
|
||||
CHECK(isolate_data);
|
||||
@@ -63,7 +63,7 @@ index 8e227ddd1be50c046a8cf2895a31d607eb7d31de..82f53bba29613de212f64be440ca20d7
|
||||
EscapableHandleScope scope(isolate);
|
||||
Context::Scope context_scope(context);
|
||||
|
||||
@@ -872,7 +872,7 @@ MaybeLocal<Object> InitializePerIsolateSymbols(Local<Context> context,
|
||||
@@ -864,7 +864,7 @@ MaybeLocal<Object> InitializePerIsolateSymbols(Local<Context> context,
|
||||
Maybe<void> InitializePrimordials(Local<Context> context,
|
||||
IsolateData* isolate_data) {
|
||||
// Run per-context JS files.
|
||||
@@ -508,10 +508,10 @@ index 492d5f455f45a5c8a957ecdabed38709a633f640..48f9917113555c7ed87e37750c45d152
|
||||
Local<Array> keys;
|
||||
if (!entries->GetOwnPropertyNames(context).ToLocal(&keys))
|
||||
diff --git a/src/node_errors.cc b/src/node_errors.cc
|
||||
index 4386a1bc5678e351ce084cd2c47202561619b164..8d51201ad24999ed8f54e16c7878432d41841cf2 100644
|
||||
index 36a21b9523351fe2f225ffe7fca184d737640b62..c6e9e2c00064348c435ae10871a4013cb49376e6 100644
|
||||
--- a/src/node_errors.cc
|
||||
+++ b/src/node_errors.cc
|
||||
@@ -633,7 +633,7 @@ v8::ModifyCodeGenerationFromStringsResult ModifyCodeGenerationFromStrings(
|
||||
@@ -631,7 +631,7 @@ v8::ModifyCodeGenerationFromStringsResult ModifyCodeGenerationFromStrings(
|
||||
v8::Local<v8::Context> context,
|
||||
v8::Local<v8::Value> source,
|
||||
bool is_code_like) {
|
||||
@@ -520,7 +520,7 @@ index 4386a1bc5678e351ce084cd2c47202561619b164..8d51201ad24999ed8f54e16c7878432d
|
||||
|
||||
if (context->GetNumberOfEmbedderDataFields() <=
|
||||
ContextEmbedderIndex::kAllowCodeGenerationFromStrings) {
|
||||
@@ -1000,7 +1000,7 @@ const char* errno_string(int errorno) {
|
||||
@@ -1037,7 +1037,7 @@ const char* errno_string(int errorno) {
|
||||
}
|
||||
|
||||
void PerIsolateMessageListener(Local<Message> message, Local<Value> error) {
|
||||
@@ -529,7 +529,7 @@ index 4386a1bc5678e351ce084cd2c47202561619b164..8d51201ad24999ed8f54e16c7878432d
|
||||
switch (message->ErrorLevel()) {
|
||||
case Isolate::MessageErrorLevel::kMessageWarning: {
|
||||
Environment* env = Environment::GetCurrent(isolate);
|
||||
@@ -1161,7 +1161,7 @@ void Initialize(Local<Object> target,
|
||||
@@ -1198,7 +1198,7 @@ void Initialize(Local<Object> target,
|
||||
SetMethod(
|
||||
context, target, "getErrorSourcePositions", GetErrorSourcePositions);
|
||||
|
||||
@@ -592,7 +592,7 @@ index 3c5f38ba4f492749c9d7d82179d2a6563787602b..6e83da3ee975dea431e21209bba9227e
|
||||
data_.Reset();
|
||||
return ret;
|
||||
diff --git a/src/node_modules.cc b/src/node_modules.cc
|
||||
index ed22da844a61b14b8580cd3d6bb3a233b8559b38..14f2a35f87e8c2fa17898147d7247cc00c066f35 100644
|
||||
index 62050791174563f88b8629d576eed8959b3c2e20..fa04b4a8cdd02a2cad1eaf2e5a848b951d1b1150 100644
|
||||
--- a/src/node_modules.cc
|
||||
+++ b/src/node_modules.cc
|
||||
@@ -64,7 +64,7 @@ void BindingData::Deserialize(v8::Local<v8::Context> context,
|
||||
@@ -604,7 +604,7 @@ index ed22da844a61b14b8580cd3d6bb3a233b8559b38..14f2a35f87e8c2fa17898147d7247cc0
|
||||
Realm* realm = Realm::GetCurrent(context);
|
||||
BindingData* binding = realm->AddBindingData<BindingData>(holder);
|
||||
CHECK_NOT_NULL(binding);
|
||||
@@ -656,7 +656,7 @@ void BindingData::CreatePerContextProperties(Local<Object> target,
|
||||
@@ -617,7 +617,7 @@ void BindingData::CreatePerContextProperties(Local<Object> target,
|
||||
Realm* realm = Realm::GetCurrent(context);
|
||||
realm->AddBindingData<BindingData>(target);
|
||||
|
||||
@@ -640,7 +640,7 @@ index 66a8ee48fc68b22eaf6c9d9209cc5cb2439e55ff..b31e244f8af7d37c35319853a478776c
|
||||
env->AssignToContext(context, this, ContextInfo(""));
|
||||
}
|
||||
diff --git a/src/node_report.cc b/src/node_report.cc
|
||||
index 8ff711f12e19f73e50daac2b9c0fd26773d32758..6966710e8f0be542364850776ddf76f9223a02e7 100644
|
||||
index e1f4e30417d17f85d2294f3a01e6d90f0a443948..12a59307b452b0d67ebe909cae0458b8a0ca085b 100644
|
||||
--- a/src/node_report.cc
|
||||
+++ b/src/node_report.cc
|
||||
@@ -399,7 +399,7 @@ static void PrintJavaScriptErrorProperties(JSONWriter* writer,
|
||||
|
||||
@@ -8,10 +8,10 @@ they use themselves as the entry point. We should try to upstream some form
|
||||
of this.
|
||||
|
||||
diff --git a/lib/internal/process/pre_execution.js b/lib/internal/process/pre_execution.js
|
||||
index d12d21905c4823f45cffeea4423e99e81b1008f5..4987cd3f6c9eefb440bca3f58113df6cd5b410ac 100644
|
||||
index 15443a710ccf53fae333da3b1fbb52a970c658d5..464b34829c1a566836bfca6bbc2b87fcf5e50016 100644
|
||||
--- a/lib/internal/process/pre_execution.js
|
||||
+++ b/lib/internal/process/pre_execution.js
|
||||
@@ -267,12 +267,14 @@ function patchProcessObject(expandArgv1) {
|
||||
@@ -265,12 +265,14 @@ function patchProcessObject(expandArgv1) {
|
||||
// the entry point.
|
||||
if (expandArgv1 && process.argv[1] && process.argv[1][0] !== '-') {
|
||||
// Expand process.argv[1] into a full path.
|
||||
|
||||
@@ -8,10 +8,10 @@ resource path. This commit ensures that the TraverseParent function
|
||||
bails out if the parent path is outside of the resource path.
|
||||
|
||||
diff --git a/src/node_modules.cc b/src/node_modules.cc
|
||||
index 60b03b1563b230f78d8a9bdd8480da4d2ae90a27..35bfada261258407982d9e24cf7b3e820235c941 100644
|
||||
index 947513d5b91e8c13478b25d80a1157edbcd64b64..4e46df6afe6ca57f6df9a64d3fc572450baf7d5c 100644
|
||||
--- a/src/node_modules.cc
|
||||
+++ b/src/node_modules.cc
|
||||
@@ -279,8 +279,41 @@ const BindingData::PackageConfig* BindingData::TraverseParent(
|
||||
@@ -315,8 +315,41 @@ const BindingData::PackageConfig* BindingData::TraverseParent(
|
||||
Realm* realm, const std::filesystem::path& check_path) {
|
||||
std::filesystem::path current_path = check_path;
|
||||
auto env = realm->env();
|
||||
@@ -47,22 +47,22 @@ index 60b03b1563b230f78d8a9bdd8480da4d2ae90a27..35bfada261258407982d9e24cf7b3e82
|
||||
+ });
|
||||
+ };
|
||||
+
|
||||
+ bool did_original_path_start_with_resources_path = starts_with(check_path.
|
||||
+ generic_string(), resources_path);
|
||||
+ bool did_original_path_start_with_resources_path = starts_with(
|
||||
+ ConvertGenericPathToUTF8(check_path), resources_path);
|
||||
+
|
||||
do {
|
||||
current_path = current_path.parent_path();
|
||||
|
||||
@@ -299,6 +332,12 @@ const BindingData::PackageConfig* BindingData::TraverseParent(
|
||||
return nullptr;
|
||||
@@ -336,6 +369,12 @@ const BindingData::PackageConfig* BindingData::TraverseParent(
|
||||
}
|
||||
}
|
||||
|
||||
+ // If current path is outside the resources path, bail.
|
||||
+ if (did_original_path_start_with_resources_path &&
|
||||
+ !starts_with(current_path.generic_string(), resources_path)) {
|
||||
+ !starts_with(ConvertGenericPathToUTF8(current_path), resources_path)) {
|
||||
+ return nullptr;
|
||||
+ }
|
||||
+
|
||||
// Check if the path ends with `/node_modules`
|
||||
if (current_path.generic_string().ends_with("/node_modules")) {
|
||||
if (current_path.filename() == "node_modules") {
|
||||
return nullptr;
|
||||
|
||||
@@ -20,7 +20,7 @@ index 82225b0a53dd828750991a4e15a060b736b6ea2b..4b0d31356a2496a7fc67876a22da2453
|
||||
V(performance_entry_callback, v8::Function) \
|
||||
V(prepare_stack_trace_callback, v8::Function) \
|
||||
diff --git a/src/node_modules.cc b/src/node_modules.cc
|
||||
index 35bfada261258407982d9e24cf7b3e820235c941..ed22da844a61b14b8580cd3d6bb3a233b8559b38 100644
|
||||
index 60b03b1563b230f78d8a9bdd8480da4d2ae90a27..62050791174563f88b8629d576eed8959b3c2e20 100644
|
||||
--- a/src/node_modules.cc
|
||||
+++ b/src/node_modules.cc
|
||||
@@ -21,6 +21,7 @@ namespace modules {
|
||||
@@ -90,7 +90,7 @@ index 35bfada261258407982d9e24cf7b3e820235c941..ed22da844a61b14b8580cd3d6bb3a233
|
||||
void BindingData::ReadPackageJSON(const FunctionCallbackInfo<Value>& args) {
|
||||
CHECK_GE(args.Length(), 1); // path, [is_esm, base, specifier]
|
||||
CHECK(args[0]->IsString()); // path
|
||||
@@ -597,6 +633,8 @@ void InitImportMetaPathHelpers(const FunctionCallbackInfo<Value>& args) {
|
||||
@@ -558,6 +594,8 @@ void InitImportMetaPathHelpers(const FunctionCallbackInfo<Value>& args) {
|
||||
void BindingData::CreatePerIsolateProperties(IsolateData* isolate_data,
|
||||
Local<ObjectTemplate> target) {
|
||||
Isolate* isolate = isolate_data->isolate();
|
||||
@@ -99,7 +99,7 @@ index 35bfada261258407982d9e24cf7b3e820235c941..ed22da844a61b14b8580cd3d6bb3a233
|
||||
SetMethod(isolate, target, "readPackageJSON", ReadPackageJSON);
|
||||
SetMethod(isolate,
|
||||
target,
|
||||
@@ -635,6 +673,8 @@ void BindingData::CreatePerContextProperties(Local<Object> target,
|
||||
@@ -596,6 +634,8 @@ void BindingData::CreatePerContextProperties(Local<Object> target,
|
||||
|
||||
void BindingData::RegisterExternalReferences(
|
||||
ExternalReferenceRegistry* registry) {
|
||||
|
||||
@@ -86,10 +86,10 @@ index 0ca643aa74d13f278685d2330b791182b55c15b4..cbcecfba33070b820aca0e2814982160
|
||||
NODE_DEFINE_CONSTANT(target, ETIMEDOUT);
|
||||
#endif
|
||||
diff --git a/src/node_errors.cc b/src/node_errors.cc
|
||||
index ae8553ee2022d60fea4572976b14ba9cd253aa45..4386a1bc5678e351ce084cd2c47202561619b164 100644
|
||||
index 238942d45a136facec55ca5a2534e2dc407137e9..36a21b9523351fe2f225ffe7fca184d737640b62 100644
|
||||
--- a/src/node_errors.cc
|
||||
+++ b/src/node_errors.cc
|
||||
@@ -862,10 +862,6 @@ const char* errno_string(int errorno) {
|
||||
@@ -899,10 +899,6 @@ const char* errno_string(int errorno) {
|
||||
ERRNO_CASE(ENOBUFS);
|
||||
#endif
|
||||
|
||||
@@ -100,7 +100,7 @@ index ae8553ee2022d60fea4572976b14ba9cd253aa45..4386a1bc5678e351ce084cd2c4720256
|
||||
#ifdef ENODEV
|
||||
ERRNO_CASE(ENODEV);
|
||||
#endif
|
||||
@@ -904,14 +900,6 @@ const char* errno_string(int errorno) {
|
||||
@@ -941,14 +937,6 @@ const char* errno_string(int errorno) {
|
||||
ERRNO_CASE(ENOSPC);
|
||||
#endif
|
||||
|
||||
@@ -115,7 +115,7 @@ index ae8553ee2022d60fea4572976b14ba9cd253aa45..4386a1bc5678e351ce084cd2c4720256
|
||||
#ifdef ENOSYS
|
||||
ERRNO_CASE(ENOSYS);
|
||||
#endif
|
||||
@@ -994,10 +982,6 @@ const char* errno_string(int errorno) {
|
||||
@@ -1031,10 +1019,6 @@ const char* errno_string(int errorno) {
|
||||
ERRNO_CASE(ESTALE);
|
||||
#endif
|
||||
|
||||
|
||||
@@ -48,7 +48,7 @@ index fe669d40c31a29334b047b9cfee3067f64ef0a7b..9e5de7bbe574add017cd12ee091304d0
|
||||
|
||||
static CFunction fast_timing_safe_equal(CFunction::Make(FastTimingSafeEqual));
|
||||
diff --git a/src/node_buffer.cc b/src/node_buffer.cc
|
||||
index e39852c8e0392e0a9ae5d4ea58be115416e19233..c94b14741c827a81d69a6f036426a344e563ad72 100644
|
||||
index b9f0c97938203b4652780a7d707c5e83319330b0..8a5b6b57321c2843a965a7e51b2ebed991a1e424 100644
|
||||
--- a/src/node_buffer.cc
|
||||
+++ b/src/node_buffer.cc
|
||||
@@ -44,6 +44,14 @@
|
||||
@@ -74,7 +74,7 @@ index e39852c8e0392e0a9ae5d4ea58be115416e19233..c94b14741c827a81d69a6f036426a344
|
||||
using v8::FunctionCallbackInfo;
|
||||
using v8::Global;
|
||||
using v8::HandleScope;
|
||||
@@ -584,19 +591,24 @@ void SlowCopy(const FunctionCallbackInfo<Value>& args) {
|
||||
@@ -583,19 +590,24 @@ void SlowCopy(const FunctionCallbackInfo<Value>& args) {
|
||||
|
||||
// Assume caller has properly validated args.
|
||||
uint32_t FastCopy(Local<Value> receiver,
|
||||
@@ -107,7 +107,7 @@ index e39852c8e0392e0a9ae5d4ea58be115416e19233..c94b14741c827a81d69a6f036426a344
|
||||
return to_copy;
|
||||
}
|
||||
|
||||
@@ -865,19 +877,17 @@ void Compare(const FunctionCallbackInfo<Value> &args) {
|
||||
@@ -864,19 +876,17 @@ void Compare(const FunctionCallbackInfo<Value> &args) {
|
||||
}
|
||||
|
||||
int32_t FastCompare(v8::Local<v8::Value>,
|
||||
@@ -135,7 +135,7 @@ index e39852c8e0392e0a9ae5d4ea58be115416e19233..c94b14741c827a81d69a6f036426a344
|
||||
}
|
||||
|
||||
static v8::CFunction fast_compare(v8::CFunction::Make(FastCompare));
|
||||
@@ -1149,14 +1159,13 @@ void SlowIndexOfNumber(const FunctionCallbackInfo<Value>& args) {
|
||||
@@ -1148,14 +1158,13 @@ void SlowIndexOfNumber(const FunctionCallbackInfo<Value>& args) {
|
||||
}
|
||||
|
||||
int32_t FastIndexOfNumber(v8::Local<v8::Value>,
|
||||
@@ -153,7 +153,7 @@ index e39852c8e0392e0a9ae5d4ea58be115416e19233..c94b14741c827a81d69a6f036426a344
|
||||
}
|
||||
|
||||
static v8::CFunction fast_index_of_number(
|
||||
@@ -1496,21 +1505,31 @@ void SlowWriteString(const FunctionCallbackInfo<Value>& args) {
|
||||
@@ -1510,21 +1519,31 @@ void SlowWriteString(const FunctionCallbackInfo<Value>& args) {
|
||||
|
||||
template <encoding encoding>
|
||||
uint32_t FastWriteString(Local<Value> receiver,
|
||||
|
||||
@@ -9,10 +9,10 @@ This is already applied in newer versions of Node so we can drop
|
||||
this patch once we upgrade to v23.
|
||||
|
||||
diff --git a/src/api/environment.cc b/src/api/environment.cc
|
||||
index 0a358735c331767e8eb563a80e9aaccfb544c27b..d7d18d5fcbf008ac131db189a141315af4f6410b 100644
|
||||
index 79327877b0f34cbafb3efcc21617027d4011f806..8a12475857135bd3e904610b7eb887c397c8e73c 100644
|
||||
--- a/src/api/environment.cc
|
||||
+++ b/src/api/environment.cc
|
||||
@@ -835,7 +835,7 @@ MaybeLocal<Object> InitializePrivateSymbols(Local<Context> context,
|
||||
@@ -827,7 +827,7 @@ MaybeLocal<Object> InitializePrivateSymbols(Local<Context> context,
|
||||
|
||||
Local<Object> private_symbols_object;
|
||||
if (!private_symbols->NewInstance(context).ToLocal(&private_symbols_object) ||
|
||||
@@ -21,7 +21,7 @@ index 0a358735c331767e8eb563a80e9aaccfb544c27b..d7d18d5fcbf008ac131db189a141315a
|
||||
.IsNothing()) {
|
||||
return MaybeLocal<Object>();
|
||||
}
|
||||
@@ -861,7 +861,7 @@ MaybeLocal<Object> InitializePerIsolateSymbols(Local<Context> context,
|
||||
@@ -853,7 +853,7 @@ MaybeLocal<Object> InitializePerIsolateSymbols(Local<Context> context,
|
||||
Local<Object> per_isolate_symbols_object;
|
||||
if (!per_isolate_symbols->NewInstance(context).ToLocal(
|
||||
&per_isolate_symbols_object) ||
|
||||
|
||||
@@ -18,10 +18,10 @@ This can be removed when Node.js upgrades to a version of V8 containing CLs
|
||||
from the above issue.
|
||||
|
||||
diff --git a/src/api/environment.cc b/src/api/environment.cc
|
||||
index cb37fa080fc8e8d524cfa2758c4a8c2c5652324d..8e227ddd1be50c046a8cf2895a31d607eb7d31de 100644
|
||||
index fd71ceac65ccef1d2832b45b0b5612877cee22c1..ceac508418f489a8077c1bc85a2feaf85bf60480 100644
|
||||
--- a/src/api/environment.cc
|
||||
+++ b/src/api/environment.cc
|
||||
@@ -316,6 +316,10 @@ Isolate* NewIsolate(Isolate::CreateParams* params,
|
||||
@@ -308,6 +308,10 @@ Isolate* NewIsolate(Isolate::CreateParams* params,
|
||||
MultiIsolatePlatform* platform,
|
||||
const SnapshotData* snapshot_data,
|
||||
const IsolateSettings& settings) {
|
||||
@@ -32,7 +32,7 @@ index cb37fa080fc8e8d524cfa2758c4a8c2c5652324d..8e227ddd1be50c046a8cf2895a31d607
|
||||
Isolate* isolate = Isolate::Allocate();
|
||||
if (isolate == nullptr) return nullptr;
|
||||
|
||||
@@ -359,9 +363,12 @@ Isolate* NewIsolate(ArrayBufferAllocator* allocator,
|
||||
@@ -351,9 +355,12 @@ Isolate* NewIsolate(ArrayBufferAllocator* allocator,
|
||||
uv_loop_t* event_loop,
|
||||
MultiIsolatePlatform* platform,
|
||||
const EmbedderSnapshotData* snapshot_data,
|
||||
|
||||
653
patches/node/remove_obsolete_noarraybufferzerofillscope.patch
Normal file
653
patches/node/remove_obsolete_noarraybufferzerofillscope.patch
Normal file
@@ -0,0 +1,653 @@
|
||||
From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001
|
||||
From: Robo <hop2deep@gmail.com>
|
||||
Date: Wed, 21 Jan 2026 09:53:15 +0000
|
||||
Subject: remove obsolete NoArrayBufferZeroFillScope
|
||||
|
||||
Replace the scope in favor of the V8 api added in
|
||||
https://chromium-review.googlesource.com/c/v8/v8/+/5679067
|
||||
|
||||
Ports changes from
|
||||
1) https://github.com/nodejs/node/commit/869ea331f3a8215229290e2e6038956874c382a6
|
||||
2) https://github.com/nodejs/node/commit/ef9dc0857a73610f5de5dc9f37afd0a927c4c17f
|
||||
3) partially from https://github.com/nodejs/node/commit/e0a71517fef4ca83f2d40d2d1600022bc82a7f9f
|
||||
|
||||
This is needed to remove dependency on the zero_fill_field_
|
||||
that is exposed to JS
|
||||
Refs https://github.com/nodejs/node/commit/3cdb1cd437f63dd256ae2ab3b7e9016257326cb4
|
||||
|
||||
diff --git a/src/api/environment.cc b/src/api/environment.cc
|
||||
index 8a12475857135bd3e904610b7eb887c397c8e73c..3702672f4e2c3b1bff9f9f5c66ca251af447826a 100644
|
||||
--- a/src/api/environment.cc
|
||||
+++ b/src/api/environment.cc
|
||||
@@ -107,11 +107,7 @@ MaybeLocal<Value> PrepareStackTraceCallback(Local<Context> context,
|
||||
}
|
||||
|
||||
void* NodeArrayBufferAllocator::Allocate(size_t size) {
|
||||
- void* ret;
|
||||
- if (zero_fill_field_ || per_process::cli_options->zero_fill_all_buffers)
|
||||
- ret = allocator_->Allocate(size);
|
||||
- else
|
||||
- ret = allocator_->AllocateUninitialized(size);
|
||||
+ void* ret = allocator_->Allocate(size);
|
||||
if (ret != nullptr) [[likely]] {
|
||||
total_mem_usage_.fetch_add(size, std::memory_order_relaxed);
|
||||
}
|
||||
diff --git a/src/crypto/crypto_cipher.cc b/src/crypto/crypto_cipher.cc
|
||||
index c00d3616e08b00b1e0a3a29b2dbb5278e1e14fcc..8939c5e5085d00b098f66074b9ee033f5be55d08 100644
|
||||
--- a/src/crypto/crypto_cipher.cc
|
||||
+++ b/src/crypto/crypto_cipher.cc
|
||||
@@ -20,6 +20,7 @@ using ncrypto::SSLPointer;
|
||||
using v8::Array;
|
||||
using v8::ArrayBuffer;
|
||||
using v8::BackingStore;
|
||||
+using v8::BackingStoreInitializationMode;
|
||||
using v8::Context;
|
||||
using v8::FunctionCallbackInfo;
|
||||
using v8::FunctionTemplate;
|
||||
@@ -774,10 +775,10 @@ CipherBase::UpdateResult CipherBase::Update(
|
||||
return kErrorState;
|
||||
}
|
||||
|
||||
- {
|
||||
- NoArrayBufferZeroFillScope no_zero_fill_scope(env()->isolate_data());
|
||||
- *out = ArrayBuffer::NewBackingStore(env()->isolate(), buf_len);
|
||||
- }
|
||||
+ *out = ArrayBuffer::NewBackingStore(
|
||||
+ env()->isolate(),
|
||||
+ buf_len,
|
||||
+ BackingStoreInitializationMode::kUninitialized);
|
||||
|
||||
buffer = {
|
||||
.data = reinterpret_cast<const unsigned char*>(data),
|
||||
@@ -852,11 +853,10 @@ bool CipherBase::Final(std::unique_ptr<BackingStore>* out) {
|
||||
|
||||
const int mode = ctx_.getMode();
|
||||
|
||||
- {
|
||||
- NoArrayBufferZeroFillScope no_zero_fill_scope(env()->isolate_data());
|
||||
- *out = ArrayBuffer::NewBackingStore(
|
||||
- env()->isolate(), static_cast<size_t>(ctx_.getBlockSize()));
|
||||
- }
|
||||
+ *out = ArrayBuffer::NewBackingStore(
|
||||
+ env()->isolate(),
|
||||
+ static_cast<size_t>(ctx_.getBlockSize()),
|
||||
+ BackingStoreInitializationMode::kUninitialized);
|
||||
|
||||
if (kind_ == kDecipher &&
|
||||
Cipher::FromCtx(ctx_).isSupportedAuthenticatedMode()) {
|
||||
@@ -972,10 +972,10 @@ bool PublicKeyCipher::Cipher(
|
||||
return false;
|
||||
}
|
||||
|
||||
- {
|
||||
- NoArrayBufferZeroFillScope no_zero_fill_scope(env->isolate_data());
|
||||
- *out = ArrayBuffer::NewBackingStore(env->isolate(), out_len);
|
||||
- }
|
||||
+ *out = ArrayBuffer::NewBackingStore(
|
||||
+ env->isolate(),
|
||||
+ out_len,
|
||||
+ BackingStoreInitializationMode::kUninitialized);
|
||||
|
||||
if (EVP_PKEY_cipher(
|
||||
ctx.get(),
|
||||
diff --git a/src/crypto/crypto_common.cc b/src/crypto/crypto_common.cc
|
||||
index b81b9005365272217c77e2b9289bd9f877c0e77c..185b1d8fe657b5db64dc92497ca742d69f7a2764 100644
|
||||
--- a/src/crypto/crypto_common.cc
|
||||
+++ b/src/crypto/crypto_common.cc
|
||||
@@ -37,6 +37,7 @@ using ncrypto::X509Pointer;
|
||||
using ncrypto::X509View;
|
||||
using v8::ArrayBuffer;
|
||||
using v8::BackingStore;
|
||||
+using v8::BackingStoreInitializationMode;
|
||||
using v8::Context;
|
||||
using v8::EscapableHandleScope;
|
||||
using v8::Integer;
|
||||
@@ -307,11 +308,10 @@ MaybeLocal<Object> ECPointToBuffer(Environment* env,
|
||||
return MaybeLocal<Object>();
|
||||
}
|
||||
|
||||
- std::unique_ptr<BackingStore> bs;
|
||||
- {
|
||||
- NoArrayBufferZeroFillScope no_zero_fill_scope(env->isolate_data());
|
||||
- bs = ArrayBuffer::NewBackingStore(env->isolate(), len);
|
||||
- }
|
||||
+ std::unique_ptr<BackingStore> bs = ArrayBuffer::NewBackingStore(
|
||||
+ env->isolate(),
|
||||
+ len,
|
||||
+ BackingStoreInitializationMode::kUninitialized);
|
||||
|
||||
len = EC_POINT_point2oct(group,
|
||||
point,
|
||||
diff --git a/src/crypto/crypto_ec.cc b/src/crypto/crypto_ec.cc
|
||||
index 2a3107dbbf5c0dfe70c2e105338d186e5620ddbf..f36c84a77313bd57d0a7a902d1a2529636ca1422 100644
|
||||
--- a/src/crypto/crypto_ec.cc
|
||||
+++ b/src/crypto/crypto_ec.cc
|
||||
@@ -29,6 +29,7 @@ using ncrypto::MarkPopErrorOnReturn;
|
||||
using v8::Array;
|
||||
using v8::ArrayBuffer;
|
||||
using v8::BackingStore;
|
||||
+using v8::BackingStoreInitializationMode;
|
||||
using v8::Context;
|
||||
using v8::FunctionCallbackInfo;
|
||||
using v8::FunctionTemplate;
|
||||
@@ -201,14 +202,10 @@ void ECDH::ComputeSecret(const FunctionCallbackInfo<Value>& args) {
|
||||
return;
|
||||
}
|
||||
|
||||
- std::unique_ptr<BackingStore> bs;
|
||||
- {
|
||||
- NoArrayBufferZeroFillScope no_zero_fill_scope(env->isolate_data());
|
||||
- // NOTE: field_size is in bits
|
||||
- int field_size = EC_GROUP_get_degree(ecdh->group_);
|
||||
- size_t out_len = (field_size + 7) / 8;
|
||||
- bs = ArrayBuffer::NewBackingStore(env->isolate(), out_len);
|
||||
- }
|
||||
+ int field_size = EC_GROUP_get_degree(ecdh->group_);
|
||||
+ size_t out_len = (field_size + 7) / 8;
|
||||
+ auto bs = ArrayBuffer::NewBackingStore(
|
||||
+ env->isolate(), out_len, BackingStoreInitializationMode::kUninitialized);
|
||||
|
||||
if (!ECDH_compute_key(
|
||||
bs->Data(), bs->ByteLength(), pub, ecdh->key_.get(), nullptr))
|
||||
@@ -257,12 +254,10 @@ void ECDH::GetPrivateKey(const FunctionCallbackInfo<Value>& args) {
|
||||
return THROW_ERR_CRYPTO_OPERATION_FAILED(env,
|
||||
"Failed to get ECDH private key");
|
||||
|
||||
- std::unique_ptr<BackingStore> bs;
|
||||
- {
|
||||
- NoArrayBufferZeroFillScope no_zero_fill_scope(env->isolate_data());
|
||||
- bs = ArrayBuffer::NewBackingStore(env->isolate(),
|
||||
- BignumPointer::GetByteCount(b));
|
||||
- }
|
||||
+ auto bs = ArrayBuffer::NewBackingStore(
|
||||
+ env->isolate(),
|
||||
+ BignumPointer::GetByteCount(b),
|
||||
+ BackingStoreInitializationMode::kUninitialized);
|
||||
CHECK_EQ(bs->ByteLength(),
|
||||
BignumPointer::EncodePaddedInto(
|
||||
b, static_cast<unsigned char*>(bs->Data()), bs->ByteLength()));
|
||||
diff --git a/src/crypto/crypto_rsa.cc b/src/crypto/crypto_rsa.cc
|
||||
index 1f2fccce6ed8f14525557644e0bdd130eedf3337..1099a8f89bb53083f01942ee14fff453d8cdc0af 100644
|
||||
--- a/src/crypto/crypto_rsa.cc
|
||||
+++ b/src/crypto/crypto_rsa.cc
|
||||
@@ -20,6 +20,7 @@ using ncrypto::EVPKeyPointer;
|
||||
using ncrypto::RSAPointer;
|
||||
using v8::ArrayBuffer;
|
||||
using v8::BackingStore;
|
||||
+using v8::BackingStoreInitializationMode;
|
||||
using v8::FunctionCallbackInfo;
|
||||
using v8::Int32;
|
||||
using v8::JustVoid;
|
||||
@@ -535,12 +536,10 @@ Maybe<void> GetRsaKeyDetail(Environment* env,
|
||||
return Nothing<void>();
|
||||
}
|
||||
|
||||
- std::unique_ptr<BackingStore> public_exponent;
|
||||
- {
|
||||
- NoArrayBufferZeroFillScope no_zero_fill_scope(env->isolate_data());
|
||||
- public_exponent = ArrayBuffer::NewBackingStore(
|
||||
- env->isolate(), BignumPointer::GetByteCount(e));
|
||||
- }
|
||||
+ auto public_exponent = ArrayBuffer::NewBackingStore(
|
||||
+ env->isolate(),
|
||||
+ BignumPointer::GetByteCount(e),
|
||||
+ BackingStoreInitializationMode::kUninitialized);
|
||||
CHECK_EQ(BignumPointer::EncodePaddedInto(
|
||||
e,
|
||||
static_cast<unsigned char*>(public_exponent->Data()),
|
||||
diff --git a/src/crypto/crypto_sig.cc b/src/crypto/crypto_sig.cc
|
||||
index 2f6e683e3497d4315259773d09443e5215bff28f..c33e93c34ef32c18e6de6bc03698ed6b851b4aa3 100644
|
||||
--- a/src/crypto/crypto_sig.cc
|
||||
+++ b/src/crypto/crypto_sig.cc
|
||||
@@ -21,6 +21,7 @@ using ncrypto::EVPKeyPointer;
|
||||
using ncrypto::EVPMDCtxPointer;
|
||||
using v8::ArrayBuffer;
|
||||
using v8::BackingStore;
|
||||
+using v8::BackingStoreInitializationMode;
|
||||
using v8::Boolean;
|
||||
using v8::FunctionCallbackInfo;
|
||||
using v8::FunctionTemplate;
|
||||
@@ -92,11 +93,8 @@ std::unique_ptr<BackingStore> Node_SignFinal(Environment* env,
|
||||
return nullptr;
|
||||
|
||||
size_t sig_len = pkey.size();
|
||||
- std::unique_ptr<BackingStore> sig;
|
||||
- {
|
||||
- NoArrayBufferZeroFillScope no_zero_fill_scope(env->isolate_data());
|
||||
- sig = ArrayBuffer::NewBackingStore(env->isolate(), sig_len);
|
||||
- }
|
||||
+ auto sig = ArrayBuffer::NewBackingStore(
|
||||
+ env->isolate(), sig_len, BackingStoreInitializationMode::kUninitialized);
|
||||
EVPKeyCtxPointer pkctx = pkey.newCtx();
|
||||
if (pkctx && EVP_PKEY_sign_init(pkctx.get()) > 0 &&
|
||||
ApplyRSAOptions(pkey, pkctx.get(), padding, pss_salt_len) &&
|
||||
@@ -168,11 +166,9 @@ std::unique_ptr<BackingStore> ConvertSignatureToP1363(
|
||||
if (n == kNoDsaSignature)
|
||||
return std::move(signature);
|
||||
|
||||
- std::unique_ptr<BackingStore> buf;
|
||||
- {
|
||||
- NoArrayBufferZeroFillScope no_zero_fill_scope(env->isolate_data());
|
||||
- buf = ArrayBuffer::NewBackingStore(env->isolate(), 2 * n);
|
||||
- }
|
||||
+ auto buf = ArrayBuffer::NewBackingStore(
|
||||
+ env->isolate(), 2 * n, BackingStoreInitializationMode::kUninitialized);
|
||||
+
|
||||
if (!ExtractP1363(static_cast<unsigned char*>(signature->Data()),
|
||||
static_cast<unsigned char*>(buf->Data()),
|
||||
signature->ByteLength(), n))
|
||||
diff --git a/src/crypto/crypto_tls.cc b/src/crypto/crypto_tls.cc
|
||||
index a80685790bd29102d99929ff81f866e0aee370f1..24336b86f6f25533a7b668e9f9806a5635e3a398 100644
|
||||
--- a/src/crypto/crypto_tls.cc
|
||||
+++ b/src/crypto/crypto_tls.cc
|
||||
@@ -46,6 +46,7 @@ using v8::Array;
|
||||
using v8::ArrayBuffer;
|
||||
using v8::ArrayBufferView;
|
||||
using v8::BackingStore;
|
||||
+using v8::BackingStoreInitializationMode;
|
||||
using v8::Boolean;
|
||||
using v8::Context;
|
||||
using v8::DontDelete;
|
||||
@@ -1087,10 +1088,10 @@ int TLSWrap::DoWrite(WriteWrap* w,
|
||||
// and copying it when it could just be used.
|
||||
|
||||
if (nonempty_count != 1) {
|
||||
- {
|
||||
- NoArrayBufferZeroFillScope no_zero_fill_scope(env()->isolate_data());
|
||||
- bs = ArrayBuffer::NewBackingStore(env()->isolate(), length);
|
||||
- }
|
||||
+ bs = ArrayBuffer::NewBackingStore(
|
||||
+ env()->isolate(),
|
||||
+ length,
|
||||
+ BackingStoreInitializationMode::kUninitialized);
|
||||
size_t offset = 0;
|
||||
for (i = 0; i < count; i++) {
|
||||
memcpy(static_cast<char*>(bs->Data()) + offset,
|
||||
@@ -1107,8 +1108,10 @@ int TLSWrap::DoWrite(WriteWrap* w,
|
||||
written = SSL_write(ssl_.get(), buf->base, buf->len);
|
||||
|
||||
if (written == -1) {
|
||||
- NoArrayBufferZeroFillScope no_zero_fill_scope(env()->isolate_data());
|
||||
- bs = ArrayBuffer::NewBackingStore(env()->isolate(), length);
|
||||
+ bs = ArrayBuffer::NewBackingStore(
|
||||
+ env()->isolate(),
|
||||
+ length,
|
||||
+ BackingStoreInitializationMode::kUninitialized);
|
||||
memcpy(bs->Data(), buf->base, buf->len);
|
||||
}
|
||||
}
|
||||
@@ -1746,11 +1749,8 @@ void TLSWrap::GetFinished(const FunctionCallbackInfo<Value>& args) {
|
||||
if (len == 0)
|
||||
return;
|
||||
|
||||
- std::unique_ptr<BackingStore> bs;
|
||||
- {
|
||||
- NoArrayBufferZeroFillScope no_zero_fill_scope(env->isolate_data());
|
||||
- bs = ArrayBuffer::NewBackingStore(env->isolate(), len);
|
||||
- }
|
||||
+ auto bs = ArrayBuffer::NewBackingStore(
|
||||
+ env->isolate(), len, BackingStoreInitializationMode::kUninitialized);
|
||||
|
||||
CHECK_EQ(bs->ByteLength(),
|
||||
SSL_get_finished(w->ssl_.get(), bs->Data(), bs->ByteLength()));
|
||||
@@ -1777,11 +1777,8 @@ void TLSWrap::GetPeerFinished(const FunctionCallbackInfo<Value>& args) {
|
||||
if (len == 0)
|
||||
return;
|
||||
|
||||
- std::unique_ptr<BackingStore> bs;
|
||||
- {
|
||||
- NoArrayBufferZeroFillScope no_zero_fill_scope(env->isolate_data());
|
||||
- bs = ArrayBuffer::NewBackingStore(env->isolate(), len);
|
||||
- }
|
||||
+ auto bs = ArrayBuffer::NewBackingStore(
|
||||
+ env->isolate(), len, BackingStoreInitializationMode::kUninitialized);
|
||||
|
||||
CHECK_EQ(bs->ByteLength(),
|
||||
SSL_get_peer_finished(w->ssl_.get(), bs->Data(), bs->ByteLength()));
|
||||
@@ -1806,11 +1803,8 @@ void TLSWrap::GetSession(const FunctionCallbackInfo<Value>& args) {
|
||||
if (slen <= 0)
|
||||
return; // Invalid or malformed session.
|
||||
|
||||
- std::unique_ptr<BackingStore> bs;
|
||||
- {
|
||||
- NoArrayBufferZeroFillScope no_zero_fill_scope(env->isolate_data());
|
||||
- bs = ArrayBuffer::NewBackingStore(env->isolate(), slen);
|
||||
- }
|
||||
+ auto bs = ArrayBuffer::NewBackingStore(
|
||||
+ env->isolate(), slen, BackingStoreInitializationMode::kUninitialized);
|
||||
|
||||
unsigned char* p = static_cast<unsigned char*>(bs->Data());
|
||||
CHECK_LT(0, i2d_SSL_SESSION(sess, &p));
|
||||
@@ -1993,11 +1987,8 @@ void TLSWrap::ExportKeyingMaterial(const FunctionCallbackInfo<Value>& args) {
|
||||
uint32_t olen = args[0].As<Uint32>()->Value();
|
||||
Utf8Value label(env->isolate(), args[1]);
|
||||
|
||||
- std::unique_ptr<BackingStore> bs;
|
||||
- {
|
||||
- NoArrayBufferZeroFillScope no_zero_fill_scope(env->isolate_data());
|
||||
- bs = ArrayBuffer::NewBackingStore(env->isolate(), olen);
|
||||
- }
|
||||
+ auto bs = ArrayBuffer::NewBackingStore(
|
||||
+ env->isolate(), olen, BackingStoreInitializationMode::kUninitialized);
|
||||
|
||||
ByteSource context;
|
||||
bool use_context = !args[2]->IsUndefined();
|
||||
diff --git a/src/crypto/crypto_x509.cc b/src/crypto/crypto_x509.cc
|
||||
index fd29d17de195017970856ce30d7a9c5785b0b8ee..7fe3d09851d4476fa3f77ea0a0b49e8af13fae4f 100644
|
||||
--- a/src/crypto/crypto_x509.cc
|
||||
+++ b/src/crypto/crypto_x509.cc
|
||||
@@ -28,6 +28,7 @@ using v8::Array;
|
||||
using v8::ArrayBuffer;
|
||||
using v8::ArrayBufferView;
|
||||
using v8::BackingStore;
|
||||
+using v8::BackingStoreInitializationMode;
|
||||
using v8::Boolean;
|
||||
using v8::Context;
|
||||
using v8::Date;
|
||||
@@ -683,11 +684,8 @@ MaybeLocal<Object> GetPubKey(Environment* env, OSSL3_CONST RSA* rsa) {
|
||||
int size = i2d_RSA_PUBKEY(rsa, nullptr);
|
||||
CHECK_GE(size, 0);
|
||||
|
||||
- std::unique_ptr<BackingStore> bs;
|
||||
- {
|
||||
- NoArrayBufferZeroFillScope no_zero_fill_scope(env->isolate_data());
|
||||
- bs = ArrayBuffer::NewBackingStore(env->isolate(), size);
|
||||
- }
|
||||
+ auto bs = ArrayBuffer::NewBackingStore(
|
||||
+ env->isolate(), size, BackingStoreInitializationMode::kUninitialized);
|
||||
|
||||
unsigned char* serialized = reinterpret_cast<unsigned char*>(bs->Data());
|
||||
CHECK_GE(i2d_RSA_PUBKEY(rsa, &serialized), 0);
|
||||
diff --git a/src/encoding_binding.cc b/src/encoding_binding.cc
|
||||
index 5ace688bb7ffc86eedf5aff11ab0ab487ad9440e..31058543a164bb45ba989e8c433994e0857a98b9 100644
|
||||
--- a/src/encoding_binding.cc
|
||||
+++ b/src/encoding_binding.cc
|
||||
@@ -15,6 +15,7 @@ namespace encoding_binding {
|
||||
|
||||
using v8::ArrayBuffer;
|
||||
using v8::BackingStore;
|
||||
+using v8::BackingStoreInitializationMode;
|
||||
using v8::Context;
|
||||
using v8::FunctionCallbackInfo;
|
||||
using v8::Isolate;
|
||||
@@ -123,9 +124,8 @@ void BindingData::EncodeUtf8String(const FunctionCallbackInfo<Value>& args) {
|
||||
|
||||
Local<ArrayBuffer> ab;
|
||||
{
|
||||
- NoArrayBufferZeroFillScope no_zero_fill_scope(env->isolate_data());
|
||||
- std::unique_ptr<BackingStore> bs =
|
||||
- ArrayBuffer::NewBackingStore(isolate, length);
|
||||
+ std::unique_ptr<BackingStore> bs = ArrayBuffer::NewBackingStore(
|
||||
+ isolate, length, BackingStoreInitializationMode::kUninitialized);
|
||||
|
||||
CHECK(bs);
|
||||
|
||||
diff --git a/src/env-inl.h b/src/env-inl.h
|
||||
index 98e1e1e75bae94038bba0049447ab48b0acfb8cc..fe395bf89f9c1e5bb2dabc8fceda7b9b2b877415 100644
|
||||
--- a/src/env-inl.h
|
||||
+++ b/src/env-inl.h
|
||||
@@ -44,16 +44,6 @@
|
||||
|
||||
namespace node {
|
||||
|
||||
-NoArrayBufferZeroFillScope::NoArrayBufferZeroFillScope(
|
||||
- IsolateData* isolate_data)
|
||||
- : node_allocator_(isolate_data->node_allocator()) {
|
||||
- if (node_allocator_ != nullptr) node_allocator_->zero_fill_field()[0] = 0;
|
||||
-}
|
||||
-
|
||||
-NoArrayBufferZeroFillScope::~NoArrayBufferZeroFillScope() {
|
||||
- if (node_allocator_ != nullptr) node_allocator_->zero_fill_field()[0] = 1;
|
||||
-}
|
||||
-
|
||||
inline v8::Isolate* IsolateData::isolate() const {
|
||||
return isolate_;
|
||||
}
|
||||
diff --git a/src/env.cc b/src/env.cc
|
||||
index 161d577e0ea6a251c83ba1903b1ec9a582a5317c..52713421465c23c959afac1955168294b2048341 100644
|
||||
--- a/src/env.cc
|
||||
+++ b/src/env.cc
|
||||
@@ -39,6 +39,9 @@ namespace node {
|
||||
|
||||
using errors::TryCatchScope;
|
||||
using v8::Array;
|
||||
+using v8::ArrayBuffer;
|
||||
+using v8::BackingStore;
|
||||
+using v8::BackingStoreInitializationMode;
|
||||
using v8::Boolean;
|
||||
using v8::Context;
|
||||
using v8::CppHeap;
|
||||
@@ -724,9 +727,10 @@ void Environment::add_refs(int64_t diff) {
|
||||
}
|
||||
|
||||
uv_buf_t Environment::allocate_managed_buffer(const size_t suggested_size) {
|
||||
- NoArrayBufferZeroFillScope no_zero_fill_scope(isolate_data());
|
||||
- std::unique_ptr<v8::BackingStore> bs =
|
||||
- v8::ArrayBuffer::NewBackingStore(isolate(), suggested_size);
|
||||
+ std::unique_ptr<BackingStore> bs = ArrayBuffer::NewBackingStore(
|
||||
+ isolate(),
|
||||
+ suggested_size,
|
||||
+ BackingStoreInitializationMode::kUninitialized);
|
||||
uv_buf_t buf = uv_buf_init(static_cast<char*>(bs->Data()), bs->ByteLength());
|
||||
released_allocated_buffers_.emplace(buf.base, std::move(bs));
|
||||
return buf;
|
||||
diff --git a/src/env.h b/src/env.h
|
||||
index c346e3a9c827993036438685d758a734f9ce8c05..28c8df87c8e2f06e2ed8c554260bfdedb860bb4a 100644
|
||||
--- a/src/env.h
|
||||
+++ b/src/env.h
|
||||
@@ -114,19 +114,6 @@ class ModuleWrap;
|
||||
class Environment;
|
||||
class Realm;
|
||||
|
||||
-// Disables zero-filling for ArrayBuffer allocations in this scope. This is
|
||||
-// similar to how we implement Buffer.allocUnsafe() in JS land.
|
||||
-class NoArrayBufferZeroFillScope {
|
||||
- public:
|
||||
- inline explicit NoArrayBufferZeroFillScope(IsolateData* isolate_data);
|
||||
- inline ~NoArrayBufferZeroFillScope();
|
||||
-
|
||||
- private:
|
||||
- NodeArrayBufferAllocator* node_allocator_;
|
||||
-
|
||||
- friend class Environment;
|
||||
-};
|
||||
-
|
||||
struct IsolateDataSerializeInfo {
|
||||
std::vector<SnapshotIndex> primitive_values;
|
||||
std::vector<PropInfo> template_values;
|
||||
diff --git a/src/node_buffer.cc b/src/node_buffer.cc
|
||||
index e844fe6cb33acefd075516e675075421ad5c3cff..06c84eb6ec097e3cb39502116135a7802aed13ce 100644
|
||||
--- a/src/node_buffer.cc
|
||||
+++ b/src/node_buffer.cc
|
||||
@@ -66,6 +66,7 @@ namespace Buffer {
|
||||
using v8::ArrayBuffer;
|
||||
using v8::ArrayBufferView;
|
||||
using v8::BackingStore;
|
||||
+using v8::BackingStoreInitializationMode;
|
||||
using v8::Context;
|
||||
using v8::EscapableHandleScope;
|
||||
using v8::FunctionCallbackInfo;
|
||||
@@ -376,9 +377,8 @@ MaybeLocal<Object> New(Environment* env, size_t length) {
|
||||
|
||||
Local<ArrayBuffer> ab;
|
||||
{
|
||||
- NoArrayBufferZeroFillScope no_zero_fill_scope(env->isolate_data());
|
||||
- std::unique_ptr<BackingStore> bs =
|
||||
- ArrayBuffer::NewBackingStore(isolate, length);
|
||||
+ std::unique_ptr<BackingStore> bs = ArrayBuffer::NewBackingStore(
|
||||
+ isolate, length, BackingStoreInitializationMode::kUninitialized);
|
||||
|
||||
CHECK(bs);
|
||||
|
||||
@@ -417,18 +417,14 @@ MaybeLocal<Object> Copy(Environment* env, const char* data, size_t length) {
|
||||
return Local<Object>();
|
||||
}
|
||||
|
||||
- Local<ArrayBuffer> ab;
|
||||
- {
|
||||
- NoArrayBufferZeroFillScope no_zero_fill_scope(env->isolate_data());
|
||||
- std::unique_ptr<BackingStore> bs =
|
||||
- ArrayBuffer::NewBackingStore(isolate, length);
|
||||
+ std::unique_ptr<BackingStore> bs = ArrayBuffer::NewBackingStore(
|
||||
+ isolate, length, BackingStoreInitializationMode::kUninitialized);
|
||||
|
||||
- CHECK(bs);
|
||||
+ CHECK(bs);
|
||||
|
||||
- memcpy(bs->Data(), data, length);
|
||||
+ memcpy(bs->Data(), data, length);
|
||||
|
||||
- ab = ArrayBuffer::New(isolate, std::move(bs));
|
||||
- }
|
||||
+ Local<ArrayBuffer> ab = ArrayBuffer::New(isolate, std::move(bs));
|
||||
|
||||
MaybeLocal<Object> obj =
|
||||
New(env, ab, 0, ab->ByteLength())
|
||||
@@ -1440,14 +1436,16 @@ void CreateUnsafeArrayBuffer(const FunctionCallbackInfo<Value>& args) {
|
||||
|
||||
Local<ArrayBuffer> buf;
|
||||
|
||||
- NodeArrayBufferAllocator* allocator = env->isolate_data()->node_allocator();
|
||||
// 0-length, or zero-fill flag is set, or building snapshot
|
||||
if (size == 0 || per_process::cli_options->zero_fill_all_buffers ||
|
||||
- allocator == nullptr) {
|
||||
+ env->isolate_data()->is_building_snapshot()) {
|
||||
buf = ArrayBuffer::New(isolate, size);
|
||||
} else {
|
||||
- std::unique_ptr<BackingStore> store =
|
||||
- ArrayBuffer::NewBackingStore(isolate, size);
|
||||
+ std::unique_ptr<BackingStore> store = ArrayBuffer::NewBackingStore(
|
||||
+ isolate,
|
||||
+ size,
|
||||
+ BackingStoreInitializationMode::kUninitialized,
|
||||
+ v8::BackingStoreOnFailureMode::kReturnNull);
|
||||
if (!store) {
|
||||
return env->ThrowRangeError("Array buffer allocation failed");
|
||||
}
|
||||
diff --git a/src/node_http2.cc b/src/node_http2.cc
|
||||
index 8237c9b7d325dd925ae8798d7795fcd94eeb13d0..a22cf6c4e33e5cf2d3168ce03dc35af8a9584af7 100644
|
||||
--- a/src/node_http2.cc
|
||||
+++ b/src/node_http2.cc
|
||||
@@ -27,6 +27,7 @@ using v8::Array;
|
||||
using v8::ArrayBuffer;
|
||||
using v8::ArrayBufferView;
|
||||
using v8::BackingStore;
|
||||
+using v8::BackingStoreInitializationMode;
|
||||
using v8::Boolean;
|
||||
using v8::Context;
|
||||
using v8::EscapableHandleScope;
|
||||
@@ -298,11 +299,10 @@ Local<Value> Http2Settings::Pack(
|
||||
size_t count,
|
||||
const nghttp2_settings_entry* entries) {
|
||||
EscapableHandleScope scope(env->isolate());
|
||||
- std::unique_ptr<BackingStore> bs;
|
||||
- {
|
||||
- NoArrayBufferZeroFillScope no_zero_fill_scope(env->isolate_data());
|
||||
- bs = ArrayBuffer::NewBackingStore(env->isolate(), count * 6);
|
||||
- }
|
||||
+ std::unique_ptr<BackingStore> bs = ArrayBuffer::NewBackingStore(
|
||||
+ env->isolate(),
|
||||
+ count * 6,
|
||||
+ BackingStoreInitializationMode::kUninitialized);
|
||||
if (nghttp2_pack_settings_payload(static_cast<uint8_t*>(bs->Data()),
|
||||
bs->ByteLength(),
|
||||
entries,
|
||||
@@ -468,13 +468,11 @@ Origins::Origins(
|
||||
return;
|
||||
}
|
||||
|
||||
- {
|
||||
- NoArrayBufferZeroFillScope no_zero_fill_scope(env->isolate_data());
|
||||
- bs_ = ArrayBuffer::NewBackingStore(env->isolate(),
|
||||
- alignof(nghttp2_origin_entry) - 1 +
|
||||
- count_ * sizeof(nghttp2_origin_entry) +
|
||||
- origin_string_len);
|
||||
- }
|
||||
+ bs_ = ArrayBuffer::NewBackingStore(
|
||||
+ env->isolate(),
|
||||
+ alignof(nghttp2_origin_entry) - 1 +
|
||||
+ count_ * sizeof(nghttp2_origin_entry) + origin_string_len,
|
||||
+ BackingStoreInitializationMode::kUninitialized);
|
||||
|
||||
// Make sure the start address is aligned appropriately for an nghttp2_nv*.
|
||||
char* start = nbytes::AlignUp(static_cast<char*>(bs_->Data()),
|
||||
@@ -2120,12 +2118,10 @@ void Http2Session::OnStreamRead(ssize_t nread, const uv_buf_t& buf_) {
|
||||
// happen, we concatenate the data we received with the already-stored
|
||||
// pending input data, slicing off the already processed part.
|
||||
size_t pending_len = stream_buf_.len - stream_buf_offset_;
|
||||
- std::unique_ptr<BackingStore> new_bs;
|
||||
- {
|
||||
- NoArrayBufferZeroFillScope no_zero_fill_scope(env()->isolate_data());
|
||||
- new_bs = ArrayBuffer::NewBackingStore(env()->isolate(),
|
||||
- pending_len + nread);
|
||||
- }
|
||||
+ std::unique_ptr<BackingStore> new_bs = ArrayBuffer::NewBackingStore(
|
||||
+ env()->isolate(),
|
||||
+ pending_len + nread,
|
||||
+ BackingStoreInitializationMode::kUninitialized);
|
||||
memcpy(static_cast<char*>(new_bs->Data()),
|
||||
stream_buf_.base + stream_buf_offset_,
|
||||
pending_len);
|
||||
diff --git a/src/node_internals.h b/src/node_internals.h
|
||||
index 12ea72b61b0a5e194207bb369dfed4b8667107cb..18844e18a32d6b07e62481138fa2342765643484 100644
|
||||
--- a/src/node_internals.h
|
||||
+++ b/src/node_internals.h
|
||||
@@ -121,8 +121,6 @@ v8::MaybeLocal<v8::Object> InitializePrivateSymbols(
|
||||
|
||||
class NodeArrayBufferAllocator : public ArrayBufferAllocator {
|
||||
public:
|
||||
- inline uint32_t* zero_fill_field() { return &zero_fill_field_; }
|
||||
-
|
||||
void* Allocate(size_t size) override; // Defined in src/node.cc
|
||||
void* AllocateUninitialized(size_t size) override;
|
||||
void Free(void* data, size_t size) override;
|
||||
@@ -139,7 +137,6 @@ class NodeArrayBufferAllocator : public ArrayBufferAllocator {
|
||||
}
|
||||
|
||||
private:
|
||||
- uint32_t zero_fill_field_ = 1; // Boolean but exposed as uint32 to JS land.
|
||||
std::atomic<size_t> total_mem_usage_ {0};
|
||||
|
||||
// Delegate to V8's allocator for compatibility with the V8 memory cage.
|
||||
diff --git a/src/stream_base.cc b/src/stream_base.cc
|
||||
index fc81108120f0066f2d5dabedc74e22cb6c84d8e4..0bf2642599ee91e2d2aa20d6d066c80b3026ecc5 100644
|
||||
--- a/src/stream_base.cc
|
||||
+++ b/src/stream_base.cc
|
||||
@@ -19,6 +19,7 @@ namespace node {
|
||||
using v8::Array;
|
||||
using v8::ArrayBuffer;
|
||||
using v8::BackingStore;
|
||||
+using v8::BackingStoreInitializationMode;
|
||||
using v8::ConstructorBehavior;
|
||||
using v8::Context;
|
||||
using v8::DontDelete;
|
||||
@@ -243,8 +244,8 @@ int StreamBase::Writev(const FunctionCallbackInfo<Value>& args) {
|
||||
|
||||
std::unique_ptr<BackingStore> bs;
|
||||
if (storage_size > 0) {
|
||||
- NoArrayBufferZeroFillScope no_zero_fill_scope(env->isolate_data());
|
||||
- bs = ArrayBuffer::NewBackingStore(isolate, storage_size);
|
||||
+ bs = ArrayBuffer::NewBackingStore(
|
||||
+ isolate, storage_size, BackingStoreInitializationMode::kUninitialized);
|
||||
}
|
||||
|
||||
offset = 0;
|
||||
@@ -398,14 +399,14 @@ int StreamBase::WriteString(const FunctionCallbackInfo<Value>& args) {
|
||||
|
||||
if (try_write) {
|
||||
// Copy partial data
|
||||
- NoArrayBufferZeroFillScope no_zero_fill_scope(env->isolate_data());
|
||||
- bs = ArrayBuffer::NewBackingStore(isolate, buf.len);
|
||||
+ bs = ArrayBuffer::NewBackingStore(
|
||||
+ isolate, buf.len, BackingStoreInitializationMode::kUninitialized);
|
||||
memcpy(bs->Data(), buf.base, buf.len);
|
||||
data_size = buf.len;
|
||||
} else {
|
||||
// Write it
|
||||
- NoArrayBufferZeroFillScope no_zero_fill_scope(env->isolate_data());
|
||||
- bs = ArrayBuffer::NewBackingStore(isolate, storage_size);
|
||||
+ bs = ArrayBuffer::NewBackingStore(
|
||||
+ isolate, storage_size, BackingStoreInitializationMode::kUninitialized);
|
||||
data_size = StringBytes::Write(isolate,
|
||||
static_cast<char*>(bs->Data()),
|
||||
storage_size,
|
||||
@@ -0,0 +1,74 @@
|
||||
From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001
|
||||
From: Joyee Cheung <joyeec9h3@gmail.com>
|
||||
Date: Thu, 20 Nov 2025 13:50:28 +0900
|
||||
Subject: src: handle DER decoding errors from system certificates
|
||||
|
||||
When decoding certificates from the system store, it's not actually
|
||||
guaranteed to succeed. In case the system returns a certificate
|
||||
that cannot be decoded (might be related to SSL implementation issues),
|
||||
skip them.
|
||||
|
||||
diff --git a/src/crypto/crypto_context.cc b/src/crypto/crypto_context.cc
|
||||
index 0c6b12f8e17b4a7e86ebc836a4e1cc77333f211a..dacf10c3c2e663b03a251c86d69276d0be0dff9d 100644
|
||||
--- a/src/crypto/crypto_context.cc
|
||||
+++ b/src/crypto/crypto_context.cc
|
||||
@@ -505,7 +505,11 @@ void ReadMacOSKeychainCertificates(
|
||||
CFRelease(search);
|
||||
|
||||
if (ortn) {
|
||||
- fprintf(stderr, "ERROR: SecItemCopyMatching failed %d\n", ortn);
|
||||
+ per_process::Debug(DebugCategory::CRYPTO,
|
||||
+ "Cannot read certificates from system because "
|
||||
+ "SecItemCopyMatching failed %d\n",
|
||||
+ ortn);
|
||||
+ return;
|
||||
}
|
||||
|
||||
CFIndex count = CFArrayGetCount(curr_anchors);
|
||||
@@ -516,7 +520,9 @@ void ReadMacOSKeychainCertificates(
|
||||
|
||||
CFDataRef der_data = SecCertificateCopyData(cert_ref);
|
||||
if (!der_data) {
|
||||
- fprintf(stderr, "ERROR: SecCertificateCopyData failed\n");
|
||||
+ per_process::Debug(DebugCategory::CRYPTO,
|
||||
+ "Skipping read of a system certificate "
|
||||
+ "because SecCertificateCopyData failed\n");
|
||||
continue;
|
||||
}
|
||||
auto data_buffer_pointer = CFDataGetBytePtr(der_data);
|
||||
@@ -524,9 +530,19 @@ void ReadMacOSKeychainCertificates(
|
||||
X509* cert =
|
||||
d2i_X509(nullptr, &data_buffer_pointer, CFDataGetLength(der_data));
|
||||
CFRelease(der_data);
|
||||
+
|
||||
+ if (cert == nullptr) {
|
||||
+ per_process::Debug(DebugCategory::CRYPTO,
|
||||
+ "Skipping read of a system certificate "
|
||||
+ "because decoding failed\n");
|
||||
+ continue;
|
||||
+ }
|
||||
+
|
||||
bool is_valid = IsCertificateTrustedForPolicy(cert, cert_ref);
|
||||
if (is_valid) {
|
||||
system_root_certificates_X509->emplace_back(cert);
|
||||
+ } else {
|
||||
+ X509_free(cert);
|
||||
}
|
||||
}
|
||||
CFRelease(curr_anchors);
|
||||
@@ -636,7 +652,14 @@ void GatherCertsForLocation(std::vector<X509*>* vector,
|
||||
reinterpret_cast<const unsigned char*>(cert_from_store->pbCertEncoded);
|
||||
const size_t cert_size = cert_from_store->cbCertEncoded;
|
||||
|
||||
- vector->emplace_back(d2i_X509(nullptr, &cert_data, cert_size));
|
||||
+ X509* x509 = d2i_X509(nullptr, &cert_data, cert_size);
|
||||
+ if (x509 == nullptr) {
|
||||
+ per_process::Debug(DebugCategory::CRYPTO,
|
||||
+ "Skipping read of a system certificate "
|
||||
+ "because decoding failed\n");
|
||||
+ } else {
|
||||
+ vector->emplace_back(x509);
|
||||
+ }
|
||||
}
|
||||
}
|
||||
|
||||
276
patches/node/src_prepare_for_v8_sandboxing.patch
Normal file
276
patches/node/src_prepare_for_v8_sandboxing.patch
Normal file
@@ -0,0 +1,276 @@
|
||||
From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001
|
||||
From: James M Snell <jasnell@gmail.com>
|
||||
Date: Sun, 18 May 2025 10:46:30 -0700
|
||||
Subject: src: prepare for v8 sandboxing
|
||||
|
||||
PR-URL: https://github.com/nodejs/node/pull/58376
|
||||
Reviewed-By: Yagiz Nizipli <yagiz@nizipli.com>
|
||||
Reviewed-By: Chengzhong Wu <legendecas@gmail.com>
|
||||
|
||||
diff --git a/src/crypto/crypto_dh.cc b/src/crypto/crypto_dh.cc
|
||||
index f23cedf4f2449d8edc9a8de1b70332e75d693cdd..5ac2b1a83688fe99b13c37bf375ca6e22497dc18 100644
|
||||
--- a/src/crypto/crypto_dh.cc
|
||||
+++ b/src/crypto/crypto_dh.cc
|
||||
@@ -22,6 +22,8 @@ using ncrypto::DHPointer;
|
||||
using ncrypto::EVPKeyCtxPointer;
|
||||
using ncrypto::EVPKeyPointer;
|
||||
using v8::ArrayBuffer;
|
||||
+using v8::BackingStoreInitializationMode;
|
||||
+using v8::BackingStoreOnFailureMode;
|
||||
using v8::ConstructorBehavior;
|
||||
using v8::Context;
|
||||
using v8::DontDelete;
|
||||
@@ -55,12 +57,27 @@ void DiffieHellman::MemoryInfo(MemoryTracker* tracker) const {
|
||||
|
||||
namespace {
|
||||
MaybeLocal<Value> DataPointerToBuffer(Environment* env, DataPointer&& data) {
|
||||
+#ifdef V8_ENABLE_SANDBOX
|
||||
+ auto backing = ArrayBuffer::NewBackingStore(
|
||||
+ env->isolate(),
|
||||
+ data.size(),
|
||||
+ BackingStoreInitializationMode::kUninitialized,
|
||||
+ BackingStoreOnFailureMode::kReturnNull);
|
||||
+ if (!backing) {
|
||||
+ THROW_ERR_MEMORY_ALLOCATION_FAILED(env);
|
||||
+ return MaybeLocal<Value>();
|
||||
+ }
|
||||
+ if (data.size() > 0) {
|
||||
+ memcpy(backing->Data(), data.get(), data.size());
|
||||
+ }
|
||||
+#else
|
||||
auto backing = ArrayBuffer::NewBackingStore(
|
||||
data.get(),
|
||||
data.size(),
|
||||
[](void* data, size_t len, void* ptr) { DataPointer free_me(data, len); },
|
||||
nullptr);
|
||||
data.release();
|
||||
+#endif // V8_ENABLE_SANDBOX
|
||||
|
||||
auto ab = ArrayBuffer::New(env->isolate(), std::move(backing));
|
||||
return Buffer::New(env, ab, 0, ab->ByteLength()).FromMaybe(Local<Value>());
|
||||
diff --git a/src/crypto/crypto_util.cc b/src/crypto/crypto_util.cc
|
||||
index eab18ab9888e2f7c0757fefab80505d8c99dc742..7ecf810ea0f4106c7c44593dae1b0a3cf0673380 100644
|
||||
--- a/src/crypto/crypto_util.cc
|
||||
+++ b/src/crypto/crypto_util.cc
|
||||
@@ -37,6 +37,8 @@ using ncrypto::SSLCtxPointer;
|
||||
using ncrypto::SSLPointer;
|
||||
using v8::ArrayBuffer;
|
||||
using v8::BackingStore;
|
||||
+using v8::BackingStoreInitializationMode;
|
||||
+using v8::BackingStoreOnFailureMode;
|
||||
using v8::BigInt;
|
||||
using v8::Context;
|
||||
using v8::Exception;
|
||||
@@ -359,34 +361,29 @@ ByteSource& ByteSource::operator=(ByteSource&& other) noexcept {
|
||||
return *this;
|
||||
}
|
||||
|
||||
-std::unique_ptr<BackingStore> ByteSource::ReleaseToBackingStore(Environment* env) {
|
||||
+std::unique_ptr<BackingStore> ByteSource::ReleaseToBackingStore(
|
||||
+ Environment* env) {
|
||||
// It's ok for allocated_data_ to be nullptr but
|
||||
// only if size_ is zero.
|
||||
CHECK_IMPLIES(size_ > 0, allocated_data_ != nullptr);
|
||||
-#if defined(V8_ENABLE_SANDBOX)
|
||||
- // When V8 sandboxed pointers are enabled, we have to copy into the memory
|
||||
- // cage. We still want to ensure we erase the data on free though, so
|
||||
- // provide a custom deleter that calls OPENSSL_cleanse.
|
||||
- if (!size())
|
||||
- return ArrayBuffer::NewBackingStore(env->isolate(), 0);
|
||||
- std::unique_ptr<ArrayBuffer::Allocator> allocator(ArrayBuffer::Allocator::NewDefaultAllocator());
|
||||
- void* v8_data = allocator->Allocate(size());
|
||||
- CHECK(v8_data);
|
||||
- memcpy(v8_data, allocated_data_, size());
|
||||
- OPENSSL_clear_free(allocated_data_, size());
|
||||
+#ifdef V8_ENABLE_SANDBOX
|
||||
+ // If the v8 sandbox is enabled, then all array buffers must be allocated
|
||||
+ // via the isolate. External buffers are not allowed. So, instead of wrapping
|
||||
+ // the allocated data we'll copy it instead.
|
||||
+
|
||||
+ // TODO(@jasnell): It would be nice to use an abstracted utility to do this
|
||||
+ // branch instead of duplicating the V8_ENABLE_SANDBOX check each time.
|
||||
std::unique_ptr<BackingStore> ptr = ArrayBuffer::NewBackingStore(
|
||||
- v8_data,
|
||||
+ env->isolate(),
|
||||
size(),
|
||||
- [](void* data, size_t length, void*) {
|
||||
- OPENSSL_cleanse(data, length);
|
||||
- std::unique_ptr<ArrayBuffer::Allocator> allocator(ArrayBuffer::Allocator::NewDefaultAllocator());
|
||||
- allocator->Free(data, length);
|
||||
- }, nullptr);
|
||||
- CHECK(ptr);
|
||||
- allocated_data_ = nullptr;
|
||||
- data_ = nullptr;
|
||||
- size_ = 0;
|
||||
- return ptr;
|
||||
+ BackingStoreInitializationMode::kUninitialized,
|
||||
+ BackingStoreOnFailureMode::kReturnNull);
|
||||
+ if (!ptr) {
|
||||
+ THROW_ERR_MEMORY_ALLOCATION_FAILED(env);
|
||||
+ return nullptr;
|
||||
+ }
|
||||
+ memcpy(ptr->Data(), allocated_data_, size());
|
||||
+ OPENSSL_clear_free(allocated_data_, size_);
|
||||
#else
|
||||
std::unique_ptr<BackingStore> ptr = ArrayBuffer::NewBackingStore(
|
||||
allocated_data_,
|
||||
@@ -394,12 +391,12 @@ std::unique_ptr<BackingStore> ByteSource::ReleaseToBackingStore(Environment* env
|
||||
[](void* data, size_t length, void* deleter_data) {
|
||||
OPENSSL_clear_free(deleter_data, length);
|
||||
}, allocated_data_);
|
||||
+#endif // V8_ENABLE_SANDBOX
|
||||
CHECK(ptr);
|
||||
allocated_data_ = nullptr;
|
||||
data_ = nullptr;
|
||||
size_ = 0;
|
||||
return ptr;
|
||||
-#endif // defined(V8_ENABLE_SANDBOX)
|
||||
}
|
||||
|
||||
Local<ArrayBuffer> ByteSource::ToArrayBuffer(Environment* env) {
|
||||
@@ -711,8 +708,19 @@ void SecureBuffer(const FunctionCallbackInfo<Value>& args) {
|
||||
}
|
||||
#else
|
||||
void SecureBuffer(const FunctionCallbackInfo<Value>& args) {
|
||||
- CHECK(args[0]->IsUint32());
|
||||
Environment* env = Environment::GetCurrent(args);
|
||||
+#ifdef V8_ENABLE_SANDBOX
|
||||
+ // The v8 sandbox is enabled, so we cannot use the secure heap because
|
||||
+ // the sandbox requires that all array buffers be allocated via the isolate.
|
||||
+ // That is fundamentally incompatible with the secure heap which allocates
|
||||
+ // in openssl's secure heap area. Instead we'll just throw an error here.
|
||||
+ //
|
||||
+ // That said, we really shouldn't get here in the first place since the
|
||||
+ // option to enable the secure heap is only available when the sandbox
|
||||
+ // is disabled.
|
||||
+ UNREACHABLE();
|
||||
+#else
|
||||
+ CHECK(args[0]->IsUint32());
|
||||
uint32_t len = args[0].As<Uint32>()->Value();
|
||||
void* data = OPENSSL_malloc(len);
|
||||
if (data == nullptr) {
|
||||
@@ -730,6 +738,7 @@ void SecureBuffer(const FunctionCallbackInfo<Value>& args) {
|
||||
data);
|
||||
Local<ArrayBuffer> buffer = ArrayBuffer::New(env->isolate(), store);
|
||||
args.GetReturnValue().Set(Uint8Array::New(buffer, 0, len));
|
||||
+#endif // V8_ENABLE_SANDBOX
|
||||
}
|
||||
#endif // defined(V8_ENABLE_SANDBOX)
|
||||
|
||||
diff --git a/src/crypto/crypto_x509.cc b/src/crypto/crypto_x509.cc
|
||||
index 7fe3d09851d4476fa3f77ea0a0b49e8af13fae4f..b60ad6b1cdb0b923ba2de1b7205ed5ce07612b81 100644
|
||||
--- a/src/crypto/crypto_x509.cc
|
||||
+++ b/src/crypto/crypto_x509.cc
|
||||
@@ -29,6 +29,7 @@ using v8::ArrayBuffer;
|
||||
using v8::ArrayBufferView;
|
||||
using v8::BackingStore;
|
||||
using v8::BackingStoreInitializationMode;
|
||||
+using v8::BackingStoreOnFailureMode;
|
||||
using v8::Boolean;
|
||||
using v8::Context;
|
||||
using v8::Date;
|
||||
@@ -168,18 +169,20 @@ MaybeLocal<Value> ToV8Value(Local<Context> context, const BIOPointer& bio) {
|
||||
MaybeLocal<Value> ToBuffer(Environment* env, BIOPointer* bio) {
|
||||
if (bio == nullptr || !*bio) return {};
|
||||
BUF_MEM* mem = *bio;
|
||||
-#if defined(V8_ENABLE_SANDBOX)
|
||||
- std::unique_ptr<ArrayBuffer::Allocator> allocator(ArrayBuffer::Allocator::NewDefaultAllocator());
|
||||
- void* v8_data = allocator->Allocate(mem->length);
|
||||
- CHECK(v8_data);
|
||||
- memcpy(v8_data, mem->data, mem->length);
|
||||
- std::unique_ptr<v8::BackingStore> backing = ArrayBuffer::NewBackingStore(
|
||||
- v8_data,
|
||||
+#ifdef V8_ENABLE_SANDBOX
|
||||
+ // If the v8 sandbox is enabled, then all array buffers must be allocated
|
||||
+ // via the isolate. External buffers are not allowed. So, instead of wrapping
|
||||
+ // the BIOPointer we'll copy it instead.
|
||||
+ auto backing = ArrayBuffer::NewBackingStore(
|
||||
+ env->isolate(),
|
||||
mem->length,
|
||||
- [](void* data, size_t length, void*) {
|
||||
- std::unique_ptr<ArrayBuffer::Allocator> allocator(ArrayBuffer::Allocator::NewDefaultAllocator());
|
||||
- allocator->Free(data, length);
|
||||
- }, nullptr);
|
||||
+ BackingStoreInitializationMode::kUninitialized,
|
||||
+ BackingStoreOnFailureMode::kReturnNull);
|
||||
+ if (!backing) {
|
||||
+ THROW_ERR_MEMORY_ALLOCATION_FAILED(env);
|
||||
+ return MaybeLocal<Value>();
|
||||
+ }
|
||||
+ memcpy(backing->Data(), mem->data, mem->length);
|
||||
#else
|
||||
auto backing = ArrayBuffer::NewBackingStore(
|
||||
mem->data,
|
||||
@@ -188,8 +191,7 @@ MaybeLocal<Value> ToBuffer(Environment* env, BIOPointer* bio) {
|
||||
BIOPointer free_me(static_cast<BIO*>(data));
|
||||
},
|
||||
bio->release());
|
||||
-#endif
|
||||
-
|
||||
+#endif // V8_ENABLE_SANDBOX
|
||||
auto ab = ArrayBuffer::New(env->isolate(), std::move(backing));
|
||||
Local<Value> ret;
|
||||
if (!Buffer::New(env, ab, 0, ab->ByteLength()).ToLocal(&ret)) return {};
|
||||
diff --git a/src/js_native_api_v8.cc b/src/js_native_api_v8.cc
|
||||
index 413db3ed9b88d7b7fb2ac6dd1153dade9ff830fd..6da93b8569a34841e846c320ec0a6ca7f1ea0da6 100644
|
||||
--- a/src/js_native_api_v8.cc
|
||||
+++ b/src/js_native_api_v8.cc
|
||||
@@ -114,7 +114,7 @@ napi_status NewExternalString(napi_env env,
|
||||
CHECK_NEW_STRING_ARGS(env, str, length, result);
|
||||
|
||||
napi_status status;
|
||||
-#if defined(V8_ENABLE_SANDBOX)
|
||||
+#ifdef V8_ENABLE_SANDBOX
|
||||
status = create_api(env, str, length, result);
|
||||
if (status == napi_ok) {
|
||||
if (copied != nullptr) {
|
||||
diff --git a/src/node_api.cc b/src/node_api.cc
|
||||
index 2769997f0ede0e921fcb8826942609e497e5f9cb..d9b17780f6143f1c3f8488a20144376963e43fbc 100644
|
||||
--- a/src/node_api.cc
|
||||
+++ b/src/node_api.cc
|
||||
@@ -1056,7 +1056,7 @@ napi_create_external_buffer(napi_env env,
|
||||
NAPI_PREAMBLE(env);
|
||||
CHECK_ARG(env, result);
|
||||
|
||||
-#if defined(V8_ENABLE_SANDBOX)
|
||||
+#ifdef V8_ENABLE_SANDBOX
|
||||
return napi_set_last_error(env, napi_no_external_buffers_allowed);
|
||||
#else
|
||||
v8::Isolate* isolate = env->isolate;
|
||||
diff --git a/src/node_options.cc b/src/node_options.cc
|
||||
index e93e8684e518b30a2514768a269be6d32d1f5b94..547cda780376f578b0f78eb9158dc14a3faf874d 100644
|
||||
--- a/src/node_options.cc
|
||||
+++ b/src/node_options.cc
|
||||
@@ -83,6 +83,8 @@ void PerProcessOptions::CheckOptions(std::vector<std::string>* errors,
|
||||
}
|
||||
|
||||
// Any value less than 2 disables use of the secure heap.
|
||||
+#ifndef V8_ENABLE_SANDBOX
|
||||
+ // The secure heap is not supported when V8_ENABLE_SANDBOX is enabled.
|
||||
if (secure_heap >= 2) {
|
||||
if ((secure_heap & (secure_heap - 1)) != 0)
|
||||
errors->push_back("--secure-heap must be a power of 2");
|
||||
@@ -95,6 +97,7 @@ void PerProcessOptions::CheckOptions(std::vector<std::string>* errors,
|
||||
if ((secure_heap_min & (secure_heap_min - 1)) != 0)
|
||||
errors->push_back("--secure-heap-min must be a power of 2");
|
||||
}
|
||||
+#endif // V8_ENABLE_SANDBOX
|
||||
#endif // HAVE_OPENSSL
|
||||
|
||||
if (use_largepages != "off" &&
|
||||
@@ -1243,6 +1246,7 @@ PerProcessOptionsParser::PerProcessOptionsParser(
|
||||
"force FIPS crypto (cannot be disabled)",
|
||||
&PerProcessOptions::force_fips_crypto,
|
||||
kAllowedInEnvvar);
|
||||
+#ifndef V8_ENABLE_SANDBOX
|
||||
AddOption("--secure-heap",
|
||||
"total size of the OpenSSL secure heap",
|
||||
&PerProcessOptions::secure_heap,
|
||||
@@ -1251,6 +1255,7 @@ PerProcessOptionsParser::PerProcessOptionsParser(
|
||||
"minimum allocation size from the OpenSSL secure heap",
|
||||
&PerProcessOptions::secure_heap_min,
|
||||
kAllowedInEnvvar);
|
||||
+#endif // V8_ENABLE_SANDBOX
|
||||
#endif // HAVE_OPENSSL
|
||||
#if OPENSSL_VERSION_MAJOR >= 3
|
||||
AddOption("--openssl-legacy-provider",
|
||||
@@ -10,10 +10,10 @@ Reviewed-By: Moshe Atlow <moshe@atlow.co.il>
|
||||
Reviewed-By: James M Snell <jasnell@gmail.com>
|
||||
|
||||
diff --git a/src/api/environment.cc b/src/api/environment.cc
|
||||
index 82f53bba29613de212f64be440ca20d7c630fddf..0a358735c331767e8eb563a80e9aaccfb544c27b 100644
|
||||
index 33827edce63c9fe08b52aea59571391a83853443..79327877b0f34cbafb3efcc21617027d4011f806 100644
|
||||
--- a/src/api/environment.cc
|
||||
+++ b/src/api/environment.cc
|
||||
@@ -886,7 +886,7 @@ Maybe<void> InitializePrimordials(Local<Context> context,
|
||||
@@ -878,7 +878,7 @@ Maybe<void> InitializePrimordials(Local<Context> context,
|
||||
CHECK(!exports->Has(context, primordials_string).FromJust());
|
||||
|
||||
Local<Object> primordials = Object::New(isolate);
|
||||
@@ -51,10 +51,10 @@ index 7b2efa49468c0bed2f5935552addd3ab37d0a50b..413db3ed9b88d7b7fb2ac6dd1153dade
|
||||
return GET_RETURN_STATUS(env);
|
||||
}
|
||||
diff --git a/src/node_buffer.cc b/src/node_buffer.cc
|
||||
index c94b14741c827a81d69a6f036426a344e563ad72..15129e4455fdc8792f21511a04d534ba3a4ebb5f 100644
|
||||
index 8a5b6b57321c2843a965a7e51b2ebed991a1e424..e844fe6cb33acefd075516e675075421ad5c3cff 100644
|
||||
--- a/src/node_buffer.cc
|
||||
+++ b/src/node_buffer.cc
|
||||
@@ -284,8 +284,9 @@ MaybeLocal<Uint8Array> New(Environment* env,
|
||||
@@ -283,8 +283,9 @@ MaybeLocal<Uint8Array> New(Environment* env,
|
||||
size_t length) {
|
||||
CHECK(!env->buffer_prototype_object().IsEmpty());
|
||||
Local<Uint8Array> ui = Uint8Array::New(ab, byte_offset, length);
|
||||
|
||||
@@ -136,10 +136,10 @@ index 75be21c9e8b413f522240a906da06d26c44d5b71..e94c2b5f2cf7cac413cd5cb782fa1cca
|
||||
std::make_error_code(std::errc::file_exists),
|
||||
"cp",
|
||||
diff --git a/src/node_modules.cc b/src/node_modules.cc
|
||||
index 14f2a35f87e8c2fa17898147d7247cc00c066f35..871282c6f8780ee0bca1e7230c0c2d83fd0c98c0 100644
|
||||
index fa04b4a8cdd02a2cad1eaf2e5a848b951d1b1150..947513d5b91e8c13478b25d80a1157edbcd64b64 100644
|
||||
--- a/src/node_modules.cc
|
||||
+++ b/src/node_modules.cc
|
||||
@@ -360,12 +360,13 @@ const BindingData::PackageConfig* BindingData::TraverseParent(
|
||||
@@ -327,22 +327,24 @@ const BindingData::PackageConfig* BindingData::TraverseParent(
|
||||
|
||||
// Stop the search when the process doesn't have permissions
|
||||
// to walk upwards
|
||||
@@ -158,10 +158,6 @@ index 14f2a35f87e8c2fa17898147d7247cc00c066f35..871282c6f8780ee0bca1e7230c0c2d83
|
||||
+ }
|
||||
}
|
||||
|
||||
// If current path is outside the resources path, bail.
|
||||
@@ -375,13 +376,14 @@ const BindingData::PackageConfig* BindingData::TraverseParent(
|
||||
}
|
||||
|
||||
// Check if the path ends with `/node_modules`
|
||||
- if (current_path.generic_string().ends_with("/node_modules")) {
|
||||
+ if (current_path.filename() == "node_modules") {
|
||||
@@ -176,7 +172,7 @@ index 14f2a35f87e8c2fa17898147d7247cc00c066f35..871282c6f8780ee0bca1e7230c0c2d83
|
||||
if (package_json != nullptr) {
|
||||
return package_json;
|
||||
}
|
||||
@@ -403,20 +405,12 @@ void BindingData::GetNearestParentPackageJSONType(
|
||||
@@ -364,20 +366,12 @@ void BindingData::GetNearestParentPackageJSONType(
|
||||
|
||||
ToNamespacedPath(realm->env(), &path_value);
|
||||
|
||||
|
||||
@@ -6,63 +6,6 @@ Subject: support V8 sandboxed pointers
|
||||
This refactors several allocators to allocate within the V8 memory cage,
|
||||
allowing them to be compatible with the V8_SANDBOXED_POINTERS feature.
|
||||
|
||||
diff --git a/src/api/environment.cc b/src/api/environment.cc
|
||||
index fd71ceac65ccef1d2832b45b0b5612877cee22c1..cb37fa080fc8e8d524cfa2758c4a8c2c5652324d 100644
|
||||
--- a/src/api/environment.cc
|
||||
+++ b/src/api/environment.cc
|
||||
@@ -106,6 +106,14 @@ MaybeLocal<Value> PrepareStackTraceCallback(Local<Context> context,
|
||||
return result;
|
||||
}
|
||||
|
||||
+NodeArrayBufferAllocator::NodeArrayBufferAllocator() {
|
||||
+ zero_fill_field_ = static_cast<uint32_t*>(allocator_->Allocate(sizeof(*zero_fill_field_)));
|
||||
+}
|
||||
+
|
||||
+NodeArrayBufferAllocator::~NodeArrayBufferAllocator() {
|
||||
+ allocator_->Free(zero_fill_field_, sizeof(*zero_fill_field_));
|
||||
+}
|
||||
+
|
||||
void* NodeArrayBufferAllocator::Allocate(size_t size) {
|
||||
void* ret;
|
||||
if (zero_fill_field_ || per_process::cli_options->zero_fill_all_buffers)
|
||||
diff --git a/src/crypto/crypto_dh.cc b/src/crypto/crypto_dh.cc
|
||||
index f23cedf4f2449d8edc9a8de1b70332e75d693cdd..976653dd1e9363e046788fc3419a9b649ceb2ea4 100644
|
||||
--- a/src/crypto/crypto_dh.cc
|
||||
+++ b/src/crypto/crypto_dh.cc
|
||||
@@ -55,13 +55,32 @@ void DiffieHellman::MemoryInfo(MemoryTracker* tracker) const {
|
||||
|
||||
namespace {
|
||||
MaybeLocal<Value> DataPointerToBuffer(Environment* env, DataPointer&& data) {
|
||||
+#if defined(V8_ENABLE_SANDBOX)
|
||||
+ std::unique_ptr<v8::BackingStore> backing;
|
||||
+ if (data.size() > 0) {
|
||||
+ std::unique_ptr<ArrayBuffer::Allocator> allocator(ArrayBuffer::Allocator::NewDefaultAllocator());
|
||||
+ void* v8_data = allocator->Allocate(data.size());
|
||||
+ CHECK(v8_data);
|
||||
+ memcpy(v8_data, data.get(), data.size());
|
||||
+ backing = ArrayBuffer::NewBackingStore(
|
||||
+ v8_data,
|
||||
+ data.size(),
|
||||
+ [](void* data, size_t length, void*) {
|
||||
+ std::unique_ptr<ArrayBuffer::Allocator> allocator(ArrayBuffer::Allocator::NewDefaultAllocator());
|
||||
+ allocator->Free(data, length);
|
||||
+ }, nullptr);
|
||||
+ } else {
|
||||
+ NoArrayBufferZeroFillScope no_zero_fill_scope(env->isolate_data());
|
||||
+ backing = v8::ArrayBuffer::NewBackingStore(env->isolate(), data.size());
|
||||
+ }
|
||||
+#else
|
||||
auto backing = ArrayBuffer::NewBackingStore(
|
||||
data.get(),
|
||||
data.size(),
|
||||
[](void* data, size_t len, void* ptr) { DataPointer free_me(data, len); },
|
||||
nullptr);
|
||||
data.release();
|
||||
-
|
||||
+#endif
|
||||
auto ab = ArrayBuffer::New(env->isolate(), std::move(backing));
|
||||
return Buffer::New(env, ab, 0, ab->ByteLength()).FromMaybe(Local<Value>());
|
||||
}
|
||||
diff --git a/src/crypto/crypto_util.cc b/src/crypto/crypto_util.cc
|
||||
index 4505786745c54a529f904d5e7813a86204e0a78b..eab18ab9888e2f7c0757fefab80505d8c99dc742 100644
|
||||
--- a/src/crypto/crypto_util.cc
|
||||
@@ -188,6 +131,28 @@ index f616223cfb0f6e10f7cf57ada9704316bde2797e..eb6dad44a49d997097c8fb5009eeb60a
|
||||
auto ab = ArrayBuffer::New(env->isolate(), std::move(backing));
|
||||
Local<Value> ret;
|
||||
if (!Buffer::New(env, ab, 0, ab->ByteLength()).ToLocal(&ret)) return {};
|
||||
diff --git a/src/node_buffer.cc b/src/node_buffer.cc
|
||||
index 357dc5f6d1c1c2d3756a94c1326b0502403e1eaf..b9f0c97938203b4652780a7d707c5e83319330b0 100644
|
||||
--- a/src/node_buffer.cc
|
||||
+++ b/src/node_buffer.cc
|
||||
@@ -1412,7 +1412,7 @@ inline size_t CheckNumberToSize(Local<Value> number) {
|
||||
CHECK(value >= 0 && value < maxSize);
|
||||
size_t size = static_cast<size_t>(value);
|
||||
#ifdef V8_ENABLE_SANDBOX
|
||||
- CHECK_LE(size, kMaxSafeBufferSizeForSandbox);
|
||||
+ CHECK_LE(size, v8::internal::kMaxSafeBufferSizeForSandbox);
|
||||
#endif
|
||||
return size;
|
||||
}
|
||||
@@ -1437,7 +1437,7 @@ void CreateUnsafeArrayBuffer(const FunctionCallbackInfo<Value>& args) {
|
||||
buf = ArrayBuffer::New(isolate, size);
|
||||
} else {
|
||||
std::unique_ptr<BackingStore> store =
|
||||
- ArrayBuffer::NewBackingStoreForNodeLTS(isolate, size);
|
||||
+ ArrayBuffer::NewBackingStore(isolate, size);
|
||||
if (!store) {
|
||||
return env->ThrowRangeError("Array buffer allocation failed");
|
||||
}
|
||||
diff --git a/src/node_i18n.cc b/src/node_i18n.cc
|
||||
index 6be3920632b25db450025ebab6a2636e4811cdbe..b49916d2b5fc5e58cf3fb67329430fd3df8fb813 100644
|
||||
--- a/src/node_i18n.cc
|
||||
@@ -228,30 +193,6 @@ index 6be3920632b25db450025ebab6a2636e4811cdbe..b49916d2b5fc5e58cf3fb67329430fd3
|
||||
}
|
||||
|
||||
constexpr const char* EncodingName(const enum encoding encoding) {
|
||||
diff --git a/src/node_internals.h b/src/node_internals.h
|
||||
index 12ea72b61b0a5e194207bb369dfed4b8667107cb..64442215714a98f648971e517ddd9c77e38fe3f2 100644
|
||||
--- a/src/node_internals.h
|
||||
+++ b/src/node_internals.h
|
||||
@@ -121,7 +121,9 @@ v8::MaybeLocal<v8::Object> InitializePrivateSymbols(
|
||||
|
||||
class NodeArrayBufferAllocator : public ArrayBufferAllocator {
|
||||
public:
|
||||
- inline uint32_t* zero_fill_field() { return &zero_fill_field_; }
|
||||
+ NodeArrayBufferAllocator();
|
||||
+ ~NodeArrayBufferAllocator() override;
|
||||
+ inline uint32_t* zero_fill_field() { return zero_fill_field_; }
|
||||
|
||||
void* Allocate(size_t size) override; // Defined in src/node.cc
|
||||
void* AllocateUninitialized(size_t size) override;
|
||||
@@ -139,7 +141,7 @@ class NodeArrayBufferAllocator : public ArrayBufferAllocator {
|
||||
}
|
||||
|
||||
private:
|
||||
- uint32_t zero_fill_field_ = 1; // Boolean but exposed as uint32 to JS land.
|
||||
+ uint32_t* zero_fill_field_ = nullptr; // Boolean but exposed as uint32 to JS land.
|
||||
std::atomic<size_t> total_mem_usage_ {0};
|
||||
|
||||
// Delegate to V8's allocator for compatibility with the V8 memory cage.
|
||||
diff --git a/src/node_serdes.cc b/src/node_serdes.cc
|
||||
index c55a2e28066147ae5ca5def10ec76ccc03c634b4..c54183c72944989219b6437c9e571a3f7f3f8dd5 100644
|
||||
--- a/src/node_serdes.cc
|
||||
|
||||
@@ -0,0 +1,33 @@
|
||||
From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001
|
||||
From: Shelley Vohr <shelley.vohr@gmail.com>
|
||||
Date: Tue, 4 Nov 2025 21:20:26 +0100
|
||||
Subject: test: correct conditional secure heap flags test
|
||||
|
||||
PR-URL: https://github.com/nodejs/node/pull/60385
|
||||
Reviewed-By: Colin Ihrig <cjihrig@gmail.com>
|
||||
Reviewed-By: Luigi Pinca <luigipinca@gmail.com>
|
||||
(cherry picked from commit 53c4a39fec941e04150554fdd3e654b48f2e1b31)
|
||||
|
||||
diff --git a/test/parallel/test-process-env-allowed-flags-are-documented.js b/test/parallel/test-process-env-allowed-flags-are-documented.js
|
||||
index afd43cfffe638f4f084f1c36949068e7239eadc3..c70e073bab888c349e8f5c691f5679a3796c896c 100644
|
||||
--- a/test/parallel/test-process-env-allowed-flags-are-documented.js
|
||||
+++ b/test/parallel/test-process-env-allowed-flags-are-documented.js
|
||||
@@ -49,6 +49,8 @@ if (!hasOpenSSL3) {
|
||||
documented.delete('--openssl-shared-config');
|
||||
}
|
||||
|
||||
+const isV8Sandboxed = process.config.variables.v8_enable_sandbox;
|
||||
+
|
||||
// Filter out options that are conditionally present.
|
||||
const conditionalOpts = [
|
||||
{
|
||||
@@ -74,6 +76,9 @@ const conditionalOpts = [
|
||||
}, {
|
||||
include: process.features.inspector,
|
||||
filter: (opt) => opt.startsWith('--inspect') || opt === '--debug-port'
|
||||
+ }, {
|
||||
+ include: !isV8Sandboxed,
|
||||
+ filter: (opt) => ['--secure-heap', '--secure-heap-min'].includes(opt)
|
||||
},
|
||||
];
|
||||
documented.forEach((opt) => {
|
||||
@@ -1,2 +1,5 @@
|
||||
chore_allow_customizing_microtask_policy_per_context.patch
|
||||
turboshaft_avoid_introducing_too_many_variables.patch
|
||||
runtime_setprototypeproperties_handling_of.patch
|
||||
runtime_correcting_setprototypeproperties.patch
|
||||
reduce_stack_memory_consumption_in_bytecodegenerator.patch
|
||||
|
||||
@@ -0,0 +1,263 @@
|
||||
From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001
|
||||
From: Jakob Kummerow <jkummerow@chromium.org>
|
||||
Date: Fri, 21 Nov 2025 11:52:15 +0100
|
||||
Subject: Reduce stack memory consumption in BytecodeGenerator
|
||||
|
||||
Using a SmallVector with 64 stack-allocated entries is not great
|
||||
for functions that can be used in deep recursions, so this patch
|
||||
replaces that with a ZoneVector.
|
||||
By allocating any backing store only when it's actually needed,
|
||||
and presizing that initial backing store when that happens, this
|
||||
should have similar performance while using a lot less stack space,
|
||||
allowing us to compile more deeply nested expressions.
|
||||
|
||||
For the highly artificial example of a function full of nested
|
||||
empty blocks `function f() {{{{{...}}}}}`, this increases the max
|
||||
nesting level from around 670 to around 2600. With more aggressive
|
||||
inlining in official builds, it can have similar effects on patterns
|
||||
that don't even call `VisitStatements()` recursively.
|
||||
|
||||
Bug: 429332174
|
||||
Change-Id: Id11e15ba0fd9bc39efa68bf83e1181fe0e7274a7
|
||||
Reviewed-on: https://chromium-review.googlesource.com/c/v8/v8/+/7180480
|
||||
Reviewed-by: Raphael Herouart <rherouart@chromium.org>
|
||||
Commit-Queue: Jakob Kummerow <jkummerow@chromium.org>
|
||||
Reviewed-by: Leszek Swirski <leszeks@chromium.org>
|
||||
Cr-Commit-Position: refs/heads/main@{#103870}
|
||||
|
||||
diff --git a/src/interpreter/bytecode-generator.cc b/src/interpreter/bytecode-generator.cc
|
||||
index 63400abcc7ca0bd5369d566dd37e2ae93d7c3efe..a1cf142edc4c0224731ebab988bcbf9272acd57e 100644
|
||||
--- a/src/interpreter/bytecode-generator.cc
|
||||
+++ b/src/interpreter/bytecode-generator.cc
|
||||
@@ -2306,10 +2306,7 @@ void BytecodeGenerator::VisitDeclarations(Declaration::List* declarations) {
|
||||
// The subsequent ones must be about the same <var> to return true.
|
||||
|
||||
bool BytecodeGenerator::IsPrototypeAssignment(
|
||||
- Statement* stmt, Variable** var, HoleCheckMode* hole_check_mode,
|
||||
- SmallZoneVector<std::pair<const AstRawString*, Expression*>,
|
||||
- kInitialPropertyCount>& properties,
|
||||
- std::unordered_set<const AstRawString*>& duplicates) {
|
||||
+ Statement* stmt, std::unique_ptr<PrototypeAssignments>* assignments) {
|
||||
// The expression Statement is an assignment
|
||||
// ========================================
|
||||
ExpressionStatement* expr_stmt = stmt->AsExpressionStatement();
|
||||
@@ -2381,41 +2378,46 @@ bool BytecodeGenerator::IsPrototypeAssignment(
|
||||
return false;
|
||||
}
|
||||
|
||||
- if (!duplicates.insert(prop_str).second) {
|
||||
- return false;
|
||||
- }
|
||||
-
|
||||
- if (*var == nullptr) {
|
||||
- // This is the first proto assignment in the sequence
|
||||
- *var = tmp_var;
|
||||
- *hole_check_mode = proto_prop->obj()->AsVariableProxy()->hole_check_mode();
|
||||
- } else if (*var != tmp_var) {
|
||||
- // This prototype assignment is about another var
|
||||
- return false;
|
||||
+ if (!*assignments) {
|
||||
+ // This is the first prototype assignment in the sequence.
|
||||
+ *assignments = std::make_unique<PrototypeAssignments>(
|
||||
+ tmp_var, proto_prop->obj()->AsVariableProxy()->hole_check_mode(),
|
||||
+ ZoneVector<PrototypeAssignment>(zone()));
|
||||
+ (*assignments)->properties.reserve(8);
|
||||
+ (*assignments)->duplicates.insert(prop_str);
|
||||
+ } else {
|
||||
+ if (!(*assignments)->duplicates.insert(prop_str).second) return false;
|
||||
+ if ((*assignments)->var != tmp_var) {
|
||||
+ // This prototype assignment is about another var.
|
||||
+ return false;
|
||||
+ }
|
||||
+ DCHECK_EQ((*assignments)->hole_check_mode,
|
||||
+ proto_prop->obj()->AsVariableProxy()->hole_check_mode());
|
||||
}
|
||||
|
||||
- // Success
|
||||
- properties.push_back(std::make_pair(
|
||||
- prop_str,
|
||||
- value)); // This will be reused as part of an ObjectLiteral
|
||||
+ // Success!
|
||||
+ (*assignments)
|
||||
+ ->properties.push_back(std::make_pair(
|
||||
+ prop_str,
|
||||
+ value)); // This will be reused as part of an ObjectLiteral.
|
||||
|
||||
- DCHECK_EQ(*hole_check_mode,
|
||||
- proto_prop->obj()->AsVariableProxy()->hole_check_mode());
|
||||
return true;
|
||||
}
|
||||
|
||||
void BytecodeGenerator::VisitConsecutivePrototypeAssignments(
|
||||
- const SmallZoneVector<std::pair<const AstRawString*, Expression*>,
|
||||
- kInitialPropertyCount>& properties,
|
||||
- Variable* var, HoleCheckMode hole_check_mode) {
|
||||
+ std::unique_ptr<PrototypeAssignments> assignments) {
|
||||
// Create a boiler plate object in the constant pool to be merged into the
|
||||
- // proto
|
||||
+ // proto.
|
||||
size_t entry = builder()->AllocateDeferredConstantPoolEntry();
|
||||
- proto_assign_seq_.push_back(std::make_pair(
|
||||
- zone()->New<ProtoAssignmentSeqBuilder>(properties), entry));
|
||||
+ proto_assign_seq_.push_back(
|
||||
+ std::make_pair(zone()->New<ProtoAssignmentSeqBuilder>(
|
||||
+ std::move(assignments->properties)),
|
||||
+ entry));
|
||||
+ const ZoneVector<PrototypeAssignment>* props =
|
||||
+ proto_assign_seq_.back().first->properties();
|
||||
|
||||
int first_idx = -1;
|
||||
- for (auto& p : properties) {
|
||||
+ for (auto& p : *props) {
|
||||
auto func = p.second->AsFunctionLiteral();
|
||||
if (func) {
|
||||
int idx = GetNewClosureSlot(func);
|
||||
@@ -2426,13 +2428,13 @@ void BytecodeGenerator::VisitConsecutivePrototypeAssignments(
|
||||
}
|
||||
}
|
||||
|
||||
- // We need it to be valid, even if unused
|
||||
+ // We need {first_idx} to be valid, even if it's unused.
|
||||
if (first_idx == -1) {
|
||||
first_idx = 0;
|
||||
}
|
||||
- // Load the variable whose prototype is to be set into the Accumulator
|
||||
- BuildVariableLoad(var, hole_check_mode);
|
||||
- // Merge in-place proto-def boilerplate object into Accumulator
|
||||
+ // Load the variable whose prototype is to be set into the Accumulator.
|
||||
+ BuildVariableLoad(assignments->var, assignments->hole_check_mode);
|
||||
+ // Merge in-place proto-def boilerplate object into the Accumulator.
|
||||
builder()->SetPrototypeProperties(entry, first_idx);
|
||||
}
|
||||
|
||||
@@ -2440,25 +2442,23 @@ void BytecodeGenerator::VisitStatements(
|
||||
const ZonePtrList<Statement>* statements, int start) {
|
||||
for (int stmt_idx = start; stmt_idx < statements->length(); stmt_idx++) {
|
||||
if (v8_flags.proto_assign_seq_opt) {
|
||||
- Variable* var = nullptr;
|
||||
- HoleCheckMode hole_check_mode;
|
||||
-
|
||||
int proto_assign_idx = stmt_idx;
|
||||
- SmallZoneVector<std::pair<const AstRawString*, Expression*>,
|
||||
- kInitialPropertyCount>
|
||||
- properties(zone());
|
||||
- std::unordered_set<const AstRawString*> duplicates;
|
||||
+ // {VisitStatements} can be used for deep recursions, so this is a
|
||||
+ // stack-friendly design: statically we only need one {unique_ptr}, and
|
||||
+ // the actual storage is heap-allocated when it is needed.
|
||||
+ std::unique_ptr<PrototypeAssignments> assignments;
|
||||
while (proto_assign_idx < statements->length() &&
|
||||
- IsPrototypeAssignment(statements->at(proto_assign_idx), &var,
|
||||
- &hole_check_mode, properties, duplicates)) {
|
||||
+ IsPrototypeAssignment(statements->at(proto_assign_idx),
|
||||
+ &assignments)) {
|
||||
++proto_assign_idx;
|
||||
}
|
||||
|
||||
if (proto_assign_idx - stmt_idx > 1) {
|
||||
- DCHECK_EQ((size_t)(proto_assign_idx - stmt_idx), properties.size());
|
||||
- VisitConsecutivePrototypeAssignments(properties, var, hole_check_mode);
|
||||
- stmt_idx = proto_assign_idx - 1; // the outer loop should now ignore
|
||||
- // these statements
|
||||
+ DCHECK_EQ(static_cast<size_t>(proto_assign_idx - stmt_idx),
|
||||
+ assignments->properties.size());
|
||||
+ VisitConsecutivePrototypeAssignments(std::move(assignments));
|
||||
+ stmt_idx = proto_assign_idx - 1; // The outer loop should now ignore
|
||||
+ // these statements.
|
||||
DCHECK(!builder()->RemainderOfBlockIsDead());
|
||||
continue;
|
||||
}
|
||||
diff --git a/src/interpreter/bytecode-generator.h b/src/interpreter/bytecode-generator.h
|
||||
index 5dd136a01848aaf4a182dd31aa05a6ebe845fae8..b2e4cf6d40c3cd66042f5f52533b4883ff159418 100644
|
||||
--- a/src/interpreter/bytecode-generator.h
|
||||
+++ b/src/interpreter/bytecode-generator.h
|
||||
@@ -30,6 +30,13 @@ class LoopBuilder;
|
||||
class BlockCoverageBuilder;
|
||||
class BytecodeJumpTable;
|
||||
|
||||
+struct PrototypeAssignments {
|
||||
+ Variable* var;
|
||||
+ HoleCheckMode hole_check_mode;
|
||||
+ ZoneVector<PrototypeAssignment> properties;
|
||||
+ std::unordered_set<const AstRawString*> duplicates;
|
||||
+};
|
||||
+
|
||||
class BytecodeGenerator final : public AstVisitor<BytecodeGenerator> {
|
||||
public:
|
||||
enum TypeHint : uint8_t {
|
||||
@@ -69,18 +76,12 @@ class BytecodeGenerator final : public AstVisitor<BytecodeGenerator> {
|
||||
#define DECLARE_VISIT(type) void Visit##type(type* node);
|
||||
AST_NODE_LIST(DECLARE_VISIT)
|
||||
#undef DECLARE_VISIT
|
||||
- static constexpr int kInitialPropertyCount = 64;
|
||||
|
||||
bool IsPrototypeAssignment(
|
||||
- Statement* stmt, Variable** var, HoleCheckMode* hole_check_mode,
|
||||
- SmallZoneVector<std::pair<const AstRawString*, Expression*>,
|
||||
- kInitialPropertyCount>& properties,
|
||||
- std::unordered_set<const AstRawString*>& duplicate);
|
||||
-
|
||||
- void VisitConsecutivePrototypeAssignments(
|
||||
- const SmallZoneVector<std::pair<const AstRawString*, Expression*>,
|
||||
- kInitialPropertyCount>& properties,
|
||||
- Variable* var, HoleCheckMode hole_check_mode);
|
||||
+ Statement* stmt, std::unique_ptr<PrototypeAssignments>* assignments);
|
||||
+ V8_NOINLINE void VisitConsecutivePrototypeAssignments(
|
||||
+ std::unique_ptr<PrototypeAssignments> assignments);
|
||||
+
|
||||
// Visiting function for declarations list and statements are overridden.
|
||||
void VisitModuleDeclarations(Declaration::List* declarations);
|
||||
void VisitGlobalDeclarations(Declaration::List* declarations);
|
||||
diff --git a/src/interpreter/prototype-assignment-sequence-builder.cc b/src/interpreter/prototype-assignment-sequence-builder.cc
|
||||
index a7c05b6e8555fde41ba6a81523437fd03b16c3e6..fb427c825c2753d3e12f557279a5230985a1ec44 100644
|
||||
--- a/src/interpreter/prototype-assignment-sequence-builder.cc
|
||||
+++ b/src/interpreter/prototype-assignment-sequence-builder.cc
|
||||
@@ -25,7 +25,7 @@ void ProtoAssignmentSeqBuilder::BuildBoilerplateDescription(
|
||||
|
||||
int position = 0;
|
||||
for (size_t i = 0; i < properties_.size(); i++) {
|
||||
- auto pair = properties_.at(i);
|
||||
+ PrototypeAssignment pair = properties_.at(i);
|
||||
const AstRawString* key_str = pair.first;
|
||||
|
||||
DirectHandle<Object> key = Cast<Object>(key_str->string());
|
||||
diff --git a/src/interpreter/prototype-assignment-sequence-builder.h b/src/interpreter/prototype-assignment-sequence-builder.h
|
||||
index 0c29f4f4bf0843877b2bd568866d8e290d4f3b51..6583022aa43a30df707325e6b7a14891f97a4ef1 100644
|
||||
--- a/src/interpreter/prototype-assignment-sequence-builder.h
|
||||
+++ b/src/interpreter/prototype-assignment-sequence-builder.h
|
||||
@@ -7,17 +7,17 @@
|
||||
|
||||
#include "src/ast/ast.h"
|
||||
#include "src/objects/literal-objects.h"
|
||||
+#include "src/zone/zone-containers.h"
|
||||
|
||||
namespace v8 {
|
||||
namespace internal {
|
||||
|
||||
+using PrototypeAssignment = std::pair<const AstRawString*, Expression*>;
|
||||
+
|
||||
class ProtoAssignmentSeqBuilder final : public ZoneObject {
|
||||
public:
|
||||
- static constexpr int kInitialPropertyCount = 64;
|
||||
-
|
||||
explicit ProtoAssignmentSeqBuilder(
|
||||
- const SmallZoneVector<std::pair<const AstRawString*, Expression*>,
|
||||
- kInitialPropertyCount>& properties)
|
||||
+ ZoneVector<PrototypeAssignment>&& properties)
|
||||
: properties_(std::move(properties)) {}
|
||||
|
||||
~ProtoAssignmentSeqBuilder() = default;
|
||||
@@ -53,10 +53,10 @@ class ProtoAssignmentSeqBuilder final : public ZoneObject {
|
||||
IsolateT* isolate,
|
||||
Handle<Script> script);
|
||||
|
||||
+ const ZoneVector<PrototypeAssignment>* properties() { return &properties_; }
|
||||
+
|
||||
private:
|
||||
- SmallZoneVector<std::pair<const AstRawString*, Expression*>,
|
||||
- kInitialPropertyCount>
|
||||
- properties_;
|
||||
+ ZoneVector<PrototypeAssignment> properties_;
|
||||
IndirectHandle<ObjectBoilerplateDescription> boilerplate_description_;
|
||||
};
|
||||
|
||||
148
patches/v8/runtime_correcting_setprototypeproperties.patch
Normal file
148
patches/v8/runtime_correcting_setprototypeproperties.patch
Normal file
@@ -0,0 +1,148 @@
|
||||
From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001
|
||||
From: Raphael Herouart <rherouart@chromium.org>
|
||||
Date: Tue, 18 Nov 2025 11:00:26 +0000
|
||||
Subject: [runtime] Correcting SetPrototypeProperties:
|
||||
|
||||
- Off by One Error in code generation
|
||||
- Attributes should be preserved when setting properties
|
||||
- SmallVector Memory Leak
|
||||
|
||||
Bug: 429332174
|
||||
Change-Id: I8a669a98f44777ad54ea7e7bb06fc4f8c552c865
|
||||
Reviewed-on: https://chromium-review.googlesource.com/c/v8/v8/+/7160576
|
||||
Reviewed-by: Toon Verwaest <verwaest@chromium.org>
|
||||
Commit-Queue: Raphael Herouart <rherouart@chromium.org>
|
||||
Cr-Commit-Position: refs/heads/main@{#103784}
|
||||
|
||||
diff --git a/src/interpreter/bytecode-generator.cc b/src/interpreter/bytecode-generator.cc
|
||||
index bf874d94ec34056d499fea9cbd034f959d506b58..63400abcc7ca0bd5369d566dd37e2ae93d7c3efe 100644
|
||||
--- a/src/interpreter/bytecode-generator.cc
|
||||
+++ b/src/interpreter/bytecode-generator.cc
|
||||
@@ -2307,8 +2307,8 @@ void BytecodeGenerator::VisitDeclarations(Declaration::List* declarations) {
|
||||
|
||||
bool BytecodeGenerator::IsPrototypeAssignment(
|
||||
Statement* stmt, Variable** var, HoleCheckMode* hole_check_mode,
|
||||
- base::SmallVector<std::pair<const AstRawString*, Expression*>,
|
||||
- kInitialPropertyCount>& properties,
|
||||
+ SmallZoneVector<std::pair<const AstRawString*, Expression*>,
|
||||
+ kInitialPropertyCount>& properties,
|
||||
std::unordered_set<const AstRawString*>& duplicates) {
|
||||
// The expression Statement is an assignment
|
||||
// ========================================
|
||||
@@ -2405,8 +2405,8 @@ bool BytecodeGenerator::IsPrototypeAssignment(
|
||||
}
|
||||
|
||||
void BytecodeGenerator::VisitConsecutivePrototypeAssignments(
|
||||
- const base::SmallVector<std::pair<const AstRawString*, Expression*>,
|
||||
- kInitialPropertyCount>& properties,
|
||||
+ const SmallZoneVector<std::pair<const AstRawString*, Expression*>,
|
||||
+ kInitialPropertyCount>& properties,
|
||||
Variable* var, HoleCheckMode hole_check_mode) {
|
||||
// Create a boiler plate object in the constant pool to be merged into the
|
||||
// proto
|
||||
@@ -2444,9 +2444,9 @@ void BytecodeGenerator::VisitStatements(
|
||||
HoleCheckMode hole_check_mode;
|
||||
|
||||
int proto_assign_idx = stmt_idx;
|
||||
- base::SmallVector<std::pair<const AstRawString*, Expression*>,
|
||||
- kInitialPropertyCount>
|
||||
- properties;
|
||||
+ SmallZoneVector<std::pair<const AstRawString*, Expression*>,
|
||||
+ kInitialPropertyCount>
|
||||
+ properties(zone());
|
||||
std::unordered_set<const AstRawString*> duplicates;
|
||||
while (proto_assign_idx < statements->length() &&
|
||||
IsPrototypeAssignment(statements->at(proto_assign_idx), &var,
|
||||
@@ -2457,10 +2457,10 @@ void BytecodeGenerator::VisitStatements(
|
||||
if (proto_assign_idx - stmt_idx > 1) {
|
||||
DCHECK_EQ((size_t)(proto_assign_idx - stmt_idx), properties.size());
|
||||
VisitConsecutivePrototypeAssignments(properties, var, hole_check_mode);
|
||||
- stmt_idx = proto_assign_idx; // the outer loop should now ignore these
|
||||
- // statements
|
||||
+ stmt_idx = proto_assign_idx - 1; // the outer loop should now ignore
|
||||
+ // these statements
|
||||
DCHECK(!builder()->RemainderOfBlockIsDead());
|
||||
- if (stmt_idx == statements->length()) break;
|
||||
+ continue;
|
||||
}
|
||||
}
|
||||
|
||||
diff --git a/src/interpreter/bytecode-generator.h b/src/interpreter/bytecode-generator.h
|
||||
index 41c5cda1ca6dd4017b329e41bad8af3bcc4ee242..5dd136a01848aaf4a182dd31aa05a6ebe845fae8 100644
|
||||
--- a/src/interpreter/bytecode-generator.h
|
||||
+++ b/src/interpreter/bytecode-generator.h
|
||||
@@ -73,13 +73,13 @@ class BytecodeGenerator final : public AstVisitor<BytecodeGenerator> {
|
||||
|
||||
bool IsPrototypeAssignment(
|
||||
Statement* stmt, Variable** var, HoleCheckMode* hole_check_mode,
|
||||
- base::SmallVector<std::pair<const AstRawString*, Expression*>,
|
||||
- kInitialPropertyCount>& properties,
|
||||
+ SmallZoneVector<std::pair<const AstRawString*, Expression*>,
|
||||
+ kInitialPropertyCount>& properties,
|
||||
std::unordered_set<const AstRawString*>& duplicate);
|
||||
|
||||
void VisitConsecutivePrototypeAssignments(
|
||||
- const base::SmallVector<std::pair<const AstRawString*, Expression*>,
|
||||
- kInitialPropertyCount>& properties,
|
||||
+ const SmallZoneVector<std::pair<const AstRawString*, Expression*>,
|
||||
+ kInitialPropertyCount>& properties,
|
||||
Variable* var, HoleCheckMode hole_check_mode);
|
||||
// Visiting function for declarations list and statements are overridden.
|
||||
void VisitModuleDeclarations(Declaration::List* declarations);
|
||||
diff --git a/src/interpreter/prototype-assignment-sequence-builder.h b/src/interpreter/prototype-assignment-sequence-builder.h
|
||||
index 880ed4dcec8399e9b52e6d1924b8773bff1db063..0c29f4f4bf0843877b2bd568866d8e290d4f3b51 100644
|
||||
--- a/src/interpreter/prototype-assignment-sequence-builder.h
|
||||
+++ b/src/interpreter/prototype-assignment-sequence-builder.h
|
||||
@@ -16,8 +16,8 @@ class ProtoAssignmentSeqBuilder final : public ZoneObject {
|
||||
static constexpr int kInitialPropertyCount = 64;
|
||||
|
||||
explicit ProtoAssignmentSeqBuilder(
|
||||
- const base::SmallVector<std::pair<const AstRawString*, Expression*>,
|
||||
- kInitialPropertyCount>& properties)
|
||||
+ const SmallZoneVector<std::pair<const AstRawString*, Expression*>,
|
||||
+ kInitialPropertyCount>& properties)
|
||||
: properties_(std::move(properties)) {}
|
||||
|
||||
~ProtoAssignmentSeqBuilder() = default;
|
||||
@@ -54,8 +54,8 @@ class ProtoAssignmentSeqBuilder final : public ZoneObject {
|
||||
Handle<Script> script);
|
||||
|
||||
private:
|
||||
- base::SmallVector<std::pair<const AstRawString*, Expression*>,
|
||||
- kInitialPropertyCount>
|
||||
+ SmallZoneVector<std::pair<const AstRawString*, Expression*>,
|
||||
+ kInitialPropertyCount>
|
||||
properties_;
|
||||
IndirectHandle<ObjectBoilerplateDescription> boilerplate_description_;
|
||||
};
|
||||
diff --git a/src/runtime/runtime-literals.cc b/src/runtime/runtime-literals.cc
|
||||
index ded3b466625c99da6f27936ae4e5e0c879baec1b..961b9ee5b7d329bb018300fe2f18bea60e1cd883 100644
|
||||
--- a/src/runtime/runtime-literals.cc
|
||||
+++ b/src/runtime/runtime-literals.cc
|
||||
@@ -730,6 +730,13 @@ RUNTIME_FUNCTION(Runtime_SetPrototypeProperties) {
|
||||
feedback_cell_array, current_slot));
|
||||
}
|
||||
|
||||
+ if (IsSpecialReceiverMap(js_proto->map())) {
|
||||
+ RETURN_RESULT_OR_FAILURE(
|
||||
+ isolate, SetPrototypePropertiesSlow(isolate, context, obj,
|
||||
+ object_boilerplate_description,
|
||||
+ feedback_cell_array, current_slot));
|
||||
+ }
|
||||
+
|
||||
bool is_default_func_prototype =
|
||||
IsDefaultFunctionPrototype(js_proto, isolate);
|
||||
|
||||
@@ -782,7 +789,11 @@ RUNTIME_FUNCTION(Runtime_SetPrototypeProperties) {
|
||||
value = InstantiateIfSharedFunctionInfo(
|
||||
context, isolate, value, feedback_cell_array, current_slot);
|
||||
DirectHandle<String> name = Cast<String>(key);
|
||||
- JSObject::SetOwnPropertyIgnoreAttributes(js_proto, name, value, NONE)
|
||||
+ Maybe<PropertyAttributes> maybe = JSReceiver::GetPropertyAttributes(&it);
|
||||
+ PropertyAttributes attr = maybe.ToChecked();
|
||||
+ if (attr == ABSENT) attr = NONE;
|
||||
+
|
||||
+ JSObject::SetOwnPropertyIgnoreAttributes(js_proto, name, value, attr)
|
||||
.Check();
|
||||
|
||||
result = value;
|
||||
153
patches/v8/runtime_setprototypeproperties_handling_of.patch
Normal file
153
patches/v8/runtime_setprototypeproperties_handling_of.patch
Normal file
@@ -0,0 +1,153 @@
|
||||
From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001
|
||||
From: Raphael Herouart <rherouart@chromium.org>
|
||||
Date: Tue, 21 Oct 2025 14:49:06 +0000
|
||||
Subject: [runtime] SetPrototypeProperties handling of
|
||||
Hole/Undefined/Non-Object Values
|
||||
|
||||
Bug: 451750214
|
||||
Change-Id: Ida29afe0b92ed4a6acff97214005ed3589093294
|
||||
Reviewed-on: https://chromium-review.googlesource.com/c/v8/v8/+/7062734
|
||||
Commit-Queue: Raphael Herouart <rherouart@chromium.org>
|
||||
Reviewed-by: Leszek Swirski <leszeks@chromium.org>
|
||||
Cr-Commit-Position: refs/heads/main@{#103261}
|
||||
|
||||
diff --git a/src/interpreter/bytecode-generator.cc b/src/interpreter/bytecode-generator.cc
|
||||
index 6d444622bacbb71c4754bc055da5cae39ed213b7..bf874d94ec34056d499fea9cbd034f959d506b58 100644
|
||||
--- a/src/interpreter/bytecode-generator.cc
|
||||
+++ b/src/interpreter/bytecode-generator.cc
|
||||
@@ -2306,7 +2306,7 @@ void BytecodeGenerator::VisitDeclarations(Declaration::List* declarations) {
|
||||
// The subsequent ones must be about the same <var> to return true.
|
||||
|
||||
bool BytecodeGenerator::IsPrototypeAssignment(
|
||||
- Statement* stmt, Variable** var,
|
||||
+ Statement* stmt, Variable** var, HoleCheckMode* hole_check_mode,
|
||||
base::SmallVector<std::pair<const AstRawString*, Expression*>,
|
||||
kInitialPropertyCount>& properties,
|
||||
std::unordered_set<const AstRawString*>& duplicates) {
|
||||
@@ -2388,6 +2388,7 @@ bool BytecodeGenerator::IsPrototypeAssignment(
|
||||
if (*var == nullptr) {
|
||||
// This is the first proto assignment in the sequence
|
||||
*var = tmp_var;
|
||||
+ *hole_check_mode = proto_prop->obj()->AsVariableProxy()->hole_check_mode();
|
||||
} else if (*var != tmp_var) {
|
||||
// This prototype assignment is about another var
|
||||
return false;
|
||||
@@ -2398,13 +2399,15 @@ bool BytecodeGenerator::IsPrototypeAssignment(
|
||||
prop_str,
|
||||
value)); // This will be reused as part of an ObjectLiteral
|
||||
|
||||
+ DCHECK_EQ(*hole_check_mode,
|
||||
+ proto_prop->obj()->AsVariableProxy()->hole_check_mode());
|
||||
return true;
|
||||
}
|
||||
|
||||
void BytecodeGenerator::VisitConsecutivePrototypeAssignments(
|
||||
const base::SmallVector<std::pair<const AstRawString*, Expression*>,
|
||||
kInitialPropertyCount>& properties,
|
||||
- Variable* var) {
|
||||
+ Variable* var, HoleCheckMode hole_check_mode) {
|
||||
// Create a boiler plate object in the constant pool to be merged into the
|
||||
// proto
|
||||
size_t entry = builder()->AllocateDeferredConstantPoolEntry();
|
||||
@@ -2428,7 +2431,7 @@ void BytecodeGenerator::VisitConsecutivePrototypeAssignments(
|
||||
first_idx = 0;
|
||||
}
|
||||
// Load the variable whose prototype is to be set into the Accumulator
|
||||
- BuildVariableLoad(var, HoleCheckMode::kElided);
|
||||
+ BuildVariableLoad(var, hole_check_mode);
|
||||
// Merge in-place proto-def boilerplate object into Accumulator
|
||||
builder()->SetPrototypeProperties(entry, first_idx);
|
||||
}
|
||||
@@ -2438,6 +2441,8 @@ void BytecodeGenerator::VisitStatements(
|
||||
for (int stmt_idx = start; stmt_idx < statements->length(); stmt_idx++) {
|
||||
if (v8_flags.proto_assign_seq_opt) {
|
||||
Variable* var = nullptr;
|
||||
+ HoleCheckMode hole_check_mode;
|
||||
+
|
||||
int proto_assign_idx = stmt_idx;
|
||||
base::SmallVector<std::pair<const AstRawString*, Expression*>,
|
||||
kInitialPropertyCount>
|
||||
@@ -2445,13 +2450,13 @@ void BytecodeGenerator::VisitStatements(
|
||||
std::unordered_set<const AstRawString*> duplicates;
|
||||
while (proto_assign_idx < statements->length() &&
|
||||
IsPrototypeAssignment(statements->at(proto_assign_idx), &var,
|
||||
- properties, duplicates)) {
|
||||
+ &hole_check_mode, properties, duplicates)) {
|
||||
++proto_assign_idx;
|
||||
}
|
||||
|
||||
if (proto_assign_idx - stmt_idx > 1) {
|
||||
DCHECK_EQ((size_t)(proto_assign_idx - stmt_idx), properties.size());
|
||||
- VisitConsecutivePrototypeAssignments(properties, var);
|
||||
+ VisitConsecutivePrototypeAssignments(properties, var, hole_check_mode);
|
||||
stmt_idx = proto_assign_idx; // the outer loop should now ignore these
|
||||
// statements
|
||||
DCHECK(!builder()->RemainderOfBlockIsDead());
|
||||
diff --git a/src/interpreter/bytecode-generator.h b/src/interpreter/bytecode-generator.h
|
||||
index b6421819c353febe283069852645a6b85e4c855a..41c5cda1ca6dd4017b329e41bad8af3bcc4ee242 100644
|
||||
--- a/src/interpreter/bytecode-generator.h
|
||||
+++ b/src/interpreter/bytecode-generator.h
|
||||
@@ -72,7 +72,7 @@ class BytecodeGenerator final : public AstVisitor<BytecodeGenerator> {
|
||||
static constexpr int kInitialPropertyCount = 64;
|
||||
|
||||
bool IsPrototypeAssignment(
|
||||
- Statement* stmt, Variable** var,
|
||||
+ Statement* stmt, Variable** var, HoleCheckMode* hole_check_mode,
|
||||
base::SmallVector<std::pair<const AstRawString*, Expression*>,
|
||||
kInitialPropertyCount>& properties,
|
||||
std::unordered_set<const AstRawString*>& duplicate);
|
||||
@@ -80,7 +80,7 @@ class BytecodeGenerator final : public AstVisitor<BytecodeGenerator> {
|
||||
void VisitConsecutivePrototypeAssignments(
|
||||
const base::SmallVector<std::pair<const AstRawString*, Expression*>,
|
||||
kInitialPropertyCount>& properties,
|
||||
- Variable* var);
|
||||
+ Variable* var, HoleCheckMode hole_check_mode);
|
||||
// Visiting function for declarations list and statements are overridden.
|
||||
void VisitModuleDeclarations(Declaration::List* declarations);
|
||||
void VisitGlobalDeclarations(Declaration::List* declarations);
|
||||
diff --git a/src/runtime/runtime-literals.cc b/src/runtime/runtime-literals.cc
|
||||
index 83074253314c438eed3006332c63c6bf7dfe4421..ded3b466625c99da6f27936ae4e5e0c879baec1b 100644
|
||||
--- a/src/runtime/runtime-literals.cc
|
||||
+++ b/src/runtime/runtime-literals.cc
|
||||
@@ -613,7 +613,7 @@ static DirectHandle<Object> InstantiateIfSharedFunctionInfo(
|
||||
}
|
||||
|
||||
static MaybeDirectHandle<Object> SetPrototypePropertiesSlow(
|
||||
- Isolate* isolate, DirectHandle<Context> context, DirectHandle<JSObject> obj,
|
||||
+ Isolate* isolate, DirectHandle<Context> context, DirectHandle<JSAny> obj,
|
||||
Handle<ObjectBoilerplateDescription> object_boilerplate_description,
|
||||
DirectHandle<ClosureFeedbackCellArray> feedback_cell_array,
|
||||
int& current_slot, int start_index = 0) {
|
||||
@@ -684,7 +684,7 @@ RUNTIME_FUNCTION(Runtime_SetPrototypeProperties) {
|
||||
HandleScope scope(isolate);
|
||||
DCHECK_EQ(4, args.length());
|
||||
DirectHandle<Context> context(isolate->context(), isolate);
|
||||
- DirectHandle<JSObject> obj = args.at<JSObject>(0); // acc JS Object
|
||||
+ DirectHandle<JSAny> obj = args.at<JSAny>(0); // acc JS Object
|
||||
Handle<ObjectBoilerplateDescription> object_boilerplate_description =
|
||||
args.at<ObjectBoilerplateDescription>(1);
|
||||
DirectHandle<ClosureFeedbackCellArray> feedback_cell_array =
|
||||
diff --git a/test/unittests/interpreter/bytecode_expectations/SetPrototypePropertiesOptimization.golden b/test/unittests/interpreter/bytecode_expectations/SetPrototypePropertiesOptimization.golden
|
||||
index 84ebbb755f8a5432c2e8da3d26ceb648bee2cf2d..bb9d697caec6e79810fa757abec4b71ad4cf3f2f 100644
|
||||
--- a/test/unittests/interpreter/bytecode_expectations/SetPrototypePropertiesOptimization.golden
|
||||
+++ b/test/unittests/interpreter/bytecode_expectations/SetPrototypePropertiesOptimization.golden
|
||||
@@ -50,15 +50,17 @@ snippet: "
|
||||
"
|
||||
frame size: 0
|
||||
parameter count: 1
|
||||
-bytecode array length: 7
|
||||
+bytecode array length: 9
|
||||
bytecodes: [
|
||||
B(LdaImmutableCurrentContextSlot), U8(2),
|
||||
- /* 109 E> */ B(SetPrototypeProperties), U8(0), U8(0),
|
||||
+ /* 109 E> */ B(ThrowReferenceErrorIfHole), U8(1),
|
||||
+ B(SetPrototypeProperties), U8(0), U8(0),
|
||||
B(LdaUndefined),
|
||||
/* 245 S> */ B(Return),
|
||||
]
|
||||
constant pool: [
|
||||
OBJECT_BOILERPLATE_DESCRIPTION_TYPE,
|
||||
+ INTERNALIZED_ONE_BYTE_STRING_TYPE ["MyClass"],
|
||||
]
|
||||
handlers: [
|
||||
]
|
||||
@@ -325,7 +325,7 @@ index 181d298bfa27d21f013016b34a586078d12f8a58..92d6f7b36d4c5c0a64723f7d18427a62
|
||||
|
||||
#undef TRACE
|
||||
diff --git a/src/compiler/turboshaft/turbolev-graph-builder.cc b/src/compiler/turboshaft/turbolev-graph-builder.cc
|
||||
index 9d1dafe2b0b733c88283b21eddb36c9827912eca..bcb461488899bcbf3a130845f39f0005bd34131e 100644
|
||||
index 3db187b8c48cc0c7168be039e7d90078c4df7bda..d80362036da4c80e192ed489e3c66e8bfed271ba 100644
|
||||
--- a/src/compiler/turboshaft/turbolev-graph-builder.cc
|
||||
+++ b/src/compiler/turboshaft/turbolev-graph-builder.cc
|
||||
@@ -118,12 +118,7 @@ class BlockOriginTrackingReducer : public Next {
|
||||
|
||||
@@ -40,6 +40,7 @@ DevToolsSecurity -enable
|
||||
# security import "$dir"/public.key -k $KEY_CHAIN
|
||||
|
||||
# Generate Trust Settings
|
||||
# TODO: Remove NPX
|
||||
npm_config_yes=true npx ts-node "$(dirname $0)"/gen-trust.ts "$dir"/certificate.cer "$dir"/trust.xml
|
||||
|
||||
# Import Trust Settings
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
const chalk = require('chalk');
|
||||
const { GitProcess } = require('dugite');
|
||||
|
||||
const childProcess = require('node:child_process');
|
||||
const fs = require('node:fs');
|
||||
const os = require('node:os');
|
||||
const path = require('node:path');
|
||||
@@ -61,13 +61,16 @@ function getAbsoluteElectronExec () {
|
||||
return path.resolve(SRC_DIR, getElectronExec());
|
||||
}
|
||||
|
||||
async function handleGitCall (args, gitDir) {
|
||||
const details = await GitProcess.exec(args, gitDir);
|
||||
if (details.exitCode === 0) {
|
||||
return details.stdout.replace(/^\*|\s+|\s+$/, '');
|
||||
function handleGitCall (args, gitDir) {
|
||||
const result = childProcess.spawnSync('git', args, {
|
||||
cwd: gitDir,
|
||||
encoding: 'utf8',
|
||||
stdio: ['inherit', 'pipe', 'pipe']
|
||||
});
|
||||
if (result.status === 0) {
|
||||
return result.stdout.replace(/^\*|\s+|\s+$/, '');
|
||||
} else {
|
||||
const error = GitProcess.parseError(details.stderr);
|
||||
console.log(`${fail} couldn't parse git process call: `, error);
|
||||
console.log(`${fail} couldn't parse git process call: `, result.stderr);
|
||||
process.exit(1);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1,6 +1,5 @@
|
||||
#!/usr/bin/env node
|
||||
|
||||
const { GitProcess } = require('dugite');
|
||||
const { ESLint } = require('eslint');
|
||||
const minimist = require('minimist');
|
||||
|
||||
@@ -153,7 +152,7 @@ const LINTERS = [{
|
||||
}, {
|
||||
key: 'javascript',
|
||||
roots: ['build', 'default_app', 'lib', 'npm', 'script', 'spec'],
|
||||
ignoreRoots: ['spec/node_modules'],
|
||||
ignoreRoots: ['spec/node_modules', 'spec/fixtures/native-addon'],
|
||||
test: filename => filename.endsWith('.js') || filename.endsWith('.ts') || filename.endsWith('.mjs'),
|
||||
run: async (opts, filenames) => {
|
||||
const eslint = new ESLint({
|
||||
@@ -282,7 +281,7 @@ const LINTERS = [{
|
||||
}, {
|
||||
key: 'md',
|
||||
roots: ['.'],
|
||||
ignoreRoots: ['.git', 'node_modules', 'spec/node_modules'],
|
||||
ignoreRoots: ['.git', 'node_modules', 'spec/node_modules', 'spec/fixtures/native-addon'],
|
||||
test: filename => filename.endsWith('.md'),
|
||||
run: async (opts, filenames) => {
|
||||
const { getCodeBlocks } = await import('@electron/lint-roller/dist/lib/markdown.js');
|
||||
@@ -431,9 +430,13 @@ function populateLinterWithArgs (linter, opts) {
|
||||
}
|
||||
|
||||
async function findChangedFiles (top) {
|
||||
const result = await GitProcess.exec(['diff', '--name-only', '--cached'], top);
|
||||
if (result.exitCode !== 0) {
|
||||
console.log('Failed to find changed files', GitProcess.parseError(result.stderr));
|
||||
const result = childProcess.spawnSync('git', ['diff', '--name-only', '--cached'], {
|
||||
cwd: top,
|
||||
encoding: 'utf8',
|
||||
stdio: ['inherit', 'pipe', 'pipe']
|
||||
});
|
||||
if (result.status !== 0) {
|
||||
console.log('Failed to find changed files', result.stderr);
|
||||
process.exit(1);
|
||||
}
|
||||
const relativePaths = result.stdout.split(/\r\n|\r|\n/g);
|
||||
|
||||
@@ -9,7 +9,7 @@ const NAN_DIR = path.resolve(BASE, 'third_party', 'nan');
|
||||
const NPX_CMD = process.platform === 'win32' ? 'npx.cmd' : 'npx';
|
||||
|
||||
const utils = require('./lib/utils');
|
||||
const { YARN_VERSION } = require('./yarn');
|
||||
const { YARN_SCRIPT_PATH } = require('./yarn');
|
||||
|
||||
if (!require.main) {
|
||||
throw new Error('Must call the nan spec runner directly');
|
||||
@@ -106,13 +106,12 @@ async function main () {
|
||||
stdio: 'inherit',
|
||||
shell: process.platform === 'win32'
|
||||
});
|
||||
|
||||
if (buildStatus !== 0 || signal != null) {
|
||||
console.error('Failed to build nan test modules');
|
||||
return process.exit(buildStatus !== 0 ? buildStatus : signal);
|
||||
}
|
||||
|
||||
const { status: installStatus, signal: installSignal } = cp.spawnSync(NPX_CMD, [`yarn@${YARN_VERSION}`, 'install'], {
|
||||
const { status: installStatus, signal: installSignal } = cp.spawnSync(process.execPath, [YARN_SCRIPT_PATH, 'install'], {
|
||||
env,
|
||||
cwd: NAN_DIR,
|
||||
stdio: 'inherit',
|
||||
|
||||
@@ -113,6 +113,7 @@
|
||||
"parallel/test-tls-passphrase",
|
||||
"parallel/test-tls-peer-certificate",
|
||||
"parallel/test-tls-pfx-authorizationerror",
|
||||
"parallel/test-tls-psk-alpn-callback-exception-handling",
|
||||
"parallel/test-tls-psk-circuit",
|
||||
"parallel/test-tls-reduced-SECLEVEL-in-cipher",
|
||||
"parallel/test-tls-root-certificates",
|
||||
|
||||
@@ -13,6 +13,7 @@ import { createGitHubTokenStrategy } from '../github-token';
|
||||
import { ELECTRON_ORG, ELECTRON_REPO, ElectronReleaseRepo, NIGHTLY_REPO } from '../types';
|
||||
|
||||
const rootPackageJson = JSON.parse(fs.readFileSync(path.resolve(__dirname, '../../../package.json'), 'utf-8'));
|
||||
rootPackageJson.name = 'electron';
|
||||
|
||||
if (!process.env.ELECTRON_NPM_OTP) {
|
||||
console.error('Please set ELECTRON_NPM_OTP');
|
||||
@@ -211,6 +212,7 @@ new Promise<string>((resolve, reject) => {
|
||||
});
|
||||
})
|
||||
.then((tarballPath) => {
|
||||
// TODO: Remove NPX
|
||||
const existingVersionJSON = childProcess.execSync(`npx npm@7 view ${rootPackageJson.name}@${currentElectronVersion} --json`).toString('utf-8');
|
||||
// It's possible this is a re-run and we already have published the package, if not we just publish like normal
|
||||
if (!existingVersionJSON) {
|
||||
|
||||
@@ -1,9 +1,9 @@
|
||||
#!/usr/bin/env node
|
||||
|
||||
import { Octokit } from '@octokit/rest';
|
||||
import { GitProcess } from 'dugite';
|
||||
import { valid, compare, gte, lte } from 'semver';
|
||||
|
||||
import { spawnSync } from 'node:child_process';
|
||||
import { basename } from 'node:path';
|
||||
import { parseArgs } from 'node:util';
|
||||
|
||||
@@ -20,8 +20,12 @@ const semverify = (version: string) => version.replace(/^origin\//, '').replace(
|
||||
|
||||
const runGit = async (args: string[]) => {
|
||||
console.info(`Running: git ${args.join(' ')}`);
|
||||
const response = await GitProcess.exec(args, ELECTRON_DIR);
|
||||
if (response.exitCode !== 0) {
|
||||
const response = spawnSync('git', args, {
|
||||
cwd: ELECTRON_DIR,
|
||||
encoding: 'utf8',
|
||||
stdio: ['inherit', 'pipe', 'pipe']
|
||||
});
|
||||
if (response.status !== 0) {
|
||||
throw new Error(response.stderr.trim());
|
||||
}
|
||||
return response.stdout.trim();
|
||||
|
||||
@@ -1,8 +1,8 @@
|
||||
#!/usr/bin/env node
|
||||
|
||||
import { Octokit } from '@octokit/rest';
|
||||
import { GitProcess } from 'dugite';
|
||||
|
||||
import { spawnSync } from 'node:child_process';
|
||||
import { existsSync, readFileSync, writeFileSync, mkdirSync } from 'node:fs';
|
||||
import { resolve as _resolve } from 'node:path';
|
||||
|
||||
@@ -105,8 +105,13 @@ class Pool {
|
||||
**/
|
||||
|
||||
const runGit = async (dir: string, args: string[]) => {
|
||||
const response = await GitProcess.exec(args, dir);
|
||||
if (response.exitCode !== 0) {
|
||||
const response = spawnSync('git', args, {
|
||||
cwd: dir,
|
||||
encoding: 'utf8',
|
||||
stdio: ['inherit', 'pipe', 'pipe'],
|
||||
maxBuffer: 100 * 1024 * 1024 // 100MB buffer to handle large git outputs
|
||||
});
|
||||
if (response.status !== 0) {
|
||||
throw new Error(response.stderr.trim());
|
||||
}
|
||||
return response.stdout.trim();
|
||||
|
||||
@@ -1,8 +1,7 @@
|
||||
import { Octokit } from '@octokit/rest';
|
||||
import * as chalk from 'chalk';
|
||||
import { GitProcess } from 'dugite';
|
||||
|
||||
import { execSync } from 'node:child_process';
|
||||
import { execSync, spawnSync } from 'node:child_process';
|
||||
import { join } from 'node:path';
|
||||
|
||||
import { createGitHubTokenStrategy } from './github-token';
|
||||
@@ -166,11 +165,12 @@ async function createRelease (
|
||||
}
|
||||
|
||||
async function pushRelease (branch: string) {
|
||||
const pushDetails = await GitProcess.exec(
|
||||
['push', 'origin', `HEAD:${branch}`, '--follow-tags'],
|
||||
ELECTRON_DIR
|
||||
);
|
||||
if (pushDetails.exitCode === 0) {
|
||||
const pushDetails = spawnSync('git', ['push', 'origin', `HEAD:${branch}`, '--follow-tags'], {
|
||||
cwd: ELECTRON_DIR,
|
||||
encoding: 'utf8',
|
||||
stdio: ['inherit', 'pipe', 'pipe']
|
||||
});
|
||||
if (pushDetails.status === 0) {
|
||||
console.log(
|
||||
`${pass} Successfully pushed the release. Wait for ` +
|
||||
'release builds to finish before running "npm run release".'
|
||||
@@ -191,11 +191,12 @@ async function runReleaseBuilds (branch: string, newVersion: string) {
|
||||
|
||||
async function tagRelease (version: string) {
|
||||
console.log(`Tagging release ${version}.`);
|
||||
const checkoutDetails = await GitProcess.exec(
|
||||
['tag', '-a', '-m', version, version],
|
||||
ELECTRON_DIR
|
||||
);
|
||||
if (checkoutDetails.exitCode === 0) {
|
||||
const checkoutDetails = spawnSync('git', ['tag', '-a', '-m', version, version], {
|
||||
cwd: ELECTRON_DIR,
|
||||
encoding: 'utf8',
|
||||
stdio: ['inherit', 'pipe', 'pipe']
|
||||
});
|
||||
if (checkoutDetails.status === 0) {
|
||||
console.log(`${pass} Successfully tagged ${version}.`);
|
||||
} else {
|
||||
console.log(
|
||||
|
||||
@@ -1,6 +1,7 @@
|
||||
import { GitProcess } from 'dugite';
|
||||
import * as semver from 'semver';
|
||||
|
||||
import { spawnSync } from 'node:child_process';
|
||||
|
||||
import { ELECTRON_DIR } from '../lib/utils';
|
||||
|
||||
export enum PreType {
|
||||
@@ -27,7 +28,11 @@ export const isStable = (v: string) => {
|
||||
|
||||
export async function nextAlpha (v: string) {
|
||||
const next = semver.coerce(semver.clean(v));
|
||||
const tagBlob = await GitProcess.exec(['tag', '--list', '-l', `v${next}-alpha.*`], ELECTRON_DIR);
|
||||
const tagBlob = spawnSync('git', ['tag', '--list', '-l', `v${next}-alpha.*`], {
|
||||
cwd: ELECTRON_DIR,
|
||||
encoding: 'utf8',
|
||||
stdio: ['inherit', 'pipe', 'pipe']
|
||||
});
|
||||
const tags = tagBlob.stdout.split('\n').filter(e => e !== '');
|
||||
tags.sort((t1, t2) => {
|
||||
const a = parseInt(t1.split('.').pop()!, 10);
|
||||
@@ -41,7 +46,11 @@ export async function nextAlpha (v: string) {
|
||||
|
||||
export async function nextBeta (v: string) {
|
||||
const next = semver.coerce(semver.clean(v));
|
||||
const tagBlob = await GitProcess.exec(['tag', '--list', '-l', `v${next}-beta.*`], ELECTRON_DIR);
|
||||
const tagBlob = spawnSync('git', ['tag', '--list', '-l', `v${next}-beta.*`], {
|
||||
cwd: ELECTRON_DIR,
|
||||
encoding: 'utf8',
|
||||
stdio: ['inherit', 'pipe', 'pipe']
|
||||
});
|
||||
const tags = tagBlob.stdout.split('\n').filter(e => e !== '');
|
||||
tags.sort((t1, t2) => {
|
||||
const a = parseInt(t1.split('.').pop()!, 10);
|
||||
@@ -57,7 +66,11 @@ export async function nextNightly (v: string) {
|
||||
let next = semver.valid(semver.coerce(v));
|
||||
const pre = `nightly.${getCurrentDate()}`;
|
||||
|
||||
const branch = (await GitProcess.exec(['rev-parse', '--abbrev-ref', 'HEAD'], ELECTRON_DIR)).stdout.trim();
|
||||
const branch = spawnSync('git', ['rev-parse', '--abbrev-ref', 'HEAD'], {
|
||||
cwd: ELECTRON_DIR,
|
||||
encoding: 'utf8',
|
||||
stdio: ['inherit', 'pipe', 'pipe']
|
||||
}).stdout.trim();
|
||||
if (branch === 'main') {
|
||||
next = semver.inc(await getLastMajorForMain(), 'major');
|
||||
} else if (isStable(v)) {
|
||||
@@ -69,8 +82,12 @@ export async function nextNightly (v: string) {
|
||||
|
||||
async function getLastMajorForMain () {
|
||||
let branchNames;
|
||||
const result = await GitProcess.exec(['branch', '-a', '--remote', '--list', 'origin/[0-9]*-x-y'], ELECTRON_DIR);
|
||||
if (result.exitCode === 0) {
|
||||
const result = spawnSync('git', ['branch', '-a', '--remote', '--list', 'origin/[0-9]*-x-y'], {
|
||||
cwd: ELECTRON_DIR,
|
||||
encoding: 'utf8',
|
||||
stdio: ['inherit', 'pipe', 'pipe']
|
||||
});
|
||||
if (result.status === 0) {
|
||||
branchNames = result.stdout.trim().split('\n');
|
||||
const filtered = branchNames.map(b => b.replace('origin/', ''));
|
||||
return getNextReleaseBranch(filtered);
|
||||
|
||||
@@ -114,11 +114,14 @@ async function runClangTidy (
|
||||
outDir: string,
|
||||
filenames: string[],
|
||||
checks: string = '',
|
||||
jobs: number = 1
|
||||
jobs: number = 1,
|
||||
fix: boolean = false
|
||||
): Promise<boolean> {
|
||||
const cmd = path.resolve(LLVM_BIN, 'clang-tidy');
|
||||
const args = [`-p=${outDir}`, '--use-color'];
|
||||
const args = [`-p=${outDir}`];
|
||||
|
||||
if (!process.env.CI) args.push('--use-color');
|
||||
if (fix) args.push('--fix');
|
||||
if (checks) args.push(`--checks=${checks}`);
|
||||
|
||||
// Remove any files that aren't in the compilation database to prevent
|
||||
@@ -209,7 +212,7 @@ function parseCommandLine () {
|
||||
if (!arg || arg.startsWith('-')) {
|
||||
console.log(
|
||||
'Usage: script/run-clang-tidy.ts [-h|--help] [--jobs|-j] ' +
|
||||
'[--checks] --out-dir OUTDIR [file1 file2]'
|
||||
'[--fix] [--checks] --out-dir OUTDIR [file1 file2]'
|
||||
);
|
||||
process.exit(0);
|
||||
}
|
||||
@@ -218,7 +221,7 @@ function parseCommandLine () {
|
||||
};
|
||||
|
||||
const opts = minimist(process.argv.slice(2), {
|
||||
boolean: ['help'],
|
||||
boolean: ['fix', 'help'],
|
||||
string: ['checks', 'out-dir'],
|
||||
default: { jobs: 1 },
|
||||
alias: { help: 'h', jobs: 'j' },
|
||||
@@ -270,17 +273,23 @@ async function main (): Promise<boolean> {
|
||||
const filenames = [];
|
||||
|
||||
if (opts._.length > 0) {
|
||||
if (opts._.some((filename) => filename.endsWith('.h'))) {
|
||||
throw new ErrorWithExitCode(
|
||||
'Filenames must be for translation units, not headers', 3
|
||||
);
|
||||
}
|
||||
|
||||
filenames.push(...opts._.map((filename) => path.resolve(filename)));
|
||||
} else {
|
||||
filenames.push(
|
||||
...(await findMatchingFiles(
|
||||
path.resolve(SOURCE_ROOT, 'shell'),
|
||||
(filename: string) => /.*\.(?:cc|h|mm)$/.test(filename)
|
||||
(filename: string) => /.*\.(?:cc|mm)$/.test(filename)
|
||||
))
|
||||
);
|
||||
}
|
||||
|
||||
return runClangTidy(outDir, filenames, opts.checks, opts.jobs);
|
||||
return runClangTidy(outDir, filenames, opts.checks, opts.jobs, opts.fix);
|
||||
}
|
||||
|
||||
if (require.main === module) {
|
||||
|
||||
@@ -21,6 +21,7 @@ const fail = chalk.red('✗');
|
||||
const FAILURE_STATUS_KEY = 'Electron_Spec_Runner_Failures';
|
||||
|
||||
const args = minimist(process.argv, {
|
||||
boolean: ['skipYarnInstall'],
|
||||
string: ['runners', 'target', 'electronVersion'],
|
||||
number: ['enableRerun'],
|
||||
unknown: arg => unknownFlags.push(arg)
|
||||
@@ -36,10 +37,9 @@ for (const flag of unknownFlags) {
|
||||
}
|
||||
|
||||
const utils = require('./lib/utils');
|
||||
const { YARN_VERSION } = require('./yarn');
|
||||
const { YARN_SCRIPT_PATH } = require('./yarn');
|
||||
|
||||
const BASE = path.resolve(__dirname, '../..');
|
||||
const NPX_CMD = process.platform === 'win32' ? 'npx.cmd' : 'npx';
|
||||
|
||||
const runners = new Map([
|
||||
['main', { description: 'Main process specs', run: runMainProcessElectronTests }]
|
||||
@@ -96,7 +96,7 @@ async function main () {
|
||||
const somethingChanged = (currentSpecHash !== lastSpecHash) ||
|
||||
(lastSpecInstallHash !== currentSpecInstallHash);
|
||||
|
||||
if (somethingChanged) {
|
||||
if (somethingChanged && !args.skipYarnInstall) {
|
||||
await installSpecModules(path.resolve(__dirname, '..', 'spec'));
|
||||
await getSpecHash().then(saveSpecHash);
|
||||
}
|
||||
@@ -375,7 +375,7 @@ async function runTestUsingElectron (specDir, testName, shouldRerun, additionalA
|
||||
if (shouldRerun) {
|
||||
await rerunFailedTests(specDir, testName);
|
||||
} else {
|
||||
return false;
|
||||
process.exit(1);
|
||||
}
|
||||
}
|
||||
console.log(`${pass} Electron ${testName} process tests passed.`);
|
||||
@@ -419,7 +419,8 @@ async function installSpecModules (dir) {
|
||||
if (fs.existsSync(path.resolve(dir, 'node_modules'))) {
|
||||
await fs.promises.rm(path.resolve(dir, 'node_modules'), { force: true, recursive: true });
|
||||
}
|
||||
const { status } = childProcess.spawnSync(NPX_CMD, [`yarn@${YARN_VERSION}`, 'install', '--frozen-lockfile'], {
|
||||
const yarnArgs = [YARN_SCRIPT_PATH, 'install', '--immutable'];
|
||||
const { status } = childProcess.spawnSync(process.execPath, yarnArgs, {
|
||||
env,
|
||||
cwd: dir,
|
||||
stdio: 'inherit',
|
||||
@@ -429,14 +430,27 @@ async function installSpecModules (dir) {
|
||||
console.log(`${fail} Failed to yarn install in '${dir}'`);
|
||||
process.exit(1);
|
||||
}
|
||||
|
||||
if (process.platform === 'linux') {
|
||||
const { status: rebuildStatus } = childProcess.spawnSync('npm', ['rebuild', 'abstract-socket'], {
|
||||
env,
|
||||
cwd: dir,
|
||||
stdio: 'inherit',
|
||||
shell: process.platform === 'win32'
|
||||
});
|
||||
if (rebuildStatus !== 0) {
|
||||
console.log(`${fail} Failed to rebuild abstract-socket native module`);
|
||||
process.exit(1);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
function getSpecHash () {
|
||||
return Promise.all([
|
||||
(async () => {
|
||||
const hasher = crypto.createHash('SHA256');
|
||||
hasher.update(fs.readFileSync(path.resolve(__dirname, '../yarn.lock')));
|
||||
hasher.update(fs.readFileSync(path.resolve(__dirname, '../spec/package.json')));
|
||||
hasher.update(fs.readFileSync(path.resolve(__dirname, '../spec/yarn.lock')));
|
||||
hasher.update(fs.readFileSync(path.resolve(__dirname, '../script/spec-runner.js')));
|
||||
return hasher.digest('hex');
|
||||
})(),
|
||||
|
||||
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user