ReviewOS

zig-utils/zig-js

Runtime: give class static blocks their own new.target context for direct eval

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

Found while verifying #915 (parent diagnostics lane #899). On exact parent 650efda, class C { static { eval("typeof new.target"); } } throws SyntaxError instead of yielding undefined. The prepared diagnostic patch changes the message but does not repair this existing runtime rejection. Reproduced through test262 --eval in tree and required-VM modes; actual system JSC accepts this direct-eval case.

Root-cause evidence: interpreter.zig static-block execution creates a variable environment and replaces this/home, but neither grants direct_eval_new_target_allowed nor installs an independent undefined new_target. The VM class-template path delegates to the same class evaluator. Ordinary function invocations already manage both fields.

Specification: ClassStaticBlockDefinitionEvaluation creates a non-lexical-this synthetic function; PerformEval recognizes its function environment. https://tc39.es/ecma262/multipage/ecmascript-language-functions-and-classes.html#sec-runtime-semantics-classstaticblockdefinitionevaluation and https://tc39.es/ecma262/multipage/global-object.html#sec-performeval

Acceptance: direct/nested direct eval and arrows inherit the static block binding; indirect eval still rejects; an enclosing constructor new.target never leaks into the block; caller state is restored after normal and abrupt completion; test tree and required VM, including GC-safe rooting of the saved caller value. Audit the adjacent field-initializer boundary for the same defect without silently widening this fix. Re-run focused class/eval corpus and preserve memory guards. Do not emulate the separate JSC PrivateSymbol.newTargetLocal error observed for a tagged-template static-block case.

Evidence: /private/tmp/zig-js-new-target-oracle.ZOJlB1. No fix landed yet.

9 days ago

Prepared the root fix in the isolated worktree: static blocks install undefined new.target and direct-eval permission, restoring the caller state on every exit; the saved caller value is a temporary GC root. Both interpreter and required VM use the shared class evaluator. Verification now passed: seven static-block binding/arrow/eval/abrupt-restoration checks per mode; 26 production frontend cases; exact-parent corpus 5155 pass / 0 fail before and after across six new.target/template/arrow/eval/class groups. The combined #915/#916 diagnostic oracle improved 13 of 22 cases in both modes, with 18 exact JSC matches and four explicit remaining discrepancies. Separate early-error/source-position probes passed 24 checks per mode. Peak guarded batch footprint 1953 MB, host low-water 40%; these are correctness results, not benchmark timing evidence. Selected production inline-unit compilation is now running with native Zig test filters; the full combined unit artifact remains unverified after exceeding the 3 GiB cap. No commit yet pending authorship-history clarification. Logs: /private/tmp/zig-js-new-target-static-block-verification.log and /private/tmp/zig-js-new-target-oracle.xvKTkj.

9 days ago

Landed directly on main as 06652de under glennmichael123, without trailers. The source exactly matches the verified batch. Seven static-block checks per tree/required-VM mode pass; combined batch verification includes 71 focused inline tests (0 failed/leaked), 26 frontend cases, and 5155/5155 valid corpus cases before/after. Short cross-tier probes were rerun successfully on September 14. Full combined unit artifact remains an explicit memory-limited verification gap; no full-suite claim is made. Adjacent static-field eval permission was inspected and is a separate follow-up investigation, not included in this fix.

Sign in to comment on this issue.