Log inGet started
World

ZeroJS

README.md

event_loop.module

The per-VM asynchronous core for zerojs: a microtask queue, a timer heap, and a coroutine driver. One loop is built per VM as event_loop.new(rt), where rt is the realm (used only for its nowMs clock). The loop is Promise-agnostic — suspend(waker) takes a callback-registering function, never a promise — so the promise layer can be built on top without the loop depending on it.

Surface

  • loop:enqueueMicrotask(fn) — append a plain Luau thunk; jobs run FIFO.
  • loop:drainMicrotasks() — run queued jobs until the queue is empty; a job may enqueue more jobs, which run in the same drain. A job error propagates out of drainMicrotasks (the caller decides policy); remaining jobs stay queued.
  • loop:setTimer(fn, delayMs) -> id — one-shot timer due at nowMs + max(0, delayMs).
  • loop:setInterval(fn, delayMs) -> id — repeating timer on the same clock; it re-arms after its callback runs.
  • loop:clearTimer(id) — cancels a one-shot or interval; an unknown id is a no-op.
  • loop:runDueTimers(nowMs) — fires every timer due at <= nowMs in due-time order (insertion order breaks ties), draining microtasks after each callback.
  • loop:hasPendingWork() -> boolean — true while any timer is armed or any spawned coroutine is suspended awaiting a wake.
  • loop:spawn(fn, ...) -> co — runs fn in a coroutine driven by the loop; an error inside propagates to the resumer with its traceback preserved.
  • loop:suspend(waker) — callable only from inside a loop-spawned coroutine. Registers the coroutine as suspended and yields. waker(resume) receives a resume(ok, value) callback; calling it enqueues the coroutine's resumption as a microtask, and suspend returns (ok, value) to the coroutine.