mirror of
https://github.com/lightpanda-io/browser.git
synced 2026-02-04 14:33:47 +00:00
prefer DoublyLinkedList for storing MutationObservers in Page
This commit is contained in:
@@ -98,7 +98,7 @@ _element_assigned_slots: Element.AssignedSlotLookup = .{},
|
|||||||
_script_manager: ScriptManager,
|
_script_manager: ScriptManager,
|
||||||
|
|
||||||
// List of active MutationObservers
|
// List of active MutationObservers
|
||||||
_mutation_observers: std.ArrayList(*MutationObserver) = .{},
|
_mutation_observers: std.DoublyLinkedList = .{},
|
||||||
_mutation_delivery_scheduled: bool = false,
|
_mutation_delivery_scheduled: bool = false,
|
||||||
_mutation_delivery_depth: u32 = 0,
|
_mutation_delivery_depth: u32 = 0,
|
||||||
|
|
||||||
@@ -1025,17 +1025,12 @@ pub fn getElementByIdFromNode(self: *Page, node: *Node, id: []const u8) ?*Elemen
|
|||||||
return null;
|
return null;
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn registerMutationObserver(self: *Page, observer: *MutationObserver) !void {
|
pub inline fn registerMutationObserver(self: *Page, observer: *MutationObserver) !void {
|
||||||
try self._mutation_observers.append(self.arena, observer);
|
self._mutation_observers.append(&observer.node);
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn unregisterMutationObserver(self: *Page, observer: *MutationObserver) void {
|
pub inline fn unregisterMutationObserver(self: *Page, observer: *MutationObserver) void {
|
||||||
for (self._mutation_observers.items, 0..) |obs, i| {
|
self._mutation_observers.remove(&observer.node);
|
||||||
if (obs == observer) {
|
|
||||||
_ = self._mutation_observers.swapRemove(i);
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn registerIntersectionObserver(self: *Page, observer: *IntersectionObserver) !void {
|
pub fn registerIntersectionObserver(self: *Page, observer: *IntersectionObserver) !void {
|
||||||
@@ -1126,11 +1121,9 @@ pub fn deliverMutations(self: *Page) void {
|
|||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
// Iterate backwards to handle observers that disconnect during their callback
|
var it: ?*std.DoublyLinkedList.Node = self._mutation_observers.first;
|
||||||
var i = self._mutation_observers.items.len;
|
while (it) |node| : (it = node.next) {
|
||||||
while (i > 0) {
|
const observer: *MutationObserver = @fieldParentPtr("node", node);
|
||||||
i -= 1;
|
|
||||||
const observer = self._mutation_observers.items[i];
|
|
||||||
observer.deliverRecords(self) catch |err| {
|
observer.deliverRecords(self) catch |err| {
|
||||||
log.err(.page, "page.deliverMutations", .{ .err = err });
|
log.err(.page, "page.deliverMutations", .{ .err = err });
|
||||||
};
|
};
|
||||||
@@ -2048,7 +2041,9 @@ pub fn attributeChange(self: *Page, element: *Element, name: []const u8, value:
|
|||||||
|
|
||||||
Element.Html.Custom.invokeAttributeChangedCallbackOnElement(element, name, old_value, value, self);
|
Element.Html.Custom.invokeAttributeChangedCallbackOnElement(element, name, old_value, value, self);
|
||||||
|
|
||||||
for (self._mutation_observers.items) |observer| {
|
var it: ?*std.DoublyLinkedList.Node = self._mutation_observers.first;
|
||||||
|
while (it) |node| : (it = node.next) {
|
||||||
|
const observer: *MutationObserver = @fieldParentPtr("node", node);
|
||||||
observer.notifyAttributeChange(element, name, old_value, self) catch |err| {
|
observer.notifyAttributeChange(element, name, old_value, self) catch |err| {
|
||||||
log.err(.page, "attributeChange.notifyObserver", .{ .err = err });
|
log.err(.page, "attributeChange.notifyObserver", .{ .err = err });
|
||||||
};
|
};
|
||||||
@@ -2072,7 +2067,9 @@ pub fn attributeRemove(self: *Page, element: *Element, name: []const u8, old_val
|
|||||||
|
|
||||||
Element.Html.Custom.invokeAttributeChangedCallbackOnElement(element, name, old_value, null, self);
|
Element.Html.Custom.invokeAttributeChangedCallbackOnElement(element, name, old_value, null, self);
|
||||||
|
|
||||||
for (self._mutation_observers.items) |observer| {
|
var it: ?*std.DoublyLinkedList.Node = self._mutation_observers.first;
|
||||||
|
while (it) |node| : (it = node.next) {
|
||||||
|
const observer: *MutationObserver = @fieldParentPtr("node", node);
|
||||||
observer.notifyAttributeChange(element, name, old_value, self) catch |err| {
|
observer.notifyAttributeChange(element, name, old_value, self) catch |err| {
|
||||||
log.err(.page, "attributeRemove.notifyObserver", .{ .err = err });
|
log.err(.page, "attributeRemove.notifyObserver", .{ .err = err });
|
||||||
};
|
};
|
||||||
@@ -2162,7 +2159,7 @@ fn findMatchingSlot(node: *Node, slot_name: []const u8) ?*Element.Html.Slot {
|
|||||||
}
|
}
|
||||||
|
|
||||||
pub fn hasMutationObservers(self: *const Page) bool {
|
pub fn hasMutationObservers(self: *const Page) bool {
|
||||||
return self._mutation_observers.items.len > 0;
|
return self._mutation_observers.first != null;
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn getCustomizedBuiltInDefinition(self: *Page, element: *Element) ?*CustomElementDefinition {
|
pub fn getCustomizedBuiltInDefinition(self: *Page, element: *Element) ?*CustomElementDefinition {
|
||||||
@@ -2178,8 +2175,9 @@ pub fn characterDataChange(
|
|||||||
target: *Node,
|
target: *Node,
|
||||||
old_value: []const u8,
|
old_value: []const u8,
|
||||||
) void {
|
) void {
|
||||||
// Notify mutation observers
|
var it: ?*std.DoublyLinkedList.Node = self._mutation_observers.first;
|
||||||
for (self._mutation_observers.items) |observer| {
|
while (it) |node| : (it = node.next) {
|
||||||
|
const observer: *MutationObserver = @fieldParentPtr("node", node);
|
||||||
observer.notifyCharacterDataChange(target, old_value, self) catch |err| {
|
observer.notifyCharacterDataChange(target, old_value, self) catch |err| {
|
||||||
log.err(.page, "cdataChange.notifyObserver", .{ .err = err });
|
log.err(.page, "cdataChange.notifyObserver", .{ .err = err });
|
||||||
};
|
};
|
||||||
@@ -2204,8 +2202,9 @@ pub fn childListChange(
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// Notify mutation observers
|
var it: ?*std.DoublyLinkedList.Node = self._mutation_observers.first;
|
||||||
for (self._mutation_observers.items) |observer| {
|
while (it) |node| : (it = node.next) {
|
||||||
|
const observer: *MutationObserver = @fieldParentPtr("node", node);
|
||||||
observer.notifyChildListChange(target, added_nodes, removed_nodes, previous_sibling, next_sibling, self) catch |err| {
|
observer.notifyChildListChange(target, added_nodes, removed_nodes, previous_sibling, next_sibling, self) catch |err| {
|
||||||
log.err(.page, "childListChange.notifyObserver", .{ .err = err });
|
log.err(.page, "childListChange.notifyObserver", .{ .err = err });
|
||||||
};
|
};
|
||||||
|
|||||||
@@ -34,6 +34,8 @@ const MutationObserver = @This();
|
|||||||
_callback: js.Function,
|
_callback: js.Function,
|
||||||
_observing: std.ArrayList(Observing) = .{},
|
_observing: std.ArrayList(Observing) = .{},
|
||||||
_pending_records: std.ArrayList(*MutationRecord) = .{},
|
_pending_records: std.ArrayList(*MutationRecord) = .{},
|
||||||
|
/// Intrusively linked to next element (see Page.zig).
|
||||||
|
node: std.DoublyLinkedList.Node = .{},
|
||||||
|
|
||||||
const Observing = struct {
|
const Observing = struct {
|
||||||
target: *Node,
|
target: *Node,
|
||||||
@@ -53,6 +55,7 @@ pub const ObserveOptions = struct {
|
|||||||
pub fn init(callback: js.Function, page: *Page) !*MutationObserver {
|
pub fn init(callback: js.Function, page: *Page) !*MutationObserver {
|
||||||
return page._factory.create(MutationObserver{
|
return page._factory.create(MutationObserver{
|
||||||
._callback = callback,
|
._callback = callback,
|
||||||
|
.node = .{},
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
Reference in New Issue
Block a user