Problem
A VM closure created inside a live block, class, loop-head, disposal, or with Environment Record captures that runtime record through Function.closure while its statically resolved outer function bindings remain in Frame slots. Direct eval needs the exact lexical order current frame -> captured runtime records -> parent frame. The current DirectEvalPlan rejects any nonzero parent_environment_depth because materialization can only place every activation view on one side of Function.closure.
This is the final explicit runtime-Environment boundary in #771. Admission must stay fail-closed until the engine can represent the interleaving without changing published Environment.parent links or copying binding values.
Scope
- Retain each ordinary Frame defining closure Environment as a precise, relocating edge so every child-to-parent frame boundary can recover its captured runtime segment.
- Extend immutable direct-eval plans with validated boundary metadata for the exact number and ordering of intervening Environment Records, including named-function-expression records.
- Materialize identity-preserving forwarding records whose own-binding operations target the original declarative or object Environment Record while their parent links interleave activation views in spec order.
- Preserve TDZ, const/function-name state, deletability, aliases, with HasBinding and Symbol.unscopables observability, catch Annex B rules, per-iteration binding identity, and closures produced by eval.
- Keep publication transactional under deterministic OOM, exact under moving GC, and race-free for escaped frames and shared no-GIL execution.
No-workaround rules
- No binding-value snapshots, source rewriting, published-parent mutation, global fallback, tree-walker callback, broad admission, or eager materialization for calls that do not resolve to the realm eval intrinsic.
- No stacks, queues, jobs, Promise/microtask, Worker lifecycle, or Map/Set iterator implementation changes.
Acceptance
- Required bytecode and forced tree-walker agree for direct eval inside nested block/class/catch/loop and with scopes, including shadowing, TDZ, mutation, deletion, named function-expression self binding, and eval-created escaping closures.
- Runtime records remain exact live identities: per-iteration captures stay distinct, with traps and Symbol.unscopables run in the specified order, and later initialization or mutation is visible through both original and interleaved chains.
- Frame closure edges and forwarding-record target edges trace and relocate precisely; deterministic allocation-failure sweeps publish no partial frame cache or vm.env chain.
- Shared-realm no-GIL and TSan witnesses show no parent-edge or binding-table race, including concurrent first materialization and escaped defining frames.
- The parent_environment_depth and current environment_depth barriers are removed only for fully validated plans; malformed or unsupported boundaries fail closed without fallback.
- Focused compiler/VM/frontend, relevant exact Test262 eval/function/with/class accounting, full units, threadfuzz, debugger, watchdog, moving-GC, TSan, and no-GIL gates pass with zero regressions.
- A conventional commit lands directly on main and cross-links #771 and #776; exact Test262 flips are recorded without an unmeasured performance claim.
Completed integration
CI run 33113309062 completed successfully on main commit 8a1398ffc04e9e30987f968693667c7271ca3ce1, a descendant containing this implementation. All 53 executed jobs succeeded (unit and TSan-unit shards, Linux no-GIL TSan, functional/no-GIL corpus gates, fuzz profiles, ABI, Wasm, Test262 parallel, and docs); the scheduled-only nightly job was skipped. Together with the measured local evidence in the comments, this completes this issue's acceptance.
The independently scoped provisional root-registration/preparation defect remains open in #787. This closure covers registered caller-root relocation and exact eval environment identity, not that outstanding activation-driver ownership work. The exposed capture-metadata race was fixed and verified in #789.