LibWeb: Use fast CSS selector matching in default matches() code path

Before this change, checking if fast selector matching could be used was
only enabled in style recalculation and hover invalidation. With this
change it's enabled for all callers of SelectorEngine::matches() by
default. This way APIs like `Element.matches()` and `querySelector()`
could take advantage of this optimization.
This commit is contained in:
Aliaksandr Kalenik 2025-02-02 20:35:29 +01:00 committed by Jelle Raaijmakers
commit 0f17ad9ebc
Notes: github-actions[bot] 2025-02-03 09:29:08 +00:00
7 changed files with 59 additions and 66 deletions

View file

@ -33,6 +33,50 @@ static bool component_value_contains_nesting_selector(Parser::ComponentValue con
return false;
}
static bool can_selector_use_fast_matches(CSS::Selector const& selector)
{
for (auto const& compound_selector : selector.compound_selectors()) {
if (compound_selector.combinator != CSS::Selector::Combinator::None
&& compound_selector.combinator != CSS::Selector::Combinator::Descendant
&& compound_selector.combinator != CSS::Selector::Combinator::ImmediateChild) {
return false;
}
for (auto const& simple_selector : compound_selector.simple_selectors) {
if (simple_selector.type == CSS::Selector::SimpleSelector::Type::PseudoClass) {
auto const pseudo_class = simple_selector.pseudo_class().type;
if (pseudo_class != CSS::PseudoClass::FirstChild
&& pseudo_class != CSS::PseudoClass::LastChild
&& pseudo_class != CSS::PseudoClass::OnlyChild
&& pseudo_class != CSS::PseudoClass::Hover
&& pseudo_class != CSS::PseudoClass::Active
&& pseudo_class != CSS::PseudoClass::Focus
&& pseudo_class != CSS::PseudoClass::FocusVisible
&& pseudo_class != CSS::PseudoClass::FocusWithin
&& pseudo_class != CSS::PseudoClass::Link
&& pseudo_class != CSS::PseudoClass::AnyLink
&& pseudo_class != CSS::PseudoClass::Visited
&& pseudo_class != CSS::PseudoClass::LocalLink
&& pseudo_class != CSS::PseudoClass::Empty
&& pseudo_class != CSS::PseudoClass::Root
&& pseudo_class != CSS::PseudoClass::Enabled
&& pseudo_class != CSS::PseudoClass::Disabled
&& pseudo_class != CSS::PseudoClass::Checked) {
return false;
}
} else if (simple_selector.type != CSS::Selector::SimpleSelector::Type::TagName
&& simple_selector.type != CSS::Selector::SimpleSelector::Type::Universal
&& simple_selector.type != CSS::Selector::SimpleSelector::Type::Class
&& simple_selector.type != CSS::Selector::SimpleSelector::Type::Id
&& simple_selector.type != CSS::Selector::SimpleSelector::Type::Attribute) {
return false;
}
}
}
return true;
}
Selector::Selector(Vector<CompoundSelector>&& compound_selectors)
: m_compound_selectors(move(compound_selectors))
{
@ -88,6 +132,8 @@ Selector::Selector(Vector<CompoundSelector>&& compound_selectors)
}
collect_ancestor_hashes();
m_can_use_fast_matches = can_selector_use_fast_matches(*this);
}
void Selector::collect_ancestor_hashes()