100 Commits
Author SHA1 Message Date
claude[bot]andClaude 2954493d46 docs: fix incorrect heading levels (#55407)
Several API entries were one heading level too deep relative to their
sibling events and methods, or skipped a level under their section.


Claude-Session: https://claude.ai/code/session_01KX1hkKfxeSmmXK7rv1wNCE

Co-authored-by: Claude <noreply@anthropic.com>
2026-10-27 17:47:53 -07:00
claude[bot]andClaude Opus 5.5 27e39e926c fix: use upstream's File System Access path matcher (#55328)
* fix: use upstream's File System Access path matcher

Electron kept its own copy of ShouldBlockAccessToPath() and the Windows
MaybeIsLocalUNCPath() helpers. That copy never evaluated the suffix block
rules, so the kBlockWrite rules for .git/hooks, .git/config and .git/modules
were not enforced, and it lacked the hypervisor host-share servers (mac, psf,
vmware-host, .host, vboxsvr, vboxsrv) and trailing-dot handling that upstream
added in 158.0.8120.0.

Extend refactor_expose_file_system_access_blocklist.patch to move upstream's
ShouldBlockAccessToPath() and its UNC helpers verbatim into
chrome_file_system_access_blocklist.cc, exposed as a static member of
ChromeFileSystemAccessPermissionContext, and call it from Electron with the
access trigger so kBlockWrite rules only apply to save and programmatic write
operations, matching Chrome. Future upstream changes to the matcher now
conflict on roll instead of drifting.

This replaces Electron's stricter UNC checks with upstream's: '_' is now
allowed in UNC server names, and only drive (X$) and ADMIN$/IPC$/PRINT$/FAX$
admin shares are blocked rather than every '$'-suffixed share.

Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01MtuMgvwAcw7t9Q6HEB31Vx

* test: cover Windows UNC classification in the File System Access blocklist

Shares a fixture directory over loopback SMB and pastes it under different
UNC server and share names, checking that local server names (localhost,
127.0.0.1, and a trailing-dot localhost when it resolves) and drive admin
shares are blocked while other servers and non-admin hidden shares are not.
The hidden share and trailing-dot cases pin down the intentional changes
from Electron's previous matcher.

Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01MtuMgvwAcw7t9Q6HEB31Vx

* test: fix the UNC spec's localhost case and share names

A file URL drops a "localhost" host, so pasting \\localhost\share reached
Chromium as a path with no server. Drop that case; 127.0.0.1 and the
trailing-dot localhost still cover local server names.

Keep share names to 12 characters so net share doesn't stop to ask about
MS-DOS clients, and answer that prompt anyway in case it appears.

Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01MtuMgvwAcw7t9Q6HEB31Vx

---------

Co-authored-by: Claude <noreply@anthropic.com>
2026-10-26 16:57:02 -04:00
claude[bot]andClaude 15980f8024 build: don't hardcode the Python 3.11 path on Windows runners (#55308)
install-build-tools copied C:\Python311\python.exe to python3.exe, which
ties every Windows build to the runner image's Python 3.11 install path.
Only create python3.exe when python3 doesn't already run, and take the
directory from the Python 3 on PATH.


Claude-Session: https://claude.ai/code/session_01CFb55iGpm94Xhee9mSX3eV

Co-authored-by: Claude <noreply@anthropic.com>
2026-10-26 11:41:52 -04:00
claude[bot]andClaude Opus 5.5 6ffeb62f95 test: fix seven specs that relied on in-suite retries (#55359)
* test: read the download item inside will-download in api-session spec

`will-download event > identifies the frame and origin that started the
download` called preventDefault() in its will-download listener and only
read item.getInitiatorOrigin() after awaiting the event. preventDefault()
cancels the download, which destroys the item, and that can happen before
the awaiting code runs, so the read threw "DownloadItem used after being
destroyed". Read the origin inside the listener, while the item is alive.

Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01LPMvJBQiyP6b7QjatACmnS

* test: wait for the page to see clearData() in api-session spec

`ses.clearData() > clears all data when no options supplied` (and its
"called twice in parallel" twin) read localStorage.length right after
clearData() resolved. The page answers from its own cached copy of
localStorage, which the storage backend updates over a separate pipe, so
the page could still report the old item. Wait until the page sees the
clear, as the clearStorageData() spec already does.

Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01LPMvJBQiyP6b7QjatACmnS

* test: enable Network capture before navigating in debugger valid unicode spec

"handles valid unicode characters in message" started loadURL() on a
fresh window and only then attached the debugger and sent Network.enable
without waiting for it. Network.enable reaches the renderer only once it
exists, so when the tiny response won that race Network.responseReceived
was never emitted and the test hung until its 30s timeout.

Load about:blank first, attach, await Network.enable, then start
listening and navigate, matching the neighbouring invalid unicode spec.

Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01LPMvJBQiyP6b7QjatACmnS

* test: drop the 5s timeout on contentTracing recording specs

startRecording() resolves only once every child process acks the start,
or after the tracing service's 10s ack timeout, and stopRecording() then
waits up to 5s for the stop acks. A child that is slow to get scheduled on
a busy CI host therefore stretches a single record() past the 5s
per-suite timeout whatever the trace categories are, and the test only
passed on the in-suite retry.

Use the default spec timeout instead. Stopping the network service for
25s while a recording runs makes the slowest record() take about 15s,
which matches that bound and stays well inside the default.

Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01LPMvJBQiyP6b7QjatACmnS

* test: listen for the PDF viewer download's done event before it can fire

The asar PDF viewer download test attached its 'done' listener only after
the click loop noticed that the download had started. When the click's
executeJavaScript() round trip came back late, the small download could
start and finish inside that window, and the test then waited for a
'done' event that had already fired until the spec timed out.

Start listening for 'done' in the synchronous will-download handler that
accepts the first download, so the event cannot be missed.

Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01LPMvJBQiyP6b7QjatACmnS

* test: isolate the custom protocol extension fixtures' profiles

runFixture() started the custom-protocol fixture apps on the default
profile (they have no package.json, so userData is the stock Electron
directory other fixture apps use too) and never stopped them. When
another browser process holds that profile, the fixture's MV3 service
worker never answers the content script, the page title never changes
and the app hangs until the test times out. Because the hung app was not
killed it kept the profile open, so every in-job retry hung the same way.

Give each run its own --user-data-dir, and kill the app and remove the
directory when the test ends.

Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01LPMvJBQiyP6b7QjatACmnS

* test: follow links without synthesized clicks in navigation ordering specs

The "navigation events > ordering" specs for a second navigation, a
redirect and an in-page navigation clicked a link in a window that was
never shown, by sending CDP mouse events after a fixed 2s wait. On
Wayland a hidden window presents no frames, and the click can be lost
before it reaches the page: the browser forwards mouseDown and mouseUp,
but the page sees no pointer, mouse or click event, so the navigation
never starts and the test times out.

These specs check the order of navigation events, not input delivery.
Follow the link with a renderer-side click() once the page has loaded
instead; it is the same renderer-initiated navigation, and it no longer
depends on frames being presented or on the 2s wait.

Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01LPMvJBQiyP6b7QjatACmnS

---------

Co-authored-by: Claude <noreply@anthropic.com>
2026-10-26 11:33:06 -04:00
claude[bot]andClaude Opus 5.5 f11c314b8d test: fix retry-reliant clearData IndexedDB spec (#55232)
* test: read clearData() results from a new document

`ses.clearData() > only clears specified data categories` hung until
the spec timeout on sanitizer runs. Clearing IndexedDB force-closes the
bucket and disconnects the page's IndexedDB factory pipe, but the page
learns about that separately from the `get-indexeddb` IPC that follows.
If it handles the IPC first, `indexedDB.open()` goes down the dead pipe
and fails with "AbortError: The connection was closed.". The fixture
only logged the error, so the test waited forever. Every main run that
needed the retry logged that error from the fixture.

Read the data back from a fresh load of the fixture (with ?readOnly, so
it does not seed it again), and have the fixture report open failures
instead of only logging them.

Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01LPMvJBQiyP6b7QjatACmnS

* test: report how cookie-app exited in the app restart spec

`ses.cookies > should survive an app restart for persistent partition`
needs a retry in about one in six linux-x64-ubsan runs and in no other
lane, and its failures leave nothing to go on: the test dropped the
app's stderr and exit status. Run the app with spawnAndWait(), require
a clean exit, and attach the app's stdout and stderr to both
assertions, so the next failure shows what the app printed, e.g. a
UBSan report.

Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01LPMvJBQiyP6b7QjatACmnS

---------

Co-authored-by: Claude <noreply@anthropic.com>
2026-10-26 08:01:58 +00:00
claude[bot]andClaude 4ba52efe38 test: fix retry-reliant spellchecker and OOM crash-key specs (#55226)
The macOS spellchecker specs relied on retries because the system spelling
server starts on first use, which took 30 to 60 seconds on fresh CI
machines. Until then AppKit times every request out and Blink never asks
again about the text it already checked, so the first context menu spec
never saw its misspelling. Wait once, in a beforeAll, until the spell
checker answers with suggestions for a misspelled word, and have the
context menu waits require the suggestions as well as the misspelled word.

The renderer OOM crash-key specs filled the heap with arrays of pointers,
so each of the ~20 full GCs V8 runs near the heap limit traced the whole
heap. On the Intel macOS runners that took long enough for the crash
fixture's 30 second exit timer to end the app before the renderer crashed.
Fill the heap with arrays of doubles instead, which the GC does not trace.


Claude-Session: https://claude.ai/code/session_01LPMvJBQiyP6b7QjatACmnS

Co-authored-by: Claude <noreply@anthropic.com>
2026-10-26 08:01:54 +00:00
claude[bot]andClaude 74141f73b9 test: fix retry-reliant macOS UI specs (#55223)
app sandbox options: the mixed-sandbox fixture credited each window's
argv to whichever window it had created last, so a sandboxed window
that reported after its DevTools opened left argv.sandbox unset and the
spec hung until the timeout. Take each window's argv from its own
webContents.ipc, open both windows at once, read the report until the
app ends the connection, and fail as soon as the app exits early.

shell.openExternal: the 'removes focus' spec read isFocused() only after
openExternal() resolved, by which time the activation requests made to
take focus beforehand, or the browser finishing its launch, can have
given focus back. Read the state when 'blur' arrives instead.

Notification remove*: wait for the notifications to drop out of
getHistory() instead of sleeping 100 or 500 ms, since Notification
Center applies removals asynchronously.


Claude-Session: https://claude.ai/code/session_01LPMvJBQiyP6b7QjatACmnS

Co-authored-by: Claude <noreply@anthropic.com>
2026-10-26 08:01:50 +00:00
claude[bot]andClaude 0187553fce test: fix retry-reliant webview and debugger specs (#55227)
debugger.sendCommand "does not crash for invalid unicode characters in
message" attached to a window that had never loaded anything and sent
Network.enable without waiting for it. With no renderer yet, the command
only reached the renderer during the first navigation, and
Network.loadingFinished was sometimes never reported. Load about:blank
first, attach, await Network.enable, then navigate.

<webview>.reload() "should emit beforeunload handler": the guest has no
user gesture, so Chromium skips the beforeunload confirmation and the
reload goes ahead. The fixture's IPC, deferred with setTimeout(0) in the
hidden window, could be dropped when the document unloaded. Send it
synchronously from the handler.

<webview> "follows the embedder window when it is hidden and shown
again" took the guest's next visibility report as the state to check, but
the guest can report 'hidden' before the embedder has shown it. Wait for
each expected state instead, and run the suite serially like the
BrowserWindow visibilityState specs, since on macOS a window from another
spec worker can occlude the embedder.


Claude-Session: https://claude.ai/code/session_01LPMvJBQiyP6b7QjatACmnS

Co-authored-by: Claude <noreply@anthropic.com>
2026-10-26 08:01:47 +00:00
claude[bot]andClaude 6408a0c6bb test: fix retry-reliant macOS fullscreen BrowserWindow specs (#55230)
"should be able to load a URL while transitioning to fullscreen" and
"transparent option > correctly returns isMaximized() when the window is
maximized then minimized" time out on their first attempt on macOS and
pass on retry. Each runs right after a test that ends with two windows
sharing fullscreen (a borderless child of a fullscreen parent, and
"multiple windows inherit correct fullscreen state"). Those tests'
reported durations, which include the afterEach hook, are too short to
contain a fullscreen exit in the failing runs, so closeAllWindows()
destroyed a window that was still animating out of fullscreen, and AppKit
ignored the next test's first window request.

closeWindow() only waited when isFullScreen() was true, which it no
longer is while a window is being taken out of fullscreen along with
another one. Track which BrowserWindows have entered fullscreen and not
yet left it, wait for their 'leave-full-screen' too, and warn when that
does not arrive within the existing 5s bound.

"does not exit simpleFullScreen when requestFullscreen is called" still
spent its first attempt's whole 10s focus wait without the page getting
focus on macOS arm64, and passed on the retry, which requested app
activation again. Request activation on every poll instead of once.


Claude-Session: https://claude.ai/code/session_01LPMvJBQiyP6b7QjatACmnS

Co-authored-by: Claude <noreply@anthropic.com>
2026-10-26 08:01:43 +00:00
0240841b24 refactor: compile upstream FSA blocklist helpers instead of copying them (#54751)
* fix: carry upstream macOS firmlink blocklist fix into exposed FSA blocklist

Chromium 156.0.8078.3 already contains upstream 64c8e2a1ceda ("[FSA] Block
macOS firmlink alias paths to sensitive directories"), but
refactor_expose_file_system_access_blocklist.patch re-adds
NormalizeFilePath()/GenerateBlockPaths() as static members in the header
without the new pieces, so Electron's copy of the blocklist does not carry
the fix.

Update the patch's header copy to match upstream: add the
MaybeStripMacDataVolumePrefix() and NormalizeFilePathForBlocklist() static
helpers, the /System/Volumes kBlockAllChildren rule, and normalize
generated rules through NormalizeFilePathForBlocklist().

Refs https://chromium-review.googlesource.com/c/chromium/src/+/8410087 (upstream commit 64c8e2a1cedafdbcc750abc423ad9b389537c223)

Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01MtuMgvwAcw7t9Q6HEB31Vx

* fix: fold macOS Data volume firmlink paths in file system access blocklist checks

Switches Electron's copy of ShouldBlockAccessToPath() to the
NormalizeFilePathForBlocklist() helper (from upstream 64c8e2a1ceda, exposed
in the header by the companion refactor_expose_file_system_access_blocklist
patch update), so paths spelled via /System/Volumes/Data are matched
against the root-namespace blocklist rules the same way Chrome does.

Refs https://chromium-review.googlesource.com/c/chromium/src/+/8410087 (upstream commit 64c8e2a1cedafdbcc750abc423ad9b389537c223)

Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01MtuMgvwAcw7t9Q6HEB31Vx

* test: cover /System/Volumes/Data alias paths in FSA blocklist

Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01MtuMgvwAcw7t9Q6HEB31Vx

* refactor: compile upstream FSA blocklist helpers instead of copying them

refactor_expose_file_system_access_blocklist.patch used to hand-copy
upstream's NormalizeFilePath(), NormalizeFilePathForBlocklist() and
GenerateBlockPaths() into the header as inline static members. Since #53634
dropped the .cc hunks, upstream edits to the originals no longer conflict on
roll, so the copy goes stale silently (this is how the firmlink fix
64c8e2a1ceda was lost on the M156 roll; main's copy also still keeps the
.git/hooks rule Windows-only, while upstream applies it on all platforms).

Instead, declare NormalizeFilePathForBlocklist() and GenerateBlockPaths() as
static members in the header and move upstream's definitions verbatim out of
chrome_file_system_access_permission_context.cc into a new
chrome_file_system_access_blocklist.cc, which Electron now compiles as part
of //electron/chromium_src:chrome. Upstream changes to the blocklist now
conflict loudly on the removal hunk instead of being dropped.

Electron's call sites are unchanged.

Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01MtuMgvwAcw7t9Q6HEB31Vx

* chore: update patches

Regenerate the index line for chrome_file_system_access_permission_context.cc
in refactor_expose_file_system_access_blocklist.patch so the patch round-trips
through `e patches chromium` against 156.0.8078.3 (fixes "needs update" in the
checkout jobs).

Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01MtuMgvwAcw7t9Q6HEB31Vx

* chore: update patches

Regenerate the index line for chrome_file_system_access_permission_context.cc
in refactor_expose_file_system_access_blocklist.patch against
157.0.8085.0 after merging main (Chromium roll #54590), matching the
update-patches.patch artifact from the failed apply-patches check.

Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01MtuMgvwAcw7t9Q6HEB31Vx

* test: resolve home dir symlinks and cover /System/Volumes rule in FSA firmlink spec

Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01MtuMgvwAcw7t9Q6HEB31Vx

* chore: update patches

Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01MtuMgvwAcw7t9Q6HEB31Vx

* chore: update patches

Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01MtuMgvwAcw7t9Q6HEB31Vx

* chore: update patches

Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01MtuMgvwAcw7t9Q6HEB31Vx

* chore: update patches

Rebase refactor_expose_file_system_access_blocklist.patch onto 158.0.8118.0
and carry the upstream kBlockPaths additions from that version into
chrome_file_system_access_blocklist.cc.

Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01MtuMgvwAcw7t9Q6HEB31Vx

* chore: update patches

Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01MtuMgvwAcw7t9Q6HEB31Vx

---------

Co-authored-by: Claude <noreply@anthropic.com>
Co-authored-by: PatchUp <73610968+patchup[bot]@users.noreply.github.com>
2026-10-25 15:00:26 -07:00
claude[bot]andClaude Opus 5.5 316685ba12 fix: show macOS context menus reliably after a previous one is cancelled (#55235)
* fix: show macOS context menus reliably after a previous one is cancelled

-[ElectronMenuController cancel] dismissed the menu with -cancelTracking,
which plays a fade-out animation. While that animation runs, a following
-popUpMenuPositioningItem:atLocation:inView: returns without showing the
menu or calling -menuWillOpen:, so a Menu.popup() made right after
Menu.closePopup() (or after a cancelled popup on another window) showed
nothing, and neither 'menu-will-show', 'menu-will-close' nor the popup
callback ever fired.

Use -cancelTrackingWithoutAnimation instead, and clear isMenuOpen_ before
calling it so that a -menuDidClose: delivered during the cancel is ignored
and 'menu-will-close' and the close callback are still reported exactly
once, from -cancel.

Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01LPMvJBQiyP6b7QjatACmnS

* test: cover reopening a macOS popup menu from a closed popup's callback

Pops a menu up, closes it with closePopup() once it shows, and pops it
up again from the first popup's callback. Both popups must emit exactly
one menu-will-show, one menu-will-close and one callback, in order.
With the animated -cancelTracking the second popup showed nothing, so
the test timed out. It runs with retry: 0 because every attempt repeats
the same sequence, so a retry could only hide a regression.

Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01LPMvJBQiyP6b7QjatACmnS

---------

Co-authored-by: Claude <noreply@anthropic.com>
2026-10-25 22:00:04 +00:00
claude[bot]andClaude 96a2dc1f28 ci: print TCC diagnostics when macOS runner lacks capture/input access (#55237)
ci: print TCC diagnostics when the macOS runner lacks capture/input access

On a small share of hosted macOS VMs (about 0.5% of macos-x64 and 0.2%
of macos-arm64 test jobs since late September, on the same runner image
as the passing jobs) TCC denies the job screen capture, posting events
and Accessibility from the first spec on. desktopCapturer.getSources
then rejects with "Failed to get sources.", getUserMedia/getDisplayMedia
with "Could not start video source", and the real-input specs time out
with postEventAccess:false and accessibilityTrusted:false.

Add a preflight before the specs that checks
CGPreflightScreenCaptureAccess() and CGPreflightPostEventAccess() from
the job's process chain. When access is missing it prints the process
chain, the TCC.db rows for these services and tccd's attribution of the
request, and emits a warning naming the runner host problem. It does not
change TCC state or fail the step; that can follow once the attribution
shows which process TCC holds responsible.


Claude-Session: https://claude.ai/code/session_01LPMvJBQiyP6b7QjatACmnS

Co-authored-by: Claude <noreply@anthropic.com>
2026-10-24 07:16:37 +00:00
claude[bot]andClaude 7d44215c46 ci: label PGO profile update PRs with their target branch (#55298)
Profile update PRs opened against a release branch now also get that
branch's label (e.g. 46-x-y), added in the same additive labels call as
semver/none. main PRs are unchanged; they already receive the current
major's label on merge from pull-request-merged.yml.


Claude-Session: https://claude.ai/code/session_019kGNYv837tKLbJDSHsECro

Co-authored-by: Claude <noreply@anthropic.com>
2026-10-24 10:18:33 +09:00
claude[bot]andClaude eb6db76aee test: poll the window server without blocking the app shim specs (#55231)
The app shim specs ask osascript which windows are on screen, and did so
with spawnSync, every 10ms, on the main process's UI thread. A window in a
shim is drawn by AppKit in the shim's process, which asks the host
synchronously through remote_cocoa whether the window can become key, has
the key appearance or shows its title whenever it orders, lays out or draws
it. While the host sat in spawnSync those calls went unanswered, so the shim
advanced roughly one call per osascript run. On the slower Intel macOS
runners that starved the tab merge in "tabs two windows of one shim
together" past waitUntil's 10s, on every in-suite retry.

Run osascript with an async execFile so the host keeps answering the shim
while the window server is queried.


Claude-Session: https://claude.ai/code/session_01Xomb9LeAiuTMvaEtSsauvb

Co-authored-by: Claude <noreply@anthropic.com>
2026-10-23 17:02:00 -07:00
claude[bot]andClaude bea5390a06 build: update build-tools to f3e78a8 (#55285)
Claude-Session: https://claude.ai/code/session_01VtzqDnnQUTDMMgM2SxviUT

Co-authored-by: Claude <noreply@anthropic.com>
2026-10-23 20:49:15 +00:00
claude[bot]andClaude Opus 5.5 a6d4549ee9 fix: handle a null pending call in dbus::ObjectProxy (#55236)
* fix: handle a null pending call in dbus::ObjectProxy

dbus_connection_send_with_reply() can succeed with a null
DBusPendingCall when the connection is already disconnected.
ObjectProxy::StartAsyncMethodCall() then passes it to
dbus_pending_call_set_notify(), which fails a libdbus argument check and
aborts the process. This made the app spec "when a D-Bus bus goes away >
exits cleanly instead of crashing" end in SIGABRT on Linux.

Add a Chromium patch that runs the callback with a null response, as the
function already does for its other failures.

Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01LPMvJBQiyP6b7QjatACmnS

* test: add a regression test for the null D-Bus pending call

Extend the dbus::ObjectProxy patch with a dbus_unittests case,
ObjectProxyMockBusTest.NullPendingCallRunsCallbackWithNull, in
dbus/object_proxy_unittest.cc. It uses a MockBus whose SendWithReply()
leaves the pending call null, and checks that the callback runs
asynchronously, exactly once, with a null response and a null error
response. Unlike the Linux bus-loss spec, it does not depend on shutdown
timing.

Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01LPMvJBQiyP6b7QjatACmnS

* test: cover a D-Bus method call made after the bus is lost

Add "app module > when a D-Bus bus goes away > fails a method call made
after the bus is lost instead of crashing". The test runs separate
private session and system dbus-daemons, waits until the app's
org.freedesktop.login1 proxy has connected to the system bus, then
kills the system daemon. Electron quits when Chromium handles the
disconnect, and the fixture's 'quit' handler then starts a login1
method call on the lost system bus. Right after that, it sends a badge
update signal on the session bus. Both buses use the same D-Bus thread,
so the signal reaching the session bus proves the call has run. The
test waits for that signal, lets the app exit, and expects exit code 0.

Without the null pending call fix, the login1 call aborts the app with
SIGABRT. The test waits only on D-Bus traffic and app output, not on
timeouts.

Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01LPMvJBQiyP6b7QjatACmnS

---------

Co-authored-by: Claude <noreply@anthropic.com>
2026-10-23 19:57:26 +00:00
claude[bot]andClaude Opus 5.5 ab1a105caa fix: make DeviceMonitorMessageWindow a NoDestructor (#54809)
* fix: mark leaked serial device observation as dangling on Windows

With dangling raw_ptr checks enabled, the Windows browser process fails
the dangling-pointer check at exit after a page uses navigator.serial.
DeviceService is destroyed after the ThreadPool has shut down, so the
serial enumerator's UI-thread helper is leaked with its observation of
the COM-port DeviceMonitorWin still active when an AtExit callback frees
the monitor. Mark that observation LeakedDanglingUntriaged, as was done
for ElectronUsbDelegate.

Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01Xn1qtQBJvK9weVCmD9tLkv

* chore: reference upstream CL in serial dangling patch

Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01Xn1qtQBJvK9weVCmD9tLkv

* fix: notify DeviceMonitorWin observers before destruction

Replace the LeakedDanglingUntriaged annotation with the approach from
upstream CL 8561777: ~DeviceMonitorWin notifies observers, and the
serial enumerator's UI thread helper resets its observation there, so
no raw_ptr dangles when the monitor is freed at exit.

Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01Xn1qtQBJvK9weVCmD9tLkv

* fix: update DeviceMonitorWin patch to upstream CL 8561777 PS7

Upstream review moved the fix to making DeviceMonitorMessageWindow a
base::NoDestructor instead of notifying observers before destruction.

Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01Xn1qtQBJvK9weVCmD9tLkv

* fix: update DeviceMonitorWin patch to upstream CL 8561777 PS8

Adds the DeviceMonitorWin SEQUENCE_CHECKER from patchset 8.

Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01DWqmuJ7QaqrgrGccdfquWX

---------

Co-authored-by: Claude <noreply@anthropic.com>
2026-10-23 17:39:46 +00:00
claude[bot]andClaude ac6b2966ad test: run copyVideoFrameAt specs serially (#55257)
The webFrameMain.copyVideoFrameAt specs clear the system clipboard,
assert it holds no image, and then wait for one to appear. While they
run in the parallel phase, a spec file in another Electron process can
write or clear the clipboard between those steps. Tag the suite serial,
as spec/CLAUDE.md requires for tests that use the system clipboard.


Claude-Session: https://claude.ai/code/session_01AnikcZrheSxnwN9HdN9p3E

Co-authored-by: Claude <noreply@anthropic.com>
2026-10-23 15:40:33 +00:00
claude[bot]andClaude Opus 5.5 d8cc3947bb test: fix retry-reliant network and utility process specs (#55228)
* test: fix retry-reliant network and utility process specs

- startRemoteControlApp(): the remote-control app quits itself after 30s,
  but sanitizer builds give each test 180s. Slow ASan tests that were still
  talking to the app after 30s failed with "socket hang up" or hung. Pass
  the configured spec timeout as --remote-app-timeout.
- utilityProcess child-process-gone "with default serviceName": every
  unnamed utility process shares this name, and the event for a child that
  exited via process.exit() can land in the next test (as 'killed' on
  Windows). Match this child's event by its exit code.
- webRequest "requests that no blocking listener can match": replace the
  elapsed-time thresholds with a server-side log of served paths that the
  busy main process reads, so the tests check whether the request reached
  the network while the main process was blocked, not how fast it was.

Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01LPMvJBQiyP6b7QjatACmnS

* test: keep webRequest busy-main checks independent across retries

The served-path log lives for the whole describe block and a vitest
retry re-runs only the test body, so a retried attempt found the
earlier attempt's entries: the precedence check failed on every retry
and the round-trip checks could pass without testing anything. Give
every request that these checks look for its own path.

Also register the forked child in the utilityProcess
'with default serviceName' test with deferKillUtilityProcess, as
spec/CLAUDE.md requires.

Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01LPMvJBQiyP6b7QjatACmnS

* test: fail fast when the remote-control app exits before it listens

startRemoteControlApp() waited only for the "Listening" line, so when
the app exited or failed to spawn first, the test hung until its
timeout (180s on sanitizer builds). Reject as soon as the child exits
or errors before reporting its port, with its exit code, signal and
stderr, and drop these listeners once the port arrives so that a later
normal exit rejects nothing.

Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01LPMvJBQiyP6b7QjatACmnS

* test: run the default-serviceName child-process-gone test in its own app

Every utility process forked without a serviceName is called "Node
Utility Process", so in the spec runner the child-process-gone event
of an earlier test's child could reach this test's listener. Matching
by exit code only made a collision less likely. Fork the crashing child
inside a remote-control app of its own, where it is the only process
with that name, and read the event there.

Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01LPMvJBQiyP6b7QjatACmnS

---------

Co-authored-by: Claude <noreply@anthropic.com>
2026-10-23 10:35:00 -04:00
claude[bot]andClaude Opus 5.5 45084688a7 fix: close the utilityProcess port before its descriptor is destroyed (#55233)
* fix: close the utilityProcess port before its descriptor is destroyed

A UtilityProcessWrapper that is still alive when the heap is torn down at
exit, for example one whose child had not finished launching when
ElectronBrowserMainParts shut the others down, was destroyed with its
postMessage port still lent to the mojo::Connector. Debug and sanitizer
builds then hit DCHECK(handle_.is_valid()) in MessagePortDescriptor::Reset().

Move the connector and port descriptor onto a NativePeer. Its
TearDownNative() takes the handle back and resets the descriptor, so the
port is closed at MicrotasksRunner shutdown or after collection, never
during cppgc sweeping. The exit-time order (dispatch pending messages,
close the port, emit 'exit') is unchanged.

Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01LPMvJBQiyP6b7QjatACmnS

* fix: close the utilityProcess port in the destructor and shut down launching wrappers

Per review, replace the PortLifecycle native peer with a smaller fix:

- ~UtilityProcessWrapper closes the connector port and any stdio read fds
  not yet handed to JS. Both are non-GC members, so this is allowed during
  cppgc sweeping, and it fixes the DCHECK in MessagePortDescriptor::Reset()
  for a wrapper still alive at heap teardown.
- Bind the connector error handler with base::Unretained: the connector is
  owned by the wrapper and destroying it cancels the handler.
- Drop the connector_->is_valid() check in CloseConnectorPort();
  GiveDisentangledHandle() replaces an invalid handle with a dangling one, so
  the port is always reset.
- Track wrappers from construction instead of from launch, and add
  UtilityProcessWrapper::ShutdownAll(), so PostMainMessageLoopRun() also
  shuts down wrappers whose child is still launching before Node.js stops.
  FromProcessId() ignores a null pid.

Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01LPMvJBQiyP6b7QjatACmnS

---------

Co-authored-by: Claude <noreply@anthropic.com>
2026-10-23 10:33:32 -04:00
claude[bot]andClaude e3790be1a2 fix: bind WebRequestHost so blocking chrome.webRequest listeners can finish (#55234)
fix: bind extensions::mojom::WebRequestHost for renderers and service workers

Chromium enables kWebRequestPerContextEventDispatch by default. With it,
the browser keeps a request blocked on a blocking chrome.webRequest
listener until the renderer calls WebRequestHost.EventHandlingDone.
Electron never registered a binder for that channel-associated
interface, so the call was dropped ("Request for unknown
Channel-associated interface: extensions.mojom.WebRequestHost") and the
request could stay blocked.

Register WebRequestEventRouter::BindForRenderer in
ExposeInterfacesToRenderer and
RegisterAssociatedInterfaceBindersForServiceWorker, matching
ChromeContentBrowserClientExtensionsPart.


Claude-Session: https://claude.ai/code/session_01LPMvJBQiyP6b7QjatACmnS

Co-authored-by: Claude <noreply@anthropic.com>
2026-10-23 10:28:27 -04:00
claude[bot]andClaude 6d9ae6c112 test: fix retry-reliant misc specs (#55224)
GDK_BACKEND: wait for the fixture app to exit instead of polling its
output for up to 10s. The old wait let the next launch (the second test
or a retry) overlap the previous copy's shutdown, which on the ASAN lane
pushed the second launch past the 10s limit.

long-animation-frame: check only the long frame that ran the fixture's
busy-loop requestAnimationFrame callback. A slow host can report other
long frames in the same batch with no script or with an unattributed
one, which made the every-entry check resolve false.


Claude-Session: https://claude.ai/code/session_01LPMvJBQiyP6b7QjatACmnS

Co-authored-by: Claude <noreply@anthropic.com>
2026-10-23 10:19:46 -04:00
claude[bot]andClaude 4d38eab74e test: migrate cpp-heap specs to v8 heap snapshot helpers (#55243)
Split out of #55229 and extended per review there.

- heapsnapshot-helpers.js reads V8's flat snapshot arrays:
  takeHeapSnapshot()/parseHeapSnapshot(), countHeapSnapshotNodes(),
  snapshotContainsRetainingPath() and countRetainingPathNodes(). Path
  steps skip weak edges and can also match edge type, edge name, node
  type and detachedness; each node counts once however many paths reach
  it. The old object-graph containsRetainingPath() is removed.
- Every recordState() + containsRetainingPath() check in cpp-heap.spec.ts
  uses the new helpers, and --expose-internals is dropped.
- The node-counting checks (powerMonitor, autoUpdater, the two
  webContents before/after counts and api-ipc's ObjectTemplateInfo count)
  use countHeapSnapshotNodes() over the node array; the occurrences
  checks (three Session roots, one WebFrameMain root) count distinct nodes.
- The renderer cached-templates test keeps webContents.takeHeapSnapshot()
  and counts its markers with countHeapSnapshotNodes() instead of
  createJSHeapSnapshot().
- Tests that make the remote app quit inside remotely() register their
  exit/close listener first, so a fast exit is not missed (19 tests).
- 'should settle an in-flight call stack reply after frame disposal'
  keeps the page running script so the V8 interrupt is serviced, and
  awaits the result instead of racing a 5 s timeout.
- 'should release the root for a detached frame after navigation' runs
  its app with --disable-renderer-backgrounding so the old page's unload
  IPC is not dropped.


Claude-Session: https://claude.ai/code/session_01LPMvJBQiyP6b7QjatACmnS

Co-authored-by: Claude <noreply@anthropic.com>
2026-10-23 10:06:26 -04:00
claude[bot]andClaude Opus 5.5 59227614a2 test: fix retry-reliant gc-lifecycle specs (#55229)
* test: fix retry-reliant gc-lifecycle specs

Replace races with waits on the real event or state in cpp-heap,
webFrameMain and webContents specs that needed vitest's in-suite retry
on main:

- cpp-heap: register exit/close listeners before remotely() triggers
  app.quit(); keep the renderer running script while a call stack is
  collected; keep renderers at foreground priority for the unload-IPC
  test; read heap snapshots as flat arrays for the slow WebFrameMain,
  DevTools and UtilityProcess snapshot tests.
- webFrameMain: foreground priority for the detached-frame test, a fixed
  video box measured after it can play for copyVideoFrameAt, and a
  running page for collectJavaScriptCallStack.
- webContents: wait for 'destroyed' in clone(), for did-stop-loading
  before an in-page loadURL(), and for restore() before executeJavaScript;
  wait for visibilityState in the background throttling specs; parse PDFs
  with pdf.js in-process; and hold the unresponsive-event page in a sync
  XHR the test releases instead of a fixed 40 s spin.

Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01LPMvJBQiyP6b7QjatACmnS

* test: wait for visibilityState in the first hidden-page throttling spec

'stops producing frames again once re-enabled' checked
document.visibilityState immediately after frames stopped or started,
but the page learns its visibility separately from its widget being
shown or hidden and can still report the old state for a moment. Use
the becomes() helper like the other specs in this describe.

Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01LPMvJBQiyP6b7QjatACmnS

* test: run detached-frame unload spec in its own app, split out cpp-heap work

'disposes detached frame after cross-origin navigation' needs the old
renderer at foreground priority so its unload IPC is not dropped. Instead
of appending --disable-renderer-backgrounding to the spec runner's own
command line at test time, run the scenario in the remote-control app
launched with that switch. The assertions are unchanged.

The cpp-heap.spec.ts changes and the new heap snapshot helpers move to a
separate PR, as requested in review.

Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01LPMvJBQiyP6b7QjatACmnS

---------

Co-authored-by: Claude <noreply@anthropic.com>
2026-10-23 09:22:47 -04:00
claude[bot]andClaude Opus 5.5 2fb6c26db6 feat: support chrome.storage.sync in extensions (#54088)
* feat: support chrome.storage.sync in extensions

Register a ValueStoreCache for the SYNC settings namespace from
ElectronExtensionsAPIClient::AddAdditionalValueStoreCaches. Until now
Electron never overrode that hook, so StorageFrontend only knew about
LOCAL (and the in-memory SESSION area) and every chrome.storage.sync
call failed with '"sync" is not available in this instance of Chrome'.

ElectronSyncValueStoreCache mirrors Chromium's LocalValueStoreCache but
uses settings_namespace::SYNC, which gives it its own LevelDB directory
under the partition path (kSyncExtensionSettingsDirectoryName), so sync
and local never alias. It enforces the chrome.storage.sync quotas from
extensions/common/api/storage.json (QUOTA_BYTES 102400,
QUOTA_BYTES_PER_ITEM 8192, MAX_ITEMS 512); the per-minute and per-hour
write limits are already applied to kSync by storage_api.cc. There is
no sync service in Electron, so the area behaves like Chrome with sync
disabled: a second local store with no cross-device sync.
chrome.storage.managed stays unsupported because there is no policy
source to back it.

This answers the question raised on #53995 about supporting
chrome.storage instead of dropping sync from the test fixture.

Co-Authored-By: Claude Fable 5.1 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01AFucMLGyVVqSUAKXrqbaUT

* fix: include value_store_factory.h in ElectronExtensionsAPIClient

The linux-x64 and linux-x64-ubsan builds failed compiling
electron_extensions_api_client.cc:

  ../../base/memory/scoped_refptr.h:398:6: error: member access into
  incomplete type 'value_store::ValueStoreFactory'
  ../../base/memory/scoped_refptr.h:405:6: error: member access into
  incomplete type 'value_store::ValueStoreFactory'
  note: in instantiation of ... requested here
    electron_extensions_api_client.cc:97:39:
      new ElectronSyncValueStoreCache(factory);

AddAdditionalValueStoreCaches copies the
scoped_refptr<value_store::ValueStoreFactory> into the new
ElectronSyncValueStoreCache, which instantiates AddRef/Release on the
pointee. extensions_api_client.h and electron_sync_value_store_cache.h
only forward-declare ValueStoreFactory, so the translation unit needs
the full definition. Include components/value_store/value_store_factory.h
the same way chrome_extensions_api_client.cc does.

Co-Authored-By: Claude Fable 5.1 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01AFucMLGyVVqSUAKXrqbaUT

* test: use vitest matchers in chrome.storage.sync spec

main dropped chai in favour of vitest's own matchers and now lints
against chai-style chains, so convert the chrome.storage.sync spec's
assertions to the equivalent vitest matchers.

Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01AFucMLGyVVqSUAKXrqbaUT

---------

Co-authored-by: Claude <noreply@anthropic.com>
2026-10-23 09:16:18 -04:00
claude[bot]andClaude 0e77ca92cd test: wait for GDK_BACKEND fixture exit instead of a fixed 10s poll (#55222)
The GDK_BACKEND specs polled the fixture's stdout with waitUntil's fixed
10s default while ignoring its stderr, and the fixture launched a second
Electron (ELECTRON_RUN_AS_NODE) through a blocking execFileSync. On ASan
builds the two Electron launches can take longer than 10s under load, so
the test has been passing only on retry there and failed all four
attempts on main's ASan shard after the 158.0.8116.0 roll, with no output
to say why.

Wait for the fixture to exit with spawnAndWait, bounded by the per-test
timeout (which sanitizer builds raise), and put the exit code, signal,
stdout and stderr in the assertion message. Have the fixture read the
inherited variable through /bin/sh instead of a second Electron, with a
timeout on execFileSync, and exit with an error instead of hanging if
that fails.


Claude-Session: https://claude.ai/code/session_011SCvSB39Bwi5Fiyo8eAsgn

Co-authored-by: Claude <noreply@anthropic.com>
2026-10-23 12:50:01 +09:00
claude[bot]andClaude 16ac8dadf2 build: bump secret-service-action to v1.1.0 (#55216)
Claude-Session: https://claude.ai/code/session_01ELojQikqpZ2KVGqjEeNwUe

Co-authored-by: Claude <noreply@anthropic.com>
2026-10-22 22:47:39 +00:00
claude[bot]andClaude 4d07e30770 build: exclude build-tool PDBs from pdb.zip (#55212)
The win32-x64 pdb.zip has grown past GitHub's 2 GiB per-asset limit, so
release upload fails with a 422. Drop the PDBs of the natives codecache
generators and node_mksnapshot, host build tools that never ship.


Claude-Session: https://claude.ai/code/session_01CNVT3t9ytyoJ9SVMv3pu3z

Co-authored-by: Claude <noreply@anthropic.com>
2026-10-22 21:46:45 +00:00
claude[bot]andClaude 35ac258e35 ci: pre-seed node-gyp headers on Linux too (#55202)
The Linux build/test images ship a node-gyp header cache built with the
image builder's host Node (currently 22.23.3), but the containers run
the nodesource Node (22.23.4), so the cache never matches. Every
native-addon fixture then downloads the headers itself and copies them
into the shared devdir in parallel, truncating headers that an
already-configured fixture is compiling against.

Run the pre-seed on every platform and pass --ensure so it is a no-op
when the cache already matches.


Claude-Session: https://claude.ai/code/session_01Xtmcutqr2Yx3gWuQ7LyDad

Co-authored-by: Claude <noreply@anthropic.com>
2026-10-22 14:26:21 -07:00
claude[bot]andClaude 2c887742eb ci: drop angle commit-graph alongside alternates in fix-sync (#55201)
ci: drop angle commit-graph with alternates in fix-sync

Since the build image bump to git 2.55, auto maintenance (which uses the
"geometric" strategy by default since git 2.54) writes a commit-graph in
the angle checkout of the Linux-built src cache. That graph lists commits
that only exist in the alternates git cache, so once fix_angle_git removes
the alternates, git fetch aborts on mac and Windows with "which is in the
commit graph file but not in the object database". Remove the commit-graph
together with the alternates.


Claude-Session: https://claude.ai/code/session_01Xtmcutqr2Yx3gWuQ7LyDad

Co-authored-by: Claude <noreply@anthropic.com>
2026-10-22 11:15:20 -04:00
claude[bot]andClaude 3b100611a1 build: remove the spec runner's end-of-job individual test rerun (#55134)
script/spec-runner.js parsed the JUnit report after a failed run and re-ran
each failing test on its own (--enableRerun=3), so a test that failed all of
its in-suite retries but passed once alone still left the job green. That hid
tests that only pass in isolation. Drop the rerun, the JUnit parsing and its
@xmldom/xmldom dependency, and stop passing --enableRerun=3 in the test
workflow. A leftover --enableRerun is now rejected instead of being forwarded
to Electron, where it would silently do nothing. vitest's in-suite retry is
unchanged.


Claude-Session: https://claude.ai/code/session_01LPMvJBQiyP6b7QjatACmnS

Co-authored-by: Claude <noreply@anthropic.com>
2026-10-22 04:52:31 +00:00
claude[bot]andClaude 6259feb41f build: bump build-images for eMudhra ca-certificates removal (#55187)
build: bump build-images to pick up eMudhra ca-certificates removal

Point the build image pin at the image built from electron/build-images#106,
which installs jammy's ca-certificates 20260816ubuntu0.22.04.1 (USN-8944-1)
dropping the eMudhra "emSign ECC Root CA - G3" root.


Claude-Session: https://claude.ai/code/session_01Kpt4TnMMYe362XSUYdQNnF

Co-authored-by: Claude <noreply@anthropic.com>
2026-10-21 23:45:48 +00:00
claude[bot]andClaude 9150ae972a build: bump pinned Node.js in CI to 22.23.4 / 24.22.1 security releases (#55188)
Claude-Session: https://claude.ai/code/session_01MM6DBDZdmumVSaiGNt2vF7

Co-authored-by: Claude <noreply@anthropic.com>
2026-10-21 23:32:20 +00:00
claude[bot]andClaude Opus 5.5 ffbe71f787 build: dismiss first sign-in windows before Windows PGO collection (#55109)
* build: disable native window occlusion for Windows PGO collection

Since the Chromium 157 roll, native window occlusion marks the benchmark
window as occluded on the hosted Windows arm64 runner, so the page reports
itself hidden and the rAF-driven browser benchmarks never start. Minimizing
the console window (#54845) did not help. Launching the instrumented Electron
with CalculateNativeWinOcclusion disabled keeps the shown window visible and
only removes browser-side occlusion tracking from the profile.

Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01CMnZca8hbAx3iAsLvGkMzk

* build: only disable native window occlusion for Windows arm64 PGO collection

x64 collects fine with native window occlusion tracking on, so keep it enabled there.

Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01CMnZca8hbAx3iAsLvGkMzk

* build: dismiss first sign-in windows before Windows PGO collection

The windows-11-arm runner image leaves its first sign-in privacy settings
window full screen over the desktop. Since Chromium 157, native occlusion
tracking counts it as covering the benchmark window, so the page goes
hidden and the benchmarks never start. Copy the spec pipeline's step that
dismisses those windows into the PGO collect segment, and drop the
CalculateNativeWinOcclusion opt-out so profiles are collected with
occlusion tracking on, as before.

Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01CMnZca8hbAx3iAsLvGkMzk

* build: share the first sign-in dismiss step as a composite action

Move the "Dismiss first sign-in windows (Windows)" step from the spec
pipeline into .github/actions/dismiss-windows-first-sign-in so the spec
and PGO collect segments run the same script instead of two copies. The
script is unchanged apart from taking the WSL terminal minimizer's
duration from a minimizer-seconds input (3600 for specs, 19800 for PGO
collection so it outlasts the 330 minute collect step). The callers keep
timeout-minutes and continue-on-error, which composite steps do not
support.

Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01CMnZca8hbAx3iAsLvGkMzk

---------

Co-authored-by: Claude <noreply@anthropic.com>
2026-10-20 21:58:37 -07:00
claude[bot]andClaude Opus 5.5 efd4495c23 test: fix unload-IPC and protocol.handle 'is fast' flakes (#55083)
* test: fix unload-IPC and protocol.handle 'is fast' flakes

Keep renderers at foreground priority in the two tests that wait for an
IPC sent from an unload handler after a cross-site navigation, so the
backgrounded old renderer does not miss Chromium's 500 ms unload timeout
under parallel spec load.

Rework protocol.handle 'is fast' to compare the native relay path against
both a direct fetch and the JS-pumped path, with a looser bound against
direct fetches and timings in the failure message.

Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01LPMvJBQiyP6b7QjatACmnS

* test: fix lint

Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01LPMvJBQiyP6b7QjatACmnS

---------

Co-authored-by: Claude <noreply@anthropic.com>
2026-10-20 07:50:22 +00:00
claude[bot]andClaude 23c730b8b8 test: wait for the parent's ack before utility children exit (#55082)
process.exit() does not wait for pending postMessage() writes, so a
utility child that exits right after posting can lose its message.
Restore the acknowledgement handshake that #54924 removed from the
api-net fixture and helper, and add it to the env-app and
js2c-code-cache fixtures, so those children only exit once the parent
has acknowledged their message.

The #54924 test no longer posts right before exiting. The child posts
its parentPort messages, then posts on a transferred MessagePortMain and
exits only when the parent replies there. parentPort and the port share
the same ordered Mojo channel, so all of the parentPort messages have
reached the parent when the port message does.


Claude-Session: https://claude.ai/code/session_01LPMvJBQiyP6b7QjatACmnS

Co-authored-by: Claude <noreply@anthropic.com>
2026-10-19 20:11:15 -04:00
claude[bot]andClaude 7a353a3c8c test: fix desktopCapturer restore-token specs on main (#55118)
The restore-token specs added in #54550 were written against a base that
predated #54439, which dropped chai/chai-as-promised/dirty-chai in favour
of vitest's own matchers and added the no-chai-assertions lint rule. On
main, `.to.be.eventually.rejectedWith()` and `.to.be.empty()` throw at
runtime and every chai chain trips lint. Switch them to vitest matchers.


Claude-Session: https://claude.ai/code/session_012AdLYu5PBMGgRbsE7frDma

Co-authored-by: Claude <noreply@anthropic.com>
2026-10-19 17:00:02 -04:00
claude[bot]andClaude Opus 5.5 40ebdcc38d docs: fix code block line highlighting after docs reformats (#55097)
* docs: fix code block line highlighting after lint reformats

Several highlighted code blocks in the IPC and preload tutorials had their
line-highlight ranges drift when the docs code blocks were auto-formatted
(the `import/order` blank line added in #42113, and the if/else collapse in
#38260), so the highlights now land one line off from the code they were
meant to call out. Update the ranges to point back at the originally
highlighted code without changing the code blocks themselves.

Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01A9enZ3jn8BveASiB5p9G1E

* docs: fix code block line highlighting that drifted from content edits

The Playwright examples in automated-testing.md lost a line when their two
`require` statements were merged, leaving the highlights one line late, and
the code signing examples replaced a two-line certificate option with a
`windowsSign` object while keeping the old two-line ranges. Point the
highlights back at the intended code and cover the whole `windowsSign`
object.

Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01A9enZ3jn8BveASiB5p9G1E

---------

Co-authored-by: Claude <noreply@anthropic.com>
2026-10-19 07:59:47 -04:00
claude[bot]andClaude Opus 5.5 bcc5c510df test: re-enable Node.js tests that now pass with BoringSSL (#55071)
* test: re-enable Node.js tests that now pass with BoringSSL

Most of these were disabled because BoringSSL behaved differently from
OpenSSL. Upstream Node.js made the tests BoringSSL-aware in
nodejs/node#63161 (v24.18.0) and fixed the ML-KEM expectations in
nodejs/node#65966 (v24.22.0), so they now pass.

The es-module/test-esm-wasm entry is a stale prefix: test.py matches
entries as substrings of the path, so it was hiding 13 split files that
pass. A few entries are dropped because the tests now skip themselves.

parallel/test-cluster-primary-error, parallel/test-cluster-primary-kill,
parallel/test-diagnostics-channel-memory-leak and
parallel/test-worker-resource-limits move to the flaky list instead.

Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01CfxP4tDxnGgFhy1kPesp3M

* test: keep two node tests disabled that crash on the testing build

test-vm-compile-function-lineoffset hits a V8 Smi::IsValid debug check and test-domain-error-types segfaults under --stress-compaction.

Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01CfxP4tDxnGgFhy1kPesp3M

---------

Co-authored-by: Claude <noreply@anthropic.com>
2026-10-17 21:16:40 -07:00
claude[bot]andClaude 90bee4aae0 ci: skip native builds when installing deps for type generation (#55056)
The Archaeologist generate-types action ran a full `yarn install`, which
builds the spec/fixtures/native-addon/* workspaces concurrently on a cold
node-gyp cache. node-gyp copies headers into the shared devDir
non-atomically (nodejs/node-gyp#3301), so a fixture can compile against
a half-written header and flake the job.

Type generation only needs @electron/docs-parser and
@electron/typescript-definitions, which are plain JS, so skip build
scripts entirely. This also makes the job faster.


Claude-Session: https://claude.ai/code/session_01EyzGBdHYekwCgoTwBy4bcb

Co-authored-by: Claude <noreply@anthropic.com>
2026-10-16 10:18:49 -07:00
claude[bot]andClaude Opus 5.5 2ba5be3978 fix: avoid misaligned char16_t reads in crdtp string deserialization (#54804)
* fix: avoid misaligned char16_t reads in crdtp string deserialization

Copy STRING16 CBOR payloads into an aligned buffer before converting them,
fixing the "misaligned address for type 'const char16_t'" UBSan abort.

Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01TvtfDf4VmRTDrn2oZYYK6Q

* chore: link upstream CL in crdtp alignment patch

Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01TvtfDf4VmRTDrn2oZYYK6Q

---------

Co-authored-by: Claude <noreply@anthropic.com>
2026-10-16 10:06:43 -07:00
claude[bot]andClaude c37ca8bbfd docs: update tutorials for Electron Forge 8 (#54926)
Forge 8 moved `electron-forge import` into create-electron-app and made
`electron-forge publish` a deprecated alias for `electron-forge release`.
Update the packaging tutorial to import via create-electron-app and the
publishing tutorial to use the release command.


Claude-Session: https://claude.ai/code/session_01QrLq1PMBg8cho8fEt4vRG9

Co-authored-by: Claude <noreply@anthropic.com>
2026-10-16 01:15:17 -07:00
claude[bot]andClaude Opus 5.5 a58b297ab2 build: handle empty .patches files in patches-stats (#55038)
* build: handle empty .patches files in patches-stats

Skip empty .patches files instead of trying to read the patch directory itself as a patch, matching the guard in script/lint.js.

Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01NaKbwSnZWfbpde5rv7z4VT

* build: surface patches stats upload failures as a warning

Replace the `|| true` on the patches stats upload step with a `::warning::` annotation so failures are visible in GitHub Actions without failing the job.

Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01NaKbwSnZWfbpde5rv7z4VT

---------

Co-authored-by: Claude <noreply@anthropic.com>
2026-10-16 00:51:27 -07:00
claude[bot]andClaude 324b659c35 ci: bump build-tools to pick up the Windows clang-cl siso timeout (#54958)
Bump the pinned @electron/build-tools SHA from 32e2253f to 3bf7c9f5 to
pick up electron/build-tools#912, which raises siso's remote timeout for
Windows clang-cl compiles to 10m (matching macOS) so heavy compiles
finish remotely and get cached instead of falling back to local on every
warm build. Also picks up electron/build-tools#911 (e-rcv only).


Claude-Session: https://claude.ai/code/session_01GkpQ9nmAGxxVpwT8wPzfbC

Co-authored-by: Claude <noreply@anthropic.com>
2026-10-15 13:23:21 -04:00
claude[bot]andClaude 1f3fd88e4a fix: notify the browser of user activation in webContents.executeJavaScript (#54923)
When `userGesture` is set, webContents.executeJavaScript() and
executeJavaScriptInIsolatedWorld() only activated the frame in the
renderer, which then reports the activation to the browser on the
frame's channel-associated interfaces. A request the script makes on its
own Mojo pipe, such as FileSystemFileHandle.createWritable() or
navigator.hid.requestDevice(), can reach the browser before that update
and be refused for lacking user activation.

Update the browser's activation state before sending the script, as
RenderFrameHostImpl::ExecuteJavaScriptForTests() (used by
webFrameMain.executeJavaScript()) already does.


Claude-Session: https://claude.ai/code/session_01LPMvJBQiyP6b7QjatACmnS

Co-authored-by: Claude <noreply@anthropic.com>
2026-10-14 19:30:49 -05:00
claude[bot]andClaude Opus 5.5 4a802b071e fix: deliver pending utilityProcess messages before emitting exit (#54924)
* fix: deliver pending utilityProcess messages before emitting exit

HandleTermination closed the parentPort connector before emitting 'exit',
so messages the child had posted but the browser had not dispatched yet
were dropped. The connector dispatches one message per task, and the exit
notification can already be queued ahead of those tasks, so a child that
posts several messages and then calls process.exit() lost all but the
first.

Dispatch whatever is already queued on the port before closing it. Browser
shutdown still closes the port without dispatching, since the child is
still running then.

Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01LPMvJBQiyP6b7QjatACmnS

* test: extract sleepSync helper and drop utility-process ack handshake

Move the Atomics.wait() call in the utilityProcess message-before-exit
test into a documented sleepSync() spec helper.

With pending parentPort messages now dispatched before 'exit', the
api-net-spec.js fixture can post its result and exit right away again,
so remove the ack handshake that #54901 added as a workaround, along
with the error logging that covered the wait for the ack.

Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01LPMvJBQiyP6b7QjatACmnS

---------

Co-authored-by: Claude <noreply@anthropic.com>
2026-10-14 18:59:38 -04:00
claude[bot]andClaude Opus 5.5 fc354a26ab test: fix flaky specs that relied on the individual-test rerun (#54901)
* build: stop re-running failed specs individually at the end of a test job

script/spec-runner.js had an --enableRerun mode that, after a failing run,
parsed the JUnit report and re-ran each failed test on its own in a fresh
Electron. CI passed --enableRerun=3 on the macOS, Windows and Linux test
legs, so a test that only passes when it has the machine to itself turned
the job green while still being recorded as a failure. In practice the mode
only ever made one solo attempt per test (a failed rerun exited the runner
immediately), and later failures were never rerun once an earlier one
failed again.

Remove the mode: the JUnit parsing, the solo rerun loop, the per-launch
--log-file renaming and the --files filtering that only reruns used. A
failing run now exits 1 straight away. Drop --enableRerun=3 from the test
workflow and the @xmldom/xmldom dev dependency that only the JUnit parser
used. vitest's in-suite retry (retry: 3 on CI) is unchanged.

Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01LPMvJBQiyP6b7QjatACmnS

* test: give the MSIX suite's setup PowerShell commands more time

The autoUpdater MSIX suite installs its signing certificate and registers
Electron as a sparse package in a before hook, each through PowerShell with
a 30s timeout. While other spec files run alongside it, these two commands
regularly take longer than that on windows-arm64 (the hook failed after
roughly 60-90s), but they complete when the suite runs on its own, which is
why the job only went green through the end-of-job solo rerun. vitest does
not retry a failed hook, so with the rerun gone that would fail the job.

This is a timeout increase on purpose: the operations themselves are just
slow on a loaded host. Give those two setup commands 120s each and the hook
300s; every other PowerShell call keeps the 30s limit.

Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01LPMvJBQiyP6b7QjatACmnS

* test: make sure the browser sees user activation before createWritable()

"File System API, denies permission when trying to create a writable file
handle" failed every in-suite attempt on Linux and macOS with
"SecurityError: User activation is required to request permissions", and
the permission request handler was never called, so the browser-side
FileSystemAccessPermissionContext saw no transient activation. It passed
when re-run on its own.

The test grants activation and calls createWritable() in the same
executeJavaScript(code, true). The renderer reports the activation on the
frame's channel-associated LocalFrameHost interface, but createWritable()
reaches the browser on the file handle's own Mojo pipe, so the permission
check can run before the activation update has been processed. Activate
the page in a separate executeJavaScript() call first: its reply comes back
on the channel-associated ElectronFrame interface, after the activation
update. Do the same in the matching "allows permission" test, which makes
the same request.

This is the most likely explanation from the code and the in-suite traces;
the failure doesn't reproduce on an idle Linux machine.

Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01LPMvJBQiyP6b7QjatACmnS

* test: poll for the restarted Network Service instead of sleeping 500ms

The Network Service crash recovery specs crash the service and then sleep
for a fixed 500ms before asserting that the next net.fetch() succeeds. On
busy Windows runners the NetworkContext (or, for the utility process, the
URLLoaderFactory update) isn't back yet after 500ms, and the fetch fails
with net::ERR_FAILED. The test then only passed when re-run on its own.

Poll a probe server with net.fetch() until a request succeeds, then make
the asserted request.

Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01LPMvJBQiyP6b7QjatACmnS

* test: acknowledge utility process results before the child exits

The api-net-spec.js fixture runs itUtility test bodies in a utility
process and does postMessage(result) immediately followed by
process.exit(0). The result travels over the parent port's message pipe
and the exit is reported by the process host, so the exit can reach the
parent first (or the message can be lost entirely when the process goes
away before the port is flushed). On Windows this failed a scattering of
net specs with "utility process exited (0) before posting a result",
which then passed when re-run on their own.

Make the fixture wait for an acknowledgement from the parent before it
exits, on the failure paths too, and have waitForUtilityResult() send that
acknowledgement once it has the result.

Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01LPMvJBQiyP6b7QjatACmnS

* test: navigate to a local page in the sandbox "exit" event spec

"exposes "exit" event to preload script" registers a process 'exit'
handler that sends an IPC, then navigates the hidden window to
http://www.google.com. That is a cross-site navigation, so the 'exit'
handler runs while the old document is being unloaded in a renderer that
is about to go away, and on busy macOS runners the IPC sometimes never
arrived (the test timed out after 30s and passed when re-run on its own).
It also made the test depend on reaching the internet.

Navigate to spec/fixtures/pages/blank.html instead. The unload then stays
in the same renderer and the IPC is sent before the new page commits.

Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01LPMvJBQiyP6b7QjatACmnS

* test: reach the heap limit quickly in the heap snapshot utility spec

"supports generating snapshots via v8.setHeapSnapshotNearHeapLimit" forks
oom-grow.js with a 50MB old space limit and waits for it to run out of
memory. The fixture grew the heap by one 1000-character string per
setImmediate, so it took tens of thousands of event loop turns (about 8s on
an idle Linux machine) to get near the limit, and on busy macos-x64 runners
that went past the 60s timeout. It passed when re-run on its own.

Allocate an array of 128K numbers per turn instead. The test now takes
about 1s locally (1.2-1.7s with every core busy) and still produces the
snapshot it checks for.

Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01LPMvJBQiyP6b7QjatACmnS

* test: wait for the guest to be destroyed in the USB/HID chooser specs

The navigator.usb and navigator.hid "does not crash when the requesting
webContents is destroyed from the select-*-device handler" specs call
guest.destroy() in the handler and then check isDestroyed() after a single
setTimeout() tick. destroy() only posts the teardown to the UI thread, so on
a busy runner the check can run first and fail with "expected false to be
true" (seen on macos-x64).

Poll isDestroyed() until it is true instead.

Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01LPMvJBQiyP6b7QjatACmnS

* test: run the document.visibilityState/hidden specs serially

"visibilityState changes when window is hidden" failed all four in-suite
attempts on a macos-x64 main push with "expected 'hidden' to equal
'visible'" on the page's first report, before the test hides the window,
and passed when re-run on its own. These specs run in the parallel phase,
where other spec files open windows at the same time. On macOS a window
that another one covers is occluded, and Chromium then reports its page as
hidden.

Tag the describe serial so its windows are the only ones on screen.

Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01LPMvJBQiyP6b7QjatACmnS

* test: run the protocol.handle throughput spec serially

"protocol module handle is fast" compares the time to fetch a 128MB body
directly and through a protocol.handle() interceptor and requires the
median ratio to stay under 3. It ran in the parallel phase, where other
spec files' Electron processes compete for the CPU and can slow one side of
a pair more than the other; on the Chromium roll PR and on release
branches it failed with "median ratio >= 3" and passed when re-run on its
own.

Tag it serial so the measurement has the machine to itself.

Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01LPMvJBQiyP6b7QjatACmnS

* test: wait longer for the preload code cache probe in its before hook

The "preload code cache" suite's before hook loads a probe preload and
waits up to 5s for its cache file to appear, to learn the process lock
half of the file name. The browser writes that file from a BEST_EFFORT
thread pool task, which a busy machine can hold back for longer than that;
on macos-arm64 the hook failed with "timed out waiting for probe cache file
to be written" and passed when re-run on its own. vitest does not retry
hooks, so give this wait 30s (it returns as soon as the file is there) and
the hook 60s.

Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01LPMvJBQiyP6b7QjatACmnS

* test: run the import/require parity fixture from a test, not a hook

The "import / require parity" suite ran its fixture app, which starts a
main, a utility and a renderer process, in a before hook with the 20s
fixture timeout. On busy windows-x64 runners it sometimes did not finish
in time ("Timed out after 20000ms waiting for ... import-require-parity to
exit") and the suite only passed when re-run on its own. vitest does not
retry hooks, so with that rerun gone a single slow launch would fail the
job.

Run the fixture from the first test instead and share the result with the
other two. A failed or timed-out run is forgotten, so vitest's retry of
that test starts a fresh one, like every other fixture launch in this file.

Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01LPMvJBQiyP6b7QjatACmnS

* test: skip already-destroyed webContents in cleanupWebContents()

cleanupWebContents() takes a snapshot of webContents.getAllWebContents()
and destroys each entry in turn. Destroying one can take others in the
snapshot down with it (its guests or devtools, for example), and calling
destroy() on one of those throws "Object has been destroyed". That failed
the "chrome extensions" suite's after hook on linux-x64, and hooks are not
retried, so the suite only passed when re-run on its own.

Skip entries that are already destroyed.

Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01LPMvJBQiyP6b7QjatACmnS

* test: focus the webview before requesting fullscreen in the ESC spec

Since Chromium 157 refuses requestFullscreen() from a view that doesn't
have focus (SuppressFullscreenFromUnfocusedView, the same change #54883
handled for the simpleFullScreen spec), "pressing ESC should emit the
leave-html-full-screen event" has needed in-suite retries on macOS. The
test used a hidden window, whose page can never be focused.

Use a shown window, take app activation on macOS as #54883 does, focus the
window and then the <webview> element, and wait until the guest page
reports document.hasFocus() before calling requestFullscreen().

Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01LPMvJBQiyP6b7QjatACmnS

* test: share the Network Service recovery probe between the crash specs

Both crash-recovery specs now wait through waitForNetworkServiceRecovery(),
which races each probe against a timeout and, for the utility process
variant, the child's exit, so a stalled request or a dead child fails fast
with its cause. The network-restart-test.js child is now registered with
deferKillUtilityProcess so that a failed wait doesn't leak it.

Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01LPMvJBQiyP6b7QjatACmnS

* test: refocus the window on each poll in the webview ESC spec

Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01LPMvJBQiyP6b7QjatACmnS

* test: give every preload code cache write wait the same longer timeout

The per-test waits on the cache write still used waitFor's 5s default,
while the beforeAll probe waiting on the same thread pool write had 30s.
They now share cacheWriteTimeout, and the suite's test timeout leaves room
for it.

Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01LPMvJBQiyP6b7QjatACmnS

* test: give the MSIX afterAll unregistration the setup timeout too

Remove-AppxPackage runs in a hook under the same load as setup, and hooks
are not retried. Both hook timeouts are now derived from
powershellSetupTimeout so that they cover the commands they run.

Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01LPMvJBQiyP6b7QjatACmnS

* test: navigate the sandbox exit-event page cross-site to a local server

The page now navigates to the suite's server on 127.0.0.1, so 'exit' is
again covered on a cross-site, process-swapping navigation, as it was
with google.com, without depending on the internet. The spec checks that
the navigation did swap processes.

Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01LPMvJBQiyP6b7QjatACmnS

* test: run createWritable() through webFrameMain.executeJavaScript()

webFrameMain.executeJavaScript() updates the browser process's user
activation state before it runs the script, so the permission request no
longer races the activation update. This replaces the extra activation
round trip.

Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01LPMvJBQiyP6b7QjatACmnS

* build: reject a leftover --enableRerun in the spec runner

It is no longer a known option, so it would otherwise be forwarded to the
Electron workers as a switch that silently does nothing.

Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01LPMvJBQiyP6b7QjatACmnS

* test: break comments added in this PR at sentence and clause boundaries

Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01LPMvJBQiyP6b7QjatACmnS

* test: keep the individual-test rerun for now (moved to a follow-up)

Per review, this PR now only fixes the specs that passed thanks to the
end-of-job solo rerun, so the fixes can be backported. Restore the spec
runner's --enableRerun mode, its @xmldom/xmldom dependency, --enableRerun=3
in the test workflow and the vitest.config.ts comment to main's versions.
Removing the rerun moves to a follow-up once main has been clean for a
few days.

Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01LPMvJBQiyP6b7QjatACmnS

* test: go back to a same-site navigation in the sandbox exit-event spec

A cross-site navigation unloads the old page through
RenderFrameHostImpl::Unload, which gives the renderer only
kUnloadTimeout (500ms) before the process is torn down.
That is the race this spec originally lost on busy runners.

Navigate to the local blank.html again,
so the unload stays in the same renderer,
and drop the process-swap check and the IPC handshake
that only the cross-site variant needed.

Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01LPMvJBQiyP6b7QjatACmnS

* test: retry a Network Service recovery probe that times out

A probe that got no response within 5s threw,
and waitUntil fails on a thrown error,
so one slow probe right after the crash failed the test
although the next one would have succeeded.
A timed-out probe now counts as a failed attempt;
only the utility process exiting still fails right away.

Since a probe can now be abandoned while its fetch is still in flight,
the utility process fixture echoes an id sent with each fetch,
and the spec waits for the reply with that id,
so a late reply isn't taken as the reply to a later probe
or to the final fetch.

Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01LPMvJBQiyP6b7QjatACmnS

* test: handle a rejected 'exit' wait before the first recovery probe

once(child, 'exit') rejects if the utility process emits 'error',
and nothing chained off it until the first recovery probe.
An 'error' before then was an unhandled rejection,
which fails the whole run rather than this test.

Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01LPMvJBQiyP6b7QjatACmnS

* test: log errors in the utility net fixture while it waits for the ack

The fixture now stays up for a round trip after posting its result.
In that window, leftover async work from the test body
(a socket 'error' with no listener, a late unhandled rejection)
could kill it with a non-zero code and fail a test that passed.
While waiting for the ack, log such errors instead.

Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01LPMvJBQiyP6b7QjatACmnS
2026-10-14 15:23:33 -05:00
claude[bot]andClaude Opus 5.5 667340e75a ci: use the workflow token for GitHub file fetches (#54904)
* ci: use gh repo read-file instead of curling raw.githubusercontent.com

Fetch the Node.js ABI version registry with an authenticated
`gh repo read-file` call so the check is not subject to the
unauthenticated raw.githubusercontent.com rate limit.

Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_011cCzirYhYrRFvXMXrSZvHd

* ci: authenticate Chromium DEPS fetches in lint workflow

The lint workflow downloaded Chromium's DEPS and buildtools/DEPS from
raw.githubusercontent.com anonymously, which is subject to GitHub's
unauthenticated rate limits, and `curl -sL` would silently write an
error body into the DEPS file on failure. Fetch them through the REST
contents API with the workflow token instead (the build container has
no gh CLI), and use `-f --retry 3` so failures are loud.

Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_011cCzirYhYrRFvXMXrSZvHd

---------

Co-authored-by: Claude <noreply@anthropic.com>
2026-10-14 19:13:56 +00:00
claude[bot]andClaude Opus 5.5 5b46c1f9a0 fix: rebuild the session URLLoaderFactory after a Network Service restart (#54902)
* fix: rebuild the session URLLoaderFactory after a Network Service restart

content::RestartNetworkService() notifies Network Service process gone
handlers synchronously, before StoragePartitionImpl has noticed that its
NetworkContext is gone (it only re-initializes the context from the old
pipe's disconnect handler). ElectronBrowserContext clears its cached
URLLoaderFactory in that notification, but if GetURLLoaderFactory() runs
before the StoragePartition's disconnect handler fires, it builds a new
factory on the dying NetworkContext and caches it forever, so every later
net.fetch()/session.fetch() on that session fails with net::ERR_FAILED.

Keep a cloned Remote to the cached factory and rebuild the factory once
that clone has been disconnected, the same way Chromium's reconnectable
factories rebuild when they are no longer connected.

Make the main-process crash recovery spec probe net.fetch() right after
the restart instead of sleeping for 500ms, so it exercises this window.

Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01LPMvJBQiyP6b7QjatACmnS

* fix: use ReconnectableURLLoaderFactory for the session URLLoaderFactory

Instead of resetting the cached URLLoaderFactory from a Network Service
process gone handler (which can run before StoragePartitionImpl has
reinitialized its NetworkContext) and watching a cloned pipe for
disconnects, hold a content::ReconnectableURLLoaderFactory, the same way
StoragePartitionImpl does for its own browser process factory. Its create
callback rebuilds the WillCreateURLLoaderFactory chain from the default
StoragePartition's current NetworkContext whenever the cached factory has
been disconnected.

Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01LPMvJBQiyP6b7QjatACmnS

---------

Co-authored-by: Claude <noreply@anthropic.com>
2026-10-14 10:56:06 -04:00
claude[bot]andClaude Opus 5.5 bec2821ba7 test: focus the page before requesting fullscreen in simpleFullScreen spec (#54883)
* test: focus the page before requesting HTML fullscreen in simpleFullScreen spec

Chromium 157 now refuses requestFullscreen() when the requesting view
does not have focus, even with a user gesture (the
SuppressFullscreenFromUnfocusedView feature was switched to stable in
https://chromium-review.googlesource.com/c/chromium/src/+/8527266).
Since the 157.0.8100.0 roll, "does not exit simpleFullScreen when
requestFullscreen is called" fails every in-suite attempt on macOS with
"TypeError: not granted" and only passes when re-run on its own.

Wait until the window is focused and the page reports document.hasFocus()
after entering simple fullscreen, before requesting HTML fullscreen.

Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01LPMvJBQiyP6b7QjatACmnS

* test: steal app activation before focusing the simpleFullScreen page

webContents.focus() activates the app with activateIgnoringOtherApps:NO,
so when an earlier fullscreen spec leaves another app frontmost it never
regains activation and document.hasFocus() stays false. On the
macos-arm64 (mas) shard the first attempt timed out in focusWebContents
after 10s. Take activation explicitly with app.focus({ steal: true })
before waiting for the page to be focused.

Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01LPMvJBQiyP6b7QjatACmnS

---------

Co-authored-by: Claude <noreply@anthropic.com>
2026-10-13 23:58:08 +00:00
claude[bot]andClaude da4c6886fb ci: minimize the runner terminal window before Windows PGO collection (#54845)
Since the Chromium 157 roll, native window occlusion treats the runner's
console window as covering the benchmark window on windows-11-arm, so the
page goes hidden and the browser benchmarks never start. This applies the
same minimize step that #54354 added for the spec pipeline.


Claude-Session: https://claude.ai/code/session_01CMnZca8hbAx3iAsLvGkMzk

Co-authored-by: Claude <noreply@anthropic.com>
2026-10-12 23:30:29 -07:00
claude[bot]andClaude 166ab5d05b ci: log esbuild exit status on macOS build failures (#54801)
The macOS "Failed to run esbuild: Error: The service was stopped" flake
shows the esbuild child's stdout closing with no panic trace, so it is
not clear whether esbuild was killed or exited. devtools-frontend's
esbuild.js always sets ESBUILD_BINARY_PATH to third_party/esbuild/esbuild,
so on macOS move the real binary to esbuild.real and install a wrapper
there. It passes stdin/stdout (the service protocol) through untouched,
tees stderr, and for a failed run writes the exit code or signal, pids,
args and stderr tail to $RUNNER_TEMP/esbuild-exit-logs. The failure-only
macOS diagnostics step prints those records and any recent esbuild/node
crash reports from DiagnosticReports, and uploads them as an artifact.


Claude-Session: https://claude.ai/code/session_01C54ZXg4wkmKsg8WHQ4wv1J

Co-authored-by: Claude <noreply@anthropic.com>
2026-10-12 17:24:38 -04:00
claude[bot]andClaude Opus 5.5 04449e9846 fix: block macOS firmlink alias paths in File System Access blocklist (#54679)
* fix: carry upstream macOS firmlink blocklist fix into exposed FSA blocklist

Chromium 156.0.8078.3 already contains upstream 64c8e2a1ceda ("[FSA] Block
macOS firmlink alias paths to sensitive directories"), but
refactor_expose_file_system_access_blocklist.patch re-adds
NormalizeFilePath()/GenerateBlockPaths() as static members in the header
without the new pieces, so Electron's copy of the blocklist does not carry
the fix.

Update the patch's header copy to match upstream: add the
MaybeStripMacDataVolumePrefix() and NormalizeFilePathForBlocklist() static
helpers, the /System/Volumes kBlockAllChildren rule, and normalize
generated rules through NormalizeFilePathForBlocklist().

Refs https://chromium-review.googlesource.com/c/chromium/src/+/8410087 (upstream commit 64c8e2a1cedafdbcc750abc423ad9b389537c223)

Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01MtuMgvwAcw7t9Q6HEB31Vx

* fix: fold macOS Data volume firmlink paths in file system access blocklist checks

Switches Electron's copy of ShouldBlockAccessToPath() to the
NormalizeFilePathForBlocklist() helper (from upstream 64c8e2a1ceda, exposed
in the header by the companion refactor_expose_file_system_access_blocklist
patch update), so paths spelled via /System/Volumes/Data are matched
against the root-namespace blocklist rules the same way Chrome does.

Refs https://chromium-review.googlesource.com/c/chromium/src/+/8410087 (upstream commit 64c8e2a1cedafdbcc750abc423ad9b389537c223)

Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01MtuMgvwAcw7t9Q6HEB31Vx

* test: cover /System/Volumes/Data alias paths in FSA blocklist

Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01MtuMgvwAcw7t9Q6HEB31Vx

* test: resolve home dir symlinks and cover /System/Volumes rule in FSA firmlink spec

Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01MtuMgvwAcw7t9Q6HEB31Vx

---------

Co-authored-by: Claude <noreply@anthropic.com>
2026-10-10 12:36:46 +01:00
claude[bot]andClaude ee103a5761 build: accept in-range Chromium cherry-picks in roller lint (#54790)
When a referenced CL first landed outside the roll range, check its
ChromiumDash CHERRY_PICK relations and accept the CL if one of those
cherry-picks landed inside the range. Upstream fixes are often
cherry-picked back to the release branch a roller tracks, so the
original CL's earliest version is newer than the roll.

Skip-Lint: Electron-only lint script change, no Chromium CL to reference


Claude-Session: https://claude.ai/code/session_01JRenJ1F4jDUjHjqFsnZ8fF
(cherry picked from commit 24bb4b8881)

Co-authored-by: Claude <noreply@anthropic.com>
2026-10-10 11:00:24 +00:00
claude[bot]andClaude 2ccdf3f405 test: fix file paths in vitest GitHub Actions annotations (#54813)
CI checks Electron out in src/electron rather than at GITHUB_WORKSPACE,
so the github-actions reporter emitted absolute paths in failure
annotations and job summary permalinks that pointed at
src/electron/spec/... Map them to paths relative to the repo root.


Claude-Session: https://claude.ai/code/session_017VP4oeZGEQd17hf55hysYL

Co-authored-by: Claude <noreply@anthropic.com>
2026-10-10 10:37:43 +00:00
claude[bot]andClaude 1a4f7601a1 ci: only fail branch audit on annotations from failed check runs (#54814)
Since switching to Vitest, retries within a test run create error
annotations on GHA even when the test passes on retry. Only report
error annotations when the check run itself concluded with failure.


Claude-Session: https://claude.ai/code/session_0121mfvEwWPCmTmmWsC4feka

Co-authored-by: Claude <noreply@anthropic.com>
2026-10-10 11:37:38 +01:00
claude[bot]andClaude 054d1a159f test: wait for stable focus before checking openExternal removes focus (#54669)
test: wait for stable focus before openExternal blur check

The browser launched by the earlier shell.openExternal() specs can still
be coming to the front when the macOS "removes focus" spec opens its
window, taking focus back right after the window first gains it. Wait
until the window holds focus (re-focusing it if needed) before calling
openExternal and waiting for blur.


Claude-Session: https://claude.ai/code/session_01X1mwQWDtyUGtjT3hFLoqms

Co-authored-by: Claude <noreply@anthropic.com>
2026-10-07 08:02:57 +00:00
claude[bot]andClaude 75d042de11 fix: block WSL UNC paths in File System Access sensitive directory checks (#54676)
Port the upstream Chromium fix onto Electron's copy of MaybeIsLocalUNCPath()
so that `wsl.localhost` and `wsl.localhost.` UNC hosts are treated as local
(case-insensitive) and blocked like other local UNC paths.

Refs https://chromium-review.googlesource.com/c/chromium/src/+/8341352 (upstream commit bc5a321c6196db0a2de36f1fe3e4fab977b10007)


Claude-Session: https://claude.ai/code/session_018khRcY1YYaYT95VfQQiaGj

Co-authored-by: Claude <noreply@anthropic.com>
2026-10-07 16:59:37 +09:00
claude[bot]andClaude Opus 5.5 6abd6a31bf test: run WebContentsView focusOnNavigation and shell.openExternal specs serially (#54662)
* test: wait for focus event in WebContentsView focusOnNavigation spec

The WebContentsView focusOnNavigation block was not tagged serial, unlike
the equivalent block in api-web-contents.spec.ts. On macOS another
parallel worker (notably the shell.openExternal specs, which bring the
default browser to the front) can take app activation away mid-test.
The window then stops being key, ReadyToCommitNavigation skips focusing
because the owner window is inactive, and isFocused() returns false.

Run the block in the serial phase, and wait for the webContents 'focus'
event after navigating instead of checking isFocused() as soon as
loadURL resolves.

Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01X1mwQWDtyUGtjT3hFLoqms

* test: run shell.openExternal specs serially

On macOS the shell.openExternal specs launch the default browser and bring
it to the front. While they ran in the parallel phase, that took app
activation away from focus-sensitive specs in other workers (for example
the WebContentsView focusOnNavigation spec on macOS x64). Run them in the
serial phase so nothing else is running when the browser activates.

Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01X1mwQWDtyUGtjT3hFLoqms

---------

Co-authored-by: Claude <noreply@anthropic.com>
2026-10-07 00:48:41 +00:00
claude[bot]andClaude Opus 5.5 dc580b6529 docs: note that beta.1 waits for the Chromium roll (#54649)
* docs: note beta.1 waits for the Chromium roll

The Releases WG moved alpha-to-beta promotion to release automation,
gated on the release branch's Chromium reaching the version in Chrome's
Beta channel. beta.1 is no longer a fixed date, so stop listing it as one
of our solid release dates and note it can land a few days late.

Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01AmPhpNhEFuPd7juZ3fc781

* docs: explain beta.1 delay without roll jargon

Say plainly that beta.1 can be late when the release branch has not yet
been updated to the Chromium Beta-channel version, instead of referring
to "our Chromium roll" without explaining it.

Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01AmPhpNhEFuPd7juZ3fc781

* docs: link Chrome's Beta channel in release timeline

Link to Chromium's release channel page and briefly explain that the
Beta channel is where each Chrome version is tested for about four weeks
before stable.

Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01AmPhpNhEFuPd7juZ3fc781

* docs: clarify which release dates are fixed

Replace "our solid release dates" with plain wording: alpha.1 and stable
ship on the scheduled dates, while the prereleases in between, including
beta.1, don't have fixed dates.

Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01AmPhpNhEFuPd7juZ3fc781

* docs: tighten beta.1 timing note

Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01AmPhpNhEFuPd7juZ3fc781

* docs: use canonical Chrome release channels URL

Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01AmPhpNhEFuPd7juZ3fc781

---------

Co-authored-by: Claude <noreply@anthropic.com>
2026-10-06 17:46:30 +01:00
claude[bot]andClaude cba5248898 docs: document preload code cache threat model (#54654)
Explain why SetFromRenderer stores the renderer-produced blob unverified and that the (BrowserContext, ProcessLock, id) scope is the security boundary.


Claude-Session: https://claude.ai/code/session_018A4Mt59Nr4h4WSFjyNNkxb

Co-authored-by: Claude <noreply@anthropic.com>
2026-10-07 00:47:31 +09:00
claude[bot]andClaude Opus 5.5 78d8f05222 test: add mouse-input addon for setIgnoreMouseEvents specs (#54535)
* test: add Windows mouse-input addon for setIgnoreMouseEvents specs

Adds @electron-ci/mouse-input, a Windows-only native test addon that
injects real mouse input with SendInput(). Unlike
webContents.sendInputEvent() these events go through the WH_MOUSE_LL
hook that setIgnoreMouseEvents(true, { forward: true }) relies on.

Uses it for serial specs covering click-through, forwarding of moves,
mouseenter/mouseleave stability inside an element and :hover being
cleared when the cursor moves off an element. On CI the suite fails
instead of skipping when SendInput cannot inject input.

Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01Y5cq8qhU8xUitP6SzyT2FV

* test: extend mouse-input addon to macOS and Linux X11

Adds CGEventPost (macOS) and XTEST (Linux X11, dlopen()ed so no dev
headers are needed) backends behind the existing JS API and generalizes
the setIgnoreMouseEvents real-input spec: hit testing on Windows and X11,
click-through on all three, forwarding cases on macOS and Windows only.

Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01Y5cq8qhU8xUitP6SzyT2FV

* ci: install libXtst in Linux test jobs that lack it

The mouse-input spec addon loads libXtst.so.6 at runtime for XTEST. The
x64 build image ships it but the arm64 test image does not, so install
the runtime package there before running the specs.

Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01Y5cq8qhU8xUitP6SzyT2FV

* ci: dismiss the first sign-in privacy window on Windows test runners

The windows-11-arm image shows Windows' "Choose privacy settings for
your device" window full screen above even topmost windows, so real
mouse input clicked it instead of the windows under test and the OS hit
tested it at the test point (seen in the mouse-input spike's
screenshots). Stop UserOOBEBroker/WWAHost and set the policies that keep
it from coming back, logging the windows on screen before and after.

Add describeWindowAtPoint() to the Windows addon backend and report it
when the hit test or click-through cases time out, so a covering window
is named in the failure.

Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01Y5cq8qhU8xUitP6SzyT2FV

* ci: also close the Start menu on Windows test runners

With the first sign-in privacy window gone, windows-11-arm had the Start
menu open over the test area: describeWindowAtPoint() reported its
CoreWindow at the hit test point, and the click-through case's click then
launched Calculator from it, which covered the point for the retries.
Stop StartMenuExperienceHost (it restarts with the menu closed) and log
what the OS hit tests on screen afterwards.

Before clicking, the click-through case now waits for the window below to
be what the OS hit tests at the point, where the platform can say, so a
covering window fails the case with its name instead of taking the click.

Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01Y5cq8qhU8xUitP6SzyT2FV

* test: keep ordinary windows from covering the click-through case

On windows-11-arm the runner's terminal (a Windows Terminal window
running wsl.exe) came up over the non-topmost window below after the
cleanup step ran, so the case's hit test check found it there. Make the
window below topmost too; the ignoring window is shown after it and
stays above it.

The cleanup step also found a System Properties dialog left at the
centre of the screen, so it now minimizes (dialogs: closes) every
visible, uncloaked top level window besides the desktop and taskbar
and logs each one, rather than stopping known processes only.

Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01Y5cq8qhU8xUitP6SzyT2FV

* ci: close the Start menu with Escape instead of stopping its host

Stopping StartMenuExperienceHost on the Windows test runners was followed
by WebContentsView visibilityState specs reading 'hidden' on
windows-11-arm in both runs that did it, and in none before. Only press
Escape when the Start menu's CoreWindow is actually showing (uncloaked),
and log its state.

Clearing the desktop now repeats until nothing is left: closing the
leftover System Properties dialog left its Performance Options dialog
over the test area.

Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01Y5cq8qhU8xUitP6SzyT2FV

* ci: sample window occlusion inputs during Windows specs (diagnostic)

With the Start menu closed on windows-11-arm, api-web-contents-view.spec.ts
sees freshly shown windows as hidden for a while (3 of 3 runs). Log the
display, screen saver and power request settings and the WSL/terminal
processes, then run a background sampler that records, whenever it changes,
the foreground window and any window able to occlude Electron's that sits
above the topmost Electron window, plus display on/off and session lock
changes. Its log is printed after the specs.

Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01Y5cq8qhU8xUitP6SzyT2FV

* ci: stop the windows-11-arm WSL update from covering the specs

The occlusion sampler showed what hides api-web-contents-view.spec.ts's
windows on windows-11-arm: the image runs
`wsl.exe --update --confirm --prompt-before-exit` and relaunches it about
every 90 seconds, each time in a new Windows Terminal window that takes the
foreground over most of the 1024x768 desktop for about a minute, so
Chromium's native occlusion tracking reports Electron windows beneath it as
hidden. The display never turned off (no display timeout on AC, display
status stayed on), so that is ruled out.

Log what launches the update, stop it (and its launcher when that is a
script host outside the step's own ancestry), and have the sampler minimize
any such window that still shows up.

Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01Y5cq8qhU8xUitP6SzyT2FV

* ci: trim the Windows occlusion sampler down to a WSL terminal minimizer

The sampler found what hid api-web-contents-view.spec.ts's windows on
windows-11-arm; drop its diagnostic sampling and the power and screen saver
dumps, and keep only what fixes it: a background minimizer, now
script/actions/minimize-wsl-terminals.ps1, that minimizes each
`wsl.exe --update` terminal as it appears and logs its title, pid and
parent process, printed after the specs.

Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01Y5cq8qhU8xUitP6SzyT2FV

---------

Co-authored-by: Claude <noreply@anthropic.com>
2026-09-30 14:57:53 -04:00
claude[bot]andClaude Opus 5.5 4c10d222cf ci: capture macOS memory-pressure diagnostics on build failure (#54006)
* build: bound devtools-frontend esbuild bundle concurrency on macOS

macOS x64 release builds have been failing in Build Electron when
devtools-frontend esbuild bundle actions die with "The service was
stopped": the esbuild service process is killed externally with no
crash trace, consistent with memory pressure on the 14 GB
macos-15-xlarge runners while siso runs five minify+sourcemap bundles
at once through the generic action pool.

Float a devtools-frontend patch that gives esbuild bundle actions their
own GN pool (depth 2 on macOS hosts), and dump vm_stat, swap usage and
the kernel memorystatus/jetsam log when a macOS build fails so the kill
is observable.

Co-Authored-By: Claude Fable 5.1 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01H2pb2QXCU6xBfNMLmjgrLU

* chore: update patches

Refresh the devtools-frontend BUILD.gn blob ids in the esbuild pool patch
after the Chromium roll on main moved the devtools-frontend pin. No change
to the patch content.

Co-Authored-By: Claude Fable 5.1 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01H2pb2QXCU6xBfNMLmjgrLU

* ci: drop esbuild pool patch, keep macOS memory diagnostics only

Scope this change down to the failure-only macOS memory-pressure
diagnostics step so we can confirm or rule out memory pressure as the
cause of the intermittent devtools esbuild failures before patching
devtools-frontend.

Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01U8eWCdgZ42Hdi8CMcrcrNb

---------

Co-authored-by: Claude <noreply@anthropic.com>
2026-09-30 14:06:39 -04:00
claude[bot]andClaude Opus 5.5 338a350f7e test: listen for both singleton exits before either can happen (#54593)
* test: listen for both singleton exits before either can happen

'prevents the second launch of app' only started listening for the first
instance's 'exit' after the second instance's exit had been handled. The
two copies quit within milliseconds of each other, so when the spec
process's event loop is busy and sees both exits in the same pass, the
first copy's 'exit' is emitted with no listener, and the test then waits
for it until the 120s test timeout.

Register both exit listeners as each process is spawned, as the other
requestSingleInstanceLock tests already do, kill both copies on the way
out, and fail within 30s naming which copy stalled instead of waiting
out the test timeout.

Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01XT1kpjmqsAdPLBVZMV1pVX

* test: use waitUntil for the singleton launch waits

Record each copy's exit code from an 'exit' listener attached at spawn
and wait on it with the existing waitUntil helper instead of a local
within() helper. Only kill a copy that is still running.

Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01XT1kpjmqsAdPLBVZMV1pVX

---------

Co-authored-by: Claude <noreply@anthropic.com>
2026-09-30 14:06:21 -04:00
claude[bot]andClaude 03703aea6a test: run pointer lock permission spec serially (#54546)
The helper waits for the webContents 'focus' event before requesting
pointer lock (#54529). In the parallel phase another spec's window can
hold focus, so the event never arrives and the first attempt times out
on macOS. Tag the block 'serial', like the clipboard and paste blocks
that use the same focus wait.


Claude-Session: https://claude.ai/code/session_011wzReGh8dFocAi8ujeiTsA

Co-authored-by: Claude <noreply@anthropic.com>
2026-09-29 16:50:57 -07:00
claude[bot]andClaude efbc851383 test: run fullscreen specs serially (#54549)
The `iframe using HTML fullscreen API while window is OS-fullscreened`
block in chromium.spec.ts and the macOS `fullscreen state` block in
api-browser-window.spec.ts move windows in and out of OS fullscreen.
Under the parallel runner two of these transitions can overlap on
macOS and one never finishes, timing out the test. Tag both blocks
serial.


Claude-Session: https://claude.ai/code/session_01XUFN2KBqhJMviaCibjxNUU

Co-authored-by: Claude <noreply@anthropic.com>
2026-09-29 16:50:44 -07:00
claude[bot]andClaude 1d0cc3e705 test: wait for PageState sync before navigating in restore spec (#54504)
The previous fix waited for the edited form state after navigating away,
where it can only arrive via the old frame's unload-time update. The
browser only waits briefly for that frame to unload, so a slow hidden
renderer could still miss it. Wait for the renderer's delayed state sync
while the form page is still current instead.


Claude-Session: https://claude.ai/code/session_01VEsRtPpi9c1f38o3GaZskj

Co-authored-by: Claude <noreply@anthropic.com>
2026-09-29 16:49:28 -07:00
claude[bot]andClaude d23dd9df44 ci: enable faraday hold-for-review gate (#54202)
Adds the hold-for-review block to .github/faraday.yml so that a pull request carrying the hold-for-review label is held for 24 business hours (Pacific time) before faraday lets it merge; pull requests carrying fast-track are exempt. The gate is implemented in electron/faraday#24.


Claude-Session: https://claude.ai/code/session_01DpVCp5zarjEPP2s4MQwLXo

Co-authored-by: Claude <noreply@anthropic.com>
2026-09-29 19:29:29 -04:00
claude[bot]andClaude e128184820 fix: avoid NoDestructor on trivially destructible QueueState in release builds (#54554)
With DCHECKs off, SEQUENCE_CHECKER expands to nothing, leaving QueueState
trivially destructible and tripping base::NoDestructor's static_assert.
Give it a user-provided destructor so it is non-trivial in every config.


Claude-Session: https://claude.ai/code/session_01FsSQW86CrHuBNQNRMyPCex

Co-authored-by: Claude <noreply@anthropic.com>
2026-09-29 11:02:05 -07:00
claude[bot]andClaude 2454be571a test: parse all custom page size PDFs in one pdf.js process (#54491)
`printToPDF() with custom page sizes` printed 11 page sizes and called
readPDF() on each one. Every readPDF() call starts a full Electron
process to run pdf.js. On macOS x64 CI, with the parallel vitest
workers, that is about 2-5s per call, so the loop often went over the
30s test timeout.

Add readPDFs(), which parses several PDFs in one pdf-reader process.
The test now prints every size first and then parses them all with a
single launch. readPDF() is now a wrapper around readPDFs().


Claude-Session: https://claude.ai/code/session_01TVWNFK7iBS3en5muZhanuM

Co-authored-by: Claude <noreply@anthropic.com>
2026-09-28 21:51:37 -07:00
claude[bot]andClaude 6b6c3023ed test: wait for focus before requesting pointer lock in spec (#54529)
content rejects requestPointerLock() with WrongDocumentError, without
ever consulting the permission request handler, when the widget does not
have focus. On macOS webContents.focus() takes effect asynchronously, so
the request could race ahead of focus and the helper found no recorded
permission request. Wait for the focus event first, and assert the
request was rejected by the handler (SecurityError).


Claude-Session: https://claude.ai/code/session_011wzReGh8dFocAi8ujeiTsA

Co-authored-by: Claude <noreply@anthropic.com>
2026-09-28 23:42:38 +00:00
claude[bot]andClaude c21fc2dd24 test: wait for earlier Electron workers to exit before serial specs (#54489)
vitest starts stopping a finished file's worker without waiting for it, so a
worker in the 'serial' project could launch while earlier Electron workers
were still quitting and be handed activation by them. From that state
app.hide() was ignored, and the macOS app.isActive and app.isHidden specs
timed out on every attempt. Serial workers now wait for all earlier workers
to exit, and the specs take activation through a window of their own before
hiding.


Claude-Session: https://claude.ai/code/session_01JBP7gbUymggpz1TCjF51Q1

Co-authored-by: Claude <noreply@anthropic.com>
2026-09-28 17:05:15 +02:00
claude[bot]andClaude 5213c824cb build: label main PGO profile update PRs with no-backport (#54482)
Each supported release branch gets its own profile update PR from its own
pgo-generation run, so the PR opened against main should never be
backported.


Claude-Session: https://claude.ai/code/session_01VbNpxpzqzEsUwcAgW6xiW8

Co-authored-by: Claude <noreply@anthropic.com>
2026-09-27 07:49:45 +00:00
claude[bot]andClaude 24b40f68b9 test: fix flaky navigationHistory.restore PageState spec (#54468)
The test read the restored input value once on dom-ready and then polled
that constant, so any early read turned into a guaranteed 10s timeout.
The saved PageState could also be snapshotted before the old
cross-process form page sent its final state on unload, leaving the
entry without the edited value.

Wait until the saved entry's PageState actually contains the typed value,
then await restore() and assert the input value directly.


Claude-Session: https://claude.ai/code/session_01VEsRtPpi9c1f38o3GaZskj

Co-authored-by: Claude <noreply@anthropic.com>
2026-09-27 06:06:32 +00:00
claude[bot]andClaude f4f4e8a0da test: fix chrome.tabs reload spec race with the reload commit (#54467)
chrome.tabs.reload() resolves after the reload has started, so the
reply to the 'reload' message is addressed to the document being
replaced. When the new document commits first the reply is dropped,
console-message never fires and the test times out.

Keep the reload result in the service worker, wait for did-finish-load,
then ask the reloaded page for it with a new getReloadStatus message.


Claude-Session: https://claude.ai/code/session_01KgNfjEYpFmXyDvfN11dqJM

Co-authored-by: Claude <noreply@anthropic.com>
2026-09-27 06:06:18 +00:00
claude[bot]andClaude Opus 5.5 783bf56ab7 fix: abort on wrong-typed optional string CDP param (#54418)
* test: add crash case for wrong-typed optional string CDP param

Sending a number for Input.dispatchKeyEvent's optional `text` param via
webContents.debugger aborts the browser process instead of rejecting.

Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01TvtfDf4VmRTDrn2oZYYK6Q

* test: add in-process debugger case for wrong-typed string param

Mirrors the crash-case fixture inside api-debugger.spec.ts.

Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01TvtfDf4VmRTDrn2oZYYK6Q

* fix: use Chromium's crdtp std::string traits in Node

Drop Node's crdtp::ProtocolTypeTraits<std::string> definitions so the
specialization has one definition, Chromium's, which reports a protocol
error on wrong-typed values instead of CHECKing.

Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01TvtfDf4VmRTDrn2oZYYK6Q

* chore: attribute crdtp traits patch to Claude

Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01TvtfDf4VmRTDrn2oZYYK6Q

---------

Co-authored-by: Claude <noreply@anthropic.com>
2026-09-26 20:15:16 +09:00
claude[bot]andClaude 0a6c0bb09b refactor: create WebContentsPreferences via WebContentsUserData helpers (#54273)
WebContentsPreferences attached itself to its WebContents from inside its
constructor, so every call site used a bare `new` that clang-tidy flags as
a leak. Make the constructor private and go through the standard
WebContentsUserData CreateForWebContents / GetOrCreateForWebContents
helpers instead, which also lets us drop the NOLINT suppression.


Claude-Session: https://claude.ai/code/session_0112Bsu49VLUQVoKDV6AVN2u

Co-authored-by: Claude <noreply@anthropic.com>
2026-09-25 17:47:41 -07:00
claude[bot]andClaude 4f001d6c2f ci: minimize the runner agent's terminal window before Windows tests (#54354)
On windows-latest runners the hosted-compute-agent's Windows Terminal
window is in the foreground and covers most of the 1024x768 desktop.
When it sits over test windows, Windows' native occlusion tracking marks
their pages hidden, which breaks frame- and visibility-dependent specs.
Minimize it before running the Electron specs.


Claude-Session: https://claude.ai/code/session_01RvyMenJ6w1FuaRBrspcAAN

Co-authored-by: Claude <noreply@anthropic.com>
2026-09-25 11:54:29 +00:00
claude[bot]andClaude 24b734b37d test: keep background-throttling hidden-page windows on top (#54344)
The setBackgroundThrottling() "on a page nobody can see" specs added in
#54311 fail their first attempt on Windows x64 CI. A newly shown test
window can land behind another window on the CI desktop, and Chromium's
native occlusion tracker then keeps the page hidden, so the steps that
expect frames from a shown window never see any. Create these windows
always-on-top so only hide() decides whether the page is visible.


Claude-Session: https://claude.ai/code/session_01RvyMenJ6w1FuaRBrspcAAN

Co-authored-by: Claude <noreply@anthropic.com>
2026-09-25 11:08:49 +02:00
claude[bot]andClaude Opus 5.5 70d678d1d9 docs: narrow clipboardItem.getType() return type from its MIME type (#54300)
* docs: narrow clipboardItem.getType() return type from its MIME type

Type getType() with a generic MIME type parameter and a conditional
return type so a literal `electron application/bookmark` resolves to a
ClipboardBookmark, any other literal MIME type resolves to a Blob, and
a non-literal string still resolves to the union. Adds ts-smoke cases
for all three and drops the now-unneeded `instanceof Blob` check from
the `text/uri-list` example.

Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01HmVsAQiHawruFHijTtkzV9

* build: bump @electron/docs-parser to 3.0.2

Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01HmVsAQiHawruFHijTtkzV9

---------

Co-authored-by: Claude <noreply@anthropic.com>
2026-09-24 20:01:03 -07:00
claude[bot]andClaude Opus 5.5 718c8a6425 docs: overhaul crash reporting documentation (#54280)
* docs: overhaul crash reporting documentation

Add a Crash Reporting tutorial covering how Crashpad collects minidumps,
setting up crashReporter, attaching context with globalExtra and
per-process parameters, reacting to process-gone events, receiving
uploads, symbolicating with Electron's published symbols, and hosted
services.

Correct the crashReporter API reference: value limit is 20320 bytes (not
127) and long keys emit a warning; rateLimit works on all platforms;
ignoreSystemCrashHandler has no effect on Windows; compress: false is
deprecated; getParameters() excludes globalExtra; getUploadedReports()
also lists reports that were not uploaded; Node child processes have no
process.crashReporter.start(); document ptype and _companyName in the
payload; note MAS no-op behaviour; drop the archived mini-breakpad-server
and Mozilla-only Socorro and move hosted services to the tutorial.

Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01SFzbSEnmLgZoxGXgEKSH4i

* docs: trim implementation details from crash reporting docs

Document behaviour rather than internals so the docs don't become an
accidental API contract: drop the crash dumps directory layout and file
naming, handler process details, Chromium-internal upload fields and
query parameters, exact release asset names and the symbol server path
format, and notes about behaviour from old Electron versions.

Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01SFzbSEnmLgZoxGXgEKSH4i

* docs: remove privacy section from crash reporting tutorial

Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01SFzbSEnmLgZoxGXgEKSH4i

* docs: recommend electron-minidump for symbolication

Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01SFzbSEnmLgZoxGXgEKSH4i

* docs: move default values to end of crashReporter option descriptions

Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01SFzbSEnmLgZoxGXgEKSH4i

* docs: address crash reporting review feedback

Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01SFzbSEnmLgZoxGXgEKSH4i

* docs: link crashReporter methods in MAS note

Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01SFzbSEnmLgZoxGXgEKSH4i

---------

Co-authored-by: Claude <noreply@anthropic.com>
2026-09-24 14:20:41 -07:00
claude[bot]andClaude Opus 5.5 1042d2998b test: rename spec files from -spec.ts to .spec.ts (#54258)
* test: rename spec files from -spec.ts to .spec.ts

Renames every spec/*-spec.ts file to spec/*.spec.ts and updates the
mocha file filter in spec/index.js, the glob in script/split-tests.js,
script/spec-weights.json, the macOS and Wayland spec allowlists, and
comments/docs that refer to spec files by name, so mocha and CI shard
splitting still pick up every spec file.

Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01EoGAobkKTt7KNqEiajK2Gm

* test: fail spec runs on files still named -spec.ts

The spec runner only loads *.spec.ts, so a spec file still named
*-spec.ts (for example from a PR opened before the rename) would
silently never run. spec/index.js now throws before mocha starts if
one is present in spec/, so the test jobs go red instead. This is a
temporary guard for the transition.

Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01EoGAobkKTt7KNqEiajK2Gm

---------

Co-authored-by: Claude <noreply@anthropic.com>
2026-09-23 16:45:57 -07:00
claude[bot]andClaude Fable 5.1 c664db0701 build: fail the PGO collect attempt on renderer death and relaunch (#54177)
* build: fail PGO workload when the renderer dies

A renderer OOM 13 seconds into the network workload left the benchmark app
awaiting webContents.executeJavaScript forever, so the collect job hung
until the 330-minute step timeout and collect-profile.js's retry loop,
which only runs once the app exits, never ran. Every page evaluation now
races against a deadline and a renderer-death signal, so a dead renderer
fails the running workload and the app quits into the retry path.

Co-Authored-By: Claude Fable 5.1 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01CMnZca8hbAx3iAsLvGkMzk

* build: recover PGO workload when the renderer dies

A renderer dying mid-workload no longer costs the whole collection
attempt. The benchmark app destroys the dead BrowserWindow, creates a
fresh one and retries that workload (PGO_RENDERER_RETRIES, default 2);
if the renderer keeps dying the workload is recorded with
`recovered: false` and the run continues so every other process still
shuts down cleanly and writes its counters. Only the dead renderer's own
counters are lost (%m exit-time writing on Linux/Windows; under Darwin's
%c continuous mode even those survive).

collect-profile.js accepts a run that gave up on a workload after in-app
renderer recovery instead of wiping the profraw dir and relaunching -
the loss is bounded and a relaunch would most likely die the same way.
The whole-attempt relaunch is kept for a run that was actually lost (the
app exited non-zero, or hung until killed, or left no results file) or
that failed for a reason the app does not recover in place;
PGO_ABORT_ON_FAILURE only cuts a run short for those. A clean run that
wrote no profraw at all (binary not instrumented) still fails fast.

Co-Authored-By: Claude Fable 5.1 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01CMnZca8hbAx3iAsLvGkMzk

* build: fail the PGO collect attempt on renderer death and relaunch

Drop the in-place renderer recovery: recreating the window and rerunning
the workload double-counts the aborted workload's counters in every
other process (and, under continuous mode, in the renderer's own file),
and giving up on a workload skipped part of the run while still passing
the attempt. A renderer death now records the workload with
rendererDeath: true, exits the app non-zero at once, and collect-profile
treats that as a lost attempt: the profraw dir is wiped and the whole
run relaunched, and when no retry is left the job fails without merging
or copying anything partial.

Co-Authored-By: Claude Fable 5.1 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01CMnZca8hbAx3iAsLvGkMzk

---------

Co-authored-by: Claude <noreply@anthropic.com>
2026-09-21 16:13:22 -04:00
claude[bot]andClaude 560f6b482d test: stop using chrome.storage.sync in the devtools extension fixture (#53995)
Electron does not implement chrome.storage.sync, so every sync call in
spec/fixtures/devtools-extensions/foo/panel.js fails with

  Unchecked runtime.lastError: "sync" is not available in this instance
  of Chrome

which the browser process logs as ERROR:CONSOLE:0 - 52 lines per main
CI run (e.g. https://github.com/electron/electron/actions/runs/35042445438).

The only test that loads this fixture, "loads devtools extensions
registered on the parent window" in spec/webview-spec.ts, asserts just
runtimeId and tabId from the message the panel posts; the storage
results were never checked. Exercise chrome.storage.local once per
operation (set, remove, clear, each followed by a get) instead, drop the
duplicated sync/local pairs and post only storageItems.local. runtimeId,
tabId and i18nString are unchanged.


Claude-Session: https://claude.ai/code/session_01AFucMLGyVVqSUAKXrqbaUT

Co-authored-by: Claude <noreply@anthropic.com>
2026-09-19 16:31:26 -07:00
claude[bot]andClaude Fable 5.1 2f64d2b3a4 docs: use json5 for bare object literal code blocks (#54107)
* docs: use json5 for bare object literal code blocks

Several docs code blocks contain only a bare object literal (an example
return value or options object) but are tagged as `js`. As JavaScript,
`{ key: value, ... }` on its own is a block statement, not an object, so
standard/ESLint reports "Parsing error: Unexpected token :" on most of
them; they only lint today because @electron/lint-roller special-cases
them with a regex that wraps orphan `{...}` blocks in parens before
linting. The blocks are valid JSON5, so tag them as such and drop the
`<!-- eslint-skip -->` comments that preceded them, which nothing in the
current tooling honors.

Co-Authored-By: Claude Fable 5.1 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01NBwKFgaRoEHjxoyGFpU6Ck

* docs: use json5 for bare array menu template blocks

The three menu template examples in docs/tutorial/menus.md are bare
array literals, not runnable JavaScript. Like the bare object literal
blocks in the previous commit, they are valid JSON5, so tag them as
such instead of `js`.

Co-Authored-By: Claude Fable 5.1 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01NBwKFgaRoEHjxoyGFpU6Ck

* docs: use json5 for bare literal blocks nested in blockquotes

The radio menu item example in the `[!TIP]` blockquote in
docs/tutorial/menus.md is a bare array literal tagged `js`; it was
missed earlier because the fence is prefixed with `> `. It is valid
JSON5 (including the trailing `//` comment), so tag it json5 like the
other bare literal blocks.

Co-Authored-By: Claude Fable 5.1 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01NBwKFgaRoEHjxoyGFpU6Ck

---------

Co-authored-by: Claude <noreply@anthropic.com>
2026-09-19 16:04:46 -07:00
claude[bot]andClaude 3449370868 build: drop unused dev dependencies and dedupe yarn.lock (#54093)
- Remove @types/semver and @types/w3c-web-serial, which no TypeScript
  code uses any more.
- Remove the @electron-ci/osr-gpu native addon fixture, which no spec
  requires.
- Update @electron/fiddle-core to ^2.2.2 in the root and workflows
  workspaces.
- Run `yarn dedupe` over the lockfile.

Co-authored-by: Claude <noreply@anthropic.com>
2026-09-18 18:25:54 +00:00
claude[bot]andClaude 7128ee7576 build: bundle lib/ with rolldown instead of webpack (#54080)
* build: bundle lib/ with rolldown instead of webpack

Replace the webpack + ts-loader pipeline that builds Electron's internal
JavaScript bundles with a small rolldown driver (build/bundle/bundle.mjs).

- build/bundle/targets.mjs describes the seven bundles (browser, renderer,
  worker, webview, isolated_renderer, node, utility) and the per-target
  behaviour that used to live in one webpack config each.
- BUILDFLAG(...) folding, the `electron` aliases, the Promise/process/
  Buffer/global providers and the profiling/try-catch wrappers are kept
  with the same semantics. Node built-ins imported from lazily evaluated
  modules stay lazy via a one line CommonJS shim so that load order
  matches the old bundles.
- Type checking moves out of the bundling step into a single
  electron_lib_typecheck action (build/bundle/typecheck.mjs) that every
  bundle depends on, instead of running seven times.
- gen-filenames.ts asks bundle.mjs for the module graph directly and
  emits a lib_typecheck_sources list for the new action.
- A few lib/ modules are adjusted for an ESM-first bundler: net.ts uses
  a plain module.exports object, web-contents.ts keeps its session
  side-effect import explicitly, and defineProperties caches the loaded
  module so each electron.* getter keeps returning the same object.

Drops webpack, webpack-cli and ts-loader from devDependencies.

* chore: wrap comment for clang-format

* build: keep bundle declarations out of the wrapper's parameter scope

node_mksnapshot compiles the js2c bundles with Node's built-in module
parameters (exports, require, module, process, internalBinding,
primordials), and a hoisted top-level `const { internalBinding } = ...`
from lib/node redeclared one of them. Wrap the bundle body in an IIFE, as
the webpack output was.

---------

Co-authored-by: Claude <noreply@anthropic.com>
2026-09-18 17:52:57 +02:00
claude[bot]andClaude 9aced3cae3 test: ignore security warnings in the iframe external protocol spec (#54060)
test: ignore security warnings in the sandboxed iframe external protocol spec

The spec asserted on the first console message the page logged. Since the
renderer security warnings moved to C++ (#53970) the main frame logs an
"Electron Security Warning (Insecure Content-Security-Policy)" message when
it finishes loading, and on Windows that regularly lands before the
"Navigation to external protocol blocked by sandbox" message the test is
waiting for. Wait for the first message that is not a security warning
instead.

Co-authored-by: Claude <noreply@anthropic.com>
2026-09-18 02:30:49 +00:00
claude[bot]andClaude f851e5e95b ci: run reduced test subsets on macOS x64 and mas (#54013)
Pull requests now run the macOS x64 test legs and the mas test legs as a
single shard each over a curated allowlist of spec files
(script/macos-x64-spec-allowlist.txt, script/macos-mas-spec-allowlist.txt),
while the darwin arm64 legs keep running the whole suite. The whole suite
still runs on every macOS leg for pushes to main and release branches, for
roller/ pull requests and for pull requests carrying the run-full-macos
label. This takes a PR from 13 macOS runners to 8.

The gate is a new full-macos-tests boolean input on the build-and-test
pipelines and the test segment, computed in build.yml from the event name,
head ref and PR labels, and defaulting to true for every other caller.


Claude-Session: https://claude.ai/code/session_015NrhHJaEg6V3V9G6yF9SHA

Co-authored-by: Claude <noreply@anthropic.com>
2026-09-18 02:02:27 +02:00
claude[bot]andClaude Fable 5.1 c7e11acc11 fix: align utilityProcess kill() with child_process.kill() (#53992)
* fix: don't reap utilityProcess children in kill()

UtilityProcessWrapper::Kill() opened a second base::Process for the
child, sent SIGTERM and then handed it to base::EnsureProcessTerminated,
which on POSIX reaps the child itself (immediately via kqueue on macOS,
after a 2s delay on Linux). content's BrowserChildProcessHostImpl reaps
the same child once its mojo pipe drops, via
base::GetKnownDeadTerminationStatus. Whichever side lost that race
failed: content's kill(SIGKILL) hit ESRCH and its waitpid() hit ECHILD,
logging "ERROR:base/process/kill_posix.cc:87 Unable to terminate
process" and "kill_posix.cc:33 waitpid(): No child processes" (about
1,200 lines per main CI run), and the exit code content reported was
derived from a status that was already gone.

content reaps reliably on its own, so only keep base's helper on
Windows. On POSIX send SIGTERM and post a delayed SIGKILL that fires
only if the wrapper has not yet seen the child terminate, matching the
2s grace period base::EnsureProcessTerminated used. waitpid now reports
the signal, which HandleTermination already maps to exit code 0.

Co-Authored-By: Claude Fable 5.1 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01AFucMLGyVVqSUAKXrqbaUT

* fix: run the utilityProcess SIGKILL fallback off the UI thread

Review feedback on the previous commit: the delayed SIGKILL was posted to
the UI thread, so it could not run while main-process JavaScript kept
that sequence busy, and a child that ignores SIGTERM could outlive
kill() indefinitely. The base::EnsureProcessTerminated call it replaced
enforced its two-second deadline on a background thread.

Post the fallback to a ThreadPool sequence (MayBlock, BEST_EFFORT)
instead. The task takes only the pid and the child's
base::Process::CreationTime(), read before SIGTERM while the child is
certainly alive, and re-reads the creation time when it fires: once
content has reaped the child the pid yields a null time, and a reused
pid yields a different one, so neither is signalled. A not-yet-reaped
zombie matches and accepts SIGKILL harmlessly. No wrapper state is
touched off the UI thread, so nothing has to be marshalled back, and
the ForceKill member goes away.

Co-Authored-By: Claude Fable 5.1 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01AFucMLGyVVqSUAKXrqbaUT

* fix: align utilityProcess kill() with child_process.kill()

Kill() now only delivers the signal: base::Process::Terminate() sends
SIGTERM on POSIX and calls TerminateProcess on Windows, and nothing else
happens. The base::EnsureProcessTerminated call introduced in 489d3ac
(#34980) is gone on every platform, and with it the ThreadPool SIGKILL
fallback from the previous commit. EnsureProcessTerminated reaped the
child itself and SIGKILLed it after 2s, which raced content's
BrowserChildProcessHost reap (its kill()/waitpid() then failed with
ESRCH/ECHILD and logged two ERROR lines per kill) and force-killed a
child that handles SIGTERM. Like Node's child_process.kill(), delivery
is now all kill() guarantees; content reaps the child once its mojo
pipe drops.

The docs for child.kill() describe the new contract, with an API
history entry, and a POSIX spec forks a child whose SIGTERM handler
exits with 42 after 2.5s and asserts that kill() lets it.

Co-Authored-By: Claude Fable 5.1 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01AFucMLGyVVqSUAKXrqbaUT

* docs: record the utilityProcess kill() change in breaking-changes.md

Apply review nits: drop the API-history block under `child.kill()`,
note the behavior change under Breaking API Changes (46.0) in
docs/breaking-changes.md instead, and say that the child is reaped by
Electron on POSIX.

Co-Authored-By: Claude Fable 5.1 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01AFucMLGyVVqSUAKXrqbaUT

---------

Co-authored-by: Claude <noreply@anthropic.com>
2026-09-17 15:25:10 -07:00
claude[bot]andClaude Fable 5.1 321404e2de test: disable the GPU for macos-x64 CI apps (#53994)
* test: start macos-x64 CI apps on SwiftShader

The macos-x64 CI runners are Intel VMs without a Metal-capable GPU. Every
Electron browser process started during a test run (the spec runner itself
and each app a test spawns) launches a hardware GPU process whose ANGLE/EGL
initialization fails:

  ERROR:ui/gl/gl_display.cc:648 Initialization of all (1) EGL display types failed
  ERROR:ui/gl/gl_initializer_mac.cc:127 GLDisplayEGL::Initialize failed
  ERROR:content/gpu/viz_main_impl.cc:192 Exiting GPU process due to errors during initialization

Chromium relaunches the GPU process one to seven times before falling back
to SwiftShader, which produces roughly 2,300 such lines per macos-x64 run
and none on macos-arm64.

Pass --use-angle=swiftshader so the GPU process starts on SwiftShader
directly and skips the failed hardware launches. Spawned apps do not
inherit the runner's switches, so the switch is added in three places:

- spec/index.js appends it to the spec runner's own command line.
- spec/lib/spec-helpers.ts exports `ciGpuArgs`, used by
  startRemoteControlApp().
- spec/lib/pdf-helpers.ts passes `ciGpuArgs` to the pdf-reader fixture.

The switch is gated on CI && darwin && x64 so developers on Intel Macs
keep their real GPU. Per-test direct spawn() calls in individual spec
files are left as they are.

Co-Authored-By: Claude Fable 5.1 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01AFucMLGyVVqSUAKXrqbaUT

* test: disable the GPU for macos-x64 CI apps instead of forcing SwiftShader

The previous commit passed --use-angle=swiftshader so the GPU process on
the macos-x64 runners would start on SwiftShader instead of failing the
hardware EGL init first. The CI run of that change showed SwiftShader's
Vulkan backend does not initialize on those VMs either:

  ERROR:ui/gl/gl_display.cc eglInitialize SwANGLE failed with error EGL_NOT_INITIALIZED

so the GPU process still exited and relaunched until Chromium fell back to
software compositing with GL disabled. On the mas,3 shard this was 19m00s
against 18m26s for the matching main run, with the ERROR line count going
from 961 to 1498: no runtime gain and more failed launches to log.

Software compositing with GL disabled is the state every process on these
runners ends up in anyway, so start there directly. The spec runner calls
app.disableHardwareAcceleration() (the same call the
ELECTRON_TEST_DISABLE_HARDWARE_ACCELERATION escape hatch uses) and the apps
spawned through startRemoteControlApp() and readPDF() receive --disable-gpu
via ciGpuArgs, since an environment variable would not reach their argv the
way the helpers are written. The gate is unchanged: CI on darwin x64 only.

Co-Authored-By: Claude Fable 5.1 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01AFucMLGyVVqSUAKXrqbaUT

* test: register child cleanup right after spawn in spec helpers

startRemoteControlApp only installed its deferred kill after the remote
app printed its listening port, and readPDF never registered one at all.
If startup stalls or PDF parsing hangs, mocha's timeout fires before the
cleanup exists and the Electron child survives into the in-job retry of
the same test. Per spec/CLAUDE.md, register the kill immediately after
spawn() and only kill a child that is still running.

Co-Authored-By: Claude Fable 5.1 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01AFucMLGyVVqSUAKXrqbaUT

---------

Co-authored-by: Claude <noreply@anthropic.com>
2026-09-17 15:21:25 -07:00
claude[bot]andClaude 08d5570f9d ci: fix need-repro comment check for gh CLI 2.99+ (#54010)
gh CLI 2.99+ rejects combining --comments with --json
("specify only one of --comments or --json"), and the ubuntu-24.04
runner image now ships gh 2.100.0, so the "Check if comment needed"
step fails on every blocked/need-repro label event. --json comments
alone preloads all comments with author.login and authorAssociation,
so the jq filter is unchanged.


Claude-Session: https://claude.ai/code/session_015E1RC2wE1U8CsgwaCGSfRB

Co-authored-by: Claude <noreply@anthropic.com>
2026-09-16 20:06:29 +00:00
claude[bot]andClaude 7100958c0e docs: search gitiles history before treating a Chrome fix CL as restricted (#53993)
A Gerrit change record can be access-restricted while the fix commit is
already public in git history and served unauthenticated by gitiles.
Teach chrome-release-cls a gitiles `+log ...&grep=<bug>` search (main +
branch-heads, Bug:/Fixed: footers, bounded ranges for chromium/src)
that works with or without a checkout, and state that RESTRICTED is
only valid once git/gitiles history is also empty. Have
chrome-release-verify step 3 re-resolve RESTRICTED/no-CL rows itself
(git fetch + log --all --remotes --grep, gitiles, fresh Gerrit query)
instead of inheriting the earlier verdict.


Claude-Session: https://claude.ai/code/session_013Z8MztJY8qTV43PRt5J6gx

Co-authored-by: Claude <noreply@anthropic.com>
2026-09-16 16:22:45 +00:00
claude[bot]andClaude 1da9b90978 fix: correct SUCCEEDED/FAILED usage on non-HRESULT return values (#53937)
base::win::RegKey methods return a LONG Win32 error code (ERROR_SUCCESS
or a positive error), not an HRESULT. SUCCEEDED()/FAILED() only test the
sign bit, so every registry failure in browser_win.cc read as success.
Compare against ERROR_SUCCESS instead.

In jump_list.cc, the closing parenthesis of SUCCEEDED() wrapped the whole
`GetCount(...) && (removed_count > 0)` expression, so the macro was
applied to a bool and always evaluated to true. Move the parenthesis so
SUCCEEDED() wraps only the HRESULT-returning call.


Claude-Session: https://claude.ai/code/session_013QkZj2JgXtCzU9uXNpneem

Co-authored-by: Claude <noreply@anthropic.com>
2026-09-15 11:48:38 -07:00
claude[bot]andClaude 010fb2dccf test: tolerate Windows keeping asar internals fixtures open during cleanup (#53930)
The asar internals suite writes its archives to a temp directory and
removes it in an after hook. Every archive the suite touches stays open
for the rest of the process (the asar layer caches its Archive objects,
and Archive opens the file without FILE_SHARE_DELETE), and Windows will
not delete an open file, so the hook fails there with EPERM from
rmSync (a sharing violation surfaced as std::errc::permission_denied).

Keep the cleanup, but only let it fail on platforms where it can work.


Claude-Session: https://claude.ai/code/session_01DtsTxhCv8KyVejsgxcHg8J

Co-authored-by: Claude <noreply@anthropic.com>
2026-09-15 14:53:38 +00:00
claude[bot]andClaude f6bcc1932f ci: set cache-mode: read on release and publish segment jobs (#53823)
The workflow_dispatch/schedule release, publish and PGO pipelines default
to cache-mode: write, but the build / publish / test / clang-tidy /
gn-check / pgo-collect segment jobs they call only ever restore caches
(yarn via install-dependencies and setup-node, the per-run SAS token via
restore-cache-azcopy). Cap those callers at cache-mode: read so a compromised
release job cannot poison the default-branch Actions caches.

Checkout jobs (save the SAS-token cache) and build-siso jobs (save the siso
binary cache) are left at the default and keep write access. Nothing is
set at workflow level.


Claude-Session: https://claude.ai/code/session_01MYe3WCXtgiqomNuVQdi4Yd

Co-authored-by: Claude <noreply@anthropic.com>
2026-09-14 19:36:04 -07:00
claude[bot]andClaude 3336a43a2d build: retry SAS key generation in checkout action (#53880)
A single transient HTTP 502 from the sas-sidecar on the "Generate SAS Key"
curl fails the whole checkout job and every dependent build/collect job for
that platform. Retry transient errors a few times with a short delay so a
one-off blip no longer kills the leg.


Claude-Session: https://claude.ai/code/session_01CMnZca8hbAx3iAsLvGkMzk

Co-authored-by: Claude <noreply@anthropic.com>
2026-09-14 14:21:52 +00:00
claude[bot]andClaude 2323efb0d8 test: clear shared dictionary cache before asserting empty usage info (#53830)
The `shared dictionary APIs can get shared dictionary usage info` test
asserted that `session.defaultSession.getSharedDictionaryUsageInfo()`
deep-equals `[]`, assuming the shared default session's shared-dictionary
store is pristine. During the long single-process spec run on macOS
arm64, a Chromium background service can register a real www.google.com
shared dictionary on the default session, making the `deep.equal([])`
assertions fail (~1-2% flake, recently gone job-red). We now clear the
default session's shared-dictionary cache in a `beforeEach` so the block
still exercises the real API but asserts from a known-clean state.


Claude-Session: https://claude.ai/code/session_01GVga33efnYewyFhPuTZrP5

Co-authored-by: Claude <noreply@anthropic.com>
2026-09-11 22:47:03 -04:00
claude[bot]andClaude 401a041adc docs: hand-port Chrome security picks in-PR instead of dropping them (#53774)
The chrome-release-verify skill told the agent to drop a cherry-pick and
defer to a separate manual-port PR whenever no target-milestone merge
existed and the code differed structurally. That produced separate manual
PRs for the Sep 8 release. Prefer a nearby-milestone rebase or the
prerequisite CL, otherwise hand-port inside the pick with adaptation
notes; reserve DROPPED for code that is absent on the branch.


Claude-Session: https://claude.ai/code/session_01S6J8NGLtud5JY6ncWM79L5

Co-authored-by: Claude <noreply@anthropic.com>
2026-09-09 07:15:00 -07:00
claude[bot]andClaude 32770bcd04 build: add ai_assistance bundle dep on generated skill files (#53732)
Carry devtools-frontend CL 8344907 as a patch so the ai_assistance
esbuild bundle action orders after skills:generate_skills. Without the
edge, Windows publish builds intermittently fail with
"Cannot read file: ...\ai_assistance\skills\styling.skill.js".

Main can drop this patch once it rolls to Chromium >= 155.0.8044.0,
which carries the upstream fix. The M155 branch does not, so 45-x-y
needs it for the life of the branch.


Claude-Session: https://claude.ai/code/session_01XBJkdoZS6zCPDpsxhcsP6h

Co-authored-by: Claude <noreply@anthropic.com>
2026-09-08 04:47:31 +02:00