Version 1.5.0
·
24 commits
to main
since this release
Immutable
release. Only release title and notes can be modified.
What's Changed
Added
deriveStore(input, options?): New factory deriving a read-only keyed record from a sync function, an async function (options.initialrequired), or a seed record withoptions.watched. Per-property granularity matchescreateStore; exposes no setters. New exported typesDerivedStore<T>,DeriveStoreOptions<T>,StoreCallback<T>.deriveList(input, options?): New factory creating a read-only keyed list (DerivedList<T>) from a sync computation, an async computation (options.initialrequired), an external push (seed array +options.watched), or per-item derivation from anyListSource. New exported typeDeriveListOptions<T>.deriveListaccepts anySignal<T[]>source: Unkeyed array sources — aMemo,Task,State, orSlot— are keyed on read viakeyedAdapter, with item identity stable across recomputes. Newoptionsparameter (keyConfig,itemEquals);ListSource<T>(formerlyCollectionSource<T>) widens the source type to includeSignal<T[]>.isPending(signal)/abort(signal): New graph-level utilities for any signal with an asynchronous origin, including aderiveList/deriveStorebacked by aTask.isPendingis reactive; both are no-ops on signals without an async origin.deriveSignal(input, options?): New factory creating a single-value signal from a sync function, an async function, or an external push (seed value +options.watched), mirroringderiveList/deriveStore. ReturnsSignal<T>; unlike those,options.initialstays optional — an early read before the first resolution throwsUnsetSignalValueError. New exported typeDeriveSignalOptions<T>.MutableList<T>/isMutableList(x),DerivedList<T>/isDerivedList(x),MutableStore<T>/isMutableStore(x): Non-deprecated bridge names ahead of the v2.0 taxonomy forList/isList,Collection/isCollection, andStore/isStore— same types and behavior today.isMutableStore(x)additionally requires the write capability, so it rejects aDerivedStore.ListSource<T>/ListCallback<T>/ListChanges<T>/PerItemCallback<T, U>: Non-deprecated bridge names forCollectionSource/CollectionCallback/CollectionChanges/DeriveCollectionCallback. Terminal 2.0 vocabulary — no further rename at the 2.0 boundary.tools/codemod-v2.ts: New ts-morph codemod rewriting consumer code to the v2.0 bridge names (List→MutableList,createCollection→deriveList, …; full mapping inMIGRATION-2.0.md). Exact identifier matches only;--modulescopes which import declarations are rewritten; renamedisList/isStorecall sites are flagged for manual review.MIGRATION-2.0.md: New guide to the v2.0 shape-indexed taxonomy (ADR-0018) — the bridge-name table, how to run the codemod, and what it cannot decide automatically.
Deprecated
All symbols below are removed in v2.0; List and Store are repurposed as readonly base types, so keeping those names silently changes meaning. See MIGRATION-2.0.md.
| Deprecated | Use instead |
|---|---|
List<T> / isList(x) |
MutableList<T> / isMutableList(x) |
Collection<T> / isCollection(x) |
DerivedList<T> / isDerivedList(x) |
Store<T> / isStore(x) |
MutableStore<T> / isMutableStore(x) — isMutableStore additionally requires the write capability, so it rejects a DerivedStore |
.deriveCollection(fn) |
deriveList(source, fn) |
createCollection(watched, options?) |
deriveList(seed, { watched, ... }) — the value option becomes the seed |
createComputed(fn, options?) |
deriveSignal(fn, options?) — options.value becomes options.initial |
createMutableSignal(value) |
createSignal(value) — wider: also accepts a function or an existing signal |
CollectionSource<T> / CollectionCallback<T> / CollectionChanges<T> / DeriveCollectionCallback<T, U> |
ListSource<T> / ListCallback<T> / ListChanges<T> / PerItemCallback<T, U> |
DeriveCollectionOptions<T> |
DeriveListOptions<T> |
CollectionOptions<T, S> |
None — folded into DeriveListOptions<T> |
State<T> / isState(x), Memo<T> / isMemo(x), Task<T> / isTask(x), Sensor<T> / isSensor(x), SensorCallback<T> / SensorOptions<T>, isComputed(x) |
No mechanical replacement — use isSignal(x) / isMutableSignal(x) or a plain property check (ComputedOptions<T> is unaffected) |
Fixed
DEEP_EQUALITYallocated aWeakSeton every comparison, dominating primitive-heavy hot paths (src/graph.ts):deepEqual()constructed the cycle-guardWeakSeteagerly, before any inspection of its arguments — so every List item write,Storeproperty write, and derived-collection item comparison paid for aWeakSetconstruction even when both sides were primitives that return atObject.isor the typeof checks. Profiling theList.replace()item-to-subscriber path attributed roughly a quarter of total time toWeakSetallocation alone. Now the guard set is allocated lazily, at the first comparison that actually recurses into objects; primitive comparisons allocate nothing. Guard semantics are unchanged (ADR-0016 path-scoped cycle detection), and the performance-regression margin on thelistReplacescenario drops from the 1.20x limit to ~0.7x.
Full Changelog: v1.4.1...v1.5.0