ReviewOS

zig-utils/zig-js

Parser: preserve function context and usage tracking inside template substitutions

#912
Closed glennmichael123 opened this 9 days ago ·
9 days ago

Reproduction

On d2438f1, function F(){ return ${new.target === F}; } new F() incorrectly throws SyntaxError. Both tagged and untagged substitutions lose the enclosing new.target context. Likewise function f(a){ return ${arguments[0]}; } f(7) incorrectly throws ReferenceError instead of returning "7".

A 14-case differential against system JavaScriptCore yields 4 exact matches: eight valid programs fail (five new.target, three arguments), and two intentionally invalid global-new.target controls differ only in diagnostic wording. Direct-eval and generator-arguments controls currently pass.

Root cause and scope

The two template paths construct a fresh substitution Parser and copy async/generator/class/strict/module context, but omit new_target_depth, current_arguments_use, and current_direct_eval_use. These substitutions are expressions in the existing function, not new function scopes. Losing the usage sinks also produces incorrect function metadata even where an execution path masks the problem.

Share substitution-parser initialization, inherit the expression/function context and borrowed usage sinks, and retain ordinary nested-function ownership and arrow inheritance. Do not copy loop/label state into the expression parser. Pin metadata ownership, parameter-vs-body eval tracking, nested/tagged templates, both execution modes, and rejection of global new.target.

Related: #911 (complete expression boundaries), #899 (diagnostic parity), #496 (correct frontend metadata before performance claims).

9 days ago

Fixed and pushed in bff189a. Shared template subparser initialization preserves new.target depth and arguments/direct-eval usage sinks, including parameter-vs-body tracking and nested function ownership. Eight previously failing valid probes now pass; JSC exact differential 4/14 -> 12/14 (the two invalid global-new.target cases are still correctly rejected, with wording tracked under #899). All 15 runtime scenarios pass in tree-walker and required-bytecode modes with zero plain-function fallback. Both focused tests and all 59 parser unit tests pass with zero leaked. Six test262 subtrees retain 1,051 passes and zero failures before/after. Tests ran sequentially under the memory guard; no full-suite or performance claim.

Sign in to comment on this issue.