ReviewOS

zig-utils/zig-js

Runtime: implement AbortSignal.timeout and Bun timeout handle

#330
Closed chris opened this 9 days ago ·
9 days ago

Parent ABI work: #329 Tracked by: #134 and #246 Profiles: #164 (Bun-only private export)

Problem

The Bun profile declares WebCore__AbortSignal__getTimeout, but its return value is a borrowed pointer to an event-loop-owned AbortSignal.Timeout, not an opaque marker. A correct implementation also requires the JavaScript AbortSignal.timeout(milliseconds) path, timer scheduling, cancellation, firing, test-isolation generation, and exact ref balancing. Returning a decorative pointer or always-null stub would make the audit misleading.

Scope

  • Implement standards-correct AbortSignal.timeout(milliseconds) without blocking the calling agent.
  • Add an event-loop timer record with a monotonic deadline, cancellation, firing, and teardown.
  • Keep the timeout signal alive until it fires or becomes unobservable, then release the extra native ref exactly once.
  • Make every abort path cancel and invalidate the borrowed timeout handle before callbacks/events can observe stale state.
  • Implement Bun-profile WebCore__AbortSignal__getTimeout with the pinned borrowed-pointer layout and lifetime contract.
  • Exercise natural firing, early abort, observer removal, teardown, generation isolation, and deadline inspection.
  • Refresh the Bun inventory and runtime fixture; Home must retain its 14-symbol AbortSignal surface without this Bun-only export.

Acceptance

  • Timeout signals abort asynchronously with TimeoutError at the scheduled deadline and never keep the event loop alive by themselves.
  • getTimeout is non-null only while the timer is active and returns the exact event-loop record consumed by the pinned Bun profile.
  • Fire/cancel/abort/teardown races cannot double-unref, use freed timer memory, or dispatch into a replaced realm.
  • No blocking sleep is used to emulate the timer.
  • Focused timer/ABI tests and one descendant full CI matrix are green.
9 days ago

Implemented and pushed in f5125d04 and 66ef3401.

What landed:

  • standards-correct, nonblocking AbortSignal.timeout(milliseconds) with required-argument and unsigned-64-bit range conversion;
  • context-owned monotonic unrefed timers, pre-entry/microtask checkpoints, cancellation, teardown, and generation isolation;
  • observer-driven precise rooting for JS and native listeners, with timeout handles invalidated before abort callbacks/events;
  • Bun-only WebCore__AbortSignal__getTimeout using the pinned 64-byte four-field layout;
  • Bun inventory advanced to 336/461 implemented (125 pending), while Home remains 344/471 with its existing 14-symbol surface;
  • focused engine lifecycle coverage plus a real Bun-profile ABI fixture wired into CI.

Local evidence:

  • zig build test -Dtest-filter="AbortSignal timeout owns" — 3/3 passed, 0 leaked;
  • zig build test-bun-private-abort-signal -Dprivate-abi-consumer=bun — passed; Bun audit 336 implemented / 125 pending;
  • zig build c-api-audit home-private-abi-audit test-home-private-abi — public C 117/117 and Home fixture 333/333 passed;
  • isolated 4 MiB heap-recovery regression probe passed after one transient threshold miss in the intentionally long combined run.

Descendant CI is queued: https://github.com/zig-utils/zig-js/actions/runs/29706389904 . I am keeping the issue open until that complete matrix is green.

9 days ago

Standards follow-up pushed in 4a928338: the exact Web IDL [EnforceRange] unsigned long long conversion uses the unambiguous JavaScript Number range 0..Number.MAX_SAFE_INTEGER, and missing, NaN, infinite, negative, or larger inputs throw TypeError. The focused lifecycle test now covers all rejected classes plus acceptance of the maximum safe value and remains 3/3 green. This supersedes the earlier comment's shorthand “unsigned-64-bit range” wording.

9 days ago

Task-ordering follow-up pushed in 19d10631: an existing Promise job now runs before a due timeout task, and microtasks queued by one timeout listener drain before the next due timer task is selected. The focused lifecycle test asserts promise,abort; it and the exact Bun-profile fixture are green. The final descendant CI will be the run for 19d10631.

9 days ago

Accepted on main through f5125d04, 66ef3401, 4a928338, and 19d10631. This includes nonblocking observer-rooted timeouts, exact Web IDL range conversion, Bun ABI layout/fixture coverage, generation-safe teardown, and task/microtask ordering. Full 41-job descendant CI is green: https://github.com/zig-utils/zig-js/actions/runs/29706564614

Sign in to comment on this issue.