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

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 (198) hide show
  1. package/dist/dev-shared.js +6505 -0
  2. package/dist/dev.attribution.js +3484 -0
  3. package/dist/dev.js +10227 -9508
  4. package/dist/observe/affects-marks.js +86 -0
  5. package/dist/observe/affects.js +112 -0
  6. package/dist/observe/attribution.js +7 -0
  7. package/dist/observe/boundaries.js +696 -0
  8. package/dist/observe/core/action.js +182 -0
  9. package/dist/observe/core/async.js +824 -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 +3079 -0
  15. package/dist/observe/core/constants.js +269 -0
  16. package/dist/observe/core/context.js +63 -0
  17. package/dist/observe/core/copies.js +10 -0
  18. package/dist/observe/core/core.js +1707 -0
  19. package/dist/observe/core/dev.js +394 -0
  20. package/dist/observe/core/effect.js +193 -0
  21. package/dist/observe/core/error-hooks.js +71 -0
  22. package/dist/observe/core/error.js +82 -0
  23. package/dist/observe/core/external.js +97 -0
  24. package/dist/observe/core/graph.js +162 -0
  25. package/dist/observe/core/heap.js +124 -0
  26. package/dist/observe/core/identities.js +62 -0
  27. package/dist/observe/core/invariants.js +12 -0
  28. package/dist/observe/core/lanes.js +972 -0
  29. package/dist/observe/core/owner.js +371 -0
  30. package/dist/observe/core/scheduler.js +1157 -0
  31. package/dist/observe/core/truth.js +47 -0
  32. package/dist/observe/core/verdict.js +470 -0
  33. package/dist/observe/deferred.js +186 -0
  34. package/dist/observe/flatten.js +79 -0
  35. package/dist/observe/from.js +248 -0
  36. package/dist/observe/index.js +71 -0
  37. package/dist/observe/map.js +593 -0
  38. package/dist/observe/reveal.js +212 -0
  39. package/dist/observe/signals.js +717 -0
  40. package/dist/observe/store/affects.js +142 -0
  41. package/dist/observe/store/edges.js +39 -0
  42. package/dist/observe/store/hooks.js +16 -0
  43. package/dist/observe/store/index.js +47 -0
  44. package/dist/observe/store/optimistic.js +713 -0
  45. package/dist/observe/store/projection.js +345 -0
  46. package/dist/observe/store/reconcile.js +281 -0
  47. package/dist/observe/store/store.js +2127 -0
  48. package/dist/observe/store/storePath.js +103 -0
  49. package/dist/observe/store/target.js +46 -0
  50. package/dist/observe/store/types.js +83 -0
  51. package/dist/observe/store/utils.js +1063 -0
  52. package/dist/prod/affects-marks.js +86 -0
  53. package/dist/prod/affects.js +98 -112
  54. package/dist/prod/attribution.js +45 -0
  55. package/dist/prod/boundaries.js +578 -468
  56. package/dist/prod/core/action.js +92 -59
  57. package/dist/prod/core/async.js +522 -336
  58. package/dist/prod/core/attribution-hooks.js +3 -0
  59. package/dist/prod/core/constants.js +168 -44
  60. package/dist/prod/core/context.js +12 -16
  61. package/dist/prod/core/copies.js +10 -0
  62. package/dist/prod/core/core.js +1345 -627
  63. package/dist/prod/core/dev.js +123 -1
  64. package/dist/prod/core/effect.js +113 -80
  65. package/dist/prod/core/error-hooks.js +71 -0
  66. package/dist/prod/core/error.js +18 -4
  67. package/dist/prod/core/external.js +6 -7
  68. package/dist/prod/core/graph.js +119 -72
  69. package/dist/prod/core/heap.js +85 -109
  70. package/dist/prod/core/identities.js +62 -0
  71. package/dist/prod/core/invariants.js +1 -32
  72. package/dist/prod/core/lanes.js +931 -132
  73. package/dist/prod/core/owner.js +192 -129
  74. package/dist/prod/core/scheduler.js +948 -642
  75. package/dist/prod/core/truth.js +47 -0
  76. package/dist/prod/core/verdict.js +409 -420
  77. package/dist/prod/deferred.js +184 -0
  78. package/dist/prod/flatten.js +77 -0
  79. package/dist/prod/from.js +248 -0
  80. package/dist/prod/index.js +40 -16
  81. package/dist/prod/map.js +481 -211
  82. package/dist/prod/reveal.js +212 -0
  83. package/dist/prod/signals.js +401 -84
  84. package/dist/prod/store/affects.js +142 -0
  85. package/dist/prod/store/edges.js +39 -0
  86. package/dist/prod/store/hooks.js +16 -0
  87. package/dist/prod/store/index.js +27 -18
  88. package/dist/prod/store/optimistic.js +707 -0
  89. package/dist/prod/store/projection.js +331 -0
  90. package/dist/prod/store/reconcile.js +281 -0
  91. package/dist/prod/store/store.js +1952 -267
  92. package/dist/prod/store/storePath.js +1 -1
  93. package/dist/prod/store/target.js +43 -0
  94. package/dist/prod/store/types.js +83 -0
  95. package/dist/prod/store/utils.js +997 -138
  96. package/dist/types/affects-marks.d.ts +14 -0
  97. package/dist/types/affects.d.ts +12 -30
  98. package/dist/types/attribution.d.ts +19 -0
  99. package/dist/types/attribution.prod.d.ts +22 -0
  100. package/dist/types/boundaries.d.ts +99 -124
  101. package/dist/types/carved.d.ts +1 -0
  102. package/dist/types/core/action.d.ts +23 -9
  103. package/dist/types/core/async.d.ts +34 -6
  104. package/dist/types/core/attribution-costs.d.ts +35 -0
  105. package/dist/types/core/attribution-feedback.d.ts +133 -0
  106. package/dist/types/core/attribution-hooks.d.ts +307 -8
  107. package/dist/types/core/attribution-queries.d.ts +24 -0
  108. package/dist/types/core/attribution.d.ts +802 -72
  109. package/dist/types/core/constants.d.ts +195 -38
  110. package/dist/types/core/copies.d.ts +54 -0
  111. package/dist/types/core/core.d.ts +295 -65
  112. package/dist/types/core/dev.d.ts +509 -22
  113. package/dist/types/core/effect.d.ts +1 -1
  114. package/dist/types/core/error-hooks.d.ts +71 -0
  115. package/dist/types/core/error.d.ts +18 -1
  116. package/dist/types/core/graph.d.ts +40 -1
  117. package/dist/types/core/heap.d.ts +5 -5
  118. package/dist/types/core/identities.d.ts +17 -0
  119. package/dist/types/core/index.d.ts +11 -7
  120. package/dist/types/core/invariants.d.ts +1 -26
  121. package/dist/types/core/lanes.d.ts +74 -43
  122. package/dist/types/core/owner.d.ts +27 -9
  123. package/dist/types/core/scheduler.d.ts +353 -102
  124. package/dist/types/core/truth.d.ts +18 -0
  125. package/dist/types/core/types.d.ts +97 -71
  126. package/dist/types/core/verdict.d.ts +35 -0
  127. package/dist/types/deferred.d.ts +28 -0
  128. package/dist/types/flatten.d.ts +8 -0
  129. package/dist/types/from.d.ts +47 -0
  130. package/dist/types/index.d.ts +33 -7
  131. package/dist/types/map.d.ts +4 -2
  132. package/dist/types/reveal.d.ts +19 -0
  133. package/dist/types/signals.d.ts +196 -45
  134. package/dist/types/store/affects.d.ts +12 -0
  135. package/dist/types/store/edges.d.ts +9 -0
  136. package/dist/types/store/hooks.d.ts +62 -0
  137. package/dist/types/store/index.d.ts +42 -15
  138. package/dist/types/store/optimistic.d.ts +24 -45
  139. package/dist/types/store/projection.d.ts +17 -68
  140. package/dist/types/store/reconcile.d.ts +3 -46
  141. package/dist/types/store/store.d.ts +133 -136
  142. package/dist/types/store/storePath.d.ts +1 -1
  143. package/dist/types/store/target.d.ts +166 -0
  144. package/dist/types/store/types.d.ts +105 -0
  145. package/dist/types/store/utils.d.ts +188 -0
  146. package/package.json +31 -26
  147. package/dist/node.cjs +0 -8745
  148. package/dist/prod/core/optimistic.js +0 -265
  149. package/dist/prod/store/next/optimistic.js +0 -385
  150. package/dist/prod/store/next/projection.js +0 -172
  151. package/dist/prod/store/next/reconcile.js +0 -331
  152. package/dist/prod/store/next/store.js +0 -1499
  153. package/dist/prod/store/next/target.js +0 -20
  154. package/dist/types/core/optimistic.d.ts +0 -6
  155. package/dist/types/store/next/optimistic.d.ts +0 -20
  156. package/dist/types/store/next/projection.d.ts +0 -8
  157. package/dist/types/store/next/reconcile.d.ts +0 -3
  158. package/dist/types/store/next/store.d.ts +0 -77
  159. package/dist/types/store/next/target.d.ts +0 -117
  160. package/dist/types-cjs/affects.d.cts +0 -47
  161. package/dist/types-cjs/boundaries.d.cts +0 -175
  162. package/dist/types-cjs/core/action.d.cts +0 -64
  163. package/dist/types-cjs/core/async.d.cts +0 -21
  164. package/dist/types-cjs/core/attribution-hooks.d.cts +0 -52
  165. package/dist/types-cjs/core/attribution.d.cts +0 -186
  166. package/dist/types-cjs/core/constants.d.cts +0 -97
  167. package/dist/types-cjs/core/context.d.cts +0 -36
  168. package/dist/types-cjs/core/core.d.cts +0 -163
  169. package/dist/types-cjs/core/dev.d.cts +0 -81
  170. package/dist/types-cjs/core/effect.d.cts +0 -30
  171. package/dist/types-cjs/core/error.d.cts +0 -47
  172. package/dist/types-cjs/core/external.d.cts +0 -15
  173. package/dist/types-cjs/core/graph.d.cts +0 -6
  174. package/dist/types-cjs/core/heap.d.cts +0 -22
  175. package/dist/types-cjs/core/index.d.cts +0 -13
  176. package/dist/types-cjs/core/invariants.d.cts +0 -59
  177. package/dist/types-cjs/core/lanes.d.cts +0 -44
  178. package/dist/types-cjs/core/optimistic.d.cts +0 -6
  179. package/dist/types-cjs/core/owner.d.cts +0 -124
  180. package/dist/types-cjs/core/scheduler.d.cts +0 -180
  181. package/dist/types-cjs/core/types.d.cts +0 -192
  182. package/dist/types-cjs/core/verdict.d.cts +0 -2
  183. package/dist/types-cjs/index.d.cts +0 -10
  184. package/dist/types-cjs/map.d.cts +0 -69
  185. package/dist/types-cjs/package.json +0 -3
  186. package/dist/types-cjs/signals.d.cts +0 -624
  187. package/dist/types-cjs/store/index.d.cts +0 -19
  188. package/dist/types-cjs/store/next/optimistic.d.cts +0 -20
  189. package/dist/types-cjs/store/next/projection.d.cts +0 -8
  190. package/dist/types-cjs/store/next/reconcile.d.cts +0 -3
  191. package/dist/types-cjs/store/next/store.d.cts +0 -77
  192. package/dist/types-cjs/store/next/target.d.cts +0 -117
  193. package/dist/types-cjs/store/optimistic.d.cts +0 -45
  194. package/dist/types-cjs/store/projection.d.cts +0 -70
  195. package/dist/types-cjs/store/reconcile.d.cts +0 -46
  196. package/dist/types-cjs/store/store.d.cts +0 -138
  197. package/dist/types-cjs/store/storePath.d.cts +0 -58
  198. package/dist/types-cjs/store/utils.d.cts +0 -74
