mirror of
https://github.com/lightpanda-io/browser.git
synced 2025-12-15 15:58:57 +00:00
tweak custom element callbacks
This commit is contained in:
@@ -107,6 +107,8 @@ _intersection_delivery_scheduled: bool = false,
|
||||
|
||||
// Lookup for customized built-in elements. Maps element pointer to definition.
|
||||
_customized_builtin_definitions: std.AutoHashMapUnmanaged(*Element, *CustomElementDefinition) = .{},
|
||||
_customized_builtin_connected_callback_invoked: std.AutoHashMapUnmanaged(*Element, void) = .{},
|
||||
_customized_builtin_disconnected_callback_invoked: std.AutoHashMapUnmanaged(*Element, void) = .{},
|
||||
|
||||
// This is set when an element is being upgraded (constructor is called).
|
||||
// The constructor can access this to get the element being upgraded.
|
||||
@@ -223,6 +225,8 @@ fn reset(self: *Page, comptime initializing: bool) !void {
|
||||
self._intersection_observers = .{};
|
||||
self._intersection_delivery_scheduled = false;
|
||||
self._customized_builtin_definitions = .{};
|
||||
self._customized_builtin_connected_callback_invoked = .{};
|
||||
self._customized_builtin_disconnected_callback_invoked = .{};
|
||||
self._undefined_custom_elements = .{};
|
||||
|
||||
try self.registerBackgroundTasks();
|
||||
@@ -1380,13 +1384,14 @@ pub fn appendNode(self: *Page, parent: *Node, child: *Node, opts: InsertNodeOpts
|
||||
|
||||
pub fn appendAllChildren(self: *Page, parent: *Node, target: *Node) !void {
|
||||
self.domChanged();
|
||||
const is_connected = parent.isConnected();
|
||||
const dest_connected = target.isConnected();
|
||||
|
||||
var it = parent.childrenIterator();
|
||||
while (it.next()) |child| {
|
||||
// Check if child was connected BEFORE removing it from parent
|
||||
const child_was_connected = child.isConnected();
|
||||
self.removeNode(parent, child, .{ .will_be_reconnected = dest_connected });
|
||||
try self.appendNode(target, child, .{ .child_already_connected = is_connected });
|
||||
try self.appendNode(target, child, .{ .child_already_connected = child_was_connected });
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1500,14 +1505,19 @@ pub fn _insertNodeRelative(self: *Page, comptime from_parser: bool, parent: *Nod
|
||||
// 1. A disconnected child became connected (parent.isConnected() == true)
|
||||
// 2. Child is being added to a shadow tree (parent_in_shadow == true)
|
||||
// In both cases, we need to update ID maps and invoke callbacks
|
||||
|
||||
// Only invoke connectedCallback if the root child is transitioning from
|
||||
// disconnected to connected. When that happens, all descendants should also
|
||||
// get connectedCallback invoked (they're becoming connected as a group).
|
||||
const should_invoke_connected = parent_is_connected and !opts.child_already_connected;
|
||||
|
||||
var tw = @import("webapi/TreeWalker.zig").Full.Elements.init(child, .{});
|
||||
while (tw.next()) |el| {
|
||||
if (el.getAttributeSafe("id")) |id| {
|
||||
try self.addElementId(el.asNode()._parent.?, el, id);
|
||||
}
|
||||
|
||||
// Only invoke connected callback if actually connected to document
|
||||
if (parent_is_connected) {
|
||||
if (should_invoke_connected) {
|
||||
Element.Html.Custom.invokeConnectedCallbackOnElement(el, self);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -136,6 +136,10 @@ fn upgradeElement(self: *CustomElementRegistry, element: *Element, page: *Page)
|
||||
fn upgradeCustomElement(custom: *@import("element/html/Custom.zig"), definition: *CustomElementDefinition, page: *Page) !void {
|
||||
custom._definition = definition;
|
||||
|
||||
// Reset callback flags since this is a fresh upgrade
|
||||
custom._connected_callback_invoked = false;
|
||||
custom._disconnected_callback_invoked = false;
|
||||
|
||||
const node = custom.asNode();
|
||||
const prev_upgrading = page._upgrading_element;
|
||||
page._upgrading_element = node;
|
||||
|
||||
@@ -32,6 +32,8 @@ const Custom = @This();
|
||||
_proto: *HtmlElement,
|
||||
_tag_name: String,
|
||||
_definition: ?*CustomElementDefinition,
|
||||
_connected_callback_invoked: bool = false,
|
||||
_disconnected_callback_invoked: bool = false,
|
||||
|
||||
pub fn asElement(self: *Custom) *Element {
|
||||
return self._proto._proto;
|
||||
@@ -41,10 +43,20 @@ pub fn asNode(self: *Custom) *Node {
|
||||
}
|
||||
|
||||
pub fn invokeConnectedCallback(self: *Custom, page: *Page) void {
|
||||
// Only invoke if we haven't already called it while connected
|
||||
if (self._connected_callback_invoked) return;
|
||||
|
||||
self._connected_callback_invoked = true;
|
||||
self._disconnected_callback_invoked = false;
|
||||
self.invokeCallback("connectedCallback", .{}, page);
|
||||
}
|
||||
|
||||
pub fn invokeDisconnectedCallback(self: *Custom, page: *Page) void {
|
||||
// Only invoke if we haven't already called it while disconnected
|
||||
if (self._disconnected_callback_invoked) return;
|
||||
|
||||
self._disconnected_callback_invoked = true;
|
||||
self._connected_callback_invoked = false;
|
||||
self.invokeCallback("disconnectedCallback", .{}, page);
|
||||
}
|
||||
|
||||
@@ -63,6 +75,16 @@ pub fn invokeConnectedCallbackOnElement(element: *Element, page: *Page) void {
|
||||
}
|
||||
|
||||
// Customized built-in element
|
||||
// Check if we've already invoked connectedCallback while connected
|
||||
if (page._customized_builtin_connected_callback_invoked.contains(element)) return;
|
||||
|
||||
page._customized_builtin_connected_callback_invoked.put(
|
||||
page.arena,
|
||||
element,
|
||||
{},
|
||||
) catch return;
|
||||
_ = page._customized_builtin_disconnected_callback_invoked.remove(element);
|
||||
|
||||
invokeCallbackOnElement(element, "connectedCallback", .{}, page);
|
||||
}
|
||||
|
||||
@@ -74,6 +96,16 @@ pub fn invokeDisconnectedCallbackOnElement(element: *Element, page: *Page) void
|
||||
}
|
||||
|
||||
// Customized built-in element
|
||||
// Check if we've already invoked disconnectedCallback while disconnected
|
||||
if (page._customized_builtin_disconnected_callback_invoked.contains(element)) return;
|
||||
|
||||
page._customized_builtin_disconnected_callback_invoked.put(
|
||||
page.arena,
|
||||
element,
|
||||
{},
|
||||
) catch return;
|
||||
_ = page._customized_builtin_connected_callback_invoked.remove(element);
|
||||
|
||||
invokeCallbackOnElement(element, "disconnectedCallback", .{}, page);
|
||||
}
|
||||
|
||||
@@ -119,6 +151,10 @@ pub fn checkAndAttachBuiltIn(element: *Element, page: *Page) !void {
|
||||
// Attach the definition
|
||||
try page.setCustomizedBuiltInDefinition(element, definition);
|
||||
|
||||
// Reset callback flags since this is a fresh upgrade
|
||||
_ = page._customized_builtin_connected_callback_invoked.remove(element);
|
||||
_ = page._customized_builtin_disconnected_callback_invoked.remove(element);
|
||||
|
||||
// Invoke constructor
|
||||
const prev_upgrading = page._upgrading_element;
|
||||
const node = element.asNode();
|
||||
|
||||
Reference in New Issue
Block a user