@solidjs/signals 2.0.0-rc.0 → 2.0.0-rc.10

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 (149) hide show
  1. package/README.md +1 -1
  2. package/dist/dev-shared.js +7138 -0
  3. package/dist/dev.attribution.js +3307 -0
  4. package/dist/dev.js +8076 -6692
  5. package/dist/observe/affects.js +129 -0
  6. package/dist/observe/attribution.js +7 -0
  7. package/dist/observe/boundaries.js +793 -0
  8. package/dist/observe/core/action.js +177 -0
  9. package/dist/observe/core/async.js +849 -0
  10. package/dist/observe/core/attribution-costs.js +66 -0
  11. package/dist/observe/core/attribution-feedback.js +280 -0
  12. package/dist/observe/core/attribution-hooks.js +83 -0
  13. package/dist/observe/core/attribution-queries.js +43 -0
  14. package/dist/observe/core/attribution.js +2904 -0
  15. package/dist/observe/core/constants.js +283 -0
  16. package/dist/{types-cjs/core/context.d.cts → observe/core/context.js} +37 -12
  17. package/dist/observe/core/core.js +1999 -0
  18. package/dist/observe/core/dev.js +343 -0
  19. package/dist/observe/core/effect.js +200 -0
  20. package/dist/observe/core/error-hooks.js +71 -0
  21. package/dist/observe/core/error.js +80 -0
  22. package/dist/observe/core/external.js +98 -0
  23. package/dist/observe/core/graph.js +155 -0
  24. package/dist/observe/core/heap.js +147 -0
  25. package/dist/observe/core/invariants.js +45 -0
  26. package/dist/observe/core/lanes.js +205 -0
  27. package/dist/observe/core/optimistic.js +627 -0
  28. package/dist/observe/core/owner.js +353 -0
  29. package/dist/observe/core/scheduler.js +1547 -0
  30. package/dist/observe/core/verdict.js +674 -0
  31. package/dist/observe/index.js +59 -0
  32. package/dist/observe/map.js +484 -0
  33. package/dist/observe/signals.js +731 -0
  34. package/dist/observe/store/index.js +44 -0
  35. package/dist/observe/store/next/optimistic.js +717 -0
  36. package/dist/observe/store/next/projection.js +266 -0
  37. package/dist/observe/store/next/reconcile.js +375 -0
  38. package/dist/observe/store/next/store.js +2480 -0
  39. package/dist/observe/store/next/target.js +51 -0
  40. package/dist/observe/store/store.js +331 -0
  41. package/dist/observe/store/storePath.js +103 -0
  42. package/dist/observe/store/utils.js +1070 -0
  43. package/dist/prod/affects.js +10 -9
  44. package/dist/prod/attribution.js +45 -0
  45. package/dist/prod/boundaries.js +388 -178
  46. package/dist/prod/core/action.js +65 -37
  47. package/dist/prod/core/async.js +477 -208
  48. package/dist/prod/core/attribution-hooks.js +3 -0
  49. package/dist/prod/core/constants.js +186 -1
  50. package/dist/prod/core/context.js +10 -16
  51. package/dist/prod/core/core.js +1556 -415
  52. package/dist/prod/core/dev.js +18 -1
  53. package/dist/prod/core/effect.js +119 -79
  54. package/dist/prod/core/error-hooks.js +71 -0
  55. package/dist/prod/core/error.js +13 -1
  56. package/dist/prod/core/external.js +4 -4
  57. package/dist/prod/core/graph.js +105 -54
  58. package/dist/prod/core/heap.js +72 -65
  59. package/dist/prod/core/invariants.js +3 -2
  60. package/dist/prod/core/lanes.js +117 -52
  61. package/dist/prod/core/optimistic.js +474 -103
  62. package/dist/prod/core/owner.js +131 -84
  63. package/dist/prod/core/scheduler.js +1013 -248
  64. package/dist/prod/core/verdict.js +418 -113
  65. package/dist/prod/index.js +25 -13
  66. package/dist/prod/map.js +314 -151
  67. package/dist/prod/signals.js +382 -32
  68. package/dist/prod/store/index.js +38 -0
  69. package/dist/prod/store/next/optimistic.js +710 -0
  70. package/dist/prod/store/next/projection.js +257 -0
  71. package/dist/prod/store/next/reconcile.js +373 -0
  72. package/dist/prod/store/next/store.js +2356 -0
  73. package/dist/prod/store/next/target.js +51 -0
  74. package/dist/prod/store/store.js +129 -881
  75. package/dist/prod/store/utils.js +982 -242
  76. package/dist/types/attribution.d.ts +19 -0
  77. package/dist/types/attribution.prod.d.ts +22 -0
  78. package/dist/types/boundaries.d.ts +78 -5
  79. package/dist/types/core/action.d.ts +12 -5
  80. package/dist/types/core/async.d.ts +3 -1
  81. package/dist/types/core/attribution-costs.d.ts +35 -0
  82. package/dist/types/core/attribution-feedback.d.ts +133 -0
  83. package/dist/types/core/attribution-hooks.d.ts +304 -0
  84. package/dist/types/core/attribution-queries.d.ts +24 -0
  85. package/dist/types/core/attribution.d.ts +892 -0
  86. package/dist/types/core/constants.d.ts +179 -0
  87. package/dist/types/core/core.d.ts +305 -23
  88. package/dist/types/core/dev.d.ts +421 -8
  89. package/dist/types/core/effect.d.ts +8 -1
  90. package/dist/types/core/error-hooks.d.ts +71 -0
  91. package/dist/types/core/error.d.ts +9 -0
  92. package/dist/types/core/graph.d.ts +23 -0
  93. package/dist/types/core/heap.d.ts +5 -3
  94. package/dist/types/core/index.d.ts +6 -3
  95. package/dist/types/core/invariants.d.ts +5 -1
  96. package/dist/types/core/lanes.d.ts +51 -19
  97. package/dist/types/core/owner.d.ts +15 -3
  98. package/dist/types/core/scheduler.d.ts +252 -3
  99. package/dist/types/core/types.d.ts +124 -41
  100. package/dist/types/index.d.ts +18 -5
  101. package/dist/types/map.d.ts +2 -0
  102. package/dist/types/signals.d.ts +164 -13
  103. package/dist/types/store/index.d.ts +16 -5
  104. package/dist/types/store/next/optimistic.d.ts +25 -0
  105. package/dist/types/store/next/projection.d.ts +27 -0
  106. package/dist/types/store/next/reconcile.d.ts +10 -0
  107. package/dist/types/store/next/store.d.ts +143 -0
  108. package/dist/types/store/next/target.d.ts +196 -0
  109. package/dist/types/store/store.d.ts +46 -112
  110. package/dist/types/store/utils.d.ts +188 -40
  111. package/package.json +32 -26
  112. package/dist/node.cjs +0 -7938
  113. package/dist/prod/store/optimistic.js +0 -217
  114. package/dist/prod/store/projection.js +0 -231
  115. package/dist/prod/store/reconcile.js +0 -707
  116. package/dist/types/store/optimistic.d.ts +0 -45
  117. package/dist/types/store/projection.d.ts +0 -70
  118. package/dist/types/store/reconcile.d.ts +0 -46
  119. package/dist/types-cjs/affects.d.cts +0 -47
  120. package/dist/types-cjs/boundaries.d.cts +0 -175
  121. package/dist/types-cjs/core/action.d.cts +0 -64
  122. package/dist/types-cjs/core/async.d.cts +0 -21
  123. package/dist/types-cjs/core/constants.d.cts +0 -71
  124. package/dist/types-cjs/core/core.d.cts +0 -148
  125. package/dist/types-cjs/core/dev.d.cts +0 -64
  126. package/dist/types-cjs/core/effect.d.cts +0 -30
  127. package/dist/types-cjs/core/error.d.cts +0 -47
  128. package/dist/types-cjs/core/external.d.cts +0 -15
  129. package/dist/types-cjs/core/graph.d.cts +0 -5
  130. package/dist/types-cjs/core/heap.d.cts +0 -22
  131. package/dist/types-cjs/core/index.d.cts +0 -13
  132. package/dist/types-cjs/core/invariants.d.cts +0 -59
  133. package/dist/types-cjs/core/lanes.d.cts +0 -56
  134. package/dist/types-cjs/core/optimistic.d.cts +0 -6
  135. package/dist/types-cjs/core/owner.d.cts +0 -124
  136. package/dist/types-cjs/core/scheduler.d.cts +0 -170
  137. package/dist/types-cjs/core/types.d.cts +0 -148
  138. package/dist/types-cjs/core/verdict.d.cts +0 -2
  139. package/dist/types-cjs/index.d.cts +0 -10
  140. package/dist/types-cjs/map.d.cts +0 -69
  141. package/dist/types-cjs/package.json +0 -3
  142. package/dist/types-cjs/signals.d.cts +0 -605
  143. package/dist/types-cjs/store/index.d.cts +0 -9
  144. package/dist/types-cjs/store/optimistic.d.cts +0 -45
  145. package/dist/types-cjs/store/projection.d.cts +0 -70
  146. package/dist/types-cjs/store/reconcile.d.cts +0 -46
  147. package/dist/types-cjs/store/store.d.cts +0 -213
  148. package/dist/types-cjs/store/storePath.d.cts +0 -58
  149. package/dist/types-cjs/store/utils.d.cts +0 -114
