Make Global Function explicit.

This is the first in a series of changes to make globals explicit. The ultimate
goal of having explicit Globals is to move away from the global HandleScope and
to explicit HandleScopes.

Currently, we treat globals and locals interchangeably. In fact, for Global ->
Local, we just ptrCast. This works because we have 1 global HandleScope, which
effectively disables V8's GC and thus nothing ever gets moved.

If we're going to introduce explicit HandleScopes, then we need to first have
correct Globals. Specifically, when we want to act on the global, we need to
get the local value, and that will eventually mean making sure there's a
HandleScope.

While adding explicit globals, we're keeping the global HandleScope so that we
can minimize the change. So, given that we still have the global HandleScope
the change is largely two things:
1 - js.Function.persit() returns a js.Function.Global. Types that persist global
   functions must be updated to js.Function.Global.
2 - To turn js.Function.Global -> js.Function, we need to call .local() on it.

The bridge has been updated to support js.Function.Global for both input and
output parameters. Thus, window.setOnLoad can now directly take a
js.Function.Global, and window.getOnLoad can directly return that
js.Function.Global.
This commit is contained in:
Karl Seguin
2026-01-14 15:12:22 +08:00
parent a30c65966b
commit 5def997bed
25 changed files with 198 additions and 191 deletions

View File

@@ -33,10 +33,6 @@ pub const Result = struct {
exception: []const u8,
};
pub fn id(self: *const Function) u32 {
return @as(u32, @bitCast(v8.v8__Object__GetIdentityHash(@ptrCast(self.handle))));
}
pub fn withThis(self: *const Function, value: anytype) !Function {
const this_obj = if (@TypeOf(value) == js.Object)
value.handle
@@ -172,20 +168,41 @@ pub fn getPropertyValue(self: *const Function, name: []const u8) !?js.Value {
};
}
pub fn persist(self: *const Function) !Function {
pub fn persist(self: *const Function) !Global {
var ctx = self.ctx;
const global = js.Global(Function).init(ctx.isolate.handle, self.handle);
var global: v8.Global = undefined;
v8.v8__Global__New(ctx.isolate.handle, self.handle, &global);
try ctx.global_functions.append(ctx.arena, global);
return .{
.handle = global,
.ctx = ctx,
.this = self.this,
.handle = global.local(),
};
}
pub fn persistWithThis(self: *const Function, value: anytype) !Function {
var persisted = try self.persist();
return persisted.withThis(value);
pub fn persistWithThis(self: *const Function, value: anytype) !Global {
const with_this = try self.withThis(value);
return with_this.persist();
}
pub const Global = struct {
handle: v8.Global,
ctx: *js.Context,
pub fn deinit(self: *Global) void {
v8.v8__Global__Reset(&self.handle);
}
pub fn local(self: *const Global) Function {
return .{
.ctx = self.ctx,
.handle = @ptrCast(v8.v8__Global__Get(&self.handle, self.ctx.isolate.handle)),
};
}
pub fn isEqual(self: *const Global, other: Function) bool {
return v8.v8__Global__IsEqual(&self.handle, other.handle);
}
};