Parents: #465, #498 Related: #491, #616, #618, #706, #721, #724
Problem
Program, plain-function, and async bytecode admission reject for-in statements even though generators have a partial lowering through enum_keys. That generator path materializes a JavaScript Array and drives it through the ordinary iterator protocol. A patched Array iterator can therefore introduce observable calls and synthetic IteratorClose behavior that for-in must not perform, and keys deleted before visitation are not rechecked. Extending that path to more tiers would broaden a semantic divergence rather than remove one.
Scope
- Add an owned bytecode enumeration path shared by program, plain, generator, and async bodies.
- Evaluate the RHS once, box primitives once, snapshot the ordered candidate string-key set without exposing it, advance one candidate per VM dispatch without invoking user-modifiable iterator methods, and recheck the candidate against the original target before binding.
- Keep enumerator state activation-local and GC-scanned across ordinary execution, suspension, exceptions, debugger/watchdog checkpoints, native-tier fallback, and labeled abrupt control flow.
- Preserve null/undefined no-op behavior, prototype shadowing, enumerable ordering, Symbol exclusion, Proxy ownKeys/descriptor/has effects, deletion before visitation, and the absence of synthetic IteratorClose.
- Preserve
var/let/const, assignment/member/destructuring targets, per-iteration closure cells, defaults, and computed keys. Program patterns and member references must use #706 activation scratch; function, generator, and async bodies retain frame/environment activation temps. - Keep unsupported
for (using ... of ...)disposal on its causal path.
No-workaround rules
- No source rewriting, user-visible helper iterator, Array iterator dependence, duplicated RHS/key evaluation, tree-walker callback for the owned enumeration path, hidden program globals, result cache, benchmark recognizer, skipped Proxy/descriptor checks, or stack/queue/job runtime changes.
Acceptance
- Program/plain/generator/async admission uses one owned
for-inoperation family with exact operand-stack and root accounting. - Forced tree-walker and required-bytecode witnesses match key order, effects, exceptions, labels, deletion, primitives, Proxies, native patterns, captures, and suspension.
- Program identifier, member, and destructuring bindings prove per-iteration and nested-evaluation isolation through #706 scratch, without synthesized globals.
- Focused compiler/frontend, full units, applicable TSan/GC relocation, and exact nonzero Test262
for-inaccounting pass with zero regressions. - Parent issues and the landing commit are cross-linked with quantified evidence.