From 87056ee0d2505c26149a36fc5b69446504b172bb Mon Sep 17 00:00:00 2001 From: Andreas Kling Date: Tue, 10 Sep 2024 15:18:29 +0200 Subject: [PATCH] LibWeb: Bucket CSS rules by pseudo-element Instead of throwing all pseudo-element rules in one bucket, let's have one bucket per pseudo-element. This means we only run ::before rules for ::before pseudo-elements, only ::after rules for ::after, etc. Average style update time on https://tailwindcss.com/ 250ms -> 215ms. --- Userland/Libraries/LibWeb/CSS/StyleComputer.cpp | 10 ++++++++-- Userland/Libraries/LibWeb/CSS/StyleComputer.h | 2 +- 2 files changed, 9 insertions(+), 3 deletions(-) diff --git a/Userland/Libraries/LibWeb/CSS/StyleComputer.cpp b/Userland/Libraries/LibWeb/CSS/StyleComputer.cpp index 069c1cf53c7..5c5387ce9de 100644 --- a/Userland/Libraries/LibWeb/CSS/StyleComputer.cpp +++ b/Userland/Libraries/LibWeb/CSS/StyleComputer.cpp @@ -386,7 +386,7 @@ Vector StyleComputer::collect_matching_rules(DOM::Element const& e if (auto it = rule_cache.rules_by_tag_name.find(element.local_name()); it != rule_cache.rules_by_tag_name.end()) add_rules_to_run(it->value); if (pseudo_element.has_value()) - add_rules_to_run(rule_cache.pseudo_element_rules); + add_rules_to_run(rule_cache.rules_by_pseudo_element[to_underlying(pseudo_element.value())]); if (element.is_document_element()) add_rules_to_run(rule_cache.root_rules); @@ -2745,11 +2745,13 @@ NonnullOwnPtr StyleComputer::make_rule_cache_for_casca }; bool contains_root_pseudo_class = false; + Optional pseudo_element; for (auto const& simple_selector : selector.compound_selectors().last().simple_selectors) { if (!matching_rule.contains_pseudo_element) { if (simple_selector.type == CSS::Selector::SimpleSelector::Type::PseudoElement) { matching_rule.contains_pseudo_element = true; + pseudo_element = simple_selector.pseudo_element().type(); ++num_pseudo_element_rules; } } @@ -2836,7 +2838,11 @@ NonnullOwnPtr StyleComputer::make_rule_cache_for_casca } if (!added_to_bucket) { if (matching_rule.contains_pseudo_element) { - rule_cache->pseudo_element_rules.append(move(matching_rule)); + if (to_underlying(pseudo_element.value()) < to_underlying(CSS::Selector::PseudoElement::Type::KnownPseudoElementCount)) { + rule_cache->rules_by_pseudo_element[to_underlying(pseudo_element.value())].append(move(matching_rule)); + } else { + // NOTE: We don't cache rules for unknown pseudo-elements. They can't match anything anyway. + } } else if (contains_root_pseudo_class) { rule_cache->root_rules.append(move(matching_rule)); } else { diff --git a/Userland/Libraries/LibWeb/CSS/StyleComputer.h b/Userland/Libraries/LibWeb/CSS/StyleComputer.h index 30e0a960220..93cc9373ccc 100644 --- a/Userland/Libraries/LibWeb/CSS/StyleComputer.h +++ b/Userland/Libraries/LibWeb/CSS/StyleComputer.h @@ -215,7 +215,7 @@ private: HashMap> rules_by_class; HashMap> rules_by_tag_name; HashMap, AK::ASCIICaseInsensitiveFlyStringTraits> rules_by_attribute_name; - Vector pseudo_element_rules; + Array, to_underlying(CSS::Selector::PseudoElement::Type::KnownPseudoElementCount)> rules_by_pseudo_element; Vector root_rules; Vector other_rules;