disable observer weak ref

https://github.com/lightpanda-io/browser/pull/1870 doesn't work. I think there
are ways for the inspector to move objects into a context that skips our
reference count (those remote objects?). This disables weak references for
MutationObserver and IntersectionObserver. The issue is probably more widespread
but these are two types CDP drivers us _a lot_ via inspector, so this should
fix a number of immediate crashes.

I believe the correct fix is to remove Origin and store things at the Session-
level.
This commit is contained in:
Karl Seguin
2026-03-17 19:54:21 +08:00
parent d0e6a1f5bb
commit 21f7b95db9
3 changed files with 7 additions and 52 deletions

View File

@@ -206,7 +206,7 @@ pub fn createFinalizerCallback(
pub fn takeover(self: *Origin, original: *Origin) !void {
const arena = self.arena;
try self.globals.ensureUnusedCapacity(arena, self.globals.items.len);
try self.globals.ensureUnusedCapacity(arena, original.globals.items.len);
for (original.globals.items) |obj| {
self.globals.appendAssumeCapacity(obj);
}

View File

@@ -37,7 +37,6 @@ pub fn registerTypes() []const type {
const IntersectionObserver = @This();
_rc: u8 = 0,
_arena: Allocator,
_callback: js.Function.Temp,
_observing: std.ArrayList(*Element) = .{},
@@ -94,26 +93,14 @@ pub fn init(callback: js.Function.Temp, options: ?ObserverInit, page: *Page) !*I
}
pub fn deinit(self: *IntersectionObserver, shutdown: bool, session: *Session) void {
const rc = self._rc;
if (comptime IS_DEBUG) {
std.debug.assert(rc != 0);
}
if (rc == 1 or shutdown) {
if (shutdown) {
self._callback.release();
if ((comptime IS_DEBUG) and !shutdown) {
std.debug.assert(self._observing.items.len == 0);
}
session.releaseArena(self._arena);
} else {
self._rc = rc - 1;
} else if (comptime IS_DEBUG) {
std.debug.assert(false);
}
}
pub fn acquireRef(self: *IntersectionObserver) void {
self._rc += 1;
}
pub fn observe(self: *IntersectionObserver, target: *Element, page: *Page) !void {
// Check if already observing this target
for (self._observing.items) |elem| {
@@ -124,7 +111,6 @@ pub fn observe(self: *IntersectionObserver, target: *Element, page: *Page) !void
// Register with page if this is our first observation
if (self._observing.items.len == 0) {
self._rc += 1;
try page.registerIntersectionObserver(self);
}
@@ -159,10 +145,6 @@ pub fn unobserve(self: *IntersectionObserver, target: *Element, page: *Page) voi
break;
}
}
if (self._observing.items.len == 0) {
self.deinit(false, page._session);
}
}
pub fn disconnect(self: *IntersectionObserver, page: *Page) void {
@@ -173,13 +155,7 @@ pub fn disconnect(self: *IntersectionObserver, page: *Page) void {
}
self._pending_entries.clearRetainingCapacity();
const observing_count = self._observing.items.len;
self._observing.clearRetainingCapacity();
if (observing_count > 0) {
self.deinit(false, page._session);
}
page.unregisterIntersectionObserver(self);
}
@@ -382,7 +358,6 @@ pub const JsApi = struct {
pub const name = "IntersectionObserver";
pub const prototype_chain = bridge.prototypeChain();
pub var class_id: bridge.ClassId = undefined;
pub const weak = true;
pub const finalizer = bridge.finalizer(IntersectionObserver.deinit);
};

View File

@@ -39,7 +39,6 @@ pub fn registerTypes() []const type {
const MutationObserver = @This();
_rc: u8 = 0,
_arena: Allocator,
_callback: js.Function.Temp,
_observing: std.ArrayList(Observing) = .{},
@@ -87,26 +86,14 @@ pub fn init(callback: js.Function.Temp, page: *Page) !*MutationObserver {
}
pub fn deinit(self: *MutationObserver, shutdown: bool, session: *Session) void {
const rc = self._rc;
if (comptime IS_DEBUG) {
std.debug.assert(rc != 0);
}
if (rc == 1 or shutdown) {
if (shutdown) {
self._callback.release();
if ((comptime IS_DEBUG) and !shutdown) {
std.debug.assert(self._observing.items.len == 0);
}
session.releaseArena(self._arena);
} else {
self._rc = rc - 1;
} else if (comptime IS_DEBUG) {
std.debug.assert(false);
}
}
pub fn acquireRef(self: *MutationObserver) void {
self._rc += 1;
}
pub fn observe(self: *MutationObserver, target: *Node, options: ObserveOptions, page: *Page) !void {
const arena = self._arena;
@@ -171,7 +158,6 @@ pub fn observe(self: *MutationObserver, target: *Node, options: ObserveOptions,
// Register with page if this is our first observation
if (self._observing.items.len == 0) {
self._rc += 1;
try page.registerMutationObserver(self);
}
@@ -187,12 +173,7 @@ pub fn disconnect(self: *MutationObserver, page: *Page) void {
}
self._pending_records.clearRetainingCapacity();
const observing_count = self._observing.items.len;
self._observing.clearRetainingCapacity();
if (observing_count > 0) {
self.deinit(false, page._session);
}
page.unregisterMutationObserver(self);
}
@@ -459,7 +440,6 @@ pub const JsApi = struct {
pub const name = "MutationObserver";
pub const prototype_chain = bridge.prototypeChain();
pub var class_id: bridge.ClassId = undefined;
pub const weak = true;
pub const finalizer = bridge.finalizer(MutationObserver.deinit);
};