LibWeb/DOM: Stop adding duplicates to the agent's signal_slots

We use a Vector for this, but its spec definition is an ordered set.
That means we need to ensure we don't add duplicates. This fixes issues
where we would send slotchange events multiple times to the same
HTMLSlotElement.
This commit is contained in:
Sam Atkins 2025-11-21 13:48:43 +00:00 committed by Andreas Kling
parent 6e17503423
commit e691f0e10f
Notes: github-actions[bot] 2025-11-21 15:21:07 +00:00
2 changed files with 21 additions and 19 deletions

View file

@ -256,7 +256,10 @@ void assign_a_slot(Slottable const& slottable)
void signal_a_slot_change(GC::Ref<HTML::HTMLSlotElement> slottable)
{
// 1. Append slot to slots relevant agents signal slots.
HTML::relevant_similar_origin_window_agent(slottable).signal_slots.append(slottable);
// NB: signal_slots is supposed to be a set, so ensure the slottable is not already there.
auto& signal_slots = HTML::relevant_similar_origin_window_agent(slottable).signal_slots;
if (!signal_slots.contains_slow(slottable))
signal_slots.append(slottable);
// 2. Queue a mutation observer microtask.
Bindings::queue_mutation_observer_microtask(slottable->document());

View file

@ -2,16 +2,15 @@ Harness status: OK
Found 32 tests
16 Pass
16 Fail
Fail slotchange event must fire on a default slot element inside an open shadow root in a document
Fail slotchange event must fire on a default slot element inside a closed shadow root in a document
Fail slotchange event must fire on a default slot element inside an open shadow root not in a document
Fail slotchange event must fire on a default slot element inside a closed shadow root not in a document
Fail slotchange event must fire on a named slot element insidean open shadow root in a document
Fail slotchange event must fire on a named slot element insidea closed shadow root in a document
Fail slotchange event must fire on a named slot element insidean open shadow root not in a document
Fail slotchange event must fire on a named slot element insidea closed shadow root not in a document
32 Pass
Pass slotchange event must fire on a default slot element inside an open shadow root in a document
Pass slotchange event must fire on a default slot element inside a closed shadow root in a document
Pass slotchange event must fire on a default slot element inside an open shadow root not in a document
Pass slotchange event must fire on a default slot element inside a closed shadow root not in a document
Pass slotchange event must fire on a named slot element insidean open shadow root in a document
Pass slotchange event must fire on a named slot element insidea closed shadow root in a document
Pass slotchange event must fire on a named slot element insidean open shadow root not in a document
Pass slotchange event must fire on a named slot element insidea closed shadow root not in a document
Pass slotchange event must not fire on a slot element inside an open shadow root in a document when another slot's assigned nodes change
Pass slotchange event must not fire on a slot element inside a closed shadow root in a document when another slot's assigned nodes change
Pass slotchange event must not fire on a slot element inside an open shadow root not in a document when another slot's assigned nodes change
@ -20,14 +19,14 @@ Pass slotchange event must fire on a slot element when a shadow host has a slott
Pass slotchange event must fire on a slot element when a shadow host has a slottable and the slot was inserted and must not fire when the shadow host was mutated after the slot was removed inside a closed shadow root in a document
Pass slotchange event must fire on a slot element when a shadow host has a slottable and the slot was inserted and must not fire when the shadow host was mutated after the slot was removed inside an open shadow root not in a document
Pass slotchange event must fire on a slot element when a shadow host has a slottable and the slot was inserted and must not fire when the shadow host was mutated after the slot was removed inside a closed shadow root not in a document
Fail slotchange event must fire on a slot element inside an open shadow root in a document even if the slot was removed immediately after the assigned nodes were mutated
Fail slotchange event must fire on a slot element inside a closed shadow root in a document even if the slot was removed immediately after the assigned nodes were mutated
Fail slotchange event must fire on a slot element inside an open shadow root not in a document even if the slot was removed immediately after the assigned nodes were mutated
Fail slotchange event must fire on a slot element inside a closed shadow root not in a document even if the slot was removed immediately after the assigned nodes were mutated
Fail slotchange event must fire on a slot element inside an open shadow root in a document when innerHTML modifies the children of the shadow host
Fail slotchange event must fire on a slot element inside a closed shadow root in a document when innerHTML modifies the children of the shadow host
Fail slotchange event must fire on a slot element inside an open shadow root not in a document when innerHTML modifies the children of the shadow host
Fail slotchange event must fire on a slot element inside a closed shadow root not in a document when innerHTML modifies the children of the shadow host
Pass slotchange event must fire on a slot element inside an open shadow root in a document even if the slot was removed immediately after the assigned nodes were mutated
Pass slotchange event must fire on a slot element inside a closed shadow root in a document even if the slot was removed immediately after the assigned nodes were mutated
Pass slotchange event must fire on a slot element inside an open shadow root not in a document even if the slot was removed immediately after the assigned nodes were mutated
Pass slotchange event must fire on a slot element inside a closed shadow root not in a document even if the slot was removed immediately after the assigned nodes were mutated
Pass slotchange event must fire on a slot element inside an open shadow root in a document when innerHTML modifies the children of the shadow host
Pass slotchange event must fire on a slot element inside a closed shadow root in a document when innerHTML modifies the children of the shadow host
Pass slotchange event must fire on a slot element inside an open shadow root not in a document when innerHTML modifies the children of the shadow host
Pass slotchange event must fire on a slot element inside a closed shadow root not in a document when innerHTML modifies the children of the shadow host
Pass slotchange event must fire on a slot element inside an open shadow root in a document when nested slots's contents change
Pass slotchange event must fire on a slot element inside a closed shadow root in a document when nested slots's contents change
Pass slotchange event must fire on a slot element inside an open shadow root not in a document when nested slots's contents change