@solidjs/signals 2.0.0-rc.7 → 2.0.0-rc.9

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 (134) hide show
  1. package/dist/dev-shared.js +6357 -0
  2. package/dist/dev.attribution.js +2485 -0
  3. package/dist/dev.js +2851 -7027
  4. package/dist/observe/affects.js +129 -0
  5. package/dist/observe/attribution.js +7 -0
  6. package/dist/observe/boundaries.js +641 -0
  7. package/dist/observe/core/action.js +177 -0
  8. package/dist/observe/core/async.js +846 -0
  9. package/dist/observe/core/attribution-costs.js +66 -0
  10. package/dist/observe/core/attribution-feedback.js +282 -0
  11. package/dist/observe/core/attribution-hooks.js +82 -0
  12. package/dist/observe/core/attribution-queries.js +28 -0
  13. package/dist/observe/core/attribution.js +2095 -0
  14. package/dist/observe/core/constants.js +248 -0
  15. package/dist/{types-cjs/core/context.d.cts → observe/core/context.js} +37 -12
  16. package/dist/observe/core/core.js +1789 -0
  17. package/dist/observe/core/dev.js +293 -0
  18. package/dist/observe/core/effect.js +195 -0
  19. package/dist/observe/core/error-hooks.js +71 -0
  20. package/dist/observe/core/error.js +80 -0
  21. package/dist/observe/core/external.js +98 -0
  22. package/dist/observe/core/graph.js +155 -0
  23. package/dist/observe/core/heap.js +147 -0
  24. package/dist/observe/core/invariants.js +45 -0
  25. package/dist/observe/core/lanes.js +205 -0
  26. package/dist/observe/core/optimistic.js +585 -0
  27. package/dist/observe/core/owner.js +322 -0
  28. package/dist/observe/core/scheduler.js +1428 -0
  29. package/dist/observe/core/verdict.js +669 -0
  30. package/dist/observe/index.js +59 -0
  31. package/dist/observe/map.js +484 -0
  32. package/dist/{types-cjs/signals.d.cts → observe/signals.js} +311 -317
  33. package/dist/observe/store/index.js +40 -0
  34. package/dist/observe/store/next/optimistic.js +660 -0
  35. package/dist/observe/store/next/projection.js +255 -0
  36. package/dist/observe/store/next/reconcile.js +375 -0
  37. package/dist/observe/store/next/store.js +2327 -0
  38. package/dist/observe/store/next/target.js +51 -0
  39. package/dist/observe/store/store.js +325 -0
  40. package/dist/observe/store/storePath.js +103 -0
  41. package/dist/observe/store/utils.js +1023 -0
  42. package/dist/prod/attribution.js +41 -0
  43. package/dist/prod/boundaries.js +128 -76
  44. package/dist/prod/core/action.js +65 -37
  45. package/dist/prod/core/async.js +324 -172
  46. package/dist/prod/core/constants.js +57 -1
  47. package/dist/prod/core/context.js +3 -3
  48. package/dist/prod/core/core.js +1003 -364
  49. package/dist/prod/core/dev.js +17 -1
  50. package/dist/prod/core/effect.js +76 -42
  51. package/dist/prod/core/error-hooks.js +71 -0
  52. package/dist/prod/core/external.js +4 -4
  53. package/dist/prod/core/graph.js +37 -37
  54. package/dist/prod/core/heap.js +61 -56
  55. package/dist/prod/core/lanes.js +107 -63
  56. package/dist/prod/core/optimistic.js +374 -93
  57. package/dist/prod/core/owner.js +62 -46
  58. package/dist/prod/core/scheduler.js +653 -286
  59. package/dist/prod/core/verdict.js +245 -127
  60. package/dist/prod/index.js +15 -5
  61. package/dist/prod/map.js +292 -141
  62. package/dist/prod/signals.js +29 -16
  63. package/dist/prod/store/next/optimistic.js +77 -55
  64. package/dist/prod/store/next/projection.js +31 -20
  65. package/dist/prod/store/next/reconcile.js +87 -84
  66. package/dist/prod/store/next/store.js +718 -401
  67. package/dist/prod/store/next/target.js +32 -10
  68. package/dist/prod/store/store.js +12 -14
  69. package/dist/prod/store/utils.js +950 -130
  70. package/dist/types/attribution.d.ts +20 -0
  71. package/dist/types/attribution.prod.d.ts +22 -0
  72. package/dist/types/boundaries.d.ts +10 -1
  73. package/dist/types/core/action.d.ts +12 -5
  74. package/dist/types/core/async.d.ts +1 -1
  75. package/dist/types/core/attribution-costs.d.ts +35 -0
  76. package/dist/types/core/attribution-feedback.d.ts +133 -0
  77. package/dist/types/core/attribution-hooks.d.ts +147 -9
  78. package/dist/types/core/attribution-queries.d.ts +10 -0
  79. package/dist/types/core/attribution.d.ts +216 -182
  80. package/dist/types/core/constants.d.ts +56 -0
  81. package/dist/types/core/core.d.ts +190 -2
  82. package/dist/types/core/dev.d.ts +246 -28
  83. package/dist/types/core/effect.d.ts +8 -1
  84. package/dist/types/core/error-hooks.d.ts +71 -0
  85. package/dist/types/core/index.d.ts +4 -1
  86. package/dist/types/core/invariants.d.ts +4 -0
  87. package/dist/types/core/lanes.d.ts +39 -5
  88. package/dist/types/core/scheduler.d.ts +153 -0
  89. package/dist/types/core/types.d.ts +32 -9
  90. package/dist/types/index.d.ts +10 -3
  91. package/dist/types/map.d.ts +2 -0
  92. package/dist/types/signals.d.ts +8 -0
  93. package/dist/types/store/index.d.ts +2 -0
  94. package/dist/types/store/next/optimistic.d.ts +1 -1
  95. package/dist/types/store/next/store.d.ts +11 -5
  96. package/dist/types/store/next/target.d.ts +37 -10
  97. package/dist/types/store/utils.d.ts +178 -0
  98. package/package.json +21 -17
  99. package/dist/node.cjs +0 -10541
  100. package/dist/node.dev.cjs +0 -13724
  101. package/dist/types-cjs/affects.d.cts +0 -47
  102. package/dist/types-cjs/boundaries.d.cts +0 -175
  103. package/dist/types-cjs/core/action.d.cts +0 -64
  104. package/dist/types-cjs/core/async.d.cts +0 -23
  105. package/dist/types-cjs/core/attribution-hooks.d.cts +0 -127
  106. package/dist/types-cjs/core/attribution.d.cts +0 -495
  107. package/dist/types-cjs/core/constants.d.cts +0 -159
  108. package/dist/types-cjs/core/core.d.cts +0 -185
  109. package/dist/types-cjs/core/dev.d.cts +0 -136
  110. package/dist/types-cjs/core/effect.d.cts +0 -30
  111. package/dist/types-cjs/core/error.d.cts +0 -56
  112. package/dist/types-cjs/core/external.d.cts +0 -15
  113. package/dist/types-cjs/core/graph.d.cts +0 -28
  114. package/dist/types-cjs/core/heap.d.cts +0 -24
  115. package/dist/types-cjs/core/index.d.cts +0 -13
  116. package/dist/types-cjs/core/invariants.d.cts +0 -59
  117. package/dist/types-cjs/core/lanes.d.cts +0 -54
  118. package/dist/types-cjs/core/optimistic.d.cts +0 -6
  119. package/dist/types-cjs/core/owner.d.cts +0 -124
  120. package/dist/types-cjs/core/scheduler.d.cts +0 -236
  121. package/dist/types-cjs/core/types.d.cts +0 -204
  122. package/dist/types-cjs/core/verdict.d.cts +0 -2
  123. package/dist/types-cjs/index.d.cts +0 -10
  124. package/dist/types-cjs/map.d.cts +0 -69
  125. package/dist/types-cjs/package.json +0 -3
  126. package/dist/types-cjs/store/index.d.cts +0 -18
  127. package/dist/types-cjs/store/next/optimistic.d.cts +0 -25
  128. package/dist/types-cjs/store/next/projection.d.cts +0 -8
  129. package/dist/types-cjs/store/next/reconcile.d.cts +0 -10
  130. package/dist/types-cjs/store/next/store.d.cts +0 -121
  131. package/dist/types-cjs/store/next/target.d.cts +0 -166
  132. package/dist/types-cjs/store/store.d.cts +0 -143
  133. package/dist/types-cjs/store/storePath.d.cts +0 -58
  134. package/dist/types-cjs/store/utils.d.cts +0 -74
