diff --git a/Libraries/LibWeb/DOM/Node.cpp b/Libraries/LibWeb/DOM/Node.cpp index 106aed60edd..a57185b5a54 100644 --- a/Libraries/LibWeb/DOM/Node.cpp +++ b/Libraries/LibWeb/DOM/Node.cpp @@ -689,12 +689,35 @@ void Node::insert_before(GC::Ref node, GC::Ptr child, bool suppress_ // 8. If suppress observers flag is unset, then queue a tree mutation record for parent with nodes, « », previousSibling, and child. if (!suppress_observers) { - queue_tree_mutation_record(move(nodes), {}, previous_sibling.ptr(), child.ptr()); + queue_tree_mutation_record(nodes, {}, previous_sibling.ptr(), child.ptr()); } // 9. Run the children changed steps for parent. children_changed(); + // 10. Let staticNodeList be a list of nodes, initially « ». + // Spec-Note: We collect all nodes before calling the post-connection steps on any one of them, instead of calling + // the post-connection steps while we’re traversing the node tree. This is because the post-connection + // steps can modify the tree’s structure, making live traversal unsafe, possibly leading to the + // post-connection steps being called multiple times on the same node. + GC::MarkedVector> static_node_list(heap()); + + // 11. For each node of nodes, in tree order: + for (auto& node : nodes) { + // 1. For each shadow-including inclusive descendant inclusiveDescendant of node, in shadow-including tree + // order, append inclusiveDescendant to staticNodeList. + node->for_each_shadow_including_inclusive_descendant([&static_node_list](Node& inclusive_descendant) { + static_node_list.append(inclusive_descendant); + return TraversalDecision::Continue; + }); + } + + // 12. For each node of staticNodeList, if node is connected, then run the post-connection steps with node. + for (auto& node : static_node_list) { + if (node->is_connected()) + node->post_connection(); + } + if (is_connected()) { // FIXME: This will need to become smarter when we implement the :has() selector. invalidate_style(StyleInvalidationReason::ParentOfInsertedNode); @@ -1201,6 +1224,10 @@ void Node::set_needs_style_update(bool value) } } +void Node::post_connection() +{ +} + void Node::inserted() { set_needs_style_update(true); diff --git a/Libraries/LibWeb/DOM/Node.h b/Libraries/LibWeb/DOM/Node.h index 3399b878671..64499ee7c03 100644 --- a/Libraries/LibWeb/DOM/Node.h +++ b/Libraries/LibWeb/DOM/Node.h @@ -248,6 +248,7 @@ public: Element const* parent_element() const; virtual void inserted(); + virtual void post_connection(); virtual void removed_from(Node*); virtual void children_changed() { } virtual void adopted_from(Document&) { }