@solidjs/signals 2.0.0-rc.15 → 2.0.0-rc.17
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 +2268 -1734
- package/dist/dev.attribution.js +75 -52
- package/dist/dev.js +1348 -658
- package/dist/observe/affects-marks.js +86 -0
- package/dist/observe/affects.js +22 -73
- package/dist/observe/boundaries.js +192 -190
- package/dist/observe/core/async.js +177 -131
- package/dist/observe/core/attribution-queries.js +1 -1
- package/dist/observe/core/attribution.js +176 -159
- package/dist/observe/core/constants.js +17 -3
- package/dist/observe/core/context.js +5 -3
- package/dist/observe/core/core.js +520 -364
- package/dist/observe/core/dev.js +66 -38
- package/dist/observe/core/effect.js +50 -48
- package/dist/observe/core/error.js +5 -3
- package/dist/observe/core/external.js +5 -6
- package/dist/observe/core/graph.js +60 -44
- package/dist/observe/core/heap.js +33 -33
- package/dist/observe/core/identities.js +62 -0
- package/dist/observe/core/lanes.js +238 -260
- package/dist/observe/core/owner.js +117 -79
- package/dist/observe/core/scheduler.js +381 -217
- package/dist/observe/core/truth.js +45 -0
- package/dist/observe/core/verdict.js +91 -50
- package/dist/observe/deferred.js +184 -0
- package/dist/observe/index.js +7 -1
- package/dist/observe/map.js +345 -260
- package/dist/observe/reveal.js +76 -76
- package/dist/observe/signals.js +47 -31
- package/dist/observe/store/affects.js +18 -18
- package/dist/observe/store/edges.js +39 -0
- package/dist/observe/store/optimistic.js +146 -100
- package/dist/observe/store/projection.js +68 -55
- package/dist/observe/store/store.js +180 -118
- package/dist/prod/affects-marks.js +86 -0
- package/dist/prod/affects.js +23 -72
- package/dist/prod/boundaries.js +156 -154
- package/dist/prod/core/async.js +173 -127
- package/dist/prod/core/constants.js +17 -3
- package/dist/prod/core/context.js +5 -3
- package/dist/prod/core/core.js +495 -343
- package/dist/prod/core/effect.js +70 -68
- package/dist/prod/core/error.js +5 -3
- package/dist/prod/core/external.js +5 -6
- package/dist/prod/core/graph.js +60 -44
- package/dist/prod/core/heap.js +38 -38
- package/dist/prod/core/identities.js +62 -0
- package/dist/prod/core/lanes.js +230 -252
- package/dist/prod/core/owner.js +114 -77
- package/dist/prod/core/scheduler.js +327 -163
- package/dist/prod/core/truth.js +45 -0
- package/dist/prod/core/verdict.js +90 -49
- package/dist/prod/deferred.js +182 -0
- package/dist/prod/index.js +7 -1
- package/dist/prod/map.js +360 -275
- package/dist/prod/reveal.js +76 -76
- package/dist/prod/signals.js +42 -26
- package/dist/prod/store/affects.js +6 -6
- package/dist/prod/store/edges.js +39 -0
- package/dist/prod/store/optimistic.js +143 -98
- package/dist/prod/store/projection.js +25 -19
- package/dist/prod/store/store.js +157 -100
- package/dist/types/affects-marks.d.ts +14 -0
- package/dist/types/boundaries.d.ts +1 -1
- package/dist/types/core/async.d.ts +10 -0
- package/dist/types/core/constants.d.ts +13 -1
- package/dist/types/core/core.d.ts +54 -5
- package/dist/types/core/dev.d.ts +51 -13
- package/dist/types/core/error.d.ts +9 -1
- package/dist/types/core/graph.d.ts +11 -0
- package/dist/types/core/identities.d.ts +17 -0
- package/dist/types/core/index.d.ts +2 -1
- package/dist/types/core/lanes.d.ts +2 -14
- package/dist/types/core/owner.d.ts +9 -3
- package/dist/types/core/scheduler.d.ts +70 -32
- package/dist/types/core/truth.d.ts +16 -0
- package/dist/types/core/types.d.ts +21 -0
- package/dist/types/core/verdict.d.ts +32 -0
- package/dist/types/deferred.d.ts +28 -0
- package/dist/types/index.d.ts +6 -0
- package/dist/types/map.d.ts +2 -2
- package/dist/types/signals.d.ts +28 -7
- package/dist/types/store/edges.d.ts +9 -0
- package/dist/types/store/index.d.ts +10 -3
- package/dist/types/store/optimistic.d.ts +3 -2
- package/dist/types/store/projection.d.ts +4 -3
- package/dist/types/store/store.d.ts +1 -1
- package/dist/types/store/target.d.ts +16 -8
- package/dist/types/store/types.d.ts +14 -0
- package/package.json +1 -1
|
@@ -1,12 +1,12 @@
|
|
|
1
|
-
import { CONFIG_OVERRIDE,
|
|
1
|
+
import { CONFIG_OVERRIDE, CONFIG_GUESS, EFFECT_RENDER, CONFIG_CHILDREN_FORBIDDEN, NOT_PENDING, CONFIG_SLOT_NODE, CONFIG_AUTO_DISPOSE } from "../core/constants.js";
|
|
2
2
|
|
|
3
|
-
import { computed, ext, untrack, read, isEqual } from "../core/core.js";
|
|
3
|
+
import { computed, joinPassAt, ext, untrack, read, isEqual } from "../core/core.js";
|
|
4
4
|
|
|
5
|
-
import { pendingGuessOf,
|
|
5
|
+
import { pendingGuessOf, optimisticWrite } from "../core/lanes.js";
|
|
6
6
|
|
|
7
7
|
import { getOwner } from "../core/owner.js";
|
|
8
8
|
|
|
9
|
-
import { GlobalQueue, txOf,
|
|
9
|
+
import { GlobalQueue, txOf, insertSubs, joinFuture, resolveTx, passLane, list, laneDirty, notifyEpoch, schedule } from "../core/scheduler.js";
|
|
10
10
|
|
|
11
11
|
import { runProjectionComputed } from "./projection.js";
|
|
12
12
|
|
|
@@ -18,6 +18,8 @@ import { $OWNER } from "./target.js";
|
|
|
18
18
|
|
|
19
19
|
import { $TARGET, markRawIngest, $TRACK, isWrappable } from "./types.js";
|
|
20
20
|
|
|
21
|
+
import { laneValueOf } from "../core/truth.js";
|
|
22
|
+
|
|
21
23
|
/**
|
|
22
24
|
* Store — optimistic stores on lanes (plan sec. 31, S4; INTERNALS §3/§7, RUL-3).
|
|
23
25
|
*
|
|
@@ -81,7 +83,7 @@ function notifyOptimisticWrites(e, n) {
|
|
|
81
83
|
// inner store's truth for its key before guessing over it.
|
|
82
84
|
const o = e.ch ? e.v : null;
|
|
83
85
|
const guess = (e, n, i, r) => {
|
|
84
|
-
if (o !== null) e.
|
|
86
|
+
if (o !== null) e.Ie = i ? n in t : unwrapValue(t[n]);
|
|
85
87
|
// By value: a function leaf is a value, not an updater (#3017).
|
|
86
88
|
optimisticWrite(e, () => r);
|
|
87
89
|
};
|
|
@@ -91,16 +93,16 @@ function notifyOptimisticWrites(e, n) {
|
|
|
91
93
|
// A chained draft holds the inner store's raws; a raw is the inner slot it
|
|
92
94
|
// resolves to (as a read of it serves) — the row a held write staged is
|
|
93
95
|
// the same row, not a guess over the slot (#3796).
|
|
94
|
-
const
|
|
95
|
-
const f = unwrapValue(o &&
|
|
96
|
+
const u = n[t];
|
|
97
|
+
const f = unwrapValue(o && u ? resolveChainedRaw(e, t, u) : u);
|
|
96
98
|
if (!(t in i)) {
|
|
97
99
|
guess(getNode(e, t), t, false, f);
|
|
98
100
|
guess(getHasNode(e, t), t, true, true);
|
|
99
101
|
s = true;
|
|
100
102
|
} else {
|
|
101
103
|
const n = i[t];
|
|
102
|
-
const
|
|
103
|
-
if (!isEqual(
|
|
104
|
+
const u = unwrapValue(o && n ? resolveChainedRaw(e, t, n) : n);
|
|
105
|
+
if (!isEqual(u, f) && !targetsEqual(u, f)) {
|
|
104
106
|
guess(getNode(e, t), t, false, f);
|
|
105
107
|
if (r) s = true;
|
|
106
108
|
}
|
|
@@ -120,29 +122,31 @@ function notifyOptimisticWrites(e, n) {
|
|
|
120
122
|
if (s) {
|
|
121
123
|
const o = r ? n.map(unwrapValue) : shallowKeys(n);
|
|
122
124
|
// The rows the setter removed from the view it saw, by key: a later
|
|
123
|
-
// re-base over another action's truth must not bring them back.
|
|
125
|
+
// re-base over another action's truth must not bring them back. A set
|
|
126
|
+
// (empty or not) marks a keyed arrangement guess (`fold`).
|
|
124
127
|
let s = null;
|
|
125
|
-
const
|
|
126
|
-
if (r &&
|
|
128
|
+
const u = e.fam.key;
|
|
129
|
+
if (r && u !== null && u !== undefined) {
|
|
130
|
+
s = new Set;
|
|
127
131
|
const e = new Set;
|
|
128
132
|
for (let n = 0; n < o.length; n++) {
|
|
129
|
-
const t = isWrappable(o[n]) ?
|
|
133
|
+
const t = isWrappable(o[n]) ? u(o[n]) : undefined;
|
|
130
134
|
if (t !== undefined) e.add(t);
|
|
131
135
|
}
|
|
132
136
|
for (let n = 0; n < i.length; n++) {
|
|
133
137
|
const t = unwrapValue(i[n]);
|
|
134
|
-
const r = isWrappable(t) ?
|
|
135
|
-
if (r !== undefined && !e.has(r))
|
|
138
|
+
const r = isWrappable(t) ? u(t) : undefined;
|
|
139
|
+
if (r !== undefined && !e.has(r)) s.add(r);
|
|
136
140
|
}
|
|
137
141
|
}
|
|
138
142
|
optimisticWrite(getContainerNode(e), new LaneView(o, t, s));
|
|
139
143
|
}
|
|
140
144
|
if (e.dk !== null) optimisticWrite(e.dk, {});
|
|
141
145
|
markOverlaid(e);
|
|
142
|
-
const
|
|
143
|
-
if (
|
|
146
|
+
const u = optStaged.get(e);
|
|
147
|
+
if (u === undefined) return null;
|
|
144
148
|
optStaged.delete(e);
|
|
145
|
-
return
|
|
149
|
+
return u;
|
|
146
150
|
}
|
|
147
151
|
|
|
148
152
|
/** The container comparator's lane arm (store.ts `containerEquals`): an
|
|
@@ -185,7 +189,7 @@ function rowSame(e, n, t) {
|
|
|
185
189
|
|
|
186
190
|
// A cycle (a row that references itself) is not plain data: no match, so
|
|
187
191
|
// the landing stays a correction.
|
|
188
|
-
GlobalQueue.
|
|
192
|
+
GlobalQueue.nn = (e, n) => {
|
|
189
193
|
try {
|
|
190
194
|
return echoes(e, n);
|
|
191
195
|
} catch {
|
|
@@ -226,18 +230,18 @@ function arrangementEqual(e, n, t) {
|
|
|
226
230
|
}
|
|
227
231
|
}
|
|
228
232
|
for (let s = 0; s < n.length; s++) {
|
|
229
|
-
const
|
|
233
|
+
const u = n[s];
|
|
230
234
|
let f;
|
|
231
|
-
if (isWrappable(
|
|
235
|
+
if (isWrappable(u)) {
|
|
232
236
|
if (o !== null) {
|
|
233
|
-
const e = t(
|
|
237
|
+
const e = t(u);
|
|
234
238
|
if (e !== undefined) f = o.get(e);
|
|
235
239
|
} else if (s < i && isWrappable(unwrapValue(r[s]))) f = r[s];
|
|
236
240
|
}
|
|
237
241
|
if (f !== undefined) {
|
|
238
|
-
if (unwrapValue(f) !==
|
|
242
|
+
if (unwrapValue(f) !== u) reconcileDraft(f, u, t);
|
|
239
243
|
if (e[s] !== f) e[s] = f;
|
|
240
|
-
} else if (unwrapValue(e[s]) !==
|
|
244
|
+
} else if (unwrapValue(e[s]) !== u) e[s] = u;
|
|
241
245
|
}
|
|
242
246
|
if (e.length !== n.length) e.length = n.length;
|
|
243
247
|
return;
|
|
@@ -266,66 +270,105 @@ function arrangementEqual(e, n, t) {
|
|
|
266
270
|
* node is born for it as the lane's derivation), on `length` only when the
|
|
267
271
|
* committed length differs, and as the `LaneView`'s base for structural
|
|
268
272
|
* reads. Unkeyed families compose
|
|
269
|
-
* positionally — the guess stands as written (the documented residue). */ GlobalQueue.an = (e, n) => {
|
|
270
|
-
|
|
271
|
-
|
|
272
|
-
|
|
273
|
-
|
|
274
|
-
if (!
|
|
275
|
-
|
|
273
|
+
* positionally — the guess stands as written (the documented residue). */ GlobalQueue.an = (e, n, t) => {
|
|
274
|
+
if (!t) return fold(e, n);
|
|
275
|
+
const i = e.O;
|
|
276
|
+
if (i === undefined || e.ze !== $TRACK) return;
|
|
277
|
+
const r = e.T.v;
|
|
278
|
+
if (!(r instanceof LaneView)) return;
|
|
279
|
+
if (!Array.isArray(n) || !Array.isArray(r.rows)) {
|
|
280
|
+
r.base = n;
|
|
276
281
|
return;
|
|
277
282
|
}
|
|
278
|
-
const
|
|
279
|
-
if (
|
|
280
|
-
const
|
|
283
|
+
const o = i.fam?.key ?? null;
|
|
284
|
+
if (o === null) return;
|
|
285
|
+
const s = new Map;
|
|
281
286
|
for (let e = 0; e < n.length; e++) {
|
|
282
287
|
const t = n[e];
|
|
283
|
-
const i = isWrappable(t) ?
|
|
284
|
-
if (i !== undefined && !
|
|
288
|
+
const i = isWrappable(t) ? o(t) : undefined;
|
|
289
|
+
if (i !== undefined && !s.has(i)) s.set(i, t);
|
|
285
290
|
}
|
|
286
|
-
const
|
|
287
|
-
const
|
|
288
|
-
const
|
|
289
|
-
for (let e = 0; e <
|
|
290
|
-
const n =
|
|
291
|
-
const t = isWrappable(n) ?
|
|
292
|
-
const i = t !== undefined ?
|
|
291
|
+
const u = new Set;
|
|
292
|
+
const f = [];
|
|
293
|
+
const a = r.rows;
|
|
294
|
+
for (let e = 0; e < a.length; e++) {
|
|
295
|
+
const n = a[e];
|
|
296
|
+
const t = isWrappable(n) ? o(n) : undefined;
|
|
297
|
+
const i = t !== undefined ? s.get(t) : undefined;
|
|
293
298
|
if (i !== undefined) {
|
|
294
|
-
|
|
295
|
-
|
|
296
|
-
} else
|
|
299
|
+
f.push(i);
|
|
300
|
+
u.add(t);
|
|
301
|
+
} else f.push(n);
|
|
297
302
|
}
|
|
298
|
-
const
|
|
303
|
+
const l = r.removed;
|
|
299
304
|
for (let e = 0; e < n.length; e++) {
|
|
300
305
|
const t = n[e];
|
|
301
|
-
const i = isWrappable(t) ?
|
|
302
|
-
if (i !== undefined && !
|
|
306
|
+
const i = isWrappable(t) ? o(t) : undefined;
|
|
307
|
+
if (i !== undefined && !u.has(i) && (l === null || !l.has(i))) f.push(t);
|
|
303
308
|
}
|
|
304
|
-
|
|
305
|
-
|
|
306
|
-
const
|
|
307
|
-
const
|
|
308
|
-
const
|
|
309
|
-
for (let e = 0; e <
|
|
310
|
-
const n =
|
|
309
|
+
r.rows = f;
|
|
310
|
+
r.base = f;
|
|
311
|
+
const c = txOf(e);
|
|
312
|
+
const d = committed(i);
|
|
313
|
+
const p = i.n;
|
|
314
|
+
for (let e = 0; e < f.length; e++) {
|
|
315
|
+
const n = p?.[e];
|
|
311
316
|
// A slot the lane does not own shows the committed row: it becomes the
|
|
312
317
|
// lane's only where the composed row is another row (by key — the same
|
|
313
318
|
// key's new object is the same row, its target adopted it).
|
|
314
319
|
if (n === undefined) {
|
|
315
|
-
if (!sameRow(
|
|
316
|
-
} else if (!sameRow(n.
|
|
320
|
+
if (!sameRow(d[e], f[e], o)) laneSet(getNode(i, e), f[e], c);
|
|
321
|
+
} else if (!sameRow(n.l & CONFIG_OVERRIDE ? n.T.v : d[e], f[e], o)) laneSet(n, f[e], c);
|
|
317
322
|
}
|
|
318
|
-
if (
|
|
319
|
-
for (let e =
|
|
320
|
-
const n =
|
|
323
|
+
if (p !== null) {
|
|
324
|
+
for (let e = f.length; ;e++) {
|
|
325
|
+
const n = p[e];
|
|
321
326
|
if (n === undefined) break;
|
|
322
|
-
laneSet(n, undefined,
|
|
327
|
+
laneSet(n, undefined, c);
|
|
323
328
|
}
|
|
324
|
-
const e =
|
|
325
|
-
if (e !== undefined && (e.
|
|
329
|
+
const e = p.length;
|
|
330
|
+
if (e !== undefined && (e.l & CONFIG_OVERRIDE || d.length !== f.length)) laneSet(e, f.length, c);
|
|
326
331
|
}
|
|
327
332
|
};
|
|
328
333
|
|
|
334
|
+
/** D-34 for a keyed arrangement guess: rows by key, not positions. A
|
|
335
|
+
* current truth that differs folds into the hold beneath it instead of
|
|
336
|
+
* voiding the lane: the guess stays the lane's value and the screen's until
|
|
337
|
+
* the hold commits, where rows match by key, and the graph outside the lane
|
|
338
|
+
* re-derives from the truth now (`foldedRead`). A confirmation is silent
|
|
339
|
+
* (A17): only truth readers are told. True: the lane stages the truth
|
|
340
|
+
* beneath (`laneWrite`). */ function fold(e, n) {
|
|
341
|
+
const t = e.O?.k;
|
|
342
|
+
const i = txOf(e);
|
|
343
|
+
// A guess the screen never showed is void at the correction (D-34); a
|
|
344
|
+
// keyed arrangement guess's view carries its removed-keys set.
|
|
345
|
+
if (!i.ke || !(t?.l & CONFIG_OVERRIDE) || !t.T.v?.removed) return false;
|
|
346
|
+
const r = e.T.v;
|
|
347
|
+
if ((!e.xe || !e.xe(r, n)) && !GlobalQueue.nn(r, n)) {
|
|
348
|
+
i.folded = foldedRead;
|
|
349
|
+
insertSubs(e);
|
|
350
|
+
} else GlobalQueue.sn?.(i);
|
|
351
|
+
joinFuture(resolveTx(i._parent ?? i));
|
|
352
|
+
return true;
|
|
353
|
+
}
|
|
354
|
+
|
|
355
|
+
/** A folded lane's guess read by a deriving pass outside the lane, tracked
|
|
356
|
+
* or not (`untrack` is about dependencies, not about which world a pass
|
|
357
|
+
* derives from), or by `latest()` (`c` null): the hold's world — the truth
|
|
358
|
+
* staged beneath the guess, else the value it covered — and the pass joins
|
|
359
|
+
* the hold. Lane passes and the screen keep the guess: held truth is masked
|
|
360
|
+
* from lane passes only (#3164). The store's own derive reconciles its
|
|
361
|
+
* landings against the arrangement the guesses made: it is the author, not
|
|
362
|
+
* a reader. */ function foldedRead(e, n) {
|
|
363
|
+
if (e !== null) {
|
|
364
|
+
if (!(n.l & CONFIG_GUESS) || passLane !== null || e.i === EFFECT_RENDER || e.l & CONFIG_CHILDREN_FORBIDDEN || n.O?.fam?.node === e) return NOT_PENDING;
|
|
365
|
+
const t = txOf(n);
|
|
366
|
+
joinPassAt(e, resolveTx(t._parent ?? t));
|
|
367
|
+
}
|
|
368
|
+
if (n.se !== NOT_PENDING) return n.se;
|
|
369
|
+
return n.l & CONFIG_SLOT_NODE ? GlobalQueue.fn(n) : n.Ie;
|
|
370
|
+
}
|
|
371
|
+
|
|
329
372
|
function sameRow(e, n, t) {
|
|
330
373
|
if (e === n) return true;
|
|
331
374
|
if (!isWrappable(e) || !isWrappable(n)) return false;
|
|
@@ -337,12 +380,12 @@ function sameRow(e, n, t) {
|
|
|
337
380
|
* node that was not the lane's becomes its derivation (its committed value
|
|
338
381
|
* untouched beneath; the lane's end commits the latest). */ function laneSet(e, n, t) {
|
|
339
382
|
const i = ext(e);
|
|
340
|
-
if (!(e.
|
|
341
|
-
e.
|
|
383
|
+
if (!(e.l & CONFIG_OVERRIDE)) {
|
|
384
|
+
e.l |= CONFIG_OVERRIDE;
|
|
342
385
|
list(e, t);
|
|
343
|
-
} else if (i.
|
|
344
|
-
i.
|
|
345
|
-
if (e.
|
|
386
|
+
} else if (i.v === n) return;
|
|
387
|
+
i.v = n;
|
|
388
|
+
if (e.o !== null) {
|
|
346
389
|
insertSubs(e);
|
|
347
390
|
laneDirty(e, t);
|
|
348
391
|
}
|
|
@@ -387,7 +430,7 @@ function sweepOverlaid() {
|
|
|
387
430
|
// The container shows its backing again (a shown arrangement guess
|
|
388
431
|
// that ended without a landing left its `LaneView` as the value).
|
|
389
432
|
const t = e.k;
|
|
390
|
-
if (t !== null && t.
|
|
433
|
+
if (t !== null && t.Ie instanceof LaneView) t.Ie = t.Ie.base;
|
|
391
434
|
}
|
|
392
435
|
if (n.size === 0) overlaidFamilies.delete(e);
|
|
393
436
|
}
|
|
@@ -404,11 +447,11 @@ function sweepOverlaid() {
|
|
|
404
447
|
if (i !== null) for (const e of Reflect.ownKeys(i)) {
|
|
405
448
|
const r = i[e];
|
|
406
449
|
const o = untrack(() => unwrapValue(n[e]));
|
|
407
|
-
if (r.
|
|
408
|
-
r.
|
|
450
|
+
if (r.xe && r.xe(r.Ie, o)) continue;
|
|
451
|
+
r.Ie = o;
|
|
409
452
|
// (The lane's end notified it this epoch when the shown value and the
|
|
410
453
|
// covered one differed — its readers re-derive already.)
|
|
411
|
-
if (r.
|
|
454
|
+
if (r.o !== null && r.Me !== notifyEpoch) {
|
|
412
455
|
insertSubs(r);
|
|
413
456
|
t = true;
|
|
414
457
|
}
|
|
@@ -417,9 +460,9 @@ function sweepOverlaid() {
|
|
|
417
460
|
if (r !== null) for (const e of Reflect.ownKeys(r)) {
|
|
418
461
|
const i = r[e];
|
|
419
462
|
const o = untrack(() => e in n);
|
|
420
|
-
if (i.
|
|
421
|
-
i.
|
|
422
|
-
if (i.
|
|
463
|
+
if (i.Ie === o) continue;
|
|
464
|
+
i.Ie = o;
|
|
465
|
+
if (i.o !== null && i.Me !== notifyEpoch) {
|
|
423
466
|
insertSubs(i);
|
|
424
467
|
t = true;
|
|
425
468
|
}
|
|
@@ -427,9 +470,9 @@ function sweepOverlaid() {
|
|
|
427
470
|
// The arrangement the readers saw (the shown guess) against the inner's
|
|
428
471
|
// now: a structural reader re-derives when they differ.
|
|
429
472
|
const o = e.k;
|
|
430
|
-
if (o !== null && o.
|
|
473
|
+
if (o !== null && o.o !== null && o.Ie instanceof LaneView && o.Me !== notifyEpoch) {
|
|
431
474
|
const i = Array.isArray(n) ? untrack(() => n.map(unwrapValue)) : n;
|
|
432
|
-
if (!arrangementEqual(o.
|
|
475
|
+
if (!arrangementEqual(o.Ie.rows, i, e.fam?.key ?? null)) {
|
|
433
476
|
insertSubs(o);
|
|
434
477
|
t = true;
|
|
435
478
|
}
|
|
@@ -438,12 +481,12 @@ function sweepOverlaid() {
|
|
|
438
481
|
}
|
|
439
482
|
|
|
440
483
|
function carriesLane(e) {
|
|
441
|
-
if (e.k !== null && e.k.
|
|
442
|
-
if (e.dk !== null && e.dk.
|
|
484
|
+
if (e.k !== null && e.k.l & CONFIG_OVERRIDE) return true;
|
|
485
|
+
if (e.dk !== null && e.dk.l & CONFIG_OVERRIDE) return true;
|
|
443
486
|
const n = e.n;
|
|
444
|
-
if (n !== null) for (const e of Reflect.ownKeys(n)) if (n[e].
|
|
487
|
+
if (n !== null) for (const e of Reflect.ownKeys(n)) if (n[e].l & CONFIG_OVERRIDE) return true;
|
|
445
488
|
const t = e.h;
|
|
446
|
-
if (t !== null) for (const e of Reflect.ownKeys(t)) if (t[e].
|
|
489
|
+
if (t !== null) for (const e of Reflect.ownKeys(t)) if (t[e].l & CONFIG_OVERRIDE) return true;
|
|
447
490
|
return false;
|
|
448
491
|
}
|
|
449
492
|
|
|
@@ -461,9 +504,9 @@ function overlaid(e) {
|
|
|
461
504
|
* the backing answers. */ function optimisticHas(e, n) {
|
|
462
505
|
if (!overlaid(e)) return undefined;
|
|
463
506
|
const t = e.h?.[n];
|
|
464
|
-
if (t !== undefined && t.
|
|
507
|
+
if (t !== undefined && t.l & CONFIG_OVERRIDE) return !!shown(t);
|
|
465
508
|
const i = e.n?.[n];
|
|
466
|
-
if (i !== undefined && i.
|
|
509
|
+
if (i !== undefined && i.l & CONFIG_OVERRIDE) return shown(i) !== undefined;
|
|
467
510
|
return undefined;
|
|
468
511
|
}
|
|
469
512
|
|
|
@@ -474,7 +517,7 @@ function overlaid(e) {
|
|
|
474
517
|
if (t === undefined) return undefined;
|
|
475
518
|
if (!t) return null;
|
|
476
519
|
const i = e.n?.[n];
|
|
477
|
-
const r = i !== undefined && i.
|
|
520
|
+
const r = i !== undefined && i.l & CONFIG_OVERRIDE ? shown(i) : e.v[n];
|
|
478
521
|
// An array's `length` is reported as the array has it (non-configurable).
|
|
479
522
|
if (n === "length" && Array.isArray(e.v)) return {
|
|
480
523
|
value: r,
|
|
@@ -507,7 +550,7 @@ i = false) {
|
|
|
507
550
|
for (const e of Reflect.ownKeys(o)) {
|
|
508
551
|
const r = o[e];
|
|
509
552
|
let s;
|
|
510
|
-
if (r.
|
|
553
|
+
if (r.l & CONFIG_OVERRIDE) s = t(r); else if (!i || (s = pendingGuessOf(r)) === NOT_PENDING) continue;
|
|
511
554
|
if (e === "length" && Array.isArray(n)) {
|
|
512
555
|
if (n.length !== s) ensure().length = s;
|
|
513
556
|
} else if (!isEqual(n[e], s) || !hasOwn.call(n, e)) {
|
|
@@ -519,11 +562,11 @@ i = false) {
|
|
|
519
562
|
if (s !== null) {
|
|
520
563
|
for (const e of Reflect.ownKeys(s)) {
|
|
521
564
|
const o = s[e];
|
|
522
|
-
let
|
|
523
|
-
if (o.
|
|
524
|
-
const f = !!
|
|
525
|
-
const
|
|
526
|
-
if (!f && e in
|
|
565
|
+
let u;
|
|
566
|
+
if (o.l & CONFIG_OVERRIDE) u = t(o); else if (!i || (u = pendingGuessOf(o)) === NOT_PENDING) continue;
|
|
567
|
+
const f = !!u;
|
|
568
|
+
const a = r ?? n;
|
|
569
|
+
if (!f && e in a) delete ensure()[e];
|
|
527
570
|
}
|
|
528
571
|
}
|
|
529
572
|
return r ?? n;
|
|
@@ -532,9 +575,11 @@ i = false) {
|
|
|
532
575
|
function createOptimisticStore(e, n, t) {
|
|
533
576
|
const i = typeof e === "function";
|
|
534
577
|
const r = i ? t : n;
|
|
535
|
-
|
|
578
|
+
// Seedless derived form: the root starts as an empty record (see
|
|
579
|
+
// createProjectionInternal).
|
|
580
|
+
const o = i ? n || {} : e;
|
|
536
581
|
const s = r?.key === undefined ? "id" : r.key;
|
|
537
|
-
const
|
|
582
|
+
const u = {
|
|
538
583
|
map: new WeakMap,
|
|
539
584
|
node: null,
|
|
540
585
|
live: new Set,
|
|
@@ -542,8 +587,8 @@ function createOptimisticStore(e, n, t) {
|
|
|
542
587
|
opt: true,
|
|
543
588
|
key: typeof s === "function" ? s : s === null ? null : e => isWrappable(e) ? e[s] : undefined
|
|
544
589
|
};
|
|
545
|
-
const f = wrap(o, null, null,
|
|
546
|
-
if (
|
|
590
|
+
const f = wrap(o, null, null, u);
|
|
591
|
+
if (u.shallow) {
|
|
547
592
|
f[$TARGET].s = true;
|
|
548
593
|
markRawIngest(o);
|
|
549
594
|
}
|
|
@@ -554,11 +599,11 @@ function createOptimisticStore(e, n, t) {
|
|
|
554
599
|
loadingValue: undefined
|
|
555
600
|
};
|
|
556
601
|
const i = computed(() => {
|
|
557
|
-
if (!
|
|
602
|
+
if (!u.node) u.node = getOwner();
|
|
558
603
|
runProjectionComputed(f, n, s);
|
|
559
604
|
}, t);
|
|
560
|
-
i.
|
|
561
|
-
|
|
605
|
+
i.l &= ~CONFIG_AUTO_DISPOSE;
|
|
606
|
+
u.node = i;
|
|
562
607
|
}
|
|
563
608
|
return [ f, e => storeSetter(f, e) ];
|
|
564
609
|
}
|
|
@@ -10,7 +10,7 @@ import { enqueueSub } from "../core/heap.js";
|
|
|
10
10
|
|
|
11
11
|
import { getOwner, isDisposed } from "../core/owner.js";
|
|
12
12
|
|
|
13
|
-
import { question, setQuestion, schedule } from "../core/scheduler.js";
|
|
13
|
+
import { question, setQuestion, insertSubs, schedule } from "../core/scheduler.js";
|
|
14
14
|
|
|
15
15
|
import { reconcileState } from "./reconcile.js";
|
|
16
16
|
|
|
@@ -18,7 +18,7 @@ import { wrap, storeSetter, runDirect } from "./store.js";
|
|
|
18
18
|
|
|
19
19
|
import { setLookup } from "./target.js";
|
|
20
20
|
|
|
21
|
-
import { $TARGET, markRawIngest,
|
|
21
|
+
import { $TARGET, markRawIngest, isWrappable, setWriteOverride } from "./types.js";
|
|
22
22
|
|
|
23
23
|
/**
|
|
24
24
|
* Store — projections (plan sec. 31, S3; INTERNALS §7/§7b).
|
|
@@ -122,7 +122,7 @@ function cloneState(e, t) {
|
|
|
122
122
|
const r = e.node;
|
|
123
123
|
e.woke = true;
|
|
124
124
|
forEachFamilyNode(e, e => {
|
|
125
|
-
if (e.
|
|
125
|
+
if (e.o === null) return;
|
|
126
126
|
// The leaf carries the derive's pending as a propagated copy, as a memo
|
|
127
127
|
// between them would: a dependent recovering one branch stays pending
|
|
128
128
|
// through a leaf it still reads (core `retryReaches`), and the landing's
|
|
@@ -139,7 +139,7 @@ function cloneState(e, t) {
|
|
|
139
139
|
/** The derive's flight rejected: every live reader of the family
|
|
140
140
|
* re-derives (its pull throws the derive's error). */ function errorFamily(e) {
|
|
141
141
|
forEachFamilyNode(e, e => {
|
|
142
|
-
if (e.
|
|
142
|
+
if (e.o === null) return;
|
|
143
143
|
forEachDependent(e, e => {
|
|
144
144
|
enqueueSub(e);
|
|
145
145
|
});
|
|
@@ -154,7 +154,7 @@ function cloneState(e, t) {
|
|
|
154
154
|
e.woke = false;
|
|
155
155
|
const t = e.node;
|
|
156
156
|
forEachFamilyNode(e, e => {
|
|
157
|
-
if (e.
|
|
157
|
+
if (e.o !== null) settlePendingSource(e, t);
|
|
158
158
|
});
|
|
159
159
|
}
|
|
160
160
|
|
|
@@ -183,16 +183,16 @@ function forEachFamilyNode(e, t) {
|
|
|
183
183
|
// for the whole first flight — the derive works a detached shadow of the
|
|
184
184
|
// seed so draft writes cannot tear through to readers (#2988). Every
|
|
185
185
|
// commit point reconciles the shadow through the normal commit path.
|
|
186
|
-
const a = i.
|
|
186
|
+
const a = i.ce ? cloneState(s.v, s.s) : null;
|
|
187
187
|
// The question a write of this run answers: inside a slice, the slice's
|
|
188
188
|
// (the sync pass); in a continuation — the flight still registered — the
|
|
189
189
|
// flight's (`handleAsync` stamped it with the action that asked).
|
|
190
|
-
const asking = () => question || (i.
|
|
190
|
+
const asking = () => question || (i.T !== null && i.T.Se !== null ? i.T.Ee : 0);
|
|
191
191
|
const f = wrapDraft(e, () => c.run === u && !isDisposed(i), o, s.s,
|
|
192
192
|
// A write after the run returned (a continuation, a callback) arms the
|
|
193
193
|
// drain itself when no landing will.
|
|
194
194
|
() => {
|
|
195
|
-
if (!(i.
|
|
195
|
+
if (!(i.m & STATUS_PENDING) && !i.ce) schedule();
|
|
196
196
|
}, asking);
|
|
197
197
|
// The creation run commits directly (a memo's first value is its
|
|
198
198
|
// `_value`); every later run — a re-derive in a flush, an async landing
|
|
@@ -219,7 +219,12 @@ function forEachFamilyNode(e, t) {
|
|
|
219
219
|
}
|
|
220
220
|
// A landing (not the sync pass's own commit): the readers held
|
|
221
221
|
// pending on the derive settle.
|
|
222
|
-
if (!d || !(i.
|
|
222
|
+
if (!d || !(i.m & STATUS_UNINITIALIZED)) settleFamily(c);
|
|
223
|
+
// A commit is the derive's change for the readers that observed its
|
|
224
|
+
// flight (linked by `pullFamily`; a settled pull does not link), as
|
|
225
|
+
// a memo's landing is for its readers: one that caught the NotReady
|
|
226
|
+
// (a fallback value, not pending) re-runs too (#4070).
|
|
227
|
+
insertSubs(i);
|
|
223
228
|
};
|
|
224
229
|
const u = handleAsync(i, l, commit, (e, t) => {
|
|
225
230
|
// The flight rejected: the leaves' readers learn it from here —
|
|
@@ -228,10 +233,10 @@ function forEachFamilyNode(e, t) {
|
|
|
228
233
|
// reader re-derives and meets the error at its pull (memo parity,
|
|
229
234
|
// #2897) — and the flush that runs them advances the clock, so a
|
|
230
235
|
// later tracked re-read may retry (core `read`).
|
|
231
|
-
if (d && i.
|
|
236
|
+
if (d && i.m & STATUS_UNINITIALIZED) return;
|
|
232
237
|
if (t) wakeFamily(c, e); else errorFamily(c);
|
|
233
238
|
});
|
|
234
|
-
if (!i.
|
|
239
|
+
if (!i.ce) commit(u);
|
|
235
240
|
}, false);
|
|
236
241
|
try {
|
|
237
242
|
d ? runDirect(pass) : pass();
|
|
@@ -248,11 +253,14 @@ function forEachFamilyNode(e, t) {
|
|
|
248
253
|
// the wake, as for the throw. Not a sync pass that superseded one — the
|
|
249
254
|
// status it reads is the dead flight's, cleared when this pass settles
|
|
250
255
|
// (#3181: a reader the settle walk had just released, re-parked for good).
|
|
251
|
-
if (i.
|
|
256
|
+
if (i.m & STATUS_PENDING && i.T.Se !== null && !i.ce && !d) wakeFamily(c, i.T?.F);
|
|
252
257
|
return i;
|
|
253
258
|
}
|
|
254
259
|
|
|
255
260
|
function createProjectionInternal(e, t, r) {
|
|
261
|
+
// Seedless (`fn` takes no draft): the root starts as an empty record. It is
|
|
262
|
+
// a draft like any seed, never observable before the first landing (A25).
|
|
263
|
+
t ||= {};
|
|
256
264
|
const n = r?.key === undefined ? "id" : r.key;
|
|
257
265
|
const o = {
|
|
258
266
|
map: new WeakMap,
|
|
@@ -276,20 +284,18 @@ function createProjectionInternal(e, t, r) {
|
|
|
276
284
|
if (!o.node) o.node = getOwner();
|
|
277
285
|
runProjectionComputed(i, e, n);
|
|
278
286
|
}, s);
|
|
279
|
-
c.
|
|
287
|
+
c.l &= ~CONFIG_AUTO_DISPOSE;
|
|
280
288
|
o.node = c;
|
|
289
|
+
// The derive's leaves are not its dependents: a mark's repoll
|
|
290
|
+
// (affects-marks.ts) reaches their readers through this.
|
|
291
|
+
c.fam = o;
|
|
281
292
|
return {
|
|
282
293
|
store: i,
|
|
283
294
|
node: c
|
|
284
295
|
};
|
|
285
296
|
}
|
|
286
297
|
|
|
287
|
-
|
|
288
|
-
* A derived store: `fn` runs in a computed and writes its draft; readers of
|
|
289
|
-
* the store's keys re-run only when the keys they read change (the
|
|
290
|
-
* firewall). `fn` may be async or an async iterator; the seed is a draft,
|
|
291
|
-
* never an observable value, until the first landing (A25).
|
|
292
|
-
*/ function createProjection(e, t, r) {
|
|
298
|
+
function createProjection(e, t, r) {
|
|
293
299
|
return createProjectionInternal(e, t, r).store;
|
|
294
300
|
}
|
|
295
301
|
|