diff --git a/Userland/Libraries/LibWeb/DOM/Node.cpp b/Userland/Libraries/LibWeb/DOM/Node.cpp index 9656e0249e..f6ae00829e 100644 --- a/Userland/Libraries/LibWeb/DOM/Node.cpp +++ b/Userland/Libraries/LibWeb/DOM/Node.cpp @@ -32,6 +32,7 @@ #include #include #include +#include #include #include #include @@ -442,9 +443,29 @@ void Node::insert_before(JS::NonnullGCPtr node, JS::GCPtr child, boo else insert_before_impl(*node_to_insert, child); - // FIXME: 4. If parent is a shadow host and node is a slottable, then assign a slot for node. - // FIXME: 5. If parent’s root is a shadow root, and parent is a slot whose assigned nodes is the empty list, then run signal a slot change for parent. - // FIXME: 6. Run assign slottables for a tree with node’s root. + // 4. If parent is a shadow host whose shadow root’s slot assignment is "named" and node is a slottable, then + // assign a slot for node. + if (is_element()) { + auto& element = static_cast(*this); + + auto is_named_shadow_host = element.is_shadow_host() + && element.shadow_root_internal()->slot_assignment() == Bindings::SlotAssignmentMode::Named; + + if (is_named_shadow_host && node->is_slottable()) + assign_a_slot(node->as_slottable()); + } + + // 5. If parent’s root is a shadow root, and parent is a slot whose assigned nodes is the empty list, then run + // signal a slot change for parent. + if (root().is_shadow_root() && is(*this)) { + auto& slot = static_cast(*this); + + if (slot.assigned_nodes_internal().is_empty()) + signal_a_slot_change(slot); + } + + // 6. Run assign slottables for a tree with node’s root. + assign_slottables_for_a_tree(node->root()); // 7. For each shadow-including inclusive descendant inclusiveDescendant of node, in shadow-including tree order: node_to_insert->for_each_shadow_including_inclusive_descendant([&](Node& inclusive_descendant) { @@ -587,13 +608,34 @@ void Node::remove(bool suppress_observers) // 11. Remove node from its parent’s children. parent->remove_child_impl(*this); - // FIXME: 12. If node is assigned, then run assign slottables for node’s assigned slot. + // 12. If node is assigned, then run assign slottables for node’s assigned slot. + if (auto assigned_slot = assigned_slot_for_node(*this)) + assign_slottables(*assigned_slot); - // FIXME: 13. If parent’s root is a shadow root, and parent is a slot whose assigned nodes is the empty list, then run signal a slot change for parent. + // 13. If parent’s root is a shadow root, and parent is a slot whose assigned nodes is the empty list, then run + // signal a slot change for parent. + if (parent->root().is_shadow_root() && is(parent)) { + auto& slot = static_cast(*parent); - // FIXME: 14. If node has an inclusive descendant that is a slot, then: - // 1. Run assign slottables for a tree with parent’s root. - // 2. Run assign slottables for a tree with node. + if (slot.assigned_nodes_internal().is_empty()) + signal_a_slot_change(slot); + } + + // 14. If node has an inclusive descendant that is a slot, then: + auto has_descendent_slot = false; + + for_each_in_inclusive_subtree_of_type([&](auto const&) { + has_descendent_slot = true; + return IterationDecision::Break; + }); + + if (has_descendent_slot) { + // 1. Run assign slottables for a tree with parent’s root. + assign_slottables_for_a_tree(parent->root()); + + // 2. Run assign slottables for a tree with node. + assign_slottables_for_a_tree(*this); + } // 15. Run the removing steps with node and parent. removed_from(parent);