ReviewOS

zig-utils/zig-js

Compiler: lower plain destructuring declarations

#730
Closed chris opened this 8 days ago ·
8 days ago

Parents: #465, #493 Related: #726, #729

Problem

#726 gave plain functions native destructuring assignment, but a plain-function var, let, or const destructuring declaration still returns unsupported_lowering. The frame compiler neither hoists pattern-bound var names nor predeclares block-scoped pattern bindings, so the existing native pattern evaluator cannot safely target activation slots.

Scope

  • Hoist every function-scoped var binding inside nested array/object patterns into the owning activation.
  • Predeclare every block-scoped destructuring binding in its exact lexical scope and initialize all bindings to TDZ before evaluating the declaration initializer.
  • Lower array/object declaration BindingInitialization through activation-owned bytecode for frame slots, mapped parameters, captured upvalues, and repeated-body Environment Records.
  • Preserve computed-key/default ordering, iterator close, object rest, duplicate var behavior, const assignment checks, shadowing, abrupt completion, recursion, activation reuse, moving GC, and no-GIL sharing.
  • Keep program/generator/async behavior and the tree-walker semantic baseline exact.

No-workaround rules

  • No syntax refusal, source rewriting, synthesized global names, tree-walker fallback presented as coverage, heuristic cutoff, weakened TDZ/const behavior, or duplicated iterator/property evaluation.
  • No stacks, queues, jobs, Promise, microtask, Worker lifecycle, or Map/Set iterator changes.

Acceptance

  • Compiler admission proves representative plain destructuring declarations contain native iterator/object-rest/frame stores and no bind_pattern.
  • Forced tree-walker and required bytecode agree on initializer/key/default order, TDZ, const, hoisted var, closures, mapped parameters, abrupt IteratorClose, recursion, activation reuse, and moving GC.
  • Focused compiler/frontend/VM, full units, applicable TSan/no-GIL, and relevant nonzero Test262 declaration/destructuring subtrees pass with exact accounting.
  • Conventional commit lands directly on main and cross-links #465, #493, #726, and #729.
8 days ago

Implementation is now exercising the complete ordinary frame-declaration path locally.

Current candidate behavior:

  • hoists every nested var pattern name, including for-in/of heads;
  • predeclares block pattern bindings in their exact lexical scope and emits TDZ initialization before initializer/RHS evaluation;
  • lowers declaration BindingInitialization through activation-owned iterator/object-rest bytecode, selecting frame, mapped-parameter, lexical, upvalue, or repeated-body Environment storage;
  • extends the TDZ classifier to computed keys/defaults while excluding binding positions;
  • retains the existing exact fallback for dynamic with References rather than miscompiling them.

Validation so far:

  • focused declaration differential: 10/10 tree-walker ↔ required-bytecode cases, zero fallback;
  • destructuring group: 17/17;
  • compiler-related units: 86/86;
  • focused frontend: 14/14;
  • focused VM: 4/4;
  • focused declaration TSan: 1/1, zero failures/leaks.

The first differential exposed and fixed the adjacent for (var [x] of ...) hoisting/binder gap. A full unit attempt was immediately discarded and stopped because its preflight displayed a concurrently running user-owned Home corpus process; no result from that attempt will be used. Full units and Test262 accounting remain pending clean serial windows.

8 days ago

Clean full normal integration is complete on the current candidate: 1,861 passed / 1 platform skip / 0 failed / 0 leaked across ten shards in 150.9 s. The post-review compiler group is also 86/86, including exact TDZ pattern-evaluation classification and the dynamic-with fail-closed regression.

A full TSan run was started only after a clear preflight, but a user-owned Home TypeScript corpus survey began while its shards were active. I stopped only the zig-js TSan suite and retained no result from that overlapped attempt. Full TSan and Test262 accounting remain pending a fresh clean serial window.

8 days ago

Landed on main in a2d301ae (feat(compiler): lower plain destructuring declarations (#730)), authored as Chris with no trailers.

The production compiler now hoists nested var patterns, predeclares exact lexical pattern scopes, classifies only computed/default evaluation regions for TDZ, and emits activation-owned BindingInitialization for ordinary declarations plus for-in/of heads. Frame, mapped-parameter, upvalue, and repeated-body Environment stores all use their exact existing storage operations. Dynamic with references remain fail-closed.

Valid local evidence is recorded in the commit: full 1,861-pass suite, focused TSan, compiler/frontend/VM groups, and exact variable/dstr 97 -> 97. Subsequent broader local pairs were discarded when Home jobs appeared and are not claimed.

The isolated CI run 32671223602 is active, including Test262 parallel and all four TSan unit shards. This issue remains open until the relevant remote gates settle.

8 days ago

Remote validation settled with 52 successful jobs, 1 intentional skip, and 0 failures. The sole cancelled job was benchmark-comparison-harness: GitHub superseded it when the descendant #731 main push started. The newer #731 CI run includes this commit and continues as the exact-main successor. Closing #730 as implemented and locally/remote validated in a2d301ae.

8 days ago

#736 is complete in e2ba5ac3 and extends this issue’s activation-owned destructuring lowering to initializer-free formal parameters. Hidden raw input slots feed the same native array/object prologue, including abrupt IteratorClose and precise frame/upvalue stores.

Sign in to comment on this issue.