@@ -0,0 +1,322 @@
1
+ import { REACTIVE_DISPOSED, CONFIG_CHILD_COMPANIONS, STATUS_PENDING, CONFIG_AUTO_DISPOSE, REACTIVE_ZOMBIE, REACTIVE_IN_HEAP, REACTIVE_IN_HEAP_HEIGHT, CONFIG_TRANSPARENT, defaultContext } from "./constants.js";
2
+
3
+ import { context, runWithOwner, pendingCheckActive, latestReadActive, tracking } from "./core.js";
4
+
5
+ import "./dev.js";
6
+
7
+ import { clearDeps, unobserved } from "./graph.js";
8
+
9
+ import { deleteFromHeap, queueFor, insertIntoHeap, insertIntoHeapHeight } from "./heap.js";
10
+
11
+ import { GlobalQueue, wokenTransitions, schedule, zombieQueue, dirtyQueue, globalQueue } from "./scheduler.js";
12
+
13
+ const PENDING_OWNER = {};
14
+
15
+ // Dummy owner to trigger store's read() path
16
+ function markDisposal(e) {
17
+ let n = e.Ot;
18
+ while (n) {
19
+ const e = n.ft;
20
+ n.ft = e | REACTIVE_ZOMBIE;
21
+ // migrate height-adjust entries too, not just recompute entries: every
22
+ // `deleteFromHeap` call site picks the queue from the zombie flag, so a
23
+ // node left physically linked in `dirtyQueue` after being zombified gets
24
+ // unlinked from the wrong queue on dispose, corrupting the bucket and
25
+ // livelocking the next `runHeap` that reaches it (#2759)
26
+ if (e & (REACTIVE_IN_HEAP | REACTIVE_IN_HEAP_HEIGHT)) {
27
+ deleteFromHeap(n, e & REACTIVE_ZOMBIE ? zombieQueue : dirtyQueue);
28
+ if (e & REACTIVE_IN_HEAP) insertIntoHeap(n, zombieQueue); else insertIntoHeapHeight(n, zombieQueue);
29
+ }
30
+ markDisposal(n);
31
+ n = n.At;
32
+ }
33
+ }
34
+
35
+ function dispose(e) {
36
+ // Direct disposal is death, not dormancy: strip the observation lifecycle
37
+ // so a later read freezes at the last committed value instead of
38
+ // reawakening the node (#3024). The teardown itself (heap removal — a node
39
+ // left queued would be recomputed and resurrected by the next flush (#2983)
40
+ // — dep unlinking, child disposal) is exactly unobserved()'s body; only
41
+ // this flag distinguishes death from dormancy.
42
+ e.C &= ~CONFIG_AUTO_DISPOSE;
43
+ unobserved(e);
44
+ }
45
+
46
+ function disposeChildren(e, n = false, t) {
47
+ const i = e.ft;
48
+ if (i & REACTIVE_DISPOSED) return;
49
+ if (n) {
50
+ e.ft = i | REACTIVE_DISPOSED;
51
+ // Companions are created detached and outlive their owner, but a verdict
52
+ // must not: a disposed source can never settle, so an isPending companion
53
+ // latched `true` here would hold a spinner forever (INV-9, the PR #2845
54
+ // edge). Snap runs after the DISPOSED flag is set so the oracle reads
55
+ // false, and notifies subscribers still watching the companion.
56
+ const n = e;
57
+ if (n.o?.he || n.o?.Ge) GlobalQueue.Qn(n);
58
+ // A firewall's leaves have no lifecycle of their own, so a companion on
59
+ // one of them outlives its source the same way (INV-9's rationale). The
60
+ // firewall knows which leaves carry companions (CONFIG_CHILD_COMPANIONS,
61
+ // #3038): snap them with it — the snap retires a shadow whose firewall is
62
+ // disposed (spec O5).
63
+ if (n.C & CONFIG_CHILD_COMPANIONS) n.o.Jt.forEach(GlobalQueue.Qn);
64
+ // A pending reader parked in a transaction may be the only thing holding
65
+ // it (#3372): its death is a completion event the transaction must be
66
+ // re-judged for, and nothing else re-enters a parked transaction.
67
+ const t = n.Te;
68
+ if (t && n.S & STATUS_PENDING && !wokenTransitions.includes(t)) wokenTransitions.push(t),
69
+ schedule();
70
+ }
71
+ if (n && e.ht && e.o !== null) e.o.ce = null;
72
+ let o = t ? e.o?.Pt ?? null : e.Ot;
73
+ while (o) {
74
+ const e = o.At;
75
+ const n = o;
76
+ // Owner teardown is death regardless of the child's own lifecycle
77
+ // (#3024): strip AUTO_DISPOSE so a post-disposal read freezes at the
78
+ // last committed value instead of reawakening in a torn-down tree.
79
+ // Runs before the recursion so already-dormant children (whose
80
+ // disposeChildren call early-returns on REACTIVE_DISPOSED) die too.
81
+ // Only unobserved()'s own node keeps its dormancy — it is never in
82
+ // this loop; its children are rebuilt fresh on reawaken.
83
+ n.C &= ~CONFIG_AUTO_DISPOSE;
84
+ // Heap removal must not be gated on `_deps`: a dependency-free
85
+ // computation queued by refresh() has a null dep list but still sits in
86
+ // the dirty heap, and left there the post-disposal flush recomputes it —
87
+ // recompute() rewriting `_flags` clears REACTIVE_DISPOSED and the node
88
+ // comes back to life (post-unmount runs, leaked cleanups, #2983).
89
+ // deleteFromHeap self-guards on the in-heap flags (and tolerates plain
90
+ // Owners, whose _flags is undefined), so no gate here.
91
+ deleteFromHeap(n, queueFor(n));
92
+ clearDeps(n);
93
+ disposeChildren(o, true);
94
+ o = e;
95
+ }
96
+ if (t) {
97
+ if (e.o !== null) e.o.Pt = null;
98
+ } else {
99
+ e.Ot = null;
100
+ e.Ft = 0;
101
+ }
102
+ // O(1) splice out of parent's chain on individual dispose. Skipped during
103
+ // batch dispose (parent already disposed) and zombie disposal (node sits on
104
+ // parent's _pendingFirstChild). We leave node._nextSibling intact so outer
105
+ // walks that already advanced past us still reach later siblings.
106
+ if (n && !t && !(i & REACTIVE_ZOMBIE) && e._parent !== null && !(e._parent.ft & REACTIVE_DISPOSED)) {
107
+ const n = e.Yt;
108
+ const t = e.At;
109
+ if (n !== null) n.At = t; else e._parent.Ot = t;
110
+ if (t !== null) t.Yt = n;
111
+ e.Yt = null;
112
+ }
113
+ runDisposal(e, t);
114
+ // Final effect-returned cleanup fires at true disposal, after `_disposal`
115
+ // to mirror rerun ordering (compute-phase teardown first, cleanup last).
116
+ if (n && e.an) {
117
+ const n = e.an;
118
+ e.an = undefined;
119
+ n();
120
+ }
121
+ }
122
+
123
+ function runDisposal(e, n) {
124
+ let t = n ? e.o?.Dt : e.Ue;
125
+ if (!t) return;
126
+ if (Array.isArray(t)) {
127
+ for (let e = 0; e < t.length; e++) {
128
+ const n = t[e];
129
+ n.call(n);
130
+ }
131
+ } else {
132
+ t.call(t);
133
+ }
134
+ if (n) {
135
+ if (e.o !== null) e.o.Dt = null;
136
+ } else e.Ue = null;
137
+ }
138
+
139
+ function childId(e, n) {
140
+ let t = e;
141
+ while (t.C & CONFIG_TRANSPARENT && t._parent) t = t._parent;
142
+ if (t.id != null) return formatId(t.id, n ? t.Ft++ : t.Ft);
143
+ throw new Error("");
144
+ }
145
+
146
+ /**
147
+ * Allocates and returns the next stable child id for `owner`. Used by
148
+ * hydration plumbing and `createUniqueId`. Not part of the user-facing API.
149
+ *
150
+ * @internal
151
+ */ function getNextChildId(e) {
152
+ return childId(e, true);
153
+ }
154
+
155
+ /**
156
+ * The id a freshly-created node inherits: an explicit `options.id` wins;
157
+ * transparent nodes share their parent's id; otherwise the parent's next
158
+ * child id is consumed (or `undefined` outside an id-carrying tree).
159
+ */ function inheritId(e, n, t) {
160
+ return e?.id ?? (n ? t?.id : t?.id != null ? getNextChildId(t) : undefined);
161
+ }
162
+
163
+ /**
164
+ * Returns the *next* child id for `owner` without consuming it. Used by
165
+ * hydration plumbing to peek at the id a future child will receive.
166
+ *
167
+ * @internal
168
+ */ function peekNextChildId(e) {
169
+ return childId(e, false);
170
+ }
171
+
172
+ function formatId(e, n) {
173
+ const t = n.toString(36), i = t.length - 1;
174
+ return e + (i ? String.fromCharCode(64 + i) : "") + t;
175
+ }
176
+
177
+ /**
178
+ * Returns the currently-tracking observer (the computation that subscribes to
179
+ * reactive reads at this point), or `null` if reads here would be untracked.
180
+ * Used by reactive primitives that need to know whether they're inside a
181
+ * tracking scope. App code rarely needs this — see `getOwner()` for the
182
+ * lifecycle owner instead.
183
+ *
184
+ * @example
185
+ * ```ts
186
+ * // Library predicate: only register a hot-path subscription when the
187
+ * // caller is inside a tracking scope (memo / effect compute / JSX).
188
+ * function trackIfTracked(source: () => unknown) {
189
+ * if (getObserver()) source();
190
+ * }
191
+ * ```
192
+ */ function getObserver() {
193
+ if (pendingCheckActive || latestReadActive) return PENDING_OWNER;
194
+ return tracking ? context : null;
195
+ }
196
+
197
+ /**
198
+ * Returns the current reactive **owner** — the lifecycle node that the next
199
+ * `cleanup()` / `onCleanup()` / `createSignal()` etc. will be attached to.
200
+ *
201
+ * Returns `null` if called outside any owner. Capture the owner with
202
+ * `getOwner()` and re-enter it later with `runWithOwner(owner, fn)` to attach
203
+ * disposables created from a callback (event handler, async resolution, etc.)
204
+ * back to a component's lifecycle.
205
+ *
206
+ * @example
207
+ * ```ts
208
+ * function defer<T>(fn: () => T) {
209
+ * const owner = getOwner();
210
+ * queueMicrotask(() => runWithOwner(owner, fn));
211
+ * }
212
+ * ```
213
+ */ function getOwner() {
214
+ return context;
215
+ }
216
+
217
+ /**
218
+ * Low-level: registers `fn` as a disposal callback on the current owner.
219
+ * Most code should use `onCleanup()` from `solid-js`, which adds dev-mode
220
+ * checks. `cleanup()` is the unchecked primitive used by internals.
221
+ */ function cleanup(e) {
222
+ if (!context) return e;
223
+ if (!context.Ue) context.Ue = e; else if (Array.isArray(context.Ue)) context.Ue.push(e); else context.Ue = [ context.Ue, e ];
224
+ return e;
225
+ }
226
+
227
+ /**
228
+ * Returns `true` if the owner has been disposed (or marked zombie pending
229
+ * disposal). Pair with a captured owner to bail out of late callbacks whose
230
+ * surrounding component already unmounted.
231
+ *
232
+ * @example
233
+ * ```ts
234
+ * function onSettleSafe(fn: () => void) {
235
+ * const owner = getOwner();
236
+ * queueMicrotask(() => {
237
+ * if (owner && isDisposed(owner)) return; // component unmounted; skip
238
+ * runWithOwner(owner, fn);
239
+ * });
240
+ * }
241
+ * ```
242
+ */ function isDisposed(e) {
243
+ return !!(e.ft & (REACTIVE_DISPOSED | REACTIVE_ZOMBIE));
244
+ }
245
+
246
+ function disposeRootSelf(e = true) {
247
+ disposeChildren(this, e);
248
+ }
249
+
250
+ /**
251
+ * Creates a fresh owner attached as a child of the current owner (or as a
252
+ * detached root if there is none). Used by framework internals to group
253
+ * cleanups; app code should use `createRoot()` (host a reactive scope outside
254
+ * a component) or `runWithOwner()` (re-enter a captured owner).
255
+ *
256
+ * @internal
257
+ */ function createOwner(e) {
258
+ const n = context;
259
+ const t = e?.transparent ?? false;
260
+ // Prod and observe boilerplates (see core.ts computed()). The observe
261
+ // literal carries the `_name` slot the rendering layer fills with the
262
+ // component label (`owner._name = "<App>"`) — a slot, so labelling a root
263
+ // is a plain store rather than a shape fork between labelled and plain roots.
264
+ const i = {
265
+ id: inheritId(e, t, n),
266
+ C: t ? CONFIG_TRANSPARENT : 0,
267
+ cn: true,
268
+ fn: n?.cn ? n.fn : n,
269
+ Ot: null,
270
+ At: null,
271
+ Yt: null,
272
+ Ue: null,
273
+ T: n?.T ?? globalQueue,
274
+ wt: n?.wt || defaultContext,
275
+ Ft: 0,
276
+ o: null,
277
+ _parent: n,
278
+ dispose: disposeRootSelf,
279
+ _name: undefined
280
+ };
281
+ if (n) {
282
+ const e = n.Ot;
283
+ if (e === null) {
284
+ n.Ot = i;
285
+ } else {
286
+ i.At = e;
287
+ e.Yt = i;
288
+ n.Ot = i;
289
+ }
290
+ }
291
+ return i;
292
+ }
293
+
294
+ /**
295
+ * Creates a detached reactive root. The callback receives a `dispose()`
296
+ * function which, when called, tears down every signal, memo, effect, and
297
+ * `onCleanup` registered inside the root.
298
+ *
299
+ * Use this to host long-lived reactive scopes outside of a component (custom
300
+ * controllers, app bootstrapping, tests). Inside a component, prefer
301
+ * letting Solid's component lifecycle own things.
302
+ *
303
+ * @example
304
+ * ```ts
305
+ * const dispose = createRoot(dispose => {
306
+ * const [n, setN] = createSignal(0);
307
+ * createEffect(() => n(), value => console.log(value));
308
+ * setInterval(() => setN(x => x + 1), 1000);
309
+ * return dispose;
310
+ * });
311
+ *
312
+ * // Later, to tear everything down:
313
+ * dispose();
314
+ * ```
315
+ *
316
+ * @description https://docs.solidjs.com/reference/reactive-utilities/create-root
317
+ */ function createRoot(e, n) {
318
+ const t = createOwner(n);
319
+ return runWithOwner(t, () => e(() => t.dispose()));
320
+ }
321
+
322
+ export { cleanup, createOwner, createRoot, dispose, disposeChildren, getNextChildId, getObserver, getOwner, inheritId, isDisposed, markDisposal, peekNextChildId };