@solidjs/signals 2.0.0-rc.15 → 2.0.0-rc.16

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.
Files changed (89) hide show
  1. package/dist/dev-shared.js +785 -367
  2. package/dist/dev.attribution.js +75 -52
  3. package/dist/dev.js +1120 -567
  4. package/dist/observe/affects-marks.js +86 -0
  5. package/dist/observe/affects.js +22 -73
  6. package/dist/observe/boundaries.js +191 -189
  7. package/dist/observe/core/async.js +175 -131
  8. package/dist/observe/core/attribution-queries.js +1 -1
  9. package/dist/observe/core/attribution.js +176 -159
  10. package/dist/observe/core/constants.js +17 -3
  11. package/dist/observe/core/context.js +3 -3
  12. package/dist/observe/core/core.js +503 -363
  13. package/dist/observe/core/dev.js +66 -38
  14. package/dist/observe/core/effect.js +48 -48
  15. package/dist/observe/core/error.js +5 -3
  16. package/dist/observe/core/external.js +5 -6
  17. package/dist/observe/core/graph.js +57 -43
  18. package/dist/observe/core/heap.js +33 -33
  19. package/dist/observe/core/identities.js +62 -0
  20. package/dist/observe/core/lanes.js +226 -259
  21. package/dist/observe/core/owner.js +62 -50
  22. package/dist/observe/core/scheduler.js +319 -171
  23. package/dist/observe/core/truth.js +45 -0
  24. package/dist/observe/core/verdict.js +88 -50
  25. package/dist/observe/deferred.js +184 -0
  26. package/dist/observe/index.js +7 -1
  27. package/dist/observe/map.js +345 -260
  28. package/dist/observe/reveal.js +76 -76
  29. package/dist/observe/signals.js +41 -30
  30. package/dist/observe/store/affects.js +6 -6
  31. package/dist/observe/store/edges.js +39 -0
  32. package/dist/observe/store/optimistic.js +41 -36
  33. package/dist/observe/store/projection.js +68 -55
  34. package/dist/observe/store/store.js +157 -104
  35. package/dist/prod/affects-marks.js +86 -0
  36. package/dist/prod/affects.js +23 -72
  37. package/dist/prod/boundaries.js +155 -153
  38. package/dist/prod/core/async.js +171 -127
  39. package/dist/prod/core/constants.js +17 -3
  40. package/dist/prod/core/context.js +3 -3
  41. package/dist/prod/core/core.js +478 -342
  42. package/dist/prod/core/effect.js +68 -68
  43. package/dist/prod/core/error.js +5 -3
  44. package/dist/prod/core/external.js +5 -6
  45. package/dist/prod/core/graph.js +57 -43
  46. package/dist/prod/core/heap.js +38 -38
  47. package/dist/prod/core/identities.js +62 -0
  48. package/dist/prod/core/lanes.js +217 -250
  49. package/dist/prod/core/owner.js +62 -51
  50. package/dist/prod/core/scheduler.js +310 -162
  51. package/dist/prod/core/truth.js +45 -0
  52. package/dist/prod/core/verdict.js +87 -49
  53. package/dist/prod/deferred.js +182 -0
  54. package/dist/prod/index.js +7 -1
  55. package/dist/prod/map.js +360 -275
  56. package/dist/prod/reveal.js +76 -76
  57. package/dist/prod/signals.js +41 -30
  58. package/dist/prod/store/affects.js +6 -6
  59. package/dist/prod/store/edges.js +39 -0
  60. package/dist/prod/store/optimistic.js +37 -33
  61. package/dist/prod/store/projection.js +25 -19
  62. package/dist/prod/store/store.js +142 -96
  63. package/dist/types/affects-marks.d.ts +14 -0
  64. package/dist/types/boundaries.d.ts +1 -1
  65. package/dist/types/core/async.d.ts +10 -0
  66. package/dist/types/core/constants.d.ts +13 -1
  67. package/dist/types/core/core.d.ts +44 -2
  68. package/dist/types/core/dev.d.ts +43 -13
  69. package/dist/types/core/graph.d.ts +11 -0
  70. package/dist/types/core/identities.d.ts +17 -0
  71. package/dist/types/core/index.d.ts +2 -1
  72. package/dist/types/core/lanes.d.ts +2 -14
  73. package/dist/types/core/owner.d.ts +5 -3
  74. package/dist/types/core/scheduler.d.ts +47 -28
  75. package/dist/types/core/truth.d.ts +16 -0
  76. package/dist/types/core/types.d.ts +21 -0
  77. package/dist/types/core/verdict.d.ts +32 -0
  78. package/dist/types/deferred.d.ts +28 -0
  79. package/dist/types/index.d.ts +6 -0
  80. package/dist/types/map.d.ts +2 -2
  81. package/dist/types/signals.d.ts +28 -7
  82. package/dist/types/store/edges.d.ts +9 -0
  83. package/dist/types/store/index.d.ts +10 -3
  84. package/dist/types/store/optimistic.d.ts +3 -2
  85. package/dist/types/store/projection.d.ts +4 -3
  86. package/dist/types/store/store.d.ts +1 -1
  87. package/dist/types/store/target.d.ts +16 -8
  88. package/dist/types/store/types.d.ts +14 -0
  89. package/package.json +1 -1
