mirror of
https://github.com/electron/electron.git
synced 2026-05-02 03:00:22 -04:00
V8's second-pass weak callbacks run inside a DisallowJavascriptExecutionScope: they may touch the V8 API but must not invoke JS, directly or indirectly. Several Electron Wrappables (WebContents in particular) emit JS events from their destructors, so deleting synchronously inside SecondWeakCallback can crash with "Invoke in DisallowJavascriptExecutionScope" when GC happens to collect the JS wrapper during a foreground GC task — typically during shutdown's uv_run drain after a leaked WebContentsView. This was previously latent and timing-dependent (electron/electron#47420, electron/electron#45416, podman-desktop/podman-desktop#12409). The esbuild migration's keepNames option (which wraps every function/class with an Object.defineProperty call) shifted heap layout enough to make the spec/fixtures/crash-cases/webcontentsview-create-leak-exit case reliably reproduce it on every run, giving a clean signal for the fix. Both WrappableBase and DeprecatedWrappableBase SecondWeakCallback now post the deletion via base::SequencedTaskRunner::GetCurrentDefault() so the destructor (and any Emit it does) runs once V8 has left the GC scope. Falls back to synchronous deletion if no task runner is available (early/late process lifetime). Fixes electron/electron#47420. Co-authored-by: trop[bot] <37223003+trop[bot]@users.noreply.github.com> Co-authored-by: Sam Attard <sattard@anthropic.com>