docs / Runtime

Reactive Core

The runtime reactivity engine: cells, the microtask scheduler, block trees, scoped flushing, and the flushSync/tick escapes.

The runtime reactivity engine implements tracked cells, derived values, effects, and a block-tree scheduler. (The legacy `track.ts` module is dead code and must not be imported.)

Cells

  • `track(value)` creates a tracked cell. Reads register a dependency on the active reaction; writes mark the owning block dirty and schedule it.
  • `untrack(fn)` runs fn with tracking disabled; `peek(cell)` reads without registering a dependency.
  • `derived(fn)` is a computed cell: fn runs under an effect and its result is written to the derived cell. Mutating tracked state inside a derived evaluation is forbidden.

Scheduler

  • Default mode is microtask-batched: writes enqueue `queueMicrotask(flush_microtasks)`, and one flush runs all queued root blocks.
  • More than 1001 consecutive flush rounds throw "Maximum update depth exceeded" — the effect read-write loop guard.
  • `flushSync(fn)` switches to synchronous scheduling while fn runs; `tick()` resolves on the next requestAnimationFrame.
  • Low-level control: `schedule_update`, `queue_microtask` are exported.

Blocks

Every component body and effect compiles to a block in a doubly-linked tree: render blocks, branch blocks, effect blocks, user effects, pre-effects, root blocks and try blocks. `destroy_block(pause/resume)`, `pause_block`, `is_destroyed`, and `on_destroy(fn)` manage lifecycle.

Scoped flushing

Each cell records its owning block. When a block reads a cell owned by another block the flush is scoped, unless the owner is not an ancestor (the `disable_scoped_flush` guard).