From a40590b4bfdd3fb546e395ea2eb7740cf39eed86 Mon Sep 17 00:00:00 2001 From: Pierre Tachoire Date: Sat, 6 Sep 2025 16:28:17 +0200 Subject: [PATCH 01/12] cdp: add DOM.getFrameOwner --- src/cdp/domains/dom.zig | 20 ++++++++++++++++++++ 1 file changed, 20 insertions(+) diff --git a/src/cdp/domains/dom.zig b/src/cdp/domains/dom.zig index 64f24fdf..3a517ee4 100644 --- a/src/cdp/domains/dom.zig +++ b/src/cdp/domains/dom.zig @@ -39,6 +39,7 @@ pub fn processMessage(cmd: anytype) !void { getContentQuads, getBoxModel, requestChildNodes, + getFrameOwner, }, cmd.input.action) orelse return error.UnknownMethod; switch (action) { @@ -55,6 +56,7 @@ pub fn processMessage(cmd: anytype) !void { .getContentQuads => return getContentQuads(cmd), .getBoxModel => return getBoxModel(cmd), .requestChildNodes => return requestChildNodes(cmd), + .getFrameOwner => return getFrameOwner(cmd), } } @@ -461,6 +463,24 @@ fn requestChildNodes(cmd: anytype) !void { return cmd.sendResult(null, .{}); } +fn getFrameOwner(cmd: anytype) !void { + const params = (try cmd.params(struct { + frameId: []const u8, + })) orelse return error.InvalidParams; + + const bc = cmd.browser_context orelse return error.BrowserContextNotLoaded; + const target_id = bc.target_id orelse return error.TargetNotLoaded; + if (std.mem.eql(u8, target_id, params.frameId) == false) { + return cmd.sendError(-32000, "Frame with the given id does not belong to the target."); + } + + const page = bc.session.currentPage() orelse return error.PageNotLoaded; + const doc = parser.documentHTMLToDocument(page.window.document); + + const node = try bc.node_registry.register(parser.documentToNode(doc)); + return cmd.sendResult(.{ .nodeId = node.id, .backendNodeId = node.id }, .{}); +} + const testing = @import("../testing.zig"); test "cdp.dom: getSearchResults unknown search id" { From 5ea97c4910fd8d586356d3881882c07d76702fee Mon Sep 17 00:00:00 2001 From: Pierre Tachoire Date: Sat, 6 Sep 2025 17:59:58 +0200 Subject: [PATCH 02/12] cdp: add send error options with session id by default --- src/cdp/cdp.zig | 12 ++++++++---- src/cdp/domains/dom.zig | 2 +- src/cdp/domains/target.zig | 4 ++-- 3 files changed, 11 insertions(+), 7 deletions(-) diff --git a/src/cdp/cdp.zig b/src/cdp/cdp.zig index 3fcf14dc..d8878bdc 100644 --- a/src/cdp/cdp.zig +++ b/src/cdp/cdp.zig @@ -151,18 +151,18 @@ pub fn CDPT(comptime TypeProvider: type) type { if (std.mem.eql(u8, input_session_id, "STARTUP")) { is_startup = true; } else if (self.isValidSessionId(input_session_id) == false) { - return command.sendError(-32001, "Unknown sessionId"); + return command.sendError(-32001, "Unknown sessionId", .{}); } } if (is_startup) { dispatchStartupCommand(&command) catch |err| { - command.sendError(-31999, @errorName(err)) catch {}; + command.sendError(-31999, @errorName(err), .{}) catch {}; return err; }; } else { dispatchCommand(&command, input.method) catch |err| { - command.sendError(-31998, @errorName(err)) catch {}; + command.sendError(-31998, @errorName(err), .{}) catch {}; return err; }; } @@ -757,10 +757,14 @@ pub fn Command(comptime CDP_T: type, comptime Sender: type) type { return self.cdp.sendEvent(method, p, opts); } - pub fn sendError(self: *Self, code: i32, message: []const u8) !void { + const SendErrorOpts = struct { + include_session_id: bool = true, + }; + pub fn sendError(self: *Self, code: i32, message: []const u8, opts: SendErrorOpts) !void { return self.sender.sendJSON(.{ .id = self.input.id, .@"error" = .{ .code = code, .message = message }, + .sessionId = if (opts.include_session_id) self.input.session_id else null, }); } diff --git a/src/cdp/domains/dom.zig b/src/cdp/domains/dom.zig index 3a517ee4..c482d90d 100644 --- a/src/cdp/domains/dom.zig +++ b/src/cdp/domains/dom.zig @@ -471,7 +471,7 @@ fn getFrameOwner(cmd: anytype) !void { const bc = cmd.browser_context orelse return error.BrowserContextNotLoaded; const target_id = bc.target_id orelse return error.TargetNotLoaded; if (std.mem.eql(u8, target_id, params.frameId) == false) { - return cmd.sendError(-32000, "Frame with the given id does not belong to the target."); + return cmd.sendError(-32000, "Frame with the given id does not belong to the target.", .{}); } const page = bc.session.currentPage() orelse return error.PageNotLoaded; diff --git a/src/cdp/domains/target.zig b/src/cdp/domains/target.zig index 87fe4324..0f55bb74 100644 --- a/src/cdp/domains/target.zig +++ b/src/cdp/domains/target.zig @@ -79,7 +79,7 @@ fn createBrowserContext(cmd: anytype) !void { } const bc = cmd.createBrowserContext() catch |err| switch (err) { - error.AlreadyExists => return cmd.sendError(-32000, "Cannot have more than one browser context at a time"), + error.AlreadyExists => return cmd.sendError(-32000, "Cannot have more than one browser context at a time", .{}), else => return err, }; @@ -102,7 +102,7 @@ fn disposeBrowserContext(cmd: anytype) !void { })) orelse return error.InvalidParams; if (cmd.cdp.disposeBrowserContext(params.browserContextId) == false) { - return cmd.sendError(-32602, "No browser context with the given id found"); + return cmd.sendError(-32602, "No browser context with the given id found", .{}); } try cmd.sendResult(null, .{}); } From 2221d0cb6fa59c38b48609788eaa7273dae103e4 Mon Sep 17 00:00:00 2001 From: Pierre Tachoire Date: Sat, 6 Sep 2025 18:00:27 +0200 Subject: [PATCH 03/12] cdp: send the chrome's error on missing node --- src/cdp/domains/dom.zig | 19 +++++++++++++------ 1 file changed, 13 insertions(+), 6 deletions(-) diff --git a/src/cdp/domains/dom.zig b/src/cdp/domains/dom.zig index c482d90d..1e72177e 100644 --- a/src/cdp/domains/dom.zig +++ b/src/cdp/domains/dom.zig @@ -208,7 +208,9 @@ fn querySelector(cmd: anytype) !void { const bc = cmd.browser_context orelse return error.BrowserContextNotLoaded; - const node = bc.node_registry.lookup_by_id.get(params.nodeId) orelse return error.UnknownNode; + const node = bc.node_registry.lookup_by_id.get(params.nodeId) orelse { + return cmd.sendError(-32000, "Could not find node with given id", .{}); + }; const selected_node = try css.querySelector( cmd.arena, @@ -235,7 +237,9 @@ fn querySelectorAll(cmd: anytype) !void { const bc = cmd.browser_context orelse return error.BrowserContextNotLoaded; - const node = bc.node_registry.lookup_by_id.get(params.nodeId) orelse return error.UnknownNode; + const node = bc.node_registry.lookup_by_id.get(params.nodeId) orelse { + return cmd.sendError(-32000, "Could not find node with given id", .{}); + }; const arena = cmd.arena; const selected_nodes = try css.querySelectorAll(arena, node._node, params.selector); @@ -554,16 +558,19 @@ test "cdp.dom: querySelector unknown search id" { _ = try ctx.loadBrowserContext(.{ .id = "BID-A", .html = "

