File size: 4,409 Bytes
9da4a9b
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
# 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.