From dc6e625680a5499c7253bb26089c69453db71436 Mon Sep 17 00:00:00 2001 From: Andreas Kling Date: Sun, 18 Sep 2022 00:42:33 +0200 Subject: [PATCH] LibWeb: Make ParentNode.children vend the same HTMLCollection every time Instead of creating a new HTMLCollection every time you access .children, we now follow the spec and vend the same object. This was annoyingly difficult before, and trivial now that the DOM is garbage-collected. :^) --- Userland/Libraries/LibWeb/DOM/ParentNode.cpp | 17 ++++++++++++----- Userland/Libraries/LibWeb/DOM/ParentNode.h | 5 +++++ 2 files changed, 17 insertions(+), 5 deletions(-) diff --git a/Userland/Libraries/LibWeb/DOM/ParentNode.cpp b/Userland/Libraries/LibWeb/DOM/ParentNode.cpp index d3610752b58..80bb2141517 100644 --- a/Userland/Libraries/LibWeb/DOM/ParentNode.cpp +++ b/Userland/Libraries/LibWeb/DOM/ParentNode.cpp @@ -84,15 +84,22 @@ u32 ParentNode::child_element_count() const return count; } +void ParentNode::visit_edges(Cell::Visitor& visitor) +{ + Base::visit_edges(visitor); + visitor.visit(m_children); +} + // https://dom.spec.whatwg.org/#dom-parentnode-children JS::NonnullGCPtr ParentNode::children() { // The children getter steps are to return an HTMLCollection collection rooted at this matching only element children. - // FIXME: This should return the same HTMLCollection object every time, - // but that would cause a reference cycle since HTMLCollection refs the root. - return HTMLCollection::create(*this, [this](Element const& element) { - return is_parent_of(element); - }); + if (!m_children) { + m_children = HTMLCollection::create(*this, [this](Element const& element) { + return is_parent_of(element); + }); + } + return *m_children; } // https://dom.spec.whatwg.org/#concept-getelementsbytagname diff --git a/Userland/Libraries/LibWeb/DOM/ParentNode.h b/Userland/Libraries/LibWeb/DOM/ParentNode.h index 0d2482140cf..b7822339940 100644 --- a/Userland/Libraries/LibWeb/DOM/ParentNode.h +++ b/Userland/Libraries/LibWeb/DOM/ParentNode.h @@ -45,6 +45,11 @@ protected: : Node(document, type) { } + + virtual void visit_edges(Cell::Visitor&) override; + +private: + JS::GCPtr m_children; }; template<>