mirror of
https://github.com/electron/electron.git
synced 2026-04-10 03:01:51 -04:00
Compare commits
40 Commits
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
7007907df0 | ||
|
|
2c8b6ee0c0 | ||
|
|
4c64377ead | ||
|
|
0ef056130c | ||
|
|
64373df3ca | ||
|
|
13e44072be | ||
|
|
16a038502a | ||
|
|
00a492d282 | ||
|
|
290a77b843 | ||
|
|
87baa17e65 | ||
|
|
e6928c1319 | ||
|
|
976a7bece5 | ||
|
|
03244a56f1 | ||
|
|
8e0f534873 | ||
|
|
1573d6b28c | ||
|
|
1b3e1433dd | ||
|
|
e551cf8c00 | ||
|
|
bd3abf3a2c | ||
|
|
da140aea7c | ||
|
|
8699ce4f98 | ||
|
|
5fded6ae88 | ||
|
|
0e6e480a8b | ||
|
|
44b21205c7 | ||
|
|
db8e94113b | ||
|
|
db7ed2bfc9 | ||
|
|
315496c148 | ||
|
|
842290c50f | ||
|
|
9bf952f1c5 | ||
|
|
7594783ff8 | ||
|
|
f929de8896 | ||
|
|
37bb19a3e3 | ||
|
|
f5016aaec0 | ||
|
|
17697b193d | ||
|
|
3679fd56e7 | ||
|
|
09a028cf8b | ||
|
|
d0978d2812 | ||
|
|
143faed926 | ||
|
|
3e6086d930 | ||
|
|
7549704f1a | ||
|
|
48c473fa06 |
2
.github/actions/checkout/action.yml
vendored
2
.github/actions/checkout/action.yml
vendored
@@ -43,7 +43,7 @@ runs:
|
||||
curl --unix-socket /var/run/sas/sas.sock --fail "http://foo/$CACHE_FILE?platform=${{ inputs.target-platform }}&getAccountName=true" > sas-token
|
||||
- name: Save SAS Key
|
||||
if: ${{ inputs.generate-sas-token == 'true' }}
|
||||
uses: actions/cache/save@5a3ec84eff668545956fd18022155c47e93e2684 # v4.2.3
|
||||
uses: actions/cache/save@cdf6c1fa76f9f475f3d7449005a359c84ca0f306 # v5.0.3
|
||||
with:
|
||||
path: sas-token
|
||||
key: sas-key-${{ inputs.target-platform }}-${{ github.run_number }}-${{ github.run_attempt }}
|
||||
|
||||
@@ -7,7 +7,7 @@ runs:
|
||||
shell: bash
|
||||
id: yarn-cache-dir-path
|
||||
run: echo "dir=$(node src/electron/script/yarn.js config get cacheFolder)" >> $GITHUB_OUTPUT
|
||||
- uses: actions/cache@5a3ec84eff668545956fd18022155c47e93e2684 # v4.2.3
|
||||
- uses: actions/cache@cdf6c1fa76f9f475f3d7449005a359c84ca0f306 # v5.0.3
|
||||
id: yarn-cache
|
||||
with:
|
||||
path: ${{ steps.yarn-cache-dir-path.outputs.dir }}
|
||||
|
||||
2
.github/workflows/archaeologist-dig.yml
vendored
2
.github/workflows/archaeologist-dig.yml
vendored
@@ -13,7 +13,7 @@ jobs:
|
||||
contents: read
|
||||
steps:
|
||||
- name: Checkout Electron
|
||||
uses: actions/checkout@11bd71901bbe5b1630ceea73d27597364c9af683 #v4.0.2
|
||||
uses: actions/checkout@de0fac2e4500dabe0009e67214ff5f5447ce83dd #v6.0.2
|
||||
with:
|
||||
fetch-depth: 0
|
||||
- name: Setup Node.js/npm
|
||||
|
||||
6
.github/workflows/build-git-cache.yml
vendored
6
.github/workflows/build-git-cache.yml
vendored
@@ -23,7 +23,7 @@ jobs:
|
||||
GCLIENT_EXTRA_ARGS: '--custom-var=checkout_arm=True --custom-var=checkout_arm64=True'
|
||||
steps:
|
||||
- name: Checkout Electron
|
||||
uses: actions/checkout@11bd71901bbe5b1630ceea73d27597364c9af683
|
||||
uses: actions/checkout@de0fac2e4500dabe0009e67214ff5f5447ce83dd
|
||||
with:
|
||||
path: src/electron
|
||||
fetch-depth: 0
|
||||
@@ -47,7 +47,7 @@ jobs:
|
||||
TARGET_OS: 'win'
|
||||
steps:
|
||||
- name: Checkout Electron
|
||||
uses: actions/checkout@11bd71901bbe5b1630ceea73d27597364c9af683
|
||||
uses: actions/checkout@de0fac2e4500dabe0009e67214ff5f5447ce83dd
|
||||
with:
|
||||
path: src/electron
|
||||
fetch-depth: 0
|
||||
@@ -72,7 +72,7 @@ jobs:
|
||||
GCLIENT_EXTRA_ARGS: '--custom-var=checkout_mac=True --custom-var=host_os=mac'
|
||||
steps:
|
||||
- name: Checkout Electron
|
||||
uses: actions/checkout@11bd71901bbe5b1630ceea73d27597364c9af683
|
||||
uses: actions/checkout@de0fac2e4500dabe0009e67214ff5f5447ce83dd
|
||||
with:
|
||||
path: src/electron
|
||||
fetch-depth: 0
|
||||
|
||||
8
.github/workflows/build.yml
vendored
8
.github/workflows/build.yml
vendored
@@ -57,7 +57,7 @@ jobs:
|
||||
build-image-sha: ${{ steps.set-output.outputs.build-image-sha }}
|
||||
docs-only: ${{ steps.set-output.outputs.docs-only }}
|
||||
steps:
|
||||
- uses: actions/checkout@11bd71901bbe5b1630ceea73d27597364c9af683 #v4.0.2
|
||||
- uses: actions/checkout@de0fac2e4500dabe0009e67214ff5f5447ce83dd #v6.0.2
|
||||
with:
|
||||
ref: ${{ github.event.pull_request.head.sha }}
|
||||
- uses: dorny/paths-filter@de90cc6fb38fc0963ad72b210f1f284cd68cea36 # v3.0.2
|
||||
@@ -124,7 +124,7 @@ jobs:
|
||||
build-image-sha: ${{ needs.setup.outputs.build-image-sha }}
|
||||
steps:
|
||||
- name: Checkout Electron
|
||||
uses: actions/checkout@11bd71901bbe5b1630ceea73d27597364c9af683
|
||||
uses: actions/checkout@de0fac2e4500dabe0009e67214ff5f5447ce83dd
|
||||
with:
|
||||
path: src/electron
|
||||
fetch-depth: 0
|
||||
@@ -156,7 +156,7 @@ jobs:
|
||||
build-image-sha: ${{ needs.setup.outputs.build-image-sha}}
|
||||
steps:
|
||||
- name: Checkout Electron
|
||||
uses: actions/checkout@11bd71901bbe5b1630ceea73d27597364c9af683
|
||||
uses: actions/checkout@de0fac2e4500dabe0009e67214ff5f5447ce83dd
|
||||
with:
|
||||
path: src/electron
|
||||
fetch-depth: 0
|
||||
@@ -188,7 +188,7 @@ jobs:
|
||||
build-image-sha: ${{ needs.setup.outputs.build-image-sha}}
|
||||
steps:
|
||||
- name: Checkout Electron
|
||||
uses: actions/checkout@11bd71901bbe5b1630ceea73d27597364c9af683
|
||||
uses: actions/checkout@de0fac2e4500dabe0009e67214ff5f5447ce83dd
|
||||
with:
|
||||
path: src/electron
|
||||
fetch-depth: 0
|
||||
|
||||
2
.github/workflows/linux-publish.yml
vendored
2
.github/workflows/linux-publish.yml
vendored
@@ -35,7 +35,7 @@ jobs:
|
||||
GCLIENT_EXTRA_ARGS: '--custom-var=checkout_arm=True --custom-var=checkout_arm64=True'
|
||||
steps:
|
||||
- name: Checkout Electron
|
||||
uses: actions/checkout@11bd71901bbe5b1630ceea73d27597364c9af683
|
||||
uses: actions/checkout@de0fac2e4500dabe0009e67214ff5f5447ce83dd
|
||||
with:
|
||||
path: src/electron
|
||||
fetch-depth: 0
|
||||
|
||||
2
.github/workflows/macos-publish.yml
vendored
2
.github/workflows/macos-publish.yml
vendored
@@ -36,7 +36,7 @@ jobs:
|
||||
GCLIENT_EXTRA_ARGS: '--custom-var=checkout_mac=True --custom-var=host_os=mac'
|
||||
steps:
|
||||
- name: Checkout Electron
|
||||
uses: actions/checkout@11bd71901bbe5b1630ceea73d27597364c9af683
|
||||
uses: actions/checkout@de0fac2e4500dabe0009e67214ff5f5447ce83dd
|
||||
with:
|
||||
path: src/electron
|
||||
fetch-depth: 0
|
||||
|
||||
@@ -27,7 +27,7 @@ jobs:
|
||||
container: ${{ fromJSON(inputs.container) }}
|
||||
steps:
|
||||
- name: Checkout Electron
|
||||
uses: actions/checkout@11bd71901bbe5b1630ceea73d27597364c9af683
|
||||
uses: actions/checkout@de0fac2e4500dabe0009e67214ff5f5447ce83dd
|
||||
with:
|
||||
path: src/electron
|
||||
fetch-depth: 0
|
||||
@@ -43,7 +43,7 @@ jobs:
|
||||
with:
|
||||
target-platform: linux
|
||||
- name: Checkout Electron
|
||||
uses: actions/checkout@11bd71901bbe5b1630ceea73d27597364c9af683
|
||||
uses: actions/checkout@de0fac2e4500dabe0009e67214ff5f5447ce83dd
|
||||
with:
|
||||
path: src/electron
|
||||
fetch-depth: 0
|
||||
|
||||
2
.github/workflows/pipeline-electron-lint.yml
vendored
2
.github/workflows/pipeline-electron-lint.yml
vendored
@@ -27,7 +27,7 @@ jobs:
|
||||
container: ${{ fromJSON(inputs.container) }}
|
||||
steps:
|
||||
- name: Checkout Electron
|
||||
uses: actions/checkout@11bd71901bbe5b1630ceea73d27597364c9af683
|
||||
uses: actions/checkout@de0fac2e4500dabe0009e67214ff5f5447ce83dd
|
||||
with:
|
||||
path: src/electron
|
||||
fetch-depth: 0
|
||||
|
||||
@@ -95,7 +95,7 @@ jobs:
|
||||
run: |
|
||||
mkdir src
|
||||
- name: Checkout Electron
|
||||
uses: actions/checkout@11bd71901bbe5b1630ceea73d27597364c9af683
|
||||
uses: actions/checkout@de0fac2e4500dabe0009e67214ff5f5447ce83dd
|
||||
with:
|
||||
path: src/electron
|
||||
fetch-depth: 0
|
||||
@@ -163,7 +163,7 @@ jobs:
|
||||
if: ${{ inputs.target-platform == 'linux' }}
|
||||
uses: ./src/electron/.github/actions/restore-cache-aks
|
||||
- name: Checkout Electron
|
||||
uses: actions/checkout@11bd71901bbe5b1630ceea73d27597364c9af683
|
||||
uses: actions/checkout@de0fac2e4500dabe0009e67214ff5f5447ce83dd
|
||||
with:
|
||||
path: src/electron
|
||||
fetch-depth: 0
|
||||
|
||||
@@ -48,7 +48,7 @@ jobs:
|
||||
container: ${{ fromJSON(inputs.check-container) }}
|
||||
steps:
|
||||
- name: Checkout Electron
|
||||
uses: actions/checkout@11bd71901bbe5b1630ceea73d27597364c9af683
|
||||
uses: actions/checkout@de0fac2e4500dabe0009e67214ff5f5447ce83dd
|
||||
with:
|
||||
path: src/electron
|
||||
fetch-depth: 0
|
||||
@@ -115,7 +115,7 @@ jobs:
|
||||
- name: Add CHROMIUM_BUILDTOOLS_PATH to env
|
||||
run: echo "CHROMIUM_BUILDTOOLS_PATH=$(pwd)/src/buildtools" >> $GITHUB_ENV
|
||||
- name: Checkout Electron
|
||||
uses: actions/checkout@11bd71901bbe5b1630ceea73d27597364c9af683
|
||||
uses: actions/checkout@de0fac2e4500dabe0009e67214ff5f5447ce83dd
|
||||
with:
|
||||
path: src/electron
|
||||
fetch-depth: 0
|
||||
|
||||
@@ -102,7 +102,7 @@ jobs:
|
||||
run: |
|
||||
mkdir src
|
||||
- name: Checkout Electron
|
||||
uses: actions/checkout@11bd71901bbe5b1630ceea73d27597364c9af683
|
||||
uses: actions/checkout@de0fac2e4500dabe0009e67214ff5f5447ce83dd
|
||||
with:
|
||||
path: src/electron
|
||||
fetch-depth: 0
|
||||
@@ -172,7 +172,7 @@ jobs:
|
||||
if: ${{ inputs.target-platform == 'linux' }}
|
||||
uses: ./src/electron/.github/actions/restore-cache-aks
|
||||
- name: Checkout Electron
|
||||
uses: actions/checkout@11bd71901bbe5b1630ceea73d27597364c9af683
|
||||
uses: actions/checkout@de0fac2e4500dabe0009e67214ff5f5447ce83dd
|
||||
with:
|
||||
path: src/electron
|
||||
fetch-depth: 0
|
||||
|
||||
@@ -69,6 +69,7 @@ jobs:
|
||||
if: ${{ inputs.target-arch == 'arm' && inputs.target-platform == 'linux' }}
|
||||
run: |
|
||||
cp $(which node) /mnt/runner-externals/node20/bin/
|
||||
cp $(which node) /mnt/runner-externals/node24/bin/
|
||||
- name: Setup Node.js/npm
|
||||
if: ${{ inputs.target-platform == 'win' }}
|
||||
uses: actions/setup-node@49933ea5288caeca8642d1e84afbd3f7d6820020
|
||||
@@ -118,7 +119,7 @@ jobs:
|
||||
if: ${{ inputs.target-platform == 'macos' }}
|
||||
run: sudo xcode-select --switch /Applications/Xcode_16.4.app
|
||||
- name: Checkout Electron
|
||||
uses: actions/checkout@11bd71901bbe5b1630ceea73d27597364c9af683
|
||||
uses: actions/checkout@de0fac2e4500dabe0009e67214ff5f5447ce83dd
|
||||
with:
|
||||
path: src/electron
|
||||
fetch-depth: 0
|
||||
@@ -190,15 +191,25 @@ jobs:
|
||||
run: |
|
||||
cd src/out/Default
|
||||
unzip -:o dist.zip
|
||||
#- name: Import & Trust Self-Signed Codesigning Cert on MacOS
|
||||
# if: ${{ inputs.target-platform == 'macos' && inputs.target-arch == 'x64' }}
|
||||
# run: |
|
||||
# sudo security authorizationdb write com.apple.trust-settings.admin allow
|
||||
# cd src/electron
|
||||
# ./script/codesign/generate-identity.sh
|
||||
- name: Import & Trust Self-Signed Codesigning Cert on MacOS
|
||||
if: ${{ inputs.target-platform == 'macos' }}
|
||||
run: |
|
||||
cd src/electron
|
||||
./script/codesign/generate-identity.sh
|
||||
# Only sign on x64 — arm64 builds are already ad-hoc signed, and re-signing
|
||||
# with an untrusted cert breaks macOS system integrations (e.g. dock bounce).
|
||||
# Autoupdater tests sign their own fixture copies via signApp().
|
||||
- name: Sign Electron.app for macOS tests
|
||||
if: ${{ inputs.target-platform == 'macos' && inputs.target-arch == 'x64' }}
|
||||
run: |
|
||||
identity=$(src/electron/script/codesign/get-trusted-identity.sh)
|
||||
if [ -n "$identity" ]; then
|
||||
codesign -s "$identity" --deep --force src/out/Default/Electron.app
|
||||
fi
|
||||
|
||||
- name: Run Electron Tests
|
||||
shell: bash
|
||||
timeout-minutes: 40
|
||||
env:
|
||||
MOCHA_REPORTER: mocha-multi-reporters
|
||||
MOCHA_MULTI_REPORTERS: mocha-junit-reporter, tap
|
||||
@@ -249,6 +260,19 @@ jobs:
|
||||
|
||||
fi
|
||||
fi
|
||||
- name: Take screenshot on timeout or cancellation
|
||||
if: ${{ inputs.target-platform != 'linux' && (cancelled() || failure()) }}
|
||||
shell: bash
|
||||
run: |
|
||||
screenshot_dir="src/electron/spec/artifacts"
|
||||
mkdir -p "$screenshot_dir"
|
||||
screenshot_file="$screenshot_dir/screenshot-timeout-$(date +%Y%m%d%H%M%S).png"
|
||||
if [ "${{ inputs.target-platform }}" = "macos" ]; then
|
||||
screencapture -x "$screenshot_file" || true
|
||||
elif [ "${{ inputs.target-platform }}" = "win" ]; then
|
||||
powershell -command "Add-Type -AssemblyName System.Windows.Forms; \$screen = [System.Windows.Forms.Screen]::PrimaryScreen.Bounds; \$bitmap = New-Object System.Drawing.Bitmap(\$screen.Width, \$screen.Height); \$graphics = [System.Drawing.Graphics]::FromImage(\$bitmap); \$graphics.CopyFromScreen(\$screen.Location, [System.Drawing.Point]::Empty, \$screen.Size); \$bitmap.Save('$screenshot_file')" || true
|
||||
fi
|
||||
|
||||
- name: Upload Test results to Datadog
|
||||
env:
|
||||
DD_ENV: ci
|
||||
@@ -264,7 +288,7 @@ jobs:
|
||||
fi
|
||||
if: always() && !cancelled()
|
||||
- name: Upload Test Artifacts
|
||||
if: always() && !cancelled()
|
||||
if: always()
|
||||
uses: actions/upload-artifact@ea165f8d65b6e75b540449e92b4886f43607fa02
|
||||
with:
|
||||
name: test_artifacts_${{ env.ARTIFACT_KEY }}_${{ matrix.shard }}
|
||||
|
||||
@@ -50,7 +50,7 @@ jobs:
|
||||
container: ${{ fromJSON(inputs.test-container) }}
|
||||
steps:
|
||||
- name: Checkout Electron
|
||||
uses: actions/checkout@11bd71901bbe5b1630ceea73d27597364c9af683
|
||||
uses: actions/checkout@de0fac2e4500dabe0009e67214ff5f5447ce83dd
|
||||
with:
|
||||
path: src/electron
|
||||
fetch-depth: 0
|
||||
@@ -106,7 +106,7 @@ jobs:
|
||||
container: ${{ fromJSON(inputs.test-container) }}
|
||||
steps:
|
||||
- name: Checkout Electron
|
||||
uses: actions/checkout@11bd71901bbe5b1630ceea73d27597364c9af683
|
||||
uses: actions/checkout@de0fac2e4500dabe0009e67214ff5f5447ce83dd
|
||||
with:
|
||||
path: src/electron
|
||||
fetch-depth: 0
|
||||
|
||||
2
.github/workflows/scorecards.yml
vendored
2
.github/workflows/scorecards.yml
vendored
@@ -22,7 +22,7 @@ jobs:
|
||||
|
||||
steps:
|
||||
- name: "Checkout code"
|
||||
uses: actions/checkout@11bd71901bbe5b1630ceea73d27597364c9af683 # v4.2.2
|
||||
uses: actions/checkout@de0fac2e4500dabe0009e67214ff5f5447ce83dd # v4.2.2
|
||||
with:
|
||||
persist-credentials: false
|
||||
|
||||
|
||||
2
.github/workflows/windows-publish.yml
vendored
2
.github/workflows/windows-publish.yml
vendored
@@ -40,7 +40,7 @@ jobs:
|
||||
build-image-sha: ${{ inputs.build-image-sha }}
|
||||
steps:
|
||||
- name: Checkout Electron
|
||||
uses: actions/checkout@11bd71901bbe5b1630ceea73d27597364c9af683
|
||||
uses: actions/checkout@de0fac2e4500dabe0009e67214ff5f5447ce83dd
|
||||
with:
|
||||
path: src/electron
|
||||
fetch-depth: 0
|
||||
|
||||
@@ -9,4 +9,8 @@ npmMinimalAgeGate: 10080
|
||||
npmPreapprovedPackages:
|
||||
- "@electron/*"
|
||||
|
||||
httpProxy: "${HTTP_PROXY:-}"
|
||||
|
||||
httpsProxy: "${HTTPS_PROXY:-}"
|
||||
|
||||
yarnPath: .yarn/releases/yarn-4.12.0.cjs
|
||||
|
||||
2
DEPS
2
DEPS
@@ -4,7 +4,7 @@ vars = {
|
||||
'chromium_version':
|
||||
'142.0.7444.265',
|
||||
'node_version':
|
||||
'v22.22.0',
|
||||
'v22.22.1',
|
||||
'nan_version':
|
||||
'e14bdcd1f72d62bca1d541b66da43130384ec213',
|
||||
'squirrel.mac_version':
|
||||
|
||||
@@ -94,7 +94,7 @@ The `desktopCapturer` module has the following methods:
|
||||
Returns `Promise<DesktopCapturerSource[]>` - Resolves with an array of [`DesktopCapturerSource`](structures/desktop-capturer-source.md) objects, each `DesktopCapturerSource` represents a screen or an individual window that can be captured.
|
||||
|
||||
> [!NOTE]
|
||||
|
||||
<!-- markdownlint-disable-next-line MD032 -->
|
||||
> * Capturing audio requires `NSAudioCaptureUsageDescription` Info.plist key on macOS 14.2 Sonoma and higher - [read more](#macos-versions-142-or-higher).
|
||||
> * Capturing the screen contents requires user consent on macOS 10.15 Catalina or higher, which can detected by [`systemPreferences.getMediaAccessStatus`][].
|
||||
|
||||
@@ -109,30 +109,41 @@ Returns `Promise<DesktopCapturerSource[]>` - Resolves with an array of [`Desktop
|
||||
|
||||
PipeWire supports a single capture for both screens and windows. If you request the window and screen type, the selected source will be returned as a window capture.
|
||||
|
||||
---
|
||||
### macOS versions 14.2 or higher
|
||||
|
||||
### MacOS versions 14.2 or higher
|
||||
|
||||
`NSAudioCaptureUsageDescription` Info.plist key must be added in-order for audio to be captured by `desktopCapturer`. If instead you are running electron from another program like a terminal or IDE then that parent program must contain the Info.plist key.
|
||||
`NSAudioCaptureUsageDescription` Info.plist key must be added in order for audio to be captured by
|
||||
`desktopCapturer`. If instead you are running Electron from another program like a terminal or IDE
|
||||
then that parent program must contain the Info.plist key.
|
||||
|
||||
This is in order to facillitate use of Apple's new [CoreAudio Tap API](https://developer.apple.com/documentation/CoreAudio/capturing-system-audio-with-core-audio-taps#Configure-the-sample-code-project) by Chromium.
|
||||
|
||||
> [!WARNING]
|
||||
> Failure of `desktopCapturer` to start an audio stream due to `NSAudioCaptureUsageDescription` permission not present will still create a dead audio stream however no warnings or errors are displayed.
|
||||
> Failure of `desktopCapturer` to start an audio stream due to `NSAudioCaptureUsageDescription`
|
||||
> permission not present will still create a dead audio stream however no warnings or errors are
|
||||
> displayed.
|
||||
|
||||
As of electron `v39.0.0-beta.4` Chromium [made Apple's new `CoreAudio Tap API` the default](https://source.chromium.org/chromium/chromium/src/+/ad17e8f8b93d5f34891b06085d373a668918255e) for desktop audio capture. There is no fallback to the older `Screen & System Audio Recording` permissions system even if [CoreAudio Tap API](https://developer.apple.com/documentation/CoreAudio/capturing-system-audio-with-core-audio-taps) stream creation fails.
|
||||
As of Electron `v39.0.0-beta.4`, Chromium [made Apple's new `CoreAudio Tap API` the default](https://source.chromium.org/chromium/chromium/src/+/ad17e8f8b93d5f34891b06085d373a668918255e)
|
||||
for desktop audio capture. There is no fallback to the older `Screen & System Audio Recording`
|
||||
permissions system even if [CoreAudio Tap API](https://developer.apple.com/documentation/CoreAudio/capturing-system-audio-with-core-audio-taps) stream creation fails.
|
||||
|
||||
If you need to continue using `Screen & System Audio Recording` permissions for `desktopCapturer` on macOS versions 14.2 and later, you can apply a chromium feature flag to force use of that older permissions system:
|
||||
If you need to continue using `Screen & System Audio Recording` permissions for `desktopCapturer`
|
||||
on macOS versions 14.2 and later, you can apply a Chromium feature flag to force use of that older
|
||||
permissions system:
|
||||
|
||||
```js
|
||||
// main.js (right beneath your require/import statments)
|
||||
app.commandLine.appendSwitch('disable-features', 'MacCatapLoopbackAudioForScreenShare')
|
||||
```
|
||||
|
||||
---
|
||||
### macOS versions 12.7.6 or lower
|
||||
|
||||
### MacOS versions 12.7.6 or lower
|
||||
`navigator.mediaDevices.getUserMedia` does not work on macOS versions 12.7.6 and prior for audio
|
||||
capture due to a fundamental limitation whereby apps that want to access the system's audio require
|
||||
a [signed kernel extension](https://developer.apple.com/library/archive/documentation/Security/Conceptual/System_Integrity_Protection_Guide/KernelExtensions/KernelExtensions.html).
|
||||
Chromium, and by extension Electron, does not provide this. Only in macOS 13 and onwards does Apple
|
||||
provide APIs to capture desktop audio without the need for a signed kernel extension.
|
||||
|
||||
`navigator.mediaDevices.getUserMedia` does not work on macOS versions 12.7.6 and prior for audio capture due to a fundamental limitation whereby apps that want to access the system's audio require a [signed kernel extension](https://developer.apple.com/library/archive/documentation/Security/Conceptual/System_Integrity_Protection_Guide/KernelExtensions/KernelExtensions.html). Chromium, and by extension Electron, does not provide this. Only in macOS 13 and onwards does Apple provide APIs to capture desktop audio without the need for a signed kernel extension.
|
||||
|
||||
It is possible to circumvent this limitation by capturing system audio with another macOS app like [BlackHole](https://existential.audio/blackhole/) or [Soundflower](https://rogueamoeba.com/freebies/soundflower/) and passing it through a virtual audio input device. This virtual device can then be queried with `navigator.mediaDevices.getUserMedia`.
|
||||
It is possible to circumvent this limitation by capturing system audio with another macOS app like
|
||||
[BlackHole](https://existential.audio/blackhole/) or [Soundflower](https://rogueamoeba.com/freebies/soundflower/)
|
||||
and passing it through a virtual audio input device. This virtual device can then be queried
|
||||
with `navigator.mediaDevices.getUserMedia`.
|
||||
|
||||
@@ -110,6 +110,8 @@ Returns [`Point`](structures/point.md)
|
||||
|
||||
The current absolute position of the mouse pointer.
|
||||
|
||||
Not supported on Wayland (Linux).
|
||||
|
||||
> [!NOTE]
|
||||
> The return value is a DIP point, not a screen physical point.
|
||||
|
||||
|
||||
@@ -113,6 +113,8 @@ filenames = {
|
||||
"shell/browser/win/scoped_hstring.h",
|
||||
"shell/common/api/electron_api_native_image_win.cc",
|
||||
"shell/common/application_info_win.cc",
|
||||
"shell/common/command_line_util_win.cc",
|
||||
"shell/common/command_line_util_win.h",
|
||||
"shell/common/language_util_win.cc",
|
||||
"shell/common/node_bindings_win.cc",
|
||||
"shell/common/node_bindings_win.h",
|
||||
|
||||
@@ -8,13 +8,19 @@ const {
|
||||
isOnBatteryPower
|
||||
} = process._linkedBinding('electron_browser_power_monitor');
|
||||
|
||||
// Hold the native PowerMonitor at module level so it is never garbage-collected
|
||||
// while this module is alive. The C++ side registers OS-level callbacks (HWND
|
||||
// user-data on Windows, shutdown handler on macOS, notification observers) that
|
||||
// prevent safe collection of the C++ wrapper while those registrations exist.
|
||||
let pm: any;
|
||||
|
||||
class PowerMonitor extends EventEmitter implements Electron.PowerMonitor {
|
||||
constructor () {
|
||||
super();
|
||||
// Don't start the event source until both a) the app is ready and b)
|
||||
// there's a listener registered for a powerMonitor event.
|
||||
this.once('newListener', () => {
|
||||
const pm = createPowerMonitor();
|
||||
pm = createPowerMonitor();
|
||||
pm.emit = this.emit.bind(this);
|
||||
|
||||
if (process.platform === 'linux') {
|
||||
|
||||
@@ -777,8 +777,7 @@ WebContents.prototype._init = function () {
|
||||
const originCounts = new Map<string, number>();
|
||||
const openDialogs = new Set<AbortController>();
|
||||
this.on('-run-dialog', async (info, callback) => {
|
||||
const originUrl = new URL(info.frame.url);
|
||||
const origin = originUrl.protocol === 'file:' ? originUrl.href : originUrl.origin;
|
||||
const origin = info.frame.origin === 'file://' ? info.frame.url : info.frame.origin;
|
||||
if ((originCounts.get(origin) ?? 0) < 0) return callback(false, '');
|
||||
|
||||
const prefs = this.getLastWebPreferences();
|
||||
|
||||
@@ -19,8 +19,8 @@ export function invokeInWebContents<T> (sender: Electron.WebContents, command: s
|
||||
const requestId = ++nextId;
|
||||
const channel = `${command}_RESPONSE_${requestId}`;
|
||||
ipcMainInternal.on(channel, function handler (event, error: Error, result: any) {
|
||||
if (event.type === 'frame' && event.sender !== sender) {
|
||||
console.error(`Reply to ${command} sent by unexpected WebContents (${event.sender.id})`);
|
||||
if (event.type !== 'frame' || event.sender !== sender) {
|
||||
console.error(`Reply to ${command} sent by unexpected sender`);
|
||||
return;
|
||||
}
|
||||
|
||||
|
||||
@@ -1232,6 +1232,8 @@ export const wrapFsWithAsar = (fs: Record<string, any>) => {
|
||||
// has filesystem caching.
|
||||
overrideAPI(fs, 'copyFile');
|
||||
overrideAPISync(fs, 'copyFileSync');
|
||||
overrideAPI(fs, 'cp');
|
||||
overrideAPISync(fs, 'cpSync');
|
||||
|
||||
overrideAPI(fs, 'open');
|
||||
overrideAPISync(process, 'dlopen', 1);
|
||||
|
||||
@@ -23,11 +23,14 @@ export default contextBridge;
|
||||
|
||||
export const internalContextBridge = {
|
||||
contextIsolationEnabled: process.contextIsolated,
|
||||
tryOverrideGlobalValueFromIsolatedWorld: (keys: string[], value: any) => {
|
||||
return binding._overrideGlobalValueFromIsolatedWorld(keys, value, true, true);
|
||||
},
|
||||
overrideGlobalValueFromIsolatedWorld: (keys: string[], value: any) => {
|
||||
return binding._overrideGlobalValueFromIsolatedWorld(keys, value, false);
|
||||
return binding._overrideGlobalValueFromIsolatedWorld(keys, value, false, false);
|
||||
},
|
||||
overrideGlobalValueWithDynamicPropsFromIsolatedWorld: (keys: string[], value: any) => {
|
||||
return binding._overrideGlobalValueFromIsolatedWorld(keys, value, true);
|
||||
return binding._overrideGlobalValueFromIsolatedWorld(keys, value, true, false);
|
||||
},
|
||||
overrideGlobalPropertyFromIsolatedWorld: (keys: string[], getter: Function, setter?: Function) => {
|
||||
return binding._overrideGlobalPropertyFromIsolatedWorld(keys, getter, setter || null);
|
||||
|
||||
@@ -11,14 +11,12 @@ const { contextIsolationEnabled } = internalContextBridge;
|
||||
* 1) Use menu API to show context menu.
|
||||
*/
|
||||
window.onload = function () {
|
||||
if (window.InspectorFrontendHost) {
|
||||
if (contextIsolationEnabled) {
|
||||
internalContextBridge.overrideGlobalValueFromIsolatedWorld([
|
||||
'InspectorFrontendHost', 'showContextMenuAtPoint'
|
||||
], createMenu);
|
||||
} else {
|
||||
window.InspectorFrontendHost.showContextMenuAtPoint = createMenu;
|
||||
}
|
||||
if (contextIsolationEnabled) {
|
||||
internalContextBridge.tryOverrideGlobalValueFromIsolatedWorld([
|
||||
'InspectorFrontendHost', 'showContextMenuAtPoint'
|
||||
], createMenu);
|
||||
} else {
|
||||
window.InspectorFrontendHost!.showContextMenuAtPoint = createMenu;
|
||||
}
|
||||
};
|
||||
|
||||
|
||||
2
patches/angle/.patches
Normal file
2
patches/angle/.patches
Normal file
@@ -0,0 +1,2 @@
|
||||
cherry-pick-a08731cf6d70.patch
|
||||
cherry-pick-bf6dd974238b.patch
|
||||
239
patches/angle/cherry-pick-a08731cf6d70.patch
Normal file
239
patches/angle/cherry-pick-a08731cf6d70.patch
Normal file
@@ -0,0 +1,239 @@
|
||||
From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001
|
||||
From: Shahbaz Youssefi <syoussefi@chromium.org>
|
||||
Date: Thu, 19 Feb 2026 14:42:08 -0500
|
||||
Subject: Vulkan: Avoid overflow in texture size calculation
|
||||
|
||||
Bug: chromium:485622239
|
||||
Change-Id: Idf9847afa0aa2e72b6433ac8348ae2820c1ad8c5
|
||||
Reviewed-on: https://chromium-review.googlesource.com/c/angle/angle/+/7595734
|
||||
Reviewed-by: Amirali Abdolrashidi <abdolrashidi@google.com>
|
||||
Commit-Queue: Shahbaz Youssefi <syoussefi@chromium.org>
|
||||
|
||||
diff --git a/src/libANGLE/renderer/vulkan/TextureVk.cpp b/src/libANGLE/renderer/vulkan/TextureVk.cpp
|
||||
index 0459bb7fc8a415e21563de813a306d1801f1a39e..8b152a581d4ebae1cc4c0cb0a95d02434a43f24d 100644
|
||||
--- a/src/libANGLE/renderer/vulkan/TextureVk.cpp
|
||||
+++ b/src/libANGLE/renderer/vulkan/TextureVk.cpp
|
||||
@@ -3069,8 +3069,17 @@ angle::Result TextureVk::reinitImageAsRenderable(ContextVk *contextVk, const vk:
|
||||
// invalidate must be called after wait for finish.
|
||||
ANGLE_TRY(srcBuffer->invalidate(renderer));
|
||||
|
||||
- size_t dstBufferSize = sourceBox.width * sourceBox.height * sourceBox.depth *
|
||||
- dstFormat.pixelBytes * layerCount;
|
||||
+ // Use size_t calculations to avoid 32-bit overflows. Note that the dimensions are bound by
|
||||
+ // the maximums specified in Constants.h, and that gl::Box members are signed 32-bit
|
||||
+ // integers.
|
||||
+ static_assert(gl::IMPLEMENTATION_MAX_2D_TEXTURE_SIZE *
|
||||
+ gl::IMPLEMENTATION_MAX_2D_TEXTURE_SIZE <
|
||||
+ std::numeric_limits<int32_t>::max());
|
||||
+ size_t dstBufferSize = sourceBox.width * sourceBox.height;
|
||||
+ static_assert(gl::IMPLEMENTATION_MAX_3D_TEXTURE_SIZE *
|
||||
+ gl::IMPLEMENTATION_MAX_2D_ARRAY_TEXTURE_LAYERS * 16 <
|
||||
+ std::numeric_limits<int32_t>::max());
|
||||
+ dstBufferSize *= sourceBox.depth * dstFormat.pixelBytes * layerCount;
|
||||
|
||||
// Allocate memory in the destination texture for the copy/conversion.
|
||||
uint8_t *dstData = nullptr;
|
||||
diff --git a/src/tests/gl_tests/FramebufferTest.cpp b/src/tests/gl_tests/FramebufferTest.cpp
|
||||
index 020a0416881e85ebff9a6fa2f902e61f899477b9..f72f1a7674eab758487be0bf30bee5150a0e7508 100644
|
||||
--- a/src/tests/gl_tests/FramebufferTest.cpp
|
||||
+++ b/src/tests/gl_tests/FramebufferTest.cpp
|
||||
@@ -8894,6 +8894,62 @@ TEST_P(FramebufferTest_ES31, MixesMultisampleTextureRenderbuffer)
|
||||
ASSERT_GL_NO_ERROR();
|
||||
}
|
||||
|
||||
+// Test that 2D array texture size calculation doesn't overflow internally when rendering to it. An
|
||||
+// RGB format is used which is often emualted with RGBA.
|
||||
+//
|
||||
+// Practically we cannot run this test. On most configurations, allocating a 4GB texture fails due
|
||||
+// to internal driver limitations. On the few configs that the test actually runs, allocating such
|
||||
+// large memory leads to instability.
|
||||
+TEST_P(FramebufferTest_ES3, DISABLED_MaxSize2DArrayNoOverflow)
|
||||
+{
|
||||
+ GLint maxTexture2DSize;
|
||||
+ glGetIntegerv(GL_MAX_TEXTURE_SIZE, &maxTexture2DSize);
|
||||
+
|
||||
+ maxTexture2DSize = std::min(maxTexture2DSize, 16384);
|
||||
+
|
||||
+ // Create a 2D array texture with RGB format. Every layer is going to take 1GB of memory (if
|
||||
+ // emulated with RGBA), so only create 4 layers of it (for a total of 4GB of memory). If 32-bit
|
||||
+ // math is involved when calculating sizes related to this texture, they will overflow.
|
||||
+ constexpr uint32_t kLayers = 4;
|
||||
+ GLTexture tex;
|
||||
+ glBindTexture(GL_TEXTURE_2D_ARRAY, tex);
|
||||
+ glTexStorage3D(GL_TEXTURE_2D_ARRAY, 1, GL_RGB8, maxTexture2DSize, maxTexture2DSize, kLayers);
|
||||
+ glTexParameteri(GL_TEXTURE_2D_ARRAY, GL_TEXTURE_MIN_FILTER, GL_NEAREST);
|
||||
+ glTexParameteri(GL_TEXTURE_2D_ARRAY, GL_TEXTURE_MAG_FILTER, GL_NEAREST);
|
||||
+
|
||||
+ // Initialize the texture so its content is considered valid and worth preserving.
|
||||
+ constexpr int kValidSubsectionWidth = 16;
|
||||
+ constexpr int kValidSubsectionHeight = 20;
|
||||
+ std::vector<GLColorRGB> data(kValidSubsectionWidth * kValidSubsectionHeight,
|
||||
+ GLColorRGB(0, 255, 0));
|
||||
+ for (uint32_t layer = 0; layer < kLayers; ++layer)
|
||||
+ {
|
||||
+ glTexSubImage3D(GL_TEXTURE_2D_ARRAY, 0, 0, 0, layer, kValidSubsectionWidth,
|
||||
+ kValidSubsectionHeight, 1, GL_RGB, GL_UNSIGNED_BYTE, data.data());
|
||||
+ }
|
||||
+
|
||||
+ // Draw with the texture, making sure it's initialized and data is flushed.
|
||||
+ ANGLE_GL_PROGRAM(drawTex2DArray, essl3_shaders::vs::Texture2DArray(),
|
||||
+ essl3_shaders::fs::Texture2DArray());
|
||||
+ drawQuad(drawTex2DArray, essl3_shaders::PositionAttrib(), 0.5f);
|
||||
+
|
||||
+ // Bind a framebuffer to the texture and render into it. In some backends, the texture is
|
||||
+ // recreated to RGBA to be renderable.
|
||||
+ GLFramebuffer fbo;
|
||||
+ glBindFramebuffer(GL_FRAMEBUFFER, fbo);
|
||||
+ glFramebufferTextureLayer(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, tex, 0, 1);
|
||||
+
|
||||
+ ANGLE_GL_PROGRAM(drawRed, essl1_shaders::vs::Simple(), essl1_shaders::fs::Red());
|
||||
+ glViewport(0, 0, kValidSubsectionWidth / 2, kValidSubsectionHeight);
|
||||
+ drawQuad(drawRed, essl1_shaders::PositionAttrib(), 0.5f);
|
||||
+
|
||||
+ EXPECT_PIXEL_RECT_EQ(0, 0, kValidSubsectionWidth / 2, kValidSubsectionHeight, GLColor::red);
|
||||
+ EXPECT_PIXEL_RECT_EQ(kValidSubsectionWidth / 2, 0,
|
||||
+ kValidSubsectionWidth - kValidSubsectionWidth / 2, kValidSubsectionHeight,
|
||||
+ GLColor::green);
|
||||
+ ASSERT_GL_NO_ERROR();
|
||||
+}
|
||||
+
|
||||
ANGLE_INSTANTIATE_TEST_ES2_AND(AddMockTextureNoRenderTargetTest,
|
||||
ES2_D3D9().enable(Feature::AddMockTextureNoRenderTarget),
|
||||
ES2_D3D11().enable(Feature::AddMockTextureNoRenderTarget));
|
||||
diff --git a/src/tests/gl_tests/VulkanImageTest.cpp b/src/tests/gl_tests/VulkanImageTest.cpp
|
||||
index 2f06e2d5d9240371865f0adccc80f0d622c2199a..87e7482d971851c3bfd78818ce8b9ffc5e4bfa4d 100644
|
||||
--- a/src/tests/gl_tests/VulkanImageTest.cpp
|
||||
+++ b/src/tests/gl_tests/VulkanImageTest.cpp
|
||||
@@ -677,8 +677,8 @@ TEST_P(VulkanMemoryTest, AllocateVMAImageAfterFreeing2DArrayGarbageWhenDeviceOOM
|
||||
kTextureHeight, 1, GL_RGBA, GL_UNSIGNED_BYTE, textureColor.data());
|
||||
}
|
||||
|
||||
- ANGLE_GL_PROGRAM(drawTex2DArray, essl1_shaders::vs::Texture2DArray(),
|
||||
- essl1_shaders::fs::Texture2DArray());
|
||||
+ ANGLE_GL_PROGRAM(drawTex2DArray, essl3_shaders::vs::Texture2DArray(),
|
||||
+ essl3_shaders::fs::Texture2DArray());
|
||||
drawQuad(drawTex2DArray, essl1_shaders::PositionAttrib(), 0.5f);
|
||||
|
||||
// Fill up the device memory until we start allocating on the system memory.
|
||||
diff --git a/util/shader_utils.cpp b/util/shader_utils.cpp
|
||||
index 45f5461c36820c26ea1718e575bde65f1e181548..84ba2674884787edb43972f1bda970b474c58fd9 100644
|
||||
--- a/util/shader_utils.cpp
|
||||
+++ b/util/shader_utils.cpp
|
||||
@@ -582,18 +582,6 @@ void main()
|
||||
})";
|
||||
}
|
||||
|
||||
-const char *Texture2DArray()
|
||||
-{
|
||||
- return R"(#version 300 es
|
||||
-out vec2 v_texCoord;
|
||||
-in vec4 a_position;
|
||||
-void main()
|
||||
-{
|
||||
- gl_Position = vec4(a_position.xy, 0.0, 1.0);
|
||||
- v_texCoord = (a_position.xy * 0.5) + 0.5;
|
||||
-})";
|
||||
-}
|
||||
-
|
||||
} // namespace vs
|
||||
|
||||
namespace fs
|
||||
@@ -691,20 +679,6 @@ void main()
|
||||
})";
|
||||
}
|
||||
|
||||
-const char *Texture2DArray()
|
||||
-{
|
||||
- return R"(#version 300 es
|
||||
-precision highp float;
|
||||
-uniform highp sampler2DArray tex2DArray;
|
||||
-uniform int slice;
|
||||
-in vec2 v_texCoord;
|
||||
-out vec4 fragColor;
|
||||
-void main()
|
||||
-{
|
||||
- fragColor = texture(tex2DArray, vec3(v_texCoord, float(slice)));
|
||||
-})";
|
||||
-}
|
||||
-
|
||||
} // namespace fs
|
||||
} // namespace essl1_shaders
|
||||
|
||||
@@ -789,6 +763,18 @@ void main()
|
||||
})";
|
||||
}
|
||||
|
||||
+const char *Texture2DArray()
|
||||
+{
|
||||
+ return R"(#version 300 es
|
||||
+out vec2 v_texCoord;
|
||||
+in vec4 a_position;
|
||||
+void main()
|
||||
+{
|
||||
+ gl_Position = vec4(a_position.xy, 0.0, 1.0);
|
||||
+ v_texCoord = (a_position.xy * 0.5) + 0.5;
|
||||
+})";
|
||||
+}
|
||||
+
|
||||
} // namespace vs
|
||||
|
||||
namespace fs
|
||||
@@ -846,6 +832,20 @@ void main()
|
||||
})";
|
||||
}
|
||||
|
||||
+const char *Texture2DArray()
|
||||
+{
|
||||
+ return R"(#version 300 es
|
||||
+precision highp float;
|
||||
+uniform highp sampler2DArray tex2DArray;
|
||||
+uniform int slice;
|
||||
+in vec2 v_texCoord;
|
||||
+out vec4 fragColor;
|
||||
+void main()
|
||||
+{
|
||||
+ fragColor = texture(tex2DArray, vec3(v_texCoord, float(slice)));
|
||||
+})";
|
||||
+}
|
||||
+
|
||||
} // namespace fs
|
||||
} // namespace essl3_shaders
|
||||
|
||||
diff --git a/util/shader_utils.h b/util/shader_utils.h
|
||||
index 676341ebc55ea4984df68ab755444b49a5199f6f..cf211cfc9b1b48ae1de7368f8260e006f73e4219 100644
|
||||
--- a/util/shader_utils.h
|
||||
+++ b/util/shader_utils.h
|
||||
@@ -90,7 +90,6 @@ ANGLE_UTIL_EXPORT const char *Passthrough();
|
||||
// A shader that simply passes through attribute a_position, setting it to gl_Position and varying
|
||||
// texcoord.
|
||||
ANGLE_UTIL_EXPORT const char *Texture2D();
|
||||
-ANGLE_UTIL_EXPORT const char *Texture2DArray();
|
||||
|
||||
} // namespace vs
|
||||
|
||||
@@ -120,7 +119,6 @@ ANGLE_UTIL_EXPORT const char *Blue();
|
||||
|
||||
// A shader that samples the texture
|
||||
ANGLE_UTIL_EXPORT const char *Texture2D();
|
||||
-ANGLE_UTIL_EXPORT const char *Texture2DArray();
|
||||
|
||||
} // namespace fs
|
||||
} // namespace essl1_shaders
|
||||
@@ -151,6 +149,7 @@ ANGLE_UTIL_EXPORT const char *Passthrough();
|
||||
// A shader that simply passes through attribute a_position, setting it to gl_Position and varying
|
||||
// texcoord.
|
||||
ANGLE_UTIL_EXPORT const char *Texture2DLod();
|
||||
+ANGLE_UTIL_EXPORT const char *Texture2DArray();
|
||||
|
||||
} // namespace vs
|
||||
|
||||
@@ -169,6 +168,9 @@ ANGLE_UTIL_EXPORT const char *Blue();
|
||||
// A shader that samples the texture at a given lod.
|
||||
ANGLE_UTIL_EXPORT const char *Texture2DLod();
|
||||
|
||||
+// A shader that samples the texture at a given slice.
|
||||
+ANGLE_UTIL_EXPORT const char *Texture2DArray();
|
||||
+
|
||||
} // namespace fs
|
||||
} // namespace essl3_shaders
|
||||
|
||||
376
patches/angle/cherry-pick-bf6dd974238b.patch
Normal file
376
patches/angle/cherry-pick-bf6dd974238b.patch
Normal file
@@ -0,0 +1,376 @@
|
||||
From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001
|
||||
From: Geoff Lang <geofflang@chromium.org>
|
||||
Date: Wed, 11 Feb 2026 15:51:46 -0500
|
||||
Subject: Optionally validate GL_MAX_*_UNIFORM_BLOCKS at compile time.
|
||||
|
||||
These were validated at link time but some drivers have compiler crashes
|
||||
when compiling shaders with too many uniform blocks.
|
||||
|
||||
Bug: chromium:475877320
|
||||
Change-Id: I4413ce06307b4fe9e27105d85f66f610c235a301
|
||||
Reviewed-on: https://chromium-review.googlesource.com/c/angle/angle/+/7568089
|
||||
Commit-Queue: Geoff Lang <geofflang@chromium.org>
|
||||
Reviewed-by: Shahbaz Youssefi <syoussefi@chromium.org>
|
||||
|
||||
diff --git a/include/GLSLANG/ShaderLang.h b/include/GLSLANG/ShaderLang.h
|
||||
index a4d90d43b6e300d6a1158e1b5a9b623e0123f7ce..c87dfa42d6f71fa5d8e92a7e9b31c566e87ee16a 100644
|
||||
--- a/include/GLSLANG/ShaderLang.h
|
||||
+++ b/include/GLSLANG/ShaderLang.h
|
||||
@@ -26,7 +26,7 @@
|
||||
|
||||
// Version number for shader translation API.
|
||||
// It is incremented every time the API changes.
|
||||
-#define ANGLE_SH_VERSION 382
|
||||
+#define ANGLE_SH_VERSION 383
|
||||
|
||||
enum ShShaderSpec
|
||||
{
|
||||
@@ -388,6 +388,10 @@ struct ShCompileOptions
|
||||
|
||||
uint64_t forceShaderPrecisionHighpToMediump : 1;
|
||||
|
||||
+ // Validate that the count of uniform blocks is within the GL_MAX_*_UNIFORM_BLOCKS limits. These
|
||||
+ // limits must be supplied in the BuiltinResources.
|
||||
+ uint64_t validatePerStageMaxUniformBlocks : 1;
|
||||
+
|
||||
// Ask compiler to generate Vulkan transform feedback emulation support code.
|
||||
uint64_t addVulkanXfbEmulationSupportCode : 1;
|
||||
|
||||
@@ -587,6 +591,12 @@ struct ShBuiltInResources
|
||||
int MinProgramTexelOffset;
|
||||
int MaxProgramTexelOffset;
|
||||
|
||||
+ // GL_MAX_FRAGMENT_UNIFORM_BLOCKS
|
||||
+ int MaxFragmentUniformBlocks;
|
||||
+
|
||||
+ // GL_MAX_VERTEX_UNIFORM_BLOCKS
|
||||
+ int MaxVertexUniformBlocks;
|
||||
+
|
||||
// Extension constants.
|
||||
|
||||
// Value of GL_MAX_DUAL_SOURCE_DRAW_BUFFERS_EXT for OpenGL ES output context.
|
||||
@@ -704,6 +714,9 @@ struct ShBuiltInResources
|
||||
// maximum point size (higher limit from ALIASED_POINT_SIZE_RANGE)
|
||||
float MaxPointSize;
|
||||
|
||||
+ // GL_MAX_COMPUTE_UNIFORM_BLOCKS
|
||||
+ int MaxComputeUniformBlocks;
|
||||
+
|
||||
// EXT_geometry_shader constants
|
||||
int MaxGeometryUniformComponents;
|
||||
int MaxGeometryUniformBlocks;
|
||||
@@ -727,6 +740,7 @@ struct ShBuiltInResources
|
||||
int MaxTessControlImageUniforms;
|
||||
int MaxTessControlAtomicCounters;
|
||||
int MaxTessControlAtomicCounterBuffers;
|
||||
+ int MaxTessControlUniformBlocks;
|
||||
|
||||
int MaxTessPatchComponents;
|
||||
int MaxPatchVertices;
|
||||
@@ -739,6 +753,7 @@ struct ShBuiltInResources
|
||||
int MaxTessEvaluationImageUniforms;
|
||||
int MaxTessEvaluationAtomicCounters;
|
||||
int MaxTessEvaluationAtomicCounterBuffers;
|
||||
+ int MaxTessEvaluationUniformBlocks;
|
||||
|
||||
// Subpixel bits used in rasterization.
|
||||
int SubPixelBits;
|
||||
diff --git a/include/platform/autogen/FeaturesGL_autogen.h b/include/platform/autogen/FeaturesGL_autogen.h
|
||||
index c5fb020f74f23cb072732459f520823bfb97b82c..c492b8287a03b5cd3966caae4fc96ecf71317918 100644
|
||||
--- a/include/platform/autogen/FeaturesGL_autogen.h
|
||||
+++ b/include/platform/autogen/FeaturesGL_autogen.h
|
||||
@@ -632,6 +632,12 @@ struct FeaturesGL : FeatureSetBase
|
||||
&members,
|
||||
};
|
||||
|
||||
+ FeatureInfo validateMaxPerStageUniformBlocksAtCompileTime = {
|
||||
+ "validateMaxPerStageUniformBlocksAtCompileTime",
|
||||
+ FeatureCategory::OpenGLWorkarounds,
|
||||
+ &members,
|
||||
+ };
|
||||
+
|
||||
};
|
||||
|
||||
inline FeaturesGL::FeaturesGL() = default;
|
||||
diff --git a/include/platform/gl_features.json b/include/platform/gl_features.json
|
||||
index f69426154880aacbdeb1be35749ee765b8790a6f..656133772e36d4a9be0d006e3298437216ae0044 100644
|
||||
--- a/include/platform/gl_features.json
|
||||
+++ b/include/platform/gl_features.json
|
||||
@@ -820,6 +820,14 @@
|
||||
"Some Adreno drivers assume incorrect glSampleCoverage if new FBO is bound with different sample count"
|
||||
],
|
||||
"issue": "https://crbug.com/408364831"
|
||||
+ },
|
||||
+ {
|
||||
+ "name": "validate_max_per_stage_uniform_blocks_at_compile_time",
|
||||
+ "category": "Workarounds",
|
||||
+ "description": [
|
||||
+ "Validate GL_MAX_*_UNIFORM_BLOCKS at compile time instead of link time to work around compiler bugs."
|
||||
+ ],
|
||||
+ "issue": "http://crbug.com/475877320"
|
||||
}
|
||||
]
|
||||
}
|
||||
diff --git a/src/compiler/translator/Compiler.cpp b/src/compiler/translator/Compiler.cpp
|
||||
index bd5e6990fbde80f02faf42c2b914580737caa4b2..f966774d4e521527721b54fbe170595bf209600e 100644
|
||||
--- a/src/compiler/translator/Compiler.cpp
|
||||
+++ b/src/compiler/translator/Compiler.cpp
|
||||
@@ -1633,6 +1633,8 @@ void TCompiler::setResourceString()
|
||||
<< ":MaxFragmentInputVectors:" << mResources.MaxFragmentInputVectors
|
||||
<< ":MinProgramTexelOffset:" << mResources.MinProgramTexelOffset
|
||||
<< ":MaxProgramTexelOffset:" << mResources.MaxProgramTexelOffset
|
||||
+ << ":MaxFragmentUniformBlocks:" << mResources.MaxFragmentUniformBlocks
|
||||
+ << ":MaxVertexUniformBlocks:" << mResources.MaxVertexUniformBlocks
|
||||
<< ":MaxDualSourceDrawBuffers:" << mResources.MaxDualSourceDrawBuffers
|
||||
<< ":MaxViewsOVR:" << mResources.MaxViewsOVR
|
||||
<< ":NV_draw_buffers:" << mResources.NV_draw_buffers
|
||||
@@ -1682,6 +1684,7 @@ void TCompiler::setResourceString()
|
||||
<< ":MaxFragmentAtomicCounterBuffers:" << mResources.MaxFragmentAtomicCounterBuffers
|
||||
<< ":MaxCombinedAtomicCounterBuffers:" << mResources.MaxCombinedAtomicCounterBuffers
|
||||
<< ":MaxAtomicCounterBufferSize:" << mResources.MaxAtomicCounterBufferSize
|
||||
+ << ":MaxComputeUnformBlocks:" << mResources.MaxComputeUniformBlocks
|
||||
<< ":MaxGeometryUniformComponents:" << mResources.MaxGeometryUniformComponents
|
||||
<< ":MaxGeometryUniformBlocks:" << mResources.MaxGeometryUniformBlocks
|
||||
<< ":MaxGeometryInputComponents:" << mResources.MaxGeometryInputComponents
|
||||
@@ -1705,6 +1708,7 @@ void TCompiler::setResourceString()
|
||||
<< ":MaxTessControlImageUniforms:" << mResources.MaxTessControlImageUniforms
|
||||
<< ":MaxTessControlAtomicCounters:" << mResources.MaxTessControlAtomicCounters
|
||||
<< ":MaxTessControlAtomicCounterBuffers:" << mResources.MaxTessControlAtomicCounterBuffers
|
||||
+ << ":MaxTessControlUniformBlocks:" << mResources.MaxTessControlUniformBlocks
|
||||
<< ":MaxTessPatchComponents:" << mResources.MaxTessPatchComponents
|
||||
<< ":MaxPatchVertices:" << mResources.MaxPatchVertices
|
||||
<< ":MaxTessGenLevel:" << mResources.MaxTessGenLevel
|
||||
@@ -1714,7 +1718,9 @@ void TCompiler::setResourceString()
|
||||
<< ":MaxTessEvaluationUniformComponents:" << mResources.MaxTessEvaluationUniformComponents
|
||||
<< ":MaxTessEvaluationImageUniforms:" << mResources.MaxTessEvaluationImageUniforms
|
||||
<< ":MaxTessEvaluationAtomicCounters:" << mResources.MaxTessEvaluationAtomicCounters
|
||||
- << ":MaxTessEvaluationAtomicCounterBuffers:" << mResources.MaxTessEvaluationAtomicCounterBuffers;
|
||||
+ << ":MaxTessEvaluationAtomicCounterBuffers:" << mResources.MaxTessEvaluationAtomicCounterBuffers
|
||||
+ << ":MaxTessControlUniformBlocks:" << mResources.MaxTessControlUniformBlocks
|
||||
+ ;
|
||||
// clang-format on
|
||||
|
||||
mBuiltInResourcesString = strstream.str();
|
||||
diff --git a/src/compiler/translator/ParseContext.cpp b/src/compiler/translator/ParseContext.cpp
|
||||
index de788456a27399e0a25a57f737c2a7b5e73b848c..53a3f79a9302cbacd16e4080527ceb7f21feabdb 100644
|
||||
--- a/src/compiler/translator/ParseContext.cpp
|
||||
+++ b/src/compiler/translator/ParseContext.cpp
|
||||
@@ -250,6 +250,37 @@ bool IsSamplerOrStructWithOnlySamplers(const TType *type)
|
||||
{
|
||||
return IsSampler(type->getBasicType()) || type->isStructureContainingOnlySamplers();
|
||||
}
|
||||
+
|
||||
+unsigned int GetMaxUniformBlocksForShaderType(sh::GLenum shaderType,
|
||||
+ const ShCompileOptions &options,
|
||||
+ const ShBuiltInResources &resources)
|
||||
+{
|
||||
+ // If the validatePerStageMaxUniformBlocks workaround is disabled. Set a limit that will not be
|
||||
+ // hit.
|
||||
+ if (!options.validatePerStageMaxUniformBlocks)
|
||||
+ {
|
||||
+ return std::numeric_limits<unsigned int>::max();
|
||||
+ }
|
||||
+
|
||||
+ switch (shaderType)
|
||||
+ {
|
||||
+ case GL_FRAGMENT_SHADER:
|
||||
+ return resources.MaxFragmentUniformBlocks;
|
||||
+ case GL_VERTEX_SHADER:
|
||||
+ return resources.MaxVertexUniformBlocks;
|
||||
+ case GL_COMPUTE_SHADER:
|
||||
+ return resources.MaxComputeUniformBlocks;
|
||||
+ case GL_GEOMETRY_SHADER:
|
||||
+ return resources.MaxGeometryUniformBlocks;
|
||||
+ case GL_TESS_CONTROL_SHADER:
|
||||
+ return resources.MaxTessControlUniformBlocks;
|
||||
+ case GL_TESS_EVALUATION_SHADER:
|
||||
+ return resources.MaxTessEvaluationUniformBlocks;
|
||||
+ default:
|
||||
+ UNREACHABLE();
|
||||
+ return 0;
|
||||
+ }
|
||||
+}
|
||||
} // namespace
|
||||
|
||||
// This tracks each binding point's current default offset for inheritance of subsequent
|
||||
@@ -341,6 +372,8 @@ TParseContext::TParseContext(TSymbolTable &symt,
|
||||
mMaxAtomicCounterBufferSize(resources.MaxAtomicCounterBufferSize),
|
||||
mMaxShaderStorageBufferBindings(resources.MaxShaderStorageBufferBindings),
|
||||
mMaxPixelLocalStoragePlanes(resources.MaxPixelLocalStoragePlanes),
|
||||
+ mMaxUniformBlocks(GetMaxUniformBlocksForShaderType(mShaderType, options, resources)),
|
||||
+ mNumUniformBlocks(0),
|
||||
mDeclaringFunction(false),
|
||||
mDeclaringMain(false),
|
||||
mIsMainDeclared(false),
|
||||
@@ -5080,6 +5113,22 @@ TIntermDeclaration *TParseContext::addInterfaceBlock(
|
||||
error(arraySizesLine, "geometry shader input blocks must be an array", "");
|
||||
}
|
||||
|
||||
+ // Validate max uniform block limits
|
||||
+ if (typeQualifier.qualifier == EvqUniform)
|
||||
+ {
|
||||
+ unsigned int blockCount =
|
||||
+ arraySizes == nullptr || arraySizes->empty() ? 1 : (*arraySizes)[0];
|
||||
+ if (mNumUniformBlocks + blockCount > mMaxUniformBlocks)
|
||||
+ {
|
||||
+ error(arraySizesLine,
|
||||
+ "uniform block count greater than per stage maximum uniform blocks", "");
|
||||
+ }
|
||||
+ else
|
||||
+ {
|
||||
+ mNumUniformBlocks += blockCount;
|
||||
+ }
|
||||
+ }
|
||||
+
|
||||
checkIndexIsNotSpecified(typeQualifier.line, typeQualifier.layoutQualifier.index);
|
||||
|
||||
if (mShaderVersion < 310)
|
||||
diff --git a/src/compiler/translator/ParseContext.h b/src/compiler/translator/ParseContext.h
|
||||
index 5f6800df8c003aa8f930915222a0c04ff838cdad..fb13198d49df37be82cf4199cc05a0cb1337d00c 100644
|
||||
--- a/src/compiler/translator/ParseContext.h
|
||||
+++ b/src/compiler/translator/ParseContext.h
|
||||
@@ -798,6 +798,12 @@ class TParseContext : angle::NonCopyable
|
||||
int mMaxShaderStorageBufferBindings;
|
||||
int mMaxPixelLocalStoragePlanes;
|
||||
|
||||
+ // Maximum number of uniform blocks allowed to be declared in this shader. Taken from the
|
||||
+ // built-in resources and resolved to this shader type.
|
||||
+ unsigned int mMaxUniformBlocks;
|
||||
+ // Current count of declared uniform blocks.
|
||||
+ unsigned int mNumUniformBlocks;
|
||||
+
|
||||
// keeps track whether we are declaring / defining a function
|
||||
bool mDeclaringFunction;
|
||||
|
||||
diff --git a/src/compiler/translator/ShaderLang.cpp b/src/compiler/translator/ShaderLang.cpp
|
||||
index fa67c01cc5bc4f0d3027aa06f4133fd3521b61ce..56bd95a7241f479bb63e2ec13838a6de184b24ab 100644
|
||||
--- a/src/compiler/translator/ShaderLang.cpp
|
||||
+++ b/src/compiler/translator/ShaderLang.cpp
|
||||
@@ -254,6 +254,8 @@ void InitBuiltInResources(ShBuiltInResources *resources)
|
||||
resources->MaxFragmentInputVectors = 15;
|
||||
resources->MinProgramTexelOffset = -8;
|
||||
resources->MaxProgramTexelOffset = 7;
|
||||
+ resources->MaxFragmentUniformBlocks = 12;
|
||||
+ resources->MaxVertexUniformBlocks = 12;
|
||||
|
||||
// Extensions constants.
|
||||
resources->MaxDualSourceDrawBuffers = 0;
|
||||
@@ -314,6 +316,8 @@ void InitBuiltInResources(ShBuiltInResources *resources)
|
||||
resources->MaxUniformBufferBindings = 32;
|
||||
resources->MaxShaderStorageBufferBindings = 4;
|
||||
|
||||
+ resources->MaxComputeUniformBlocks = 12;
|
||||
+
|
||||
resources->MaxGeometryUniformComponents = 1024;
|
||||
resources->MaxGeometryUniformBlocks = 12;
|
||||
resources->MaxGeometryInputComponents = 64;
|
||||
@@ -335,6 +339,7 @@ void InitBuiltInResources(ShBuiltInResources *resources)
|
||||
resources->MaxTessControlImageUniforms = 0;
|
||||
resources->MaxTessControlAtomicCounters = 0;
|
||||
resources->MaxTessControlAtomicCounterBuffers = 0;
|
||||
+ resources->MaxTessControlUniformBlocks = 12;
|
||||
|
||||
resources->MaxTessPatchComponents = 120;
|
||||
resources->MaxPatchVertices = 32;
|
||||
@@ -347,6 +352,7 @@ void InitBuiltInResources(ShBuiltInResources *resources)
|
||||
resources->MaxTessEvaluationImageUniforms = 0;
|
||||
resources->MaxTessEvaluationAtomicCounters = 0;
|
||||
resources->MaxTessEvaluationAtomicCounterBuffers = 0;
|
||||
+ resources->MaxTessEvaluationUniformBlocks = 12;
|
||||
|
||||
resources->SubPixelBits = 8;
|
||||
|
||||
diff --git a/src/libANGLE/Compiler.cpp b/src/libANGLE/Compiler.cpp
|
||||
index 00684c8ed08609a3a4d6ef6f36107756207ed72b..1893b6bddb33fde567162e2e9dbb12785dad538d 100644
|
||||
--- a/src/libANGLE/Compiler.cpp
|
||||
+++ b/src/libANGLE/Compiler.cpp
|
||||
@@ -169,6 +169,8 @@ Compiler::Compiler(rx::GLImplFactory *implFactory, const State &state, egl::Disp
|
||||
mResources.MaxFragmentInputVectors = caps.maxFragmentInputComponents / 4;
|
||||
mResources.MinProgramTexelOffset = caps.minProgramTexelOffset;
|
||||
mResources.MaxProgramTexelOffset = caps.maxProgramTexelOffset;
|
||||
+ mResources.MaxFragmentUniformBlocks = caps.maxShaderUniformBlocks[gl::ShaderType::Fragment];
|
||||
+ mResources.MaxVertexUniformBlocks = caps.maxShaderUniformBlocks[gl::ShaderType::Vertex];
|
||||
|
||||
// EXT_blend_func_extended
|
||||
mResources.EXT_blend_func_extended = extensions.blendFuncExtendedEXT;
|
||||
@@ -211,6 +213,7 @@ Compiler::Compiler(rx::GLImplFactory *implFactory, const State &state, egl::Disp
|
||||
mResources.MaxCombinedImageUniforms = caps.maxCombinedImageUniforms;
|
||||
mResources.MaxCombinedShaderOutputResources = caps.maxCombinedShaderOutputResources;
|
||||
mResources.MaxUniformLocations = caps.maxUniformLocations;
|
||||
+ mResources.MaxComputeUniformBlocks = caps.maxShaderUniformBlocks[gl::ShaderType::Compute];
|
||||
|
||||
for (size_t index = 0u; index < 3u; ++index)
|
||||
{
|
||||
@@ -280,6 +283,8 @@ Compiler::Compiler(rx::GLImplFactory *implFactory, const State &state, egl::Disp
|
||||
mResources.MaxTessControlAtomicCounters = caps.maxShaderAtomicCounters[ShaderType::TessControl];
|
||||
mResources.MaxTessControlAtomicCounterBuffers =
|
||||
caps.maxShaderAtomicCounterBuffers[ShaderType::TessControl];
|
||||
+ mResources.MaxTessControlUniformBlocks =
|
||||
+ caps.maxShaderUniformBlocks[gl::ShaderType::TessControl];
|
||||
|
||||
mResources.MaxTessPatchComponents = caps.maxTessPatchComponents;
|
||||
mResources.MaxPatchVertices = caps.maxPatchVertices;
|
||||
@@ -297,6 +302,8 @@ Compiler::Compiler(rx::GLImplFactory *implFactory, const State &state, egl::Disp
|
||||
caps.maxShaderAtomicCounters[ShaderType::TessEvaluation];
|
||||
mResources.MaxTessEvaluationAtomicCounterBuffers =
|
||||
caps.maxShaderAtomicCounterBuffers[ShaderType::TessEvaluation];
|
||||
+ mResources.MaxTessEvaluationUniformBlocks =
|
||||
+ caps.maxShaderUniformBlocks[gl::ShaderType::TessEvaluation];
|
||||
|
||||
// Subpixel bits.
|
||||
mResources.SubPixelBits = static_cast<int>(caps.subPixelBits);
|
||||
diff --git a/src/libANGLE/renderer/gl/ShaderGL.cpp b/src/libANGLE/renderer/gl/ShaderGL.cpp
|
||||
index bef2feaee055bae36c24bd4edfc98c86ada25cc3..6b66d4e529933d90984ea972ed9375964e6a2ff5 100644
|
||||
--- a/src/libANGLE/renderer/gl/ShaderGL.cpp
|
||||
+++ b/src/libANGLE/renderer/gl/ShaderGL.cpp
|
||||
@@ -272,6 +272,11 @@ std::shared_ptr<ShaderTranslateTask> ShaderGL::compile(const gl::Context *contex
|
||||
options->pls = contextGL->getNativePixelLocalStorageOptions();
|
||||
}
|
||||
|
||||
+ if (features.validateMaxPerStageUniformBlocksAtCompileTime.enabled)
|
||||
+ {
|
||||
+ options->validatePerStageMaxUniformBlocks = true;
|
||||
+ }
|
||||
+
|
||||
return std::shared_ptr<ShaderTranslateTask>(
|
||||
new ShaderTranslateTaskGL(functions, mShaderID, contextGL->hasNativeParallelCompile()));
|
||||
}
|
||||
diff --git a/src/libANGLE/renderer/gl/renderergl_utils.cpp b/src/libANGLE/renderer/gl/renderergl_utils.cpp
|
||||
index b8b328b050ba1af54dbb02143d26456d827260dc..aaa928d6e595dbea220e95129be92461cd1eb280 100644
|
||||
--- a/src/libANGLE/renderer/gl/renderergl_utils.cpp
|
||||
+++ b/src/libANGLE/renderer/gl/renderergl_utils.cpp
|
||||
@@ -2707,6 +2707,10 @@ void InitializeFeatures(const FunctionsGL *functions, angle::FeaturesGL *feature
|
||||
// number of samples in currently bound FBO and require to reset sample
|
||||
// coverage each time FBO changes.
|
||||
ANGLE_FEATURE_CONDITION(features, resetSampleCoverageOnFBOChange, isQualcomm);
|
||||
+
|
||||
+ // IMG GL drivers crash while compiling shaders with more than the limit of uniform blocks.
|
||||
+ ANGLE_FEATURE_CONDITION(features, validateMaxPerStageUniformBlocksAtCompileTime,
|
||||
+ IsPowerVR(vendor));
|
||||
}
|
||||
|
||||
void InitializeFrontendFeatures(const FunctionsGL *functions, angle::FrontendFeatures *features)
|
||||
diff --git a/util/autogen/angle_features_autogen.cpp b/util/autogen/angle_features_autogen.cpp
|
||||
index 7ff616edd4b5a61e544254e6bf1a0bc6c49293a4..f56164ad977ad19b7d58ccbf628f28c8fb24f0a2 100644
|
||||
--- a/util/autogen/angle_features_autogen.cpp
|
||||
+++ b/util/autogen/angle_features_autogen.cpp
|
||||
@@ -473,6 +473,7 @@ constexpr PackedEnumMap<Feature, const char *> kFeatureNames = {{
|
||||
{Feature::UseVkEventForBufferBarrier, "useVkEventForBufferBarrier"},
|
||||
{Feature::UseVkEventForImageBarrier, "useVkEventForImageBarrier"},
|
||||
{Feature::UseVmaForImageSuballocation, "useVmaForImageSuballocation"},
|
||||
+ {Feature::ValidateMaxPerStageUniformBlocksAtCompileTime, "validateMaxPerStageUniformBlocksAtCompileTime"},
|
||||
{Feature::VaryingsRequireMatchingPrecisionInSpirv, "varyingsRequireMatchingPrecisionInSpirv"},
|
||||
{Feature::VerifyPipelineCacheInBlobCache, "verifyPipelineCacheInBlobCache"},
|
||||
{Feature::VertexIDDoesNotIncludeBaseVertex, "vertexIDDoesNotIncludeBaseVertex"},
|
||||
diff --git a/util/autogen/angle_features_autogen.h b/util/autogen/angle_features_autogen.h
|
||||
index fd19b2b8f4eb7a0bf9973bf2baeaf68c106e11a8..55bf1b418c4f2f185e833c4c385094792f1bbf05 100644
|
||||
--- a/util/autogen/angle_features_autogen.h
|
||||
+++ b/util/autogen/angle_features_autogen.h
|
||||
@@ -473,6 +473,7 @@ enum class Feature
|
||||
UseVkEventForBufferBarrier,
|
||||
UseVkEventForImageBarrier,
|
||||
UseVmaForImageSuballocation,
|
||||
+ ValidateMaxPerStageUniformBlocksAtCompileTime,
|
||||
VaryingsRequireMatchingPrecisionInSpirv,
|
||||
VerifyPipelineCacheInBlobCache,
|
||||
VertexIDDoesNotIncludeBaseVertex,
|
||||
@@ -151,3 +151,10 @@ graphite_handle_out_of_order_recording_errors.patch
|
||||
ozone_wayland_treat_dnd_drop_performed_with_none_action_as_a.patch
|
||||
cherry-pick-e045399a1ecb.patch
|
||||
loaf_add_feature_to_enable_sourceurl_for_all_protocols.patch
|
||||
cherry-pick-50b057660b4d.patch
|
||||
cherry-pick-074d472db745.patch
|
||||
validate_uniform_block_count_limits_at_compile_time_on_img.patch
|
||||
feat_plumb_node_integration_in_worker_through_workersettings.patch
|
||||
cherry-pick-45c5a70d984d.patch
|
||||
cherry-pick-05e4b544803c.patch
|
||||
cherry-pick-5efc7a0127a6.patch
|
||||
|
||||
204
patches/chromium/cherry-pick-05e4b544803c.patch
Normal file
204
patches/chromium/cherry-pick-05e4b544803c.patch
Normal file
@@ -0,0 +1,204 @@
|
||||
From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001
|
||||
From: Anders Hartvoll Ruud <andruud@chromium.org>
|
||||
Date: Wed, 25 Feb 2026 03:25:14 -0800
|
||||
Subject: Stringify CSSUnparsedValues via toString, as normal
|
||||
|
||||
CSSUnparsedValue exposes a special stringification function
|
||||
ToUnparsedString() in addition to the regular toString().
|
||||
The documentation says it returns "tokens without substituting
|
||||
variables", but it's not clear what this means; we don't substitute
|
||||
any variables in CSSStyleValue::toString() either.
|
||||
|
||||
This CL makes ToUnparsedString() private (and renames it).
|
||||
Clients needing to serialize a CSSUnparsedValue can do so via
|
||||
the normal toString() function. (If ToUnparsedString() existed
|
||||
for performance reasons, that should have been documented.)
|
||||
|
||||
Also, the /**/-"fixup" pass over the value has been folded into
|
||||
ToStringInternal(). This is to make it easy to find the canonical string
|
||||
representation of this value within CSSUnparsedValue (without going
|
||||
through a CSSValue).
|
||||
|
||||
The main point of this CL is to prepare for validating
|
||||
the "argument grammar" of the value during the StyleValue-to-CSSValue
|
||||
conversion in StylePropertyMap (which requires item (2) above).
|
||||
|
||||
We now jump through additional hoops to ultimately get a string
|
||||
from the outside of CSSUnparsedValue, but there should otherwise
|
||||
be no behavior change.
|
||||
|
||||
Bug: 484751092
|
||||
Change-Id: I5db45ad85f780c67a2ea3ba8482c390ebab10068
|
||||
Reviewed-on: https://chromium-review.googlesource.com/c/chromium/src/+/7600415
|
||||
Commit-Queue: Anders Hartvoll Ruud <andruud@chromium.org>
|
||||
Reviewed-by: Steinar H Gunderson <sesse@chromium.org>
|
||||
Cr-Commit-Position: refs/heads/main@{#1590041}
|
||||
|
||||
diff --git a/third_party/blink/renderer/core/css/cssom/cross_thread_style_value_test.cc b/third_party/blink/renderer/core/css/cssom/cross_thread_style_value_test.cc
|
||||
index dcc2eccbc84e6cd5710ab51cee2dab49661467c1..86d42c87a6bd10838a3e059c9227868e5bfc0798 100644
|
||||
--- a/third_party/blink/renderer/core/css/cssom/cross_thread_style_value_test.cc
|
||||
+++ b/third_party/blink/renderer/core/css/cssom/cross_thread_style_value_test.cc
|
||||
@@ -19,12 +19,12 @@
|
||||
#include "third_party/blink/renderer/core/css/cssom/css_keyword_value.h"
|
||||
#include "third_party/blink/renderer/core/css/cssom/css_style_value.h"
|
||||
#include "third_party/blink/renderer/core/css/cssom/css_unit_value.h"
|
||||
-#include "third_party/blink/renderer/core/css/cssom/css_unparsed_value.h"
|
||||
#include "third_party/blink/renderer/core/css/cssom/css_unsupported_color.h"
|
||||
#include "third_party/blink/renderer/platform/scheduler/public/non_main_thread.h"
|
||||
#include "third_party/blink/renderer/platform/scheduler/public/post_cross_thread_task.h"
|
||||
#include "third_party/blink/renderer/platform/wtf/cross_thread_copier_std.h"
|
||||
#include "third_party/blink/renderer/platform/wtf/cross_thread_functional.h"
|
||||
+#include "third_party/blink/renderer/platform/wtf/wtf.h"
|
||||
|
||||
namespace blink {
|
||||
|
||||
@@ -152,8 +152,7 @@ TEST_F(CrossThreadStyleValueTest, CrossThreadUnparsedValueToCSSStyleValue) {
|
||||
CSSStyleValue* style_value = value->ToCSSStyleValue();
|
||||
EXPECT_EQ(style_value->GetType(),
|
||||
CSSStyleValue::StyleValueType::kUnparsedType);
|
||||
- EXPECT_EQ(static_cast<CSSUnparsedValue*>(style_value)->ToUnparsedString(),
|
||||
- "Unparsed");
|
||||
+ EXPECT_EQ(style_value->toString(), "Unparsed");
|
||||
}
|
||||
|
||||
TEST_F(CrossThreadStyleValueTest, PassKeywordValueCrossThread) {
|
||||
diff --git a/third_party/blink/renderer/core/css/cssom/css_unparsed_value.cc b/third_party/blink/renderer/core/css/cssom/css_unparsed_value.cc
|
||||
index 67a4afde452f94ffb9ecbaeea104a3997c65b7b3..9c6bb62d044f804b0ce7bc8df398d77695cf950c 100644
|
||||
--- a/third_party/blink/renderer/core/css/cssom/css_unparsed_value.cc
|
||||
+++ b/third_party/blink/renderer/core/css/cssom/css_unparsed_value.cc
|
||||
@@ -124,16 +124,26 @@ IndexedPropertySetterResult CSSUnparsedValue::AnonymousIndexedSetter(
|
||||
}
|
||||
|
||||
const CSSValue* CSSUnparsedValue::ToCSSValue() const {
|
||||
- String unparsed_string = ToUnparsedString();
|
||||
- CSSParserTokenStream stream(unparsed_string);
|
||||
+ String unparsed_string = ToStringInternal();
|
||||
|
||||
- if (stream.AtEnd()) {
|
||||
+ if (unparsed_string.IsNull()) {
|
||||
return MakeGarbageCollected<CSSUnparsedDeclarationValue>(
|
||||
MakeGarbageCollected<CSSVariableData>());
|
||||
}
|
||||
|
||||
- // The string we just parsed has /**/ inserted between every token
|
||||
- // to make sure we get back the correct sequence of tokens.
|
||||
+ // TODO(crbug.com/985028): We should probably propagate the CSSParserContext
|
||||
+ // to here.
|
||||
+ return MakeGarbageCollected<CSSUnparsedDeclarationValue>(
|
||||
+ CSSVariableData::Create(unparsed_string, false /* is_animation_tainted */,
|
||||
+ false /* is_attr_tainted */,
|
||||
+ false /* needs_variable_resolution */));
|
||||
+}
|
||||
+
|
||||
+String CSSUnparsedValue::ToStringInternal() const {
|
||||
+ String serialized = SerializeSegments();
|
||||
+
|
||||
+ // The serialization above defensively inserted /**/ between segments
|
||||
+ // to make sure that e.g. ['foo', 'bar'] does not collapse into 'foobar'.
|
||||
// The spec mentions nothing of the sort:
|
||||
// https://drafts.css-houdini.org/css-typed-om-1/#unparsedvalue-serialization
|
||||
//
|
||||
@@ -147,6 +157,10 @@ const CSSValue* CSSUnparsedValue::ToCSSValue() const {
|
||||
// the original contents of any comments will be lost, but Typed OM does
|
||||
// not have anywhere to store that kind of data, so it is expected.
|
||||
StringBuilder builder;
|
||||
+ CSSParserTokenStream stream(serialized);
|
||||
+ if (stream.AtEnd()) {
|
||||
+ return g_null_atom;
|
||||
+ }
|
||||
CSSParserToken token = stream.ConsumeRaw();
|
||||
token.Serialize(builder);
|
||||
while (!stream.Peek().IsEOF()) {
|
||||
@@ -156,17 +170,10 @@ const CSSValue* CSSUnparsedValue::ToCSSValue() const {
|
||||
token = stream.ConsumeRaw();
|
||||
token.Serialize(builder);
|
||||
}
|
||||
- String original_text = builder.ReleaseString();
|
||||
-
|
||||
- // TODO(crbug.com/985028): We should probably propagate the CSSParserContext
|
||||
- // to here.
|
||||
- return MakeGarbageCollected<CSSUnparsedDeclarationValue>(
|
||||
- CSSVariableData::Create(original_text, false /* is_animation_tainted */,
|
||||
- false /* is_attr_tainted */,
|
||||
- false /* needs_variable_resolution */));
|
||||
+ return builder.ReleaseString();
|
||||
}
|
||||
|
||||
-String CSSUnparsedValue::ToUnparsedString() const {
|
||||
+String CSSUnparsedValue::SerializeSegments() const {
|
||||
StringBuilder builder;
|
||||
HeapHashSet<Member<const CSSUnparsedValue>> values_on_stack;
|
||||
if (AppendUnparsedString(builder, values_on_stack)) {
|
||||
diff --git a/third_party/blink/renderer/core/css/cssom/css_unparsed_value.h b/third_party/blink/renderer/core/css/cssom/css_unparsed_value.h
|
||||
index 5d1961b170f14ae21ca8f69b3c3cd8af28f4478a..ec7e3ed708f406d7a61fdb370b2eed8a8297cffb 100644
|
||||
--- a/third_party/blink/renderer/core/css/cssom/css_unparsed_value.h
|
||||
+++ b/third_party/blink/renderer/core/css/cssom/css_unparsed_value.h
|
||||
@@ -67,15 +67,9 @@ class CORE_EXPORT CSSUnparsedValue final : public CSSStyleValue {
|
||||
CSSStyleValue::Trace(visitor);
|
||||
}
|
||||
|
||||
- // Unlike CSSStyleValue::toString(), this returns tokens without
|
||||
- // substituting variables. There are extra /**/ inserted between
|
||||
- // every token to ensure there are no ambiguities, which is fine
|
||||
- // because this value is never presented directly to the user
|
||||
- // (ToCSSValue() will parse to a token range and then re-serialize
|
||||
- // using extra /**/ only where needed).
|
||||
- String ToUnparsedString() const;
|
||||
-
|
||||
private:
|
||||
+ String ToStringInternal() const;
|
||||
+ String SerializeSegments() const;
|
||||
// Return 'false' if there is a cycle in the serialization.
|
||||
bool AppendUnparsedString(
|
||||
StringBuilder&,
|
||||
diff --git a/third_party/blink/renderer/core/css/cssom/paint_worklet_style_property_map_test.cc b/third_party/blink/renderer/core/css/cssom/paint_worklet_style_property_map_test.cc
|
||||
index f81fa39423a9235bc58e1600ca7a250affd3d9bb..2ee4dd7e591095b8460ca559b29b78e37ab71729 100644
|
||||
--- a/third_party/blink/renderer/core/css/cssom/paint_worklet_style_property_map_test.cc
|
||||
+++ b/third_party/blink/renderer/core/css/cssom/paint_worklet_style_property_map_test.cc
|
||||
@@ -5,6 +5,7 @@
|
||||
#include "third_party/blink/renderer/core/css/cssom/paint_worklet_style_property_map.h"
|
||||
|
||||
#include <memory>
|
||||
+
|
||||
#include "base/synchronization/waitable_event.h"
|
||||
#include "base/task/single_thread_task_runner.h"
|
||||
#include "testing/gtest/include/gtest/gtest.h"
|
||||
@@ -13,7 +14,6 @@
|
||||
#include "third_party/blink/renderer/core/css/cssom/css_keyword_value.h"
|
||||
#include "third_party/blink/renderer/core/css/cssom/css_paint_worklet_input.h"
|
||||
#include "third_party/blink/renderer/core/css/cssom/css_unit_value.h"
|
||||
-#include "third_party/blink/renderer/core/css/cssom/css_unparsed_value.h"
|
||||
#include "third_party/blink/renderer/core/css/cssom/css_unsupported_color.h"
|
||||
#include "third_party/blink/renderer/core/css/properties/longhands/custom_property.h"
|
||||
#include "third_party/blink/renderer/core/dom/element.h"
|
||||
@@ -23,6 +23,7 @@
|
||||
#include "third_party/blink/renderer/platform/scheduler/public/post_cross_thread_task.h"
|
||||
#include "third_party/blink/renderer/platform/wtf/cross_thread_copier_base.h"
|
||||
#include "third_party/blink/renderer/platform/wtf/cross_thread_functional.h"
|
||||
+#include "third_party/blink/renderer/platform/wtf/wtf.h"
|
||||
|
||||
namespace blink {
|
||||
|
||||
@@ -66,8 +67,7 @@ class PaintWorkletStylePropertyMapTest : public PageTestBase {
|
||||
CSSStyleValue* style_value = data.at("--x")->ToCSSStyleValue();
|
||||
EXPECT_EQ(style_value->GetType(),
|
||||
CSSStyleValue::StyleValueType::kUnparsedType);
|
||||
- EXPECT_EQ(static_cast<CSSUnparsedValue*>(style_value)->ToUnparsedString(),
|
||||
- "50");
|
||||
+ EXPECT_EQ(style_value->toString(), "50");
|
||||
waitable_event->Signal();
|
||||
}
|
||||
|
||||
diff --git a/third_party/blink/renderer/core/css/properties/computed_style_utils.cc b/third_party/blink/renderer/core/css/properties/computed_style_utils.cc
|
||||
index 1db0fd72478d708008f1b95a6aff206b28f60a6a..b52d8065c770aba822e9977c251c540643972629 100644
|
||||
--- a/third_party/blink/renderer/core/css/properties/computed_style_utils.cc
|
||||
+++ b/third_party/blink/renderer/core/css/properties/computed_style_utils.cc
|
||||
@@ -4872,7 +4872,7 @@ ComputedStyleUtils::CrossThreadStyleValueFromCSSStyleValue(
|
||||
To<CSSUnsupportedColor>(style_value)->Value());
|
||||
case CSSStyleValue::StyleValueType::kUnparsedType:
|
||||
return std::make_unique<CrossThreadUnparsedValue>(
|
||||
- To<CSSUnparsedValue>(style_value)->ToUnparsedString());
|
||||
+ To<CSSUnparsedValue>(style_value)->toString());
|
||||
default:
|
||||
return std::make_unique<CrossThreadUnsupportedValue>(
|
||||
style_value->toString());
|
||||
296
patches/chromium/cherry-pick-074d472db745.patch
Normal file
296
patches/chromium/cherry-pick-074d472db745.patch
Normal file
@@ -0,0 +1,296 @@
|
||||
From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001
|
||||
From: Mikel Astiz <mastiz@chromium.org>
|
||||
Date: Tue, 10 Mar 2026 13:22:17 -0700
|
||||
Subject: [M146][base] Fix UAF in base::OnceCallbackList on re-entrant Notify()
|
||||
|
||||
Before this patch, `base::OnceCallbackList` was susceptible to a
|
||||
heap-use-after-free when `Notify()` was called re-entrantly.
|
||||
|
||||
The UAF occurred because `OnceCallbackList::RunCallback()` immediately
|
||||
spliced executed nodes out of `callbacks_` and into `null_callbacks_`.
|
||||
If a nested `Notify()` executed a node that an outer `Notify()` loop was
|
||||
already holding an iterator to, and that node's subscription was
|
||||
subsequently destroyed during the re-entrant cycle, the node would be
|
||||
physically erased from `null_callbacks_`. When control returned to the
|
||||
outer loop, it would attempt to evaluate the now-dangling iterator.
|
||||
|
||||
This CL fixes the bug by deferring list mutations until the outermost
|
||||
iteration completes:
|
||||
1. `RunCallback()` no longer splices nodes during iteration.
|
||||
2. Cancellation logic is pushed down to the subclasses via a new
|
||||
`CancelCallback()` hook, which is an extension to the pre-existing
|
||||
`CancelNullCallback()` with increased responsibilities and clearer
|
||||
semantics.
|
||||
3. If a subscription is destroyed while `is_iterating` is true,
|
||||
`OnceCallbackList` resets the node and stashes its iterator in
|
||||
`pending_erasures_`.
|
||||
4. A new `CleanUpNullCallbacksPostIteration()` phase runs at the end
|
||||
of the outermost `Notify()`, which safely splices executed nodes
|
||||
into `null_callbacks_` and physically erases the pending dead nodes.
|
||||
|
||||
As a side effect, the type-trait hack in `Notify()` based on
|
||||
`is_instantiation<CallbackType, OnceCallback>` can be removed, because
|
||||
this information is exposed directly by
|
||||
`OnceCallbackList::CleanUpNullCallbacksPostIteration()`.
|
||||
|
||||
The newly-added unit-test
|
||||
CallbackListTest.OnceCallbackListCancelDuringReentrantNotify reproduces
|
||||
the scenario and crashed before this patch.
|
||||
|
||||
(cherry picked from commit 36acd49636845be2419269acbe9a5137da3d5d96)
|
||||
|
||||
Change-Id: I6b1e2bcb97be1bc8d6a15e5ca7511992e00e1772
|
||||
Fixed: 489381399
|
||||
Reviewed-on: https://chromium-review.googlesource.com/c/chromium/src/+/7627506
|
||||
Commit-Queue: Mikel Astiz <mastiz@chromium.org>
|
||||
Reviewed-by: Gabriel Charette <gab@chromium.org>
|
||||
Cr-Original-Commit-Position: refs/heads/main@{#1594520}
|
||||
Reviewed-on: https://chromium-review.googlesource.com/c/chromium/src/+/7653916
|
||||
Bot-Commit: Rubber Stamper <rubber-stamper@appspot.gserviceaccount.com>
|
||||
Cr-Commit-Position: refs/branch-heads/7680@{#2287}
|
||||
Cr-Branched-From: 76b7d80e5cda23fe6537eed26d68c92e995c7f39-refs/heads/main@{#1582197}
|
||||
|
||||
diff --git a/base/callback_list.h b/base/callback_list.h
|
||||
index 82cb11dc0ee02906b009cc383c41a056861199d0..d5f99cf685486f1ea74718b4e6b228a5d83f0c29 100644
|
||||
--- a/base/callback_list.h
|
||||
+++ b/base/callback_list.h
|
||||
@@ -9,6 +9,7 @@
|
||||
#include <list>
|
||||
#include <memory>
|
||||
#include <utility>
|
||||
+#include <vector>
|
||||
|
||||
#include "base/auto_reset.h"
|
||||
#include "base/base_export.h"
|
||||
@@ -16,7 +17,6 @@
|
||||
#include "base/functional/bind.h"
|
||||
#include "base/functional/callback.h"
|
||||
#include "base/memory/weak_ptr.h"
|
||||
-#include "base/types/is_instantiation.h"
|
||||
|
||||
// OVERVIEW:
|
||||
//
|
||||
@@ -240,17 +240,14 @@ class CallbackListBase {
|
||||
|
||||
// Any null callbacks remaining in the list were canceled due to
|
||||
// Subscription destruction during iteration, and can safely be erased now.
|
||||
- const size_t erased_callbacks =
|
||||
- std::erase_if(callbacks_, [](const auto& cb) { return cb.is_null(); });
|
||||
-
|
||||
- // Run |removal_callback_| if any callbacks were canceled. Note that we
|
||||
- // cannot simply compare list sizes before and after iterating, since
|
||||
- // notification may result in Add()ing new callbacks as well as canceling
|
||||
- // them. Also note that if this is a OnceCallbackList, the OnceCallbacks
|
||||
- // that were executed above have all been removed regardless of whether
|
||||
- // they're counted in |erased_callbacks_|.
|
||||
- if (removal_callback_ &&
|
||||
- (erased_callbacks || is_instantiation<CallbackType, OnceCallback>)) {
|
||||
+ const bool any_callbacks_erased = static_cast<CallbackListImpl*>(this)
|
||||
+ ->CleanUpNullCallbacksPostIteration();
|
||||
+
|
||||
+ // Run |removal_callback_| if any callbacks were canceled or executed. Note
|
||||
+ // that simply comparing list sizes before and after iterating cannot be
|
||||
+ // done, since notification may result in Add()ing new callbacks as well as
|
||||
+ // canceling them.
|
||||
+ if (removal_callback_ && any_callbacks_erased) {
|
||||
removal_callback_.Run(); // May delete |this|!
|
||||
}
|
||||
}
|
||||
@@ -264,21 +261,9 @@ class CallbackListBase {
|
||||
private:
|
||||
// Cancels the callback pointed to by |it|, which is guaranteed to be valid.
|
||||
void CancelCallback(const typename Callbacks::iterator& it) {
|
||||
- if (static_cast<CallbackListImpl*>(this)->CancelNullCallback(it)) {
|
||||
- return;
|
||||
- }
|
||||
-
|
||||
- if (iterating_) {
|
||||
- // Calling erase() here is unsafe, since the loop in Notify() may be
|
||||
- // referencing this same iterator, e.g. if adjacent callbacks'
|
||||
- // Subscriptions are both destroyed when the first one is Run(). Just
|
||||
- // reset the callback and let Notify() clean it up at the end.
|
||||
- it->Reset();
|
||||
- } else {
|
||||
- callbacks_.erase(it);
|
||||
- if (removal_callback_) {
|
||||
- removal_callback_.Run(); // May delete |this|!
|
||||
- }
|
||||
+ if (static_cast<CallbackListImpl*>(this)->CancelCallback(it, iterating_) &&
|
||||
+ removal_callback_) {
|
||||
+ removal_callback_.Run(); // May delete |this|!
|
||||
}
|
||||
}
|
||||
|
||||
@@ -304,23 +289,71 @@ class OnceCallbackList
|
||||
// Runs the current callback, which may cancel it or any other callbacks.
|
||||
template <typename... RunArgs>
|
||||
void RunCallback(typename Traits::Callbacks::iterator it, RunArgs&&... args) {
|
||||
- // OnceCallbacks still have Subscriptions with outstanding iterators;
|
||||
- // splice() removes them from |callbacks_| without invalidating those.
|
||||
- null_callbacks_.splice(null_callbacks_.end(), this->callbacks_, it);
|
||||
+ // Do not splice here. Splicing during iteration breaks re-entrant Notify()
|
||||
+ // by invalidating the outer loop's iterator. Splicing is deferred to
|
||||
+ // CleanUpNullCallbacksPostIteration(), which is called when the outermost
|
||||
+ // Notify() finishes.
|
||||
|
||||
// NOTE: Intentionally does not call std::forward<RunArgs>(args)...; see
|
||||
// comments in Notify().
|
||||
std::move(*it).Run(args...);
|
||||
}
|
||||
|
||||
- // If |it| refers to an already-canceled callback, does any necessary cleanup
|
||||
- // and returns true. Otherwise returns false.
|
||||
- bool CancelNullCallback(const typename Traits::Callbacks::iterator& it) {
|
||||
+ // Called during subscription destruction to cancel the callback. Returns true
|
||||
+ // if the callback was removed from the active list and the generic removal
|
||||
+ // callback should be executed. Returns false if the callback was already
|
||||
+ // executed, or if the erasure is deferred due to active iteration.
|
||||
+ bool CancelCallback(const typename Traits::Callbacks::iterator& it,
|
||||
+ bool is_iterating) {
|
||||
+ if (is_iterating) {
|
||||
+ // During iteration, nodes cannot be safely erased from |callbacks_|
|
||||
+ // without invalidating iterators. They also cannot be spliced into
|
||||
+ // |null_callbacks_| right now. Thus, the node is reset and tracked for
|
||||
+ // erasure in CleanUpNullCallbacksPostIteration().
|
||||
+ it->Reset();
|
||||
+ pending_erasures_.push_back(it);
|
||||
+ return false;
|
||||
+ }
|
||||
+
|
||||
if (it->is_null()) {
|
||||
+ // The callback already ran, so it's safely sitting in |null_callbacks_|.
|
||||
null_callbacks_.erase(it);
|
||||
- return true;
|
||||
+ return false;
|
||||
}
|
||||
- return false;
|
||||
+
|
||||
+ // The callback hasn't run yet, so it's still in |callbacks_|.
|
||||
+ this->callbacks_.erase(it);
|
||||
+ return true;
|
||||
+ }
|
||||
+
|
||||
+ // Performs post-iteration cleanup. Successfully executed callbacks (which
|
||||
+ // become null) are spliced into |null_callbacks_| to keep their
|
||||
+ // Subscriptions' iterators valid. Callbacks explicitly canceled during
|
||||
+ // iteration (tracked in |pending_erasures_|) are erased. Returns true if any
|
||||
+ // callbacks were erased or spliced out.
|
||||
+ bool CleanUpNullCallbacksPostIteration() {
|
||||
+ bool any_spliced = false;
|
||||
+ for (auto it = this->callbacks_.begin(); it != this->callbacks_.end();) {
|
||||
+ if (it->is_null()) {
|
||||
+ any_spliced = true;
|
||||
+ auto next = std::next(it);
|
||||
+ null_callbacks_.splice(null_callbacks_.end(), this->callbacks_, it);
|
||||
+ it = next;
|
||||
+ } else {
|
||||
+ ++it;
|
||||
+ }
|
||||
+ }
|
||||
+
|
||||
+ bool any_erased = !pending_erasures_.empty();
|
||||
+ for (auto pending_it : pending_erasures_) {
|
||||
+ // Note: `pending_it` was originally an iterator into `callbacks_`, but
|
||||
+ // the node it points to has just been spliced into `null_callbacks_`. The
|
||||
+ // iterator itself remains valid and can now be used for erasure from
|
||||
+ // `null_callbacks_`.
|
||||
+ null_callbacks_.erase(pending_it);
|
||||
+ }
|
||||
+ pending_erasures_.clear();
|
||||
+ return any_spliced || any_erased;
|
||||
}
|
||||
|
||||
// Holds null callbacks whose Subscriptions are still alive, so the
|
||||
@@ -328,6 +361,11 @@ class OnceCallbackList
|
||||
// OnceCallbacks, since RepeatingCallbacks are not canceled except by
|
||||
// Subscription destruction.
|
||||
typename Traits::Callbacks null_callbacks_;
|
||||
+
|
||||
+ // Holds iterators for callbacks canceled during iteration.
|
||||
+ // Erasure is deferred to CleanUpNullCallbacksPostIteration() when iteration
|
||||
+ // completes to prevent invalidating iterators that an outer loop might hold.
|
||||
+ std::vector<typename Traits::Callbacks::iterator> pending_erasures_;
|
||||
};
|
||||
|
||||
template <typename Signature>
|
||||
@@ -344,14 +382,29 @@ class RepeatingCallbackList
|
||||
it->Run(args...);
|
||||
}
|
||||
|
||||
- // If |it| refers to an already-canceled callback, does any necessary cleanup
|
||||
- // and returns true. Otherwise returns false.
|
||||
- bool CancelNullCallback(const typename Traits::Callbacks::iterator& it) {
|
||||
- // Because at most one Subscription can point to a given callback, and
|
||||
- // RepeatingCallbacks are only reset by CancelCallback(), no one should be
|
||||
- // able to request cancellation of a canceled RepeatingCallback.
|
||||
- DCHECK(!it->is_null());
|
||||
- return false;
|
||||
+ // Called during subscription destruction to cancel the callback. Returns true
|
||||
+ // if the callback was removed from the active list and the generic removal
|
||||
+ // callback should be executed. Returns false if the callback was already
|
||||
+ // executed, or if the erasure is deferred due to active iteration.
|
||||
+ bool CancelCallback(const typename Traits::Callbacks::iterator& it,
|
||||
+ bool is_iterating) {
|
||||
+ if (is_iterating) {
|
||||
+ // During iteration, nodes cannot be safely erased from |callbacks_|
|
||||
+ // without invalidating iterators. The node is reset and will be swept up
|
||||
+ // by CleanUpNullCallbacksPostIteration().
|
||||
+ it->Reset();
|
||||
+ return false;
|
||||
+ }
|
||||
+
|
||||
+ this->callbacks_.erase(it);
|
||||
+ return true;
|
||||
+ }
|
||||
+
|
||||
+ // Performs post-iteration cleanup by erasing all canceled callbacks. Returns
|
||||
+ // true if any callbacks were erased.
|
||||
+ bool CleanUpNullCallbacksPostIteration() {
|
||||
+ return std::erase_if(this->callbacks_,
|
||||
+ [](const auto& cb) { return cb.is_null(); }) > 0;
|
||||
}
|
||||
};
|
||||
|
||||
diff --git a/base/callback_list_unittest.cc b/base/callback_list_unittest.cc
|
||||
index 7474278525e5efecc0de903809a54d366896d524..a855443fbae862befbc3a2a484ea335632136e94 100644
|
||||
--- a/base/callback_list_unittest.cc
|
||||
+++ b/base/callback_list_unittest.cc
|
||||
@@ -10,6 +10,7 @@
|
||||
#include "base/functional/bind.h"
|
||||
#include "base/functional/callback_helpers.h"
|
||||
#include "base/memory/raw_ptr.h"
|
||||
+#include "base/test/bind.h"
|
||||
#include "base/test/test_future.h"
|
||||
#include "testing/gtest/include/gtest/gtest.h"
|
||||
|
||||
@@ -577,6 +578,30 @@ TEST(CallbackListTest, ReentrantNotify) {
|
||||
EXPECT_EQ(1, d.total());
|
||||
}
|
||||
|
||||
+// Regression test for crbug.com/489381399: Verifies Notify() can be called
|
||||
+// reentrantly for OnceCallbackList even if a callback is canceled during the
|
||||
+// reentrant notification.
|
||||
+TEST(CallbackListTest, OnceCallbackListCancelDuringReentrantNotify) {
|
||||
+ OnceClosureList cb_reg;
|
||||
+ CallbackListSubscription sub_a, sub_b;
|
||||
+
|
||||
+ auto cb_a = base::BindLambdaForTesting([&]() {
|
||||
+ // Re-entrant notification.
|
||||
+ cb_reg.Notify();
|
||||
+ // After re-entrant notification returns, sub_b has been run. Destroying it
|
||||
+ // now should be a no-op.
|
||||
+ sub_b = {};
|
||||
+ });
|
||||
+
|
||||
+ auto cb_b = base::DoNothing();
|
||||
+
|
||||
+ sub_a = cb_reg.Add(std::move(cb_a));
|
||||
+ sub_b = cb_reg.Add(std::move(cb_b));
|
||||
+
|
||||
+ // This should not crash.
|
||||
+ cb_reg.Notify();
|
||||
+}
|
||||
+
|
||||
TEST(CallbackListTest, ClearPreventsInvocation) {
|
||||
Listener listener;
|
||||
RepeatingClosureList cb_reg;
|
||||
199
patches/chromium/cherry-pick-45c5a70d984d.patch
Normal file
199
patches/chromium/cherry-pick-45c5a70d984d.patch
Normal file
@@ -0,0 +1,199 @@
|
||||
From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001
|
||||
From: Anders Hartvoll Ruud <andruud@chromium.org>
|
||||
Date: Wed, 25 Feb 2026 03:24:19 -0800
|
||||
Subject: Describe a vector of segments as "segments", not "tokens"
|
||||
|
||||
The specification uses the term "tokens" to refer to a sequence
|
||||
of V8CSSUnparsedSegment objects, and CSSUnparsedValue has adopted
|
||||
this terminology. While it is usually a good idea for Blink
|
||||
to mirror the language used in specifications, "tokens" is very
|
||||
confusing here, since it always means CSSParserTokens in every other
|
||||
place in the style code.
|
||||
|
||||
Bug: 487117772
|
||||
Change-Id: I2dc132c4e618e398e1f8bdabc03a8d2ab6c118e7
|
||||
Reviewed-on: https://chromium-review.googlesource.com/c/chromium/src/+/7606599
|
||||
Commit-Queue: Anders Hartvoll Ruud <andruud@chromium.org>
|
||||
Reviewed-by: Steinar H Gunderson <sesse@chromium.org>
|
||||
Cr-Commit-Position: refs/heads/main@{#1590040}
|
||||
|
||||
diff --git a/third_party/blink/renderer/core/css/cssom/css_unparsed_value.cc b/third_party/blink/renderer/core/css/cssom/css_unparsed_value.cc
|
||||
index 3d43306dd902b3071637e5d5d0af26e5ee47f141..67a4afde452f94ffb9ecbaeea104a3997c65b7b3 100644
|
||||
--- a/third_party/blink/renderer/core/css/cssom/css_unparsed_value.cc
|
||||
+++ b/third_party/blink/renderer/core/css/cssom/css_unparsed_value.cc
|
||||
@@ -24,12 +24,12 @@ String FindVariableName(CSSParserTokenStream& stream) {
|
||||
|
||||
V8CSSUnparsedSegment* VariableReferenceValue(
|
||||
const StringView& variable_name,
|
||||
- const HeapVector<Member<V8CSSUnparsedSegment>>& tokens) {
|
||||
+ const HeapVector<Member<V8CSSUnparsedSegment>>& segments) {
|
||||
CSSUnparsedValue* unparsed_value;
|
||||
- if (tokens.size() == 0) {
|
||||
+ if (segments.size() == 0) {
|
||||
unparsed_value = nullptr;
|
||||
} else {
|
||||
- unparsed_value = CSSUnparsedValue::Create(tokens);
|
||||
+ unparsed_value = CSSUnparsedValue::Create(segments);
|
||||
}
|
||||
|
||||
CSSStyleVariableReferenceValue* variable_reference =
|
||||
@@ -41,13 +41,13 @@ V8CSSUnparsedSegment* VariableReferenceValue(
|
||||
HeapVector<Member<V8CSSUnparsedSegment>> ParserTokenStreamToTokens(
|
||||
CSSParserTokenStream& stream) {
|
||||
int nesting_level = 0;
|
||||
- HeapVector<Member<V8CSSUnparsedSegment>> tokens;
|
||||
+ HeapVector<Member<V8CSSUnparsedSegment>> segments;
|
||||
StringBuilder builder;
|
||||
while (stream.Peek().GetType() != kEOFToken) {
|
||||
if (stream.Peek().FunctionId() == CSSValueID::kVar ||
|
||||
stream.Peek().FunctionId() == CSSValueID::kEnv) {
|
||||
if (!builder.empty()) {
|
||||
- tokens.push_back(MakeGarbageCollected<V8CSSUnparsedSegment>(
|
||||
+ segments.push_back(MakeGarbageCollected<V8CSSUnparsedSegment>(
|
||||
builder.ReleaseString()));
|
||||
}
|
||||
|
||||
@@ -57,7 +57,7 @@ HeapVector<Member<V8CSSUnparsedSegment>> ParserTokenStreamToTokens(
|
||||
if (stream.Peek().GetType() == CSSParserTokenType::kCommaToken) {
|
||||
stream.Consume();
|
||||
}
|
||||
- tokens.push_back(VariableReferenceValue(
|
||||
+ segments.push_back(VariableReferenceValue(
|
||||
variable_name, ParserTokenStreamToTokens(stream)));
|
||||
} else {
|
||||
if (stream.Peek().GetBlockType() == CSSParserToken::kBlockStart) {
|
||||
@@ -73,10 +73,10 @@ HeapVector<Member<V8CSSUnparsedSegment>> ParserTokenStreamToTokens(
|
||||
}
|
||||
}
|
||||
if (!builder.empty()) {
|
||||
- tokens.push_back(
|
||||
+ segments.push_back(
|
||||
MakeGarbageCollected<V8CSSUnparsedSegment>(builder.ReleaseString()));
|
||||
}
|
||||
- return tokens;
|
||||
+ return segments;
|
||||
}
|
||||
|
||||
} // namespace
|
||||
@@ -96,8 +96,8 @@ CSSUnparsedValue* CSSUnparsedValue::FromCSSVariableData(
|
||||
V8CSSUnparsedSegment* CSSUnparsedValue::AnonymousIndexedGetter(
|
||||
uint32_t index,
|
||||
ExceptionState& exception_state) const {
|
||||
- if (index < tokens_.size()) {
|
||||
- return tokens_[index].Get();
|
||||
+ if (index < segments_.size()) {
|
||||
+ return segments_[index].Get();
|
||||
}
|
||||
return nullptr;
|
||||
}
|
||||
@@ -106,20 +106,20 @@ IndexedPropertySetterResult CSSUnparsedValue::AnonymousIndexedSetter(
|
||||
uint32_t index,
|
||||
V8CSSUnparsedSegment* segment,
|
||||
ExceptionState& exception_state) {
|
||||
- if (index < tokens_.size()) {
|
||||
- tokens_[index] = segment;
|
||||
+ if (index < segments_.size()) {
|
||||
+ segments_[index] = segment;
|
||||
return IndexedPropertySetterResult::kIntercepted;
|
||||
}
|
||||
|
||||
- if (index == tokens_.size()) {
|
||||
- tokens_.push_back(segment);
|
||||
+ if (index == segments_.size()) {
|
||||
+ segments_.push_back(segment);
|
||||
return IndexedPropertySetterResult::kIntercepted;
|
||||
}
|
||||
|
||||
exception_state.ThrowRangeError(
|
||||
ExceptionMessages::IndexOutsideRange<unsigned>(
|
||||
- "index", index, 0, ExceptionMessages::kInclusiveBound, tokens_.size(),
|
||||
- ExceptionMessages::kInclusiveBound));
|
||||
+ "index", index, 0, ExceptionMessages::kInclusiveBound,
|
||||
+ segments_.size(), ExceptionMessages::kInclusiveBound));
|
||||
return IndexedPropertySetterResult::kIntercepted;
|
||||
}
|
||||
|
||||
@@ -182,14 +182,14 @@ bool CSSUnparsedValue::AppendUnparsedString(
|
||||
return false; // Cycle.
|
||||
}
|
||||
values_on_stack.insert(this);
|
||||
- for (unsigned i = 0; i < tokens_.size(); i++) {
|
||||
+ for (unsigned i = 0; i < segments_.size(); i++) {
|
||||
if (i) {
|
||||
builder.Append("/**/");
|
||||
}
|
||||
- switch (tokens_[i]->GetContentType()) {
|
||||
+ switch (segments_[i]->GetContentType()) {
|
||||
case V8CSSUnparsedSegment::ContentType::kCSSVariableReferenceValue: {
|
||||
const auto* reference_value =
|
||||
- tokens_[i]->GetAsCSSVariableReferenceValue();
|
||||
+ segments_[i]->GetAsCSSVariableReferenceValue();
|
||||
builder.Append("var(");
|
||||
builder.Append(reference_value->variable());
|
||||
if (reference_value->fallback()) {
|
||||
@@ -203,7 +203,7 @@ bool CSSUnparsedValue::AppendUnparsedString(
|
||||
break;
|
||||
}
|
||||
case V8CSSUnparsedSegment::ContentType::kString:
|
||||
- builder.Append(tokens_[i]->GetAsString());
|
||||
+ builder.Append(segments_[i]->GetAsString());
|
||||
break;
|
||||
}
|
||||
}
|
||||
diff --git a/third_party/blink/renderer/core/css/cssom/css_unparsed_value.h b/third_party/blink/renderer/core/css/cssom/css_unparsed_value.h
|
||||
index c9dab7a0b3ffeaeb6b5d2ab50d876d40c38a760e..5d1961b170f14ae21ca8f69b3c3cd8af28f4478a 100644
|
||||
--- a/third_party/blink/renderer/core/css/cssom/css_unparsed_value.h
|
||||
+++ b/third_party/blink/renderer/core/css/cssom/css_unparsed_value.h
|
||||
@@ -26,8 +26,8 @@ class CORE_EXPORT CSSUnparsedValue final : public CSSStyleValue {
|
||||
|
||||
public:
|
||||
static CSSUnparsedValue* Create(
|
||||
- const HeapVector<Member<V8CSSUnparsedSegment>>& tokens) {
|
||||
- return MakeGarbageCollected<CSSUnparsedValue>(tokens);
|
||||
+ const HeapVector<Member<V8CSSUnparsedSegment>>& segments) {
|
||||
+ return MakeGarbageCollected<CSSUnparsedValue>(segments);
|
||||
}
|
||||
|
||||
// Blink-internal constructor
|
||||
@@ -37,14 +37,14 @@ class CORE_EXPORT CSSUnparsedValue final : public CSSStyleValue {
|
||||
static CSSUnparsedValue* FromCSSValue(const CSSUnparsedDeclarationValue&);
|
||||
static CSSUnparsedValue* FromCSSVariableData(const CSSVariableData&);
|
||||
static CSSUnparsedValue* FromString(const String& string) {
|
||||
- HeapVector<Member<V8CSSUnparsedSegment>> tokens;
|
||||
- tokens.push_back(MakeGarbageCollected<V8CSSUnparsedSegment>(string));
|
||||
- return Create(tokens);
|
||||
+ HeapVector<Member<V8CSSUnparsedSegment>> segments;
|
||||
+ segments.push_back(MakeGarbageCollected<V8CSSUnparsedSegment>(string));
|
||||
+ return Create(segments);
|
||||
}
|
||||
|
||||
explicit CSSUnparsedValue(
|
||||
- const HeapVector<Member<V8CSSUnparsedSegment>>& tokens)
|
||||
- : tokens_(tokens) {}
|
||||
+ const HeapVector<Member<V8CSSUnparsedSegment>>& segments)
|
||||
+ : segments_(segments) {}
|
||||
CSSUnparsedValue(const CSSUnparsedValue&) = delete;
|
||||
CSSUnparsedValue& operator=(const CSSUnparsedValue&) = delete;
|
||||
|
||||
@@ -60,10 +60,10 @@ class CORE_EXPORT CSSUnparsedValue final : public CSSStyleValue {
|
||||
V8CSSUnparsedSegment* segment,
|
||||
ExceptionState& exception_state);
|
||||
|
||||
- wtf_size_t length() const { return tokens_.size(); }
|
||||
+ wtf_size_t length() const { return segments_.size(); }
|
||||
|
||||
void Trace(Visitor* visitor) const override {
|
||||
- visitor->Trace(tokens_);
|
||||
+ visitor->Trace(segments_);
|
||||
CSSStyleValue::Trace(visitor);
|
||||
}
|
||||
|
||||
@@ -81,7 +81,7 @@ class CORE_EXPORT CSSUnparsedValue final : public CSSStyleValue {
|
||||
StringBuilder&,
|
||||
HeapHashSet<Member<const CSSUnparsedValue>>& values_on_stack) const;
|
||||
|
||||
- HeapVector<Member<V8CSSUnparsedSegment>> tokens_;
|
||||
+ HeapVector<Member<V8CSSUnparsedSegment>> segments_;
|
||||
|
||||
FRIEND_TEST_ALL_PREFIXES(CSSUnparsedDeclarationValueTest, MixedList);
|
||||
};
|
||||
149
patches/chromium/cherry-pick-50b057660b4d.patch
Normal file
149
patches/chromium/cherry-pick-50b057660b4d.patch
Normal file
@@ -0,0 +1,149 @@
|
||||
From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001
|
||||
From: Kai Ninomiya <kainino@chromium.org>
|
||||
Date: Wed, 11 Mar 2026 14:52:44 -0700
|
||||
Subject: [M146] Increment WebGL context generation number on context restore
|
||||
|
||||
Objects created while the context is lost should not be valid to use
|
||||
after the context is restored.
|
||||
- Replace number_of_context_losses_ with a "context generation number"
|
||||
which increments on both context loss and context restore.
|
||||
- Technically, it would make sense to increment it only on context
|
||||
restore, but just in case any logic is relying on the current
|
||||
behavior, increment it in both places.
|
||||
- It's uint64_t just in case someone figures out how to increment it 4
|
||||
billion times.
|
||||
- Remove unused WebGLRenderingContextBase::number_of_context_losses_,
|
||||
left over from before it was moved into WebGLContextObjectSupport.
|
||||
|
||||
(cherry picked from commit c1433740f3ea902fd6b15d63c4865ad60a3761f9)
|
||||
|
||||
Bug: 485935305
|
||||
Change-Id: I1007217c8e69cfb8de4f117e0b7845ca574579c4
|
||||
Reviewed-on: https://chromium-review.googlesource.com/c/chromium/src/+/7630664
|
||||
Reviewed-by: Kenneth Russell <kbr@chromium.org>
|
||||
Commit-Queue: Kai Ninomiya <kainino@chromium.org>
|
||||
Cr-Original-Commit-Position: refs/heads/main@{#1593726}
|
||||
Reviewed-on: https://chromium-review.googlesource.com/c/chromium/src/+/7658823
|
||||
Auto-Submit: Kai Ninomiya <kainino@chromium.org>
|
||||
Bot-Commit: Rubber Stamper <rubber-stamper@appspot.gserviceaccount.com>
|
||||
Commit-Queue: Rubber Stamper <rubber-stamper@appspot.gserviceaccount.com>
|
||||
Cr-Commit-Position: refs/branch-heads/7680@{#2370}
|
||||
Cr-Branched-From: 76b7d80e5cda23fe6537eed26d68c92e995c7f39-refs/heads/main@{#1582197}
|
||||
|
||||
diff --git a/third_party/blink/renderer/modules/webgl/webgl_context_object_support.cc b/third_party/blink/renderer/modules/webgl/webgl_context_object_support.cc
|
||||
index 6a3b1416354e7993e7a9ebd25c4ca08593105d9a..83941f8163a5e9425f2df8fd3bb98e1fd37537ad 100644
|
||||
--- a/third_party/blink/renderer/modules/webgl/webgl_context_object_support.cc
|
||||
+++ b/third_party/blink/renderer/modules/webgl/webgl_context_object_support.cc
|
||||
@@ -22,7 +22,10 @@ WebGLContextObjectSupport::WebGLContextObjectSupport(
|
||||
|
||||
void WebGLContextObjectSupport::OnContextLost() {
|
||||
DCHECK(!is_lost_);
|
||||
- number_of_context_losses_++;
|
||||
+ // Invalidate all past objects.
|
||||
+ // (It may not be strictly necessary to do this here, since it's also done in
|
||||
+ // OnContextRestored, but we did it historically, and there's no harm in it.)
|
||||
+ context_generation_++;
|
||||
is_lost_ = true;
|
||||
gles2_interface_ = nullptr;
|
||||
extensions_enabled_.reset();
|
||||
@@ -31,6 +34,8 @@ void WebGLContextObjectSupport::OnContextLost() {
|
||||
void WebGLContextObjectSupport::OnContextRestored(
|
||||
gpu::gles2::GLES2Interface* gl) {
|
||||
DCHECK(is_lost_);
|
||||
+ // Invalidate all past objects.
|
||||
+ context_generation_++;
|
||||
is_lost_ = false;
|
||||
gles2_interface_ = gl;
|
||||
}
|
||||
diff --git a/third_party/blink/renderer/modules/webgl/webgl_context_object_support.h b/third_party/blink/renderer/modules/webgl/webgl_context_object_support.h
|
||||
index 907866bb21acf9647d1c0ecd791e642e96b734fc..ba8b79f8bb9db12058614982a625baaff5546af7 100644
|
||||
--- a/third_party/blink/renderer/modules/webgl/webgl_context_object_support.h
|
||||
+++ b/third_party/blink/renderer/modules/webgl/webgl_context_object_support.h
|
||||
@@ -33,10 +33,10 @@ class MODULES_EXPORT WebGLContextObjectSupport : public ScriptWrappable {
|
||||
bool IsWebGL2() const { return is_webgl2_; }
|
||||
bool IsLost() const { return is_lost_; }
|
||||
|
||||
- // How many context losses there were, to check whether a WebGLObject was
|
||||
- // created since the last context resoration or before that (and hence invalid
|
||||
- // to use).
|
||||
- uint32_t NumberOfContextLosses() const { return number_of_context_losses_; }
|
||||
+ // Which "generation" the context is on (essentially, how many times it has
|
||||
+ // been restored), to check whether a WebGLObject was created since the last
|
||||
+ // context restoration, or before that (and hence invalid to use).
|
||||
+ uint64_t GetContextGeneration() const { return context_generation_; }
|
||||
|
||||
bool ExtensionEnabled(WebGLExtensionName name) const {
|
||||
return extensions_enabled_.test(name);
|
||||
@@ -65,7 +65,7 @@ class MODULES_EXPORT WebGLContextObjectSupport : public ScriptWrappable {
|
||||
std::bitset<kWebGLExtensionNameCount> extensions_enabled_ = {};
|
||||
raw_ptr<gpu::gles2::GLES2Interface> gles2_interface_ = nullptr;
|
||||
|
||||
- uint32_t number_of_context_losses_ = 0;
|
||||
+ uint64_t context_generation_ = 0;
|
||||
bool is_lost_ = true;
|
||||
bool is_webgl2_;
|
||||
};
|
||||
diff --git a/third_party/blink/renderer/modules/webgl/webgl_object.cc b/third_party/blink/renderer/modules/webgl/webgl_object.cc
|
||||
index 9d984de0073796f23a5038bfc0a51ec676179765..07e0a9a4aa3406a1298a677a3159edadc5f2cbb5 100644
|
||||
--- a/third_party/blink/renderer/modules/webgl/webgl_object.cc
|
||||
+++ b/third_party/blink/renderer/modules/webgl/webgl_object.cc
|
||||
@@ -33,9 +33,9 @@ namespace blink {
|
||||
|
||||
WebGLObject::WebGLObject(WebGLContextObjectSupport* context)
|
||||
: context_(context),
|
||||
- cached_number_of_context_losses_(std::numeric_limits<uint32_t>::max()) {
|
||||
+ context_generation_at_creation_(std::numeric_limits<uint64_t>::max()) {
|
||||
if (context_) {
|
||||
- cached_number_of_context_losses_ = context->NumberOfContextLosses();
|
||||
+ context_generation_at_creation_ = context->GetContextGeneration();
|
||||
}
|
||||
}
|
||||
|
||||
@@ -46,7 +46,7 @@ bool WebGLObject::Validate(const WebGLContextObjectSupport* context) const {
|
||||
// the objects they ever created, so there's no way to invalidate them
|
||||
// eagerly during context loss. The invalidation is discovered lazily.
|
||||
return (context == context_ && context_ != nullptr &&
|
||||
- cached_number_of_context_losses_ == context->NumberOfContextLosses());
|
||||
+ context_generation_at_creation_ == context->GetContextGeneration());
|
||||
}
|
||||
|
||||
void WebGLObject::SetObject(GLuint object) {
|
||||
@@ -71,7 +71,7 @@ void WebGLObject::DeleteObject(gpu::gles2::GLES2Interface* gl) {
|
||||
return;
|
||||
}
|
||||
|
||||
- if (context_->NumberOfContextLosses() != cached_number_of_context_losses_) {
|
||||
+ if (context_->GetContextGeneration() != context_generation_at_creation_) {
|
||||
// This object has been invalidated.
|
||||
return;
|
||||
}
|
||||
diff --git a/third_party/blink/renderer/modules/webgl/webgl_object.h b/third_party/blink/renderer/modules/webgl/webgl_object.h
|
||||
index bb56df0f99e8e8432e03442feb9302b8dde27d01..97caa90e34288911b1a827e60c2569544d2b8f69 100644
|
||||
--- a/third_party/blink/renderer/modules/webgl/webgl_object.h
|
||||
+++ b/third_party/blink/renderer/modules/webgl/webgl_object.h
|
||||
@@ -123,9 +123,9 @@ class WebGLObject : public ScriptWrappable {
|
||||
|
||||
GLuint object_ = 0;
|
||||
|
||||
- // This was the number of context losses of the object's associated
|
||||
- // WebGLContext at the time this object was created.
|
||||
- uint32_t cached_number_of_context_losses_;
|
||||
+ // The context generation number of the associated WebGLContext when the
|
||||
+ // object was created, to prevent reuse in later generations.
|
||||
+ uint64_t context_generation_at_creation_;
|
||||
|
||||
unsigned attachment_count_ = 0;
|
||||
|
||||
diff --git a/third_party/blink/renderer/modules/webgl/webgl_rendering_context_base.h b/third_party/blink/renderer/modules/webgl/webgl_rendering_context_base.h
|
||||
index 48b5dd8f3baffed5ae898e029f7dd187ddf20ce3..33554fe5b9cdbbd703b6e02d6131104a4e591f4e 100644
|
||||
--- a/third_party/blink/renderer/modules/webgl/webgl_rendering_context_base.h
|
||||
+++ b/third_party/blink/renderer/modules/webgl/webgl_rendering_context_base.h
|
||||
@@ -2064,8 +2064,6 @@ class MODULES_EXPORT WebGLRenderingContextBase
|
||||
|
||||
bool has_been_drawn_to_ = false;
|
||||
|
||||
- uint32_t number_of_context_losses_ = 0;
|
||||
-
|
||||
// Tracks if the context has ever called glBeginPixelLocalStorageANGLE. If it
|
||||
// has, we need to start using the pixel local storage interrupt mechanism
|
||||
// when we take over the client's context.
|
||||
201
patches/chromium/cherry-pick-5efc7a0127a6.patch
Normal file
201
patches/chromium/cherry-pick-5efc7a0127a6.patch
Normal file
@@ -0,0 +1,201 @@
|
||||
From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001
|
||||
From: Anders Hartvoll Ruud <andruud@chromium.org>
|
||||
Date: Wed, 25 Feb 2026 12:17:00 -0800
|
||||
Subject: Validate CSSUnparsedValues upon assignment
|
||||
|
||||
CSS Typed OM has a concept of a value "matching a grammar" (or not)
|
||||
upon assignment to a property [1]. For CSSUnparsedValues, we currently
|
||||
don't perform any significant validation, and as a consequence
|
||||
we allow "invalid" CSSUnparsedDeclarationValues to be created
|
||||
(causing DCHECKs later in the pipeline).
|
||||
|
||||
This CL makes sure values can be parsed using CSSVariableParser::
|
||||
ConsumeUnparsedDeclaration before assignment.
|
||||
|
||||
We're still not handling the value in the context of the destination
|
||||
property, which we probably should. This is also a problem with
|
||||
current state of things, however, so for now the goal is primarily
|
||||
to avoid the DCHECKs in Issue 484751092.
|
||||
|
||||
Finally, I opened an issue against the specification [2], which
|
||||
currently doesn't define any of this.
|
||||
|
||||
[1] https://drafts.css-houdini.org/css-typed-om-1/#create-an-internal-representation
|
||||
[2] https://github.com/w3c/csswg-drafts/issues/13547
|
||||
|
||||
Fixed: 484751092
|
||||
Change-Id: Id7f888a6df8c02ade24910900f5d01909cb2dfad
|
||||
Reviewed-on: https://chromium-review.googlesource.com/c/chromium/src/+/7595347
|
||||
Reviewed-by: Steinar H Gunderson <sesse@chromium.org>
|
||||
Commit-Queue: Anders Hartvoll Ruud <andruud@chromium.org>
|
||||
Cr-Commit-Position: refs/heads/main@{#1590110}
|
||||
|
||||
diff --git a/third_party/blink/renderer/build/scripts/core/css/templates/cssom_types.cc.tmpl b/third_party/blink/renderer/build/scripts/core/css/templates/cssom_types.cc.tmpl
|
||||
index edfa73a57d30ebd4f9a7147702df42b836f7d82b..4442ba0872ca4c739596b546e6d3b600c5a31598 100644
|
||||
--- a/third_party/blink/renderer/build/scripts/core/css/templates/cssom_types.cc.tmpl
|
||||
+++ b/third_party/blink/renderer/build/scripts/core/css/templates/cssom_types.cc.tmpl
|
||||
@@ -11,6 +11,7 @@
|
||||
#include "third_party/blink/renderer/core/css/cssom/css_keyword_value.h"
|
||||
#include "third_party/blink/renderer/core/css/cssom/css_numeric_value.h"
|
||||
#include "third_party/blink/renderer/core/css/cssom/css_style_value.h"
|
||||
+#include "third_party/blink/renderer/core/css/cssom/css_unparsed_value.h"
|
||||
#include "third_party/blink/renderer/core/css/cssom/css_unsupported_style_value.h"
|
||||
#include "third_party/blink/renderer/core/css/cssom/cssom_keywords.h"
|
||||
#include "third_party/blink/renderer/core/css/properties/css_property.h"
|
||||
@@ -105,8 +106,8 @@ bool CSSOMTypes::PropertyCanTake(CSSPropertyID id,
|
||||
: CSSPropertyName(id);
|
||||
return unsupported_style_value->IsValidFor(name);
|
||||
}
|
||||
- if (value.GetType() == CSSStyleValue::kUnparsedType) {
|
||||
- return true;
|
||||
+ if (auto* unparsed_value = DynamicTo<CSSUnparsedValue>(value)) {
|
||||
+ return unparsed_value->IsValidDeclarationValue();
|
||||
}
|
||||
|
||||
switch (id) {
|
||||
diff --git a/third_party/blink/renderer/core/css/cssom/css_unparsed_value.cc b/third_party/blink/renderer/core/css/cssom/css_unparsed_value.cc
|
||||
index 9c6bb62d044f804b0ce7bc8df398d77695cf950c..17a86e1292d76ff0b0c74b701750c0e972b4d885 100644
|
||||
--- a/third_party/blink/renderer/core/css/cssom/css_unparsed_value.cc
|
||||
+++ b/third_party/blink/renderer/core/css/cssom/css_unparsed_value.cc
|
||||
@@ -4,11 +4,13 @@
|
||||
|
||||
#include "third_party/blink/renderer/core/css/cssom/css_unparsed_value.h"
|
||||
|
||||
+#include "css_style_value.h"
|
||||
#include "third_party/blink/renderer/core/css/css_unparsed_declaration_value.h"
|
||||
#include "third_party/blink/renderer/core/css/css_variable_data.h"
|
||||
#include "third_party/blink/renderer/core/css/cssom/css_style_variable_reference_value.h"
|
||||
#include "third_party/blink/renderer/core/css/parser/css_parser_token_stream.h"
|
||||
#include "third_party/blink/renderer/core/css/parser/css_tokenizer.h"
|
||||
+#include "third_party/blink/renderer/core/css/parser/css_variable_parser.h"
|
||||
#include "third_party/blink/renderer/core/css_value_keywords.h"
|
||||
#include "third_party/blink/renderer/platform/bindings/exception_messages.h"
|
||||
#include "third_party/blink/renderer/platform/bindings/exception_state.h"
|
||||
@@ -123,6 +125,10 @@ IndexedPropertySetterResult CSSUnparsedValue::AnonymousIndexedSetter(
|
||||
return IndexedPropertySetterResult::kIntercepted;
|
||||
}
|
||||
|
||||
+bool CSSUnparsedValue::IsValidDeclarationValue() const {
|
||||
+ return IsValidDeclarationValue(ToStringInternal());
|
||||
+}
|
||||
+
|
||||
const CSSValue* CSSUnparsedValue::ToCSSValue() const {
|
||||
String unparsed_string = ToStringInternal();
|
||||
|
||||
@@ -131,12 +137,40 @@ const CSSValue* CSSUnparsedValue::ToCSSValue() const {
|
||||
MakeGarbageCollected<CSSVariableData>());
|
||||
}
|
||||
|
||||
+ CHECK(IsValidDeclarationValue(unparsed_string));
|
||||
+ // The call to IsValidDeclarationValue() above also creates a CSSVariableData
|
||||
+ // to carry out its check. It would be nice to use that here, but WPTs
|
||||
+ // expect leading whitespace to be preserved, even though it's not possible
|
||||
+ // to create such declaration values normally.
|
||||
+ CSSVariableData* variable_data =
|
||||
+ CSSVariableData::Create(unparsed_string,
|
||||
+ /*is_animation_tainted=*/false,
|
||||
+ /*is_attr_tainted=*/false,
|
||||
+ /*needs_variable_resolution=*/false);
|
||||
+
|
||||
// TODO(crbug.com/985028): We should probably propagate the CSSParserContext
|
||||
// to here.
|
||||
- return MakeGarbageCollected<CSSUnparsedDeclarationValue>(
|
||||
- CSSVariableData::Create(unparsed_string, false /* is_animation_tainted */,
|
||||
- false /* is_attr_tainted */,
|
||||
- false /* needs_variable_resolution */));
|
||||
+ return MakeGarbageCollected<CSSUnparsedDeclarationValue>(variable_data);
|
||||
+}
|
||||
+
|
||||
+bool CSSUnparsedValue::IsValidDeclarationValue(const String& string) {
|
||||
+ CSSParserTokenStream stream(string);
|
||||
+ bool important_unused;
|
||||
+ // This checks that the value does not violate the "argument grammar" [1]
|
||||
+ // of any substitution functions, and that it is a valid <declaration-value>
|
||||
+ // otherwise.
|
||||
+ //
|
||||
+ // [1] https://drafts.csswg.org/css-values-5/#argument-grammar
|
||||
+ //
|
||||
+ // TODO(andruud): 'restricted_value' depends on the destination property.
|
||||
+ return CSSVariableParser::ConsumeUnparsedDeclaration(
|
||||
+ stream,
|
||||
+ /*allow_important_annotation=*/false,
|
||||
+ /*is_animation_tainted=*/false,
|
||||
+ /*must_contain_variable_reference=*/false,
|
||||
+ /*restricted_value=*/false,
|
||||
+ /*comma_ends_declaration=*/false, important_unused,
|
||||
+ *StrictCSSParserContext(SecureContextMode::kInsecureContext));
|
||||
}
|
||||
|
||||
String CSSUnparsedValue::ToStringInternal() const {
|
||||
diff --git a/third_party/blink/renderer/core/css/cssom/css_unparsed_value.h b/third_party/blink/renderer/core/css/cssom/css_unparsed_value.h
|
||||
index ec7e3ed708f406d7a61fdb370b2eed8a8297cffb..7fd66aed677e31046a1bd206854b2cbeac07c25b 100644
|
||||
--- a/third_party/blink/renderer/core/css/cssom/css_unparsed_value.h
|
||||
+++ b/third_party/blink/renderer/core/css/cssom/css_unparsed_value.h
|
||||
@@ -48,6 +48,14 @@ class CORE_EXPORT CSSUnparsedValue final : public CSSStyleValue {
|
||||
CSSUnparsedValue(const CSSUnparsedValue&) = delete;
|
||||
CSSUnparsedValue& operator=(const CSSUnparsedValue&) = delete;
|
||||
|
||||
+ // True if this CSSUnparsedValue can be converted into
|
||||
+ // a CSSUnparsedDeclarationValue.
|
||||
+ //
|
||||
+ // We may want to ban some invalid values earlier, see:
|
||||
+ // https://github.com/w3c/csswg-drafts/issues/13547
|
||||
+ bool IsValidDeclarationValue() const;
|
||||
+
|
||||
+ // Requires IsValidDeclarationValue()==true.
|
||||
const CSSValue* ToCSSValue() const override;
|
||||
|
||||
StyleValueType GetType() const override { return kUnparsedType; }
|
||||
@@ -68,6 +76,7 @@ class CORE_EXPORT CSSUnparsedValue final : public CSSStyleValue {
|
||||
}
|
||||
|
||||
private:
|
||||
+ static bool IsValidDeclarationValue(const String&);
|
||||
String ToStringInternal() const;
|
||||
String SerializeSegments() const;
|
||||
// Return 'false' if there is a cycle in the serialization.
|
||||
diff --git a/third_party/blink/web_tests/external/wpt/css/css-typed-om/set-invalid-untyped-value-crash.html b/third_party/blink/web_tests/external/wpt/css/css-typed-om/set-invalid-untyped-value-crash.html
|
||||
new file mode 100644
|
||||
index 0000000000000000000000000000000000000000..ce618bf38fe651297b969ffdc16e212dee6a3688
|
||||
--- /dev/null
|
||||
+++ b/third_party/blink/web_tests/external/wpt/css/css-typed-om/set-invalid-untyped-value-crash.html
|
||||
@@ -0,0 +1,39 @@
|
||||
+<!DOCTYPE html>
|
||||
+<title>Crash when setting invalid CSSUnparsedValue</title>
|
||||
+<link rel="help" href="https://github.com/w3c/csswg-drafts/issues/13547">
|
||||
+<div id=target></div>
|
||||
+<script>
|
||||
+ let examples = [
|
||||
+ 'var()',
|
||||
+ 'var(,)',
|
||||
+ 'var(0)',
|
||||
+ 'env()',
|
||||
+ 'env(,)',
|
||||
+ 'env(0)',
|
||||
+ 'attr()',
|
||||
+ 'attr(,)',
|
||||
+ 'attr(0)',
|
||||
+ 'if()',
|
||||
+ 'if(,)',
|
||||
+ 'if(0)',
|
||||
+ '--f()',
|
||||
+ '--f(,)',
|
||||
+ '--f(0)',
|
||||
+ 'thing!!!',
|
||||
+ 'var(--x) !important',
|
||||
+ ];
|
||||
+ // Some of the above cases may be valid. That's fine; just don't crash.
|
||||
+
|
||||
+ for (let e of examples) {
|
||||
+ try {
|
||||
+ let value = new CSSUnparsedValue([e]);
|
||||
+ target.attributeStyleMap.set('width', value);
|
||||
+ // One of the two above statements should likely throw an exception.
|
||||
+ // If they don't, then we should at least not crash on get():
|
||||
+ target.attributeStyleMap.get('width');
|
||||
+ } catch (e) {
|
||||
+ // Intentionally empty.
|
||||
+ }
|
||||
+ target.offsetTop;
|
||||
+ }
|
||||
+</script>
|
||||
@@ -65,7 +65,7 @@ index 2748dd196fe1f56357348a204e24f0b8a28b97dd..5800dd00b47c657d9e6766f3fc5a3065
|
||||
#if BUILDFLAG(IS_WIN)
|
||||
bool EscapeVirtualization(const base::FilePath& user_data_dir);
|
||||
diff --git a/chrome/browser/process_singleton_posix.cc b/chrome/browser/process_singleton_posix.cc
|
||||
index 08cbe32a258bf478f1da0a07064d3e9ef14c44a5..b9f2a43cb90fac4b031a4b4da38d6435a50990d2 100644
|
||||
index 08cbe32a258bf478f1da0a07064d3e9ef14c44a5..c683575aab2154b46b1fa9cc9e5e30aa8ed4f0ee 100644
|
||||
--- a/chrome/browser/process_singleton_posix.cc
|
||||
+++ b/chrome/browser/process_singleton_posix.cc
|
||||
@@ -614,6 +614,7 @@ class ProcessSingleton::LinuxWatcher
|
||||
@@ -106,21 +106,39 @@ index 08cbe32a258bf478f1da0a07064d3e9ef14c44a5..b9f2a43cb90fac4b031a4b4da38d6435
|
||||
const size_t kMinMessageLength = std::size(kStartToken) + 4;
|
||||
if (bytes_read_ < kMinMessageLength) {
|
||||
buf_[bytes_read_] = 0;
|
||||
@@ -757,10 +763,28 @@ void ProcessSingleton::LinuxWatcher::SocketReader::
|
||||
@@ -757,10 +763,46 @@ void ProcessSingleton::LinuxWatcher::SocketReader::
|
||||
tokens.erase(tokens.begin());
|
||||
tokens.erase(tokens.begin());
|
||||
|
||||
+ size_t num_args;
|
||||
+ base::StringToSizeT(tokens[0], &num_args);
|
||||
+ std::vector<std::string> command_line(tokens.begin() + 1, tokens.begin() + 1 + num_args);
|
||||
+ if (!base::StringToSizeT(tokens[0], &num_args) ||
|
||||
+ num_args > tokens.size() - 1) {
|
||||
+ LOG(ERROR) << "Invalid num_args in socket message";
|
||||
+ CleanupAndDeleteSelf();
|
||||
+ return;
|
||||
+ }
|
||||
+ std::vector<std::string> command_line(tokens.begin() + 1,
|
||||
+ tokens.begin() + 1 + num_args);
|
||||
+
|
||||
+ std::vector<uint8_t> additional_data;
|
||||
+ if (tokens.size() >= 3 + num_args) {
|
||||
+ // After consuming [num_args, argv...], two more tokens are needed for
|
||||
+ // additional data: [size, payload]. Subtract to avoid overflow when
|
||||
+ // num_args is large.
|
||||
+ if (tokens.size() - 1 - num_args >= 2) {
|
||||
+ size_t additional_data_size;
|
||||
+ base::StringToSizeT(tokens[1 + num_args], &additional_data_size);
|
||||
+ if (!base::StringToSizeT(tokens[1 + num_args], &additional_data_size)) {
|
||||
+ LOG(ERROR) << "Invalid additional_data_size in socket message";
|
||||
+ CleanupAndDeleteSelf();
|
||||
+ return;
|
||||
+ }
|
||||
+ std::string remaining_args = base::JoinString(
|
||||
+ base::span(tokens.begin() + 2 + num_args, tokens.end()),
|
||||
+ std::string(1, kTokenDelimiter));
|
||||
+ if (additional_data_size > remaining_args.size()) {
|
||||
+ LOG(ERROR) << "additional_data_size exceeds payload length";
|
||||
+ CleanupAndDeleteSelf();
|
||||
+ return;
|
||||
+ }
|
||||
+ const uint8_t* additional_data_bits =
|
||||
+ reinterpret_cast<const uint8_t*>(remaining_args.c_str());
|
||||
+ additional_data = std::vector<uint8_t>(
|
||||
@@ -136,7 +154,7 @@ index 08cbe32a258bf478f1da0a07064d3e9ef14c44a5..b9f2a43cb90fac4b031a4b4da38d6435
|
||||
fd_watch_controller_.reset();
|
||||
|
||||
// LinuxWatcher::HandleMessage() is in charge of destroying this SocketReader
|
||||
@@ -789,8 +813,10 @@ void ProcessSingleton::LinuxWatcher::SocketReader::FinishWithACK(
|
||||
@@ -789,8 +831,10 @@ void ProcessSingleton::LinuxWatcher::SocketReader::FinishWithACK(
|
||||
//
|
||||
ProcessSingleton::ProcessSingleton(
|
||||
const base::FilePath& user_data_dir,
|
||||
@@ -147,7 +165,7 @@ index 08cbe32a258bf478f1da0a07064d3e9ef14c44a5..b9f2a43cb90fac4b031a4b4da38d6435
|
||||
current_pid_(base::GetCurrentProcId()) {
|
||||
socket_path_ = user_data_dir.Append(chrome::kSingletonSocketFilename);
|
||||
lock_path_ = user_data_dir.Append(chrome::kSingletonLockFilename);
|
||||
@@ -911,7 +937,8 @@ ProcessSingleton::NotifyResult ProcessSingleton::NotifyOtherProcessWithTimeout(
|
||||
@@ -911,7 +955,8 @@ ProcessSingleton::NotifyResult ProcessSingleton::NotifyOtherProcessWithTimeout(
|
||||
sizeof(socket_timeout));
|
||||
|
||||
// Found another process, prepare our command line
|
||||
@@ -157,7 +175,7 @@ index 08cbe32a258bf478f1da0a07064d3e9ef14c44a5..b9f2a43cb90fac4b031a4b4da38d6435
|
||||
std::string to_send(kStartToken);
|
||||
to_send.push_back(kTokenDelimiter);
|
||||
|
||||
@@ -921,11 +948,21 @@ ProcessSingleton::NotifyResult ProcessSingleton::NotifyOtherProcessWithTimeout(
|
||||
@@ -921,11 +966,21 @@ ProcessSingleton::NotifyResult ProcessSingleton::NotifyOtherProcessWithTimeout(
|
||||
to_send.append(current_dir.value());
|
||||
|
||||
const std::vector<std::string>& argv = cmd_line.argv();
|
||||
@@ -180,10 +198,18 @@ index 08cbe32a258bf478f1da0a07064d3e9ef14c44a5..b9f2a43cb90fac4b031a4b4da38d6435
|
||||
if (!WriteToSocket(socket.fd(), to_send.data(), to_send.length())) {
|
||||
// Try to kill the other process, because it might have been dead.
|
||||
diff --git a/chrome/browser/process_singleton_win.cc b/chrome/browser/process_singleton_win.cc
|
||||
index 64ebf49c0d1b6396d1cfbe3bf91480f61b47688d..bec94d4039379400ae8b00f1adbbb16a02ccbac0 100644
|
||||
index 64ebf49c0d1b6396d1cfbe3bf91480f61b47688d..3458909dd20e2b7fdf624a0e0eaeed6e8271475b 100644
|
||||
--- a/chrome/browser/process_singleton_win.cc
|
||||
+++ b/chrome/browser/process_singleton_win.cc
|
||||
@@ -81,10 +81,12 @@ BOOL CALLBACK BrowserWindowEnumeration(HWND window, LPARAM param) {
|
||||
@@ -9,6 +9,7 @@
|
||||
#include <shellapi.h>
|
||||
#include <stddef.h>
|
||||
|
||||
+#include "base/base64.h"
|
||||
#include "base/base_paths.h"
|
||||
#include "base/command_line.h"
|
||||
#include "base/files/file_path.h"
|
||||
@@ -81,10 +82,12 @@ BOOL CALLBACK BrowserWindowEnumeration(HWND window, LPARAM param) {
|
||||
|
||||
bool ParseCommandLine(const COPYDATASTRUCT* cds,
|
||||
base::CommandLine* parsed_command_line,
|
||||
@@ -198,7 +224,7 @@ index 64ebf49c0d1b6396d1cfbe3bf91480f61b47688d..bec94d4039379400ae8b00f1adbbb16a
|
||||
static const int min_message_size = 7;
|
||||
if (cds->cbData < min_message_size * sizeof(wchar_t) ||
|
||||
cds->cbData % sizeof(wchar_t) != 0) {
|
||||
@@ -134,6 +136,23 @@ bool ParseCommandLine(const COPYDATASTRUCT* cds,
|
||||
@@ -134,6 +137,25 @@ bool ParseCommandLine(const COPYDATASTRUCT* cds,
|
||||
const std::wstring cmd_line =
|
||||
msg.substr(second_null + 1, third_null - second_null);
|
||||
*parsed_command_line = base::CommandLine::FromString(cmd_line);
|
||||
@@ -211,18 +237,20 @@ index 64ebf49c0d1b6396d1cfbe3bf91480f61b47688d..bec94d4039379400ae8b00f1adbbb16a
|
||||
+ return true;
|
||||
+ }
|
||||
+
|
||||
+ // Get the actual additional data.
|
||||
+ const std::wstring additional_data =
|
||||
+ msg.substr(third_null + 1, fourth_null - third_null);
|
||||
+ base::span<const uint8_t> additional_data_bytes =
|
||||
+ base::as_byte_span(additional_data);
|
||||
+ *parsed_additional_data = std::vector<uint8_t>(
|
||||
+ additional_data_bytes.begin(), additional_data_bytes.end());
|
||||
+ // Get the actual additional data. It is base64-encoded so it can
|
||||
+ // safely traverse the null-delimited wchar_t buffer.
|
||||
+ const std::wstring encoded_w =
|
||||
+ msg.substr(third_null + 1, fourth_null - third_null - 1);
|
||||
+ std::string encoded = base::WideToASCII(encoded_w);
|
||||
+ std::optional<std::vector<uint8_t>> decoded = base::Base64Decode(encoded);
|
||||
+ if (decoded) {
|
||||
+ *parsed_additional_data = std::move(*decoded);
|
||||
+ }
|
||||
+
|
||||
return true;
|
||||
}
|
||||
return false;
|
||||
@@ -155,13 +174,14 @@ bool ProcessLaunchNotification(
|
||||
@@ -155,13 +177,14 @@ bool ProcessLaunchNotification(
|
||||
|
||||
base::CommandLine parsed_command_line(base::CommandLine::NO_PROGRAM);
|
||||
base::FilePath current_directory;
|
||||
@@ -240,7 +268,7 @@ index 64ebf49c0d1b6396d1cfbe3bf91480f61b47688d..bec94d4039379400ae8b00f1adbbb16a
|
||||
return true;
|
||||
}
|
||||
|
||||
@@ -265,9 +285,11 @@ bool ProcessSingleton::EscapeVirtualization(
|
||||
@@ -265,9 +288,11 @@ bool ProcessSingleton::EscapeVirtualization(
|
||||
ProcessSingleton::ProcessSingleton(
|
||||
const std::string& program_name,
|
||||
const base::FilePath& user_data_dir,
|
||||
@@ -252,7 +280,7 @@ index 64ebf49c0d1b6396d1cfbe3bf91480f61b47688d..bec94d4039379400ae8b00f1adbbb16a
|
||||
program_name_(program_name),
|
||||
is_app_sandboxed_(is_app_sandboxed),
|
||||
is_virtualized_(false),
|
||||
@@ -294,7 +316,7 @@ ProcessSingleton::NotifyResult ProcessSingleton::NotifyOtherProcess() {
|
||||
@@ -294,7 +319,7 @@ ProcessSingleton::NotifyResult ProcessSingleton::NotifyOtherProcess() {
|
||||
return PROCESS_NONE;
|
||||
}
|
||||
|
||||
@@ -262,10 +290,18 @@ index 64ebf49c0d1b6396d1cfbe3bf91480f61b47688d..bec94d4039379400ae8b00f1adbbb16a
|
||||
return PROCESS_NOTIFIED;
|
||||
case NotifyChromeResult::NOTIFY_FAILED:
|
||||
diff --git a/chrome/browser/win/chrome_process_finder.cc b/chrome/browser/win/chrome_process_finder.cc
|
||||
index 58a4c5adfda49fb4bd1b5351bd02d358946043bd..adaa070eb0f3cf8f771b57743a7436fd48a1e576 100644
|
||||
index 58a4c5adfda49fb4bd1b5351bd02d358946043bd..6f21585faca6e98d2ed08be6a91df88947da6b3a 100644
|
||||
--- a/chrome/browser/win/chrome_process_finder.cc
|
||||
+++ b/chrome/browser/win/chrome_process_finder.cc
|
||||
@@ -39,7 +39,9 @@ HWND FindRunningChromeWindow(const base::FilePath& user_data_dir) {
|
||||
@@ -11,6 +11,7 @@
|
||||
#include <string>
|
||||
#include <string_view>
|
||||
|
||||
+#include "base/base64.h"
|
||||
#include "base/check.h"
|
||||
#include "base/command_line.h"
|
||||
#include "base/files/file_path.h"
|
||||
@@ -39,7 +40,9 @@ HWND FindRunningChromeWindow(const base::FilePath& user_data_dir) {
|
||||
return base::win::MessageWindow::FindWindow(user_data_dir.value());
|
||||
}
|
||||
|
||||
@@ -276,7 +312,7 @@ index 58a4c5adfda49fb4bd1b5351bd02d358946043bd..adaa070eb0f3cf8f771b57743a7436fd
|
||||
TRACE_EVENT0("startup", "AttemptToNotifyRunningChrome");
|
||||
|
||||
DCHECK(remote_window);
|
||||
@@ -70,12 +72,24 @@ NotifyChromeResult AttemptToNotifyRunningChrome(HWND remote_window) {
|
||||
@@ -70,12 +73,22 @@ NotifyChromeResult AttemptToNotifyRunningChrome(HWND remote_window) {
|
||||
new_command_line.AppendSwitch(switches::kSourceAppId);
|
||||
}
|
||||
// Send the command line to the remote chrome window.
|
||||
@@ -288,14 +324,12 @@ index 58a4c5adfda49fb4bd1b5351bd02d358946043bd..adaa070eb0f3cf8f771b57743a7436fd
|
||||
std::wstring_view{L"\0", 1}, new_command_line.GetCommandLineString(),
|
||||
std::wstring_view{L"\0", 1}});
|
||||
|
||||
+ size_t additional_data_size = additional_data.size_bytes();
|
||||
+ if (additional_data_size) {
|
||||
+ size_t padded_size = additional_data_size / sizeof(wchar_t);
|
||||
+ if (additional_data_size % sizeof(wchar_t) != 0) {
|
||||
+ padded_size++;
|
||||
+ }
|
||||
+ to_send.append(reinterpret_cast<const wchar_t*>(additional_data.data()),
|
||||
+ padded_size);
|
||||
+ if (!additional_data.empty()) {
|
||||
+ // Base64-encode so the payload survives the null-delimited wchar_t
|
||||
+ // framing; raw serialized bytes can contain 0x0000 sequences which
|
||||
+ // would otherwise terminate the field early.
|
||||
+ std::string encoded = base::Base64Encode(additional_data);
|
||||
+ to_send.append(base::ASCIIToWide(encoded));
|
||||
+ to_send.append(L"\0", 1); // Null separator.
|
||||
+ }
|
||||
+
|
||||
|
||||
@@ -0,0 +1,73 @@
|
||||
From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001
|
||||
From: Samuel Attard <sattard@anthropic.com>
|
||||
Date: Sat, 7 Mar 2026 23:07:30 -0800
|
||||
Subject: feat: plumb node_integration_in_worker through WorkerSettings
|
||||
|
||||
Copy the node_integration_in_worker flag from the initiating frame's
|
||||
WebPreferences into WorkerSettings at dedicated worker creation time,
|
||||
so the value is readable per-worker on the worker thread rather than
|
||||
relying on a process-wide command line switch. The value is also
|
||||
propagated to nested workers via WorkerSettings::Copy.
|
||||
|
||||
diff --git a/third_party/blink/renderer/core/workers/dedicated_worker.cc b/third_party/blink/renderer/core/workers/dedicated_worker.cc
|
||||
index b6cd50a0005a69edcd2b5c059ffa35f82faac792..b74fd8f7e290075d37f10a2c216bef6de60f1052 100644
|
||||
--- a/third_party/blink/renderer/core/workers/dedicated_worker.cc
|
||||
+++ b/third_party/blink/renderer/core/workers/dedicated_worker.cc
|
||||
@@ -37,6 +37,7 @@
|
||||
#include "third_party/blink/renderer/core/frame/local_frame_client.h"
|
||||
#include "third_party/blink/renderer/core/frame/web_frame_widget_impl.h"
|
||||
#include "third_party/blink/renderer/core/frame/web_local_frame_impl.h"
|
||||
+#include "third_party/blink/renderer/core/exported/web_view_impl.h"
|
||||
#include "third_party/blink/renderer/core/inspector/inspector_trace_events.h"
|
||||
#include "third_party/blink/renderer/core/inspector/main_thread_debugger.h"
|
||||
#include "third_party/blink/renderer/core/loader/document_loader.h"
|
||||
@@ -555,6 +556,12 @@ DedicatedWorker::CreateGlobalScopeCreationParams(
|
||||
auto* frame = window->GetFrame();
|
||||
parent_devtools_token = frame->GetDevToolsFrameToken();
|
||||
settings = std::make_unique<WorkerSettings>(frame->GetSettings());
|
||||
+ if (auto* web_local_frame = WebLocalFrameImpl::FromFrame(frame)) {
|
||||
+ if (auto* web_view = web_local_frame->ViewImpl()) {
|
||||
+ settings->SetNodeIntegrationInWorker(
|
||||
+ web_view->GetWebPreferences().node_integration_in_worker);
|
||||
+ }
|
||||
+ }
|
||||
agent_group_scheduler_compositor_task_runner =
|
||||
execution_context->GetScheduler()
|
||||
->ToFrameScheduler()
|
||||
diff --git a/third_party/blink/renderer/core/workers/worker_settings.cc b/third_party/blink/renderer/core/workers/worker_settings.cc
|
||||
index 45680c5f6ea0c7e89ccf43eb88f8a11e3318c02e..3fa3af62f4e7ba8186441c5e3184b1c04fe32d12 100644
|
||||
--- a/third_party/blink/renderer/core/workers/worker_settings.cc
|
||||
+++ b/third_party/blink/renderer/core/workers/worker_settings.cc
|
||||
@@ -40,6 +40,8 @@ std::unique_ptr<WorkerSettings> WorkerSettings::Copy(
|
||||
old_settings->strictly_block_blockable_mixed_content_;
|
||||
new_settings->generic_font_family_settings_ =
|
||||
old_settings->generic_font_family_settings_;
|
||||
+ new_settings->node_integration_in_worker_ =
|
||||
+ old_settings->node_integration_in_worker_;
|
||||
return new_settings;
|
||||
}
|
||||
|
||||
diff --git a/third_party/blink/renderer/core/workers/worker_settings.h b/third_party/blink/renderer/core/workers/worker_settings.h
|
||||
index 45c60dd2c44b05fdd279f759069383479823c7f2..33a2a0337efb9a46293e11d0d09b3fc182ab9618 100644
|
||||
--- a/third_party/blink/renderer/core/workers/worker_settings.h
|
||||
+++ b/third_party/blink/renderer/core/workers/worker_settings.h
|
||||
@@ -43,6 +43,11 @@ class CORE_EXPORT WorkerSettings {
|
||||
return generic_font_family_settings_;
|
||||
}
|
||||
|
||||
+ bool NodeIntegrationInWorker() const { return node_integration_in_worker_; }
|
||||
+ void SetNodeIntegrationInWorker(bool value) {
|
||||
+ node_integration_in_worker_ = value;
|
||||
+ }
|
||||
+
|
||||
private:
|
||||
void CopyFlagValuesFromSettings(Settings*);
|
||||
|
||||
@@ -54,6 +59,7 @@ class CORE_EXPORT WorkerSettings {
|
||||
bool strict_mixed_content_checking_ = false;
|
||||
bool allow_running_of_insecure_content_ = false;
|
||||
bool strictly_block_blockable_mixed_content_ = false;
|
||||
+ bool node_integration_in_worker_ = false;
|
||||
|
||||
GenericFontFamilySettings generic_font_family_settings_;
|
||||
};
|
||||
@@ -0,0 +1,65 @@
|
||||
From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001
|
||||
From: Keeley Hammond <vertedinde@electronjs.org>
|
||||
Date: Mon, 23 Mar 2026 18:27:45 -0700
|
||||
Subject: Validate uniform block count limits at compile time on IMG.
|
||||
|
||||
Normally these limits are validated at link time but the IMG compiler
|
||||
has issues when these limits are exceeded. Validate at compile time
|
||||
instead.
|
||||
|
||||
Bug: chromium:475877320
|
||||
Change-Id: Ieeed6914b8cdd2b5e50242d06facae62badddefd
|
||||
Reviewed-on: https://chromium-review.googlesource.com/c/chromium/src/+/7568129
|
||||
Auto-Submit: Geoff Lang <geofflang@chromium.org>
|
||||
Reviewed-by: Kyle Charbonneau <kylechar@chromium.org>
|
||||
Commit-Queue: Kyle Charbonneau <kylechar@chromium.org>
|
||||
Cr-Commit-Position: refs/heads/main@{#1586673}
|
||||
|
||||
diff --git a/gpu/command_buffer/service/gles2_cmd_decoder.cc b/gpu/command_buffer/service/gles2_cmd_decoder.cc
|
||||
index 02078983a7b10588c7d68f5a3affa5536edb29d5..a7131ef3a34e86d44ce5af5bb8bfab8853c32a50 100644
|
||||
--- a/gpu/command_buffer/service/gles2_cmd_decoder.cc
|
||||
+++ b/gpu/command_buffer/service/gles2_cmd_decoder.cc
|
||||
@@ -3664,6 +3664,9 @@ bool GLES2DecoderImpl::InitializeShaderTranslator() {
|
||||
driver_bug_workarounds.dontUseLoopsToInitializeVariables = true;
|
||||
if (workarounds().remove_dynamic_indexing_of_swizzled_vector)
|
||||
driver_bug_workarounds.removeDynamicIndexingOfSwizzledVector = true;
|
||||
+ if (workarounds().validate_max_per_stage_uniform_blocks_at_compile_time) {
|
||||
+ driver_bug_workarounds.validatePerStageMaxUniformBlocks = true;
|
||||
+ }
|
||||
|
||||
// Initialize uninitialized locals by default
|
||||
driver_bug_workarounds.initializeUninitializedLocals = true;
|
||||
diff --git a/gpu/config/gpu_driver_bug_list.json b/gpu/config/gpu_driver_bug_list.json
|
||||
index deeb8fb1ea810a87bb19bcb85cc352fe802361ac..900b5fa1decf4c1895f32eb5ab05fd54a806669c 100644
|
||||
--- a/gpu/config/gpu_driver_bug_list.json
|
||||
+++ b/gpu/config/gpu_driver_bug_list.json
|
||||
@@ -3772,6 +3772,17 @@
|
||||
"features": [
|
||||
"disable_d3d12_av1_multi_ref_encoding"
|
||||
]
|
||||
+ },
|
||||
+ {
|
||||
+ "id": 472,
|
||||
+ "description": "Validate GL_MAX_*_UNIFORM_BLOCKS at compile time instead of link time to work around compiler bugs.",
|
||||
+ "os": {
|
||||
+ "type": "android"
|
||||
+ },
|
||||
+ "gl_vendor": "Imagination.*",
|
||||
+ "features": [
|
||||
+ "validate_max_per_stage_uniform_blocks_at_compile_time"
|
||||
+ ]
|
||||
}
|
||||
]
|
||||
}
|
||||
diff --git a/gpu/config/gpu_workaround_list.txt b/gpu/config/gpu_workaround_list.txt
|
||||
index 32b7797c2f19b3e597963d1d2c78da6066ff3bd3..300586499f496d25c571adcb90cb066b4e778899 100644
|
||||
--- a/gpu/config/gpu_workaround_list.txt
|
||||
+++ b/gpu/config/gpu_workaround_list.txt
|
||||
@@ -127,6 +127,7 @@ use_first_valid_ref_for_av1_invalid_ref
|
||||
use_gpu_driver_workaround_for_testing
|
||||
use_non_zero_size_for_client_side_stream_buffers
|
||||
use_virtualized_gl_contexts
|
||||
+validate_max_per_stage_uniform_blocks_at_compile_time
|
||||
wake_up_gpu_before_drawing
|
||||
webgl_or_caps_max_texture_size_limit_4096
|
||||
webgl_or_caps_max_texture_size_limit_8192
|
||||
@@ -13,5 +13,6 @@
|
||||
{ "patch_dir": "src/electron/patches/webrtc", "repo": "src/third_party/webrtc" },
|
||||
{ "patch_dir": "src/electron/patches/reclient-configs", "repo": "src/third_party/engflow-reclient-configs" },
|
||||
{ "patch_dir": "src/electron/patches/sqlite", "repo": "src/third_party/sqlite/src" },
|
||||
{ "patch_dir": "src/electron/patches/skia", "repo": "src/third_party/skia" }
|
||||
{ "patch_dir": "src/electron/patches/skia", "repo": "src/third_party/skia" },
|
||||
{ "patch_dir": "src/electron/patches/angle", "repo": "src/third_party/angle/src" }
|
||||
]
|
||||
|
||||
@@ -43,7 +43,6 @@ cli_move_--trace-atomics-wait_to_eol.patch
|
||||
fix_cppgc_initializing_twice.patch
|
||||
fix_task_starvation_in_inspector_context_test.patch
|
||||
fix_expose_readfilesync_override_for_modules.patch
|
||||
fix_array_out-of-bounds_read_in_boyer-moore_search.patch
|
||||
chore_add_missing_include_of_iterator.patch
|
||||
test_accomodate_v8_thenable_stack_trace_change_in_snapshot.patch
|
||||
chore_exclude_electron_node_folder_from_exit-time-destructors.patch
|
||||
@@ -53,7 +52,6 @@ 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
|
||||
fix_generate_config_gypi_needs_to_generate_valid_json.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 ceac508418f489a8077c1bc85a2feaf85bf60480..33827edce63c9fe08b52aea59571391a83853443 100644
|
||||
index d2614bba9463056e931b6d5c1f3153e2f576b779..f3a992b634e9532cba34ec4d54b3a1d0f68a8545 100644
|
||||
--- a/src/api/environment.cc
|
||||
+++ b/src/api/environment.cc
|
||||
@@ -646,7 +646,7 @@ std::unique_ptr<MultiIsolatePlatform> MultiIsolatePlatform::Create(
|
||||
@@ -651,7 +651,7 @@ std::unique_ptr<MultiIsolatePlatform> MultiIsolatePlatform::Create(
|
||||
|
||||
MaybeLocal<Object> GetPerContextExports(Local<Context> context,
|
||||
IsolateData* isolate_data) {
|
||||
@@ -18,7 +18,7 @@ index ceac508418f489a8077c1bc85a2feaf85bf60480..33827edce63c9fe08b52aea59571391a
|
||||
EscapableHandleScope handle_scope(isolate);
|
||||
|
||||
Local<Object> global = context->Global();
|
||||
@@ -692,7 +692,7 @@ void ProtoThrower(const FunctionCallbackInfo<Value>& info) {
|
||||
@@ -697,7 +697,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 ceac508418f489a8077c1bc85a2feaf85bf60480..33827edce63c9fe08b52aea59571391a
|
||||
HandleScope handle_scope(isolate);
|
||||
|
||||
// When `IsCodeGenerationFromStringsAllowed` is true, V8 takes the fast path
|
||||
@@ -771,7 +771,7 @@ Maybe<void> InitializeContextRuntime(Local<Context> context) {
|
||||
@@ -776,7 +776,7 @@ Maybe<void> InitializeContextRuntime(Local<Context> context) {
|
||||
}
|
||||
|
||||
Maybe<void> InitializeBaseContextForSnapshot(Local<Context> context) {
|
||||
@@ -36,7 +36,7 @@ index ceac508418f489a8077c1bc85a2feaf85bf60480..33827edce63c9fe08b52aea59571391a
|
||||
HandleScope handle_scope(isolate);
|
||||
|
||||
// Delete `Intl.v8BreakIterator`
|
||||
@@ -796,7 +796,7 @@ Maybe<void> InitializeBaseContextForSnapshot(Local<Context> context) {
|
||||
@@ -801,7 +801,7 @@ Maybe<void> InitializeBaseContextForSnapshot(Local<Context> context) {
|
||||
}
|
||||
|
||||
Maybe<void> InitializeMainContextForSnapshot(Local<Context> context) {
|
||||
@@ -45,7 +45,7 @@ index ceac508418f489a8077c1bc85a2feaf85bf60480..33827edce63c9fe08b52aea59571391a
|
||||
HandleScope handle_scope(isolate);
|
||||
|
||||
// Initialize the default values.
|
||||
@@ -814,7 +814,7 @@ Maybe<void> InitializeMainContextForSnapshot(Local<Context> context) {
|
||||
@@ -819,7 +819,7 @@ Maybe<void> InitializeMainContextForSnapshot(Local<Context> context) {
|
||||
MaybeLocal<Object> InitializePrivateSymbols(Local<Context> context,
|
||||
IsolateData* isolate_data) {
|
||||
CHECK(isolate_data);
|
||||
@@ -54,7 +54,7 @@ index ceac508418f489a8077c1bc85a2feaf85bf60480..33827edce63c9fe08b52aea59571391a
|
||||
EscapableHandleScope scope(isolate);
|
||||
Context::Scope context_scope(context);
|
||||
|
||||
@@ -838,7 +838,7 @@ MaybeLocal<Object> InitializePrivateSymbols(Local<Context> context,
|
||||
@@ -843,7 +843,7 @@ MaybeLocal<Object> InitializePrivateSymbols(Local<Context> context,
|
||||
MaybeLocal<Object> InitializePerIsolateSymbols(Local<Context> context,
|
||||
IsolateData* isolate_data) {
|
||||
CHECK(isolate_data);
|
||||
@@ -63,7 +63,7 @@ index ceac508418f489a8077c1bc85a2feaf85bf60480..33827edce63c9fe08b52aea59571391a
|
||||
EscapableHandleScope scope(isolate);
|
||||
Context::Scope context_scope(context);
|
||||
|
||||
@@ -864,7 +864,7 @@ MaybeLocal<Object> InitializePerIsolateSymbols(Local<Context> context,
|
||||
@@ -869,7 +869,7 @@ MaybeLocal<Object> InitializePerIsolateSymbols(Local<Context> context,
|
||||
Maybe<void> InitializePrimordials(Local<Context> context,
|
||||
IsolateData* isolate_data) {
|
||||
// Run per-context JS files.
|
||||
@@ -85,10 +85,10 @@ index 6f731b17fe0b84dd3d2c9bc9cfef1f8062a2c5f7..71a1072ed2decbee08d40eda7c47456b
|
||||
|
||||
return handle;
|
||||
diff --git a/src/crypto/crypto_context.cc b/src/crypto/crypto_context.cc
|
||||
index 8f50d0cc132ac65fa74cf1fc2172247b5ad42962..0c6b12f8e17b4a7e86ebc836a4e1cc77333f211a 100644
|
||||
index 2cd7cd67c1c480eb9ec549a12bc2b9584d5a53b3..081a4ccdee718afc63b55da90a60ef9758dcc96a 100644
|
||||
--- a/src/crypto/crypto_context.cc
|
||||
+++ b/src/crypto/crypto_context.cc
|
||||
@@ -1020,7 +1020,7 @@ bool ArrayOfStringsToX509s(Local<Context> context,
|
||||
@@ -1043,7 +1043,7 @@ bool ArrayOfStringsToX509s(Local<Context> context,
|
||||
Local<Array> cert_array,
|
||||
std::vector<X509*>* certs) {
|
||||
ClearErrorOnReturn clear_error_on_return;
|
||||
@@ -144,7 +144,7 @@ index eb6dad44a49d997097c8fb5009eeb60a7305da27..fd29d17de195017970856ce30d7a9c57
|
||||
NewStringType::kNormal,
|
||||
mem->length)
|
||||
diff --git a/src/encoding_binding.cc b/src/encoding_binding.cc
|
||||
index 31ed995714bb99ab534f26ba9ebc6051c258a1c9..5ace688bb7ffc86eedf5aff11ab0ab487ad9440e 100644
|
||||
index cddc88f1e0309072d22aa76d4a17115e4d9159e2..22eecffa437a9e0f4a0e170953aa35fa527511b5 100644
|
||||
--- a/src/encoding_binding.cc
|
||||
+++ b/src/encoding_binding.cc
|
||||
@@ -73,7 +73,7 @@ void BindingData::Deserialize(Local<Context> context,
|
||||
@@ -183,10 +183,10 @@ index c6209cc7cf317de1bb9217e39dd760e5a83303e2..161d577e0ea6a251c83ba1903b1ec9a5
|
||||
} else {
|
||||
info.js_execution_async_resources = 0;
|
||||
diff --git a/src/inspector/network_agent.cc b/src/inspector/network_agent.cc
|
||||
index 3b5d9615021101ad03d9dfef83e0c56b462b59ad..823e7b8d3d07eb2afa1cc62d3d9e2af20f4e2e89 100644
|
||||
index 57ea5afd56a4e3c4c5826a263ce498448effbb84..c2c17760022ab669188a774e91ca96c9a5d7f57e 100644
|
||||
--- a/src/inspector/network_agent.cc
|
||||
+++ b/src/inspector/network_agent.cc
|
||||
@@ -29,31 +29,31 @@ using v8::Value;
|
||||
@@ -31,31 +31,31 @@ constexpr size_t kDefaultMaxTotalBufferSize = 100 * 1024 * 1024; // 100MB
|
||||
Maybe<protocol::String> ObjectGetProtocolString(v8::Local<v8::Context> context,
|
||||
Local<Object> object,
|
||||
Local<v8::String> property) {
|
||||
@@ -224,7 +224,7 @@ index 3b5d9615021101ad03d9dfef83e0c56b462b59ad..823e7b8d3d07eb2afa1cc62d3d9e2af2
|
||||
.ToLocal(&value) ||
|
||||
!value->IsNumber()) {
|
||||
return Nothing<double>();
|
||||
@@ -65,9 +65,9 @@ Maybe<double> ObjectGetDouble(v8::Local<v8::Context> context,
|
||||
@@ -67,9 +67,9 @@ Maybe<double> ObjectGetDouble(v8::Local<v8::Context> context,
|
||||
Maybe<int> ObjectGetInt(v8::Local<v8::Context> context,
|
||||
Local<Object> object,
|
||||
const char* property) {
|
||||
@@ -236,7 +236,7 @@ index 3b5d9615021101ad03d9dfef83e0c56b462b59ad..823e7b8d3d07eb2afa1cc62d3d9e2af2
|
||||
.ToLocal(&value) ||
|
||||
!value->IsInt32()) {
|
||||
return Nothing<int>();
|
||||
@@ -79,9 +79,9 @@ Maybe<int> ObjectGetInt(v8::Local<v8::Context> context,
|
||||
@@ -81,9 +81,9 @@ Maybe<int> ObjectGetInt(v8::Local<v8::Context> context,
|
||||
Maybe<bool> ObjectGetBool(v8::Local<v8::Context> context,
|
||||
Local<Object> object,
|
||||
const char* property) {
|
||||
@@ -248,7 +248,7 @@ index 3b5d9615021101ad03d9dfef83e0c56b462b59ad..823e7b8d3d07eb2afa1cc62d3d9e2af2
|
||||
.ToLocal(&value) ||
|
||||
!value->IsBoolean()) {
|
||||
return Nothing<bool>();
|
||||
@@ -93,9 +93,9 @@ Maybe<bool> ObjectGetBool(v8::Local<v8::Context> context,
|
||||
@@ -95,9 +95,9 @@ Maybe<bool> ObjectGetBool(v8::Local<v8::Context> context,
|
||||
MaybeLocal<v8::Object> ObjectGetObject(v8::Local<v8::Context> context,
|
||||
Local<Object> object,
|
||||
const char* property) {
|
||||
@@ -260,7 +260,7 @@ index 3b5d9615021101ad03d9dfef83e0c56b462b59ad..823e7b8d3d07eb2afa1cc62d3d9e2af2
|
||||
.ToLocal(&value) ||
|
||||
!value->IsObject()) {
|
||||
return {};
|
||||
@@ -106,7 +106,7 @@ MaybeLocal<v8::Object> ObjectGetObject(v8::Local<v8::Context> context,
|
||||
@@ -108,7 +108,7 @@ MaybeLocal<v8::Object> ObjectGetObject(v8::Local<v8::Context> context,
|
||||
// Create a protocol::Network::Headers from the v8 object.
|
||||
std::unique_ptr<protocol::Network::Headers> createHeadersFromObject(
|
||||
v8::Local<v8::Context> context, Local<Object> headers_obj) {
|
||||
@@ -269,7 +269,7 @@ index 3b5d9615021101ad03d9dfef83e0c56b462b59ad..823e7b8d3d07eb2afa1cc62d3d9e2af2
|
||||
|
||||
std::unique_ptr<protocol::DictionaryValue> dict =
|
||||
protocol::DictionaryValue::create();
|
||||
@@ -127,7 +127,7 @@ std::unique_ptr<protocol::Network::Headers> createHeadersFromObject(
|
||||
@@ -129,7 +129,7 @@ std::unique_ptr<protocol::Network::Headers> createHeadersFromObject(
|
||||
.To(&property_value)) {
|
||||
return {};
|
||||
}
|
||||
@@ -278,7 +278,7 @@ index 3b5d9615021101ad03d9dfef83e0c56b462b59ad..823e7b8d3d07eb2afa1cc62d3d9e2af2
|
||||
property_value);
|
||||
}
|
||||
|
||||
@@ -137,7 +137,7 @@ std::unique_ptr<protocol::Network::Headers> createHeadersFromObject(
|
||||
@@ -139,7 +139,7 @@ std::unique_ptr<protocol::Network::Headers> createHeadersFromObject(
|
||||
// Create a protocol::Network::Request from the v8 object.
|
||||
std::unique_ptr<protocol::Network::Request> createRequestFromObject(
|
||||
v8::Local<v8::Context> context, Local<Object> request) {
|
||||
@@ -287,7 +287,7 @@ index 3b5d9615021101ad03d9dfef83e0c56b462b59ad..823e7b8d3d07eb2afa1cc62d3d9e2af2
|
||||
protocol::String url;
|
||||
if (!ObjectGetProtocolString(context, request, "url").To(&url)) {
|
||||
return {};
|
||||
@@ -169,7 +169,7 @@ std::unique_ptr<protocol::Network::Request> createRequestFromObject(
|
||||
@@ -171,7 +171,7 @@ std::unique_ptr<protocol::Network::Request> createRequestFromObject(
|
||||
// Create a protocol::Network::Response from the v8 object.
|
||||
std::unique_ptr<protocol::Network::Response> createResponseFromObject(
|
||||
v8::Local<v8::Context> context, Local<Object> response) {
|
||||
@@ -359,10 +359,10 @@ index 4a35e41e78a22993f87ab9d5919f401a7b742438..327d7b77bc306db8193fa68bc7129c33
|
||||
CHECK(!env->temporary_required_module_facade_original.IsEmpty());
|
||||
return env->temporary_required_module_facade_original.Get(isolate);
|
||||
diff --git a/src/node.h b/src/node.h
|
||||
index 16a0c71aef949b0ddd27def9dc843298f9a6b75f..28fa4cb3e7a621480a5ff11c48666c0de1363375 100644
|
||||
index fe44369dff7519ea0d960ae478d5caf524e17366..bba7393e7378fa7468837319af7b7f643b68167e 100644
|
||||
--- a/src/node.h
|
||||
+++ b/src/node.h
|
||||
@@ -1050,7 +1050,7 @@ NODE_DEPRECATED("Use v8::Date::ValueOf() directly",
|
||||
@@ -1049,7 +1049,7 @@ NODE_DEPRECATED("Use v8::Date::ValueOf() directly",
|
||||
|
||||
#define NODE_DEFINE_CONSTANT(target, constant) \
|
||||
do { \
|
||||
@@ -371,7 +371,7 @@ index 16a0c71aef949b0ddd27def9dc843298f9a6b75f..28fa4cb3e7a621480a5ff11c48666c0d
|
||||
v8::Local<v8::Context> context = isolate->GetCurrentContext(); \
|
||||
v8::Local<v8::String> constant_name = v8::String::NewFromUtf8Literal( \
|
||||
isolate, #constant, v8::NewStringType::kInternalized); \
|
||||
@@ -1066,7 +1066,7 @@ NODE_DEPRECATED("Use v8::Date::ValueOf() directly",
|
||||
@@ -1065,7 +1065,7 @@ NODE_DEPRECATED("Use v8::Date::ValueOf() directly",
|
||||
|
||||
#define NODE_DEFINE_HIDDEN_CONSTANT(target, constant) \
|
||||
do { \
|
||||
@@ -539,10 +539,10 @@ index 36a21b9523351fe2f225ffe7fca184d737640b62..c6e9e2c00064348c435ae10871a4013c
|
||||
READONLY_PROPERTY(target, "exitCodes", exit_codes);
|
||||
|
||||
diff --git a/src/node_file.cc b/src/node_file.cc
|
||||
index 5de3ebb04b12286a07e3041d0a6dd1cc9072e76a..75be21c9e8b413f522240a906da06d26c44d5b71 100644
|
||||
index 9f888b28ecb05f3496c0b18fdd6a2c1cc9b068fd..57c8dc35dc86efed6e8736e4649b90905a8da54b 100644
|
||||
--- a/src/node_file.cc
|
||||
+++ b/src/node_file.cc
|
||||
@@ -3755,7 +3755,7 @@ void BindingData::Deserialize(Local<Context> context,
|
||||
@@ -3761,7 +3761,7 @@ void BindingData::Deserialize(Local<Context> context,
|
||||
int index,
|
||||
InternalFieldInfoBase* info) {
|
||||
DCHECK_IS_SNAPSHOT_SLOT(index);
|
||||
@@ -627,7 +627,7 @@ index 9dcca7509f37f239b8442201b086df428415dcd1..b0cf8c3a8e1c3e89d621a865390b1bdb
|
||||
// Recreate the buffer in the constructor.
|
||||
InternalFieldInfo* casted_info = static_cast<InternalFieldInfo*>(info);
|
||||
diff --git a/src/node_realm.cc b/src/node_realm.cc
|
||||
index 66a8ee48fc68b22eaf6c9d9209cc5cb2439e55ff..b31e244f8af7d37c35319853a478776c609b9bca 100644
|
||||
index b6461c7bb009fa3f44cb0225eec49dbb161d81fd..5ffe23beb7b33f8becf5ba997fea2119e9aa23cf 100644
|
||||
--- a/src/node_realm.cc
|
||||
+++ b/src/node_realm.cc
|
||||
@@ -19,7 +19,7 @@ using v8::String;
|
||||
@@ -740,7 +740,7 @@ index 9b5ada71c174567498c4902259d97f9d11fefb91..1134856a202bac0a4ff1957d5ecc5600
|
||||
if (wasi->memory_.IsEmpty()) {
|
||||
THROW_ERR_WASI_NOT_STARTED(isolate);
|
||||
diff --git a/src/node_webstorage.cc b/src/node_webstorage.cc
|
||||
index e3c3223789032badbab56a558148da67e99ca9b2..9a7b7db881a564a68683c55cb10919454e80edbf 100644
|
||||
index a442a479b8732ef793aaf3bf57decc4f324eb816..d6dee522023a4e65d948b1554e9ae472f1e96e40 100644
|
||||
--- a/src/node_webstorage.cc
|
||||
+++ b/src/node_webstorage.cc
|
||||
@@ -58,7 +58,7 @@ using v8::Value;
|
||||
@@ -752,7 +752,7 @@ index e3c3223789032badbab56a558148da67e99ca9b2..9a7b7db881a564a68683c55cb1091945
|
||||
auto dom_exception_str = FIXED_ONE_BYTE_STRING(isolate, "DOMException");
|
||||
auto err_name = FIXED_ONE_BYTE_STRING(isolate, "QuotaExceededError");
|
||||
auto err_message =
|
||||
@@ -434,7 +434,7 @@ Maybe<void> Storage::Store(Local<Name> key, Local<Value> value) {
|
||||
@@ -438,7 +438,7 @@ Maybe<void> Storage::Store(Local<Name> key, Local<Value> value) {
|
||||
}
|
||||
|
||||
static MaybeLocal<String> Uint32ToName(Local<Context> context, uint32_t index) {
|
||||
@@ -762,10 +762,10 @@ index e3c3223789032badbab56a558148da67e99ca9b2..9a7b7db881a564a68683c55cb1091945
|
||||
|
||||
static void Clear(const FunctionCallbackInfo<Value>& info) {
|
||||
diff --git a/src/node_worker.cc b/src/node_worker.cc
|
||||
index 8555ab556b5b74a1cf9cf30747f1f417bfe4e4d9..1a2532337504444d59098304b87e0d65f16e838c 100644
|
||||
index ddfea91272d03d4ef1d4ac1b982ada5dcd24b601..7b4335475cc70369a1e868de70c749465a5bdfbd 100644
|
||||
--- a/src/node_worker.cc
|
||||
+++ b/src/node_worker.cc
|
||||
@@ -1289,8 +1289,6 @@ void GetEnvMessagePort(const FunctionCallbackInfo<Value>& args) {
|
||||
@@ -1288,8 +1288,6 @@ void GetEnvMessagePort(const FunctionCallbackInfo<Value>& args) {
|
||||
Local<Object> port = env->message_port();
|
||||
CHECK_IMPLIES(!env->is_main_thread(), !port.IsEmpty());
|
||||
if (!port.IsEmpty()) {
|
||||
|
||||
@@ -11,7 +11,7 @@ really in 20/21. We have to wait until 22 is released to be able to
|
||||
build with upstream GN files.
|
||||
|
||||
diff --git a/configure.py b/configure.py
|
||||
index 91283ca577f580dbf1e0c4e2dbf851a9ceaa38ed..e8eaff30ec947677db2d45425f9180759d0c55de 100755
|
||||
index 77c87f5a9539714f68278d95ec79878cc52dc18b..ff93eebd4714ac8d9c9abe9c53e3636f02e0baac 100755
|
||||
--- a/configure.py
|
||||
+++ b/configure.py
|
||||
@@ -1728,7 +1728,7 @@ def configure_v8(o, configs):
|
||||
@@ -93,7 +93,7 @@ index f9426599f2d5dc6ad061407f0c4eb2c9203a4433..302030f610965f07dd6998d282275c1b
|
||||
// Handles compilation and caching of built-in JavaScript modules and
|
||||
// bootstrap scripts, whose source are bundled into the binary as static data.
|
||||
diff --git a/tools/install.py b/tools/install.py
|
||||
index 8797b59e59c85a8877b977fa3281e50165e6f6b2..0af01e075616195f38fb242626dcab770ec1eb57 100755
|
||||
index a619fd17b16e404cf8deb5b91f7dbd980895f760..2b981b23e724120f69a5f7ef655e5f648aa310e9 100755
|
||||
--- a/tools/install.py
|
||||
+++ b/tools/install.py
|
||||
@@ -222,6 +222,7 @@ def headers(options, action):
|
||||
@@ -115,7 +115,7 @@ index 8797b59e59c85a8877b977fa3281e50165e6f6b2..0af01e075616195f38fb242626dcab77
|
||||
diff --git a/tools/js2c.cc b/tools/js2c.cc
|
||||
old mode 100644
|
||||
new mode 100755
|
||||
index 21992cbe894a880e3223c379326b62db22f2f12d..1296a5457422099035ba34f2b02624f2e9dfb0f0
|
||||
index 9c2f70de4e00834ff448e573743898072dc14c5d..71a12c606f4da7165cc41a295a278b2e504af1b6
|
||||
--- a/tools/js2c.cc
|
||||
+++ b/tools/js2c.cc
|
||||
@@ -28,6 +28,7 @@ namespace js2c {
|
||||
@@ -210,7 +210,7 @@ index 21992cbe894a880e3223c379326b62db22f2f12d..1296a5457422099035ba34f2b02624f2
|
||||
static_cast<int>(def_buf.size()),
|
||||
def_buf.data(),
|
||||
static_cast<int>(init_buf.size()),
|
||||
@@ -846,12 +890,15 @@ int JS2C(const FileList& js_files,
|
||||
@@ -836,12 +880,15 @@ int JS2C(const FileList& js_files,
|
||||
}
|
||||
}
|
||||
|
||||
@@ -226,7 +226,7 @@ index 21992cbe894a880e3223c379326b62db22f2f12d..1296a5457422099035ba34f2b02624f2
|
||||
Fragment out = Format(definitions, initializers, registrations);
|
||||
return WriteIfChanged(out, dest);
|
||||
}
|
||||
@@ -877,6 +924,8 @@ int Main(int argc, char* argv[]) {
|
||||
@@ -867,6 +914,8 @@ int Main(int argc, char* argv[]) {
|
||||
std::string arg(argv[i]);
|
||||
if (arg == "--verbose") {
|
||||
is_verbose = true;
|
||||
@@ -235,7 +235,7 @@ index 21992cbe894a880e3223c379326b62db22f2f12d..1296a5457422099035ba34f2b02624f2
|
||||
} else if (arg == "--root") {
|
||||
if (i == argc - 1) {
|
||||
fprintf(stderr, "--root must be followed by a path\n");
|
||||
@@ -925,6 +974,14 @@ int Main(int argc, char* argv[]) {
|
||||
@@ -915,6 +964,14 @@ int Main(int argc, char* argv[]) {
|
||||
}
|
||||
}
|
||||
|
||||
@@ -250,7 +250,7 @@ index 21992cbe894a880e3223c379326b62db22f2f12d..1296a5457422099035ba34f2b02624f2
|
||||
// Should have exactly 3 types: `.js`, `.mjs` and `.gypi`.
|
||||
assert(file_map.size() == 3);
|
||||
auto gypi_it = file_map.find(".gypi");
|
||||
@@ -951,6 +1008,7 @@ int Main(int argc, char* argv[]) {
|
||||
@@ -941,6 +998,7 @@ int Main(int argc, char* argv[]) {
|
||||
std::sort(mjs_it->second.begin(), mjs_it->second.end());
|
||||
|
||||
return JS2C(js_it->second, mjs_it->second, gypi_it->second[0], output);
|
||||
|
||||
@@ -10,10 +10,10 @@ V8 requires C++20 support as of https://chromium-review.googlesource.com/c/v8/v8
|
||||
This can be removed when Electron upgrades to a version of Node.js containing the required V8 version.
|
||||
|
||||
diff --git a/common.gypi b/common.gypi
|
||||
index c28d6f5fe2c922f0b1e3f7e56289c78e7b91c294..95c56305926fc3e0e46e4cf99ec86d3d1b5576a7 100644
|
||||
index 4cb925480961ae88eb423559ab34ac0ee91239e4..bbfc0f4ec293df19662e57fa4890c4c53cd79d75 100644
|
||||
--- a/common.gypi
|
||||
+++ b/common.gypi
|
||||
@@ -539,7 +539,7 @@
|
||||
@@ -536,7 +536,7 @@
|
||||
'-fno-rtti',
|
||||
'-fno-exceptions',
|
||||
'-fno-strict-aliasing',
|
||||
@@ -22,7 +22,7 @@ index c28d6f5fe2c922f0b1e3f7e56289c78e7b91c294..95c56305926fc3e0e46e4cf99ec86d3d
|
||||
],
|
||||
'defines': [ '__STDC_FORMAT_MACROS' ],
|
||||
'ldflags': [ '-rdynamic' ],
|
||||
@@ -719,7 +719,7 @@
|
||||
@@ -716,7 +716,7 @@
|
||||
['clang==1', {
|
||||
'xcode_settings': {
|
||||
'GCC_VERSION': 'com.apple.compilers.llvm.clang.1_0',
|
||||
|
||||
@@ -33,7 +33,7 @@ index 8d7204f6cb48f783adc4d1c1eb2de0c83b7fffe2..a154559a56bf383d3c26af523c9bb07b
|
||||
|
||||
// Non-alphabetic chars.
|
||||
diff --git a/lib/internal/http.js b/lib/internal/http.js
|
||||
index 4f250a2e70a20fddeeb7886e0c269822883f7ccf..4e5c2dd1f13e6818576c3c4c88200b5cf5fb1257 100644
|
||||
index 78010bd8f23512073430008742479b655e936314..12b6430cadc31dbfa6907ed0b904ce81bd333a05 100644
|
||||
--- a/lib/internal/http.js
|
||||
+++ b/lib/internal/http.js
|
||||
@@ -10,8 +10,8 @@ const {
|
||||
@@ -64,7 +64,7 @@ index 4f250a2e70a20fddeeb7886e0c269822883f7ccf..4e5c2dd1f13e6818576c3c4c88200b5c
|
||||
|
||||
function ipToInt(ip) {
|
||||
diff --git a/node.gyp b/node.gyp
|
||||
index 0e0071b508f605bb9b7722f8304814dc176d907e..bcb9f371c4e4d8c665058115dc39eaa65125d679 100644
|
||||
index f9ee71dd9a395fa1de99a6f62ba60acdf8be12a1..e3b308ca079aab6e672a1cfa9b12d49ef64b3816 100644
|
||||
--- a/node.gyp
|
||||
+++ b/node.gyp
|
||||
@@ -174,7 +174,6 @@
|
||||
|
||||
@@ -7,7 +7,7 @@ Subject: build: ensure native module compilation fails if not using a new
|
||||
This should not be upstreamed, it is a quality-of-life patch for downstream module builders.
|
||||
|
||||
diff --git a/common.gypi b/common.gypi
|
||||
index 6b79de07be3f839af5b0644f19bfef9c33de590e..c28d6f5fe2c922f0b1e3f7e56289c78e7b91c294 100644
|
||||
index 79bd0879cd5d9408d45aae150d9ace4e1bf43d36..4cb925480961ae88eb423559ab34ac0ee91239e4 100644
|
||||
--- a/common.gypi
|
||||
+++ b/common.gypi
|
||||
@@ -89,6 +89,8 @@
|
||||
@@ -42,7 +42,7 @@ index 6b79de07be3f839af5b0644f19bfef9c33de590e..c28d6f5fe2c922f0b1e3f7e56289c78e
|
||||
# list in v8/BUILD.gn.
|
||||
['v8_enable_v8_checks == 1', {
|
||||
diff --git a/configure.py b/configure.py
|
||||
index e8eaff30ec947677db2d45425f9180759d0c55de..dc2d9d80059e845b33444f8bdc29e82d0fe0e26b 100755
|
||||
index ff93eebd4714ac8d9c9abe9c53e3636f02e0baac..04d484071821af1afc07d5a0081c6ad7f2e59ab5 100755
|
||||
--- a/configure.py
|
||||
+++ b/configure.py
|
||||
@@ -1710,6 +1710,7 @@ def configure_library(lib, output, pkgname=None):
|
||||
@@ -54,7 +54,7 @@ index e8eaff30ec947677db2d45425f9180759d0c55de..dc2d9d80059e845b33444f8bdc29e82d
|
||||
o['variables']['v8_enable_javascript_promise_hooks'] = 1
|
||||
o['variables']['v8_enable_lite_mode'] = 1 if options.v8_lite_mode else 0
|
||||
diff --git a/src/node.h b/src/node.h
|
||||
index a336f44dc1e785ea237865077216d41ab032c0af..96c599aa6448e2aa8e57e84f811564a5281c139a 100644
|
||||
index 67bef5f7d8a08c4dd37ad72073537f1d2b4cb2ee..4e66924e4ca5b5d787fc6259de940a3fb40bff38 100644
|
||||
--- a/src/node.h
|
||||
+++ b/src/node.h
|
||||
@@ -22,6 +22,12 @@
|
||||
|
||||
@@ -11,7 +11,7 @@ node-gyp will use the result of `process.config` that reflects the environment
|
||||
in which the binary got built.
|
||||
|
||||
diff --git a/common.gypi b/common.gypi
|
||||
index 95c56305926fc3e0e46e4cf99ec86d3d1b5576a7..45bb2c4ff94ceac377c9117da4497cdc5ac41171 100644
|
||||
index bbfc0f4ec293df19662e57fa4890c4c53cd79d75..23ac608d9fc3cd4b8b8381492d609051127cd755 100644
|
||||
--- a/common.gypi
|
||||
+++ b/common.gypi
|
||||
@@ -128,6 +128,7 @@
|
||||
|
||||
@@ -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 15443a710ccf53fae333da3b1fbb52a970c658d5..464b34829c1a566836bfca6bbc2b87fcf5e50016 100644
|
||||
index 3546544ad0d4542917d0dfe7634bd6ec1e25476b..3eabcb05f1d370693ade51ac794852725767ad85 100644
|
||||
--- a/lib/internal/process/pre_execution.js
|
||||
+++ b/lib/internal/process/pre_execution.js
|
||||
@@ -265,12 +265,14 @@ function patchProcessObject(expandArgv1) {
|
||||
@@ -268,12 +268,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,13 +8,16 @@ Without this patch, building with simdjson fails with
|
||||
> error: identifier '_padded' preceded by whitespace in a literal operator
|
||||
> declaration is deprecated [-Werror,-Wdeprecated-literal-operator]
|
||||
|
||||
and
|
||||
> error: declaration requires an exit-time destructor [-Werror,-Wexit-time-destructors]
|
||||
|
||||
This patch can be removed once this is fixed upstream in simdjson.
|
||||
|
||||
diff --git a/deps/simdjson/simdjson.h b/deps/simdjson/simdjson.h
|
||||
index 8f52a4331d59996786450eec982659da9244cac1..74729673d87b068dff5f24166bbb77d844f15f42 100644
|
||||
index 1d6560e80fab0458b22f0ac2437056bce4873e8f..c3dbe2b6fc08c36a07ced5e29a814f7bcd85b748 100644
|
||||
--- a/deps/simdjson/simdjson.h
|
||||
+++ b/deps/simdjson/simdjson.h
|
||||
@@ -3899,12 +3899,17 @@ inline std::ostream& operator<<(std::ostream& out, simdjson_result<padded_string
|
||||
@@ -4215,12 +4215,17 @@ inline std::ostream& operator<<(std::ostream& out, simdjson_result<padded_string
|
||||
|
||||
} // namespace simdjson
|
||||
|
||||
@@ -32,7 +35,7 @@ index 8f52a4331d59996786450eec982659da9244cac1..74729673d87b068dff5f24166bbb77d8
|
||||
namespace simdjson {
|
||||
namespace internal {
|
||||
|
||||
@@ -4304,6 +4309,9 @@ inline simdjson_result<padded_string> padded_string::load(std::string_view filen
|
||||
@@ -4729,6 +4734,9 @@ inline simdjson_result<padded_string> padded_string::load(std::wstring_view file
|
||||
|
||||
} // namespace simdjson
|
||||
|
||||
@@ -42,8 +45,8 @@ index 8f52a4331d59996786450eec982659da9244cac1..74729673d87b068dff5f24166bbb77d8
|
||||
inline simdjson::padded_string operator ""_padded(const char *str, size_t len) {
|
||||
return simdjson::padded_string(str, len);
|
||||
}
|
||||
@@ -4312,6 +4320,8 @@ inline simdjson::padded_string operator ""_padded(const char8_t *str, size_t len
|
||||
return simdjson::padded_string(reinterpret_cast<const char8_t *>(str), len);
|
||||
@@ -4737,6 +4745,8 @@ inline simdjson::padded_string operator ""_padded(const char8_t *str, size_t len
|
||||
return simdjson::padded_string(reinterpret_cast<const char *>(str), len);
|
||||
}
|
||||
#endif
|
||||
+#pragma clang diagnostic pop
|
||||
@@ -51,3 +54,37 @@ index 8f52a4331d59996786450eec982659da9244cac1..74729673d87b068dff5f24166bbb77d8
|
||||
#endif // SIMDJSON_PADDED_STRING_INL_H
|
||||
/* end file simdjson/padded_string-inl.h */
|
||||
/* skipped duplicate #include "simdjson/padded_string_view.h" */
|
||||
@@ -44745,12 +44755,16 @@ simdjson_inline simdjson_warn_unused std::unique_ptr<ondemand::parser>& parser::
|
||||
return parser_instance;
|
||||
}
|
||||
|
||||
+#pragma clang diagnostic push
|
||||
+#pragma clang diagnostic ignored "-Wexit-time-destructors"
|
||||
+
|
||||
simdjson_inline simdjson_warn_unused std::unique_ptr<ondemand::parser>& parser::get_threadlocal_parser_if_exists() {
|
||||
// @the-moisrex points out that this could be implemented with std::optional (C++17).
|
||||
thread_local std::unique_ptr<ondemand::parser> parser_instance = nullptr;
|
||||
return parser_instance;
|
||||
}
|
||||
|
||||
+#pragma clang diagnostic pop
|
||||
|
||||
} // namespace ondemand
|
||||
} // namespace arm64
|
||||
@@ -59221,12 +59235,16 @@ simdjson_inline simdjson_warn_unused std::unique_ptr<ondemand::parser>& parser::
|
||||
return parser_instance;
|
||||
}
|
||||
|
||||
+#pragma clang diagnostic push
|
||||
+#pragma clang diagnostic ignored "-Wexit-time-destructors"
|
||||
+
|
||||
simdjson_inline simdjson_warn_unused std::unique_ptr<ondemand::parser>& parser::get_threadlocal_parser_if_exists() {
|
||||
// @the-moisrex points out that this could be implemented with std::optional (C++17).
|
||||
thread_local std::unique_ptr<ondemand::parser> parser_instance = nullptr;
|
||||
return parser_instance;
|
||||
}
|
||||
|
||||
+#pragma clang diagnostic pop
|
||||
|
||||
} // namespace ondemand
|
||||
} // namespace fallback
|
||||
|
||||
@@ -15,10 +15,10 @@ Reviewed-By: Benjamin Gruenbaum <benjamingr@gmail.com>
|
||||
Reviewed-By: Yagiz Nizipli <yagiz.nizipli@sentry.io>
|
||||
|
||||
diff --git a/doc/api/cli.md b/doc/api/cli.md
|
||||
index a97053929c81ac18bcb3beda7cecb69621b6e70c..a54d0e46c8e4e3aa6be433fba73ef9a3228fa175 100644
|
||||
index 2133555fd05f0c4f4b03c1d76ae8e33c14b621fa..1f93fa0fa56b27cb176d06231b9f2c8854c3c009 100644
|
||||
--- a/doc/api/cli.md
|
||||
+++ b/doc/api/cli.md
|
||||
@@ -2749,39 +2749,6 @@ added: v12.0.0
|
||||
@@ -2755,39 +2755,6 @@ added: v12.0.0
|
||||
Set default [`tls.DEFAULT_MIN_VERSION`][] to 'TLSv1.3'. Use to disable support
|
||||
for TLSv1.2, which is not as secure as TLSv1.3.
|
||||
|
||||
@@ -58,7 +58,7 @@ index a97053929c81ac18bcb3beda7cecb69621b6e70c..a54d0e46c8e4e3aa6be433fba73ef9a3
|
||||
### `--trace-deprecation`
|
||||
|
||||
<!-- YAML
|
||||
@@ -3483,7 +3450,6 @@ one is included in the list below.
|
||||
@@ -3489,7 +3456,6 @@ one is included in the list below.
|
||||
* `--tls-min-v1.1`
|
||||
* `--tls-min-v1.2`
|
||||
* `--tls-min-v1.3`
|
||||
@@ -83,7 +83,7 @@ index fed2c77c2afed665be7aa17c2d53824f049a909e..7a3c09a40fca9458f83be1e7d8eec930
|
||||
Print stack traces for deprecations.
|
||||
.
|
||||
diff --git a/src/node.cc b/src/node.cc
|
||||
index f012b365455bb111cddea44fcff020804086ab72..b99b5170553af51466fd1ee69af3be5026f3fada 100644
|
||||
index f85b5ed687180d7a12648b87398a734fb321f346..0bc4aff4573ccd0e53de5f288b5bccdb6063652a 100644
|
||||
--- a/src/node.cc
|
||||
+++ b/src/node.cc
|
||||
@@ -232,44 +232,6 @@ void Environment::WaitForInspectorFrontendByOptions() {
|
||||
@@ -150,7 +150,7 @@ index f012b365455bb111cddea44fcff020804086ab72..b99b5170553af51466fd1ee69af3be50
|
||||
isolate_->SetPromiseHook(TracePromises);
|
||||
}
|
||||
diff --git a/src/node_options.cc b/src/node_options.cc
|
||||
index 4bbace2f702777fa12ba9246984894721df99b50..b067685822dc056e446e1a9402a5a6cba86cc722 100644
|
||||
index acd747ff5d853a920a66c27d421ae9ddfc7bcd82..5a1675f2b4448e5da71f0badee8ac5f2d2a9c6ee 100644
|
||||
--- a/src/node_options.cc
|
||||
+++ b/src/node_options.cc
|
||||
@@ -827,10 +827,6 @@ EnvironmentOptionsParser::EnvironmentOptionsParser() {
|
||||
@@ -165,7 +165,7 @@ index 4bbace2f702777fa12ba9246984894721df99b50..b067685822dc056e446e1a9402a5a6cb
|
||||
"show stack traces on deprecations",
|
||||
&EnvironmentOptions::trace_deprecation,
|
||||
diff --git a/src/node_options.h b/src/node_options.h
|
||||
index d8751a6ee734233e2fc24866ed87d9cd516072ae..e12abb55e43068e8446eaabc65deb63cc469f554 100644
|
||||
index b7d9b429f0b498dfd70301074948a13a2d35532e..31b5e51ec8ac3061778b723f59cef606fac7c924 100644
|
||||
--- a/src/node_options.h
|
||||
+++ b/src/node_options.h
|
||||
@@ -205,7 +205,6 @@ class EnvironmentOptions : public Options {
|
||||
|
||||
@@ -18,10 +18,10 @@ Reviewed-By: Michaël Zasso <targos@protonmail.com>
|
||||
Reviewed-By: Yagiz Nizipli <yagiz@nizipli.com>
|
||||
|
||||
diff --git a/doc/api/cli.md b/doc/api/cli.md
|
||||
index 7ff68d28f1c80d8a852f649e2c39216a2f4bdb16..a97053929c81ac18bcb3beda7cecb69621b6e70c 100644
|
||||
index 0dfbe4b4fe0e4113e5e6c0cbe8a5d3ec4ff97e5a..2133555fd05f0c4f4b03c1d76ae8e33c14b621fa 100644
|
||||
--- a/doc/api/cli.md
|
||||
+++ b/doc/api/cli.md
|
||||
@@ -3522,7 +3522,6 @@ V8 options that are allowed are:
|
||||
@@ -3528,7 +3528,6 @@ V8 options that are allowed are:
|
||||
* `--disallow-code-generation-from-strings`
|
||||
* `--enable-etw-stack-walking`
|
||||
* `--expose-gc`
|
||||
@@ -30,7 +30,7 @@ index 7ff68d28f1c80d8a852f649e2c39216a2f4bdb16..a97053929c81ac18bcb3beda7cecb696
|
||||
* `--jitless`
|
||||
* `--max-old-space-size`
|
||||
diff --git a/src/node_options.cc b/src/node_options.cc
|
||||
index 3026b3d814ae652a9996c1dcba62b4fa678ac871..4bbace2f702777fa12ba9246984894721df99b50 100644
|
||||
index 41de3936265f0544831521fe753d2050e91b58e1..acd747ff5d853a920a66c27d421ae9ddfc7bcd82 100644
|
||||
--- a/src/node_options.cc
|
||||
+++ b/src/node_options.cc
|
||||
@@ -1060,11 +1060,6 @@ PerIsolateOptionsParser::PerIsolateOptionsParser(
|
||||
|
||||
@@ -9,7 +9,7 @@ modules to sandboxed renderers.
|
||||
TODO(codebytere): remove and replace with a public facing API.
|
||||
|
||||
diff --git a/src/node_binding.cc b/src/node_binding.cc
|
||||
index aa4213c3622eab077fa8d764775c1f95c6313e34..11f722d2d7c21079cbc65033429086231a786ca7 100644
|
||||
index 75d2f649a76583b7c965871131147b9f451234c4..b7fa9b8e48ffcd1e80d890b127b5ffb52152838b 100644
|
||||
--- a/src/node_binding.cc
|
||||
+++ b/src/node_binding.cc
|
||||
@@ -652,6 +652,10 @@ void GetInternalBinding(const FunctionCallbackInfo<Value>& args) {
|
||||
@@ -24,10 +24,10 @@ index aa4213c3622eab077fa8d764775c1f95c6313e34..11f722d2d7c21079cbc6503342908623
|
||||
Environment* env = Environment::GetCurrent(args);
|
||||
|
||||
diff --git a/src/node_binding.h b/src/node_binding.h
|
||||
index 611f38ef5e21cc303127326d50c648fbb557b4da..3d95ad2733dc83d0b7d37d57c337732c8a0e83d7 100644
|
||||
index bf931994d31ab6f6c400eecd36ff09cb655a67f2..7e839bafd2b2b0b07aa216d317f0ab0d89108979 100644
|
||||
--- a/src/node_binding.h
|
||||
+++ b/src/node_binding.h
|
||||
@@ -154,6 +154,8 @@ void GetInternalBinding(const v8::FunctionCallbackInfo<v8::Value>& args);
|
||||
@@ -153,6 +153,8 @@ void GetInternalBinding(const v8::FunctionCallbackInfo<v8::Value>& args);
|
||||
void GetLinkedBinding(const v8::FunctionCallbackInfo<v8::Value>& args);
|
||||
void DLOpen(const v8::FunctionCallbackInfo<v8::Value>& args);
|
||||
|
||||
|
||||
@@ -7,7 +7,7 @@ common.gypi is a file that's included in the node header bundle, despite
|
||||
the fact that we do not build node with gyp.
|
||||
|
||||
diff --git a/common.gypi b/common.gypi
|
||||
index ae31b372b96358a156761ec7e9c39c9530d1abd1..6b79de07be3f839af5b0644f19bfef9c33de590e 100644
|
||||
index d71df903c125e4b5daf1184604c627b82272d3cc..79bd0879cd5d9408d45aae150d9ace4e1bf43d36 100644
|
||||
--- a/common.gypi
|
||||
+++ b/common.gypi
|
||||
@@ -91,6 +91,23 @@
|
||||
|
||||
@@ -11,7 +11,7 @@ We can fix this by allowing the C++ implementation of legacyMainResolve to use
|
||||
a fileExists function that does take Asar into account.
|
||||
|
||||
diff --git a/lib/internal/modules/esm/resolve.js b/lib/internal/modules/esm/resolve.js
|
||||
index e3afd30ba1f591d0298793bc42fd7166a4219bce..408dc96307d7f52f92db41004b358051a81c627c 100644
|
||||
index 4216e136d01a119264de1523ed466efb783311c3..a7e9c8eb1084c9d5a0c27f0fca840fc47ce12dd1 100644
|
||||
--- a/lib/internal/modules/esm/resolve.js
|
||||
+++ b/lib/internal/modules/esm/resolve.js
|
||||
@@ -28,14 +28,13 @@ const { BuiltinModule } = require('internal/bootstrap/realm');
|
||||
@@ -31,7 +31,7 @@ index e3afd30ba1f591d0298793bc42fd7166a4219bce..408dc96307d7f52f92db41004b358051
|
||||
const {
|
||||
ERR_INPUT_TYPE_NOT_ALLOWED,
|
||||
ERR_INVALID_ARG_TYPE,
|
||||
@@ -183,6 +182,11 @@ const legacyMainResolveExtensionsIndexes = {
|
||||
@@ -184,6 +183,11 @@ const legacyMainResolveExtensionsIndexes = {
|
||||
kResolvedByPackageAndNode: 9,
|
||||
};
|
||||
|
||||
@@ -43,7 +43,7 @@ index e3afd30ba1f591d0298793bc42fd7166a4219bce..408dc96307d7f52f92db41004b358051
|
||||
/**
|
||||
* Legacy CommonJS main resolution:
|
||||
* 1. let M = pkg_url + (json main field)
|
||||
@@ -201,7 +205,7 @@ function legacyMainResolve(packageJSONUrl, packageConfig, base) {
|
||||
@@ -202,7 +206,7 @@ function legacyMainResolve(packageJSONUrl, packageConfig, base) {
|
||||
|
||||
const baseStringified = isURL(base) ? base.href : base;
|
||||
|
||||
@@ -53,10 +53,10 @@ index e3afd30ba1f591d0298793bc42fd7166a4219bce..408dc96307d7f52f92db41004b358051
|
||||
const maybeMain = resolvedOption <= legacyMainResolveExtensionsIndexes.kResolvedByMainIndexNode ?
|
||||
packageConfig.main || './' : '';
|
||||
diff --git a/src/node_file.cc b/src/node_file.cc
|
||||
index 77f8f1bd4e8294f2ebc7e0724aea5902eb0f95ab..5de3ebb04b12286a07e3041d0a6dd1cc9072e76a 100644
|
||||
index 6ed00e0c173ecc37d09e5d1420fbf5451b6fd906..9f888b28ecb05f3496c0b18fdd6a2c1cc9b068fd 100644
|
||||
--- a/src/node_file.cc
|
||||
+++ b/src/node_file.cc
|
||||
@@ -3504,13 +3504,25 @@ static void CpSyncCopyDir(const FunctionCallbackInfo<Value>& args) {
|
||||
@@ -3510,13 +3510,25 @@ static void CpSyncCopyDir(const FunctionCallbackInfo<Value>& args) {
|
||||
}
|
||||
|
||||
BindingData::FilePathIsFileReturnType BindingData::FilePathIsFile(
|
||||
@@ -83,7 +83,7 @@ index 77f8f1bd4e8294f2ebc7e0724aea5902eb0f95ab..5de3ebb04b12286a07e3041d0a6dd1cc
|
||||
uv_fs_t req;
|
||||
|
||||
int rc = uv_fs_stat(env->event_loop(), &req, file_path.c_str(), nullptr);
|
||||
@@ -3568,6 +3580,11 @@ void BindingData::LegacyMainResolve(const FunctionCallbackInfo<Value>& args) {
|
||||
@@ -3574,6 +3586,11 @@ void BindingData::LegacyMainResolve(const FunctionCallbackInfo<Value>& args) {
|
||||
std::optional<std::string> initial_file_path;
|
||||
std::string file_path;
|
||||
|
||||
@@ -95,7 +95,7 @@ index 77f8f1bd4e8294f2ebc7e0724aea5902eb0f95ab..5de3ebb04b12286a07e3041d0a6dd1cc
|
||||
if (args.Length() >= 2 && args[1]->IsString()) {
|
||||
auto package_config_main = Utf8Value(isolate, args[1]).ToString();
|
||||
|
||||
@@ -3588,7 +3605,7 @@ void BindingData::LegacyMainResolve(const FunctionCallbackInfo<Value>& args) {
|
||||
@@ -3594,7 +3611,7 @@ void BindingData::LegacyMainResolve(const FunctionCallbackInfo<Value>& args) {
|
||||
BufferValue buff_file_path(isolate, local_file_path);
|
||||
ToNamespacedPath(env, &buff_file_path);
|
||||
|
||||
@@ -104,7 +104,7 @@ index 77f8f1bd4e8294f2ebc7e0724aea5902eb0f95ab..5de3ebb04b12286a07e3041d0a6dd1cc
|
||||
case BindingData::FilePathIsFileReturnType::kIsFile:
|
||||
return args.GetReturnValue().Set(i);
|
||||
case BindingData::FilePathIsFileReturnType::kIsNotFile:
|
||||
@@ -3625,7 +3642,7 @@ void BindingData::LegacyMainResolve(const FunctionCallbackInfo<Value>& args) {
|
||||
@@ -3631,7 +3648,7 @@ void BindingData::LegacyMainResolve(const FunctionCallbackInfo<Value>& args) {
|
||||
BufferValue buff_file_path(isolate, local_file_path);
|
||||
ToNamespacedPath(env, &buff_file_path);
|
||||
|
||||
|
||||
@@ -1,127 +0,0 @@
|
||||
From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001
|
||||
From: Shelley Vohr <shelley.vohr@gmail.com>
|
||||
Date: Thu, 10 Jul 2025 08:36:12 +0000
|
||||
Subject: fix: array out-of-bounds read in Boyer-Moore search
|
||||
|
||||
Refs https://chromium-review.googlesource.com/c/chromium/src/+/6703757
|
||||
|
||||
The above CL enabled array bounds sanitization, which triggered a crash in a Node.js
|
||||
test which exposed an issue in Node.js implementation of Boyer-Moore string search.
|
||||
|
||||
Some Boyer-Moore search impl functions were using "biased pointer" arithmetic to
|
||||
create array pointers that point outside the actual array bounds.
|
||||
|
||||
When start_ is large this creates pointers far outside the valid memory range.
|
||||
While this worked by accident in practice, it's undefined behavior that the CL
|
||||
correctly prohibits.
|
||||
|
||||
diff --git a/deps/nbytes/include/nbytes.h b/deps/nbytes/include/nbytes.h
|
||||
index b012729c6cca8e42c94fd9b6a9c72301b4370de4..bb2e2e5fd2781f9e3db7f0b0699e1b0513e6782d 100644
|
||||
--- a/deps/nbytes/include/nbytes.h
|
||||
+++ b/deps/nbytes/include/nbytes.h
|
||||
@@ -4,6 +4,7 @@
|
||||
#include <cmath>
|
||||
#include <cstddef>
|
||||
#include <cstdint>
|
||||
+#include <cstdlib>
|
||||
#include <cstring>
|
||||
#include <string>
|
||||
|
||||
@@ -548,7 +549,11 @@ size_t StringSearch<Char>::BoyerMooreSearch(Vector subject,
|
||||
size_t start = start_;
|
||||
|
||||
int *bad_char_occurrence = bad_char_shift_table_;
|
||||
- int *good_suffix_shift = good_suffix_shift_table_ - start_;
|
||||
+
|
||||
+ auto good_suffix_get = [&](size_t idx) -> int {
|
||||
+ if (idx < start || idx - start > kBMMaxShift) return 0;
|
||||
+ return good_suffix_shift_table_[idx - start];
|
||||
+ };
|
||||
|
||||
Char last_char = pattern_[pattern_length - 1];
|
||||
size_t index = start_index;
|
||||
@@ -575,7 +580,7 @@ size_t StringSearch<Char>::BoyerMooreSearch(Vector subject,
|
||||
index +=
|
||||
pattern_length - 1 - CharOccurrence(bad_char_occurrence, last_char);
|
||||
} else {
|
||||
- int gs_shift = good_suffix_shift[j + 1];
|
||||
+ int gs_shift = good_suffix_get(j + 1);
|
||||
int bc_occ = CharOccurrence(bad_char_occurrence, c);
|
||||
int shift = j - bc_occ;
|
||||
if (gs_shift > shift) {
|
||||
@@ -596,17 +601,22 @@ void StringSearch<Char>::PopulateBoyerMooreTable() {
|
||||
const size_t start = start_;
|
||||
const size_t length = pattern_length - start;
|
||||
|
||||
- // Biased tables so that we can use pattern indices as table indices,
|
||||
- // even if we only cover the part of the pattern from offset start.
|
||||
- int *shift_table = good_suffix_shift_table_ - start_;
|
||||
- int *suffix_table = suffix_table_ - start_;
|
||||
+ auto shift_get = [&](size_t idx) -> int& {
|
||||
+ if (idx < start) abort();
|
||||
+ return good_suffix_shift_table_[idx - start];
|
||||
+ };
|
||||
+
|
||||
+ auto suffix_get = [&](size_t idx) -> int& {
|
||||
+ if (idx < start) abort();
|
||||
+ return suffix_table_[idx - start];
|
||||
+ };
|
||||
|
||||
// Initialize table.
|
||||
for (size_t i = start; i < pattern_length; i++) {
|
||||
- shift_table[i] = length;
|
||||
+ shift_get(i) = length;
|
||||
}
|
||||
- shift_table[pattern_length] = 1;
|
||||
- suffix_table[pattern_length] = pattern_length + 1;
|
||||
+ shift_get(pattern_length) = 1;
|
||||
+ suffix_get(pattern_length) = pattern_length + 1;
|
||||
|
||||
if (pattern_length <= start) {
|
||||
return;
|
||||
@@ -620,22 +630,22 @@ void StringSearch<Char>::PopulateBoyerMooreTable() {
|
||||
while (i > start) {
|
||||
Char c = pattern_[i - 1];
|
||||
while (suffix <= pattern_length && c != pattern_[suffix - 1]) {
|
||||
- if (static_cast<size_t>(shift_table[suffix]) == length) {
|
||||
- shift_table[suffix] = suffix - i;
|
||||
+ if (static_cast<size_t>(shift_get(suffix)) == length) {
|
||||
+ shift_get(suffix) = suffix - i;
|
||||
}
|
||||
- suffix = suffix_table[suffix];
|
||||
+ suffix = suffix_get(suffix);
|
||||
}
|
||||
- suffix_table[--i] = --suffix;
|
||||
+ suffix_get(--i) = --suffix;
|
||||
if (suffix == pattern_length) {
|
||||
// No suffix to extend, so we check against last_char only.
|
||||
while ((i > start) && (pattern_[i - 1] != last_char)) {
|
||||
- if (static_cast<size_t>(shift_table[pattern_length]) == length) {
|
||||
- shift_table[pattern_length] = pattern_length - i;
|
||||
+ if (static_cast<size_t>(shift_get(pattern_length)) == length) {
|
||||
+ shift_get(pattern_length) = pattern_length - i;
|
||||
}
|
||||
- suffix_table[--i] = pattern_length;
|
||||
+ suffix_get(--i) = pattern_length;
|
||||
}
|
||||
if (i > start) {
|
||||
- suffix_table[--i] = --suffix;
|
||||
+ suffix_get(--i) = --suffix;
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -643,11 +653,11 @@ void StringSearch<Char>::PopulateBoyerMooreTable() {
|
||||
// Build shift table using suffixes.
|
||||
if (suffix < pattern_length) {
|
||||
for (size_t i = start; i <= pattern_length; i++) {
|
||||
- if (static_cast<size_t>(shift_table[i]) == length) {
|
||||
- shift_table[i] = suffix - start;
|
||||
+ if (static_cast<size_t>(shift_get(i)) == length) {
|
||||
+ shift_get(i) = suffix - start;
|
||||
}
|
||||
if (i == suffix) {
|
||||
- suffix = suffix_table[suffix];
|
||||
+ suffix = suffix_get(suffix);
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -12,7 +12,7 @@ This can be removed/refactored once Node.js upgrades to a version of V8
|
||||
containing the above CL.
|
||||
|
||||
diff --git a/src/node.cc b/src/node.cc
|
||||
index b99b5170553af51466fd1ee69af3be5026f3fada..ccb644007b8ebbf3899e64d8097d97208c0de182 100644
|
||||
index 0bc4aff4573ccd0e53de5f288b5bccdb6063652a..e1b195f25fe6069ececf3b8c516c5e27f3bf39ab 100644
|
||||
--- a/src/node.cc
|
||||
+++ b/src/node.cc
|
||||
@@ -1239,7 +1239,7 @@ InitializeOncePerProcessInternal(const std::vector<std::string>& args,
|
||||
|
||||
@@ -77,10 +77,10 @@ index 78985575beb3df7722ba90968e8f085574b5afdf..e032c016efe227c26364e81804ad183c
|
||||
// Check if the ESM initiating import CJS is being required by the same CJS module.
|
||||
if (cjsModule?.[kIsExecuting]) {
|
||||
diff --git a/lib/internal/modules/esm/resolve.js b/lib/internal/modules/esm/resolve.js
|
||||
index 859b6bfedac4bbee2df054f9ebca7cbaaed45f18..5aa946f66c71beff0b7a43c30638ab28a1a5dfc0 100644
|
||||
index ec28ea021909071557277c2c98600afb203dfaa1..cb44ec468edb22adc7a159cabec528cc135c9ec5 100644
|
||||
--- a/lib/internal/modules/esm/resolve.js
|
||||
+++ b/lib/internal/modules/esm/resolve.js
|
||||
@@ -750,6 +750,9 @@ function packageImportsResolve(name, base, conditions) {
|
||||
@@ -751,6 +751,9 @@ function packageImportsResolve(name, base, conditions) {
|
||||
throw importNotDefined(name, packageJSONUrl, base);
|
||||
}
|
||||
|
||||
@@ -90,7 +90,7 @@ index 859b6bfedac4bbee2df054f9ebca7cbaaed45f18..5aa946f66c71beff0b7a43c30638ab28
|
||||
|
||||
/**
|
||||
* Resolves a package specifier to a URL.
|
||||
@@ -764,6 +767,11 @@ function packageResolve(specifier, base, conditions) {
|
||||
@@ -765,6 +768,11 @@ function packageResolve(specifier, base, conditions) {
|
||||
return new URL('node:' + specifier);
|
||||
}
|
||||
|
||||
@@ -138,10 +138,10 @@ index 757f093becd112002f3422302f4c29bb464f1a6c..c8cea2117080930105b33e4e50586a2c
|
||||
// This translator function must be sync, as `require` is sync.
|
||||
translators.set('require-commonjs-typescript', (url, source, isMain) => {
|
||||
diff --git a/lib/internal/url.js b/lib/internal/url.js
|
||||
index ad1c2c9966085b8febd261b2fc776ce49bc1bd36..96fdce31168ae70ce20f3bfb81931705b2d55f31 100644
|
||||
index 62e240a8a0488c826339b92eb62e78162e0a32b8..f4019eeb831423f9fc1249ed9581ba9492b6c738 100644
|
||||
--- a/lib/internal/url.js
|
||||
+++ b/lib/internal/url.js
|
||||
@@ -1608,6 +1608,8 @@ function fileURLToPath(path, options = kEmptyObject) {
|
||||
@@ -1603,6 +1603,8 @@ function fileURLToPath(path, options = kEmptyObject) {
|
||||
path = new URL(path);
|
||||
else if (!isURL(path))
|
||||
throw new ERR_INVALID_ARG_TYPE('path', ['string', 'URL'], path);
|
||||
|
||||
@@ -0,0 +1,34 @@
|
||||
From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001
|
||||
From: Shelley Vohr <shelley.vohr@gmail.com>
|
||||
Date: Tue, 10 Feb 2026 16:48:47 +0100
|
||||
Subject: fix: generate_config_gypi needs to generate valid JSON
|
||||
|
||||
Node.js added new process.config.variables entries, which the GN generator
|
||||
emitted with Python repr (single quotes). This made the JSON parse blow
|
||||
up. Fix this by switching to json.dumps.
|
||||
|
||||
This should be upstreamed.
|
||||
|
||||
diff --git a/tools/generate_config_gypi.py b/tools/generate_config_gypi.py
|
||||
index abd11e1dbda8d400cb900343c6e8d2d6e84fe944..436767e633e1f492fa858645e25ce9b904a5fccb 100755
|
||||
--- a/tools/generate_config_gypi.py
|
||||
+++ b/tools/generate_config_gypi.py
|
||||
@@ -58,7 +58,7 @@ def translate_config(out_dir, config, v8_config):
|
||||
'llvm_version': 13,
|
||||
'napi_build_version': config['napi_build_version'],
|
||||
'node_builtin_shareable_builtins':
|
||||
- eval(config['node_builtin_shareable_builtins']),
|
||||
+ json.loads(config['node_builtin_shareable_builtins']),
|
||||
'node_module_version': int(config['node_module_version']),
|
||||
'node_use_openssl': config['node_use_openssl'],
|
||||
'node_use_amaro': config['node_use_amaro'],
|
||||
@@ -102,7 +102,8 @@ def main():
|
||||
|
||||
# Write output.
|
||||
with open(args.target, 'w') as f:
|
||||
- f.write(repr(translate_config(args.out_dir, config, v8_config)))
|
||||
+ f.write(json.dumps(translate_config(args.out_dir, config, v8_config),
|
||||
+ sort_keys=True))
|
||||
|
||||
# Write depfile. Force regenerating config.gypi when GN configs change.
|
||||
if args.dep_file:
|
||||
@@ -185,10 +185,10 @@ index e2407027ab05e59b2f0f1c213b98ea469db7a91b..c64761b730e61edcdc0e46a48699f2fd
|
||||
# The location of simdutf - use the one from node's deps by default.
|
||||
node_simdutf_path = "//third_party/simdutf"
|
||||
diff --git a/src/crypto/crypto_cipher.cc b/src/crypto/crypto_cipher.cc
|
||||
index 2176fb6982484e2c42538478eeb4dd81c9d50ee1..c00d3616e08b00b1e0a3a29b2dbb5278e1e14fcc 100644
|
||||
index 07eb79acdf5e2d236b36daa1b314ed1afa19a545..c862f91bf1f9494b747b2950e8e37547ba08b6b8 100644
|
||||
--- a/src/crypto/crypto_cipher.cc
|
||||
+++ b/src/crypto/crypto_cipher.cc
|
||||
@@ -1027,7 +1027,7 @@ void PublicKeyCipher::Cipher(const FunctionCallbackInfo<Value>& args) {
|
||||
@@ -1026,7 +1026,7 @@ void PublicKeyCipher::Cipher(const FunctionCallbackInfo<Value>& args) {
|
||||
if (EVP_PKEY_decrypt_init(ctx.get()) <= 0) {
|
||||
return ThrowCryptoError(env, ERR_get_error());
|
||||
}
|
||||
@@ -197,7 +197,7 @@ index 2176fb6982484e2c42538478eeb4dd81c9d50ee1..c00d3616e08b00b1e0a3a29b2dbb5278
|
||||
int rsa_pkcs1_implicit_rejection =
|
||||
EVP_PKEY_CTX_ctrl_str(ctx.get(), "rsa_pkcs1_implicit_rejection", "1");
|
||||
// From the doc -2 means that the option is not supported.
|
||||
@@ -1042,6 +1042,7 @@ void PublicKeyCipher::Cipher(const FunctionCallbackInfo<Value>& args) {
|
||||
@@ -1041,6 +1041,7 @@ void PublicKeyCipher::Cipher(const FunctionCallbackInfo<Value>& args) {
|
||||
env,
|
||||
"RSA_PKCS1_PADDING is no longer supported for private decryption");
|
||||
}
|
||||
@@ -228,7 +228,7 @@ index d94f6e1c82c4a62547b3b395f375c86ce4deb5de..b81b9005365272217c77e2b9289bd9f8
|
||||
X509View ca(sk_X509_value(peer_certs.get(), i));
|
||||
if (!cert->view().isIssuedBy(ca)) continue;
|
||||
diff --git a/src/crypto/crypto_context.cc b/src/crypto/crypto_context.cc
|
||||
index d1430cd66dd045dcb52dd166e1eabc7202d1bd94..8f50d0cc132ac65fa74cf1fc2172247b5ad42962 100644
|
||||
index 8028f6db70f481e291aca2b8e0e6129900fbf67e..2cd7cd67c1c480eb9ec549a12bc2b9584d5a53b3 100644
|
||||
--- a/src/crypto/crypto_context.cc
|
||||
+++ b/src/crypto/crypto_context.cc
|
||||
@@ -141,7 +141,7 @@ int SSL_CTX_use_certificate_chain(SSL_CTX* ctx,
|
||||
@@ -240,7 +240,7 @@ index d1430cd66dd045dcb52dd166e1eabc7202d1bd94..8f50d0cc132ac65fa74cf1fc2172247b
|
||||
X509* ca = sk_X509_value(extra_certs, i);
|
||||
|
||||
// NOTE: Increments reference count on `ca`
|
||||
@@ -1831,11 +1831,12 @@ void SecureContext::SetDHParam(const FunctionCallbackInfo<Value>& args) {
|
||||
@@ -1854,11 +1854,12 @@ void SecureContext::SetDHParam(const FunctionCallbackInfo<Value>& args) {
|
||||
// If the user specified "auto" for dhparams, the JavaScript layer will pass
|
||||
// true to this function instead of the original string. Any other string
|
||||
// value will be interpreted as custom DH parameters below.
|
||||
@@ -254,7 +254,7 @@ index d1430cd66dd045dcb52dd166e1eabc7202d1bd94..8f50d0cc132ac65fa74cf1fc2172247b
|
||||
DHPointer dh;
|
||||
{
|
||||
BIOPointer bio(LoadBIO(env, args[0]));
|
||||
@@ -2061,7 +2062,7 @@ void SecureContext::LoadPKCS12(const FunctionCallbackInfo<Value>& args) {
|
||||
@@ -2084,7 +2085,7 @@ void SecureContext::LoadPKCS12(const FunctionCallbackInfo<Value>& args) {
|
||||
}
|
||||
|
||||
// Add CA certs too
|
||||
@@ -519,7 +519,7 @@ index 9c2360df7150571377eff37fc5e958d17900da30..4505786745c54a529f904d5e7813a862
|
||||
} // namespace
|
||||
|
||||
diff --git a/src/env.h b/src/env.h
|
||||
index 874e5f4d15a75307e45cf70c06fc104fed843a6a..35e16159a94bb97f19d17767e3ad4bb798660f44 100644
|
||||
index 7a63acde77d28c0f11c7f2563c8c3cb2ebdce780..723e4738dd1c32710e521775d66e0d957334344c 100644
|
||||
--- a/src/env.h
|
||||
+++ b/src/env.h
|
||||
@@ -51,7 +51,7 @@
|
||||
@@ -554,7 +554,7 @@ index d9c533f100d25aeab1fe8589932a8ddead431258..2acab8786a8a752b17961445edeb872c
|
||||
#if NODE_OPENSSL_HAS_QUIC
|
||||
#include <openssl/quic.h>
|
||||
diff --git a/src/node_options.cc b/src/node_options.cc
|
||||
index 31fc23fdbfabceab3cffd81a3e6650dde1ccd13a..3026b3d814ae652a9996c1dcba62b4fa678ac871 100644
|
||||
index 5b74045886e91a27e766a7f0a8f2dddfacaa1d46..41de3936265f0544831521fe753d2050e91b58e1 100644
|
||||
--- a/src/node_options.cc
|
||||
+++ b/src/node_options.cc
|
||||
@@ -8,7 +8,7 @@
|
||||
@@ -567,7 +567,7 @@ index 31fc23fdbfabceab3cffd81a3e6650dde1ccd13a..3026b3d814ae652a9996c1dcba62b4fa
|
||||
#endif
|
||||
|
||||
diff --git a/src/node_options.h b/src/node_options.h
|
||||
index 2e73fd2a05e329910d4c064474880f770c9f5957..d8751a6ee734233e2fc24866ed87d9cd516072ae 100644
|
||||
index c1bcc063a001194bb76efe9a202fb4ab271ba834..b7d9b429f0b498dfd70301074948a13a2d35532e 100644
|
||||
--- a/src/node_options.h
|
||||
+++ b/src/node_options.h
|
||||
@@ -11,7 +11,7 @@
|
||||
|
||||
@@ -28,7 +28,7 @@ index 3676a9852bcd42de0a3a380de117de58035f757b..eaecfcfd8b922908957c3fefea65fb9d
|
||||
const result = dataURLProcessor(url);
|
||||
if (result === 'failure') {
|
||||
diff --git a/lib/internal/modules/esm/resolve.js b/lib/internal/modules/esm/resolve.js
|
||||
index 5aa946f66c71beff0b7a43c30638ab28a1a5dfc0..e3afd30ba1f591d0298793bc42fd7166a4219bce 100644
|
||||
index cb44ec468edb22adc7a159cabec528cc135c9ec5..4216e136d01a119264de1523ed466efb783311c3 100644
|
||||
--- a/lib/internal/modules/esm/resolve.js
|
||||
+++ b/lib/internal/modules/esm/resolve.js
|
||||
@@ -25,7 +25,7 @@ const {
|
||||
@@ -40,7 +40,7 @@ index 5aa946f66c71beff0b7a43c30638ab28a1a5dfc0..e3afd30ba1f591d0298793bc42fd7166
|
||||
const { getOptionValue } = require('internal/options');
|
||||
// Do not eagerly grab .manifest, it may be in TDZ
|
||||
const { sep, posix: { relative: relativePosixPath }, resolve } = require('path');
|
||||
@@ -276,7 +276,7 @@ function finalizeResolution(resolved, base, preserveSymlinks) {
|
||||
@@ -277,7 +277,7 @@ function finalizeResolution(resolved, base, preserveSymlinks) {
|
||||
}
|
||||
|
||||
if (!preserveSymlinks) {
|
||||
|
||||
@@ -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 b9f0c97938203b4652780a7d707c5e83319330b0..8a5b6b57321c2843a965a7e51b2ebed991a1e424 100644
|
||||
index 2fdada446c5d1ffa460f483a3360aeca658d9eef..b87b53843c3369832e561b9ffd40ca7c2134e74c 100644
|
||||
--- a/src/node_buffer.cc
|
||||
+++ b/src/node_buffer.cc
|
||||
@@ -44,6 +44,14 @@
|
||||
|
||||
@@ -15,7 +15,7 @@ This patch can be removed when we upgrade to a V8 version that
|
||||
contains the above CLs.
|
||||
|
||||
diff --git a/src/node.cc b/src/node.cc
|
||||
index 2d8d0000d52411992d2bd513cc7dd96b2292bab9..0ffc69d54631fa3dbac20337b26f7a0679560b96 100644
|
||||
index db0011b429f25cab296ca425564effe87383f506..152a9d9b17f9b14922421e2fe9866b6056f13ec7 100644
|
||||
--- a/src/node.cc
|
||||
+++ b/src/node.cc
|
||||
@@ -816,7 +816,7 @@ static ExitCode ProcessGlobalArgsInternal(std::vector<std::string>* args,
|
||||
|
||||
@@ -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 79327877b0f34cbafb3efcc21617027d4011f806..8a12475857135bd3e904610b7eb887c397c8e73c 100644
|
||||
index 6034b779fe05850cfc4e7f7af221489be9369b54..d19cae298147f1b310506eec49b6fbd036fb1195 100644
|
||||
--- a/src/api/environment.cc
|
||||
+++ b/src/api/environment.cc
|
||||
@@ -827,7 +827,7 @@ MaybeLocal<Object> InitializePrivateSymbols(Local<Context> context,
|
||||
@@ -832,7 +832,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 79327877b0f34cbafb3efcc21617027d4011f806..8a12475857135bd3e904610b7eb887c3
|
||||
.IsNothing()) {
|
||||
return MaybeLocal<Object>();
|
||||
}
|
||||
@@ -853,7 +853,7 @@ MaybeLocal<Object> InitializePerIsolateSymbols(Local<Context> context,
|
||||
@@ -858,7 +858,7 @@ MaybeLocal<Object> InitializePerIsolateSymbols(Local<Context> context,
|
||||
Local<Object> per_isolate_symbols_object;
|
||||
if (!per_isolate_symbols->NewInstance(context).ToLocal(
|
||||
&per_isolate_symbols_object) ||
|
||||
|
||||
@@ -6,7 +6,7 @@ Subject: Pass all globals through "require"
|
||||
(cherry picked from commit 7d015419cb7a0ecfe6728431a4ed2056cd411d62)
|
||||
|
||||
diff --git a/lib/internal/modules/cjs/loader.js b/lib/internal/modules/cjs/loader.js
|
||||
index a7d8fa1139c82054ac37a4e11cfb68605dc21f31..589c239aa544e118b7d9b7fff86d7deefe903896 100644
|
||||
index b87f557c16820ea52eece22813a8a218587a62dc..21730d32e0dd16065ae15ad6a0aae90e81a4c9b2 100644
|
||||
--- a/lib/internal/modules/cjs/loader.js
|
||||
+++ b/lib/internal/modules/cjs/loader.js
|
||||
@@ -202,6 +202,13 @@ const {
|
||||
@@ -23,7 +23,7 @@ index a7d8fa1139c82054ac37a4e11cfb68605dc21f31..589c239aa544e118b7d9b7fff86d7dee
|
||||
const {
|
||||
isProxy,
|
||||
} = require('internal/util/types');
|
||||
@@ -1701,10 +1708,12 @@ Module.prototype._compile = function(content, filename, format) {
|
||||
@@ -1700,10 +1707,12 @@ Module.prototype._compile = function(content, filename, format) {
|
||||
if (this[kIsMainSymbol] && getOptionValue('--inspect-brk')) {
|
||||
const { callAndPauseOnStart } = internalBinding('inspector');
|
||||
result = callAndPauseOnStart(compiledWrapper, thisValue, exports,
|
||||
|
||||
@@ -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 fd71ceac65ccef1d2832b45b0b5612877cee22c1..ceac508418f489a8077c1bc85a2feaf85bf60480 100644
|
||||
index 8356e588659d2208700659f3e3ce5438fba9462f..d2614bba9463056e931b6d5c1f3153e2f576b779 100644
|
||||
--- a/src/api/environment.cc
|
||||
+++ b/src/api/environment.cc
|
||||
@@ -308,6 +308,10 @@ Isolate* NewIsolate(Isolate::CreateParams* params,
|
||||
@@ -313,6 +313,10 @@ Isolate* NewIsolate(Isolate::CreateParams* params,
|
||||
MultiIsolatePlatform* platform,
|
||||
const SnapshotData* snapshot_data,
|
||||
const IsolateSettings& settings) {
|
||||
@@ -32,7 +32,7 @@ index fd71ceac65ccef1d2832b45b0b5612877cee22c1..ceac508418f489a8077c1bc85a2feaf8
|
||||
Isolate* isolate = Isolate::Allocate();
|
||||
if (isolate == nullptr) return nullptr;
|
||||
|
||||
@@ -351,9 +355,12 @@ Isolate* NewIsolate(ArrayBufferAllocator* allocator,
|
||||
@@ -356,9 +360,12 @@ Isolate* NewIsolate(ArrayBufferAllocator* allocator,
|
||||
uv_loop_t* event_loop,
|
||||
MultiIsolatePlatform* platform,
|
||||
const EmbedderSnapshotData* snapshot_data,
|
||||
@@ -82,7 +82,7 @@ index 85641b68b1e6f6dd4149f33ba13f76bccc8bf47d..c6209cc7cf317de1bb9217e39dd760e5
|
||||
void SetCppgcReference(Isolate* isolate,
|
||||
Local<Object> object,
|
||||
diff --git a/src/env.h b/src/env.h
|
||||
index 2d5fa8dbd75851bca30453548f6cbe0159509f26..c346e3a9c827993036438685d758a734f9ce8c05 100644
|
||||
index 888f0a5572254d775cbf672dcf07b789782292ea..2af2846af6ba7d8ad6e0edca5e2f6279e4c672a3 100644
|
||||
--- a/src/env.h
|
||||
+++ b/src/env.h
|
||||
@@ -157,7 +157,6 @@ class NODE_EXTERN_PRIVATE IsolateData : public MemoryRetainer {
|
||||
@@ -102,7 +102,7 @@ index 2d5fa8dbd75851bca30453548f6cbe0159509f26..c346e3a9c827993036438685d758a734
|
||||
worker::Worker* worker_context_ = nullptr;
|
||||
PerIsolateWrapperData* wrapper_data_;
|
||||
diff --git a/src/node.cc b/src/node.cc
|
||||
index 0ffc69d54631fa3dbac20337b26f7a0679560b96..f012b365455bb111cddea44fcff020804086ab72 100644
|
||||
index 152a9d9b17f9b14922421e2fe9866b6056f13ec7..f85b5ed687180d7a12648b87398a734fb321f346 100644
|
||||
--- a/src/node.cc
|
||||
+++ b/src/node.cc
|
||||
@@ -1288,6 +1288,14 @@ InitializeOncePerProcessInternal(const std::vector<std::string>& args,
|
||||
@@ -136,10 +136,10 @@ index 0ffc69d54631fa3dbac20337b26f7a0679560b96..f012b365455bb111cddea44fcff02080
|
||||
bool use_wasm_trap_handler =
|
||||
!per_process::cli_options->disable_wasm_trap_handler;
|
||||
diff --git a/src/node.h b/src/node.h
|
||||
index d3a965661d068db359bb1bb4b14e59c28bb615f9..16a0c71aef949b0ddd27def9dc843298f9a6b75f 100644
|
||||
index 91468bfd755db6adde5cc8cecb184312db90a654..fe44369dff7519ea0d960ae478d5caf524e17366 100644
|
||||
--- a/src/node.h
|
||||
+++ b/src/node.h
|
||||
@@ -590,7 +590,8 @@ NODE_EXTERN v8::Isolate* NewIsolate(
|
||||
@@ -589,7 +589,8 @@ NODE_EXTERN v8::Isolate* NewIsolate(
|
||||
struct uv_loop_s* event_loop,
|
||||
MultiIsolatePlatform* platform,
|
||||
const EmbedderSnapshotData* snapshot_data = nullptr,
|
||||
@@ -174,7 +174,7 @@ index 4119ac1b002681d39711eac810ca2fcc2702ffc7..790347056cde949ffe6cf8498a7eca0c
|
||||
|
||||
ExitCode NodeMainInstance::Run() {
|
||||
diff --git a/src/node_worker.cc b/src/node_worker.cc
|
||||
index 29c4b1de42b3127a98871d200c80197bf974b31f..8555ab556b5b74a1cf9cf30747f1f417bfe4e4d9 100644
|
||||
index 083abea7d744e552dd349e5e1ceb75dfaaa79eaa..ddfea91272d03d4ef1d4ac1b982ada5dcd24b601 100644
|
||||
--- a/src/node_worker.cc
|
||||
+++ b/src/node_worker.cc
|
||||
@@ -177,6 +177,9 @@ class WorkerThreadData {
|
||||
|
||||
@@ -16,24 +16,28 @@ 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
|
||||
index d19cae298147f1b310506eec49b6fbd036fb1195..ecd2d481d97e5dab934481b085b949f47904a6c4 100644
|
||||
--- a/src/api/environment.cc
|
||||
+++ b/src/api/environment.cc
|
||||
@@ -107,11 +107,7 @@ MaybeLocal<Value> PrepareStackTraceCallback(Local<Context> context,
|
||||
@@ -108,14 +108,8 @@ 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)
|
||||
- if (zero_fill_field_ || per_process::cli_options->zero_fill_all_buffers) {
|
||||
- COUNT_GENERIC_USAGE("NodeArrayBufferAllocator.Allocate.ZeroFilled");
|
||||
- ret = allocator_->Allocate(size);
|
||||
- else
|
||||
- } else {
|
||||
- COUNT_GENERIC_USAGE("NodeArrayBufferAllocator.Allocate.Uninitialized");
|
||||
- ret = allocator_->AllocateUninitialized(size);
|
||||
- }
|
||||
+ void* ret = allocator_->Allocate(size);
|
||||
+ COUNT_GENERIC_USAGE("NodeArrayBufferAllocator.Allocate.Uninitialized");
|
||||
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
|
||||
index c862f91bf1f9494b747b2950e8e37547ba08b6b8..9fd48697845fca304e1dabf7c57ab208d9649a73 100644
|
||||
--- a/src/crypto/crypto_cipher.cc
|
||||
+++ b/src/crypto/crypto_cipher.cc
|
||||
@@ -20,6 +20,7 @@ using ncrypto::SSLPointer;
|
||||
@@ -44,7 +48,7 @@ index c00d3616e08b00b1e0a3a29b2dbb5278e1e14fcc..8939c5e5085d00b098f66074b9ee033f
|
||||
using v8::Context;
|
||||
using v8::FunctionCallbackInfo;
|
||||
using v8::FunctionTemplate;
|
||||
@@ -774,10 +775,10 @@ CipherBase::UpdateResult CipherBase::Update(
|
||||
@@ -773,10 +774,10 @@ CipherBase::UpdateResult CipherBase::Update(
|
||||
return kErrorState;
|
||||
}
|
||||
|
||||
@@ -59,7 +63,7 @@ index c00d3616e08b00b1e0a3a29b2dbb5278e1e14fcc..8939c5e5085d00b098f66074b9ee033f
|
||||
|
||||
buffer = {
|
||||
.data = reinterpret_cast<const unsigned char*>(data),
|
||||
@@ -852,11 +853,10 @@ bool CipherBase::Final(std::unique_ptr<BackingStore>* out) {
|
||||
@@ -851,11 +852,10 @@ bool CipherBase::Final(std::unique_ptr<BackingStore>* out) {
|
||||
|
||||
const int mode = ctx_.getMode();
|
||||
|
||||
@@ -75,7 +79,7 @@ index c00d3616e08b00b1e0a3a29b2dbb5278e1e14fcc..8939c5e5085d00b098f66074b9ee033f
|
||||
|
||||
if (kind_ == kDecipher &&
|
||||
Cipher::FromCtx(ctx_).isSupportedAuthenticatedMode()) {
|
||||
@@ -972,10 +972,10 @@ bool PublicKeyCipher::Cipher(
|
||||
@@ -971,10 +971,10 @@ bool PublicKeyCipher::Cipher(
|
||||
return false;
|
||||
}
|
||||
|
||||
@@ -359,7 +363,7 @@ index fd29d17de195017970856ce30d7a9c5785b0b8ee..7fe3d09851d4476fa3f77ea0a0b49e8a
|
||||
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
|
||||
index 22eecffa437a9e0f4a0e170953aa35fa527511b5..5b45f2223cece766bd7d27ac0d3a853c82f8ce07 100644
|
||||
--- a/src/encoding_binding.cc
|
||||
+++ b/src/encoding_binding.cc
|
||||
@@ -15,6 +15,7 @@ namespace encoding_binding {
|
||||
@@ -383,7 +387,7 @@ index 5ace688bb7ffc86eedf5aff11ab0ab487ad9440e..31058543a164bb45ba989e8c433994e0
|
||||
CHECK(bs);
|
||||
|
||||
diff --git a/src/env-inl.h b/src/env-inl.h
|
||||
index 98e1e1e75bae94038bba0049447ab48b0acfb8cc..fe395bf89f9c1e5bb2dabc8fceda7b9b2b877415 100644
|
||||
index d1a7e1212da46a8e5c2fffee46542ac8bec828ee..97018f2378fe4848944f26f51684b21ac118d1b3 100644
|
||||
--- a/src/env-inl.h
|
||||
+++ b/src/env-inl.h
|
||||
@@ -44,16 +44,6 @@
|
||||
@@ -432,7 +436,7 @@ index 161d577e0ea6a251c83ba1903b1ec9a582a5317c..52713421465c23c959afac1955168294
|
||||
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
|
||||
index 2af2846af6ba7d8ad6e0edca5e2f6279e4c672a3..87cff857bbe65c32e1931886b953c5e32deba193 100644
|
||||
--- a/src/env.h
|
||||
+++ b/src/env.h
|
||||
@@ -114,19 +114,6 @@ class ModuleWrap;
|
||||
@@ -456,7 +460,7 @@ index c346e3a9c827993036438685d758a734f9ce8c05..28c8df87c8e2f06e2ed8c554260bfded
|
||||
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
|
||||
index 0cf2a07deb382dfd96607f84b583ffbd62447769..f2943d5ceca106564e421c668ec8815c43c21085 100644
|
||||
--- a/src/node_buffer.cc
|
||||
+++ b/src/node_buffer.cc
|
||||
@@ -66,6 +66,7 @@ namespace Buffer {
|
||||
@@ -525,7 +529,7 @@ index e844fe6cb33acefd075516e675075421ad5c3cff..06c84eb6ec097e3cb39502116135a780
|
||||
return env->ThrowRangeError("Array buffer allocation failed");
|
||||
}
|
||||
diff --git a/src/node_http2.cc b/src/node_http2.cc
|
||||
index 8237c9b7d325dd925ae8798d7795fcd94eeb13d0..a22cf6c4e33e5cf2d3168ce03dc35af8a9584af7 100644
|
||||
index 7c070ae09e77afc7773724a516217059189138a7..bb761c0a201cbed568258d07d8ec0d6a80de8b3b 100644
|
||||
--- a/src/node_http2.cc
|
||||
+++ b/src/node_http2.cc
|
||||
@@ -27,6 +27,7 @@ using v8::Array;
|
||||
|
||||
@@ -1,74 +0,0 @@
|
||||
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);
|
||||
+ }
|
||||
}
|
||||
}
|
||||
|
||||
@@ -212,10 +212,10 @@ index 7fe3d09851d4476fa3f77ea0a0b49e8af13fae4f..b60ad6b1cdb0b923ba2de1b7205ed5ce
|
||||
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
|
||||
index e62dce7a3e5f32ebb926ad2ffe57887ab1887b8d..878d9764e072f0b0105508541beff205bf97b1ab 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,
|
||||
@@ -116,7 +116,7 @@ napi_status NewExternalString(napi_env env,
|
||||
CHECK_NEW_STRING_ARGS(env, str, length, result);
|
||||
|
||||
napi_status status;
|
||||
@@ -225,10 +225,10 @@ index 413db3ed9b88d7b7fb2ac6dd1153dade9ff830fd..6da93b8569a34841e846c320ec0a6ca7
|
||||
if (status == napi_ok) {
|
||||
if (copied != nullptr) {
|
||||
diff --git a/src/node_api.cc b/src/node_api.cc
|
||||
index 2769997f0ede0e921fcb8826942609e497e5f9cb..d9b17780f6143f1c3f8488a20144376963e43fbc 100644
|
||||
index 26583f964edadef46ee65e52844a4d9a0ddacc2f..9086dd9d6f409f266a1e9ae603733ecfd0fb8d72 100644
|
||||
--- a/src/node_api.cc
|
||||
+++ b/src/node_api.cc
|
||||
@@ -1056,7 +1056,7 @@ napi_create_external_buffer(napi_env env,
|
||||
@@ -1058,7 +1058,7 @@ napi_create_external_buffer(napi_env env,
|
||||
NAPI_PREAMBLE(env);
|
||||
CHECK_ARG(env, result);
|
||||
|
||||
@@ -238,7 +238,7 @@ index 2769997f0ede0e921fcb8826942609e497e5f9cb..d9b17780f6143f1c3f8488a201443769
|
||||
#else
|
||||
v8::Isolate* isolate = env->isolate;
|
||||
diff --git a/src/node_options.cc b/src/node_options.cc
|
||||
index e93e8684e518b30a2514768a269be6d32d1f5b94..547cda780376f578b0f78eb9158dc14a3faf874d 100644
|
||||
index 1ebc7bfca2d89f78898873e8b6f838f3f4c2e576..bec62634d153e2311959ad2fb56f54dfbbb80f09 100644
|
||||
--- a/src/node_options.cc
|
||||
+++ b/src/node_options.cc
|
||||
@@ -83,6 +83,8 @@ void PerProcessOptions::CheckOptions(std::vector<std::string>* errors,
|
||||
|
||||
@@ -16,7 +16,7 @@ patch:
|
||||
(cherry picked from commit 30329d06235a9f9733b1d4da479b403462d1b326)
|
||||
|
||||
diff --git a/src/env-inl.h b/src/env-inl.h
|
||||
index da2c468f11cdc320cfec794b1b8b24904b93491e..98e1e1e75bae94038bba0049447ab48b0acfb8cc 100644
|
||||
index bcf5fb6104ccf937304d109f1c0f5d07ca54acd4..d1a7e1212da46a8e5c2fffee46542ac8bec828ee 100644
|
||||
--- a/src/env-inl.h
|
||||
+++ b/src/env-inl.h
|
||||
@@ -62,31 +62,6 @@ inline uv_loop_t* IsolateData::event_loop() const {
|
||||
@@ -146,7 +146,7 @@ index 926645dc647fe7ca01165462f08eac1ade71ac4e..85641b68b1e6f6dd4149f33ba13f76bc
|
||||
|
||||
void IsolateData::MemoryInfo(MemoryTracker* tracker) const {
|
||||
diff --git a/src/env.h b/src/env.h
|
||||
index 35e16159a94bb97f19d17767e3ad4bb798660f44..2d5fa8dbd75851bca30453548f6cbe0159509f26 100644
|
||||
index 723e4738dd1c32710e521775d66e0d957334344c..888f0a5572254d775cbf672dcf07b789782292ea 100644
|
||||
--- a/src/env.h
|
||||
+++ b/src/env.h
|
||||
@@ -177,10 +177,6 @@ class NODE_EXTERN_PRIVATE IsolateData : public MemoryRetainer {
|
||||
@@ -161,10 +161,10 @@ index 35e16159a94bb97f19d17767e3ad4bb798660f44..2d5fa8dbd75851bca30453548f6cbe01
|
||||
inline MultiIsolatePlatform* platform() const;
|
||||
inline const SnapshotData* snapshot_data() const;
|
||||
diff --git a/src/node.h b/src/node.h
|
||||
index 96c599aa6448e2aa8e57e84f811564a5281c139a..d3a965661d068db359bb1bb4b14e59c28bb615f9 100644
|
||||
index 4e66924e4ca5b5d787fc6259de940a3fb40bff38..91468bfd755db6adde5cc8cecb184312db90a654 100644
|
||||
--- a/src/node.h
|
||||
+++ b/src/node.h
|
||||
@@ -1576,24 +1576,14 @@ void RegisterSignalHandler(int signal,
|
||||
@@ -1575,24 +1575,14 @@ void RegisterSignalHandler(int signal,
|
||||
bool reset_handler = false);
|
||||
#endif // _WIN32
|
||||
|
||||
|
||||
@@ -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 33827edce63c9fe08b52aea59571391a83853443..79327877b0f34cbafb3efcc21617027d4011f806 100644
|
||||
index f3a992b634e9532cba34ec4d54b3a1d0f68a8545..6034b779fe05850cfc4e7f7af221489be9369b54 100644
|
||||
--- a/src/api/environment.cc
|
||||
+++ b/src/api/environment.cc
|
||||
@@ -878,7 +878,7 @@ Maybe<void> InitializePrimordials(Local<Context> context,
|
||||
@@ -882,7 +882,7 @@ Maybe<void> InitializePrimordials(Local<Context> context,
|
||||
CHECK(!exports->Has(context, primordials_string).FromJust());
|
||||
|
||||
Local<Object> primordials = Object::New(isolate);
|
||||
@@ -38,10 +38,10 @@ index 487b8b7adfd35646d20fdb15be5fd6f2bee9315b..6a3c4e6952a8f3250bf1b57652a1622e
|
||||
}
|
||||
return false;
|
||||
diff --git a/src/js_native_api_v8.cc b/src/js_native_api_v8.cc
|
||||
index 7b2efa49468c0bed2f5935552addd3ab37d0a50b..413db3ed9b88d7b7fb2ac6dd1153dade9ff830fd 100644
|
||||
index 4a748957431da4b3a55ecaa5db9c45e2061f76f1..e62dce7a3e5f32ebb926ad2ffe57887ab1887b8d 100644
|
||||
--- a/src/js_native_api_v8.cc
|
||||
+++ b/src/js_native_api_v8.cc
|
||||
@@ -1577,7 +1577,7 @@ napi_status NAPI_CDECL napi_get_prototype(napi_env env,
|
||||
@@ -1578,7 +1578,7 @@ napi_status NAPI_CDECL napi_get_prototype(napi_env env,
|
||||
CHECK_TO_OBJECT(env, context, obj, object);
|
||||
|
||||
// This doesn't invokes Proxy's [[GetPrototypeOf]] handler.
|
||||
@@ -51,7 +51,7 @@ index 7b2efa49468c0bed2f5935552addd3ab37d0a50b..413db3ed9b88d7b7fb2ac6dd1153dade
|
||||
return GET_RETURN_STATUS(env);
|
||||
}
|
||||
diff --git a/src/node_buffer.cc b/src/node_buffer.cc
|
||||
index 8a5b6b57321c2843a965a7e51b2ebed991a1e424..e844fe6cb33acefd075516e675075421ad5c3cff 100644
|
||||
index b87b53843c3369832e561b9ffd40ca7c2134e74c..0cf2a07deb382dfd96607f84b583ffbd62447769 100644
|
||||
--- a/src/node_buffer.cc
|
||||
+++ b/src/node_buffer.cc
|
||||
@@ -283,8 +283,9 @@ MaybeLocal<Uint8Array> New(Environment* env,
|
||||
@@ -135,7 +135,7 @@ index b1ee513fc0873a51b4885f612dbf7b950b5cf2ca..2f23cc63f148a792f1302e1d2d888227
|
||||
Local<Object> internal_constants = Object::New(isolate);
|
||||
CHECK(internal_constants->SetPrototype(env->context(),
|
||||
diff --git a/src/node_options.cc b/src/node_options.cc
|
||||
index b067685822dc056e446e1a9402a5a6cba86cc722..e93e8684e518b30a2514768a269be6d32d1f5b94 100644
|
||||
index 5a1675f2b4448e5da71f0badee8ac5f2d2a9c6ee..1ebc7bfca2d89f78898873e8b6f838f3f4c2e576 100644
|
||||
--- a/src/node_options.cc
|
||||
+++ b/src/node_options.cc
|
||||
@@ -1552,7 +1552,8 @@ void GetCLIOptionsInfo(const FunctionCallbackInfo<Value>& args) {
|
||||
@@ -159,10 +159,10 @@ index b067685822dc056e446e1a9402a5a6cba86cc722..e93e8684e518b30a2514768a269be6d3
|
||||
return;
|
||||
}
|
||||
diff --git a/src/node_webstorage.cc b/src/node_webstorage.cc
|
||||
index 9a7b7db881a564a68683c55cb10919454e80edbf..bf88ce68f9173ef24a283dd370e71903220b0077 100644
|
||||
index d6dee522023a4e65d948b1554e9ae472f1e96e40..e7d0c4e2e1150a62a1ccfbe9e9ec08b6b2e5be65 100644
|
||||
--- a/src/node_webstorage.cc
|
||||
+++ b/src/node_webstorage.cc
|
||||
@@ -532,7 +532,7 @@ template <typename T>
|
||||
@@ -536,7 +536,7 @@ template <typename T>
|
||||
static bool ShouldIntercept(Local<Name> property,
|
||||
const PropertyCallbackInfo<T>& info) {
|
||||
Environment* env = Environment::GetCurrent(info);
|
||||
|
||||
@@ -24,10 +24,10 @@ Reviewed-By: Joyee Cheung <joyeec9h3@gmail.com>
|
||||
Reviewed-By: Rafael Gonzaga <rafael.nunu@hotmail.com>
|
||||
|
||||
diff --git a/src/node_file.cc b/src/node_file.cc
|
||||
index 75be21c9e8b413f522240a906da06d26c44d5b71..e94c2b5f2cf7cac413cd5cb782fa1cca6d764960 100644
|
||||
index 57c8dc35dc86efed6e8736e4649b90905a8da54b..89c51a3fd0752ac1586de6840243e93ef5bc080e 100644
|
||||
--- a/src/node_file.cc
|
||||
+++ b/src/node_file.cc
|
||||
@@ -3056,42 +3056,6 @@ static void GetFormatOfExtensionlessFile(
|
||||
@@ -3066,42 +3066,6 @@ static void GetFormatOfExtensionlessFile(
|
||||
return args.GetReturnValue().Set(EXTENSIONLESS_FORMAT_JAVASCRIPT);
|
||||
}
|
||||
|
||||
@@ -70,7 +70,7 @@ index 75be21c9e8b413f522240a906da06d26c44d5b71..e94c2b5f2cf7cac413cd5cb782fa1cca
|
||||
static void CpSyncCheckPaths(const FunctionCallbackInfo<Value>& args) {
|
||||
Environment* env = Environment::GetCurrent(args);
|
||||
Isolate* isolate = env->isolate();
|
||||
@@ -3104,7 +3068,7 @@ static void CpSyncCheckPaths(const FunctionCallbackInfo<Value>& args) {
|
||||
@@ -3114,7 +3078,7 @@ static void CpSyncCheckPaths(const FunctionCallbackInfo<Value>& args) {
|
||||
THROW_IF_INSUFFICIENT_PERMISSIONS(
|
||||
env, permission::PermissionScope::kFileSystemRead, src.ToStringView());
|
||||
|
||||
@@ -79,7 +79,7 @@ index 75be21c9e8b413f522240a906da06d26c44d5b71..e94c2b5f2cf7cac413cd5cb782fa1cca
|
||||
|
||||
BufferValue dest(isolate, args[1]);
|
||||
CHECK_NOT_NULL(*dest);
|
||||
@@ -3112,7 +3076,7 @@ static void CpSyncCheckPaths(const FunctionCallbackInfo<Value>& args) {
|
||||
@@ -3122,7 +3086,7 @@ static void CpSyncCheckPaths(const FunctionCallbackInfo<Value>& args) {
|
||||
THROW_IF_INSUFFICIENT_PERMISSIONS(
|
||||
env, permission::PermissionScope::kFileSystemWrite, dest.ToStringView());
|
||||
|
||||
@@ -88,7 +88,7 @@ index 75be21c9e8b413f522240a906da06d26c44d5b71..e94c2b5f2cf7cac413cd5cb782fa1cca
|
||||
bool dereference = args[2]->IsTrue();
|
||||
bool recursive = args[3]->IsTrue();
|
||||
|
||||
@@ -3141,8 +3105,8 @@ static void CpSyncCheckPaths(const FunctionCallbackInfo<Value>& args) {
|
||||
@@ -3151,8 +3115,8 @@ static void CpSyncCheckPaths(const FunctionCallbackInfo<Value>& args) {
|
||||
(src_status.type() == std::filesystem::file_type::directory) ||
|
||||
(dereference && src_status.type() == std::filesystem::file_type::symlink);
|
||||
|
||||
@@ -99,7 +99,7 @@ index 75be21c9e8b413f522240a906da06d26c44d5b71..e94c2b5f2cf7cac413cd5cb782fa1cca
|
||||
|
||||
if (!error_code) {
|
||||
// Check if src and dest are identical.
|
||||
@@ -3237,7 +3201,7 @@ static bool CopyUtimes(const std::filesystem::path& src,
|
||||
@@ -3247,7 +3211,7 @@ static bool CopyUtimes(const std::filesystem::path& src,
|
||||
uv_fs_t req;
|
||||
auto cleanup = OnScopeLeave([&req]() { uv_fs_req_cleanup(&req); });
|
||||
|
||||
@@ -108,7 +108,7 @@ index 75be21c9e8b413f522240a906da06d26c44d5b71..e94c2b5f2cf7cac413cd5cb782fa1cca
|
||||
int result = uv_fs_stat(nullptr, &req, src_path_str.c_str(), nullptr);
|
||||
if (is_uv_error(result)) {
|
||||
env->ThrowUVException(result, "stat", nullptr, src_path_str.c_str());
|
||||
@@ -3248,7 +3212,7 @@ static bool CopyUtimes(const std::filesystem::path& src,
|
||||
@@ -3258,7 +3222,7 @@ static bool CopyUtimes(const std::filesystem::path& src,
|
||||
const double source_atime = s->st_atim.tv_sec + s->st_atim.tv_nsec / 1e9;
|
||||
const double source_mtime = s->st_mtim.tv_sec + s->st_mtim.tv_nsec / 1e9;
|
||||
|
||||
@@ -117,7 +117,7 @@ index 75be21c9e8b413f522240a906da06d26c44d5b71..e94c2b5f2cf7cac413cd5cb782fa1cca
|
||||
int utime_result = uv_fs_utime(nullptr,
|
||||
&req,
|
||||
dest_file_path_str.c_str(),
|
||||
@@ -3383,7 +3347,7 @@ static void CpSyncCopyDir(const FunctionCallbackInfo<Value>& args) {
|
||||
@@ -3393,7 +3357,7 @@ static void CpSyncCopyDir(const FunctionCallbackInfo<Value>& args) {
|
||||
std::error_code error;
|
||||
for (auto dir_entry : std::filesystem::directory_iterator(src)) {
|
||||
auto dest_file_path = dest / dir_entry.path().filename();
|
||||
@@ -126,7 +126,7 @@ index 75be21c9e8b413f522240a906da06d26c44d5b71..e94c2b5f2cf7cac413cd5cb782fa1cca
|
||||
|
||||
if (dir_entry.is_symlink()) {
|
||||
if (verbatim_symlinks) {
|
||||
@@ -3446,7 +3410,7 @@ static void CpSyncCopyDir(const FunctionCallbackInfo<Value>& args) {
|
||||
@@ -3452,7 +3416,7 @@ static void CpSyncCopyDir(const FunctionCallbackInfo<Value>& args) {
|
||||
}
|
||||
} else if (std::filesystem::is_regular_file(dest_file_path)) {
|
||||
if (!dereference || (!force && error_on_exist)) {
|
||||
|
||||
@@ -132,7 +132,7 @@ index f616223cfb0f6e10f7cf57ada9704316bde2797e..eb6dad44a49d997097c8fb5009eeb60a
|
||||
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
|
||||
index 70fdb52de7b3394df52d327cb485b7c615f8be2d..2fdada446c5d1ffa460f483a3360aeca658d9eef 100644
|
||||
--- a/src/node_buffer.cc
|
||||
+++ b/src/node_buffer.cc
|
||||
@@ -1412,7 +1412,7 @@ inline size_t CheckNumberToSize(Local<Value> number) {
|
||||
|
||||
@@ -1,33 +0,0 @@
|
||||
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) => {
|
||||
@@ -7,7 +7,7 @@ Instead of disabling the tests, flag them as flaky so they still run
|
||||
but don't cause CI failures on flakes.
|
||||
|
||||
diff --git a/test/parallel/parallel.status b/test/parallel/parallel.status
|
||||
index 9822dc622ebfc2d1a31539474b78e03e64426195..045a415f7b9f461bd9b2c97d42051f2580b7df1a 100644
|
||||
index 0d3ed11813f0df93374a1f683add4c621ee8d0c8..c6e7866405ced71aaa2a884addf493f7366fd377 100644
|
||||
--- a/test/parallel/parallel.status
|
||||
+++ b/test/parallel/parallel.status
|
||||
@@ -5,6 +5,16 @@ prefix parallel
|
||||
@@ -28,7 +28,7 @@ index 9822dc622ebfc2d1a31539474b78e03e64426195..045a415f7b9f461bd9b2c97d42051f25
|
||||
test-net-write-fully-async-hex-string: PASS, FLAKY
|
||||
# https://github.com/nodejs/node/issues/52273
|
||||
diff --git a/test/sequential/sequential.status b/test/sequential/sequential.status
|
||||
index f6c9c77379930a8234cd4c5f933c261d6bd1a238..28d5378e4051b78e9a7ff81886c3382e92a5da2e 100644
|
||||
index 33d1109b015ba1abcd52eb6400afff32b82afb3c..6e088c2273d4b034dc458608505cabe8aa304ea1 100644
|
||||
--- a/test/sequential/sequential.status
|
||||
+++ b/test/sequential/sequential.status
|
||||
@@ -7,6 +7,18 @@ prefix sequential
|
||||
|
||||
@@ -1 +1,3 @@
|
||||
graphite_add_insertstatus_koutoforderrecording.patch
|
||||
cherry-pick-03d405099043.patch
|
||||
cherry-pick-7911bee5d90e.patch
|
||||
|
||||
166
patches/skia/cherry-pick-03d405099043.patch
Normal file
166
patches/skia/cherry-pick-03d405099043.patch
Normal file
@@ -0,0 +1,166 @@
|
||||
From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001
|
||||
From: Michael Ludwig <michaelludwig@google.com>
|
||||
Date: Thu, 19 Feb 2026 16:29:16 -0500
|
||||
Subject: [ganesh] Guard verb counts in tessellation accumulation against
|
||||
overflow
|
||||
|
||||
Rejects adding a path if the total verb count would overflow.
|
||||
Rejects merging ops if their total verb counts would overflow.
|
||||
Clamps the min allocation size in the GrVertexChunkArray to prevent
|
||||
overflow.
|
||||
Clamps the preallocation verb count parameter to avoid overflow in their
|
||||
intermediate calculations.
|
||||
|
||||
Bug: b/484983991
|
||||
Change-Id: I32359cf10a996baf46b023a6cb8c608834942e0b
|
||||
Reviewed-on: https://skia-review.googlesource.com/c/skia/+/1169977
|
||||
Commit-Queue: Michael Ludwig <michaelludwig@google.com>
|
||||
Reviewed-by: Thomas Smith <thomsmit@google.com>
|
||||
|
||||
diff --git a/src/gpu/ganesh/GrVertexChunkArray.cpp b/src/gpu/ganesh/GrVertexChunkArray.cpp
|
||||
index b920c81df0c1c8dd76672ba84989b72322833847..ccfd8ef10f101072a8023584f7e0db8fc3195685 100644
|
||||
--- a/src/gpu/ganesh/GrVertexChunkArray.cpp
|
||||
+++ b/src/gpu/ganesh/GrVertexChunkArray.cpp
|
||||
@@ -10,6 +10,7 @@
|
||||
#include "src/gpu/ganesh/GrMeshDrawTarget.h"
|
||||
|
||||
#include <algorithm>
|
||||
+#include <limits>
|
||||
|
||||
GrVertexChunkBuilder::~GrVertexChunkBuilder() {
|
||||
if (!fChunks->empty()) {
|
||||
@@ -37,6 +38,12 @@ bool GrVertexChunkBuilder::allocChunk(int minCount) {
|
||||
fCurrChunkVertexCapacity = 0;
|
||||
return false;
|
||||
}
|
||||
- fMinVerticesPerChunk *= 2;
|
||||
+
|
||||
+ int maxVerticesPerChunk = std::numeric_limits<int>::max() / fStride;
|
||||
+ if (maxVerticesPerChunk / 2 > fMinVerticesPerChunk) {
|
||||
+ fMinVerticesPerChunk *= 2;
|
||||
+ } else {
|
||||
+ fMinVerticesPerChunk = maxVerticesPerChunk;
|
||||
+ }
|
||||
return true;
|
||||
}
|
||||
diff --git a/src/gpu/ganesh/ops/AtlasRenderTask.cpp b/src/gpu/ganesh/ops/AtlasRenderTask.cpp
|
||||
index 5f05079cfa740ecf140ed7c43d6e04102893a21a..13b2ff4a85d091427c8a95344dfa788cf0ecccbe 100644
|
||||
--- a/src/gpu/ganesh/ops/AtlasRenderTask.cpp
|
||||
+++ b/src/gpu/ganesh/ops/AtlasRenderTask.cpp
|
||||
@@ -54,6 +54,17 @@ bool AtlasRenderTask::addPath(const SkMatrix& viewMatrix, const SkPath& path,
|
||||
SkASSERT(this->isEmpty());
|
||||
SkASSERT(!fDynamicAtlas->isInstantiated()); // Paths can't be added after instantiate().
|
||||
|
||||
+ // Check for room in the list first and return false if prior draws need to be flushed first.
|
||||
+ if (GrFillRuleForSkPath(path) == GrFillRule::kNonzero) {
|
||||
+ if (!fWindingPathList.canAdd(path)) {
|
||||
+ return false;
|
||||
+ }
|
||||
+ } else {
|
||||
+ if (!fEvenOddPathList.canAdd(path)) {
|
||||
+ return false;
|
||||
+ }
|
||||
+ }
|
||||
+
|
||||
if (!fDynamicAtlas->addRect(widthInAtlas, heightInAtlas, locationInAtlas)) {
|
||||
return false;
|
||||
}
|
||||
diff --git a/src/gpu/ganesh/ops/AtlasRenderTask.h b/src/gpu/ganesh/ops/AtlasRenderTask.h
|
||||
index c44b426db504f2e108f131fa42bf6a5bd31f7a78..de056f1961ba6cbced6b2ea9ffe630e63785da71 100644
|
||||
--- a/src/gpu/ganesh/ops/AtlasRenderTask.h
|
||||
+++ b/src/gpu/ganesh/ops/AtlasRenderTask.h
|
||||
@@ -22,6 +22,7 @@
|
||||
#include "src/gpu/ganesh/ops/OpsTask.h"
|
||||
#include "src/gpu/ganesh/tessellate/PathTessellator.h"
|
||||
|
||||
+#include <limits>
|
||||
#include <memory>
|
||||
#include <utility>
|
||||
|
||||
@@ -89,6 +90,7 @@ private:
|
||||
class AtlasPathList : SkNoncopyable {
|
||||
public:
|
||||
void add(PathDrawAllocator* alloc, const SkMatrix& pathMatrix, const SkPath& path) {
|
||||
+ SkASSERT(this->canAdd(path));
|
||||
fPathDrawList = &alloc->emplace_back(pathMatrix, path, SK_PMColor4fTRANSPARENT,
|
||||
fPathDrawList);
|
||||
if (path.isInverseFillType()) {
|
||||
@@ -98,6 +100,12 @@ private:
|
||||
fTotalCombinedPathVerbCnt += path.countVerbs();
|
||||
++fPathCount;
|
||||
}
|
||||
+
|
||||
+ bool canAdd(const SkPath& path) const {
|
||||
+ // Return true so long as we won't overflow the total verb count
|
||||
+ return std::numeric_limits<int>::max() - fTotalCombinedPathVerbCnt >= path.countVerbs();
|
||||
+ }
|
||||
+
|
||||
const PathDrawList* pathDrawList() const { return fPathDrawList; }
|
||||
int totalCombinedPathVerbCnt() const { return fTotalCombinedPathVerbCnt; }
|
||||
int pathCount() const { return fPathCount; }
|
||||
diff --git a/src/gpu/ganesh/ops/PathTessellateOp.cpp b/src/gpu/ganesh/ops/PathTessellateOp.cpp
|
||||
index 3bc370f046751a155b11085188ca152853c52263..f879a2ec1dd28e7ec0438d99226f28612eb8b9ec 100644
|
||||
--- a/src/gpu/ganesh/ops/PathTessellateOp.cpp
|
||||
+++ b/src/gpu/ganesh/ops/PathTessellateOp.cpp
|
||||
@@ -5,6 +5,7 @@
|
||||
* found in the LICENSE file.
|
||||
*/
|
||||
#include "src/gpu/ganesh/ops/PathTessellateOp.h"
|
||||
+#include <limits>
|
||||
|
||||
#include "include/core/SkColor.h"
|
||||
#include "include/gpu/ganesh/GrRecordingContext.h"
|
||||
@@ -53,10 +54,13 @@ GrDrawOp::CombineResult PathTessellateOp::onCombineIfPossible(GrOp* grOp,
|
||||
SkArenaAlloc*,
|
||||
const GrCaps&) {
|
||||
auto* op = grOp->cast<PathTessellateOp>();
|
||||
+ bool verbCountOverflow = std::numeric_limits<int>::max() - fTotalCombinedPathVerbCnt <
|
||||
+ op->fTotalCombinedPathVerbCnt;
|
||||
bool canMerge = fAAType == op->fAAType &&
|
||||
fStencil == op->fStencil &&
|
||||
fProcessors == op->fProcessors &&
|
||||
- fShaderMatrix == op->fShaderMatrix;
|
||||
+ fShaderMatrix == op->fShaderMatrix &&
|
||||
+ !verbCountOverflow;
|
||||
if (canMerge) {
|
||||
fTotalCombinedPathVerbCnt += op->fTotalCombinedPathVerbCnt;
|
||||
fPatchAttribs |= op->fPatchAttribs;
|
||||
diff --git a/src/gpu/tessellate/FixedCountBufferUtils.h b/src/gpu/tessellate/FixedCountBufferUtils.h
|
||||
index f2ab0f427c1fa08ac3a11c5a285f51243cb7ad27..055f6a026656f69bf6ef5feeba21695a99e7f9f2 100644
|
||||
--- a/src/gpu/tessellate/FixedCountBufferUtils.h
|
||||
+++ b/src/gpu/tessellate/FixedCountBufferUtils.h
|
||||
@@ -14,6 +14,7 @@
|
||||
#include <algorithm>
|
||||
#include <cstddef>
|
||||
#include <cstdint>
|
||||
+#include <limits>
|
||||
|
||||
namespace skgpu { struct VertexWriter; }
|
||||
|
||||
@@ -44,6 +45,8 @@ public:
|
||||
// Over-allocate enough curves for 1 in 4 to chop. Every chop introduces 2 new patches:
|
||||
// another curve patch and a triangle patch that glues the two chops together,
|
||||
// i.e. + 2 * ((count + 3) / 4) == (count + 3) / 2
|
||||
+ constexpr int kMaxVerbCount = std::numeric_limits<int>::max() >> 2;
|
||||
+ totalCombinedPathVerbCnt = std::min(kMaxVerbCount, totalCombinedPathVerbCnt);
|
||||
return totalCombinedPathVerbCnt + (totalCombinedPathVerbCnt + 3) / 2;
|
||||
}
|
||||
|
||||
@@ -88,6 +91,8 @@ public:
|
||||
|
||||
static constexpr int PreallocCount(int totalCombinedPathVerbCnt) {
|
||||
// Over-allocate enough wedges for 1 in 4 to chop, i.e., ceil(maxWedges * 5/4)
|
||||
+ constexpr int kMaxVerbCount = std::numeric_limits<int>::max() >> 3;
|
||||
+ totalCombinedPathVerbCnt = std::min(kMaxVerbCount, totalCombinedPathVerbCnt);
|
||||
return (totalCombinedPathVerbCnt * 5 + 3) / 4;
|
||||
}
|
||||
|
||||
@@ -140,6 +145,8 @@ public:
|
||||
// Over-allocate enough patches for each stroke to chop once, and for 8 extra caps. Since
|
||||
// we have to chop at inflections, points of 180 degree rotation, and anywhere a stroke
|
||||
// requires too many parametric segments, many strokes will end up getting choppped.
|
||||
+ constexpr int kMaxVerbCount = std::numeric_limits<int>::max() >> 2;
|
||||
+ totalCombinedPathVerbCnt = std::min(kMaxVerbCount, totalCombinedPathVerbCnt);
|
||||
return (totalCombinedPathVerbCnt * 2) + 8/* caps */;
|
||||
}
|
||||
|
||||
544
patches/skia/cherry-pick-7911bee5d90e.patch
Normal file
544
patches/skia/cherry-pick-7911bee5d90e.patch
Normal file
@@ -0,0 +1,544 @@
|
||||
From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001
|
||||
From: Greg Daniel <egdaniel@google.com>
|
||||
Date: Wed, 11 Mar 2026 15:29:58 -0400
|
||||
Subject: Make sure we are getting the correct atlas for glyph mask format.
|
||||
|
||||
Bug: b/491421267
|
||||
Change-Id: I4eacd46599eca2df8c10a3fc894b9ce890fae1e2
|
||||
Reviewed-on: https://skia-review.googlesource.com/c/skia/+/1184076
|
||||
Commit-Queue: Greg Daniel <egdaniel@google.com>
|
||||
Reviewed-by: Michael Ludwig <michaelludwig@google.com>
|
||||
(cherry picked from commit 0cab3e4ee34b3bca6ba7df676639d73ffe4b2135)
|
||||
Reviewed-on: https://skia-review.googlesource.com/c/skia/+/1184917
|
||||
|
||||
diff --git a/bench/GlyphQuadFillBench.cpp b/bench/GlyphQuadFillBench.cpp
|
||||
index d5de90c5afd20e85662443c2019521d71bef6fc4..edad3c19f1826e4aecdba74f5c1f04a4d3f9ebf6 100644
|
||||
--- a/bench/GlyphQuadFillBench.cpp
|
||||
+++ b/bench/GlyphQuadFillBench.cpp
|
||||
@@ -68,7 +68,7 @@ class DirectMaskGlyphVertexFillBenchmark : public Benchmark {
|
||||
const sktext::gpu::AtlasSubRun* subRun =
|
||||
sktext::gpu::TextBlobTools::FirstSubRun(fBlob.get());
|
||||
SkASSERT_RELEASE(subRun);
|
||||
- subRun->testingOnly_packedGlyphIDToGlyph(&fCache);
|
||||
+ subRun->testingOnly_packedGlyphIDToGlyph(&fCache, subRun->maskFormat());
|
||||
fVertices.reset(new char[subRun->vertexStride(drawMatrix) * subRun->glyphCount() * 4]);
|
||||
}
|
||||
|
||||
diff --git a/gn/tests.gni b/gn/tests.gni
|
||||
index 6fc06d23db5357a05a8be5f3e6040be257a34fdf..d3cfbdafdefd766bb910c33007bd7e0bf85c5ff4 100644
|
||||
--- a/gn/tests.gni
|
||||
+++ b/gn/tests.gni
|
||||
@@ -485,6 +485,12 @@ pathops_tests_sources = [
|
||||
]
|
||||
|
||||
ganesh_tests_sources = [
|
||||
+ "$_tests/AdvancedBlendTest.cpp",
|
||||
+ "$_tests/ApplyGammaTest.cpp",
|
||||
+ "$_tests/AtlasOobTest.cpp",
|
||||
+ "$_tests/BackendAllocationTest.cpp",
|
||||
+ "$_tests/BackendSurfaceMutableStateTest.cpp",
|
||||
+ "$_tests/BlendTest.cpp",
|
||||
"$_tests/BulkRectTest.cpp",
|
||||
"$_tests/ClearTest.cpp",
|
||||
"$_tests/DMSAATest.cpp",
|
||||
diff --git a/src/gpu/ganesh/text/GrAtlasManager.cpp b/src/gpu/ganesh/text/GrAtlasManager.cpp
|
||||
index 403bfe274e56293bfe2382b02525ae742ba541a7..1e7d9aa0ce14f19e09d79544730c6aa922ae37d6 100644
|
||||
--- a/src/gpu/ganesh/text/GrAtlasManager.cpp
|
||||
+++ b/src/gpu/ganesh/text/GrAtlasManager.cpp
|
||||
@@ -178,8 +178,7 @@ GrDrawOpAtlas::ErrorCode GrAtlasManager::addGlyphToAtlas(const SkGlyph& skGlyph,
|
||||
}
|
||||
SkASSERT(glyph != nullptr);
|
||||
|
||||
- MaskFormat glyphFormat = Glyph::FormatFromSkGlyph(skGlyph.maskFormat());
|
||||
- MaskFormat expectedMaskFormat = this->resolveMaskFormat(glyphFormat);
|
||||
+ MaskFormat expectedMaskFormat = this->resolveMaskFormat(glyph->fGlyphEntryKey.fFormat);
|
||||
int bytesPerPixel = MaskFormatBytesPerPixel(expectedMaskFormat);
|
||||
|
||||
int padding;
|
||||
@@ -299,7 +298,7 @@ std::tuple<bool, int> GlyphVector::regenerateAtlasForGanesh(
|
||||
|
||||
uint64_t currentAtlasGen = atlasManager->atlasGeneration(maskFormat);
|
||||
|
||||
- this->packedGlyphIDToGlyph(target->strikeCache());
|
||||
+ this->packedGlyphIDToGlyph(target->strikeCache(), maskFormat);
|
||||
|
||||
if (fAtlasGeneration != currentAtlasGen) {
|
||||
// Calculate the texture coordinates for the vertexes during first use (fAtlasGeneration
|
||||
@@ -316,9 +315,10 @@ std::tuple<bool, int> GlyphVector::regenerateAtlasForGanesh(
|
||||
for (const Variant& variant : glyphs) {
|
||||
Glyph* gpuGlyph = variant.glyph;
|
||||
SkASSERT(gpuGlyph != nullptr);
|
||||
-
|
||||
+ SkASSERT(gpuGlyph->fGlyphEntryKey.fFormat == maskFormat);
|
||||
if (!atlasManager->hasGlyph(maskFormat, gpuGlyph)) {
|
||||
- const SkGlyph& skGlyph = *metricsAndImages.glyph(gpuGlyph->fPackedID);
|
||||
+ const SkGlyph& skGlyph =
|
||||
+ *metricsAndImages.glyph(gpuGlyph->fGlyphEntryKey.fPackedID);
|
||||
auto code = atlasManager->addGlyphToAtlas(
|
||||
skGlyph, gpuGlyph, srcPadding, target->resourceProvider(), uploadTarget);
|
||||
if (code != GrDrawOpAtlas::ErrorCode::kSucceeded) {
|
||||
diff --git a/src/gpu/graphite/Device.cpp b/src/gpu/graphite/Device.cpp
|
||||
index 1bc1f0d51712df81118a67bb22f5d28a6ead8606..e2b8e40b80d44ccfff9bdbd14f657fbbbfe3a3d9 100644
|
||||
--- a/src/gpu/graphite/Device.cpp
|
||||
+++ b/src/gpu/graphite/Device.cpp
|
||||
@@ -1325,6 +1325,7 @@ void Device::drawAtlasSubRun(const sktext::gpu::AtlasSubRun* subRun,
|
||||
int padding) {
|
||||
return glyphs->regenerateAtlasForGraphite(begin, end, maskFormat, padding, fRecorder);
|
||||
};
|
||||
+
|
||||
for (int subRunCursor = 0; subRunCursor < subRunEnd;) {
|
||||
// For the remainder of the run, add any atlas uploads to the Recorder's TextAtlasManager
|
||||
auto[ok, glyphsRegenerated] = subRun->regenerateAtlas(subRunCursor, subRunEnd,
|
||||
diff --git a/src/gpu/graphite/text/TextAtlasManager.cpp b/src/gpu/graphite/text/TextAtlasManager.cpp
|
||||
index 6602a76c150bff077666fb91b990d3e45d528ce2..cbb51a66846922995912c3159afba879a2487313 100644
|
||||
--- a/src/gpu/graphite/text/TextAtlasManager.cpp
|
||||
+++ b/src/gpu/graphite/text/TextAtlasManager.cpp
|
||||
@@ -207,8 +207,7 @@ DrawAtlas::ErrorCode TextAtlasManager::addGlyphToAtlas(const SkGlyph& skGlyph,
|
||||
}
|
||||
SkASSERT(glyph != nullptr);
|
||||
|
||||
- MaskFormat glyphFormat = Glyph::FormatFromSkGlyph(skGlyph.maskFormat());
|
||||
- MaskFormat expectedMaskFormat = this->resolveMaskFormat(glyphFormat);
|
||||
+ MaskFormat expectedMaskFormat = this->resolveMaskFormat(glyph->fGlyphEntryKey.fFormat);
|
||||
int bytesPerPixel = MaskFormatBytesPerPixel(expectedMaskFormat);
|
||||
|
||||
int padding;
|
||||
@@ -359,7 +358,7 @@ std::tuple<bool, int> GlyphVector::regenerateAtlasForGraphite(int begin,
|
||||
|
||||
uint64_t currentAtlasGen = atlasManager->atlasGeneration(maskFormat);
|
||||
|
||||
- this->packedGlyphIDToGlyph(recorder->priv().strikeCache());
|
||||
+ this->packedGlyphIDToGlyph(recorder->priv().strikeCache(), maskFormat);
|
||||
|
||||
if (fAtlasGeneration != currentAtlasGen) {
|
||||
// Calculate the texture coordinates for the vertexes during first use (fAtlasGeneration
|
||||
@@ -375,9 +374,10 @@ std::tuple<bool, int> GlyphVector::regenerateAtlasForGraphite(int begin,
|
||||
for (const Variant& variant : glyphs) {
|
||||
Glyph* gpuGlyph = variant.glyph;
|
||||
SkASSERT(gpuGlyph != nullptr);
|
||||
-
|
||||
+ SkASSERT(gpuGlyph->fGlyphEntryKey.fFormat == maskFormat);
|
||||
if (!atlasManager->hasGlyph(maskFormat, gpuGlyph)) {
|
||||
- const SkGlyph& skGlyph = *metricsAndImages.glyph(gpuGlyph->fPackedID);
|
||||
+ const SkGlyph& skGlyph =
|
||||
+ *metricsAndImages.glyph(gpuGlyph->fGlyphEntryKey.fPackedID);
|
||||
auto code = atlasManager->addGlyphToAtlas(skGlyph, gpuGlyph, srcPadding);
|
||||
if (code != DrawAtlas::ErrorCode::kSucceeded) {
|
||||
success = code != DrawAtlas::ErrorCode::kError;
|
||||
diff --git a/src/text/gpu/Glyph.h b/src/text/gpu/Glyph.h
|
||||
index 2c6f828ca6f9941b1dc8d73d428370b11d1d52bd..7942006a563bcab925ea2129ab6f6beea438a4c8 100644
|
||||
--- a/src/text/gpu/Glyph.h
|
||||
+++ b/src/text/gpu/Glyph.h
|
||||
@@ -14,6 +14,25 @@
|
||||
|
||||
namespace sktext::gpu {
|
||||
|
||||
+struct GlyphEntryKey {
|
||||
+ explicit GlyphEntryKey(SkPackedGlyphID id, skgpu::MaskFormat format)
|
||||
+ : fPackedID(id), fFormat(format) {}
|
||||
+
|
||||
+ const SkPackedGlyphID fPackedID;
|
||||
+ skgpu::MaskFormat fFormat;
|
||||
+
|
||||
+ bool operator==(const GlyphEntryKey& that) const {
|
||||
+ return fPackedID == that.fPackedID && fFormat == that.fFormat;
|
||||
+ }
|
||||
+ bool operator!=(const GlyphEntryKey& that) const {
|
||||
+ return !(*this == that);
|
||||
+ }
|
||||
+
|
||||
+ uint32_t hash() const {
|
||||
+ return fPackedID.hash();
|
||||
+ }
|
||||
+};
|
||||
+
|
||||
class Glyph {
|
||||
public:
|
||||
static skgpu::MaskFormat FormatFromSkGlyph(SkMask::Format format) {
|
||||
@@ -34,10 +53,11 @@ public:
|
||||
SkUNREACHABLE;
|
||||
}
|
||||
|
||||
- Glyph(SkPackedGlyphID packedGlyphID) : fPackedID(packedGlyphID) {}
|
||||
+ explicit Glyph(SkPackedGlyphID packedGlyphID, skgpu::MaskFormat format)
|
||||
+ : fGlyphEntryKey(packedGlyphID, format) {}
|
||||
|
||||
- const SkPackedGlyphID fPackedID;
|
||||
- skgpu::AtlasLocator fAtlasLocator;
|
||||
+ const GlyphEntryKey fGlyphEntryKey;
|
||||
+ skgpu::AtlasLocator fAtlasLocator;
|
||||
};
|
||||
|
||||
} // namespace sktext::gpu
|
||||
diff --git a/src/text/gpu/GlyphVector.cpp b/src/text/gpu/GlyphVector.cpp
|
||||
index 2a8e85f926aa547169f4b85372e9d3fb99816956..7bec7a0b77d8560d5ef978281edd7df6c45cb56f 100644
|
||||
--- a/src/text/gpu/GlyphVector.cpp
|
||||
+++ b/src/text/gpu/GlyphVector.cpp
|
||||
@@ -99,14 +99,14 @@ SkSpan<const Glyph*> GlyphVector::glyphs() const {
|
||||
|
||||
// packedGlyphIDToGlyph must be run in single-threaded mode.
|
||||
// If fSkStrike is not sk_sp<SkStrike> then the conversion to Glyph* has not happened.
|
||||
-void GlyphVector::packedGlyphIDToGlyph(StrikeCache* cache) {
|
||||
+void GlyphVector::packedGlyphIDToGlyph(StrikeCache* cache, MaskFormat maskFormat) {
|
||||
if (fTextStrike == nullptr) {
|
||||
SkStrike* strike = fStrikePromise.strike();
|
||||
fTextStrike = cache->findOrCreateStrike(strike->strikeSpec());
|
||||
|
||||
// Get all the atlas locations for each glyph.
|
||||
for (Variant& variant : fGlyphs) {
|
||||
- variant.glyph = fTextStrike->getGlyph(variant.packedGlyphID);
|
||||
+ variant.glyph = fTextStrike->getGlyph(variant.packedGlyphID, maskFormat);
|
||||
}
|
||||
|
||||
// This must be pinned for the Atlas filling to work.
|
||||
diff --git a/src/text/gpu/GlyphVector.h b/src/text/gpu/GlyphVector.h
|
||||
index 42b92a93f70cc6d86d0a87dd07c2244e0da1281c..1eec6327d38fb4472b027faae68eecb9ad7509d7 100644
|
||||
--- a/src/text/gpu/GlyphVector.h
|
||||
+++ b/src/text/gpu/GlyphVector.h
|
||||
@@ -68,7 +68,7 @@ public:
|
||||
// the sub runs.
|
||||
int unflattenSize() const { return GlyphVectorSize(fGlyphs.size()); }
|
||||
|
||||
- void packedGlyphIDToGlyph(StrikeCache* cache);
|
||||
+ void packedGlyphIDToGlyph(StrikeCache* cache, skgpu::MaskFormat);
|
||||
|
||||
static size_t GlyphVectorSize(size_t count) {
|
||||
return sizeof(Variant) * count;
|
||||
diff --git a/src/text/gpu/StrikeCache.cpp b/src/text/gpu/StrikeCache.cpp
|
||||
index add3127c92fdbfe56d6b56209a2235ce5a9f5acb..19df48329fd500f8682669ec96eb883b58243fdd 100644
|
||||
--- a/src/text/gpu/StrikeCache.cpp
|
||||
+++ b/src/text/gpu/StrikeCache.cpp
|
||||
@@ -207,10 +207,11 @@ TextStrike::TextStrike(StrikeCache* strikeCache, const SkStrikeSpec& strikeSpec)
|
||||
: fStrikeCache(strikeCache)
|
||||
, fStrikeSpec{strikeSpec} {}
|
||||
|
||||
-Glyph* TextStrike::getGlyph(SkPackedGlyphID packedGlyphID) {
|
||||
- Glyph* glyph = fCache.findOrNull(packedGlyphID);
|
||||
+Glyph* TextStrike::getGlyph(SkPackedGlyphID packedGlyphID, skgpu::MaskFormat format) {
|
||||
+ GlyphEntryKey localKey(packedGlyphID, format);
|
||||
+ Glyph* glyph = fCache.findOrNull(localKey);
|
||||
if (glyph == nullptr) {
|
||||
- glyph = fAlloc.make<Glyph>(packedGlyphID);
|
||||
+ glyph = fAlloc.make<Glyph>(packedGlyphID, format);
|
||||
fCache.set(glyph);
|
||||
fMemoryUsed += sizeof(Glyph);
|
||||
if (!fRemoved) {
|
||||
@@ -220,11 +221,11 @@ Glyph* TextStrike::getGlyph(SkPackedGlyphID packedGlyphID) {
|
||||
return glyph;
|
||||
}
|
||||
|
||||
-const SkPackedGlyphID& TextStrike::HashTraits::GetKey(const Glyph* glyph) {
|
||||
- return glyph->fPackedID;
|
||||
+const GlyphEntryKey& TextStrike::HashTraits::GetKey(const Glyph* glyph) {
|
||||
+ return glyph->fGlyphEntryKey;
|
||||
}
|
||||
|
||||
-uint32_t TextStrike::HashTraits::Hash(SkPackedGlyphID key) {
|
||||
+uint32_t TextStrike::HashTraits::Hash(GlyphEntryKey key) {
|
||||
return key.hash();
|
||||
}
|
||||
|
||||
diff --git a/src/text/gpu/StrikeCache.h b/src/text/gpu/StrikeCache.h
|
||||
index 007c45c6c6feecba3ff031ba3939ad2402e082b9..014afd5286602e3e049d8e48ae328273e599dc41 100644
|
||||
--- a/src/text/gpu/StrikeCache.h
|
||||
+++ b/src/text/gpu/StrikeCache.h
|
||||
@@ -13,6 +13,7 @@
|
||||
#include "src/core/SkDescriptor.h"
|
||||
#include "src/core/SkStrikeSpec.h"
|
||||
#include "src/core/SkTHash.h"
|
||||
+#include "src/gpu/AtlasTypes.h"
|
||||
|
||||
#include <cstddef>
|
||||
#include <cstdint>
|
||||
@@ -32,6 +33,7 @@ struct SkPackedGlyphID;
|
||||
namespace sktext::gpu {
|
||||
|
||||
class Glyph;
|
||||
+struct GlyphEntryKey;
|
||||
class StrikeCache;
|
||||
|
||||
// The TextStrike manages an SkArenaAlloc for Glyphs. The SkStrike is what actually creates
|
||||
@@ -43,7 +45,7 @@ public:
|
||||
TextStrike(StrikeCache* strikeCache,
|
||||
const SkStrikeSpec& strikeSpec);
|
||||
|
||||
- Glyph* getGlyph(SkPackedGlyphID);
|
||||
+ Glyph* getGlyph(SkPackedGlyphID, skgpu::MaskFormat format);
|
||||
const SkStrikeSpec& strikeSpec() const { return fStrikeSpec; }
|
||||
const SkDescriptor& getDescriptor() const { return fStrikeSpec.descriptor(); }
|
||||
|
||||
@@ -54,11 +56,11 @@ private:
|
||||
const SkStrikeSpec fStrikeSpec;
|
||||
|
||||
struct HashTraits {
|
||||
- static const SkPackedGlyphID& GetKey(const Glyph* glyph);
|
||||
- static uint32_t Hash(SkPackedGlyphID key);
|
||||
+ static const GlyphEntryKey& GetKey(const Glyph* glyph);
|
||||
+ static uint32_t Hash(GlyphEntryKey key);
|
||||
};
|
||||
// Map SkPackedGlyphID -> Glyph*.
|
||||
- skia_private::THashTable<Glyph*, SkPackedGlyphID, HashTraits> fCache;
|
||||
+ skia_private::THashTable<Glyph*, GlyphEntryKey, HashTraits> fCache;
|
||||
|
||||
// Store for the glyph information.
|
||||
SkArenaAlloc fAlloc{512};
|
||||
diff --git a/src/text/gpu/SubRunContainer.cpp b/src/text/gpu/SubRunContainer.cpp
|
||||
index 3a061a2012cd99de9ee4b3674f78ae99e0385d6c..a19460c82593c6713c047ab19e71caa27e375a6d 100644
|
||||
--- a/src/text/gpu/SubRunContainer.cpp
|
||||
+++ b/src/text/gpu/SubRunContainer.cpp
|
||||
@@ -651,8 +651,9 @@ public:
|
||||
|
||||
int glyphSrcPadding() const override { return 0; }
|
||||
|
||||
- void testingOnly_packedGlyphIDToGlyph(StrikeCache* cache) const override {
|
||||
- fGlyphs.packedGlyphIDToGlyph(cache);
|
||||
+ void testingOnly_packedGlyphIDToGlyph(StrikeCache* cache,
|
||||
+ skgpu::MaskFormat maskFormat) const override {
|
||||
+ fGlyphs.packedGlyphIDToGlyph(cache, maskFormat);
|
||||
}
|
||||
|
||||
std::tuple<bool, SkRect> deviceRectAndNeedsTransform(
|
||||
@@ -755,8 +756,9 @@ public:
|
||||
|
||||
const AtlasSubRun* testingOnly_atlasSubRun() const override { return this; }
|
||||
|
||||
- void testingOnly_packedGlyphIDToGlyph(StrikeCache *cache) const override {
|
||||
- fGlyphs.packedGlyphIDToGlyph(cache);
|
||||
+ void testingOnly_packedGlyphIDToGlyph(StrikeCache *cache,
|
||||
+ skgpu::MaskFormat maskFormat) const override {
|
||||
+ fGlyphs.packedGlyphIDToGlyph(cache, maskFormat);
|
||||
}
|
||||
|
||||
int glyphSrcPadding() const override { return 1; }
|
||||
@@ -884,8 +886,9 @@ public:
|
||||
|
||||
const AtlasSubRun* testingOnly_atlasSubRun() const override { return this; }
|
||||
|
||||
- void testingOnly_packedGlyphIDToGlyph(StrikeCache *cache) const override {
|
||||
- fGlyphs.packedGlyphIDToGlyph(cache);
|
||||
+ void testingOnly_packedGlyphIDToGlyph(StrikeCache *cache,
|
||||
+ skgpu::MaskFormat maskFormat) const override {
|
||||
+ fGlyphs.packedGlyphIDToGlyph(cache, maskFormat);
|
||||
}
|
||||
|
||||
int glyphSrcPadding() const override { return SK_DistanceFieldInset; }
|
||||
diff --git a/src/text/gpu/SubRunContainer.h b/src/text/gpu/SubRunContainer.h
|
||||
index 2573dbb3964e9ab2cc0e276b60d4ab4f9804f0d9..4d1a3c8c2d55015d3d351d322ef039c45be2a398 100644
|
||||
--- a/src/text/gpu/SubRunContainer.h
|
||||
+++ b/src/text/gpu/SubRunContainer.h
|
||||
@@ -167,7 +167,7 @@ public:
|
||||
|
||||
const VertexFiller& vertexFiller() const { return fVertexFiller; }
|
||||
|
||||
- virtual void testingOnly_packedGlyphIDToGlyph(StrikeCache* cache) const = 0;
|
||||
+ virtual void testingOnly_packedGlyphIDToGlyph(StrikeCache* cache, skgpu::MaskFormat) const = 0;
|
||||
|
||||
protected:
|
||||
const VertexFiller fVertexFiller;
|
||||
diff --git a/tests/AtlasOobTest.cpp b/tests/AtlasOobTest.cpp
|
||||
new file mode 100644
|
||||
index 0000000000000000000000000000000000000000..4e6fb02ee6af6543df285d8112f1a2ced5bd9ac9
|
||||
--- /dev/null
|
||||
+++ b/tests/AtlasOobTest.cpp
|
||||
@@ -0,0 +1,201 @@
|
||||
+/*
|
||||
+ * Copyright 2026 Google LLC
|
||||
+ *
|
||||
+ * Use of this source code is governed by a BSD-style license that can be
|
||||
+ * found in the LICENSE file.
|
||||
+ */
|
||||
+#include "include/core/SkCanvas.h"
|
||||
+#include "include/core/SkGraphics.h"
|
||||
+#include "include/core/SkSerialProcs.h"
|
||||
+#include "include/core/SkSurface.h"
|
||||
+#include "include/private/chromium/SkChromeRemoteGlyphCache.h"
|
||||
+#include "include/private/chromium/Slug.h"
|
||||
+#include "src/core/SkDescriptor.h"
|
||||
+#include "src/core/SkReadBuffer.h"
|
||||
+#include "src/core/SkTypeface_remote.h"
|
||||
+#include "src/core/SkWriteBuffer.h"
|
||||
+#include "src/gpu/AtlasTypes.h"
|
||||
+#include "tests/CtsEnforcement.h"
|
||||
+#include "tests/Test.h"
|
||||
+#include "tools/ToolUtils.h"
|
||||
+
|
||||
+#if defined(SK_GANESH)
|
||||
+#include "include/gpu/ganesh/GrDirectContext.h"
|
||||
+#include "include/gpu/ganesh/SkSurfaceGanesh.h"
|
||||
+#endif
|
||||
+
|
||||
+#if defined(SK_GRAPHITE)
|
||||
+#include "include/gpu/graphite/Context.h"
|
||||
+#include "include/gpu/graphite/Surface.h"
|
||||
+#include "tools/graphite/GraphiteTestContext.h"
|
||||
+#endif // defined(SK_GRAPHITE)
|
||||
+
|
||||
+#include <vector>
|
||||
+#include <cstring>
|
||||
+
|
||||
+namespace {
|
||||
+class FakeDiscardableManager : public SkStrikeClient::DiscardableHandleManager {
|
||||
+public:
|
||||
+ bool deleteHandle(SkDiscardableHandleId) override { return false; }
|
||||
+ void notifyCacheMiss(SkStrikeClient::CacheMissType, int) override {}
|
||||
+ void notifyReadFailure(const ReadFailureData&) override {}
|
||||
+ void assertHandleValid(SkDiscardableHandleId) override {}
|
||||
+};
|
||||
+
|
||||
+unsigned char kStrikeData[] = {
|
||||
+ 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x65, 0x07, 0x00, 0x00, 0x00, 0x64, 0x00, 0x00, 0x00,
|
||||
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x02, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x65,
|
||||
+ 0x00, 0x00, 0x00, 0x65, 0xd8, 0x50, 0xda, 0x99, 0x4c, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00,
|
||||
+ 0x63, 0x65, 0x72, 0x73, 0x38, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x65, 0x00, 0x00, 0x80, 0x41,
|
||||
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
|
||||
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
|
||||
+ 0x00, 0x00, 0x00, 0xff, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0x00, 0x10, 0x00,
|
||||
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
|
||||
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
|
||||
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
|
||||
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
|
||||
+ 0x00, 0x00, 0x00, 0x00, 0x07, 0x00, 0x00, 0x00, 0x61, 0x00, 0x00, 0x00, 0x00, 0x00, 0x20, 0x41,
|
||||
+ 0x00, 0x00, 0x00, 0x00, 0x08, 0x00, 0x08, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00,
|
||||
+ 0x40, 0x00, 0x00, 0x00, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
|
||||
+ 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
|
||||
+ 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
|
||||
+ 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
|
||||
+ 0xff, 0xff, 0xff, 0xff, 0x62, 0x00, 0x00, 0x00, 0x00, 0x00, 0x20, 0x41, 0x00, 0x00, 0x00, 0x00,
|
||||
+ 0x08, 0x00, 0x08, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x40, 0x00, 0x00, 0x00,
|
||||
+ 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
|
||||
+ 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
|
||||
+ 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
|
||||
+ 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
|
||||
+ 0x63, 0x00, 0x00, 0x00, 0x00, 0x00, 0x20, 0x41, 0x00, 0x00, 0x00, 0x00, 0x08, 0x00, 0x08, 0x00,
|
||||
+ 0x00, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x40, 0x00, 0x00, 0x00, 0xff, 0xff, 0xff, 0xff,
|
||||
+ 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
|
||||
+ 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
|
||||
+ 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
|
||||
+ 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0x64, 0x00, 0x00, 0x00,
|
||||
+ 0x00, 0x00, 0x20, 0x41, 0x00, 0x00, 0x00, 0x00, 0x08, 0x00, 0x08, 0x00, 0x00, 0x00, 0x00, 0x00,
|
||||
+ 0x01, 0x00, 0x00, 0x00, 0x40, 0x00, 0x00, 0x00, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
|
||||
+ 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
|
||||
+ 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
|
||||
+ 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
|
||||
+ 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0x65, 0x00, 0x00, 0x00, 0x00, 0x00, 0x20, 0x41,
|
||||
+ 0x00, 0x00, 0x00, 0x00, 0x08, 0x00, 0x08, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00,
|
||||
+ 0x40, 0x00, 0x00, 0x00, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
|
||||
+ 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
|
||||
+ 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
|
||||
+ 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
|
||||
+ 0xff, 0xff, 0xff, 0xff, 0x66, 0x00, 0x00, 0x00, 0x00, 0x00, 0x20, 0x41, 0x00, 0x00, 0x00, 0x00,
|
||||
+ 0x08, 0x00, 0x08, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x40, 0x00, 0x00, 0x00,
|
||||
+ 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
|
||||
+ 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
|
||||
+ 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
|
||||
+ 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
|
||||
+ 0x67, 0x00, 0x00, 0x00, 0x00, 0x00, 0x20, 0x41, 0x00, 0x00, 0x00, 0x00, 0x08, 0x00, 0x08, 0x00,
|
||||
+ 0x00, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x40, 0x00, 0x00, 0x00, 0xff, 0xff, 0xff, 0xff,
|
||||
+ 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
|
||||
+ 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
|
||||
+ 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
|
||||
+ 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0x00, 0x00, 0x00, 0x00,
|
||||
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x65, 0x00, 0x00, 0x00, 0x66, 0x86, 0x07, 0xc2, 0x42,
|
||||
+ 0x4c, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x63, 0x65, 0x72, 0x73, 0x38, 0x00, 0x00, 0x00,
|
||||
+ 0x00, 0x00, 0x00, 0x65, 0x00, 0x00, 0x80, 0x41, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
|
||||
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
|
||||
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xff, 0x00, 0x00, 0x00, 0x00,
|
||||
+ 0x00, 0x00, 0x00, 0x00, 0x03, 0x00, 0x10, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
|
||||
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
|
||||
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
|
||||
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
|
||||
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00,
|
||||
+ 0x99, 0x00, 0x00, 0x00, 0x00, 0x00, 0x20, 0x41, 0x00, 0x00, 0x00, 0x00, 0x04, 0x00, 0x04, 0x00,
|
||||
+ 0x00, 0x00, 0x00, 0x00, 0x03, 0x00, 0x00, 0x00, 0x40, 0x00, 0x00, 0x00, 0xff, 0xff, 0xff, 0xff,
|
||||
+ 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
|
||||
+ 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
|
||||
+ 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
|
||||
+ 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0x00, 0x00, 0x00, 0x00,
|
||||
+ 0x00, 0x00, 0x00, 0x00
|
||||
+};
|
||||
+
|
||||
+unsigned char kDrawSlugOp[] = {
|
||||
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x41, 0x00, 0x00, 0x00, 0x41,
|
||||
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x80, 0x00, 0x00, 0x00, 0x00, 0x00, 0x80, 0x3f,
|
||||
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x80, 0x3f,
|
||||
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x80, 0x3f,
|
||||
+ 0x01, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00,
|
||||
+ 0x00, 0x00, 0x80, 0x3f, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
|
||||
+ 0x00, 0x00, 0x80, 0x3f, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
|
||||
+ 0x00, 0x00, 0x80, 0x3f, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x41,
|
||||
+ 0x00, 0x00, 0x00, 0x41, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
|
||||
+ 0x86, 0x07, 0xc2, 0x42, 0x4c, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x63, 0x65, 0x72, 0x73,
|
||||
+ 0x38, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x65, 0x00, 0x00, 0x80, 0x41, 0x00, 0x00, 0x00, 0x00,
|
||||
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
|
||||
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xff,
|
||||
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x03, 0x00, 0x10, 0x00, 0x01, 0x00, 0x00, 0x00,
|
||||
+ 0x99, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
|
||||
+};
|
||||
+
|
||||
+} // namespace
|
||||
+
|
||||
+// TODO: We expect this test to correctly hit an SkUnreachable and then crash. That does not work
|
||||
+// with our current testing framework because we have no to "expect" a crash. So for now we will
|
||||
+// land this test with only the valid loop enabled, but to test this is working locally, you should
|
||||
+// change the loop to have both iterations.
|
||||
+static void run_atlas_oob_test(skiatest::Reporter* reporter, SkCanvas* canvas) {
|
||||
+ auto discardableManager = sk_make_sp<FakeDiscardableManager>();
|
||||
+ SkStrikeClient client(discardableManager, false);
|
||||
+
|
||||
+ // 1. Prepare Strike Data
|
||||
+ if (!client.readStrikeData(kStrikeData, sizeof(kStrikeData))) {
|
||||
+ REPORTER_ASSERT(reporter, false, "Failed to read initial strike data");
|
||||
+ }
|
||||
+
|
||||
+ // 2. Prepare and Execute DrawSlug ops
|
||||
+ SkPaint paint;
|
||||
+ for (int idx = 0; idx < 1; ++idx) {
|
||||
+// for (int idx = 0; idx < 2; ++idx) {
|
||||
+ if (idx == 0) {
|
||||
+ kDrawSlugOp[0x48] = (unsigned char)skgpu::MaskFormat::kARGB;
|
||||
+ } else if (idx == 1) {
|
||||
+ kDrawSlugOp[0x48] = (unsigned char)skgpu::MaskFormat::kA8;
|
||||
+ }
|
||||
+ kDrawSlugOp[0xd8] = SkMask::kARGB32_Format;
|
||||
+ kDrawSlugOp[0xe0] = 0x99;
|
||||
+
|
||||
+ auto slug = client.deserializeSlugForTest(kDrawSlugOp, sizeof(kDrawSlugOp));
|
||||
+ if (slug) {
|
||||
+ slug->draw(canvas, paint);
|
||||
+ }
|
||||
+ }
|
||||
+
|
||||
+}
|
||||
+
|
||||
+#if defined(SK_GANESH)
|
||||
+DEF_GANESH_TEST_FOR_RENDERING_CONTEXTS(Atlas_Oob_ganesh, reporter, ctxInfo, CtsEnforcement::kNextRelease) {
|
||||
+ auto dContext = ctxInfo.directContext();
|
||||
+ SkImageInfo info = SkImageInfo::MakeN32Premul(1024, 1024);
|
||||
+ auto surface = SkSurfaces::RenderTarget(dContext, skgpu::Budgeted::kNo, info);
|
||||
+ if (!surface) return;
|
||||
+ auto canvas = surface->getCanvas();
|
||||
+
|
||||
+ run_atlas_oob_test(reporter, canvas);
|
||||
+
|
||||
+ dContext->flushAndSubmit();
|
||||
+}
|
||||
+#endif // defined(SK_GANESH)
|
||||
+
|
||||
+#if defined(SK_GRAPHITE)
|
||||
+DEF_GRAPHITE_TEST_FOR_RENDERING_CONTEXTS(Atlas_Oob_graphite, reporter, context, CtsEnforcement::kNextRelease) {
|
||||
+ using namespace skgpu::graphite;
|
||||
+ std::unique_ptr<Recorder> recorder = context->makeRecorder();
|
||||
+ SkImageInfo info = SkImageInfo::MakeN32Premul(1024, 1024);
|
||||
+ auto surface = SkSurfaces::RenderTarget(recorder.get(), info);
|
||||
+ if (!surface) return;
|
||||
+ auto canvas = surface->getCanvas();
|
||||
+
|
||||
+ run_atlas_oob_test(reporter, canvas);
|
||||
+
|
||||
+ std::unique_ptr<Recording> recording = recorder->snap();
|
||||
+ InsertRecordingInfo recordingInfo;
|
||||
+ recordingInfo.fRecording = recording.get();
|
||||
+ context->insertRecording(recordingInfo);
|
||||
+ context->submit();
|
||||
+}
|
||||
+#endif // defined(SK_GRAPHITE)
|
||||
@@ -9,4 +9,4 @@ refactor_use_non-deprecated_nskeyedarchiver_apis.patch
|
||||
chore_turn_off_launchapplicationaturl_deprecation_errors_in_squirrel.patch
|
||||
fix_crash_when_process_to_extract_zip_cannot_be_launched.patch
|
||||
use_uttype_class_instead_of_deprecated_uttypeconformsto.patch
|
||||
fix_clean_up_old_staged_updates_before_downloading_new_update.patch
|
||||
fix_clean_up_orphaned_staged_updates_before_downloading_new_update.patch
|
||||
|
||||
@@ -1,64 +0,0 @@
|
||||
From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001
|
||||
From: Andy Locascio <loc@anthropic.com>
|
||||
Date: Tue, 6 Jan 2026 08:23:03 -0800
|
||||
Subject: fix: clean up old staged updates before downloading new update
|
||||
|
||||
When checkForUpdates() is called while an update is already staged,
|
||||
Squirrel creates a new temporary directory for the download without
|
||||
cleaning up the old one. This can lead to significant disk usage if
|
||||
the app keeps checking for updates without restarting.
|
||||
|
||||
This change adds a force parameter to pruneUpdateDirectories that
|
||||
bypasses the AwaitingRelaunch state check. This is called before
|
||||
creating a new temp directory, ensuring old staged updates are
|
||||
cleaned up when a new download starts.
|
||||
|
||||
diff --git a/Squirrel/SQRLUpdater.m b/Squirrel/SQRLUpdater.m
|
||||
index d156616e81e6f25a3bded30e6216b8fc311f31bc..6cd4346bf43b191147aff819cb93387e71275a46 100644
|
||||
--- a/Squirrel/SQRLUpdater.m
|
||||
+++ b/Squirrel/SQRLUpdater.m
|
||||
@@ -543,11 +543,17 @@ - (RACSignal *)downloadBundleForUpdate:(SQRLUpdate *)update intoDirectory:(NSURL
|
||||
#pragma mark File Management
|
||||
|
||||
- (RACSignal *)uniqueTemporaryDirectoryForUpdate {
|
||||
- return [[[RACSignal
|
||||
+ // Clean up any old staged update directories before creating a new one.
|
||||
+ // This prevents disk usage from growing when checkForUpdates() is called
|
||||
+ // multiple times without the app restarting.
|
||||
+ return [[[[[self
|
||||
+ pruneUpdateDirectoriesWithForce:YES]
|
||||
+ ignoreValues]
|
||||
+ concat:[RACSignal
|
||||
defer:^{
|
||||
SQRLDirectoryManager *directoryManager = [[SQRLDirectoryManager alloc] initWithApplicationIdentifier:SQRLShipItLauncher.shipItJobLabel];
|
||||
return [directoryManager storageURL];
|
||||
- }]
|
||||
+ }]]
|
||||
flattenMap:^(NSURL *storageURL) {
|
||||
NSURL *updateDirectoryTemplate = [storageURL URLByAppendingPathComponent:[SQRLUpdaterUniqueTemporaryDirectoryPrefix stringByAppendingString:@"XXXXXXX"]];
|
||||
char *updateDirectoryCString = strdup(updateDirectoryTemplate.path.fileSystemRepresentation);
|
||||
@@ -643,7 +649,7 @@ - (BOOL)isRunningOnReadOnlyVolume {
|
||||
|
||||
- (RACSignal *)performHousekeeping {
|
||||
return [[RACSignal
|
||||
- merge:@[ [self pruneUpdateDirectories], [self truncateLogs] ]]
|
||||
+ merge:@[ [self pruneUpdateDirectoriesWithForce:NO], [self truncateLogs] ]]
|
||||
catch:^(NSError *error) {
|
||||
NSLog(@"Error doing housekeeping: %@", error);
|
||||
return [RACSignal empty];
|
||||
@@ -658,11 +664,12 @@ - (RACSignal *)performHousekeeping {
|
||||
///
|
||||
/// Sends each removed directory then completes, or errors, on an unspecified
|
||||
/// thread.
|
||||
-- (RACSignal *)pruneUpdateDirectories {
|
||||
+- (RACSignal *)pruneUpdateDirectoriesWithForce:(BOOL)force {
|
||||
return [[[RACSignal
|
||||
defer:^{
|
||||
- // If we already have updates downloaded we don't wanna prune them.
|
||||
- if (self.state == SQRLUpdaterStateAwaitingRelaunch) return [RACSignal empty];
|
||||
+ // If we already have updates downloaded we don't wanna prune them,
|
||||
+ // unless force is YES (used when starting a new download).
|
||||
+ if (!force && self.state == SQRLUpdaterStateAwaitingRelaunch) return [RACSignal empty];
|
||||
|
||||
SQRLDirectoryManager *directoryManager = [[SQRLDirectoryManager alloc] initWithApplicationIdentifier:SQRLShipItLauncher.shipItJobLabel];
|
||||
return [directoryManager storageURL];
|
||||
@@ -0,0 +1,130 @@
|
||||
From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001
|
||||
From: Andy Locascio <loc@anthropic.com>
|
||||
Date: Tue, 6 Jan 2026 08:23:03 -0800
|
||||
Subject: fix: clean up orphaned staged updates before downloading new update
|
||||
|
||||
When checkForUpdates() is called while an update is already staged,
|
||||
Squirrel creates a new temporary directory for the download without
|
||||
cleaning up the old one. This can lead to significant disk usage if
|
||||
the app keeps checking for updates without restarting.
|
||||
|
||||
This change adds a pruneOrphanedUpdateDirectories step before creating
|
||||
a new temp directory. Unlike a blanket prune, this reads the current
|
||||
ShipItState.plist and preserves the directory it references, deleting
|
||||
only truly orphaned update directories. This keeps the on-disk
|
||||
footprint bounded (at most 2 dirs) while ensuring quitAndInstall
|
||||
remains safe to call even when a new check is in progress.
|
||||
|
||||
Refs https://github.com/electron/electron/issues/50200
|
||||
|
||||
diff --git a/Squirrel/SQRLUpdater.m b/Squirrel/SQRLUpdater.m
|
||||
index d156616e81e6f25a3bded30e6216b8fc311f31bc..41856e5754228d33982db72f97f2ff241615a357 100644
|
||||
--- a/Squirrel/SQRLUpdater.m
|
||||
+++ b/Squirrel/SQRLUpdater.m
|
||||
@@ -543,11 +543,19 @@ - (RACSignal *)downloadBundleForUpdate:(SQRLUpdate *)update intoDirectory:(NSURL
|
||||
#pragma mark File Management
|
||||
|
||||
- (RACSignal *)uniqueTemporaryDirectoryForUpdate {
|
||||
- return [[[RACSignal
|
||||
+ // Clean up any orphaned update directories before creating a new one.
|
||||
+ // This prevents disk usage from growing when checkForUpdates() is called
|
||||
+ // multiple times without the app restarting. The currently staged update
|
||||
+ // (referenced by ShipItState.plist) is always preserved so quitAndInstall
|
||||
+ // remains safe to call while a new check is in progress.
|
||||
+ return [[[[[self
|
||||
+ pruneOrphanedUpdateDirectories]
|
||||
+ ignoreValues]
|
||||
+ concat:[RACSignal
|
||||
defer:^{
|
||||
SQRLDirectoryManager *directoryManager = [[SQRLDirectoryManager alloc] initWithApplicationIdentifier:SQRLShipItLauncher.shipItJobLabel];
|
||||
return [directoryManager storageURL];
|
||||
- }]
|
||||
+ }]]
|
||||
flattenMap:^(NSURL *storageURL) {
|
||||
NSURL *updateDirectoryTemplate = [storageURL URLByAppendingPathComponent:[SQRLUpdaterUniqueTemporaryDirectoryPrefix stringByAppendingString:@"XXXXXXX"]];
|
||||
char *updateDirectoryCString = strdup(updateDirectoryTemplate.path.fileSystemRepresentation);
|
||||
@@ -668,25 +676,68 @@ - (RACSignal *)pruneUpdateDirectories {
|
||||
return [directoryManager storageURL];
|
||||
}]
|
||||
flattenMap:^(NSURL *storageURL) {
|
||||
- NSFileManager *manager = [[NSFileManager alloc] init];
|
||||
- NSDirectoryEnumerator *enumerator = [manager enumeratorAtURL:storageURL includingPropertiesForKeys:nil options:NSDirectoryEnumerationSkipsSubdirectoryDescendants errorHandler:^(NSURL *URL, NSError *error) {
|
||||
- NSLog(@"Error enumerating item %@ within directory %@: %@", URL, storageURL, error);
|
||||
- return YES;
|
||||
- }];
|
||||
+ return [self removeUpdateDirectoriesInStorageURL:storageURL excludingURL:nil];
|
||||
+ }]
|
||||
+ setNameWithFormat:@"%@ -prunedUpdateDirectories", self];
|
||||
+}
|
||||
|
||||
- return [[enumerator.rac_sequence.signal
|
||||
- filter:^(NSURL *enumeratedURL) {
|
||||
- NSString *name = enumeratedURL.lastPathComponent;
|
||||
- return [name hasPrefix:SQRLUpdaterUniqueTemporaryDirectoryPrefix];
|
||||
- }]
|
||||
- doNext:^(NSURL *directoryURL) {
|
||||
- NSError *error = nil;
|
||||
- if (![manager removeItemAtURL:directoryURL error:&error]) {
|
||||
- NSLog(@"Error removing old update directory at %@: %@", directoryURL, error.sqrl_verboseDescription);
|
||||
- }
|
||||
+/// Lazily removes orphaned temporary directories upon subscription, always
|
||||
+/// preserving the directory currently referenced by ShipItState.plist so that
|
||||
+/// quitAndInstall remains safe to call mid-check.
|
||||
+///
|
||||
+/// Safe to call in any state. Sends each removed directory then completes on
|
||||
+/// an unspecified thread. Errors reading the staged request are swallowed
|
||||
+/// (treated as "nothing staged").
|
||||
+- (RACSignal *)pruneOrphanedUpdateDirectories {
|
||||
+ return [[[[[SQRLShipItRequest
|
||||
+ readUsingURL:self.shipItStateURL]
|
||||
+ map:^(SQRLShipItRequest *request) {
|
||||
+ // The request holds the URL to the staged .app bundle; its parent
|
||||
+ // is the update.XXXXXXX directory we must preserve.
|
||||
+ return [request.updateBundleURL URLByDeletingLastPathComponent];
|
||||
+ }]
|
||||
+ catch:^(NSError *error) {
|
||||
+ // No staged request (or unreadable) — nothing to preserve.
|
||||
+ return [RACSignal return:nil];
|
||||
+ }]
|
||||
+ flattenMap:^(NSURL *stagedDirectoryURL) {
|
||||
+ SQRLDirectoryManager *directoryManager = [[SQRLDirectoryManager alloc] initWithApplicationIdentifier:SQRLShipItLauncher.shipItJobLabel];
|
||||
+ return [[directoryManager storageURL]
|
||||
+ flattenMap:^(NSURL *storageURL) {
|
||||
+ return [self removeUpdateDirectoriesInStorageURL:storageURL excludingURL:stagedDirectoryURL];
|
||||
}];
|
||||
}]
|
||||
- setNameWithFormat:@"%@ -prunedUpdateDirectories", self];
|
||||
+ setNameWithFormat:@"%@ -pruneOrphanedUpdateDirectories", self];
|
||||
+}
|
||||
+
|
||||
+/// Shared enumerate-and-delete logic for update temp directories.
|
||||
+///
|
||||
+/// storageURL - The Squirrel storage root to enumerate. Must not be nil.
|
||||
+/// excludedURL - Directory to skip (compared by standardized path). May be nil.
|
||||
+- (RACSignal *)removeUpdateDirectoriesInStorageURL:(NSURL *)storageURL excludingURL:(NSURL *)excludedURL {
|
||||
+ NSParameterAssert(storageURL != nil);
|
||||
+
|
||||
+ NSFileManager *manager = [[NSFileManager alloc] init];
|
||||
+ NSDirectoryEnumerator *enumerator = [manager enumeratorAtURL:storageURL includingPropertiesForKeys:nil options:NSDirectoryEnumerationSkipsSubdirectoryDescendants errorHandler:^(NSURL *URL, NSError *error) {
|
||||
+ NSLog(@"Error enumerating item %@ within directory %@: %@", URL, storageURL, error);
|
||||
+ return YES;
|
||||
+ }];
|
||||
+
|
||||
+ NSString *excludedPath = excludedURL.URLByStandardizingPath.path;
|
||||
+
|
||||
+ return [[enumerator.rac_sequence.signal
|
||||
+ filter:^(NSURL *enumeratedURL) {
|
||||
+ NSString *name = enumeratedURL.lastPathComponent;
|
||||
+ if (![name hasPrefix:SQRLUpdaterUniqueTemporaryDirectoryPrefix]) return NO;
|
||||
+ if (excludedPath != nil && [enumeratedURL.URLByStandardizingPath.path isEqualToString:excludedPath]) return NO;
|
||||
+ return YES;
|
||||
+ }]
|
||||
+ doNext:^(NSURL *directoryURL) {
|
||||
+ NSError *error = nil;
|
||||
+ if (![manager removeItemAtURL:directoryURL error:&error]) {
|
||||
+ NSLog(@"Error removing old update directory at %@: %@", directoryURL, error.sqrl_verboseDescription);
|
||||
+ }
|
||||
+ }];
|
||||
}
|
||||
|
||||
|
||||
@@ -3,3 +3,4 @@ turboshaft_avoid_introducing_too_many_variables.patch
|
||||
runtime_setprototypeproperties_handling_of.patch
|
||||
runtime_correcting_setprototypeproperties.patch
|
||||
reduce_stack_memory_consumption_in_bytecodegenerator.patch
|
||||
cherry-pick-d5b0cb2acffe.patch
|
||||
|
||||
50
patches/v8/cherry-pick-d5b0cb2acffe.patch
Normal file
50
patches/v8/cherry-pick-d5b0cb2acffe.patch
Normal file
@@ -0,0 +1,50 @@
|
||||
From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001
|
||||
From: Darius Mercadier <dmercadier@chromium.org>
|
||||
Date: Wed, 25 Feb 2026 12:56:18 +0100
|
||||
Subject: [M144 Merge] [maglev] fix CanElideWriteBarrier Smi recording for phis
|
||||
|
||||
Recording a Tagged use is not enough for 2 reasons:
|
||||
|
||||
* Tagged uses are sometimes ignored, in particular for loop phis
|
||||
where we distinguish in-loop and out-of-loop uses.
|
||||
|
||||
* This Tagged use could only prevent untagging of this specific phi,
|
||||
but none of its inputs. So we could have a Smi phi as input to the
|
||||
current phi which gets untagged and retagged to a non-Smi, all
|
||||
while the current phi doesn't get untagged.
|
||||
|
||||
(cherry picked from commit a54bf5cd45e5b119e2afe6019428e81c3d626fb3)
|
||||
|
||||
Change-Id: I9b3a2ea339f2c9d81dbb74a44425ba55d8c73871
|
||||
Reviewed-on: https://chromium-review.googlesource.com/c/v8/v8/+/7604255
|
||||
Auto-Submit: Darius Mercadier <dmercadier@chromium.org>
|
||||
Reviewed-by: Leszek Swirski <leszeks@chromium.org>
|
||||
Commit-Queue: Darius Mercadier <dmercadier@chromium.org>
|
||||
Cr-Original-Commit-Position: refs/heads/main@{#105444}
|
||||
Reviewed-on: https://chromium-review.googlesource.com/c/v8/v8/+/7659106
|
||||
Auto-Submit: Srinivas Sista <srinivassista@chromium.org>
|
||||
Reviewed-by: Rezvan Mahdavi Hezaveh <rezvan@chromium.org>
|
||||
Commit-Queue: Srinivas Sista <srinivassista@chromium.org>
|
||||
Reviewed-by: Deepti Gandluri <gdeepti@chromium.org>
|
||||
Owners-Override: Srinivas Sista <srinivassista@chromium.org>
|
||||
Cr-Commit-Position: refs/branch-heads/14.4@{#64}
|
||||
Cr-Branched-From: 80acc26727d5a34e77dabeebe7c9213ec1bd4768-refs/heads/14.4.258@{#1}
|
||||
Cr-Branched-From: ce7e597e90f6df3fa4b6df224bc613b80c635450-refs/heads/main@{#104020}
|
||||
|
||||
diff --git a/src/maglev/maglev-graph-builder.cc b/src/maglev/maglev-graph-builder.cc
|
||||
index 4664ca78b4413da6a3d9d6cafa705d33f5c02ee2..c682aec3ff109e42290c2e2ddec350f913e4e063 100644
|
||||
--- a/src/maglev/maglev-graph-builder.cc
|
||||
+++ b/src/maglev/maglev-graph-builder.cc
|
||||
@@ -4496,7 +4496,11 @@ bool MaglevGraphBuilder::CanElideWriteBarrier(ValueNode* object,
|
||||
ValueNode* value) {
|
||||
if (value->Is<RootConstant>() || value->Is<ConsStringMap>()) return true;
|
||||
if (!IsEmptyNodeType(GetType(value)) && CheckType(value, NodeType::kSmi)) {
|
||||
- value->MaybeRecordUseReprHint(UseRepresentation::kTagged);
|
||||
+ if constexpr (SmiValuesAre31Bits()) {
|
||||
+ if (Phi* value_as_phi = value->TryCast<Phi>()) {
|
||||
+ value_as_phi->SetUseRequires31BitValue();
|
||||
+ }
|
||||
+ }
|
||||
return true;
|
||||
}
|
||||
|
||||
@@ -32,7 +32,8 @@ async function main () {
|
||||
}));
|
||||
const hitRate = stats.CacheHit / (stats.Remote + stats.CacheHit + stats.LocalFallback);
|
||||
|
||||
console.log(`Effective cache hit rate: ${(hitRate * 100).toFixed(2)}%`);
|
||||
const messagePrefix = process.env.GITHUB_ACTIONS ? '::notice title=Build Stats::' : '';
|
||||
console.log(`${messagePrefix}Effective cache hit rate: ${(hitRate * 100).toFixed(2)}%`);
|
||||
|
||||
if (uploadStats) {
|
||||
if (!process.env.DD_API_KEY) {
|
||||
|
||||
21
script/codesign/cleanup-identity.sh
Executable file
21
script/codesign/cleanup-identity.sh
Executable file
@@ -0,0 +1,21 @@
|
||||
#!/bin/sh
|
||||
|
||||
# Removes the codesigning keychain created by generate-identity.sh.
|
||||
# Safe to run even if generate-identity.sh was never run (each step
|
||||
# is guarded).
|
||||
|
||||
set -eo pipefail
|
||||
|
||||
KEYCHAIN="electron-codesign.keychain-db"
|
||||
|
||||
# delete-keychain also removes it from the search list
|
||||
if security list-keychains -d user | grep -q "$KEYCHAIN"; then
|
||||
security delete-keychain "$KEYCHAIN"
|
||||
echo "Deleted keychain: $KEYCHAIN"
|
||||
else
|
||||
echo "Keychain not found, nothing to delete"
|
||||
fi
|
||||
|
||||
# Clean up working directory
|
||||
rm -rf "$(dirname $0)"/.working
|
||||
echo "Cleanup complete"
|
||||
@@ -3,6 +3,8 @@
|
||||
set -eo pipefail
|
||||
|
||||
dir="$(dirname $0)"/.working
|
||||
KEYCHAIN="electron-codesign.keychain-db"
|
||||
KEYCHAIN_TEMP="$(openssl rand -hex 12)"
|
||||
|
||||
cleanup() {
|
||||
rm -rf "$dir"
|
||||
@@ -18,30 +20,16 @@ mkdir -p "$dir"
|
||||
|
||||
# Generate Certs
|
||||
openssl req -new -newkey rsa:2048 -x509 -days 7300 -nodes -config "$(dirname $0)"/codesign.cnf -extensions extended -batch -out "$dir"/certificate.cer -keyout "$dir"/certificate.key
|
||||
sudo security add-trusted-cert -d -r trustRoot -k /Library/Keychains/System.keychain "$dir"/certificate.cer
|
||||
sudo security import "$dir"/certificate.key -A -k /Library/Keychains/System.keychain
|
||||
|
||||
# restart(reload) taskgated daemon
|
||||
sudo pkill -f /usr/libexec/taskgated
|
||||
# macOS 15+ blocks modifications to the system keychain via SIP/TCC,
|
||||
# so we use a custom user-scoped keychain instead.
|
||||
# Refs https://github.com/electron/electron/issues/48182
|
||||
security create-keychain -p "$KEYCHAIN_TEMP" "$KEYCHAIN"
|
||||
security set-keychain-settings -t 3600 -u "$KEYCHAIN"
|
||||
security unlock-keychain -p "$KEYCHAIN_TEMP" "$KEYCHAIN"
|
||||
|
||||
# need once
|
||||
sudo security authorizationdb write system.privilege.taskport allow
|
||||
# need once
|
||||
DevToolsSecurity -enable
|
||||
security list-keychains -d user -s "$KEYCHAIN" $(security list-keychains -d user | tr -d '"')
|
||||
security import "$dir"/certificate.cer -k "$KEYCHAIN" -T /usr/bin/codesign
|
||||
security import "$dir"/certificate.key -k "$KEYCHAIN" -T /usr/bin/codesign -A
|
||||
|
||||
# openssl req -newkey rsa:2048 -nodes -keyout "$dir"/private.pem -x509 -days 1 -out "$dir"/certificate.pem -extensions extended -config "$(dirname $0)"/codesign.cnf
|
||||
# openssl x509 -inform PEM -in "$dir"/certificate.pem -outform DER -out "$dir"/certificate.cer
|
||||
# openssl x509 -pubkey -noout -in "$dir"/certificate.pem > "$dir"/public.key
|
||||
# rm -f "$dir"/certificate.pem
|
||||
|
||||
# Import Certs
|
||||
# security import "$dir"/certificate.cer -k $KEY_CHAIN
|
||||
# security import "$dir"/private.pem -k $KEY_CHAIN
|
||||
# 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
|
||||
sudo security trust-settings-import -d "$dir/trust.xml"
|
||||
security set-key-partition-list -S apple-tool:,apple:,codesign: -s -k "$KEYCHAIN_TEMP" "$KEYCHAIN"
|
||||
|
||||
@@ -2,7 +2,7 @@
|
||||
|
||||
set -e
|
||||
|
||||
valid_certs=$(security find-identity -p codesigning -v)
|
||||
valid_certs=$(security find-identity -p codesigning)
|
||||
if [[ $valid_certs == *"1)"* ]]; then
|
||||
first_valid_cert=$(echo $valid_certs | sed 's/ \".*//' | sed 's/.* //')
|
||||
echo $first_valid_cert
|
||||
|
||||
@@ -46,8 +46,6 @@
|
||||
"parallel/test-repl",
|
||||
"parallel/test-repl-underscore",
|
||||
"parallel/test-tls-securepair-leak",
|
||||
"parallel/test-single-executable-blob-config",
|
||||
"parallel/test-single-executable-blob-config-errors",
|
||||
"parallel/test-shadow-realm-custom-loaders",
|
||||
"parallel/test-snapshot-api",
|
||||
"parallel/test-snapshot-argv1",
|
||||
@@ -109,6 +107,9 @@
|
||||
"parallel/test-tls-multi-key",
|
||||
"parallel/test-tls-multi-pfx",
|
||||
"parallel/test-tls-no-cert-required",
|
||||
"parallel/test-tls-off-thread-cert-loading",
|
||||
"parallel/test-tls-off-thread-cert-loading-disabled",
|
||||
"parallel/test-tls-off-thread-cert-loading-system",
|
||||
"parallel/test-tls-options-boolean-check",
|
||||
"parallel/test-tls-passphrase",
|
||||
"parallel/test-tls-peer-certificate",
|
||||
@@ -172,6 +173,8 @@
|
||||
"report/test-report-uv-handles",
|
||||
"report/test-report-worker",
|
||||
"report/test-report-writereport",
|
||||
"sea/test-single-executable-blob-config",
|
||||
"sea/test-single-executable-blob-config-errors",
|
||||
"sequential/test-single-executable-application",
|
||||
"sequential/test-single-executable-application-disable-experimental-sea-warning",
|
||||
"sequential/test-single-executable-application-empty",
|
||||
|
||||
@@ -317,6 +317,12 @@ void BaseWindow::OnWindowSheetEnd() {
|
||||
Emit("sheet-end");
|
||||
}
|
||||
|
||||
void BaseWindow::OnWindowIsKeyChanged(bool is_key) {
|
||||
#if BUILDFLAG(IS_MAC)
|
||||
window()->SetActive(is_key);
|
||||
#endif
|
||||
}
|
||||
|
||||
void BaseWindow::OnWindowEnterHtmlFullScreen() {
|
||||
Emit("enter-html-full-screen");
|
||||
}
|
||||
|
||||
@@ -83,6 +83,7 @@ class BaseWindow : public gin_helper::TrackableObject<BaseWindow>,
|
||||
void OnWindowRotateGesture(float rotation) override;
|
||||
void OnWindowSheetBegin() override;
|
||||
void OnWindowSheetEnd() override;
|
||||
void OnWindowIsKeyChanged(bool is_key) override;
|
||||
void OnWindowEnterFullScreen() override;
|
||||
void OnWindowLeaveFullScreen() override;
|
||||
void OnWindowEnterHtmlFullScreen() override;
|
||||
|
||||
@@ -280,16 +280,22 @@ v8::Local<v8::Value> BrowserWindow::GetWebContents(v8::Isolate* isolate) {
|
||||
}
|
||||
|
||||
void BrowserWindow::OnWindowShow() {
|
||||
if (!web_contents_shown_) {
|
||||
web_contents()->WasShown();
|
||||
web_contents_shown_ = true;
|
||||
}
|
||||
BaseWindow::OnWindowShow();
|
||||
}
|
||||
|
||||
void BrowserWindow::OnWindowHide() {
|
||||
web_contents()->WasOccluded();
|
||||
web_contents_shown_ = false;
|
||||
BaseWindow::OnWindowHide();
|
||||
}
|
||||
|
||||
void BrowserWindow::Show() {
|
||||
web_contents()->WasShown();
|
||||
web_contents_shown_ = true;
|
||||
BaseWindow::Show();
|
||||
}
|
||||
|
||||
@@ -298,6 +304,7 @@ void BrowserWindow::ShowInactive() {
|
||||
if (IsModal())
|
||||
return;
|
||||
web_contents()->WasShown();
|
||||
web_contents_shown_ = true;
|
||||
BaseWindow::ShowInactive();
|
||||
}
|
||||
|
||||
|
||||
@@ -80,6 +80,7 @@ class BrowserWindow : public BaseWindow,
|
||||
// Helpers.
|
||||
|
||||
v8::Global<v8::Value> web_contents_;
|
||||
bool web_contents_shown_ = false;
|
||||
v8::Global<v8::Value> web_contents_view_;
|
||||
base::WeakPtr<api::WebContents> api_web_contents_;
|
||||
|
||||
|
||||
@@ -80,6 +80,14 @@ PowerMonitor::PowerMonitor(v8::Isolate* isolate) {
|
||||
}
|
||||
|
||||
PowerMonitor::~PowerMonitor() {
|
||||
#if BUILDFLAG(IS_MAC) || BUILDFLAG(IS_WIN)
|
||||
DestroyPlatformSpecificMonitors();
|
||||
#endif
|
||||
|
||||
#if BUILDFLAG(IS_MAC)
|
||||
Browser::Get()->SetShutdownHandler(base::RepeatingCallback<bool()>());
|
||||
#endif
|
||||
|
||||
auto* power_monitor = base::PowerMonitor::GetInstance();
|
||||
power_monitor->RemovePowerStateObserver(this);
|
||||
power_monitor->RemovePowerSuspendObserver(this);
|
||||
|
||||
@@ -49,6 +49,7 @@ class PowerMonitor final : public gin_helper::DeprecatedWrappable<PowerMonitor>,
|
||||
|
||||
#if BUILDFLAG(IS_MAC) || BUILDFLAG(IS_WIN)
|
||||
void InitPlatformSpecificMonitors();
|
||||
void DestroyPlatformSpecificMonitors();
|
||||
#endif
|
||||
|
||||
// base::PowerStateObserver implementations:
|
||||
|
||||
@@ -15,6 +15,7 @@
|
||||
}
|
||||
|
||||
- (void)addEmitter:(electron::api::PowerMonitor*)monitor_;
|
||||
- (void)removeEmitter:(electron::api::PowerMonitor*)monitor_;
|
||||
|
||||
@end
|
||||
|
||||
@@ -62,6 +63,10 @@
|
||||
self->emitters.push_back(monitor_);
|
||||
}
|
||||
|
||||
- (void)removeEmitter:(electron::api::PowerMonitor*)monitor_ {
|
||||
std::erase(self->emitters, monitor_);
|
||||
}
|
||||
|
||||
- (void)onScreenLocked:(NSNotification*)notification {
|
||||
for (auto* emitter : self->emitters) {
|
||||
emitter->Emit("lock-screen");
|
||||
@@ -98,4 +103,9 @@ void PowerMonitor::InitPlatformSpecificMonitors() {
|
||||
[g_lock_monitor addEmitter:this];
|
||||
}
|
||||
|
||||
void PowerMonitor::DestroyPlatformSpecificMonitors() {
|
||||
if (g_lock_monitor)
|
||||
[g_lock_monitor removeEmitter:this];
|
||||
}
|
||||
|
||||
} // namespace electron::api
|
||||
|
||||
@@ -49,6 +49,20 @@ void PowerMonitor::InitPlatformSpecificMonitors() {
|
||||
DEVICE_NOTIFY_WINDOW_HANDLE);
|
||||
}
|
||||
|
||||
void PowerMonitor::DestroyPlatformSpecificMonitors() {
|
||||
if (window_) {
|
||||
WTSUnRegisterSessionNotification(window_);
|
||||
UnregisterSuspendResumeNotification(static_cast<HANDLE>(window_));
|
||||
gfx::SetWindowUserData(window_, nullptr);
|
||||
DestroyWindow(window_);
|
||||
window_ = nullptr;
|
||||
}
|
||||
if (atom_) {
|
||||
UnregisterClass(MAKEINTATOM(atom_), instance_);
|
||||
atom_ = 0;
|
||||
}
|
||||
}
|
||||
|
||||
LRESULT CALLBACK PowerMonitor::WndProcStatic(HWND hwnd,
|
||||
UINT message,
|
||||
WPARAM wparam,
|
||||
@@ -76,7 +90,7 @@ LRESULT CALLBACK PowerMonitor::WndProc(HWND hwnd,
|
||||
}
|
||||
if (should_treat_as_current_session) {
|
||||
if (wparam == WTS_SESSION_LOCK) {
|
||||
// Unretained is OK because this object is eternally pinned.
|
||||
// SelfKeepAlive prevents GC of this object, so Unretained is safe.
|
||||
content::GetUIThreadTaskRunner({})->PostTask(
|
||||
FROM_HERE,
|
||||
base::BindOnce([](PowerMonitor* pm) { pm->Emit("lock-screen"); },
|
||||
|
||||
@@ -32,10 +32,6 @@
|
||||
#include "shell/browser/linux/x11_util.h"
|
||||
#endif
|
||||
|
||||
#if defined(USE_OZONE)
|
||||
#include "ui/ozone/public/ozone_platform.h"
|
||||
#endif
|
||||
|
||||
namespace electron::api {
|
||||
|
||||
gin::DeprecatedWrapperInfo Screen::kWrapperInfo = {gin::kEmbedderNativeGin};
|
||||
@@ -81,16 +77,9 @@ Screen::~Screen() {
|
||||
}
|
||||
|
||||
gfx::Point Screen::GetCursorScreenPoint(v8::Isolate* isolate) {
|
||||
#if defined(USE_OZONE)
|
||||
// Wayland will crash unless a window is created prior to calling
|
||||
// GetCursorScreenPoint.
|
||||
if (!ui::OzonePlatform::IsInitialized()) {
|
||||
gin_helper::ErrorThrower thrower(isolate);
|
||||
thrower.ThrowError(
|
||||
"screen.getCursorScreenPoint() cannot be called before a window has "
|
||||
"been created.");
|
||||
#if BUILDFLAG(IS_LINUX)
|
||||
if (x11_util::IsWayland())
|
||||
return {};
|
||||
}
|
||||
#endif
|
||||
return screen_->GetCursorScreenPoint();
|
||||
}
|
||||
|
||||
@@ -1240,10 +1240,11 @@ void WebContents::MaybeOverrideCreateParamsForNewWindow(
|
||||
dict.Get(options::kOffscreen, &is_offscreen) && is_offscreen);
|
||||
|
||||
if (is_offscreen) {
|
||||
// Use a no-op callback here. The real OnPaint callback will be bound
|
||||
// to the child WebContents in AddNewContents via SetCallback().
|
||||
auto* view = new OffScreenWebContentsView(
|
||||
false, offscreen_use_shared_texture_,
|
||||
offscreen_shared_texture_pixel_format_,
|
||||
base::BindRepeating(&WebContents::OnPaint, base::Unretained(this)));
|
||||
offscreen_shared_texture_pixel_format_, base::DoNothing());
|
||||
create_params->view = view;
|
||||
create_params->delegate_view = view;
|
||||
}
|
||||
@@ -1271,6 +1272,15 @@ content::WebContents* WebContents::AddNewContents(
|
||||
v8::HandleScope handle_scope(isolate);
|
||||
auto api_web_contents = CreateAndTake(isolate, std::move(new_contents), type);
|
||||
|
||||
// Rebind the paint callback to the child WebContents. The
|
||||
// OffScreenWebContentsView was initially created with the parent's OnPaint
|
||||
// in MaybeOverrideCreateParamsForNewWindow, but the paint data
|
||||
// belongs to the child.
|
||||
if (auto* osr_view = api_web_contents->GetOffScreenWebContentsView()) {
|
||||
osr_view->SetCallback(base::BindRepeating(&WebContents::OnPaint,
|
||||
api_web_contents->GetWeakPtr()));
|
||||
}
|
||||
|
||||
// We call RenderFrameCreated here as at this point the empty "about:blank"
|
||||
// render frame has already been created. If the window never navigates again
|
||||
// RenderFrameCreated won't be called and certain prefs like
|
||||
@@ -2176,6 +2186,11 @@ void WebContents::DidUpdateFaviconURL(
|
||||
iter->icon_url.is_valid())
|
||||
unique_urls.insert(iter->icon_url);
|
||||
}
|
||||
// Only emit if favicon URLs actually changed
|
||||
if (unique_urls == last_favicon_urls_)
|
||||
return;
|
||||
last_favicon_urls_ = unique_urls;
|
||||
|
||||
Emit("page-favicon-updated", unique_urls);
|
||||
}
|
||||
|
||||
|
||||
@@ -11,6 +11,7 @@
|
||||
#include <string>
|
||||
#include <vector>
|
||||
|
||||
#include "base/containers/flat_set.h"
|
||||
#include "base/functional/callback_forward.h"
|
||||
#include "base/memory/raw_ptr.h"
|
||||
#include "base/memory/raw_ptr_exclusion.h"
|
||||
@@ -460,6 +461,9 @@ class WebContents final : public ExclusiveAccessContext,
|
||||
WebContents& operator=(const WebContents&) = delete;
|
||||
|
||||
private:
|
||||
// Store last emitted favicon URLs to avoid duplicate page-favicon-updated
|
||||
// events
|
||||
base::flat_set<GURL> last_favicon_urls_;
|
||||
// Does not manage lifetime of |web_contents|.
|
||||
WebContents(v8::Isolate* isolate, content::WebContents* web_contents);
|
||||
// Takes over ownership of |web_contents|.
|
||||
|
||||
@@ -83,13 +83,17 @@ void WebContentsView::ApplyBorderRadius() {
|
||||
|
||||
int WebContentsView::NonClientHitTest(const gfx::Point& point) {
|
||||
if (api_web_contents_) {
|
||||
auto* iwc = api_web_contents_->inspectable_web_contents();
|
||||
if (!iwc)
|
||||
return HTNOWHERE;
|
||||
// Convert the point to the contents view's coordinate space rather than
|
||||
// the InspectableWebContentsView's coordinate space, because the draggable
|
||||
// region is relative to the web content area. When DevTools is docked
|
||||
// (e.g. to the left), the contents view is offset within the parent,
|
||||
// so we need to account for that offset.
|
||||
auto* inspectable_view =
|
||||
api_web_contents_->inspectable_web_contents()->GetView();
|
||||
auto* inspectable_view = iwc->GetView();
|
||||
if (!inspectable_view)
|
||||
return HTNOWHERE;
|
||||
auto* contents_view = inspectable_view->GetContentsView();
|
||||
gfx::Point local_point(point);
|
||||
views::View::ConvertPointFromWidget(contents_view, &local_point);
|
||||
|
||||
@@ -9,7 +9,9 @@
|
||||
#include <utility>
|
||||
|
||||
#include "base/files/file_util.h"
|
||||
#include "base/logging.h"
|
||||
#include "base/path_service.h"
|
||||
#include "base/strings/string_util.h"
|
||||
#include "base/task/single_thread_task_runner.h"
|
||||
#include "base/threading/thread_restrictions.h"
|
||||
#include "chrome/common/chrome_paths.h"
|
||||
@@ -71,6 +73,29 @@ Browser* Browser::Get() {
|
||||
return ElectronBrowserMainParts::Get()->browser();
|
||||
}
|
||||
|
||||
// static
|
||||
bool Browser::IsValidProtocolScheme(const std::string& scheme) {
|
||||
// RFC 3986 Section 3.1:
|
||||
// scheme = ALPHA *( ALPHA / DIGIT / "+" / "-" / "." )
|
||||
if (scheme.empty()) {
|
||||
LOG(ERROR) << "Protocol scheme must not be empty";
|
||||
return false;
|
||||
}
|
||||
if (!base::IsAsciiAlpha(scheme[0])) {
|
||||
LOG(ERROR) << "Protocol scheme must start with an ASCII letter";
|
||||
return false;
|
||||
}
|
||||
for (size_t i = 1; i < scheme.size(); ++i) {
|
||||
const char c = scheme[i];
|
||||
if (!base::IsAsciiAlpha(c) && !base::IsAsciiDigit(c) && c != '+' &&
|
||||
c != '-' && c != '.') {
|
||||
LOG(ERROR) << "Protocol scheme contains invalid character: '" << c << "'";
|
||||
return false;
|
||||
}
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
#if BUILDFLAG(IS_WIN) || BUILDFLAG(IS_LINUX)
|
||||
void Browser::Focus(gin::Arguments* args) {
|
||||
// Focus on the first visible window.
|
||||
|
||||
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user