@solidjs/signals 2.0.0-rc.1 → 2.0.0-rc.2

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 (50) hide show
  1. package/dist/dev.js +1661 -361
  2. package/dist/node.cjs +1939 -1331
  3. package/dist/prod/affects.js +16 -16
  4. package/dist/prod/boundaries.js +90 -90
  5. package/dist/prod/core/action.js +3 -3
  6. package/dist/prod/core/async.js +74 -72
  7. package/dist/prod/core/constants.js +39 -1
  8. package/dist/prod/core/core.js +332 -224
  9. package/dist/prod/core/effect.js +56 -56
  10. package/dist/prod/core/external.js +4 -4
  11. package/dist/prod/core/graph.js +65 -54
  12. package/dist/prod/core/heap.js +52 -44
  13. package/dist/prod/core/invariants.js +3 -2
  14. package/dist/prod/core/lanes.js +41 -34
  15. package/dist/prod/core/optimistic.js +63 -60
  16. package/dist/prod/core/owner.js +97 -96
  17. package/dist/prod/core/scheduler.js +243 -194
  18. package/dist/prod/core/verdict.js +184 -77
  19. package/dist/prod/map.js +104 -104
  20. package/dist/prod/signals.js +1 -1
  21. package/dist/prod/store/next/optimistic.js +31 -23
  22. package/dist/prod/store/next/projection.js +3 -3
  23. package/dist/prod/store/next/reconcile.js +78 -74
  24. package/dist/prod/store/next/store.js +357 -90
  25. package/dist/prod/store/store.js +7 -7
  26. package/dist/types/core/attribution-hooks.d.ts +52 -0
  27. package/dist/types/core/attribution.d.ts +186 -0
  28. package/dist/types/core/constants.d.ts +26 -0
  29. package/dist/types/core/core.d.ts +8 -1
  30. package/dist/types/core/dev.d.ts +20 -3
  31. package/dist/types/core/graph.d.ts +1 -0
  32. package/dist/types/core/lanes.d.ts +4 -16
  33. package/dist/types/core/scheduler.d.ts +8 -0
  34. package/dist/types/core/types.d.ts +85 -41
  35. package/dist/types/store/next/projection.d.ts +0 -16
  36. package/dist/types/store/next/store.d.ts +6 -0
  37. package/dist/types/store/next/target.d.ts +18 -0
  38. package/dist/types-cjs/core/attribution-hooks.d.cts +52 -0
  39. package/dist/types-cjs/core/attribution.d.cts +186 -0
  40. package/dist/types-cjs/core/constants.d.cts +26 -0
  41. package/dist/types-cjs/core/core.d.cts +8 -1
  42. package/dist/types-cjs/core/dev.d.cts +20 -3
  43. package/dist/types-cjs/core/graph.d.cts +1 -0
  44. package/dist/types-cjs/core/lanes.d.cts +4 -16
  45. package/dist/types-cjs/core/scheduler.d.cts +8 -0
  46. package/dist/types-cjs/core/types.d.cts +85 -41
  47. package/dist/types-cjs/store/next/projection.d.cts +0 -16
  48. package/dist/types-cjs/store/next/store.d.cts +6 -0
  49. package/dist/types-cjs/store/next/target.d.cts +18 -0
  50. package/package.json +1 -1
@@ -1,8 +1,8 @@
1
- import { REACTIVE_DISPOSED, REACTIVE_IN_HEAP, REACTIVE_IN_HEAP_HEIGHT, REACTIVE_ZOMBIE, CONFIG_TRANSPARENT, defaultContext } from "./constants.js";
1
+ import { REACTIVE_DISPOSED, REACTIVE_ZOMBIE, REACTIVE_IN_HEAP, REACTIVE_IN_HEAP_HEIGHT, CONFIG_TRANSPARENT, defaultContext, CONFIG_AUTO_DISPOSE } from "./constants.js";
2
2
 
3
3
  import { context, runWithOwner, pendingCheckActive, latestReadActive, tracking } from "./core.js";
4
4
 
5
- import { unlinkSubs } from "./graph.js";
5
+ import { clearDeps, unobserved } from "./graph.js";
6
6
 
7
7
  import { deleteFromHeap, queueFor, insertIntoHeap, insertIntoHeapHeight } from "./heap.js";
8
8
 
@@ -12,118 +12,120 @@ const PENDING_OWNER = {};
12
12
 
13
13
  // Dummy owner to trigger store's read() path
