ReviewOS

zig-utils/zig-js

Parser: diagnose lexical declaration conflicts

#964
Closed chris opened this 9 days ago ·
9 days ago

Parent: #899

Problem

Script and function declaration early-error passes still return bare ParseError.UnexpectedToken for duplicate lexical BoundNames, lexical-loop/body var conflicts, duplicate rigid block functions, and vars that cross an enclosing lexical scope. Eight direct exits lose both the conflicting name and declaration kind.

Executed eval probes against raw JavaScriptCore 625.1.22 and current main (8e8884c9) include:

sourceJavaScriptCorezig-js
for (let [a,a] of []) {}Unexpected identifier 'a'. Cannot declare a lexical variable twice: 'a'.eval: UnexpectedToken at 1:16
const {a,a} = {}Unexpected token '}'. Cannot declare a lexical variable twice: 'a'.eval: UnexpectedToken at 1:17
for (let x of []) { var x; }Cannot declare a var variable that shadows a let/const/class variable: 'x'.eval: UnexpectedToken at 1:29
{ function* f(){} function* f(){} }Cannot declare a function that shadows a let/const/class/function variable 'f'.eval: UnexpectedToken at 1:36
{ async function f(){} async function f(){} }Cannot declare an async function that shadows a let/const/class/function variable 'f'.eval: UnexpectedToken at 1:46
{ function* f(){} let f; }Cannot declare a let variable twice: 'f'.eval: UnexpectedToken at 1:27
let x; { var x; }Cannot declare a var variable that shadows a let/const/class variable: 'x'.eval: UnexpectedToken at 1:18

Implementation

  • Carry the exact second BoundName slice through duplicate lexical checks, retaining object-pattern closing-token wording where JavaScriptCore uses it.
  • Classify the declaration being added so a later let/const/class or function reports its own declaration-specific message.
  • Preserve the existing one-pass lexical scope walk and secure name maps. Add no subtree rescan or allocation to successful programs; any pattern-shape lookup occurs only after a duplicate is found.

Verification

  • Byte-for-byte JavaScriptCore differential covering loop-head patterns, declaration patterns, lexical-loop body vars, rigid function kinds, declaration order, nested blocks, switch scopes, and function bodies.
  • Focused frontend message checks and the complete standalone parser module.
  • Exact-parent test262 comparison over lexical-declaration, block-scope, for-in/of, function-code, and statement/function subtrees with nonzero denominators and path-level flip accounting.
9 days ago

Implemented and pushed to main in 6b8c2ed.

Validation:

  • 21/21 direct probes match JavaScriptCore 625.1.22 exactly, including destructuring-order and async-generator cases
  • standalone parser module: 240/240 passed
  • focused evaluator matrix: 1/1 passed
  • exact-parent test262 comparison: 1,959 pass / 1 known fail across seven disjoint declaration subtrees, with byte-identical failure inventories and 0 flips
  • direct generic parser exits: 24 -> 16

The pattern-shape lookup runs only after a declaration collision, so accepted programs retain the existing declaration scan and allocation shape.

Sign in to comment on this issue.