ReviewOS

zig-utils/zig-js

Parser: diagnose function and arrow parameters

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

Parent: #899

Problem

Function, method, arrow, and dynamic-function parameter failures still leave 14 direct ParseError.UnexpectedToken exits in src/parser.zig, so the JavaScript boundary exposes an internal tag instead of JavaScriptCore's diagnostic.

Executed probes against raw JavaScriptCore 625.1.22 and current main (bc299cc1) show the missing grammar context:

sourceJavaScriptCorezig-js
function f(1) {}Unexpected number '1'. Expected a parameter pattern or a ')' in parameter list.UnexpectedToken
function f(break) {}Cannot use the keyword 'break' as a parameter name.UnexpectedToken
async (await) => 1Cannot use 'await' as a parameter name in an async function.UnexpectedToken
(a,a) => 0Duplicate parameter 'a' not allowed in an arrow function.UnexpectedToken
([a], {a}) => 0Duplicate parameter 'a' not allowed in function with destructuring parameters.UnexpectedToken
(a=1) => { 'use strict'; }'use strict' directive not allowed inside a function with a non-simple parameter list.UnexpectedToken
'use strict'; (function eval(){})'eval' is not a valid function name in strict mode.UnexpectedToken

The same audit exposed a conformance bug: current zig-js rejects sloppy simple duplicate parameters in generator and async functions. Both JavaScriptCore 625.1.22 and Node 24.18 accept function* f(a,a){}, async function f(a,a){}, and async function* f(a,a){}. These declarations use FormalParameters; only methods and arrows use UniqueFormalParameters, while any non-simple parameter list still forbids duplicates.

Implementation

  • Carry a token and reason from invalid formal parameters, restricted async/generator names, arrow line terminators, duplicate-name checks, and strict-directive checks.
  • Preserve JavaScriptCore's context-specific duplicate messages for arrows, methods, destructuring lists, default/rest lists, and strict mode.
  • Permit sloppy simple duplicates in ordinary generator/async declarations and expressions, while retaining all strict and non-simple early errors.
  • Reuse the existing reason/token channel and the parameter slice already owned by the parser. Do not rescan source or add allocation on accepted single-parameter paths.

Verification

  • Byte-for-byte raw JavaScriptCore differential for declarations, expressions, methods, arrows, and Function constructor parameters.
  • Node 24.18 syntax controls for the sloppy generator/async duplicate cases.
  • Focused frontend cases and the complete standalone parser module.
  • Exact-parent test262 diagnostics over the function, generator, async-function, arrow, async-arrow, rest-parameter, and function-code subtrees, with nonzero denominators and path-level flip accounting.
9 days ago

Implemented and pushed to main in 4841712.

  • 47/47 parser rejection probes match raw JavaScriptCore 625.1.22 byte for byte across declarations, expressions, methods, arrows, strict bindings, duplicate/default/rest/destructuring lists, and dynamic Function parameter boundaries.
  • Sloppy simple duplicate parameters now remain valid in ordinary, generator, async, and async-generator functions; methods, arrows, strict lists, and non-simple lists retain their required uniqueness.
  • Exact-parent test262 comparison across 13 function-related subtrees is unchanged at 3,295 pass / 1 known fail, with identical failure-path inventories and 0 flips.
  • The standalone parser module passes 238/238 tests; both focused frontend cases pass.
  • Direct bare ParseError.UnexpectedToken exits fell from 42 to 29.

Sign in to comment on this issue.