LibWeb: Avoid iterating in children_changed unless necessary

Previously when one child of an element changed we would iterate over
every child to check whether they needed to be invalidated because they
relied on tree counting functions.

We now skip this in most cases by only doing it when at least one child
relies on tree counting functions.
This commit is contained in:
Callum Law 2025-10-21 13:39:42 +13:00 committed by Jelle Raaijmakers
parent 6afd39b16a
commit a4184fda1f
Notes: github-actions[bot] 2025-10-21 23:02:12 +00:00
2 changed files with 20 additions and 9 deletions

View file

@ -1395,14 +1395,15 @@ void Element::children_changed(ChildrenChangedMetadata const* metadata)
{
Node::children_changed(metadata);
set_needs_style_update(true);
for_each_child([&](DOM::Node& child) {
if (auto* element = as_if<DOM::Element>(child); element && element->style_uses_tree_counting_function()) {
element->set_needs_style_update(true);
set_child_needs_style_update(true);
}
return IterationDecision::Continue;
});
if (child_style_uses_tree_counting_function()) {
for_each_child_of_type<Element>([&](Element& element) {
element.set_needs_style_update(true);
set_child_needs_style_update(true);
return IterationDecision::Continue;
});
}
}
void Element::set_pseudo_element_node(Badge<Layout::TreeBuilder>, CSS::PseudoElement pseudo_element, GC::Ptr<Layout::NodeWithStyle> pseudo_element_node)

View file

@ -266,8 +266,17 @@ public:
void set_style_uses_attr_css_function() { m_style_uses_attr_css_function = true; }
bool style_uses_var_css_function() const { return m_style_uses_var_css_function; }
void set_style_uses_var_css_function() { m_style_uses_var_css_function = true; }
bool style_uses_tree_counting_function() { return m_style_uses_tree_counting_function; }
void set_style_uses_tree_counting_function() { m_style_uses_tree_counting_function = true; }
bool style_uses_tree_counting_function() const { return m_style_uses_tree_counting_function; }
void set_style_uses_tree_counting_function()
{
if (auto parent = parent_element())
parent->set_child_style_uses_tree_counting_function();
m_style_uses_tree_counting_function = true;
}
bool child_style_uses_tree_counting_function() const { return m_child_style_uses_tree_counting_function; }
void set_child_style_uses_tree_counting_function() { m_child_style_uses_tree_counting_function = true; }
// NOTE: The function is wrapped in a GC::HeapFunction immediately.
HTML::TaskID queue_an_element_task(HTML::Task::Source, Function<void()>);
@ -637,6 +646,7 @@ private:
bool m_style_uses_attr_css_function : 1 { false };
bool m_style_uses_var_css_function : 1 { false };
bool m_style_uses_tree_counting_function : 1 { false };
bool m_child_style_uses_tree_counting_function : 1 { false };
bool m_affected_by_has_pseudo_class_in_subject_position : 1 { false };
bool m_affected_by_has_pseudo_class_in_non_subject_position : 1 { false };
bool m_affected_by_direct_sibling_combinator : 1 { false };