Skip to content

VM: expose ordinary activation bindings to direct eval #771

Description

@chrisbbreuer

Parent: #465
Related: #498

Problem

Ordinary function bytecode has exact frame slots, TDZ metadata, arguments objects, receiver/home-object state, and direct-eval call opcodes, but compilePlainFunctionInner and nested-template compilation still reject every function whose parser metadata sets uses_direct_eval. The interpreter therefore remains the only activation model in which direct eval can observe and mutate a caller function local. This is now a causal universal-bytecode boundary, not a missing parser or eval implementation.

Scope

  • Give a running ordinary bytecode activation an explicit direct-eval binding view over parameters, var/function bindings, lexical slots and TDZ state, mapped/unmapped arguments, this, super, new.target, and private-name context.
  • Preserve EvalDeclarationInstantiation for strict and sloppy direct eval, including deletable eval declarations, var/lexical conflicts, parameter-environment restrictions, catch/Annex B interactions, and mutation of the exact caller binding.
  • Lower fixed and spread direct-eval calls, tail-position eval calls, nested arrows, methods, constructors, recursive/reentrant activations, and eval that defines or invokes closures without effect replay.
  • Keep indirect/member/optional eval global, preserve cross-realm intrinsic identity, and retain causal admission reasons for syntax whose dynamic environment is still incomplete.
  • Make the activation view precise under moving GC, deterministic OOM, debugger/watchdog state, shared-chunk no-GIL execution, and activation teardown.

No-workaround rules

  • No source rewriting, local-value snapshots that lose writes or TDZ identity, eager heap allocation of every frame local, AST callback from required bytecode, globalizing direct eval, permissive policy default, or hidden tree-walker fallback.
  • No stacks, queues, jobs, Promise/microtask, Worker lifecycle, or Map/Set iterator implementation changes.

Acceptance

  • Forced tree-walker and required bytecode agree for reads/writes/declarations across parameters, var, let/const/class, shadowing, TDZ, catch, mapped/unmapped arguments, this, super, new.target, and private names.
  • Fixed, spread, tail-position, arrow, method, constructor, nested/reentrant, closure-producing, strict/sloppy, direct/indirect, and cross-realm eval controls preserve exact results, errors, side effects, and step/debugger ordering.
  • The activation binding view is bounded, moving-GC safe, failure-atomic under injected OOM, race-free under shared no-GIL/TSan execution, and released at activation teardown.
  • Admission inventory removes the broad uses_direct_eval rejection only for complete semantics; unsupported nested syntax remains causally fail-closed with no interpreter callback.
  • Focused compiler/VM/frontend, full units, relevant exact Test262 eval/function/class accounting, TSan, no-GIL, threadfuzz, debugger, watchdog, and moving-GC gates pass with zero regressions.
  • A conventional commit lands directly on main and cross-links VM: make correct JavaScript universally bytecode-eligible #465 and VM: build a fast no-JIT execution tier for restricted hosts #498; flips and exact measured boundaries are recorded without a performance claim.

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