mirror of
https://github.com/LadybirdBrowser/ladybird.git
synced 2024-11-08 12:56:23 +03:00
LibWeb: Let HTMLCollection cache its element list
Use the new DOM tree version mechanism to allow HTMLCollection to remember its internal list of elements instead of rebuilding it on every access. This avoids thousands of full DOM walks while loading our GitHub repo. ~15% speed-up on jQuery subtests in Speedometer 3.0 :^)
This commit is contained in:
parent
cf60f52a78
commit
6bb4a2bfaa
Notes:
sideshowbarker
2024-07-17 00:49:59 +09:00
Author: https://github.com/awesomekling Commit: https://github.com/SerenityOS/serenity/commit/6bb4a2bfaa Pull-request: https://github.com/SerenityOS/serenity/pull/23640 Reviewed-by: https://github.com/AtkinsSJ ✅ Reviewed-by: https://github.com/tcl3 Reviewed-by: https://github.com/trflynn89
@ -6,6 +6,7 @@
|
||||
*/
|
||||
|
||||
#include <LibWeb/Bindings/Intrinsics.h>
|
||||
#include <LibWeb/DOM/Document.h>
|
||||
#include <LibWeb/DOM/Element.h>
|
||||
#include <LibWeb/DOM/HTMLCollection.h>
|
||||
#include <LibWeb/DOM/ParentNode.h>
|
||||
@ -45,24 +46,33 @@ void HTMLCollection::visit_edges(Cell::Visitor& visitor)
|
||||
{
|
||||
Base::visit_edges(visitor);
|
||||
visitor.visit(m_root);
|
||||
for (auto& element : m_cached_elements)
|
||||
visitor.visit(element);
|
||||
}
|
||||
|
||||
JS::MarkedVector<Element*> HTMLCollection::collect_matching_elements() const
|
||||
{
|
||||
JS::MarkedVector<Element*> elements(m_root->heap());
|
||||
if (m_scope == Scope::Descendants) {
|
||||
m_root->for_each_in_subtree_of_type<Element>([&](auto& element) {
|
||||
if (m_filter(element))
|
||||
elements.append(const_cast<Element*>(&element));
|
||||
return IterationDecision::Continue;
|
||||
});
|
||||
} else {
|
||||
m_root->for_each_child_of_type<Element>([&](auto& element) {
|
||||
if (m_filter(element))
|
||||
elements.append(const_cast<Element*>(&element));
|
||||
return IterationDecision::Continue;
|
||||
});
|
||||
if (m_cached_dom_tree_version != root()->document().dom_tree_version()) {
|
||||
m_cached_elements.clear();
|
||||
if (m_scope == Scope::Descendants) {
|
||||
m_root->for_each_in_subtree_of_type<Element>([&](auto& element) {
|
||||
if (m_filter(element))
|
||||
m_cached_elements.append(element);
|
||||
return IterationDecision::Continue;
|
||||
});
|
||||
} else {
|
||||
m_root->for_each_child_of_type<Element>([&](auto& element) {
|
||||
if (m_filter(element))
|
||||
m_cached_elements.append(element);
|
||||
return IterationDecision::Continue;
|
||||
});
|
||||
}
|
||||
m_cached_dom_tree_version = root()->document().dom_tree_version();
|
||||
}
|
||||
|
||||
JS::MarkedVector<Element*> elements(heap());
|
||||
for (auto& element : m_cached_elements)
|
||||
elements.append(element);
|
||||
return elements;
|
||||
}
|
||||
|
||||
|
@ -60,6 +60,9 @@ protected:
|
||||
private:
|
||||
virtual void visit_edges(Cell::Visitor&) override;
|
||||
|
||||
mutable u64 m_cached_dom_tree_version { 0 };
|
||||
mutable Vector<JS::NonnullGCPtr<Element>> m_cached_elements;
|
||||
|
||||
JS::NonnullGCPtr<ParentNode> m_root;
|
||||
Function<bool(Element const&)> m_filter;
|
||||
|
||||
|
Loading…
Reference in New Issue
Block a user