Fire slot change events when the slot content changes (#35137)

* Add the onslotchange attribute to ShadowRoot

Signed-off-by: Simon Wülker <simon.wuelker@arcor.de>

* Add spec comments to MutationObserver::queue_mutation_observer_microtask

Signed-off-by: Simon Wülker <simon.wuelker@arcor.de>

* Add DomRefCell::take

Signed-off-by: Simon Wülker <simon.wuelker@arcor.de>

* Add spec comments to notify_mutation_observers

Signed-off-by: Simon Wülker <simon.wuelker@arcor.de>

* Fire slotchange events when a slot changes

Signed-off-by: Simon Wülker <simon.wuelker@arcor.de>

* ./mach fmt

Signed-off-by: Simon Wülker <simon.wuelker@arcor.de>

* Fix check for when to dispatch slot events

Signed-off-by: Simon Wülker <simon.wuelker@arcor.de>

* Potentially fire slot change events in Node::remove

Signed-off-by: Simon Wülker <simon.wuelker@arcor.de>

* Update WPT expectations

Signed-off-by: Simon Wülker <simon.wuelker@arcor.de>

* ./mach fmt

Signed-off-by: Simon Wülker <simon.wuelker@arcor.de>

* Bump stylo

Signed-off-by: Simon Wülker <simon.wuelker@arcor.de>

* Move "signal a slot change" into ScriptThread impl

Signed-off-by: Simon Wülker <simon.wuelker@arcor.de>

---------

Signed-off-by: Simon Wülker <simon.wuelker@arcor.de>
This commit is contained in:
Simon Wülker 2025-01-27 15:13:22 +01:00 committed by GitHub
parent cd93841ba1
commit 859cc6ab9b
No known key found for this signature in database
GPG key ID: B5690EEEBB952194
17 changed files with 152 additions and 119 deletions

View file

@ -2323,6 +2323,48 @@ impl Node {
let old_next_sibling = node.GetNextSibling();
// Steps 9-10 are handled in unbind_from_tree.
parent.remove_child(node, cached_index);
// Step 12. If node is assigned, then run assign slottables for nodes assigned slot.
let assigned_slot = node
.downcast::<Element>()
.and_then(|e| e.assigned_slot())
.or_else(|| {
node.downcast::<Text>().and_then(|text| {
text.slottable_data()
.borrow()
.assigned_slot
.as_ref()
.map(Dom::as_rooted)
})
});
if let Some(slot) = assigned_slot {
slot.assign_slottables();
}
// Step 13. If parents 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.is_in_a_shadow_tree() {
if let Some(slot_element) = parent.downcast::<HTMLSlotElement>() {
if !slot_element.has_assigned_nodes() {
ScriptThread::signal_a_slot_change(slot_element);
}
}
}
// Step 14. If node has an inclusive descendant that is a slot:
let has_slot_descendant = node
.traverse_preorder(ShadowIncluding::No)
.any(|elem| elem.is::<HTMLSlotElement>());
if has_slot_descendant {
// Step 14.1 Run assign slottables for a tree with parents root.
parent
.GetRootNode(&GetRootNodeOptions::empty())
.assign_slottables_for_a_tree();
// Step 14.2 Run assign slottables for a tree with node.
node.assign_slottables_for_a_tree();
}
// Step 11. transient registered observers
// Step 12.
if let SuppressObserver::Unsuppressed = suppress_observers {