dssl / native /spec /10-resolved-document.md
EHS-Studio's picture
Claude Sonnet 5.5
v0.16.3: native DSSL spec, and the seven bugs writing it found
9da4a9b
|
Raw History Blame Contribute Delete
4.41 kB

10. The resolved document

The resolver turns one source file into a resolved document. This chapter defines its exact shape and how two implementations are compared. This is what makes Level 2 testable without a browser.

10.1 Inputs

  • DOC-1. The resolver takes: the source text, the file name, the token registry (4.5) and the motion registry (7.3). The registry defaults are the built-in tokens and no motions.

10.2 The document

{
  errors:        [ { file, line, message, hint? } ],      // parser errors, then resolver errors
  warnings:      [ { file, line, message, hint? } ],
  rules:         [ Rule ],
  shadowRules:   [ Rule ],
  raws:          [ { css, file, line, order } ],
  fontLinks:     [ { url, line, file } ],
  motionNames:   [ name ],                                // motions defined in this file, in source order
  motionFrames:  { name: { essential, frames: [ { offset, props } ] } },
  mediaQueries:  [ query ],                               // distinct, in first-use order
  tokens:        { key: value },                          // the final token map
  registryRule:  Rule
}
Rule = { id, sel, media, signals, containers, layer, order, decls, file, line, pseudo, states }
decl = { prop, value, line, via?, fromGradient? }
  • DOC-2. rules holds the ordinary rules and the token rules from tokens blocks, in the order they were emitted. shadowRules holds pseudo-element rules (5.8). raws holds raw and fonts font-face blocks in emission order. The registry rule is not in rules.
  • DOC-3. mediaQueries lists every distinct entry of media found in rules and shadowRules, in the order first seen, rules first.
  • DOC-4. tokens is the final map of 4.3 (every key, with the last definition in source order). Keys are compared as a set; the canonical form sorts them.
  • DOC-5. A declaration may carry via (the semantic property that produced a display value) and fromGradient (true for the background-image from gradient:). Both are part of the record.
  • DOC-6. states is a set of state words. It is written as a sorted array.
  • DOC-7. ok is not stored. It is errors.length == 0.

10.3 Canonical form

To compare two documents they are written as JSON in this form.

  • DOC-8. Object keys are sorted by code point. Arrays keep their order, except states and the tokens object, which are sorted.
  • DOC-9. Numbers are written as the shortest decimal that reads back to the same double, with no exponent for values between 1e-6 and 1e21, and no -0. Infinity is the string "Infinity" (an iterations of infinite).
  • DOC-10. A field that is undefined is omitted. A field that is null is null.
  • DOC-11. Strings are compared as UTF-8 text.
  • DOC-12. Two implementations are equal on a source when their canonical JSON is byte-identical, after removing lint warnings from implementations that declared lint: false (DIA-12).

10.4 The corpus

The comparison needs inputs. The corpus is a folder of .dssl files:

  • every stylesheet the site ships (public/styles/*.dssl),
  • every fenced dssl block from the guide, the readme and this spec,
  • the fixtures of the existing test suites,
  • one file per diagnostic message, written to trigger it.

For each input, scripts/native-dump.mjs writes the canonical JSON of the reference engine's output to native/expected/. The Rust test native/tests/differential.rs resolves the same input and compares.

  • DOC-13. The expected files are generated. They are committed so that a change in the reference engine shows up in review as a change in expected output, and so the Rust tests run without Node.
  • DOC-14. A divergence (chapter 12) is excluded from the comparison by listing the input in native/corpus/EXCLUDED.md with the divergence id. An excluded input is still run, and its diff is printed, so a fix is noticed.
  • DOC-15. Once the harness exists, native/PARITY.md lists, per chapter, how many corpus inputs pass, fail and are excluded. It is generated by the test run and not written by hand.

10.5 What the document does not contain

  • The syntax tree (Level 1 compares it separately, 2.9).
  • Behaviors (they are expanded during the walk and do not appear in the output).
  • Anything about a particular element. Matching is stage 3 and needs a document.