From 193e012aa6a7da63bafc1cf779a31b4d42d7eb59 Mon Sep 17 00:00:00 2001 From: sjorsdonkers <72333389+sjorsdonkers@users.noreply.github.com> Date: Wed, 21 May 2025 13:58:42 +0200 Subject: [PATCH] Rename to ExecutionWorlds --- src/browser/session.zig | 4 ++-- src/cdp/cdp.zig | 14 +++++--------- src/cdp/domains/dom.zig | 4 ++-- src/cdp/domains/page.zig | 6 +++--- src/runtime/js.zig | 35 +++++++++++++++++++---------------- src/runtime/testing.zig | 4 ++-- src/testing.zig | 4 ++-- 7 files changed, 35 insertions(+), 36 deletions(-) diff --git a/src/browser/session.zig b/src/browser/session.zig index ddcc138e..972bff81 100644 --- a/src/browser/session.zig +++ b/src/browser/session.zig @@ -49,14 +49,14 @@ pub const Session = struct { // page and start another. transfer_arena: Allocator, - executor: Env.Executor, + executor: Env.ExecutionWorld, storage_shed: storage.Shed, cookie_jar: storage.CookieJar, page: ?Page = null, pub fn init(self: *Session, browser: *Browser) !void { - var executor = try browser.env.newExecutor(); + var executor = try browser.env.newExecutionWorld(); errdefer executor.deinit(); const allocator = browser.app.allocator; diff --git a/src/cdp/cdp.zig b/src/cdp/cdp.zig index 66980723..ef8377f8 100644 --- a/src/cdp/cdp.zig +++ b/src/cdp/cdp.zig @@ -372,12 +372,11 @@ pub fn BrowserContext(comptime CDP_T: type) type { return error.CurrentlyOnly1IsolatedWorldSupported; } - var executor = try self.cdp.browser.env.newExecutor(); + var executor = try self.cdp.browser.env.newExecutionWorld(); errdefer executor.deinit(); self.isolated_world = .{ .name = try self.arena.dupe(u8, world_name), - .scope = null, .executor = executor, .grant_universal_access = grant_universal_access, }; @@ -511,18 +510,15 @@ pub fn BrowserContext(comptime CDP_T: type) type { /// An object id is unique across all contexts, different object ids can refer to the same Node in different contexts. const IsolatedWorld = struct { name: []const u8, - scope: ?*Env.Scope, - executor: Env.Executor, + executor: Env.ExecutionWorld, grant_universal_access: bool, pub fn deinit(self: *IsolatedWorld) void { self.executor.deinit(); - self.scope = null; } pub fn removeContext(self: *IsolatedWorld) !void { - if (self.scope == null) return error.NoIsolatedContextToRemove; + if (self.executor.scope == null) return error.NoIsolatedContextToRemove; self.executor.endScope(); - self.scope = null; } // The isolate world must share at least some of the state with the related page, specifically the DocumentHTML @@ -531,8 +527,8 @@ 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.scope != null) return error.Only1IsolatedContextSupported; - self.scope = try self.executor.startScope(&page.window, &page.state, {}, false); + if (self.executor.scope != null) return error.Only1IsolatedContextSupported; + _ = try self.executor.startScope(&page.window, &page.state, {}, false); } }; diff --git a/src/cdp/domains/dom.zig b/src/cdp/domains/dom.zig index 14b89343..53d8e19a 100644 --- a/src/cdp/domains/dom.zig +++ b/src/cdp/domains/dom.zig @@ -262,8 +262,8 @@ fn resolveNode(cmd: anytype) !void { var scope = page.scope; if (params.executionContextId) |context_id| { if (scope.context.debugContextId() != context_id) { - const isolated_world = bc.isolated_world orelse return error.ContextNotFound; - scope = isolated_world.scope orelse return error.ContextNotFound; + var isolated_world = bc.isolated_world orelse return error.ContextNotFound; + scope = &(isolated_world.executor.scope orelse return error.ContextNotFound); if (scope.context.debugContextId() != context_id) return error.ContextNotFound; } diff --git a/src/cdp/domains/page.zig b/src/cdp/domains/page.zig index 75e10695..6ec1a1b1 100644 --- a/src/cdp/domains/page.zig +++ b/src/cdp/domains/page.zig @@ -115,7 +115,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); - const scope = world.scope.?; + const scope = &world.executor.scope.?; // Create the auxdata json for the contextCreated event // Calling contextCreated will assign a Id to the context and send the contextCreated event @@ -236,7 +236,7 @@ pub fn pageNavigate(bc: anytype, event: *const Notification.PageNavigate) !void const aux_json = try std.fmt.bufPrint(&buffer, "{{\"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( - isolated_world.scope.?, + &isolated_world.executor.scope.?, isolated_world.name, "://", aux_json, @@ -258,7 +258,7 @@ pub fn pageCreated(bc: anytype, page: *Page) !void { try isolated_world.createContext(page); const polyfill = @import("../../browser/polyfill/polyfill.zig"); - try polyfill.load(bc.arena, isolated_world.scope.?); + try polyfill.load(bc.arena, &isolated_world.executor.scope.?); } } diff --git a/src/runtime/js.zig b/src/runtime/js.zig index 51960b10..37fe113e 100644 --- a/src/runtime/js.zig +++ b/src/runtime/js.zig @@ -53,8 +53,8 @@ pub const Platform = struct { // The Env maps to a V8 isolate, which represents a isolated sandbox for // executing JavaScript. The Env is where we'll define our V8 <-> Zig bindings, -// and it's where we'll start Executors, which actually execute JavaScript. -// The `S` parameter is arbitrary state. When we start an Executor, an instance +// and it's where we'll start ExecutionWorlds, which actually execute JavaScript. +// The `S` parameter is arbitrary state. When we start an ExecutionWorld, an instance // of S must be given. This instance is available to any Zig binding. // The `types` parameter is a tuple of Zig structures we want to bind to V8. pub fn Env(comptime State: type, comptime WebApis: type) type { @@ -259,7 +259,7 @@ pub fn Env(comptime State: type, comptime WebApis: type) type { self.isolate.performMicrotasksCheckpoint(); } - pub fn newExecutor(self: *Self) !Executor { + pub fn newExecutionWorld(self: *Self) !ExecutionWorld { return .{ .env = self, .scope = null, @@ -280,32 +280,35 @@ pub fn Env(comptime State: type, comptime WebApis: type) type { self.isolate.lowMemoryNotification(); } - pub const Executor = struct { + // ExecutionWorld closely models a JS World. + // https://chromium.googlesource.com/chromium/src/+/master/third_party/blink/renderer/bindings/core/v8/V8BindingDesign.md#World + // https://developer.mozilla.org/en-US/docs/Mozilla/Add-ons/WebExtensions/API/scripting/ExecutionWorld + pub const ExecutionWorld = struct { env: *Self, // Arena whose lifetime is for a single getter/setter/function/etc. // Largely used to get strings out of V8, like a stack trace from // a TryCatch. The allocator will be owned by the Scope, but the - // arena itself is owned by the Executor so that we can re-use it + // arena itself is owned by the ExecutionWorld so that we can re-use it // from scope to scope. call_arena: ArenaAllocator, // Arena whose lifetime is for a single page load, aka a Scope. Where // the call_arena lives for a single function call, the scope_arena // lives for the lifetime of the entire page. The allocator will be - // owned by the Scope, but the arena itself is owned by the Executor + // owned by the Scope, but the arena itself is owned by the ExecutionWorld // so that we can re-use it from scope to scope. scope_arena: ArenaAllocator, // A Scope maps to a Browser's Page. Here though, it's only a - // mechanism to organization page-specific memory. The Executor + // mechanism to organization page-specific memory. The ExecutionWorld // does all the work, but having all page-specific data structures // grouped together helps keep things clean. scope: ?Scope = null, - // no init, must be initialized via env.newExecutor() + // no init, must be initialized via env.newExecutionWorld() - pub fn deinit(self: *Executor) void { + pub fn deinit(self: *ExecutionWorld) void { if (self.scope != null) { self.endScope(); } @@ -320,7 +323,7 @@ pub fn Env(comptime State: type, comptime WebApis: type) type { // when the handle_scope is freed. // We also maintain our own "scope_arena" which allows us to have // all page related memory easily managed. - pub fn startScope(self: *Executor, global: anytype, state: State, module_loader: anytype, enter: bool) !*Scope { + pub fn startScope(self: *ExecutionWorld, global: anytype, state: State, module_loader: anytype, enter: bool) !*Scope { std.debug.assert(self.scope == null); const ModuleLoader = switch (@typeInfo(@TypeOf(module_loader))) { @@ -338,9 +341,9 @@ pub fn Env(comptime State: type, comptime WebApis: type) type { const Global = @TypeOf(global.*); var context: v8.Context = blk: { - var handle_scope: v8.HandleScope = undefined; - v8.HandleScope.init(&handle_scope, isolate); - defer handle_scope.deinit(); + var temp_scope: v8.HandleScope = undefined; + v8.HandleScope.init(&temp_scope, isolate); + defer temp_scope.deinit(); const js_global = v8.FunctionTemplate.initDefault(isolate); attachClass(Global, isolate, js_global); @@ -466,7 +469,7 @@ pub fn Env(comptime State: type, comptime WebApis: type) type { return scope; } - pub fn endScope(self: *Executor) void { + pub fn endScope(self: *ExecutionWorld) void { self.scope.?.deinit(); self.scope = null; _ = self.scope_arena.reset(.{ .retain_with_limit = SCOPE_ARENA_RETAIN }); @@ -1517,7 +1520,7 @@ pub fn Env(comptime State: type, comptime WebApis: type) type { } // Retrieves the RemoteObject for a given value. - // The value is loaded through the Executor's mapZigInstanceToJs function, + // The value is loaded through the ExecutionWorld's mapZigInstanceToJs function, // just like a method return value. Therefore, if we've mapped this // value before, we'll get the existing JS PersistedObject and if not // we'll create it and track it for cleanup when the scope ends. @@ -2198,7 +2201,7 @@ fn isEmpty(comptime T: type) bool { } // Responsible for calling Zig functions from JS invokations. This could -// probably just contained in Executor, but having this specific logic, which +// probably just contained in ExecutionWorld, but having this specific logic, which // is somewhat repetitive between constructors, functions, getters, etc contained // here does feel like it makes it clenaer. fn Caller(comptime E: type, comptime State: type) type { diff --git a/src/runtime/testing.zig b/src/runtime/testing.zig index abd5768a..c51298c0 100644 --- a/src/runtime/testing.zig +++ b/src/runtime/testing.zig @@ -30,7 +30,7 @@ pub fn Runner(comptime State: type, comptime Global: type, comptime types: anyty return struct { env: *Env, scope: *Env.Scope, - executor: Env.Executor, + executor: Env.ExecutionWorld, pub const Env = js.Env(State, struct { pub const Interfaces = AdjustedTypes; @@ -45,7 +45,7 @@ pub fn Runner(comptime State: type, comptime Global: type, comptime types: anyty self.env = try Env.init(allocator, .{}); errdefer self.env.deinit(); - self.executor = try self.env.newExecutor(); + self.executor = try self.env.newExecutionWorld(); errdefer self.executor.deinit(); self.scope = try self.executor.startScope( diff --git a/src/testing.zig b/src/testing.zig index 7db16d65..72692489 100644 --- a/src/testing.zig +++ b/src/testing.zig @@ -383,7 +383,7 @@ pub const JsRunner = struct { renderer: Renderer, http_client: HttpClient, scope: *Env.Scope, - executor: Env.Executor, + executor: Env.ExecutionWorld, storage_shelf: storage.Shelf, cookie_jar: storage.CookieJar, @@ -435,7 +435,7 @@ pub const JsRunner = struct { .tls_verify_host = false, }); - self.executor = try self.env.newExecutor(); + self.executor = try self.env.newExecutionWorld(); errdefer self.executor.deinit(); self.scope = try self.executor.startScope(&self.window, &self.state, {}, true);