@solidjs/signals 2.0.0-rc.14 → 2.0.0-rc.15
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 +248 -189
- package/dist/dev.attribution.js +124 -41
- package/dist/dev.js +553 -322
- package/dist/observe/affects.js +34 -31
- package/dist/observe/boundaries.js +166 -132
- package/dist/observe/core/async.js +90 -83
- package/dist/observe/core/attribution-queries.js +1 -1
- package/dist/observe/core/attribution.js +281 -197
- package/dist/observe/core/constants.js +7 -2
- package/dist/observe/core/context.js +3 -3
- package/dist/observe/core/core.js +277 -245
- package/dist/observe/core/dev.js +3 -3
- package/dist/observe/core/effect.js +21 -21
- package/dist/observe/core/external.js +2 -2
- package/dist/observe/core/graph.js +25 -25
- package/dist/observe/core/heap.js +9 -9
- package/dist/observe/core/lanes.js +206 -160
- package/dist/observe/core/owner.js +27 -27
- package/dist/observe/core/scheduler.js +92 -86
- package/dist/observe/core/verdict.js +66 -54
- package/dist/observe/map.js +35 -35
- package/dist/observe/reveal.js +24 -24
- package/dist/observe/signals.js +38 -28
- package/dist/observe/store/affects.js +75 -68
- package/dist/observe/store/hooks.js +13 -0
- package/dist/observe/store/index.js +0 -2
- package/dist/observe/store/optimistic.js +67 -34
- package/dist/observe/store/projection.js +37 -31
- package/dist/observe/store/reconcile.js +32 -30
- package/dist/observe/store/store.js +128 -85
- package/dist/prod/affects.js +34 -31
- package/dist/prod/boundaries.js +143 -109
- package/dist/prod/core/async.js +64 -67
- package/dist/prod/core/constants.js +7 -2
- package/dist/prod/core/context.js +3 -3
- package/dist/prod/core/core.js +302 -270
- package/dist/prod/core/effect.js +38 -38
- package/dist/prod/core/external.js +4 -4
- package/dist/prod/core/graph.js +27 -27
- package/dist/prod/core/heap.js +30 -30
- package/dist/prod/core/lanes.js +257 -211
- package/dist/prod/core/owner.js +39 -39
- package/dist/prod/core/scheduler.js +125 -119
- package/dist/prod/core/verdict.js +70 -58
- package/dist/prod/map.js +73 -73
- package/dist/prod/reveal.js +38 -38
- package/dist/prod/signals.js +30 -20
- package/dist/prod/store/affects.js +75 -68
- package/dist/prod/store/hooks.js +13 -0
- package/dist/prod/store/index.js +0 -2
- package/dist/prod/store/optimistic.js +114 -81
- package/dist/prod/store/projection.js +30 -24
- package/dist/prod/store/reconcile.js +32 -30
- package/dist/prod/store/store.js +136 -93
- package/dist/types/boundaries.d.ts +4 -0
- package/dist/types/core/attribution.d.ts +6 -2
- package/dist/types/core/constants.d.ts +5 -0
- package/dist/types/core/core.d.ts +33 -3
- package/dist/types/core/lanes.d.ts +10 -0
- package/dist/types/core/scheduler.d.ts +12 -6
- package/dist/types/core/types.d.ts +0 -6
- package/dist/types/store/affects.d.ts +11 -0
- package/dist/types/store/hooks.d.ts +48 -0
- package/dist/types/store/index.d.ts +0 -1
- package/dist/types/store/store.d.ts +3 -38
- package/package.json +1 -1
|
@@ -10,7 +10,9 @@ import { GlobalQueue, txOf, list, insertSubs, laneDirty, notifyEpoch, schedule }
|
|
|
10
10
|
|
|
11
11
|
import { runProjectionComputed } from "./projection.js";
|
|
12
12
|
|
|
13
|
-
import { wrap, storeSetter, LaneView, committed, getNode, unwrapValue, sameKey,
|
|
13
|
+
import { wrap, storeSetter, LaneView, committed, getNode, unwrapValue, sameKey, resolveChainedRaw, getHasNode, targetsEqual, getContainerNode, cloneRaw } from "./store.js";
|
|
14
|
+
|
|
15
|
+
import { installOptHooks } from "./hooks.js";
|
|
14
16
|
|
|
15
17
|
import { $OWNER } from "./target.js";
|
|
16
18
|
|
|
@@ -79,7 +81,7 @@ function notifyOptimisticWrites(e, n) {
|
|
|
79
81
|
// inner store's truth for its key before guessing over it.
|
|
80
82
|
const o = e.ch ? e.v : null;
|
|
81
83
|
const guess = (e, n, i, r) => {
|
|
82
|
-
if (o !== null) e.
|
|
84
|
+
if (o !== null) e.Ae = i ? n in t : unwrapValue(t[n]);
|
|
83
85
|
// By value: a function leaf is a value, not an updater (#3017).
|
|
84
86
|
optimisticWrite(e, () => r);
|
|
85
87
|
};
|
|
@@ -89,17 +91,17 @@ function notifyOptimisticWrites(e, n) {
|
|
|
89
91
|
// A chained draft holds the inner store's raws; a raw is the inner slot it
|
|
90
92
|
// resolves to (as a read of it serves) — the row a held write staged is
|
|
91
93
|
// the same row, not a guess over the slot (#3796).
|
|
92
|
-
const
|
|
93
|
-
const
|
|
94
|
+
const a = n[t];
|
|
95
|
+
const f = unwrapValue(o && a ? resolveChainedRaw(e, t, a) : a);
|
|
94
96
|
if (!(t in i)) {
|
|
95
|
-
guess(getNode(e, t), t, false,
|
|
97
|
+
guess(getNode(e, t), t, false, f);
|
|
96
98
|
guess(getHasNode(e, t), t, true, true);
|
|
97
99
|
s = true;
|
|
98
100
|
} else {
|
|
99
101
|
const n = i[t];
|
|
100
|
-
const
|
|
101
|
-
if (!isEqual(
|
|
102
|
-
guess(getNode(e, t), t, false,
|
|
102
|
+
const a = unwrapValue(o && n ? resolveChainedRaw(e, t, n) : n);
|
|
103
|
+
if (!isEqual(a, f) && !targetsEqual(a, f)) {
|
|
104
|
+
guess(getNode(e, t), t, false, f);
|
|
103
105
|
if (r) s = true;
|
|
104
106
|
}
|
|
105
107
|
}
|
|
@@ -120,16 +122,16 @@ function notifyOptimisticWrites(e, n) {
|
|
|
120
122
|
// The rows the setter removed from the view it saw, by key: a later
|
|
121
123
|
// re-base over another action's truth must not bring them back.
|
|
122
124
|
let s = null;
|
|
123
|
-
const
|
|
124
|
-
if (r &&
|
|
125
|
+
const a = e.fam.key;
|
|
126
|
+
if (r && a !== null && a !== undefined) {
|
|
125
127
|
const e = new Set;
|
|
126
128
|
for (let n = 0; n < o.length; n++) {
|
|
127
|
-
const t = isWrappable(o[n]) ?
|
|
129
|
+
const t = isWrappable(o[n]) ? a(o[n]) : undefined;
|
|
128
130
|
if (t !== undefined) e.add(t);
|
|
129
131
|
}
|
|
130
132
|
for (let n = 0; n < i.length; n++) {
|
|
131
133
|
const t = unwrapValue(i[n]);
|
|
132
|
-
const r = isWrappable(t) ?
|
|
134
|
+
const r = isWrappable(t) ? a(t) : undefined;
|
|
133
135
|
if (r !== undefined && !e.has(r)) (s ??= new Set).add(r);
|
|
134
136
|
}
|
|
135
137
|
}
|
|
@@ -137,10 +139,10 @@ function notifyOptimisticWrites(e, n) {
|
|
|
137
139
|
}
|
|
138
140
|
if (e.dk !== null) optimisticWrite(e.dk, {});
|
|
139
141
|
markOverlaid(e);
|
|
140
|
-
const
|
|
141
|
-
if (
|
|
142
|
+
const a = optStaged.get(e);
|
|
143
|
+
if (a === undefined) return null;
|
|
142
144
|
optStaged.delete(e);
|
|
143
|
-
return
|
|
145
|
+
return a;
|
|
144
146
|
}
|
|
145
147
|
|
|
146
148
|
/** The container comparator's lane arm (store.ts `containerEquals`): an
|
|
@@ -157,9 +159,40 @@ function rowSame(e, n, t) {
|
|
|
157
159
|
if (t === null || !isWrappable(e) || !isWrappable(n)) return false;
|
|
158
160
|
const i = t(unwrapValue(e));
|
|
159
161
|
const r = t(unwrapValue(n));
|
|
162
|
+
// Keyless rows are identified by position — reconcile's fallback when the
|
|
163
|
+
// key is missing. The caller already paired these by index, so two keyless
|
|
164
|
+
// rows are the same row and the landing confirms the arrangement instead of
|
|
165
|
+
// dissolving it. Dissolving held an external echo under the action, and a
|
|
166
|
+
// mainline `until` then timed out on a source that already contained it
|
|
167
|
+
// (#3898). Keyed rows still match only on the key.
|
|
168
|
+
if (i === undefined && r === undefined) return true;
|
|
160
169
|
return i !== undefined && sameKey(i, r);
|
|
161
170
|
}
|
|
162
171
|
|
|
172
|
+
/** Whether reconcile would write anything into `a` from `b`: wrappable
|
|
173
|
+
* pairs descend, leaves compare as its writes do. A key mismatch is a
|
|
174
|
+
* replacement, which a content difference already says. Plain data — the
|
|
175
|
+
* server's echo of a guessed row is a new object with the same contents. */ function echoes(e, n) {
|
|
176
|
+
if (e === n) return true;
|
|
177
|
+
if (!isWrappable(e) || !isWrappable(n)) return false;
|
|
178
|
+
e = unwrapValue(e);
|
|
179
|
+
n = unwrapValue(n);
|
|
180
|
+
const t = Object.keys(e);
|
|
181
|
+
if (Array.isArray(e) !== Array.isArray(n) || t.length !== Object.keys(n).length) return false;
|
|
182
|
+
for (const i of t) if (!hasOwn.call(n, i) || !echoes(e[i], n[i])) return false;
|
|
183
|
+
return true;
|
|
184
|
+
}
|
|
185
|
+
|
|
186
|
+
// A cycle (a row that references itself) is not plain data: no match, so
|
|
187
|
+
// the landing stays a correction.
|
|
188
|
+
GlobalQueue.tn = (e, n) => {
|
|
189
|
+
try {
|
|
190
|
+
return echoes(e, n);
|
|
191
|
+
} catch {
|
|
192
|
+
return false;
|
|
193
|
+
}
|
|
194
|
+
};
|
|
195
|
+
|
|
163
196
|
function arrangementEqual(e, n, t) {
|
|
164
197
|
if (Array.isArray(e) !== Array.isArray(n)) return false;
|
|
165
198
|
if (Array.isArray(e)) {
|
|
@@ -193,18 +226,18 @@ function arrangementEqual(e, n, t) {
|
|
|
193
226
|
}
|
|
194
227
|
}
|
|
195
228
|
for (let s = 0; s < n.length; s++) {
|
|
196
|
-
const
|
|
197
|
-
let
|
|
198
|
-
if (isWrappable(
|
|
229
|
+
const a = n[s];
|
|
230
|
+
let f;
|
|
231
|
+
if (isWrappable(a)) {
|
|
199
232
|
if (o !== null) {
|
|
200
|
-
const e = t(
|
|
201
|
-
if (e !== undefined)
|
|
202
|
-
} else if (s < i && isWrappable(unwrapValue(r[s])))
|
|
233
|
+
const e = t(a);
|
|
234
|
+
if (e !== undefined) f = o.get(e);
|
|
235
|
+
} else if (s < i && isWrappable(unwrapValue(r[s]))) f = r[s];
|
|
203
236
|
}
|
|
204
|
-
if (
|
|
205
|
-
if (unwrapValue(
|
|
206
|
-
if (e[s] !==
|
|
207
|
-
} else if (unwrapValue(e[s]) !==
|
|
237
|
+
if (f !== undefined) {
|
|
238
|
+
if (unwrapValue(f) !== a) reconcileDraft(f, a, t);
|
|
239
|
+
if (e[s] !== f) e[s] = f;
|
|
240
|
+
} else if (unwrapValue(e[s]) !== a) e[s] = a;
|
|
208
241
|
}
|
|
209
242
|
if (e.length !== n.length) e.length = n.length;
|
|
210
243
|
return;
|
|
@@ -233,10 +266,10 @@ function arrangementEqual(e, n, t) {
|
|
|
233
266
|
* node is born for it as the lane's derivation), on `length` only when the
|
|
234
267
|
* committed length differs, and as the `LaneView`'s base for structural
|
|
235
268
|
* reads. Unkeyed families compose
|
|
236
|
-
* positionally — the guess stands as written (the documented residue). */ GlobalQueue.
|
|
237
|
-
const t = e.
|
|
238
|
-
if (t === undefined || e.
|
|
239
|
-
const i = e.m.
|
|
269
|
+
* positionally — the guess stands as written (the documented residue). */ GlobalQueue.an = (e, n) => {
|
|
270
|
+
const t = e.lt;
|
|
271
|
+
if (t === undefined || e.ot !== $TRACK) return;
|
|
272
|
+
const i = e.m.B;
|
|
240
273
|
if (!(i instanceof LaneView)) return;
|
|
241
274
|
if (!Array.isArray(n) || !Array.isArray(i.rows)) {
|
|
242
275
|
i.base = n;
|
|
@@ -251,45 +284,45 @@ function arrangementEqual(e, n, t) {
|
|
|
251
284
|
if (i !== undefined && !o.has(i)) o.set(i, t);
|
|
252
285
|
}
|
|
253
286
|
const s = new Set;
|
|
254
|
-
const
|
|
255
|
-
const
|
|
256
|
-
for (let e = 0; e <
|
|
257
|
-
const n =
|
|
287
|
+
const a = [];
|
|
288
|
+
const f = i.rows;
|
|
289
|
+
for (let e = 0; e < f.length; e++) {
|
|
290
|
+
const n = f[e];
|
|
258
291
|
const t = isWrappable(n) ? r(n) : undefined;
|
|
259
292
|
const i = t !== undefined ? o.get(t) : undefined;
|
|
260
293
|
if (i !== undefined) {
|
|
261
|
-
|
|
294
|
+
a.push(i);
|
|
262
295
|
s.add(t);
|
|
263
|
-
} else
|
|
296
|
+
} else a.push(n);
|
|
264
297
|
}
|
|
265
|
-
const
|
|
298
|
+
const u = i.removed;
|
|
266
299
|
for (let e = 0; e < n.length; e++) {
|
|
267
300
|
const t = n[e];
|
|
268
301
|
const i = isWrappable(t) ? r(t) : undefined;
|
|
269
|
-
if (i !== undefined && !s.has(i) && (
|
|
302
|
+
if (i !== undefined && !s.has(i) && (u === null || !u.has(i))) a.push(t);
|
|
270
303
|
}
|
|
271
|
-
i.rows =
|
|
272
|
-
i.base =
|
|
273
|
-
const
|
|
304
|
+
i.rows = a;
|
|
305
|
+
i.base = a;
|
|
306
|
+
const l = txOf(e);
|
|
274
307
|
const c = committed(t);
|
|
275
308
|
const d = t.n;
|
|
276
|
-
for (let e = 0; e <
|
|
309
|
+
for (let e = 0; e < a.length; e++) {
|
|
277
310
|
const n = d?.[e];
|
|
278
311
|
// A slot the lane does not own shows the committed row: it becomes the
|
|
279
312
|
// lane's only where the composed row is another row (by key — the same
|
|
280
313
|
// key's new object is the same row, its target adopted it).
|
|
281
314
|
if (n === undefined) {
|
|
282
|
-
if (!sameRow(c[e],
|
|
283
|
-
} else if (!sameRow(n.
|
|
315
|
+
if (!sameRow(c[e], a[e], r)) laneSet(getNode(t, e), a[e], l);
|
|
316
|
+
} else if (!sameRow(n.i & CONFIG_OVERRIDE ? n.m.B : c[e], a[e], r)) laneSet(n, a[e], l);
|
|
284
317
|
}
|
|
285
318
|
if (d !== null) {
|
|
286
|
-
for (let e =
|
|
319
|
+
for (let e = a.length; ;e++) {
|
|
287
320
|
const n = d[e];
|
|
288
321
|
if (n === undefined) break;
|
|
289
|
-
laneSet(n, undefined,
|
|
322
|
+
laneSet(n, undefined, l);
|
|
290
323
|
}
|
|
291
324
|
const e = d.length;
|
|
292
|
-
if (e !== undefined && (e.
|
|
325
|
+
if (e !== undefined && (e.i & CONFIG_OVERRIDE || c.length !== a.length)) laneSet(e, a.length, l);
|
|
293
326
|
}
|
|
294
327
|
};
|
|
295
328
|
|
|
@@ -304,11 +337,11 @@ function sameRow(e, n, t) {
|
|
|
304
337
|
* node that was not the lane's becomes its derivation (its committed value
|
|
305
338
|
* untouched beneath; the lane's end commits the latest). */ function laneSet(e, n, t) {
|
|
306
339
|
const i = ext(e);
|
|
307
|
-
if (!(e.
|
|
308
|
-
e.
|
|
340
|
+
if (!(e.i & CONFIG_OVERRIDE)) {
|
|
341
|
+
e.i |= CONFIG_OVERRIDE;
|
|
309
342
|
list(e, t);
|
|
310
|
-
} else if (i.
|
|
311
|
-
i.
|
|
343
|
+
} else if (i.B === n) return;
|
|
344
|
+
i.B = n;
|
|
312
345
|
if (e.t !== null) {
|
|
313
346
|
insertSubs(e);
|
|
314
347
|
laneDirty(e, t);
|
|
@@ -354,7 +387,7 @@ function sweepOverlaid() {
|
|
|
354
387
|
// The container shows its backing again (a shown arrangement guess
|
|
355
388
|
// that ended without a landing left its `LaneView` as the value).
|
|
356
389
|
const t = e.k;
|
|
357
|
-
if (t !== null && t.
|
|
390
|
+
if (t !== null && t.Ae instanceof LaneView) t.Ae = t.Ae.base;
|
|
358
391
|
}
|
|
359
392
|
if (n.size === 0) overlaidFamilies.delete(e);
|
|
360
393
|
}
|
|
@@ -371,11 +404,11 @@ function sweepOverlaid() {
|
|
|
371
404
|
if (i !== null) for (const e of Reflect.ownKeys(i)) {
|
|
372
405
|
const r = i[e];
|
|
373
406
|
const o = untrack(() => unwrapValue(n[e]));
|
|
374
|
-
if (r.
|
|
375
|
-
r.
|
|
407
|
+
if (r.ye && r.ye(r.Ae, o)) continue;
|
|
408
|
+
r.Ae = o;
|
|
376
409
|
// (The lane's end notified it this epoch when the shown value and the
|
|
377
410
|
// covered one differed — its readers re-derive already.)
|
|
378
|
-
if (r.t !== null && r.
|
|
411
|
+
if (r.t !== null && r.qe !== notifyEpoch) {
|
|
379
412
|
insertSubs(r);
|
|
380
413
|
t = true;
|
|
381
414
|
}
|
|
@@ -384,9 +417,9 @@ function sweepOverlaid() {
|
|
|
384
417
|
if (r !== null) for (const e of Reflect.ownKeys(r)) {
|
|
385
418
|
const i = r[e];
|
|
386
419
|
const o = untrack(() => e in n);
|
|
387
|
-
if (i.
|
|
388
|
-
i.
|
|
389
|
-
if (i.t !== null && i.
|
|
420
|
+
if (i.Ae === o) continue;
|
|
421
|
+
i.Ae = o;
|
|
422
|
+
if (i.t !== null && i.qe !== notifyEpoch) {
|
|
390
423
|
insertSubs(i);
|
|
391
424
|
t = true;
|
|
392
425
|
}
|
|
@@ -394,9 +427,9 @@ function sweepOverlaid() {
|
|
|
394
427
|
// The arrangement the readers saw (the shown guess) against the inner's
|
|
395
428
|
// now: a structural reader re-derives when they differ.
|
|
396
429
|
const o = e.k;
|
|
397
|
-
if (o !== null && o.t !== null && o.
|
|
430
|
+
if (o !== null && o.t !== null && o.Ae instanceof LaneView && o.qe !== notifyEpoch) {
|
|
398
431
|
const i = Array.isArray(n) ? untrack(() => n.map(unwrapValue)) : n;
|
|
399
|
-
if (!arrangementEqual(o.
|
|
432
|
+
if (!arrangementEqual(o.Ae.rows, i, e.fam?.key ?? null)) {
|
|
400
433
|
insertSubs(o);
|
|
401
434
|
t = true;
|
|
402
435
|
}
|
|
@@ -405,12 +438,12 @@ function sweepOverlaid() {
|
|
|
405
438
|
}
|
|
406
439
|
|
|
407
440
|
function carriesLane(e) {
|
|
408
|
-
if (e.k !== null && e.k.
|
|
409
|
-
if (e.dk !== null && e.dk.
|
|
441
|
+
if (e.k !== null && e.k.i & CONFIG_OVERRIDE) return true;
|
|
442
|
+
if (e.dk !== null && e.dk.i & CONFIG_OVERRIDE) return true;
|
|
410
443
|
const n = e.n;
|
|
411
|
-
if (n !== null) for (const e of Reflect.ownKeys(n)) if (n[e].
|
|
444
|
+
if (n !== null) for (const e of Reflect.ownKeys(n)) if (n[e].i & CONFIG_OVERRIDE) return true;
|
|
412
445
|
const t = e.h;
|
|
413
|
-
if (t !== null) for (const e of Reflect.ownKeys(t)) if (t[e].
|
|
446
|
+
if (t !== null) for (const e of Reflect.ownKeys(t)) if (t[e].i & CONFIG_OVERRIDE) return true;
|
|
414
447
|
return false;
|
|
415
448
|
}
|
|
416
449
|
|
|
@@ -428,9 +461,9 @@ function overlaid(e) {
|
|
|
428
461
|
* the backing answers. */ function optimisticHas(e, n) {
|
|
429
462
|
if (!overlaid(e)) return undefined;
|
|
430
463
|
const t = e.h?.[n];
|
|
431
|
-
if (t !== undefined && t.
|
|
464
|
+
if (t !== undefined && t.i & CONFIG_OVERRIDE) return !!shown(t);
|
|
432
465
|
const i = e.n?.[n];
|
|
433
|
-
if (i !== undefined && i.
|
|
466
|
+
if (i !== undefined && i.i & CONFIG_OVERRIDE) return shown(i) !== undefined;
|
|
434
467
|
return undefined;
|
|
435
468
|
}
|
|
436
469
|
|
|
@@ -441,7 +474,7 @@ function overlaid(e) {
|
|
|
441
474
|
if (t === undefined) return undefined;
|
|
442
475
|
if (!t) return null;
|
|
443
476
|
const i = e.n?.[n];
|
|
444
|
-
const r = i !== undefined && i.
|
|
477
|
+
const r = i !== undefined && i.i & CONFIG_OVERRIDE ? shown(i) : e.v[n];
|
|
445
478
|
// An array's `length` is reported as the array has it (non-configurable).
|
|
446
479
|
if (n === "length" && Array.isArray(e.v)) return {
|
|
447
480
|
value: r,
|
|
@@ -474,7 +507,7 @@ i = false) {
|
|
|
474
507
|
for (const e of Reflect.ownKeys(o)) {
|
|
475
508
|
const r = o[e];
|
|
476
509
|
let s;
|
|
477
|
-
if (r.
|
|
510
|
+
if (r.i & CONFIG_OVERRIDE) s = t(r); else if (!i || (s = pendingGuessOf(r)) === NOT_PENDING) continue;
|
|
478
511
|
if (e === "length" && Array.isArray(n)) {
|
|
479
512
|
if (n.length !== s) ensure().length = s;
|
|
480
513
|
} else if (!isEqual(n[e], s) || !hasOwn.call(n, e)) {
|
|
@@ -486,11 +519,11 @@ i = false) {
|
|
|
486
519
|
if (s !== null) {
|
|
487
520
|
for (const e of Reflect.ownKeys(s)) {
|
|
488
521
|
const o = s[e];
|
|
489
|
-
let
|
|
490
|
-
if (o.
|
|
491
|
-
const
|
|
492
|
-
const
|
|
493
|
-
if (!
|
|
522
|
+
let a;
|
|
523
|
+
if (o.i & CONFIG_OVERRIDE) a = t(o); else if (!i || (a = pendingGuessOf(o)) === NOT_PENDING) continue;
|
|
524
|
+
const f = !!a;
|
|
525
|
+
const u = r ?? n;
|
|
526
|
+
if (!f && e in u) delete ensure()[e];
|
|
494
527
|
}
|
|
495
528
|
}
|
|
496
529
|
return r ?? n;
|
|
@@ -501,7 +534,7 @@ function createOptimisticStore(e, n, t) {
|
|
|
501
534
|
const r = i ? t : n;
|
|
502
535
|
const o = i ? n : e;
|
|
503
536
|
const s = r?.key === undefined ? "id" : r.key;
|
|
504
|
-
const
|
|
537
|
+
const a = {
|
|
505
538
|
map: new WeakMap,
|
|
506
539
|
node: null,
|
|
507
540
|
live: new Set,
|
|
@@ -509,9 +542,9 @@ function createOptimisticStore(e, n, t) {
|
|
|
509
542
|
opt: true,
|
|
510
543
|
key: typeof s === "function" ? s : s === null ? null : e => isWrappable(e) ? e[s] : undefined
|
|
511
544
|
};
|
|
512
|
-
const
|
|
513
|
-
if (
|
|
514
|
-
|
|
545
|
+
const f = wrap(o, null, null, a);
|
|
546
|
+
if (a.shallow) {
|
|
547
|
+
f[$TARGET].s = true;
|
|
515
548
|
markRawIngest(o);
|
|
516
549
|
}
|
|
517
550
|
if (i) {
|
|
@@ -521,13 +554,13 @@ function createOptimisticStore(e, n, t) {
|
|
|
521
554
|
loadingValue: undefined
|
|
522
555
|
};
|
|
523
556
|
const i = computed(() => {
|
|
524
|
-
if (!
|
|
525
|
-
runProjectionComputed(
|
|
557
|
+
if (!a.node) a.node = getOwner();
|
|
558
|
+
runProjectionComputed(f, n, s);
|
|
526
559
|
}, t);
|
|
527
|
-
i.
|
|
528
|
-
|
|
560
|
+
i.i &= ~CONFIG_AUTO_DISPOSE;
|
|
561
|
+
a.node = i;
|
|
529
562
|
}
|
|
530
|
-
return [
|
|
563
|
+
return [ f, e => storeSetter(f, e) ];
|
|
531
564
|
}
|
|
532
565
|
|
|
533
566
|
export { createOptimisticStore, notifyOptimisticWrites, optimisticHas, optimisticOwnDescriptor, optimisticView, sweepOverlaid };
|
|
@@ -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, setWriteOverride } from "./types.js";
|
|
21
|
+
import { $TARGET, markRawIngest, setWriteOverride, isWrappable } from "./types.js";
|
|
22
22
|
|
|
23
23
|
/**
|
|
24
24
|
* Store — projections (plan sec. 31, S3; INTERNALS §7/§7b).
|
|
@@ -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.De ? 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.m !== null && i.m.
|
|
190
|
+
const asking = () => question || (i.m !== null && i.m.Te !== null ? i.m._e : 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.S & STATUS_PENDING) && !i.De) 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,7 @@ 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.S & STATUS_UNINITIALIZED)) settleFamily(c);
|
|
223
223
|
};
|
|
224
224
|
const u = handleAsync(i, l, commit, (e, t) => {
|
|
225
225
|
// The flight rejected: the leaves' readers learn it from here —
|
|
@@ -228,10 +228,10 @@ function forEachFamilyNode(e, t) {
|
|
|
228
228
|
// reader re-derives and meets the error at its pull (memo parity,
|
|
229
229
|
// #2897) — and the flush that runs them advances the clock, so a
|
|
230
230
|
// later tracked re-read may retry (core `read`).
|
|
231
|
-
if (d && i.
|
|
231
|
+
if (d && i.S & STATUS_UNINITIALIZED) return;
|
|
232
232
|
if (t) wakeFamily(c, e); else errorFamily(c);
|
|
233
233
|
});
|
|
234
|
-
if (!i.
|
|
234
|
+
if (!i.De) commit(u);
|
|
235
235
|
}, false);
|
|
236
236
|
try {
|
|
237
237
|
d ? runDirect(pass) : pass();
|
|
@@ -239,42 +239,48 @@ function forEachFamilyNode(e, t) {
|
|
|
239
239
|
// A flight went up (NotReady out of the pass — the derive's own, with
|
|
240
240
|
// the derive as its source): the leaves' readers learn it from here —
|
|
241
241
|
// they do not subscribe to the derive.
|
|
242
|
-
|
|
242
|
+
// A synchronous error the same way (#3956: a rerun that finds the
|
|
243
|
+
// entry failed throws): every live reader re-derives and meets it.
|
|
244
|
+
if (!d) e instanceof NotReadyError ? wakeFamily(c, e) : errorFamily(c);
|
|
243
245
|
throw e;
|
|
244
246
|
}
|
|
245
247
|
// A pass that returned with a flight up (an iterator's sync first yield):
|
|
246
248
|
// the wake, as for the throw. Not a sync pass that superseded one — the
|
|
247
249
|
// status it reads is the dead flight's, cleared when this pass settles
|
|
248
250
|
// (#3181: a reader the settle walk had just released, re-parked for good).
|
|
249
|
-
if (i.
|
|
251
|
+
if (i.S & STATUS_PENDING && i.m.Te !== null && !i.De && !d) wakeFamily(c, i.m?.F);
|
|
250
252
|
return i;
|
|
251
253
|
}
|
|
252
254
|
|
|
253
255
|
function createProjectionInternal(e, t, r) {
|
|
254
|
-
const n =
|
|
256
|
+
const n = r?.key === undefined ? "id" : r.key;
|
|
257
|
+
const o = {
|
|
255
258
|
map: new WeakMap,
|
|
256
259
|
node: null,
|
|
257
260
|
live: new Set,
|
|
258
|
-
shallow: !!r?.shallow
|
|
261
|
+
shallow: !!r?.shallow,
|
|
262
|
+
// The row key, for a child paired after the adoption (store.ts
|
|
263
|
+
// `adoptChild`, #3712) as the adoption pairs them.
|
|
264
|
+
key: typeof n === "function" ? n : n === null ? null : e => isWrappable(e) ? e[n] : undefined
|
|
259
265
|
};
|
|
260
|
-
const
|
|
261
|
-
if (
|
|
262
|
-
|
|
266
|
+
const i = wrap(t, null, null, o);
|
|
267
|
+
if (o.shallow) {
|
|
268
|
+
i[$TARGET].s = true;
|
|
263
269
|
markRawIngest(t);
|
|
264
270
|
}
|
|
265
|
-
let
|
|
266
|
-
if (r?.seedLoadingValue)
|
|
271
|
+
let s;
|
|
272
|
+
if (r?.seedLoadingValue) s = {
|
|
267
273
|
loadingValue: undefined
|
|
268
274
|
};
|
|
269
|
-
const
|
|
270
|
-
if (!
|
|
271
|
-
runProjectionComputed(
|
|
272
|
-
},
|
|
273
|
-
|
|
274
|
-
|
|
275
|
+
const c = computed(() => {
|
|
276
|
+
if (!o.node) o.node = getOwner();
|
|
277
|
+
runProjectionComputed(i, e, n);
|
|
278
|
+
}, s);
|
|
279
|
+
c.i &= ~CONFIG_AUTO_DISPOSE;
|
|
280
|
+
o.node = c;
|
|
275
281
|
return {
|
|
276
|
-
store:
|
|
277
|
-
node:
|
|
282
|
+
store: i,
|
|
283
|
+
node: c
|
|
278
284
|
};
|
|
279
285
|
}
|
|
280
286
|
|
|
@@ -2,7 +2,9 @@ import { isEqual } from "../core/core.js";
|
|
|
2
2
|
|
|
3
3
|
import { isOwned, $OWNER, storeLookup, lookupTarget } from "./target.js";
|
|
4
4
|
|
|
5
|
-
import { userWriting,
|
|
5
|
+
import { userWriting, unwrapValue, adoptPB, sameKey, materializePB, notifyFold, sameRow, targetsEqual, bumpDeep, notifyKeyValue, notifyKeyDiff, notifyFoldTail, hasAccessorFlag } from "./store.js";
|
|
6
|
+
|
|
7
|
+
import { optHooks } from "./hooks.js";
|
|
6
8
|
|
|
7
9
|
import { $TARGET, markRawIngest, isWrappable, rawValuesUsed, isRawValue } from "./types.js";
|
|
8
10
|
|
|
@@ -73,33 +75,33 @@ import { $TARGET, markRawIngest, isWrappable, rawValuesUsed, isRawValue } from "
|
|
|
73
75
|
// — key matching from the arrangement the guesses made (R28), so a row
|
|
74
76
|
// the guess added keeps its proxy when the server returns it.
|
|
75
77
|
const i = l?.opt === true ? optHooks.view(e, f) : f;
|
|
76
|
-
const
|
|
77
|
-
const
|
|
78
|
+
const s = Array.isArray(n);
|
|
79
|
+
const u = e.s === true;
|
|
78
80
|
const r = f;
|
|
79
81
|
adoptPB(e, n, false);
|
|
80
|
-
if (
|
|
81
|
-
if (Array.isArray(i) !==
|
|
82
|
+
if (u) markRawIngest(n);
|
|
83
|
+
if (Array.isArray(i) !== s) {
|
|
82
84
|
notifyFold(e, r, n);
|
|
83
85
|
return;
|
|
84
86
|
}
|
|
85
|
-
if (
|
|
87
|
+
if (s) {
|
|
86
88
|
const f = i;
|
|
87
|
-
const
|
|
89
|
+
const s = n;
|
|
88
90
|
const a = e.n;
|
|
89
91
|
let c = 0;
|
|
90
|
-
if (t && !
|
|
92
|
+
if (t && !u) {
|
|
91
93
|
const i = f.length;
|
|
92
|
-
const
|
|
94
|
+
const u = s.length;
|
|
93
95
|
let d = false;
|
|
94
96
|
let p = 0;
|
|
95
97
|
// Aligned prefix: same row (by reference or key) at the same index.
|
|
96
|
-
for (const y = Math.min(i,
|
|
97
|
-
const i =
|
|
98
|
-
const
|
|
99
|
-
if (
|
|
98
|
+
for (const y = Math.min(i, u); p < y; p++) {
|
|
99
|
+
const i = s[p];
|
|
100
|
+
const u = f[p];
|
|
101
|
+
if (u !== i && !sameRow(u, i, t)) break;
|
|
100
102
|
// misaligned: fall to the keyed remainder below
|
|
101
|
-
if ((
|
|
102
|
-
if (e.dk !== null && !d && !(i !== null && typeof i === "object" ? targetsEqual(
|
|
103
|
+
if ((u !== i || i !== null && typeof i === "object" && isOwned(i)) && i !== null && typeof i === "object") descend(unwrapValue(u), i, t, l, o);
|
|
104
|
+
if (e.dk !== null && !d && !(i !== null && typeof i === "object" ? targetsEqual(u, i) : isEqual(u, i))) {
|
|
103
105
|
bumpDeep(e);
|
|
104
106
|
d = true;
|
|
105
107
|
}
|
|
@@ -111,12 +113,12 @@ import { $TARGET, markRawIngest, isWrappable, rawValuesUsed, isRawValue } from "
|
|
|
111
113
|
}
|
|
112
114
|
}
|
|
113
115
|
}
|
|
114
|
-
if (e.dk !== null && !d && p <
|
|
116
|
+
if (e.dk !== null && !d && p < s.length) bumpDeep(e);
|
|
115
117
|
const y = p;
|
|
116
118
|
// misalignment point (== nlen on aligned ticks)
|
|
117
119
|
let w = null;
|
|
118
|
-
for (;p <
|
|
119
|
-
const e =
|
|
120
|
+
for (;p < s.length; p++) {
|
|
121
|
+
const e = s[p];
|
|
120
122
|
if (e !== null && typeof e === "object") {
|
|
121
123
|
const n = t(e);
|
|
122
124
|
let i;
|
|
@@ -156,12 +158,12 @@ import { $TARGET, markRawIngest, isWrappable, rawValuesUsed, isRawValue } from "
|
|
|
156
158
|
}
|
|
157
159
|
}
|
|
158
160
|
} else {
|
|
159
|
-
const i = Math.min(f.length,
|
|
160
|
-
const d =
|
|
161
|
+
const i = Math.min(f.length, s.length);
|
|
162
|
+
const d = s.length;
|
|
161
163
|
let p = false;
|
|
162
164
|
for (let y = 0; y < d; y++) {
|
|
163
|
-
const d =
|
|
164
|
-
if (!
|
|
165
|
+
const d = s[y];
|
|
166
|
+
if (!u && y < i && d !== null && typeof d === "object") descend(unwrapValue(f[y]), d, t, l, o);
|
|
165
167
|
if (e.dk !== null && !p && !(d !== null && typeof d === "object" ? targetsEqual(f[y], d) : isEqual(f[y], d))) {
|
|
166
168
|
bumpDeep(e);
|
|
167
169
|
p = true;
|
|
@@ -179,7 +181,7 @@ import { $TARGET, markRawIngest, isWrappable, rawValuesUsed, isRawValue } from "
|
|
|
179
181
|
if (a !== null && c < e.nc) {
|
|
180
182
|
for (const e of Reflect.ownKeys(a)) {
|
|
181
183
|
const t = typeof e === "string" ? +e : NaN;
|
|
182
|
-
if (!(t >= 0 && t <
|
|
184
|
+
if (!(t >= 0 && t < s.length)) notifyKeyDiff(a[e], e, r, n, false);
|
|
183
185
|
}
|
|
184
186
|
}
|
|
185
187
|
notifyFoldTail(e, r, n);
|
|
@@ -189,15 +191,15 @@ import { $TARGET, markRawIngest, isWrappable, rawValuesUsed, isRawValue } from "
|
|
|
189
191
|
let c = 0;
|
|
190
192
|
let d = false;
|
|
191
193
|
for (const f in n) {
|
|
192
|
-
const
|
|
194
|
+
const s = n[f];
|
|
193
195
|
const p = r[f];
|
|
194
|
-
const y =
|
|
195
|
-
if (p ===
|
|
196
|
+
const y = s !== null && typeof s === "object";
|
|
197
|
+
if (p === s && (!y || !isOwned(s)) && (a === null || a[f] === undefined || !hasAccessorFlag(a[f]))) {
|
|
196
198
|
if (a !== null && a[f] !== undefined) c++;
|
|
197
199
|
continue;
|
|
198
200
|
}
|
|
199
|
-
if (y && !
|
|
200
|
-
if (e.dk !== null && !d && !(y ? targetsEqual(p,
|
|
201
|
+
if (y && !u) descend(unwrapValue(i[f]), s, t, l, o);
|
|
202
|
+
if (e.dk !== null && !d && !(y ? targetsEqual(p, s) : isEqual(p, s))) {
|
|
201
203
|
bumpDeep(e);
|
|
202
204
|
d = true;
|
|
203
205
|
}
|
|
@@ -205,7 +207,7 @@ import { $TARGET, markRawIngest, isWrappable, rawValuesUsed, isRawValue } from "
|
|
|
205
207
|
const e = a[f];
|
|
206
208
|
if (e !== undefined) {
|
|
207
209
|
c++;
|
|
208
|
-
notifyKeyValue(e, f, p,
|
|
210
|
+
notifyKeyValue(e, f, p, s, r, n);
|
|
209
211
|
}
|
|
210
212
|
}
|
|
211
213
|
}
|
|
@@ -214,7 +216,7 @@ import { $TARGET, markRawIngest, isWrappable, rawValuesUsed, isRawValue } from "
|
|
|
214
216
|
const f = p[e];
|
|
215
217
|
if (f === $OWNER) continue;
|
|
216
218
|
const i = n[f];
|
|
217
|
-
if (!
|
|
219
|
+
if (!u && i !== null && typeof i === "object") descend(unwrapValue(r[f]), i, t, l, o);
|
|
218
220
|
if (a !== null) {
|
|
219
221
|
const e = a[f];
|
|
220
222
|
if (e !== undefined) {
|