Merge branch 'main' into css_style_declaration

This commit is contained in:
Raph
2025-05-24 02:00:33 +02:00
18 changed files with 83 additions and 90 deletions

View File

@@ -17,7 +17,7 @@ inputs:
zig-v8: zig-v8:
description: 'zig v8 version to install' description: 'zig v8 version to install'
required: false required: false
default: 'v0.1.23' default: 'v0.1.24'
v8: v8:
description: 'v8 version to install' description: 'v8 version to install'
required: false required: false
@@ -59,11 +59,11 @@ runs:
- name: install v8 - name: install v8
shell: bash shell: bash
run: | run: |
mkdir -p v8/out/debug/obj/zig/ mkdir -p v8/out/${{ inputs.os }}/debug/obj/zig/
ln -s ${{ inputs.cache-dir }}/v8/libc_v8.a v8/out/debug/obj/zig/libc_v8.a ln -s ${{ inputs.cache-dir }}/v8/libc_v8.a v8/out/${{ inputs.os }}/debug/obj/zig/libc_v8.a
mkdir -p v8/out/release/obj/zig/ mkdir -p v8/out/${{ inputs.os }}/release/obj/zig/
ln -s ${{ inputs.cache-dir }}/v8/libc_v8.a v8/out/release/obj/zig/libc_v8.a ln -s ${{ inputs.cache-dir }}/v8/libc_v8.a v8/out/${{ inputs.os }}/release/obj/zig/libc_v8.a
- name: libiconv - name: libiconv
shell: bash shell: bash

View File

@@ -88,7 +88,7 @@ jobs:
- name: run puppeteer - name: run puppeteer
run: | run: |
python3 -m http.server 1234 -d ./public & echo $! > PYTHON.pid python3 -m http.server 1234 -d ./public & echo $! > PYTHON.pid
./lightpanda serve --gc_hints & echo $! > LPD.pid ./lightpanda serve & echo $! > LPD.pid
RUNS=100 npm run bench-puppeteer-cdp > puppeteer.out || exit 1 RUNS=100 npm run bench-puppeteer-cdp > puppeteer.out || exit 1
cat /proc/`cat LPD.pid`/status |grep VmHWM|grep -oP '\d+' > LPD.VmHWM cat /proc/`cat LPD.pid`/status |grep VmHWM|grep -oP '\d+' > LPD.VmHWM
kill `cat LPD.pid` `cat PYTHON.pid` kill `cat LPD.pid` `cat PYTHON.pid`

View File

@@ -5,7 +5,7 @@ ARG ZIG=0.14.0
ARG ZIG_MINISIG=RWSGOq2NVecA2UPNdBUZykf1CCb147pkmdtYxgb3Ti+JO/wCYvhbAb/U ARG ZIG_MINISIG=RWSGOq2NVecA2UPNdBUZykf1CCb147pkmdtYxgb3Ti+JO/wCYvhbAb/U
ARG ARCH=x86_64 ARG ARCH=x86_64
ARG V8=11.1.134 ARG V8=11.1.134
ARG ZIG_V8=v0.1.23 ARG ZIG_V8=v0.1.24
RUN apt-get update -yq && \ RUN apt-get update -yq && \
apt-get install -yq xz-utils \ apt-get install -yq xz-utils \
@@ -57,8 +57,8 @@ RUN make install-libiconv && \
# download and install v8 # download and install v8
RUN curl --fail -L -o libc_v8.a https://github.com/lightpanda-io/zig-v8-fork/releases/download/${ZIG_V8}/libc_v8_${V8}_linux_${ARCH}.a && \ RUN curl --fail -L -o libc_v8.a https://github.com/lightpanda-io/zig-v8-fork/releases/download/${ZIG_V8}/libc_v8_${V8}_linux_${ARCH}.a && \
mkdir -p v8/build/${ARCH}-linux/release/ninja/obj/zig/ && \ mkdir -p v8/out/linux/release/obj/zig/ && \
mv libc_v8.a v8/build/${ARCH}-linux/release/ninja/obj/zig/libc_v8.a mv libc_v8.a v8/out/linux/release/obj/zig/libc_v8.a
# build release # build release
RUN make build RUN make build

View File

