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.
This commit is contained in:
Andreas Kling 2024-08-02 20:41:16 +02:00 committed by Andreas Kling
parent 936b76f36e
commit e746b2b133
Notes: github-actions[bot] 2024-08-02 20:00:37 +00:00
3 changed files with 26 additions and 1 deletions

View file

@ -5342,4 +5342,14 @@ void Document::reset_cursor_blink_cycle()
m_cursor_position->node()->paintable()->set_needs_display();
}
JS::GCPtr<HTML::Navigable> Document::cached_navigable()
{
return m_cached_navigable.ptr();
}
void Document::set_cached_navigable(JS::GCPtr<HTML::Navigable> navigable)
{
m_cached_navigable = navigable.ptr();
}
}

View file

@ -696,6 +696,10 @@ public:
bool cursor_blink_state() const { return m_cursor_blink_state; }
void user_did_edit_document_text(Badge<EditEventHandler>);
// 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<HTML::Navigable> cached_navigable();
void set_cached_navigable(JS::GCPtr<HTML::Navigable>);
protected:
virtual void initialize(JS::Realm&) override;
@ -965,6 +969,9 @@ private:
JS::GCPtr<DOM::Position> m_cursor_position;
RefPtr<Core::Timer> 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<HTML::Navigable> m_cached_navigable;
};
template<>

View file

@ -362,9 +362,17 @@ void Node::set_node_value(Optional<String> const& maybe_value)
// https://html.spec.whatwg.org/multipage/document-sequences.html#node-navigable
JS::GCPtr<HTML::Navigable> Node::navigable() const
{
auto& document = const_cast<Document&>(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&>(document()));
auto navigable = HTML::Navigable::navigable_with_active_document(document);
document.set_cached_navigable(navigable);
return navigable;
}
void Node::invalidate_style()