Commit bcf07e6
fix(devx): read a regex literal as a literal in the shared textual scanners (#15486)
`skipStringLiteral` opened a string on any `'`, `"` or backtick, so a REGEX
literal whose character class carries one of them opened a literal the source
does not have. `packages/rest/src/error-response.ts` has the live instance, and
every byte after it in that file was read with the string/code polarity
reversed. 69 of 2232 files were being walked that way.
The recogniser is stated from ECMA-262's two lexical goal symbols rather than
approximated: a `/` opens a RegularExpressionLiteral only where
`InputElementRegExp` applies, the grammar's own exclusion of `*` and `/` as a
first character is why comments are unambiguous, a character class is where `/`
and quotes are ordinary characters, and a body cannot cross a LineTerminator.
The three preceding tokens the rule genuinely cannot decide -- `)`, `}` and a
bare `<`/`>` -- are classified as DIVISION, which skips nothing and so can only
leave a regex unread, never invent one; reading them the other way would be
this defect in a new spelling and uncounted.
Measured, both directions, against the TypeScript compiler's own parser over
the same population: 1615 `/` bytes the language calls code, 1496 regex
literals, 0 fabricated, 0 missed, 0 closing-slash mismatches. Of the 47
undecidable positions read as division, 0 are regex literals (45 are arithmetic
after `)`, 2 are JSX closing tags).
Ledgers re-derived by measurement, not by hand:
· SCANNER_LITERAL_BLIND_SPOTS -- 2163/2232 files health-certified -> 2232;
69 recovered, 0 still desynchronised; of the 70 `code:` positions the
pre-fix scan could not place, 47 are now placed and 23 are certified
genuinely inside a string; new `regexRecogniser` sub-ledger.
· INLINE_LITERAL_EXPRESSION_CENSUS -- 358 anchor hits, guard (1) 73 -> 64,
reduction 224 -> 233, live positions 4 -> 4.
· OBJECT_LITERAL_CODE_HELPER_BLINDNESS.localTwinCensus -- 144/43/101, the
reducible subclass still empty.
`deriveSites` is byte-identical across the change, key by key, in both
directions (63 sites, 5 unresolved), so no unregistered wire code surfaced and
no registration decision is owed.
The `--self-test` pin that asserted the OPPOSITE direction (a regex fixture
must come back `desync`) reds by design; it was re-measured rather than edited,
the fixture is unchanged, and only the expected answer moved. A new battery
pins the recogniser in both directions -- the live instance and the four
primitives that inherit it, the division cases as negative fixtures, the
grammar's comment exclusions, the keyword and arrow positions, the undecidable
positions as division, and the sibling recogniser in `js-comment-mask.mjs`
both where the two agree and at the one place they deliberately differ.
Claude-Session: https://claude.ai/code/session_012zGPuVVX3deAx9LdjK8jCk
Co-authored-by: Claude <noreply@anthropic.com>1 parent 1c009e3 commit bcf07e6
1 file changed
Lines changed: 723 additions & 143 deletions
0 commit comments