Skip to content

Commit e281e3a

Browse files
gmtaAtkinsSJ
authored andcommitted
LibWeb: Move mutation observers from IntrusiveList to GC::RootVector
We need to prevent these mutation observers from being garbage collected, and since they are only part of SimilarOriginWindowAgent and themselves as part of the intrusive list, nobody is visiting them. Make the list of pending mutation observers a GC::RootVector so we keep them alive until they have been processed in the microtask. Restores 1400+ WPT subtest passes in `dom/nodes/Element-classlist.html`.
1 parent 150828a commit e281e3a

File tree

4 files changed

+6
-19
lines changed

4 files changed

+6
-19
lines changed

Libraries/LibWeb/Bindings/MainThreadVM.cpp

Lines changed: 1 addition & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -731,15 +731,8 @@ void queue_mutation_observer_microtask(DOM::Document const& document)
731731
surrounding_agent.mutation_observer_microtask_queued = false;
732732

733733
// 2. Let notifySet be a clone of the surrounding agent’s pending mutation observers.
734-
GC::RootVector<DOM::MutationObserver*> notify_set(heap);
735-
for (auto& observer : surrounding_agent.pending_mutation_observers)
736-
notify_set.append(&observer);
737-
738734
// 3. Empty the surrounding agent’s pending mutation observers.
739-
// NB: We instead do this at the end of the microtask. Steps 2 and 3 are equivalent to moving
740-
// surrounding_agent.pending_mutation_observers, but it's unmovable. Actually copying the MutationObservers
741-
// causes issues, so for now, keep notify_set as pointers and defer this step until after we've finished
742-
// using the notify_set.
735+
auto notify_set = move(surrounding_agent.pending_mutation_observers);
743736

744737
// 4. Let signalSet be a clone of the surrounding agent’s signal slots.
745738
// 5. Empty the surrounding agent’s signal slots.
@@ -788,9 +781,6 @@ void queue_mutation_observer_microtask(DOM::Document const& document)
788781
event_init.bubbles = true;
789782
slot->dispatch_event(DOM::Event::create(slot->realm(), HTML::EventNames::slotchange, event_init));
790783
}
791-
792-
// NB: Step 3, done later.
793-
surrounding_agent.pending_mutation_observers.clear();
794784
}));
795785
}
796786

Libraries/LibWeb/DOM/MutationObserver.h

Lines changed: 0 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -64,11 +64,6 @@ class MutationObserver final : public Bindings::PlatformObject {
6464

6565
// https://dom.spec.whatwg.org/#concept-mo-queue
6666
Vector<GC::Ref<MutationRecord>> m_record_queue;
67-
68-
IntrusiveListNode<MutationObserver> m_list_node;
69-
70-
public:
71-
using List = IntrusiveList<&MutationObserver::m_list_node>;
7267
};
7368

7469
// https://dom.spec.whatwg.org/#registered-observer

Libraries/LibWeb/HTML/Scripting/SimilarOriginWindowAgent.cpp

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -14,7 +14,7 @@ namespace Web::HTML {
1414
NonnullOwnPtr<SimilarOriginWindowAgent> SimilarOriginWindowAgent::create(GC::Heap& heap)
1515
{
1616
// See 'creating an agent' step in: https://html.spec.whatwg.org/multipage/webappapis.html#obtain-similar-origin-window-agent
17-
auto agent = adopt_own(*new SimilarOriginWindowAgent(CanBlock::No));
17+
auto agent = adopt_own(*new SimilarOriginWindowAgent(heap, CanBlock::No));
1818
agent->event_loop = heap.allocate<HTML::EventLoop>(HTML::EventLoop::Type::Window);
1919
return agent;
2020
}

Libraries/LibWeb/HTML/Scripting/SimilarOriginWindowAgent.h

Lines changed: 4 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,6 @@
11
/*
22
* Copyright (c) 2025, Shannon Booth <shannon@serenityos.org>
3+
* Copyright (c) 2025, Jelle Raaijmakers <jelle@ladybird.org>
34
*
45
* SPDX-License-Identifier: BSD-2-Clause
56
*/
@@ -29,7 +30,7 @@ struct SimilarOriginWindowAgent : public Agent {
2930

3031
// https://dom.spec.whatwg.org/#mutation-observer-list
3132
// Each similar-origin window agent also has pending mutation observers (a set of zero or more MutationObserver objects), which is initially empty.
32-
DOM::MutationObserver::List pending_mutation_observers;
33+
GC::RootVector<GC::Ref<DOM::MutationObserver>> pending_mutation_observers;
3334

3435
// https://html.spec.whatwg.org/multipage/custom-elements.html#custom-element-reactions-stack
3536
// Each similar-origin window agent has a custom element reactions stack, which is initially empty.
@@ -45,8 +46,9 @@ struct SimilarOriginWindowAgent : public Agent {
4546
Vector<GC::Root<DOM::Element>> const& current_element_queue() const { return custom_element_reactions_stack.element_queue_stack.last(); }
4647

4748
private:
48-
explicit SimilarOriginWindowAgent(CanBlock can_block)
49+
SimilarOriginWindowAgent(GC::Heap& heap, CanBlock can_block)
4950
: Agent(can_block)
51+
, pending_mutation_observers(heap)
5052
{
5153
}
5254
};

0 commit comments

Comments
 (0)