* chore: bump build image tag in .devcontainer/docker-compose.yml to 22fded7
* chore: bump build image sha in build-image-sha action
Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01KmMk2yWrVE76u5SLy2QaJk
---------
Co-authored-by: electron-roller[bot] <84116207+electron-roller[bot]@users.noreply.github.com>
Co-authored-by: Claude <noreply@anthropic.com>
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>
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>
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>
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>
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>
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>
* ci: allow running include analysis via label and configure root filter
Adding the `run-include-analysis` label to a PR now enables include
analysis on the linux-x64 build, mirroring `run-full-macos`. A new
`include-analysis-root-filter` workflow_dispatch input (default
`^electron/`) is threaded through to analyze_includes.py --root-filter.
Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01S5ed3Z28JjZpMNp9QSNc7P
* ci: also run include analysis on macOS
Run the include analysis on the darwin variant of the macos-arm64 build
as well as linux-x64, and name the artifacts include-analysis.linux.html
and include-analysis.macos.html so they don't conflict. The macOS report
replaces the template's hardcoded "(Linux)" with "(macOS)".
Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01S5ed3Z28JjZpMNp9QSNc7P
---------
Co-authored-by: Claude <noreply@anthropic.com>
* 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>
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>
* 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>
* fix: derive V8 cache compatibility from net patch effects
Replace the custom V8 cache salt and Wasm embedded blob guard
from #54234 with embedder string version hashing.
Generate -electron.<16-hex fingerprint> during GN configuration from
the net committed changes between Chromium's pinned V8 revision and
patched HEAD. This requires no release time bookkeeping and preserves
cache identities across packaging only changes to the patch series.
* build: fix metadata generation and restoration
* build: address review follow-ups
- Keep code cache hash checks free of process global mutation
- Limit the helper to DCHECK enabled builds
- Make the fingerprint algorithm self contained and include it
in the source cache key
- Allow an explicit packager identity
- Skip Wasm tests without generated assets
- Correct the documentation structure
* build: simplify V8 fingerprint regeneration tracking
Track Git HEAD and the exported V8 patch series instead of symbolic
branch refs, packed-refs, or Git directories. Detached checkout updates
and patch exports trigger regeneration, while equivalent re-exports
preserve the committed source fingerprint.
Reject reftable storage explicitly and provide actionable diagnostics
when the checkout does not contain Chromium's pinned V8 revision.
* fix: gn check for release builds
* chore: convert to vitest imports
* chore: cleanup testing binding dependency
* chore: update patches
* chore: remove redundant dep declaration
* 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>
* test: assert with vitest's matchers instead of chai
Every assertion moves from chai's chainable language to vitest's own
matchers, so an assertion is always a call and never a bare property read:
- `to.equal` → `toBe`, `to.deep.equal`/`eql` → `toEqual`, `to.be.true` →
`toBe(true)`, `to.have.property` → `toHaveProperty`, `to.include` →
`toContain`/`toMatchObject`/`toContainEqual`, `to.be.a('string')` →
`toBeTypeOf('string')`, `instanceOf` → `toBeInstanceOf`, `lengthOf` →
`toHaveLength`, `above`/`least`/`below`/`most` → `toBeGreaterThan` and
friends, `match` → `toMatch`, `throw` → `toThrow`, `oneOf` → `toContain`
with the operands swapped, `closeTo(e, d)` → `Math.abs(x - e) <= d`,
`members`/`keys` → `arrayContaining`/`Object.keys`. A chain that kept
going after `.property()` or `.a()` becomes one matcher where vitest has
one (`toHaveProperty(key, expect.any(String))`) and separate assertions
otherwise. chai-as-promised becomes `.resolves`/`.rejects`, a failed
manual check is `assert.fail()` rather than `new chai.AssertionError`.
- vitest reports promise assertions that are not awaited; the app badge,
webview zoom and `import('electron')` specs had some that never ran and
now do (the service worker badge ones waited for a count the worker had
already cleared, so those just check the worker's answer; the zoom fixture
issued loadURL() from dom-ready, which aborts, and now waits for the load).
- Code that runs outside the spec module graph (itremote bodies in a
renderer, the utility-process net harness, two crash-case apps) is
CommonJS and vitest refuses `require('vitest')`, so it loads the same
module through spec/lib/vitest-cjs.cjs.
- A lint rule (script/lint-plugins/no-chai-assertions.mjs) rejects chai
chains on `expect()`, and no-unused-expressions is on for the specs, so
neither form of property-style assertion can come back.
- chai, chai-as-promised, dirty-chai and their @types leave
spec/package.json; the refresh-page fixture served chai.js only as "a
large script" and serves the jquery fixture instead.
* test: return promises instead of taking mocha's `done` callback
vitest has no `done` parameter. The tests and hooks that used one now
return a promise instead; where the callback was only ever called as
`done()` it is the promise's `resolve`, and where it was also handed to an
error-first API or called as `done(error)` it keeps mocha's meaning
(reject on a truthy argument, resolve otherwise) through a local `done`.
* test: move the spec runner's own semantics out of the mocha shim
Three things the shim did are not mocha compatibility but how the Electron
specs need to run, whichever API they are written against: every hook and
test starts from a fresh macrotask so that Chromium's message loop turns
between them, `defer()`-ed cleanup runs before the enclosing suites' own
afterEach hooks, and spec/disabled-tests.json can switch a test off by its
title. Those now live in a small custom vitest runner
(spec/vitest/runner.ts) that applies to every test, and the shim only
translates mocha's API.
* test: write the specs against vitest's API instead of mocha's
Mechanical conversion of every spec file and helper:
- `describe`/`it`/`beforeEach`/... are imported from 'vitest' rather than
taken from the runner's globals; `before`/`after` become
`beforeAll`/`afterAll`.
- `this.timeout(n)` becomes the `{ timeout: n }` option of the test or
suite (a hook's second argument; hooks inside a suite that had a timeout
get it explicitly, since vitest's suite option only reaches the tests), `this.retries(n)` `{ retry: n }`, and
`this.skip()` the test context's `ctx.skip()`. The two `before` hooks that
skipped a whole suite now compute the condition up front
(`describe.runIf`) or per test. `function () {}` callbacks that only
existed for `this` are arrows again.
- `ifit`/`ifdescribe` map to `it.skip`/`describe.skip`, mocha's chained
`it(...).timeout(n)` and `this.bail()` are gone, and the two helpers that
read `this.test` use the context's task state.
* test: remove the mocha compatibility layer
Nothing imports mocha's API any more, so spec/vitest/mocha-compat.ts and the
setup file that installed its globals go, together with @types/mocha and the
Mocha type overloads in spec/ambient.d.ts. Timeouts are vitest's own again
(30 s per test and hook, ELECTRON_SPEC_TIMEOUT raises it for the sanitizer
jobs, replacing MOCHA_TIMEOUT), the junit path variable becomes
ELECTRON_SPEC_JUNIT_FILE, and `closeAllWindows` loses the parameter that a
hook's context argument would otherwise land in.
Picks up Squirrel/Squirrel.Mac#335, which keeps the old app in place when
ShipIt is interrupted while moving the new one in, and #332, the final form
of the GN build, which takes its vendored dependencies from vendor/ instead
of Carthage/Checkouts/.
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>
* ci: use Cloudflare DNS directly on macOS runners
The macOS runner VMs resolve through a UDP-only caching DNS proxy on
the VM host. Point the system resolver at 1.1.1.1/1.0.0.1 instead,
via a shared composite action used by every macOS job.
Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com>
* ci: set Cloudflare DNS as the first step of macOS jobs
Inline the step so it runs before checkout, and drop the
resolution check and fallback.
Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com>
---------
Co-authored-by: Claude Opus 5.5 (1M context) <noreply@anthropic.com>
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>
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>
* 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>
* 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>
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>
* test: run the spec suite with vitest
Replace the in-process mocha runner with vitest driving a pool of Electron
processes.
- spec/vitest/electron-pool.ts is a vitest pool whose workers are
'electron spec/ --vitest-worker' browser processes talking to the CLI
over a Node IPC channel (JSON, see ipc-serialization.ts, because the
host Node cannot read Electron's newer V8 wire format).
- spec/index.js keeps the pre-ready process setup and then hands the main
process to vitest's worker runtime (spec/vitest/worker.ts).
experimental.viteModuleRunner is off, so spec files are imported by
Electron's own Node exactly as before (native ESM, type stripping, no
Vite transform).
- spec/vitest/mocha-compat.ts provides mocha's BDD globals (describe/it/
before/after, this.timeout()/this.skip(), done callbacks, resettable
timeouts, hooks in declaration order, a macrotask between runnables) on
top of vitest, so the spec files run unchanged.
- Two projects run in sequence: everything not tagged 'serial' across
several workers, then the 'serial' suites one file at a time.
- script/spec-runner.js translates --files/-g into vitest filters, wraps
the CLI in dbus_mock.py on Linux and reruns failures from vitest's JUnit
report; leftover Electron processes are killed once per run
(global-setup.js) and per worker process group.
- spec-timings.json for shard balancing comes from timings-reporter.ts;
mocha, its reporters and ELECTRON_FORCE_TEST_SUITE_EXIT are gone.
* test: run the macOS app activation, hide and dock specs serially
app.isActive(), app.hide()/show() and the dock are machine-wide state, so
these suites cannot share the screen with other spec processes. The
isActive spec also assumed the process starts out inactive, which a
freshly launched worker on the CI hosts is not; hide first in that case.
* ci: send child-process logging to a file on the Windows test legs
Child processes cannot write to the test runner's stderr pipe on Windows;
with plain --enable-logging each of them fails AttachConsole() and
AllocConsole()s its own window, which lands on top of the desktop and can
occlude the windows the specs create. Run the Windows legs with
--enable-logging=file so children log through an inherited handle, and
let testing builds honour ELECTRON_ALSO_LOG_TO_STDERR (previously debug
builds only) so the main process keeps logging to the job output. The log
files are uploaded with the test artifacts; reruns get their own file.
* test: drop the stderr mirror spec
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>
* chore: bump chromium in DEPS to 155.0.8058.0
* 8373722: [macOS] Disclaim TCC responsibility for GPU process
Upstream added IsCurrentProcessSelfResponsible() and a shared
ResponsiblePidIfNotSelf() helper that call the private
responsibility_get_pid_responsible_for_pid() API. Guard them for MAS
builds too, where IsCurrentProcessSelfResponsible() reports true so the
GPU process never tries to disclaim TCC responsibility.
Ref: https://chromium-review.googlesource.com/c/chromium/src/+/8373722
Co-Authored-By: Claude Fable 5.1 <noreply@anthropic.com>
* 8372283: [OSCrypt] Remove OSCrypt.Mac.SuccessAfterPreviousError histogram and code
Upstream inlined GetPasswordImpl() into KeychainPassword::GetPassword();
move the suffixed-account lookup and legacy-account migration there.
Ref: https://chromium-review.googlesource.com/c/chromium/src/+/8372283
Co-Authored-By: Claude Fable 5.1 <noreply@anthropic.com>
* 8364168: [crash] Add CrashReporterClient hooks for upload options, annotations
Upstream added ShouldRateLimitUploads(), ShouldCompressUploads() and
GetExtraProcessAnnotations(), which replace the hooks that
crash_allow_setting_more_options.patch added. Remove the patch and
override the upstream virtuals in ElectronCrashReporterClient instead.
Ref: https://chromium-review.googlesource.com/c/chromium/src/+/8364168
Co-Authored-By: Claude Fable 5.1 <noreply@anthropic.com>
* 8364227: [usb] Defer UsbServiceImpl::GetDevices() until the first enumeration
Removes chore_defer_usb_service_getdevices_request_until_usb_service_is.patch,
which is now upstream.
Ref: https://chromium-review.googlesource.com/c/chromium/src/+/8364227
Co-Authored-By: Claude Fable 5.1 <noreply@anthropic.com>
* 8364646: [views] Let FrameCaptionButton take an explicit icon color
Upstream added FrameCaptionButton::SetIconColor(ui::ColorVariant), which
replaces the SetButtonColor() that
feat_enable_customizing_symbol_color_in_framecaptionbutton.patch added,
and GetButtonColor() stays static. Remove the patch. Set the frame color
first and then the explicit symbol color, since the icon color comes
from whichever setter ran last.
Ref: https://chromium-review.googlesource.com/c/chromium/src/+/8364646
Co-Authored-By: Claude Fable 5.1 <noreply@anthropic.com>
* 8360632: [input] Keep a hidden hung renderer marked unresponsive
Drop the RenderInputRouter and RenderWidgetHostImpl hunks from
refactor_unfilter_unresponsive_events.patch now that this change is
upstream; only the WebContentsImpl::RendererUnresponsive() filtering
change remains.
Ref: https://chromium-review.googlesource.com/c/chromium/src/+/8360632
Co-Authored-By: Claude Fable 5.1 <noreply@anthropic.com>
* 8363583: Static-assert that CSSPropertyEquality does not compare pointers with ==
Ref: https://chromium-review.googlesource.com/c/chromium/src/+/8363583
Co-Authored-By: Claude Fable 5.1 <noreply@anthropic.com>
* 8364228: [ozone/wayland] Tolerate a missing wl_seat in UpdateCursor()
Removes fix_wayland_test_crash_on_teardown.patch, which is now upstream.
Ref: https://chromium-review.googlesource.com/c/chromium/src/+/8364228
Co-Authored-By: Claude Fable 5.1 <noreply@anthropic.com>
* 8364745: [base] Report MoveFile()'s own error from ReplaceFile() on Windows
Removes fix_don_t_read_a_stale_last-error_in_replacefile_on_windows.patch,
which is now upstream.
Ref: https://chromium-review.googlesource.com/c/chromium/src/+/8364745
Co-Authored-By: Claude Fable 5.1 <noreply@anthropic.com>
* 8364645: [ozone/wayland] Fix a window stuck maximized after an early Maximize()
Removes fix_wayland_window_stuck_maximized_after_early_maximize.patch.
Upstream fixes the root cause (previously_maximized_ latching on a
stateless configure), so the patch's Restore() workaround is no longer
needed.
Ref: https://chromium-review.googlesource.com/c/chromium/src/+/8364645
Co-Authored-By: Claude Fable 5.1 <noreply@anthropic.com>
* 8337991: [StatusIconLinuxDbus] Use unique D-Bus connection name instead of well-known name
Upstream now registers every status icon under its connection's unique
name, which fixes the missing Flatpak and Snap tray icon that
fix_register_status_icon_with_unique_d-bus_name_when_owning_one.patch
worked around. StatusNotifierWatcher implementations only drop an item
once that name leaves the bus, so an icon created on the shared session
bus would now linger after it is destroyed. Keep a reduced patch,
fix_use_a_private_d-bus_connection_for_each_status_icon.patch, that
always gives each status icon a private connection instead.
Ref: https://chromium-review.googlesource.com/c/chromium/src/+/8337991
Co-Authored-By: Claude Fable 5.1 <noreply@anthropic.com>
* 8361192: [cppgc] Use _AddressOfReturnAddress() for StackStartMarker under MSVC
Removes v8/cppgc_support_stackstartmarker_on_msvc.patch, which is now
upstream.
Ref: https://chromium-review.googlesource.com/c/v8/v8/+/8361192
Co-Authored-By: Claude Fable 5.1 <noreply@anthropic.com>
* 8381377: Roll Perfetto from 8665a1fa48ac to ced94af64d7e (2 revisions)
The roll includes perfetto commit 5d6dd85f03 ("base: use intptr_t for
ssize_t on Windows", https://github.com/google/perfetto/pull/7136),
which upstreams define_ssize_t_to_be_intptr_t_to_match_libuv.patch.
Remove the patch, keeping the perfetto target with an empty .patches so
a later patch need not touch patches/config.json.
Ref: https://chromium-review.googlesource.com/c/chromium/src/+/8381377
Co-Authored-By: Claude Fable 5.1 <noreply@anthropic.com>
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
* chore: update siso revision
* chore: update patches
* 8379633: Standardize mojom arguments for which bindings are generated
Blink bindings are now opt-in via generate_blink, and disable_variants
no longer exists, so drop it from our mojom() targets.
Ref: https://chromium-review.googlesource.com/c/chromium/src/+/8379633
Co-Authored-By: Claude Fable 5.1 <noreply@anthropic.com>
* 8362279: Reland "[sandbox] Store CppHeapPointerHandles in EmbedderDataArray"
JSObject embedder data slots now hold CppHeapPointerHandles and are
visited through Serializer::ObjectSerializer::VisitCppHeapPointer(),
whose DCHECK only expects API wrapper objects. JSPromise has an embedder
slot too since Node.js and Electron build V8 with
v8_promise_internal_field_count = 1, so node_mksnapshot hit the DCHECK
while serializing the Node.js startup snapshot. Add a V8 patch that
accepts every map that may have embedder fields.
Ref: https://chromium-review.googlesource.com/c/v8/v8/+/8362279
Co-Authored-By: Claude Fable 5.1 <noreply@anthropic.com>
* 8355366: Remove base::Process from content::ChildProcessData
BrowserChildProcessLaunchedAndConnected() now receives the process
separately, and BrowserChildProcessHostIterator exposes it directly.
UtilityProcessWrapper can no longer match BrowserChildProcessCrashed()
and BrowserChildProcessKilled() on the pid, so it looks up its child
process id when the process launches and matches on that instead.
Ref: https://chromium-review.googlesource.com/c/chromium/src/+/8355366
Co-Authored-By: Claude Fable 5.1 <noreply@anthropic.com>
* 8263457: Add support for isolated browser restart
Upstream removed BrowserMainLoop::SetResultCode(), which app.exit(code)
used to make the browser process exit with an arbitrary code. Use its
replacement, BrowserMainRunner::SetOverrideResultCode(), and patch out
that method's check that codes are at or above
content::RESULT_CODE_LAST_CODE, since app.exit() codes are chosen by the
app.
Ref: https://chromium-review.googlesource.com/c/chromium/src/+/8263457
Co-Authored-By: Claude Fable 5.1 <noreply@anthropic.com>
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
* chore: bump chromium in DEPS to 155.0.8059.0
* chore: update patches
Co-authored-by: PatchUp <73610968+patchup[bot]@users.noreply.github.com>
* 7957800: Harden RenderWidgetHostViewBase Teardown
Upstream replaced the virtual RenderWidgetHostViewBase::Destroy() with a
non-virtual DestroyOrDefer() that disconnects the view from its host and
then calls the new pure-virtual DestroyImpl(), possibly deferred while
input dispatch pins the view. Subclasses must also implement the new
pure-virtual CleanUpHostObservers().
OffScreenRenderWidgetHostView now overrides DestroyImpl() and
CleanUpHostObservers(). The latter removes the render frame metadata
observer, calls ViewDestroyed() on the host, and drops the cached host
pointer since the host may be deleted before a deferred DestroyImpl()
runs. The DelegatedFrameHostClient callbacks are null-guarded
accordingly, mirroring DelegatedFrameHostClientAura.
Ref: https://chromium-review.googlesource.com/c/chromium/src/+/7957800
Co-Authored-By: Claude Fable 5.1 <noreply@anthropic.com>
* 8340933: Optimize FlexLayout and ProposedLayout allocation churn during resize
Ref: https://chromium-review.googlesource.com/c/chromium/src/+/8340933
Co-Authored-By: Claude Fable 5.1 <noreply@anthropic.com>
* chore: update patches
Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
* 8365609: [metagen] Enable metagen instance types
V8 now runs metagen by default, which loads the llvm-libclang package
into the build's own Python. The Windows src cache is synced with
host_os=linux, so Windows builders get no package at all. Have fix-sync
re-fetch just that dep with a one-dep gclient sync, so gclient selects
and extracts the object for the Windows host itself.
Ref: https://chromium-review.googlesource.com/c/v8/v8/+/8365609
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
* 8354793: Remove dxil.dll from Windows builds and installer
Ref: https://chromium-review.googlesource.com/c/chromium/src/+/8354793
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
* chore: update patches
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
* fixup! 8365609: [metagen] Enable metagen instance types
* chore: update patches
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
---------
Co-authored-by: electron-roller[bot] <84116207+electron-roller[bot]@users.noreply.github.com>
Co-authored-by: electron-claude[bot] <279139701+electron-claude[bot]@users.noreply.github.com>
Co-authored-by: Claude Fable 5.1 <noreply@anthropic.com>
Co-authored-by: PatchUp <73610968+patchup[bot]@users.noreply.github.com>
Co-authored-by: clavin <clavin@electronjs.org>
* 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>
* build: remove unused and duplicated sources from chromium_src
- global_accelerator_listener{,_linux}.cc were compiled here and again by
the //ui/base/accelerators/global_accelerator_listener dep; keep the dep
(as a public_dep, shell/ includes its header) and drop the copies.
- native_window_tracker_aura duplicates //ui/native_window_tracker, which
is already linked; //ui/views/native_window_tracker.h no longer exists.
- chrome's platform_util{,_aura,_mac} were added for the colour chooser
in 2018 and nothing includes chrome/browser/platform_util.h any more.
- browser_theme_pack, custom_theme_supplier and window_frame_util.cc only
reference each other; theme_properties and window_frame_util.h stay.
- back_to_tab_label_button, skip_ad_label_button, resize_handle_button
and overlay_window_live_caption_button are never constructed on desktop
or sit entirely inside our #if 0 hunks.
- scoped_picture_in_picture_occlusion_observation, predictors_features
(+ its proto dep), exclusive_access_bubble_type.cc and the spellcheck
language policy handlers have no callers in anything Electron builds.
- delegated_source_list_capturer is only used by thumbnail_capturer_mac,
printing_service.cc only by pdf_to_emf_converter (Windows), and the
hang_crash_dump.cc Linux stub is never called.
- web_request_resource_type.{cc,h} moved upstream in June; the
enable_electron_extensions=false branch could not gn gen with it listed.
* refactor: remove unregistered browserAction/pageAction extension classes
browser_action.json is not part of the function registration target, so
the twelve BrowserAction*Function and seven PageAction*Function classes
were never instantiated, and the ExtensionActionAPI keyed service was
never built because nothing referenced its factory. Drop them together
with a few other extension leftovers that have no callers:
ElectronExtensionSystem::OnExtensionRegisteredWithRequestContexts,
ElectronExtensionsBrowserClient::SetAPIClientForTest and
ElectronExtensionsRendererClient::AllowPopup (its upstream virtual is
gone), and use extensions::util::AllowFileAccess instead of two local
copies of it.
* refactor: remove unreferenced C++ from shell/
None of these have a caller on any platform:
- OffScreenRenderWidgetHostView::AddGuestHostView/RemoveGuestHostView/
RemoveViewProxy and guest_host_views_ (never populated, so every loop
over it was dead too)
- FileSelectHelper::IsAcceptTypeValid/GetSanitizedFileName/
SetFileSelectListenerForTesting
- FileSystemAccessPermissionContext::OriginHasReadAccess/WriteAccess
- ElectronBrowserClient::GetSiteInstanceFromAffinity
- ElectronPermissionManager::HasPermissionRequestHandler
- api::BaseWindow::SetGTKDarkThemeEnabled and the NativeWindow virtual
behind it (NativeWindowViews keeps its own private helper)
- crash_reporter::IsCrashReporterEnabled/GetGlobalCrashKeys
- InspectableWebContents::GetDelegate
- NativeWindowObserver::WillCreatePopupWindow/WillNavigate
- WebRequest::RequestFilter's three-argument constructor
- declarations with no definition: ServiceWorkerContext::
StopWorkersForScope, WebContents::OnElectronBrowserConnectionError/
OnGetZoomLevel, NetworkContextService::CreateNetworkContextParams,
WindowsToastNotification::ShowInternal, ElectronApiServiceImpl::
ProcessPendingMessages
- NativeWindow::is_closed(), WebContentsZoomController::
persist_zoom_mode(), BrowserProcessImpl::CreateGlobalFeaturesForTesting()
- the Linux stubs for asar::Archive::HeaderIntegrity/RelativePath and the
non-mac Clipboard::ReadFindText stub (their callers are already
platform-guarded, so guard the declarations instead)
- the 'render-view-deleted' event, which existed for the removed remote
module's object registry
* refactor: remove unused gin_helper and converter code
- gin_helper::ErrorThrower::ThrowReferenceError/ThrowSyntaxError, the
zero-argument PromiseBase::Reject() and PromiseBase::RejectPromise had
no callers.
- CreateDataPropertyCallback and Dispatcher::DispatchToCallbackForProperty
were never instantiated.
- Converter<blink::mojom::Referrer> (Electron uses content::Referrer) and
Converter<blink::mojom::MenuItem::Type>::ToV8 had no users; drop the
full popup_menu.mojom.h include from content_converter.h and only pull
the ReferrerPolicy enum into blink_converter.
* refactor: remove native bindings and methods that JS never calls
- The electron_common_environment binding has had no caller since the
forwarded WebContents events moved native (#53975).
- Nothing requests the electron_browser_printing binding;
webContents.getPrintersAsync() calls GetPrinterListAsync() directly.
- features.isExtensionsEnabled(), the top-level executeInWorld/
exposeAPIInWorld exports on the context_bridge binding,
webFrameMain._fromIdIfExists/_fromFtnIdIfExists,
WebContents._getPreloadScript, webFrame._isEvalAllowed and
Menu._getUserAcceleratorAt are not used by lib/ or spec/.
- Protocol::IsProtocolHandled was installed on the prototype template and
then unconditionally replaced by the JS implementation in
lib/browser/api/protocol.ts, so the C++ copy could never run.
* chore: remove dead code and stale typings from lib/
- WebFrameMain.prototype._sendInternal, WebViewImpl.setupEventProperty/
on/onAttach, the 'setLayoutZoomLevelLimits' webview method (removed in
Electron 9) and WEB_VIEW_ATTRIBUTES.NAME had no callers.
- The Electron 20 sandbox-default deprecation log could never fire:
getLastWebPreferences() never contains 'preload' and always contains
'sandbox'.
- lib/browser/api/crash-reporter.ts only ships in the browser bundle, so
its process.type checks were constant.
- WebSQL was removed in Electron 31; drop enableWebSQL from the inherited
guest preferences and the docs, and the no-op 'webSQL' clearData type.
- Drop typings for things that no longer exist (ProcessType, ReplyChannel/
_replyChannel, the WebContents '-ipc-*' and '-window-visibility-change'
overloads, ElectronInternal.LoadURLOptions, Chrome.Tabs, NodeJS.Global
augmentations, Process.log/mainModule/_serviceStartupScript, the
document-start/end overloads, NetBinding.Net/net, App: Function,
Window.ELECTRON_*_SECURITY_WARNINGS, _awaitNextLoad) and the .oxlintrc
globs for lib/preload_realm and lib/sandboxed_renderer.
* chore: remove orphaned fixtures, scripts and CI leftovers
- spec/fixtures/release-notes/ (its spec left with the release scripts in
#52100), devtools-extensions/bad-manifest/, assets/osr.png,
pages/storage/web_sql.html, pages/history.html, module/hello-child.js,
esm/local.mjs and api/local-ai-handler/no-language-model.js are not
referenced by any spec.
- script/verify-chromedriver.py and script/run-if-exists.js lost their
last callers with the AppVeyor removal; script/lib/npm.py,
script/lib/native_tests.py, build/args/native_tests.gn, the pyyaml DEPS
entry and shell/browser/ui/{accelerator_util_unittests,run_all_unittests}.cc
are leftovers of the native test target removed in #40190.
- script/lib/git.py is_repo_root/get_repo_root and script/lib/utils.js
getCurrentBranch/handleGitCall have no callers.
- pipeline-electron-build-and-test-and-nan.yml is not referenced by any
workflow since #49072.
- Three spec/disabled-tests.json titles, one node-disabled-tests entry, a
wayland allowlist entry, a sysroots.json arch and two CODEOWNERS paths
named things that no longer exist; four docs/images files are unlinked.