@solidjs/signals 2.0.0-rc.3 → 2.0.0-rc.5

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 (71) hide show
  1. package/dist/dev.js +2494 -271
  2. package/dist/node.cjs +3691 -1595
  3. package/dist/prod/affects.js +13 -12
  4. package/dist/prod/boundaries.js +43 -35
  5. package/dist/prod/core/action.js +3 -3
  6. package/dist/prod/core/async.js +137 -106
  7. package/dist/prod/core/constants.js +55 -1
  8. package/dist/prod/core/core.js +354 -247
  9. package/dist/prod/core/effect.js +47 -50
  10. package/dist/prod/core/error.js +13 -1
  11. package/dist/prod/core/external.js +4 -4
  12. package/dist/prod/core/graph.js +88 -52
  13. package/dist/prod/core/heap.js +38 -38
  14. package/dist/prod/core/lanes.js +34 -34
  15. package/dist/prod/core/optimistic.js +61 -58
  16. package/dist/prod/core/owner.js +38 -38
  17. package/dist/prod/core/scheduler.js +401 -174
  18. package/dist/prod/core/verdict.js +132 -65
  19. package/dist/prod/index.js +7 -3
  20. package/dist/prod/map.js +106 -106
  21. package/dist/prod/signals.js +253 -25
  22. package/dist/prod/store/index.js +2 -0
  23. package/dist/prod/store/next/optimistic.js +314 -121
  24. package/dist/prod/store/next/patch-hooks.js +13 -0
  25. package/dist/prod/store/next/patch.js +614 -0
  26. package/dist/prod/store/next/projection.js +23 -19
  27. package/dist/prod/store/next/reconcile.js +307 -120
  28. package/dist/prod/store/next/store.js +440 -117
  29. package/dist/prod/store/next/target.js +13 -4
  30. package/dist/prod/store/store.js +5 -5
  31. package/dist/types/core/async.d.ts +2 -0
  32. package/dist/types/core/attribution.d.ts +9 -4
  33. package/dist/types/core/constants.d.ts +54 -0
  34. package/dist/types/core/core.d.ts +34 -21
  35. package/dist/types/core/dev.d.ts +8 -0
  36. package/dist/types/core/error.d.ts +9 -0
  37. package/dist/types/core/graph.d.ts +22 -0
  38. package/dist/types/core/index.d.ts +2 -2
  39. package/dist/types/core/scheduler.d.ts +46 -0
  40. package/dist/types/core/types.d.ts +12 -0
  41. package/dist/types/index.d.ts +3 -3
  42. package/dist/types/signals.d.ts +108 -0
  43. package/dist/types/store/index.d.ts +2 -0
  44. package/dist/types/store/next/optimistic.d.ts +13 -10
  45. package/dist/types/store/next/patch-hooks.d.ts +41 -0
  46. package/dist/types/store/next/patch.d.ts +91 -0
  47. package/dist/types/store/next/projection.d.ts +1 -1
  48. package/dist/types/store/next/reconcile.d.ts +14 -0
  49. package/dist/types/store/next/store.d.ts +52 -2
  50. package/dist/types/store/next/target.d.ts +73 -8
  51. package/dist/types-cjs/core/async.d.cts +2 -0
  52. package/dist/types-cjs/core/attribution.d.cts +9 -4
  53. package/dist/types-cjs/core/constants.d.cts +54 -0
  54. package/dist/types-cjs/core/core.d.cts +34 -21
  55. package/dist/types-cjs/core/dev.d.cts +8 -0
  56. package/dist/types-cjs/core/error.d.cts +9 -0
  57. package/dist/types-cjs/core/graph.d.cts +22 -0
  58. package/dist/types-cjs/core/index.d.cts +2 -2
  59. package/dist/types-cjs/core/scheduler.d.cts +46 -0
  60. package/dist/types-cjs/core/types.d.cts +12 -0
  61. package/dist/types-cjs/index.d.cts +3 -3
  62. package/dist/types-cjs/signals.d.cts +108 -0
  63. package/dist/types-cjs/store/index.d.cts +2 -0
  64. package/dist/types-cjs/store/next/optimistic.d.cts +13 -10
  65. package/dist/types-cjs/store/next/patch-hooks.d.cts +41 -0
  66. package/dist/types-cjs/store/next/patch.d.cts +91 -0
  67. package/dist/types-cjs/store/next/projection.d.cts +1 -1
  68. package/dist/types-cjs/store/next/reconcile.d.cts +14 -0
  69. package/dist/types-cjs/store/next/store.d.cts +52 -2
  70. package/dist/types-cjs/store/next/target.d.cts +73 -8
  71. package/package.json +2 -2
