#52964: fix: illegal access errors when a same-process child window or subframe closes
Description of Change
Closes #33868.
Closes #36858.
Closes #40607.
Closes #51860.
Every Node.js environment on the renderer main thread (the main frame, nodeIntegrationInSubFrames iframes, same-process window.open() children) shared uv_default_loop(). Freeing one of them runs that loop until its handles close, with JavaScript disallowed on the isolate, so whatever immediates, timers, fs or threadpool callbacks the surviving page had pending fired inside that window and either threw Uncaught illegal access or aborted the renderer. The shared loop was also pumped under the main frame's context only, so napi async work and thread-safe functions used from a child window or subframe aborted in InternalCallbackScope (#33868).
Each frame's environment now gets its own loop integration, the same way worker environments already do: NodeBindings can integrate a given loop or own one, and the renderer keeps a NodeBindings + ElectronBindings pair per frame. A main frame's environment borrows the process-lifetime uv_default_loop() integration while it is free, so native modules that use the default loop keep working there; subframes and any further main frames own their loop. Tearing an environment down parks that loop's embed thread and frees it without touching other environments' handles.
- Environments are keyed by
RenderFrame, which replaces theuv_envhand-off between main-frame environments and the injected-frames bookkeeping. - A new environment gets its first loop run from a fresh task, since child contexts can be created from inside a script (
window.open('about:blank')). - Isolate-level Node.js setup (
NodeBindings::SetUpIsolate) now runs once per isolate instead of once per environment, so renderer frames no longer stack a V8 message listener each; the about:blank subframe skip's comment gives its remaining reason (sandboxed preload startup data) instead of this bug.
Checklist
- I have built and tested this change
- I have filled out the PR description
- I have reviewed and verified the changes
- tests are changed or added
- PR release notes describe the change in a way relevant to app developers, and are capitalized, punctuated, and past tense.
Release Notes
Notes: Fixed Uncaught illegal access errors and renderer crashes when closing a same-process child window or removing an iframe with nodeIntegrationInSubFrames enabled, and when native modules use napi async work or thread-safe functions from such windows and frames.
Backports
Semver Impact
Semantic Versioning helps users understand the impact of updates:
- Major (X.y.z): Breaking changes that may require code modifications
- Minor (x.Y.z): New features that maintain backward compatibility
- Patch (x.y.Z): Bug fixes that don't change the API
- None: Changes that don't affect using facing parts of Electron