mirror of
https://github.com/LadybirdBrowser/ladybird
synced 2026-04-26 17:55:07 +02:00
LibWeb: Reduce allocations in IntersectionObserver hot path
Pre-compute per-observer values (root node, root paintable, root bounds, is_implicit_root, root_is_element) once before the per-target loop instead of recomputing them for each target. Add intersection_root_node() which returns GC::Ref<DOM::Node> without creating GC::Root wrappers. Previously, intersection_root() was called multiple times per target (in the skip condition check, in compute_intersection, and again in root_intersection_rectangle inside compute_intersection), each call creating GC::Root objects that require heap allocation via new RootImpl. Pass the pre-computed root bounds and root paintable into compute_intersection instead of having it call root_intersection_rectangle() and intersection_root() internally. For an observer watching N targets, this eliminates roughly 4N heap allocations per frame.
This commit is contained in:
committed by
Andreas Kling
parent
9abb7e4517
commit
e2d5d72f55
Notes:
github-actions[bot]
2026-03-22 19:10:45 +00:00
Author: https://github.com/awesomekling Commit: https://github.com/LadybirdBrowser/ladybird/commit/e2d5d72f55a Pull-request: https://github.com/LadybirdBrowser/ladybird/pull/8574
@@ -243,18 +243,19 @@ String IntersectionObserver::scroll_margin() const
|
||||
// https://www.w3.org/TR/intersection-observer/#intersectionobserver-intersection-root
|
||||
Variant<GC::Root<DOM::Element>, GC::Root<DOM::Document>> IntersectionObserver::intersection_root() const
|
||||
{
|
||||
// The intersection root for an IntersectionObserver is the value of its root attribute
|
||||
// if the attribute is non-null;
|
||||
if (m_root) {
|
||||
if (m_root->is_element())
|
||||
return GC::make_root(static_cast<DOM::Element&>(*m_root));
|
||||
if (m_root->is_document())
|
||||
return GC::make_root(static_cast<DOM::Document&>(*m_root));
|
||||
VERIFY_NOT_REACHED();
|
||||
}
|
||||
auto root_node = intersection_root_node();
|
||||
if (root_node->is_element())
|
||||
return GC::make_root(static_cast<DOM::Element&>(*root_node));
|
||||
return GC::make_root(static_cast<DOM::Document&>(*root_node));
|
||||
}
|
||||
|
||||
// otherwise, it is the top-level browsing context’s document node, referred to as the implicit root.
|
||||
return GC::make_root(as<HTML::Window>(HTML::relevant_global_object(*this)).page().top_level_browsing_context().active_document());
|
||||
GC::Ref<DOM::Node> IntersectionObserver::intersection_root_node() const
|
||||
{
|
||||
if (m_root)
|
||||
return *m_root;
|
||||
|
||||
// The implicit root is the top-level browsing context’s document node.
|
||||
return *as<HTML::Window>(HTML::relevant_global_object(*this)).page().top_level_browsing_context().active_document();
|
||||
}
|
||||
|
||||
// https://www.w3.org/TR/intersection-observer/#intersectionobserver-root-intersection-rectangle
|
||||
|
||||
Reference in New Issue
Block a user