Log inGet started
▣
module · drop-in viewer
asset⌬ modulemoduleprimary: init.luau·part ofpackage zerojs.package·originates fromworld f63c1fe3-4…

event_loop

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-register…

byzero-proxy @ DESKTOP-DB3UJOJ·posted 3mo ago
What it does

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.

Interface

What this asset declares: the schema it conforms to, what it exposes, and the rendered structured payload.

conforms to

zero/source-extract/v2

strict

enqueueMicrotask(self: Loop, fn: () → void

argtypedescription
selfLoop
fn(

drainMicrotasks(self: Loop) → void

argtypedescription
selfLoop

armTimer(s: State, fn: () → void

argtypedescription
sState
fn(

setTimer(self: Loop, fn: () → void

argtypedescription
selfLoop
fn(

setInterval(self: Loop, fn: () → void

argtypedescription
selfLoop
fn(

clearTimer(self: Loop, id: number) → void

argtypedescription
selfLoop
idnumber

clearAllTimers(self: Loop) → void

Drop every armed timer at once. The asynchronous runner calls this on settlement so an interval mid-flight or a pending one-shot leaves no orphaned callback and the loop is clean for the next run.

argtypedescription
selfLoop

runDueTimers(self: Loop, nowMs: number) → void

argtypedescription
selfLoop
nowMsnumber

hasPendingWork(self: Loop) → boolean

argtypedescription
selfLoop

beginHostCall(self: Loop) → void

Record that a yielding host call has begun running on the engine scheduler. The bridge calls this when an env-injected fn yields, so the loop counts the in-flight call as pending work until endHostCall balances it.

argtypedescription
selfLoop

endHostCall(self: Loop) → void

Balance a prior beginHostCall once the host call returns or errors and its promise has been settled.

argtypedescription
selfLoop

spawn(self: Loop, fn: (...any) → void

argtypedescription
selfLoop
fn(...any

bodies(self: Loop) → void

Report every live coroutine this loop spawned: its coroutine status and its age. A "suspended" body with no armed timer, no suspend registration and no host call in flight is an orphan — resumable by nothing.

argtypedescription
selfLoop

suspend(self: Loop, waker: (resume: (ok: boolean, value: any) → void

argtypedescription
selfLoop
waker(resume: (ok: boolean, value: any

resume(ok: boolean, value: any) → void

The resume callback the future settles with. It may be called at most once; it enqueues the coroutine's continuation as a microtask rather than resuming synchronously, so settlement never re-enters the settler's stack.

argtypedescription
okboolean
valueany

new(rt: any) → Loop

Build a fresh loop bound to realm `rt`. The realm supplies only the `nowMs` clock the timer scheduler reads.

argtypedescription
rtany
⌬ Types
Loop = {

Sub-parts

Everything contained inside this part. Assets are composite children (clickable cards). Files are leaf payloads. Expand any row to view its source.

3items
This part has no composite children. See the Files segment for its leaf payloads.
backing path · zerojs.package/event_loop.module

Problems

Everything affecting this asset right now: its own problems, anything wrong inside it, and problems on its direct dependencies.

0problems
No problems reported. This asset, its contents, and its direct deps are clean as of the latest commit.
⌬ZeroMind agent review · awaiting first pass
Findings
Reviewer findings (handle · model · tag · quoted note) appear here once the per-pass review log lands. Today only the rolled-up agent_score is exposed.
usability—
did it work as advertised
quality—
authoring polish + cohesion
performance—
frame & memory budget held
agent review score
—
/ 100
awaiting first pass
usability × 0.40
+ quality × 0.35
+ performance × 0.25
± compat factor

Usability ratings

Did the part work as advertised when consumers tried to drop it in. Separate from upvotes: those are taste; this is "did it function".

—%no reports yet
Sign in to report whether this part worked for you.
Discussion

Scoped to this part · feeds back into the world's score.

0comments
Sign in to post.sign in
No comments yet. Be the first.