Use origin.arena for values that are tied to the origin

Of note, the TAO and identity map entry has to use the origin arena, not
the context arena, as those can outlive the context.
This commit is contained in:
Karl Seguin
2026-03-11 21:55:58 +08:00
parent 7d835ef99d
commit 16dfad0895
5 changed files with 20 additions and 6 deletions

View File

@@ -171,6 +171,7 @@ pub fn setOrigin(self: *Context, key: ?[]const u8) !void {
errdefer self.session.releaseOrigin(origin);
try self.origin.transferTo(origin);
lp.assert(self.origin.rc == 1, "Ref opaque origin", .{ .rc = self.origin.rc });
self.origin.deinit(env.app);
self.origin = origin;

View File

@@ -326,7 +326,7 @@ pub fn createContext(self: *Env, page: *Page) !*Context {
.script_manager = &page._script_manager,
.scheduler = .init(context_arena),
};
try context.origin.identity_map.putNoClobber(context_arena, @intFromPtr(page.window), global_global);
try context.origin.identity_map.putNoClobber(origin.arena, @intFromPtr(page.window), global_global);
// Store a pointer to our context inside the v8 context so that, given
// a v8 context, we can get our context out

View File

@@ -202,20 +202,20 @@ pub fn compileAndRun(self: *const Local, src: []const u8, name: ?[]const u8) !js
// we can just grab it from the identity_map)
pub fn mapZigInstanceToJs(self: *const Local, js_obj_handle: ?*const v8.Object, value: anytype) !js.Object {
const ctx = self.ctx;
const arena = ctx.arena;
const origin_arena = ctx.origin.arena;
const T = @TypeOf(value);
switch (@typeInfo(T)) {
.@"struct" => {
// Struct, has to be placed on the heap
const heap = try arena.create(T);
const heap = try origin_arena.create(T);
heap.* = value;
return self.mapZigInstanceToJs(js_obj_handle, heap);
},
.pointer => |ptr| {
const resolved = resolveValue(value);
const gop = try ctx.origin.identity_map.getOrPut(arena, @intFromPtr(resolved.ptr));
const gop = try ctx.origin.addIdentity(@intFromPtr(resolved.ptr));
if (gop.found_existing) {
// we've seen this instance before, return the same object
return (js.Object.Global{ .handle = gop.value_ptr.* }).local(self);
@@ -244,7 +244,7 @@ pub fn mapZigInstanceToJs(self: *const Local, js_obj_handle: ?*const v8.Object,
// The TAO contains the pointer to our Zig instance as
// well as any meta data we'll need to use it later.
// See the TaggedOpaque struct for more details.
const tao = try arena.create(TaggedOpaque);
const tao = try origin_arena.create(TaggedOpaque);
tao.* = .{
.value = resolved.ptr,
.prototype_chain = resolved.prototype_chain.ptr,

View File

@@ -129,6 +129,19 @@ pub fn trackGlobal(self: *Origin, global: v8.Global) !void {
return self.globals.append(self.arena, global);
}
pub const IdentityResult = struct {
value_ptr: *v8.Global,
found_existing: bool,
};
pub fn addIdentity(self: *Origin, ptr: usize) !IdentityResult {
const gop = try self.identity_map.getOrPut(self.arena, ptr);
return .{
.value_ptr = gop.value_ptr,
.found_existing = gop.found_existing,
};
}
pub fn trackTemp(self: *Origin, global: v8.Global) !void {
return self.temps.put(self.arena, global.data_ptr, global);
}

View File

@@ -56,7 +56,7 @@ fn _toSlice(self: String, comptime null_terminate: bool, allocator: Allocator) !
pub fn toSSO(self: String, comptime global: bool) !(if (global) SSO.Global else SSO) {
if (comptime global) {
return .{ .str = try self.toSSOWithAlloc(self.local.ctx.arena) };
return .{ .str = try self.toSSOWithAlloc(self.local.ctx.origin.arena) };
}
return self.toSSOWithAlloc(self.local.call_arena);
}