ReviewOS

zig-utils/zig-js

Globals: resolve identifiers from live object bindings

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

Parent: #465 Related: #1064, #498

Identifier/reference resolution still treats root environment mirror entries as declarative bindings after the corresponding global-object property is gone. Object Get was repaired in #1064; this separate boundary affects reads, typeof, assignment, deletion, inheritance, and warmed VM assumptions.

Executed seven-assertion probe after deleting globalThis.Math:

  1. typeof Math === "undefined".
  2. Reading Math throws ReferenceError.
  3. Strict assignment to Math throws ReferenceError.
  4. Sloppy assignment recreates globalThis.Math.
  5. Sloppy delete of Math succeeds.
  6. A subsequently inherited Math property supplies the identifier value.
  7. Deleting a lexical name returns false and preserves a same-named global-object property.

Node returns seven true values. Current tree and required-bytecode binaries return seven false values.

Acceptance:

  • Global object environment bindings resolve from live own/inherited property presence and descriptors, without falling back to stale mirror values.
  • Captured References preserve strict/sloppy GetValue/PutValue/Delete semantics and declarative lexical/TDZ/const/function-name rules.
  • Reuse the canonical Reference pipeline for VM stores where appropriate; remove obsolete duplicate assignment helpers rather than add another fallback.
  • Warmed no-JIT/native global proofs miss after deletion, descriptor changes, and relevant prototype mutation.
  • Pin deleted builtins/eval globals, inherited properties, lexical name/property collisions, with/eval side effects, GC, and no-GIL behavior against Node.
  • Focused normal/unsuppressed TSan and exact before/after global/declaration/eval corpus gates pass.
9 days ago

Implemented in 81d4f89.

Root mirror values no longer revive missing object-environment bindings. Reads and captured References follow live own/inherited properties; lexical deletion preserves same-named object properties. VM named stores reuse the rooted canonical Reference/PutValue pipeline, and the obsolete duplicate assignment helpers are removed. Global/environment pointers are rooted across observable callbacks.

Evidence:

  • All seven original assertions now match Node in both tree and required-bytecode modes.
  • Persistent tree/required/shared matrices cover strict/sloppy assignment, typeof/read failures, inheritance, lexical collisions, eval-created bindings, RHS deletion after Reference capture, getters, and GC.
  • Warmed native global proof explicitly publishes before deletion and observes correct misses/replacements after deletion, prototype mutation, and descriptor replacement.
  • An actual no-GIL worker observes coordinated deletion and inherited replacement.
  • Broader global suite: 39/39. Final focused tests: 5/5 normally and under unsuppressed TSan. Native proof tests: 2/2 normally and under TSan.
  • Test262 transcripts are byte-identical before/after: global-code 42, let 145, const 136, var 178, delete 69, assignment 485, with 181, eval 10. All 1,246 pass on both sides, with zero failures and zero flips. Inventory passes.

One old standalone recursive-global fixture had created an empty global object with only an environment entry; it now publishes the same startup properties as Context instead of depending on the removed fallback.

Sign in to comment on this issue.