Skip to content

fix(lexer): align string-escape, unterminated-string and numeric-literal diagnostics with pinned QuickJS - #25

Open
lfkdsk wants to merge 3 commits into
pocket-stack:mainfrom
lfkdsk:pr/diagnostics-parity
Open

lfkdsk wants to merge 3 commits into
pocket-stack:mainfrom
lfkdsk:pr/diagnostics-parity

Conversation

@lfkdsk

@lfkdsk lfkdsk commented Sep 17, 2026

Copy link
Copy Markdown

What

Three diagnostic-text/position alignments with pinned QuickJS 2026-06-04, plus the exact negative-diagnostic contracts that pin them:

  • Malformed string escapes (\x2, \u4, \u{}, unclosed braces, > U+10FFFF, strict/template \8 \9): one message, malformed escape sequence in string literal, emitted at the backslash (quickjs.c:22439), replacing the count/braced/range-specific wordings.
  • Unterminated strings: reported at the opening quote via the token pointer (quickjs.c:22473) instead of the line terminator (:1:9 instead of :1:13 on the scout case); bare trailing backslash takes the pinned unexpected end of string label.
  • Malformed numeric/BigInt literals: the three Oxide-specific messages collapse to the single pinned invalid number literal (js_parse_get_number, quickjs.c:22928) without changing accept/reject decisions or spans.

The numeric-literal cluster is also admitted as 28 exact contracts (rule numeric-literal.invalid, anchor js_parse_get_number), generated with scripts/audit-negative-diagnostics.mjs --generate so both engines had to agree byte-for-byte; the registry replay is 2972 exact contracts / 78 rules.

Verification

  • Escape/unterminated: 2 lexer unit tests, 12 compiler diagnostic-table rows, a 19-case pinned-oracle byte-exact test; differential matrix 17 → 0 mismatches over 37 probes; test262 string/template subset shows no pass flips (207 pass on both sides), only the exempt phase/type rows' observed text now matches pinned.
  • Numeric literals: runner subset 42 unsupported → 28 pass / 14 unsupported (the remaining 7 sloppy variants share paths with the strict-octal M1 cluster and are staged for that batch).
  • cargo test --locked --workspace --all-targets: 2845 pass / 0 fail; check-rust-only.sh and cargo fmt --check green.
  • Cross-model reviews (fleet tasks 945, 950) reproduced the numbers and mutations.

Note for the maintainer: current.conf is not re-promoted here; test-test262.sh --check will report the source as stale until the next full-receipt promotion.

lfkdsk and others added 3 commits September 17, 2026 14:15
…lumn with pinned QuickJS

Pinned QuickJS funnels every malformed \x/\u string escape to one message,
"malformed escape sequence in string literal", emitted at the backslash
(quickjs.c:22439), and reports unterminated strings through the token
pointer, i.e. at the opening quote (quickjs.c:22473).

- unify fixed-hex (\x2, \u4), braced (\u{}, unclosed, > U+10FFFF) and
  strict/template \8 \9 failures on the pinned wording instead of
  count/braced/range-specific text
- anchor raw CR/LF-terminated string errors at the opening quote instead
  of the line terminator (:1:9 instead of :1:13 on the scout case)
- bare trailing backslash takes the pinned "unexpected end of string"
  label (upstream case '\0' -> invalid_char), re-anchored at the quote
  for ordinary strings; template EOF behavior unchanged

Adds 2 lexer unit tests, 12 compiler diagnostic-table rows, and a 19-case
pinned-oracle byte-exact diagnostic test. Differential matrix 17 -> 0
mismatches over 37 probes; test262 string/template subset shows no pass
flips (207 pass both), only the exempt phase/type rows' observed text
now matches pinned.

Co-Authored-By: Claude Code <noreply@anthropic.com>
(cherry picked from commit 01428509dccb3903d986ae7a5137617a47510454)
The three oxide-specific messages for malformed numeric literals
("base-{2,8,16} literal requires at least one digit",
"BigInt suffix cannot follow a fraction or exponent",
"decimal BigInt cannot contain a leading zero") diverged from pinned
QuickJS 2026-06-04, which reports a single "invalid number literal" for
all of them at js_parse_get_number (quickjs.c:22928).

Collapse all three to "invalid number literal" without changing
accept/reject decisions or spans, and add a unit test asserting the
exact QuickJS wording across the three failure families.

Co-Authored-By: Claude Code <noreply@anthropic.com>
(cherry picked from commit 08b426f4758bd1e5bd5fdb398292aab4f13a81d9)
Add rule numeric-literal.invalid (anchor js_parse_get_number) and 28
exact negative-diagnostic contracts for malformed numeric/BigInt
literals whose sloppy and strict variants both belong to the M3 cluster;
admit the corresponding 14 paths in the Oxide profile audited-negative
section.

Rows were produced with scripts/audit-negative-diagnostics.mjs
--generate (both engines must agree byte-for-byte) and validated by the
full registry replay: 2972 exact contracts / 78 rules.

The remaining 7 M3 sloppy variants share paths with the parallel M1
strict-octal cluster and are admitted together with M1; their candidate
rows are staged in the verify report's handoff section.

Co-Authored-By: Claude Code <noreply@anthropic.com>
(cherry picked from commit 0018504c9699030bbd0910bd40075a1f6079166e)

Rebase note (onto main@49d1a299 workspace): contracts regenerated byte-identical
(28 rows, e4cf946b…) with scripts/test262/audit-negative-diagnostics.mjs --generate;
the new gate authenticates line counts/SHAs via dev-support/test262/current.conf and
compat/upstream.toml, so profile/contract/rule counts and hashes were script-updated
(profile 3194->3208 lines sha 5b7327f5…; contracts 2945->2973; rules 78->79).
The frozen focused receipt still carries the old profile/contract header hashes and
can only be re-issued by a maintainer `--full` promote (no receipt touched here, per
policy); --check consequently reports only "focused report diagnostic contract
drifted", with zero line-count/checksum drift.
@lfkdsk
lfkdsk force-pushed the pr/diagnostics-parity branch from a74ff37 to 73ffedd Compare September 17, 2026 21:29
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant