ReviewOS

home-lang/home

Native test isolation: wire the JSC module-record bridge for fresh globals

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

Current status: completed on main in 7cde27ae4.

Follow-up to #66 and the native test CLI integration in #481. The native entry point now parses --isolate instead of silently ignoring it, exposing a real runtime gap.

Original reproduction (before this fix)

From the Home checkout, with the native JSC debug build:

HOME_NATIVE_VM=1 HOME_CORPUS_FULL_VM=1 ./zig-out/bin/home-debug test packages/runtime/test/bun-corpus/cli/test/isolation.test.ts -t 'without --isolate, leaked global|with --isolate, each file gets|with --isolate, --preload re-runs|with --isolate, module state'

The byte-identical upstream file reports 1 pass / 3 fail / 15 filtered out, not a green isolation run. The non-isolated leakage control passes. Fresh-global, preload, and module-state isolation cases fail when a child reaches JSC__IdentifierArray__create in packages/runtime/src/bundler_jsc/analyze_jsc.zig. That implementation still panics with JSC module-record bridge not linked: parked Phase 12.2 C++ glue (unused on the transpile/corpus path). The caller is the native zig__ModuleInfoDeserialized__toJSModuleRecord path from BunAnalyzeTranspiledModule.cpp.

Bun 1.3.14 runs the same unmodified selection with 4 pass / 15 filtered out / 0 fail / 10 assertions. Source pin: 4982b91e3702094330f3be3883354c52b8c01323.

Required work

Wire the actual JSC identifier-array/module-record bridge and validate its ABI and lifetimes, then exercise fresh globals, module state, preload hooks, and the full isolation resource-cleanup corpus. Preserve assertions, workloads, and deadlines. No serial fallback, ignored flag, stub module record, or successful summary in place of executing the isolated files.

