remove global handlescope

This commit is contained in:
Karl Seguin
2026-01-16 16:51:19 +08:00
parent 62aa564df1
commit 5c1b7935e2
5 changed files with 72 additions and 47 deletions

View File

@@ -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 { 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 }; const info = FunctionCallbackInfo{ .handle = handle };
self._constructor(func, info) catch |err| { self._constructor(func, info) catch |err| {
self.handleError(T, @TypeOf(func), err, info, opts); 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 { 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 }; const info = FunctionCallbackInfo{ .handle = handle };
self._method(T, func, info, opts) catch |err| { self._method(T, func, info, opts) catch |err| {
self.handleError(T, @TypeOf(func), err, info, opts); 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 { 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 }; const info = FunctionCallbackInfo{ .handle = handle };
self._function(func, info, opts) catch |err| { self._function(func, info, opts) catch |err| {
self.handleError(T, @TypeOf(func), err, info, opts); 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 { 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 }; const info = PropertyCallbackInfo{ .handle = handle };
return self._getIndex(T, func, idx, info, opts) catch |err| { return self._getIndex(T, func, idx, info, opts) catch |err| {
self.handleError(T, @TypeOf(func), err, info, opts); 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 { 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 }; const info = PropertyCallbackInfo{ .handle = handle };
return self._getNamedIndex(T, func, name, info, opts) catch |err| { return self._getNamedIndex(T, func, name, info, opts) catch |err| {
self.handleError(T, @TypeOf(func), err, info, opts); 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 { 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 }; const info = PropertyCallbackInfo{ .handle = handle };
return self._setNamedIndex(T, func, name, .{ .local = &self.local, .handle = js_value }, info, opts) catch |err| { return self._setNamedIndex(T, func, name, .{ .local = &self.local, .handle = js_value }, info, opts) catch |err| {
self.handleError(T, @TypeOf(func), err, info, opts); 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 { 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 }; const info = PropertyCallbackInfo{ .handle = handle };
return self._deleteNamedIndex(T, func, name, info, opts) catch |err| { return self._deleteNamedIndex(T, func, name, info, opts) catch |err| {
self.handleError(T, @TypeOf(func), err, info, opts); self.handleError(T, @TypeOf(func), err, info, opts);

View File

@@ -45,10 +45,9 @@ isolate: js.Isolate,
// from this, and we can free it when the context is done. // from this, and we can free it when the context is done.
handle: v8.Global, handle: v8.Global,
// The Context Global (our Window) as a v8::Global. // True if the context is auto-entered,
global_global: v8.Global, entered: bool,
handle_scope: ?js.HandleScope,
cpu_profiler: ?*v8.CpuProfiler = null, cpu_profiler: ?*v8.CpuProfiler = null,
// references Env.templates // references Env.templates
@@ -67,7 +66,8 @@ call_arena: Allocator,
call_depth: usize = 0, call_depth: usize = 0,
// When a Caller is active (V8->Zig callback), this points to its Local. // 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, local: ?*const js.Local = null,
// Serves two purposes. Like `global_objects`, this is used to free // 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); v8.v8__Global__Reset(global);
} }
if (self.handle_scope) |_| { if (self.entered) {
var ls: js.Local.Scope = undefined; var ls: js.Local.Scope = undefined;
self.localScope(&ls); self.localScope(&ls);
defer ls.deinit(); defer ls.deinit();
v8.v8__Context__Exit(ls.local.handle); v8.v8__Context__Exit(ls.local.handle);
} }
v8.v8__Global__Reset(&self.handle);
// v8.v8__Global__Reset(&self.global_global);
// v8.v8__Global__Reset(&self.handle);
} }
// Any operation on the context have to be made from a local. // Any operation on the context have to be made from a local.
pub fn localScope(self: *Context, ls: *js.Local.Scope) void { pub fn localScope(self: *Context, ls: *js.Local.Scope) void {
const isolate = self.isolate; const isolate = self.isolate;
js.HandleScope.init(&ls.handle_scope, isolate);
// TODO: add and init ls.hs for the handlescope // TODO: add and init ls.hs for the handlescope
ls.local = .{ ls.local = .{
.ctx = self, .ctx = self,

View File

@@ -76,15 +76,9 @@ pub fn createContext(self: *ExecutionWorld, page: *Page, enter: bool) !*Context
const isolate = env.isolate; const isolate = env.isolate;
const arena = self.context_arena.allocator(); const arena = self.context_arena.allocator();
// our window wrapped in a v8::Global var hs: js.HandleScope = undefined;
var global_global: v8.Global = undefined; hs.init(isolate);
defer hs.deinit();
// 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();
// Getting this into the snapshot is tricky (anything involving the // Getting this into the snapshot is tricky (anything involving the
// global is tricky). Easier to do here // global is tricky). Easier to do here
@@ -101,24 +95,22 @@ pub fn createContext(self: *ExecutionWorld, page: *Page, enter: bool) !*Context
.flags = v8.kOnlyInterceptStrings | v8.kNonMasking, .flags = v8.kOnlyInterceptStrings | v8.kNonMasking,
}); });
const local_context = v8.v8__Context__New(isolate.handle, global_template, null).?; const v8_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).?; // Create the v8::Context and wrap it in a v8::Global
var context_global: v8.Global = undefined;
v8.v8__Global__New(isolate.handle, v8_context, &context_global);
// 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); v8.v8__Global__New(isolate.handle, global_obj, &global_global);
break :blk local_context;
};
var handle_scope: ?js.HandleScope = null;
if (enter) { if (enter) {
handle_scope = @as(js.HandleScope, undefined);
handle_scope.?.init(isolate);
v8.v8__Context__Enter(v8_context); v8.v8__Context__Enter(v8_context);
} }
errdefer if (enter) { errdefer if (enter) {
v8.v8__Context__Exit(v8_context); v8.v8__Context__Exit(v8_context);
handle_scope.?.deinit();
}; };
const context_id = env.context_id; const context_id = env.context_id;
@@ -127,11 +119,10 @@ pub fn createContext(self: *ExecutionWorld, page: *Page, enter: bool) !*Context
self.context = Context{ self.context = Context{
.page = page, .page = page,
.id = context_id, .id = context_id,
.entered = enter,
.isolate = isolate, .isolate = isolate,
.handle = context_global, .handle = context_global,
.global_global = global_global,
.templates = env.templates, .templates = env.templates,
.handle_scope = handle_scope,
.script_manager = &page._script_manager, .script_manager = &page._script_manager,
.call_arena = page.call_arena, .call_arena = page.call_arena,
.arena = arena, .arena = arena,

View File

@@ -1287,7 +1287,7 @@ pub fn debugContextId(self: *const Local) i32 {
return v8.v8__Context__DebugContextId(self.handle); 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. // we easily get both a Local and a HandleScope via Caller.init.
// But when we're going from Zig -> V8, things are more complicated. // 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.? // page.js.local.?
pub const Scope = struct { pub const Scope = struct {
local: Local, local: Local,
handle_scope: js.HandleScope,
pub fn deinit(self: *const Scope) void { pub fn deinit(self: *Scope) void {
_ = self; self.handle_scope.deinit();
} }
pub fn toLocal(self: *Scope, global: anytype) ToLocalReturnType(@TypeOf(global)) { pub fn toLocal(self: *Scope, global: anytype) ToLocalReturnType(@TypeOf(global)) {

View File

@@ -372,7 +372,12 @@ pub fn unknownPropertyCallback(c_name: ?*const v8.Name, handle: ?*const v8.Prope
caller.init(v8_isolate); caller.init(v8_isolate);
defer caller.deinit(); 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 { const property: []const u8 = local.valueHandleToString(@ptrCast(c_name.?), .{}) catch {
return 0; return 0;
}; };