14
14
  function markDisposal(e) {
15
- let n = e.ke;
16
- while (n) {
17
- const e = n.se;
18
- n.se = e | REACTIVE_ZOMBIE;
15
+ let t = e.ke;
16
+ while (t) {
17
+ const e = t.ie;
18
+ t.ie = e | REACTIVE_ZOMBIE;
19
19
  // migrate height-adjust entries too, not just recompute entries: every
20
20
  // `deleteFromHeap` call site picks the queue from the zombie flag, so a
21
21
  // node left physically linked in `dirtyQueue` after being zombified gets
22
22
  // unlinked from the wrong queue on dispose, corrupting the bucket and
23
23
  // livelocking the next `runHeap` that reaches it (#2759)
24
24
  if (e & (REACTIVE_IN_HEAP | REACTIVE_IN_HEAP_HEIGHT)) {
25
- deleteFromHeap(n, e & REACTIVE_ZOMBIE ? zombieQueue : dirtyQueue);
26
- if (e & REACTIVE_IN_HEAP) insertIntoHeap(n, zombieQueue); else insertIntoHeapHeight(n, zombieQueue);
25
+ deleteFromHeap(t, e & REACTIVE_ZOMBIE ? zombieQueue : dirtyQueue);
26
+ if (e & REACTIVE_IN_HEAP) insertIntoHeap(t, zombieQueue); else insertIntoHeapHeight(t, zombieQueue);
27
27
  }
28
- markDisposal(n);
29
- n = n.He;
28
+ markDisposal(t);
29
+ t = t.Ve;
30
30
  }
31
31
  }
32
32
 
33
33
  function dispose(e) {
34
- // Leave every scheduler heap on disposal (mirrors `unobserved`): a node
35
- // still queued here would be recomputed by the next flush, and recompute()
36
- // rewriting `_flags` would clear REACTIVE_DISPOSEDresurrecting it (#2983).
37
- deleteFromHeap(e, queueFor(e));
38
- let n = e.tt;
39
- while (n !== null) {
40
- n = unlinkSubs(n);
41
- }
42
- e.tt = null;
43
- e.Ye = null;
44
- disposeChildren(e, true);
34
+ // Direct disposal is death, not dormancy: strip the observation lifecycle
35
+ // so a later read freezes at the last committed value instead of
36
+ // reawakening the node (#3024). The teardown itself (heap removal a node
37
+ // left queued would be recomputed and resurrected by the next flush (#2983)
38
+ // dep unlinking, child disposal) is exactly unobserved()'s body; only
39
+ // this flag distinguishes death from dormancy.
40
+ e.T &= ~CONFIG_AUTO_DISPOSE;
41
+ unobserved(e);
45
42
  }
46
43
 
47
- function disposeChildren(e, n = false, t) {
48
- const i = e.se;
44
+ function disposeChildren(e, t = false, n) {
45
+ const i = e.ie;
49
46
  if (i & REACTIVE_DISPOSED) return;
50
- if (n) {
51
- e.se = i | REACTIVE_DISPOSED;
47
+ if (t) {
48
+ e.ie = i | REACTIVE_DISPOSED;
52
49
  // Companions are created detached and outlive their owner, but a verdict
53
50
  // must not: a disposed source can never settle, so an isPending companion
54
51
  // latched `true` here would hold a spinner forever (INV-9, the PR #2845
55
52
  // edge). Snap runs after the DISPOSED flag is set so the oracle reads
56
53
  // false, and notifies subscribers still watching the companion.
57
- const n = e;
58
- if (n.Oe || n.ge) GlobalQueue.un(n);
54
+ const t = e;
55
+ if (t.o?.Ge || t.o?.ge) GlobalQueue.un(t);
59
56
  }
60
- if (n && e.ce) e.Te = null;
61
- let l = t ? e.We : e.ke;
62
- while (l) {
63
- const e = l.He;
64
- const n = l;
57
+ if (t && e.Se && e.o !== null) e.o.Ee = null;
58
+ let o = n ? e.o?.qe ?? null : e.ke;
59
+ while (o) {
60
+ const e = o.Ve;
61
+ const t = o;
62
+ // Owner teardown is death regardless of the child's own lifecycle
63
+ // (#3024): strip AUTO_DISPOSE so a post-disposal read freezes at the
64
+ // last committed value instead of reawakening in a torn-down tree.
65
+ // Runs before the recursion so already-dormant children (whose
66
+ // disposeChildren call early-returns on REACTIVE_DISPOSED) die too.
67
+ // Only unobserved()'s own node keeps its dormancy — it is never in
68
+ // this loop; its children are rebuilt fresh on reawaken.
69
+ t.T &= ~CONFIG_AUTO_DISPOSE;
65
70
  // Heap removal must not be gated on `_deps`: a dependency-free
66
71
  // computation queued by refresh() has a null dep list but still sits in
67
72
  // the dirty heap, and left there the post-disposal flush recomputes it —
68
73
  // recompute() rewriting `_flags` clears REACTIVE_DISPOSED and the node
69
74
  // comes back to life (post-unmount runs, leaked cleanups, #2983).
70
- if (n.se & (REACTIVE_IN_HEAP | REACTIVE_IN_HEAP_HEIGHT)) deleteFromHeap(n, queueFor(n));
71
- if (n.tt) {
72
- let e = n.tt;
73
- do {
74
- e = unlinkSubs(e);
75
- } while (e !== null);
76
- n.tt = null;
77
- n.Ye = null;
78
- }
79
- disposeChildren(l, true);
80
- l = e;
75
+ // deleteFromHeap self-guards on the in-heap flags (and tolerates plain
76
+ // Owners, whose _flags is undefined), so no gate here.
77
+ deleteFromHeap(t, queueFor(t));
78
+ clearDeps(t);
79
+ disposeChildren(o, true);
80
+ o = e;
81
81
  }
82
- if (t) {
83
- e.We = null;
82
+ if (n) {
83
+ if (e.o !== null) e.o.qe = null;
84
84
  } else {
85
85
  e.ke = null;
86
- e.qe = 0;
86
+ e.Me = 0;
87
87
  }
88
88
  // O(1) splice out of parent's chain on individual dispose. Skipped during
89
89
  // batch dispose (parent already disposed) and zombie disposal (node sits on
90
90
  // parent's _pendingFirstChild). We leave node._nextSibling intact so outer
91
91
  // walks that already advanced past us still reach later siblings.
92
- if (n && !t && !(i & REACTIVE_ZOMBIE) && e.Fe !== null && !(e.Fe.se & REACTIVE_DISPOSED)) {
93
- const n = e.ct;
94
- const t = e.He;
95
- if (n !== null) n.He = t; else e.Fe.ke = t;
96
- if (t !== null) t.ct = n;
92
+ if (t && !n && !(i & REACTIVE_ZOMBIE) && e.ve !== null && !(e.ve.ie & REACTIVE_DISPOSED)) {
93
+ const t = e.ct;
94
+ const n = e.Ve;
95
+ if (t !== null) t.Ve = n; else e.ve.ke = n;
96
+ if (n !== null) n.ct = t;
97
97
  e.ct = null;
98
98
  }
99
- runDisposal(e, t);
99
+ runDisposal(e, n);
100
100
  // Final effect-returned cleanup fires at true disposal, after `_disposal`
101
101
  // to mirror rerun ordering (compute-phase teardown first, cleanup last).
102
- if (n && e.Nt) {
103
- const n = e.Nt;
104
- e.Nt = undefined;
105
- n();
102
+ if (t && e.At) {
103
+ const t = e.At;
104
+ e.At = undefined;
105
+ t();
106
106
  }
107
107
  }
108
108
 
109
- function runDisposal(e, n) {
110
- let t = n ? e.Qe : e.he;
111
- if (!t) return;
112
- if (Array.isArray(t)) {
113
- for (let e = 0; e < t.length; e++) {
114
- const n = t[e];
115
- n.call(n);
109
+ function runDisposal(e, t) {
110
+ let n = t ? e.o?.We : e.he;
111
+ if (!n) return;
112
+ if (Array.isArray(n)) {
113
+ for (let e = 0; e < n.length; e++) {
114
+ const t = n[e];
115
+ t.call(t);
116
116
  }
117
117
  } else {
118
- t.call(t);
118
+ n.call(n);
119
119
  }
120
- n ? e.Qe = null : e.he = null;
120
+ if (t) {
121
+ if (e.o !== null) e.o.We = null;
122
+ } else e.he = null;
121
123
  }
122
124
 
123
- function childId(e, n) {
124
- let t = e;
125
- while (t.T & CONFIG_TRANSPARENT && t.Fe) t = t.Fe;
126
- if (t.id != null) return formatId(t.id, n ? t.qe++ : t.qe);
125
+ function childId(e, t) {
126
+ let n = e;
127
+ while (n.T & CONFIG_TRANSPARENT && n.ve) n = n.ve;
128
+ if (n.id != null) return formatId(n.id, t ? n.Me++ : n.Me);
127
129
  throw new Error("");
128
130
  }
129
131
 
@@ -140,8 +142,8 @@ function childId(e, n) {
140
142
  * The id a freshly-created node inherits: an explicit `options.id` wins;
141
143
  * transparent nodes share their parent's id; otherwise the parent's next
142
144
  * child id is consumed (or `undefined` outside an id-carrying tree).
143
- */ function inheritId(e, n, t) {
144
- return e?.id ?? (n ? t?.id : t?.id != null ? getNextChildId(t) : undefined);
145
+ */ function inheritId(e, t, n) {
146
+ return e?.id ?? (t ? n?.id : n?.id != null ? getNextChildId(n) : undefined);
145
147
  }
146
148
 
147
149
  /**
@@ -153,9 +155,9 @@ function childId(e, n) {
153
155
  return childId(e, false);
154
156
  }
155
157
 
156
- function formatId(e, n) {
157
- const t = n.toString(36), i = t.length - 1;
158
- return e + (i ? String.fromCharCode(64 + i) : "") + t;
158
+ function formatId(e, t) {
159
+ const n = t.toString(36), i = n.length - 1;
160
+ return e + (i ? String.fromCharCode(64 + i) : "") + n;
159
161
  }
160
162
 
161
163
  /**
@@ -224,7 +226,7 @@ function formatId(e, n) {
224
226
  * }
225
227
  * ```
226
228
  */ function isDisposed(e) {
227
- return !!(e.se & (REACTIVE_DISPOSED | REACTIVE_ZOMBIE));
229
+ return !!(e.ie & (REACTIVE_DISPOSED | REACTIVE_ZOMBIE));
228
230
  }
229
231
 
230
232
  function disposeRootSelf(e = true) {
@@ -239,33 +241,32 @@ function disposeRootSelf(e = true) {
239
241
  *
240
242
  * @internal
241
243
  */ function createOwner(e) {
242
- const n = context;
243
- const t = e?.transparent ?? false;
244
+ const t = context;
245
+ const n = e?.transparent ?? false;
244
246
  const i = {
245
- id: inheritId(e, t, n),
246
- T: t ? CONFIG_TRANSPARENT : 0,
247
- Tt: true,
248
- It: n?.Tt ? n.It : n,
247
+ id: inheritId(e, n, t),
248
+ T: n ? CONFIG_TRANSPARENT : 0,
249
+ Ct: true,
250
+ Ot: t?.Ct ? t.Ot : t,
249
251
  ke: null,
250
- He: null,
252
+ Ve: null,
251
253
  ct: null,
252
254
  he: null,
253
- C: n?.C ?? globalQueue,
254
- we: n?.we || defaultContext,
255
- qe: 0,
256
- Qe: null,
257
- We: null,
258
- Fe: n,
255
+ C: t?.C ?? globalQueue,
256
+ we: t?.we || defaultContext,
257
+ Me: 0,
258
+ o: null,
259
+ ve: t,
259
260
  dispose: disposeRootSelf
260
261
  };
261
- if (n) {
262
- const e = n.ke;
262
+ if (t) {
263
+ const e = t.ke;
263
264
  if (e === null) {
264
- n.ke = i;
265
+ t.ke = i;
265
266
  } else {
266
- i.He = e;
267
+ i.Ve = e;
267
268
  e.ct = i;
268
- n.ke = i;
269
+ t.ke = i;
269
270
  }
270
271
  }
271
272
  return i;
@@ -294,9 +295,9 @@ function disposeRootSelf(e = true) {
294
295
  * ```
295
296
  *
296
297
  * @description https://docs.solidjs.com/reference/reactive-utilities/create-root
297
- */ function createRoot(e, n) {
298
- const t = createOwner(n);
299
- return runWithOwner(t, () => e(() => t.dispose()));
298
+ */ function createRoot(e, t) {
299
+ const n = createOwner(t);
300
+ return runWithOwner(n, () => e(() => n.dispose()));
300
301
  }
301
302
 
302
303
  export { cleanup, createOwner, createRoot, dispose, disposeChildren, getNextChildId, getObserver, getOwner, inheritId, isDisposed, markDisposal, peekNextChildId };