LibWeb: Bail early from doomed pseudo-element style computation

Once we know the final value of the `content` property for a
pseudo-element, we can bail early if the value is `none` or `normal`
(note that `normal` only applies to ::before and ::after).

In those cases, no pseudo-element will be generated, so everything
that follows in StyleComputer would be wasted work.

This noticeably improves performance on many pages, such as
https://tailwindcss.com/ where style updates go from 360ms -> 250ms.
This commit is contained in:
Andreas Kling 2024-09-10 14:25:03 +02:00 committed by Andreas Kling
parent e399b472e9
commit d22228ab93
Notes: github-actions[bot] 2024-09-10 13:20:51 +00:00

View file

@ -2615,8 +2615,34 @@ RefPtr<StyleProperties> StyleComputer::compute_style_impl(DOM::Element& element,
bool did_match_any_pseudo_element_rules = false;
compute_cascaded_values(style, element, pseudo_element, did_match_any_pseudo_element_rules, mode);
if (mode == ComputeStyleMode::CreatePseudoElementStyleIfNeeded && !did_match_any_pseudo_element_rules)
return nullptr;
if (mode == ComputeStyleMode::CreatePseudoElementStyleIfNeeded) {
// NOTE: If we're computing style for a pseudo-element, we look for a number of reasons to bail early.
// Bail if no pseudo-element rules matched.
if (!did_match_any_pseudo_element_rules)
return nullptr;
// Bail if no pseudo-element would be generated due to...
// - content: none
// - content: normal (for ::before and ::after)
bool content_is_normal = false;
if (auto content_value = style->maybe_null_property(CSS::PropertyID::Content)) {
if (content_value->is_keyword()) {
auto content = content_value->as_keyword().keyword();
if (content == CSS::Keyword::None)
return nullptr;
content_is_normal = content == CSS::Keyword::Normal;
} else {
content_is_normal = false;
}
} else {
// NOTE: `normal` is the initial value, so the absence of a value is treated as `normal`.
content_is_normal = true;
}
if (content_is_normal && first_is_one_of(*pseudo_element, CSS::Selector::PseudoElement::Type::Before, CSS::Selector::PseudoElement::Type::After)) {
return nullptr;
}
}
// 2. Compute the math-depth property, since that might affect the font-size
compute_math_depth(style, &element, pseudo_element);