Skip to content
Closed
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
6 changes: 3 additions & 3 deletions build.zig.zon
Original file line number Diff line number Diff line change
Expand Up @@ -13,10 +13,10 @@
.hash = "tigerbeetle_io-0.0.0-ViLgxpyRBAB5BMfIcj3KMXfbJzwARs9uSl8aRy2OXULd",
},
.v8 = .{
.url = "https://github.com/lightpanda-io/zig-v8-fork/archive/97bcfb61da8c97de1321d677a6727a927a9db9a4.tar.gz",
.hash = "v8-0.0.0-xddH69DoIADZ8YXZ_EIx_tKdQKEoGsgob_3_ZIi0O_nV",
.url = "https://github.com/lightpanda-io/zig-v8-fork/archive/363e2899e6d782ad999edbfae048228871230467.tar.gz",
.hash = "v8-0.0.0-xddH6wHzIAARDy1uFvPqqBpTXzhlnEGDTuX9IAUQz3oU",
},
//.v8 = .{ .path = "../zig-v8-fork" },
// .v8 = .{ .path = "../zig-v8-fork" },
//.tigerbeetle_io = .{ .path = "../tigerbeetle-io" },
},
}
2 changes: 1 addition & 1 deletion src/browser/browser.zig
Original file line number Diff line number Diff line change
Expand Up @@ -193,7 +193,7 @@ pub const Session = struct {
self.state.cookie_jar = &self.cookie_jar;
errdefer self.arena.deinit();

self.executor = try browser.env.startExecutor(Window, &self.state, self, .main);
self.executor = try browser.env.startExecutor(Window, &self.state, self);
errdefer browser.env.stopExecutor(self.executor);
self.inspector = try Env.Inspector.init(self.arena.allocator(), self.executor, ctx);

Expand Down
15 changes: 12 additions & 3 deletions src/cdp/cdp.zig
Original file line number Diff line number Diff line change
Expand Up @@ -168,6 +168,11 @@ pub fn CDPT(comptime TypeProvider: type) type {
}

fn dispatchCommand(command: anytype, method: []const u8) !void {
const v8 = @import("v8");
var temp_scope: v8.HandleScope = undefined;
v8.HandleScope.init(&temp_scope, command.cdp.browser.env.isolate);
defer temp_scope.deinit();

const domain = blk: {
const i = std.mem.indexOfScalarPos(u8, method, 0, '.') orelse {
return error.InvalidMethod;
Expand Down Expand Up @@ -340,7 +345,7 @@ pub fn BrowserContext(comptime CDP_T: type) type {

pub fn deinit(self: *Self) void {
if (self.isolated_world) |isolated_world| {
isolated_world.executor.endScope();
isolated_world.executor.context.enter();
Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

TODO cleanup

self.cdp.browser.env.stopExecutor(isolated_world.executor);
self.isolated_world = null;
}
Expand All @@ -360,8 +365,12 @@ pub fn BrowserContext(comptime CDP_T: type) type {
) !void {
if (self.isolated_world != null) return error.CurrentlyOnly1IsolatedWorldSupported;

const executor = try self.cdp.browser.env.startExecutor(@import("../browser/html/window.zig").Window, &self.session.state, self.session, .isolated);
errdefer self.cdp.browser.env.stopExecutor(executor);
const executor = try self.cdp.browser.env.startExecutor(@import("../browser/html/window.zig").Window, &self.session.state, self.session);
executor.context.exit();
errdefer {
executor.context.enter();
self.cdp.browser.env.stopExecutor(executor);
}

// TBD should we endScope on removePage and re-startScope on createPage?
// Window will be refactored into the executor so we leave it ugly here for now as a reminder.
Expand Down
3 changes: 1 addition & 2 deletions src/cdp/testing.zig
Original file line number Diff line number Diff line change
Expand Up @@ -114,12 +114,11 @@ const Session = struct {

const Env = struct {
pub const Executor = MockExecutor;
pub fn startExecutor(self: *Env, comptime Global: type, state: anytype, module_loader: anytype, kind: anytype) !*Executor {
pub fn startExecutor(self: *Env, comptime Global: type, state: anytype, module_loader: anytype) !*Executor {
_ = self;
_ = Global;
_ = state;
_ = module_loader;
_ = kind;
return error.MockExecutor;
}
pub fn stopExecutor(self: *Env, executor: *Executor) void {
Expand Down
5 changes: 5 additions & 0 deletions src/main.zig
Original file line number Diff line number Diff line change
Expand Up @@ -97,6 +97,11 @@ pub fn main() !void {
var browser = try Browser.init(app);
defer browser.deinit();

const v8 = @import("v8");
var temp_scope: v8.HandleScope = undefined;
v8.HandleScope.init(&temp_scope, browser.env.isolate);
defer temp_scope.deinit();

var session = try browser.newSession({});

// page
Expand Down
86 changes: 33 additions & 53 deletions src/runtime/js.zig
Original file line number Diff line number Diff line change
Expand Up @@ -155,9 +155,6 @@ pub fn Env(comptime S: type, comptime types: anytype) type {
// the global isolate
isolate: v8.Isolate,

// this is the global scope that all our classes are defined in
global_scope: v8.HandleScope,

// just kept around because we need to free it on deinit
isolate_params: v8.CreateParams,

Expand All @@ -180,9 +177,6 @@ pub fn Env(comptime S: type, comptime types: anytype) type {
// Send a lowMemoryNotification whenever we stop an executor
gc_hints: bool,

// Used in debug mode to assert that we only have one executor at a time
has_executor: if (builtin.mode == .Debug) bool else void = if (builtin.mode == .Debug) false else {},

const Self = @This();

const State = S;
Expand All @@ -203,9 +197,9 @@ pub fn Env(comptime S: type, comptime types: anytype) type {
isolate.enter();
errdefer isolate.exit();

var global_scope: v8.HandleScope = undefined;
v8.HandleScope.init(&global_scope, isolate);
errdefer global_scope.deinit();
var temp_scope: v8.HandleScope = undefined;
v8.HandleScope.init(&temp_scope, isolate);
defer temp_scope.deinit();

const env = try allocator.create(Self);
errdefer allocator.destroy(env);
Expand All @@ -216,7 +210,6 @@ pub fn Env(comptime S: type, comptime types: anytype) type {
.allocator = allocator,
.isolate_params = params,
.gc_hints = opts.gc_hints,
.global_scope = global_scope,
.prototype_lookup = undefined,
.executor_pool = std.heap.MemoryPool(Executor).init(allocator),
};
Expand All @@ -227,7 +220,9 @@ pub fn Env(comptime S: type, comptime types: anytype) type {
// we can get its index via: @field(TYPE_LOOKUP, type_name).index
const templates = &env.templates;
inline for (Types, 0..) |s, i| {
templates[i] = env.generateClass(@field(types, s.name));
@setEvalBranchQuota(10_000);
// TODO kinda shot deinit, however these live for the livetime of the isolate anyways
templates[i] = v8.Persistent(v8.FunctionTemplate).init(isolate, env.generateClass(@field(types, s.name))).castToFunctionTemplate();
}

// Above, we've created all our our FunctionTemplates. Now that we
Expand All @@ -253,7 +248,6 @@ pub fn Env(comptime S: type, comptime types: anytype) type {
}

pub fn deinit(self: *Self) void {
self.global_scope.deinit();
self.isolate.exit();
self.isolate.deinit();
self.executor_pool.deinit();
Expand All @@ -265,22 +259,10 @@ pub fn Env(comptime S: type, comptime types: anytype) type {
self.isolate.performMicrotasksCheckpoint();
}

pub fn startExecutor(self: *Self, comptime Global: type, state: State, module_loader: anytype, kind: WorldKind) !*Executor {
if (comptime builtin.mode == .Debug) {
if (kind == .main) {
std.debug.assert(self.has_executor == false);
self.has_executor = true;
}
}
pub fn startExecutor(self: *Self, comptime Global: type, state: State, module_loader: anytype) !*Executor {
const isolate = self.isolate;
const templates = &self.templates;

// Acts like an Arena. Most things V8 has to allocate from this point
// on will be tied to this handle_scope - which we deinit in
// stopExecutor
var handle_scope: v8.HandleScope = undefined;
v8.HandleScope.init(&handle_scope, isolate);

// The global FunctionTemplate (i.e. Window).
const globals = v8.FunctionTemplate.initDefault(isolate);

Expand Down Expand Up @@ -308,9 +290,10 @@ pub fn Env(comptime S: type, comptime types: anytype) type {
globals.inherit(templates[proto_index]);
}

const context = v8.Context.init(isolate, global_template, null);
if (kind == .main) context.enter();
errdefer if (kind == .main) context.exit();
const context_local = v8.Context.init(isolate, global_template, null);
const context = v8.Persistent(v8.Context).init(isolate, context_local).castToContext();
context.enter();
errdefer context.exit();

// This shouldn't be necessary, but it is:
// https://groups.google.com/g/v8-users/c/qAQQBmbi--8
Expand Down Expand Up @@ -347,10 +330,8 @@ pub fn Env(comptime S: type, comptime types: anytype) type {
executor.* = .{
.state = state,
.isolate = isolate,
.kind = kind,
.context = context,
.templates = templates,
.handle_scope = handle_scope,
.call_arena = undefined,
.scope_arena = undefined,
._call_arena_instance = std.heap.ArenaAllocator.init(self.allocator),
Expand Down Expand Up @@ -389,13 +370,6 @@ pub fn Env(comptime S: type, comptime types: anytype) type {
// `gc_hints` option is enabled, we'll use the `lowMemoryNotification`
// call on the isolate to encourage v8 to free the context.
pub fn stopExecutor(self: *Self, executor: *Executor) void {
if (comptime builtin.mode == .Debug) {
if (executor.kind == .main) {
std.debug.assert(self.has_executor == true);
self.has_executor = false;
}
}

executor.deinit();
self.executor_pool.destroy(executor);
if (self.gc_hints) {
Expand Down Expand Up @@ -770,22 +744,14 @@ pub fn Env(comptime S: type, comptime types: anytype) type {
const PersistentObject = v8.Persistent(v8.Object);
const PersistentFunction = v8.Persistent(v8.Function);

const WorldKind = enum {
main,
isolated,
worker,
};

// This is capable of executing JavaScript.
pub const Executor = struct {
state: State,
isolate: v8.Isolate,
kind: WorldKind,

handle_scope: v8.HandleScope,

// @intFromPtr of our Executor is stored in this context, so given
// a context, we can always get the Executor back.
// This context is a persistent object. The persistent needs to be recovered and reset.
context: v8.Context,

// Because calls can be nested (i.e.a function calling a callback),
Expand Down Expand Up @@ -833,8 +799,9 @@ pub fn Env(comptime S: type, comptime types: anytype) type {

fn deinit(self: *Executor) void {
if (self.scope != null) self.endScope();
if (self.kind == .main) self.context.exit();
self.handle_scope.deinit();
self.context.exit();
var presistent_context = v8.Persistent(v8.Context).recoverCast(self.context);
presistent_context.deinit();

self._call_arena_instance.deinit();
self._scope_arena_instance.deinit();
Expand Down Expand Up @@ -926,12 +893,11 @@ pub fn Env(comptime S: type, comptime types: anytype) type {
pub fn startScope(self: *Executor, global: anytype) !void {
std.debug.assert(self.scope == null);

var handle_scope: v8.HandleScope = undefined;
v8.HandleScope.init(&handle_scope, self.isolate);
self.scope = Scope{
.handle_scope = handle_scope,
.arena = self.scope_arena,
};

// DO we still need this?
_ = try self._mapZigInstanceToJs(self.context.getGlobal(), global);
}

Expand Down Expand Up @@ -1130,7 +1096,6 @@ pub fn Env(comptime S: type, comptime types: anytype) type {
// in executor, rather than having one for each of these.
pub const Scope = struct {
arena: Allocator,
handle_scope: v8.HandleScope,
callbacks: std.ArrayListUnmanaged(v8.Persistent(v8.Function)) = .{},
identity_map: std.AutoHashMapUnmanaged(usize, PersistentObject) = .{},

Expand All @@ -1142,7 +1107,6 @@ pub fn Env(comptime S: type, comptime types: anytype) type {
for (self.callbacks.items) |*cb| {
cb.deinit();
}
self.handle_scope.deinit();
}

fn trackCallback(self: *Scope, pf: PersistentFunction) !void {
Expand Down Expand Up @@ -1173,14 +1137,26 @@ pub fn Env(comptime S: type, comptime types: anytype) type {
}

pub fn call(self: *const Callback, args: anytype) !void {
var temp_scope: v8.HandleScope = undefined;
v8.HandleScope.init(&temp_scope, self.executor.isolate);
defer temp_scope.deinit();

return self.callWithThis(self.getThis(), args);
}

pub fn tryCall(self: *const Callback, args: anytype, result: *Result) !void {
var temp_scope: v8.HandleScope = undefined;
v8.HandleScope.init(&temp_scope, self.executor.isolate);
defer temp_scope.deinit();

return self.tryCallWithThis(self.getThis(), args, result);
}

pub fn tryCallWithThis(self: *const Callback, this: anytype, args: anytype, result: *Result) !void {
var temp_scope: v8.HandleScope = undefined;
v8.HandleScope.init(&temp_scope, self.executor.isolate);
defer temp_scope.deinit();

var try_catch: TryCatch = undefined;
try_catch.init(self.executor);
defer try_catch.deinit();
Expand All @@ -1199,6 +1175,10 @@ pub fn Env(comptime S: type, comptime types: anytype) type {
}

pub fn callWithThis(self: *const Callback, this: anytype, args: anytype) !void {
var temp_scope: v8.HandleScope = undefined;
v8.HandleScope.init(&temp_scope, self.executor.isolate);
defer temp_scope.deinit();

const executor = self.executor;

const js_this = try executor.valueToExistingObject(this);
Expand Down
2 changes: 1 addition & 1 deletion src/runtime/testing.zig
Original file line number Diff line number Diff line change
Expand Up @@ -43,7 +43,7 @@ pub fn Runner(comptime State: type, comptime Global: type, comptime types: anyty

const G = if (Global == void) DefaultGlobal else Global;

runner.executor = try runner.env.startExecutor(G, state, runner, .main);
runner.executor = try runner.env.startExecutor(G, state, runner);
errdefer runner.env.stopExecutor(runner.executor);

try runner.executor.startScope(if (Global == void) &default_global else global);
Expand Down
2 changes: 1 addition & 1 deletion src/testing.zig
Original file line number Diff line number Diff line change
Expand Up @@ -433,7 +433,7 @@ pub const JsRunner = struct {
.tls_verify_host = false,
});

runner.executor = try runner.env.startExecutor(Window, &runner.state, runner, .main);
runner.executor = try runner.env.startExecutor(Window, &runner.state, runner);
errdefer runner.env.stopExecutor(runner.executor);

try runner.executor.startScope(&runner.window);
Expand Down