@@ -69,14 +69,19 @@ build:
## Build in debug mode ## Build in debug mode
build-dev: build-dev:
@printf "\e[36mBuilding (debug)...\e[0m\n" @printf "\e[36mBuilding (debug)...\e[0m\n"
@$(ZIG) build -Dgit_commit=$$(git rev-parse --short HEAD) || (printf "\e[33mBuild ERROR\e[0m\n"; exit 1;) @$(ZIG) build -Dgit_commit=$$(git rev-parse --short HEAD) -Dlog_level=debug || (printf "\e[33mBuild ERROR\e[0m\n"; exit 1;)
@printf "\e[33mBuild OK\e[0m\n" @printf "\e[33mBuild OK\e[0m\n"
## Run the server in debug mode ## Run the server in release mode
run: build run: build
@printf "\e[36mRunning...\e[0m\n" @printf "\e[36mRunning...\e[0m\n"
@./zig-out/bin/lightpanda || (printf "\e[33mRun ERROR\e[0m\n"; exit 1;) @./zig-out/bin/lightpanda || (printf "\e[33mRun ERROR\e[0m\n"; exit 1;)
## Run the server in debug mode
run-debug: build-dev
@printf "\e[36mRunning...\e[0m\n"
@./zig-out/bin/lightpanda || (printf "\e[33mRun ERROR\e[0m\n"; exit 1;)
## Run a JS shell in debug mode ## Run a JS shell in debug mode
shell: shell:
@printf "\e[36mBuilding shell...\e[0m\n" @printf "\e[36mBuilding shell...\e[0m\n"

View File

@@ -164,7 +164,7 @@ For Debian/Ubuntu based Linux:
sudo apt install xz-utils \ sudo apt install xz-utils \
python3 ca-certificates git \ python3 ca-certificates git \
pkg-config libglib2.0-dev \ pkg-config libglib2.0-dev \
gperf libexpat1-dev unzip \ gperf libexpat1-dev unzip rsync \
cmake clang cmake clang
``` ```

View File

@@ -170,13 +170,30 @@ fn common(b: *std.Build, opts: *std.Build.Step.Options, step: *std.Build.Step.Co
mod.addImport("v8", v8_mod); mod.addImport("v8", v8_mod);
} }
const lib_path = try std.fmt.allocPrint(
mod.owner.allocator,
"v8/out/{s}/obj/zig/libc_v8.a",
.{if (mod.optimize.? == .Debug) "debug" else "release"},
);
mod.link_libcpp = true; mod.link_libcpp = true;
mod.addObjectFile(mod.owner.path(lib_path));
{
const release_dir = if (mod.optimize.? == .Debug) "debug" else "release";
const os = switch (target.result.os.tag) {
.linux => "linux",
.macos => "macos",
else => return error.UnsupportedPlatform,
};
var lib_path = try std.fmt.allocPrint(
mod.owner.allocator,
"v8/out/{s}/{s}/obj/zig/libc_v8.a",
.{ os, release_dir },
);
std.fs.cwd().access(lib_path, .{}) catch {
// legacy path
lib_path = try std.fmt.allocPrint(
mod.owner.allocator,
"v8/out/{s}/obj/zig/libc_v8.a",
.{release_dir},
);
};
mod.addObjectFile(mod.owner.path(lib_path));
}
switch (target.result.os.tag) { switch (target.result.os.tag) {
.macos => { .macos => {
@@ -188,7 +205,6 @@ fn common(b: *std.Build, opts: *std.Build.Step.Options, step: *std.Build.Step.Co
} }
mod.addImport("build_config", opts.createModule()); mod.addImport("build_config", opts.createModule());
mod.addObjectFile(mod.owner.path(lib_path));
} }
fn moduleNetSurf(b: *std.Build, step: *std.Build.Step.Compile, target: std.Build.ResolvedTarget) !void { fn moduleNetSurf(b: *std.Build, step: *std.Build.Step.Compile, target: std.Build.ResolvedTarget) !void {

View File

@@ -13,8 +13,8 @@
.hash = "tigerbeetle_io-0.0.0-ViLgxpyRBAB5BMfIcj3KMXfbJzwARs9uSl8aRy2OXULd", .hash = "tigerbeetle_io-0.0.0-ViLgxpyRBAB5BMfIcj3KMXfbJzwARs9uSl8aRy2OXULd",
}, },
.v8 = .{ .v8 = .{
.url = "https://github.com/lightpanda-io/zig-v8-fork/archive/240140e5b3e5a8e5e51cbdd36bc120bf28ae5c31.tar.gz", .url = "https://github.com/lightpanda-io/zig-v8-fork/archive/e38cb27ddb044c6afbf8a938b293721b9804405e.tar.gz",
.hash = "v8-0.0.0-xddH64eyAwBcX7e2x5tv9MhT0MgQbshP2rb19blo06Db", .hash = "v8-0.0.0-xddH6_GzAwCaz83JWuw3sepOGq0I7C_CmfOwA1Gb9q3y",
}, },
//.v8 = .{ .path = "../zig-v8-fork" }, //.v8 = .{ .path = "../zig-v8-fork" },
//.tigerbeetle_io = .{ .path = "../tigerbeetle-io" }, //.tigerbeetle_io = .{ .path = "../tigerbeetle-io" },

View File

@@ -28,7 +28,6 @@ pub const App = struct {
pub const Config = struct { pub const Config = struct {
run_mode: RunMode, run_mode: RunMode,
gc_hints: bool = false,
tls_verify_host: bool = true, tls_verify_host: bool = true,
http_proxy: ?std.Uri = null, http_proxy: ?std.Uri = null,
}; };

View File

@@ -86,9 +86,7 @@ pub const Browser = struct {
session.deinit(); session.deinit();
self.session = null; self.session = null;
_ = self.session_arena.reset(.{ .retain_with_limit = 1 * 1024 * 1024 }); _ = self.session_arena.reset(.{ .retain_with_limit = 1 * 1024 * 1024 });
if (self.app.config.gc_hints) { self.env.lowMemoryNotification();
self.env.lowMemoryNotification();
}
} }
} }

