@mocanvas/state 1.0.0 → 4.0.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/ARCHITECTURE.md +421 -0
- package/BENCHMARK.md +519 -0
- package/CLEAN_ROOM.md +50 -0
- package/COMPAT.md +282 -0
- package/CUSTOM_SHAPES.md +880 -0
- package/LICENSE +110 -16
- package/MIGRATION.md +807 -0
- package/README.md +24 -4
- package/UI.md +256 -0
- package/dist/{chunk-XCRMDUZF.js → chunk-KGMTQKZV.js} +214 -12
- package/dist/chunk-KGMTQKZV.js.map +1 -0
- package/dist/core-DVexut58.d.ts +325 -0
- package/dist/index.d.ts +91 -137
- package/dist/index.js +284 -1
- package/dist/index.js.map +1 -1
- package/dist/react.d.ts +20 -2
- package/dist/react.js +10 -2
- package/dist/react.js.map +1 -1
- package/package.json +11 -13
- package/dist/chunk-XCRMDUZF.js.map +0 -1
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"sources":["../src/diff.ts","../src/core.ts"],"names":["atom"],"mappings":"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","file":"chunk-KGMTQKZV.js","sourcesContent":["/**\n * Diff-carrying signals.\n *\n * A plain signal only says *that* it changed. Some consumers — the store's\n * incremental queries above all — need to know *what* changed, so that a\n * derived collection can be patched instead of rebuilt. A signal can therefore\n * keep a short history of diffs alongside its value, and a dependent that knows\n * the epoch of its own last run can ask for the diffs recorded since then.\n *\n * There are two ways to produce those diffs:\n *\n * - `atom(name, value, { historyLength, computeDiff })` — the atom derives the\n * diff from the old and new values whenever it is written.\n * - `computed(name, fn, { historyLength })` where `fn` returns\n * {@link withDiff}`(value, diff)` — the derivation already knows the diff and\n * hands it over directly.\n *\n * History is finite. When a caller asks for diffs from further back than the\n * buffer reaches — or when the signal could not describe a change as a diff at\n * all — the answer is {@link RESET_VALUE}, meaning \"start again from the\n * value\".\n */\n\n/**\n * \"I cannot express this as a diff — read the value instead.\"\n *\n * Returned by {@link ComputeDiff} when a change has no meaningful diff, and by\n * `getDiffSince` when the requested epoch has fallen out of the history buffer.\n */\nexport const RESET_VALUE: unique symbol = Symbol(\"RESET_VALUE\")\n\n/** The type of {@link RESET_VALUE}, for signatures that mention it. */\nexport type ResetValue = typeof RESET_VALUE\n\n/**\n * Derives the diff between two values of a signal.\n *\n * `lastComputedEpoch` and `currentEpoch` are passed so a derivation that keeps\n * its own history can decide the span is too wide to describe and bail out with\n * {@link RESET_VALUE}.\n */\nexport type ComputeDiff<Value, Diff> = (\n previousValue: Value,\n currentValue: Value,\n lastComputedEpoch: number,\n currentEpoch: number,\n) => Diff | ResetValue\n\n/**\n * A value paired with the diff that produced it, as returned from a computed\n * that knows how it changed. Construct one with {@link withDiff}.\n */\nexport class WithDiff<Value, Diff> {\n constructor(\n readonly value: Value,\n readonly diff: Diff,\n ) {}\n}\n\n/**\n * Return a value together with the diff describing how it changed.\n *\n * ```ts\n * const $ids = computed('ids', (prev) => {\n * if (isUninitialized(prev)) return new Set(source.get())\n * const next = new Set(source.get())\n * return withDiff(next, { added: [...] , removed: [...] })\n * }, { historyLength: 10 })\n * ```\n */\nexport function withDiff<Value, Diff>(value: Value, diff: Diff): WithDiff<Value, Diff> {\n return new WithDiff(value, diff)\n}\n\n/** Whether `value` is a {@link WithDiff} wrapper rather than a bare value. */\nexport function isWithDiff<Value, Diff>(value: unknown): value is WithDiff<Value, Diff> {\n return value instanceof WithDiff\n}\n\ninterface HistoryEntry<Diff> {\n /** The epoch the signal was at *before* this change. */\n readonly fromEpoch: number\n /** The epoch the signal reached with this change. */\n readonly toEpoch: number\n readonly diff: Diff\n}\n\n/**\n * A bounded ring of recent diffs.\n *\n * Only signals that were given a `historyLength` allocate one; everything else\n * answers `getDiffSince` with {@link RESET_VALUE} at no cost.\n */\nexport class HistoryBuffer<Diff> {\n private readonly entries: (HistoryEntry<Diff> | undefined)[]\n private index = 0\n /**\n * The earliest epoch this buffer can still answer for. Raised when an entry\n * is evicted (its change is no longer described) and when a change arrives\n * that has no diff at all.\n */\n private oldestSafeEpoch = -1\n\n constructor(readonly capacity: number) {\n if (!Number.isInteger(capacity) || capacity < 1) {\n throw new Error(`historyLength must be a positive integer, got ${String(capacity)}`)\n }\n this.entries = new Array<HistoryEntry<Diff> | undefined>(capacity)\n }\n\n /**\n * Record a diff. A `RESET_VALUE` diff means this change cannot be described,\n * so everything up to and including it becomes unanswerable.\n */\n pushEntry(fromEpoch: number, toEpoch: number, diff: Diff | ResetValue): void {\n if (diff === RESET_VALUE) {\n this.clear()\n this.oldestSafeEpoch = toEpoch\n return\n }\n const evicted = this.entries[this.index]\n this.entries[this.index] = { fromEpoch, toEpoch, diff }\n this.index = (this.index + 1) % this.capacity\n if (evicted && evicted.toEpoch > this.oldestSafeEpoch) this.oldestSafeEpoch = evicted.toEpoch\n }\n\n clear(): void {\n this.entries.fill(undefined)\n this.index = 0\n this.oldestSafeEpoch = -1\n }\n\n /**\n * Every diff recorded after `epoch`, oldest first, or {@link RESET_VALUE}\n * when the history does not reach back that far.\n */\n getChangesSince(epoch: number): Diff[] | ResetValue {\n if (epoch < this.oldestSafeEpoch) return RESET_VALUE\n const result: Diff[] = []\n // Walk oldest-to-newest through the ring: `index` is the next slot to\n // overwrite, so it is also the oldest entry.\n for (let i = 0; i < this.capacity; i++) {\n const entry = this.entries[(this.index + i) % this.capacity]\n if (!entry) continue\n if (entry.toEpoch <= epoch) continue\n result.push(entry.diff)\n }\n return result\n }\n}\n","/**\n * Fine-grained reactive signals.\n *\n * Model\n * -----\n * - A single global epoch counter advances on every atom write.\n * - Every signal remembers `lastChangedEpoch`, the epoch of the write that\n * last changed its value.\n * - Computeds are lazy and pull-based: `get()` verifies the cached value by\n * comparing the `lastChangedEpoch` of each recorded parent against the\n * epoch at which the computed was last verified (`lastCheckedEpoch`).\n * Recomputation happens only when a parent actually changed.\n * - Reactions (effects) are push-notified: an atom write walks the children\n * graph and marks reachable reactions pending. Pending reactions execute\n * once, after the outermost transaction commits, and re-check their\n * dependencies' epochs before running so that equal computed values never\n * trigger a run.\n * - Dependency tracking uses a single \"active dependent\" slot that behaves\n * like a capture stack through the native call stack (save/restore).\n */\n\nimport {\n\tHistoryBuffer,\n\tisWithDiff,\n\tRESET_VALUE,\n\ttype ComputeDiff,\n\ttype ResetValue,\n\ttype WithDiff,\n} from \"./diff\"\n\nexport const UNINITIALIZED: unique symbol = Symbol(\"UNINITIALIZED\")\nexport type Uninitialized = typeof UNINITIALIZED\n\n/**\n * Whether a computed's `prev` argument is the \"no previous value yet\" marker.\n *\n * A derivation that patches its previous result has to tell the first run apart\n * from every later one; `prev` is {@link UNINITIALIZED} exactly then.\n *\n * ```ts\n * computed('ids', (prev) => (isUninitialized(prev) ? build() : patch(prev)))\n * ```\n */\nexport function isUninitialized(value: unknown): value is Uninitialized {\n\treturn value === UNINITIALIZED\n}\n\nexport const EMPTY_ARRAY: readonly [] = Object.freeze([]) as unknown as readonly []\n\n// ---------------------------------------------------------------------------\n// Public types\n// ---------------------------------------------------------------------------\n\nexport interface Signal<T, Diff = unknown> {\n\treadonly name: string\n\tget(): T\n\tlastChangedEpoch: number\n\t/**\n\t * Every diff this signal recorded after `epoch`, oldest first.\n\t *\n\t * A signal only keeps diffs when it was given a `historyLength`; without\n\t * one — or when the change is further back than the buffer reaches, or was\n\t * never expressible as a diff — the answer is {@link RESET_VALUE}, meaning\n\t * \"give up and read the value\".\n\t */\n\tgetDiffSince(epoch: number): Diff[] | ResetValue\n}\n\nexport interface Atom<T, Diff = unknown> extends Signal<T, Diff> {\n\tset(value: T): T\n\tupdate(fn: (prev: T) => T): T\n}\n\nexport interface Computed<T, Diff = unknown> extends Signal<T, Diff> {\n\t/** Epoch at which the cached value was last verified against its parents. */\n\treadonly lastCheckedEpoch: number\n}\n\nexport interface AtomOptions<T, Diff = unknown> {\n\tisEqual?: (a: T, b: T) => boolean\n\t/**\n\t * How many recent changes to remember as diffs. Omit — the default — and\n\t * the atom keeps none and always answers `getDiffSince` with\n\t * {@link RESET_VALUE}.\n\t */\n\thistoryLength?: number\n\t/** Derives the diff between two values; see {@link ComputeDiff}. */\n\tcomputeDiff?: ComputeDiff<T, Diff>\n}\n\nexport interface ComputedOptions<T, Diff = unknown> {\n\tisEqual?: (a: T, b: T) => boolean\n\t/**\n\t * How many recent changes to remember as diffs. The derivation supplies\n\t * each diff itself by returning `withDiff(value, diff)`; a plain return\n\t * value records \"this change has no diff\".\n\t */\n\thistoryLength?: number\n\t/**\n\t * Derives the diff between two values when the derivation returned a bare\n\t * value rather than a {@link WithDiff}. Optional; see {@link ComputeDiff}.\n\t */\n\tcomputeDiff?: ComputeDiff<T, Diff>\n}\n\n/**\n * How an effect is (re)scheduled once its dependencies change.\n *\n * Shared by `react`, `reactor` and anything else driving an\n * {@link EffectScheduler}, so a host can batch effect runs per animation frame\n * instead of running them synchronously inside the write that caused them.\n */\nexport interface EffectSchedulerOptions {\n\t/**\n\t * Called whenever the effect needs to (re)run after its first run. The\n\t * default runs `execute` synchronously. Supply e.g. a requestAnimationFrame\n\t * wrapper to batch effect runs per frame.\n\t */\n\tscheduleEffect?: (execute: () => void) => void\n}\n\n/** @see {@link EffectSchedulerOptions} — the name `react()` documents. */\nexport type ReactOptions = EffectSchedulerOptions\n\nexport interface EffectScheduler {\n\treadonly name: string\n\treadonly isActive: boolean\n\treadonly lastRunEpoch: number\n\t/** Runs the effect now if any dependency changed since its last run. */\n\texecute(): void\n}\n\nexport interface Reactor {\n\tstart(): void\n\tstop(): void\n\treadonly scheduler: EffectScheduler\n}\n\n// ---------------------------------------------------------------------------\n// Internal graph node contracts\n// ---------------------------------------------------------------------------\n\n/** Anything that records parents while it runs (computeds, effects). */\ninterface Dependent {\n\treadonly name: string\n\tparents: Set<SignalNode>\n\tprevParents: Set<SignalNode>\n\t__notify(): void\n\t/**\n\t * The epoch this dependent's cached work is current as of. A parent whose\n\t * `lastChangedEpoch` is newer than this is a reason the dependent re-ran —\n\t * which is exactly what {@link whyAmIRunning} reports.\n\t */\n\t__referenceEpoch(): number\n}\n\n/** An atom as seen by the transaction log (method syntax keeps T bivariant). */\ninterface RollbackTarget {\n\t__restore(value: unknown): void\n}\n\n/** Anything that can be read and can have dependents (atoms, computeds). */\ninterface SignalNode<T = unknown> extends Signal<T, any> {\n\t__addChild(child: Dependent): void\n\t__removeChild(child: Dependent): void\n\t/** Bring the value up to date without recording a dependency. */\n\t__refresh(): void\n}\n\n// ---------------------------------------------------------------------------\n// Global runtime state\n// ---------------------------------------------------------------------------\n\nlet globalEpoch = 0\nlet activeDependent: Dependent | null = null\nlet currentTx: TxLevel | null = null\nlet isFlushing = false\nconst pendingEffects = new Set<EffectBase>()\nconst flushScratch: EffectBase[] = []\nconst MAX_FLUSH_ROUNDS = 10_000\n\nexport function getGlobalEpoch(): number {\n\treturn globalEpoch\n}\n\nfunction defaultIsEqual(a: unknown, b: unknown): boolean {\n\treturn Object.is(a, b)\n}\n\n// ---------------------------------------------------------------------------\n// Dependency capture\n// ---------------------------------------------------------------------------\n\n/**\n * Starts recording parents into `d.parents`. The previous parent set is kept\n * in `d.prevParents` so `endCapture` can diff subscriptions. Both sets are\n * reused across runs; no allocation happens unless the sets grow.\n */\nfunction beginCapture(d: Dependent): Dependent | null {\n\tconst outer = activeDependent\n\tconst recycled = d.prevParents\n\td.prevParents = d.parents\n\td.parents = recycled\n\trecycled.clear()\n\tactiveDependent = d\n\treturn outer\n}\n\n/**\n * Stops recording. When `attached` is true the dependent is live in the\n * graph, so subscriptions are diffed: dropped parents forget the dependent,\n * new parents learn about it.\n */\nfunction endCapture(d: Dependent, outer: Dependent | null, attached: boolean): void {\n\tactiveDependent = outer\n\tconst prev = d.prevParents\n\tconst next = d.parents\n\tif (attached) {\n\t\tfor (const p of prev) if (!next.has(p)) p.__removeChild(d)\n\t\tfor (const p of next) if (!prev.has(p)) p.__addChild(d)\n\t}\n\tprev.clear()\n}\n\n/** Runs `fn` without recording any dependencies for the current dependent. */\nexport function unsafe__withoutCapture<T>(fn: () => T): T {\n\tconst outer = activeDependent\n\tactiveDependent = null\n\ttry {\n\t\treturn fn()\n\t} finally {\n\t\tactiveDependent = outer\n\t}\n}\n\n/** Reads a signal without recording a dependency (closure-free helper). */\nexport function getWithoutCapture<T>(signal: Signal<T>): T {\n\tconst outer = activeDependent\n\tactiveDependent = null\n\ttry {\n\t\treturn signal.get()\n\t} finally {\n\t\tactiveDependent = outer\n\t}\n}\n\n// ---------------------------------------------------------------------------\n// Atom\n// ---------------------------------------------------------------------------\n\nclass AtomImpl<T, Diff = unknown> implements SignalNode<T>, Atom<T, Diff> {\n\treadonly name: string\n\tlastChangedEpoch: number = globalEpoch\n\treadonly children = new Set<Dependent>()\n\tprivate value: T\n\tprivate readonly isEqual: (a: T, b: T) => boolean\n\tprivate readonly history: HistoryBuffer<Diff> | null\n\tprivate readonly computeDiff: ComputeDiff<T, Diff> | null\n\n\tconstructor(\n\t\tname: string,\n\t\tvalue: T,\n\t\tisEqual: ((a: T, b: T) => boolean) | undefined,\n\t\thistoryLength: number | undefined,\n\t\tcomputeDiff: ComputeDiff<T, Diff> | undefined\n\t) {\n\t\tthis.name = name\n\t\tthis.value = value\n\t\tthis.isEqual = isEqual ?? defaultIsEqual\n\t\tthis.history = historyLength === undefined ? null : new HistoryBuffer<Diff>(historyLength)\n\t\tthis.computeDiff = computeDiff ?? null\n\t}\n\n\tget(): T {\n\t\tif (activeDependent !== null) activeDependent.parents.add(this)\n\t\treturn this.value\n\t}\n\n\tset(value: T): T {\n\t\tif (this.isEqual(this.value, value)) return this.value\n\t\tif (currentTx !== null) currentTx.record(this, this.value)\n\t\tthis.__write(value, this.diffFor(this.value, value))\n\t\tif (currentTx === null) flushPending()\n\t\treturn value\n\t}\n\n\tupdate(fn: (prev: T) => T): T {\n\t\treturn this.set(fn(this.value))\n\t}\n\n\tgetDiffSince(epoch: number): Diff[] | ResetValue {\n\t\t// Reading the diffs is reading the signal: a dependent that patches its\n\t\t// result from them must be woken by the next change just the same.\n\t\tthis.get()\n\t\tif (epoch >= this.lastChangedEpoch) return []\n\t\treturn this.history === null ? RESET_VALUE : this.history.getChangesSince(epoch)\n\t}\n\n\t/** Restores a value during rollback; skips the write when already equal. */\n\t__restore(value: T): void {\n\t\tif (this.isEqual(this.value, value)) return\n\t\t// A rollback is not a change anyone can patch towards: the diffs that\n\t\t// led here are being undone, so the history stops being answerable.\n\t\tthis.__write(value, RESET_VALUE)\n\t}\n\n\tprivate diffFor(previous: T, next: T): Diff | ResetValue {\n\t\tif (this.history === null || this.computeDiff === null) return RESET_VALUE\n\t\treturn this.computeDiff(previous, next, this.lastChangedEpoch, globalEpoch + 1)\n\t}\n\n\tprivate __write(value: T, diff: Diff | ResetValue): void {\n\t\tconst fromEpoch = this.lastChangedEpoch\n\t\tglobalEpoch++\n\t\tthis.value = value\n\t\tthis.lastChangedEpoch = globalEpoch\n\t\tthis.history?.pushEntry(fromEpoch, globalEpoch, diff)\n\t\tfor (const child of this.children) child.__notify()\n\t}\n\n\t__addChild(child: Dependent): void {\n\t\tthis.children.add(child)\n\t}\n\n\t__removeChild(child: Dependent): void {\n\t\tthis.children.delete(child)\n\t}\n\n\t__refresh(): void {\n\t\t// Atoms are always fresh.\n\t}\n}\n\nexport function atom<T, Diff = unknown>(\n\tname: string,\n\tinitialValue: T,\n\toptions?: AtomOptions<T, Diff>\n): Atom<T, Diff> {\n\treturn new AtomImpl<T, Diff>(\n\t\tname,\n\t\tinitialValue,\n\t\toptions?.isEqual,\n\t\toptions?.historyLength,\n\t\toptions?.computeDiff\n\t)\n}\n\n// ---------------------------------------------------------------------------\n// Computed\n// ---------------------------------------------------------------------------\n\nclass ComputedImpl<T, Diff = unknown> implements SignalNode<T>, Computed<T, Diff>, Dependent {\n\treadonly name: string\n\tlastChangedEpoch = -1\n\tlastCheckedEpoch = -1\n\t/**\n\t * Epoch of the most recent push notification received while attached.\n\t * While the computed has children it is subscribed to all of its parents,\n\t * so \"no notification since the last check\" proves the cache is fresh\n\t * without walking the parent list.\n\t */\n\tprivate notifiedEpoch = -1\n\tparents = new Set<SignalNode>()\n\tprevParents = new Set<SignalNode>()\n\treadonly children = new Set<Dependent>()\n\tprivate value: T | Uninitialized = UNINITIALIZED\n\tprivate isComputing = false\n\tprivate readonly fn: (prev: T | Uninitialized, lastComputedEpoch: number) => T | WithDiff<T, Diff>\n\tprivate readonly isEqual: (a: T, b: T) => boolean\n\tprivate readonly history: HistoryBuffer<Diff> | null\n\tprivate readonly computeDiff: ComputeDiff<T, Diff> | null\n\n\tconstructor(\n\t\tname: string,\n\t\tfn: (prev: T | Uninitialized, lastComputedEpoch: number) => T | WithDiff<T, Diff>,\n\t\tisEqual: ((a: T, b: T) => boolean) | undefined,\n\t\thistoryLength: number | undefined,\n\t\tcomputeDiff: ComputeDiff<T, Diff> | undefined\n\t) {\n\t\tthis.name = name\n\t\tthis.fn = fn\n\t\tthis.isEqual = isEqual ?? defaultIsEqual\n\t\tthis.history = historyLength === undefined ? null : new HistoryBuffer<Diff>(historyLength)\n\t\tthis.computeDiff = computeDiff ?? null\n\t}\n\n\tget(): T {\n\t\tif (activeDependent !== null) activeDependent.parents.add(this)\n\t\tthis.__refresh()\n\t\treturn this.value as T\n\t}\n\n\tgetDiffSince(epoch: number): Diff[] | ResetValue {\n\t\t// Bring the value up to date first: the diffs being asked for may not\n\t\t// have been produced yet.\n\t\tthis.get()\n\t\tif (epoch >= this.lastChangedEpoch) return []\n\t\treturn this.history === null ? RESET_VALUE : this.history.getChangesSince(epoch)\n\t}\n\n\t__referenceEpoch(): number {\n\t\treturn this.lastCheckedEpoch\n\t}\n\n\t__refresh(): void {\n\t\tconst epoch = globalEpoch\n\t\tif (this.lastCheckedEpoch === epoch) return\n\t\tif (this.value !== UNINITIALIZED) {\n\t\t\tif (this.children.size > 0 && this.notifiedEpoch <= this.lastCheckedEpoch) {\n\t\t\t\tthis.lastCheckedEpoch = epoch\n\t\t\t\treturn\n\t\t\t}\n\t\t\tlet changed = false\n\t\t\tfor (const p of this.parents) {\n\t\t\t\tp.__refresh()\n\t\t\t\tif (p.lastChangedEpoch > this.lastCheckedEpoch) {\n\t\t\t\t\tchanged = true\n\t\t\t\t\tbreak\n\t\t\t\t}\n\t\t\t}\n\t\t\tif (!changed) {\n\t\t\t\tthis.lastCheckedEpoch = epoch\n\t\t\t\treturn\n\t\t\t}\n\t\t}\n\t\tthis.recompute()\n\t}\n\n\tprivate recompute(): void {\n\t\tif (this.isComputing) {\n\t\t\tthrow new Error(`Cycle detected while evaluating computed \"${this.name}\"`)\n\t\t}\n\t\tthis.isComputing = true\n\t\tconst epoch = globalEpoch\n\t\tconst prev = this.value\n\t\t// The epoch this computed's cached value was produced at. A derivation\n\t\t// that patches `prev` asks its parents for the diffs recorded since.\n\t\tconst lastComputedEpoch = this.lastCheckedEpoch\n\t\tconst outer = beginCapture(this)\n\t\tlet returned: T | WithDiff<T, Diff>\n\t\ttry {\n\t\t\treturned = this.fn(prev, lastComputedEpoch)\n\t\t} finally {\n\t\t\tendCapture(this, outer, this.children.size > 0)\n\t\t\tthis.isComputing = false\n\t\t}\n\n\t\t// A derivation that knows how its result changed says so by returning\n\t\t// `withDiff(value, diff)`; a bare value falls back to `computeDiff`,\n\t\t// and failing that records \"this change cannot be described\".\n\t\tlet next: T\n\t\tlet diff: Diff | ResetValue = RESET_VALUE\n\t\tif (isWithDiff<T, Diff>(returned)) {\n\t\t\tnext = returned.value\n\t\t\tdiff = returned.diff\n\t\t} else {\n\t\t\tnext = returned\n\t\t}\n\n\t\tif (prev === UNINITIALIZED || !this.isEqual(prev as T, next)) {\n\t\t\tif (this.history !== null && diff === RESET_VALUE && this.computeDiff !== null && prev !== UNINITIALIZED) {\n\t\t\t\tdiff = this.computeDiff(prev as T, next, this.lastChangedEpoch, epoch)\n\t\t\t}\n\t\t\tconst fromEpoch = this.lastChangedEpoch\n\t\t\tthis.value = next\n\t\t\tthis.lastChangedEpoch = epoch\n\t\t\tthis.history?.pushEntry(fromEpoch, epoch, prev === UNINITIALIZED ? RESET_VALUE : diff)\n\t\t}\n\t\tthis.lastCheckedEpoch = epoch\n\t}\n\n\t__notify(): void {\n\t\tif (this.notifiedEpoch === globalEpoch) return\n\t\tthis.notifiedEpoch = globalEpoch\n\t\tfor (const child of this.children) child.__notify()\n\t}\n\n\t__addChild(child: Dependent): void {\n\t\tthis.children.add(child)\n\t\tif (this.children.size === 1) {\n\t\t\t// Becoming live: anything that happened while detached was not\n\t\t\t// pushed to us, so force a parent walk on the next refresh unless\n\t\t\t// we were verified at the current epoch.\n\t\t\tthis.notifiedEpoch = globalEpoch\n\t\t\tfor (const p of this.parents) p.__addChild(this)\n\t\t}\n\t}\n\n\t__removeChild(child: Dependent): void {\n\t\tif (this.children.delete(child) && this.children.size === 0) {\n\t\t\tfor (const p of this.parents) p.__removeChild(this)\n\t\t}\n\t}\n}\n\nexport function computed<T, Diff = unknown>(\n\tname: string,\n\tfn: (prev: T | Uninitialized, lastComputedEpoch: number) => T | WithDiff<T, Diff>,\n\toptions?: ComputedOptions<T, Diff>\n): Computed<T, Diff> {\n\treturn new ComputedImpl<T, Diff>(\n\t\tname,\n\t\tfn,\n\t\toptions?.isEqual,\n\t\toptions?.historyLength,\n\t\toptions?.computeDiff\n\t)\n}\n\n// ---------------------------------------------------------------------------\n// Effects\n// ---------------------------------------------------------------------------\n\nabstract class EffectBase implements Dependent {\n\treadonly name: string\n\tparents = new Set<SignalNode>()\n\tprevParents = new Set<SignalNode>()\n\tlastRunEpoch = -1\n\tisActive = false\n\n\tconstructor(name: string) {\n\t\tthis.name = name\n\t}\n\n\t__notify(): void {\n\t\tif (this.isActive) pendingEffects.add(this)\n\t}\n\n\t__referenceEpoch(): number {\n\t\treturn this.lastRunEpoch\n\t}\n\n\t/** Called by the flush loop once per batch of changes. */\n\tabstract __schedule(): void\n\n\tprotected attachToParents(): void {\n\t\tfor (const p of this.parents) p.__addChild(this)\n\t}\n\n\tprotected detachFromParents(): void {\n\t\tfor (const p of this.parents) p.__removeChild(this)\n\t}\n\n\t/** True when any parent changed after this effect last ran. */\n\tprotected depsChanged(): boolean {\n\t\tconst since = this.lastRunEpoch\n\t\tfor (const p of this.parents) {\n\t\t\tp.__refresh()\n\t\t\tif (p.lastChangedEpoch > since) return true\n\t\t}\n\t\treturn false\n\t}\n}\n\nclass Reaction extends EffectBase implements EffectScheduler {\n\tprivate isScheduled = false\n\tprivate readonly fn: () => void\n\tprivate readonly scheduleEffect: ((execute: () => void) => void) | null\n\tprivate readonly boundExecute: () => void\n\n\tconstructor(name: string, fn: () => void, scheduleEffect: ((execute: () => void) => void) | null) {\n\t\tsuper(name)\n\t\tthis.fn = fn\n\t\tthis.scheduleEffect = scheduleEffect\n\t\tthis.boundExecute = () => this.execute()\n\t}\n\n\tstart(): void {\n\t\tif (this.isActive) return\n\t\tthis.isActive = true\n\t\tthis.lastRunEpoch = -1\n\t\tthis.execute()\n\t}\n\n\tstop(): void {\n\t\tif (!this.isActive) return\n\t\tthis.detachFromParents()\n\t\tthis.parents.clear()\n\t\tthis.isActive = false\n\t\tthis.isScheduled = false\n\t\tthis.lastRunEpoch = -1\n\t}\n\n\t__schedule(): void {\n\t\tif (this.isScheduled) return\n\t\tthis.isScheduled = true\n\t\tif (this.scheduleEffect !== null) this.scheduleEffect(this.boundExecute)\n\t\telse this.execute()\n\t}\n\n\texecute(): void {\n\t\tthis.isScheduled = false\n\t\tif (!this.isActive) return\n\t\tif (this.lastRunEpoch !== -1 && !this.depsChanged()) return\n\t\t// Writes made by the effect are batched and flushed after it returns.\n\t\tconst tx = beginTx()\n\t\tconst outer = beginCapture(this)\n\t\tthis.lastRunEpoch = globalEpoch\n\t\ttry {\n\t\t\tthis.fn()\n\t\t} catch (error) {\n\t\t\tendCapture(this, outer, this.isActive)\n\t\t\tabortTx(tx)\n\t\t\tthrow error\n\t\t}\n\t\tendCapture(this, outer, this.isActive)\n\t\tcommitTx(tx)\n\t}\n}\n\nexport function react(name: string, fn: () => void, options?: ReactOptions): () => void {\n\tconst reaction = new Reaction(name, fn, options?.scheduleEffect ?? null)\n\treaction.start()\n\treturn () => reaction.stop()\n}\n\nexport function reactor(name: string, fn: () => void, options?: ReactOptions): Reactor {\n\tconst reaction = new Reaction(name, fn, options?.scheduleEffect ?? null)\n\treturn {\n\t\tscheduler: reaction,\n\t\tstart: () => reaction.start(),\n\t\tstop: () => reaction.stop(),\n\t}\n}\n\n/**\n * Dependency tracker for externally driven executions (e.g. a UI render).\n *\n * The host calls `track(fn)` to run `fn` with dependency capture, and\n * `subscribe(listener)` to be told when any captured dependency changes.\n * `getSnapshot()` returns a version number that increments on each such\n * change, which makes the tracker a drop-in external store for React's\n * `useSyncExternalStore`. Subscribing and unsubscribing repeatedly (as strict\n * mode does) is safe: captured parents are kept across unsubscribe so the next\n * subscribe re-attaches to them.\n */\nexport class RenderTracker extends EffectBase {\n\tprivate version = 0\n\tprivate listener: (() => void) | null = null\n\n\tconstructor(name: string) {\n\t\tsuper(name)\n\t}\n\n\t__schedule(): void {\n\t\tthis.execute()\n\t}\n\n\tprivate execute(): void {\n\t\tif (!this.isActive || this.lastRunEpoch === -1) return\n\t\tif (!this.depsChanged()) return\n\t\tthis.bump()\n\t}\n\n\tprivate bump(): void {\n\t\tthis.version++\n\t\tif (this.listener !== null) this.listener()\n\t}\n\n\t/** Runs `fn(a, b)` while recording every signal read as a dependency. */\n\ttrack<A, B, R>(fn: (a: A, b: B) => R, a: A, b: B): R {\n\t\tconst outer = beginCapture(this)\n\t\tthis.lastRunEpoch = globalEpoch\n\t\ttry {\n\t\t\treturn fn(a, b)\n\t\t} finally {\n\t\t\tendCapture(this, outer, this.isActive)\n\t\t}\n\t}\n\n\treadonly getSnapshot = (): number => this.version\n\n\treadonly subscribe = (listener: () => void): (() => void) => {\n\t\tthis.listener = listener\n\t\tif (!this.isActive) {\n\t\t\tthis.isActive = true\n\t\t\tthis.attachToParents()\n\t\t}\n\t\t// Changes between the tracked run and this subscription were not\n\t\t// observed; report them now so the host re-runs.\n\t\tif (this.lastRunEpoch !== -1 && this.depsChanged()) this.bump()\n\t\treturn this.unsubscribe\n\t}\n\n\treadonly unsubscribe = (): void => {\n\t\tif (!this.isActive) return\n\t\tthis.listener = null\n\t\tthis.isActive = false\n\t\tthis.detachFromParents()\n\t}\n}\n\n/**\n * Calls `onChange` whenever `signal`'s value changes. The initial subscription\n * does not call `onChange`. Returns an unsubscribe function.\n */\nexport function subscribeToSignal(signal: Signal<unknown>, onChange: () => void): () => void {\n\tlet initial = true\n\tconst reaction = new Reaction(\n\t\t`subscribe(${signal.name})`,\n\t\t() => {\n\t\t\tsignal.get()\n\t\t\tif (initial) initial = false\n\t\t\telse onChange()\n\t\t},\n\t\tnull\n\t)\n\treaction.start()\n\treturn () => reaction.stop()\n}\n\n// ---------------------------------------------------------------------------\n// Transactions\n// ---------------------------------------------------------------------------\n\nclass TxLevel {\n\treadonly parent: TxLevel | null\n\tlog: Map<RollbackTarget, unknown> | null = null\n\topen = true\n\n\tconstructor(parent: TxLevel | null) {\n\t\tthis.parent = parent\n\t}\n\n\t/** Remembers the first pre-write value of each atom touched in this level. */\n\trecord(atom: RollbackTarget, previous: unknown): void {\n\t\tif (this.log === null) this.log = new Map()\n\t\telse if (this.log.has(atom)) return\n\t\tthis.log.set(atom, previous)\n\t}\n}\n\nfunction beginTx(): TxLevel {\n\tconst tx = new TxLevel(currentTx)\n\tcurrentTx = tx\n\treturn tx\n}\n\nfunction commitTx(tx: TxLevel): void {\n\ttx.open = false\n\tcurrentTx = tx.parent\n\tif (tx.log !== null && tx.parent !== null) {\n\t\t// Nested transactions merge into the outer one so an outer rollback\n\t\t// can still undo writes made by an already-committed inner level.\n\t\tconst parent = tx.parent\n\t\tif (parent.log === null) parent.log = tx.log\n\t\telse for (const [atom, prev] of tx.log) if (!parent.log.has(atom)) parent.log.set(atom, prev)\n\t\ttx.log = null\n\t}\n\tif (currentTx === null) flushPending()\n}\n\nfunction rollbackTx(tx: TxLevel): void {\n\tif (!tx.open) throw new Error(\"Cannot roll back a transaction that has already ended\")\n\tconst log = tx.log\n\tif (log === null) return\n\ttx.log = null\n\tfor (const [atom, prev] of log) atom.__restore(prev)\n}\n\nfunction abortTx(tx: TxLevel): void {\n\trollbackTx(tx)\n\ttx.open = false\n\tcurrentTx = tx.parent\n\tif (currentTx === null) flushPending()\n}\n\n/**\n * Batches atom writes: dependents are notified as writes happen, but effects\n * run once, after the outermost transaction commits. If `fn` throws, writes\n * made inside the transaction are rolled back and the error is rethrown.\n */\nexport function transact<T>(fn: () => T): T {\n\tconst tx = beginTx()\n\tlet result: T\n\ttry {\n\t\tresult = fn()\n\t} catch (error) {\n\t\tabortTx(tx)\n\t\tthrow error\n\t}\n\tcommitTx(tx)\n\treturn result\n}\n\n/**\n * Like `transact`, but `fn` receives a `rollback` function that restores every\n * atom written inside this transaction (including committed nested ones) to\n * the value it had when this transaction began. The transaction stays open\n * after a rollback, so further writes are recorded again.\n */\nexport function transaction<T>(fn: (rollback: () => void) => T): T {\n\tconst tx = beginTx()\n\tlet result: T\n\ttry {\n\t\tresult = fn(() => rollbackTx(tx))\n\t} catch (error) {\n\t\tabortTx(tx)\n\t\tthrow error\n\t}\n\tcommitTx(tx)\n\treturn result\n}\n\n/**\n * Runs every pending effect. Effects that become pending while flushing\n * (because an effect wrote an atom) are picked up by the next round. A bound\n * on rounds turns an effect that keeps invalidating itself into an error.\n */\nfunction flushPending(): void {\n\tif (isFlushing || currentTx !== null || pendingEffects.size === 0) return\n\tisFlushing = true\n\tlet firstError: unknown = pendingEffects // sentinel that can never be thrown\n\tlet rounds = 0\n\ttry {\n\t\twhile (pendingEffects.size > 0) {\n\t\t\tif (++rounds > MAX_FLUSH_ROUNDS) {\n\t\t\t\tpendingEffects.clear()\n\t\t\t\tthrow new Error(\n\t\t\t\t\t`Reaction loop detected: effects kept invalidating each other for ${MAX_FLUSH_ROUNDS} rounds`\n\t\t\t\t)\n\t\t\t}\n\t\t\tconst batch = flushScratch\n\t\t\tfor (const effect of pendingEffects) batch.push(effect)\n\t\t\tpendingEffects.clear()\n\t\t\tfor (let i = 0; i < batch.length; i++) {\n\t\t\t\ttry {\n\t\t\t\t\tbatch[i]!.__schedule()\n\t\t\t\t} catch (error) {\n\t\t\t\t\tif (firstError === pendingEffects) firstError = error\n\t\t\t\t}\n\t\t\t}\n\t\t\tbatch.length = 0\n\t\t}\n\t} finally {\n\t\tflushScratch.length = 0\n\t\tisFlushing = false\n\t}\n\tif (firstError !== pendingEffects) throw firstError\n}\n\n// ---------------------------------------------------------------------------\n// Type guards\n// ---------------------------------------------------------------------------\n\nexport function isSignal(value: unknown): value is Signal<unknown> {\n\treturn value instanceof AtomImpl || value instanceof ComputedImpl\n}\n\nexport function isAtom(value: unknown): value is Atom<unknown> {\n\treturn value instanceof AtomImpl\n}\n\nexport function isComputed(value: unknown): value is Computed<unknown> {\n\treturn value instanceof ComputedImpl\n}\n\n// ---------------------------------------------------------------------------\n// Debugging\n// ---------------------------------------------------------------------------\n\n/**\n * Log why the computed or effect that is running right now was re-run.\n *\n * Drop a call inside a derivation or a `react` body and the next run prints the\n * dependencies it captured, marking the ones that changed since its previous\n * run. That is the question a signals bug almost always reduces to — \"who woke\n * this up?\" — and it cannot be answered from a breakpoint, because the parent\n * set only exists while the body is executing.\n *\n * Outside a tracked execution it warns and does nothing.\n */\nexport function whyAmIRunning(): void {\n\tconst dependent = activeDependent\n\tif (dependent === null) {\n\t\tconsole.warn(\"[state] whyAmIRunning() was called outside of a computed or effect\")\n\t\treturn\n\t}\n\tconst since = dependent.__referenceEpoch()\n\tconst changed: string[] = []\n\tconst unchanged: string[] = []\n\t// `parents` is the set captured SO FAR in this run — reads that happen after\n\t// this call are not in it yet, which is the honest answer to \"what have I\n\t// depended on up to here\".\n\tfor (const parent of dependent.parents) {\n\t\t;(parent.lastChangedEpoch > since ? changed : unchanged).push(parent.name)\n\t}\n\tconst lines = [`[state] ${dependent.name} is running because:`]\n\tfor (const name of changed) lines.push(` ${name} changed`)\n\tfor (const name of unchanged) lines.push(` ${name} (unchanged)`)\n\tif (changed.length === 0 && unchanged.length === 0) lines.push(\" (no dependencies captured yet)\")\n\tconsole.log(lines.join(\"\\n\"))\n}\n\n/**\n * The {@link Computed} that memoizes `object[propertyName]`, creating it on\n * first use.\n *\n * A getter on a class is re-evaluated on every read; wrapping it once per\n * instance turns it into a cached derivation that other signals can depend on,\n * without the class having to hold the `Computed` itself. The instance is\n * remembered per object and per property, so repeated calls return the same\n * signal and the cache is actually shared.\n *\n * ```ts\n * const $bounds = getComputedInstance(shapeUtil, \"bounds\")\n * $bounds.get()\n * ```\n *\n * SEMANTICS-ASSUMED: the docs describe this as fetching the computed instance\n * behind a property. mocanvas has no `@computed` property decorator, so the\n * lazily created wrapper is what a decorator would otherwise have installed —\n * one `Computed` per object/property that reads the property with dependency\n * capture. The object is held weakly, so this never keeps an editor alive.\n */\nconst computedInstances = new WeakMap<object, Map<PropertyKey, Computed<unknown>>>()\n\nexport function getComputedInstance<Obj extends object, Prop extends keyof Obj>(\n\tobject: Obj,\n\tpropertyName: Prop\n): Computed<Obj[Prop]> {\n\tlet byProperty = computedInstances.get(object)\n\tif (!byProperty) {\n\t\tbyProperty = new Map()\n\t\tcomputedInstances.set(object, byProperty)\n\t}\n\tconst existing = byProperty.get(propertyName)\n\tif (existing) return existing as Computed<Obj[Prop]>\n\tconst created = computed<Obj[Prop]>(\n\t\t`${object.constructor?.name ?? \"object\"}.${String(propertyName)}`,\n\t\t() => object[propertyName]\n\t)\n\tbyProperty.set(propertyName, created as Computed<unknown>)\n\treturn created\n}\n\n// ---------------------------------------------------------------------------\n// Persisted atoms\n// ---------------------------------------------------------------------------\n\n/**\n * An atom whose value outlives the page: it is read from `localStorage` when\n * created and written back whenever it changes.\n *\n * Use it for preferences the app owns rather than the document — a chosen\n * theme, whether the debug panel is open. Document state belongs in the store.\n *\n * The value is stored as JSON under `key`. When `localStorage` is unavailable\n * (server rendering, a browser with site data blocked, a private window that\n * throws on write) this degrades to an ordinary in-memory atom rather than\n * failing: a preference is never worth breaking a render over.\n *\n * SEMANTICS-ASSUMED: values are serialized with `JSON.stringify`, unparseable\n * stored values fall back to `initialValue`, and a `storage` event from another\n * tab updates the atom — the behaviour that makes a persisted preference\n * actually behave like one shared piece of state. The docs name the function\n * but do not pin the encoding.\n */\nexport function localStorageAtom<T>(key: string, initialValue: T, options?: AtomOptions<T>): Atom<T> {\n\tconst storage = (): Storage | null => {\n\t\ttry {\n\t\t\treturn typeof localStorage === \"undefined\" ? null : localStorage\n\t\t} catch {\n\t\t\treturn null\n\t\t}\n\t}\n\n\tlet start = initialValue\n\tconst store = storage()\n\tif (store !== null) {\n\t\ttry {\n\t\t\tconst raw = store.getItem(key)\n\t\t\tif (raw !== null) start = JSON.parse(raw) as T\n\t\t} catch {\n\t\t\tstart = initialValue\n\t\t}\n\t}\n\n\tconst result = atom<T>(key, start, options)\n\tconst write = (value: T): void => {\n\t\tconst s = storage()\n\t\tif (s === null) return\n\t\ttry {\n\t\t\ts.setItem(key, JSON.stringify(value))\n\t\t} catch {\n\t\t\t// Quota exceeded or storage disabled mid-session: keep the in-memory value.\n\t\t}\n\t}\n\n\t// `react` runs immediately, which also writes the initial value back — so a\n\t// key that was never set gets its default persisted, and a later read in\n\t// another tab sees the same thing this one does.\n\treact(`localStorageAtom(${key})`, () => write(result.get()))\n\n\tif (typeof window !== \"undefined\" && typeof window.addEventListener === \"function\") {\n\t\twindow.addEventListener(\"storage\", (event: StorageEvent) => {\n\t\t\tif (event.key !== key || event.newValue === null) return\n\t\t\ttry {\n\t\t\t\tresult.set(JSON.parse(event.newValue) as T)\n\t\t\t} catch {\n\t\t\t\t// Another tab wrote something we cannot read; keep ours.\n\t\t\t}\n\t\t})\n\t}\n\n\treturn result\n}\n"]}
|
|
@@ -0,0 +1,325 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Diff-carrying signals.
|
|
3
|
+
*
|
|
4
|
+
* A plain signal only says *that* it changed. Some consumers — the store's
|
|
5
|
+
* incremental queries above all — need to know *what* changed, so that a
|
|
6
|
+
* derived collection can be patched instead of rebuilt. A signal can therefore
|
|
7
|
+
* keep a short history of diffs alongside its value, and a dependent that knows
|
|
8
|
+
* the epoch of its own last run can ask for the diffs recorded since then.
|
|
9
|
+
*
|
|
10
|
+
* There are two ways to produce those diffs:
|
|
11
|
+
*
|
|
12
|
+
* - `atom(name, value, { historyLength, computeDiff })` — the atom derives the
|
|
13
|
+
* diff from the old and new values whenever it is written.
|
|
14
|
+
* - `computed(name, fn, { historyLength })` where `fn` returns
|
|
15
|
+
* {@link withDiff}`(value, diff)` — the derivation already knows the diff and
|
|
16
|
+
* hands it over directly.
|
|
17
|
+
*
|
|
18
|
+
* History is finite. When a caller asks for diffs from further back than the
|
|
19
|
+
* buffer reaches — or when the signal could not describe a change as a diff at
|
|
20
|
+
* all — the answer is {@link RESET_VALUE}, meaning "start again from the
|
|
21
|
+
* value".
|
|
22
|
+
*/
|
|
23
|
+
/**
|
|
24
|
+
* "I cannot express this as a diff — read the value instead."
|
|
25
|
+
*
|
|
26
|
+
* Returned by {@link ComputeDiff} when a change has no meaningful diff, and by
|
|
27
|
+
* `getDiffSince` when the requested epoch has fallen out of the history buffer.
|
|
28
|
+
*/
|
|
29
|
+
declare const RESET_VALUE: unique symbol;
|
|
30
|
+
/** The type of {@link RESET_VALUE}, for signatures that mention it. */
|
|
31
|
+
type ResetValue = typeof RESET_VALUE;
|
|
32
|
+
/**
|
|
33
|
+
* Derives the diff between two values of a signal.
|
|
34
|
+
*
|
|
35
|
+
* `lastComputedEpoch` and `currentEpoch` are passed so a derivation that keeps
|
|
36
|
+
* its own history can decide the span is too wide to describe and bail out with
|
|
37
|
+
* {@link RESET_VALUE}.
|
|
38
|
+
*/
|
|
39
|
+
type ComputeDiff<Value, Diff> = (previousValue: Value, currentValue: Value, lastComputedEpoch: number, currentEpoch: number) => Diff | ResetValue;
|
|
40
|
+
/**
|
|
41
|
+
* A value paired with the diff that produced it, as returned from a computed
|
|
42
|
+
* that knows how it changed. Construct one with {@link withDiff}.
|
|
43
|
+
*/
|
|
44
|
+
declare class WithDiff<Value, Diff> {
|
|
45
|
+
readonly value: Value;
|
|
46
|
+
readonly diff: Diff;
|
|
47
|
+
constructor(value: Value, diff: Diff);
|
|
48
|
+
}
|
|
49
|
+
/**
|
|
50
|
+
* Return a value together with the diff describing how it changed.
|
|
51
|
+
*
|
|
52
|
+
* ```ts
|
|
53
|
+
* const $ids = computed('ids', (prev) => {
|
|
54
|
+
* if (isUninitialized(prev)) return new Set(source.get())
|
|
55
|
+
* const next = new Set(source.get())
|
|
56
|
+
* return withDiff(next, { added: [...] , removed: [...] })
|
|
57
|
+
* }, { historyLength: 10 })
|
|
58
|
+
* ```
|
|
59
|
+
*/
|
|
60
|
+
declare function withDiff<Value, Diff>(value: Value, diff: Diff): WithDiff<Value, Diff>;
|
|
61
|
+
/** Whether `value` is a {@link WithDiff} wrapper rather than a bare value. */
|
|
62
|
+
declare function isWithDiff<Value, Diff>(value: unknown): value is WithDiff<Value, Diff>;
|
|
63
|
+
/**
|
|
64
|
+
* A bounded ring of recent diffs.
|
|
65
|
+
*
|
|
66
|
+
* Only signals that were given a `historyLength` allocate one; everything else
|
|
67
|
+
* answers `getDiffSince` with {@link RESET_VALUE} at no cost.
|
|
68
|
+
*/
|
|
69
|
+
declare class HistoryBuffer<Diff> {
|
|
70
|
+
readonly capacity: number;
|
|
71
|
+
private readonly entries;
|
|
72
|
+
private index;
|
|
73
|
+
/**
|
|
74
|
+
* The earliest epoch this buffer can still answer for. Raised when an entry
|
|
75
|
+
* is evicted (its change is no longer described) and when a change arrives
|
|
76
|
+
* that has no diff at all.
|
|
77
|
+
*/
|
|
78
|
+
private oldestSafeEpoch;
|
|
79
|
+
constructor(capacity: number);
|
|
80
|
+
/**
|
|
81
|
+
* Record a diff. A `RESET_VALUE` diff means this change cannot be described,
|
|
82
|
+
* so everything up to and including it becomes unanswerable.
|
|
83
|
+
*/
|
|
84
|
+
pushEntry(fromEpoch: number, toEpoch: number, diff: Diff | ResetValue): void;
|
|
85
|
+
clear(): void;
|
|
86
|
+
/**
|
|
87
|
+
* Every diff recorded after `epoch`, oldest first, or {@link RESET_VALUE}
|
|
88
|
+
* when the history does not reach back that far.
|
|
89
|
+
*/
|
|
90
|
+
getChangesSince(epoch: number): Diff[] | ResetValue;
|
|
91
|
+
}
|
|
92
|
+
|
|
93
|
+
/**
|
|
94
|
+
* Fine-grained reactive signals.
|
|
95
|
+
*
|
|
96
|
+
* Model
|
|
97
|
+
* -----
|
|
98
|
+
* - A single global epoch counter advances on every atom write.
|
|
99
|
+
* - Every signal remembers `lastChangedEpoch`, the epoch of the write that
|
|
100
|
+
* last changed its value.
|
|
101
|
+
* - Computeds are lazy and pull-based: `get()` verifies the cached value by
|
|
102
|
+
* comparing the `lastChangedEpoch` of each recorded parent against the
|
|
103
|
+
* epoch at which the computed was last verified (`lastCheckedEpoch`).
|
|
104
|
+
* Recomputation happens only when a parent actually changed.
|
|
105
|
+
* - Reactions (effects) are push-notified: an atom write walks the children
|
|
106
|
+
* graph and marks reachable reactions pending. Pending reactions execute
|
|
107
|
+
* once, after the outermost transaction commits, and re-check their
|
|
108
|
+
* dependencies' epochs before running so that equal computed values never
|
|
109
|
+
* trigger a run.
|
|
110
|
+
* - Dependency tracking uses a single "active dependent" slot that behaves
|
|
111
|
+
* like a capture stack through the native call stack (save/restore).
|
|
112
|
+
*/
|
|
113
|
+
|
|
114
|
+
declare const UNINITIALIZED: unique symbol;
|
|
115
|
+
type Uninitialized = typeof UNINITIALIZED;
|
|
116
|
+
/**
|
|
117
|
+
* Whether a computed's `prev` argument is the "no previous value yet" marker.
|
|
118
|
+
*
|
|
119
|
+
* A derivation that patches its previous result has to tell the first run apart
|
|
120
|
+
* from every later one; `prev` is {@link UNINITIALIZED} exactly then.
|
|
121
|
+
*
|
|
122
|
+
* ```ts
|
|
123
|
+
* computed('ids', (prev) => (isUninitialized(prev) ? build() : patch(prev)))
|
|
124
|
+
* ```
|
|
125
|
+
*/
|
|
126
|
+
declare function isUninitialized(value: unknown): value is Uninitialized;
|
|
127
|
+
declare const EMPTY_ARRAY: readonly [];
|
|
128
|
+
interface Signal<T, Diff = unknown> {
|
|
129
|
+
readonly name: string;
|
|
130
|
+
get(): T;
|
|
131
|
+
lastChangedEpoch: number;
|
|
132
|
+
/**
|
|
133
|
+
* Every diff this signal recorded after `epoch`, oldest first.
|
|
134
|
+
*
|
|
135
|
+
* A signal only keeps diffs when it was given a `historyLength`; without
|
|
136
|
+
* one — or when the change is further back than the buffer reaches, or was
|
|
137
|
+
* never expressible as a diff — the answer is {@link RESET_VALUE}, meaning
|
|
138
|
+
* "give up and read the value".
|
|
139
|
+
*/
|
|
140
|
+
getDiffSince(epoch: number): Diff[] | ResetValue;
|
|
141
|
+
}
|
|
142
|
+
interface Atom<T, Diff = unknown> extends Signal<T, Diff> {
|
|
143
|
+
set(value: T): T;
|
|
144
|
+
update(fn: (prev: T) => T): T;
|
|
145
|
+
}
|
|
146
|
+
interface Computed<T, Diff = unknown> extends Signal<T, Diff> {
|
|
147
|
+
/** Epoch at which the cached value was last verified against its parents. */
|
|
148
|
+
readonly lastCheckedEpoch: number;
|
|
149
|
+
}
|
|
150
|
+
interface AtomOptions<T, Diff = unknown> {
|
|
151
|
+
isEqual?: (a: T, b: T) => boolean;
|
|
152
|
+
/**
|
|
153
|
+
* How many recent changes to remember as diffs. Omit — the default — and
|
|
154
|
+
* the atom keeps none and always answers `getDiffSince` with
|
|
155
|
+
* {@link RESET_VALUE}.
|
|
156
|
+
*/
|
|
157
|
+
historyLength?: number;
|
|
158
|
+
/** Derives the diff between two values; see {@link ComputeDiff}. */
|
|
159
|
+
computeDiff?: ComputeDiff<T, Diff>;
|
|
160
|
+
}
|
|
161
|
+
interface ComputedOptions<T, Diff = unknown> {
|
|
162
|
+
isEqual?: (a: T, b: T) => boolean;
|
|
163
|
+
/**
|
|
164
|
+
* How many recent changes to remember as diffs. The derivation supplies
|
|
165
|
+
* each diff itself by returning `withDiff(value, diff)`; a plain return
|
|
166
|
+
* value records "this change has no diff".
|
|
167
|
+
*/
|
|
168
|
+
historyLength?: number;
|
|
169
|
+
/**
|
|
170
|
+
* Derives the diff between two values when the derivation returned a bare
|
|
171
|
+
* value rather than a {@link WithDiff}. Optional; see {@link ComputeDiff}.
|
|
172
|
+
*/
|
|
173
|
+
computeDiff?: ComputeDiff<T, Diff>;
|
|
174
|
+
}
|
|
175
|
+
/**
|
|
176
|
+
* How an effect is (re)scheduled once its dependencies change.
|
|
177
|
+
*
|
|
178
|
+
* Shared by `react`, `reactor` and anything else driving an
|
|
179
|
+
* {@link EffectScheduler}, so a host can batch effect runs per animation frame
|
|
180
|
+
* instead of running them synchronously inside the write that caused them.
|
|
181
|
+
*/
|
|
182
|
+
interface EffectSchedulerOptions {
|
|
183
|
+
/**
|
|
184
|
+
* Called whenever the effect needs to (re)run after its first run. The
|
|
185
|
+
* default runs `execute` synchronously. Supply e.g. a requestAnimationFrame
|
|
186
|
+
* wrapper to batch effect runs per frame.
|
|
187
|
+
*/
|
|
188
|
+
scheduleEffect?: (execute: () => void) => void;
|
|
189
|
+
}
|
|
190
|
+
/** @see {@link EffectSchedulerOptions} — the name `react()` documents. */
|
|
191
|
+
type ReactOptions = EffectSchedulerOptions;
|
|
192
|
+
interface EffectScheduler {
|
|
193
|
+
readonly name: string;
|
|
194
|
+
readonly isActive: boolean;
|
|
195
|
+
readonly lastRunEpoch: number;
|
|
196
|
+
/** Runs the effect now if any dependency changed since its last run. */
|
|
197
|
+
execute(): void;
|
|
198
|
+
}
|
|
199
|
+
interface Reactor {
|
|
200
|
+
start(): void;
|
|
201
|
+
stop(): void;
|
|
202
|
+
readonly scheduler: EffectScheduler;
|
|
203
|
+
}
|
|
204
|
+
/** Anything that records parents while it runs (computeds, effects). */
|
|
205
|
+
interface Dependent {
|
|
206
|
+
readonly name: string;
|
|
207
|
+
parents: Set<SignalNode>;
|
|
208
|
+
prevParents: Set<SignalNode>;
|
|
209
|
+
__notify(): void;
|
|
210
|
+
/**
|
|
211
|
+
* The epoch this dependent's cached work is current as of. A parent whose
|
|
212
|
+
* `lastChangedEpoch` is newer than this is a reason the dependent re-ran —
|
|
213
|
+
* which is exactly what {@link whyAmIRunning} reports.
|
|
214
|
+
*/
|
|
215
|
+
__referenceEpoch(): number;
|
|
216
|
+
}
|
|
217
|
+
/** Anything that can be read and can have dependents (atoms, computeds). */
|
|
218
|
+
interface SignalNode<T = unknown> extends Signal<T, any> {
|
|
219
|
+
__addChild(child: Dependent): void;
|
|
220
|
+
__removeChild(child: Dependent): void;
|
|
221
|
+
/** Bring the value up to date without recording a dependency. */
|
|
222
|
+
__refresh(): void;
|
|
223
|
+
}
|
|
224
|
+
declare function getGlobalEpoch(): number;
|
|
225
|
+
/** Runs `fn` without recording any dependencies for the current dependent. */
|
|
226
|
+
declare function unsafe__withoutCapture<T>(fn: () => T): T;
|
|
227
|
+
declare function atom<T, Diff = unknown>(name: string, initialValue: T, options?: AtomOptions<T, Diff>): Atom<T, Diff>;
|
|
228
|
+
declare function computed<T, Diff = unknown>(name: string, fn: (prev: T | Uninitialized, lastComputedEpoch: number) => T | WithDiff<T, Diff>, options?: ComputedOptions<T, Diff>): Computed<T, Diff>;
|
|
229
|
+
declare abstract class EffectBase implements Dependent {
|
|
230
|
+
readonly name: string;
|
|
231
|
+
parents: Set<SignalNode<unknown>>;
|
|
232
|
+
prevParents: Set<SignalNode<unknown>>;
|
|
233
|
+
lastRunEpoch: number;
|
|
234
|
+
isActive: boolean;
|
|
235
|
+
constructor(name: string);
|
|
236
|
+
__notify(): void;
|
|
237
|
+
__referenceEpoch(): number;
|
|
238
|
+
/** Called by the flush loop once per batch of changes. */
|
|
239
|
+
abstract __schedule(): void;
|
|
240
|
+
protected attachToParents(): void;
|
|
241
|
+
protected detachFromParents(): void;
|
|
242
|
+
/** True when any parent changed after this effect last ran. */
|
|
243
|
+
protected depsChanged(): boolean;
|
|
244
|
+
}
|
|
245
|
+
declare function react(name: string, fn: () => void, options?: ReactOptions): () => void;
|
|
246
|
+
declare function reactor(name: string, fn: () => void, options?: ReactOptions): Reactor;
|
|
247
|
+
/**
|
|
248
|
+
* Dependency tracker for externally driven executions (e.g. a UI render).
|
|
249
|
+
*
|
|
250
|
+
* The host calls `track(fn)` to run `fn` with dependency capture, and
|
|
251
|
+
* `subscribe(listener)` to be told when any captured dependency changes.
|
|
252
|
+
* `getSnapshot()` returns a version number that increments on each such
|
|
253
|
+
* change, which makes the tracker a drop-in external store for React's
|
|
254
|
+
* `useSyncExternalStore`. Subscribing and unsubscribing repeatedly (as strict
|
|
255
|
+
* mode does) is safe: captured parents are kept across unsubscribe so the next
|
|
256
|
+
* subscribe re-attaches to them.
|
|
257
|
+
*/
|
|
258
|
+
declare class RenderTracker extends EffectBase {
|
|
259
|
+
private version;
|
|
260
|
+
private listener;
|
|
261
|
+
constructor(name: string);
|
|
262
|
+
__schedule(): void;
|
|
263
|
+
private execute;
|
|
264
|
+
private bump;
|
|
265
|
+
/** Runs `fn(a, b)` while recording every signal read as a dependency. */
|
|
266
|
+
track<A, B, R>(fn: (a: A, b: B) => R, a: A, b: B): R;
|
|
267
|
+
readonly getSnapshot: () => number;
|
|
268
|
+
readonly subscribe: (listener: () => void) => (() => void);
|
|
269
|
+
readonly unsubscribe: () => void;
|
|
270
|
+
}
|
|
271
|
+
/**
|
|
272
|
+
* Calls `onChange` whenever `signal`'s value changes. The initial subscription
|
|
273
|
+
* does not call `onChange`. Returns an unsubscribe function.
|
|
274
|
+
*/
|
|
275
|
+
declare function subscribeToSignal(signal: Signal<unknown>, onChange: () => void): () => void;
|
|
276
|
+
/**
|
|
277
|
+
* Batches atom writes: dependents are notified as writes happen, but effects
|
|
278
|
+
* run once, after the outermost transaction commits. If `fn` throws, writes
|
|
279
|
+
* made inside the transaction are rolled back and the error is rethrown.
|
|
280
|
+
*/
|
|
281
|
+
declare function transact<T>(fn: () => T): T;
|
|
282
|
+
/**
|
|
283
|
+
* Like `transact`, but `fn` receives a `rollback` function that restores every
|
|
284
|
+
* atom written inside this transaction (including committed nested ones) to
|
|
285
|
+
* the value it had when this transaction began. The transaction stays open
|
|
286
|
+
* after a rollback, so further writes are recorded again.
|
|
287
|
+
*/
|
|
288
|
+
declare function transaction<T>(fn: (rollback: () => void) => T): T;
|
|
289
|
+
declare function isSignal(value: unknown): value is Signal<unknown>;
|
|
290
|
+
declare function isAtom(value: unknown): value is Atom<unknown>;
|
|
291
|
+
declare function isComputed(value: unknown): value is Computed<unknown>;
|
|
292
|
+
/**
|
|
293
|
+
* Log why the computed or effect that is running right now was re-run.
|
|
294
|
+
*
|
|
295
|
+
* Drop a call inside a derivation or a `react` body and the next run prints the
|
|
296
|
+
* dependencies it captured, marking the ones that changed since its previous
|
|
297
|
+
* run. That is the question a signals bug almost always reduces to — "who woke
|
|
298
|
+
* this up?" — and it cannot be answered from a breakpoint, because the parent
|
|
299
|
+
* set only exists while the body is executing.
|
|
300
|
+
*
|
|
301
|
+
* Outside a tracked execution it warns and does nothing.
|
|
302
|
+
*/
|
|
303
|
+
declare function whyAmIRunning(): void;
|
|
304
|
+
declare function getComputedInstance<Obj extends object, Prop extends keyof Obj>(object: Obj, propertyName: Prop): Computed<Obj[Prop]>;
|
|
305
|
+
/**
|
|
306
|
+
* An atom whose value outlives the page: it is read from `localStorage` when
|
|
307
|
+
* created and written back whenever it changes.
|
|
308
|
+
*
|
|
309
|
+
* Use it for preferences the app owns rather than the document — a chosen
|
|
310
|
+
* theme, whether the debug panel is open. Document state belongs in the store.
|
|
311
|
+
*
|
|
312
|
+
* The value is stored as JSON under `key`. When `localStorage` is unavailable
|
|
313
|
+
* (server rendering, a browser with site data blocked, a private window that
|
|
314
|
+
* throws on write) this degrades to an ordinary in-memory atom rather than
|
|
315
|
+
* failing: a preference is never worth breaking a render over.
|
|
316
|
+
*
|
|
317
|
+
* SEMANTICS-ASSUMED: values are serialized with `JSON.stringify`, unparseable
|
|
318
|
+
* stored values fall back to `initialValue`, and a `storage` event from another
|
|
319
|
+
* tab updates the atom — the behaviour that makes a persisted preference
|
|
320
|
+
* actually behave like one shared piece of state. The docs name the function
|
|
321
|
+
* but do not pin the encoding.
|
|
322
|
+
*/
|
|
323
|
+
declare function localStorageAtom<T>(key: string, initialValue: T, options?: AtomOptions<T>): Atom<T>;
|
|
324
|
+
|
|
325
|
+
export { type Atom as A, whyAmIRunning as B, type ComputeDiff as C, withDiff as D, EMPTY_ARRAY as E, HistoryBuffer as H, RESET_VALUE as R, type Signal as S, UNINITIALIZED as U, WithDiff as W, type AtomOptions as a, type Computed as b, type ComputedOptions as c, type EffectScheduler as d, type EffectSchedulerOptions as e, type ReactOptions as f, type Reactor as g, RenderTracker as h, type ResetValue as i, type Uninitialized as j, atom as k, computed as l, getComputedInstance as m, getGlobalEpoch as n, isAtom as o, isComputed as p, isSignal as q, isUninitialized as r, isWithDiff as s, localStorageAtom as t, react as u, reactor as v, subscribeToSignal as w, transact as x, transaction as y, unsafe__withoutCapture as z };
|