Skip to content

VM: resolve parameter references through exact lexical bindings #798

Description

@chrisbbreuer

Parent: #465. Related: #771, #795, #797.

Original admission boundary

supportedPlainParameterDefault admits an IdentifierReference only when it
names an earlier formal or an ordinary function's implicit arguments binding.
It rejects outer/global names, self/later formal references (which must execute
and throw ReferenceError), and inherited arrow arguments. This also blocks
otherwise-lowered member/call/constructor expressions and computed binding keys.

The compiler already has separate parameter/body binding phases, checked
formal slots, exact parent-frame resolution, and dynamic Environment references.
The classifier must use that existing resolution model rather than a separate
spelling/position whitelist.

Acceptance

  • Admit identifier references through the canonical checked local, upvalue,
    Environment, and global lowering, preserving self/later-formal TDZs.
  • Preserve parameter/body environment separation, outer lexical shadowing,
    inherited arrow arguments, with/unscopables, indirect effects, and abrupt order.
  • Cover ordinary, arrow, method, nested-closure, destructuring/default/key,
    member/call/constructor, direct-eval, and provided-argument controls in both tiers.
  • Verify compiler allocation replay, full units, focused TSan/no-GIL, and
    measured before/after positive Test262 paired execution with exact denominators.
  • Land a linked conventional commit and report pushed integration separately.

No AST callbacks, name snapshots, skipped TDZ checks, policy fallback, native
stack/queue/job redesign, or Promise/Worker/Map/Set iterator changes. Syntax that
still lacks complete lowering must retain a causal unsupported result.

Landed implementation and evidence

2865b8b4 — feat(vm): resolve lexical parameter references (#798) is on origin/main, authored and committed by Chris, without trailers.

The classifier now delegates identifier references to the existing exact parameter-phase checked local/upvalue/Environment/global lowering. Self/later formal reads execute their TDZ checks; body declarations remain invisible during parameter initialization. No new runtime callback, snapshot, allocation model, synchronization, or native ownership mechanism was introduced. Unsupported initializer syntax remains causally rejected.

Measured against 8a1398f and Test262 4249661388e5d3f92a85186213da140a6481490f:

  • 24 focused paired-mode witnesses: 2 -> 24 pass.
  • Same 9,643 eligible positive corpus files: 8,475 pass / 1,168 fail -> 8,809 pass / 834 fail. Exact failure-path diff: 334 gains, zero regressions.
  • Required-tier gains: expressions/arrow-function 37, expressions/class 109, expressions/function 38, expressions/object/method-definition 5, statements/class 108, statements/function 37.
  • All 13 default-tier diagnostic reports are byte-identical: 11,494 pass / 0 fail. 0 default-tier Test262 flips; no regressions in this measured scope. The 834 remaining paired failures stay explicit.
  • Full Debug units: 2,020 pass, 1 platform skip, 0 fail/leak, 709.4 s across four shards.
  • ReleaseSafe + TSan without suppressions: new reference checks 3/3, parameter cluster 50/50, stable admission 1/1, unsupported-object rejection guard 1/1 (overlapping filters), zero reports/failures/leaks. Includes compiler allocation replay and shared no-GIL calls.
  • Seed-1 ReleaseFast threadfuzz: 400 default + 300 verify programs, zero failures. Format and diff checks pass.

The original full-run guard expected an admission InternalError for a missing identifier default; that is now a runtime ReferenceError. The guard was corrected to a genuinely unsupported object default without removing the causal no-fallback assertion, then the complete suite reran. Earlier no-space/stale-cache build failures are recorded separately, not counted as semantic results. Fresh baseline/corpus logs replaced externally removed temporary evidence.

Evidence index: /Users/chris/.cache/zig-js-798.QefIvI/README.md. All 24 temporary corpus files were removed after retaining their fixtures. Build-cache cleanup reduced this evidence directory from 445 MB to 92 MB while preserving logs, tested executables, source diff, and shard timing data. No public performance claim.

  • Pushed required integration verified: CI 33130214332 at descendant e4f76af completed successfully: 53 jobs passed, one scheduled-only job skipped, zero failures. Superseded/cancelled earlier runs are not counted as successful gates.

Follow-up #799 owns assignment/update initializer admission; its existing provided-argument failures are unchanged by this fix. The separate native ownership audits remain on #787/#791.

Activity

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Metadata

Metadata

Assignees

No one assigned

    Labels

    No labels
    No labels

    Type

    No type

    Projects

    No projects

      Milestone

      No milestone

      Relationships

      None yet

      Development

      No branches or pull requests

      Issue actions