@solidjs/signals 2.0.0-rc.7 → 2.0.0-rc.8
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-shared.js +5243 -0
- package/dist/dev.attribution.js +2333 -0
- package/dist/dev.js +1229 -6834
- package/dist/observe/affects.js +127 -0
- package/dist/observe/attribution.js +1 -0
- package/dist/observe/boundaries.js +586 -0
- package/dist/observe/core/action.js +167 -0
- package/dist/observe/core/async.js +736 -0
- package/dist/observe/core/attribution-hooks.js +60 -0
- package/dist/observe/core/attribution.js +2318 -0
- package/dist/{types-cjs/core/constants.d.cts → observe/core/constants.js} +129 -73
- package/dist/{types-cjs/core/context.d.cts → observe/core/context.js} +37 -12
- package/dist/observe/core/core.js +1289 -0
- package/dist/observe/core/dev.js +232 -0
- package/dist/observe/core/effect.js +179 -0
- package/dist/observe/core/error.js +80 -0
- package/dist/observe/core/external.js +98 -0
- package/dist/observe/core/graph.js +155 -0
- package/dist/observe/core/heap.js +147 -0
- package/dist/observe/core/invariants.js +43 -0
- package/dist/observe/core/lanes.js +168 -0
- package/dist/observe/core/optimistic.js +438 -0
- package/dist/observe/core/owner.js +308 -0
- package/dist/observe/core/scheduler.js +1190 -0
- package/dist/observe/core/verdict.js +551 -0
- package/dist/observe/index.js +55 -0
- package/dist/observe/map.js +482 -0
- package/dist/{types-cjs/signals.d.cts → observe/signals.js} +295 -317
- package/dist/observe/store/index.js +38 -0
- package/dist/observe/store/next/optimistic.js +651 -0
- package/dist/observe/store/next/projection.js +242 -0
- package/dist/observe/store/next/reconcile.js +373 -0
- package/dist/observe/store/next/store.js +2213 -0
- package/dist/observe/store/next/target.js +51 -0
- package/dist/observe/store/store.js +323 -0
- package/dist/observe/store/storePath.js +103 -0
- package/dist/observe/store/utils.js +210 -0
- package/dist/prod/attribution.js +32 -0
- package/dist/prod/core/action.js +52 -32
- package/dist/prod/core/async.js +171 -127
- package/dist/prod/core/constants.js +24 -1
- package/dist/prod/core/context.js +3 -3
- package/dist/prod/core/core.js +434 -291
- package/dist/prod/core/effect.js +54 -34
- package/dist/prod/core/external.js +2 -2
- package/dist/prod/core/graph.js +32 -32
- package/dist/prod/core/heap.js +49 -44
- package/dist/prod/core/lanes.js +45 -38
- package/dist/prod/core/optimistic.js +207 -73
- package/dist/prod/core/owner.js +43 -39
- package/dist/prod/core/scheduler.js +319 -190
- package/dist/prod/core/verdict.js +67 -67
- package/dist/prod/index.js +9 -3
- package/dist/prod/map.js +292 -141
- package/dist/prod/signals.js +7 -10
- package/dist/prod/store/next/optimistic.js +140 -125
- package/dist/prod/store/next/projection.js +3 -3
- package/dist/prod/store/next/reconcile.js +87 -84
- package/dist/prod/store/next/store.js +524 -280
- package/dist/prod/store/next/target.js +32 -10
- package/dist/prod/store/store.js +12 -14
- package/dist/prod/store/utils.js +36 -27
- package/dist/types/attribution.d.ts +15 -0
- package/dist/types/attribution.prod.d.ts +13 -0
- package/dist/types/core/async.d.ts +1 -1
- package/dist/types/core/attribution-hooks.d.ts +119 -6
- package/dist/types/core/attribution.d.ts +208 -53
- package/dist/types/core/constants.d.ts +23 -0
- package/dist/types/core/core.d.ts +7 -0
- package/dist/types/core/dev.d.ts +124 -26
- package/dist/types/core/effect.d.ts +8 -1
- package/dist/types/core/index.d.ts +2 -1
- package/dist/types/core/lanes.d.ts +8 -1
- package/dist/types/core/scheduler.d.ts +60 -0
- package/dist/types/core/types.d.ts +29 -9
- package/dist/types/index.d.ts +9 -2
- package/dist/types/map.d.ts +2 -0
- package/dist/types/store/index.d.ts +1 -0
- package/dist/types/store/next/store.d.ts +5 -0
- package/dist/types/store/next/target.d.ts +36 -9
- package/dist/types/store/utils.d.ts +7 -0
- package/package.json +21 -17
- package/dist/node.cjs +0 -10541
- package/dist/node.dev.cjs +0 -13724
- package/dist/types-cjs/affects.d.cts +0 -47
- package/dist/types-cjs/boundaries.d.cts +0 -175
- package/dist/types-cjs/core/action.d.cts +0 -64
- package/dist/types-cjs/core/async.d.cts +0 -23
- package/dist/types-cjs/core/attribution-hooks.d.cts +0 -127
- package/dist/types-cjs/core/attribution.d.cts +0 -495
- package/dist/types-cjs/core/core.d.cts +0 -185
- package/dist/types-cjs/core/dev.d.cts +0 -136
- package/dist/types-cjs/core/effect.d.cts +0 -30
- package/dist/types-cjs/core/error.d.cts +0 -56
- package/dist/types-cjs/core/external.d.cts +0 -15
- package/dist/types-cjs/core/graph.d.cts +0 -28
- package/dist/types-cjs/core/heap.d.cts +0 -24
- package/dist/types-cjs/core/index.d.cts +0 -13
- package/dist/types-cjs/core/invariants.d.cts +0 -59
- package/dist/types-cjs/core/lanes.d.cts +0 -54
- package/dist/types-cjs/core/optimistic.d.cts +0 -6
- package/dist/types-cjs/core/owner.d.cts +0 -124
- package/dist/types-cjs/core/scheduler.d.cts +0 -236
- package/dist/types-cjs/core/types.d.cts +0 -204
- package/dist/types-cjs/core/verdict.d.cts +0 -2
- package/dist/types-cjs/index.d.cts +0 -10
- package/dist/types-cjs/map.d.cts +0 -69
- package/dist/types-cjs/package.json +0 -3
- package/dist/types-cjs/store/index.d.cts +0 -18
- package/dist/types-cjs/store/next/optimistic.d.cts +0 -25
- package/dist/types-cjs/store/next/projection.d.cts +0 -8
- package/dist/types-cjs/store/next/reconcile.d.cts +0 -10
- package/dist/types-cjs/store/next/store.d.cts +0 -121
- package/dist/types-cjs/store/next/target.d.cts +0 -166
- package/dist/types-cjs/store/store.d.cts +0 -143
- package/dist/types-cjs/store/storePath.d.cts +0 -58
- package/dist/types-cjs/store/utils.d.cts +0 -74
|
@@ -18,11 +18,11 @@ import { $TARGET, markRawIngest, setNextOptimisticViewResolver, isWrappable, raw
|
|
|
18
18
|
|
|
19
19
|
import { runProjectionComputedNext } from "./projection.js";
|
|
20
20
|
|
|
21
|
-
import { wrapNext, runAuthoritative, storeSetterNext, hasActiveOverride, unwrapValue, targetsEqual, getNode, getHasNode, getKeySetNode, bumpDeep, stagedTruthPB, authoritativeRead } from "./store.js";
|
|
21
|
+
import { wrapNext, runAuthoritative, storeSetterNext, hasActiveOverride, unwrapValue, targetsEqual, heldMaskView, getNode, getHasNode, getKeySetNode, bumpDeep, stagedTruthPB, authoritativeRead } from "./store.js";
|
|
22
22
|
|
|
23
23
|
import { sameKey } from "./reconcile.js";
|
|
24
24
|
|
|
25
|
-
import { setOptHooks } from "./target.js";
|
|
25
|
+
import { setOptHooks, $OWNER, lookupTarget } from "./target.js";
|
|
26
26
|
|
|
27
27
|
/**
|
|
28
28
|
* Store rewrite — optimistic stores (§3/§7, RUL-3): no store-side layer, no
|
|
@@ -55,7 +55,7 @@ import { setOptHooks } from "./target.js";
|
|
|
55
55
|
* staged values to converge (normal speculation). Resolves merges first:
|
|
56
56
|
* merge unions optimistic nodes/stores into the target. */ function transitionHoldsOptimism(e) {
|
|
57
57
|
const t = currentTransition(e);
|
|
58
|
-
return t.
|
|
58
|
+
return t.ft !== true && (t.it.length !== 0 || t.En.size !== 0);
|
|
59
59
|
}
|
|
60
60
|
|
|
61
61
|
let blockedInstalled = false;
|
|
@@ -76,8 +76,8 @@ function installNextBlockedHalf() {
|
|
|
76
76
|
// Scheduler flush tails call _clearOptimisticStores whenever tracked
|
|
77
77
|
// stores exist; next has no layer to clear — reverts are engine-native —
|
|
78
78
|
// so the hook only empties the batch set.
|
|
79
|
-
if (!GlobalQueue.
|
|
80
|
-
GlobalQueue.
|
|
79
|
+
if (!GlobalQueue.ni) {
|
|
80
|
+
GlobalQueue.ni = e => {
|
|
81
81
|
for (const t of e) {
|
|
82
82
|
const e = t?.[$TARGET];
|
|
83
83
|
const n = e?.fam?.overlaid;
|
|
@@ -96,24 +96,24 @@ function installNextBlockedHalf() {
|
|
|
96
96
|
e.clear();
|
|
97
97
|
};
|
|
98
98
|
}
|
|
99
|
-
const e = GlobalQueue.
|
|
100
|
-
GlobalQueue.
|
|
99
|
+
const e = GlobalQueue.cn;
|
|
100
|
+
GlobalQueue.cn = t => {
|
|
101
101
|
for (const e of t.En) {
|
|
102
102
|
const n = e?.[$TARGET];
|
|
103
103
|
const i = n?.fam;
|
|
104
|
-
const
|
|
104
|
+
const o = i?.node;
|
|
105
105
|
// The hold exists to keep optimistic state alive until the store's own
|
|
106
106
|
// truth lands (#2951). Once the family carries NO live overrides (a
|
|
107
107
|
// landing consumed them, or they never existed), a pending firewall is
|
|
108
108
|
// no reason to park the transaction — blocking then leaks it forever
|
|
109
109
|
// when the in-flight question is never answered (undisposed fixtures).
|
|
110
|
-
if (
|
|
110
|
+
if (o == null || !(o.S & STATUS_PENDING)) continue;
|
|
111
111
|
// Ownership is declared (#3146): only the flight's OWN transaction
|
|
112
112
|
// parks on the flight (the #2951 anchor routed the bare write there).
|
|
113
113
|
// A transaction that merely brushed the store never waits for truth
|
|
114
114
|
// it does not carry.
|
|
115
|
-
const
|
|
116
|
-
if (
|
|
115
|
+
const r = i.ft != null ? liveTransition(i.ft) : null;
|
|
116
|
+
if (r !== null && r !== currentTransition(t)) continue;
|
|
117
117
|
if (familyHasLiveOverrides(i)) return true;
|
|
118
118
|
}
|
|
119
119
|
return e(t);
|
|
@@ -128,10 +128,10 @@ function familyHasLiveOverrides(e) {
|
|
|
128
128
|
if (t === null) continue;
|
|
129
129
|
for (const e of Reflect.ownKeys(t)) {
|
|
130
130
|
const n = t[e];
|
|
131
|
-
if (n.o?.
|
|
131
|
+
if (n.o?.be !== undefined && n.o?.be !== NOT_PENDING) return true;
|
|
132
132
|
}
|
|
133
133
|
}
|
|
134
|
-
if (e.k !== null && e.k.o?.
|
|
134
|
+
if (e.k !== null && e.k.o?.be !== undefined && e.k.o?.be !== NOT_PENDING) return true;
|
|
135
135
|
}
|
|
136
136
|
t.clear();
|
|
137
137
|
// nothing live — drop the bookkeeping
|
|
@@ -144,23 +144,23 @@ function createOptimisticStoreNext(e, t, n) {
|
|
|
144
144
|
installOptimisticEngine();
|
|
145
145
|
installNextBlockedHalf();
|
|
146
146
|
const i = typeof e === "function";
|
|
147
|
-
const
|
|
148
|
-
const
|
|
147
|
+
const o = i ? n : t;
|
|
148
|
+
const r = i ? t : e;
|
|
149
149
|
const s = {
|
|
150
150
|
map: new WeakMap,
|
|
151
151
|
node: null,
|
|
152
|
-
shallow: !!
|
|
152
|
+
shallow: !!o?.shallow,
|
|
153
153
|
opt: true
|
|
154
154
|
};
|
|
155
|
-
const l = wrapNext(
|
|
155
|
+
const l = wrapNext(r, null, null, s);
|
|
156
156
|
s.px = l;
|
|
157
157
|
// Same key resolution the projection channels use ("id" default) — replay's
|
|
158
158
|
// satisfaction rule reads it off the family.
|
|
159
|
-
const u =
|
|
159
|
+
const u = o?.key === undefined ? "id" : o.key;
|
|
160
160
|
s.key = typeof u === "function" ? u : u === null ? null : e => isWrappable(e) ? e[u] : undefined;
|
|
161
161
|
if (s.shallow) {
|
|
162
162
|
l[$TARGET].s = true;
|
|
163
|
-
markRawIngest(
|
|
163
|
+
markRawIngest(r);
|
|
164
164
|
}
|
|
165
165
|
if (i) {
|
|
166
166
|
const t = e;
|
|
@@ -178,7 +178,7 @@ function createOptimisticStoreNext(e, t, n) {
|
|
|
178
178
|
if (e == null) return;
|
|
179
179
|
let t = liveTransition(e);
|
|
180
180
|
if (t === null) s.ft = t = createTransition();
|
|
181
|
-
s.node.
|
|
181
|
+
s.node.ge = t;
|
|
182
182
|
globalQueue.initTransition(t);
|
|
183
183
|
};
|
|
184
184
|
// Landing router (#3164 fold ruling): while a transaction retains
|
|
@@ -223,8 +223,8 @@ function createOptimisticStoreNext(e, t, n) {
|
|
|
223
223
|
// (#2933: the loading rail is transaction-invisible); a sync run clears
|
|
224
224
|
// the declaration.
|
|
225
225
|
const declareFlight = e => {
|
|
226
|
-
if (e.o?.
|
|
227
|
-
if (!e.
|
|
226
|
+
if (e.o?.Pe == null) {
|
|
227
|
+
if (!e.Ae) s.ft = null;
|
|
228
228
|
return;
|
|
229
229
|
}
|
|
230
230
|
// First flight (#3146 carve-out): nothing has ever committed, so there
|
|
@@ -236,23 +236,23 @@ function createOptimisticStoreNext(e, t, n) {
|
|
|
236
236
|
// fallback never showed and the whole page stayed blank. The loading
|
|
237
237
|
// window (#2933) already declares nothing for the same reason; once
|
|
238
238
|
// the first truth lands, every refetch flight declares as before.
|
|
239
|
-
if (e.
|
|
239
|
+
if (e.Ae || e.S & STATUS_UNINITIALIZED) return;
|
|
240
240
|
let t = activeTransition;
|
|
241
241
|
if (t === null) globalQueue.initTransition(t = createTransition());
|
|
242
242
|
s.ft = t;
|
|
243
|
-
e.
|
|
244
|
-
let n = t.
|
|
245
|
-
if (n === undefined) t.
|
|
243
|
+
e.ge = t;
|
|
244
|
+
let n = t.Re.get(e);
|
|
245
|
+
if (n === undefined) t.Re.set(e, n = new Set);
|
|
246
246
|
n.add(e);
|
|
247
247
|
};
|
|
248
248
|
let n;
|
|
249
|
-
if (
|
|
249
|
+
if (o?.seedLoadingValue) n = {
|
|
250
250
|
loadingValue: undefined
|
|
251
251
|
};
|
|
252
252
|
const i = computed(() => {
|
|
253
253
|
const e = getOwner();
|
|
254
254
|
try {
|
|
255
|
-
runAuthoritative(() => runProjectionComputedNext(l, t,
|
|
255
|
+
runAuthoritative(() => runProjectionComputedNext(l, t, o?.key === undefined ? "id" : o.key, wrapCommit, aroundDraftWrite));
|
|
256
256
|
} finally {
|
|
257
257
|
declareFlight(e);
|
|
258
258
|
}
|
|
@@ -274,8 +274,8 @@ function createOptimisticStoreNext(e, t, n) {
|
|
|
274
274
|
|
|
275
275
|
/** Resolve a retained transition through its merge chain (`_done` holds the
|
|
276
276
|
* merge target while merged, `true` once settled). Null = dead. */ function liveTransition(e) {
|
|
277
|
-
while (typeof e.
|
|
278
|
-
return e.
|
|
277
|
+
while (typeof e.ft === "object") e = e.ft;
|
|
278
|
+
return e.ft === true ? null : e;
|
|
279
279
|
}
|
|
280
280
|
|
|
281
281
|
/** The transaction truth landings fold into: the first live member of the
|
|
@@ -320,10 +320,10 @@ function createOptimisticStoreNext(e, t, n) {
|
|
|
320
320
|
* stay unarmed — the override is their display and its revert their
|
|
321
321
|
* notification, A17). */ function runFolded(e, t) {
|
|
322
322
|
runAsTransitionBatch(e, t);
|
|
323
|
-
const n = e
|
|
323
|
+
const n = e.$t;
|
|
324
324
|
for (let t = 0; t < n.length; t++) {
|
|
325
325
|
const i = n[t];
|
|
326
|
-
i.
|
|
326
|
+
i.ge = e;
|
|
327
327
|
if (i.T & CONFIG_OPTIMISTIC && !hasActiveOverride(i)) i.T |= CONFIG_HELD_TRUTH;
|
|
328
328
|
}
|
|
329
329
|
}
|
|
@@ -340,15 +340,15 @@ function createOptimisticStoreNext(e, t, n) {
|
|
|
340
340
|
if (n !== null) {
|
|
341
341
|
// Occurrence-aware key queues (parity with the adoption window):
|
|
342
342
|
// duplicate keys match per occurrence, each current row consumed once.
|
|
343
|
-
let
|
|
344
|
-
const
|
|
345
|
-
for (let t = 0; t <
|
|
343
|
+
let o = null;
|
|
344
|
+
const r = e.length;
|
|
345
|
+
for (let t = 0; t < r; t++) {
|
|
346
346
|
const i = unwrapValue(e[t]);
|
|
347
347
|
if (!isWrappable(i)) continue;
|
|
348
|
-
const
|
|
349
|
-
if (
|
|
350
|
-
const s = (
|
|
351
|
-
if (s === undefined)
|
|
348
|
+
const r = n(i);
|
|
349
|
+
if (r === undefined) continue;
|
|
350
|
+
const s = (o ??= new Map).get(r);
|
|
351
|
+
if (s === undefined) o.set(r, [ i ]); else s.push(i);
|
|
352
352
|
}
|
|
353
353
|
// Echo adoption: an optimistic structural add whose key the landing
|
|
354
354
|
// confirms must keep its raw (and so its proxy — list drivers keep the
|
|
@@ -363,42 +363,42 @@ function createOptimisticStoreNext(e, t, n) {
|
|
|
363
363
|
for (const e of Reflect.ownKeys(s)) {
|
|
364
364
|
const t = s[e];
|
|
365
365
|
if (!hasActiveOverride(t)) continue;
|
|
366
|
-
const i = unwrapValue(unwrapOverride(t.o.
|
|
366
|
+
const i = unwrapValue(unwrapOverride(t.o.be));
|
|
367
367
|
if (!isWrappable(i)) continue;
|
|
368
|
-
const
|
|
369
|
-
if (
|
|
370
|
-
const l = (
|
|
371
|
-
if (l === undefined)
|
|
368
|
+
const r = n(i);
|
|
369
|
+
if (r === undefined) continue;
|
|
370
|
+
const l = (o ??= new Map).get(r);
|
|
371
|
+
if (l === undefined) o.set(r, [ i ]); else l.push(i);
|
|
372
372
|
}
|
|
373
373
|
}
|
|
374
|
-
for (let
|
|
375
|
-
const i = t[
|
|
374
|
+
for (let r = 0; r < i; r++) {
|
|
375
|
+
const i = t[r];
|
|
376
376
|
let s;
|
|
377
|
-
if (isWrappable(i) &&
|
|
377
|
+
if (isWrappable(i) && o !== null) {
|
|
378
378
|
const e = n(i);
|
|
379
379
|
if (e !== undefined) {
|
|
380
|
-
for (const [t, n] of
|
|
380
|
+
for (const [t, n] of o) {
|
|
381
381
|
if (!sameKey(t, e)) continue;
|
|
382
382
|
s = n.shift();
|
|
383
|
-
if (n.length === 0)
|
|
383
|
+
if (n.length === 0) o.delete(t);
|
|
384
384
|
break;
|
|
385
385
|
}
|
|
386
386
|
}
|
|
387
387
|
}
|
|
388
388
|
if (s !== undefined) {
|
|
389
|
-
if (unwrapValue(e[
|
|
390
|
-
stagedApply(e[
|
|
389
|
+
if (unwrapValue(e[r]) !== s) e[r] = s;
|
|
390
|
+
stagedApply(e[r], i, n);
|
|
391
391
|
} else {
|
|
392
|
-
const t = unwrapValue(e[
|
|
393
|
-
if (!isEqual(t, i) && !targetsEqual(t, i)) e[
|
|
392
|
+
const t = unwrapValue(e[r]);
|
|
393
|
+
if (!isEqual(t, i) && !targetsEqual(t, i)) e[r] = i;
|
|
394
394
|
}
|
|
395
395
|
}
|
|
396
396
|
} else {
|
|
397
|
-
for (let
|
|
398
|
-
const i = t[
|
|
399
|
-
const
|
|
400
|
-
if (
|
|
401
|
-
if (isWrappable(i) && isWrappable(
|
|
397
|
+
for (let o = 0; o < i; o++) {
|
|
398
|
+
const i = t[o];
|
|
399
|
+
const r = unwrapValue(e[o]);
|
|
400
|
+
if (r === i) continue;
|
|
401
|
+
if (isWrappable(i) && isWrappable(r) && Array.isArray(i) === Array.isArray(r)) stagedApply(e[o], i, n); else if (!isEqual(r, i) && !targetsEqual(r, i)) e[o] = i;
|
|
402
402
|
}
|
|
403
403
|
}
|
|
404
404
|
if (e.length !== i) e.length = i;
|
|
@@ -406,29 +406,29 @@ function createOptimisticStoreNext(e, t, n) {
|
|
|
406
406
|
}
|
|
407
407
|
// Object merge; also the degenerate root-kind-change shape (arrays accept
|
|
408
408
|
// keyed writes/deletes, so a wholesale restatement still lands staged).
|
|
409
|
-
for (const
|
|
410
|
-
if (i &&
|
|
411
|
-
const
|
|
412
|
-
const s = unwrapValue(e[
|
|
413
|
-
if (s ===
|
|
414
|
-
if (isWrappable(
|
|
409
|
+
for (const o of Reflect.ownKeys(t)) {
|
|
410
|
+
if (i && o === "length" || o === $OWNER) continue;
|
|
411
|
+
const r = t[o];
|
|
412
|
+
const s = unwrapValue(e[o]);
|
|
413
|
+
if (s === r) continue;
|
|
414
|
+
if (isWrappable(r) && isWrappable(s) && Array.isArray(r) === Array.isArray(s)) {
|
|
415
415
|
// Different-keyed entities never merge (tentative-channel parity):
|
|
416
416
|
// the incoming object replaces the slot wholesale.
|
|
417
417
|
if (n !== null) {
|
|
418
418
|
const t = n(s);
|
|
419
|
-
const i = n(
|
|
419
|
+
const i = n(r);
|
|
420
420
|
if (t !== undefined && i !== undefined && !sameKey(t, i)) {
|
|
421
|
-
e[
|
|
421
|
+
e[o] = r;
|
|
422
422
|
continue;
|
|
423
423
|
}
|
|
424
424
|
}
|
|
425
|
-
stagedApply(e[
|
|
426
|
-
} else if (!isEqual(s,
|
|
427
|
-
e[
|
|
425
|
+
stagedApply(e[o], r, n);
|
|
426
|
+
} else if (!isEqual(s, r) && !targetsEqual(s, r)) {
|
|
427
|
+
e[o] = r;
|
|
428
428
|
}
|
|
429
429
|
}
|
|
430
430
|
for (const n of Reflect.ownKeys(e)) {
|
|
431
|
-
if (i && n === "length" || n in t) continue;
|
|
431
|
+
if (i && n === "length" || n === $OWNER || n in t) continue;
|
|
432
432
|
delete e[n];
|
|
433
433
|
}
|
|
434
434
|
}
|
|
@@ -451,49 +451,63 @@ function createOptimisticStoreNext(e, t, n) {
|
|
|
451
451
|
const e = liveTransition(n);
|
|
452
452
|
if (e !== null) globalQueue.initTransition(e);
|
|
453
453
|
}
|
|
454
|
-
|
|
455
|
-
|
|
454
|
+
// The write is judged against what ordinary readers SEE, not against the
|
|
455
|
+
// committed backing slot: under an adoption hold (#3074) `t.v` is already
|
|
456
|
+
// the truth a live transaction is holding, and an optimistic write equal
|
|
457
|
+
// to it compared as a no-op — no override, no lane, and the screen kept
|
|
458
|
+
// the pre-hold value until the transaction committed (#3330's store
|
|
459
|
+
// twin: `s.v = 1` after a `yield` while the derive had already staged
|
|
460
|
+
// `v: 1`). Signal parity: the override reveals on its lane now, with its
|
|
461
|
+
// derivations; the held truth reveals on the transaction's schedule.
|
|
462
|
+
const i = heldMaskView(e) ?? e.v;
|
|
463
|
+
// Compare RAWS on both sides (`nv` below is unwrapped already). A chained
|
|
464
|
+
// target's `old` is the inner store's proxy, whose reads hand back inner
|
|
465
|
+
// child PROXIES; the draft's clone holds the inner raws. Comparing the two
|
|
466
|
+
// as-is marked every untouched row changed, and the overlay then served
|
|
467
|
+
// each from an override as a fresh non-chained target — row identities
|
|
468
|
+
// churned for the life of the action and snapped back at settle (#3323).
|
|
469
|
+
const visible = (t, n) => {
|
|
456
470
|
const i = e.n?.[t];
|
|
457
|
-
return i !== undefined && hasActiveOverride(i) ? unwrapOverride(i.o?.
|
|
471
|
+
return unwrapValue(i !== undefined && hasActiveOverride(i) ? unwrapOverride(i.o?.be) : n);
|
|
458
472
|
};
|
|
459
473
|
const visiblePresent = t => {
|
|
460
474
|
const n = e.h?.[t];
|
|
461
|
-
return n !== undefined && hasActiveOverride(n) ? !!unwrapOverride(n.o?.
|
|
475
|
+
return n !== undefined && hasActiveOverride(n) ? !!unwrapOverride(n.o?.be) : t in i;
|
|
462
476
|
};
|
|
463
|
-
let
|
|
464
|
-
const
|
|
477
|
+
let o = false;
|
|
478
|
+
const r = Array.isArray(t);
|
|
465
479
|
for (const n of Reflect.ownKeys(t)) {
|
|
466
|
-
if (
|
|
480
|
+
if (r && n === "length" || n === $OWNER) continue;
|
|
467
481
|
const s = unwrapValue(t[n]);
|
|
468
482
|
if (!visiblePresent(n)) {
|
|
469
483
|
// Optimistic add: value node + presence node + membership bump.
|
|
470
484
|
setSignal(getNode(e, n, i[n]), () => s);
|
|
471
485
|
setSignal(getHasNode(e, n, n in i), true);
|
|
472
|
-
|
|
486
|
+
o = true;
|
|
473
487
|
} else {
|
|
474
488
|
const t = visible(n, i[n]);
|
|
475
489
|
if (!isEqual(t, s) && !targetsEqual(t, s)) {
|
|
476
490
|
setSignal(getNode(e, n, t), () => s);
|
|
477
|
-
if (
|
|
491
|
+
if (r) o = true;
|
|
478
492
|
}
|
|
479
493
|
}
|
|
480
494
|
}
|
|
481
495
|
for (const n of Reflect.ownKeys(i)) {
|
|
482
|
-
if (
|
|
496
|
+
if (r && n === "length" || n === $OWNER) continue;
|
|
483
497
|
if (n in t || !visiblePresent(n)) continue;
|
|
484
498
|
// Optimistic delete: node reads undefined, presence flips, membership bumps.
|
|
485
499
|
setSignal(getNode(e, n, i[n]), () => undefined);
|
|
486
500
|
setSignal(getHasNode(e, n, true), false);
|
|
487
|
-
|
|
501
|
+
o = true;
|
|
488
502
|
}
|
|
489
|
-
if (
|
|
503
|
+
if (r) {
|
|
490
504
|
const n = visible("length", i.length);
|
|
491
505
|
if (n !== t.length) {
|
|
492
506
|
setSignal(getNode(e, "length", n), () => t.length);
|
|
493
|
-
|
|
507
|
+
o = true;
|
|
494
508
|
}
|
|
495
509
|
}
|
|
496
|
-
if (
|
|
510
|
+
if (o) setSignal(getKeySetNode(e), e => e + 1);
|
|
497
511
|
// Deep-witness: optimistic value writes notify deep() subscribers too
|
|
498
512
|
// (structural ones already ride the key-set bump above).
|
|
499
513
|
bumpDeep(e);
|
|
@@ -504,7 +518,7 @@ function createOptimisticStoreNext(e, t, n) {
|
|
|
504
518
|
e.pb = stagedTruthPB.get(e) ?? null;
|
|
505
519
|
if (e.pb !== null) stagedTruthPB.delete(e);
|
|
506
520
|
(e.fam.overlaid ??= new Set).add(e);
|
|
507
|
-
GlobalQueue.
|
|
521
|
+
GlobalQueue.Nn?.(e.fam.px ?? e.px);
|
|
508
522
|
}
|
|
509
523
|
|
|
510
524
|
/** Optimistic-view composition for snapshot/deep (O1: snapshot is the CURRENT
|
|
@@ -523,19 +537,19 @@ function createOptimisticStoreNext(e, t, n) {
|
|
|
523
537
|
for (const e of Reflect.ownKeys(i)) {
|
|
524
538
|
const n = i[e];
|
|
525
539
|
if (!hasActiveOverride(n)) continue;
|
|
526
|
-
const
|
|
540
|
+
const o = unwrapOverride(n.o?.be);
|
|
527
541
|
if (e === "length" && Array.isArray(t)) {
|
|
528
|
-
if (t.length !==
|
|
529
|
-
} else if (!isEqual(t[e],
|
|
542
|
+
if (t.length !== o) ensure().length = o;
|
|
543
|
+
} else if (!isEqual(t[e], o)) ensure()[e] = o;
|
|
530
544
|
}
|
|
531
545
|
}
|
|
532
|
-
const
|
|
533
|
-
if (
|
|
534
|
-
for (const e of Reflect.ownKeys(
|
|
535
|
-
const i =
|
|
546
|
+
const o = e.h;
|
|
547
|
+
if (o !== null) {
|
|
548
|
+
for (const e of Reflect.ownKeys(o)) {
|
|
549
|
+
const i = o[e];
|
|
536
550
|
if (!hasActiveOverride(i)) continue;
|
|
537
|
-
const
|
|
538
|
-
if (!
|
|
551
|
+
const r = !!unwrapOverride(i.o?.be);
|
|
552
|
+
if (!r && e in (n ?? t)) delete ensure()[e];
|
|
539
553
|
}
|
|
540
554
|
}
|
|
541
555
|
return n ?? t;
|
|
@@ -543,16 +557,16 @@ function createOptimisticStoreNext(e, t, n) {
|
|
|
543
557
|
|
|
544
558
|
function applyTentative(e, t, n) {
|
|
545
559
|
const i = e.pb ?? e.v;
|
|
546
|
-
const
|
|
547
|
-
const
|
|
560
|
+
const o = optimisticView(e, i);
|
|
561
|
+
const r = e.fam;
|
|
548
562
|
const s = Array.isArray(t);
|
|
549
|
-
if (Array.isArray(
|
|
563
|
+
if (Array.isArray(o) !== s) return;
|
|
550
564
|
// kind change at root: flat overrides below
|
|
551
565
|
const l = [];
|
|
552
566
|
let u;
|
|
553
567
|
if (s) u = [ ...t ]; else {
|
|
554
568
|
u = {};
|
|
555
|
-
for (const e of Reflect.ownKeys(t)) u[e] = t[e];
|
|
569
|
+
for (const e of Reflect.ownKeys(t)) if (e !== $OWNER) u[e] = t[e];
|
|
556
570
|
}
|
|
557
571
|
const match = (e, t) => {
|
|
558
572
|
if (!isWrappable(e) || !isWrappable(t)) return null;
|
|
@@ -560,22 +574,22 @@ function applyTentative(e, t, n) {
|
|
|
560
574
|
if (Array.isArray(e) !== Array.isArray(t)) return null;
|
|
561
575
|
if (n) {
|
|
562
576
|
const i = n(e);
|
|
563
|
-
const
|
|
577
|
+
const o = n(t);
|
|
564
578
|
// SameValueZero (re-audit 3, P1-3): parity with the plain reconcile
|
|
565
579
|
// channel — NaN keys are self-equal.
|
|
566
|
-
if (i !== undefined &&
|
|
580
|
+
if (i !== undefined && o !== undefined && !sameKey(i, o)) return null;
|
|
567
581
|
}
|
|
568
|
-
return
|
|
582
|
+
return lookupTarget(unwrapValue(e), r) ?? null;
|
|
569
583
|
};
|
|
570
584
|
if (s) {
|
|
571
|
-
const e =
|
|
585
|
+
const e = o;
|
|
572
586
|
let i = null;
|
|
573
|
-
for (let
|
|
574
|
-
const
|
|
575
|
-
if (!isWrappable(
|
|
587
|
+
for (let o = 0; o < t.length; o++) {
|
|
588
|
+
const r = t[o];
|
|
589
|
+
if (!isWrappable(r)) continue;
|
|
576
590
|
let s;
|
|
577
591
|
if (n) {
|
|
578
|
-
const t = n(
|
|
592
|
+
const t = n(r);
|
|
579
593
|
if (t !== undefined) {
|
|
580
594
|
if (i === null) {
|
|
581
595
|
// Occurrence-aware index queues (re-audit 3, P1-3): parity with
|
|
@@ -583,40 +597,41 @@ function applyTentative(e, t, n) {
|
|
|
583
597
|
// occurrence, each view row consumed once.
|
|
584
598
|
i = new Map;
|
|
585
599
|
for (let t = 0; t < e.length; t++) {
|
|
586
|
-
const
|
|
587
|
-
if (isWrappable(
|
|
588
|
-
const e = n(
|
|
600
|
+
const o = unwrapValue(e[t]);
|
|
601
|
+
if (isWrappable(o)) {
|
|
602
|
+
const e = n(o);
|
|
589
603
|
if (e === undefined) continue;
|
|
590
|
-
const
|
|
591
|
-
if (
|
|
604
|
+
const r = i.get(e);
|
|
605
|
+
if (r === undefined) i.set(e, t); else if (Array.isArray(r)) r.push(t); else i.set(e, [ r, t ]);
|
|
592
606
|
}
|
|
593
607
|
}
|
|
594
608
|
}
|
|
595
|
-
const
|
|
596
|
-
if (
|
|
597
|
-
s = unwrapValue(e[
|
|
598
|
-
if (
|
|
609
|
+
const o = i.get(t);
|
|
610
|
+
if (o === undefined) s = undefined; else if (Array.isArray(o)) {
|
|
611
|
+
s = unwrapValue(e[o.shift()]);
|
|
612
|
+
if (o.length === 1) i.set(t, o[0]);
|
|
599
613
|
} else {
|
|
600
|
-
s = unwrapValue(e[
|
|
614
|
+
s = unwrapValue(e[o]);
|
|
601
615
|
i.delete(t);
|
|
602
616
|
}
|
|
603
|
-
} else s = unwrapValue(e[
|
|
604
|
-
} else s = unwrapValue(e[
|
|
605
|
-
const a = match(s,
|
|
617
|
+
} else s = unwrapValue(e[o]);
|
|
618
|
+
} else s = unwrapValue(e[o]);
|
|
619
|
+
const a = match(s, r);
|
|
606
620
|
if (a !== null) {
|
|
607
621
|
// Keep the existing row in the slot (identity preserved); recurse.
|
|
608
|
-
u[
|
|
609
|
-
l.push([ a,
|
|
622
|
+
u[o] = unwrapValue(s);
|
|
623
|
+
l.push([ a, r ]);
|
|
610
624
|
}
|
|
611
625
|
}
|
|
612
626
|
} else {
|
|
613
627
|
for (const e of Reflect.ownKeys(t)) {
|
|
614
|
-
|
|
628
|
+
if (e === $OWNER) continue;
|
|
629
|
+
const n = unwrapValue(o[e]);
|
|
615
630
|
const i = t[e];
|
|
616
|
-
const
|
|
617
|
-
if (
|
|
631
|
+
const r = match(n, i);
|
|
632
|
+
if (r !== null) {
|
|
618
633
|
u[e] = n;
|
|
619
|
-
l.push([
|
|
634
|
+
l.push([ r, i ]);
|
|
620
635
|
}
|
|
621
636
|
}
|
|
622
637
|
}
|
|
@@ -215,8 +215,8 @@ function runProjectionComputedNext(e, t, r, i, o) {
|
|
|
215
215
|
// for the whole first flight — the derive works a detached shadow of the
|
|
216
216
|
// seed so draft writes cannot tear through to readers (#2988). Every commit
|
|
217
217
|
// point reconciles the shadow through the normal commit path.
|
|
218
|
-
const u = n.
|
|
219
|
-
const l = wrapDraft(e, () => !c || n.o?.
|
|
218
|
+
const u = n.Ae ? JSON.parse(JSON.stringify(e[$TARGET][STORE_VALUE])) : null;
|
|
219
|
+
const l = wrapDraft(e, () => !c || n.o?.Pe === s, o);
|
|
220
220
|
storeSetterNext(l, o => {
|
|
221
221
|
s = t(u ?? o);
|
|
222
222
|
c = true;
|
|
@@ -230,7 +230,7 @@ function runProjectionComputedNext(e, t, r, i, o) {
|
|
|
230
230
|
i ? i(write, t) : write();
|
|
231
231
|
};
|
|
232
232
|
const l = handleAsync(n, s, commit);
|
|
233
|
-
if (!n.
|
|
233
|
+
if (!n.Ae) commit(l);
|
|
234
234
|
}, false);
|
|
235
235
|
return n;
|
|
236
236
|
}
|