From fa25f7008656da7e5bb6508915bb8668aa8f8e79 Mon Sep 17 00:00:00 2001 From: Andreas Kling Date: Tue, 23 May 2023 12:28:16 +0200 Subject: [PATCH] LibWeb: Make LiveNodeList faster when it only cares about children Same optimization as HTMLCollection, ported to LiveNodeList. --- .../Libraries/LibWeb/DOM/LiveNodeList.cpp | 26 ++++++++++++------- Userland/Libraries/LibWeb/DOM/LiveNodeList.h | 10 +++++-- Userland/Libraries/LibWeb/DOM/Node.cpp | 4 +-- 3 files changed, 27 insertions(+), 13 deletions(-) diff --git a/Userland/Libraries/LibWeb/DOM/LiveNodeList.cpp b/Userland/Libraries/LibWeb/DOM/LiveNodeList.cpp index 7ce6603371..ffc19db559 100644 --- a/Userland/Libraries/LibWeb/DOM/LiveNodeList.cpp +++ b/Userland/Libraries/LibWeb/DOM/LiveNodeList.cpp @@ -10,15 +10,16 @@ namespace Web::DOM { -WebIDL::ExceptionOr> LiveNodeList::create(JS::Realm& realm, Node& root, Function filter) +WebIDL::ExceptionOr> LiveNodeList::create(JS::Realm& realm, Node& root, Scope scope, Function filter) { - return MUST_OR_THROW_OOM(realm.heap().allocate(realm, realm, root, move(filter))); + return MUST_OR_THROW_OOM(realm.heap().allocate(realm, realm, root, scope, move(filter))); } -LiveNodeList::LiveNodeList(JS::Realm& realm, Node& root, Function filter) +LiveNodeList::LiveNodeList(JS::Realm& realm, Node& root, Scope scope, Function filter) : NodeList(realm) , m_root(root) , m_filter(move(filter)) + , m_scope(scope) { } @@ -33,12 +34,19 @@ void LiveNodeList::visit_edges(Cell::Visitor& visitor) JS::MarkedVector LiveNodeList::collection() const { JS::MarkedVector nodes(heap()); - m_root->for_each_in_inclusive_subtree([&](auto& node) { - if (m_filter(node)) - nodes.append(const_cast(&node)); - - return IterationDecision::Continue; - }); + if (m_scope == Scope::Descendants) { + m_root->for_each_in_subtree([&](auto& node) { + if (m_filter(node)) + nodes.append(const_cast(&node)); + return IterationDecision::Continue; + }); + } else { + m_root->for_each_child([&](auto& node) { + if (m_filter(node)) + nodes.append(const_cast(&node)); + return IterationDecision::Continue; + }); + } return nodes; } diff --git a/Userland/Libraries/LibWeb/DOM/LiveNodeList.h b/Userland/Libraries/LibWeb/DOM/LiveNodeList.h index b5d242e0b1..f9d527519a 100644 --- a/Userland/Libraries/LibWeb/DOM/LiveNodeList.h +++ b/Userland/Libraries/LibWeb/DOM/LiveNodeList.h @@ -18,7 +18,12 @@ class LiveNodeList final : public NodeList { WEB_PLATFORM_OBJECT(LiveNodeList, NodeList); public: - static WebIDL::ExceptionOr> create(JS::Realm&, Node& root, Function filter); + enum class Scope { + Children, + Descendants, + }; + + static WebIDL::ExceptionOr> create(JS::Realm&, Node& root, Scope, Function filter); virtual ~LiveNodeList() override; virtual u32 length() const override; @@ -27,7 +32,7 @@ public: virtual bool is_supported_property_index(u32) const override; private: - LiveNodeList(JS::Realm&, Node& root, Function filter); + LiveNodeList(JS::Realm&, Node& root, Scope, Function filter); virtual void visit_edges(Cell::Visitor&) override; @@ -35,6 +40,7 @@ private: JS::NonnullGCPtr m_root; Function m_filter; + Scope m_scope { Scope::Descendants }; }; } diff --git a/Userland/Libraries/LibWeb/DOM/Node.cpp b/Userland/Libraries/LibWeb/DOM/Node.cpp index 0a080b86c1..dd445705c5 100644 --- a/Userland/Libraries/LibWeb/DOM/Node.cpp +++ b/Userland/Libraries/LibWeb/DOM/Node.cpp @@ -932,8 +932,8 @@ Element* Node::parent_or_shadow_host_element() JS::NonnullGCPtr Node::child_nodes() { if (!m_child_nodes) { - m_child_nodes = LiveNodeList::create(realm(), *this, [this](auto& node) { - return is_parent_of(node); + m_child_nodes = LiveNodeList::create(realm(), *this, LiveNodeList::Scope::Children, [](auto&) { + return true; }).release_value_but_fixme_should_propagate_errors(); } return *m_child_nodes;