Terminate execution on internal navigation

Currently, if there's an internal navigation event, we continue to process the
page normally. This has negative performance implication, and can result in
user-scripts producing unexpected results.

For example, imagine a page with a script that does.

```js
if (x) {
   form.submit();
}

reloadProduct();
```

The call to `form.submit()` should stop the script from executing. And, if the
page has 10 other <script> tags after this, they shouldn't be loaded nor
executed.

This code terminates the execution of the current script on an internal
navigation event, and stops the rest of the page from load.

While I believe this creates a more "correct" behavior, it also introduces new
edge cases. There's no a period of time, between the termination being stopped
and then being resumed, where executing code is not safe.
This commit is contained in:
Karl Seguin
2025-06-12 16:26:27 +08:00
parent 97c769e805
commit b1ca242d89
2 changed files with 77 additions and 32 deletions

View File

@@ -472,6 +472,14 @@ pub fn Env(comptime State: type, comptime WebApis: type) type {
self.scope = null;
_ = self.scope_arena.reset(.{ .retain_with_limit = SCOPE_ARENA_RETAIN });
}
pub fn terminateExecution(self: *const ExecutionWorld) void {
self.env.isolate.terminateExecution();
}
pub fn resumeExecution(self: *const ExecutionWorld) void {
self.env.isolate.cancelTerminateExecution();
}
};
const PersistentObject = v8.Persistent(v8.Object);
@@ -1562,7 +1570,15 @@ pub fn Env(comptime State: type, comptime WebApis: type) type {
}
pub fn send(self: *const Inspector, msg: []const u8) void {
self.session.dispatchProtocolMessage(self.isolate, msg);
// Can't assume there's an existing Scope (with its HandleScope)
// available when doing this. Pages (and thus Scopes) come and
// go, but CDP can keep sending messages.
const isolate = self.isolate;
var temp_scope: v8.HandleScope = undefined;
v8.HandleScope.init(&temp_scope, isolate);
defer temp_scope.deinit();
self.session.dispatchProtocolMessage(isolate, msg);
}
// From CDP docs