LibWeb: Bucket heading pseudo-class rules

Treat :heading as a subject pseudo-class bucket so heading rules are
only enumerated for h1 through h6 elements. The selector matcher still
checks functional :heading() levels, so the bucket only narrows rule
collection before normal matching.
This commit is contained in:
Andreas Kling 2026-06-18 17:07:12 +02:00 committed by Andreas Kling
parent f45bf0e770
commit 093a24d3f9

View file

@ -3062,6 +3062,7 @@ static bool subject_pseudo_class_is_bucketable(PseudoClass pseudo_class)
case PseudoClass::FocusVisible:
case PseudoClass::FocusWithin:
case PseudoClass::Fullscreen:
case PseudoClass::Heading:
case PseudoClass::Hover:
case PseudoClass::Link:
case PseudoClass::LocalLink:
@ -3085,6 +3086,7 @@ static u8 subject_pseudo_class_bucket_priority(PseudoClass pseudo_class)
case PseudoClass::Active:
case PseudoClass::Fullscreen:
case PseudoClass::Target:
case PseudoClass::Heading:
return 80;
case PseudoClass::Checked:
case PseudoClass::Disabled:
@ -3266,6 +3268,8 @@ static bool matches_subject_pseudo_class_bucket(PseudoClass pseudo_class, DOM::E
return element.matches_focus_within_pseudo_class();
case PseudoClass::Fullscreen:
return element.is_fullscreen_element();
case PseudoClass::Heading:
return element.is_html_heading_element();
case PseudoClass::Hover:
return matches_hover_pseudo_class_for_rule_bucket(element);
case PseudoClass::LocalLink:
@ -4146,12 +4150,13 @@ static IterationDecision for_each_matching_rule_bucket(DOM::AbstractElement abst
if (decision == IterationDecision::Break)
return IterationDecision::Break;
static constexpr Array<PseudoClass, 16> subject_pseudo_classes {
static constexpr Array<PseudoClass, 17> subject_pseudo_classes {
PseudoClass::FocusVisible,
PseudoClass::Focus,
PseudoClass::Active,
PseudoClass::Fullscreen,
PseudoClass::Target,
PseudoClass::Heading,
PseudoClass::Checked,
PseudoClass::Disabled,
PseudoClass::LocalLink,