Skip to content
Petar Liovic edited this page Sep 9, 2026 · 1 revision

How the engine stays alive in dev, records ticks, and turns those ticks into edges.

Singleton (survives HMR)

The engine lives on globalThis under Symbol.for('__basis_engine_instance__').

HMR re-runs modules. A normal let engine would reset the rings every save. The symbol key keeps one instance for the tab so the current window of ticks is not wiped when you edit a file.

Recording a write

recordUpdate marks that variable dirty for this paint frame. Many setStates in the same frame still become one 1 on the ring.

Rings are fixed Uint8Arrays with a moving head. The hot path does not shift() a JS array.

Effects vs events

While an effect is running, updates are attributed to that effect (beginEffectTracking / endEffectTracking). That is the effect_L12 → state edge.

Updates outside an effect (click handler, timeout) share a virtual event node for that frame. Several writes in that batch are siblings of the same event, not a chain from each other.

Event nodes older than the interaction window are dropped on idle passes.

When analysis runs

Only variables that wrote since the last pass are dirty. Pairwise work is dirty × others, not every name against every name, every frame.

That work is scheduled on requestIdleCallback. Ranking for printBasisReport() runs when you ask, not in the background.

What this page is not

It is not a second copy of the hit rule, the Babel rewrite, or the benchmark screenshots. Those have their own pages.

Clone this wiki locally