@@ -1,21 +1,21 @@
1
- import { REACTIVE_DISPOSED, REACTIVE_IN_HEAP, REACTIVE_IN_HEAP_HEIGHT, REACTIVE_ZOMBIE, CONFIG_TRANSPARENT, defaultContext } from "./constants.js";
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
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
 
9
- import { GlobalQueue, zombieQueue, dirtyQueue, globalQueue } from "./scheduler.js";
9
+ import { GlobalQueue, wokenTransitions, schedule, zombieQueue, dirtyQueue, globalQueue } from "./scheduler.js";
10
10
 
11
11
  const PENDING_OWNER = {};
12
12
 
13
13
  // Dummy owner to trigger store's read() path
14
14
  function markDisposal(e) {
15
- let n = e.Fe;
15
+ let n = e.tn;
16
16
  while (n) {
17
- const e = n.se;
18
- n.se = e | REACTIVE_ZOMBIE;
17
+ const e = n.oe;
18
+ n.oe = 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
@@ -26,104 +26,146 @@ function markDisposal(e) {
26
26
  if (e & REACTIVE_IN_HEAP) insertIntoHeap(n, zombieQueue); else insertIntoHeapHeight(n, zombieQueue);
27
27
  }
28
28
  markDisposal(n);
29
- n = n.He;
29
+ n = n.un;
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_DISPOSED — resurrecting 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.C &= ~CONFIG_AUTO_DISPOSE;
41
+ unobserved(e);
45
42
  }
46
43
 
47
44
  function disposeChildren(e, n = false, t) {
48
- const i = e.se;
45
+ const i = e.oe;
49
46
  if (i & REACTIVE_DISPOSED) return;
47
+ // A previous frame parked as zombies (#3404) dies with its owner (#3024):
48
+ // the commit that would retire it returns on the DISPOSED flag set below,
49
+ // so it drains here or its cleanups never run and the zombies stay
50
+ // subscribed, to rerun in a torn-down tree (#3561). Death only (`self`):
51
+ // a rerun's `disposeChildren(el)` leaves the frame rendering until commit.
52
+ if (n && !t && e.o !== null && (e.o._n !== null || e.o.fn !== null)) disposeChildren(e, false, true);
50
53
  if (n) {
51
- e.se = i | REACTIVE_DISPOSED;
54
+ e.oe = i | REACTIVE_DISPOSED;
52
55
  // Companions are created detached and outlive their owner, but a verdict
53
56
  // must not: a disposed source can never settle, so an isPending companion
54
57
  // latched `true` here would hold a spinner forever (INV-9, the PR #2845
55
58
  // edge). Snap runs after the DISPOSED flag is set so the oracle reads
56
59
  // false, and notifies subscribers still watching the companion.
57
60
  const n = e;
58
- if (n.ge || n.pe) GlobalQueue.un(n);
61
+ if (n.o?.Ze || n.o?.He) GlobalQueue.ti(n);
62
+ // A firewall's leaves have no lifecycle of their own, so a companion on
63
+ // one of them outlives its source the same way (INV-9's rationale). The
64
+ // firewall knows which leaves carry companions (CONFIG_CHILD_COMPANIONS,
65
+ // #3038): snap them with it — the snap retires a shadow whose firewall is
66
+ // disposed (spec O5).
67
+ if (n.C & CONFIG_CHILD_COMPANIONS) n.o.Un.forEach(GlobalQueue.ti);
68
+ // A pending reader parked in a transaction may be the only thing holding
69
+ // it (#3372): its death is a completion event the transaction must be
70
+ // re-judged for, and nothing else re-enters a parked transaction.
71
+ const t = n.we;
72
+ if (t && n.h & STATUS_PENDING && !wokenTransitions.includes(t)) wokenTransitions.push(t),
73
+ schedule();
59
74
  }
60
- if (n && e.ce) e.Te = null;
61
- let l = t ? e.We : e.Fe;
75
+ if (n && e.he && e.o !== null) e.o.Ce = null;
76
+ let l = t ? e.o?._n ?? null : e.tn;
77
+ if (!t) e.tn = null;
62
78
  while (l) {
63
- const e = l.He;
64
- const n = l;
79
+ const e = l;
80
+ // Owner teardown is death regardless of the child's own lifecycle
81
+ // (#3024): strip AUTO_DISPOSE so a post-disposal read freezes at the
82
+ // last committed value instead of reawakening in a torn-down tree.
83
+ // Runs before the recursion so already-dormant children (whose
84
+ // disposeChildren call early-returns on REACTIVE_DISPOSED) die too.
85
+ // Only unobserved()'s own node keeps its dormancy — it is never in
86
+ // this loop; its children are rebuilt fresh on reawaken.
87
+ e.C &= ~CONFIG_AUTO_DISPOSE;
65
88
  // Heap removal must not be gated on `_deps`: a dependency-free
66
89
  // computation queued by refresh() has a null dep list but still sits in
67
90
  // the dirty heap, and left there the post-disposal flush recomputes it —
68
91
  // recompute() rewriting `_flags` clears REACTIVE_DISPOSED and the node
69
92
  // 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
- }
93
+ // deleteFromHeap self-guards on the in-heap flags (and tolerates plain
94
+ // Owners, whose _flags is undefined), so no gate here.
95
+ deleteFromHeap(e, queueFor(e));
96
+ clearDeps(e);
97
+ // The chain is detached above so a node a cleanup links mid-drain lands
98
+ // on the fresh head and survives. Pointing each drained child's prev at
99
+ // itself routes its later splice onto the detached chain, never the head,
100
+ // and keeps the dev owner-chain-head invariant honest for those children.
101
+ l.gn = l;
79
102
  disposeChildren(l, true);
80
- l = e;
103
+ // Read after, not before: a sibling this disposal made dormant spliced
104
+ // itself out of the detached chain, and a cleanup may then have linked
105
+ // it at the fresh head, which rewrote the `_nextSibling` a pre-read
106
+ // would still be holding.
107
+ l = l.un;
81
108
  }
82
109
  if (t) {
83
- e.We = null;
84
- } else {
85
- e.Fe = null;
86
- e.qe = 0;
87
- }
110
+ if (e.o !== null) e.o._n = null;
111
+ } else e.En = 0;
88
112
  // O(1) splice out of parent's chain on individual dispose. Skipped during
