@solidjs/signals
Advanced tools
+27
-11
@@ -1,2 +0,2 @@ | ||
| import { STATUS_UNINITIALIZED, STATUS_ERROR, STATUS_PENDING, REACTIVE_DIRTY, REACTIVE_OPTIMISTIC_DIRTY, NOT_PENDING } from "./constants.js"; | ||
| import { STATUS_UNINITIALIZED, STATUS_ERROR, STATUS_PENDING, REACTIVE_DIRTY, REACTIVE_OPTIMISTIC_DIRTY, NOT_PENDING, CONFIG_AUTO_DISPOSE } from "./constants.js"; | ||
@@ -9,3 +9,3 @@ import { untrack, context, setSignal } from "./core.js"; | ||
| import { trimStaleDeps } from "./graph.js"; | ||
| import { trimStaleDeps, unobserved } from "./graph.js"; | ||
@@ -164,7 +164,7 @@ import { enqueueSub } from "./heap.js"; | ||
| const n = e.Ae; | ||
| const r = e.Re; | ||
| const o = e.Pe; | ||
| const r = e.Pe; | ||
| const o = e.Re; | ||
| try { | ||
| if (!n && u || !o || !o(t, r)) { | ||
| e.Re = t; | ||
| e.Pe = t; | ||
| e.ce = clock; | ||
@@ -198,2 +198,12 @@ // The latest() shadow write gives latest() effects independent lanes; the | ||
| }; | ||
| // A pending node's in-flight promise is an observer: `unlinkSubs` skips | ||
| // autodispose while STATUS_PENDING so subscriber churn can't orphan the | ||
| // work (a lazy async memo would otherwise tear down and re-execute — one | ||
| // fetch per suspended re-read). Settling is that observer's release, so | ||
| // it runs the same last-one-out check the other release sites run. | ||
| const settleAutodispose = () => { | ||
| if (e.T & CONFIG_AUTO_DISPOSE && !e.o && !(e.S & STATUS_PENDING)) { | ||
| unobserved(e); | ||
| } | ||
| }; | ||
| if (o) { | ||
@@ -205,3 +215,6 @@ let r = false, t = false, o, l = true; | ||
| r = true; | ||
| } else asyncWrite(e); | ||
| } else { | ||
| asyncWrite(e); | ||
| settleAutodispose(); | ||
| } | ||
| }, e => { | ||
@@ -211,3 +224,6 @@ if (l) { | ||
| t = true; | ||
| } else handleError(e); | ||
| } else { | ||
| handleError(e); | ||
| settleAutodispose(); | ||
| } | ||
| }); | ||
@@ -302,3 +318,3 @@ l = false; | ||
| // plain store to an existing slot — no shape change.) | ||
| e.be = false; | ||
| e._e = false; | ||
| e.S = n ? 0 : e.S & STATUS_UNINITIALIZED; | ||
@@ -308,4 +324,4 @@ if (e._) setPendingError(e); | ||
| // once the verdict layer created them, which installs the hooks). | ||
| if (e.ge || e.he) GlobalQueue.ae(e); | ||
| if (e.u && GlobalQueue._e !== null) GlobalQueue._e(e); | ||
| if (e.be || e.ge) GlobalQueue.ae(e); | ||
| if (e.u && GlobalQueue.he !== null) GlobalQueue.he(e); | ||
| if (e.i) e.i(); | ||
@@ -334,3 +350,3 @@ } | ||
| GlobalQueue.ae !== null && GlobalQueue.ae(e); | ||
| if (e.u && GlobalQueue._e !== null) GlobalQueue._e(e); | ||
| if (e.u && GlobalQueue.he !== null) GlobalQueue.he(e); | ||
| } | ||
@@ -337,0 +353,0 @@ if (o && !t) { |
+19
-19
@@ -133,3 +133,3 @@ import { handleAsync, clearStatus, notifyStatus } from "./async.js"; | ||
| e.ce = clock; | ||
| let a = e.Ne === NOT_PENDING ? e.Re : e.Ne; | ||
| let a = e.Ne === NOT_PENDING ? e.Pe : e.Ne; | ||
| let r = e.He; | ||
@@ -206,6 +206,6 @@ let c = tracking; | ||
| trimStaleDeps(e); | ||
| const o = l ? unwrapOverride(e.Ee) : e.Ne === NOT_PENDING ? e.Re : e.Ne; | ||
| const o = l ? unwrapOverride(e.Ee) : e.Ne === NOT_PENDING ? e.Pe : e.Ne; | ||
| let s = false; | ||
| try { | ||
| s = !n && u || !e.Pe || !e.Pe(o, a); | ||
| s = !n && u || !e.Re || !e.Re(o, a); | ||
| } catch (t) { | ||
@@ -232,3 +232,3 @@ // A throwing user comparator is an error of this node's computation. | ||
| if (t || n && activeTransition !== e.Ue || i) { | ||
| e.Re = a; | ||
| e.Pe = a; | ||
| // Lane-propagated correction: upstream data is fresh, correct the | ||
@@ -299,3 +299,3 @@ // override unconditionally. The direct _value commit is the lane's | ||
| T: (n ? CONFIG_TRANSPARENT : 0) | (t?.ownedWrite ? CONFIG_OWNED_WRITE : 0) | (!context || t?.lazy ? CONFIG_AUTO_DISPOSE : 0) | (t?.sync ? CONFIG_SYNC : 0) | (t?.V ? CONFIG_NO_SNAPSHOT : 0) | (snapshotCaptureActive && ownerInSnapshotScope(context) ? CONFIG_IN_SNAPSHOT_SCOPE : 0), | ||
| Pe: t?.equals != null ? t.equals : isEqual, | ||
| Re: t?.equals != null ? t.equals : isEqual, | ||
| it: t?.unobserved, | ||
@@ -307,3 +307,3 @@ xe: null, | ||
| ke: e, | ||
| Re: undefined, | ||
| Pe: undefined, | ||
| He: 0, | ||
@@ -330,3 +330,3 @@ u: null, | ||
| Ue: null, | ||
| be: false | ||
| _e: false | ||
| }; | ||
@@ -347,3 +347,3 @@ setupComputedNode(i, t); | ||
| T: (o ? CONFIG_TRANSPARENT : 0) | (u?.ownedWrite ? CONFIG_OWNED_WRITE : 0) | (u?.sync ? CONFIG_SYNC : 0) | (snapshotCaptureActive && ownerInSnapshotScope(context) ? CONFIG_IN_SNAPSHOT_SCOPE : 0), | ||
| Pe: false, | ||
| Re: false, | ||
| it: u?.unobserved, | ||
@@ -355,3 +355,3 @@ xe: null, | ||
| ke: e, | ||
| Re: undefined, | ||
| Pe: undefined, | ||
| He: 0, | ||
@@ -378,3 +378,3 @@ u: null, | ||
| Ue: null, | ||
| be: false, | ||
| _e: false, | ||
| $e: false, | ||
@@ -414,3 +414,3 @@ rt: undefined, | ||
| if (!(e.S & STATUS_PENDING) && !(e.T & CONFIG_NO_SNAPSHOT)) { | ||
| e.Ve = e.Re === undefined ? NO_SNAPSHOT : e.Re; | ||
| e.Ve = e.Pe === undefined ? NO_SNAPSHOT : e.Pe; | ||
| snapshotSources.add(e); | ||
@@ -423,6 +423,6 @@ } | ||
| const i = { | ||
| Pe: t?.equals != null ? t.equals : isEqual, | ||
| Re: t?.equals != null ? t.equals : isEqual, | ||
| T: (t?.ownedWrite ? CONFIG_OWNED_WRITE : 0) | (t?.V ? CONFIG_NO_SNAPSHOT : 0), | ||
| it: t?.unobserved, | ||
| Re: e, | ||
| Pe: e, | ||
| o: null, | ||
@@ -528,3 +528,3 @@ ot: null, | ||
| if (t && tracking) link(e, t); | ||
| return !t || e.Ne === NOT_PENDING ? e.Re : e.Ne; | ||
| return !t || e.Ne === NOT_PENDING ? e.Pe : e.Ne; | ||
| } | ||
@@ -577,3 +577,3 @@ if (t && tracking) { | ||
| const i = n === NO_SNAPSHOT ? undefined : n; | ||
| const l = e.Ne !== NOT_PENDING ? e.Ne : e.Re; | ||
| const l = e.Ne !== NOT_PENDING ? e.Ne : e.Pe; | ||
| if (l !== i) t.se |= REACTIVE_SNAPSHOT_STALE; | ||
@@ -595,3 +595,3 @@ return i; | ||
| if (currentOptimisticLane !== null && activeTransition !== null && t !== null && GlobalQueue.Ct(e, l, t)) { | ||
| return e.Re; | ||
| return e.Pe; | ||
| } | ||
@@ -602,3 +602,3 @@ // In optimistic lane context, return _value for optimistic/lane-assigned signals | ||
| // (The lane-context clause lives with the engine.) | ||
| const u = !t || currentOptimisticLane !== null && GlobalQueue.Ot(e, l, t) || e.Ne === NOT_PENDING || stale && e.Ue && activeTransition !== e.Ue ? e.Re : e.Ne; | ||
| const u = !t || currentOptimisticLane !== null && GlobalQueue.Ot(e, l, t) || e.Ne === NOT_PENDING || stale && e.Ue && activeTransition !== e.Ue ? e.Pe : e.Ne; | ||
| // Record that this isPending() probe observed the fresh pending value, so | ||
@@ -620,7 +620,7 @@ // the probe doesn't pair "pending" with the new value (#2831). | ||
| if (e.Ee !== undefined && !projectionWriteActive) return GlobalQueue.Pt(e, t); | ||
| const n = e.Ne === NOT_PENDING ? e.Re : e.Ne; | ||
| const n = e.Ne === NOT_PENDING ? e.Pe : e.Ne; | ||
| if (typeof t === "function") t = t(n); | ||
| // Uninitialized check first: the first commit has no previous value, so the | ||
| // user comparator must not run against `undefined` (matches recompute). | ||
| const i = !!(e.S & STATUS_UNINITIALIZED) || !e.Pe || !e.Pe(n, t); | ||
| const i = !!(e.S & STATUS_UNINITIALIZED) || !e.Re || !e.Re(n, t); | ||
| if (!i) return t; | ||
@@ -627,0 +627,0 @@ if (e.Ne === NOT_PENDING) queuePendingNode(e); |
@@ -65,3 +65,3 @@ import { REACTIVE_DISPOSED, STATUS_ERROR, EFFECT_USER, CONFIG_AUTO_DISPOSE, CONFIG_CHILDREN_FORBIDDEN, EFFECT_TRACKED, STATUS_PENDING, EFFECT_RENDER } from "./constants.js"; | ||
| const E = unwrapStatusError(t._); | ||
| t.rt = t.Re; | ||
| t.rt = t.Pe; | ||
| t.$e = false; | ||
@@ -86,3 +86,3 @@ try { | ||
| E?.(); | ||
| const e = t.ct(t.Re, t.rt); | ||
| const e = t.ct(t.Pe, t.rt); | ||
| if (false && e !== undefined && typeof e !== "function") ; | ||
@@ -99,3 +99,3 @@ // The final cleanup is invoked by disposeChildren at true disposal. | ||
| } finally { | ||
| t.rt = t.Re; | ||
| t.rt = t.Pe; | ||
| t.$e = false; | ||
@@ -102,0 +102,0 @@ } |
@@ -1,2 +0,2 @@ | ||
| import { CONFIG_AUTO_DISPOSE, REACTIVE_ZOMBIE, REACTIVE_RECOMPUTING_DEPS } from "./constants.js"; | ||
| import { CONFIG_AUTO_DISPOSE, REACTIVE_ZOMBIE, STATUS_PENDING, REACTIVE_RECOMPUTING_DEPS } from "./constants.js"; | ||
@@ -21,4 +21,9 @@ import { deleteFromHeap, queueFor } from "./heap.js"; | ||
| // No more subscribers; only tear down if CONFIG_AUTO_DISPOSE is set. | ||
| // A pending node is exempt: its in-flight async work (or the | ||
| // transition holding it) is an observer — tearing down would orphan | ||
| // the work and re-execute it on the next read. The settle path runs | ||
| // this same last-one-out check when that observer releases (the | ||
| // untracked-read dispose in core.ts guards on pending identically). | ||
| const l = n; | ||
| l.ke && l.T & CONFIG_AUTO_DISPOSE && !(l.se & REACTIVE_ZOMBIE) && unobserved(l); | ||
| l.ke && l.T & CONFIG_AUTO_DISPOSE && !(l.se & REACTIVE_ZOMBIE) && !(l.S & STATUS_PENDING) && unobserved(l); | ||
| } | ||
@@ -25,0 +30,0 @@ } |
@@ -39,4 +39,4 @@ import { NOT_PENDING } from "./constants.js"; | ||
| // their effects wait on its async instead of flushing immediately. | ||
| adoptCompanionLane(n.ge, e); | ||
| adoptCompanionLane(n.he, e); | ||
| adoptCompanionLane(n.be, e); | ||
| adoptCompanionLane(n.ge, e); | ||
| return e; | ||
@@ -43,0 +43,0 @@ } |
@@ -28,5 +28,5 @@ import { NOT_PENDING, unwrapOverride, STATUS_UNINITIALIZED, OVERRIDE_UNDEFINED, STATUS_PENDING, REACTIVE_MANUAL_WRITE, REACTIVE_OPTIMISTIC_DIRTY, EFFECT_RENDER, EFFECT_USER } from "./constants.js"; | ||
| const t = e.Ee !== NOT_PENDING; | ||
| const i = t ? unwrapOverride(e.Ee) : e.Re; | ||
| const i = t ? unwrapOverride(e.Ee) : e.Pe; | ||
| if (typeof n === "function") n = n(i); | ||
| const u = !!(e.S & STATUS_UNINITIALIZED) || !e.Pe || !e.Pe(i, n); | ||
| const u = !!(e.S & STATUS_UNINITIALIZED) || !e.Re || !e.Re(i, n); | ||
| if (!u) { | ||
@@ -91,3 +91,3 @@ // Same-value write with an active override still entangles the current | ||
| n.Ee = NOT_PENDING; | ||
| if (i !== NOT_PENDING && n.Re !== unwrapOverride(i)) insertSubs(n, true); | ||
| if (i !== NOT_PENDING && n.Pe !== unwrapOverride(i)) insertSubs(n, true); | ||
| n.Ue = null; | ||
@@ -101,5 +101,5 @@ n.sn = null; | ||
| const n = e[t]; | ||
| if (n.ge || n.he) GlobalQueue.un(n); | ||
| if (n.be || n.ge) GlobalQueue.un(n); | ||
| const i = n.nn; | ||
| if (i && (i.ge === n || i.he === n)) GlobalQueue.un(i); | ||
| if (i && (i.be === n || i.ge === n)) GlobalQueue.un(i); | ||
| } | ||
@@ -106,0 +106,0 @@ e.splice(0, n); |
@@ -54,3 +54,3 @@ import { REACTIVE_DISPOSED, REACTIVE_ZOMBIE, REACTIVE_IN_HEAP, REACTIVE_IN_HEAP_HEIGHT, CONFIG_TRANSPARENT, defaultContext } from "./constants.js"; | ||
| const n = e; | ||
| if (n.ge || n.he) GlobalQueue.un(n); | ||
| if (n.be || n.ge) GlobalQueue.un(n); | ||
| } | ||
@@ -57,0 +57,0 @@ if (n && e.ke) e.Te = null; |
@@ -282,3 +282,3 @@ import { EFFECT_RENDER, EFFECT_USER, STATUS_PENDING, REACTIVE_DISPOSED, REACTIVE_ZOMBIE, NOT_PENDING, EFFECT_TRACKED, CONFIG_IN_SNAPSHOT_SCOPE, REACTIVE_SNAPSHOT_STALE, REACTIVE_OPTIMISTIC_DIRTY, REACTIVE_REASK, REACTIVE_MANUAL_WRITE, STATUS_UNINITIALIZED } from "./constants.js"; | ||
| static ae=null; | ||
| static _e=null; | ||
| static he=null; | ||
| static un=null; | ||
@@ -499,10 +499,10 @@ static St=null; | ||
| if (e.Ne !== NOT_PENDING) { | ||
| e.Re = e.Ne; | ||
| e.Pe = e.Ne; | ||
| e.Ne = NOT_PENDING; | ||
| } | ||
| if (e.ge || e.he) GlobalQueue.un(e); | ||
| if (e.be || e.ge) GlobalQueue.un(e); | ||
| return; | ||
| } | ||
| if (e.Ne !== NOT_PENDING) { | ||
| e.Re = e.Ne; | ||
| e.Pe = e.Ne; | ||
| e.Ne = NOT_PENDING; | ||
@@ -515,3 +515,3 @@ // Set _modified for effects, but not for tracked effects (they handle their own scheduling) | ||
| if (t.Le !== null || t.ye !== null) GlobalQueue.Ce(t, false, true); | ||
| if (e.ge || e.he) GlobalQueue.un(e); | ||
| if (e.be || e.ge) GlobalQueue.un(e); | ||
| } | ||
@@ -518,0 +518,0 @@ |
@@ -35,11 +35,11 @@ import { NOT_PENDING, REACTIVE_DISPOSED, REACTIVE_DIRTY, REACTIVE_CHECK, unwrapOverride, REACTIVE_ZOMBIE, STATUS_UNINITIALIZED, STATUS_PENDING, REACTIVE_MANUAL_WRITE, STATUS_ERROR, REACTIVE_RECOMPUTING_DEPS } from "./constants.js"; | ||
| */ function getPendingSignal(e) { | ||
| if (!e.ge) { | ||
| if (!e.be) { | ||
| // Start false, write true if pending - ensures reversion returns to false | ||
| e.ge = optimisticSignal(false, { | ||
| e.be = optimisticSignal(false, { | ||
| ownedWrite: true | ||
| }); | ||
| e.ge.nn = e; | ||
| if (computePendingState(e)) setSignal(e.ge, true); | ||
| e.be.nn = e; | ||
| if (computePendingState(e)) setSignal(e.be, true); | ||
| } | ||
| return e.ge; | ||
| return e.be; | ||
| } | ||
@@ -106,6 +106,6 @@ | ||
| if (e.oe) { | ||
| for (const t of e.oe) if (!t.be) return false; | ||
| for (const t of e.oe) if (!t._e) return false; | ||
| return true; | ||
| } | ||
| return e.be; | ||
| return e._e; | ||
| } | ||
@@ -134,3 +134,3 @@ | ||
| if (e.Ne !== NOT_PENDING && !(t.S & STATUS_UNINITIALIZED)) { | ||
| if (hasActiveOverride(e)) return !e.Pe || !e.Pe(e.Ne, unwrapOverride(e.Ee)); | ||
| if (hasActiveOverride(e)) return !e.Re || !e.Re(e.Ne, unwrapOverride(e.Ee)); | ||
| return true; | ||
@@ -142,11 +142,11 @@ } | ||
| function syncCompanions(e, t) { | ||
| if (e.ge) updatePendingSignal(e); | ||
| if (e.he) setSignal(e.he, t); | ||
| if (e.be) updatePendingSignal(e); | ||
| if (e.ge) setSignal(e.ge, t); | ||
| } | ||
| function updatePendingSignal(e) { | ||
| if (e.ge) { | ||
| setSignal(e.ge, computePendingState(e)); | ||
| if (e.be) { | ||
| setSignal(e.be, computePendingState(e)); | ||
| } | ||
| if (e.he) updatePendingSignal(e.he); | ||
| if (e.ge) updatePendingSignal(e.ge); | ||
| } | ||
@@ -156,3 +156,3 @@ | ||
| for (let t = e.u; t !== null; t = t.fe) { | ||
| if (t.ge || t.he) updatePendingSignal(t); | ||
| if (t.be || t.ge) updatePendingSignal(t); | ||
| } | ||
@@ -175,3 +175,3 @@ } | ||
| i.add(e); | ||
| if (e.ge || e.he) n(e); | ||
| if (e.be || e.ge) n(e); | ||
| for (let t = e.o; t !== null; t = t.ue) visit(t.le); | ||
@@ -186,7 +186,7 @@ for (let t = e.u ?? null; t !== null; t = t.fe) { | ||
| function snapCompanionsToState(e) { | ||
| const t = e.ge; | ||
| const t = e.be; | ||
| if (t && (t.Ee === undefined || t.Ee === NOT_PENDING)) { | ||
| const n = computePendingState(e); | ||
| if (t.Re !== n || t.Ne !== NOT_PENDING) { | ||
| t.Re = n; | ||
| if (t.Pe !== n || t.Ne !== NOT_PENDING) { | ||
| t.Pe = n; | ||
| t.Ne = NOT_PENDING; | ||
@@ -198,5 +198,5 @@ t.ce = clock; | ||
| } | ||
| const n = e.he; | ||
| const n = e.ge; | ||
| if (n && !(n.se & REACTIVE_DISPOSED)) { | ||
| if ((n.Ee === undefined || n.Ee === NOT_PENDING) && n.Ne === NOT_PENDING && !Object.is(n.Re, e.Re) && !(n.se & (REACTIVE_DIRTY | REACTIVE_CHECK))) { | ||
| if ((n.Ee === undefined || n.Ee === NOT_PENDING) && n.Ne === NOT_PENDING && !Object.is(n.Pe, e.Pe) && !(n.se & (REACTIVE_DIRTY | REACTIVE_CHECK))) { | ||
| n.se |= REACTIVE_DIRTY; | ||
@@ -212,3 +212,3 @@ insertIntoHeap(n, queueFor(n)); | ||
| function getLatestValueComputed(e) { | ||
| if (!e.he) { | ||
| if (!e.ge) { | ||
| const t = latestReadActive; | ||
@@ -221,4 +221,4 @@ setLatestReadActive(false); | ||
| // Detach from owner so it isn't disposed with effects | ||
| e.he = optimisticComputed(() => read(e)); | ||
| e.he.nn = e; | ||
| e.ge = optimisticComputed(() => read(e)); | ||
| e.ge.nn = e; | ||
| // Parent-child lane relationship | ||
@@ -229,3 +229,3 @@ setContextInternal(i); | ||
| } | ||
| return e.he; | ||
| return e.ge; | ||
| } | ||
@@ -237,3 +237,3 @@ | ||
| setLatestReadActive(false); | ||
| const i = e.Ee !== undefined && e.Ee !== NOT_PENDING ? unwrapOverride(e.Ee) : e.Re; | ||
| const i = e.Ee !== undefined && e.Ee !== NOT_PENDING ? unwrapOverride(e.Ee) : e.Pe; | ||
| let r; | ||
@@ -294,5 +294,5 @@ try { | ||
| const n = !!(e.S & STATUS_PENDING); | ||
| const i = t && !(n && !e.be); | ||
| const r = n && e.be !== i; | ||
| e.be = i; | ||
| const i = t && !(n && !e._e); | ||
| const r = n && e._e !== i; | ||
| e._e = i; | ||
| return r; | ||
@@ -355,3 +355,3 @@ } | ||
| GlobalQueue._e = updateChildCompanions; | ||
| GlobalQueue.he = updateChildCompanions; | ||
@@ -358,0 +358,0 @@ GlobalQueue.un = snapCompanionsToState; |
@@ -103,4 +103,4 @@ import { computed } from "../core/core.js"; | ||
| T.Ne = NOT_PENDING; | ||
| T.Re = o; | ||
| if (!T.Pe || !T.Pe(n, o)) { | ||
| T.Pe = o; | ||
| if (!T.Re || !T.Re(n, o)) { | ||
| insertSubs(T, true); | ||
@@ -107,0 +107,0 @@ schedule(); |
@@ -157,3 +157,3 @@ import { $REFRESH, STORE_SNAPSHOT_PROPS, NOT_PENDING, unwrapOverride, STATUS_UNINITIALIZED, STATUS_PENDING, NO_SNAPSHOT } from "../core/constants.js"; | ||
| */ function visibleNodeValue(e) { | ||
| return e.Ee !== undefined && e.Ee !== NOT_PENDING ? unwrapOverride(e.Ee) : e.Ne !== NOT_PENDING ? e.Ne : e.Re; | ||
| return e.Ee !== undefined && e.Ee !== NOT_PENDING ? unwrapOverride(e.Ee) : e.Ne !== NOT_PENDING ? e.Ne : e.Pe; | ||
| } | ||
@@ -160,0 +160,0 @@ |
+1
-1
| { | ||
| "name": "@solidjs/signals", | ||
| "version": "2.0.0-beta.22", | ||
| "version": "2.0.0-beta.23", | ||
| "description": "Solid's reactive primitives: signals, memos, effects, stores, and async-aware computations.", | ||
@@ -5,0 +5,0 @@ "author": "Ryan Carniato", |
Sorry, the diff of this file is too big to display
Sorry, the diff of this file is too big to display
1059539
0.32%23403
0.29%