ReviewOS

zig-utils/zig-js

Compiler: lower ordinary spread calls and constructors

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

Parents: #465, #498 Related: #710, #491

Problem

The VM already has call_spread, call_eval_spread, call_with_this_spread, and new_spread, and the compiler already builds argument arrays with exact iterator expansion. Admission nevertheless rejects every spread call/constructor outside generators, and rejects computed-member spread even inside generators. This keeps ordinary plain, async, and program code on the tree-walker despite an existing runtime contract.

Scope

  • Lower non-tail spread calls and constructors in program, plain-function, generator, and async bytecode through the existing variadic operations.
  • Preserve callee/reference resolution before argument-list evaluation, including named/computed member receivers and super home-object/current-this semantics.
  • Preserve left-to-right argument evaluation, iterator protocol and abrupt propagation (including the required absence of IteratorClose for spread expansion), abrupt completion, constructor new.target, proxy/accessor behavior, and suspension in generator/async computed keys and spread operands.
  • Keep slot-based direct eval(...spread) behind its existing dynamic-environment barrier; env-mode direct eval retains call_eval_spread.
  • Keep proper-tail-call spread causally unsupported until receiver-aware and receiver-less tail-spread operations exist.

No-workaround rules

  • No AST rewriting, repeated callee/key/getter evaluation, receiver-less method calls, array-only spread shortcut, source-shape exception, tree-walker callback, disabled proper tail calls, new global/shared scratch, or new runtime primitive.
  • No stacks/queues/jobs-runtime, Promise/microtask, Worker, or Map/Set iterator changes.

Acceptance

  • Plain/program/async direct, named/computed member, super, and constructor spread compile through the exact existing opcode family; generator coverage remains exact.
  • Witnesses cover receiver/new-target identity, callee/key/getter/argument ordering, mixed spread/non-spread lists, iterators and abrupt closing, proxies, recursion, and suspension.
  • Forced tree-walker and required/compiled bytecode agree; direct-eval and tail-spread barriers stay causal and audited.
  • Focused compiler/frontend, full units, applicable TSan, and exact relevant Test262 before → after accounting pass with zero regressions.
  • Parent/related issues and landing commit are cross-linked with quantified evidence.
9 days ago

Landed in d1c8251b — feat(compiler): lower spread calls and constructors (#711).

Evidence: focused units 2/2; focused TSan 2/2; frontend 12/12; full units 1,816 passed, 1 skipped, 0 failed/leaked. Exact Test262 diagnostics were byte-identical: call 92/92 → 92/92, new 59/59 → 59/59, super 94/94 → 94/94; 245/245 total, 0 flips, 0 regressions.

The landing reuses the existing variadic opcode family, preserves all causal barriers, and also fixes tree-walker MemberExpression Get-before-Arguments ordering without touching stacks, queues, jobs, Promise/microtask, Worker, or Map/Set iterator surfaces.

9 days ago

Follow-on optional spread-call lowering landed via #712 in ef067c10. The #711 regression test now requires holder.method?.(...args) to compile through call_with_this_spread; strict tail-spread remains the existing causal barrier.

9 days ago

Follow-up #719 landed in 2388fd77: the spread and optional-reference lowering from this work now extends to proper tail calls in strict ordinary functions, including receiver-aware member/super forms. Exact-parent call/optional/super/return Test262 remained byte-identical at 240/240 with 0 regressions.

Sign in to comment on this issue.