@solidjs/signals 2.0.0-rc.6 → 2.0.0-rc.7
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/dev.js +2033 -1291
- package/dist/node.cjs +1821 -2401
- package/dist/node.dev.cjs +13724 -0
- package/dist/prod/boundaries.js +3 -1
- package/dist/prod/core/async.js +6 -1
- package/dist/prod/core/attribution-hooks.js +3 -0
- package/dist/prod/core/constants.js +9 -1
- package/dist/prod/core/context.js +10 -16
- package/dist/prod/core/core.js +215 -139
- package/dist/prod/core/dev.js +2 -0
- package/dist/prod/core/effect.js +37 -28
- package/dist/prod/core/external.js +2 -2
- package/dist/prod/core/graph.js +35 -31
- package/dist/prod/core/heap.js +34 -40
- package/dist/prod/core/lanes.js +41 -27
- package/dist/prod/core/optimistic.js +42 -32
- package/dist/prod/core/owner.js +32 -32
- package/dist/prod/core/scheduler.js +140 -154
- package/dist/prod/core/verdict.js +31 -34
- package/dist/prod/index.js +0 -2
- package/dist/prod/map.js +104 -94
- package/dist/prod/signals.js +51 -34
- package/dist/prod/store/next/optimistic.js +153 -172
- package/dist/prod/store/next/reconcile.js +140 -288
- package/dist/prod/store/next/store.js +307 -237
- package/dist/prod/store/store.js +2 -2
- package/dist/types/core/attribution-hooks.d.ts +64 -0
- package/dist/types/core/attribution.d.ts +265 -9
- package/dist/types/core/constants.d.ts +8 -0
- package/dist/types/core/core.d.ts +12 -3
- package/dist/types/core/dev.d.ts +49 -8
- package/dist/types/core/heap.d.ts +5 -3
- package/dist/types/core/invariants.d.ts +1 -1
- package/dist/types/core/lanes.d.ts +10 -0
- package/dist/types/core/scheduler.d.ts +9 -4
- package/dist/types/signals.d.ts +10 -0
- package/dist/types/store/index.d.ts +3 -6
- package/dist/types/store/next/optimistic.d.ts +4 -2
- package/dist/types/store/next/reconcile.d.ts +5 -12
- package/dist/types/store/next/store.d.ts +3 -9
- package/dist/types/store/next/target.d.ts +20 -46
- package/dist/types/store/store.d.ts +14 -9
- package/dist/types-cjs/core/attribution-hooks.d.cts +64 -0
- package/dist/types-cjs/core/attribution.d.cts +265 -9
- package/dist/types-cjs/core/constants.d.cts +8 -0
- package/dist/types-cjs/core/core.d.cts +12 -3
- package/dist/types-cjs/core/dev.d.cts +49 -8
- package/dist/types-cjs/core/heap.d.cts +5 -3
- package/dist/types-cjs/core/invariants.d.cts +1 -1
- package/dist/types-cjs/core/lanes.d.cts +10 -0
- package/dist/types-cjs/core/scheduler.d.cts +9 -4
- package/dist/types-cjs/signals.d.cts +10 -0
- package/dist/types-cjs/store/index.d.cts +3 -6
- package/dist/types-cjs/store/next/optimistic.d.cts +4 -2
- package/dist/types-cjs/store/next/reconcile.d.cts +5 -12
- package/dist/types-cjs/store/next/store.d.cts +3 -9
- package/dist/types-cjs/store/next/target.d.cts +20 -46
- package/dist/types-cjs/store/store.d.cts +14 -9
- package/package.json +3 -2
- package/dist/prod/store/next/patch-hooks.js +0 -13
- package/dist/prod/store/next/patch.js +0 -614
- package/dist/types/store/next/patch-hooks.d.ts +0 -41
- package/dist/types/store/next/patch.d.ts +0 -91
- package/dist/types-cjs/store/next/patch-hooks.d.cts +0 -41
- package/dist/types-cjs/store/next/patch.d.cts +0 -91
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import { CONFIG_AUTO_DISPOSE, STATUS_PENDING, NOT_PENDING, CONFIG_OPTIMISTIC, CONFIG_HELD_TRUTH, unwrapOverride } from "../../core/constants.js";
|
|
1
|
+
import { CONFIG_AUTO_DISPOSE, STATUS_PENDING, STATUS_UNINITIALIZED, NOT_PENDING, CONFIG_OPTIMISTIC, CONFIG_HELD_TRUTH, unwrapOverride } from "../../core/constants.js";
|
|
2
2
|
|
|
3
3
|
import { computed, setSignal, isEqual } from "../../core/core.js";
|
|
4
4
|
|
|
@@ -20,9 +20,7 @@ import { runProjectionComputedNext } from "./projection.js";
|
|
|
20
20
|
|
|
21
21
|
import { wrapNext, runAuthoritative, storeSetterNext, hasActiveOverride, unwrapValue, targetsEqual, getNode, getHasNode, getKeySetNode, bumpDeep, stagedTruthPB, authoritativeRead } from "./store.js";
|
|
22
22
|
|
|
23
|
-
import {
|
|
24
|
-
|
|
25
|
-
import { sameKey, buildIdentityRowOps } from "./reconcile.js";
|
|
23
|
+
import { sameKey } from "./reconcile.js";
|
|
26
24
|
|
|
27
25
|
import { setOptHooks } from "./target.js";
|
|
28
26
|
|
|
@@ -57,7 +55,7 @@ import { setOptHooks } from "./target.js";
|
|
|
57
55
|
* staged values to converge (normal speculation). Resolves merges first:
|
|
58
56
|
* merge unions optimistic nodes/stores into the target. */ function transitionHoldsOptimism(e) {
|
|
59
57
|
const t = currentTransition(e);
|
|
60
|
-
return t.sn !== true && (t.
|
|
58
|
+
return t.sn !== true && (t.Xe.length !== 0 || t.En.size !== 0);
|
|
61
59
|
}
|
|
62
60
|
|
|
63
61
|
let blockedInstalled = false;
|
|
@@ -78,29 +76,20 @@ function installNextBlockedHalf() {
|
|
|
78
76
|
// Scheduler flush tails call _clearOptimisticStores whenever tracked
|
|
79
77
|
// stores exist; next has no layer to clear — reverts are engine-native —
|
|
80
78
|
// so the hook only empties the batch set.
|
|
81
|
-
if (!GlobalQueue.
|
|
82
|
-
GlobalQueue.
|
|
83
|
-
// Patch channel (revert site): engine-native reverts flip node values
|
|
84
|
-
// back to committed; patched records need a forced DOM re-apply from
|
|
85
|
-
// the post-revert view. Emission only — next keeps no layer to clear.
|
|
79
|
+
if (!GlobalQueue.Wt) {
|
|
80
|
+
GlobalQueue.Wt = e => {
|
|
86
81
|
for (const t of e) {
|
|
87
82
|
const e = t?.[$TARGET];
|
|
88
83
|
const n = e?.fam?.overlaid;
|
|
89
84
|
if (n !== undefined) {
|
|
90
85
|
for (const e of n) {
|
|
91
|
-
if (e.pc !== null && e.pc.p !== null) patchHooks.emitPatchOptimistic(e, null, null);
|
|
92
|
-
// Row-ops resync (family increment 2): reverts flip node values
|
|
93
|
-
// back engine-natively; a driven list must rebuild retention by
|
|
94
|
-
// row identity against the post-revert view (resolved from the
|
|
95
|
-
// target at drain — overrides are gone by then).
|
|
96
|
-
if (e.pc !== null && e.pc.ro !== null) rowHooks.emitRowOpsOptimistic(e, null, null);
|
|
97
86
|
// Keyset resync (classic channel twin): the keyset node's own
|
|
98
87
|
// revert can compare EQUAL (a landing's bump matched the
|
|
99
88
|
// tentative bump) while the arrangement underneath changed —
|
|
100
89
|
// mapArray/ownKeys subscribers must re-read the post-revert
|
|
101
90
|
// view. Authoritative bump: never re-arm the node we are
|
|
102
91
|
// clearing.
|
|
103
|
-
|
|
92
|
+
if (e.k !== null) runAuthoritative(() => setSignal(e.k, e => e + 1));
|
|
104
93
|
}
|
|
105
94
|
}
|
|
106
95
|
}
|
|
@@ -112,19 +101,19 @@ function installNextBlockedHalf() {
|
|
|
112
101
|
for (const e of t.En) {
|
|
113
102
|
const n = e?.[$TARGET];
|
|
114
103
|
const i = n?.fam;
|
|
115
|
-
const
|
|
104
|
+
const r = i?.node;
|
|
116
105
|
// The hold exists to keep optimistic state alive until the store's own
|
|
117
106
|
// truth lands (#2951). Once the family carries NO live overrides (a
|
|
118
107
|
// landing consumed them, or they never existed), a pending firewall is
|
|
119
108
|
// no reason to park the transaction — blocking then leaks it forever
|
|
120
109
|
// when the in-flight question is never answered (undisposed fixtures).
|
|
121
|
-
if (
|
|
110
|
+
if (r == null || !(r.S & STATUS_PENDING)) continue;
|
|
122
111
|
// Ownership is declared (#3146): only the flight's OWN transaction
|
|
123
112
|
// parks on the flight (the #2951 anchor routed the bare write there).
|
|
124
113
|
// A transaction that merely brushed the store never waits for truth
|
|
125
114
|
// it does not carry.
|
|
126
|
-
const
|
|
127
|
-
if (
|
|
115
|
+
const o = i.ft != null ? liveTransition(i.ft) : null;
|
|
116
|
+
if (o !== null && o !== currentTransition(t)) continue;
|
|
128
117
|
if (familyHasLiveOverrides(i)) return true;
|
|
129
118
|
}
|
|
130
119
|
return e(t);
|
|
@@ -155,21 +144,21 @@ function createOptimisticStoreNext(e, t, n) {
|
|
|
155
144
|
installOptimisticEngine();
|
|
156
145
|
installNextBlockedHalf();
|
|
157
146
|
const i = typeof e === "function";
|
|
158
|
-
|
|
147
|
+
const r = i ? n : t;
|
|
159
148
|
const o = i ? t : e;
|
|
160
|
-
const
|
|
149
|
+
const s = {
|
|
161
150
|
map: new WeakMap,
|
|
162
151
|
node: null,
|
|
163
|
-
shallow: !!
|
|
152
|
+
shallow: !!r?.shallow,
|
|
164
153
|
opt: true
|
|
165
154
|
};
|
|
166
|
-
const l = wrapNext(o, null, null,
|
|
167
|
-
|
|
155
|
+
const l = wrapNext(o, null, null, s);
|
|
156
|
+
s.px = l;
|
|
168
157
|
// Same key resolution the projection channels use ("id" default) — replay's
|
|
169
158
|
// satisfaction rule reads it off the family.
|
|
170
|
-
const
|
|
171
|
-
|
|
172
|
-
if (
|
|
159
|
+
const u = r?.key === undefined ? "id" : r.key;
|
|
160
|
+
s.key = typeof u === "function" ? u : u === null ? null : e => isWrappable(e) ? e[u] : undefined;
|
|
161
|
+
if (s.shallow) {
|
|
173
162
|
l[$TARGET].s = true;
|
|
174
163
|
markRawIngest(o);
|
|
175
164
|
}
|
|
@@ -185,11 +174,11 @@ function createOptimisticStoreNext(e, t, n) {
|
|
|
185
174
|
// flight (loading window) keeps the ambient reveal (#2933: the loading
|
|
186
175
|
// rail is transaction-invisible).
|
|
187
176
|
const enterFlightTransition = () => {
|
|
188
|
-
const e =
|
|
177
|
+
const e = s.ft;
|
|
189
178
|
if (e == null) return;
|
|
190
179
|
let t = liveTransition(e);
|
|
191
|
-
if (t === null)
|
|
192
|
-
|
|
180
|
+
if (t === null) s.ft = t = createTransition();
|
|
181
|
+
s.node.Ae = t;
|
|
193
182
|
globalQueue.initTransition(t);
|
|
194
183
|
};
|
|
195
184
|
// Landing router (#3164 fold ruling): while a transaction retains
|
|
@@ -200,9 +189,9 @@ function createOptimisticStoreNext(e, t, n) {
|
|
|
200
189
|
// flight-owned transaction (#3146). Sync commits (the derive's body,
|
|
201
190
|
// owner is the firewall itself) reveal with their own recompute's flush.
|
|
202
191
|
const wrapCommit = (e, t) => {
|
|
203
|
-
const n = retainingTransition(
|
|
204
|
-
if (n !== null) return void stageLanding(
|
|
205
|
-
if (getOwner() !==
|
|
192
|
+
const n = retainingTransition(s);
|
|
193
|
+
if (n !== null) return void stageLanding(s, n, t);
|
|
194
|
+
if (getOwner() !== s.node) enterFlightTransition();
|
|
206
195
|
runAuthoritative(e);
|
|
207
196
|
};
|
|
208
197
|
// Draft writes (the derive mutating its draft, sync body and post-await
|
|
@@ -212,7 +201,7 @@ function createOptimisticStoreNext(e, t, n) {
|
|
|
212
201
|
// batch; the write-override eager-commit branch in notifyWrites yields
|
|
213
202
|
// to any active transaction).
|
|
214
203
|
const aroundDraftWrite = e => {
|
|
215
|
-
const t = retainingTransition(
|
|
204
|
+
const t = retainingTransition(s);
|
|
216
205
|
if (t === null) e(); else runFolded(t, e);
|
|
217
206
|
};
|
|
218
207
|
// Flight declaration (#3146): a recompute that registered a truth-flight
|
|
@@ -235,32 +224,41 @@ function createOptimisticStoreNext(e, t, n) {
|
|
|
235
224
|
// the declaration.
|
|
236
225
|
const declareFlight = e => {
|
|
237
226
|
if (e.o?.Ie == null) {
|
|
238
|
-
if (!e.Ne)
|
|
227
|
+
if (!e.Ne) s.ft = null;
|
|
239
228
|
return;
|
|
240
229
|
}
|
|
241
|
-
|
|
230
|
+
// First flight (#3146 carve-out): nothing has ever committed, so there
|
|
231
|
+
// is no truth to keep on screen and no optimistic state to protect. An
|
|
232
|
+
// uninitialized ask suspends its readers into their Loading boundary
|
|
233
|
+
// exactly like a plain derived store's first flight — declaring a
|
|
234
|
+
// transaction here instead held the ROOT MOUNT (render()'s scheduled
|
|
235
|
+
// insert rides transitions) until the fetch landed, so the boundary's
|
|
236
|
+
// fallback never showed and the whole page stayed blank. The loading
|
|
237
|
+
// window (#2933) already declares nothing for the same reason; once
|
|
238
|
+
// the first truth lands, every refetch flight declares as before.
|
|
239
|
+
if (e.Ne || e.S & STATUS_UNINITIALIZED) return;
|
|
242
240
|
let t = activeTransition;
|
|
243
241
|
if (t === null) globalQueue.initTransition(t = createTransition());
|
|
244
|
-
|
|
242
|
+
s.ft = t;
|
|
245
243
|
e.Ae = t;
|
|
246
244
|
let n = t._e.get(e);
|
|
247
245
|
if (n === undefined) t._e.set(e, n = new Set);
|
|
248
246
|
n.add(e);
|
|
249
247
|
};
|
|
250
|
-
let
|
|
251
|
-
if (
|
|
248
|
+
let n;
|
|
249
|
+
if (r?.seedLoadingValue) n = {
|
|
252
250
|
loadingValue: undefined
|
|
253
251
|
};
|
|
254
|
-
const
|
|
252
|
+
const i = computed(() => {
|
|
255
253
|
const e = getOwner();
|
|
256
254
|
try {
|
|
257
|
-
runAuthoritative(() => runProjectionComputedNext(l, t,
|
|
255
|
+
runAuthoritative(() => runProjectionComputedNext(l, t, r?.key === undefined ? "id" : r.key, wrapCommit, aroundDraftWrite));
|
|
258
256
|
} finally {
|
|
259
257
|
declareFlight(e);
|
|
260
258
|
}
|
|
261
|
-
},
|
|
262
|
-
|
|
263
|
-
|
|
259
|
+
}, n);
|
|
260
|
+
i.T &= ~CONFIG_AUTO_DISPOSE;
|
|
261
|
+
s.node = i;
|
|
264
262
|
}
|
|
265
263
|
return [ l, e => {
|
|
266
264
|
// Retention ledger (#3164): record the owning transaction so landings
|
|
@@ -270,7 +268,7 @@ function createOptimisticStoreNext(e, t, n) {
|
|
|
270
268
|
// per #2951 and dies with it).
|
|
271
269
|
const t = activeTransition;
|
|
272
270
|
storeSetterNext(l, e);
|
|
273
|
-
if (t !== null) (
|
|
271
|
+
if (t !== null) (s.rt ??= new Set).add(t);
|
|
274
272
|
} ];
|
|
275
273
|
}
|
|
276
274
|
|
|
@@ -322,7 +320,7 @@ function createOptimisticStoreNext(e, t, n) {
|
|
|
322
320
|
* stay unarmed — the override is their display and its revert their
|
|
323
321
|
* notification, A17). */ function runFolded(e, t) {
|
|
324
322
|
runAsTransitionBatch(e, t);
|
|
325
|
-
const n = e.
|
|
323
|
+
const n = e.Mt;
|
|
326
324
|
for (let t = 0; t < n.length; t++) {
|
|
327
325
|
const i = n[t];
|
|
328
326
|
i.Ae = e;
|
|
@@ -342,15 +340,15 @@ function createOptimisticStoreNext(e, t, n) {
|
|
|
342
340
|
if (n !== null) {
|
|
343
341
|
// Occurrence-aware key queues (parity with the adoption window):
|
|
344
342
|
// duplicate keys match per occurrence, each current row consumed once.
|
|
345
|
-
let
|
|
346
|
-
const
|
|
347
|
-
for (let t = 0; t <
|
|
343
|
+
let r = null;
|
|
344
|
+
const o = e.length;
|
|
345
|
+
for (let t = 0; t < o; t++) {
|
|
348
346
|
const i = unwrapValue(e[t]);
|
|
349
347
|
if (!isWrappable(i)) continue;
|
|
350
|
-
const
|
|
351
|
-
if (
|
|
352
|
-
const
|
|
353
|
-
if (
|
|
348
|
+
const o = n(i);
|
|
349
|
+
if (o === undefined) continue;
|
|
350
|
+
const s = (r ??= new Map).get(o);
|
|
351
|
+
if (s === undefined) r.set(o, [ i ]); else s.push(i);
|
|
354
352
|
}
|
|
355
353
|
// Echo adoption: an optimistic structural add whose key the landing
|
|
356
354
|
// confirms must keep its raw (and so its proxy — list drivers keep the
|
|
@@ -360,47 +358,47 @@ function createOptimisticStoreNext(e, t, n) {
|
|
|
360
358
|
// keys; overlay rows only extend coverage. Adopted raws enter staged
|
|
361
359
|
// truth; at settle the override reverts and the reveal re-seats the
|
|
362
360
|
// same raw.
|
|
363
|
-
const
|
|
364
|
-
if (
|
|
365
|
-
for (const e of Reflect.ownKeys(
|
|
366
|
-
const t =
|
|
361
|
+
const s = e[$TARGET]?.n;
|
|
362
|
+
if (s != null) {
|
|
363
|
+
for (const e of Reflect.ownKeys(s)) {
|
|
364
|
+
const t = s[e];
|
|
367
365
|
if (!hasActiveOverride(t)) continue;
|
|
368
366
|
const i = unwrapValue(unwrapOverride(t.o.Pe));
|
|
369
367
|
if (!isWrappable(i)) continue;
|
|
370
|
-
const
|
|
371
|
-
if (
|
|
372
|
-
const
|
|
373
|
-
if (
|
|
368
|
+
const o = n(i);
|
|
369
|
+
if (o === undefined) continue;
|
|
370
|
+
const l = (r ??= new Map).get(o);
|
|
371
|
+
if (l === undefined) r.set(o, [ i ]); else l.push(i);
|
|
374
372
|
}
|
|
375
373
|
}
|
|
376
|
-
for (let
|
|
377
|
-
const i = t[
|
|
378
|
-
let
|
|
379
|
-
if (isWrappable(i) &&
|
|
374
|
+
for (let o = 0; o < i; o++) {
|
|
375
|
+
const i = t[o];
|
|
376
|
+
let s;
|
|
377
|
+
if (isWrappable(i) && r !== null) {
|
|
380
378
|
const e = n(i);
|
|
381
379
|
if (e !== undefined) {
|
|
382
|
-
for (const [t, n] of
|
|
380
|
+
for (const [t, n] of r) {
|
|
383
381
|
if (!sameKey(t, e)) continue;
|
|
384
|
-
|
|
385
|
-
if (n.length === 0)
|
|
382
|
+
s = n.shift();
|
|
383
|
+
if (n.length === 0) r.delete(t);
|
|
386
384
|
break;
|
|
387
385
|
}
|
|
388
386
|
}
|
|
389
387
|
}
|
|
390
|
-
if (
|
|
391
|
-
if (unwrapValue(e[
|
|
392
|
-
stagedApply(e[
|
|
388
|
+
if (s !== undefined) {
|
|
389
|
+
if (unwrapValue(e[o]) !== s) e[o] = s;
|
|
390
|
+
stagedApply(e[o], i, n);
|
|
393
391
|
} else {
|
|
394
|
-
const t = unwrapValue(e[
|
|
395
|
-
if (!isEqual(t, i) && !targetsEqual(t, i)) e[
|
|
392
|
+
const t = unwrapValue(e[o]);
|
|
393
|
+
if (!isEqual(t, i) && !targetsEqual(t, i)) e[o] = i;
|
|
396
394
|
}
|
|
397
395
|
}
|
|
398
396
|
} else {
|
|
399
|
-
for (let
|
|
400
|
-
const i = t[
|
|
401
|
-
const
|
|
402
|
-
if (
|
|
403
|
-
if (isWrappable(i) && isWrappable(
|
|
397
|
+
for (let r = 0; r < i; r++) {
|
|
398
|
+
const i = t[r];
|
|
399
|
+
const o = unwrapValue(e[r]);
|
|
400
|
+
if (o === i) continue;
|
|
401
|
+
if (isWrappable(i) && isWrappable(o) && Array.isArray(i) === Array.isArray(o)) stagedApply(e[r], i, n); else if (!isEqual(o, i) && !targetsEqual(o, i)) e[r] = i;
|
|
404
402
|
}
|
|
405
403
|
}
|
|
406
404
|
if (e.length !== i) e.length = i;
|
|
@@ -408,25 +406,25 @@ function createOptimisticStoreNext(e, t, n) {
|
|
|
408
406
|
}
|
|
409
407
|
// Object merge; also the degenerate root-kind-change shape (arrays accept
|
|
410
408
|
// keyed writes/deletes, so a wholesale restatement still lands staged).
|
|
411
|
-
for (const
|
|
412
|
-
if (i &&
|
|
413
|
-
const
|
|
414
|
-
const
|
|
415
|
-
if (
|
|
416
|
-
if (isWrappable(
|
|
409
|
+
for (const r of Reflect.ownKeys(t)) {
|
|
410
|
+
if (i && r === "length") continue;
|
|
411
|
+
const o = t[r];
|
|
412
|
+
const s = unwrapValue(e[r]);
|
|
413
|
+
if (s === o) continue;
|
|
414
|
+
if (isWrappable(o) && isWrappable(s) && Array.isArray(o) === Array.isArray(s)) {
|
|
417
415
|
// Different-keyed entities never merge (tentative-channel parity):
|
|
418
416
|
// the incoming object replaces the slot wholesale.
|
|
419
417
|
if (n !== null) {
|
|
420
|
-
const t = n(
|
|
421
|
-
const i = n(
|
|
418
|
+
const t = n(s);
|
|
419
|
+
const i = n(o);
|
|
422
420
|
if (t !== undefined && i !== undefined && !sameKey(t, i)) {
|
|
423
|
-
e[
|
|
421
|
+
e[r] = o;
|
|
424
422
|
continue;
|
|
425
423
|
}
|
|
426
424
|
}
|
|
427
|
-
stagedApply(e[
|
|
428
|
-
} else if (!isEqual(
|
|
429
|
-
e[
|
|
425
|
+
stagedApply(e[r], o, n);
|
|
426
|
+
} else if (!isEqual(s, o) && !targetsEqual(s, o)) {
|
|
427
|
+
e[r] = o;
|
|
430
428
|
}
|
|
431
429
|
}
|
|
432
430
|
for (const n of Reflect.ownKeys(e)) {
|
|
@@ -454,21 +452,6 @@ function createOptimisticStoreNext(e, t, n) {
|
|
|
454
452
|
if (e !== null) globalQueue.initTransition(e);
|
|
455
453
|
}
|
|
456
454
|
const i = e.v;
|
|
457
|
-
// Patch channel (override-application site): the draft IS the intended
|
|
458
|
-
// visible state; prev is the view before these overrides apply. Bypasses
|
|
459
|
-
// the transition stash — optimism is visible in flight.
|
|
460
|
-
if (e.pc !== null && e.pc.p !== null) patchHooks.emitPatchOptimistic(e, t, optimisticView(e, i));
|
|
461
|
-
// Row-ops channel (family increment 2): optimistic STRUCTURE on an array
|
|
462
|
-
// rides node overrides — it never enters the reconcile walk — so a driven
|
|
463
|
-
// list must get its structural ops here, lane-timed. Identity diff of the
|
|
464
|
-
// pre-write optimistic view against the draft; aligned writes emit nothing.
|
|
465
|
-
if (e.pc !== null && e.pc.ro !== null && Array.isArray(t)) {
|
|
466
|
-
const n = optimisticView(e, i);
|
|
467
|
-
if (Array.isArray(n)) {
|
|
468
|
-
const i = buildIdentityRowOps(n, t);
|
|
469
|
-
if (i !== null) rowHooks.emitRowOpsOptimistic(e, t, i);
|
|
470
|
-
}
|
|
471
|
-
}
|
|
472
455
|
const visible = (t, n) => {
|
|
473
456
|
const i = e.n?.[t];
|
|
474
457
|
return i !== undefined && hasActiveOverride(i) ? unwrapOverride(i.o?.Pe) : n;
|
|
@@ -477,40 +460,40 @@ function createOptimisticStoreNext(e, t, n) {
|
|
|
477
460
|
const n = e.h?.[t];
|
|
478
461
|
return n !== undefined && hasActiveOverride(n) ? !!unwrapOverride(n.o?.Pe) : t in i;
|
|
479
462
|
};
|
|
480
|
-
let
|
|
481
|
-
const
|
|
463
|
+
let r = false;
|
|
464
|
+
const o = Array.isArray(t);
|
|
482
465
|
for (const n of Reflect.ownKeys(t)) {
|
|
483
|
-
if (
|
|
484
|
-
const
|
|
466
|
+
if (o && n === "length") continue;
|
|
467
|
+
const s = unwrapValue(t[n]);
|
|
485
468
|
if (!visiblePresent(n)) {
|
|
486
469
|
// Optimistic add: value node + presence node + membership bump.
|
|
487
|
-
setSignal(getNode(e, n, i[n]), () =>
|
|
470
|
+
setSignal(getNode(e, n, i[n]), () => s);
|
|
488
471
|
setSignal(getHasNode(e, n, n in i), true);
|
|
489
|
-
|
|
472
|
+
r = true;
|
|
490
473
|
} else {
|
|
491
474
|
const t = visible(n, i[n]);
|
|
492
|
-
if (!isEqual(t,
|
|
493
|
-
setSignal(getNode(e, n, t), () =>
|
|
494
|
-
if (
|
|
475
|
+
if (!isEqual(t, s) && !targetsEqual(t, s)) {
|
|
476
|
+
setSignal(getNode(e, n, t), () => s);
|
|
477
|
+
if (o) r = true;
|
|
495
478
|
}
|
|
496
479
|
}
|
|
497
480
|
}
|
|
498
481
|
for (const n of Reflect.ownKeys(i)) {
|
|
499
|
-
if (
|
|
482
|
+
if (o && n === "length") continue;
|
|
500
483
|
if (n in t || !visiblePresent(n)) continue;
|
|
501
484
|
// Optimistic delete: node reads undefined, presence flips, membership bumps.
|
|
502
485
|
setSignal(getNode(e, n, i[n]), () => undefined);
|
|
503
486
|
setSignal(getHasNode(e, n, true), false);
|
|
504
|
-
|
|
487
|
+
r = true;
|
|
505
488
|
}
|
|
506
|
-
if (
|
|
489
|
+
if (o) {
|
|
507
490
|
const n = visible("length", i.length);
|
|
508
491
|
if (n !== t.length) {
|
|
509
492
|
setSignal(getNode(e, "length", n), () => t.length);
|
|
510
|
-
|
|
493
|
+
r = true;
|
|
511
494
|
}
|
|
512
495
|
}
|
|
513
|
-
if (
|
|
496
|
+
if (r) setSignal(getKeySetNode(e), e => e + 1);
|
|
514
497
|
// Deep-witness: optimistic value writes notify deep() subscribers too
|
|
515
498
|
// (structural ones already ride the key-set bump above).
|
|
516
499
|
bumpDeep(e);
|
|
@@ -540,19 +523,19 @@ function createOptimisticStoreNext(e, t, n) {
|
|
|
540
523
|
for (const e of Reflect.ownKeys(i)) {
|
|
541
524
|
const n = i[e];
|
|
542
525
|
if (!hasActiveOverride(n)) continue;
|
|
543
|
-
const
|
|
526
|
+
const r = unwrapOverride(n.o?.Pe);
|
|
544
527
|
if (e === "length" && Array.isArray(t)) {
|
|
545
|
-
if (t.length !==
|
|
546
|
-
} else if (!isEqual(t[e],
|
|
528
|
+
if (t.length !== r) ensure().length = r;
|
|
529
|
+
} else if (!isEqual(t[e], r)) ensure()[e] = r;
|
|
547
530
|
}
|
|
548
531
|
}
|
|
549
|
-
const
|
|
550
|
-
if (
|
|
551
|
-
for (const e of Reflect.ownKeys(
|
|
552
|
-
const i =
|
|
532
|
+
const r = e.h;
|
|
533
|
+
if (r !== null) {
|
|
534
|
+
for (const e of Reflect.ownKeys(r)) {
|
|
535
|
+
const i = r[e];
|
|
553
536
|
if (!hasActiveOverride(i)) continue;
|
|
554
|
-
const
|
|
555
|
-
if (!
|
|
537
|
+
const o = !!unwrapOverride(i.o?.Pe);
|
|
538
|
+
if (!o && e in (n ?? t)) delete ensure()[e];
|
|
556
539
|
}
|
|
557
540
|
}
|
|
558
541
|
return n ?? t;
|
|
@@ -560,35 +543,39 @@ function createOptimisticStoreNext(e, t, n) {
|
|
|
560
543
|
|
|
561
544
|
function applyTentative(e, t, n) {
|
|
562
545
|
const i = e.pb ?? e.v;
|
|
563
|
-
const
|
|
564
|
-
const
|
|
565
|
-
const
|
|
566
|
-
if (Array.isArray(
|
|
546
|
+
const r = optimisticView(e, i);
|
|
547
|
+
const o = e.fam.map;
|
|
548
|
+
const s = Array.isArray(t);
|
|
549
|
+
if (Array.isArray(r) !== s) return;
|
|
567
550
|
// kind change at root: flat overrides below
|
|
568
|
-
const
|
|
569
|
-
|
|
551
|
+
const l = [];
|
|
552
|
+
let u;
|
|
553
|
+
if (s) u = [ ...t ]; else {
|
|
554
|
+
u = {};
|
|
555
|
+
for (const e of Reflect.ownKeys(t)) u[e] = t[e];
|
|
556
|
+
}
|
|
570
557
|
const match = (e, t) => {
|
|
571
558
|
if (!isWrappable(e) || !isWrappable(t)) return null;
|
|
572
559
|
if (rawValuesUsed && (isRawValue(e) || isRawValue(t))) return null;
|
|
573
560
|
if (Array.isArray(e) !== Array.isArray(t)) return null;
|
|
574
561
|
if (n) {
|
|
575
562
|
const i = n(e);
|
|
576
|
-
const
|
|
563
|
+
const r = n(t);
|
|
577
564
|
// SameValueZero (re-audit 3, P1-3): parity with the plain reconcile
|
|
578
565
|
// channel — NaN keys are self-equal.
|
|
579
|
-
if (i !== undefined &&
|
|
566
|
+
if (i !== undefined && r !== undefined && !sameKey(i, r)) return null;
|
|
580
567
|
}
|
|
581
|
-
return
|
|
568
|
+
return o.get(unwrapValue(e)) ?? null;
|
|
582
569
|
};
|
|
583
|
-
if (
|
|
584
|
-
const e =
|
|
570
|
+
if (s) {
|
|
571
|
+
const e = r;
|
|
585
572
|
let i = null;
|
|
586
|
-
for (let
|
|
587
|
-
const
|
|
588
|
-
if (!isWrappable(
|
|
589
|
-
let
|
|
573
|
+
for (let r = 0; r < t.length; r++) {
|
|
574
|
+
const o = t[r];
|
|
575
|
+
if (!isWrappable(o)) continue;
|
|
576
|
+
let s;
|
|
590
577
|
if (n) {
|
|
591
|
-
const t = n(
|
|
578
|
+
const t = n(o);
|
|
592
579
|
if (t !== undefined) {
|
|
593
580
|
if (i === null) {
|
|
594
581
|
// Occurrence-aware index queues (re-audit 3, P1-3): parity with
|
|
@@ -596,40 +583,40 @@ function applyTentative(e, t, n) {
|
|
|
596
583
|
// occurrence, each view row consumed once.
|
|
597
584
|
i = new Map;
|
|
598
585
|
for (let t = 0; t < e.length; t++) {
|
|
599
|
-
const
|
|
600
|
-
if (isWrappable(
|
|
601
|
-
const e = n(
|
|
586
|
+
const r = unwrapValue(e[t]);
|
|
587
|
+
if (isWrappable(r)) {
|
|
588
|
+
const e = n(r);
|
|
602
589
|
if (e === undefined) continue;
|
|
603
|
-
const
|
|
604
|
-
if (
|
|
590
|
+
const o = i.get(e);
|
|
591
|
+
if (o === undefined) i.set(e, t); else if (Array.isArray(o)) o.push(t); else i.set(e, [ o, t ]);
|
|
605
592
|
}
|
|
606
593
|
}
|
|
607
594
|
}
|
|
608
|
-
const
|
|
609
|
-
if (
|
|
610
|
-
|
|
611
|
-
if (
|
|
595
|
+
const r = i.get(t);
|
|
596
|
+
if (r === undefined) s = undefined; else if (Array.isArray(r)) {
|
|
597
|
+
s = unwrapValue(e[r.shift()]);
|
|
598
|
+
if (r.length === 1) i.set(t, r[0]);
|
|
612
599
|
} else {
|
|
613
|
-
|
|
600
|
+
s = unwrapValue(e[r]);
|
|
614
601
|
i.delete(t);
|
|
615
602
|
}
|
|
616
|
-
} else
|
|
617
|
-
} else
|
|
618
|
-
const a = match(
|
|
603
|
+
} else s = unwrapValue(e[r]);
|
|
604
|
+
} else s = unwrapValue(e[r]);
|
|
605
|
+
const a = match(s, o);
|
|
619
606
|
if (a !== null) {
|
|
620
607
|
// Keep the existing row in the slot (identity preserved); recurse.
|
|
621
|
-
u[
|
|
622
|
-
|
|
608
|
+
u[r] = unwrapValue(s);
|
|
609
|
+
l.push([ a, o ]);
|
|
623
610
|
}
|
|
624
611
|
}
|
|
625
612
|
} else {
|
|
626
613
|
for (const e of Reflect.ownKeys(t)) {
|
|
627
|
-
const n = unwrapValue(
|
|
614
|
+
const n = unwrapValue(r[e]);
|
|
628
615
|
const i = t[e];
|
|
629
|
-
const
|
|
630
|
-
if (
|
|
616
|
+
const o = match(n, i);
|
|
617
|
+
if (o !== null) {
|
|
631
618
|
u[e] = n;
|
|
632
|
-
|
|
619
|
+
l.push([ o, i ]);
|
|
633
620
|
}
|
|
634
621
|
}
|
|
635
622
|
}
|
|
@@ -639,13 +626,7 @@ function applyTentative(e, t, n) {
|
|
|
639
626
|
e.pb = null;
|
|
640
627
|
notifyOptimisticWrites(e, u);
|
|
641
628
|
e.pb = a;
|
|
642
|
-
for (let e = 0; e <
|
|
643
|
-
}
|
|
644
|
-
|
|
645
|
-
function shallowWithSymbols(e) {
|
|
646
|
-
const t = {};
|
|
647
|
-
for (const n of Reflect.ownKeys(e)) t[n] = e[n];
|
|
648
|
-
return t;
|
|
629
|
+
for (let e = 0; e < l.length; e++) applyTentative(l[e][0], unwrapValue(l[e][1]), n);
|
|
649
630
|
}
|
|
650
631
|
|
|
651
632
|
export { createOptimisticStoreNext, notifyOptimisticWrites, optimisticView, transitionHoldsOptimism };
|