@@ -1,6 +1,6 @@
1
1
  import { forEachDependent } from "./core/async.js";
2
2
 
3
- import { ext } from "./core/core.js";
3
+ import { ext, statusNotifierOf } from "./core/core.js";
4
4
 
5
5
  import { $REFRESH, STATUS_PENDING } from "./core/constants.js";
6
6
 
@@ -40,17 +40,18 @@ import { $TARGET, getStoreAffectsNodes } from "./store/store.js";
40
40
  * flush that would surface them, before effects run — verdict-only, netting
41
41
  * no visual change.
42
42
  */ function notifyMarkBoundaries(e) {
43
- if (!e.u && !e.o?.l) return;
43
+ if (!e.u && !e.o?.i) return;
44
44
  const r = new NotReadyError(e);
45
- r.i = true;
45
+ r.l = true;
46
46
  const t = new Set;
47
47
  const visit = e => {
48
48
  if (t.has(e)) return;
49
49
  t.add(e);
50
50
  // Display consumers (render effects, boundary computeds) act on the
51
51
  // notification; descent stops there, exactly like the status rails.
52
- if (e.o?.A) {
53
- e.o.A.call(e, STATUS_PENDING, r);
52
+ const o = statusNotifierOf(e);
53
+ if (o) {
54
+ o.call(e, STATUS_PENDING, r);
54
55
  return;
55
56
  }
56
57
  forEachDependent(e, visit);
@@ -68,10 +69,10 @@ import { $TARGET, getStoreAffectsNodes } from "./store/store.js";
68
69
  * earlier overlapping registration get covered, and dedup stops re-descent.
69
70
  */ function registerAffectsMark(e) {
70
71
  markAffects(e);
71
- globalQueue.k.m.push(e);
72
+ globalQueue.m.A.push(e);
72
73
  // Companions only exist once the verdict layer (isPending/latest) loaded;
73
74
  // without them there is no materialized verdict to poke.
74
- GlobalQueue.p !== null && GlobalQueue.p(e);
75
+ GlobalQueue.k !== null && GlobalQueue.k(e);
75
76
  notifyMarkBoundaries(e);
76
77
  schedule();
77
78
  }
@@ -85,8 +86,8 @@ import { $TARGET, getStoreAffectsNodes } from "./store/store.js";
85
86
  shiftAffectsMarks(-1);
86
87
  e.o.t--;
87
88
  if (!e.o.t) {
88
- GlobalQueue.p !== null && GlobalQueue.p(e, true);
89
- GlobalQueue.G?.(e);
89
+ GlobalQueue.k !== null && GlobalQueue.k(e, true);
90
+ GlobalQueue.p?.(e);
90
91
  }
91
92
  }
92
93
 
@@ -103,11 +104,11 @@ import { $TARGET, getStoreAffectsNodes } from "./store/store.js";
103
104
  // Each call site is gated by state only this module creates (a non-empty
104
105
  // `_affectsNodes` batch, a live scope in the store's `affectsScopes`), so the
105
106
  // hooks are installed before the first time any of them can fire.
106
- GlobalQueue.M = releaseAffectsMarks;
107
+ GlobalQueue.G = releaseAffectsMarks;
107
108
 
108
- GlobalQueue.h = markAffects;
109
+ GlobalQueue.M = markAffects;
109
110
 
110
- GlobalQueue.j = releaseAffectsMark;
111
+ GlobalQueue.N = releaseAffectsMark;
111
112
 
112
113
  function affects(e, r) {
113
114
  const t = e?.[$TARGET];
@@ -22,7 +22,7 @@ function boundaryComputed(e, t) {
22
22
  const r = computed(e, {
23
23
  lazy: true
24
24
  });
25
- ext(r).A = (e, t) => {
25
+ ext(r).h = (e, t) => {
26
26
  // Use passed values if provided, otherwise read from node
27
27
  const n = e !== undefined ? e : r.S;
28
28
  const s = t !== undefined ? t : r.o?._;
@@ -80,18 +80,18 @@ function isRevealController(e) {
80
80
  }
81
81
 
82
82
  function isSlotReady(e) {
83
- return isRevealController(e) ? e.O() : e.v.size === 0 && !e.N;
83
+ return isRevealController(e) ? e.O() : e.v.size === 0 && !e.U;
84
84
  }
85
85
 
86
86
  function isSlotMinimallyReady(e) {
87
- return isRevealController(e) ? e.U() : isSlotReady(e);
87
+ return isRevealController(e) ? e.I() : isSlotReady(e);
88
88
  }
89
89
 
90
90
  function setSlotState(e, t, r, n) {
91
- setSignal(e.I, r);
92
- setSignal(e.D, n);
91
+ setSignal(e.D, r);
92
+ setSignal(e.P, n);
93
93
  if (isRevealController(e)) {
94
- if (!r && e.P === t) e.P = undefined;
94
+ if (!r && e.j === t) e.j = undefined;
95
95
  return e.B(r, n);
96
96
  }
97
97
  if (!r && e.W === t && e.L) e.W = undefined;
@@ -101,12 +101,12 @@ class RevealController {
101
101
  F;
102
102
  q;
103
103
  V=[];
104
- P;
105
- I=signal(false, {
104
+ j;
105
+ D=signal(false, {
106
106
  ownedWrite: true,
107
107
  H: true
108
108
  });
109
- D=signal(false, {
109
+ P=signal(false, {
110
110
  ownedWrite: true,
111
111
  H: true
112
112
  });
@@ -120,7 +120,7 @@ class RevealController {
120
120
  Y(e) {
121
121
  for (let t = 0; t < this.V.length; t++) {
122
122
  const r = this.V[t];
123
- if ((isRevealController(r) ? r.P : r.W) !== this) continue;
123
+ if ((isRevealController(r) ? r.j : r.W) !== this) continue;
124
124
  if (e(r) === false) return false;
125
125
  }
126
126
  return true;
@@ -134,7 +134,7 @@ class RevealController {
134
134
  * - `together`: every direct slot is minimally ready.
135
135
  * - `sequential`: the first owned slot is minimally ready (frontier can advance).
136
136
  * - `natural`: any owned slot is minimally ready.
137
- */ U() {
137
+ */ I() {
138
138
  const e = untrack(this.F);
139
139
  if (e === "together") return this.Y(isSlotMinimallyReady);
140
140
  if (e === "natural") {
@@ -161,7 +161,7 @@ class RevealController {
161
161
  if (this.V.includes(e)) return;
162
162
  this.V.push(e);
163
163
  const t = untrack(this.F);
164
- setSignal(e.I, true), setSignal(e.D, t === "sequential" ? !!untrack(this.q) : false);
164
+ setSignal(e.D, true), setSignal(e.P, t === "sequential" ? !!untrack(this.q) : false);
165
165
  untrack(() => this.B());
166
166
  }
167
167
  $(e) {
@@ -175,7 +175,7 @@ class RevealController {
175
175
  const r = this.J;
176
176
  const n = this.K;
177
177
  try {
178
- const r = e ?? read(this.I), n = untrack(this.F), s = n === "sequential" && !!untrack(this.q), i = t ?? s;
178
+ const r = e ?? read(this.D), n = untrack(this.F), s = n === "sequential" && !!untrack(this.q), i = t ?? s;
179
179
  if (r) {
180
180
  // Held by an outer group. Propagate the hold (and whatever collapsed policy
181
181
  // the outer asked for) down the whole subtree. Inner order is ignored while
@@ -187,8 +187,8 @@ class RevealController {
187
187
  // so the parent backpointer survives for upward readiness notifications.
188
188
  this.Y(e => {
189
189
  if (isRevealController(e)) {
190
+ setSignal(e.P, false);
190
191
  setSignal(e.D, false);
191
- setSignal(e.I, false);
192
192
  e.B(false, false);
193
193
  } else {
194
194
  setSlotState(e, this, !isSlotReady(e), false);
@@ -215,8 +215,8 @@ class RevealController {
215
215
  // advancing past this slot, and we bypass setSlotState so the parent
216
216
  // backpointer survives for upward readiness notifications.
217
217
  if (isRevealController(t)) {
218
+ setSignal(t.P, false);
218
219
  setSignal(t.D, false);
219
- setSignal(t.I, false);
220
220
  t.B(false, false);
221
221
  } else {
222
222
  setSlotState(t, this, true, false);
@@ -225,10 +225,10 @@ class RevealController {
225
225
  }
226
226
  } finally {
227
227
  this.J = this.O();
228
- this.K = this.U();
228
+ this.K = this.I();
229
229
  this.X = false;
230
230
  }
231
- if (this.P && (r !== this.J || n !== this.K)) this.P.B();
231
+ if (this.j && (r !== this.J || n !== this.K)) this.j.B();
232
232
  }
233
233
  }
234
234
 
@@ -236,13 +236,13 @@ class CollectionQueue extends Queue {
236
236
  ee;
237
237
  v=new Set;
238
238
  te;
239
- N=true;
240
- I=signal(false, {
239
+ U=true;
240
+ D=signal(false, {
241
241
  ownedWrite: true,
242
242
  H: true
243
243
  });
244
244
  _;
245
- D=signal(false, {
245
+ P=signal(false, {
246
246
  ownedWrite: true,
247
247
  H: true
248
248
  });
@@ -255,7 +255,7 @@ class CollectionQueue extends Queue {
255
255
  this.ee = e;
256
256
  }
257
257
  run(e) {
258
- if (!e || read(this.I) && (!_revealUsed || read(this.D))) return;
258
+ if (!e || read(this.D) && (!_revealUsed || read(this.P))) return;
259
259
  return super.run(e);
260
260
  }
261
261
  notify(e, t, r, n) {
@@ -286,12 +286,12 @@ class CollectionQueue extends Queue {
286
286
  // (the Loading > Errored > content composition escape, #2856).
287
287
  if (this.ee & STATUS_PENDING && this.L) return super.notify(e, t, r, n);
288
288
  if (r & this.ee) {
289
- this.N = true;
289
+ this.U = true;
290
290
  const t = n?.source || e.o?._?.source;
291
291
  if (t) {
292
292
  const e = this.v.size === 0;
293
293
  this.v.add(t);
294
- if (e) setSignal(this.I, true);
294
+ if (e) setSignal(this.D, true);
295
295
  if (this.ee & STATUS_ERROR) {
296
296
  setSignal(this._, unwrapStatusError(t.o?._));
297
297
  }
@@ -309,13 +309,13 @@ class CollectionQueue extends Queue {
309
309
  if (e.ie & REACTIVE_DISPOSED || !e.o?.t && !(e.S & this.ee) && !(this.ee & STATUS_ERROR && e.S & STATUS_PENDING)) this.v.delete(e);
310
310
  }
311
311
  if (!this.v.size) {
312
- if (this.ee & STATUS_PENDING && this.N && !this.L && this.te) {
313
- this.N = !!(this.te.S & this.ee);
312
+ if (this.ee & STATUS_PENDING && this.U && !this.L && this.te) {
313
+ this.U = !!(this.te.S & this.ee);
314
314
  } else {
315
- this.N = false;
315
+ this.U = false;
316
316
  }
317
- if (!this.N) {
318
- setSignal(this.I, false);
317
+ if (!this.U) {
318
+ setSignal(this.D, false);
319
319
  if (this.re) {
320
320
  try {
321
321
  this.ne = untrack(() => this.re());
@@ -346,7 +346,7 @@ function createCollectionBoundary(e, t, r, n) {
346
346
  } catch (e) {
347
347
  if (e instanceof NotReadyError) t = true; else throw e;
348
348
  }
349
- i.N = t || !!(o.S & e) || o.o?._ instanceof NotReadyError;
349
+ i.U = t || !!(o.S & e) || o.o?._ instanceof NotReadyError;
350
350
  });
351
351
  const l = _revealUsed && e === STATUS_PENDING ? getContext(RevealControllerContext) : null;
352
352
  if (l) {
@@ -355,14 +355,14 @@ function createCollectionBoundary(e, t, r, n) {
355
355
  cleanup(() => l.$(i));
356
356
  }
357
357
  return accessor(computed(() => {
358
- if (!read(i.I)) {
358
+ if (!read(i.D)) {
359
359
  const e = read(o);
360
- if (!untrack(() => read(i.I))) return i.L = true, e;
360
+ if (!untrack(() => read(i.D))) return i.L = true, e;
361
361
  }
362
362
  // Collapsed reveal slots suppress their own output entirely; the
363
363
  // renderer treats the hole as empty, so the cast never leaks to users
364
364
  // outside a `createRevealOrder` scope.
365
- if (_revealUsed && read(i.D)) return undefined;
365
+ if (_revealUsed && read(i.P)) return undefined;
366
366
  return r(i);
367
367
  },
368
368
  // Boundary structure, not a user source: its value is fallback-or-content and
@@ -424,7 +424,12 @@ function createCollectionBoundary(e, t, r, n) {
424
424
  * ```
425
425
  */ function createErrorBoundary(e, t) {
426
426
  return createCollectionBoundary(STATUS_ERROR, e, e => t(accessor(e._), () => {
427
- for (const t of e.v) recompute(t);
427
+ for (const t of e.v) {
428
+ // Non-computed sources (patch-channel registrations under plain
429
+ // owners) are not recomputable — their reset is the record's next
430
+ // transition re-applying the patch (re-audit 2, P1-4).
431
+ if (t.oe !== undefined) recompute(t);
432
+ }
428
433
  schedule();
429
434
  }));
430
435
  }
@@ -484,7 +489,7 @@ function createCollectionBoundary(e, t, r, n) {
484
489
  o.B();
485
490
  });
486
491
  if (n) {
487
- o.P = n;
492
+ o.j = n;
488
493
  n.Z(o);
489
494
  cleanup(() => n.$(o));
490
495
  }
@@ -556,7 +561,10 @@ function flattenArray(e, t = [], r) {
556
561
  } while (typeof n === "function" && !n.length);
557
562
  }
558
563
  if (Array.isArray(n)) {
559
- s = flattenArray(n, t, r);
564
+ // OR, don't overwrite: an accessor already pushed under doNotUnwrap
565
+ // still needs the resolving wrapper even when a later sibling
566
+ // fragment contains no functions (#3133).
567
+ s = flattenArray(n, t, r) || s;
560
568
  } else if (r?.skipNonRendered && (n == null || n === true || n === false || n === "")) {
561
569
  // skip
562
570
  } else t.push(n);
@@ -78,11 +78,11 @@ function restoreTransition(e, r) {
78
78
  const i = e(...r);
79
79
  globalQueue.initTransition();
80
80
  let o = activeTransition;
81
- o.oe.push(i);
81
+ o.ue.push(i);
82
82
  const done = (e, r, u = false) => {
83
83
  o = currentTransition(o);
84
- const s = o.oe.indexOf(i);
85
- if (s >= 0) o.oe.splice(s, 1);
84
+ const s = o.ue.indexOf(i);
85
+ if (s >= 0) o.ue.splice(s, 1);
86
86
  // Re-adopt through initTransition like every other resumption site:
87
87
  // a bare setActiveTransition leaves globalQueue._batch as a detached
88
88
  // ambient batch, and anything registered before the scheduled flush