Implement timer APIs and the event loop infrastructure needed to schedule callbacks.
Scope#
Event Loop#
- Implement a basic event loop that processes:
- Microtasks (Promise callbacks — already have microtask queue in Promise impl)
- Macrotasks (timer callbacks)
- Animation frame callbacks
- The event loop should integrate with the platform crate's run loop (AppKit NSRunLoop)
- Provide a way to pump the event loop from tests without a real window
Timer Functions (globals)#
setTimeout(callback, delay)— schedule callback after delay (ms), return timer IDclearTimeout(id)— cancel a pending timeoutsetInterval(callback, delay)— schedule repeating callback, return timer IDclearInterval(id)— cancel a repeating timer- Timer IDs are positive integers, monotonically increasing
- Delay of 0 or negative should still be deferred (not synchronous)
- Support string argument to setTimeout (eval — lower priority, can skip)
requestAnimationFrame#
requestAnimationFrame(callback)— schedule callback before next repaint, return IDcancelAnimationFrame(id)— cancel a pending animation frame- Callback receives a DOMHighResTimeStamp argument (milliseconds since page load)
- In test mode, can use a fake timestamp
Timer Storage#
- Maintain a timer heap or sorted list of pending timers
- Each timer: { id, callback (GcRef), delay, interval (bool), scheduled_at }
- Timer callbacks must be GC roots while pending
- Cleared timers should release their callback references
Integration with Microtasks#
- After each macrotask (timer callback), drain the microtask queue
- This ensures Promise .then() callbacks run between timer callbacks
- Order: run macrotask → drain microtasks → next macrotask
Acceptance Criteria#
-
setTimeout(fn, 100)executes fn after ~100ms -
clearTimeout(id)prevents execution -
setInterval(fn, 100)executes fn repeatedly -
clearInterval(id)stops repetition -
setTimeout(fn, 0)defers execution (not synchronous) -
requestAnimationFrame(fn)schedules before next paint - Timer callbacks run after microtask queue drains
- Timer IDs are unique positive integers
- Testable without a real window/run loop
Phase 11 — DOM-JS Bindings (issue 5 of 8). Depends on: issue 1 (Console API, for testing output).