ReviewOS

home-lang/home

Native fake timers: implement clock overrides and timer advancement

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

Status: implemented and verified on codex/runtime-port; keeping this issue open pending integration.

Native fake-clock checkpoint — d0ed7c906

Committed and pushed on codex/runtime-port as Chris Breuer, without coauthors; not yet merged to main. #490 now passes the unchanged core fake-timer file: 30 tests / 83 assertions, up from 16 pass / 14 fail. Installed Bun 1.3.14 passes the same 30 / 83 control. Mockable timer deadlines now share the fake clock, fractional advancement retains nanoseconds, real option/getter validation runs before clock mutation, and both reset paths release timer/AbortSignal references outside the heap lock.

Verification:

  • Native build and cached rebuild: 17/17 steps.
  • All 21 native regression files pass; the new fake-clock test also passes three consecutive repeats and fails against the cached pre-change Home binary. It checks actual Home execution, inherited/throwing getters, Date/performance agreement, fractional nested callbacks, retained cancelled handles, natural exit and bounded GC counts after allocating 3,072 timeout/interval wrappers plus 1,536 AbortSignal timeouts across resets.
  • Entire unchanged fake-timer directory: 61 reported pass / 438 TODO / 0 fail / 115 assertions in Home and Bun. 14 reported passes are it.failing cases, not implemented features; all 438 TODOs are excluded from logical completion. There are 47 ordinary passing tests, including the core 30.
  • Unchanged isolation: 19 tests / 67 assertions. Unchanged timers/promises: 4 / 7. Twenty-four selected corpus files match the pinned Bun checkout byte-for-byte. Focused Pickier, timer-file Zig formatting and whitespace checks pass.

The wider Node timer file still hangs after printing 19 passes on its final caught-immediate-exception fixture. This happens in the pre-change Home binary too. The standalone fixture times out in both Home binaries and exits successfully in Bun; the original-checkout Bun control passes the full 20 / 31. Tracked separately in #493; neither incomplete runs nor expected failures count as logical parity.

Deferred imports #491, parallel coordinator/IPC #485, the full worker deadline #482, remaining native ownership, other platforms and full-suite parity remain open. The full port and 100% logical Bun-suite compatibility are not complete. See docs/docs/NATIVE_RUNTIME_BINDINGS.md for the implementation and verification boundary.

Original failure report (historical)

Follow-up to #66, #481, and #484. Isolated-file cancellation must remain distinct from implementing fake clock semantics.

Native reproduction

HOME_NATIVE_VM=1 HOME_CORPUS_FULL_VM=1 ./zig-out/bin/home-debug test packages/runtime/test/bun-corpus/js/bun/test/fake-timers/fake-timers.test.ts

The unchanged upstream file reports 16 pass / 14 fail / 65 assertions. Failures include advancing timer callbacks, mocked Date.now(), and useFakeTimers({ now }). This same result was reproduced with the cached native binary from before the isolation work; it is not a newly introduced failure from cancelling isolated-file timers. Installed Bun 1.3.14 passes the same file with 30 pass / 83 assertions.

Required work

Connect fake-clock time, timer scheduling/advancement, Date overrides, and parsed now options through the real native implementation. Check cancellation and reset lifetimes as well as observed times. Preserve the upstream workload and assertions. A working isFakeTimers() or empty timer count is not proof that callbacks advance or clocks are overridden.

Source pin: 4982b91e3702094330f3be3883354c52b8c01323. Reproduction was made during the native isolation work on codex/runtime-port. #484 covers cancellation between isolated globals, not the full fake-timers suite.

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

Native fake-clock checkpoint — d0ed7c906

Committed and pushed on codex/runtime-port as Chris Breuer, without coauthors; not yet merged to main. #490 now passes the unchanged core fake-timer file: 30 tests / 83 assertions, up from 16 pass / 14 fail. Installed Bun 1.3.14 passes the same 30 / 83 control. Mockable timer deadlines now share the fake clock, fractional advancement retains nanoseconds, real option/getter validation runs before clock mutation, and both reset paths release timer/AbortSignal references outside the heap lock.

Verification:

  • Native build and cached rebuild: 17/17 steps.
  • All 21 native regression files pass; the new fake-clock test also passes three consecutive repeats and fails against the cached pre-change Home binary. It checks actual Home execution, inherited/throwing getters, Date/performance agreement, fractional nested callbacks, retained cancelled handles, natural exit and bounded GC counts after allocating 3,072 timeout/interval wrappers plus 1,536 AbortSignal timeouts across resets.
  • Entire unchanged fake-timer directory: 61 reported pass / 438 TODO / 0 fail / 115 assertions in Home and Bun. 14 reported passes are it.failing cases, not implemented features; all 438 TODOs are excluded from logical completion. There are 47 ordinary passing tests, including the core 30.
  • Unchanged isolation: 19 tests / 67 assertions. Unchanged timers/promises: 4 / 7. Twenty-four selected corpus files match the pinned Bun checkout byte-for-byte. Focused Pickier, timer-file Zig formatting and whitespace checks pass.

The wider Node timer file still hangs after printing 19 passes on its final caught-immediate-exception fixture. This happens in the pre-change Home binary too. The standalone fixture times out in both Home binaries and exits successfully in Bun; the original-checkout Bun control passes the full 20 / 31. Tracked separately in #493; neither incomplete runs nor expected failures count as logical parity.

Deferred imports #491, parallel coordinator/IPC #485, the full worker deadline #482, remaining native ownership, other platforms and full-suite parity remain open. The full port and 100% logical Bun-suite compatibility are not complete. See docs/docs/NATIVE_RUNTIME_BINDINGS.md for the implementation and verification boundary.

8 days ago

The separately discovered fixture hang in #493 is fixed in 6d797186c. Its cause was failed POSIX spawn error handling during Node common-helper import, not fake-clock or immediate dispatch. Core fake clocks remain 30 tests / 83 assertions, isolation 19 / 67, and all 21 native regression files pass. The full Node timer file now passes 20 / 31. #66 records remaining spawn-related gaps #495–#497 and the full-port boundary.

8 days ago

Integration status reconciled on current main: fake-clock implementation d0ed7c906d48692aa702dfc3cdd54ae5e1bad59a is an ancestor of ff9dc16be5503b066bf5accc3af1071ffd358094.

Fresh current-main validation:

  • tests/runtime/native-fake-timers.test.mjs: pass, including advancement, Date/performance agreement, reset lifetime, and GC controls
  • unchanged pinned core js/bun/test/fake-timers/fake-timers.test.ts: 30/30 pass, 0 fail

The fake-clock implementation and pending-integration scope are complete. Explicit upstream TODOs and broader timer/platform parity remain excluded and tracked under #66.

Sign in to comment on this issue.