@@ -0,0 +1,86 @@
1
+ import { CONFIG_VERDICT, CONFIG_AUTHORITATIVE, STATUS_ERROR, CONFIG_SLOT_NODE, REACTIVE_RECOMPUTING_DEPS } from "./core/constants.js";
2
+
3
+ import { ext } from "./core/core.js";
4
+
5
+ import { enqueueSub } from "./core/heap.js";
6
+
7
+ import { GlobalQueue } from "./core/scheduler.js";
8
+
9
+ // The mark core: a declared not-final state on a node that reads pending
10
+ // (`isPending` → true) on the node and everything derived from it, without
11
+ // holding anything or entangling a reader. Two declarers share it:
12
+ // `affects()` (affects.ts — a mark scoped to a transaction, with a store
13
+ // half) and `createDeferred` (deferred.ts — a mark whose lifetime is the
14
+ // node's own flight). Split out so the second does not ship the first.
15
+ // Representation: a count on the marked node (`_x._marks`). Coverage of the
16
+ // derivations is pull-derived at probe time — `isPending`'s read walks the
17
+ // probed node's dependencies for a marked one (verdict.ts → `_marked`) — so
18
+ // nothing is stored downstream and a mid-window recompute strands nothing.
19
+ // The push half is the verdict readers' re-derivation when a node's marks
20
+ // start and end (`repoll`): the only notification a mark makes.
21
+ /** Live marks, every declarer — the gate on the probe's walk. */
22
+ let active = 0;
23
+
24
+ /** The verdict readers downstream of `node` — through derivations, stopping
25
+ * at effects — re-derive: the mark's one notification (a probe's answer
26
+ * changed with no value notifying anyone). Truth readers (`until`, the
27
+ * `refresh` waiter) too, which a lagging flight parked (deferred.ts) — but
28
+ * not through a derived store, whose leaves change only once its derive
29
+ * re-runs: they re-derive at that write. */ function repoll(e, r = new Set, o = CONFIG_VERDICT | CONFIG_AUTHORITATIVE) {
30
+ for (let t = e.o; t !== null; t = t.t) {
31
+ const e = t.u;
32
+ if (r.has(e)) continue;
33
+ r.add(e);
34
+ if (e.l & o) enqueueSub(e);
35
+ if (!e.i) repoll(e, r, o);
36
+ // A derived store's derive: its leaves' readers derive from it too
37
+ // (store/projection.ts; a live target's property, has and keys nodes).
38
+ const n = e.fam;
39
+ if (n) for (const e of n.live) for (const o of [ e.n, e.h, {
40
+ k: e.k,
41
+ d: e.dk
42
+ } ]) if (o) for (const e of Reflect.ownKeys(o)) o[e] && repoll(o[e], r, CONFIG_VERDICT);
43
+ }
44
+ }
45
+
46
+ /** A node is covered by a live mark iff it carries one, or derives — through
47
+ * its current dependencies — from one that does. A store slot derives from
48
+ * its family's derive (a derived store's leaves are not the derive's
49
+ * dependents, store/projection.ts), so coverage hops there. A real error
50
+ * outranks an inherited mark (A24 (c)): coverage does not flow through an
51
+ * errored node (a direct mark on one still reads pending). Mid-recompute,
52
+ * only the validated prefix of the dependency list is this pass's. */ function marked(e, r) {
53
+ if (e.T !== null && e.T.I !== 0) return true;
54
+ const o = e;
55
+ if (o.m & STATUS_ERROR || r.has(e)) return false;
56
+ r.add(e);
57
+ if (o.l & CONFIG_SLOT_NODE) {
58
+ const e = o.O?.fam?.node;
59
+ return e != null && marked(e, r);
60
+ }
61
+ const t = o.R & REACTIVE_RECOMPUTING_DEPS ? o._ : undefined;
62
+ if (t !== null) for (let e = o.C ?? null; e !== null; e = e.G) {
63
+ if (marked(e.S, r)) return true;
64
+ if (e === t) break;
65
+ }
66
+ return false;
67
+ }
68
+
69
+ /** One mark on `node`. The declarer repolls once its bookkeeping is done. */ function mark(e) {
70
+ ext(e).I++;
71
+ active++;
72
+ }
73
+
74
+ /** Drops one mark from `node`: true when it was the last — the node's
75
+ * verdict readers have re-derived. */ function unmark(e) {
76
+ active--;
77
+ if (--e.T.I !== 0) return false;
78
+ repoll(e);
79
+ return true;
80
+ }
81
+
82
+ GlobalQueue.p = e => active !== 0 && marked(e, new Set);
83
+
84
+ GlobalQueue.N = mark;
85
+
86
+ export { mark, repoll, unmark };
@@ -1,126 +1,112 @@
1
- import { forEachDependent } from "./core/async.js";
2
-
3
- import { ext } from "./core/core.js";
4
-
5
- import { $REFRESH, STATUS_PENDING } from "./core/constants.js";
6
-
7
- import { NotReadyError } from "./core/error.js";
8
-
9
- import { GlobalQueue, globalQueue, schedule, shiftAffectsMarks } from "./core/scheduler.js";
10
-
11
- import "./core/verdict.js";
12
-
13
- import "./core/effect.js";
14
-
15
- import "./core/invariants.js";
16
-
17
- import { $TARGET, getStoreAffectsNodes } from "./store/store.js";
18
-
19
- /**
20
- * The counting half of a mark, shared by direct registration and store-scope
21
- * inheritance (a node created inside a live keyless mark's identity scope).
22
- * A mark is ONLY this count: coverage of everything derived from the node is
23
- * pull-derived by the verdict layer's `markWalk` (dep-graph reachability), so
24
- * nothing is stored downstream and nothing can be stranded or stripped by
25
- * mid-window recomputes.
26
- */ function markAffects(e) {
27
- ext(e).t = (e.o?.t || 0) + 1;
28
- shiftAffectsMarks(1);
29
- }
30
-
31
- /**
32
- * Boundary visual channel: within a transaction, a live mark holds Loading
33
- * fallbacks / reveal ordering the way real in-flight async would — but the
34
- * notification is tagged visibility-only at the source (`_markVisual`), so
35
- * the root queue never registers reporters from it: marks are invisible to
36
- * ALL completion and settlement accounting by construction. Boundaries hold
37
- * the marked node in `_sources` while `_affectsCount` is live; the release
38
- * sweep (finalizePureQueue re-checks boundary children after mark release)
39
- * is the display-state update point. Ambient marks release inside the same
40
- * flush that would surface them, before effects run — verdict-only, netting
41
- * no visual change.
42
- */ function notifyMarkBoundaries(e) {
43
- if (!e.u && !e.o?.l) return;
44
- const r = new NotReadyError(e);
45
- r.i = true;
46
- const t = new Set;
47
- const visit = e => {
48
- if (t.has(e)) return;
49
- t.add(e);
50
- // Display consumers (render effects, boundary computeds) act on the
51
- // notification; descent stops there, exactly like the status rails.
52
- if (e.o?.A) {
53
- e.o.A.call(e, STATUS_PENDING, r);
54
- return;
55
- }
56
- forEachDependent(e, visit);
57
- };
58
- forEachDependent(e, visit);
1
+ import { $REFRESH, STATUS_PENDING, CONFIG_SLOT_NODE } from "./core/constants.js";
2
+
3
+ import "./core/core.js";
4
+
5
+ import { schedule, resolveTx, flushTransaction, installMarkHooks, GlobalQueue } from "./core/scheduler.js";
6
+
7
+ import { mark, repoll, unmark } from "./affects-marks.js";
8
+
9
+ import { storeMarks, installStoreAffects, releaseMarkScope } from "./store/affects.js";
10
+
11
+ import { $TARGET } from "./store/types.js";
12
+
13
+ // `affects()` — the declaration verb of the pending model (A24 (4), ruled
14
+ // 2026-07-13; the #2893 audit corollaries; rebuilt on L2 2026-10-02 as ruled:
15
+ // transaction-inert).
16
+ // A mark is a declared in-flight change: the marked node — and everything
17
+ // derived from it — reads pending (`isPending` → true) from the declaration
18
+ // until the surrounding transaction lands (an ambient mark, declared outside
19
+ // one, releases at the next seam; either, on a node whose own flight is
20
+ // still up then, at the seam after that flight lands). The marked values stay readable: no reader
21
+ // suspends on a mark, a mark holds nothing and entangles nothing — it is not
22
+ // a node of its transaction (`blocked` never sees it), and a reader of marked
23
+ // data joins nothing through it. A mark is never a re-ask, so a declared
24
+ // reload's own `refresh()` cannot silence it; a real error outranks it.
25
+ // Representation: the mark core (affects-marks.ts) — a count on the marked
26
+ // node, coverage pull-derived at probe time, readers repolled at registration
27
+ // and release. Here: each mark's scope (the transaction's `_marks`, or the
28
+ // ambient list) and the store half.
29
+ // Installed on `GlobalQueue` when imported: a program that never declares a
30
+ // mark carries none of this.
31
+ /** Marks declared outside a transaction: released at the next seam. */
32
+ const ambient = [];
33
+
34
+ /** Releases one scope's marks (a landed transaction's, the ambient list at
35
+ * the seam): a node whose last mark drops re-derives its verdict readers. */ function release(e) {
36
+ for (let t = 0; t < e.length; t++) {
37
+ const r = e[t];
38
+ // A store mark's carrier: its scope (and the marks the nodes born in
39
+ // its window inherited) goes with the last mark.
40
+ if (unmark(r)) releaseMarkScope(r);
41
+ }
42
+ e.length = 0;
59
43
  }
60
44
 
61
- /**
62
- * Registers one `affects()` mark on a node: counts it, records the
63
- * registration with the current transaction (after initTransition the queue's
64
- * batch IS the active transition, mirroring `_optimisticNodes`), re-derives
65
- * every downstream verdict companion (the mark channel's only push — verdict
66
- * pokes, not state), and notifies boundary display state. Both walks run on
67
- * every registration (not just the first): subscribers gained since an
68
- * earlier overlapping registration get covered, and dedup stops re-descent.
69
- */ function registerAffectsMark(e) {
70
- markAffects(e);
71
- globalQueue.k.m.push(e);
72
- // Companions only exist once the verdict layer (isPending/latest) loaded;
73
- // without them there is no materialized verdict to poke.
74
- GlobalQueue.p !== null && GlobalQueue.p(e);
75
- notifyMarkBoundaries(e);
76
- schedule();
45
+ /** One registration: a count on the node, listed with the scope — the
46
+ * flush's transaction, or the ambient list (released at the seam). */ function register(e) {
47
+ mark(e);
48
+ const t = flushTransaction;
49
+ if (t === null) ambient.push(e); else {
50
+ const r = resolveTx(t);
51
+ (r.I ??= []).push(e);
52
+ }
53
+ repoll(e);
77
54
  }
78
55
 
79
- /**
80
- * Releases one registration. When the node's last mark drops, re-derives
81
- * every downstream verdict through the settlement snap (committed, not
82
- * transition-scoped — release runs inside queue finalization, where a
83
- * setSignal would open a fresh override window that nothing settles).
84
- */ function releaseAffectsMark(e) {
85
- shiftAffectsMarks(-1);
86
- e.o.t--;
87
- if (!e.o.t) {
88
- GlobalQueue.p !== null && GlobalQueue.p(e, true);
89
- GlobalQueue.G?.(e);
56
+ function affects(e, t) {
57
+ // A store (the store half, store/affects.ts): the slot's leaf, or the
58
+ // record's carrier and every live node under it.
59
+ const r = e?.[$TARGET];
60
+ if (r !== undefined) {
61
+ installStoreAffects();
62
+ const e = storeMarks(r, t);
63
+ for (let t = 0; t < e.length; t++) register(e[t]);
64
+ schedule();
65
+ return;
90
66
  }
67
+ const s = e?.[$REFRESH];
68
+ if (!s) {
69
+ return;
70
+ }
71
+ register(s);
72
+ schedule();
91
73
  }
92
74
 
93
- /**
94
- * Releases one batch of affects marks (a settling transaction's, or the
95
- * ambient batch at a plain flush end).
96
- */ function releaseAffectsMarks(e) {
97
- for (let r = 0; r < e.length; r++) releaseAffectsMark(e[r]);
75
+ installMarkHooks(e => {
76
+ // A landing's mark on a node whose own flight is up (a declared reload's
77
+ // quiet re-ask the action did not wait for) stays to the seam after
78
+ // that flight lands, as an ambient one does: the reload's window is the
79
+ // flight's (#4349). The rest release with the transaction.
80
+ const t = [];
81
+ for (let r = 0; r < e.length; r++) (inFlight(e[r]) ? ambient : t).push(e[r]);
98
82
  e.length = 0;
99
- }
100
-
101
- // Late installation (same pattern as `GlobalQueue._update`): the mark engine
102
- // lives with the feature so graphs that never declare a mark never ship it.
103
- // Each call site is gated by state only this module creates (a non-empty
104
- // `_affectsNodes` batch, a live scope in the store's `affectsScopes`), so the
105
- // hooks are installed before the first time any of them can fire.
106
- GlobalQueue.M = releaseAffectsMarks;
107
-
108
- GlobalQueue.h = markAffects;
109
-
110
- GlobalQueue.j = releaseAffectsMark;
111
-
112
- function affects(e, r) {
113
- const t = e?.[$TARGET];
114
- if (t) {
115
- const e = getStoreAffectsNodes(t, r);
116
- for (let r = 0; r < e.length; r++) registerAffectsMark(e[r]);
83
+ release(t);
84
+ }, e => {
85
+ if (ambient.length === 0) return;
86
+ // The flush parked: the declaration's window is the frame's — the marks
87
+ // are its transaction's ("nothing async below ⇒ no window").
88
+ if (e !== null) {
89
+ const t = e.I ??= [];
90
+ for (let e = 0; e < ambient.length; e++) t.push(ambient[e]);
91
+ ambient.length = 0;
117
92
  return;
118
93
  }
119
- const o = e?.[$REFRESH];
120
- if (o) {
121
- registerAffectsMark(o);
122
- return;
94
+ // Nothing parked, but a marked node's own flight is up (a declared
95
+ // reload's quiet re-ask — the node's, or a store leaf's family derive):
96
+ // the window is the flight's; the mark stays to the seam after the
97
+ // landing. The rest release: verdict-only, nothing to show.
98
+ let t = 0;
99
+ const r = [];
100
+ for (let e = 0; e < ambient.length; e++) {
101
+ const s = ambient[e];
102
+ if (inFlight(s)) ambient[t++] = s; else r.push(s);
123
103
  }
104
+ ambient.length = t;
105
+ if (r.length !== 0) release(r);
106
+ });
107
+
108
+ function inFlight(e) {
109
+ return (e.m & STATUS_PENDING) !== 0 || (e.l & CONFIG_SLOT_NODE) !== 0 && GlobalQueue.k?.(e) === true;
124
110
  }
125
111
 
126
112
  export { affects };
@@ -0,0 +1,45 @@
1
+ const EMPTY = Object.freeze([]);
2
+
3
+ const noop = () => {};
4
+
5
+ const attribution = {
6
+ enable: () => noop,
7
+ disable: noop,
8
+ history: () => EMPTY,
9
+ markFlight: noop
10
+ };
11
+
12
+ // The named surface, inert: every fold empty, every query empty, every
13
+ // formatter blank. Typed against the real entry's exports so the two cannot
14
+ // drift.
15
+ const costs = () => ({
16
+ scopes: [],
17
+ writes: []
18
+ });
19
+
20
+ const feedback = () => ({
21
+ sources: [],
22
+ interactions: [],
23
+ navigations: [],
24
+ flights: [],
25
+ fallbacks: []
26
+ });
27
+
28
+ const why = () => [];
29
+
30
+ const subscriptions = () => [];
31
+
32
+ const formatRerun = () => "";
33
+
34
+ const formatOrigin = () => "";
35
+
36
+ // Prod registers no roots: the graph has no observable size.
37
+ const graphSize = () => ({
38
+ roots: 0,
39
+ owners: 0,
40
+ computations: 0,
41
+ signals: 0,
42
+ edges: 0
43
+ });
44
+
45
+ export { attribution, costs, feedback, formatOrigin, formatRerun, graphSize, subscriptions, why };