89
113
  // batch dispose (parent already disposed) and zombie disposal (node sits on
90
114
  // parent's _pendingFirstChild). We leave node._nextSibling intact so outer
91
115
  // walks that already advanced past us still reach later siblings.
92
- if (n && !t && !(i & REACTIVE_ZOMBIE) && e.ke !== null && !(e.ke.se & REACTIVE_DISPOSED)) {
93
- const n = e.ct;
94
- const t = e.He;
95
- if (n !== null) n.He = t; else e.ke.Fe = t;
96
- if (t !== null) t.ct = n;
97
- e.ct = null;
116
+ if (n && !t && !(i & REACTIVE_ZOMBIE) && e._parent !== null && !(e._parent.oe & REACTIVE_DISPOSED)) {
117
+ const n = e.gn;
118
+ const t = e.un;
119
+ if (n !== null) n.un = t; else e._parent.tn = t;
120
+ if (t !== null) t.gn = n;
121
+ e.gn = null;
98
122
  }
99
123
  runDisposal(e, t);
100
124
  // Final effect-returned cleanup fires at true disposal, after `_disposal`
101
125
  // to mirror rerun ordering (compute-phase teardown first, cleanup last).
102
- if (n && e.Tt) {
103
- const n = e.Tt;
104
- e.Tt = undefined;
126
+ if (n && e.wn) {
127
+ const n = e.wn;
128
+ e.wn = undefined;
105
129
  n();
106
130
  }
107
131
  }
108
132
 
133
+ function linkChild(e, n) {
134
+ const t = e.tn;
135
+ n.gn = null;
136
+ n.un = t;
137
+ if (t !== null) t.gn = n;
138
+ e.tn = n;
139
+ }
140
+
109
141
  function runDisposal(e, n) {
110
- let t = n ? e.Qe : e.ye;
142
+ // Detach the list BEFORE running it (#3601), as `_cleanup` is (#2813). A
143
+ // cleanup that disposes an ancestor re-enters this node through the death
144
+ // walk while the loop is still running; with the list still attached, that
145
+ // walk ran every entry a second time. Detached, the re-entrant drain finds
146
+ // nothing. The same shape latched a throwing cleanup: the list survived the
147
+ // throw and every later drain re-ran and re-threw it.
148
+ const t = n ? e.o?.fn : e.qe;
111
149
  if (!t) return;
150
+ if (n) e.o.fn = null; else e.qe = null;
112
151
  if (Array.isArray(t)) {
113
- for (let e = 0; e < t.length; e++) {
152
+ // Unwind order (#3572, restores 1.x #1562): later registrations run
153
+ // before earlier ones. Children have already been disposed by the caller,
154
+ // so with LIFO a body that registers cleanup before creating its children
155
+ // tears down after them — the same order a per-component owner gives.
156
+ for (let e = t.length - 1; e >= 0; e--) {
114
157
  const n = t[e];
115
158
  n.call(n);
116
159
  }
117
160
  } else {
118
161
  t.call(t);
119
162
  }
120
- n ? e.Qe = null : e.ye = null;
121
163
  }
122
164
 
123
165
  function childId(e, n) {
124
166
  let t = e;
125
- while (t.T & CONFIG_TRANSPARENT && t.ke) t = t.ke;
126
- if (t.id != null) return formatId(t.id, n ? t.qe++ : t.qe);
167
+ while (t.C & CONFIG_TRANSPARENT && t._parent) t = t._parent;
168
+ if (t.id != null) return formatId(t.id, n ? t.En++ : t.En);
127
169
  throw new Error("");
128
170
  }
129
171
 
@@ -204,7 +246,7 @@ function formatId(e, n) {
204
246
  * checks. `cleanup()` is the unchecked primitive used by internals.
205
247
  */ function cleanup(e) {
206
248
  if (!context) return e;
207
- if (!context.ye) context.ye = e; else if (Array.isArray(context.ye)) context.ye.push(e); else context.ye = [ context.ye, e ];
249
+ if (!context.qe) context.qe = e; else if (Array.isArray(context.qe)) context.qe.push(e); else context.qe = [ context.qe, e ];
208
250
  return e;
209
251
  }
210
252
 
@@ -224,7 +266,7 @@ function formatId(e, n) {
224
266
  * }
225
267
  * ```
226
268
  */ function isDisposed(e) {
227
- return !!(e.se & (REACTIVE_DISPOSED | REACTIVE_ZOMBIE));
269
+ return !!(e.oe & (REACTIVE_DISPOSED | REACTIVE_ZOMBIE));
228
270
  }
229
271
 
230
272
  function disposeRootSelf(e = true) {
@@ -241,40 +283,40 @@ function disposeRootSelf(e = true) {
241
283
  */ function createOwner(e) {
242
284
  const n = context;
243
285
  const t = e?.transparent ?? false;
244
- const i = {
286
+ // Prod and observe boilerplates (see core.ts computed()). The observe
287
+ // literal carries the `_name` slot the rendering layer fills with the
288
+ // component label (`owner._name = "<App>"`) — a slot, so labelling a root
289
+ // is a plain store rather than a shape fork between labelled and plain roots.
290
+ const i = {
245
291
  id: inheritId(e, t, n),
246
- T: t ? CONFIG_TRANSPARENT : 0,
247
- Nt: true,
248
- dt: n?.Nt ? n.dt : n,
249
- Fe: null,
250
- He: null,
251
- ct: null,
252
- ye: null,
253
- C: n?.C ?? globalQueue,
254
- we: n?.we || defaultContext,
255
- qe: 0,
256
- Qe: null,
257
- We: null,
258
- ke: n,
292
+ C: t ? CONFIG_TRANSPARENT : 0,
293
+ Wn: true,
294
+ qn: n?.Wn ? n.qn : n,
295
+ tn: null,
296
+ un: null,
297
+ gn: null,
298
+ qe: null,
299
+ T: n?.T ?? globalQueue,
300
+ Je: n?.Je || defaultContext,
301
+ En: 0,
302
+ o: null,
303
+ _parent: n,
259
304
  dispose: disposeRootSelf
260
305
  };
261
- if (n) {
262
- const e = n.Fe;
263
- if (e === null) {
264
- n.Fe = i;
265
- } else {
266
- i.He = e;
267
- e.ct = i;
268
- n.Fe = i;
269
- }
270
- }
306
+ if (n) linkChild(n, i);
271
307
  return i;
272
308
  }
273
309
 
274
310
  /**
275
- * Creates a detached reactive root. The callback receives a `dispose()`
276
- * function which, when called, tears down every signal, memo, effect, and
277
- * `onCleanup` registered inside the root.
311
+ * Creates a reactive root — an owner scope with its own `dispose()`. A root
312
+ * created inside an existing owner is owned by it and is disposed when the
313
+ * parent is disposed; call `dispose()` to tear it down earlier. To create a
314
+ * root that outlives its creator, detach explicitly:
315
+ * `runWithOwner(null, () => createRoot(...))`. Pass `id` to seed hydration
316
+ * ids for the tree it owns.
317
+ *
318
+ * `dispose()` tears down every signal, memo, effect, and `onCleanup`
319
+ * registered inside the root.
278
320
  *
279
321
  * Use this to host long-lived reactive scopes outside of a component (custom
280
322
  * controllers, app bootstrapping, tests). Inside a component, prefer
@@ -282,6 +324,7 @@ function disposeRootSelf(e = true) {
282
324
  *
283
325
  * @example
284
326
  * ```ts
327
+ * // At module level there is no owner, so this root lives until disposed.
285
328
  * const dispose = createRoot(dispose => {
286
329
  * const [n, setN] = createSignal(0);
287
330
  * createEffect(() => n(), value => console.log(value));
@@ -291,6 +334,10 @@ function disposeRootSelf(e = true) {
291
334
  *
292
335
  * // Later, to tear everything down:
293
336
  * dispose();
337
+ *
338
+ * // Inside an owner (component, effect, another root), detach explicitly
339
+ * // if the root must outlive its creator:
340
+ * const detached = runWithOwner(null, () => createRoot(d => d));
294
341
  * ```
295
342
  *
296
343
  * @description https://docs.solidjs.com/reference/reactive-utilities/create-root
@@ -299,4 +346,4 @@ function disposeRootSelf(e = true) {
299
346
  return runWithOwner(t, () => e(() => t.dispose()));
300
347
  }
301
348
 
302
- export { cleanup, createOwner, createRoot, dispose, disposeChildren, getNextChildId, getObserver, getOwner, inheritId, isDisposed, markDisposal, peekNextChildId };
349
+ export { cleanup, createOwner, createRoot, dispose, disposeChildren, getNextChildId, getObserver, getOwner, inheritId, isDisposed, linkChild, markDisposal, peekNextChildId };