|
11 | 11 | // scanner silently becomes `any`, and reading `.comment` off a misspelled |
12 | 12 | // property would type-check clean. |
13 | 13 | // |
14 | | -// The two flag arrays are the load-bearing part of the surface, so they are |
| 14 | +// The three flag arrays are the load-bearing part of the surface, so they are |
15 | 15 | // typed precisely: a caller that confuses them inverts the very question this |
16 | 16 | // module exists to answer once (see the module's header on the two failure |
17 | 17 | // families). |
|
23 | 23 | /** |
24 | 24 | * Per-character flags from one left-to-right pass over a JS source. |
25 | 25 | * |
26 | | - * Both arrays are the same length as the source, so an offset into either |
27 | | - * indexes the same character in the original text. |
| 26 | + * All three arrays are the same length as the source, so an offset into any of |
| 27 | + * them indexes the same character in the original text. |
28 | 28 | * |
29 | 29 | * `comment` flags comment CONTENT (line, block and shebang). `literal` flags |
30 | 30 | * the CONTENT of a string, template or regex literal — **not** its delimiters, |
31 | 31 | * so a caller still sees the opening and closing quote as code and can pair |
32 | 32 | * them. Template interiors are flagged through `${...}` as well. |
| 33 | + * |
| 34 | + * `interpolation` flags the bytes a template interpolation contributes, which |
| 35 | + * the language RUNS as code. Those same bytes are flagged `literal` too — that |
| 36 | + * answer does not move — so a caller wanting the view the language would |
| 37 | + * execute masks `literal && !interpolation`, which is exactly how |
| 38 | + * `scripts/pm/dispatch-gates.mjs` counts an identifier inside `${...}` as a |
| 39 | + * reference. The `${` and its closing `}` stay OUT of it (a bracket counter |
| 40 | + * over the subtracted view stays balanced), and so does a nested template's |
| 41 | + * body inside the interpolation (those bytes really are content). |
33 | 42 | */ |
34 | 43 | export interface SourceFlags { |
35 | 44 | comment: Uint8Array; |
36 | 45 | literal: Uint8Array; |
| 46 | + interpolation: Uint8Array; |
37 | 47 | } |
38 | 48 |
|
39 | 49 | /** |
40 | | - * Flag every character of `source` as comment content and/or literal content. |
| 50 | + * Flag every character of `source` as comment content, literal content and/or |
| 51 | + * interpolation code. |
41 | 52 | * |
42 | 53 | * @param source JavaScript (or TypeScript-shaped) source text. |
43 | 54 | */ |
@@ -110,7 +121,12 @@ export function makeRegexRecogniser(options: { |
110 | 121 | /** |
111 | 122 | * Drive the scanner over its own fixture corpus, printing a line per case. |
112 | 123 | * |
113 | | - * Returns nothing: a failing case calls `process.exit(1)` rather than reporting |
114 | | - * a value, so there is no verdict for a caller to forget to read. |
| 124 | + * Returns the module's verdict sentinel, reached only once the success line has |
| 125 | + * been printed — the handshake its own CLI dispatch performs: that dispatch |
| 126 | + * compares the returned value by identity and exits 1 on anything else, so a |
| 127 | + * `return` leaving this function above the verdict cannot be reported as a |
| 128 | + * self-test that passed. A failing case still calls `process.exit(1)`. The |
| 129 | + * sentinel constant is not exported, so `string` is the widest type a caller |
| 130 | + * can name for it. |
115 | 131 | */ |
116 | | -export function selfTest(): void; |
| 132 | +export function selfTest(): string; |
0 commit comments