Compare commits

..

67 Commits

Author SHA1 Message Date
trop[bot]
9d2f8cb4da refactor: remove dead named-window lookup from guest-window-manager (#50498)
The frameNamesToWindow map was a holdover from the BrowserWindowProxy
IPC shim. Since nativeWindowOpen became the only code path, Blink's
FrameTree::FindOrCreateFrameForNavigation resolves named window targets
directly in the renderer, scoped to the opener's browsing context
group. When a matching named window exists, Blink navigates it without
ever sending a CreateNewWindow IPC to the browser, so this map was
never consulted in the legitimate same-opener case.

The only time the map found a match was when two unrelated renderers
happened to use the same target name, in which case openGuestWindow
would short-circuit before consuming the guest WebContents that
Chromium had already created for the new window, leaking it.

Adds a test verifying Blink handles same-opener named-target reuse
end-to-end without any browser-side tracking.

Co-authored-by: trop[bot] <37223003+trop[bot]@users.noreply.github.com>
Co-authored-by: Sam Attard <sattard@anthropic.com>
2026-03-26 00:50:03 -07:00
trop[bot]
1173004739 fix: crash calling OSR shared texture release() after texture GC'd (#50499)
The weak persistent tracking the OffscreenReleaseHolderMonitor was tied
to the texture object, but the release() closure holds a raw pointer to
the monitor via its v8::External data. If JS retained texture.release
while dropping the texture itself, the monitor would be freed on GC and
a later release() call would crash.

Track the release function instead of the texture object. Since the
texture holds release as a property, this keeps the monitor alive as
long as either is reachable.

Co-authored-by: trop[bot] <37223003+trop[bot]@users.noreply.github.com>
Co-authored-by: Sam Attard <sattard@anthropic.com>
2026-03-26 00:49:22 -07:00
trop[bot]
be37adefd0 fix: crash in clipboard.readImage() on malformed image data (#50493)
gfx::PNGCodec::Decode() returns a null SkBitmap when it fails to decode
the clipboard contents as a PNG. Passing that null bitmap to
gfx::Image::CreateFrom1xBitmap() triggers a crash.

Return an empty gfx::Image instead, matching the existing null-check
pattern in skia_util.cc.

Co-authored-by: trop[bot] <37223003+trop[bot]@users.noreply.github.com>
Co-authored-by: Sam Attard <sattard@anthropic.com>
2026-03-25 22:16:26 -07:00
Keeley Hammond
7007907df0 chore: cherry-pick 3 changes from chromium (#50461)
* chore: cherry-pick 45c5a70d984d from chromium

Describe a vector of segments as "segments", not "tokens"

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}

Co-Authored-By: Claude <svc-devxp-claude@slack-corp.com>

* chore: cherry-pick 05e4b544803c from chromium

Stringify CSSUnparsedValues via toString, as normal

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}

Co-Authored-By: Claude <svc-devxp-claude@slack-corp.com>

* chore: cherry-pick 5efc7a0127a6 from chromium

Validate CSSUnparsedValues upon assignment

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}

Co-Authored-By: Claude <svc-devxp-claude@slack-corp.com>

* chore: update patches

Co-Authored-By: Claude <svc-devxp-claude@slack-corp.com>

---------

