Parent: #496 Related: #493, #538, #539, #460, #461
Problem
The lexer currently treats almost every non-ASCII code point that is not whitespace, a line terminator, ZWNJ/ZWJ-at-start, U+2E2F, or U+180E as an identifier character. That permissive approximation accepts punctuation and symbols that ECMAScript excludes from Unicode ID_Start/ID_Continue. Source text is attacker-controlled, and accepting invalid source changes parse boundaries, early errors, and potentially the meaning of adjacent tokens.
The owned zig-regex dependency already publishes binary-searched Unicode 17.0.0 ID_Start and ID_Continue tables for ECMAScript named captures. The lexer should consume the same exact generated authority rather than maintaining an incomplete approximation or duplicating tables.
Scope
- Commit parser-only 1K/2K/4K raw-Unicode identifier rows before changing validation, with exact AST identities, checksums, warmup, allocation replay, and parser-only timed boundaries.
- Preserve the branch-cheap ASCII
$/_/letter/digit path. - Validate raw and escaped non-ASCII identifier starts/continues against Unicode 17
ID_Start/ID_Continue, plus ECMAScript$,_, U+200C ZWNJ, and U+200D ZWJ additions. - Reject invalid punctuation, symbols, unassigned/surrogate code points, invalid UTF-8, invalid escapes, and continue-only characters at start without consuming them as identifiers.
- Preserve keyword-after-escape early errors, raw token positions, decoded identifier text, private names, RegExp named captures, source lifetime, and OOM behavior.
No-workaround rules
- No hand-maintained allow/deny exceptions, ASCII-only mode, locale predicates, host-library Unicode behavior, source rewriting, deferred syntax errors, or benchmark recognition.
- Do not duplicate generated Unicode tables into zig-js or change the dependency outside its existing public Unicode property API.
- Do not modify stacks, queues, jobs, Promise/microtask behavior, or Thread/Worker lifecycle.
Acceptance
- Benchmark-first 1K/2K/4K rows freeze exact valid raw-Unicode sources and outputs before the lexer change.
- Raw and escaped start/continue witnesses cover BMP, astral,
Other_ID_*, combining marks, digits, connector punctuation, ZWNJ/ZWJ, symbols, punctuation, whitespace, unassigned code points, and malformed UTF-8/escapes. - Lexer and RegExp named-capture identifier classification agree for every Unicode scalar value, modulo the grammar-specific ASCII/ZWJ additions.
- Exact-parent evidence reports wall, retired instructions, allocations/bytes, RSS, dispersion, and identical checksums; ASCII and escaped-identifier controls do not regress materially.
- Focused lexer/frontend, full units, TSan, identifier/private-name test262, and forced parser/execution paths pass with no regressions.
- Raw evidence and report are checked in before any performance claim.