🎩 You're Invited:Meet the Socket team at Black Hat in Las Vegas, August 3-6.RSVP
Sign In

@solidjs/signals

Package Overview
Dependencies
Maintainers
2
Versions
114
Alerts
File Explorer

Advanced tools

Socket logo

Install Socket

Detect and block malicious and high-risk dependencies

Install

@solidjs/signals - npm Package Compare versions

Comparing version
2.0.0-beta.24
to
2.0.0-beta.25
+110
-76
dist/prod/core/core.js

@@ -85,3 +85,3 @@ import { handleAsync, clearStatus, notifyStatus } from "./async.js";

e.se |= REACTIVE_DIRTY;
if (dirtyQueue.He > e.Fe) dirtyQueue.He = e.Fe;
if (dirtyQueue.Fe > e.He) dirtyQueue.Fe = e.He;
insertIntoHeap(e, dirtyQueue);

@@ -118,4 +118,4 @@ }

markDisposal(e);
e.ye = e.xe;
e.Le = e.me;
e.Le = e.xe;
e.ye = e.me;
e.xe = null;

@@ -127,4 +127,4 @@ e.me = null;

let i = !!(e.se & REACTIVE_OPTIMISTIC_DIRTY);
const l = e.Ee !== undefined && e.Ee !== NOT_PENDING;
const u = !!(e.S & STATUS_UNINITIALIZED);
const u = e.Ee !== undefined && e.Ee !== NOT_PENDING;
const l = !!(e.S & STATUS_UNINITIALIZED);
// Re-ask classification lives in the verdict module; capture the flag before

@@ -136,7 +136,7 @@ // the recompute wipes _flags below.

e.qe = null;
e.Ye++;
e.We++;
e.se = REACTIVE_RECOMPUTING_DEPS;
e.ce = clock;
let a = e.Ne === NOT_PENDING ? e.Pe : e.Ne;
let r = e.Fe;
let r = e.He;
let c = tracking;

@@ -151,3 +151,3 @@ let _ = currentOptimisticLane;

// covers creation-time computes and flushes that run inside the window.
const E = latestReadActive;
const f = latestReadActive;
latestReadActive = false;

@@ -158,3 +158,3 @@ // Lane posture lives with the engine: OPTIMISTIC_DIRTY is only ever set by

