diff --git a/src/browser/js/Env.zig b/src/browser/js/Env.zig index e91ce4a1..bae6a8f0 100644 --- a/src/browser/js/Env.zig +++ b/src/browser/js/Env.zig @@ -296,7 +296,7 @@ pub fn createContext(self: *Env, page: *Page, params: ContextParams) !*Context { // it gets setup automatically as objects are created, but the Window // object already exists in v8 (it's the global) so we manually create // the mapping here. - const tao = try context_arena.create(@import("TaggedOpaque.zig")); + const tao = try params.identity_arena.create(@import("TaggedOpaque.zig")); tao.* = .{ .value = @ptrCast(page.window), .prototype_chain = (&Window.JsApi.Meta.prototype_chain).ptr, diff --git a/src/browser/js/Local.zig b/src/browser/js/Local.zig index 4022a302..c9a3b880 100644 --- a/src/browser/js/Local.zig +++ b/src/browser/js/Local.zig @@ -244,7 +244,10 @@ 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 context_arena.create(TaggedOpaque); + // Use identity_arena so TAOs survive context destruction. V8 objects + // are stored in identity_map (session-level) and may be referenced + // after their creating context is destroyed (e.g., via microtasks). + const tao = try ctx.identity_arena.create(TaggedOpaque); tao.* = .{ .value = resolved.ptr, .prototype_chain = resolved.prototype_chain.ptr,