diff --git a/src/browser/js/Caller.zig b/src/browser/js/Caller.zig index 517c6f75..d4ea7691 100644 --- a/src/browser/js/Caller.zig +++ b/src/browser/js/Caller.zig @@ -88,6 +88,10 @@ pub const CallOpts = struct { }; pub fn constructor(self: *Caller, comptime T: type, func: anytype, handle: *const v8.FunctionCallbackInfo, comptime opts: CallOpts) void { + var hs: js.HandleScope = undefined; + hs.init(self.local.isolate); + defer hs.deinit(); + const info = FunctionCallbackInfo{ .handle = handle }; self._constructor(func, info) catch |err| { self.handleError(T, @TypeOf(func), err, info, opts); @@ -127,6 +131,10 @@ fn _constructor(self: *Caller, func: anytype, info: FunctionCallbackInfo) !void } pub fn method(self: *Caller, comptime T: type, func: anytype, handle: *const v8.FunctionCallbackInfo, comptime opts: CallOpts) void { + var hs: js.HandleScope = undefined; + hs.init(self.local.isolate); + defer hs.deinit(); + const info = FunctionCallbackInfo{ .handle = handle }; self._method(T, func, info, opts) catch |err| { self.handleError(T, @TypeOf(func), err, info, opts); @@ -146,6 +154,10 @@ fn _method(self: *Caller, comptime T: type, func: anytype, info: FunctionCallbac } pub fn function(self: *Caller, comptime T: type, func: anytype, handle: *const v8.FunctionCallbackInfo, comptime opts: CallOpts) void { + var hs: js.HandleScope = undefined; + hs.init(self.local.isolate); + defer hs.deinit(); + const info = FunctionCallbackInfo{ .handle = handle }; self._function(func, info, opts) catch |err| { self.handleError(T, @TypeOf(func), err, info, opts); @@ -160,6 +172,10 @@ fn _function(self: *Caller, func: anytype, info: FunctionCallbackInfo, comptime } pub fn getIndex(self: *Caller, comptime T: type, func: anytype, idx: u32, handle: *const v8.PropertyCallbackInfo, comptime opts: CallOpts) u8 { + var hs: js.HandleScope = undefined; + hs.init(self.local.isolate); + defer hs.deinit(); + const info = PropertyCallbackInfo{ .handle = handle }; return self._getIndex(T, func, idx, info, opts) catch |err| { self.handleError(T, @TypeOf(func), err, info, opts); @@ -178,6 +194,10 @@ fn _getIndex(self: *Caller, comptime T: type, func: anytype, idx: u32, info: Pro } pub fn getNamedIndex(self: *Caller, comptime T: type, func: anytype, name: *const v8.Name, handle: *const v8.PropertyCallbackInfo, comptime opts: CallOpts) u8 { + var hs: js.HandleScope = undefined; + hs.init(self.local.isolate); + defer hs.deinit(); + const info = PropertyCallbackInfo{ .handle = handle }; return self._getNamedIndex(T, func, name, info, opts) catch |err| { self.handleError(T, @TypeOf(func), err, info, opts); @@ -196,6 +216,10 @@ fn _getNamedIndex(self: *Caller, comptime T: type, func: anytype, name: *const v } pub fn setNamedIndex(self: *Caller, comptime T: type, func: anytype, name: *const v8.Name, js_value: *const v8.Value, handle: *const v8.PropertyCallbackInfo, comptime opts: CallOpts) u8 { + var hs: js.HandleScope = undefined; + hs.init(self.local.isolate); + defer hs.deinit(); + const info = PropertyCallbackInfo{ .handle = handle }; return self._setNamedIndex(T, func, name, .{ .local = &self.local, .handle = js_value }, info, opts) catch |err| { self.handleError(T, @TypeOf(func), err, info, opts); @@ -218,6 +242,10 @@ fn _setNamedIndex(self: *Caller, comptime T: type, func: anytype, name: *const v } pub fn deleteNamedIndex(self: *Caller, comptime T: type, func: anytype, name: *const v8.Name, handle: *const v8.PropertyCallbackInfo, comptime opts: CallOpts) u8 { + var hs: js.HandleScope = undefined; + hs.init(self.local.isolate); + defer hs.deinit(); + const info = PropertyCallbackInfo{ .handle = handle }; return self._deleteNamedIndex(T, func, name, info, opts) catch |err| { self.handleError(T, @TypeOf(func), err, info, opts); diff --git a/src/browser/js/Context.zig b/src/browser/js/Context.zig index b42727c1..27de2bf0 100644 --- a/src/browser/js/Context.zig +++ b/src/browser/js/Context.zig @@ -45,10 +45,9 @@ isolate: js.Isolate, // from this, and we can free it when the context is done. handle: v8.Global, -// The Context Global (our Window) as a v8::Global. -global_global: v8.Global, +// True if the context is auto-entered, +entered: bool, -handle_scope: ?js.HandleScope, cpu_profiler: ?*v8.CpuProfiler = null, // references Env.templates @@ -67,7 +66,8 @@ call_arena: Allocator, call_depth: usize = 0, // When a Caller is active (V8->Zig callback), this points to its Local. -// When null, Zig->V8 calls must create a temporary Local with HandleScope. +// When null, Zig->V8 calls must create a js.Local.Scope and initialize via +// context.localScope local: ?*const js.Local = null, // Serves two purposes. Like `global_objects`, this is used to free @@ -168,20 +168,20 @@ pub fn deinit(self: *Context) void { v8.v8__Global__Reset(global); } - if (self.handle_scope) |_| { + if (self.entered) { var ls: js.Local.Scope = undefined; self.localScope(&ls); defer ls.deinit(); v8.v8__Context__Exit(ls.local.handle); } - - // v8.v8__Global__Reset(&self.global_global); - // v8.v8__Global__Reset(&self.handle); + v8.v8__Global__Reset(&self.handle); } // Any operation on the context have to be made from a local. pub fn localScope(self: *Context, ls: *js.Local.Scope) void { const isolate = self.isolate; + js.HandleScope.init(&ls.handle_scope, isolate); + // TODO: add and init ls.hs for the handlescope ls.local = .{ .ctx = self, diff --git a/src/browser/js/ExecutionWorld.zig b/src/browser/js/ExecutionWorld.zig index fbeb445f..4f5c7602 100644 --- a/src/browser/js/ExecutionWorld.zig +++ b/src/browser/js/ExecutionWorld.zig @@ -76,49 +76,41 @@ pub fn createContext(self: *ExecutionWorld, page: *Page, enter: bool) !*Context const isolate = env.isolate; const arena = self.context_arena.allocator(); - // our window wrapped in a v8::Global - var global_global: v8.Global = undefined; + var hs: js.HandleScope = undefined; + hs.init(isolate); + defer hs.deinit(); + + // Getting this into the snapshot is tricky (anything involving the + // global is tricky). Easier to do here + const global_template = @import("Snapshot.zig").createGlobalTemplate(isolate.handle, env.templates); + v8.v8__ObjectTemplate__SetNamedHandler(global_template, &.{ + .getter = bridge.unknownPropertyCallback, + .setter = null, + .query = null, + .deleter = null, + .enumerator = null, + .definer = null, + .descriptor = null, + .data = null, + .flags = v8.kOnlyInterceptStrings | v8.kNonMasking, + }); + + const v8_context = v8.v8__Context__New(isolate.handle, global_template, null).?; // Create the v8::Context and wrap it in a v8::Global var context_global: v8.Global = undefined; - const v8_context = blk: { - var temp_scope: js.HandleScope = undefined; - temp_scope.init(isolate); - defer temp_scope.deinit(); + v8.v8__Global__New(isolate.handle, v8_context, &context_global); - // Getting this into the snapshot is tricky (anything involving the - // global is tricky). Easier to do here - const global_template = @import("Snapshot.zig").createGlobalTemplate(isolate.handle, env.templates); - v8.v8__ObjectTemplate__SetNamedHandler(global_template, &.{ - .getter = bridge.unknownPropertyCallback, - .setter = null, - .query = null, - .deleter = null, - .enumerator = null, - .definer = null, - .descriptor = null, - .data = null, - .flags = v8.kOnlyInterceptStrings | v8.kNonMasking, - }); + // our window wrapped in a v8::Global + const global_obj = v8.v8__Context__Global(v8_context).?; + var global_global: v8.Global = undefined; + v8.v8__Global__New(isolate.handle, global_obj, &global_global); - const local_context = v8.v8__Context__New(isolate.handle, global_template, null).?; - v8.v8__Global__New(isolate.handle, local_context, &context_global); - - const global_obj = v8.v8__Context__Global(local_context).?; - v8.v8__Global__New(isolate.handle, global_obj, &global_global); - - break :blk local_context; - }; - - var handle_scope: ?js.HandleScope = null; if (enter) { - handle_scope = @as(js.HandleScope, undefined); - handle_scope.?.init(isolate); v8.v8__Context__Enter(v8_context); } errdefer if (enter) { v8.v8__Context__Exit(v8_context); - handle_scope.?.deinit(); }; const context_id = env.context_id; @@ -127,11 +119,10 @@ pub fn createContext(self: *ExecutionWorld, page: *Page, enter: bool) !*Context self.context = Context{ .page = page, .id = context_id, + .entered = enter, .isolate = isolate, .handle = context_global, - .global_global = global_global, .templates = env.templates, - .handle_scope = handle_scope, .script_manager = &page._script_manager, .call_arena = page.call_arena, .arena = arena, diff --git a/src/browser/js/Local.zig b/src/browser/js/Local.zig index 6db4bcec..55e92280 100644 --- a/src/browser/js/Local.zig +++ b/src/browser/js/Local.zig @@ -1287,7 +1287,7 @@ pub fn debugContextId(self: *const Local) i32 { return v8.v8__Context__DebugContextId(self.handle); } -// Encapsulates a Local and a HandleScope (TODO). When we're going from V8->Zig +// Encapsulates a Local and a HandleScope. When we're going from V8->Zig // we easily get both a Local and a HandleScope via Caller.init. // But when we're going from Zig -> V8, things are more complicated. @@ -1314,9 +1314,10 @@ pub fn debugContextId(self: *const Local) i32 { // page.js.local.? pub const Scope = struct { local: Local, + handle_scope: js.HandleScope, - pub fn deinit(self: *const Scope) void { - _ = self; + pub fn deinit(self: *Scope) void { + self.handle_scope.deinit(); } pub fn toLocal(self: *Scope, global: anytype) ToLocalReturnType(@TypeOf(global)) { diff --git a/src/browser/js/bridge.zig b/src/browser/js/bridge.zig index 14606178..ac4a1e19 100644 --- a/src/browser/js/bridge.zig +++ b/src/browser/js/bridge.zig @@ -372,7 +372,12 @@ pub fn unknownPropertyCallback(c_name: ?*const v8.Name, handle: ?*const v8.Prope caller.init(v8_isolate); defer caller.deinit(); - const local = caller.local; + const local = &caller.local; + + var hs: js.HandleScope = undefined; + hs.init(local.isolate); + defer hs.deinit(); + const property: []const u8 = local.valueHandleToString(@ptrCast(c_name.?), .{}) catch { return 0; };