Include ::part() rules when comparing pseudo-class rule matches during
focus state invalidation. For observer style scopes, also walk the
containing shadow roots of the old and new focused nodes so document and
ancestor shadow scopes can invalidate exported part targets.
Add coverage for direct and exported parts using :focus, :focus-visible,
and :focus-within.
Match :focus-within by walking flat-tree parents so shadow hosts and
slotted content follow the Selectors definition instead of DOM ancestry.
When focus state changes, also run pseudo-class invalidation in shadow
style scopes that can observe the focused node. This lets shadow-root
rules such as :host(:focus-within)::before and ::slotted(:focus) update
without waiting for an unrelated DOM mutation to restyle the host.
Add focused coverage for host pseudo-elements, shadow descendants, and
slotted controls, and update the style-invalidation counter baseline for
the lower focus-family no-op restyle counts.
Previously, and according to the spec, `a::part(foo)::before` would be a
single CompoundSelector, even though it matches against 3 different
targets. This meant some awkward swapping of targets in the middle of
matching, and in particular it made `::part()` and `::slotted()` quite
hacky, requiring them to track extra data on the MatchContext to then
use later. This was scattered around and difficult to follow.
Partly inspired by Gecko, this commit instead introduces an invisible
PseudoElement combinator. After parsing a selector, we find any
CompoundSelectors that contain a pseudo-element and split them up, so
that each CompoundSelector only has a single target in the end. Where
the pseudo-element was at the start of a CompoundSelector, we insert an
invisible universal selector before it to represent its originating
element.
So now, a CompoundSelector deals with one target, and switching targets
is done at the combinator.
The one inconsistency is that we match the target of ::slotted()
and ::part() in pseudo_element_transition_target(), instead of before
then when processing the SimpleSelector. This is to avoid repeating the
same computations twice.
No outward-facing behaviour changes, though the invalidation metrics
have changed.
Document.cpp contained the CSS rule-cache matching used to decide which
elements need style updates when hover, focus, or target state changes.
Move that logic into CSS::Invalidation::PseudoClassInvalidator.
Document still owns the current state slots and chooses when a state
transition happens. The helper now owns the selector matching and
recursive invalidation pass for those pseudo-class transitions.