1

2

" }); - try testing.expectError(error.UnknownNode, ctx.processMessage(.{ + try ctx.processMessage(.{ .id = 9, .method = "DOM.querySelector", .params = .{ .nodeId = 99, .selector = "" }, - })); - try testing.expectError(error.UnknownNode, ctx.processMessage(.{ + }); + try ctx.expectSentError(-32000, "Could not find node with given id", .{}); + + try ctx.processMessage(.{ .id = 9, .method = "DOM.querySelectorAll", .params = .{ .nodeId = 99, .selector = "" }, - })); + }); + try ctx.expectSentError(-32000, "Could not find node with given id", .{}); } test "cdp.dom: querySelector Node not found" { From 9cb4431e89454f9479dc1cb3c169bf3b84de2a65 Mon Sep 17 00:00:00 2001 From: Pierre Tachoire Date: Sat, 6 Sep 2025 18:01:00 +0200 Subject: [PATCH 04/12] cdp: add initiator on request will be send --- src/cdp/domains/network.zig | 9 ++++++++- 1 file changed, 8 insertions(+), 1 deletion(-) diff --git a/src/cdp/domains/network.zig b/src/cdp/domains/network.zig index c8a1788d..83e2b8f8 100644 --- a/src/cdp/domains/network.zig +++ b/src/cdp/domains/network.zig @@ -244,7 +244,14 @@ pub fn httpRequestStart(arena: Allocator, bc: anytype, msg: *const Notification. const transfer = msg.transfer; // We're missing a bunch of fields, but, for now, this seems like enough - try bc.cdp.sendEvent("Network.requestWillBeSent", .{ .requestId = try std.fmt.allocPrint(arena, "REQ-{d}", .{transfer.id}), .frameId = target_id, .loaderId = bc.loader_id, .documentUrl = DocumentUrlWriter.init(&page.url.uri), .request = TransferAsRequestWriter.init(transfer) }, .{ .session_id = session_id }); + try bc.cdp.sendEvent("Network.requestWillBeSent", .{ + .requestId = try std.fmt.allocPrint(arena, "REQ-{d}", .{transfer.id}), + .frameId = target_id, + .loaderId = bc.loader_id, + .documentUrl = DocumentUrlWriter.init(&page.url.uri), + .request = TransferAsRequestWriter.init(transfer), + .initiator = .{ .type = "other" }, + }, .{ .session_id = session_id }); } pub fn httpResponseHeaderDone(arena: Allocator, bc: anytype, msg: *const Notification.ResponseHeaderDone) !void { From c4090851c59ecc0f5e2944bfe8565a7975a08c2c Mon Sep 17 00:00:00 2001 From: Pierre Tachoire Date: Sat, 6 Sep 2025 19:04:14 +0200 Subject: [PATCH 05/12] css: accept digit as name start --- src/browser/css/parser.zig | 6 ++++-- src/browser/css/selector.zig | 5 +++++ 2 files changed, 9 insertions(+), 2 deletions(-) diff --git a/src/browser/css/parser.zig b/src/browser/css/parser.zig index 63b863d8..d93fdb80 100644 --- a/src/browser/css/parser.zig +++ b/src/browser/css/parser.zig @@ -821,7 +821,8 @@ pub const Parser = struct { // nameStart returns whether c can be the first character of an identifier // (not counting an initial hyphen, or an escape sequence). fn nameStart(c: u8) bool { - return 'a' <= c and c <= 'z' or 'A' <= c and c <= 'Z' or c == '_' or c > 127; + return 'a' <= c and c <= 'z' or 'A' <= c and c <= 'Z' or c == '_' or c > 127 or + '0' <= c and c <= '9'; } // nameChar returns whether c can be a character within an identifier @@ -890,7 +891,7 @@ test "parser.parseIdentifier" { err: bool = false, }{ .{ .s = "x", .exp = "x" }, - .{ .s = "96", .exp = "", .err = true }, + .{ .s = "96", .exp = "96", .err = false }, .{ .s = "-x", .exp = "-x" }, .{ .s = "r\\e9 sumé", .exp = "résumé" }, .{ .s = "r\\0000e9 sumé", .exp = "résumé" }, @@ -975,6 +976,7 @@ test "parser.parse" { .{ .s = ":root", .exp = .{ .pseudo_class = .root } }, .{ .s = ".\\:bar", .exp = .{ .class = ":bar" } }, .{ .s = ".foo\\:bar", .exp = .{ .class = "foo:bar" } }, + .{ .s = "[class=75c0fa18a94b9e3a6b8e14d6cbe688a27f5da10a]", .exp = .{ .attribute = .{ .key = "class", .val = "75c0fa18a94b9e3a6b8e14d6cbe688a27f5da10a", .op = .eql } } }, }; for (testcases) |tc| { diff --git a/src/browser/css/selector.zig b/src/browser/css/selector.zig index 00ef1558..a6402efc 100644 --- a/src/browser/css/selector.zig +++ b/src/browser/css/selector.zig @@ -993,6 +993,11 @@ test "Browser.CSS.Selector: matchFirst" { .n = .{ .child = &.{ .name = "p", .sibling = &.{ .name = "p", .att = "bar" } } }, .exp = 0, }, + .{ + .q = "[foo=1baz]", + .n = .{ .child = &.{ .name = "p", .sibling = &.{ .name = "p", .att = "bar" } } }, + .exp = 0, + }, .{ .q = "[foo!=bar]", .n = .{ .child = &.{ .name = "p", .sibling = &.{ .name = "p", .att = "bar" } } }, From 82e5698f1ddcacf3176209d1d01453db52bac263 Mon Sep 17 00:00:00 2001 From: Pierre Tachoire Date: Sat, 6 Sep 2025 19:59:06 +0200 Subject: [PATCH 06/12] cdp: accept neg depth in describeNode --- src/cdp/domains/dom.zig | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/cdp/domains/dom.zig b/src/cdp/domains/dom.zig index 1e72177e..f50b6e87 100644 --- a/src/cdp/domains/dom.zig +++ b/src/cdp/domains/dom.zig @@ -306,11 +306,11 @@ fn describeNode(cmd: anytype) !void { nodeId: ?Node.Id = null, backendNodeId: ?Node.Id = null, objectId: ?[]const u8 = null, - depth: u32 = 1, + depth: i32 = 1, pierce: bool = false, })) orelse return error.InvalidParams; - if (params.depth != 1 or params.pierce) return error.NotImplemented; + if (params.pierce) return error.NotImplemented; const bc = cmd.browser_context orelse return error.BrowserContextNotLoaded; const node = try getNode(cmd.arena, bc, params.nodeId, params.backendNodeId, params.objectId); From 745de2ede2cc702f04c6609073ab1209e4c3de25 Mon Sep 17 00:00:00 2001 From: Pierre Tachoire Date: Sat, 6 Sep 2025 20:03:03 +0200 Subject: [PATCH 07/12] cdp: add Runtime.getProperties --- src/cdp/domains/runtime.zig | 1 + 1 file changed, 1 insertion(+) diff --git a/src/cdp/domains/runtime.zig b/src/cdp/domains/runtime.zig index 707b5912..138155db 100644 --- a/src/cdp/domains/runtime.zig +++ b/src/cdp/domains/runtime.zig @@ -27,6 +27,7 @@ pub fn processMessage(cmd: anytype) !void { addBinding, callFunctionOn, releaseObject, + getProperties, }, cmd.input.action) orelse return error.UnknownMethod; switch (action) { From 49a27a67bcfe324ad66dc01f41532180effabeb5 Mon Sep 17 00:00:00 2001 From: Pierre Tachoire Date: Mon, 8 Sep 2025 11:40:18 +0200 Subject: [PATCH 08/12] cdp: send a warning for pierce parameter --- src/cdp/domains/dom.zig | 9 ++++++++- 1 file changed, 8 insertions(+), 1 deletion(-) diff --git a/src/cdp/domains/dom.zig b/src/cdp/domains/dom.zig index f50b6e87..57b3984a 100644 --- a/src/cdp/domains/dom.zig +++ b/src/cdp/domains/dom.zig @@ -17,6 +17,7 @@ // along with this program. If not, see . const std = @import("std"); +const log = @import("../../log.zig"); const Allocator = std.mem.Allocator; const Node = @import("../Node.zig"); const css = @import("../../browser/dom/css.zig"); @@ -69,6 +70,10 @@ fn getDocument(cmd: anytype) !void { }; const params = try cmd.params(Params) orelse Params{}; + if (params.pierce) { + log.warn(.cdp, "not implemented", .{ .feature = "DOM.getDocument: Not implemented pierce parameter" }); + } + const bc = cmd.browser_context orelse return error.BrowserContextNotLoaded; const page = bc.session.currentPage() orelse return error.PageNotLoaded; const doc = parser.documentHTMLToDocument(page.window.document); @@ -310,7 +315,9 @@ fn describeNode(cmd: anytype) !void { pierce: bool = false, })) orelse return error.InvalidParams; - if (params.pierce) return error.NotImplemented; + if (params.pierce) { + log.warn(.cdp, "not implemented", .{ .feature = "DOM.describeNode: Not implemented pierce parameter" }); + } const bc = cmd.browser_context orelse return error.BrowserContextNotLoaded; const node = try getNode(cmd.arena, bc, params.nodeId, params.backendNodeId, params.objectId); From 04487b6b9182c9393ae3fe82945484b4c03252a7 Mon Sep 17 00:00:00 2001 From: Pierre Tachoire Date: Mon, 8 Sep 2025 12:07:48 +0200 Subject: [PATCH 09/12] cdp: allow double isolated world with same world name In this case we reuse the existing isolated world and isolated context and we log a warning --- src/cdp/cdp.zig | 24 ++++++++++++++++++++++-- 1 file changed, 22 insertions(+), 2 deletions(-) diff --git a/src/cdp/cdp.zig b/src/cdp/cdp.zig index d8878bdc..6dec217b 100644 --- a/src/cdp/cdp.zig +++ b/src/cdp/cdp.zig @@ -428,7 +428,20 @@ pub fn BrowserContext(comptime CDP_T: type) type { pub fn createIsolatedWorld(self: *Self, world_name: []const u8, grant_universal_access: bool) !*IsolatedWorld { if (self.isolated_world != null) { - return error.CurrentlyOnly1IsolatedWorldSupported; + // if the two world have different names, be safe and return an + // error. + if (std.mem.eql(u8, self.isolated_world.?.name, world_name) == false) { + return error.CurrentlyOnly1IsolatedWorldSupported; + } + + // If the two worlds have the same name, reuse the existing one + // but send a warning. + log.warn(.cdp, "not implemented", .{ + .feature = "createIsolatedWorld: Not implemented second isolated world creation", + .info = "reuse existing isolated world with the same name", + .world_name = world_name, + }); + return &self.isolated_world.?; } var executor = try self.cdp.browser.env.newExecutionWorld(); @@ -682,7 +695,14 @@ const IsolatedWorld = struct { // This also means this pointer becomes invalid after removePage untill a new page is created. // Currently we have only 1 page/frame and thus also only 1 state in the isolate world. pub fn createContext(self: *IsolatedWorld, page: *Page) !void { - if (self.executor.js_context != null) return error.Only1IsolatedContextSupported; + // if (self.executor.js_context != null) return error.Only1IsolatedContextSupported; + if (self.executor.js_context != null) { + log.warn(.cdp, "not implemented", .{ + .feature = "createContext: Not implemented second isolated context creation", + .info = "reuse existing context", + }); + return; + } _ = try self.executor.createJsContext( &page.window, page, From e68ff62723e2831fa9e39a9ab6a44672f180efbf Mon Sep 17 00:00:00 2001 From: Pierre Tachoire Date: Mon, 8 Sep 2025 14:44:46 +0200 Subject: [PATCH 10/12] cdp: use depth param on DOM.describeNode --- src/cdp/domains/dom.zig | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/cdp/domains/dom.zig b/src/cdp/domains/dom.zig index 57b3984a..08564afa 100644 --- a/src/cdp/domains/dom.zig +++ b/src/cdp/domains/dom.zig @@ -322,7 +322,7 @@ fn describeNode(cmd: anytype) !void { const node = try getNode(cmd.arena, bc, params.nodeId, params.backendNodeId, params.objectId); - return cmd.sendResult(.{ .node = bc.nodeWriter(node, .{}) }, .{}); + return cmd.sendResult(.{ .node = bc.nodeWriter(node, .{ .depth = params.depth }) }, .{}); } // An array of quad vertices, x immediately followed by y for each point, points clock-wise. From 94fe34bd10fcc570ed124e814969fbdadf5f1c55 Mon Sep 17 00:00:00 2001 From: Pierre Tachoire Date: Tue, 9 Sep 2025 17:06:58 +0200 Subject: [PATCH 11/12] cdp: multiple isolated worlds --- src/cdp/cdp.zig | 42 +++++++++++++++++--------------------- src/cdp/domains/dom.zig | 13 ++++++++---- src/cdp/domains/page.zig | 14 +++++-------- src/cdp/domains/target.zig | 4 ++-- 4 files changed, 35 insertions(+), 38 deletions(-) diff --git a/src/cdp/cdp.zig b/src/cdp/cdp.zig index 6dec217b..3373d51d 100644 --- a/src/cdp/cdp.zig +++ b/src/cdp/cdp.zig @@ -331,7 +331,7 @@ pub fn BrowserContext(comptime CDP_T: type) type { node_search_list: Node.Search.List, inspector: Inspector, - isolated_world: ?IsolatedWorld, + isolated_worlds: std.ArrayListUnmanaged(IsolatedWorld), http_proxy_changed: bool = false, @@ -375,7 +375,7 @@ pub fn BrowserContext(comptime CDP_T: type) type { .page_life_cycle_events = false, // TODO; Target based value .node_registry = registry, .node_search_list = undefined, - .isolated_world = null, + .isolated_worlds = .empty, .inspector = inspector, .notification_arena = cdp.notification_arena.allocator(), .intercept_state = try InterceptState.init(allocator), @@ -404,9 +404,10 @@ pub fn BrowserContext(comptime CDP_T: type) type { // so we need to shutdown the page one first. self.cdp.browser.closeSession(); - if (self.isolated_world) |*world| { + for (self.isolated_worlds.items) |*world| { world.deinit(); } + self.isolated_worlds.clearRetainingCapacity(); self.node_registry.deinit(); self.node_search_list.deinit(); self.cdp.browser.notification.unregisterAll(self); @@ -427,32 +428,19 @@ pub fn BrowserContext(comptime CDP_T: type) type { } pub fn createIsolatedWorld(self: *Self, world_name: []const u8, grant_universal_access: bool) !*IsolatedWorld { - if (self.isolated_world != null) { - // if the two world have different names, be safe and return an - // error. - if (std.mem.eql(u8, self.isolated_world.?.name, world_name) == false) { - return error.CurrentlyOnly1IsolatedWorldSupported; - } - - // If the two worlds have the same name, reuse the existing one - // but send a warning. - log.warn(.cdp, "not implemented", .{ - .feature = "createIsolatedWorld: Not implemented second isolated world creation", - .info = "reuse existing isolated world with the same name", - .world_name = world_name, - }); - return &self.isolated_world.?; - } - var executor = try self.cdp.browser.env.newExecutionWorld(); errdefer executor.deinit(); - self.isolated_world = .{ - .name = try self.arena.dupe(u8, world_name), + const owned_name = try self.arena.dupe(u8, world_name); + const world = try self.isolated_worlds.addOne(self.arena); + + world.* = .{ + .name = owned_name, .executor = executor, .grant_universal_access = grant_universal_access, }; - return &self.isolated_world.?; + + return world; } pub fn nodeWriter(self: *Self, root: *const Node, opts: Node.Writer.Opts) Node.Writer { @@ -711,6 +699,14 @@ const IsolatedWorld = struct { Env.GlobalMissingCallback.init(&self.polyfill_loader), ); } + + pub fn createContextAndLoadPolyfills(self: *IsolatedWorld, arena: Allocator, page: *Page) !void { + // We need to recreate the isolated world context + try self.createContext(page); + + const loader = @import("../browser/polyfill/polyfill.zig"); + try loader.preload(arena, &self.executor.js_context.?); + } }; // This is a generic because when we send a result we have two different diff --git a/src/cdp/domains/dom.zig b/src/cdp/domains/dom.zig index 08564afa..fdb5dd13 100644 --- a/src/cdp/domains/dom.zig +++ b/src/cdp/domains/dom.zig @@ -277,10 +277,15 @@ fn resolveNode(cmd: anytype) !void { var js_context = page.main_context; if (params.executionContextId) |context_id| { if (js_context.v8_context.debugContextId() != context_id) { - var isolated_world = bc.isolated_world orelse return error.ContextNotFound; - js_context = &(isolated_world.executor.js_context orelse return error.ContextNotFound); - - if (js_context.v8_context.debugContextId() != context_id) return error.ContextNotFound; + var found = false; + for (bc.isolated_worlds.items) |*isolated_world| { + js_context = &(isolated_world.executor.js_context orelse return error.ContextNotFound); + if (js_context.v8_context.debugContextId() == context_id) { + found = true; + break; + } + } + if (!found) return error.ContextNotFound; } } diff --git a/src/cdp/domains/page.zig b/src/cdp/domains/page.zig index 4495a474..978ae7a8 100644 --- a/src/cdp/domains/page.zig +++ b/src/cdp/domains/page.zig @@ -122,7 +122,7 @@ fn createIsolatedWorld(cmd: anytype) !void { const world = try bc.createIsolatedWorld(params.worldName, params.grantUniveralAccess); const page = bc.session.currentPage() orelse return error.PageNotLoaded; - try pageCreated(bc, page); + try world.createContextAndLoadPolyfills(bc.arena, page); const js_context = &world.executor.js_context.?; // Create the auxdata json for the contextCreated event @@ -259,7 +259,7 @@ pub fn pageNavigate(arena: Allocator, bc: anytype, event: *const Notification.Pa true, ); } - if (bc.isolated_world) |*isolated_world| { + for (bc.isolated_worlds.items) |*isolated_world| { const aux_json = try std.fmt.allocPrint(arena, "{{\"isDefault\":false,\"type\":\"isolated\",\"frameId\":\"{s}\"}}", .{target_id}); // Calling contextCreated will assign a new Id to the context and send the contextCreated event bc.inspector.contextCreated( @@ -274,18 +274,14 @@ pub fn pageNavigate(arena: Allocator, bc: anytype, event: *const Notification.Pa pub fn pageRemove(bc: anytype) !void { // The main page is going to be removed, we need to remove contexts from other worlds first. - if (bc.isolated_world) |*isolated_world| { + for (bc.isolated_worlds.items) |*isolated_world| { try isolated_world.removeContext(); } } pub fn pageCreated(bc: anytype, page: *Page) !void { - if (bc.isolated_world) |*isolated_world| { - // We need to recreate the isolated world context - try isolated_world.createContext(page); - - const polyfill = @import("../../browser/polyfill/polyfill.zig"); - try polyfill.preload(bc.arena, &isolated_world.executor.js_context.?); + for (bc.isolated_worlds.items) |*isolated_world| { + try isolated_world.createContextAndLoadPolyfills(bc.arena, page); } } diff --git a/src/cdp/domains/target.zig b/src/cdp/domains/target.zig index 0f55bb74..b3b839ad 100644 --- a/src/cdp/domains/target.zig +++ b/src/cdp/domains/target.zig @@ -241,10 +241,10 @@ fn closeTarget(cmd: anytype) !void { } bc.session.removePage(); - if (bc.isolated_world) |*world| { + for (bc.isolated_worlds.items) |*world| { world.deinit(); - bc.isolated_world = null; } + bc.isolated_worlds.clearRetainingCapacity(); bc.target_id = null; } From 5d1e17c598829576a0d05042b40c728ef5a8140c Mon Sep 17 00:00:00 2001 From: Pierre Tachoire Date: Wed, 10 Sep 2025 11:29:08 +0200 Subject: [PATCH 12/12] cdp: use for...else instead of found bool --- src/cdp/domains/dom.zig | 5 +---- 1 file changed, 1 insertion(+), 4 deletions(-) diff --git a/src/cdp/domains/dom.zig b/src/cdp/domains/dom.zig index fdb5dd13..035918e8 100644 --- a/src/cdp/domains/dom.zig +++ b/src/cdp/domains/dom.zig @@ -277,15 +277,12 @@ fn resolveNode(cmd: anytype) !void { var js_context = page.main_context; if (params.executionContextId) |context_id| { if (js_context.v8_context.debugContextId() != context_id) { - var found = false; for (bc.isolated_worlds.items) |*isolated_world| { js_context = &(isolated_world.executor.js_context orelse return error.ContextNotFound); if (js_context.v8_context.debugContextId() == context_id) { - found = true; break; } - } - if (!found) return error.ContextNotFound; + } else return error.ContextNotFound; } }