ReviewOS

zig-utils/zig-js

Compiler: lower import.meta inside module functions

#714
Closed chris opened this 8 days ago ·
8 days ago

Parents: #465, #498 Related: #491

Problem

The module runtime gives every declaring module a stable, distinct lazily created import.meta object, but otherwise eligible module functions had no bytecode lowering for .import_meta. Investigation also found a causal activation gap: generator state retained its ImportMetaSlot, while normal async activation creation/resume and generator-family parameter-default evaluation could inherit the caller slot instead of the declaring module slot.

Scope

  • Add an owned bytecode operation that loads the active declaring module meta-object through the existing lazy ImportMetaSlot contract.
  • Carry the declaring slot through plain, generator, async, and async-generator creation, parameter evaluation, suspension, and resume boundaries.
  • Preserve one null-prototype extensible object per declaring module, stable identity across repeated calls, cross-module distinction, allocation failure, closures, generators, async functions, suspension, and moving/concurrent GC relocation.
  • Preserve lexical provenance when an exported function is called from another module or host entry; never substitute the caller module or global realm.
  • Keep non-module import.meta syntax rejection unchanged and retain exact interpreter fallback for unsupported surrounding syntax.
  • Reject the new operation cleanly from native tiers until they own the same module-root and exception contract.

No-workaround rules

  • No global/environment shadow binding, eager object clone, per-read allocation, source/AST rewriting, tree-walker callback presented as bytecode, process-global cache, or global lock serialization.
  • No stacks/queues/jobs, Promise/microtask, Worker lifecycle, or Map/Set iterator implementation changes.

Acceptance

  • Plain, generator, and async module functions containing import.meta are bytecode-eligible and return the exact declaring-module object.
  • Repeated reads are identical within one module and distinct across modules/callers; creation remains lazy and allocation failure is exact.
  • Suspension plus confirmed moving-GC relocation preserves the live module meta-object and activation root.
  • Forced tree-walker/required-bytecode and automatic native fallback agree without repeated/eager allocation.
  • Focused compiler/module/GC tests, applicable TSan, full units, and exact relevant Test262 before → after accounting pass with zero regressions.
  • Parent/related issues and landing commit carry quantified evidence links.

Landing

8 days ago

Landed on main in ffeedf57.

Measured evidence on the exact landed source:

  • focused import-meta units: 6/6 passed, including eight-lane concurrent first publication and allocation-failure retry;
  • focused TSan: 6/6 passed with zero warnings;
  • forced tree-walker, required bytecode, and automatic native rejection all preserve the declaring-module identity;
  • moving nursery: the exact dependency ImportMetaSlot pointer changed, then suspended generator and async activations resumed with identical identity;
  • frontend: 12/12 passed;
  • full units: 1,826 passed, 1 established skip, 0 failed, 0 leaked across six shards;
  • Test262 test/language/expressions/import.meta: 22/22 before → 22/22 after, byte-identical transcripts, 0 flips and 0 regressions.

No stacks/queues/jobs, Promise/microtask, Worker lifecycle, or Map/Set iterator implementation was changed.

Sign in to comment on this issue.