Skip to content

[pull] main from electron:main - #5

Open
pull[bot] wants to merge 4560 commits into
16CentAstrology:mainfrom
electron:main
Open

pull[bot] wants to merge 4560 commits into
16CentAstrology:mainfrom
electron:main

Conversation

@pull

@pull pull Bot commented Dec 13, 2022 •

Copy link
Copy Markdown

See Commits and Changes for more details.


Created by pull[bot]

Can you help keep this open source service alive? 💖 Please sponsor : )

@pull pull Bot added the ⤵️ pull label Dec 13, 2022
dependabot Bot and others added 29 commits September 30, 2026 15:36
…38.1 (#54570)

build(deps): bump github/codeql-action/upload-sarif

Bumps [github/codeql-action/upload-sarif](https://github.com/github/codeql-action) from 4.38.0 to 4.38.1.
- [Release notes](https://github.com/github/codeql-action/releases)
- [Changelog](https://github.com/github/codeql-action/blob/main/CHANGELOG.md)
- [Commits](github/codeql-action@b96794f...1c5b675)

---
updated-dependencies:
- dependency-name: github/codeql-action/upload-sarif
  dependency-version: 4.38.1
  dependency-type: direct:production
  update-type: version-update:semver-patch
...

Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
…1267)

Refactors the non-shareable window filtering in the Chromium
ScreenCaptureKit patch:

1. Extracts inline NSWindowSharingNone filtering into a reusable
   GetNonShareableWindows() helper function.

2. Fixes a bug where content-protected windows (via
   win.setContentProtection(true)) could temporarily appear in screen
   captures during picture-in-picture state changes — the PiP filter
   update handler was only excluding PiP windows, not non-shareable
   ones.

Notes: Fixed a bug where content-protected windows could temporarily appear in screen captures during picture-in-picture state changes.
…4608)

UsbChooserContextFactory did not override GetBrowserContextToUse(), so
off-the-record contexts got no UsbChooserContext and the chooser
controller dereferenced null. Give in-memory sessions their own context,
as the HID and serial factories do.
* fix: clear vibrancy view before destruction

Keep the removed NativeViewHost alive until vibrant_native_view_host_ has been cleared.

Memory was freed at:

0 Electron Framework 0x000000012b8e4940 base::debug::CollectStackTrace(base::span<void const*, 18446744073709551615ul, void const**>) + 24
1 Electron Framework 0x000000012b8cfa00 base::debug::StackTrace::StackTrace(unsigned long) + 128
2 Electron Framework 0x000000012b8ea86c base::allocator::(anonymous namespace)::DanglingRawPtrDetected(unsigned long) + 764
3 Electron Framework 0x000000012b996bcc void partition_alloc::PartitionRoot::FreeInline<(partition_alloc::internal::FreeFlags)8>(void*) + 5392
4 Electron Framework 0x00000001335fe8f4 views::NativeViewHost::~NativeViewHost() + 16
5 Electron Framework 0x0000000124916004 ___ZN8electron15NativeWindowMac11SetVibrancyERKNSt4__Cr12basic_stringIcNS1_11char_traitsIcEENS1_9allocatorIcEEEEi_block_invoke + 140
6 Electron Framework 0x0000000124915a74 electron::NativeWindowMac::SetVibrancy(std::__Cr::basic_string<char, std::__Cr::char_traits<char>, std::__Cr::allocator<char>> const&, int) + 1048

The dangling raw_ptr was released at:

0 Electron Framework 0x000000012b8e4940 base::debug::CollectStackTrace(base::span<void const*, 18446744073709551615ul, void const**>) + 24
1 Electron Framework 0x000000012b8cfa00 base::debug::StackTrace::StackTrace(unsigned long) + 128
2 Electron Framework 0x000000012b8eb158 void base::allocator::(anonymous namespace)::DanglingRawPtrReleased<(base::features::DanglingPtrMode)1, (base::features::DanglingPtrType)0>(unsigned long) + 92
3 Electron Framework 0x000000012b93c3b4 base::internal::RawPtrBackupRefImpl<false>::ReleaseInternal(unsigned long) + 480
4 Electron Framework 0x0000000124916058 ___ZN8electron15NativeWindowMac11SetVibrancyERKNSt4__Cr12basic_stringIcNS1_11char_traitsIcEENS1_9allocatorIcEEEEi_block_invoke + 224
5 Electron Framework 0x0000000124915a74 electron::NativeWindowMac::SetVibrancy(std::__Cr::basic_string<char, std::__Cr::char_traits<char>, std::__Cr::allocator<char>> const&, int) + 1048

* fix: clear notification delegate before callback

Release delegate_ before NotificationDestroyed() can synchronously delete the delegate.

Memory was freed at:

0 Electron Framework 0x000000012b8e4940 base::debug::CollectStackTrace(base::span<void const*, 18446744073709551615ul, void const**>) + 24
1 Electron Framework 0x000000012b8cfa00 base::debug::StackTrace::StackTrace(unsigned long) + 128
2 Electron Framework 0x000000012b8ea86c base::allocator::(anonymous namespace)::DanglingRawPtrDetected(unsigned long) + 764
3 Electron Framework 0x000000012b9aa080 void partition_alloc::PartitionRoot::FreeInline<(partition_alloc::internal::FreeFlags)22>(void*, partition_alloc::FreeHint<partition_alloc::internal::FreeFlags partition_alloc::internal::FreeHintFlags<partition_alloc::internal::FreeFlags>(partition_alloc::internal::FreeFlags)((partition_alloc::internal::FreeFlags)22)>::Type) + 5928
4 Electron Framework 0x000000012b99f940 void partition_alloc::PartitionRoot::FreeInUnknownRoot<(partition_alloc::internal::FreeFlags)22>(void*, partition_alloc::FreeHint<partition_alloc::internal::FreeFlags partition_alloc::internal::FreeHintFlags<partition_alloc::internal::FreeFlags>(partition_alloc::internal::FreeFlags)((partition_alloc::internal::FreeFlags)22)>::Type) + 1324
5 Electron Framework 0x000000012b9c3a50 allocator_shim::internal::PartitionAllocFunctionsInternal<(partition_alloc::internal::AllocFlags)16, (partition_alloc::internal::FreeFlags)6>::FreeWithSize(void*, unsigned long, void*) + 200
6 Electron Framework 0x00000001247f797c electron::Notification::~Notification() + 72
7 Electron Framework 0x0000000124919fbc electron::CocoaNotification::~CocoaNotification() + 220
8 Electron Framework 0x000000012491a014 electron::CocoaNotification::~CocoaNotification() + 12
9 Electron Framework 0x00000001247f81cc electron::NotificationPresenter::RemoveNotification(electron::Notification*) + 200

The dangling raw_ptr was released at:

0 Electron Framework 0x000000012b8e4940 base::debug::CollectStackTrace(base::span<void const*, 18446744073709551615ul, void const**>) + 24
1 Electron Framework 0x000000012b8cfa00 base::debug::StackTrace::StackTrace(unsigned long) + 128
2 Electron Framework 0x000000012b8eb158 void base::allocator::(anonymous namespace)::DanglingRawPtrReleased<(base::features::DanglingPtrMode)1, (base::features::DanglingPtrType)0>(unsigned long) + 92
3 Electron Framework 0x000000012b93c3b4 base::internal::RawPtrBackupRefImpl<false>::ReleaseInternal(unsigned long) + 480
4 Electron Framework 0x00000001247f7a50 electron::Notification::~Notification() + 284
5 Electron Framework 0x0000000124919fbc electron::CocoaNotification::~CocoaNotification() + 220
6 Electron Framework 0x000000012491a014 electron::CocoaNotification::~CocoaNotification() + 12
7 Electron Framework 0x00000001247f81cc electron::NotificationPresenter::RemoveNotification(electron::Notification*) + 200

* fix: erase notifications before destruction

Remove each raw_ptr from notifications_ before deleting the Notification it references.

Memory was freed at:

0 Electron Framework 0x000000012cacd6e0 base::debug::CollectStackTrace(base::span<void const*, 18446744073709551615ul, void const**>) + 24
1 Electron Framework 0x000000012cab6968 base::debug::StackTrace::StackTrace(unsigned long) + 168
2 Electron Framework 0x000000012cad3a24 base::allocator::(anonymous namespace)::DanglingRawPtrDetected(unsigned long) + 764
3 Electron Framework 0x000000012cbbb9ac void partition_alloc::PartitionRoot::FreeInline<(partition_alloc::internal::FreeFlags)22>(void*, partition_alloc::FreeHint<partition_alloc::internal::FreeFlags partition_alloc::internal::FreeHintFlags<partition_alloc::internal::FreeFlags>(partition_alloc::internal::FreeFlags)((partition_alloc::internal::FreeFlags)22)>::Type) + 5868
4 Electron Framework 0x000000012cbb1264 void partition_alloc::PartitionRoot::FreeInUnknownRoot<(partition_alloc::internal::FreeFlags)22>(void*, partition_alloc::FreeHint<partition_alloc::internal::FreeFlags partition_alloc::internal::FreeHintFlags<partition_alloc::internal::FreeFlags>(partition_alloc::internal::FreeFlags)((partition_alloc::internal::FreeFlags)22)>::Type) + 1324
5 Electron Framework 0x000000012cbd522c allocator_shim::internal::PartitionAllocFunctionsInternal<(partition_alloc::internal::AllocFlags)16, (partition_alloc::internal::FreeFlags)6>::FreeWithSize(void*, unsigned long, void*) + 200
6 Electron Framework 0x00000001258ed394 electron::NotificationPresenter::~NotificationPresenter() + 72
7 Electron Framework 0x0000000125a0ee60 electron::NotificationPresenterMac::~NotificationPresenterMac() + 356
8 Electron Framework 0x0000000125a0ef00 electron::NotificationPresenterMac::~NotificationPresenterMac() + 12
9 Electron Framework 0x0000000125868dfc electron::ElectronBrowserClient::~ElectronBrowserClient() + 500

The dangling raw_ptr was released at:

0 Electron Framework 0x000000012cacd6e0 base::debug::CollectStackTrace(base::span<void const*, 18446744073709551615ul, void const**>) + 24
1 Electron Framework 0x000000012cab6968 base::debug::StackTrace::StackTrace(unsigned long) + 168
2 Electron Framework 0x000000012cad3aec void base::allocator::(anonymous namespace)::DanglingRawPtrReleased<(base::features::DanglingPtrMode)0, (base::features::DanglingPtrType)0>(unsigned long) + 84
3 Electron Framework 0x000000012cb27fc8 base::internal::RawPtrBackupRefImpl<false>::ReleaseInternal(unsigned long) + 480
4 Electron Framework 0x00000001258b87c8 void std::__Cr::__destroy_at[abi:sqn240000]<base::raw_ptr<DraggableRegionProvider, (partition_alloc::internal::RawPtrTraits)0>>(base::raw_ptr<DraggableRegionProvider, (partition_alloc::internal::RawPtrTraits)0>*) + 136
5 Electron Framework 0x00000001258eda14 std::__Cr::__tree<base::raw_ptr<electron::Notification, (partition_alloc::internal::RawPtrTraits)0>, std::__Cr::less<base::raw_ptr<electron::Notification, (partition_alloc::internal::RawPtrTraits)0>>, std::__Cr::allocator<base::raw_ptr<electron::Notification, (partition_alloc::internal::RawPtrTraits)0>>>::__tree_deleter::operator()[abi:sqn240000](std::__Cr::__tree_node<base::raw_ptr<electron::Notification, (partition_alloc::internal::RawPtrTraits)0>, void*>*) + 52
6 Electron Framework 0x00000001258ed3d4 electron::NotificationPresenter::~NotificationPresenter() + 136
7 Electron Framework 0x0000000125a0ee60 electron::NotificationPresenterMac::~NotificationPresenterMac() + 356
8 Electron Framework 0x0000000125a0ef00 electron::NotificationPresenterMac::~NotificationPresenterMac() + 12
9 Electron Framework 0x0000000125868dfc electron::ElectronBrowserClient::~ElectronBrowserClient() + 500

* fix: clear Node environment before teardown

Clear NodeBindings::uv_env_ before NodeService releases the node::Environment.

Memory was freed at:

0 Electron Framework 0x0000000129b78940 base::debug::CollectStackTrace(base::span<void const*, 18446744073709551615ul, void const**>) + 24
1 Electron Framework 0x0000000129b63a00 base::debug::StackTrace::StackTrace(unsigned long) + 128
2 Electron Framework 0x0000000129b7e86c base::allocator::(anonymous namespace)::DanglingRawPtrDetected(unsigned long) + 764
3 Electron Framework 0x0000000129c3c93c void partition_alloc::PartitionRoot::FreeInline<(partition_alloc::internal::FreeFlags)18>(void*, partition_alloc::FreeHint<partition_alloc::internal::FreeFlags partition_alloc::internal::FreeHintFlags<partition_alloc::internal::FreeFlags>(partition_alloc::internal::FreeFlags)((partition_alloc::internal::FreeFlags)18)>::Type) + 8480
4 Electron Framework 0x0000000129c33390 void partition_alloc::PartitionRoot::FreeInUnknownRoot<(partition_alloc::internal::FreeFlags)18>(void*, partition_alloc::FreeHint<partition_alloc::internal::FreeFlags partition_alloc::internal::FreeHintFlags<partition_alloc::internal::FreeFlags>(partition_alloc::internal::FreeFlags)((partition_alloc::internal::FreeFlags)18)>::Type) + 1324
5 Electron Framework 0x0000000129c56ce8 allocator_shim::internal::PartitionAllocFunctionsInternal<(partition_alloc::internal::AllocFlags)16, (partition_alloc::internal::FreeFlags)2>::FreeWithSize(void*, unsigned long, void*) + 200
6 Electron Framework 0x0000000122c4bd24 node::FreeEnvironment(node::Environment*) + 248
7 Electron Framework 0x0000000122b3a74c _ZNSt4__Cr20__shared_ptr_pointerB9sqn240000IPN4node11EnvironmentEZN8electron12NodeBindings17CreateEnvironmentEPN2v87IsolateENS6_5LocalINS6_7ContextEEEPNS1_20MultiIsolatePlatformEmNS_6vectorINS_12basic_stringIcNS_11char_traitsIcEENS_9allocatorIcEEEENSI_ISK_EEEESM_NS_8optionalIN4base17RepeatingCallbackIFvvEEEEEE3$_0NSI_IS2_EEE16__on_zero_sharedEv + 188
8 Electron Framework 0x0000000122b7ee40 electron::NodeService::~NodeService() + 416
9 Electron Framework 0x0000000122b7ef2c electron::NodeService::~NodeService() + 12

The dangling raw_ptr was released at:

0 Electron Framework 0x0000000129b78940 base::debug::CollectStackTrace(base::span<void const*, 18446744073709551615ul, void const**>) + 24
1 Electron Framework 0x0000000129b63a00 base::debug::StackTrace::StackTrace(unsigned long) + 128
2 Electron Framework 0x0000000129b7e934 void base::allocator::(anonymous namespace)::DanglingRawPtrReleased<(base::features::DanglingPtrMode)0, (base::features::DanglingPtrType)0>(unsigned long) + 84
3 Electron Framework 0x0000000129bd03b4 base::internal::RawPtrBackupRefImpl<false>::ReleaseInternal(unsigned long) + 480
4 Electron Framework 0x0000000122b34b94 electron::NodeBindings::~NodeBindings() + 372
5 Electron Framework 0x0000000122bde08c electron::NodeBindingsMac::~NodeBindingsMac() + 12
6 Electron Framework 0x0000000122b7edf8 electron::NodeService::~NodeService() + 344
7 Electron Framework 0x0000000122b7ef2c electron::NodeService::~NodeService() + 12

* fix: enable dangling raw_ptr checks

* fix: avoid retaining isolate in PromiseBase

Resolve PromiseHandle traced references with the currently entered
isolate instead of retaining a raw pointer that can outlive
IsolateHolder. Promise operations already require execution on their
creation thread with the isolate entered.

```
gin::IsolateHolder::~IsolateHolder -> JavascriptEnvironment::~JavascriptEnvironment -> isolate free

static Promise<void> destruction -> PromiseBase::~PromiseBase -> isolate_ raw_ptr release
```

* fix: annotate additional dangling raw pointers

* fix(win): annotate additional dangling raw_ptr
* refactor: migrate View, ImageView and WebContentsView to cppgc

The View wrappers were gin_helper::EventEmitter objects, and every edge
between them was a strong V8 root. A parent held each child in a
v8::Global, BaseWindow and BrowserWindow held their content view in a
v8::Global, and WebContentsView held its WebContents in a
cppgc::Persistent. A view reachable only through such a cycle, such as
a layout callback that closes over its own view, was never collected.

The wrappers are now cppgc managed gin::Wrappables, and those edges are
traced:

- Children are kept in a traced list of child entries, matched by their
  native views::View so that two WebContentsViews sharing a webContents
  stay distinct.
- The layout callback is a v8::TracedReference; the layout manager only
  holds a WeakPtr to the native side.
- WebContentsView holds its WebContents with a Member.
- BaseWindow and BrowserWindow root their views with cppgc::Persistent
  while the native window uses them.

Native state moves to View::Host, a NativePeer that owns or observes the
views::View and is torn down through Release(), never from a GC
destructor. WebContentsViewHost additionally holds the WebContents,
window and draggable-region observers and the overlay update. A
user-data claim on content::WebContents records which host owns the
webContents, so a view that adopts the webContents of a collected but
not yet released view is not destroyed with it. The claim is checked and
the webContents disposed in the same task through the new
WebContents::DestroyNow(). At shutdown, hosts leave disposal to the
WebContents itself.

ImageView and WebContentsView keep their own WrapperInfos and share one
kElectronView pointer tag, and Converter<View*> accepts all three.
gin_helper::Constructible gains ConstructibleParent, so a subclass
constructor template inherits View's, and BindToConstructCall, so
`class extends` and Reflect.construct keep the subclass prototype.

* chore: fix lint
…ource (#54595)

https://chromium-review.googlesource.com/c/chromium/src/+/8401888 added
ui::NativeTheme::SetPreferredColorSchemeOverride(), which does what the
set_theme_source() patch did, for every theme instance at once. Use it and
drop the patch. themeSource keeps its own stored value, and "system"
restores the override the process started with, so that --force-dark-mode
behaves as before.
… on Windows (#54383)

* feat: add app.isUnnecessarilyElevated() and a deElevate option to app.relaunch() on Windows

An Electron app started with a full administrator token while UAC is
enabled cannot always launch its sandboxed child processes (the sandbox
broker's CreateProcessAsUser fails under some enterprise policies,
surfacing as render-process-gone launch-failed with exit code 18 or a
blank window), and app code that was never meant to run elevated does.
Chrome handles this by relaunching itself de-elevated at startup.

Give apps the same option: app.isUnnecessarilyElevated() reports whether
the process holds an elevated split token, and app.relaunch({ deElevate:
true }) makes the relauncher start the new instance through
base::win::RunDeElevated() with the user's normal token.

* fix: carry the RunDeElevated working directory fix so a de-elevated relaunch keeps its cwd

* refactor: rename to app.canDeElevate()

* fix: launch the de-elevated relaunch through RunDeElevatedNoWait so it keeps the working directory without a base patch
* build: update linux-arm64 PGO profile

* build: update linux-x64 PGO profile

* build: update macos-arm64 PGO profile

* build: update macos-x64 PGO profile

* build: update v8-builtins PGO profile

* build: update win-arm64 PGO profile

* build: update win-x64 PGO profile

---------

Co-authored-by: electron-pgo-updater[bot] <290827142+electron-pgo-updater[bot]@users.noreply.github.com>
* refactor: give WebContentsView a native view of its own

A WebContentsView used its webContents InspectableWebContentsView as its
native view. The webContents owns that view and deletes it along with
itself, so a WebContentsView could outlive its native view and every View
method had to check for a null view.

WebContentsViewHost now owns a container view for the whole life of the
WebContentsView and presents the inspectable view in it, filling it, as
its last child. Child views added from JavaScript stay before it and so
beneath the page, as they were when added to the inspectable view. With
that, View::Host always owns its view, and the unowned mode goes away.

Ownership of the webContents no longer needs a user-data claim. The host
whose container presents the inspectable view owns it. Adopting a
webContents in a new WebContentsView moves the inspectable view into the
new container, so only that view acts on the webContents and destroys it
when collected. Two WebContentsViews that share a webContents are now
separate children, rather than one native view tracked twice.

* fix: update the overlay when a WebContentsView moves

Since a WebContentsView has its own container view, moving it without
resizing leaves the page view's bounds unchanged, so the window controls
overlay was never re-sent to the page.
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>
* 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>
…#53550)

* fix(net): support non-ASCII headers and multiple cookies in net.fetch

* fix: address PR review feedback on protocol handler header collapse and request aborts
The `setIgnoreMenuShortcuts` webview spec navigated the guest to
about:blank right after `did-attach-webview`, while the guest could still
be loading its `<webview>` src. If that load had committed but not
finished, navigating aborted it, and the aborted page's `did-fail-load`
(ERR_ABORTED, with an empty description) settled the pending `loadURL()`
promise, rejecting it with `(-3) loading '.../zoom-factor.html'`.

Slower macOS x64 runners hit this window regularly. Wait for the guest's
initial load to finish before navigating it.

Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
…ecs 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>
…38.2 (#54680)

build(deps): bump github/codeql-action/upload-sarif

Bumps [github/codeql-action/upload-sarif](https://github.com/github/codeql-action) from 4.38.1 to 4.38.2.
- [Release notes](https://github.com/github/codeql-action/releases)
- [Changelog](https://github.com/github/codeql-action/blob/main/CHANGELOG.md)
- [Commits](github/codeql-action@1c5b675...2892aa5)

---
updated-dependencies:
- dependency-name: github/codeql-action/upload-sarif
  dependency-version: 4.38.2
  dependency-type: direct:production
  update-type: version-update:semver-patch
...

Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
Six cold Electron launches share a 30s test deadline even though each fixture permits 10s after app readiness. Reuse spawnAndWait to bound and reap each child, and derive the enclosing deadline from all six per-process budgets. Keep all six launches and their ready-to-show assertions.

Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
…ecks (#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>
#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>
* chore: bump chromium in DEPS to 157.0.8079.0

* chore: update patches

* 8426044: Deduplicate notifications for find-in-page

Upstream removed WebContentsDelegate::FindReply() in favor of
WebContentsObserver::DidReceiveFindReply(). Moved Electron's
found-in-page handling from the delegate forwarder to the observer
forwarder on the NativeLifecycle peer.

Ref: https://chromium-review.googlesource.com/c/chromium/src/+/8426044

Co-Authored-By: Claude Fable 5.1 <noreply@anthropic.com>

* 8471431: siso: don't include optional LLVM tools in clang inputs

https://crrev.com/c/8471431 narrowed the
third_party/llvm-build/Release+Asserts:headers filegroup glob from
bin/clang-* to bin/clang-cl, bin/clang-cl.exe and bin/clang-[0-9]*.
siso uploads that filegroup as a precomputed subtree and drops other
inputs under it, so bin/clang-tidy no longer reached the RBE workers and
the clang-tidy steps failed with exit 127.

build-tools now adds bin/clang-tidy back to that filegroup:
electron/build-tools#910

Ref: https://chromium-review.googlesource.com/c/chromium/src/+/8471431

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

* chore: bump chromium in DEPS to 157.0.8081.0

* 8469895: [VideoCapture] Remove unsafe lifetime assumptions in InProcessVideoCaptureDeviceLauncher

Ref: https://chromium-review.googlesource.com/c/chromium/src/+/8469895

Co-Authored-By: Claude Fable 5.1 <noreply@anthropic.com>

* 8261571: dbus: Let desktop Linux end the session instead of crashing when a bus is lost

Upstream landed Bus::Options::disconnected_callback and a reworked
dbus_thread_linux that takes the embedder's callback via Initialize(),
which supersedes both the backport patch and the downstream
SetDisconnectedCallback() shim. Removed both patches and switched
ElectronBrowserMainParts to dbus_thread_linux::Initialize().

Ref: https://chromium-review.googlesource.com/c/chromium/src/+/8261571

Co-Authored-By: Claude Fable 5.1 <noreply@anthropic.com>

* 8470272: [find-in-page] Fix endless frame traversal around an inner WebContents

Ref: https://chromium-review.googlesource.com/c/chromium/src/+/8470272

Co-Authored-By: Claude Fable 5.1 <noreply@anthropic.com>

* chore: update patches

* 8424588: [mojo] (Mostly) ban untyped `handle` use

TakeHeapSnapshot now takes handle<platform>, so the browser passes the
mojo::PlatformHandle directly and the renderer receives it without
unwrapping.

Ref: https://chromium-review.googlesource.com/c/chromium/src/+/8424588

Co-Authored-By: Claude Fable 5.1 <noreply@anthropic.com>

* 8465643: Forward proxy auth for requests without login prompts

Plumb the new do_not_prompt_for_login flag through
URLLoaderNetworkObserver, SimpleURLLoaderClient and CreateLoginDelegate.
Electron keeps routing these challenges to the 'login' event, which is
its non-UI credential source, mirroring how Chrome still consults
extensions for them.

Ref: https://chromium-review.googlesource.com/c/chromium/src/+/8465643

Co-Authored-By: Claude Fable 5.1 <noreply@anthropic.com>

* 8422739: Enforce cross-origin access control in WebUIURLLoaderFactory

CreateWebUIURLLoaderFactory now requires a request initiator origin
lock. Pass the frame's initiator origin that content already hands to
RegisterNonNetworkSubresourceURLLoaderFactories; the lock only gates
chrome-untrusted:// initiators, so component extensions keep their
access to chrome://resources.

Ref: https://chromium-review.googlesource.com/c/chromium/src/+/8422739

Co-Authored-By: Claude Fable 5.1 <noreply@anthropic.com>

* chore: bump chromium in DEPS to 157.0.8083.0

* 8497008: CATransaction: Clean up old flags

Ref: https://chromium-review.googlesource.com/c/chromium/src/+/8497008

Co-Authored-By: Claude Fable 5.1 <noreply@anthropic.com>

* 8499815: Ruff: reformat third_party/blink.

Ref: https://chromium-review.googlesource.com/c/chromium/src/+/8499815

Co-Authored-By: Claude Fable 5.1 <noreply@anthropic.com>

* 8455902: gin: Mark Invoker as stack allocated and drop raw_ptr for its Arguments

Ref: https://chromium-review.googlesource.com/c/chromium/src/+/8455902

Co-Authored-By: Claude Fable 5.1 <noreply@anthropic.com>

* chore: update patches

* 8469168: Change DataPipeGetter::Read to return result as base::expected

Ref: https://chromium-review.googlesource.com/c/chromium/src/+/8469168

Co-Authored-By: Claude Fable 5.1 <noreply@anthropic.com>

* 8480632: Ignore stale UpdateDragOperation replies from non-current RWH on Android

Ref: https://chromium-review.googlesource.com/c/chromium/src/+/8480632

Co-Authored-By: Claude Fable 5.1 <noreply@anthropic.com>

* chore: bump chromium in DEPS to 157.0.8085.0

* chore: update patches

* 8463605: [Clear-Site-Data] Prevent cross-site fetch clearing unpartitioned data

Ref: https://chromium-review.googlesource.com/c/chromium/src/+/8463605

Co-Authored-By: Claude Fable 5.1 <noreply@anthropic.com>

* 8448270: [Linux] Support XDG NetworkMonitor portal in NetworkChangeNotifierLinux

The browser process now opens a private session bus for the portal, with
no Bus::Options::disconnected_callback, so it aborts when the session bus
is lost. That is what fails "when a D-Bus bus goes away > exits cleanly
instead of crashing" on Linux. Carry the upstream fix until it rolls in.

Ref: https://chromium-review.googlesource.com/c/chromium/src/+/8448270
Ref: https://chromium-review.googlesource.com/c/chromium/src/+/8512441#nolint

* 8465423: Use C++20 std::numbers::pi in blink

Backport the upstream fix for Windows math constants.

Ref: https://chromium-review.googlesource.com/c/chromium/src/+/8465423
Ref: https://chromium-review.googlesource.com/c/chromium/src/+/8510323#nolint

* 8489251: Exit tab fullscreen when the held-Esc timer fires under keyboard lock

Ref: https://chromium-review.googlesource.com/c/chromium/src/+/8489251

* 8366647: [snapshot] Optional SHA256 code cache source hashing

Ref: https://chromium-review.googlesource.com/c/v8/v8/+/8366647

* fix: disable V8 metagen feature

Refs https://issues.chromium.org/issues/531344950
Skip-Lint: General feature disablement, no specific to a particular CL.

* 8503816: Enable AperitifHelpers by default

Disable AperitifHelpers on macOS until Electron adopts the new helpers.
Ref: https://chromium-review.googlesource.com/c/chromium/src/+/8503816

* build: pin build-tools to merged siso clang-tidy fix

electron/build-tools#910 squash-merged as 32e2253f7c5696d85a77fe19d54d284cf9a62322; re-pin from the PR branch commit a411ee5 so CI no longer depends on the deleted branch.

Skip-Lint: build-tools pin, not a Chromium CL adaptation
Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01V38FjDEdZgMvFpf5Fmp65m

---------

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: Shelley Vohr <shelley.vohr@gmail.com>
Co-authored-by: deepak1556 <hop2deep@gmail.com>
These specs need OS focus, which another worker's window can take
under the parallel runner:

- api-web-contents-view.spec.ts "does not crash when closed via
  window.close()" waits for 'blur', which only fires if the view had
  focus, and contents only get initial focus in an active window.
- api-web-frame-main.spec.ts "keeps a single instance ... during a
  cross-origin swap" needs the view focused before the swap; it now
  waits for that instead of assuming focus() is synchronous.
- api-web-contents.spec.ts:
  - The win32 beforeunload re-activation test now waits for focus
    instead of sleeping 100 ms.
  - The setIgnoreMenuShortcuts() block sends real menu shortcuts.
    "honors the initial ignoreMenuShortcuts preference" now waits for
    focus.
  - The showItemInFolder workspace test opens a real Finder or
    Explorer window, which takes focus and stays open.

Tag them serial.

Co-authored-by: Claude Opus 5.5 <noreply@anthropic.com>
* test: run more fullscreen specs serially

Like #54549, tag the remaining specs that move a window in and out of
fullscreen (or kiosk) mode as serial. Under the parallel runner, these
transitions can overlap with another worker's, so one never finishes and
the test times out. A fullscreen window can also cover other workers'
windows and change their visibility or focus.

- api-browser-window.spec.ts: maximize-then-fullscreen,
  setWindowButtonVisibility in fullscreen, restore() fullscreen state,
  setFullScreen(false) when HTML fullscreen, the non-fullscreenable
  child window, and the kiosk and fullscreen-with-resizable state blocks
  (macOS); the fullscreen state memory blocks (Windows).
- webview.spec.ts: requestFullscreen from webview.
- api-web-contents-view.spec.ts: can be fullscreened.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>

* test: run the remaining fullscreen specs serially

Tag three more specs that put a visible window into fullscreen:

- api-browser-window.spec.ts: getNormalBounds() "Fullscreen state" and
  setFullScreen(false) "on windows" (Windows).
- chromium.spec.ts: navigator.keyboard "should lock the keyboard"
  (Linux and Windows), which also needs a focused window for HTML
  fullscreen.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>

---------

Co-authored-by: Claude Opus 5.5 <noreply@anthropic.com>
The electron_common_testing binding and autoUpdater.isVersionAllowedForUpdate
only exist when DCHECK_IS_ON(). On release builds the native-settled promise
spec fails with "No such binding was linked: electron_common_testing" and the
ElectronSquirrelPreventDowngrades version comparison spec fails with
"isVersionAllowedForUpdate is not a function".

Gate both on isTestingBindingAvailable(), as #53956 did for the other
DCHECK-only hooks.

Co-authored-by: Claude Opus 5.5 <noreply@anthropic.com>
Move the fork, post and await logic shared by the net specs and the app proxy test
into spec/lib/utility-process-helpers.ts, so both use one copy.

The helper attaches the message and exit listeners before posting work
and registers the child with deferKillUtilityProcess.
It rejects as soon as the child exits without posting a result,
instead of leaving the test to wait for its timeout.

Cover the helper with two emitter-driven cases:
an exit emitted right after the result, and an exit with no result.

Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
Co-authored-by: Claude Opus 5.5 <noreply@anthropic.com>
#54725)

* test: wait for the page to be focused before clipboard and paste specs

Specs that read the clipboard, paste, or request pointer lock waited for
the webContents 'focus' event, or didn't wait at all. That event comes
from the browser process, and the page can still report
document.hasFocus() === false right after it, so navigator.clipboard
rejected with "Document is not focused." and paste() could be dropped.

Add a focusWebContents() helper to spec-helpers that focuses the
contents, waits for 'focus', and then waits until the page reports that
it has focus. Use it for the clipboard read/write, paste execCommand,
pointer lock, and user activation specs, and before each paste() in the
File System API specs. In the done-style File System specs, a failure
while preparing the paste is now passed to done() instead of escaping
the 'did-finish-load' listener.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>

* test: bound the focus wait and fail File System specs in the test body

focusWebContents no longer waits on the 'focus' event, which had no timeout.
It requests focus and polls document.hasFocus() within waitUntil's timeout.

The navigator.clipboard.read specs that expect success now read back known text,
and paste execCommand checks that the document had focus when it pasted,
so a focus failure can no longer pass as an expected result.

The done-style File System API specs are now async.
They record permission details in the handlers and assert in the test body,
and they fail as soon as the fixture reports 'file-system-error'
instead of waiting for the test timeout.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>

---------

Co-authored-by: Claude Opus 5.5 <noreply@anthropic.com>
#54727)

The WebContentsView visibilityState specs wait for their page to become
'visible'. A BrowserWindow's own webContents is force-shown, but a
BaseWindow's content views are not, so Chromium's native occlusion
tracker decides their visibility. On the Windows CI hosts another
process's console window can sit above a newly shown test window, and
under the parallel runner another worker's window can cover it, so the
page stays 'hidden' and waitUntil() times out.

As #54334 did for visibility-state.spec.ts, create these windows
always-on-top on Windows, and run the block serially.

Co-authored-by: Claude Opus 5.5 <noreply@anthropic.com>
If a netLog test failed while logging, the afterEach hook asserted that
logging had stopped, so the hook failed too and logging stayed on. Every
later test in the file, and every retry, then failed in beforeEach's
"not currently logging" check.

Stop any log that is still running in afterEach, before deleting the
dump files, and drop the hook's assertion.

Co-authored-by: Claude Opus 5.5 <noreply@anthropic.com>
…in (#54731)

The chrome.scripting registerContentScripts spec registers a script
with the fixed id 'session-script' in a session that persists across
retries. On a retry the earlier attempt's script is still registered, so
registerContentScripts() rejects with "Duplicate script ID
'session-script'", the background page never responds, and the retry
times out.

Unregister the id first if it is already registered.

Co-authored-by: Claude Opus 5.5 <noreply@anthropic.com>
The fixture listened on the fixed path /tmp/echo.sock. A run that is
killed (the crash spec SIGKILLs a wedged child) leaves that socket
behind, so the retry's listen() fails with EADDRINUSE. The fixture's
'error' handler then threw in the main process, which shows a modal
error dialog instead of exiting, so the retry timed out as well.

Listen on a path that includes the process id, pass it to the page in
the query string, and exit with code 1 on a server error.

Co-authored-by: Claude Opus 5.5 <noreply@anthropic.com>
electron-pgo-updater Bot and others added 30 commits November 1, 2026 09:24
* build: update linux-arm64 PGO profile

* build: update linux-x64 PGO profile

* build: update macos-arm64 PGO profile

* build: update macos-x64 PGO profile

* build: update v8-builtins PGO profile

* build: update win-arm64 PGO profile

* build: update win-x64 PGO profile

---------

Co-authored-by: electron-pgo-updater[bot] <290827142+electron-pgo-updater[bot]@users.noreply.github.com>
fix: trash: Use gio when necessary

Before, Electron would use the per-desktop tool depending on
desktop environment. This ended up breaking file trashing inside of
sandboxed environments like Flatpak. Now we handle the case where
Electron is running inside of a sandbox, and allow overriding
properly depending on the situation.
The docs lint rejects code blocks using the `typescript` language
identifier and wants `ts`, but the error message said the opposite.


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

Co-authored-by: Claude <noreply@anthropic.com>
…55504)

* fix: keep `ses.setProxy()` config when the network service restarts

Proxy command-line switches were re-applied to every session each time
its NetworkContext was rebuilt, overwriting a proxy the app had set with
ses.setProxy(). Apply them once, when the session's prefs are created.

Co-Authored-By: Claude <noreply@anthropic.com>

* test: use testing helpers in the setProxy restart spec

Restart the network service with simulateNetworkServiceCrash() and add
flushSessionProxyConfigForTesting() so the spec no longer polls.

Co-Authored-By: Claude <noreply@anthropic.com>

---------

Co-authored-by: Claude <noreply@anthropic.com>
* chore: bump chromium in DEPS to 159.0.8131.0

* 8669680: [FSA] Allow subfolders of WSL home directories

Upstream added the kFileSystemAccessAllowWslHomeSubfolders feature and the
IsAllowedWslHomePath() helper inside the blocklist code that
refactor_expose_file_system_access_blocklist.patch moves into
chrome_file_system_access_blocklist.cc. Carried both, and the updated
MaybeIsLocalUNCPath() check in ShouldBlockAccessToPath(), over into the
blocklist file.

Ref: https://chromium-review.googlesource.com/c/chromium/src/+/8669680

Co-Authored-By: Claude Fable 5.1 <noreply@anthropic.com>

* chore: update patches

* chore: bump chromium in DEPS to 159.0.8132.0

* chore: update patches

* 8396808: [api] Remove deprecated callback data accessors

Ref: https://chromium-review.googlesource.com/c/v8/v8/+/8396808

Co-Authored-By: Claude Fable 5.1 <noreply@anthropic.com>

* 8559539: [objects] Speed up large DescriptorArray lookups with a hash table

The CL's DescriptorArray sharing change reshaped the Node.js startup
snapshot object graph so that a RegExpData shared by two JSRegExp
objects was first reached at the serializer's maximum recursion depth
and deferred. The second trusted pointer to it then hit the CHECK in
Serializer::ObjectSerializer::VisitTrustedPointer() that assumed
pending objects never appear there, aborting node_mksnapshot. That
CHECK dates from
https://chromium-review.googlesource.com/c/v8/v8/+/4628448#nolint

Teach VisitTrustedPointer() to emit a pending forward reference, which
the deserializer already supports for trusted pointer slots.

Ref: https://chromium-review.googlesource.com/c/v8/v8/+/8559539

Co-Authored-By: Claude Fable 5.1 <noreply@anthropic.com>

* chore: bump chromium in DEPS to 159.0.8134.0

* chore: update patches

* 8668230: vr: make it possible to run the OpenXR browser tests on Linux

Upstream extended the Windows-only OpenXR browser test block in
xr_browser_tests_vr_required to Linux, with an unconditional dep on
//device/vr:openxr_data. That target only exists when enable_openxr is
true, and Electron sets checkout_openxr = false, so on Linux (where
enable_vr is true regardless) `gn gen` failed with an unresolved
dependency. Add a patch guarding the block on enable_openxr.

Ref: https://chromium-review.googlesource.com/c/chromium/src/+/8668230

Co-Authored-By: Claude Fable 5.1 <noreply@anthropic.com>

* 8660938: [api] Promote EmbedderDataArray API deprecations to V8_DEPRECATED

Context::SetAlignedPointerInEmbedderData and Context::SetEmbedderData are
now V8_DEPRECATED. Their replacements (SetAlignedPointerInEmbedderDataV2
and SetEmbedderDataV3) do not grow the context's EmbedderDataArray, whose
size is now fixed at build time by v8_embedder_data_array_size (default
5). Node.js stores its context data at indices 32-39 and Electron at
index 5, so set v8_embedder_data_array_size = 40 and switch Electron's
node_bindings and the Node.js patch over to the V2/V3 setters.

Ref: https://chromium-review.googlesource.com/c/v8/v8/+/8660938

Co-Authored-By: Claude Fable 5.1 <noreply@anthropic.com>

* chore: bump chromium in DEPS to 159.0.8136.0

* chore: update patches

* chore: update patches

Skip-Lint: Addressed additional callsites required API updates.

* 8673899: blink: decouple check_generated_file_list and validate_web_idl from C++ compile

Ref: https://chromium-review.googlesource.com/c/chromium/src/+/8673899

* fixup! 8396808: [api] Remove deprecated callback data accessors

Route NAN callback data reads through a compatibility helper using
DataV2() on V8 15.6+.

Ref: https://chromium-review.googlesource.com/c/v8/v8/+/8396808

* chore: bump chromium in DEPS to 159.0.8138.0

* chore: bump chromium in DEPS to 159.0.8139.2

* chore: bump chromium in DEPS to 159.0.8140.0

* chore: update patches

* chore: update siso revision

* 8706254: Roll hunspell dictionaries from eb106bd524ee to 00f6e69c905b (1 revision)

Ref: https://chromium-review.googlesource.com/c/chromium/src/+/8706254

Co-Authored-By: Claude Fable 5.1 <noreply@anthropic.com>

* 8667829: Remove TOP_LEVEL_STORAGE_ACCESS content type and associated logic

Upstream removed the TOP_LEVEL_STORAGE_ACCESS permission type, the
PermissionControllerDelegate::GetPermissionResultForEmbeddedRequester
override that only existed for it, and the requesting_origin field on
PermissionRequestDescription. Electron never read that field, so the
requesting_origin parameter of RequestPermissionWithDetails that fed it
is dropped along with the override, the permission string converter
case, and the docs for the now-unreachable top-level-storage-access
permission.

Ref: https://chromium-review.googlesource.com/c/chromium/src/+/8667829

Co-Authored-By: Claude Fable 5.1 <noreply@anthropic.com>

* 8640149: [ozone/wayland] Do not export toplevels that have no role

Remove the redundant cherry-pick: this fix is already included in the rolled Chromium revision.

Ref: https://chromium-review.googlesource.com/c/chromium/src/+/8640149

Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.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: deepak1556 <hop2deep@gmail.com>
Co-authored-by: Charles Kerr <charles@charleskerr.com>
Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
…ow (#55482)

* build: add crossbench benchmark harness and nightly comparison workflow

Adds script/benchmarks/, which runs crossbench against Electron builds
and Chrome for Testing interleaved on one runner and compares them with
Welch's t-test and Mann-Whitney U, plus a daily Benchmarks workflow
that compares the latest nightly with the previous one and with Chrome
for Testing at the same Chromium version on the ARC Linux runners and
sends the results to Datadog.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01Vf2yMv3H6HNt1XyAwo35Sm

* build: fail benchmark runs on crossbench errors and clean up timed-out process trees

- run.mjs: run each crossbench invocation in its own process group and,
  on timeout or after it exits, kill the whole tree (SIGTERM, then SIGKILL
  after a grace period; taskkill /T on Windows) and wait for it to be gone.
  A timeout returns 124. Every round still runs, but any failed invocation
  makes run.mjs exit non-zero. Each invocation records its expected
  repetition count in metadata.json.
- compare.mjs: only use invocations that exited with 0, drop measures with
  missing repetitions, and log what was left out. Exit non-zero when there
  are no samples or a required comparison (vs baseline; vs CfT unless it
  was skipped) has no comparable metric. comparison.json and the summary
  are still written.
- Add tests for both, and note in the workflow why compare and upload run
  after a failed run step.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01Vf2yMv3H6HNt1XyAwo35Sm

* build: pick same-major baselines, page nightlies and stamp Datadog points at upload

- fetch-targets: the default baseline for a release candidate is the
  newest older release on the same major line by semver, not the next
  entry in date-ordered releases.json; fail clearly when there is none.
- fetch-targets: page through the electron/nightlies releases API so
  older nightlies get a default baseline.
- compare: stamp Datadog points at upload time; run.mjs also records
  finishedAt when it is stopped by a signal.
- benchmarks.yml: drop the concurrency group, which cancelled queued runs.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01Vf2yMv3H6HNt1XyAwo35Sm

* build: port benchmark scripts to TypeScript and use @electron/fiddle-core

fetch-targets now resolves versions with @electron/fiddle-core's
ElectronVersions (releases.electronjs.org, which lists nightlies and
their Chromium versions), installs Electron with its Installer, and
downloads chromedriver with @electron/get's downloadArtifact. Both
verify the release's SHASUMS256.txt. This replaces the hand-rolled
GitHub nightlies paging, semver comparison, downloads and checksum
checks. Chrome for Testing lookup and download stay custom. Builds are
now always for the host platform and architecture, and the stale
nightly check uses the release date from releases.json.

The scripts and tests are now .mts, run with Node's built-in type
stripping and checked by tsconfig.script.json like the repo's other
.mts scripts. The harness app stays plain JavaScript because every
Electron version under test loads it with --app.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01Vf2yMv3H6HNt1XyAwo35Sm

* build: temporarily run benchmarks on this PR for an example run

Adds a pull_request trigger, limited to the benchmark workflows and
script/benchmarks/, so reviewers can see an end-to-end run before the
workflow lands on main. PR runs use 3 rounds, compare the latest two
nightlies plus Chrome for Testing, and do not upload to Datadog.
Remove before merge.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01Vf2yMv3H6HNt1XyAwo35Sm

* build: remove temporary benchmarks pull_request trigger

This reverts commit 8ede480. The
example run succeeded:
https://github.com/electron/electron/actions/runs/40946119960

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01Vf2yMv3H6HNt1XyAwo35Sm

* build: measure benchmarks with crossbench's own probes

Replace the custom METRICS_JS probe with crossbench's built-in probes:

- performance.entries for FCP, loadEventEnd and the file-loading pages'
  'files-loaded' mark, so the js probe is no longer needed.
- meminfo at the end of loading/first_load for per-process PSS (total,
  browser, renderer and GPU).
- A new `trace` suite that records a Chrome-style startup trace (the
  tracing probe, --trace-startup) with four categories and runs
  trace_processor queries on it: FCP and LCP from navigationStart, and
  BrowserWindow.setSize() latency from Widget::OnNativeWidgetSizeChanged
  to the presentation of the next renderer frame. This replaces the
  two-rAF resize timer. The traced stories run in their own invocation so
  tracing never touches the timed loading and file_loading numbers.

compare.mts reads the new outputs and reports a story with none of its
expected values as incomplete. Statistics, Datadog upload and failure
semantics are unchanged; loading.*.lcp and loading.resize.* are replaced
by trace.first_load.lcp and trace.resize.*.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01Vf2yMv3H6HNt1XyAwo35Sm

* build: drop Chrome for Testing from benchmark comparisons

The benchmarks only need to compare Electron against itself, so remove
the Chrome for Testing target. fetch-targets.mts now fetches just the
candidate and baseline Electron builds, run.mts and the page configs no
longer branch on the target kind, and compare.mts only produces the
vs_baseline comparison, which stays required.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01Vf2yMv3H6HNt1XyAwo35Sm

---------

Co-authored-by: Claude <noreply@anthropic.com>
The callback target points to a heap-allocated HWND slot owned by the dialogs map, not to the native window itself. Use raw_ptr for that borrowed storage and remove the misleading exclusion comment. Keep the existing cross-thread locking and cancellation behavior unchanged.

Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
All current Dictionary::SetGetter callers use mutable RenderFrameHost pointers. Remove the unused const-pointer AccessorValue specialization and its raw_ptr exclusion dependency; keep the value and const-reference cases unchanged.

Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
* fix: defer DOMStorage inspector reads out of V8 interrupts

DOMStorage.getDOMStorageItems can run the globalThis.localStorage getter,
and Node dispatches messages from a remote frontend inside a V8 API
interrupt whenever JavaScript is running. Chromium's V8 forbids calling
into JavaScript there, so parallel/test-inspector-dom-storage-malformed
intermittently aborted with "Invoke in DisallowJavascriptExecutionScope".

Add a Node patch that makes getDOMStorageItems an async command and
answers it from an immediate when it is dispatched from an interrupt.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01KX1hkMQWmcBFqxqMV1b6ZT

* fix: backport upstream DOMStorage inspector interrupt fix

Replace our own inspector_defer_domstorage_reads_out_of_v8_interrupts
patch with the DOMStorage commits from nodejs/node#66740:

- c43f994f8293 inspector: avoid JS execution in
  DOMStorage.getDOMStorageItems
- 5dca62fd674c test: cover DOMStorage reads from V8 interrupts

The first commit of that PR (3090adef8b79, the re-land of
nodejs/node#65397) is already carried as
inspector_defer_remaining_js_execution_from_v8_interrupts.patch.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01KX1hkMQWmcBFqxqMV1b6ZT

---------

Co-authored-by: Claude <noreply@anthropic.com>
BrowserView APIs are deprecated in favor of WebContentsView, so
labelling them as Experimental as well is contradictory.


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

Co-authored-by: Claude Opus 5.5 <noreply@anthropic.com>
…39.1 (#55587)

build(deps): bump github/codeql-action/upload-sarif

Bumps [github/codeql-action/upload-sarif](https://github.com/github/codeql-action) from 4.39.0 to 4.39.1.
- [Release notes](https://github.com/github/codeql-action/releases)
- [Changelog](https://github.com/github/codeql-action/blob/main/CHANGELOG.md)
- [Commits](github/codeql-action@6f2ac81...9b32540)

---
updated-dependencies:
- dependency-name: github/codeql-action/upload-sarif
  dependency-version: 4.39.1
  dependency-type: direct:production
  update-type: version-update:semver-patch
...

Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
Bumps [actions/setup-python](https://github.com/actions/setup-python) from 7.0.0 to 7.1.0.
- [Release notes](https://github.com/actions/setup-python/releases)
- [Commits](actions/setup-python@5fda3b9...6d4fd22)

---
updated-dependencies:
- dependency-name: actions/setup-python
  dependency-version: 7.1.0
  dependency-type: direct:production
  update-type: version-update:semver-minor
...

Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
* chore: bump build image tag in .github/actions/build-image-sha/action.yml to 4db2fbc

* chore: bump build image tag in .devcontainer/docker-compose.yml to 4db2fbc

---------

Co-authored-by: electron-roller[bot] <84116207+electron-roller[bot]@users.noreply.github.com>
* test: bypass system proxy in configureHostResolver spec

On an Azure Pipelines Linux agent configured with an HTTP proxy, the
'affects dns lookup behavior' test failed every retry: the request to
the .test hostname came back as a 502 Bad Gateway from the proxy
(server: Kestrel). With an HTTP proxy, Chromium hands the hostname to
the proxy and name resolution happens there, so the host resolver
configured via app.configureHostResolver is never exercised. Force a
direct connection on the default session for the duration of the test.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01Vf2yMuskMgmVbr4wqwUBKN

* test: bypass system proxy in security-warnings spec

security-warnings.spec.ts serves its pages from http://localhost2:<port>,
which spec/index.js maps to 127.0.0.1 with host-resolver-rules. On an
Azure Pipelines Linux agent configured with an HTTP proxy, Chromium sent
the localhost2 requests to the proxy (localhost2 is not implicitly
bypassed and host-resolver-rules do not apply to the proxy's lookup), so
the pages never loaded and 18 of 20 tests timed out waiting for console
messages on every attempt. Use a direct connection on the default
session while the suite runs and restore the system proxy afterwards.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01Vf2yMuskMgmVbr4wqwUBKN

* test: use isolated sessions for proxy-sensitive specs

Addresses review feedback: instead of switching the default session to
a direct connection and restoring the system proxy afterwards, give
each spec its own in-memory session with { mode: 'direct' }. The
configureHostResolver test passes its session to net.request (and sets
the certificate verifier for the DoH server there), and the
security-warnings windows all load in a dedicated partition, so the
default session is no longer touched.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01Vf2yMuskMgmVbr4wqwUBKN

---------

Co-authored-by: Claude <noreply@anthropic.com>
…#55589)

* build: use nightly publish time for the benchmarks stale-nightly skip

The scheduled benchmarks run skipped the latest nightly when it was more
than 24 hours old, measured from midnight UTC of its release date because
releases.json only has a date. A nightly published after the 20:43 UTC run
on its release day was already about 45 hours old at the next day's run, so
it was never benchmarked.

Measure the age from the nightly's GitHub release publish time in
electron/nightlies instead, falling back to the release date with a warning
when the API call fails, and allow 25 hours so a daily run that starts late
still picks it up.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01Vf2yMv3H6HNt1XyAwo35Sm

* build: clarify benchmarks nightly skip wording

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01Vf2yMv3H6HNt1XyAwo35Sm

---------

Co-authored-by: Claude <noreply@anthropic.com>
* fix: legacy window reparenting

* fix: drop the leave filter in PreHandleMSG

HWNDMessageHandler routes WM_MOUSELEAVE and WM_NCMOUSELEAVE to
OnMouseRange, so a leave the OS delivers to this window already reaches
ElectronDesktopWindowTreeHostWin::HandleMouseEvent, where kMouseExited
is filtered. Keeping the PreHandleMSG case as well skipped the
active_mouse_tracking_flags_ = 0 reset in
HandleMouseEventInternal, which left the cached flags set with the OS
tracking off; after that TrackMouseEvents() no longer arms anything for
the same flags.

With a single filter both paths behave the same, and the comments at the
filter and above RearmMouseLeaveTracking() describe what happens now.

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

* test: cover a view moved to another window

Chromium moves a live Chrome_RenderWidgetHostHWND with ::SetParent when
its WebContentsView changes window, which sends no WM_PARENTNOTIFY, so a
window that gains a view never hears about the HWND it now hosts, and
cannot filter the mouse leave that HWND reports once forwarding starts.

Load a view in one window, move it, still loaded, into a second window,
let real input hover an element while that window is still solid, then
enable forwarding over it. Check that moves keep being forwarded, hover
is never interrupted, and exactly one leave fires on exit.

Without the fix the first forwarded move is preceded by a spurious leave
and the element stops being hovered; with it the counts are 0 and 1.

Requested in review by @jkleinsc.

---------

Co-authored-by: Charles Kerr <charles@charleskerr.com>
* fix: crash when using chrome.system.storage in extensions

Electron never created the global StorageMonitor that the API dereferences without a null check. Create it like Chrome does, and destroy it after browser contexts are gone.

Co-Authored-By: Claude <noreply@anthropic.com>

* test: skip chrome.system.storage specs on Linux

Co-Authored-By: Claude <noreply@anthropic.com>

---------

Co-authored-by: Claude <noreply@anthropic.com>
…55606)

* fix: honor hasShadow: false for windows in app shims

The option only reached a stored value, so these windows kept the system shadow.

* docs: drop the app shim hasShadow note

The constructor option now behaves as documented, so it needs no callout.

* fix: honor focusable for windows in app shims

focusable: false and win.setFocusable() had no effect on these windows, and win.isFocusable() always returned false.
* refactor: drive useSystemPicker via upstream native picker

setDisplayMediaRequestHandler's useSystemPicker option now opens Chromium's
own NativeScreenCapturePickerMac through
content::desktop_capture::OpenNativeScreenCapturePicker, instead of an
Electron-specific SCContentSharingPicker path inside the capture device.

- Replace feat_allow_usage_of_sccontentsharingpicker_on_supported_platforms.patch
  (424 lines) with a small patch: always create the picker on macOS, and
  only start or close picker sessions for ids the picker issued
  (IdType::kNativePickerSession). getSources() ids keep the regular
  ScreenCaptureKit path, so UseSCContentSharingPicker stays off and
  getSources() is unchanged.
- Tag picker results as kNativePickerSession, and reject that id type when
  it comes from a renderer (legacy chromeMediaSource: 'desktop') or back
  through the handler callback, so a page can't reuse another page's
  picker selection.
- Close the picker session when the user cancels or the picker errors,
  like Chrome does, and fail the request if its page is gone by the time
  the user picks. A new request supersedes one whose picker never
  answered, since the picker tracks one pending selection at a time.
- Exclude content-protected windows from the picker, as the old patch did.
- The picker type follows the page's displaySurface: 'window' opens the
  window picker, anything else the screen picker.
- Drop the JS wrapper and fake "window:-4:N" source; the C++ binding reads
  the option directly.

* feat: grant system audio from useSystemPicker when the page asks for it

* fix: honor systemAudio and windowAudio for useSystemPicker audio

* docs: list every useSystemPicker behavior change

The breaking-changes entry now covers system audio and the track's
displaySurface as well as the picker kind, session.md links it through an
API history entry, and documents that cancelling the picker or calling
getDisplayMedia() again while it's open rejects with NotAllowedError.

* fix: address review on the useSystemPicker picker path

- Only reject picker session ids on macOS: Wayland's delegated getSources()
  ids carry the same tag and must still be accepted.
- A null display media handler turns getDisplayMedia() off again, even with
  useSystemPicker.
- Only the frame that opened the picker may replace its request; any other
  frame is rejected while the picker is open.
- Use vitest matchers in the picker id specs and run them on macOS only.

* fix: reject overlapping system picker requests and drop them on navigation

- Match Chromium's Open(): a request made while the picker is open is
  rejected and the open picker keeps its request.
- Tie the pending request to its document so navigating away or closing
  the frame fails it and closes its picker session.
- Exclude content-protected windows inside NativeScreenCapturePickerMac::Open(),
  which rebuilds excludedWindowIDs on every call.

* feat: offer windows and screens together when the page has no preference

A useSystemPicker page that doesn't set displaySurface now gets one
picker with both windows and screens on macOS 15.2+, where the picker
reports which kind was picked. 'window' and 'monitor'/'browser' still
narrow it, and macOS 15.0/15.1 keep the screens-only picker.

* feat: offer whole-application sharing in the combined picker

The no-preference picker now also lets the user share every window of
one application. An application pick reports displaySurface 'window',
the closest web value; only a picked display reports 'monitor'.

* docs: drop the multi-select note; the picker never offered it

* fix: free the system picker when the requesting renderer crashes

A crashed renderer keeps its DocumentUserData until the next navigation,
so SystemPickerRequestOwner now also watches RenderFrameDeleted. Keep the
one-picker slot held until the picker reports its session, so a request
failed mid-Open() can't let a second Open() through to a rejection. Adds a
test-only picker stub and a spec for the crash case.

* test: read the picker availability from the internal binding

* test: format the picker crash spec

* chore: update patches

* fix: give displaySurface 'browser' the no-preference system picker

Electron has no tabs to offer, and displaySurface is a hint that must
not fail the request, so a page asking for 'browser' gets the combined
picker instead of screens only.

---------

Co-authored-by: PatchUp <73610968+patchup[bot]@users.noreply.github.com>
* feat: add dynamicId to Extension

Expose Chromium's per-load extension GUID (extensions::Extension::guid())
as `dynamicId` on the Extension structure, so apps can build
chrome-extension://<dynamicId>/ URLs for web accessible resources declared
with `use_dynamic_url`.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01KX1hkLiDMxW5As4tg8fPHq

* test: add dynamicId spec

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01KX1hkLiDMxW5As4tg8fPHq

---------

Co-authored-by: Claude <noreply@anthropic.com>
…iles (#55631)

* test: log every retried spec regardless of duration

The default reporter only prints a test, and its retry count, when it
fails or is slower than slowTestThreshold, so a fast test that passes
on a retry never shows up in the CI log. Add a small reporter, enabled
on CI, that prints one line per retried test and a total at the end.

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

* test: disable retries in spec files with no recent retries

These nine files had no retries across roughly 100 main runs since
Oct 19 on eight or more test lanes, so a new flake in them should fail instead
of being hidden by a retry.

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

---------

Co-authored-by: Claude <noreply@anthropic.com>
Xvfb resets when its last client disconnects and drops connections that
arrive during the reset. The vitest pool starts a fresh Electron per spec
file, so the display regularly reaches zero clients while the next worker
connects; that worker then exits with "Missing X server or $DISPLAY"
before it is ready and the run reports a pool error.


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

Co-authored-by: Claude <noreply@anthropic.com>
…5629)

* fix: run local notification callbacks on the main thread on macOS

With a nil queue, NSNotificationCenter runs observer blocks on whichever
thread posts the notification, and the block called the JS callback
there. A background thread would block on the isolate's v8::Locker held
by the main thread, which could hang app.quit(). Keep the callbacks in a
main-thread-only map and post notifications from other threads to the
main thread.

Also make the detached-frame cppgc fixture collect with async GCs so
conservative stack scanning (notably ASan fake stacks) cannot keep a
stale callback holder alive, and disable retries in cpp-heap.spec.ts.

Fixes #55392

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>

* fix: address clang-tidy findings in notification dispatch

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>

* refactor: track notification subscriptions in a single map

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>

---------

Co-authored-by: Claude Opus 5.5 <noreply@anthropic.com>
…d" (#55635)

Add a siso patch that re-runs a failed local action once on macOS when
its stderr contains "Failed to run esbuild: Error: The service was
stopped". The devtools-frontend bundle actions intermittently fail this
way on macOS CI when the esbuild service child exits at startup, and a
rerun succeeds. Each retry prints a "siso: esbuild service was stopped
in ... retrying once" line to the build output so hits can be counted.


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

Co-authored-by: Claude <noreply@anthropic.com>
NativeWindowMacRemote::SetHasShadow only stored the value, so after the
creation-time hasShadow option was honored, a later setHasShadow() left
the shim's window unchanged while hasShadow() reported the new value.
Send it to the shim, which sets it on the NSWindow, as NativeWindowMac
does for in-process windows.

Also tag the app shim focusable spec as serial, since it needs OS-level
focus and other spec processes' windows can take it.


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

Co-authored-by: Claude <noreply@anthropic.com>
…es (#55623)

fix: limit webRequest redirects across loader restarts

Keep a per-request redirect count across target loader restarts.
Reject redirects beyond Chromium's limit with ERR_TOO_MANY_REDIRECTS.
* docs: Migrate API best practices from Governance to e/e

* fix: address some of the lint issues

* fix: apply oxfmt fixes

* fix: Address another round of linter warnings

* fix: Use js instead of javascript for code block identifiers

* fix: typescript -> ts

* Link to API best practices from CLAUDE.md
* chore: bump build image tag in .github/actions/build-image-sha/action.yml to 48409d6

* chore: bump build image tag in .devcontainer/docker-compose.yml to 48409d6

---------

Co-authored-by: electron-roller[bot] <84116207+electron-roller[bot]@users.noreply.github.com>
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Projects

None yet

Development

Successfully merging this pull request may close these issues.