@@ -2,7 +2,7 @@ import { CONFIG_OVERRIDE, CONFIG_AUTO_DISPOSE, NOT_PENDING } from "../core/const
2
2
 
3
3
  import { computed, ext, untrack, read, isEqual } from "../core/core.js";
4
4
 
5
- import { pendingGuessOf, laneValueOf, optimisticWrite } from "../core/lanes.js";
5
+ import { pendingGuessOf, optimisticWrite } from "../core/lanes.js";
6
6
 
7
7
  import { getOwner } from "../core/owner.js";
8
8
 
@@ -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.Ae = i ? n in t : unwrapValue(t[n]);
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
  };
@@ -185,7 +187,7 @@ function rowSame(e, n, t) {
185
187
 
186
188
  // A cycle (a row that references itself) is not plain data: no match, so
187
189
  // the landing stays a correction.
188
- GlobalQueue.tn = (e, n) => {
190
+ GlobalQueue.nn = (e, n) => {
189
191
  try {
190
192
  return echoes(e, n);
191
193
  } catch {
@@ -267,9 +269,9 @@ function arrangementEqual(e, n, t) {
267
269
  * committed length differs, and as the `LaneView`'s base for structural
268
270
  * reads. Unkeyed families compose
269
271
  * 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;
272
+ const t = e.O;
273
+ if (t === undefined || e.ze !== $TRACK) return;
274
+ const i = e.T.v;
273
275
  if (!(i instanceof LaneView)) return;
274
276
  if (!Array.isArray(n) || !Array.isArray(i.rows)) {
275
277
  i.base = n;
@@ -313,7 +315,7 @@ function arrangementEqual(e, n, t) {
313
315
  // key's new object is the same row, its target adopted it).
314
316
  if (n === undefined) {
315
317
  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);
318
+ } else if (!sameRow(n.l & CONFIG_OVERRIDE ? n.T.v : c[e], a[e], r)) laneSet(n, a[e], l);
317
319
  }
318
320
  if (d !== null) {
319
321
  for (let e = a.length; ;e++) {
@@ -322,7 +324,7 @@ function arrangementEqual(e, n, t) {
322
324
  laneSet(n, undefined, l);
323
325
  }
324
326
  const e = d.length;
325
- if (e !== undefined && (e.i & CONFIG_OVERRIDE || c.length !== a.length)) laneSet(e, a.length, l);
327
+ if (e !== undefined && (e.l & CONFIG_OVERRIDE || c.length !== a.length)) laneSet(e, a.length, l);
326
328
  }
327
329
  };
328
330
 
@@ -337,12 +339,12 @@ function sameRow(e, n, t) {
337
339
  * node that was not the lane's becomes its derivation (its committed value
338
340
  * untouched beneath; the lane's end commits the latest). */ function laneSet(e, n, t) {
339
341
  const i = ext(e);
340
- if (!(e.i & CONFIG_OVERRIDE)) {
341
- e.i |= CONFIG_OVERRIDE;
342
+ if (!(e.l & CONFIG_OVERRIDE)) {
343
+ e.l |= CONFIG_OVERRIDE;
342
344
  list(e, t);
343
- } else if (i.B === n) return;
344
- i.B = n;
345
- if (e.t !== null) {
345
+ } else if (i.v === n) return;
346
+ i.v = n;
347
+ if (e.o !== null) {
346
348
  insertSubs(e);
347
349
  laneDirty(e, t);
348
350
  }
@@ -387,7 +389,7 @@ function sweepOverlaid() {
387
389
  // The container shows its backing again (a shown arrangement guess
388
390
  // that ended without a landing left its `LaneView` as the value).
389
391
  const t = e.k;
390
- if (t !== null && t.Ae instanceof LaneView) t.Ae = t.Ae.base;
392
+ if (t !== null && t.Ie instanceof LaneView) t.Ie = t.Ie.base;
391
393
  }
392
394
  if (n.size === 0) overlaidFamilies.delete(e);
393
395
  }
@@ -404,11 +406,11 @@ function sweepOverlaid() {
404
406
  if (i !== null) for (const e of Reflect.ownKeys(i)) {
405
407
  const r = i[e];
406
408
  const o = untrack(() => unwrapValue(n[e]));
407
- if (r.ye && r.ye(r.Ae, o)) continue;
408
- r.Ae = o;
409
+ if (r.xe && r.xe(r.Ie, o)) continue;
410
+ r.Ie = o;
409
411
  // (The lane's end notified it this epoch when the shown value and the
410
412
  // covered one differed — its readers re-derive already.)
411
- if (r.t !== null && r.qe !== notifyEpoch) {
413
+ if (r.o !== null && r.Me !== notifyEpoch) {
412
414
  insertSubs(r);
413
415
  t = true;
414
416
  }
@@ -417,9 +419,9 @@ function sweepOverlaid() {
417
419
  if (r !== null) for (const e of Reflect.ownKeys(r)) {
418
420
  const i = r[e];
419
421
  const o = untrack(() => e in n);
420
- if (i.Ae === o) continue;
421
- i.Ae = o;
422
- if (i.t !== null && i.qe !== notifyEpoch) {
422
+ if (i.Ie === o) continue;
423
+ i.Ie = o;
424
+ if (i.o !== null && i.Me !== notifyEpoch) {
423
425
  insertSubs(i);
424
426
  t = true;
425
427
  }
@@ -427,9 +429,9 @@ function sweepOverlaid() {
427
429
  // The arrangement the readers saw (the shown guess) against the inner's
428
430
  // now: a structural reader re-derives when they differ.
429
431
  const o = e.k;
430
- if (o !== null && o.t !== null && o.Ae instanceof LaneView && o.qe !== notifyEpoch) {
432
+ if (o !== null && o.o !== null && o.Ie instanceof LaneView && o.Me !== notifyEpoch) {
431
433
  const i = Array.isArray(n) ? untrack(() => n.map(unwrapValue)) : n;
432
- if (!arrangementEqual(o.Ae.rows, i, e.fam?.key ?? null)) {
434
+ if (!arrangementEqual(o.Ie.rows, i, e.fam?.key ?? null)) {
433
435
  insertSubs(o);
434
436
  t = true;
435
437
  }
@@ -438,12 +440,12 @@ function sweepOverlaid() {
438
440
  }
439
441
 
440
442
  function carriesLane(e) {
441
- if (e.k !== null && e.k.i & CONFIG_OVERRIDE) return true;
442
- if (e.dk !== null && e.dk.i & CONFIG_OVERRIDE) return true;
443
+ if (e.k !== null && e.k.l & CONFIG_OVERRIDE) return true;
444
+ if (e.dk !== null && e.dk.l & CONFIG_OVERRIDE) return true;
443
445
  const n = e.n;
444
- if (n !== null) for (const e of Reflect.ownKeys(n)) if (n[e].i & CONFIG_OVERRIDE) return true;
446
+ if (n !== null) for (const e of Reflect.ownKeys(n)) if (n[e].l & CONFIG_OVERRIDE) return true;
445
447
  const t = e.h;
446
- if (t !== null) for (const e of Reflect.ownKeys(t)) if (t[e].i & CONFIG_OVERRIDE) return true;
448
+ if (t !== null) for (const e of Reflect.ownKeys(t)) if (t[e].l & CONFIG_OVERRIDE) return true;
447
449
  return false;
448
450
  }
449
451
 
@@ -461,9 +463,9 @@ function overlaid(e) {
461
463
  * the backing answers. */ function optimisticHas(e, n) {
462
464
  if (!overlaid(e)) return undefined;
463
465
  const t = e.h?.[n];
464
- if (t !== undefined && t.i & CONFIG_OVERRIDE) return !!shown(t);
466
+ if (t !== undefined && t.l & CONFIG_OVERRIDE) return !!shown(t);
465
467
  const i = e.n?.[n];
466
- if (i !== undefined && i.i & CONFIG_OVERRIDE) return shown(i) !== undefined;
468
+ if (i !== undefined && i.l & CONFIG_OVERRIDE) return shown(i) !== undefined;
467
469
  return undefined;
468
470
  }
469
471
 
@@ -474,7 +476,7 @@ function overlaid(e) {
474
476
  if (t === undefined) return undefined;
475
477
  if (!t) return null;
476
478
  const i = e.n?.[n];
477
- const r = i !== undefined && i.i & CONFIG_OVERRIDE ? shown(i) : e.v[n];
479
+ const r = i !== undefined && i.l & CONFIG_OVERRIDE ? shown(i) : e.v[n];
478
480
  // An array's `length` is reported as the array has it (non-configurable).
479
481
  if (n === "length" && Array.isArray(e.v)) return {
480
482
  value: r,
@@ -507,7 +509,7 @@ i = false) {
507
509
  for (const e of Reflect.ownKeys(o)) {
508
510
  const r = o[e];
509
511
  let s;
510
- if (r.i & CONFIG_OVERRIDE) s = t(r); else if (!i || (s = pendingGuessOf(r)) === NOT_PENDING) continue;
512
+ if (r.l & CONFIG_OVERRIDE) s = t(r); else if (!i || (s = pendingGuessOf(r)) === NOT_PENDING) continue;
511
513
  if (e === "length" && Array.isArray(n)) {
512
514
  if (n.length !== s) ensure().length = s;
513
515
  } else if (!isEqual(n[e], s) || !hasOwn.call(n, e)) {
@@ -520,7 +522,7 @@ i = false) {
520
522
  for (const e of Reflect.ownKeys(s)) {
521
523
  const o = s[e];
522
524
  let a;
523
- if (o.i & CONFIG_OVERRIDE) a = t(o); else if (!i || (a = pendingGuessOf(o)) === NOT_PENDING) continue;
525
+ if (o.l & CONFIG_OVERRIDE) a = t(o); else if (!i || (a = pendingGuessOf(o)) === NOT_PENDING) continue;
524
526
  const f = !!a;
525
527
  const u = r ?? n;
526
528
  if (!f && e in u) delete ensure()[e];
@@ -532,7 +534,9 @@ i = false) {
532
534
  function createOptimisticStore(e, n, t) {
533
535
  const i = typeof e === "function";
534
536
  const r = i ? t : n;
535
- const o = i ? n : e;
537
+ // Seedless derived form: the root starts as an empty record (see
538
+ // createProjectionInternal).
539
+ const o = i ? n || {} : e;
536
540
  const s = r?.key === undefined ? "id" : r.key;
537
541
  const a = {
538
542
  map: new WeakMap,
@@ -557,7 +561,7 @@ function createOptimisticStore(e, n, t) {
557
561
  if (!a.node) a.node = getOwner();
558
562
  runProjectionComputed(f, n, s);
559
563
  }, t);
560
- i.i &= ~CONFIG_AUTO_DISPOSE;
564
+ i.l &= ~CONFIG_AUTO_DISPOSE;
561
565
  a.node = i;
562
566
  }
563
567
  return [ f, e => storeSetter(f, e) ];
@@ -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, setWriteOverride, isWrappable } from "./types.js";
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.t === null) return;
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.t === null) return;
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.t !== null) settlePendingSource(e, t);
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.De ? cloneState(s.v, s.s) : null;
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.m !== null && i.m.Te !== null ? i.m._e : 0);
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.S & STATUS_PENDING) && !i.De) schedule();
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.S & STATUS_UNINITIALIZED)) settleFamily(c);
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.S & STATUS_UNINITIALIZED) return;
236
+ if (d && i.m & STATUS_UNINITIALIZED) return;
232
237
  if (t) wakeFamily(c, e); else errorFamily(c);
233
238
  });
234
- if (!i.De) commit(u);
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.S & STATUS_PENDING && i.m.Te !== null && !i.De && !d) wakeFamily(c, i.m?.F);
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.i &= ~CONFIG_AUTO_DISPOSE;
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