Repository: electron/electron
Pull request: fix: crash when inspector evaluates on provisional frames

Backport of #48503

See that PR for details.


Notes: fix crash when inspector agent attempts to evaluate on provisional frames

Changed files:
filename: patches/chromium/.patches
patch: @@ -137,4 +137,5 @@ fix_add_macos_memory_query_fallback_to_avoid_crash.patch
 fix_resolve_dynamic_background_material_update_issue_on_windows_11.patch
 feat_add_support_for_embedder_snapshot_validation.patch
 band-aid_over_an_issue_with_using_deprecated_nsopenpanel_api.patch
+inspectorpageagent_provisional_frame_speculative_fix.patch
 expose_referrerscriptinfo_hostdefinedoptionsindex.patch

filename: patches/chromium/inspectorpageagent_provisional_frame_speculative_fix.patch
patch: @@ -0,0 +1,116 @@
+From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001
+From: Joey Arhar <jarhar@chromium.org>
+Date: Wed, 1 Oct 2025 02:03:37 -0700
+Subject: InspectorPageAgent provisional frame speculative fix
+
+According to crash reports, addScriptToEvaluateOnNewDocument is running
+on provisional frames.
+
+Fixed: 390710982
+Change-Id: I5cecf63c9517d0b28fff40361c607b0aa54e68cf
+Reviewed-on: https://chromium-review.googlesource.com/c/chromium/src/+/6216479
+Reviewed-by: Alex Rudenko <alexrudenko@chromium.org>
+Commit-Queue: Alex Rudenko <alexrudenko@chromium.org>
+Auto-Submit: Joey Arhar <jarhar@chromium.org>
+Cr-Commit-Position: refs/heads/main@{#1523418}
+
+diff --git a/third_party/blink/renderer/core/inspector/inspector_page_agent.cc b/third_party/blink/renderer/core/inspector/inspector_page_agent.cc
+index fe17063fa8f572368096b88e1e3cc35b469e816a..07c1b9dd216518f70257a6637e3b50d87f098e8b 100644
+--- a/third_party/blink/renderer/core/inspector/inspector_page_agent.cc
++++ b/third_party/blink/renderer/core/inspector/inspector_page_agent.cc
+@@ -603,7 +603,11 @@ protocol::Response InspectorPageAgent::addScriptToEvaluateOnNewDocument(
+     // Runtime.enable that forces main context creation. In this case, we would
+     // not normally evaluate the script, but we should.
+     for (LocalFrame* frame : *inspected_frames_) {
+-      EvaluateScriptOnNewDocument(*frame, *identifier);
++      // Don't evaluate scripts on provisional frames:
++      // https://crbug.com/390710982
++      if (!frame->IsProvisional()) {
++        EvaluateScriptOnNewDocument(*frame, *identifier);
++      }
+     }
+   }
+ 
+diff --git a/third_party/blink/web_tests/FlagExpectations/disable-site-isolation-trials b/third_party/blink/web_tests/FlagExpectations/disable-site-isolation-trials
+index f462af59547e93378034b7e9301053a43f636ea4..3b829d94fa447e58a1acc57b7c7bdbd4564c9507 100644
+--- a/third_party/blink/web_tests/FlagExpectations/disable-site-isolation-trials
++++ b/third_party/blink/web_tests/FlagExpectations/disable-site-isolation-trials
+@@ -63,6 +63,7 @@ http/tests/inspector-protocol/target/target-filter.js [ Skip ]
+ virtual/fenced-frame-mparch/http/tests/inspector-protocol/fenced-frame/fenced-frame-in-oopif-auto-attach.js [ Skip ]
+ http/tests/inspector-protocol/target/target-info-changed-auto-attach.js [ Skip ]
+ http/tests/inspector-protocol/page/frame-detached-oopif.js [ Skip ]
++http/tests/inspector-protocol/page/addScriptToEvaluateOnNewDocument-reload.js [ Skip ]
+ 
+ # Rely on OOPIF for an iframe to be a separate devtools target
+ http/tests/inspector-protocol/timeline/auction-worklet-frame.js [ Skip ]
+diff --git a/third_party/blink/web_tests/http/tests/inspector-protocol/page/addScriptToEvaluateOnNewDocument-reload-expected.txt b/third_party/blink/web_tests/http/tests/inspector-protocol/page/addScriptToEvaluateOnNewDocument-reload-expected.txt
+new file mode 100644
+index 0000000000000000000000000000000000000000..0131df6c227e1803741e654d42b15f589275061a
+--- /dev/null
++++ b/third_party/blink/web_tests/http/tests/inspector-protocol/page/addScriptToEvaluateOnNewDocument-reload-expected.txt
+@@ -0,0 +1,28 @@
++Tests that Page.addScriptToEvaluateOnNewDocument on auto-attach with runImmediately=true.
++Regression test for crbug.com/390710982.
++console called: {
++    method : Runtime.consoleAPICalled
++    params : {
++        args : [
++            [0] : {
++                type : string
++                value : evaluated
++            }
++        ]
++        executionContextId : <number>
++        stackTrace : {
++            callFrames : [
++                [0] : {
++                    columnNumber : 8
++                    functionName :
++                    lineNumber : 0
++                    scriptId : <string>
++                    url :
++                }
++            ]
++        }
++        timestamp : <number>
++        type : log
++    }
++    sessionId : <string>
++}
+diff --git a/third_party/blink/web_tests/http/tests/inspector-protocol/page/addScriptToEvaluateOnNewDocument-reload.js b/third_party/blink/web_tests/http/tests/inspector-protocol/page/addScriptToEvaluateOnNewDocument-reload.js
+new file mode 100644
+index 0000000000000000000000000000000000000000..52ebe845c323c6d692147052f3458777dcd7f966
+--- /dev/null
++++ b/third_party/blink/web_tests/http/tests/inspector-protocol/page/addScriptToEvaluateOnNewDocument-reload.js
+@@ -0,0 +1,31 @@
++(async function(/** @type {import('test_runner').TestRunner} */ testRunner) {
++  const { session, dp } = await testRunner.startBlank(
++    `Tests that Page.addScriptToEvaluateOnNewDocument on auto-attach with runImmediately=true.
++Regression test for crbug.com/390710982.`);
++
++  await dp.Page.enable();
++  await dp.Target.enable();
++  await dp.Target.setAutoAttach({ flatten: true, autoAttach: true, waitForDebuggerOnStart: true });
++
++  dp.Target.onAttachedToTarget(async event => {
++    const dp2 = session.createChild(event.params.sessionId).protocol;
++    dp2.Page.enable();
++    dp2.Runtime.enable();
++    dp2.Runtime.onConsoleAPICalled(event => {
++      testRunner.log(event, 'console called: ');
++    });
++    dp2.Page.addScriptToEvaluateOnNewDocument({
++      source: 'console.log("evaluated")',
++      runImmediately: true,
++    });
++    await dp2.Runtime.runIfWaitingForDebugger();
++  });
++
++  const loaded = dp.Page.onceLoadEventFired();
++  await dp.Page.navigate({
++    url: testRunner.url('resources/iframe-src.html')
++  });
++  await loaded;
++
++  testRunner.completeTest();
++});