mirror of
https://github.com/LadybirdBrowser/ladybird.git
synced 2024-09-29 08:11:13 +00:00
LibWeb: Treat :is(.foo) & :where(.foo) as class selectors when bucketing
These are just roundabout ways of writing .foo, so we can still put them in the rules-by-class bucket and skip running them when the element doesn't have that class. Note that :is(.foo .bar) is also bucketed as a class rule, since the context element must have the `bar` class for the selector to match. This is a massive speedup on https://vercel.com/ as it cuts the number of selectors we actually evaluate from 7.0% to 1.9%.
This commit is contained in:
parent
4ba38c55d6
commit
ad37c8cd26
Notes:
github-actions[bot]
2024-09-09 10:48:01 +00:00
Author: https://github.com/awesomekling Commit: https://github.com/LadybirdBrowser/ladybird/commit/ad37c8cd262 Pull-request: https://github.com/LadybirdBrowser/ladybird/pull/1341
|
@ -2627,6 +2627,31 @@ void StyleComputer::build_rule_cache_if_needed() const
|
|||
const_cast<StyleComputer&>(*this).build_rule_cache();
|
||||
}
|
||||
|
||||
static Optional<FlyString> is_roundabout_selector_bucketable_as_class(CSS::Selector::SimpleSelector const& simple_selector)
|
||||
{
|
||||
if (simple_selector.type != CSS::Selector::SimpleSelector::Type::PseudoClass)
|
||||
return {};
|
||||
|
||||
if (simple_selector.pseudo_class().type != CSS::PseudoClass::Is
|
||||
&& simple_selector.pseudo_class().type != CSS::PseudoClass::Where)
|
||||
return {};
|
||||
|
||||
if (simple_selector.pseudo_class().argument_selector_list.size() != 1)
|
||||
return {};
|
||||
|
||||
auto const& argument_selector = *simple_selector.pseudo_class().argument_selector_list.first();
|
||||
|
||||
auto const& compound_selector = argument_selector.compound_selectors().last();
|
||||
if (compound_selector.simple_selectors.size() != 1)
|
||||
return {};
|
||||
|
||||
auto const& inner_simple_selector = compound_selector.simple_selectors.first();
|
||||
if (inner_simple_selector.type != CSS::Selector::SimpleSelector::Type::Class)
|
||||
return {};
|
||||
|
||||
return inner_simple_selector.name();
|
||||
}
|
||||
|
||||
NonnullOwnPtr<StyleComputer::RuleCache> StyleComputer::make_rule_cache_for_cascade_origin(CascadeOrigin cascade_origin)
|
||||
{
|
||||
auto rule_cache = make<RuleCache>();
|
||||
|
@ -2689,6 +2714,13 @@ NonnullOwnPtr<StyleComputer::RuleCache> StyleComputer::make_rule_cache_for_casca
|
|||
added_to_bucket = true;
|
||||
break;
|
||||
}
|
||||
// NOTE: Selectors like `:is/where(.foo)` and `:is/where(.foo .bar)` are bucketed as class selectors for `foo` and `bar` respectively.
|
||||
if (auto class_ = is_roundabout_selector_bucketable_as_class(simple_selector); class_.has_value()) {
|
||||
rule_cache->rules_by_class.ensure(class_.value()).append(move(matching_rule));
|
||||
++num_class_rules;
|
||||
added_to_bucket = true;
|
||||
break;
|
||||
}
|
||||
if (simple_selector.type == CSS::Selector::SimpleSelector::Type::TagName) {
|
||||
rule_cache->rules_by_tag_name.ensure(simple_selector.qualified_name().name.lowercase_name).append(move(matching_rule));
|
||||
++num_tag_name_rules;
|
||||
|
|
Loading…
Reference in a new issue