Co-authored-by: Claude <svc-devxp-claude@slack-corp.com>
2026-03-25 01:42:34 +00:00
Keeley Hammond
2c8b6ee0c0 chore: cherry-pick fbfb27470bf6 from chromium (#50436)
* chore: cherry-pick fbfb27470bf6 from chromium

* chore: cherry-pick bf6dd974238b from angle (#50435)

* fix: remove duplicate MaxGeometryUniformBlocks from angle cherry-pick patch

The angle cherry-pick added MaxGeometryUniformBlocks in new locations,
but it already existed in the EXT_geometry_shader section, causing a
duplicate struct member build error in ShaderLang.h.

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>

---------

Co-authored-by: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
2026-03-24 23:22:22 +00:00
Keeley Hammond
4c64377ead chore: cherry-pick 50b057660b4d from chromium (#50440)
* chore: cherry-pick 50b057660b4d from chromium

* chore: update patches

---------

Co-authored-by: PatchUp <73610968+patchup[bot]@users.noreply.github.com>
Co-authored-by: John Kleinschmidt <jkleinsc@electronjs.org>
2026-03-24 19:01:06 -04:00
Keeley Hammond
0ef056130c fix: read nodeIntegrationInWorker from per-frame WebPreferences (#50122) (#50468)
* fix: read nodeIntegrationInWorker from per-frame WebPreferences (#50122)

Previously the renderer checked a process-wide command-line switch to
decide whether to create a Node.js environment for dedicated workers.
When a renderer process hosted multiple WebContents with different
nodeIntegrationInWorker values (e.g. via window.open with overridden
webPreferences in setWindowOpenHandler), all workers in the process
used whichever value the first WebContents set on the command line.

Instead, plumb the flag through blink's WorkerSettings at worker
creation time, copying it from the initiating frame's WebPreferences.
The check on the worker thread then reads the per-worker value. Nested
workers inherit the flag from their parent worker via
WorkerSettings::Copy.

The --node-integration-in-worker command-line switch is removed as it
is no longer consumed.

* fix: restore base/command_line.h include needed by SetUpWebAssemblyTrapHandler

The backported PR removed this include (matching main where
SetUpWebAssemblyTrapHandler was refactored), but on 39-x-y the function
still uses base::CommandLine.

Co-Authored-By: Claude <svc-devxp-claude@slack-corp.com>

---------

Co-authored-by: Samuel Attard <sam@electronjs.org>
Co-authored-by: Claude <svc-devxp-claude@slack-corp.com>
2026-03-24 22:49:16 +00:00
Keeley Hammond
64373df3ca chore: cherry-pick 074d472db745 from chromium (#50443)
* chore: cherry-pick 074d472db745 from chromium

* chore: update patches

---------

Co-authored-by: PatchUp <73610968+patchup[bot]@users.noreply.github.com>
2026-03-23 21:40:49 -04:00
trop[bot]
13e44072be fix: don't re-parse URL unnecessarily when handling dialogs (#50400)
* fix: fallback to opaque URL when needed inside dialog callback

Co-authored-by: Noah Gregory <noahmgregory@gmail.com>

* refactor: remove additional URL parsing entirely when showing dialogs

Co-authored-by: Noah Gregory <noahmgregory@gmail.com>

* test: add crash test case for URL-less dialogs

Co-authored-by: Noah Gregory <noahmgregory@gmail.com>

* refactor: exit on events instead of on timeout for dialog crash test

Co-authored-by: Robo <hop2deep@gmail.com>

Co-authored-by: Noah Gregory <noahmgregory@gmail.com>

* style: make linter happy

Co-authored-by: Noah Gregory <noahmgregory@gmail.com>

* style: make linter actually happy

Co-authored-by: Noah Gregory <noahmgregory@gmail.com>

* fix: address failing `safeDialogs` tests

Co-authored-by: Noah Gregory <noahmgregory@gmail.com>

---------

Co-authored-by: trop[bot] <37223003+trop[bot]@users.noreply.github.com>
Co-authored-by: Noah Gregory <noahmgregory@gmail.com>
2026-03-20 17:31:06 -04:00
trop[bot]
16a038502a ci: output build cache hit rate as GHA annotation (#50369)
Co-authored-by: trop[bot] <37223003+trop[bot]@users.noreply.github.com>
Co-authored-by: David Sanders <dsanders11@ucsbalum.com>
2026-03-19 14:53:25 -04:00
trop[bot]
00a492d282 chore: Respect HTTP(S) proxy env variable for Yarn (#50349)
Respect HTTP(S) proxy env variable for Yarn

Co-authored-by: trop[bot] <37223003+trop[bot]@users.noreply.github.com>
Co-authored-by: Filip Mösner <filip.mosner@seznam.cz>
2026-03-18 19:15:19 -04:00
trop[bot]
290a77b843 fix: correctly track BaseWindow::IsActive() on MacOS (#50338)
fix: correctly set IsActive() in BaseWindow on MacOS

Co-authored-by: trop[bot] <37223003+trop[bot]@users.noreply.github.com>
Co-authored-by: Kyle Cutler <kycutler@microsoft.com>
2026-03-18 19:12:31 -04:00
trop[bot]
87baa17e65 fix: ensure WebContents::WasShown runs when window is shown (#50341)
Avoids a freeze when failing to enter fullscreen on macOS.

Co-authored-by: trop[bot] <37223003+trop[bot]@users.noreply.github.com>
Co-authored-by: John Beutner <beutner.john@gmail.com>
2026-03-18 14:57:20 -04:00
trop[bot]
e6928c1319 fix: user resizable transparent windows on win32 (#50300)
test: revert win32 frameless and transparent resizable expectations

Co-authored-by: trop[bot] <37223003+trop[bot]@users.noreply.github.com>
Co-authored-by: Justin Mayfield <tooker@gmail.com>
2026-03-17 09:46:38 +01:00
trop[bot]
976a7bece5 fix: add ASAR support to additional copy methods (#50284)
* fix: add ASAR support for additional copy methods

Co-authored-by: Noah Gregory <noahmgregory@gmail.com>

* test: add tests for ASAR support for additional copy messages

Co-authored-by: Noah Gregory <noahmgregory@gmail.com>

---------

Co-authored-by: trop[bot] <37223003+trop[bot]@users.noreply.github.com>
Co-authored-by: Noah Gregory <noahmgregory@gmail.com>
2026-03-16 12:55:29 -04:00
trop[bot]
03244a56f1 ci: update actions/cache to 5.0.3 (#50237)
chore: update actions/cache to 5.0.3

Needed due to https://github.blog/changelog/2025-09-19-deprecation-of-node-20-on-github-actions-runners/

Co-authored-by: trop[bot] <37223003+trop[bot]@users.noreply.github.com>
Co-authored-by: John Kleinschmidt <kleinschmidtorama@gmail.com>
2026-03-13 15:01:38 -04:00
Keeley Hammond
8e0f534873 chore: cherry-pick d5b0cb2acffe from v8 (#50232)
* chore: cherry-pick d5b0cb2acffe from v8

* chore: update patches

---------

Co-authored-by: Samuel Attard <sattard@anthropic.com>
2026-03-13 02:54:53 +00:00
Keeley Hammond
1573d6b28c chore: cherry-pick 7911bee5d90e from skia (#50230)
* chore: cherry-pick 7911bee5d90e from skia

* chore: update patch
2026-03-12 21:49:05 -04:00
John Kleinschmidt
1b3e1433dd ci: update actions/checkout to v6.0.2 (#50223)
* ci: update actions/checkout to v6.0.2

* ci: link node 24 for linux arm testing

(cherry picked from commit 7421434936)
2026-03-12 21:24:38 -04:00
John Kleinschmidt
e551cf8c00 ci: add timeout to test step (#50212)
ci: add timeout to test step (#50186)

Additionally, take a screenshot on timeout so that we can debug why there is a hang
2026-03-12 14:43:58 +01:00
trop[bot]
bd3abf3a2c fix: preserve staged update dir when pruning orphaned updates on macOS (#50215)
fix: preserve staged update dir when pruning orphaned update dirs on macOS

The previous squirrel.mac patch cleaned up all staged update directories
before starting a new download. This kept disk usage bounded but broke
quitAndInstall() if called while a subsequent checkForUpdates() was in
flight — the already-staged bundle would be deleted out from under it.

This reworks the patch to read ShipItState.plist and preserve the
directory it references, deleting only truly orphaned update.XXXXXXX
directories. Disk footprint stays bounded (at most 2 dirs: staged +
in-progress) and quitAndInstall() remains safe mid-check.

Also adds test coverage for the quitAndInstall/checkForUpdates race and
a triple-stack scenario where 3 updates arrive without a restart.

Refs https://github.com/electron/electron/issues/50200

Co-authored-by: trop[bot] <37223003+trop[bot]@users.noreply.github.com>
Co-authored-by: Samuel Attard <sattard@anthropic.com>
2026-03-12 01:51:35 +00:00
trop[bot]
da140aea7c fix: prevent traffic light buttons flashing on deminiaturize (#50208)
* fix: prevent traffic light buttons flashing on deminiaturize

When a window with a custom `trafficLightPosition` is minimized and
restored, macOS re-layouts the title bar container during the
deminiaturize animation, causing the traffic light buttons to briefly
appear at their default position before being repositioned.

Fix this by hiding the buttons container in `windowWillMiniaturize` and
restoring them (with a redraw to the correct position) in
`windowDidDeminiaturize`.

Co-authored-by: Shelley Vohr <shelley.vohr@gmail.com>

* chore: address feedback from review

Co-authored-by: Shelley Vohr <shelley.vohr@gmail.com>

---------

Co-authored-by: trop[bot] <37223003+trop[bot]@users.noreply.github.com>
Co-authored-by: Shelley Vohr <shelley.vohr@gmail.com>
2026-03-11 15:37:00 -04:00
trop[bot]
8699ce4f98 fix: don't call TaskDialogIndirect with disabled parent windows (#50190)
Co-authored-by: trop[bot] <37223003+trop[bot]@users.noreply.github.com>
Co-authored-by: Noah Gregory <noahmgregory@gmail.com>
2026-03-10 16:59:29 -04:00
trop[bot]
5fded6ae88 fix: bind offscreen paint callback to child WebContents (#50184)
fix: bind offscreen paint callback to child WebContents

Previously, MaybeOverrideCreateParamsForNewWindow bound the
OffScreenWebContentsView's paint callback to the parent WebContents
using base::Unretained(this). This was both unsafe (dangling pointer
risk if the parent is destroyed before the child) and semantically
incorrect — paint events belong to the child window, not the opener.

Replace the callback in MaybeOverrideCreateParamsForNewWindow with
base::DoNothing(), then rebind it to the child WebContents in
AddNewContents via a new SetCallback method on OffScreenWebContentsView.

Co-authored-by: trop[bot] <37223003+trop[bot]@users.noreply.github.com>
Co-authored-by: Shelley Vohr <shelley.vohr@gmail.com>
2026-03-10 14:00:14 -04:00
trop[bot]
0e6e480a8b fix: validate protocol scheme names in setAsDefaultProtocolClient (#50156)
fix: validate protocol scheme names in setAsDefaultProtocolClient

On Windows, `app.setAsDefaultProtocolClient(protocol)` directly
concatenates the protocol string into the registry key path with no
validation. A protocol name containing `\` could write to an arbitrary
subkey under `HKCU\Software\Classes\`, potentially hijacking existing
protocol handlers.

To fix this, add `Browser::IsValidProtocolScheme()` which validates that a protocol
name conforms to the RFC 3986 scheme grammar:

  scheme = ALPHA *( ALPHA / DIGIT / "+" / "-" / "." )

This rejects backslashes, forward slashes, whitespace, and any other
characters not permitted in URI schemes.

Co-authored-by: trop[bot] <37223003+trop[bot]@users.noreply.github.com>
Co-authored-by: Shelley Vohr <shelley.vohr@gmail.com>
2026-03-10 07:27:59 -04:00
Keeley Hammond
44b21205c7 chore: cherry-pick 03d405099043 from skia (#50167)
* chore: cherry-pick 03d405099043 from skia

* chore: update patch
2026-03-10 10:45:58 +01:00
electron-roller[bot]
db8e94113b chore: bump node to v22.22.1 (39-x-y) (#50100)
* chore: bump node in DEPS to v22.22.1

* chore: update patches

* chore: fixup remove_obsolete_noarraybufferzerofillscope.patch

* deps: update simdjson to 4.2.4

 https://github.com/nodejs/node/pull/61056

* fix: generate_config_gypi needs to generate valid JSON

https: //github.com/nodejs/node/pull/60794
(cherry picked from commit a1d06cdd8a)
Co-Authored-By: Shelley Vohr <shelley.vohr@gmail.com>

* src: fix off-thread cert loading in bundled cert mode

https://github.com/nodejs/node/pull/60764
(cherry picked from commit cb4deec8f0)

This test fails on boringssl incompatibilities:
https://github.com/electron/electron/pull/49744/changes#r2799802487

Co-Authored-By: Shelley Vohr <shelley.vohr@gmail.com>

* test: move sea tests into test/sea

https://github.com/nodejs/node/pull/60250
(cherry picked from commit 695929b66a)

* src: fix off-thread cert loading in bundled cert mode

nodejs/node#60764

The Node.js cli flag --use-bundled-ca is not supported in Electron

---------

Co-authored-by: electron-roller[bot] <84116207+electron-roller[bot]@users.noreply.github.com>
Co-authored-by: John Kleinschmidt <kleinschmidtorama@gmail.com>
Co-authored-by: Shelley Vohr <shelley.vohr@gmail.com>
Co-authored-by: John Kleinschmidt <jkleinsc@electronjs.org>
2026-03-10 10:45:51 +01:00
Samuel Attard
db7ed2bfc9 fix: correct parsing of second-instance additionalData (#50174)
- POSIX: validate StringToSizeT result and token count when splitting
  the socket message into argv and additionalData; previously a
  malformed message could produce incorrect slicing.
- Windows: base64-encode additionalData before embedding in the
  null-delimited wchar_t buffer. The prior reinterpret_cast approach
  dropped everything after the first aligned 0x0000 in the serialized
  payload, so complex objects could arrive truncated.

Manually backported from #50119
2026-03-10 10:10:50 +01:00
trop[bot]
315496c148 fix: InspectorFrontendHost override in embedded windows (#50136)
fix: InspectorFrontendHost override in embedded windows

Co-authored-by: trop[bot] <37223003+trop[bot]@users.noreply.github.com>
Co-authored-by: Shelley Vohr <shelley.vohr@gmail.com>
2026-03-10 09:55:40 +01:00
trop[bot]
842290c50f fix: use requesting frame origin in permission helper and device choosers (#50147)
* fix: use requesting frame origin instead of top-level URL for permissions

`WebContentsPermissionHelper::RequestPermission` passes
`web_contents_->GetLastCommittedURL()` as the origin to the permission
manager instead of the actual requesting frame's origin. This enables
origin confusion when granting permissions to embedded third-party iframes,
since app permission handlers see the top-level origin instead of the
iframe's. The same pattern exists in the HID, USB, and Serial device
choosers, where grants are keyed to the primary main frame's origin rather
than the requesting frame's.

Fix this by using `requesting_frame->GetLastCommittedOrigin()` in all
affected code paths, renaming `details.requestingUrl` to
`details.requestingOrigin`, and populating it with the serialized
origin only.

Co-authored-by: Shelley Vohr <shelley.vohr@gmail.com>

* chore: keep requestingUrl name in permission handler details

The previous commit changed the details.requestingUrl field to
details.requestingOrigin in permission request/check handlers. That
field was already populated from the requesting frame's RFH, so the
rename was unnecessary and would break apps that read the existing
property. Revert to requestingUrl to preserve the existing API shape.

The functional changes to use the requesting frame in
WebContentsPermissionHelper and the HID/USB/Serial choosers remain.

Co-authored-by: Samuel Attard <sattard@anthropic.com>

---------

Co-authored-by: trop[bot] <37223003+trop[bot]@users.noreply.github.com>
Co-authored-by: Shelley Vohr <shelley.vohr@gmail.com>
Co-authored-by: Samuel Attard <sattard@anthropic.com>
2026-03-09 22:16:08 -07:00
Keeley Hammond
9bf952f1c5 chore: cherry-pick a08731cf6d70 from angle (#50171) 2026-03-09 19:26:52 -05:00
Keeley Hammond
7594783ff8 fix: strictly validate sender for internal IPC reply channels (#50118) (#50161)
The sender-mismatch check in invokeInWebContents and invokeInWebFrameMain
used a negative condition (`type === 'frame' && sender !== expected`),
which only rejected mismatched frame senders and accepted anything else.

Invert to a positive check so only the exact expected frame can resolve
the reply — matches the guard style used elsewhere in lib/browser/.

Co-authored-by: Samuel Attard <sam@electronjs.org>
2026-03-09 17:15:01 -05:00
trop[bot]
f929de8896 fix: validate response header names and values before AddHeader (#50129)
Matches the existing validation applied to request headers in
electron_api_url_loader.cc.

Co-authored-by: trop[bot] <37223003+trop[bot]@users.noreply.github.com>
Co-authored-by: Samuel Attard <sattard@anthropic.com>
2026-03-09 11:40:51 -04:00
trop[bot]
37bb19a3e3 revert: updated Alt detection to explicitly exclude AltGraph/AltGr (#50109)
Revert "fix: updated Alt detection to explicitly exclude AltGraph/AltGr (#49778)"

This reverts commit 90c9de70ac.

Ref: https://github.com/electron/electron/issues/50050

Co-authored-by: trop[bot] <37223003+trop[bot]@users.noreply.github.com>
Co-authored-by: clavin <clavin@electronjs.org>
2026-03-09 11:32:20 -04:00
trop[bot]
f5016aaec0 fix: screen.getCursorScreenPoint() crash on Wayland (#50106)
* docs: document that getCursorScreenPoint() needs a Window on Wayland

Co-authored-by: Charles Kerr <charles@charleskerr.com>

* feat: add IsWayland() helper

Co-authored-by: Charles Kerr <charles@charleskerr.com>

* fix: Wayland crash in GetCursorScreenPoint()

fix: support Screen::GetCursorScreenPoint() on X11

Co-authored-by: Charles Kerr <charles@charleskerr.com>

---------

Co-authored-by: trop[bot] <37223003+trop[bot]@users.noreply.github.com>
Co-authored-by: Charles Kerr <charles@charleskerr.com>
2026-03-08 19:20:30 +01:00
trop[bot]
17697b193d docs: cleanup desktop-capturer doc after chromium audio capture additions (#50112)
* docs: cleanup desktop-capturer doc after chromium audio capture additions

Co-authored-by: Michaela Laurencin <mlaurencin@electronjs.org>

* Apply suggestions from code review

Co-authored-by: Erick Zhao <erick@hotmail.ca>

Co-authored-by: Michaela Laurencin <35157522+mlaurencin@users.noreply.github.com>

* disable linter for list in note

Co-authored-by: Michaela Laurencin <35157522+mlaurencin@users.noreply.github.com>

---------

Co-authored-by: trop[bot] <37223003+trop[bot]@users.noreply.github.com>
Co-authored-by: Michaela Laurencin <mlaurencin@electronjs.org>
Co-authored-by: Michaela Laurencin <35157522+mlaurencin@users.noreply.github.com>
2026-03-06 15:47:05 -05:00
trop[bot]
3679fd56e7 fix: prevent use-after-free in PowerMonitor via dangling OS callbacks (#50089)
PowerMonitor registered OS-level callbacks (HWND UserData and
WTS/suspend notifications on Windows, shutdown handler and lock-screen
observer on macOS) but never cleaned them up in its destructor. The JS
layer also only held the native object in a closure-local variable,
allowing GC to reclaim it while those registrations still referenced
freed memory.

Retain the native PowerMonitor at module level in power-monitor.ts so
it cannot be garbage-collected. Add DestroyPlatformSpecificMonitors()
to properly tear down OS registrations on destruction: on Windows,
unregister WTS and suspend notifications, clear GWLP_USERDATA, and
destroy the HWND; on macOS, remove the emitter from the global
MacLockMonitor and reset the Browser shutdown handler.

Co-authored-by: trop[bot] <37223003+trop[bot]@users.noreply.github.com>
Co-authored-by: Shelley Vohr <shelley.vohr@gmail.com>
2026-03-05 17:20:30 -05:00
trop[bot]
09a028cf8b fix: avoid redundant page-favicon-updated events on setBounds (#50086)
* fix: avoid duplicate calls in electron_api_web_contents

Co-authored-by: ANANYA542 <ananyashrma6512@gmail.com>

* Style: fix lint errors

Co-authored-by: ANANYA542 <ananyashrma6512@gmail.com>

* fix: prevent duplicate page-favicon-updated events and add regression test

Co-authored-by: Ananya542 <ananyashrma6512@gmail.com>

---------

Co-authored-by: trop[bot] <37223003+trop[bot]@users.noreply.github.com>
Co-authored-by: ANANYA542 <ananyashrma6512@gmail.com>
2026-03-05 17:14:09 +01:00
trop[bot]
d0978d2812 build: fix code-signing for MacOS x64 tests (#50071)
* fix: code-sign binaries for notification tests

Co-authored-by: Keeley Hammond <khammond@slack-corp.com>

* test: remove redundent feedURL test

Co-authored-by: Keeley Hammond <khammond@slack-corp.com>

* test: move squirrel feed tests to api-autoupdater

Co-authored-by: Keeley Hammond <khammond@slack-corp.com>

* fix: fix SQRLShipItRequest.JSONKeyPathsByPropertyKey mappings

Co-authored-by: Keeley Hammond <khammond@slack-corp.com>

* Revert "fix: fix SQRLShipItRequest.JSONKeyPathsByPropertyKey mappings"

This reverts commit 5ad9892a67.

Co-authored-by: Keeley Hammond <khammond@slack-corp.com>

* test: unsign tests requiring no signed app

Co-authored-by: Keeley Hammond <khammond@slack-corp.com>

* fixup! fix: fix SQRLShipItRequest.JSONKeyPathsByPropertyKey mappings

chore: fix patch shear

---------

Co-authored-by: trop[bot] <37223003+trop[bot]@users.noreply.github.com>
Co-authored-by: Keeley Hammond <khammond@slack-corp.com>
Co-authored-by: Charles Kerr <charles@charleskerr.com>
2026-03-05 11:14:06 -05:00
trop[bot]
143faed926 fix: use proper quoting for exe paths and args on Windows (#50074)
Previously, GetProtocolLaunchPath and FormatCommandLineString in
browser_win.cc used naive quoting which could break when paths or
arguments contained backslashes, spaces, or embedded quotes.

Fix by extracting the CommandLineToArgvW-compatible quoting logic from
relauncher_win.cc into a shared utility and use it in both browser_win.cc
and relauncher_win.cc to properly quote the exe path and each argument
individually.

Co-authored-by: trop[bot] <37223003+trop[bot]@users.noreply.github.com>
Co-authored-by: Shelley Vohr <shelley.vohr@gmail.com>
2026-03-04 13:37:46 -06:00
trop[bot]
3e6086d930 fix: menu bar hiding on two setFullscreen(false) (#49995)
* test: add failing test for `setFullscreen(false)`

`setFullscreen(false)` should do nothing
when not already in fullscreen, but it hides the menu bar
on Linux.

Co-authored-by: WofWca <wofwca@protonmail.com>

* fix: menu bar hiding on two setFullScreen(false)

This fixes the following bug on Linux (and maybe macOS):
1. Create a window with a menu bar.
2. Call `win.setFullScreen(false)`.

The menu bar will hide.

See the original bug in our project:
https://github.com/deltachat/deltachat-desktop/issues/4752.

Co-authored-by: WofWca <wofwca@protonmail.com>

---------

Co-authored-by: trop[bot] <37223003+trop[bot]@users.noreply.github.com>
Co-authored-by: WofWca <wofwca@protonmail.com>
2026-03-04 14:06:35 -05:00
trop[bot]
7549704f1a chore: remove applescript from trash (#50064)
Previously, when trashItemAtURL: failed (e.g. on network shares or
under app translocation), the code fell back to constructing an
AppleScript that interpolated the bundle path directly into a string
literal via %@ with no escaping. This was fragile and unnecessary —
trashItemAtURL: has been the standard API since 10.8 and covers the
relevant cases. The fix simply removes the AppleScript fallback
entirely, so Trash() now returns the result of trashItemAtURL: directly.

Co-authored-by: trop[bot] <37223003+trop[bot]@users.noreply.github.com>
Co-authored-by: Shelley Vohr <shelley.vohr@gmail.com>
2026-03-04 16:42:13 +01:00
trop[bot]
48c473fa06 fix: uaf in non-client hittest during view teardown (#50054)
* fix: uaf in non-client hittest during view teardown

Co-authored-by: deepak1556 <hop2deep@gmail.com>

* chore: update crash spec

Co-authored-by: deepak1556 <hop2deep@gmail.com>

---------

Co-authored-by: trop[bot] <37223003+trop[bot]@users.noreply.github.com>
Co-authored-by: deepak1556 <hop2deep@gmail.com>
2026-03-04 16:14:35 +01:00
trop[bot]
69c8cbf259 fix: prevent use-after-free in permission request callbacks (#50035)
EnterFullscreenModeForTab, RequestPointerLock, and RequestKeyboardLock
bind callbacks with base::Unretained(this); fullscreen also captures a
raw RenderFrameHost*. These callbacks may be invoked by the app's JS
permission handler after the WebContents or RenderFrameHost is destroyed.

Use GetWeakPtr() in all three call sites, and capture a
GlobalRenderFrameHostToken instead of the raw RenderFrameHost* for
fullscreen so the pointer is resolved and null-checked only when the
callback fires. Cancel in-flight permission requests from ~WebContents()
via a new ElectronPermissionManager::CancelPendingRequests()` so stale
callbacks are never handed back to JS.

Co-authored-by: trop[bot] <37223003+trop[bot]@users.noreply.github.com>
Co-authored-by: Shelley Vohr <shelley.vohr@gmail.com>
2026-03-03 09:13:37 -05:00
trop[bot]
c7f44f4101 fix: validate USB device selection against filtered device list (#50047)
Previously, UsbChooserController::OnDeviceChosen looked up the chosen
device_id via chooser_context_->GetDeviceInfo(), which searches all
known USB devices on the system rather than the filtered list shown to
the select-usb-device handler. This meant a device excluded by the
renderer's filters or exclusion_filters could still be granted
permission if the handler returned its GUID.

Co-authored-by: trop[bot] <37223003+trop[bot]@users.noreply.github.com>
Co-authored-by: Shelley Vohr <shelley.vohr@gmail.com>
2026-03-03 09:07:20 -05:00
trop[bot]
a369ec963b chore: remove unused commandLineSwitches flag (#50013)
chore: remove unused commandLineSwitches flag

Co-authored-by: trop[bot] <37223003+trop[bot]@users.noreply.github.com>
Co-authored-by: Shelley Vohr <shelley.vohr@gmail.com>
2026-03-03 10:45:35 +01:00
trop[bot]
4544b97e28 fix: use destination context when wrapping VideoFrame in contextBridge (#50021)
Enter the destination context scope before creating the VideoFrame V8
wrapper, matching the sibling Element and Blob branches. Without this,
ScriptState::ForCurrentRealm resolved to the calling context instead of
the target context, producing an incorrect wrapper.

Also switch to ScriptState::From with an explicit context argument to
make the intent clearer.

Adds spec coverage for VideoFrame crossing the bridge in both
directions and adds VideoFrame to the existing prototype checks.

Co-authored-by: trop[bot] <37223003+trop[bot]@users.noreply.github.com>
Co-authored-by: Samuel Attard <sattard@anthropic.com>
2026-03-02 23:30:46 -08:00
trop[bot]
277164fc20 fix: use setter's creation context when proxying setter in OverrideGlobalPropertyFromIsolatedWorld (#50019)
The setter branch was deriving source_context from getter-> instead of
setter->. Currently latent since the only call site passes both from
the same preload context, but this would crash or mis-resolve if a
future call site passed a setter without a getter or from a different
context.

Co-authored-by: trop[bot] <37223003+trop[bot]@users.noreply.github.com>
Co-authored-by: Samuel Attard <sattard@anthropic.com>
2026-03-02 20:47:56 -08:00
trop[bot]
41377f9467 build: authenticate curl requests to googlesource in lint workflow (#50026)
fix: authenticate curl requests to googlesource in lint workflow

The "Download GN Binary" and "Download clang-format Binary" steps
fetch files from chromium.googlesource.com without passing
authentication cookies. When googlesource rate-limits or returns a
transient error (502), the HTML error page is piped into `base64 -d`,
causing `base64: invalid input`.

The `set-chromium-cookie` action already configures `~/.gitcookies`
in a prior step. Pass `-b ~/.gitcookies` to both `curl` calls so
they authenticate, matching what the cookie verification step itself
does.

Co-authored-by: trop[bot] <37223003+trop[bot]@users.noreply.github.com>
Co-authored-by: Shelley Vohr <shelley.vohr@gmail.com>
2026-03-02 18:39:44 -05:00
trop[bot]
08e0583889 fix: potential UAF in OnDownloadPathGenerated (#50009)
fix: potential UAF in OnDownloadPathGenerated

Co-authored-by: trop[bot] <37223003+trop[bot]@users.noreply.github.com>
Co-authored-by: Shelley Vohr <shelley.vohr@gmail.com>
2026-03-02 18:36:42 -05:00
trop[bot]
6af676f473 fix: delete temporary blink* globals after restoring Blink implementations (#50000)
ElectronRendererClient::DidCreateScriptContext (and the worker
equivalent) save Blink's fetch/Response/FormData/Request/Headers/
EventSource as temporary globalThis.blink* properties before Node
initialization may overwrite them. node/init.ts and worker/init.ts
restore the originals but previously never deleted the temporary
blink* globals.

They persisted as non-standard global pollution visible to page
content when contextIsolation is disabled -- a minor fingerprinting
signal and a bypass for any preload that wraps window.fetch (page
could call blinkfetch() instead).

Co-authored-by: trop[bot] <37223003+trop[bot]@users.noreply.github.com>
Co-authored-by: Samuel Attard <sattard@anthropic.com>
2026-03-02 11:30:38 -05:00
trop[bot]
2973952857 fix: deliver Universal Links when NSUserActivity.userInfo is nil (#50004)
* fix(mac): deliver Universal Links when NSUserActivity.userInfo is nil

Co-authored-by: Dante Issaias <dante@issaias.com>

* chore: format

Co-authored-by: Dante Issaias <dante@issaias.com>

---------

Co-authored-by: trop[bot] <37223003+trop[bot]@users.noreply.github.com>
Co-authored-by: Dante Issaias <dante@issaias.com>
2026-03-02 11:26:07 -05:00
trop[bot]
a5f098d2b7 feat: add support for --experimental-transform-types (#49881)
* feat: add support for `--experimental-transform-types`

Co-authored-by: Niklas Wenzel <dev@nikwen.de>

* chore: add tests

Co-authored-by: Niklas Wenzel <dev@nikwen.de>

* docs: add `--experimental-transform-types` to docs

Co-authored-by: Niklas Wenzel <dev@nikwen.de>

---------

Co-authored-by: trop[bot] <37223003+trop[bot]@users.noreply.github.com>
Co-authored-by: Niklas Wenzel <dev@nikwen.de>
2026-02-25 12:57:48 -05:00
trop[bot]
74856fdd47 build: exit upload with error code if github upload fails (#49943)
Co-authored-by: trop[bot] <37223003+trop[bot]@users.noreply.github.com>
Co-authored-by: John Kleinschmidt <kleinschmidtorama@gmail.com>
2026-02-25 11:39:26 -05:00
trop[bot]
d733f01f3b fix: apply zoomFactor from setWindowOpenHandler to window.open() windows (#49910)
fix: apply zoomFactor from setWindowOpenHandler to window.open() windows

Co-authored-by: trop[bot] <37223003+trop[bot]@users.noreply.github.com>
Co-authored-by: Shelley Vohr <shelley.vohr@gmail.com>
2026-02-24 18:01:00 -05:00
trop[bot]
8a42df2b63 docs: fix some string enum typings (#49932)
Co-authored-by: trop[bot] <37223003+trop[bot]@users.noreply.github.com>
Co-authored-by: David Sanders <dsanders11@ucsbalum.com>
2026-02-24 11:18:59 -05:00
trop[bot]
47e54e38de fix: updated Alt detection to explicitly exclude AltGraph/AltGr (#49914)
fix: updated Alt detection to explicitly exclude AltGraph/AltGr (#49778)

Updated Alt detection to explicitly exclude AltGraph/AltGr

Co-authored-by: trop[bot] <37223003+trop[bot]@users.noreply.github.com>
Co-authored-by: Shashwat Raj <65155843+darthvader58@users.noreply.github.com>
2026-02-23 15:29:37 -08:00
trop[bot]
6ad3726bfa fix: prevent GBytes leak in GdkPixbufFromSkBitmap on Linux/GTK (#49896)
Inside gtk_util::GdkPixbufFromSkBitmap, g_bytes_new() was called
inline as an argument to gdk_pixbuf_new_from_bytes(), which per
GTK docs does not take ownership of the GBytes - it adds its own
internal reference. The caller's GBytes* was never stored or
unreffed, leaking 4 x width x height bytes of pixel data on every
call.

Co-authored-by: trop[bot] <37223003+trop[bot]@users.noreply.github.com>
Co-authored-by: redeemer <marcin.probola@gmail.com>
2026-02-20 14:58:00 -08:00
trop[bot]
a9c0dc5d6c fix: refresh menu item state on key equivalent dispatch (#49888)
Co-authored-by: trop[bot] <37223003+trop[bot]@users.noreply.github.com>
Co-authored-by: Shelley Vohr <shelley.vohr@gmail.com>
2026-02-20 14:59:32 -05:00
trop[bot]
6b0aef1d59 ci: log mocha retries in spec runner (#49879)
Co-authored-by: trop[bot] <37223003+trop[bot]@users.noreply.github.com>
Co-authored-by: Nilay Arya <84241885+nilayarya@users.noreply.github.com>
2026-02-19 17:54:42 -06:00
Sam Maddock
e54b5eec81 fix: frameless window resize in MAS builds (#49861)
fix: frameless window resize in MAS builds (#49780)

Co-authored-by: Shelley Vohr <shelley.vohr@gmail.com>
2026-02-19 09:53:55 +01:00
trop[bot]
79f164a724 docs: note required windows in 'new-window-for-tab' event (#49858)
docs: note required windows in new-window-for-tab

Co-authored-by: trop[bot] <37223003+trop[bot]@users.noreply.github.com>
Co-authored-by: Shelley Vohr <shelley.vohr@gmail.com>
2026-02-18 20:35:19 -08:00
trop[bot]
0bcaabff0c feat: add support for long-animation-frame script attribution (#49771)
* feat: add support for `long-animation-frame` script attribution

Co-authored-by: Niklas Wenzel <dev@nikwen.de>

* docs: document `AlwaysLogLOAFURL`

Co-authored-by: Niklas Wenzel <dev@nikwen.de>

* chore: add test

Co-authored-by: Niklas Wenzel <dev@nikwen.de>

* docs: adjust docs as per PR comment

Co-authored-by: Niklas Wenzel <dev@nikwen.de>

* fix: test failures

Co-authored-by: Niklas Wenzel <dev@nikwen.de>

* chore: simplify test

Co-authored-by: Niklas Wenzel <dev@nikwen.de>

* fix: tests on Windows and Linux

Co-authored-by: Niklas Wenzel <dev@nikwen.de>

* chore: fixup patches

---------

Co-authored-by: trop[bot] <37223003+trop[bot]@users.noreply.github.com>
Co-authored-by: Niklas Wenzel <dev@nikwen.de>
2026-02-18 16:19:21 -05:00
trop[bot]
2ffb9e1e05 fix: draggable region position with docked DevTools (#49846)
Co-authored-by: trop[bot] <37223003+trop[bot]@users.noreply.github.com>
Co-authored-by: Shelley Vohr <shelley.vohr@gmail.com>
2026-02-18 15:01:01 -05:00
trop[bot]
02e6c95754 build: use spawn instead of spawnSync for build (#49829)
Co-authored-by: trop[bot] <37223003+trop[bot]@users.noreply.github.com>
Co-authored-by: John Kleinschmidt <kleinschmidtorama@gmail.com>
2026-02-18 12:34:35 +01:00
trop[bot]
46e18e8263 docs: fix typos across tutorial documentation (#49834)
Co-authored-by: trop[bot] <37223003+trop[bot]@users.noreply.github.com>
Co-authored-by: ron <ronald_eddy@yahoo.com>
2026-02-17 15:05:01 -05:00
trop[bot]
4b6eb69fd0 chore: add Copilot CLI instructions (#49820)
chore: add copilot-instructions

Co-authored-by: trop[bot] <37223003+trop[bot]@users.noreply.github.com>
Co-authored-by: John Kleinschmidt <kleinschmidtorama@gmail.com>
2026-02-17 13:27:08 -05:00
200 changed files with 4768 additions and 943 deletions

View File

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

View File

@@ -15,7 +15,7 @@ runs:
git config --global core.preloadindex true
git config --global core.longpaths true
fi
export BUILD_TOOLS_SHA=4430e4a505e0f4fa2a41b707a10a36f780bbdd26
export BUILD_TOOLS_SHA=a0cc95a1884a631559bcca0c948465b725d9295a
npm i -g @electron/build-tools
# Update depot_tools to ensure python
e d update_depot_tools

View File

@@ -7,7 +7,7 @@ runs:
shell: bash
id: yarn-cache-dir-path
run: echo "dir=$(node src/electron/script/yarn.js config get cacheFolder)" >> $GITHUB_OUTPUT
- uses: actions/cache@5a3ec84eff668545956fd18022155c47e93e2684 # v4.2.3
- uses: actions/cache@cdf6c1fa76f9f475f3d7449005a359c84ca0f306 # v5.0.3
id: yarn-cache
with:
path: ${{ steps.yarn-cache-dir-path.outputs.dir }}

122
.github/copilot-instructions.md vendored Normal file
View File

@@ -0,0 +1,122 @@
# Copilot Instructions for Electron
## Build System
Electron uses `@electron/build-tools` (`e` CLI). Install with `npm i -g @electron/build-tools`.
```bash
e sync # Fetch sources and apply patches
e build # Build Electron (GN + Ninja)
e build -k 999 # Build, continuing through errors
e start # Run built Electron
e start --version # Verify Electron launches
e test # Run full test suite
e debug # Run in debugger (lldb on macOS, gdb on Linux)
```
### Linting
```bash
npm run lint # Run all linters (JS, C++, Python, GN, docs)
npm run lint:js # JavaScript/TypeScript only
npm run lint:clang-format # C++ formatting only
npm run lint:cpp # C++ linting only
npm run lint:docs # Documentation only
```
### Running a Single Test
```bash
npm run test -- -g "pattern" # Run tests matching a regex pattern
# Example: npm run test -- -g "ipc"
```
### Running a Single Node.js Test
```bash
node script/node-spec-runner.js parallel/test-crypto-keygen
```
## Architecture
Electron embeds Chromium (rendering) and Node.js (backend) to enable desktop apps with web technologies. The parent directory (`../`) is the Chromium source tree.
### Process Model
Electron has two primary process types, mirroring Chromium:
- **Main process** (`shell/browser/` + `lib/browser/`): Controls app lifecycle, creates windows, system APIs
- **Renderer process** (`shell/renderer/` + `lib/renderer/`): Runs web content in BrowserWindows
### Native ↔ JavaScript Bridge
Each API is implemented as a C++/JS pair:
- C++ side: `shell/browser/api/electron_api_{name}.cc/.h` — uses `gin::Wrappable` and `ObjectTemplateBuilder`
- JS side: `lib/browser/api/{name}.ts` — exports the module, registered in `lib/browser/api/module-list.ts`
- Binding: `NODE_LINKED_BINDING_CONTEXT_AWARE(electron_browser_{name}, Initialize)` in C++ and registered in `shell/common/node_bindings.cc`
- Type declaration: `typings/internal-ambient.d.ts` maps `process._linkedBinding('electron_browser_{name}')`
### Patches System
Electron patches upstream dependencies (Chromium, Node.js, V8, etc.) rather than forking them. Patches live in `patches/` organized by target, with `patches/config.json` mapping directories to repos.
```text
patches/{target}/*.patch → [e sync] → target repo commits
← [e patches] ←
```
Key rules:
- Fix existing patches rather than creating new ones
- Preserve original authorship in TODO comments — never change `TODO(name)` assignees
- Each patch commit message must explain why the patch exists
- After modifying patches, run `e patches {target}` to export
When working on the `roller/chromium/main` branch for Chromium upgrades, use `e sync --3` for 3-way merge conflict resolution.
## Conventions
### File Naming
- JS/TS files: kebab-case (`file-name.ts`)
- C++ files: snake_case with `electron_api_` prefix (`electron_api_safe_storage.cc`)
- Test files: `api-{module-name}-spec.ts` in `spec/`
- Source file lists are maintained in `filenames.gni` (with platform-specific sections)
### JavaScript/TypeScript
- Semicolons required (`"semi": ["error", "always"]`)
- `const` and `let` only (no `var`)
- Arrow functions preferred
- Import order enforced: `@electron/internal``@electron``electron` → external → builtin → relative
- API naming: `PascalCase` for classes (`BrowserWindow`), `camelCase` for module APIs (`globalShortcut`)
- Prefer getters/setters over jQuery-style `.text([text])` patterns
### C++
- Follows Chromium coding style, enforced by `clang-format` and `clang-tidy`
- Uses Chromium abstractions (`base::`, `content::`, etc.)
- Header guards: `#ifndef ELECTRON_SHELL_BROWSER_API_ELECTRON_API_{NAME}_H_`
- Platform-specific files: `_mac.mm`, `_win.cc`, `_linux.cc`
### Testing
- Framework: Mocha + Chai + Sinon
- Test helpers in `spec/lib/` (e.g., `spec-helpers.ts`, `window-helpers.ts`)
- Use `defer()` from spec-helpers for cleanup, `closeAllWindows()` for window teardown
- Tests import from `electron/main` or `electron/renderer`
### Documentation
- API docs in `docs/api/` as Markdown, parsed by `@electron/docs-parser` to generate `electron.d.ts`
- API history tracked via YAML blocks in HTML comments within doc files
- Docs must pass `npm run lint:docs`
### Build Configuration
- `BUILD.gn`: Main GN build config
- `buildflags/buildflags.gni`: Feature flags (PDF viewer, extensions, spellchecker)
- `build/args/`: Build argument profiles (`testing.gn`, `release.gn`, `all.gn`)
- `DEPS`: Dependency versions and checkout paths
- `chromium_src/`: Chromium source file overrides (compiled instead of originals)

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

@@ -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
@@ -46,7 +46,7 @@ jobs:
shell: bash
run: |
chromium_revision="$(grep -A1 chromium_version src/electron/DEPS | tr -d '\n' | cut -d\' -f4)"
gn_version="$(curl -sL "https://chromium.googlesource.com/chromium/src/+/${chromium_revision}/DEPS?format=TEXT" | base64 -d | grep gn_version | head -n1 | cut -d\' -f4)"
gn_version="$(curl -sL -b ~/.gitcookies "https://chromium.googlesource.com/chromium/src/+/${chromium_revision}/DEPS?format=TEXT" | base64 -d | grep gn_version | head -n1 | cut -d\' -f4)"
cipd ensure -ensure-file - -root . <<-CIPD
\$ServiceURL https://chrome-infra-packages.appspot.com/
@@ -62,7 +62,7 @@ jobs:
chromium_revision="$(grep -A1 chromium_version src/electron/DEPS | tr -d '\n' | cut -d\' -f4)"
mkdir -p src/buildtools
curl -sL "https://chromium.googlesource.com/chromium/src/+/${chromium_revision}/buildtools/DEPS?format=TEXT" | base64 -d > src/buildtools/DEPS
curl -sL -b ~/.gitcookies "https://chromium.googlesource.com/chromium/src/+/${chromium_revision}/buildtools/DEPS?format=TEXT" | base64 -d > src/buildtools/DEPS
gclient sync --spec="solutions=[{'name':'src/buildtools','url':None,'deps_file':'DEPS','custom_vars':{'process_deps':True},'managed':False}]"
- name: Add problem matchers

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

2
DEPS
View File

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

View File

@@ -250,7 +250,9 @@ Returns:
Emitted when the user clicks the native macOS new tab button. The new
tab button is only visible if the current `BrowserWindow` has a
`tabbingIdentifier`
`tabbingIdentifier`.
You must create a window in this handler in order for macOS tabbing to work as expected.
### Event: 'browser-window-blur'
@@ -1315,7 +1317,7 @@ Returns `boolean` - Whether the current desktop environment is Unity launcher.
### `app.getLoginItemSettings([options])` _macOS_ _Windows_
* `options` Object (optional)
* `type` string (optional) _macOS_ - Can be one of `mainAppService`, `agentService`, `daemonService`, or `loginItemService`. Defaults to `mainAppService`. Only available on macOS 13 and up. See [app.setLoginItemSettings](app.md#appsetloginitemsettingssettings-macos-windows) for more information about each type.
* `type` string (optional) _macOS_ - Can be `mainAppService`, `agentService`, `daemonService`, or `loginItemService`. Defaults to `mainAppService`. Only available on macOS 13 and up. See [app.setLoginItemSettings](app.md#appsetloginitemsettingssettings-macos-windows) for more information about each type.
* `serviceName` string (optional) _macOS_ - The name of the service. Required if `type` is non-default. Only available on macOS 13 and up.
* `path` string (optional) _Windows_ - The executable path to compare against. Defaults to `process.execPath`.
* `args` string[] (optional) _Windows_ - The command-line arguments to compare against. Defaults to an empty array.
@@ -1330,13 +1332,13 @@ Returns `Object`:
* `wasOpenedAtLogin` boolean _macOS_ - `true` if the app was opened at login automatically.
* `wasOpenedAsHidden` boolean _macOS_ _Deprecated_ - `true` if the app was opened as a hidden login item. This indicates that the app should not open any windows at startup. This setting is not available on [MAS builds][mas-builds] or on macOS 13 and up.
* `restoreState` boolean _macOS_ _Deprecated_ - `true` if the app was opened as a login item that should restore the state from the previous session. This indicates that the app should restore the windows that were open the last time the app was closed. This setting is not available on [MAS builds][mas-builds] or on macOS 13 and up.
* `status` string _macOS_ - can be one of `not-registered`, `enabled`, `requires-approval`, or `not-found`.
* `status` string _macOS_ - can be `not-registered`, `enabled`, `requires-approval`, or `not-found`.
* `executableWillLaunchAtLogin` boolean _Windows_ - `true` if app is set to open at login and its run key is not deactivated. This differs from `openAtLogin` as it ignores the `args` option, this property will be true if the given executable would be launched at login with **any** arguments.
* `launchItems` Object[] _Windows_
* `name` string _Windows_ - name value of a registry entry.
* `path` string _Windows_ - The executable to an app that corresponds to a registry entry.
* `args` string[] _Windows_ - the command-line arguments to pass to the executable.
* `scope` string _Windows_ - one of `user` or `machine`. Indicates whether the registry entry is under `HKEY_CURRENT USER` or `HKEY_LOCAL_MACHINE`.
* `scope` string _Windows_ - can be `user` or `machine`. Indicates whether the registry entry is under `HKEY_CURRENT USER` or `HKEY_LOCAL_MACHINE`.
* `enabled` boolean _Windows_ - `true` if the app registry key is startup approved and therefore shows as `enabled` in Task Manager and Windows settings.
### `app.setLoginItemSettings(settings)` _macOS_ _Windows_

View File

@@ -351,7 +351,11 @@ Emitted when the window has closed a sheet.
#### Event: 'new-window-for-tab' _macOS_
Emitted when the native new tab button is clicked.
Emitted when the user clicks the native macOS new tab button. The new
tab button is only visible if the current `BrowserWindow` has a
`tabbingIdentifier`.
You must create a window in this handler in order for macOS tabbing to work as expected.
#### Event: 'system-context-menu' _Windows_ _Linux_

View File

@@ -435,7 +435,11 @@ Emitted when the window has closed a sheet.
#### Event: 'new-window-for-tab' _macOS_
Emitted when the native new tab button is clicked.
Emitted when the user clicks the native macOS new tab button. The new
tab button is only visible if the current `BrowserWindow` has a
`tabbingIdentifier`.
You must create a window in this handler in order for macOS tabbing to work as expected.
#### Event: 'system-context-menu' _Windows_ _Linux_

View File

@@ -345,6 +345,11 @@ Affects the default output directory of [v8.setHeapSnapshotNearHeapLimit](https:
Disable exposition of [Navigator API][] on the global scope from Node.js.
### `--experimental-transform-types`
Enables the [transformation](https://nodejs.org/api/typescript.html#type-stripping)
of TypeScript-only syntax into JavaScript code.
## Chromium Flags
There isn't a documented list of all Chromium switches, but there are a few ways to find them.
@@ -361,6 +366,13 @@ Keep in mind that standalone switches can sometimes be split into individual fea
Finally, you'll need to ensure that the version of Chromium in Electron matches the version of the browser you're using to cross-reference the switches.
### Chromium features relevant to Electron apps
* `AlwaysLogLOAFURL`: enables script attribution for
[`long-animation-frame`](https://developer.mozilla.org/en-US/docs/Web/API/Performance_API/Long_animation_frame_timing)
`PerformanceObserver` events for non-http(s), non-data, non-blob URLs (such as `file:` or custom
protocol URLs).
[app]: app.md
[append-switch]: command-line.md#commandlineappendswitchswitch-value
[debugging-main-process]: ../tutorial/debugging-main-process.md

View File

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

View File

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

View File

@@ -6,7 +6,7 @@ hide_title: false
---
After creating an [application distribution](application-distribution.md), the
app's source code are usually bundled into an [ASAR archive](https://github.com/electron/asar),
app's source code is usually bundled into an [ASAR archive](https://github.com/electron/asar),
which is a simple extensive archive format designed for Electron apps. By bundling the app
we can mitigate issues around long path names on Windows, speed up `require` and conceal your source
code from cursory inspection.
@@ -134,7 +134,7 @@ underlying system calls, Electron will extract the needed file into a
temporary file and pass the path of the temporary file to the APIs to make them
work. This adds a little overhead for those APIs.
APIs that requires extra unpacking are:
APIs that require extra unpacking are:
* `child_process.execFile`
* `child_process.execFileSync`

View File

@@ -24,7 +24,7 @@ All versions of `@electron/asar` support ASAR integrity.
## How it works
Each ASAR archive contains a JSON string header. The header format includes an `integrity` object
that contain a hex encoded hash of the entire archive as well as an array of hex encoded hashes for each
that contains a hex encoded hash of the entire archive as well as an array of hex encoded hashes for each
block of `blockSize` bytes.
```json

View File

@@ -203,7 +203,7 @@ test('launch app', async () => {
})
```
After that, you will access to an instance of Playwright's `ElectronApp` class. This
After that, you will have access to an instance of Playwright's `ElectronApp` class. This
is a powerful class that has access to main process modules for example:
```js {5-10} @ts-nocheck
@@ -237,7 +237,7 @@ test('save screenshot', async () => {
})
```
Putting all this together using the Playwright test-runner, let's create a `example.spec.js`
Putting all this together using the Playwright test-runner, let's create an `example.spec.js`
test file with a single test and assertion:
```js title='example.spec.js' @ts-nocheck
@@ -377,7 +377,7 @@ class TestDriver {
module.exports = { TestDriver }
```
In your app code, can then write a simple handler to receive RPC calls:
In your app code, you can then write a simple handler to receive RPC calls:
```js title='main.js'
const METHODS = {

View File

@@ -17,7 +17,7 @@ run them, users need to go through multiple advanced and manual steps.
If you are building an Electron app that you intend to package and distribute,
it should be code signed. The Electron ecosystem tooling makes codesigning your
apps straightforward - this documentation explains how sign your apps on both
apps straightforward - this documentation explains how to sign your apps on both
Windows and macOS.
## Signing & notarizing macOS builds
@@ -210,7 +210,7 @@ const msiCreator = new MSICreator({
const supportBinaries = await msiCreator.create()
// 🆕 Step 2a: optionally sign support binaries if you
// sign you binaries as part of of your packaging script
// sign your binaries as part of your packaging script
for (const binary of supportBinaries) {
// Binaries are the new stub executable and optionally
// the Squirrel auto updater.

View File

@@ -110,7 +110,7 @@ const win = new BrowserWindow({
#### Show and hide the traffic lights programmatically _macOS_
You can also show and hide the traffic lights programmatically from the main process.
The `win.setWindowButtonVisibility` forces traffic lights to be show or hidden depending
The `win.setWindowButtonVisibility` forces traffic lights to be shown or hidden depending
on the value of its boolean parameter.
```js title='main.js'

View File

@@ -5,12 +5,12 @@
By default, windows are dragged using the title bar provided by the OS chrome. Apps
that remove the default title bar need to use the `app-region` CSS property to define
specific areas that can be used to drag the window. Setting `app-region: drag` marks
a rectagular area as draggable.
a rectangular area as draggable.
It is important to note that draggable areas ignore all pointer events. For example,
a button element that overlaps a draggable region will not emit mouse clicks or mouse
enter/exit events within that overlapping area. Setting `app-region: no-drag` reenables
pointer events by excluding a rectagular area from a draggable region.
pointer events by excluding a rectangular area from a draggable region.
To make the whole window draggable, you can add `app-region: drag` as
`body`'s style:

View File

@@ -29,7 +29,7 @@ be updated accordingly.
In macOS 10.14 Mojave, Apple introduced a new [system-wide dark mode][system-wide-dark-mode]
for all macOS computers. If your Electron app has a dark mode, you can make it
follow the system-wide dark mode setting using
[the `nativeTheme` api](../api/native-theme.md).
[the `nativeTheme` API](../api/native-theme.md).
In macOS 10.15 Catalina, Apple introduced a new "automatic" dark mode option
for all macOS computers. In order for the `nativeTheme.shouldUseDarkColors` and

View File

@@ -171,7 +171,7 @@ sections.
In the main process, we'll be creating a `handleFileOpen()` function that calls
`dialog.showOpenDialog` and returns the value of the file path selected by the user. This function
is used as a callback whenever an `ipcRender.invoke` message is sent through the `dialog:openFile`
is used as a callback whenever an `ipcRenderer.invoke` message is sent through the `dialog:openFile`
channel from the renderer process. The return value is then returned as a Promise to the original
`invoke` call.
@@ -446,7 +446,7 @@ After loading the preload script, your renderer process should have access to th
We don't directly expose the whole `ipcRenderer.on` API for [security reasons][]. Make sure to
limit the renderer's access to Electron APIs as much as possible.
Also don't just pass the callback to `ipcRenderer.on` as this will leak `ipcRenderer` via `event.sender`.
Use a custom handler that invoke the `callback` only with the desired arguments.
Use a custom handler that invokes the `callback` only with the desired arguments.
:::
:::info

View File

@@ -10,7 +10,7 @@ hide_title: false
## Accelerators
Accelerators are strings that can be used to represent keyboard shortcuts throughout your Electron.
These strings can contain multiple modifiers keys and a single key code joined by the `+` character.
These strings can contain multiple modifier keys and a single key code joined by the `+` character.
> [!NOTE]
> Accelerators are **case-insensitive**.

View File

@@ -62,9 +62,9 @@ const createWindow = () => {
}
```
In this next step, we will create our `BrowserWindow` and tell our application how to handle an event in which an external protocol is clicked.
In this next step, we will create our `BrowserWindow` and tell our application how to handle an event in which an external protocol is clicked.
This code will be different in Windows and Linux compared to MacOS. This is due to both platforms emitting the `second-instance` event rather than the `open-url` event and Windows requiring additional code in order to open the contents of the protocol link within the same Electron instance. Read more about this [here](../api/app.md#apprequestsingleinstancelockadditionaldata).
This code will be different in Windows and Linux compared to macOS. This is due to both platforms emitting the `second-instance` event rather than the `open-url` event and Windows requiring additional code in order to open the contents of the protocol link within the same Electron instance. Read more about this [here](../api/app.md#apprequestsingleinstancelockadditionaldata).
#### Windows and Linux code:
@@ -91,7 +91,7 @@ if (!gotTheLock) {
}
```
#### MacOS code:
#### macOS code:
```js @ts-type={createWindow:()=>void}
// This method will be called when Electron has finished

View File

@@ -65,7 +65,7 @@ The full list of certificate types can be found
Apps signed with "Apple Development" and "Apple Distribution" certificates can
only run under [App Sandbox][app-sandboxing], so they must use the MAS build of
Electron. However, the "Developer ID Application" certificate does not have this
restrictions, so apps signed with it can use either the normal build or the MAS
restriction, so apps signed with it can use either the normal build or the MAS
build of Electron.
#### Legacy certificate names
@@ -208,7 +208,7 @@ signAsync({
After signing the app with the "Apple Distribution" certificate, you can
continue to submit it to Mac App Store.
However, this guide do not ensure your app will be approved by Apple; you
However, this guide does not ensure your app will be approved by Apple; you
still need to read Apple's [Submitting Your App][submitting-your-app] guide on
how to meet the Mac App Store requirements.

View File

@@ -25,7 +25,7 @@ Electron application, and this property only exists on macOS.
One of the main uses for your app's Dock icon is to expose additional app menus. The Dock menu is
triggered by right-clicking or <kbd>Ctrl</kbd>-clicking the app icon. By default, the app's Dock menu
will come with system-provided window management utilities, including the ability to show all windows,
hide the app, and switch betweeen different open windows.
hide the app, and switch between different open windows.
To set an app-defined custom Dock menu, pass any [Menu](../api/menu.md) instance into the
[`dock.setMenu`](../api/dock.md#docksetmenumenu-macos) API.

View File

@@ -1339,7 +1339,7 @@ For developers wanting to learn more, you can refer to the [official N-API docum
### Putting `cpp_addon.cc` together
We've now finished the bridge part our addon - that is, the code that's most concerned with being the bridge between your JavaScript and C++ code (and by contrast, less so actually interacting with the operating system or GTK). After adding all the sections above, your `src/cpp_addon.cc` should look like this:
We've now finished the bridge part of our addon - that is, the code that's most concerned with being the bridge between your JavaScript and C++ code (and by contrast, less so actually interacting with the operating system or GTK). After adding all the sections above, your `src/cpp_addon.cc` should look like this:
```cpp title='src/cpp_addon.cc'
#include <napi.h>

View File

@@ -4,13 +4,13 @@ This tutorial builds on the [general introduction to Native Code and Electron](.
Specifically, we'll be integrating with two commonly used native Windows libraries:
* `comctl32.lib`, which contains common controls and user interface components. It provides various UI elements like buttons, scrollbars, toolbars, status bars, progress bars, and tree views. As far as GUI development on Windows goes, this library is very low-level and basic - more modern frameworks like WinUI or WPF are advanced and alternatives but require a lot more C++ and Windows version considerations than are useful for this tutorial. This way, we can avoid the many perils of building native interfaces for multiple Windows versions!
* `comctl32.lib`, which contains common controls and user interface components. It provides various UI elements like buttons, scrollbars, toolbars, status bars, progress bars, and tree views. As far as GUI development on Windows goes, this library is very low-level and basic - more modern frameworks like WinUI or WPF are more advanced alternatives but require a lot more C++ and Windows version considerations than are useful for this tutorial. This way, we can avoid the many perils of building native interfaces for multiple Windows versions!
* `shcore.lib`, a library that provides high-DPI awareness functionality and other Shell-related features around managing displays and UI elements.
This tutorial will be most useful to those who already have some familiarity with native C++ GUI development on Windows. You should have experience with basic window classes and procedures, like `WNDCLASSEXW` and `WindowProc` functions. You should also be familiar with the Windows message loop, which is the heart of any native application - our code will be using `GetMessage`, `TranslateMessage`, and `DispatchMessage` to handle messages. Lastly, we'll be using (but not explaining) standard Win32 controls like `WC_EDITW` or `WC_BUTTONW`.
> [!NOTE]
> If you're not familiar with C++ GUI development on Windows, we recommend Microsoft's excellent documentation and guides, particular for beginners. "[Get Started with Win32 and C++](https://learn.microsoft.com/en-us/windows/win32/learnwin32/learn-to-program-for-windows)" is a great introduction.
> If you're not familiar with C++ GUI development on Windows, we recommend Microsoft's excellent documentation and guides, particularly for beginners. "[Get Started with Win32 and C++](https://learn.microsoft.com/en-us/windows/win32/learnwin32/learn-to-program-for-windows)" is a great introduction.
## Requirements
@@ -1333,7 +1333,7 @@ npm run build
## Conclusion
You've now built a complete native Node.js addon for Windows using C++ and the Win32 API. Some of things we've done here are:
You've now built a complete native Node.js addon for Windows using C++ and the Win32 API. Some of the things we've done here are:
1. Creating a native Windows GUI from C++
2. Implementing a Todo list application with Add, Edit, and Delete functionality

View File

@@ -1167,7 +1167,7 @@ The approach demonstrated here allows you to:
* Setting up bidirectional communication using callbacks and events
* Configuring a custom build process to compile Swift code
For more information on developing with Swift and Swift, refer to Apple's developer documentation:
For more information on developing with Swift and SwiftUI, refer to Apple's developer documentation:
* [Swift Programming Language](https://developer.apple.com/swift/)
* [SwiftUI Framework](https://developer.apple.com/documentation/swiftui)

View File

@@ -36,7 +36,7 @@ setting.
This is an advanced feature requiring a native node module to work with your own code.
The frames are directly copied in GPU textures, thus this mode is very fast because
there's no CPU-GPU memory copies overhead, and you can directly import the shared
texture to your own rendering program. You can read more details at
texture to your own rendering program. You can read more details
[here](https://github.com/electron/electron/blob/main/shell/browser/osr/README.md).
2. Use CPU shared memory bitmap

View File

@@ -294,7 +294,7 @@ particularly useful if users complain about your app sometimes "stuttering".
Generally speaking, all advice for building performant web apps for modern
browsers apply to Electron's renderers, too. The two primary tools at your
disposal are currently `requestIdleCallback()` for small operations and
disposal are currently `requestIdleCallback()` for small operations and
`Web Workers` for long-running operations.
_`requestIdleCallback()`_ allows developers to queue up a function to be
@@ -360,7 +360,7 @@ turning into a desktop application. As web developers, we are used to loading
resources from a variety of content delivery networks. Now that you are
shipping a proper desktop application, attempt to "cut the cord" where possible
and avoid letting your users wait for resources that never change and could
easily be included in your app.
easily be included in your app.
A typical example is Google Fonts. Many developers make use of Google's
impressive collection of free fonts, which comes with a content delivery

View File

@@ -113,7 +113,7 @@ For a full list of Electron's main process modules, check out our API documentat
Each Electron app spawns a separate renderer process for each open `BrowserWindow`
(and each web embed). As its name implies, a renderer is responsible for
_rendering_ web content. For all intents and purposes, code ran in renderer processes
_rendering_ web content. For all intents and purposes, code run in renderer processes
should behave according to web standards (insofar as Chromium does, at least).
Therefore, all user interfaces and app functionality within a single browser

View File

@@ -767,7 +767,7 @@ ipcMain.handle('get-secrets', (e) => {
})
function validateSender (frame) {
// Value the host of the URL using an actual URL parser and an allowlist
// Validate the host of the URL using an actual URL parser and an allowlist
if ((new URL(frame.url)).host === 'electronjs.org') return true
return false
}

View File

@@ -2,8 +2,8 @@
Being based on Chromium, Electron requires a display driver to function.
If Chromium can't find a display driver, Electron will fail to launch -
and therefore not executing any of your tests, regardless of how you are running
them. Testing Electron-based apps on Travis, CircleCI, Jenkins or similar Systems
and therefore not execute any of your tests, regardless of how you are running
them. Testing Electron-based apps on Travis, CircleCI, Jenkins or similar systems
requires therefore a little bit of configuration. In essence, we need to use
a virtual display driver.

View File

@@ -44,7 +44,7 @@ following JSON format:
"updateTo": {
"version": "1.2.1",
"pub_date": "2023-09-18T12:29:53+01:00",
"notes": "Theses are some release notes innit",
"notes": "These are some release notes innit",
"name": "1.2.1",
"url": "https://mycompany.example.com/myapp/releases/myrelease"
}
@@ -54,7 +54,7 @@ following JSON format:
"updateTo": {
"version": "1.2.3",
"pub_date": "2024-09-18T12:29:53+01:00",
"notes": "Theses are some more release notes innit",
"notes": "These are some more release notes innit",
"name": "1.2.3",
"url": "https://mycompany.example.com/myapp/releases/myrelease3"
}
@@ -307,7 +307,7 @@ app update. All other properties in the object are optional.
{
"url": "https://your-static.storage/your-app-1.2.3-darwin.zip",
"name": "1.2.3",
"notes": "Theses are some release notes innit",
"notes": "These are some release notes innit",
"pub_date": "2024-09-18T12:29:53+01:00"
}
```

View File

@@ -149,7 +149,7 @@ for an example delay-load hook if you're implementing your own.
native Node modules with prebuilt binaries for multiple versions of Node
and Electron.
If the `prebuild`-powered module provide binaries for the usage in Electron,
If the `prebuild`-powered module provides binaries for the usage in Electron,
make sure to omit `--build-from-source` and the `npm_config_build_from_source`
environment variable in order to take full advantage of the prebuilt binaries.

View File

@@ -38,7 +38,7 @@ To test your app, use a Windows on Arm device running Windows 10 (version 1903 o
### Node.js/node-gyp
[Node.js v12.9.0 or later is recommended.](https://nodejs.org/en/) If updating to a new version of Node is undesirable, you can instead [update npm's copy of node-gyp manually](https://github.com/nodejs/node-gyp/wiki/Updating-npm's-bundled-node-gyp) to version 5.0.2 or later, which contains the required changes to compile native modules for Arm.
[Node.js v12.9.0 or later is recommended.](https://nodejs.org/en/) If updating to a new version of Node is undesirable, you can instead [update npm's copy of node-gyp manually](https://github.com/nodejs/node-gyp/wiki/Updating-npm's-bundled-node-gyp) to version 5.0.2 or later, which contains the required changes to compile native modules for Arm.
### Visual Studio 2017

View File

@@ -134,7 +134,7 @@ system.
Before running the CLI for the first time, you will have to setup the "Windows Desktop App
Converter". This will take a few minutes, but don't worry - you only have to do
this once. Download and Desktop App Converter from [here][app-converter].
this once. Download the Desktop App Converter from [here][app-converter].
You will receive two files: `DesktopAppConverter.zip` and `BaseImage-14316.wim`.
1. Unzip `DesktopAppConverter.zip`. From an elevated PowerShell (opened with

View File

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

View File

@@ -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') {

View File

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

View File

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

View File

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

View File

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

View File

@@ -9,6 +9,7 @@ if ((globalThis as any).blinkfetch) {
const keys = ['fetch', 'Response', 'FormData', 'Request', 'Headers', 'EventSource'];
for (const key of keys) {
(globalThis as any)[key] = (globalThis as any)[`blink${key}`];
delete (globalThis as any)[`blink${key}`];
}
}

View File

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

View File

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

View File

@@ -22,6 +22,7 @@ if ((globalThis as any).blinkfetch) {
const keys = ['fetch', 'Response', 'FormData', 'Request', 'Headers', 'EventSource'];
for (const key of keys) {
(globalThis as any)[key] = (globalThis as any)[`blink${key}`];
delete (globalThis as any)[`blink${key}`];
}
}

2
patches/angle/.patches Normal file
View File

@@ -0,0 +1,2 @@
cherry-pick-a08731cf6d70.patch
cherry-pick-bf6dd974238b.patch

View 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

View 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,

View File

@@ -150,3 +150,11 @@ viz_fix_visual_artifacts_while_resizing_window_with_dcomp.patch
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

View 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());

View 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;

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

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

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

View File

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

View File

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

View File

@@ -0,0 +1,52 @@
From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001
From: Niklas Wenzel <dev@nikwen.de>
Date: Wed, 4 Feb 2026 06:02:40 -0800
Subject: LoAF: Add feature to enable sourceURL for all protocols
Backports https://crrev.com/c/7510894 (minus the test changes).
Can be removed when that CL is included via a Chromium roll.
Change-Id: Id5e58a151b13cc0ac054f4ec237b038255d683fd
Reviewed-on: https://chromium-review.googlesource.com/c/chromium/src/+/7510894
Commit-Queue: Noam Rosenthal <nrosenthal@google.com>
Reviewed-by: Dave Tapuska <dtapuska@chromium.org>
Reviewed-by: Noam Rosenthal <nrosenthal@google.com>
Cr-Commit-Position: refs/heads/main@{#1579397}
diff --git a/third_party/blink/renderer/core/frame/animation_frame_timing_monitor.cc b/third_party/blink/renderer/core/frame/animation_frame_timing_monitor.cc
index 6e118aeed3b13e4d36064f2e114aba9edf4bb6dc..5e0304eda6548e7065527e03c0635bd1387138bd 100644
--- a/third_party/blink/renderer/core/frame/animation_frame_timing_monitor.cc
+++ b/third_party/blink/renderer/core/frame/animation_frame_timing_monitor.cc
@@ -519,8 +519,15 @@ void AnimationFrameTimingMonitor::Trace(Visitor* visitor) const {
visitor->Trace(frame_handling_input_);
}
+BASE_FEATURE(kAlwaysLogLOAFURL, base::FEATURE_DISABLED_BY_DEFAULT);
+
namespace {
+
bool ShouldAllowScriptURL(const String& url) {
+ if (base::FeatureList::IsEnabled(kAlwaysLogLOAFURL)) {
+ return true;
+ }
+
KURL kurl(url);
return kurl.ProtocolIsData() || kurl.ProtocolIsInHTTPFamily() ||
kurl.ProtocolIs("blob") || kurl.IsEmpty();
diff --git a/third_party/blink/renderer/core/frame/animation_frame_timing_monitor.h b/third_party/blink/renderer/core/frame/animation_frame_timing_monitor.h
index f2fe39be2db525d89fcd9787c2ae9285babab26d..c395cf39d404f6c4f6f6e23c9fb8dfe92151a7d2 100644
--- a/third_party/blink/renderer/core/frame/animation_frame_timing_monitor.h
+++ b/third_party/blink/renderer/core/frame/animation_frame_timing_monitor.h
@@ -22,6 +22,11 @@ class TimeTicks;
namespace blink {
+// When enabled, long-animation-frame events will always include the sourceURL,
+// regardless of protocol. This is useful during development when using `file:`
+// URLs or custom protocols defined by embedders.
+CORE_EXPORT BASE_DECLARE_FEATURE(kAlwaysLogLOAFURL);
+
class LocalFrame;
// Monitors long-animation-frame timing (LoAF).

View File

@@ -396,7 +396,7 @@ index 71158ca9a7101911bb76f0c1b5300b0ff0e326b3..1441b9d4f9560c8b26d4beffe31449ed
// The NSWindow used by BridgedNativeWidget. Provides hooks into AppKit that
// can only be accomplished by overriding methods.
diff --git a/components/remote_cocoa/app_shim/native_widget_mac_nswindow.mm b/components/remote_cocoa/app_shim/native_widget_mac_nswindow.mm
index 433f12928857e288b6b0d4f4dd3d1f29da08cf6c..bb95aabec2e0d5c7b3a5d315c9a3f8cb3a45c8d2 100644
index 433f12928857e288b6b0d4f4dd3d1f29da08cf6c..98bd545ad806c0f3eece970560c769a4b119a486 100644
--- a/components/remote_cocoa/app_shim/native_widget_mac_nswindow.mm
+++ b/components/remote_cocoa/app_shim/native_widget_mac_nswindow.mm
@@ -21,6 +21,7 @@
@@ -426,7 +426,29 @@ index 433f12928857e288b6b0d4f4dd3d1f29da08cf6c..bb95aabec2e0d5c7b3a5d315c9a3f8cb
- (BOOL)hasKeyAppearance;
- (long long)_resizeDirectionForMouseLocation:(CGPoint)location;
- (BOOL)_isConsideredOpenForPersistentState;
@@ -165,6 +170,8 @@ - (void)cr_mouseDownOnFrameView:(NSEvent*)event {
@@ -158,13 +163,30 @@ - (void)cr_mouseDownOnFrameView:(NSEvent*)event;
@implementation NSView (CRFrameViewAdditions)
// If a mouseDown: falls through to the frame view, turn it into a window drag.
- (void)cr_mouseDownOnFrameView:(NSEvent*)event {
+#if !IS_MAS_BUILD()
if ([self.window _resizeDirectionForMouseLocation:event.locationInWindow] !=
-1)
return;
+#else
+ // For MAS builds, approximate the resize direction check.
+ if (self.window.styleMask & NSWindowStyleMaskResizable) {
+ constexpr CGFloat kResizeThreshold = 5.0;
+ NSPoint location = event.locationInWindow;
+ NSRect frame = self.window.frame;
+ CGFloat width = NSWidth(frame);
+ CGFloat height = NSHeight(frame);
+ if (location.x < kResizeThreshold || location.x > width - kResizeThreshold ||
+ location.y < kResizeThreshold || location.y > height - kResizeThreshold) {
+ return;
+ }
+ }
+#endif
[self.window performWindowDragWithEvent:event];
}
@end
@@ -435,7 +457,7 @@ index 433f12928857e288b6b0d4f4dd3d1f29da08cf6c..bb95aabec2e0d5c7b3a5d315c9a3f8cb
@implementation NativeWidgetMacNSWindowTitledFrame
- (void)mouseDown:(NSEvent*)event {
if (self.window.isMovable)
@@ -192,6 +199,8 @@ - (BOOL)usesCustomDrawing {
@@ -192,6 +214,8 @@ - (BOOL)usesCustomDrawing {
}
@end
@@ -444,7 +466,7 @@ index 433f12928857e288b6b0d4f4dd3d1f29da08cf6c..bb95aabec2e0d5c7b3a5d315c9a3f8cb
@implementation NativeWidgetMacNSWindow {
@private
CommandDispatcher* __strong _commandDispatcher;
@@ -389,6 +398,8 @@ - (NSAccessibilityRole)accessibilityRole {
@@ -389,6 +413,8 @@ - (NSAccessibilityRole)accessibilityRole {
// NSWindow overrides.
@@ -453,7 +475,7 @@ index 433f12928857e288b6b0d4f4dd3d1f29da08cf6c..bb95aabec2e0d5c7b3a5d315c9a3f8cb
+ (Class)frameViewClassForStyleMask:(NSWindowStyleMask)windowStyle {
if (windowStyle & NSWindowStyleMaskTitled) {
if (Class customFrame = [NativeWidgetMacNSWindowTitledFrame class])
@@ -400,6 +411,8 @@ + (Class)frameViewClassForStyleMask:(NSWindowStyleMask)windowStyle {
@@ -400,6 +426,8 @@ + (Class)frameViewClassForStyleMask:(NSWindowStyleMask)windowStyle {
return [super frameViewClassForStyleMask:windowStyle];
}

View File

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

View File

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

View File

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

View File

@@ -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()) {

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

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