@solidjs/signals 2.0.0-rc.5 → 2.0.0-rc.6
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 +475 -72
- package/dist/node.cjs +851 -662
- package/dist/prod/core/async.js +41 -19
- package/dist/prod/core/core.js +58 -62
- package/dist/prod/core/effect.js +6 -6
- package/dist/prod/core/heap.js +1 -1
- package/dist/prod/core/lanes.js +4 -4
- package/dist/prod/core/optimistic.js +16 -16
- package/dist/prod/core/owner.js +4 -4
- package/dist/prod/core/scheduler.js +45 -32
- package/dist/prod/core/verdict.js +23 -19
- package/dist/prod/signals.js +68 -1
- package/dist/prod/store/next/optimistic.js +137 -64
- package/dist/prod/store/next/projection.js +2 -2
- package/dist/prod/store/next/store.js +122 -106
- package/dist/types/core/attribution-hooks.d.ts +11 -0
- package/dist/types/core/attribution.d.ts +48 -0
- package/dist/types/core/dev.d.ts +8 -2
- package/dist/types/core/scheduler.d.ts +5 -0
- package/dist/types/signals.d.ts +0 -11
- package/dist/types/store/next/target.d.ts +10 -0
- package/dist/types-cjs/core/attribution-hooks.d.cts +11 -0
- package/dist/types-cjs/core/attribution.d.cts +48 -0
- package/dist/types-cjs/core/dev.d.cts +8 -2
- package/dist/types-cjs/core/scheduler.d.cts +5 -0
- package/dist/types-cjs/signals.d.cts +0 -11
- package/dist/types-cjs/store/next/target.d.cts +10 -0
- package/package.json +1 -1
|
@@ -2,7 +2,9 @@ import { CONFIG_AUTO_DISPOSE, STATUS_PENDING, NOT_PENDING, CONFIG_OPTIMISTIC, CO
|
|
|
2
2
|
|
|
3
3
|
import { computed, setSignal, isEqual } from "../../core/core.js";
|
|
4
4
|
|
|
5
|
-
import {
|
|
5
|
+
import { getOwner } from "../../core/owner.js";
|
|
6
|
+
|
|
7
|
+
import { activeTransition, GlobalQueue, currentTransition, globalQueue, createTransition, runAsTransitionBatch } from "../../core/scheduler.js";
|
|
6
8
|
|
|
7
9
|
import "../../core/invariants.js";
|
|
8
10
|
|
|
@@ -108,14 +110,22 @@ function installNextBlockedHalf() {
|
|
|
108
110
|
const e = GlobalQueue.dn;
|
|
109
111
|
GlobalQueue.dn = t => {
|
|
110
112
|
for (const e of t.En) {
|
|
111
|
-
const
|
|
112
|
-
const
|
|
113
|
+
const n = e?.[$TARGET];
|
|
114
|
+
const i = n?.fam;
|
|
115
|
+
const o = i?.node;
|
|
113
116
|
// The hold exists to keep optimistic state alive until the store's own
|
|
114
117
|
// truth lands (#2951). Once the family carries NO live overrides (a
|
|
115
118
|
// landing consumed them, or they never existed), a pending firewall is
|
|
116
119
|
// no reason to park the transaction — blocking then leaks it forever
|
|
117
120
|
// when the in-flight question is never answered (undisposed fixtures).
|
|
118
|
-
if (
|
|
121
|
+
if (o == null || !(o.S & STATUS_PENDING)) continue;
|
|
122
|
+
// Ownership is declared (#3146): only the flight's OWN transaction
|
|
123
|
+
// parks on the flight (the #2951 anchor routed the bare write there).
|
|
124
|
+
// A transaction that merely brushed the store never waits for truth
|
|
125
|
+
// it does not carry.
|
|
126
|
+
const r = i.ft != null ? liveTransition(i.ft) : null;
|
|
127
|
+
if (r !== null && r !== currentTransition(t)) continue;
|
|
128
|
+
if (familyHasLiveOverrides(i)) return true;
|
|
119
129
|
}
|
|
120
130
|
return e(t);
|
|
121
131
|
};
|
|
@@ -129,10 +139,10 @@ function familyHasLiveOverrides(e) {
|
|
|
129
139
|
if (t === null) continue;
|
|
130
140
|
for (const e of Reflect.ownKeys(t)) {
|
|
131
141
|
const n = t[e];
|
|
132
|
-
if (n.o?.
|
|
142
|
+
if (n.o?.Pe !== undefined && n.o?.Pe !== NOT_PENDING) return true;
|
|
133
143
|
}
|
|
134
144
|
}
|
|
135
|
-
if (e.k !== null && e.k.o?.
|
|
145
|
+
if (e.k !== null && e.k.o?.Pe !== undefined && e.k.o?.Pe !== NOT_PENDING) return true;
|
|
136
146
|
}
|
|
137
147
|
t.clear();
|
|
138
148
|
// nothing live — drop the bookkeeping
|
|
@@ -153,26 +163,47 @@ function createOptimisticStoreNext(e, t, n) {
|
|
|
153
163
|
shallow: !!n?.shallow,
|
|
154
164
|
opt: true
|
|
155
165
|
};
|
|
156
|
-
const
|
|
157
|
-
r.px =
|
|
166
|
+
const l = wrapNext(o, null, null, r);
|
|
167
|
+
r.px = l;
|
|
158
168
|
// Same key resolution the projection channels use ("id" default) — replay's
|
|
159
169
|
// satisfaction rule reads it off the family.
|
|
160
|
-
const
|
|
161
|
-
r.key = typeof
|
|
170
|
+
const s = n?.key === undefined ? "id" : n.key;
|
|
171
|
+
r.key = typeof s === "function" ? s : s === null ? null : e => isWrappable(e) ? e[s] : undefined;
|
|
162
172
|
if (r.shallow) {
|
|
163
|
-
|
|
173
|
+
l[$TARGET].s = true;
|
|
164
174
|
markRawIngest(o);
|
|
165
175
|
}
|
|
166
176
|
if (i) {
|
|
167
177
|
const t = e;
|
|
178
|
+
// #3146: an async settle event belongs to the flight's OWN transaction.
|
|
179
|
+
// A live declared one re-enters (a merge if the generic settle path
|
|
180
|
+
// already entered a graph-stamped stranger — the landing supersedes any
|
|
181
|
+
// recompute deriving from that stranger's world); a dead one renews (per
|
|
182
|
+
// A18(1) each arrival reveals on its own schedule, so per-yield
|
|
183
|
+
// transactions die with their commit and the next settle event opens the
|
|
184
|
+
// flight's next one — still declared, never anonymous). An UNDECLARED
|
|
185
|
+
// flight (loading window) keeps the ambient reveal (#2933: the loading
|
|
186
|
+
// rail is transaction-invisible).
|
|
187
|
+
const enterFlightTransition = () => {
|
|
188
|
+
const e = r.ft;
|
|
189
|
+
if (e == null) return;
|
|
190
|
+
let t = liveTransition(e);
|
|
191
|
+
if (t === null) r.ft = t = createTransition();
|
|
192
|
+
r.node.Ae = t;
|
|
193
|
+
globalQueue.initTransition(t);
|
|
194
|
+
};
|
|
168
195
|
// Landing router (#3164 fold ruling): while a transaction retains
|
|
169
196
|
// optimistic edits on this family, truth landings stage INTO it and
|
|
170
197
|
// reveal atomically at settle; with no retainer they commit immediately
|
|
171
198
|
// under the authoritative posture (async commits land outside the
|
|
172
|
-
// computed's sync body, so the posture is re-applied here)
|
|
199
|
+
// computed's sync body, so the posture is re-applied here) — inside the
|
|
200
|
+
// flight-owned transaction (#3146). Sync commits (the derive's body,
|
|
201
|
+
// owner is the firewall itself) reveal with their own recompute's flush.
|
|
173
202
|
const wrapCommit = (e, t) => {
|
|
174
203
|
const n = retainingTransition(r);
|
|
175
|
-
if (n
|
|
204
|
+
if (n !== null) return void stageLanding(r, n, t);
|
|
205
|
+
if (getOwner() !== r.node) enterFlightTransition();
|
|
206
|
+
runAuthoritative(e);
|
|
176
207
|
};
|
|
177
208
|
// Draft writes (the derive mutating its draft, sync body and post-await
|
|
178
209
|
// continuations alike) are the same truth channel per-operation: bind
|
|
@@ -184,24 +215,61 @@ function createOptimisticStoreNext(e, t, n) {
|
|
|
184
215
|
const t = retainingTransition(r);
|
|
185
216
|
if (t === null) e(); else runFolded(t, e);
|
|
186
217
|
};
|
|
218
|
+
// Flight declaration (#3146): a recompute that registered a truth-flight
|
|
219
|
+
// OWNS its transaction. The ask's transaction is recorded on the family
|
|
220
|
+
// (created by the flight's own pending throw when none was ambient, the
|
|
221
|
+
// causing write's/refresh's when one was — graph-driven causality) and
|
|
222
|
+
// the firewall is stamped so every settle path resolves the flight's
|
|
223
|
+
// transaction by construction, not by whatever last brushed the node.
|
|
224
|
+
// When the ask took none (a dead stale stamp — the previous flight's,
|
|
225
|
+
// cleared nowhere — bare-returns the pre-throw entry), the flight opens
|
|
226
|
+
// its own here, same activation point as the pre-throw's creation: the
|
|
227
|
+
// ambient batch (the causing write, same-tick bare optimism) adopts into
|
|
228
|
+
// it exactly as it would have there, and the pending notification that
|
|
229
|
+
// follows this unwind registers observers against it. The flight
|
|
230
|
+
// also registers as its own async reporter: the transaction lives
|
|
231
|
+
// exactly as long as the question is unanswered, observed or not — the
|
|
232
|
+
// #2951 refetch-hold no longer depends on a tracked observer having
|
|
233
|
+
// happened to register one. Loading-window flights declare nothing
|
|
234
|
+
// (#2933: the loading rail is transaction-invisible); a sync run clears
|
|
235
|
+
// the declaration.
|
|
236
|
+
const declareFlight = e => {
|
|
237
|
+
if (e.o?.Ie == null) {
|
|
238
|
+
if (!e.Ne) r.ft = null;
|
|
239
|
+
return;
|
|
240
|
+
}
|
|
241
|
+
if (e.Ne) return;
|
|
242
|
+
let t = activeTransition;
|
|
243
|
+
if (t === null) globalQueue.initTransition(t = createTransition());
|
|
244
|
+
r.ft = t;
|
|
245
|
+
e.Ae = t;
|
|
246
|
+
let n = t._e.get(e);
|
|
247
|
+
if (n === undefined) t._e.set(e, n = new Set);
|
|
248
|
+
n.add(e);
|
|
249
|
+
};
|
|
187
250
|
let i;
|
|
188
251
|
if (n?.seedLoadingValue) i = {
|
|
189
252
|
loadingValue: undefined
|
|
190
253
|
};
|
|
191
254
|
const o = computed(() => {
|
|
192
|
-
|
|
255
|
+
const e = getOwner();
|
|
256
|
+
try {
|
|
257
|
+
runAuthoritative(() => runProjectionComputedNext(l, t, n?.key === undefined ? "id" : n.key, wrapCommit, aroundDraftWrite));
|
|
258
|
+
} finally {
|
|
259
|
+
declareFlight(e);
|
|
260
|
+
}
|
|
193
261
|
}, i);
|
|
194
262
|
o.T &= ~CONFIG_AUTO_DISPOSE;
|
|
195
263
|
r.node = o;
|
|
196
264
|
}
|
|
197
|
-
return [
|
|
265
|
+
return [ l, e => {
|
|
198
266
|
// Retention ledger (#3164): record the owning transaction so landings
|
|
199
267
|
// know to fold. Captured at entry — the action machinery has the
|
|
200
268
|
// transaction ambient while user code runs; a bare write with no
|
|
201
269
|
// transaction retains nothing (it rides the flight's own transition
|
|
202
270
|
// per #2951 and dies with it).
|
|
203
271
|
const t = activeTransition;
|
|
204
|
-
storeSetterNext(
|
|
272
|
+
storeSetterNext(l, e);
|
|
205
273
|
if (t !== null) (r.rt ??= new Set).add(t);
|
|
206
274
|
} ];
|
|
207
275
|
}
|
|
@@ -281,8 +349,8 @@ function createOptimisticStoreNext(e, t, n) {
|
|
|
281
349
|
if (!isWrappable(i)) continue;
|
|
282
350
|
const r = n(i);
|
|
283
351
|
if (r === undefined) continue;
|
|
284
|
-
const
|
|
285
|
-
if (
|
|
352
|
+
const l = (o ??= new Map).get(r);
|
|
353
|
+
if (l === undefined) o.set(r, [ i ]); else l.push(i);
|
|
286
354
|
}
|
|
287
355
|
// Echo adoption: an optimistic structural add whose key the landing
|
|
288
356
|
// confirms must keep its raw (and so its proxy — list drivers keep the
|
|
@@ -292,35 +360,35 @@ function createOptimisticStoreNext(e, t, n) {
|
|
|
292
360
|
// keys; overlay rows only extend coverage. Adopted raws enter staged
|
|
293
361
|
// truth; at settle the override reverts and the reveal re-seats the
|
|
294
362
|
// same raw.
|
|
295
|
-
const
|
|
296
|
-
if (
|
|
297
|
-
for (const e of Reflect.ownKeys(
|
|
298
|
-
const t =
|
|
363
|
+
const l = e[$TARGET]?.n;
|
|
364
|
+
if (l != null) {
|
|
365
|
+
for (const e of Reflect.ownKeys(l)) {
|
|
366
|
+
const t = l[e];
|
|
299
367
|
if (!hasActiveOverride(t)) continue;
|
|
300
|
-
const i = unwrapValue(unwrapOverride(t.o.
|
|
368
|
+
const i = unwrapValue(unwrapOverride(t.o.Pe));
|
|
301
369
|
if (!isWrappable(i)) continue;
|
|
302
370
|
const r = n(i);
|
|
303
371
|
if (r === undefined) continue;
|
|
304
|
-
const
|
|
305
|
-
if (
|
|
372
|
+
const s = (o ??= new Map).get(r);
|
|
373
|
+
if (s === undefined) o.set(r, [ i ]); else s.push(i);
|
|
306
374
|
}
|
|
307
375
|
}
|
|
308
376
|
for (let r = 0; r < i; r++) {
|
|
309
377
|
const i = t[r];
|
|
310
|
-
let
|
|
378
|
+
let l;
|
|
311
379
|
if (isWrappable(i) && o !== null) {
|
|
312
380
|
const e = n(i);
|
|
313
381
|
if (e !== undefined) {
|
|
314
382
|
for (const [t, n] of o) {
|
|
315
383
|
if (!sameKey(t, e)) continue;
|
|
316
|
-
|
|
384
|
+
l = n.shift();
|
|
317
385
|
if (n.length === 0) o.delete(t);
|
|
318
386
|
break;
|
|
319
387
|
}
|
|
320
388
|
}
|
|
321
389
|
}
|
|
322
|
-
if (
|
|
323
|
-
if (unwrapValue(e[r]) !==
|
|
390
|
+
if (l !== undefined) {
|
|
391
|
+
if (unwrapValue(e[r]) !== l) e[r] = l;
|
|
324
392
|
stagedApply(e[r], i, n);
|
|
325
393
|
} else {
|
|
326
394
|
const t = unwrapValue(e[r]);
|
|
@@ -343,13 +411,13 @@ function createOptimisticStoreNext(e, t, n) {
|
|
|
343
411
|
for (const o of Reflect.ownKeys(t)) {
|
|
344
412
|
if (i && o === "length") continue;
|
|
345
413
|
const r = t[o];
|
|
346
|
-
const
|
|
347
|
-
if (
|
|
348
|
-
if (isWrappable(r) && isWrappable(
|
|
414
|
+
const l = unwrapValue(e[o]);
|
|
415
|
+
if (l === r) continue;
|
|
416
|
+
if (isWrappable(r) && isWrappable(l) && Array.isArray(r) === Array.isArray(l)) {
|
|
349
417
|
// Different-keyed entities never merge (tentative-channel parity):
|
|
350
418
|
// the incoming object replaces the slot wholesale.
|
|
351
419
|
if (n !== null) {
|
|
352
|
-
const t = n(
|
|
420
|
+
const t = n(l);
|
|
353
421
|
const i = n(r);
|
|
354
422
|
if (t !== undefined && i !== undefined && !sameKey(t, i)) {
|
|
355
423
|
e[o] = r;
|
|
@@ -357,7 +425,7 @@ function createOptimisticStoreNext(e, t, n) {
|
|
|
357
425
|
}
|
|
358
426
|
}
|
|
359
427
|
stagedApply(e[o], r, n);
|
|
360
|
-
} else if (!isEqual(
|
|
428
|
+
} else if (!isEqual(l, r) && !targetsEqual(l, r)) {
|
|
361
429
|
e[o] = r;
|
|
362
430
|
}
|
|
363
431
|
}
|
|
@@ -373,13 +441,18 @@ function createOptimisticStoreNext(e, t, n) {
|
|
|
373
441
|
* overrides — the same view the draft was seeded from) and emit engine writes
|
|
374
442
|
* for exactly the changed keys. Visible-view diffing keeps no-op writes from
|
|
375
443
|
* entangling lanes (RUL-10 / opt R38). */ function notifyOptimisticWrites(e, t) {
|
|
376
|
-
// A bare write while the store's own truth is in flight rides
|
|
377
|
-
// transaction (#2951
|
|
378
|
-
//
|
|
444
|
+
// A bare write while the store's own truth is in flight rides the FLIGHT'S
|
|
445
|
+
// OWN transaction (#2951 via the #3146 declaration): entangle it so the
|
|
446
|
+
// override survives until the refetch settles instead of flash-reverting
|
|
379
447
|
// at plain flush end. The blocked-check store-half keeps that transaction
|
|
380
|
-
// from settling while the firewall is pending.
|
|
381
|
-
|
|
382
|
-
|
|
448
|
+
// from settling while the firewall is pending. Declared ownership replaces
|
|
449
|
+
// the old circumstantial route through the firewall's `_transition` stamp,
|
|
450
|
+
// which was whatever last brushed the node.
|
|
451
|
+
const n = e.fam?.ft;
|
|
452
|
+
if (n != null) {
|
|
453
|
+
const e = liveTransition(n);
|
|
454
|
+
if (e !== null) globalQueue.initTransition(e);
|
|
455
|
+
}
|
|
383
456
|
const i = e.v;
|
|
384
457
|
// Patch channel (override-application site): the draft IS the intended
|
|
385
458
|
// visible state; prev is the view before these overrides apply. Bypasses
|
|
@@ -398,26 +471,26 @@ function createOptimisticStoreNext(e, t, n) {
|
|
|
398
471
|
}
|
|
399
472
|
const visible = (t, n) => {
|
|
400
473
|
const i = e.n?.[t];
|
|
401
|
-
return i !== undefined && hasActiveOverride(i) ? unwrapOverride(i.o?.
|
|
474
|
+
return i !== undefined && hasActiveOverride(i) ? unwrapOverride(i.o?.Pe) : n;
|
|
402
475
|
};
|
|
403
476
|
const visiblePresent = t => {
|
|
404
477
|
const n = e.h?.[t];
|
|
405
|
-
return n !== undefined && hasActiveOverride(n) ? !!unwrapOverride(n.o?.
|
|
478
|
+
return n !== undefined && hasActiveOverride(n) ? !!unwrapOverride(n.o?.Pe) : t in i;
|
|
406
479
|
};
|
|
407
480
|
let o = false;
|
|
408
481
|
const r = Array.isArray(t);
|
|
409
482
|
for (const n of Reflect.ownKeys(t)) {
|
|
410
483
|
if (r && n === "length") continue;
|
|
411
|
-
const
|
|
484
|
+
const l = unwrapValue(t[n]);
|
|
412
485
|
if (!visiblePresent(n)) {
|
|
413
486
|
// Optimistic add: value node + presence node + membership bump.
|
|
414
|
-
setSignal(getNode(e, n, i[n]), () =>
|
|
487
|
+
setSignal(getNode(e, n, i[n]), () => l);
|
|
415
488
|
setSignal(getHasNode(e, n, n in i), true);
|
|
416
489
|
o = true;
|
|
417
490
|
} else {
|
|
418
491
|
const t = visible(n, i[n]);
|
|
419
|
-
if (!isEqual(t,
|
|
420
|
-
setSignal(getNode(e, n, t), () =>
|
|
492
|
+
if (!isEqual(t, l) && !targetsEqual(t, l)) {
|
|
493
|
+
setSignal(getNode(e, n, t), () => l);
|
|
421
494
|
if (r) o = true;
|
|
422
495
|
}
|
|
423
496
|
}
|
|
@@ -467,7 +540,7 @@ function createOptimisticStoreNext(e, t, n) {
|
|
|
467
540
|
for (const e of Reflect.ownKeys(i)) {
|
|
468
541
|
const n = i[e];
|
|
469
542
|
if (!hasActiveOverride(n)) continue;
|
|
470
|
-
const o = unwrapOverride(n.o?.
|
|
543
|
+
const o = unwrapOverride(n.o?.Pe);
|
|
471
544
|
if (e === "length" && Array.isArray(t)) {
|
|
472
545
|
if (t.length !== o) ensure().length = o;
|
|
473
546
|
} else if (!isEqual(t[e], o)) ensure()[e] = o;
|
|
@@ -478,7 +551,7 @@ function createOptimisticStoreNext(e, t, n) {
|
|
|
478
551
|
for (const e of Reflect.ownKeys(o)) {
|
|
479
552
|
const i = o[e];
|
|
480
553
|
if (!hasActiveOverride(i)) continue;
|
|
481
|
-
const r = !!unwrapOverride(i.o?.
|
|
554
|
+
const r = !!unwrapOverride(i.o?.Pe);
|
|
482
555
|
if (!r && e in (n ?? t)) delete ensure()[e];
|
|
483
556
|
}
|
|
484
557
|
}
|
|
@@ -489,11 +562,11 @@ function applyTentative(e, t, n) {
|
|
|
489
562
|
const i = e.pb ?? e.v;
|
|
490
563
|
const o = optimisticView(e, i);
|
|
491
564
|
const r = e.fam.map;
|
|
492
|
-
const
|
|
493
|
-
if (Array.isArray(o) !==
|
|
565
|
+
const l = Array.isArray(t);
|
|
566
|
+
if (Array.isArray(o) !== l) return;
|
|
494
567
|
// kind change at root: flat overrides below
|
|
495
|
-
const
|
|
496
|
-
const u =
|
|
568
|
+
const s = [];
|
|
569
|
+
const u = l ? [ ...t ] : shallowWithSymbols(t);
|
|
497
570
|
const match = (e, t) => {
|
|
498
571
|
if (!isWrappable(e) || !isWrappable(t)) return null;
|
|
499
572
|
if (rawValuesUsed && (isRawValue(e) || isRawValue(t))) return null;
|
|
@@ -507,13 +580,13 @@ function applyTentative(e, t, n) {
|
|
|
507
580
|
}
|
|
508
581
|
return r.get(unwrapValue(e)) ?? null;
|
|
509
582
|
};
|
|
510
|
-
if (
|
|
583
|
+
if (l) {
|
|
511
584
|
const e = o;
|
|
512
585
|
let i = null;
|
|
513
586
|
for (let o = 0; o < t.length; o++) {
|
|
514
587
|
const r = t[o];
|
|
515
588
|
if (!isWrappable(r)) continue;
|
|
516
|
-
let
|
|
589
|
+
let l;
|
|
517
590
|
if (n) {
|
|
518
591
|
const t = n(r);
|
|
519
592
|
if (t !== undefined) {
|
|
@@ -533,20 +606,20 @@ function applyTentative(e, t, n) {
|
|
|
533
606
|
}
|
|
534
607
|
}
|
|
535
608
|
const o = i.get(t);
|
|
536
|
-
if (o === undefined)
|
|
537
|
-
|
|
609
|
+
if (o === undefined) l = undefined; else if (Array.isArray(o)) {
|
|
610
|
+
l = unwrapValue(e[o.shift()]);
|
|
538
611
|
if (o.length === 1) i.set(t, o[0]);
|
|
539
612
|
} else {
|
|
540
|
-
|
|
613
|
+
l = unwrapValue(e[o]);
|
|
541
614
|
i.delete(t);
|
|
542
615
|
}
|
|
543
|
-
} else
|
|
544
|
-
} else
|
|
545
|
-
const a = match(
|
|
616
|
+
} else l = unwrapValue(e[o]);
|
|
617
|
+
} else l = unwrapValue(e[o]);
|
|
618
|
+
const a = match(l, r);
|
|
546
619
|
if (a !== null) {
|
|
547
620
|
// Keep the existing row in the slot (identity preserved); recurse.
|
|
548
|
-
u[o] = unwrapValue(
|
|
549
|
-
|
|
621
|
+
u[o] = unwrapValue(l);
|
|
622
|
+
s.push([ a, r ]);
|
|
550
623
|
}
|
|
551
624
|
}
|
|
552
625
|
} else {
|
|
@@ -556,7 +629,7 @@ function applyTentative(e, t, n) {
|
|
|
556
629
|
const r = match(n, i);
|
|
557
630
|
if (r !== null) {
|
|
558
631
|
u[e] = n;
|
|
559
|
-
|
|
632
|
+
s.push([ r, i ]);
|
|
560
633
|
}
|
|
561
634
|
}
|
|
562
635
|
}
|
|
@@ -566,7 +639,7 @@ function applyTentative(e, t, n) {
|
|
|
566
639
|
e.pb = null;
|
|
567
640
|
notifyOptimisticWrites(e, u);
|
|
568
641
|
e.pb = a;
|
|
569
|
-
for (let e = 0; e <
|
|
642
|
+
for (let e = 0; e < s.length; e++) applyTentative(s[e][0], unwrapValue(s[e][1]), n);
|
|
570
643
|
}
|
|
571
644
|
|
|
572
645
|
function shallowWithSymbols(e) {
|
|
@@ -12,11 +12,11 @@ import "../../core/effect.js";
|
|
|
12
12
|
|
|
13
13
|
import { CONFIG_AUTO_DISPOSE } from "../../core/constants.js";
|
|
14
14
|
|
|
15
|
-
import { $TARGET,
|
|
15
|
+
import { $TARGET, STORE_VALUE, markRawIngest, setWriteOverride } from "../store.js";
|
|
16
16
|
|
|
17
17
|
import { reconcileNextState } from "./reconcile.js";
|
|
18
18
|
|
|
19
|
-
import {
|
|
19
|
+
import { storeSetterNext, wrapNext } from "./store.js";
|
|
20
20
|
|
|
21
21
|
/**
|
|
22
22
|
* Store rewrite — projections (§7/§7b): a projection is a computed store.
|