Vixen
dd8b0a81
csharp
public sealed class ContainerScopes

The container chains the document's elements are inside, and what they answer.

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

Remarks

What MediaScopes is for a surface, this is for a box. An element carries a scope on its StyleTree slot, the cascade reads one integer before the matcher, and a group's verdict is cached against Revision. The difference is what a scope is: a surface is a place the document is shown and there are a handful, a container is any box with a container-type and there can be one per row of a list.

⚠ Interned on the whole chain by value, and that is a decision about the sharing cache rather than about memory. The obvious design is a scope per container element, which is what MediaScopes does — and it would give every row of a thousand-row list a distinct scope id. StyleSharingKey carries the scope, so distinct ids mean no two rows ever share a computed style: a document that used one container query would lose the sharing cache entirely, silently, and only on the documents big enough to need it. Interning on (parent, name, box) collapses a thousand identical rows to one scope, so sharing works exactly as well as it did before the query was written.

⚠ The cost of interning by value is churn while a box is moving, and it is not paid for yet. A drag that resizes a container by a pixel a frame interns a new scope each frame, and nothing evicts the old ones — the table grows for the length of the drag. Reset is the whole of the eviction policy today and the caller is expected to use it when it rebuilds. A generation stamp per scope, swept after a pass that moved nothing, is the shape of the answer and is deliberately not built here: it wants the layout wiring in front of it to say how often a rebuild actually happens.

⚠ A container does not answer its own query. CSS Containment 3 § 5.1 scopes a container query to the elements inside the container, so the scope an element is in is its ancestors' and never includes itself. That is a property of how the caller assigns scopes — Root for an element with no container above it, and a container's own scope handed to its children rather than to itself — and it is the single easiest thing to get wrong, because getting it wrong produces a query that matches slightly too often rather than one that never matches.

Fields and properties (2)

  • public const int Root

    The scope of an element with no query container above it.

  • public int Count

    How many distinct chains have been interned, the root included.

Methods (6)

  • public ContainerScopes(ContainerConditions conditions)

    Creates a registry over a condition table, with the root scope in it.

  • public int Enter(int parent, string? name, ContainerBox box)

    The scope inside a container, given the scope that container is itself in.

  • public ContainerScope InnermostOf(int scope)

    The container a scope's innermost box is, for a caller that needs to read it back.

  • public ContainerVerdicts VerdictsOf(int scope)

    Which container groups hold for an element in a scope.

  • public bool Refresh()

    Whether any scope's verdicts have moved since they were last read.

  • public void Reset()

    Forgets every scope but the root.

Used by (11)

  • CascadeFixtureVixen.Ui.Styling.Tests
  • ContainerQueryTestsVixen.Ui.Styling.Tests
  • ContainerWiringTestsVixen.Ui.Tests
  • HasInvalidationTestsVixen.Ui.Styling.Tests
  • IncrementalRestyleOracleTestsVixen.Ui.Styling.Tests
  • StyleEngineVixen.Ui.Styling
  • StyleResolverVixen.Ui.Styling
  • StyleSharingOracleTestsVixen.Ui.Styling.Tests
  • StyleTreeVixen.Ui.Styling
  • UiDocumentVixen.Ui
  • UtilityFixtureVixen.Ui.Styling.Utilities.Tests