View File

@@ -49,14 +49,14 @@ pub const Session = struct {
// page and start another. // page and start another.
transfer_arena: Allocator, transfer_arena: Allocator,
executor: Env.Executor, executor: Env.ExecutionWorld,
storage_shed: storage.Shed, storage_shed: storage.Shed,
cookie_jar: storage.CookieJar, cookie_jar: storage.CookieJar,
page: ?Page = null, page: ?Page = null,
pub fn init(self: *Session, browser: *Browser) !void { pub fn init(self: *Session, browser: *Browser) !void {
var executor = try browser.env.newExecutor(); var executor = try browser.env.newExecutionWorld();
errdefer executor.deinit(); errdefer executor.deinit();
const allocator = browser.app.allocator; const allocator = browser.app.allocator;

View File

@@ -372,12 +372,11 @@ pub fn BrowserContext(comptime CDP_T: type) type {
return error.CurrentlyOnly1IsolatedWorldSupported; return error.CurrentlyOnly1IsolatedWorldSupported;
} }
var executor = try self.cdp.browser.env.newExecutor(); var executor = try self.cdp.browser.env.newExecutionWorld();
errdefer executor.deinit(); errdefer executor.deinit();
self.isolated_world = .{ self.isolated_world = .{
.name = try self.arena.dupe(u8, world_name), .name = try self.arena.dupe(u8, world_name),
.scope = null,
.executor = executor, .executor = executor,
.grant_universal_access = grant_universal_access, .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. /// An object id is unique across all contexts, different object ids can refer to the same Node in different contexts.
const IsolatedWorld = struct { const IsolatedWorld = struct {
name: []const u8, name: []const u8,
scope: ?*Env.Scope, executor: Env.ExecutionWorld,
executor: Env.Executor,
grant_universal_access: bool, grant_universal_access: bool,
pub fn deinit(self: *IsolatedWorld) void { pub fn deinit(self: *IsolatedWorld) void {
self.executor.deinit(); self.executor.deinit();
self.scope = null;
} }
pub fn removeContext(self: *IsolatedWorld) !void { 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.executor.endScope();
self.scope = null;
} }
// The isolate world must share at least some of the state with the related page, specifically the DocumentHTML // 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. // 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. // 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 { pub fn createContext(self: *IsolatedWorld, page: *Page) !void {
if (self.scope != null) return error.Only1IsolatedContextSupported; if (self.executor.scope != null) return error.Only1IsolatedContextSupported;
self.scope = try self.executor.startScope(&page.window, &page.state, {}, false); _ = try self.executor.startScope(&page.window, &page.state, {}, false);
} }
}; };

View File

@@ -262,8 +262,8 @@ fn resolveNode(cmd: anytype) !void {
var scope = page.scope; var scope = page.scope;
if (params.executionContextId) |context_id| { if (params.executionContextId) |context_id| {
if (scope.context.debugContextId() != context_id) { if (scope.context.debugContextId() != context_id) {
const isolated_world = bc.isolated_world orelse return error.ContextNotFound; var isolated_world = bc.isolated_world orelse return error.ContextNotFound;
scope = isolated_world.scope orelse return error.ContextNotFound; scope = &(isolated_world.executor.scope orelse return error.ContextNotFound);
if (scope.context.debugContextId() != context_id) return error.ContextNotFound; if (scope.context.debugContextId() != context_id) return error.ContextNotFound;
} }

View File

@@ -115,7 +115,7 @@ fn createIsolatedWorld(cmd: anytype) !void {
const world = try bc.createIsolatedWorld(params.worldName, params.grantUniveralAccess); const world = try bc.createIsolatedWorld(params.worldName, params.grantUniveralAccess);
const page = bc.session.currentPage() orelse return error.PageNotLoaded; const page = bc.session.currentPage() orelse return error.PageNotLoaded;
try pageCreated(bc, page); try pageCreated(bc, page);
const scope = world.scope.?; const scope = &world.executor.scope.?;
// Create the auxdata json for the contextCreated event // Create the auxdata json for the contextCreated event
// Calling contextCreated will assign a Id to the context and send 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}); 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 // Calling contextCreated will assign a new Id to the context and send the contextCreated event
bc.inspector.contextCreated( bc.inspector.contextCreated(
isolated_world.scope.?, &isolated_world.executor.scope.?,
isolated_world.name, isolated_world.name,
"://", "://",
aux_json, aux_json,
@@ -258,7 +258,7 @@ pub fn pageCreated(bc: anytype, page: *Page) !void {
try isolated_world.createContext(page); try isolated_world.createContext(page);
const polyfill = @import("../../browser/polyfill/polyfill.zig"); const polyfill = @import("../../browser/polyfill/polyfill.zig");
try polyfill.load(bc.arena, isolated_world.scope.?); try polyfill.load(bc.arena, &isolated_world.executor.scope.?);
} }
} }

View File

@@ -70,7 +70,6 @@ pub fn main() !void {
var app = try App.init(alloc, .{ var app = try App.init(alloc, .{
.run_mode = args.mode, .run_mode = args.mode,
.gc_hints = args.gcHints(),
.http_proxy = args.httpProxy(), .http_proxy = args.httpProxy(),
.tls_verify_host = args.tlsVerifyHost(), .tls_verify_host = args.tlsVerifyHost(),
}); });
@@ -129,13 +128,6 @@ const Command = struct {
mode: Mode, mode: Mode,
exec_name: []const u8, exec_name: []const u8,
fn gcHints(self: *const Command) bool {
return switch (self.mode) {
.serve => |opts| opts.gc_hints,
else => false,
};
}
fn tlsVerifyHost(self: *const Command) bool { fn tlsVerifyHost(self: *const Command) bool {
return switch (self.mode) { return switch (self.mode) {
inline .serve, .fetch => |opts| opts.tls_verify_host, inline .serve, .fetch => |opts| opts.tls_verify_host,
@@ -161,7 +153,6 @@ const Command = struct {
host: []const u8, host: []const u8,
port: u16, port: u16,
timeout: u16, timeout: u16,
gc_hints: bool,
tls_verify_host: bool, tls_verify_host: bool,
http_proxy: ?std.Uri, http_proxy: ?std.Uri,
}; };
@@ -210,9 +201,6 @@ const Command = struct {
\\--timeout Inactivity timeout in seconds before disconnecting clients \\--timeout Inactivity timeout in seconds before disconnecting clients
\\ Defaults to 3 (seconds) \\ Defaults to 3 (seconds)
\\ \\
\\--gc_hints Encourage V8 to cleanup garbage for each new browser context.
\\ Defaults to false
\\
\\--insecure_disable_tls_host_verification \\--insecure_disable_tls_host_verification
\\ Disables host verification on all HTTP requests. \\ Disables host verification on all HTTP requests.
\\ This is an advanced option which should only be \\ This is an advanced option which should only be
@@ -296,10 +284,6 @@ fn inferMode(opt: []const u8) ?App.RunMode {
return .serve; return .serve;
} }
if (std.mem.eql(u8, opt, "--gc_hints")) {
return .serve;
}
return null; return null;
} }
@@ -310,7 +294,6 @@ fn parseServeArgs(
var host: []const u8 = "127.0.0.1"; var host: []const u8 = "127.0.0.1";
var port: u16 = 9222; var port: u16 = 9222;
var timeout: u16 = 3; var timeout: u16 = 3;
var gc_hints = false;
var tls_verify_host = true; var tls_verify_host = true;
var http_proxy: ?std.Uri = null; var http_proxy: ?std.Uri = null;
@@ -355,11 +338,6 @@ fn parseServeArgs(
continue; continue;
} }
if (std.mem.eql(u8, "--gc_hints", opt)) {
gc_hints = true;
continue;
}
if (std.mem.eql(u8, "--http_proxy", opt)) { if (std.mem.eql(u8, "--http_proxy", opt)) {
const str = args.next() orelse { const str = args.next() orelse {
log.err("--http_proxy argument requires an value", .{}); log.err("--http_proxy argument requires an value", .{});
@@ -377,7 +355,6 @@ fn parseServeArgs(
.host = host, .host = host,
.port = port, .port = port,
.timeout = timeout, .timeout = timeout,
.gc_hints = gc_hints,
.http_proxy = http_proxy, .http_proxy = http_proxy,
.tls_verify_host = tls_verify_host, .tls_verify_host = tls_verify_host,
}; };

View File

@@ -53,8 +53,8 @@ pub const Platform = struct {
// The Env maps to a V8 isolate, which represents a isolated sandbox for // 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, // 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. // and it's where we'll start ExecutionWorlds, which actually execute JavaScript.
// The `S` parameter is arbitrary state. When we start an Executor, an instance // 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. // 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. // 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 { 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(); self.isolate.performMicrotasksCheckpoint();
} }
pub fn newExecutor(self: *Self) !Executor { pub fn newExecutionWorld(self: *Self) !ExecutionWorld {
return .{ return .{
.env = self, .env = self,
.scope = null, .scope = null,
@@ -269,10 +269,9 @@ pub fn Env(comptime State: type, comptime WebApis: type) type {
} }
// V8 doesn't immediately free memory associated with // V8 doesn't immediately free memory associated with
// a Context, it's managed by the garbage collector. So, when the // a Context, it's managed by the garbage collector. We use the
// `gc_hints` option is enabled, we'll use the `lowMemoryNotification` // `lowMemoryNotification` call on the isolate to encourage v8 to free
// call on the isolate to encourage v8 to free any contexts which // any contexts which have been freed.
// have been freed.
pub fn lowMemoryNotification(self: *Self) void { pub fn lowMemoryNotification(self: *Self) void {
var handle_scope: v8.HandleScope = undefined; var handle_scope: v8.HandleScope = undefined;
v8.HandleScope.init(&handle_scope, self.isolate); v8.HandleScope.init(&handle_scope, self.isolate);
@@ -280,32 +279,35 @@ pub fn Env(comptime State: type, comptime WebApis: type) type {
self.isolate.lowMemoryNotification(); 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, env: *Self,
// Arena whose lifetime is for a single getter/setter/function/etc. // Arena whose lifetime is for a single getter/setter/function/etc.
// Largely used to get strings out of V8, like a stack trace from // 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 // 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. // from scope to scope.
call_arena: ArenaAllocator, call_arena: ArenaAllocator,
// Arena whose lifetime is for a single page load, aka a Scope. Where // 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 // the call_arena lives for a single function call, the scope_arena
// lives for the lifetime of the entire page. The allocator will be // 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. // so that we can re-use it from scope to scope.
scope_arena: ArenaAllocator, scope_arena: ArenaAllocator,
// A Scope maps to a Browser's Page. Here though, it's only a // 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 // does all the work, but having all page-specific data structures
// grouped together helps keep things clean. // grouped together helps keep things clean.
scope: ?Scope = null, 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) { if (self.scope != null) {
self.endScope(); self.endScope();
} }
@@ -320,7 +322,7 @@ pub fn Env(comptime State: type, comptime WebApis: type) type {
// when the handle_scope is freed. // when the handle_scope is freed.
// We also maintain our own "scope_arena" which allows us to have // We also maintain our own "scope_arena" which allows us to have
// all page related memory easily managed. // 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); std.debug.assert(self.scope == null);
const ModuleLoader = switch (@typeInfo(@TypeOf(module_loader))) { const ModuleLoader = switch (@typeInfo(@TypeOf(module_loader))) {
@@ -338,9 +340,9 @@ pub fn Env(comptime State: type, comptime WebApis: type) type {
const Global = @TypeOf(global.*); const Global = @TypeOf(global.*);
var context: v8.Context = blk: { var context: v8.Context = blk: {
var handle_scope: v8.HandleScope = undefined; var temp_scope: v8.HandleScope = undefined;
v8.HandleScope.init(&handle_scope, isolate); v8.HandleScope.init(&temp_scope, isolate);
defer handle_scope.deinit(); defer temp_scope.deinit();
const js_global = v8.FunctionTemplate.initDefault(isolate); const js_global = v8.FunctionTemplate.initDefault(isolate);
attachClass(Global, isolate, js_global); attachClass(Global, isolate, js_global);
@@ -466,7 +468,7 @@ pub fn Env(comptime State: type, comptime WebApis: type) type {
return scope; return scope;
} }
pub fn endScope(self: *Executor) void { pub fn endScope(self: *ExecutionWorld) void {
self.scope.?.deinit(); self.scope.?.deinit();
self.scope = null; self.scope = null;
_ = self.scope_arena.reset(.{ .retain_with_limit = SCOPE_ARENA_RETAIN }); _ = self.scope_arena.reset(.{ .retain_with_limit = SCOPE_ARENA_RETAIN });
@@ -1517,7 +1519,7 @@ pub fn Env(comptime State: type, comptime WebApis: type) type {
} }
// Retrieves the RemoteObject for a given value. // 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 // just like a method return value. Therefore, if we've mapped this
// value before, we'll get the existing JS PersistedObject and if not // 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. // we'll create it and track it for cleanup when the scope ends.
@@ -2198,7 +2200,7 @@ fn isEmpty(comptime T: type) bool {
} }
// Responsible for calling Zig functions from JS invokations. This could // 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 // is somewhat repetitive between constructors, functions, getters, etc contained
// here does feel like it makes it clenaer. // here does feel like it makes it clenaer.
fn Caller(comptime E: type, comptime State: type) type { fn Caller(comptime E: type, comptime State: type) type {

View File

@@ -30,7 +30,7 @@ pub fn Runner(comptime State: type, comptime Global: type, comptime types: anyty
return struct { return struct {
env: *Env, env: *Env,
scope: *Env.Scope, scope: *Env.Scope,
executor: Env.Executor, executor: Env.ExecutionWorld,
pub const Env = js.Env(State, struct { pub const Env = js.Env(State, struct {
pub const Interfaces = AdjustedTypes; 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, .{}); self.env = try Env.init(allocator, .{});
errdefer self.env.deinit(); errdefer self.env.deinit();
self.executor = try self.env.newExecutor(); self.executor = try self.env.newExecutionWorld();
errdefer self.executor.deinit(); errdefer self.executor.deinit();
self.scope = try self.executor.startScope( self.scope = try self.executor.startScope(

View File

@@ -383,7 +383,7 @@ pub const JsRunner = struct {
renderer: Renderer, renderer: Renderer,
http_client: HttpClient, http_client: HttpClient,
scope: *Env.Scope, scope: *Env.Scope,
executor: Env.Executor, executor: Env.ExecutionWorld,
storage_shelf: storage.Shelf, storage_shelf: storage.Shelf,
cookie_jar: storage.CookieJar, cookie_jar: storage.CookieJar,
@@ -435,7 +435,7 @@ pub const JsRunner = struct {
.tls_verify_host = false, .tls_verify_host = false,
}); });
self.executor = try self.env.newExecutor(); self.executor = try self.env.newExecutionWorld();
errdefer self.executor.deinit(); errdefer self.executor.deinit();
self.scope = try self.executor.startScope(&self.window, &self.state, {}, true); self.scope = try self.executor.startScope(&self.window, &self.state, {}, true);