ReviewOS

home-lang/home

Native deferred imports: port syntax, evaluation phases, and cached module metadata

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

Follow-up to #66 and #484. The restored module-record bridge uses evaluation phase explicitly for Home's current metadata producer; the current Bun C++ ABI also supports deferred phase, which the native Home parser/printer and cache metadata do not yet represent.

Native reproduction

HOME_NATIVE_VM=1 HOME_CORPUS_FULL_VM=1 ./zig-out/bin/home-debug test packages/runtime/test/bun-corpus/js/bun/resolve/import-defer.test.ts -t 'defers module evaluation until a property is accessed' --max-concurrency=1

The unchanged upstream selection reports 0 pass / 1 fail / 19 filtered out / 1 assertion. Its child rejects import defer * as ns from "./dep.js" with Expected "from" but found "*", before testing deferred evaluation. Filtered cases are not passes; no full-file parity is claimed.

Required work

Port the syntax, resolution/evaluation behavior, import-phase metadata and serialization, namespace handling, and JSC bridge together. Preserve ordinary eager imports and cached SourceProvider reuse across isolated globals. Exercise the complete upstream deferred-import suite, including cache/warm-load paths; merely passing a true phase bit to C++ is insufficient.

Source pin: 4982b91e3702094330f3be3883354c52b8c01323. Reproduction was made during the native isolation work on codex/runtime-port. Keep this separate from parallel test coordination (#485) and fake-timer semantics (#490).

8 days ago

Reproduction and boundaries are recorded in the published isolation checkpoint 6e092777a and docs/docs/NATIVE_RUNTIME_BINDINGS.md. #484 is verified on the branch; fake-clock work #490 and deferred-import work #491 remain separate open failures under #66.

8 days ago

Implemented and published in fd1471630 on codex/runtime-port.

The port now carries deferred module evaluation through the full native path:

  • contextual import defer * as ns parsing while preserving ordinary/escaped defer identifiers and invalid-grammar errors;
  • AST/import-record phase state, dead-code namespace preservation, and printer round-tripping;
  • (specifier, phase) request dedup so eager and deferred requests for one module coexist;
  • deferred namespace import entries, local re-export behavior, import attributes, TLA dependencies, and JSC useImportDefer enablement;
  • serialized phase bytes with validation, alignment padding, and transpiler-cache version 21.

Verification:

  • exact pinned test/js/bun/resolve/import-defer.test.ts SHA a9ea4987…: 20 pass / 0 fail / 54 assertions;
  • cold and warm on-disk runtime transpiler-cache runs across two isolated globals: 2/2 pass on each run;
  • native ModuleInfo round-trip covers eager/deferred duplicate specifiers, first attributes per phase, deferred local exports, and corrupt phase rejection;
  • scoped home_rt: 1,830 pass / 19 skip / 0 fail, 20/20 build steps;
  • debug build: 18/18 build steps;
  • Zig formatting, git diff --check, scoped Pickier, and exact corpus hashes pass.

The adjacent pinned compile-bytecode source is also byte-identical, but its harness currently aborts before registering tests because this checkout lacks its esbuild dependency. Direct investigation found a generic standalone embedded-bytecode cache miss even for console.log("hello"); that is independent of deferred metadata and is tracked as #549.

Sign in to comment on this issue.