LibWeb: Replace cached navigable with Navigable-maintained back-pointer
Now that Navigable directly owns its active document (m_active_document) we can have Navigable maintain a back-pointer on Document instead of using the old cache-with-validation pattern that fell back to a linear scan of all navigables via navigable_with_active_document().
This commit is contained in:
parent
2645695fdd
commit
4985dabf3d
8 changed files with 36 additions and 34 deletions
|
|
@ -4608,7 +4608,7 @@ void Document::destroy()
|
|||
// Not in the spec:
|
||||
for (auto& navigable_container : HTML::NavigableContainer::all_instances()) {
|
||||
if (&navigable_container->document() == this && navigable_container->content_navigable())
|
||||
HTML::all_navigables().remove(*navigable_container->content_navigable());
|
||||
navigable_container->content_navigable()->remove_from_all_navigables();
|
||||
}
|
||||
|
||||
// 9. Set document's node navigable's active session history entry's document state's document to null.
|
||||
|
|
@ -7323,14 +7323,14 @@ GC::Ptr<DOM::Document> Document::container_document() const
|
|||
return node_navigable->container_document();
|
||||
}
|
||||
|
||||
GC::Ptr<HTML::Navigable> Document::cached_navigable()
|
||||
GC::Ptr<HTML::Navigable> Document::navigable() const
|
||||
{
|
||||
return m_cached_navigable.ptr();
|
||||
return m_navigable.ptr();
|
||||
}
|
||||
|
||||
void Document::set_cached_navigable(GC::Ptr<HTML::Navigable> navigable)
|
||||
void Document::set_navigable(GC::Ptr<HTML::Navigable> navigable)
|
||||
{
|
||||
m_cached_navigable = navigable.ptr();
|
||||
m_navigable = navigable.ptr();
|
||||
}
|
||||
|
||||
void Document::notify_css_background_image_loaded()
|
||||
|
|
|
|||
|
|
@ -901,10 +901,10 @@ public:
|
|||
|
||||
bool cursor_blink_state() const { return m_cursor_blink_state; }
|
||||
|
||||
// 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.
|
||||
GC::Ptr<HTML::Navigable> cached_navigable();
|
||||
void set_cached_navigable(GC::Ptr<HTML::Navigable>);
|
||||
// Back-pointer to the navigable whose active document is this document.
|
||||
// Maintained by Navigable when it sets/clears its active document.
|
||||
GC::Ptr<HTML::Navigable> navigable() const;
|
||||
void set_navigable(GC::Ptr<HTML::Navigable>);
|
||||
|
||||
template<OneOf<Painting::Paintable, HTML::Navigable, CSS::VisualViewport, Web::EventHandler> T>
|
||||
void set_needs_repaint(Badge<T>, InvalidateDisplayList should_invalidate_display_list = InvalidateDisplayList::Yes)
|
||||
|
|
@ -1416,7 +1416,7 @@ private:
|
|||
bool m_cursor_blink_state { false };
|
||||
|
||||
// NOTE: This is GC::Weak, not GC::Ptr, on purpose. We don't want the document to keep some old detached navigable alive.
|
||||
GC::Weak<HTML::Navigable> m_cached_navigable;
|
||||
GC::Weak<HTML::Navigable> m_navigable;
|
||||
|
||||
Core::SharedVersion m_cookie_version { Core::INVALID_SHARED_VERSION };
|
||||
Optional<Core::SharedVersionIndex> m_cookie_version_index;
|
||||
|
|
|
|||
|
|
@ -398,17 +398,9 @@ WebIDL::ExceptionOr<void> Node::set_node_value(Optional<String> const& maybe_val
|
|||
// https://html.spec.whatwg.org/multipage/document-sequences.html#node-navigable
|
||||
GC::Ptr<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.
|
||||
auto navigable = HTML::Navigable::navigable_with_active_document(document);
|
||||
document.set_cached_navigable(navigable);
|
||||
return navigable;
|
||||
return document().navigable();
|
||||
}
|
||||
|
||||
[[maybe_unused]] static StringView to_string(StyleInvalidationReason reason)
|
||||
|
|
|
|||
|
|
@ -299,6 +299,18 @@ Navigable::Navigable(GC::Ref<Page> page, bool is_svg_page)
|
|||
|
||||
Navigable::~Navigable() = default;
|
||||
|
||||
void Navigable::set_has_been_destroyed()
|
||||
{
|
||||
m_has_been_destroyed = true;
|
||||
}
|
||||
|
||||
void Navigable::remove_from_all_navigables()
|
||||
{
|
||||
if (m_active_document)
|
||||
m_active_document->set_navigable(nullptr);
|
||||
all_navigables().remove(*this);
|
||||
}
|
||||
|
||||
void Navigable::finalize()
|
||||
{
|
||||
all_navigables().remove(*this);
|
||||
|
|
@ -369,15 +381,6 @@ void Navigable::clear_navigation_load_event_guard()
|
|||
m_navigation_load_event_guard.clear();
|
||||
}
|
||||
|
||||
GC::Ptr<Navigable> Navigable::navigable_with_active_document(GC::Ref<DOM::Document> document)
|
||||
{
|
||||
for (auto navigable : all_navigables()) {
|
||||
if (navigable->active_document() == document)
|
||||
return navigable;
|
||||
}
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
// https://html.spec.whatwg.org/multipage/document-sequences.html#initialize-the-navigable
|
||||
void Navigable::initialize_navigable(GC::Ref<DocumentState> document_state, GC::Ptr<Navigable> parent, GC::Ref<DOM::Document> document)
|
||||
{
|
||||
|
|
@ -401,6 +404,7 @@ void Navigable::initialize_navigable(GC::Ref<DocumentState> document_state, GC::
|
|||
// 4. Set navigable's active session history entry to entry.
|
||||
m_active_session_history_entry = entry;
|
||||
m_active_document = document;
|
||||
document->set_navigable(this);
|
||||
|
||||
// 5. Set navigable's parent to parent.
|
||||
m_parent = parent;
|
||||
|
|
@ -441,7 +445,10 @@ void Navigable::activate_history_entry(GC::Ptr<SessionHistoryEntry> entry, GC::R
|
|||
|
||||
// 4. Set navigable's active session history entry to entry.
|
||||
m_active_session_history_entry = entry;
|
||||
if (m_active_document && m_active_document != new_document)
|
||||
m_active_document->set_navigable(nullptr);
|
||||
m_active_document = new_document;
|
||||
new_document->set_navigable(this);
|
||||
|
||||
// 5. Make active newDocument.
|
||||
new_document->make_active();
|
||||
|
|
@ -485,7 +492,11 @@ Optional<UniqueNodeID> Navigable::active_document_id() const
|
|||
|
||||
void Navigable::set_active_document(GC::Ptr<DOM::Document> document)
|
||||
{
|
||||
if (m_active_document && m_active_document != document)
|
||||
m_active_document->set_navigable(nullptr);
|
||||
m_active_document = document;
|
||||
if (document)
|
||||
document->set_navigable(this);
|
||||
|
||||
VERIFY(m_active_session_history_entry);
|
||||
Optional<UniqueNodeID> document_id;
|
||||
|
|
|
|||
|
|
@ -128,8 +128,6 @@ public:
|
|||
|
||||
GC::Ptr<Navigable> find_a_navigable_by_target_name(StringView name);
|
||||
|
||||
static GC::Ptr<Navigable> navigable_with_active_document(GC::Ref<DOM::Document>);
|
||||
|
||||
enum class Traversal {
|
||||
Tag
|
||||
};
|
||||
|
|
@ -186,7 +184,8 @@ public:
|
|||
|
||||
// https://github.com/whatwg/html/issues/9690
|
||||
[[nodiscard]] bool has_been_destroyed() const { return m_has_been_destroyed; }
|
||||
void set_has_been_destroyed() { m_has_been_destroyed = true; }
|
||||
void set_has_been_destroyed();
|
||||
void remove_from_all_navigables();
|
||||
|
||||
CSSPixelPoint to_top_level_position(CSSPixelPoint);
|
||||
CSSPixelRect to_top_level_rect(CSSPixelRect const&);
|
||||
|
|
|
|||
|
|
@ -337,7 +337,7 @@ void NavigableContainer::destroy_the_child_navigable()
|
|||
document().schedule_html_parser_end_check();
|
||||
|
||||
// Not in the spec:
|
||||
HTML::all_navigables().remove(*navigable);
|
||||
navigable->remove_from_all_navigables();
|
||||
|
||||
// 6. Let parentDocState be container's node navigable's active session history entry's document state.
|
||||
auto parent_doc_state = this->navigable()->active_session_history_entry()->document_state();
|
||||
|
|
|
|||
|
|
@ -1630,7 +1630,7 @@ void TraversableNavigable::destroy_top_level_traversable()
|
|||
// FIXME: Figure out why we need to do this... we shouldn't be leaking Navigables for all time.
|
||||
// However, without this, we can keep stale destroyed traversables around.
|
||||
set_has_been_destroyed();
|
||||
all_navigables().remove(*this);
|
||||
remove_from_all_navigables();
|
||||
}
|
||||
|
||||
// https://html.spec.whatwg.org/multipage/browsing-the-web.html#finalize-a-same-document-navigation
|
||||
|
|
|
|||
|
|
@ -719,7 +719,7 @@ BrowsingContext* Window::browsing_context()
|
|||
GC::Ptr<Navigable> Window::navigable() const
|
||||
{
|
||||
// A Window's navigable is the navigable whose active document is the Window's associated Document's, or null if there is no such navigable.
|
||||
return Navigable::navigable_with_active_document(*m_associated_document);
|
||||
return m_associated_document->navigable();
|
||||
}
|
||||
|
||||
// https://html.spec.whatwg.org/multipage/system-state.html#pdf-viewer-plugin-objects
|
||||
|
|
|
|||
Loading…
Reference in a new issue