From 68fbc0bde3163a2d2fe9418e4dab00098c183f4b Mon Sep 17 00:00:00 2001 From: Pierre Tachoire Date: Tue, 27 Jan 2026 17:01:55 +0100 Subject: [PATCH] use inspector.resetContextGroup during cdp deinit Ensure the inspector is correctly reset from context before deinit it. It fixes the contextCollected crash in a better way. --- src/browser/Page.zig | 7 ------- src/browser/js/Inspector.zig | 12 ++++++++++++ src/cdp/cdp.zig | 5 +++++ 3 files changed, 17 insertions(+), 7 deletions(-) diff --git a/src/browser/Page.zig b/src/browser/Page.zig index 71ca5db2..31803987 100644 --- a/src/browser/Page.zig +++ b/src/browser/Page.zig @@ -253,15 +253,8 @@ fn reset(self: *Page, comptime initializing: bool) !void { } if (comptime initializing == false) { - // Removing the context triggers the linked inspector. - // It seems to append a collect task to the message loop. self._session.executor.removeContext(); - // We force running the message loop after removing the context b/c we - // will force a GC run just after. If we remove this part, the task - // will run after the GC and we will use memory after free. - self._session.browser.runMessageLoop(); - // We force a garbage collection between page navigations to keep v8 // memory usage as low as possible. self._session.browser.env.memoryPressureNotification(.moderate); diff --git a/src/browser/js/Inspector.zig b/src/browser/js/Inspector.zig index 1d35f3f5..13ad79ed 100644 --- a/src/browser/js/Inspector.zig +++ b/src/browser/js/Inspector.zig @@ -151,6 +151,18 @@ pub fn contextCreated( } } +pub fn contextDestroyed(self: *Inspector, local: *const js.Local) void { + v8.v8_inspector__Inspector__ContextDestroyed(self.handle, local.handle); +} + +pub fn resetContextGroup(self: *const Inspector) void { + var hs: v8.HandleScope = undefined; + v8.v8__HandleScope__CONSTRUCT(&hs, self.isolate); + defer v8.v8__HandleScope__DESTRUCT(&hs); + + v8.v8_inspector__Inspector__ResetContextGroup(self.handle, CONTEXT_GROUP_ID); +} + // Retrieves the RemoteObject for a given value. // The value is loaded through the ExecutionWorld's mapZigInstanceToJs function, // just like a method return value. Therefore, if we've mapped this diff --git a/src/cdp/cdp.zig b/src/cdp/cdp.zig index 3f0af4a8..9942decf 100644 --- a/src/cdp/cdp.zig +++ b/src/cdp/cdp.zig @@ -424,6 +424,11 @@ pub fn BrowserContext(comptime CDP_T: type) type { // in progress before deinit. self.cdp.browser.env.runMicrotasks(); + // resetContextGroup detach the inspector from all contexts. + // It append async tasks, so we make sure we run the message loop + // before deinit it. + self.inspector.resetContextGroup(); + self.session.browser.runMessageLoop(); self.inspector.deinit(); // abort all intercepted requests before closing the sesion/page