From e746b2b133758b3552ae07941cc6d14332c64d59 Mon Sep 17 00:00:00 2001 From: Andreas Kling Date: Fri, 2 Aug 2024 20:41:16 +0200 Subject: [PATCH] LibWeb: Cache the Document's node navigable when possible To avoid expensive lookups, we now cache a weak pointer from document to the last known node navigable. Before using the cache, we validate that the document is still the navigable's active document. --- Userland/Libraries/LibWeb/DOM/Document.cpp | 10 ++++++++++ Userland/Libraries/LibWeb/DOM/Document.h | 7 +++++++ Userland/Libraries/LibWeb/DOM/Node.cpp | 10 +++++++++- 3 files changed, 26 insertions(+), 1 deletion(-) diff --git a/Userland/Libraries/LibWeb/DOM/Document.cpp b/Userland/Libraries/LibWeb/DOM/Document.cpp index 40f5c733f6c2..0e70001f0542 100644 --- a/Userland/Libraries/LibWeb/DOM/Document.cpp +++ b/Userland/Libraries/LibWeb/DOM/Document.cpp @@ -5342,4 +5342,14 @@ void Document::reset_cursor_blink_cycle() m_cursor_position->node()->paintable()->set_needs_display(); } +JS::GCPtr Document::cached_navigable() +{ + return m_cached_navigable.ptr(); +} + +void Document::set_cached_navigable(JS::GCPtr navigable) +{ + m_cached_navigable = navigable.ptr(); +} + } diff --git a/Userland/Libraries/LibWeb/DOM/Document.h b/Userland/Libraries/LibWeb/DOM/Document.h index edc773a02ea4..e9fe535d6bae 100644 --- a/Userland/Libraries/LibWeb/DOM/Document.h +++ b/Userland/Libraries/LibWeb/DOM/Document.h @@ -696,6 +696,10 @@ class Document bool cursor_blink_state() const { return m_cursor_blink_state; } void user_did_edit_document_text(Badge); + // Cached pointer to the last known node navigable. + // If this document is currently the "active document" of the cached navigable, the cache is still valid. + JS::GCPtr cached_navigable(); + void set_cached_navigable(JS::GCPtr); protected: virtual void initialize(JS::Realm&) override; @@ -965,6 +969,9 @@ class Document JS::GCPtr m_cursor_position; RefPtr m_cursor_blink_timer; bool m_cursor_blink_state { false }; + + // NOTE: This is WeakPtr, not GCPtr, on purpose. We don't want the document to keep some old detached navigable alive. + WeakPtr m_cached_navigable; }; template<> diff --git a/Userland/Libraries/LibWeb/DOM/Node.cpp b/Userland/Libraries/LibWeb/DOM/Node.cpp index db1d643fccc4..828917dfa330 100644 --- a/Userland/Libraries/LibWeb/DOM/Node.cpp +++ b/Userland/Libraries/LibWeb/DOM/Node.cpp @@ -362,9 +362,17 @@ void Node::set_node_value(Optional const& maybe_value) // https://html.spec.whatwg.org/multipage/document-sequences.html#node-navigable JS::GCPtr Node::navigable() const { + auto& document = const_cast(this->document()); + if (auto cached_navigable = document.cached_navigable()) { + if (cached_navigable->active_document() == &document) + return cached_navigable; + } + // To get the node navigable of a node node, return the navigable whose active document is node's node document, // or null if there is no such navigable. - return HTML::Navigable::navigable_with_active_document(const_cast(document())); + auto navigable = HTML::Navigable::navigable_with_active_document(document); + document.set_cached_navigable(navigable); + return navigable; } void Node::invalidate_style()