Skip to content

Commit

Permalink
LibWeb: Skip pending :has() invalidations if there are no :has()
Browse files Browse the repository at this point in the history
`invalidate_style()` already tries to avoid scheduling invalidation for
`:has()` by checking result of `may_have_has_selectors()`, but it might
still result in unnecessary work because `may_have_has_selectors()`
does not force building of rules cache. This change adds
`have_has_selectors()` that forces building of rules cache and is
invoked in `update_style()` to double-check whether we actually need to
process scheduled `:has()` invalidations.

This allows to skip ~100000 ancestor traversals on this WPT test:
https://wpt.live/html/select/options-length-too-large.html
  • Loading branch information
kalenikaliaksandr authored and awesomekling committed Feb 11, 2025
1 parent 90ba4b1 commit 875a714
Show file tree
Hide file tree
Showing 3 changed files with 18 additions and 1 deletion.
6 changes: 6 additions & 0 deletions Libraries/LibWeb/CSS/StyleComputer.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -3172,4 +3172,10 @@ bool StyleComputer::may_have_has_selectors() const
return m_selector_insights->has_has_selectors;
}

bool StyleComputer::have_has_selectors() const
{
build_rule_cache_if_needed();
return m_selector_insights->has_has_selectors;
}

}
1 change: 1 addition & 0 deletions Libraries/LibWeb/CSS/StyleComputer.h
Original file line number Diff line number Diff line change
Expand Up @@ -177,6 +177,7 @@ class StyleComputer {
void collect_animation_into(DOM::Element&, Optional<CSS::Selector::PseudoElement::Type>, GC::Ref<Animations::KeyframeEffect> animation, ComputedProperties&, AnimationRefresh = AnimationRefresh::No) const;

[[nodiscard]] bool may_have_has_selectors() const;
[[nodiscard]] bool have_has_selectors() const;

size_t number_of_css_font_faces_with_loading_in_progress() const;

Expand Down
12 changes: 11 additions & 1 deletion Libraries/LibWeb/DOM/Document.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -1665,12 +1665,22 @@ void Document::invalidate_style_of_elements_affected_by_has()
return;
}

ScopeGuard clear_pending_nodes_guard = [&] {
m_pending_nodes_for_style_invalidation_due_to_presence_of_has.clear();
};

// It's ok to call have_has_selectors() instead of may_have_has_selectors() here and force
// rule cache build, because it's going to be build soon anyway, since we could get here
// only from update_style().
if (!style_computer().have_has_selectors()) {
return;
}

for (auto const& node : m_pending_nodes_for_style_invalidation_due_to_presence_of_has) {
if (node.is_null())
continue;
node->invalidate_ancestors_affected_by_has_in_subject_position();
}
m_pending_nodes_for_style_invalidation_due_to_presence_of_has.clear();

// Take care of elements that affected by :has() in non-subject position, i.e., ".a:has(.b) > .c".
// Elements affected by :has() in subject position, i.e., ".a:has(.b)", are handled by
Expand Down

0 comments on commit 875a714

Please sign in to comment.