Architecture
Architecture
Understand the internal architecture visually.
1. Core Runtime
signal(input)
→
base-signal storage
→
value getter
→
EffectHook registration
→
value setter / mutation
→
run dependent effects synchronously
The core runtime is small on purpose:
- `signal()` creates mutable source state
- reading `.value` records the current EffectHook effect on the base signal
- writing `.value` or using `.mutate` runs dependent effects immediately
2. Dependency Tracking
effect(fn)
→
EffectHook
→
signal.value getter
→
base signal effect Set
Tracking is global and temporary:
- `effect()` places itself in the singleton EffectHook before the initial callback
- each live signal getter records a two-way subscription between the signal and effect
- a `finally` block clears the hook when initial execution ends
3. Derived Signal Model
derive(fn)
→
base-signal storage
→
internal updater effect
→
computed value
→
read-only public facade
Derived signals reuse the base-signal engine:
- a base signal stores the current and previous computed values
- an internal effect recomputes the value
- the public derived signal exposes read-only `.value`, `prevValue`, and `dispose()`
4. Disposal
dispose() called
→
remove subscriptions now
→
clear effect bookkeeping
→
isDisposed = true
Disposal is immediate:
- calling `dispose()` removes the effect from every captured stimulus signal
- future writes cannot run the disposed effect
- disposing the same live effect or derived signal twice throws
5. Data Flow
source signal
→
derived signal
→
effect
→
side effects
The actual data flow is:
- a source signal stores state
- derived signals read source signals and recompute immediately
- effects observe signals by reading `.value`
- updates propagate synchronously through the dependency set
6. Internal State And Method Liveness
- Source signals store `_value` and `_effects`
- Effects store disposal state plus stimulus and dependent signal Sets
- Derived signals combine base-signal storage, an updater effect, and a read-only setter
- Live data methods return derived signals; dead-signal methods return snapshots
- Source mutations for arrays, objects, strings, and booleans live under `.mutate`
7. Why This Design
- It keeps the runtime small and explicit
- It avoids hidden batching or deferred execution
- It gives live and dead values a consistent projection vocabulary
- It keeps dependency capture explicit: only initial live getter reads subscribe