Skip to content

Commit 94fe34b

Browse files
committed
cdp: multiple isolated worlds
1 parent e68ff62 commit 94fe34b

File tree

4 files changed

+35
-38
lines changed

4 files changed

+35
-38
lines changed

src/cdp/cdp.zig

Lines changed: 19 additions & 23 deletions
Original file line numberDiff line numberDiff line change
@@ -331,7 +331,7 @@ pub fn BrowserContext(comptime CDP_T: type) type {
331331
node_search_list: Node.Search.List,
332332

333333
inspector: Inspector,
334-
isolated_world: ?IsolatedWorld,
334+
isolated_worlds: std.ArrayListUnmanaged(IsolatedWorld),
335335

336336
http_proxy_changed: bool = false,
337337

@@ -375,7 +375,7 @@ pub fn BrowserContext(comptime CDP_T: type) type {
375375
.page_life_cycle_events = false, // TODO; Target based value
376376
.node_registry = registry,
377377
.node_search_list = undefined,
378-
.isolated_world = null,
378+
.isolated_worlds = .empty,
379379
.inspector = inspector,
380380
.notification_arena = cdp.notification_arena.allocator(),
381381
.intercept_state = try InterceptState.init(allocator),
@@ -404,9 +404,10 @@ pub fn BrowserContext(comptime CDP_T: type) type {
404404
// so we need to shutdown the page one first.
405405
self.cdp.browser.closeSession();
406406

407-
if (self.isolated_world) |*world| {
407+
for (self.isolated_worlds.items) |*world| {
408408
world.deinit();
409409
}
410+
self.isolated_worlds.clearRetainingCapacity();
410411
self.node_registry.deinit();
411412
self.node_search_list.deinit();
412413
self.cdp.browser.notification.unregisterAll(self);
@@ -427,32 +428,19 @@ pub fn BrowserContext(comptime CDP_T: type) type {
427428
}
428429

429430
pub fn createIsolatedWorld(self: *Self, world_name: []const u8, grant_universal_access: bool) !*IsolatedWorld {
430-
if (self.isolated_world != null) {
431-
// if the two world have different names, be safe and return an
432-
// error.
433-
if (std.mem.eql(u8, self.isolated_world.?.name, world_name) == false) {
434-
return error.CurrentlyOnly1IsolatedWorldSupported;
435-
}
436-
437-
// If the two worlds have the same name, reuse the existing one
438-
// but send a warning.
439-
log.warn(.cdp, "not implemented", .{
440-
.feature = "createIsolatedWorld: Not implemented second isolated world creation",
441-
.info = "reuse existing isolated world with the same name",
442-
.world_name = world_name,
443-
});
444-
return &self.isolated_world.?;
445-
}
446-
447431
var executor = try self.cdp.browser.env.newExecutionWorld();
448432
errdefer executor.deinit();
449433

450-
self.isolated_world = .{
451-
.name = try self.arena.dupe(u8, world_name),
434+
const owned_name = try self.arena.dupe(u8, world_name);
435+
const world = try self.isolated_worlds.addOne(self.arena);
436+
437+
world.* = .{
438+
.name = owned_name,
452439
.executor = executor,
453440
.grant_universal_access = grant_universal_access,
454441
};
455-
return &self.isolated_world.?;
442+
443+
return world;
456444
}
457445

458446
pub fn nodeWriter(self: *Self, root: *const Node, opts: Node.Writer.Opts) Node.Writer {
@@ -711,6 +699,14 @@ const IsolatedWorld = struct {
711699
Env.GlobalMissingCallback.init(&self.polyfill_loader),
712700
);
713701
}
702+
703+
pub fn createContextAndLoadPolyfills(self: *IsolatedWorld, arena: Allocator, page: *Page) !void {
704+
// We need to recreate the isolated world context
705+
try self.createContext(page);
706+
707+
const loader = @import("../browser/polyfill/polyfill.zig");
708+
try loader.preload(arena, &self.executor.js_context.?);
709+
}
714710
};
715711

716712
// This is a generic because when we send a result we have two different

src/cdp/domains/dom.zig

Lines changed: 9 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -277,10 +277,15 @@ fn resolveNode(cmd: anytype) !void {
277277
var js_context = page.main_context;
278278
if (params.executionContextId) |context_id| {
279279
if (js_context.v8_context.debugContextId() != context_id) {
280-
var isolated_world = bc.isolated_world orelse return error.ContextNotFound;
281-
js_context = &(isolated_world.executor.js_context orelse return error.ContextNotFound);
282-
283-
if (js_context.v8_context.debugContextId() != context_id) return error.ContextNotFound;
280+
var found = false;
281+
for (bc.isolated_worlds.items) |*isolated_world| {
282+
js_context = &(isolated_world.executor.js_context orelse return error.ContextNotFound);
283+
if (js_context.v8_context.debugContextId() == context_id) {
284+
found = true;
285+
break;
286+
}
287+
}
288+
if (!found) return error.ContextNotFound;
284289
}
285290
}
286291

src/cdp/domains/page.zig

Lines changed: 5 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -122,7 +122,7 @@ fn createIsolatedWorld(cmd: anytype) !void {
122122

123123
const world = try bc.createIsolatedWorld(params.worldName, params.grantUniveralAccess);
124124
const page = bc.session.currentPage() orelse return error.PageNotLoaded;
125-
try pageCreated(bc, page);
125+
try world.createContextAndLoadPolyfills(bc.arena, page);
126126
const js_context = &world.executor.js_context.?;
127127

128128
// Create the auxdata json for the contextCreated event
@@ -259,7 +259,7 @@ pub fn pageNavigate(arena: Allocator, bc: anytype, event: *const Notification.Pa
259259
true,
260260
);
261261
}
262-
if (bc.isolated_world) |*isolated_world| {
262+
for (bc.isolated_worlds.items) |*isolated_world| {
263263
const aux_json = try std.fmt.allocPrint(arena, "{{\"isDefault\":false,\"type\":\"isolated\",\"frameId\":\"{s}\"}}", .{target_id});
264264
// Calling contextCreated will assign a new Id to the context and send the contextCreated event
265265
bc.inspector.contextCreated(
@@ -274,18 +274,14 @@ pub fn pageNavigate(arena: Allocator, bc: anytype, event: *const Notification.Pa
274274

275275
pub fn pageRemove(bc: anytype) !void {
276276
// The main page is going to be removed, we need to remove contexts from other worlds first.
277-
if (bc.isolated_world) |*isolated_world| {
277+
for (bc.isolated_worlds.items) |*isolated_world| {
278278
try isolated_world.removeContext();
279279
}
280280
}
281281

282282
pub fn pageCreated(bc: anytype, page: *Page) !void {
283-
if (bc.isolated_world) |*isolated_world| {
284-
// We need to recreate the isolated world context
285-
try isolated_world.createContext(page);
286-
287-
const polyfill = @import("../../browser/polyfill/polyfill.zig");
288-
try polyfill.preload(bc.arena, &isolated_world.executor.js_context.?);
283+
for (bc.isolated_worlds.items) |*isolated_world| {
284+
try isolated_world.createContextAndLoadPolyfills(bc.arena, page);
289285
}
290286
}
291287

src/cdp/domains/target.zig

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -241,10 +241,10 @@ fn closeTarget(cmd: anytype) !void {
241241
}
242242

243243
bc.session.removePage();
244-
if (bc.isolated_world) |*world| {
244+
for (bc.isolated_worlds.items) |*world| {
245245
world.deinit();
246-
bc.isolated_world = null;
247246
}
247+
bc.isolated_worlds.clearRetainingCapacity();
248248
bc.target_id = null;
249249
}
250250

0 commit comments

Comments
 (0)