if (i) {
const t = GlobalQueue.We(e, true);
const t = GlobalQueue.Ye(e, true);
if (t) currentOptimisticLane = t;

@@ -165,3 +165,3 @@ } else if (activeTransition && !t && activeTransition.Ze.length) {

// recomputes under the right posture and propagates correctly.
const t = GlobalQueue.We(e, false);
const t = GlobalQueue.Ye(e, false);
if (t) {

@@ -172,5 +172,5 @@ i = true;

}
const f = n && n !== EFFECT_USER;
const E = n && n !== EFFECT_USER;
const N = stale;
if (f) stale = true;
if (E) stale = true;
try {

@@ -189,7 +189,10 @@ if (!false && e.T & CONFIG_SYNC) {

const i = typeof n === "object" && n !== null;
const l = e.Te !== t;
a = l || !i ? n : handleAsync(e, n);
if (!l && !i) e.Te = null;
const u = e.Te !== t;
a = u || !i ? n : handleAsync(e, n);
if (!u && !i) e.Te = null;
}
clearStatus(e, t);
// On a status-free node clearStatus is a guaranteed no-op: every branch
// in its body is gated on one of these fields, and with _statusFlags === 0
// the flags write (create or not) stores the 0 already there.
if (e.S !== 0 || e.i !== undefined || e._ || e._e || e.Se || e.oe !== undefined || e.be !== undefined || e.ge !== undefined || e.u !== null) clearStatus(e, t);
// _optimisticLane is only ever assigned by engine paths.

@@ -210,4 +213,4 @@ if (e.je) GlobalQueue.Me(e);

tracking = c;
latestReadActive = E;
if (f) stale = N;
latestReadActive = f;
if (E) stale = N;
e.se = REACTIVE_NONE | (t ? e.se & REACTIVE_SNAPSHOT_STALE : 0);

@@ -218,6 +221,6 @@ context = s;

trimStaleDeps(e);
const o = l ? unwrapOverride(e.Ee) : e.Ne === NOT_PENDING ? e.Pe : e.Ne;
const o = u ? unwrapOverride(e.Ee) : e.Ne === NOT_PENDING ? e.Pe : e.Ne;
let s = false;
try {
s = !n && u || !e.Re || !e.Re(o, a);
s = !n && l || !e.Re || !e.Re(o, a);
} catch (t) {

@@ -242,4 +245,9 @@ // A throwing user comparator is an error of this node's computation.

if (e._) ; else if (s) {
const u = l ? e.Ee : undefined;
if (t || n && activeTransition !== e.Ue || i) {
const l = u ? e.Ee : undefined;
if (t ||
// Plain sync flush (no transition on either side) commits effect
// values directly — the pending round-trip (queuePendingNode +
// commitPendingNodes) exists to sequence transition reveals, and
// paying it per effect on the plain path is pure overhead.
n && (activeTransition !== e.Ue || activeTransition === null) || i) {
e.Pe = a;

@@ -250,3 +258,3 @@ // Lane-propagated correction: upstream data is fresh, correct the

// commit can't clobber the fresh value.
if (l && i) {
if (u && i) {
e.Ee = a === undefined ? OVERRIDE_UNDEFINED : a;

@@ -264,4 +272,6 @@ e.Ne = NOT_PENDING;

}
if (!l || i || e.Ee !== u) insertSubs(e, i || l);
} else if (l) {
// insertSubs only walks _subs (no scheduling of its own), so a
// subscriber-less node has nothing to notify.
if (e.o !== null && (!u || i || e.Ee !== l)) insertSubs(e, i || u);
} else if (u) {
// Unchanged value (equals the override) recomputed while the override

@@ -272,3 +282,3 @@ // is active: _value may still be stale, so hold the authoritative value

e.Ne = a;
} else if (e.Fe != r) {
} else if (e.He != r) {
for (let t = e.o; t !== null; t = t.ue) {

@@ -280,3 +290,3 @@ insertIntoHeapHeight(t.le, queueFor(t.le));

currentOptimisticLane = _;
const T = e.Ne !== NOT_PENDING || e.Le !== null || e.ye !== null || (e.S & (STATUS_PENDING | STATUS_UNINITIALIZED)) !== 0;
const T = e.Ne !== NOT_PENDING || e.ye !== null || e.Le !== null || (e.S & (STATUS_PENDING | STATUS_UNINITIALIZED)) !== 0;
// Override-covered holds (hasOverride) always queue: their commit belongs

@@ -287,3 +297,3 @@ // to their own transition's schedule (A18 re-rule) and is unobservable

// _transition.
T && (!t || e.S & STATUS_PENDING) && (!e.Ue || l) && queuePendingNode(e);
T && (!t || e.S & STATUS_PENDING) && (!e.Ue || u) && queuePendingNode(e);
e.Ue && n && activeTransition !== e.Ue && runInTransition(e.Ue, () => recompute(e));

@@ -324,9 +334,9 @@ }

Pe: undefined,
Fe: 0,
He: 0,
u: null,
lt: undefined,
ut: null,
ut: undefined,
lt: null,
Xe: null,
qe: null,
Ye: 0,
We: 0,
o: null,

@@ -342,4 +352,4 @@ ot: null,

Ne: NOT_PENDING,
Le: null,
ye: null,
Le: null,
Te: null,

@@ -358,9 +368,9 @@ Ue: null,

* the auto-dispose CONFIG bit (effect() previously cleared it post-construction).
*/ function createEffectNode(e, t, n, i, l, u) {
const o = u?.transparent ?? false;
*/ function createEffectNode(e, t, n, i, u, l) {
const o = l?.transparent ?? false;
const s = {
id: inheritId(u, o, context),
T: (o ? CONFIG_TRANSPARENT : 0) | (u?.ownedWrite ? CONFIG_OWNED_WRITE : 0) | (u?.sync ? CONFIG_SYNC : 0) | (snapshotCaptureActive && ownerInSnapshotScope(context) ? CONFIG_IN_SNAPSHOT_SCOPE : 0),
id: inheritId(l, o, context),
T: (o ? CONFIG_TRANSPARENT : 0) | (l?.ownedWrite ? CONFIG_OWNED_WRITE : 0) | (l?.sync ? CONFIG_SYNC : 0) | (snapshotCaptureActive && ownerInSnapshotScope(context) ? CONFIG_IN_SNAPSHOT_SCOPE : 0),
Re: false,
it: u?.unobserved,
it: l?.unobserved,
xe: null,

@@ -372,9 +382,9 @@ C: context?.C ?? globalQueue,

Pe: undefined,
Fe: 0,
He: 0,
u: null,
lt: undefined,
ut: null,
ut: undefined,
lt: null,
Xe: null,
qe: null,
Ye: 0,
We: 0,
o: null,

@@ -390,4 +400,4 @@ ot: null,

Ne: NOT_PENDING,
Le: null,
ye: null,
Le: null,
Te: null,

@@ -400,5 +410,5 @@ Ue: null,

_t: n,
Et: undefined,
ft: undefined,
Ae: i,
i: l
i: u
};

@@ -414,4 +424,4 @@ setupComputedNode(s, lazyOptions);

function setupComputedNode(e, t) {
e.ut = e;
const n = context?.ft ? context.Nt : context;
e.lt = e;
const n = context?.Et ? context.Nt : context;
if (context) {

@@ -427,3 +437,3 @@ const t = context.me;

}
if (n) e.Fe = n.Fe + 1;
if (n) e.He = n.He + 1;
if (GlobalQueue.Tt !== null) GlobalQueue.Tt(e);

@@ -524,2 +534,23 @@ !t?.lazy && recompute(e, true);

/**
* Sentinel returned by readNodeFast when the plain-signal fast path does not
* apply and the caller must fall back to the full read().
*/ const READ_SLOW = Symbol("read-slow");
/**
* read()'s plain-signal fast path as a standalone entry for hot callers
* (store traps). Safe to substitute for read() only because the bail
* conditions mirror read()'s prelude and fast-path guard exactly: the
* latestRead and pendingCheck windows run side-effectful hooks before the
* fast path, `_fn` nodes need prepareComputed, and firewall / override /
* snapshot / transition / lane / dev-strictRead state all take the full
* resolution. Anything slow returns READ_SLOW; the caller then calls read().
*/ function readNodeFast(e) {
if (latestReadActive || pendingCheckActive || e.ke || e.nt || e.Ee !== undefined || e.Ve !== undefined || activeTransition !== null || currentOptimisticLane !== null || snapshotCaptureActive || false) return READ_SLOW;
let t = context;
if (t?.Et) t = t.Nt;
if (t && tracking) link(e, t);
return !t || e.Ne === NOT_PENDING ? e.Pe : e.Ne;
}
function read(e) {

@@ -530,8 +561,8 @@ // Handle latest() mode: read from _latestValueComputed

// than the original node (which stays "pending" while held in a transition).
if (latestReadActive) return GlobalQueue.St(e);
if (latestReadActive) return GlobalQueue.dt(e);
let t = context;
if (t?.ft) t = t.Nt;
if (t?.Et) t = t.Nt;
const n = e;
const i = e.nt;
const l = i || e;
const u = i || e;
// Handle isPending() mode: collect pending state while preserving normal read semantics.

@@ -541,7 +572,7 @@ // Probe mode is suspended while preparing the node so nested reads during a

if (pendingCheckActive) {
GlobalQueue.dt(e, t, l, i);
GlobalQueue.St(e, t, u, i);
} else if (typeof n.ke === "function") {
prepareComputed(e, false);
}
if (!n.ke && l === e && e.Ee === undefined && e.Ve === undefined && activeTransition === null && currentOptimisticLane === null && !snapshotCaptureActive && true) {
if (!n.ke && u === e && e.Ee === undefined && e.Ve === undefined && activeTransition === null && currentOptimisticLane === null && !snapshotCaptureActive && true) {
if (t && tracking) link(e, t);

@@ -552,30 +583,30 @@ return !t || e.Ne === NOT_PENDING ? e.Pe : e.Ne;

link(e, t, pendingCheckActive);
if (l.ke) {
if (u.ke) {
const n = queueFor(e);
if (l.Fe >= n.He) {
if (u.He >= n.Fe) {
markNode(t);
markHeap(n);
updateIfNecessary(l);
updateIfNecessary(u);
}
const i = l.Fe;
const i = u.He;
// parent check is shallow, might need to be recursive
if (i >= t.Fe && e.Ge !== t) {
t.Fe = i + 1;
if (i >= t.He && e.Ge !== t) {
t.He = i + 1;
}
}
}
if (l.S & STATUS_PENDING) {
if (t && !(stale && l.Ue && activeTransition !== l.Ue)) {
if (u.S & STATUS_PENDING) {
if (t && !(stale && u.Ue && activeTransition !== u.Ue)) {
// Per-lane suspension lives with the engine (a non-null lane implies it
// is installed): under a lane, only same-lane pending async without an
// active override throws.
if (currentOptimisticLane === null || GlobalQueue.At(l)) {
if (currentOptimisticLane === null || GlobalQueue.At(u)) {
if (!tracking && e !== t) link(e, t);
throw l._;
throw u._;
}
} else if (t && l !== e && l.S & STATUS_UNINITIALIZED) {
} else if (t && u !== e && u.S & STATUS_UNINITIALIZED) {
if (!tracking && e !== t) link(e, t);
throw l._;
} else if (!t && l.S & STATUS_UNINITIALIZED) {
throw l._;
throw u._;
} else if (!t && u.S & STATUS_UNINITIALIZED) {
throw u._;
}

@@ -597,4 +628,4 @@ }

const i = n === NO_SNAPSHOT ? undefined : n;
const l = e.Ne !== NOT_PENDING ? e.Ne : e.Pe;
if (l !== i) t.se |= REACTIVE_SNAPSHOT_STALE;
const u = e.Ne !== NOT_PENDING ? e.Ne : e.Pe;
if (u !== i) t.se |= REACTIVE_SNAPSHOT_STALE;
return i;

@@ -614,3 +645,3 @@ }

// engine — a non-null lane implies it is installed.)
if (currentOptimisticLane !== null && activeTransition !== null && t !== null && GlobalQueue.Ct(e, l, t)) {
if (currentOptimisticLane !== null && activeTransition !== null && t !== null && GlobalQueue.Ct(e, u, t)) {
return e.Pe;

@@ -622,10 +653,10 @@ }

// (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.Pe : e.Ne;
const l = !t || currentOptimisticLane !== null && GlobalQueue.Ot(e, u, 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
// the probe doesn't pair "pending" with the new value (#2831).
if (pendingCheckActive) GlobalQueue.Rt(e, u);
if (!t && l === e && typeof n.ke === "function" && e.T & CONFIG_AUTO_DISPOSE && !(l.S & STATUS_PENDING) && !e.o) {
if (pendingCheckActive) GlobalQueue.Rt(e, l);
if (!t && u === e && typeof n.ke === "function" && e.T & CONFIG_AUTO_DISPOSE && !(u.S & STATUS_PENDING) && !e.o) {
unobserved(e);
}
return u;
return l;
}

@@ -648,3 +679,6 @@

e.Ne = t;
GlobalQueue.Ie !== null && GlobalQueue.Ie(e, t);
// syncCompanions only pokes _pendingSignal/_latestValueComputed — with
// neither companion present the call is a guaranteed no-op (companions are
// only ever created, never removed, and creating one installs the hook).
(e.be !== undefined || e.ge !== undefined) && GlobalQueue.Ie !== null && GlobalQueue.Ie(e, t);
e.ce = clock;

@@ -765,2 +799,2 @@ insertSubs(e);

export { clearSnapshots, computed, context, createEffectNode, currentOptimisticLane, isEqual, latestReadActive, markSnapshotScope, optimisticComputed, optimisticSignal, pendingCheckActive, prepareComputed, read, recompute, refresh, releaseSnapshotScope, runWithOwner, setContextInternal, setLatestReadActive, setMemo, setPendingCheckActive, setSignal, setSnapshotCapture, signal, snapshotCaptureActive, snapshotSources, stale, staleValues, suppressComputedRecompute, tracking, untrack };
export { READ_SLOW, clearSnapshots, computed, context, createEffectNode, currentOptimisticLane, isEqual, latestReadActive, markSnapshotScope, optimisticComputed, optimisticSignal, pendingCheckActive, prepareComputed, read, readNodeFast, recompute, refresh, releaseSnapshotScope, runWithOwner, setContextInternal, setLatestReadActive, setMemo, setPendingCheckActive, setSignal, setSnapshotCapture, signal, snapshotCaptureActive, snapshotSources, stale, staleValues, suppressComputedRecompute, tracking, untrack };

@@ -69,4 +69,4 @@ import { REACTIVE_DISPOSED, STATUS_ERROR, EFFECT_USER, CONFIG_AUTO_DISPOSE, CONFIG_CHILDREN_FORBIDDEN, EFFECT_TRACKED, STATUS_PENDING, EFFECT_RENDER } from "./constants.js";

t._t ? t._t(E, () => {
const E = t.Et;
t.Et = undefined;
const E = t.ft;
t.ft = undefined;
E?.();

@@ -82,4 +82,4 @@ }) : console.error(E);

}
const E = t.Et;
t.Et = undefined;
const E = t.ft;
t.ft = undefined;
try {

@@ -90,3 +90,3 @@ E?.();

// The final cleanup is invoked by disposeChildren at true disposal.
t.Et = e;
t.ft = e;
} catch (E) {

@@ -120,7 +120,7 @@ t._ = new StatusError(t, E);

const e = computed(() => {
const E = e.Et;
e.Et = undefined;
const E = e.ft;
e.ft = undefined;
E?.();
const R = staleValues(t);
e.Et = R;
e.ft = R;
}, {

@@ -130,3 +130,3 @@ ...E,

});
e.Et = undefined;
e.ft = undefined;
e.T = e.T & ~CONFIG_AUTO_DISPOSE | CONFIG_CHILDREN_FORBIDDEN;

@@ -133,0 +133,0 @@ e.$e = true;

@@ -72,3 +72,3 @@ import { CONFIG_AUTO_DISPOSE, REACTIVE_ZOMBIE, STATUS_PENDING, REACTIVE_RECOMPUTING_DEPS } from "./constants.js";

if (s !== null && s.tt === l) {
s.nl = n.Ye;
s.nl = n.We;
n.qe = s;

@@ -86,3 +86,3 @@ // First touch of this pass: the previous pass's label is stale.

const i = l.ot;
if (i !== null && i.le === n && (!t || i.nl === n.Ye)) {
if (i !== null && i.le === n && (!t || i.nl === n.We)) {
// Gen-matched during a recompute = repeat touch this pass (AND); outside

@@ -99,3 +99,3 @@ // a recompute there is no pass boundary, so the latest read labels it.

ue: null,
nl: n.Ye,
nl: n.We,
De: e

@@ -102,0 +102,0 @@ };

@@ -23,3 +23,3 @@ import { REACTIVE_IN_HEAP, EFFECT_TRACKED, EFFECT_USER, REACTIVE_IN_HEAP_HEIGHT, REACTIVE_RECOMPUTING_DEPS, REACTIVE_MANUAL_WRITE, REACTIVE_ZOMBIE, REACTIVE_CHECK, REACTIVE_DIRTY } from "./constants.js";

const E = queueFor(e);
if (E.He > e.Fe) E.He = e.Fe;
if (E.Fe > e.He) E.Fe = e.He;
insertIntoHeap(e, E);

@@ -29,11 +29,11 @@ }

function actualInsertIntoHeap(e, E) {
const t = (e.Ge?.ft ? e.Ge.Nt?.Fe : e.Ge?.Fe) ?? -1;
if (t >= e.Fe) e.Fe = t + 1;
const n = e.Fe;
const t = (e.Ge?.Et ? e.Ge.Nt?.He : e.Ge?.He) ?? -1;
if (t >= e.He) e.He = t + 1;
const n = e.He;
const I = E.eE[n];
if (I === undefined) E.eE[n] = e; else {
const E = I.ut;
E.lt = e;
e.ut = E;
I.ut = e;
const E = I.lt;
E.ut = e;
e.lt = E;
I.lt = e;
}

@@ -71,12 +71,12 @@ if (n > E.EE) E.EE = n;

e.se = t & -25;
const n = e.Fe;
if (e.ut === e) E.eE[n] = undefined; else {
const t = e.lt;
const n = e.He;
if (e.lt === e) E.eE[n] = undefined; else {
const t = e.ut;
const I = E.eE[n];
const o = t ?? I;
if (e === I) E.eE[n] = t; else e.ut.lt = t;
o.ut = e.ut;
if (e === I) E.eE[n] = t; else e.lt.ut = t;
o.lt = e.lt;
}
e.ut = e;
e.lt = undefined;
e.lt = e;
e.ut = undefined;
}

@@ -88,3 +88,3 @@

for (let E = 0; E <= e.EE; E++) {
for (let t = e.eE[E]; t !== undefined; t = t.lt) {
for (let t = e.eE[E]; t !== undefined; t = t.ut) {
if (t.se & REACTIVE_IN_HEAP) markNode(t);

@@ -113,7 +113,7 @@ }

e.tE = false;
for (e.He = 0; e.He <= e.EE; e.He++) {
let t = e.eE[e.He];
for (e.Fe = 0; e.Fe <= e.EE; e.Fe++) {
let t = e.eE[e.Fe];
while (t !== undefined) {
if (t.se & REACTIVE_IN_HEAP) E(t); else adjustHeight(t, e);
t = e.eE[e.He];
t = e.eE[e.Fe];
}

@@ -126,10 +126,10 @@ }

deleteFromHeap(e, E);
let t = e.Fe;
let t = e.He;
for (let E = e.Xe; E; E = E.et) {
const e = E.tt;
const n = e.nt || e;
if (n.ke && n.Fe >= t) t = n.Fe + 1;
if (n.ke && n.He >= t) t = n.He + 1;
}
if (e.Fe !== t) {
e.Fe = t;
if (e.He !== t) {
e.He = t;
for (let E = e.o; E !== null; E = E.ue) {

@@ -136,0 +136,0 @@ // Route each subscriber by its own zombie flag, mirroring the

@@ -55,3 +55,5 @@ import { NOT_PENDING, unwrapOverride, STATUS_UNINITIALIZED, OVERRIDE_UNDEFINED, STATUS_PENDING, REACTIVE_MANUAL_WRITE, REACTIVE_OPTIMISTIC_DIRTY, EFFECT_RENDER, EFFECT_USER } from "./constants.js";

e.Ee = n === undefined ? OVERRIDE_UNDEFINED : n;
GlobalQueue.Ie !== null && GlobalQueue.Ie(e, n);
// syncCompanions only pokes _pendingSignal/_latestValueComputed — with
// neither companion present the call is a guaranteed no-op.
(e.be !== undefined || e.ge !== undefined) && GlobalQueue.Ie !== null && GlobalQueue.Ie(e, n);
e.ce = clock;

@@ -220,4 +222,4 @@ insertSubs(e, true);

GlobalQueue.En = resolveOptimisticNodes;
GlobalQueue.Tn = transitionBlocked;
GlobalQueue.dn = cleanupCompletedLanes;
GlobalQueue.dn = transitionBlocked;
GlobalQueue.Tn = cleanupCompletedLanes;
GlobalQueue.In = runLaneEffects;

@@ -227,3 +229,3 @@ GlobalQueue.Ct = gatedRead;

GlobalQueue.Ot = laneReadsCommitted;
GlobalQueue.We = recomputeLane;
GlobalQueue.Ye = recomputeLane;
GlobalQueue.Ke = laneAsyncPending;

@@ -230,0 +232,0 @@ GlobalQueue.Me = laneAsyncSettled;

@@ -57,3 +57,3 @@ import { REACTIVE_DISPOSED, REACTIVE_ZOMBIE, REACTIVE_IN_HEAP, REACTIVE_IN_HEAP_HEIGHT, CONFIG_TRANSPARENT, defaultContext } from "./constants.js";

if (n && e.ke) e.Te = null;
let l = t ? e.Le : e.me;
let l = t ? e.ye : e.me;
while (l) {

@@ -75,3 +75,3 @@ const e = l.ve;

if (t) {
e.Le = null;
e.ye = null;
} else {

@@ -95,5 +95,5 @@ e.me = null;

// to mirror rerun ordering (compute-phase teardown first, cleanup last).
if (n && e.Et) {
const n = e.Et;
e.Et = undefined;
if (n && e.ft) {
const n = e.ft;
e.ft = undefined;
n();

@@ -104,3 +104,3 @@ }

function runDisposal(e, n) {
let t = n ? e.ye : e.xe;
let t = n ? e.Le : e.xe;
if (!t) return;

@@ -115,3 +115,3 @@ if (Array.isArray(t)) {

}
n ? e.ye = null : e.xe = null;
n ? e.Le = null : e.xe = null;
}

@@ -243,4 +243,4 @@

T: t ? CONFIG_TRANSPARENT : 0,
ft: true,
Nt: n?.ft ? n.Nt : n,
Et: true,
Nt: n?.Et ? n.Nt : n,
me: null,

@@ -253,4 +253,4 @@ ve: null,

Qe: 0,
Le: null,
ye: null,
Le: null,
Ge: n,

@@ -257,0 +257,0 @@ dispose: disposeRootSelf

@@ -22,3 +22,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";

tE: false,
He: 0,
Fe: 0,
EE: 0

@@ -30,3 +30,3 @@ };

tE: false,
He: 0,
Fe: 0,
EE: 0

@@ -286,4 +286,4 @@ };

static un=null;
static dt=null;
static St=null;
static dt=null;
static Rt=null;

@@ -302,4 +302,4 @@ static ze=null;

static En=null;
static dn=null;
static Tn=null;
static dn=null;
static In=null;

@@ -309,3 +309,3 @@ static Ct=null;

static Ot=null;
static We=null;
static Ye=null;
static Ke=null;

@@ -342,3 +342,3 @@ static Me=null;

// flush path instead of leaving them until the next natural flush.
scheduled = dirtyQueue.EE >= dirtyQueue.He || this.m.Qt.length > 0;
scheduled = dirtyQueue.EE >= dirtyQueue.Fe || this.m.Qt.length > 0;
reassignPendingTransition(e.Qt);

@@ -371,3 +371,3 @@ activeTransition = null;

commitPendingNodes();
if (dirtyQueue.EE >= dirtyQueue.He) {
if (dirtyQueue.EE >= dirtyQueue.Fe) {
runHeap(dirtyQueue, GlobalQueue.pe);

@@ -383,3 +383,3 @@ commitPendingNodes();

// Check if finalization added items to the heap (from optimistic reversion)
scheduled = dirtyQueue.EE >= dirtyQueue.He;
scheduled = dirtyQueue.EE >= dirtyQueue.Fe;
// Run lane effects first (for ready lanes), then regular effects

@@ -520,3 +520,3 @@ activeLanes.size && GlobalQueue.In(EFFECT_RENDER);

if (!(t.S & STATUS_PENDING)) t.S &= ~STATUS_UNINITIALIZED;
if (t.Le !== null || t.ye !== null) GlobalQueue.Ce(t, false, true);
if (t.ye !== null || t.Le !== null) GlobalQueue.Ce(t, false, true);
if (e.be || e.ge) GlobalQueue.un(e);

@@ -539,3 +539,3 @@ }

if (!t && globalQueue.vt.length) checkBoundaryChildren(globalQueue);
const n = dirtyQueue.EE >= dirtyQueue.He;
const n = dirtyQueue.EE >= dirtyQueue.Fe;
if (n) runHeap(dirtyQueue, GlobalQueue.pe);

@@ -575,3 +575,3 @@ if (i) {

// Lanes only enter activeLanes through the engine's getOrCreateLane.
if (activeLanes.size) GlobalQueue.dn(e);
if (activeLanes.size) GlobalQueue.Tn(e);
}

@@ -682,3 +682,3 @@ }

// _optimisticNodes, so without the engine the loop was vacuous anyway.
if (t && e.Ze.length && GlobalQueue.Tn(e)) t = false;
if (t && e.Ze.length && GlobalQueue.dn(e)) t = false;
t && (e.fn = true);

@@ -685,0 +685,0 @@ return t;

@@ -235,3 +235,3 @@ 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";

const e = queueFor(t);
if (t.Fe >= e.He && !(t.se & (REACTIVE_DISPOSED | REACTIVE_ZOMBIE))) {
if (t.He >= e.Fe && !(t.se & (REACTIVE_DISPOSED | REACTIVE_ZOMBIE))) {
markHeap(e);

@@ -347,5 +347,5 @@ prepareComputed(t, true);

GlobalQueue.St = latestRead;
GlobalQueue.dt = latestRead;
GlobalQueue.dt = pendingCheckRead;
GlobalQueue.St = pendingCheckRead;

@@ -352,0 +352,0 @@ GlobalQueue.Rt = recordFreshRead;

@@ -17,3 +17,3 @@ import { computed } from "../core/core.js";

import { storeSetter, $TARGET, STORE_OPTIMISTIC_OVERRIDE, STORE_NODE, STORE_OPTIMISTIC_OWNERS, getOverlayLayer, STORE_VALUE, $DELETED, isWrappable, wrap, visibleNodeValue, $TRACK, notifySelf, STORE_WRAP, createStoreProxy, storeTraps, STORE_LOOKUP, STORE_OPTIMISTIC, STORE_FIREWALL } from "./store.js";
import { storeSetter, $TARGET, STORE_OPTIMISTIC_OVERRIDE, STORE_NODE, STORE_OPTIMISTIC_OWNERS, getOverlayLayer, STORE_VALUE, $DELETED, isWrappable, wrap, visibleNodeValue, $TRACK, notifySelf, STORE_WRAP, createStoreProxy, storeTraps, STORE_LOOKUP, STORE_SHALLOW, markRawIngest, STORE_OPTIMISTIC, STORE_FIREWALL } from "./store.js";

@@ -27,2 +27,4 @@ function createOptimisticStore(e, t, i) {

const r = typeof e === "function";
// Plain form: the second slot carries options.
if (!r && i === undefined) i = t;
const o = r ? t : e;

@@ -131,5 +133,10 @@ const n = r ? e : undefined;

const o = new WeakMap;
const n = !!i?.shallow;
const wrapper = e => {
e[STORE_WRAP] = wrapProjection;
e[STORE_LOOKUP] = o;
if (n) {
e[STORE_SHALLOW] = true;
markRawIngest(e[STORE_VALUE]);
}
e[STORE_OPTIMISTIC] = true;

@@ -151,3 +158,3 @@ // Mark as optimistic store

};
const n = wrapProjection(t);
const c = wrapProjection(t);
// If there's a projection function, create a computed to drive it

@@ -161,3 +168,3 @@ if (e) {

const clearProjectionOverride = () => {
const e = n[$TARGET];
const e = c[$TARGET];
if (e?.[STORE_OPTIMISTIC_OVERRIDE]) clearOptimisticOverride(e);

@@ -178,3 +185,3 @@ };

try {
runProjectionComputed(n, e, i?.key || "id", wrapCommit, clearProjectionOverride);
runProjectionComputed(c, e, i?.key || "id", wrapCommit, clearProjectionOverride);
} finally {

@@ -187,3 +194,3 @@ setProjectionWriteActive(false);

return {
store: n,
store: c,
node: r

@@ -190,0 +197,0 @@ };

@@ -17,10 +17,17 @@ import { computed } from "../core/core.js";

import { storeSetter, $TARGET, STORE_WRAP, createStoreProxy, storeTraps, setWriteOverride, STORE_LOOKUP, STORE_FIREWALL } from "./store.js";
import { storeSetter, $TARGET, STORE_WRAP, createStoreProxy, storeTraps, setWriteOverride, STORE_LOOKUP, STORE_SHALLOW, markRawIngest, STORE_VALUE, STORE_FIREWALL } from "./store.js";
function createProjectionInternal(e, r, t) {
let o;
const i = new WeakMap;
const n = new WeakMap;
// A shallow projection's children are raw and never wrapped, so the
// wrapper only ever runs for the root — flagging unconditionally is safe.
const i = !!t?.shallow;
const wrapper = e => {
e[STORE_WRAP] = wrapProjection;
e[STORE_LOOKUP] = i;
e[STORE_LOOKUP] = n;
if (i) {
e[STORE_SHALLOW] = true;
markRawIngest(e[STORE_VALUE]);
}
Object.defineProperty(e, STORE_FIREWALL, {

@@ -34,16 +41,16 @@ get() {

const wrapProjection = e => {
if (i.has(e)) return i.get(e);
if (n.has(e)) return n.get(e);
if (e[$TARGET]?.[STORE_WRAP] === wrapProjection) return e;
const r = createStoreProxy(e, storeTraps, wrapper);
i.set(e, r);
n.set(e, r);
return r;
};
const n = wrapProjection(r);
const c = wrapProjection(r);
o = computed(() => {
if (!o) o = getOwner();
runProjectionComputed(n, e, t?.key || "id");
runProjectionComputed(c, e, t?.key || "id");
}, undefined);
o.T &= ~CONFIG_AUTO_DISPOSE;
return {
store: n,
store: c,
node: o

@@ -111,18 +118,18 @@ };

* the outer `setProjectionWriteActive` scope.
*/ function runProjectionComputed(e, r, t, o, i) {
const n = getOwner();
*/ function runProjectionComputed(e, r, t, o, n) {
const i = getOwner();
let c = false;
let s;
const u = new Proxy(e, createWriteTraps(() => !c || n.Te === s, i));
storeSetter(u, i => {
s = r(i);
const u = new Proxy(e, createWriteTraps(() => !c || i.Te === s, n));
storeSetter(u, n => {
s = r(n);
c = true;
const commit = r => {
if (r === i || r === undefined) return;
if (r === n || r === undefined) return;
const write = () => storeSetter(e, reconcile(r, t));
o ? o(write) : write();
};
commit(handleAsync(n, s, commit));
commit(handleAsync(i, s, commit));
});
return n;
return i;
}

@@ -157,3 +164,3 @@

},
set(t, o, i) {
set(t, o, n) {
if (e && !e()) return true;

@@ -163,3 +170,3 @@ setWriteOverride(true);

try {
t[o] = i;
t[o] = n;
r?.();

@@ -166,0 +173,0 @@ } finally {

@@ -11,3 +11,3 @@ import { setSignal, untrack } from "../core/core.js";

import { $TARGET, STORE_OVERRIDE, STORE_OPTIMISTIC_OVERRIDE, STORE_VALUE, STORE_NODE, storeLookup, STORE_LOOKUP, $PROXY, isWrappable, wrap, notifySelf, $TRACK, STORE_DESC, STORE_HAS, symbolKeyedRecords, getKeys, $DELETED, getStoreSymbols } from "./store.js";
import { $TARGET, STORE_SHALLOW, STORE_OVERRIDE, STORE_OPTIMISTIC_OVERRIDE, STORE_VALUE, STORE_LOOKUP, $PROXY, storeLookup, markRawIngest, STORE_NODE, $TRACK, STORE_HAS, notifySelf, isWrappable, wrap, rawValuesUsed, STORE_DESC, symbolKeyedRecords, $DELETED, isRawValue, getKeys, getStoreSymbols, STORE_WRAP, lookupTarget } from "./store.js";

@@ -21,5 +21,5 @@ // Enumerate a node record's keys. Keeps the common string-key path on the

if (symbolKeyedRecords.has(e)) {
const r = Object.getOwnPropertySymbols(e);
for (let e = 0, n = r.length; e < n; e++) {
if (r[e] !== $TRACK) t.push(r[e]);
const n = Object.getOwnPropertySymbols(e);
for (let e = 0, a = n.length; e < a; e++) {
if (n[e] !== $TRACK) t.push(n[e]);
}

@@ -37,30 +37,30 @@ }

function getOverrideValue(e, t, r, n) {
if (n && r in n) return n[r];
return t && r in t ? t[r] : e[r];
function getOverrideValue(e, t, n, a) {
if (a && n in a) return a[n];
return t && n in t ? t[n] : e[n];
}
// Append `o`'s *enumerable* own symbol keys from a pre-fetched symbol list.
function addEnumSymbols(e, t, r) {
for (let n = 0, a = t.length; n < a; n++) {
if (Object.prototype.propertyIsEnumerable.call(e, t[n])) r.add(t[n]);
function addEnumSymbols(e, t, n) {
for (let a = 0, r = t.length; a < r; a++) {
if (Object.prototype.propertyIsEnumerable.call(e, t[a])) n.add(t[a]);
}
}
function getAllKeys(e, t, r) {
function getAllKeys(e, t, n) {
// Symbols are merged explicitly below; keep the common string-key path on
// Object.keys() and avoid reflecting the base symbols twice.
const n = getKeys(e, t);
const a = Object.keys(r);
const a = getKeys(e, t);
const r = Object.keys(n);
// `value` can be a wrapped store (store-in-store) whose ownKeys trap tracks;
// mirror `getKeys` and enumerate its symbols untracked in that case.
const i = e[$TARGET] ? untrack(() => Object.getOwnPropertySymbols(e)) : Object.getOwnPropertySymbols(e);
const o = Object.getOwnPropertySymbols(r);
const s = Object.getOwnPropertySymbols(n);
// Symbol-free diff (the overwhelmingly common case) stays on the exact
// pre-#2851 path, including the identical-key-sets fast path from #2756.
if (i.length === 0 && o.length === 0) {
if (n.length === a.length) {
if (i.length === 0 && s.length === 0) {
if (a.length === r.length) {
let e = true;
for (let t = 0; t < n.length; t++) {
if (n[t] !== a[t]) {
for (let t = 0; t < a.length; t++) {
if (a[t] !== r[t]) {
e = false;

@@ -70,6 +70,6 @@ break;

}
if (e) return n;
if (e) return a;
}
const e = new Set(n);
for (let t = 0; t < a.length; t++) e.add(a[t]);
const e = new Set(a);
for (let t = 0; t < r.length; t++) e.add(r[t]);
return Array.from(e);

@@ -80,3 +80,3 @@ }

// `next`'s keys (a key present in next is never deleted by the diff).
const l = new Set(n);
const l = new Set(a);
addEnumSymbols(e, i, l);

@@ -88,4 +88,4 @@ if (t) {

}
for (let e = 0; e < a.length; e++) l.add(a[e]);
addEnumSymbols(r, o, l);
for (let e = 0; e < r.length; e++) l.add(r[e]);
addEnumSymbols(n, s, l);
return Array.from(l);

@@ -105,4 +105,4 @@ }

function keyedMatch(e, t, r) {
return e === t || isWrappable(e) && isWrappable(t) && r(e) === r(t);
function keyedMatch(e, t, n) {
return e === t || isWrappable(e) && isWrappable(t) && n(e) === n(t);
}

@@ -115,16 +115,30 @@

// props behave like normal property reads.
// Inline key iteration on purpose: these loops run per array target per
// reconcile pass, and a shared helper means a closure + per-key call in
// instruction counts. String-only records (the common case) iterate in
// place; symbol-bearing records take the nodeKeys array path.
function syncArrayNodeMembership(e, t) {
let r = e[STORE_NODE];
if (r) {
const e = nodeKeys(r);
for (let n = 0, a = e.length; n < a; n++) {
const a = e[n];
a in t || setSignal(r[a], undefined);
let n = e[STORE_NODE];
if (n) {
if (symbolKeyedRecords.has(n)) {
const e = nodeKeys(n);
for (let a = 0, r = e.length; a < r; a++) {
e[a] in t || setSignal(n[e[a]], undefined);
}
} else {
for (const e in n) {
e in t || setSignal(n[e], undefined);
}
}
}
if (r = e[STORE_HAS]) {
const e = nodeKeys(r);
for (let n = 0, a = e.length; n < a; n++) {
const a = e[n];
setSignal(r[a], a in t);
if (n = e[STORE_HAS]) {
if (symbolKeyedRecords.has(n)) {
const e = nodeKeys(n);
for (let a = 0, r = e.length; a < r; a++) {
setSignal(n[e[a]], e[a] in t);
}
} else {
for (const e in n) {
setSignal(n[e], e in t);
}
}

@@ -134,10 +148,36 @@ }

// Recurse into a matched wrappable child pair without manufacturing a proxy:
// resolve the child's target through the lookup and dispatch directly. A
// lookup miss means the child was never observed — no proxy, no nodes, no
// subscribers anywhere below — so the parent's swap making `next`
// authoritative IS the whole update; a later read wraps next's child on
// demand. This turns the diff from O(previous graph) into O(observed graph)
// and drops the wrap()/$PROXY/$TARGET round-trip per visited child.
// Wrap-family stores (projections/optimistic) own child proxy creation and
// keep the proxy-based recursion.
function applyStateChild(e, t, n, a) {
if (n[STORE_WRAP] !== undefined) {
applyState(e, wrap(t, n), a);
return;
}
const r = t[$TARGET] ?? storeLookup.get(t);
if (r === undefined) return;
e = unwrap(e);
if (r[STORE_SHALLOW]) {
applyStateShallow(e, r);
} else if (r[STORE_OVERRIDE] || r[STORE_OPTIMISTIC_OVERRIDE]) {
applyStateSlow(e, r, a);
} else {
applyStateFast(e, r, a);
}
}
// Reconcile a single array slot: recurse into a wrappable pair, otherwise replace
// the node's value outright (covers object→primitive and primitive→object).
function applyArrayItem(e, t, r, n, a) {
if (isWrappable(e) && isWrappable(t)) {
const i = wrap(t, r);
n && setSignal(n, i);
applyState(e, i, a);
} else n && setSignal(n, wrapValue(e, r));
function applyArrayItem(e, t, n, a, r) {
if (isWrappable(e) && isWrappable(t) && !(rawValuesUsed && (isRawValue(t) || isRawValue(e)))) {
const i = wrap(t, n);
a && setSignal(a, i);
applyState(e, i, r);
} else a && setSignal(a, wrapValue(e, n));
}

@@ -156,19 +196,52 @@

* `$TRACK` absence (an enumeration-tracked record already diffs every key).
*/ function applyDescendants(e, t, r, n, a, i, o) {
const l = r[STORE_LOOKUP] || storeLookup;
const s = (i ? getKeys(e, i) : Object.keys(e)).concat(getStoreSymbols(e, i));
for (let p = 0, f = s.length; p < f; p++) {
const f = s[p];
if (n?.[f]) continue;
*/ function applyDescendants(e, t, n, a, r, i, s) {
const l = n[STORE_LOOKUP] || storeLookup;
if (i) {
const n = getKeys(e, i).concat(getStoreSymbols(e, i));
for (let o = 0, f = n.length; o < f; o++) {
const f = n[o];
if (a?.[f]) continue;
// main loop already diffed this slot
const c = unwrap(i ? getOverrideValue(e, i, f, o) : e[f]);
if (!isWrappable(c)) continue;
const u = (l.get(c) ?? storeLookup.get(c))?.[$TARGET];
if (!u?.[STORE_DESC]) continue;
const y = unwrap(t[f]);
if (c === y || !isWrappable(y) || Array.isArray(c) !== Array.isArray(y) || a(c) != null && a(c) !== a(y)) continue;
applyState(y, wrap(c, r), a);
const p = unwrap(getOverrideValue(e, i, f, s));
if (!isWrappable(p)) continue;
descendInto(p, t[f], l, r);
}
return;
}
// No-override path (every applyStateFast call): iterate in place instead of
// building keys + symbols + concat arrays per object per pass. The cheap
// bails (noded key, primitive value) stay inline — only genuine descent
// candidates pay a call.
for (const n in e) {
if (a?.[n]) continue;
// main loop already diffed this slot
const i = unwrap(e[n]);
if (!isWrappable(i)) continue;
descendInto(i, t[n], l, r);
}
const o = Object.getOwnPropertySymbols(e);
for (let n = 0, i = o.length; n < i; n++) {
if (Object.prototype.propertyIsEnumerable.call(e, o[n])) {
if (a?.[o[n]]) continue;
const i = unwrap(e[o[n]]);
if (!isWrappable(i)) continue;
descendInto(i, t[o[n]], l, r);
}
}
}
function descendInto(e, t, n, a) {
const r = lookupTarget(e, n);
if (!r?.[STORE_DESC]) return;
const i = unwrap(t);
if (e === i || !isWrappable(i) || Array.isArray(e) !== Array.isArray(i) || a(e) != null && a(e) !== a(i)) return;
if (r[STORE_SHALLOW]) {
applyStateShallow(i, r);
} else if (r[STORE_OVERRIDE] || r[STORE_OPTIMISTIC_OVERRIDE]) {
applyStateSlow(i, r, a);
} else {
applyStateFast(i, r, a);
}
}
// Dispatcher: every applyState call (including recursion) checks for the

@@ -179,80 +252,180 @@ // presence of override / optimistic-override slots once and routes to the

// shape for the overwhelmingly common case of plain stores.
function applyState(e, t, r) {
function applyState(e, t, n) {
// Array items and root calls can pass a store proxy as `next`; normalize to
// its raw value or the swap would set a store's STORE_VALUE to its own proxy.
e = unwrap(e);
const n = t?.[$TARGET];
if (!n) return;
if (n[STORE_OVERRIDE] || n[STORE_OPTIMISTIC_OVERRIDE]) {
applyStateSlow(e, n, r);
const a = t?.[$TARGET];
if (!a) return;
if (a[STORE_SHALLOW]) {
applyStateShallow(e, a);
} else if (a[STORE_OVERRIDE] || a[STORE_OPTIMISTIC_OVERRIDE]) {
applyStateSlow(e, a, n);
} else {
applyStateFast(e, n, r);
applyStateFast(e, a, n);
}
}
function applyStateFast(e, t, r) {
const n = t[STORE_VALUE];
if (e === n) return;
const a = t[STORE_NODE];
// Shallow boundary diff: the target's own keys are reactive, its values are
// raw records replaced by reference — no recursion, no wrapping. Arrays merge
// positionally (below a shallow boundary the VALUE is the identity; keyed
// row identity belongs to the consumer, e.g. <For keyed>). Incoming
// wrappables are sticky-marked raw so they present raw through every store.
// One pass over a shallow target's node record: replace changed slots with
// raw next values, null out slots absent from next. Returns whether anything
// differed.
function shallowDiffNodes(e, t, n, a) {
let r = false;
for (const i in e) {
if (a && i === "length") continue;
if (i in t) {
const a = t[i];
if (a !== n(i)) {
r = true;
setSignal(e[i], a);
}
} else {
r = true;
setSignal(e[i], undefined);
}
}
return r;
}
function applyStateShallow(e, t, n) {
const a = t[STORE_VALUE];
const r = t[STORE_OVERRIDE];
const i = t[STORE_OPTIMISTIC_OVERRIDE];
if (e === a && !r && !i) return;
// Setter-staged writes fold into the diff: previous values resolve through
// the override layers (so a replaced slot compares against what readers
// saw), and the regular override clears with the swap — reconcile makes
// `next` the authoritative base, same as the deep slow path.
const prevAt = e => {
const t = getOverrideValue(a, r, e, i);
return t === $DELETED ? undefined : t;
};
t[STORE_OVERRIDE] = undefined;
const s = t[STORE_LOOKUP];
s !== undefined ? s.set(e, t[$PROXY]) : storeLookup.set(e, t);
t[STORE_VALUE] = e;
markRawIngest(e);
const l = t[STORE_NODE];
const o = l && l[$TRACK];
let f = false;
if (Array.isArray(a)) {
const n = r?.length ?? i?.length ?? a.length;
if (l) {
f = shallowDiffNodes(l, e, prevAt, true);
if (l.length && n !== e.length) setSignal(l.length, e.length);
}
if (!f && (o || t[STORE_HAS])) {
// Slots without nodes still feed $TRACK enumerators / `in` probes.
if (n !== e.length) f = true; else {
for (let t = 0, n = e.length; t < n; t++) {
if (prevAt(t) !== e[t]) {
f = true;
break;
}
}
}
}
} else {
if (l) {
f = shallowDiffNodes(l, e, prevAt, false);
}
if (!f && (o || t[STORE_HAS])) f = true;
}
let p = t[STORE_HAS];
if (p) {
for (const t in p) {
setSignal(p[t], t in e);
}
}
f && notifySelf(t);
}
function applyStateFast(e, t, n) {
const a = t[STORE_VALUE];
if (e === a) return;
const r = t[STORE_NODE];
// swap
(t[STORE_LOOKUP] || storeLookup).set(e, t[$PROXY]);
{
const n = t[STORE_LOOKUP];
n !== undefined ? n.set(e, t[$PROXY]) : storeLookup.set(e, t);
}
t[STORE_VALUE] = e;
// merge
if (Array.isArray(n)) {
if (Array.isArray(a)) {
let i = false;
const o = n.length;
if (e.length && o && isWrappable(e[0]) && r(e[0]) != null) {
let l, s, p, f, c, u, y, S;
for (p = 0, f = Math.min(o, e.length); p < f && keyedMatch(u = n[p], e[p], r); p++) {
isWrappable(u) && isWrappable(e[p]) && applyState(e[p], wrap(u, t), r);
const s = a.length;
if (e.length && s && isWrappable(e[0]) && n(e[0]) != null) {
let l, o, f, p, u, c, S, R;
for (f = 0, p = Math.min(s, e.length); f < p && keyedMatch(c = a[f], e[f], n); f++) {
// keyedMatch established both sides wrappable unless they're the
// SAME reference — and an identical slot is a guaranteed no-op
// (the child's STORE_VALUE tracks the previous graph), so skip
// the recursion dispatch entirely. Raw-marked values are leaves:
// replace the slot node instead of recursing.
if (c !== e[f]) {
if (rawValuesUsed && (isRawValue(c) || isRawValue(e[f]))) {
r?.[f] && setSignal(r[f], wrapValue(e[f], t));
} else applyStateChild(e[f], c, t, n);
}
}
// Every position key-matched at equal length (the steady-state shape
// of a polling tick): membership, length, and order are unchanged —
// nothing below could do observable work, so skip the staging
// allocations and membership sync outright.
if (f === e.length && f === s) return;
const E = new Array(e.length), O = new Map;
for (f = o - 1, c = e.length - 1; f >= p && c >= p && keyedMatch(u = n[f], e[c], r); f--,
c--) {
E[c] = u;
for (p = s - 1, u = e.length - 1; p >= f && u >= f && keyedMatch(c = a[p], e[u], n); p--,
u--) {
E[u] = c;
}
if (p > c || p > f) {
for (s = p; s <= c; s++) {
if (f > u || f > p) {
for (o = f; o <= u; o++) {
i = true;
a?.[s] && setSignal(a[s], wrapValue(e[s], t));
r?.[o] && setSignal(r[o], wrapValue(e[o], t));
}
for (;s < e.length; s++) {
for (;o < e.length; o++) {
i = true;
applyArrayItem(e[s], E[s], t, a?.[s], r);
applyArrayItem(e[o], E[o], t, r?.[o], n);
}
syncArrayNodeMembership(t, e);
(i || o !== e.length) && notifySelf(t);
o !== e.length && a?.length && setSignal(a.length, e.length);
(i || s !== e.length) && notifySelf(t);
s !== e.length && r?.length && setSignal(r.length, e.length);
return;
}
y = new Array(c + 1);
for (s = c; s >= p; s--) {
u = e[s];
S = itemKey(u, r);
l = O.get(S);
y[s] = l === undefined ? -1 : l;
O.set(S, s);
S = new Array(u + 1);
for (o = u; o >= f; o--) {
c = e[o];
R = itemKey(c, n);
l = O.get(R);
S[o] = l === undefined ? -1 : l;
O.set(R, o);
}
for (l = p; l <= f; l++) {
u = n[l];
S = itemKey(u, r);
s = O.get(S);
if (s !== undefined && s !== -1) {
E[s] = u;
s = y[s];
O.set(S, s);
for (l = f; l <= p; l++) {
c = a[l];
R = itemKey(c, n);
o = O.get(R);
if (o !== undefined && o !== -1) {
E[o] = c;
o = S[o];
O.set(R, o);
}
}
for (s = p; s < e.length; s++) {
if (s in E) {
applyArrayItem(e[s], E[s], t, a?.[s], r);
} else a?.[s] && setSignal(a[s], wrapValue(e[s], t));
for (o = f; o < e.length; o++) {
if (o in E) {
applyArrayItem(e[o], E[o], t, r?.[o], n);
} else r?.[o] && setSignal(r[o], wrapValue(e[o], t));
}
if (p < e.length) i = true;
if (f < e.length) i = true;
} else if (e.length) {
for (let o = 0, l = e.length; o < l; o++) {
const l = n[o];
if (isWrappable(l) && isWrappable(e[o])) applyState(e[o], wrap(l, t), r); else {
if (l !== e[o]) i = true;
a?.[o] && setSignal(a[o], wrapValue(e[o], t));
for (let s = 0, l = e.length; s < l; s++) {
const l = a[s];
if (isWrappable(l) && isWrappable(e[s]) && !(rawValuesUsed && (isRawValue(l) || isRawValue(e[s])))) {
if (l !== e[s]) applyStateChild(e[s], l, t, n);
} else {
if (l !== e[s]) i = true;
r?.[s] && setSignal(r[s], wrapValue(e[s], t));
}

@@ -262,5 +435,5 @@ }

syncArrayNodeMembership(t, e);
if (o !== e.length) {
if (s !== e.length) {
i = true;
a?.length && setSignal(a.length, e.length);
r?.length && setSignal(r.length, e.length);
}

@@ -272,9 +445,24 @@ i && notifySelf(t);

let i = t[STORE_NODE];
let o;
let s;
if (i) {
o = i[$TRACK];
if (o || symbolKeyedRecords.has(i)) {
const a = o ? getAllKeys(n, undefined, e) : nodeKeys(i);
for (let l = 0, s = a.length; l < s; l++) {
diffNodeKey(a[l], i, n, e, t, o, r);
s = i[$TRACK];
// The per-key body is duplicated across both loops on purpose: this is
// the hottest object-diff site and a shared helper costs a per-key call
// in instruction counts (CodSpeed regressed ~7% on deep-tree reconciles
// with the extracted form).
if (s || symbolKeyedRecords.has(i)) {
const r = s ? getAllKeys(a, undefined, e) : nodeKeys(i);
for (let l = 0, o = r.length; l < o; l++) {
const o = r[l];
const f = i[o];
const p = unwrap(a[o]);
const u = unwrap(e[o]);
if (p === u) continue;
if (!p || !isWrappable(p) || !isWrappable(u) ||
// Raw-marked values are leaves replaced by reference — a "wrappable
// pair" is only recursable when both sides are actual store children.
rawValuesUsed && (isRawValue(p) || isRawValue(u)) || Array.isArray(p) !== Array.isArray(u) || n(p) != null && n(p) !== n(u)) {
s && setSignal(s, void 0);
f && setSignal(f, isWrappable(u) ? wrap(u, t) : u);
} else applyStateChild(u, p, t, n);
}

@@ -285,14 +473,24 @@ } else {

// per pass, which dominates allocation on large-graph reconciles.
for (const a in i) {
diffNodeKey(a, i, n, e, t, o, r);
for (const r in i) {
const l = i[r];
const o = unwrap(a[r]);
const f = unwrap(e[r]);
if (o === f) continue;
if (!o || !isWrappable(o) || !isWrappable(f) ||
// Raw-marked values are leaves replaced by reference — a "wrappable
// pair" is only recursable when both sides are actual store children.
rawValuesUsed && (isRawValue(o) || isRawValue(f)) || Array.isArray(o) !== Array.isArray(f) || n(o) != null && n(o) !== n(f)) {
s && setSignal(s, void 0);
l && setSignal(l, isWrappable(f) ? wrap(f, t) : f);
} else applyStateChild(f, o, t, n);
}
}
}
if (!o && t[STORE_DESC]) applyDescendants(n, e, t, i, r);
if (!s && t[STORE_DESC]) applyDescendants(a, e, t, i, n);
// has
if (i = t[STORE_HAS]) {
const t = nodeKeys(i);
for (let r = 0, n = t.length; r < n; r++) {
const n = t[r];
setSignal(i[n], n in e);
for (let n = 0, a = t.length; n < a; n++) {
const a = t[n];
setSignal(i[a], a in e);
}

@@ -302,91 +500,87 @@ }

// One node-key step of the fast object diff — shared by the array-iterating
// (tracked / symbol-keyed) and for-in (plain) loops in applyStateFast.
function diffNodeKey(e, t, r, n, a, i, o) {
const l = t[e];
const s = unwrap(r[e]);
let p = unwrap(n[e]);
if (s === p) return;
if (!s || !isWrappable(s) || !isWrappable(p) || Array.isArray(s) !== Array.isArray(p) || o(s) != null && o(s) !== o(p)) {
i && setSignal(i, void 0);
l && setSignal(l, isWrappable(p) ? wrap(p, a) : p);
} else applyState(p, wrap(s, a), o);
}
function applyStateSlow(e, t, r) {
const n = t[STORE_VALUE];
const a = t[STORE_OVERRIDE];
function applyStateSlow(e, t, n) {
const a = t[STORE_VALUE];
const r = t[STORE_OVERRIDE];
const i = t[STORE_OPTIMISTIC_OVERRIDE];
let o = t[STORE_NODE];
let s = t[STORE_NODE];
// swap
(t[STORE_LOOKUP] || storeLookup).set(e, t[$PROXY]);
{
const n = t[STORE_LOOKUP];
n !== undefined ? n.set(e, t[$PROXY]) : storeLookup.set(e, t);
}
t[STORE_VALUE] = e;
t[STORE_OVERRIDE] = undefined;
// merge
if (Array.isArray(n)) {
if (Array.isArray(a)) {
let l = false;
const s = getOverrideValue(n, a, "length", i);
if (e.length && s && isWrappable(e[0]) && r(e[0]) != null) {
let p, f, c, u, y, S, E, O;
for (c = 0, u = Math.min(s, e.length); c < u && keyedMatch(S = getOverrideValue(n, a, c, i), e[c], r); c++) {
isWrappable(S) && isWrappable(e[c]) && applyState(e[c], wrap(S, t), r);
const o = getOverrideValue(a, r, "length", i);
if (e.length && o && isWrappable(e[0]) && n(e[0]) != null) {
let f, p, u, c, S, R, E, O;
for (u = 0, c = Math.min(o, e.length); u < c && keyedMatch(R = getOverrideValue(a, r, u, i), e[u], n); u++) {
if (isWrappable(R) && isWrappable(e[u]) && R !== e[u]) {
if (rawValuesUsed && (isRawValue(R) || isRawValue(e[u]))) {
s?.[u] && setSignal(s[u], wrapValue(e[u], t));
} else applyState(e[u], wrap(R, t), n);
}
}
const d = new Array(e.length), R = new Map;
for (u = s - 1, y = e.length - 1; u >= c && y >= c && keyedMatch(S = getOverrideValue(n, a, u, i), e[y], r); u--,
y--) {
d[y] = S;
const y = new Array(e.length), d = new Map;
for (c = o - 1, S = e.length - 1; c >= u && S >= u && keyedMatch(R = getOverrideValue(a, r, c, i), e[S], n); c--,
S--) {
y[S] = R;
}
if (c > y || c > u) {
for (f = c; f <= y; f++) {
if (u > S || u > c) {
for (p = u; p <= S; p++) {
l = true;
o?.[f] && setSignal(o[f], wrapValue(e[f], t));
s?.[p] && setSignal(s[p], wrapValue(e[p], t));
}
for (;f < e.length; f++) {
for (;p < e.length; p++) {
l = true;
applyArrayItem(e[f], d[f], t, o?.[f], r);
applyArrayItem(e[p], y[p], t, s?.[p], n);
}
const n = e.length;
const a = e.length;
syncArrayNodeMembership(t, e);
(l || s !== n) && notifySelf(t);
s !== n && o?.length && setSignal(o.length, n);
(l || o !== a) && notifySelf(t);
o !== a && s?.length && setSignal(s.length, a);
return;
}
E = new Array(y + 1);
for (f = y; f >= c; f--) {
S = e[f];
O = itemKey(S, r);
p = R.get(O);
E[f] = p === undefined ? -1 : p;
R.set(O, f);
E = new Array(S + 1);
for (p = S; p >= u; p--) {
R = e[p];
O = itemKey(R, n);
f = d.get(O);
E[p] = f === undefined ? -1 : f;
d.set(O, p);
}
for (p = c; p <= u; p++) {
S = getOverrideValue(n, a, p, i);
O = itemKey(S, r);
f = R.get(O);
if (f !== undefined && f !== -1) {
d[f] = S;
f = E[f];
R.set(O, f);
for (f = u; f <= c; f++) {
R = getOverrideValue(a, r, f, i);
O = itemKey(R, n);
p = d.get(O);
if (p !== undefined && p !== -1) {
y[p] = R;
p = E[p];
d.set(O, p);
}
}
for (f = c; f < e.length; f++) {
if (f in d) {
applyArrayItem(e[f], d[f], t, o?.[f], r);
} else o?.[f] && setSignal(o[f], wrapValue(e[f], t));
for (p = u; p < e.length; p++) {
if (p in y) {
applyArrayItem(e[p], y[p], t, s?.[p], n);
} else s?.[p] && setSignal(s[p], wrapValue(e[p], t));
}
if (c < e.length) l = true;
if (u < e.length) l = true;
} else if (e.length) {
for (let s = 0, p = e.length; s < p; s++) {
const p = getOverrideValue(n, a, s, i);
if (isWrappable(p) && isWrappable(e[s])) applyState(e[s], wrap(p, t), r); else {
if (p !== e[s]) l = true;
o?.[s] && setSignal(o[s], wrapValue(e[s], t));
for (let o = 0, f = e.length; o < f; o++) {
const f = getOverrideValue(a, r, o, i);
if (isWrappable(f) && isWrappable(e[o]) && !(rawValuesUsed && (isRawValue(f) || isRawValue(e[o])))) {
if (f !== e[o]) applyState(e[o], wrap(f, t), n);
} else {
if (f !== e[o]) l = true;
s?.[o] && setSignal(s[o], wrapValue(e[o], t));
}
}
}
const p = e.length;
const f = e.length;
syncArrayNodeMembership(t, e);
if (s !== p) {
if (o !== f) {
l = true;
o?.length && setSignal(o.length, p);
s?.length && setSignal(s.length, f);
}

@@ -398,24 +592,24 @@ l && notifySelf(t);

let l;
if (o) {
l = o[$TRACK];
const s = l ? getAllKeys(n, a, e) : nodeKeys(o);
for (let p = 0, f = s.length; p < f; p++) {
const f = s[p];
const c = o[f];
const u = unwrap(getOverrideValue(n, a, f, i));
let y = unwrap(e[f]);
if (u === y) continue;
if (!u || !isWrappable(u) || !isWrappable(y) || Array.isArray(u) !== Array.isArray(y) || r(u) != null && r(u) !== r(y)) {
if (s) {
l = s[$TRACK];
const o = l ? getAllKeys(a, r, e) : nodeKeys(s);
for (let f = 0, p = o.length; f < p; f++) {
const p = o[f];
const u = s[p];
const c = unwrap(getOverrideValue(a, r, p, i));
let S = unwrap(e[p]);
if (c === S) continue;
if (!c || !isWrappable(c) || !isWrappable(S) || rawValuesUsed && (isRawValue(c) || isRawValue(S)) || Array.isArray(c) !== Array.isArray(S) || n(c) != null && n(c) !== n(S)) {
l && setSignal(l, void 0);
c && setSignal(c, isWrappable(y) ? wrap(y, t) : y);
} else applyState(y, wrap(u, t), r);
u && setSignal(u, isWrappable(S) ? wrap(S, t) : S);
} else applyState(S, wrap(c, t), n);
}
}
if (!l && t[STORE_DESC]) applyDescendants(n, e, t, o, r, a, i);
if (!l && t[STORE_DESC]) applyDescendants(a, e, t, s, n, r, i);
// has
if (o = t[STORE_HAS]) {
const t = nodeKeys(o);
for (let r = 0, n = t.length; r < n; r++) {
const n = t[r];
setSignal(o[n], n in e);
if (s = t[STORE_HAS]) {
const t = nodeKeys(s);
for (let n = 0, a = t.length; n < a; n++) {
const a = t[n];
setSignal(s[a], a in e);
}

@@ -460,12 +654,12 @@ }

*/ function reconcile(e, t = "id") {
return r => {
if (r == null) throw new Error("");
return n => {
if (n == null) throw new Error("");
if (t === null) {
applyState(e, r, NOKEY);
applyState(e, n, NOKEY);
return;
}
const n = typeof t === "string" ? e => e[t] : t;
const a = n(r);
if (a !== undefined && n(e) !== a) throw new Error("");
applyState(e, r, n);
const a = typeof t === "string" ? e => e[t] : t;
const r = a(n);
if (r !== undefined && a(e) !== r) throw new Error("");
applyState(e, n, a);
};

@@ -472,0 +666,0 @@ }

import { $REFRESH, STORE_SNAPSHOT_PROPS, NOT_PENDING, unwrapOverride, STATUS_UNINITIALIZED, STATUS_PENDING, NO_SNAPSHOT } from "../core/constants.js";
import { suppressComputedRecompute, isEqual, signal, pendingCheckActive, untrack, setSignal, read, snapshotCaptureActive, snapshotSources } from "../core/core.js";
import { suppressComputedRecompute, isEqual, signal, pendingCheckActive, untrack, setSignal, read, readNodeFast, READ_SLOW, snapshotCaptureActive, snapshotSources } from "../core/core.js";

@@ -31,3 +31,3 @@ import { DEV } from "../core/dev.js";

const STORE_VALUE = "v", STORE_OVERRIDE = "o", STORE_OPTIMISTIC_OVERRIDE = "x", STORE_NODE = "n", STORE_HAS = "h", STORE_CUSTOM_PROTO = "c", STORE_WRAP = "w", STORE_LOOKUP = "l", STORE_FIREWALL = "f", STORE_OPTIMISTIC = "p", STORE_OPTIMISTIC_OWNERS = "t", STORE_PARENT = "u", STORE_DESC = "d";
const STORE_VALUE = "v", STORE_OVERRIDE = "o", STORE_OPTIMISTIC_OVERRIDE = "x", STORE_NODE = "n", STORE_HAS = "h", STORE_CUSTOM_PROTO = "c", STORE_WRAP = "w", STORE_LOOKUP = "l", STORE_FIREWALL = "f", STORE_OPTIMISTIC = "p", STORE_OPTIMISTIC_OWNERS = "t", STORE_PARENT = "u", STORE_DESC = "d", STORE_SHALLOW = "s";

@@ -56,2 +56,3 @@ const STORE_SELF_PENDING = Symbol(0);

e[STORE_DESC] = undefined;
e[STORE_SHALLOW] = undefined;
e[$PROXY] = null;

@@ -81,2 +82,8 @@ }

// The global lookup maps raw value -> StoreNode TARGET (not proxy): reconcile
// and the unwrap/snapshot walks resolve targets through it constantly, and a
// target hit is a plain field read away from its proxy while a proxy hit
// costs a trap to get back to the target. Per-family STORE_LOOKUP maps
// (projections/optimistic) still map raw -> proxy — their wrap functions own
// that contract — so mixed-lookup consumers resolve through lookupTarget().
const storeLookup = new WeakMap;

@@ -88,3 +95,52 @@

function lookupTarget(e, t) {
if (t !== undefined && t !== storeLookup) {
const r = t.get(e);
if (r !== undefined) return r[$TARGET];
}
return storeLookup.get(e);
}
// Values marked raw never acquire a proxy identity: wrap() serves them as-is
// everywhere — deep stores hold them as leaf values replaced by reference.
// Once raw, always raw (identity stays single, just unwrapped). Consulted
// only on wrap-creation and ingest paths; reads never touch it.
const rawValues = new WeakSet;
/**
* Marks a value as raw: no store will ever wrap it — every store presents it
* as-is, tracked by reference at whatever slot holds it and updated by
* replacement. Useful for class instances and external objects (editors,
* scene graphs, Maps) and for record-shaped data updated wholesale. Sticky
* for the value's lifetime.
*/
// Flipped on the first mark and exported as a LIVE binding: reconcile
// consults it on every recursable pair, and importing the boolean directly
// lets those sites skip even the function call when no shallow store or raw
// mark exists anywhere in the app.
let rawValuesUsed = false;
function isRawValue(e) {
return rawValuesUsed && rawValues.has(e);
}
function markRawOne(e) {
if (isWrappable(e)) {
rawValuesUsed = true;
rawValues.add(e);
}
}
function markRawIngest(e) {
if (Array.isArray(e)) {
for (let t = 0, r = e.length; t < r; t++) markRawOne(e[t]);
} else {
for (const t in e) markRawOne(e[t]);
}
}
function wrap(e, t) {
// Raw is raw in every family: the mark must preempt family wrapping too,
// or a shallow projection/optimistic store would proxy its raw records.
if (rawValuesUsed && rawValues.has(e)) return e;
if (t?.[STORE_WRAP]) {

@@ -96,7 +152,27 @@ const r = t[STORE_WRAP](e, t);

}
let r = e[$PROXY] || storeLookup.get(e);
if (!r) {
storeLookup.set(e, r = createStoreProxy(e));
if (t) r[$TARGET][STORE_PARENT] = t;
const r = storeLookup.get(e);
if (r !== undefined) return r[$PROXY];
let n = e[$PROXY];
if (!n) {
n = createStoreProxy(e);
const r = n[$TARGET];
storeLookup.set(e, r);
if (t) r[STORE_PARENT] = t;
}
return n;
}
// Shallow store root: the target itself is fully reactive (per-key nodes,
// membership, $TRACK); its values are served raw. Seed values are marked at
// creation; reconcile and the set trap mark on ingest.
function wrapShallow(e) {
const t = storeLookup.get(e);
if (t !== undefined) {
if (t[STORE_SHALLOW]) return t[$PROXY];
}
const r = createStoreProxy(e);
const n = r[$TARGET];
n[STORE_SHALLOW] = true;
storeLookup.set(e, n);
markRawIngest(e);
return r;

@@ -123,3 +199,3 @@ }

function unwrapStoreValue(e, t, r) {
const n = e?.[$TARGET] || r?.get(e)?.[$TARGET];
const n = e?.[$TARGET] || lookupTarget(e, r);
if (!n) return e;

@@ -131,13 +207,13 @@ const o = n[STORE_OVERRIDE];

const i = n[STORE_VALUE];
const E = Array.isArray(i);
const O = E ? [] : Object.create(Object.getPrototypeOf(i));
t.set(e, O);
const O = Array.isArray(i);
const s = O ? [] : Object.create(Object.getPrototypeOf(i));
t.set(e, s);
r = n[STORE_LOOKUP] ?? storeLookup;
for (const e of getStoreKeys(i, o)) {
if (E && e === "length") continue;
if (O && e === "length") continue;
const n = e in o ? o[e] : i[e];
if (n !== $DELETED) O[e] = unwrapStoreValue(n, t, r);
if (n !== $DELETED) s[e] = unwrapStoreValue(n, t, r);
}
if (E) O.length = o.length ?? i.length;
return O;
if (O) s.length = o.length ?? i.length;
return s;
}

@@ -217,6 +293,6 @@

if (t[r]) return t[r];
const E = signal(n, {
const O = signal(n, {
equals: o,
unobserved() {
if (t[r] === E) {
if (t[r] === O) {
delete t[r];

@@ -241,8 +317,8 @@ // Drop the symbol-record mark once the last user symbol node is

if (e[STORE_OPTIMISTIC]) {
E.Ee = NOT_PENDING;
O.Ee = NOT_PENDING;
}
if (i && r in i) {
const e = i[r];
E.Ve = e === undefined ? NO_SNAPSHOT : e;
snapshotSources?.add(E);
O.Ve = e === undefined ? NO_SNAPSHOT : e;
snapshotSources?.add(O);
}

@@ -253,3 +329,3 @@ if (typeof r === "symbol" && r !== $TRACK && r !== $AFFECTS) symbolKeyedRecords.add(t);

// record's own $AFFECTS carrier is the mark's channel, never a member.
if (r !== $AFFECTS && affectsScopes.size) inheritAffectsMarks(E, e[STORE_VALUE], r);
if (r !== $AFFECTS && affectsScopes.size) inheritAffectsMarks(O, e[STORE_VALUE], r);
// Node presence bubbles up the wrap chain (sticky), so reconcile can see

@@ -259,8 +335,8 @@ // "subscribers live somewhere below" through node-less intermediate

// the first already-flagged ancestor.
let O = e;
while (O && !O[STORE_DESC]) {
O[STORE_DESC] = true;
O = O[STORE_PARENT];
let s = e;
while (s && !s[STORE_DESC]) {
s[STORE_DESC] = true;
s = s[STORE_PARENT];
}
return t[r] = E;
return t[r] = O;
}

@@ -301,12 +377,12 @@

if (!isWrappable(e)) return;
const i = e[$TARGET] || (n ?? storeLookup).get(e)?.[$TARGET];
const E = i ? i[STORE_VALUE] : e;
if (o.has(E)) return;
o.add(E);
t.scope.add(E);
let O;
const i = e[$TARGET] || lookupTarget(e, n);
const O = i ? i[STORE_VALUE] : e;
if (o.has(O)) return;
o.add(O);
t.scope.add(O);
let s;
if (i) {
collectRecordNodes(i[STORE_NODE], r);
collectRecordNodes(i[STORE_HAS], r);
O = mergedOverlay(i);
s = mergedOverlay(i);
// Carry the effective lookup into untouched descendants. Default stores

@@ -317,6 +393,6 @@ // use the global lookup just like snapshotImpl; without it, nested raw

}
if (Array.isArray(E)) {
const e = O?.length ?? E.length;
if (Array.isArray(O)) {
const e = s?.length ?? O.length;
for (let i = 0; i < e; i++) {
const e = O && i in O ? O[i] : E[i];
const e = s && i in s ? s[i] : O[i];
if (e !== $DELETED) walkAffectsScope(e, t, r, n, o);

@@ -327,6 +403,6 @@ }

// existing index-only walk.
const s = i || n ? getStoreSymbols(E, O) : [];
for (let e = 0, i = s.length; e < i; e++) {
const i = s[e];
const S = getPropertyDescriptor(E, O, i);
const E = i || n ? getStoreSymbols(O, s) : [];
for (let e = 0, i = E.length; e < i; e++) {
const i = E[e];
const S = getPropertyDescriptor(O, s, i);
if (!S || S.get) continue;

@@ -336,7 +412,7 @@ walkAffectsScope(S.value, t, r, n, o);

} else {
const e = i || n ? getStoreKeys(E, O) : getKeys(E, O);
for (let i = 0, s = e.length; i < s; i++) {
const s = getPropertyDescriptor(E, O, e[i]);
if (!s || s.get) continue;
walkAffectsScope(s.value, t, r, n, o);
const e = i || n ? getStoreKeys(O, s) : getKeys(O, s);
for (let i = 0, E = e.length; i < E; i++) {
const E = getPropertyDescriptor(O, s, e[i]);
if (!E || E.get) continue;
walkAffectsScope(E.value, t, r, n, o);
}

@@ -532,6 +608,6 @@ }

const i = e[STORE_OPTIMISTIC] && !projectionWriteActive;
const E = i ? STORE_OPTIMISTIC_OVERRIDE : STORE_OVERRIDE;
const O = i ? STORE_OPTIMISTIC_OVERRIDE : STORE_OVERRIDE;
return {
base: o,
overrideKey: E,
overrideKey: O,
state: n

@@ -570,5 +646,5 @@ };

const i = isWrappable(n) ? wrap(n, e) : n;
const E = getNode(e, t, r, i, isEqual, o);
registerTransientStoreNode(E);
return E;
const O = getNode(e, t, r, i, isEqual, o);
registerTransientStoreNode(O);
return O;
}

@@ -580,10 +656,10 @@

// (whose whole purpose is immediate visibility via STORE_OPTIMISTIC_OVERRIDE).
const E = projectionWriteActive || e[STORE_OPTIMISTIC];
const O = r !== "delete";
const s = e[STORE_HAS]?.[t];
if (s) {
setSignal(s, O);
} else if (!E && r !== "invalidate" && i !== O) {
const O = projectionWriteActive || e[STORE_OPTIMISTIC];
const s = r !== "delete";
const E = e[STORE_HAS]?.[t];
if (E) {
setSignal(E, s);
} else if (!O && r !== "invalidate" && i !== s) {
const r = upsertStoreNode(e, getNodes(e, STORE_HAS), t, i);
setSignal(r, O);
setSignal(r, s);
}

@@ -594,3 +670,3 @@ const S = getNodes(e, STORE_NODE);

setSignal(S[t], () => isWrappable(n) ? wrap(n, e) : n);
} else if (!E) {
} else if (!O) {
const r = upsertStoreNode(e, S, t, o, e[STORE_SNAPSHOT_PROPS]);

@@ -607,3 +683,3 @@ setSignal(r, () => isWrappable(n) ? wrap(n, e) : n);

setSignal(S[t], undefined);
} else if (!E) {
} else if (!O) {
const r = upsertStoreNode(e, S, t, o, e[STORE_SNAPSHOT_PROPS]);

@@ -651,4 +727,16 @@ setSignal(r, undefined);

if (n !== undefined && e[STORE_VALUE][$TARGET] === undefined) {
let t = read(n);
// readNodeFast is read()'s plain-signal fast path hoisted over the
// call; READ_SLOW means a global read window (latest/pending-check/
// transition/lane/snapshot capture) or a node layer is active, and
// only then does the full read() resolution have anything to do.
let t = readNodeFast(n);
if (t === READ_SLOW) t = read(n);
if (t === $DELETED) t = undefined;
// Every node-writing site wraps wrappables before setSignal (see the
// dev assertion below), so re-wrapping on read is redundant — except
// during snapshot capture, where read() can surface a raw captured
// value seeded from snapshot props.
if (!snapshotCaptureActive) {
return t;
}
return isWrappable(t) ? wrap(t, e) : t;

@@ -660,17 +748,17 @@ }

const i = n ? undefined : o[t];
const E = e[STORE_VALUE];
if (!i && !e[STORE_OVERRIDE] && !e[STORE_OPTIMISTIC_OVERRIDE] && !e[STORE_CUSTOM_PROTO] && !e[STORE_OPTIMISTIC] && !e[STORE_SNAPSHOT_PROPS] && !E[$TARGET] && !(t in E) && getObserver() && !n && !writeOnly(r)) {
const O = e[STORE_VALUE];
if (!i && !e[STORE_OVERRIDE] && !e[STORE_OPTIMISTIC_OVERRIDE] && !e[STORE_CUSTOM_PROTO] && !e[STORE_OPTIMISTIC] && !e[STORE_SNAPSHOT_PROPS] && !O[$TARGET] && !(t in O) && getObserver() && !n && !writeOnly(r)) {
return read(getNode(e, o, t, undefined));
}
const O = getOverlayLayer(e, t);
const s = !!O;
const s = getOverlayLayer(e, t);
const E = !!s;
const S = !!e[STORE_VALUE][$TARGET];
const c = O ?? e[STORE_VALUE];
const f = s ?? e[STORE_VALUE];
if (!i) {
const n = Object.getOwnPropertyDescriptor(c, t);
const n = Object.getOwnPropertyDescriptor(f, t);
if (n && n.get) return n.get.call(r);
if (!n && !s && e[STORE_CUSTOM_PROTO]) {
const e = unwrapStoreValue(c);
if (!n && !E && e[STORE_CUSTOM_PROTO]) {
const e = unwrapStoreValue(f);
if (hasInheritedAccessor(e, t)) {
return Reflect.get(c, t, r);
return Reflect.get(f, t, r);
}

@@ -681,5 +769,10 @@ }

if (isPrototypePollutionKey(t) && !hasOwnStoreProperty(e, t)) return undefined;
let r = i && (s || !S) ? visibleNodeValue(i) : c[t];
let r = i && (E || !S) ? visibleNodeValue(i) : f[t];
r === $DELETED && (r = undefined);
if (!isWrappable(r)) return r;
// Shallow boundary: records are replaced, never edited in place. Reads
// inside a setter serve the raw so read-then-replace, filter/pop and
// projection derives all work; in-place mutation of a raw is inert by
// construction — the same contract as a markRaw child in a deep store.
if (e[STORE_SHALLOW]) return r;
const n = wrap(r, e);

@@ -689,10 +782,10 @@ Writing?.add(n);

}
let T = i ? s || !S ? read(o[t]) : (read(o[t]), c[t]) : c[t];
T === $DELETED && (T = undefined);
let c = i ? E || !S ? read(o[t]) : (read(o[t]), f[t]) : f[t];
c === $DELETED && (c = undefined);
if (!i) {
if (!s && typeof T === "function" && !Object.prototype.hasOwnProperty.call(c, t)) {
if (!E && typeof c === "function" && !Object.prototype.hasOwnProperty.call(f, t)) {
let t;
return !Array.isArray(e[STORE_VALUE]) && (t = Object.getPrototypeOf(e[STORE_VALUE])) && t !== Object.prototype ? T.bind(c) : T;
return !Array.isArray(e[STORE_VALUE]) && (t = Object.getPrototypeOf(e[STORE_VALUE])) && t !== Object.prototype ? c.bind(f) : c;
} else if (getObserver() && !n) {
return read(getNode(e, o, t, isWrappable(T) ? wrap(T, e) : T, isEqual, e[STORE_SNAPSHOT_PROPS]));
return read(getNode(e, o, t, isWrappable(c) ? wrap(c, e) : c, isEqual, e[STORE_SNAPSHOT_PROPS]));
}

@@ -703,3 +796,3 @@ }

if (!n) throwIfUninitialized(e);
return isWrappable(T) ? wrap(T, e) : T;
return isWrappable(c) ? wrap(c, e) : c;
},

@@ -731,18 +824,19 @@ has(e, t) {

untrack(() => {
const {base: o, overrideKey: i, state: E} = prepareStoreWrite(e, n, t);
const O = getOverlayLayer(e, t);
const s = O ? O[t] : o;
const S = O ? O[t] !== $DELETED : t in e[STORE_VALUE];
const c = unwrapStoreValue(r);
const {base: o, overrideKey: i, state: O} = prepareStoreWrite(e, n, t);
const s = getOverlayLayer(e, t);
const E = s ? s[t] : o;
const S = s ? s[t] !== $DELETED : t in e[STORE_VALUE];
const f = unwrapStoreValue(r);
if (e[STORE_SHALLOW] && isWrappable(f)) rawValues.add(f);
// Symbol-keyed writes on arrays are metadata, not index writes — never run
// them through the numeric index/length machinery (`parseInt` on a symbol
// throws). #2769
const T = typeof t === "string" ? Number(t) : -1;
const R = Array.isArray(E) && Number.isInteger(T) && T >= 0 && T < 4294967295 && String(T) === t;
const f = R ? T + 1 : 0;
const u = R && (getOverlayLayer(e, "length") ?? E).length;
const l = R && f > u ? f : undefined;
if (s === c && l === undefined) return true;
const c = typeof t === "string" ? Number(t) : -1;
const R = Array.isArray(O) && Number.isInteger(c) && c >= 0 && c < 4294967295 && String(c) === t;
const T = R ? c + 1 : 0;
const u = R && (getOverlayLayer(e, "length") ?? O).length;
const a = R && T > u ? T : undefined;
if (E === f && a === undefined) return true;
armOptimisticStoreWrite(e, n);
if (c !== undefined && c === o && l === undefined) {
if (f !== undefined && f === o && a === undefined) {
delete e[i]?.[t];

@@ -752,19 +846,19 @@ if (i === STORE_OPTIMISTIC_OVERRIDE) delete e[STORE_OPTIMISTIC_OWNERS]?.[t];

const r = e[i] || (e[i] = Object.create(null));
r[t] = c;
r[t] = f;
stampOptimisticOwner(e, i, t);
if (l !== undefined) {
r.length = l;
if (a !== undefined) {
r.length = a;
stampOptimisticOwner(e, i, "length");
}
}
notifyStoreProperty(e, t, "set", c, s, S);
notifyStoreProperty(e, t, "set", f, E, S);
// Shrinking an array's length must remove the truncated indices, otherwise
// they leak through `has`, `ownKeys`, and (tracked) index reads from the
// underlying value. Mark each as deleted and notify so reactive reads update. #2768
if (Array.isArray(E) && t === "length" && typeof c === "number" && typeof s === "number" && c < s) {
if (Array.isArray(O) && t === "length" && typeof f === "number" && typeof E === "number" && f < E) {
const t = e[i] || (e[i] = Object.create(null));
for (let r = c; r < s; r++) {
for (let r = f; r < E; r++) {
if (t[r] === $DELETED) continue;
const n = r in t ? t[r] : E[r];
if (!(r in t) && !(r in E)) continue;
const n = r in t ? t[r] : O[r];
if (!(r in t) && !(r in O)) continue;
t[r] = $DELETED;

@@ -776,9 +870,9 @@ stampOptimisticOwner(e, i, r);

// notify length change
if (Array.isArray(E) && t !== "length" && l !== undefined) {
if (Array.isArray(O) && t !== "length" && a !== undefined) {
const t = getNodes(e, STORE_NODE);
if (t.length) {
setSignal(t.length, l);
setSignal(t.length, a);
} else if (!projectionWriteActive && !e[STORE_OPTIMISTIC]) {
const r = upsertStoreNode(e, t, "length", u, e[STORE_SNAPSHOT_PROPS]);
setSignal(r, l);
setSignal(r, a);
}

@@ -798,7 +892,7 @@ }

armOptimisticStoreWrite(e, n);
const E = "value" in r ? {
const O = "value" in r ? {
...r,
value: unwrapStoreValue(r.value)
} : r;
Object.defineProperty(e[i] || (e[i] = Object.create(null)), t, E);
Object.defineProperty(e[i] || (e[i] = Object.create(null)), t, O);
stampOptimisticOwner(e, i, t);

@@ -931,3 +1025,3 @@ notifyStoreProperty(e, t, "invalidate");

function createStore(e, t, r) {
const n = typeof e === "function", o = n ? createProjectionInternal(e, t, r).store : wrap(e);
const n = typeof e === "function", o = n ? createProjectionInternal(e, t, r).store : t?.shallow ? wrapShallow(e) : wrap(e);
return [ o, n ? e => {

@@ -940,2 +1034,2 @@ // Mark the projection as manually written before notifying property nodes.

export { $AFFECTS, $DELETED, $PROXY, $TARGET, $TRACK, STORE_CUSTOM_PROTO, STORE_DESC, STORE_FIREWALL, STORE_HAS, STORE_LOOKUP, STORE_NODE, STORE_OPTIMISTIC, STORE_OPTIMISTIC_OVERRIDE, STORE_OPTIMISTIC_OWNERS, STORE_OVERRIDE, STORE_PARENT, STORE_VALUE, STORE_WRAP, createStore, createStoreProxy, getKeys, getOverlayLayer, getPropertyDescriptor, getStoreAffectsNodes, getStoreKeys, getStoreSymbols, isWrappable, mergedOverlay, notifySelf, ownEnumerableKeys, setWriteOverride, storeLookup, storeSetter, storeTraps, symbolKeyedRecords, trackSelf, visibleNodeValue, witnessAffectsMark, wrap };
export { $AFFECTS, $DELETED, $PROXY, $TARGET, $TRACK, STORE_CUSTOM_PROTO, STORE_DESC, STORE_FIREWALL, STORE_HAS, STORE_LOOKUP, STORE_NODE, STORE_OPTIMISTIC, STORE_OPTIMISTIC_OVERRIDE, STORE_OPTIMISTIC_OWNERS, STORE_OVERRIDE, STORE_PARENT, STORE_SHALLOW, STORE_VALUE, STORE_WRAP, createStore, createStoreProxy, getKeys, getOverlayLayer, getPropertyDescriptor, getStoreAffectsNodes, getStoreKeys, getStoreSymbols, isRawValue, isWrappable, lookupTarget, markRawIngest, mergedOverlay, notifySelf, ownEnumerableKeys, rawValuesUsed, setWriteOverride, storeLookup, storeSetter, storeTraps, symbolKeyedRecords, trackSelf, visibleNodeValue, witnessAffectsMark, wrap, wrapShallow };

@@ -15,3 +15,3 @@ import { pendingCheckActive } from "../core/core.js";

import { ownEnumerableKeys, $PROXY, isWrappable, $TARGET, trackSelf, witnessAffectsMark, mergedOverlay, STORE_VALUE, storeLookup, STORE_LOOKUP, $DELETED, wrap, getStoreSymbols, getPropertyDescriptor, getStoreKeys, getKeys, $TRACK } from "./store.js";
import { ownEnumerableKeys, $PROXY, isWrappable, $TARGET, lookupTarget, trackSelf, witnessAffectsMark, mergedOverlay, STORE_VALUE, storeLookup, STORE_LOOKUP, $DELETED, wrap, getStoreSymbols, getPropertyDescriptor, getStoreKeys, getKeys, $TRACK, rawValuesUsed, isRawValue } from "./store.js";

@@ -23,3 +23,3 @@ function snapshotImpl(e, t, r, n) {

if (!r) r = new Map;
if (o = e[$TARGET] || n?.get(e)?.[$TARGET]) {
if (o = e[$TARGET] || lookupTarget(e, n)) {
if (t) {

@@ -54,9 +54,9 @@ trackSelf(o, $TRACK);

const s = i?.length ?? e.length;
for (let p = 0; p < s; p++) {
u = i && p in i ? i[p] : e[p];
for (let a = 0; a < s; a++) {
u = i && a in i ? i[a] : e[a];
if (u === $DELETED) continue;
if (t && isWrappable(u)) wrap(u, o);
if (t && isWrappable(u) && !(rawValuesUsed && isRawValue(u))) wrap(u, o);
if ((f = snapshotImpl(u, t, r, n)) !== u || c) {
if (!c) r.set(e, c = [ ...e ]);
c[p] = f;
c[a] = f;
}

@@ -66,9 +66,9 @@ }

// Spread copies omit symbols, so assign them after the numeric walk.
const p = n ? getStoreSymbols(e, i) : [];
for (let s = 0, l = p.length; s < l; s++) {
const l = p[s];
const a = getPropertyDescriptor(e, i, l);
if (!a || a.get) continue;
const a = n ? getStoreSymbols(e, i) : [];
for (let s = 0, l = a.length; s < l; s++) {
const l = a[s];
const p = getPropertyDescriptor(e, i, l);
if (!p || p.get) continue;
u = i && l in i ? i[l] : e[l];
if (t && isWrappable(u)) wrap(u, o);
if (t && isWrappable(u) && !(rawValuesUsed && isRawValue(u))) wrap(u, o);
f = snapshotImpl(u, t, r, n);

@@ -90,8 +90,8 @@ if (f !== u || c) {

const s = n ? getStoreKeys(e, undefined) : getKeys(e, undefined);
for (let i = 0, p = s.length; i < p; i++) {
const p = s[i];
const l = Object.getOwnPropertyDescriptor(e, p);
for (let i = 0, a = s.length; i < a; i++) {
const a = s[i];
const l = Object.getOwnPropertyDescriptor(e, a);
if (l.get) continue;
u = l.value;
if (t && isWrappable(u)) wrap(u, o);
if (t && isWrappable(u) && !(rawValuesUsed && isRawValue(u))) wrap(u, o);
if ((f = snapshotImpl(u, t, r, n)) !== u || c) {

@@ -102,3 +102,3 @@ if (!c) {

}
c[p] = f;
c[a] = f;
}

@@ -110,8 +110,8 @@ }

const s = getStoreKeys(e, i);
for (let p = 0, l = s.length; p < l; p++) {
let l = s[p];
const a = getPropertyDescriptor(e, i, l);
if (a.get) continue;
for (let a = 0, l = s.length; a < l; a++) {
let l = s[a];
const p = getPropertyDescriptor(e, i, l);
if (p.get) continue;
u = l in i ? i[l] : e[l];
if (t && isWrappable(u)) wrap(u, o);
if (t && isWrappable(u) && !(rawValuesUsed && isRawValue(u))) wrap(u, o);
if ((f = snapshotImpl(u, t, r, n)) !== e[l] || c) {

@@ -118,0 +118,0 @@ if (!c) {

@@ -75,2 +75,17 @@ import { type Refreshable } from "./constants.cjs";

export declare function prepareComputed(comp: Computed<unknown>, refresh: boolean): void;
/**
* Sentinel returned by readNodeFast when the plain-signal fast path does not
* apply and the caller must fall back to the full read().
*/
export declare const READ_SLOW: unique symbol;
/**
* read()'s plain-signal fast path as a standalone entry for hot callers
* (store traps). Safe to substitute for read() only because the bail
* conditions mirror read()'s prelude and fast-path guard exactly: the
* latestRead and pendingCheck windows run side-effectful hooks before the
* fast path, `_fn` nodes need prepareComputed, and firewall / override /
* snapshot / transition / lane / dev-strictRead state all take the full
* resolution. Anything slow returns READ_SLOW; the caller then calls read().
*/
export declare function readNodeFast<T>(el: Signal<T>): T | typeof READ_SLOW;
export declare function read<T>(el: Signal<T> | Computed<T>): T;

@@ -77,0 +92,0 @@ export declare function setSignal<T>(el: Signal<T> | Computed<T>, v: T | ((prev: T) => T)): T;

@@ -44,3 +44,3 @@ import { type Refreshable } from "../core/index.cjs";

*/
export declare function createOptimisticStore<T extends object = {}>(store: NoFn<T> | Store<NoFn<T>>): [get: Store<T>, set: StoreSetter<T>];
export declare function createOptimisticStore<T extends object = {}>(store: NoFn<T> | Store<NoFn<T>>, options?: ProjectionOptions): [get: Store<T>, set: StoreSetter<T>];
export declare function createOptimisticStore<T extends object = {}>(fn: (store: T) => void | T | Promise<void | T> | AsyncIterable<void | T>, store: Partial<T> | Store<NoFn<T>>, options?: ProjectionOptions): [get: Refreshable<Store<T>>, set: StoreSetter<T>];

@@ -34,2 +34,4 @@ import { STORE_SNAPSHOT_PROPS, type Computed, type Refreshable, type Signal } from "../core/index.cjs";

key?: string | ((item: NonNullable<any>) => any);
/** Single-layer store: root keys reactive, values raw records replaced by reference */
shallow?: boolean;
}

@@ -46,3 +48,3 @@ export type NoFn<T> = T extends Function ? never : T;

export declare const $TRACK: unique symbol, $TARGET: unique symbol, $PROXY: unique symbol, $DELETED: unique symbol, $AFFECTS: unique symbol;
export declare const STORE_VALUE = "v", STORE_OVERRIDE = "o", STORE_OPTIMISTIC_OVERRIDE = "x", STORE_NODE = "n", STORE_HAS = "h", STORE_CUSTOM_PROTO = "c", STORE_WRAP = "w", STORE_LOOKUP = "l", STORE_FIREWALL = "f", STORE_OPTIMISTIC = "p", STORE_OPTIMISTIC_OWNERS = "t", STORE_PARENT = "u", STORE_DESC = "d";
export declare const STORE_VALUE = "v", STORE_OVERRIDE = "o", STORE_OPTIMISTIC_OVERRIDE = "x", STORE_NODE = "n", STORE_HAS = "h", STORE_CUSTOM_PROTO = "c", STORE_WRAP = "w", STORE_LOOKUP = "l", STORE_FIREWALL = "f", STORE_OPTIMISTIC = "p", STORE_OPTIMISTIC_OWNERS = "t", STORE_PARENT = "u", STORE_DESC = "d", STORE_SHALLOW = "s";
export type StoreNode = {

@@ -63,2 +65,3 @@ [$PROXY]: any;

[STORE_PARENT]?: StoreNode;
[STORE_SHALLOW]?: boolean;
[STORE_DESC]?: boolean;

@@ -74,3 +77,16 @@ };

export declare const symbolKeyedRecords: WeakSet<object>;
export declare function lookupTarget(value: any, lookup?: WeakMap<any, any>): StoreNode | undefined;
/**
* Marks a value as raw: no store will ever wrap it — every store presents it
* as-is, tracked by reference at whatever slot holds it and updated by
* replacement. Useful for class instances and external objects (editors,
* scene graphs, Maps) and for record-shaped data updated wholesale. Sticky
* for the value's lifetime.
*/
export declare let rawValuesUsed: boolean;
export declare function isRawValue(value: any): boolean;
export declare function markRaw<T>(value: T): T;
export declare function markRawIngest(container: any): void;
export declare function wrap<T extends Record<PropertyKey, any>>(value: T, target?: StoreNode): T;
export declare function wrapShallow<T extends Record<PropertyKey, any>>(value: T): T;
export declare function isWrappable<T>(obj: T | NotWrappable): obj is T;

@@ -183,4 +199,6 @@ export declare function setWriteOverride(value: boolean): void;

*/
export declare function createStore<T extends object = {}>(store: NoFn<T> | Store<NoFn<T>>): StoreReturn<T>;
export declare function createStore<T extends object = {}>(store: NoFn<T> | Store<NoFn<T>>, options?: StoreOptions & {
shallow?: boolean;
}): StoreReturn<T>;
export declare function createStore<T extends object = {}>(fn: (store: T) => void | T | Promise<void | T> | AsyncIterable<void | T>, store: Partial<T> | Store<NoFn<T>>, options?: ProjectionOptions): ProjectionStoreReturn<T>;
export {};

@@ -75,2 +75,17 @@ import { type Refreshable } from "./constants.js";

export declare function prepareComputed(comp: Computed<unknown>, refresh: boolean): void;
/**
* Sentinel returned by readNodeFast when the plain-signal fast path does not
* apply and the caller must fall back to the full read().
*/
export declare const READ_SLOW: unique symbol;
/**
* read()'s plain-signal fast path as a standalone entry for hot callers
* (store traps). Safe to substitute for read() only because the bail
* conditions mirror read()'s prelude and fast-path guard exactly: the
* latestRead and pendingCheck windows run side-effectful hooks before the
* fast path, `_fn` nodes need prepareComputed, and firewall / override /
* snapshot / transition / lane / dev-strictRead state all take the full
* resolution. Anything slow returns READ_SLOW; the caller then calls read().
*/
export declare function readNodeFast<T>(el: Signal<T>): T | typeof READ_SLOW;
export declare function read<T>(el: Signal<T> | Computed<T>): T;

@@ -77,0 +92,0 @@ export declare function setSignal<T>(el: Signal<T> | Computed<T>, v: T | ((prev: T) => T)): T;

@@ -44,3 +44,3 @@ import { type Refreshable } from "../core/index.js";

*/
export declare function createOptimisticStore<T extends object = {}>(store: NoFn<T> | Store<NoFn<T>>): [get: Store<T>, set: StoreSetter<T>];
export declare function createOptimisticStore<T extends object = {}>(store: NoFn<T> | Store<NoFn<T>>, options?: ProjectionOptions): [get: Store<T>, set: StoreSetter<T>];
export declare function createOptimisticStore<T extends object = {}>(fn: (store: T) => void | T | Promise<void | T> | AsyncIterable<void | T>, store: Partial<T> | Store<NoFn<T>>, options?: ProjectionOptions): [get: Refreshable<Store<T>>, set: StoreSetter<T>];

@@ -34,2 +34,4 @@ import { STORE_SNAPSHOT_PROPS, type Computed, type Refreshable, type Signal } from "../core/index.js";

key?: string | ((item: NonNullable<any>) => any);
/** Single-layer store: root keys reactive, values raw records replaced by reference */
shallow?: boolean;
}

@@ -46,3 +48,3 @@ export type NoFn<T> = T extends Function ? never : T;

export declare const $TRACK: unique symbol, $TARGET: unique symbol, $PROXY: unique symbol, $DELETED: unique symbol, $AFFECTS: unique symbol;
export declare const STORE_VALUE = "v", STORE_OVERRIDE = "o", STORE_OPTIMISTIC_OVERRIDE = "x", STORE_NODE = "n", STORE_HAS = "h", STORE_CUSTOM_PROTO = "c", STORE_WRAP = "w", STORE_LOOKUP = "l", STORE_FIREWALL = "f", STORE_OPTIMISTIC = "p", STORE_OPTIMISTIC_OWNERS = "t", STORE_PARENT = "u", STORE_DESC = "d";
export declare const STORE_VALUE = "v", STORE_OVERRIDE = "o", STORE_OPTIMISTIC_OVERRIDE = "x", STORE_NODE = "n", STORE_HAS = "h", STORE_CUSTOM_PROTO = "c", STORE_WRAP = "w", STORE_LOOKUP = "l", STORE_FIREWALL = "f", STORE_OPTIMISTIC = "p", STORE_OPTIMISTIC_OWNERS = "t", STORE_PARENT = "u", STORE_DESC = "d", STORE_SHALLOW = "s";
export type StoreNode = {

@@ -63,2 +65,3 @@ [$PROXY]: any;

[STORE_PARENT]?: StoreNode;
[STORE_SHALLOW]?: boolean;
[STORE_DESC]?: boolean;

@@ -74,3 +77,16 @@ };

export declare const symbolKeyedRecords: WeakSet<object>;
export declare function lookupTarget(value: any, lookup?: WeakMap<any, any>): StoreNode | undefined;
/**
* Marks a value as raw: no store will ever wrap it — every store presents it
* as-is, tracked by reference at whatever slot holds it and updated by
* replacement. Useful for class instances and external objects (editors,
* scene graphs, Maps) and for record-shaped data updated wholesale. Sticky
* for the value's lifetime.
*/
export declare let rawValuesUsed: boolean;
export declare function isRawValue(value: any): boolean;
export declare function markRaw<T>(value: T): T;
export declare function markRawIngest(container: any): void;
export declare function wrap<T extends Record<PropertyKey, any>>(value: T, target?: StoreNode): T;
export declare function wrapShallow<T extends Record<PropertyKey, any>>(value: T): T;
export declare function isWrappable<T>(obj: T | NotWrappable): obj is T;

@@ -183,4 +199,6 @@ export declare function setWriteOverride(value: boolean): void;

*/
export declare function createStore<T extends object = {}>(store: NoFn<T> | Store<NoFn<T>>): StoreReturn<T>;
export declare function createStore<T extends object = {}>(store: NoFn<T> | Store<NoFn<T>>, options?: StoreOptions & {
shallow?: boolean;
}): StoreReturn<T>;
export declare function createStore<T extends object = {}>(fn: (store: T) => void | T | Promise<void | T> | AsyncIterable<void | T>, store: Partial<T> | Store<NoFn<T>>, options?: ProjectionOptions): ProjectionStoreReturn<T>;
export {};
{
"name": "@solidjs/signals",
"version": "2.0.0-beta.24",
"version": "2.0.0-beta.25",
"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