Vixen
dd8b0a81
csharp
public sealed class StyleInvalidator

Works out which elements a change can possibly have restyled.

No guide page documents this yet — the page shows what the code says about itself.

Remarks

The premise is that recomputing is not an option. A DataGrid restyles when a row is selected, and if selecting a row cost a pass over ten thousand cells the grid would be unusable — so the question is not "what changed" but "what could a rule have noticed".

Answering it is a static property of the stylesheet. For every name a rule mentions, where does it appear: against the element itself, as an ancestor, before a sibling combinator? And when it appears as an ancestor, what does the far end of that rule test? That last question is the one worth asking — it turns "restyle the subtree" into "restyle the .cells in the subtree".

⚠ This used to say that nothing needs to look upward, and :has() is what changed it. The old reasoning was sound and its premise expired: a selector could only reach downward and rightward because Vixen refused :has() — doc 09's P2 decision, and invalidation was the second thing that refusal bought after match cost. It is supported now, so a name that appears inside a :has() argument carries ReachesAncestors and a change to it walks up. :focus-within remains the apparent exception that is not one: it is stored as element state and set explicitly, so it arrives as a change like any other.

⚠ The upward direction is narrowed by name but not by depth, and that asymmetry is deliberate. A downward reach can be cut at the changed element's subtree; an upward one cannot, because the :has() may sit on the document root and every rule hanging off it reaches back down. So a change to a :has()-mentioned name walks to the top and then collects by feature from there — which is a pass over the document with a set-membership test per element, on the changes that touch such a name and no others. That is the cost doc 09 named, made explicit rather than hidden: see HasInvalidationTests, which measures it as elements resolved.

Fields and properties (4)

  • public bool StateReachesDescendants

    Whether an element's own state change can be narrowed at all, or whether every rule has to be reconsidered.

  • public bool StateReachesSiblings

    Whether a state change can reach later siblings.

  • public bool StateReachesEverything

    Whether what a state change reaches cannot be narrowed by name.

  • public bool StateReachesAncestors

    Whether a state change can be noticed by a :has() above it.

Methods (3)

  • public StyleInvalidator(SelectorTable table)

    Creates an invalidator over a rule set.

  • public void Read(StyleRuleSet rules)

    Reads every rule that has been added since the last time.

  • public void Collect(StyleTree tree, StyleNodeId element, ReadOnlySpan<int> changed, bool stateChanged, List<StyleNodeId> roots)

    Collects the elements a change to an element could have restyled.

Used by (1)

  • StyleUpdaterVixen.Ui.Styling