browser: inline finalizer callbacks

Assisted-By: devx/3b7fd0ba-7378-40f0-a356-c0f5ce04cd1e
This commit is contained in:
Scott Taylor
2026-07-22 12:52:40 -04:00
parent bb2f1a7fe3
commit 2be09b5199
4 changed files with 13 additions and 22 deletions

View File

@@ -86,7 +86,7 @@ identity: js.Identity = .{},
// Zig instance ptr. The backing FinalizerCallback.Identity structs come from
// Browser.fc_identity_pool so they outlive the Page (and the Session) for v8
// weak-callback safety.
finalizer_callbacks: std.AutoHashMapUnmanaged(usize, *js.FinalizerCallback) = .empty,
finalizer_callbacks: std.AutoHashMapUnmanaged(usize, js.FinalizerCallback) = .empty,
// Persisted v8 handles owned by this Page. Handles that outlive the Page are
// reset on teardown; handles that can be released early are dropped
@@ -205,7 +205,7 @@ pub fn deinit(self: *Page) void {
{
var it = self.finalizer_callbacks.valueIterator();
while (it.next()) |fc| {
fc.*.deinit(self);
fc.deinit(self);
}
self.finalizer_callbacks = .empty;
}

View File

@@ -339,9 +339,9 @@ pub fn mapZigInstanceToJs(self: *const Local, js_obj_handle: ?*const v8.Object,
// so that we can cleanup on Page teardown if v8 doesn't finalize.
errdefer _ = page.finalizer_callbacks.remove(finalizer_ptr_id);
finalizer.acquire_ref(finalizer_ptr_id);
finalizer_gop.value_ptr.* = try self.createFinalizerCallback(resolved_ptr_id, finalizer_ptr_id, finalizer.release_ref_from_zig);
finalizer_gop.value_ptr.* = createFinalizerCallback(resolved_ptr_id, finalizer_ptr_id, finalizer.release_ref_from_zig);
}
const fc = finalizer_gop.value_ptr.*;
const fc = finalizer_gop.value_ptr;
const browser = session.browser;
const identity_finalizer = try browser.fc_identity_pool.create();
identity_finalizer.* = .{
@@ -1316,7 +1316,7 @@ fn resolveT(comptime T: type, value: *T) Resolved {
}
const finalizer_ptr_id = identity_finalizer.finalizer_ptr_id;
const fc = page.finalizer_callbacks.get(finalizer_ptr_id) orelse return;
const fc = page.finalizer_callbacks.getPtr(finalizer_ptr_id) orelse return;
{
// Unlink this identity from the FC's intrusive list
@@ -1346,7 +1346,6 @@ fn resolveT(comptime T: type, value: *T) Resolved {
// Remove from map before releaseRef to prevent address reuse issues.
_ = page.finalizer_callbacks.remove(finalizer_ptr_id);
FT.releaseRef(@ptrFromInt(finalizer_ptr_id), page);
page.releaseArena(fc.arena);
}
}
@@ -1601,8 +1600,6 @@ pub fn debugContextId(self: *const Local) i32 {
}
fn createFinalizerCallback(
self: *const Local,
// Key in identity map
// The most specific value (KeyboardEvent, not Event)
resolved_ptr_id: usize,
@@ -1611,21 +1608,12 @@ fn createFinalizerCallback(
// What actually gets acquired / released / deinit
finalizer_ptr_id: usize,
release_ref: *const fn (ptr_id: usize, page: *Page) void,
) !*FinalizerCallback {
const page = self.ctx.page;
const arena = try page.getArena(.tiny, "FinalizerCallback");
errdefer page.releaseArena(arena);
const fc = try arena.create(FinalizerCallback);
fc.* = .{
.page = page,
.arena = arena,
) FinalizerCallback {
return .{
.release_ref = release_ref,
.resolved_ptr_id = resolved_ptr_id,
.finalizer_ptr_id = finalizer_ptr_id,
};
return fc;
}
// Encapsulates a Local and a HandleScope. When we're going from V8->Zig

View File

@@ -479,8 +479,6 @@ test "TaggedAnyOpaque" {
// Page. This is to ensure that, if v8 doesn't finalize the value, we can
// release on Page teardown.
pub const FinalizerCallback = struct {
page: *Page,
arena: Allocator,
resolved_ptr_id: usize,
finalizer_ptr_id: usize,
release_ref: *const fn (ptr_id: usize, page: *Page) void,
@@ -528,7 +526,6 @@ pub const FinalizerCallback = struct {
id = identity.next;
}
self.release_ref(self.finalizer_ptr_id, page);
page.releaseArena(self.arena);
}
};

View File

@@ -268,3 +268,9 @@
}
testing.expectError('TypeError', () => new Request('https://example.com', { priority: 'bogus' }));
</script>
<script id=many_live_requests>
const requests = Array.from({ length: 1024 }, (_, i) => new Request(`https://example.com/${i}`));
testing.expectEqual(1024, requests.length);
testing.expectEqual('https://example.com/1023', requests[1023].url);
</script>