Keep this separate from process exit dispatch (#463), worker task/resource shutdown (#465/#468), and parallel test orchestration (#485). The selected non-isolated control does not establish isolation parity.

Reproduced during the published CLI checkpoint 1340cebd5. At that CLI checkpoint the isolation subsystem was still failing. The implemented checkpoint below supersedes that status; this issue stays open pending integration. See #481 for the complete verification boundary.

Published implementation and verification

Native isolation checkpoint — 6e092777a

The implementation was originally published on codex/runtime-port as Chris Breuer without coauthors and is now integrated on main. #484 passes the entire unchanged isolation file: 19 tests / 67 assertions. The real JSC module-record bridge replaces the parked panic path. File-boundary cleanup releases watcher, server, timer, watch-file scheduler, and AbortSignal GC references; server callback protections are balanced across reload and destruction.

Verification: native build and unchanged cached rebuild 17/17; generator/ABI tests 8 tests / 135 assertions; all 20 native regression files pass, including expanded isolation probes. Fourteen selected unchanged upstream commands total 92 passing tests / 242 assertions, including the 50-test CLI regression set. Two platform skips and 231 filtered cases in those selections are not passes. The existing AbortSignal spawn-glyph-only check alone is not proof of child assertion execution; direct native lifecycle and timeout checks provide separate evidence. Workloads, deadlines, and upstream assertions were preserved. Full details and control limitations are in docs/docs/NATIVE_RUNTIME_BINDINGS.md.

Separate newly tracked failures: fake clocks #490 (16 pass / 14 fail, also reproduced before this checkpoint; Bun control 30 pass) and deferred imports #491 (0 pass / 1 fail / 19 filtered out in the selected parser reproduction). Parallel orchestration #485 and the full worker eval deadline #482 remain open. Installed Bun 1.3.14 fails four newer isolation cases itself, so no passing full-file Bun control is claimed. The full port and 100% logical Bun-suite compatibility are still incomplete.

The cached-module bridge now uses real extern calls and the current C++ requested-module phase ABI, validates cached identifier/string/record bounds, and preserves SourceProvider ownership. The existing metadata producer represents eager imports only; #491 covers deferred phases end to end.

Cleanup closes fs.watch without user close callbacks, stops native servers before socket-group closure, removes watch-file registry entries on the JS thread, prevents duplicate intrusive scheduler tasks, and drains the retired scheduler safely. Real/fake timer cancellation releases native and JS pins. A Home-owned AbortSignal GC bridge distinguishes a cancelled timeout from an active timeout box, avoiding eight retained globals with long abort listeners. Header ABI checks remain strict; no class layout was changed.

The added native regression runs eight fresh files in each of two lifecycle modes, checks Home execution and every body, exercises repeated identical server reloads and explicit closes, pending initial watch-file work, real/fake long AbortSignal listeners, and bounds live globals at four. The previous AbortSignal probe accumulated eight; the final probe stays at two to three.

Adjacent unchanged checks: fs.watchFile 9 pass / 2 platform skips / 30 assertions, discarded WebSocket reload handlers 1/3, server pending requests 2/3, reload selection 1/2 (200 filtered), AbortSignal behavior 5/12, and abort-listener lifetime 5/6. General task cancellation #465, producer quiescence #468, and parallel runner #485 are not completed by this issue. No ASAN, other-platform, or whole-suite parity claim is made.

8 days ago

Native isolation checkpoint — 6e092777a

Published on codex/runtime-port as Chris Breuer, without coauthors; not yet merged to main. #484 now passes the entire unchanged isolation file: 19 tests / 67 assertions, plus three consecutive repeat runs. The real JSC module-record bridge replaces the parked panic path. File-boundary cleanup releases watcher, server, timer, watch-file scheduler, and AbortSignal GC references; server callback protections are balanced across reload and destruction.

Verification: native build and unchanged cached rebuild 17/17; generator/ABI tests 8 tests / 135 assertions; all 20 native regression files pass, including expanded isolation probes. Fourteen selected unchanged upstream commands total 92 passing tests / 242 assertions, including the 50-test CLI regression set. Two platform skips and 231 filtered cases in those selections are not passes. The existing AbortSignal spawn-glyph-only check alone is not proof of child assertion execution; direct native lifecycle and timeout checks provide separate evidence. Workloads, deadlines, and upstream assertions were preserved. Full details and control limitations are in docs/docs/NATIVE_RUNTIME_BINDINGS.md.

Separate newly tracked failures: fake clocks #490 (16 pass / 14 fail, also reproduced before this checkpoint; Bun control 30 pass) and deferred imports #491 (0 pass / 1 fail / 19 filtered out in the selected parser reproduction). Parallel orchestration #485 and the full worker eval deadline #482 remain open. Installed Bun 1.3.14 fails four newer isolation cases itself, so no passing full-file Bun control is claimed. The full port and 100% logical Bun-suite compatibility are still incomplete.

8 days ago

Follow-up #490 is implemented and verified in d0ed7c906 on codex/runtime-port: the unchanged core fake-clock suite now passes 30 tests / 83 assertions, and both reset APIs release timer/AbortSignal references outside the heap lock. All 21 native regression files and the full unchanged isolation file (19 / 67) pass after this change. Main tracker #66 has the complete accounting, including 14 expected-failure cases and 438 TODOs excluded from logical completion. The unrelated caught-immediate-exception hang is now tracked in #493. Not yet merged to main; no full-port completion claim.

8 days ago

Completed on main in 7cde27ae421975a37d5417f3450416f22d2bbfa1, authored and committed as Chris Breuer without coauthors.

Current exact ReleaseFast/JSC evidence against the unchanged pinned fixture:

  • HOME_NATIVE_VM=1 home test cli/test/isolation.test.ts: 19 pass / 0 fail / 67 assertions.
  • The four pathless temporary-directory children now enter the native Bun test runner without requiring the legacy HOME_CORPUS_FULL_VM flag. Before this commit they incorrectly entered Home's monorepo test frontend and reported zero files.
  • Fresh globals, per-file preload/module state, SourceProvider/module-record reuse, leaked subprocess/socket/watcher/timer cleanup, AbortSignal cleanup, server cleanup, and the stat-watcher work-pool race all execute and pass.
  • ReleaseFast/JSC build: 46/46 steps.

The fix honors the existing explicit HOME_NATIVE_VM=1 contract in arbitrary temporary projects while retaining --home / --zig overrides. No fixture, assertion, workload, deadline, skip, or TODO changed. Broader runtime and whole-suite parity remain open in #66.

Sign in to comment on this issue.