ReviewOS

home-lang/home

fix(test): release prior-file socket wrappers before heap assertions

#592
Open chris opened this 9 days ago ·
9 days ago

Parent tracking issue: #66

The unchanged strict full-VM Bun network directory currently has one cross-file heap-accounting failure:

HOME_NATIVE_VM=1 HOME_CORPUS_FULL_VM=1 \
  ./zig-out/bin/home-debug test \
  packages/runtime/test/bun-corpus/js/bun/net

Observed on macOS/arm64 debug at b2de7f1:

  • directory result: 56 pass, 4 upstream platform skips, 1 fail;
  • tcp-server.test.ts expects at most 2 Listener instances but heapStats reports 4;
  • the same listener leak assertion passes when tcp-server.test.ts runs by itself;
  • all individually exercised fd/connect/socket lifecycle cases pass;
  • running with per-test isolation does not eliminate the retained listener wrappers and can expose an additional retained TCPSocket wrapper;
  • filtered cross-file subsets pass, so this is sensitive to prior-file realm/global lifetime rather than a deterministic listener ownership failure.

No test threshold, forced cleanup, fixture mutation, or process-per-file workaround should be added. The runner/runtime needs to release unreachable state from prior files before heap assertions observe it.

Acceptance criteria:

  • the unchanged strict full-VM js/bun/net directory passes the listener count assertion;
  • tcp-server.test.ts still passes in isolation;
  • socket-retention and fd/connect lifecycle tests remain green;
  • no Bun delegation, relaxed heap limits, artificial GC loops, or corpus edits.
9 days ago

Pinned-Bun control result (2026-09-03): this is reproducible in Bun itself at the exact corpus/source SHA, not a Home-only retention divergence.

Control:

/Users/chris/Code/bun/build/release/bun test \
  /tmp/home-lang-bun-port/packages/runtime/test/bun-corpus/js/bun/net

The release binary cannot expose bun:internal-for-testing, so for this diagnostic only I locally stubbed that import and skipped the two createSocketPair() cases. All other source and assertions were unchanged. The result was:

  • 54 pass, 6 skip, 1 fail;
  • the same tcp-server.test.ts assertion expected Listener <= 2 and received 4;
  • the same two retained listeners also reproduce after socket.timeout works in a two-file minimized runner control under both Home and pinned Bun;
  • the retained pair specifically depends on the upstream async try/finally test shape; Home and Bun agree on it after repeated full GCs and more than one second of delay.

The two diagnostic corpus edits were reverted immediately; the Home worktree is clean. This rules out a Home-only module-registry, socket timer, or runner cleanup regression. The assertion became order-sensitive as newer socket regressions were added before the older absolute-count check. I am leaving this issue open for disposition rather than weakening the corpus or introducing Home-only cleanup. Any resolution must either be an upstream logical test correction (baseline/delta accounting) or a shared runtime lifetime improvement demonstrated against Bun as well.

Sign in to comment on this issue.