@solidjs/signals 2.0.0-rc.13 → 2.0.0-rc.15

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 (121) hide show
  1. package/dist/dev-shared.js +2059 -3768
  2. package/dist/dev.attribution.js +237 -101
  3. package/dist/dev.js +7466 -8497
  4. package/dist/observe/affects.js +128 -104
  5. package/dist/observe/boundaries.js +492 -665
  6. package/dist/observe/core/action.js +63 -66
  7. package/dist/observe/core/async.js +243 -379
  8. package/dist/observe/core/attribution-queries.js +1 -1
  9. package/dist/observe/core/attribution.js +394 -253
  10. package/dist/observe/core/constants.js +120 -187
  11. package/dist/observe/core/context.js +3 -3
  12. package/dist/observe/core/core.js +874 -1440
  13. package/dist/observe/core/dev.js +3 -3
  14. package/dist/observe/core/effect.js +73 -84
  15. package/dist/observe/core/external.js +5 -5
  16. package/dist/observe/core/graph.js +62 -71
  17. package/dist/observe/core/heap.js +75 -98
  18. package/dist/observe/core/invariants.js +1 -34
  19. package/dist/observe/core/lanes.js +750 -181
  20. package/dist/observe/core/owner.js +80 -101
  21. package/dist/observe/core/scheduler.js +719 -1356
  22. package/dist/observe/core/verdict.js +314 -621
  23. package/dist/observe/flatten.js +79 -0
  24. package/dist/observe/index.js +15 -13
  25. package/dist/observe/map.js +232 -235
  26. package/dist/observe/reveal.js +212 -0
  27. package/dist/observe/signals.js +144 -216
  28. package/dist/observe/store/affects.js +142 -0
  29. package/dist/observe/store/hooks.js +13 -0
  30. package/dist/observe/store/index.js +27 -24
  31. package/dist/observe/store/optimistic.js +571 -0
  32. package/dist/observe/store/projection.js +308 -0
  33. package/dist/observe/store/reconcile.js +259 -0
  34. package/dist/observe/store/store.js +1988 -277
  35. package/dist/observe/store/storePath.js +1 -1
  36. package/dist/{prod/store/next → observe/store}/target.js +17 -18
  37. package/dist/observe/store/types.js +73 -0
  38. package/dist/observe/store/utils.js +1 -13
  39. package/dist/prod/affects.js +130 -106
  40. package/dist/prod/boundaries.js +476 -654
  41. package/dist/prod/core/action.js +71 -74
  42. package/dist/prod/core/async.js +306 -444
  43. package/dist/prod/core/constants.js +117 -186
  44. package/dist/prod/core/context.js +3 -3
  45. package/dist/prod/core/core.js +888 -1462
  46. package/dist/prod/core/effect.js +88 -99
  47. package/dist/prod/core/external.js +5 -5
  48. package/dist/prod/core/graph.js +62 -71
  49. package/dist/prod/core/heap.js +75 -98
  50. package/dist/prod/core/invariants.js +1 -32
  51. package/dist/prod/core/lanes.js +712 -181
  52. package/dist/prod/core/owner.js +75 -96
  53. package/dist/prod/core/scheduler.js +686 -1335
  54. package/dist/prod/core/verdict.js +309 -621
  55. package/dist/prod/flatten.js +77 -0
  56. package/dist/prod/index.js +15 -13
  57. package/dist/prod/map.js +142 -145
  58. package/dist/prod/reveal.js +212 -0
  59. package/dist/prod/signals.js +155 -227
  60. package/dist/prod/store/affects.js +142 -0
  61. package/dist/prod/store/hooks.js +13 -0
  62. package/dist/prod/store/index.js +26 -19
  63. package/dist/prod/store/optimistic.js +566 -0
  64. package/dist/prod/store/projection.js +301 -0
  65. package/dist/prod/store/reconcile.js +259 -0
  66. package/dist/prod/store/store.js +1883 -272
  67. package/dist/prod/store/storePath.js +1 -1
  68. package/dist/{observe/store/next → prod/store}/target.js +13 -17
  69. package/dist/prod/store/types.js +73 -0
  70. package/dist/prod/store/utils.js +1 -11
  71. package/dist/types/affects.d.ts +11 -30
  72. package/dist/types/boundaries.d.ts +66 -176
  73. package/dist/types/carved.d.ts +1 -0
  74. package/dist/types/core/action.d.ts +5 -6
  75. package/dist/types/core/async.d.ts +10 -5
  76. package/dist/types/core/attribution-hooks.d.ts +20 -1
  77. package/dist/types/core/attribution.d.ts +26 -11
  78. package/dist/types/core/constants.d.ts +130 -180
  79. package/dist/types/core/core.d.ts +134 -264
  80. package/dist/types/core/dev.d.ts +2 -2
  81. package/dist/types/core/effect.d.ts +0 -7
  82. package/dist/types/core/graph.d.ts +7 -1
  83. package/dist/types/core/heap.d.ts +5 -7
  84. package/dist/types/core/index.d.ts +5 -5
  85. package/dist/types/core/invariants.d.ts +0 -29
  86. package/dist/types/core/lanes.d.ts +74 -86
  87. package/dist/types/core/owner.d.ts +3 -3
  88. package/dist/types/core/scheduler.d.ts +255 -331
  89. package/dist/types/core/types.d.ts +45 -85
  90. package/dist/types/core/verdict.d.ts +3 -0
  91. package/dist/types/flatten.d.ts +8 -0
  92. package/dist/types/index.d.ts +6 -4
  93. package/dist/types/reveal.d.ts +19 -0
  94. package/dist/types/signals.d.ts +35 -91
  95. package/dist/types/store/affects.d.ts +12 -0
  96. package/dist/types/store/hooks.d.ts +48 -0
  97. package/dist/types/store/index.d.ts +34 -15
  98. package/dist/types/store/optimistic.d.ts +23 -0
  99. package/dist/types/store/projection.d.ts +18 -0
  100. package/dist/types/store/reconcile.d.ts +3 -0
  101. package/dist/types/store/store.d.ts +132 -145
  102. package/dist/types/store/storePath.d.ts +1 -1
  103. package/dist/types/store/target.d.ts +151 -0
  104. package/dist/types/store/types.d.ts +84 -0
  105. package/package.json +1 -1
  106. package/dist/observe/core/optimistic.js +0 -669
  107. package/dist/observe/store/next/optimistic.js +0 -717
  108. package/dist/observe/store/next/projection.js +0 -266
  109. package/dist/observe/store/next/reconcile.js +0 -375
  110. package/dist/observe/store/next/store.js +0 -2608
  111. package/dist/prod/core/optimistic.js +0 -658
  112. package/dist/prod/store/next/optimistic.js +0 -710
  113. package/dist/prod/store/next/projection.js +0 -257
  114. package/dist/prod/store/next/reconcile.js +0 -373
  115. package/dist/prod/store/next/store.js +0 -2484
  116. package/dist/types/core/optimistic.d.ts +0 -6
  117. package/dist/types/store/next/optimistic.d.ts +0 -25
  118. package/dist/types/store/next/projection.d.ts +0 -27
  119. package/dist/types/store/next/reconcile.d.ts +0 -10
  120. package/dist/types/store/next/store.d.ts +0 -145
  121. package/dist/types/store/next/target.d.ts +0 -196
@@ -1,129 +1,153 @@
1
- import { forEachDependent } from "./core/async.js";
1
+ import { $REFRESH, CONFIG_VERDICT, STATUS_PENDING, CONFIG_SLOT_NODE, STATUS_ERROR, REACTIVE_RECOMPUTING_DEPS } from "./core/constants.js";
2
2
 
3
- import { ext, statusNotifierOf } from "./core/core.js";
4
-
5
- import { $REFRESH, STATUS_PENDING } from "./core/constants.js";
3
+ import { ext } from "./core/core.js";
6
4
 
7
5
  import "./core/dev.js";
8
6
 
9
- import { NotReadyError } from "./core/error.js";
10
-
11
- import { GlobalQueue, globalQueue, schedule, shiftAffectsMarks } from "./core/scheduler.js";
12
-
13
- import "./core/verdict.js";
14
-
15
- import "./core/effect.js";
16
-
17
- import "./core/invariants.js";
18
-
19
- import { $TARGET, getStoreAffectsNodes } from "./store/store.js";
7
+ import { enqueueSub } from "./core/heap.js";
8
+
9
+ import { schedule, resolveTx, flushTransaction, GlobalQueue } from "./core/scheduler.js";
10
+
11
+ import { storeMarks, installStoreAffects, releaseMarkScope } from "./store/affects.js";
12
+
13
+ import { $TARGET } from "./store/types.js";
14
+
15
+ // `affects()` — the declaration verb of the pending model (A24 (4), ruled
16
+ // 2026-07-13; the #2893 audit corollaries; rebuilt on L2 2026-10-02 as ruled:
17
+ // transaction-inert).
18
+ // A mark is a declared in-flight change: the marked node — and everything
19
+ // derived from it — reads pending (`isPending` → true) from the declaration
20
+ // until the surrounding transaction lands (an ambient mark, declared outside
21
+ // one, releases at the next seam). The marked values stay readable: no reader
22
+ // suspends on a mark, a mark holds nothing and entangles nothing — it is not
23
+ // a node of its transaction (`blocked` never sees it), and a reader of marked
24
+ // data joins nothing through it. A mark is never a re-ask, so a declared
25
+ // reload's own `refresh()` cannot silence it; a real error outranks it.
26
+ // Representation: a count on the marked node (`_x._marks`), listed with its
27
+ // scope (the transaction's `_marks`, or the ambient list). Coverage of the
28
+ // derivations is pull-derived at probe time — `isPending`'s read walks the
29
+ // probed node's dependencies for a marked one (verdict.ts → `_marked`) — so
30
+ // nothing is stored downstream and a mid-window recompute strands nothing.
31
+ // The push half is the verdict readers' re-derivation at registration and at
32
+ // release (`repoll`): the only notification a mark makes.
33
+ // Installed on `GlobalQueue` when imported: a program that never declares a
34
+ // mark carries none of this.
35
+ /** Live marks, every scope — the gate on the probe's walk. */
36
+ let active = 0;
37
+
38
+ /** Marks declared outside a transaction: released at the next seam. */ const ambient = [];
39
+
40
+ /** The verdict readers downstream of `node` — through derivations, stopping
41
+ * at effects — re-derive: the mark's one notification (a probe's answer
42
+ * changed with no value notifying anyone). */ function repoll(e, t = new Set) {
43
+ for (let r = e.t; r !== null; r = r.o) {
44
+ const e = r.l;
45
+ if (t.has(e)) continue;
46
+ t.add(e);
47
+ if (e.i & CONFIG_VERDICT) enqueueSub(e);
48
+ if (!e.u) repoll(e, t);
49
+ }
50
+ }
20
51
 
21
- /**
22
- * The counting half of a mark, shared by direct registration and store-scope
23
- * inheritance (a node created inside a live keyless mark's identity scope).
24
- * A mark is ONLY this count: coverage of everything derived from the node is
25
- * pull-derived by the verdict layer's `markWalk` (dep-graph reachability), so
26
- * nothing is stored downstream and nothing can be stranded or stripped by
27
- * mid-window recomputes.
28
- */ function markAffects(e) {
29
- ext(e).t = (e.o?.t || 0) + 1;
30
- shiftAffectsMarks(1);
52
+ /** A node is covered by a live mark iff it carries one, or derives — through
53
+ * its current dependencies — from one that does. A real error outranks an
54
+ * inherited mark (A24 (c)): coverage does not flow through an errored node
55
+ * (a direct mark on one still reads pending). Mid-recompute, only the
56
+ * validated prefix of the dependency list is this pass's. */ function marked(e, t) {
57
+ if (e.m !== null && e.m.T !== 0) return true;
58
+ const r = e;
59
+ if (r.S & STATUS_ERROR || t.has(e)) return false;
60
+ t.add(e);
61
+ const n = r.R & REACTIVE_RECOMPUTING_DEPS ? r.p : undefined;
62
+ if (n !== null) for (let e = r.G ?? null; e !== null; e = e._) {
63
+ if (marked(e.I, t)) return true;
64
+ if (e === n) break;
65
+ }
66
+ return false;
31
67
  }
32
68
 
33
- /**
34
- * Boundary visual channel: within a transaction, a live mark holds Loading
35
- * fallbacks / reveal ordering the way real in-flight async would — but the
36
- * notification is tagged visibility-only at the source (`_markVisual`), so
37
- * the root queue never registers reporters from it: marks are invisible to
38
- * ALL completion and settlement accounting by construction. Boundaries hold
39
- * the marked node in `_sources` while `_affectsCount` is live; the release
40
- * sweep (finalizePureQueue re-checks boundary children after mark release)
41
- * is the display-state update point. Ambient marks release inside the same
42
- * flush that would surface them, before effects run — verdict-only, netting
43
- * no visual change.
44
- */ function notifyMarkBoundaries(e) {
45
- if (!e.u && !e.o?.i) return;
46
- const r = new NotReadyError(e);
47
- r.l = true;
48
- const t = new Set;
49
- const visit = e => {
50
- if (t.has(e)) return;
51
- t.add(e);
52
- // Display consumers (render effects, boundary computeds) act on the
53
- // notification; descent stops there, exactly like the status rails.
54
- const o = statusNotifierOf(e);
55
- if (o) {
56
- o.call(e, STATUS_PENDING, r);
57
- return;
69
+ /** Releases one scope's marks (a landed transaction's, the ambient list at
70
+ * the seam): a node whose last mark drops re-derives its verdict readers. */ function release(e) {
71
+ for (let t = 0; t < e.length; t++) {
72
+ const r = e[t];
73
+ active--;
74
+ if (--r.m.T === 0) {
75
+ repoll(r);
76
+ // A store mark's carrier: its scope (and the marks the nodes born in
77
+ // its window inherited) goes with it.
78
+ releaseMarkScope(r);
58
79
  }
59
- forEachDependent(e, visit);
60
- };
61
- forEachDependent(e, visit);
80
+ }
81
+ e.length = 0;
62
82
  }
63
83
 
64
- /**
65
- * Registers one `affects()` mark on a node: counts it, records the
66
- * registration with the current transaction (after initTransition the queue's
67
- * batch IS the active transition, mirroring `_optimisticNodes`), re-derives
68
- * every downstream verdict companion (the mark channel's only push — verdict
69
- * pokes, not state), and notifies boundary display state. Both walks run on
70
- * every registration (not just the first): subscribers gained since an
71
- * earlier overlapping registration get covered, and dedup stops re-descent.
72
- */ function registerAffectsMark(e) {
73
- markAffects(e);
74
- globalQueue.m.A.push(e);
75
- // Companions only exist once the verdict layer (isPending/latest) loaded;
76
- // without them there is no materialized verdict to poke.
77
- GlobalQueue.k !== null && GlobalQueue.k(e);
78
- notifyMarkBoundaries(e);
79
- schedule();
84
+ /** One registration: a count on the node, listed with the scope — the
85
+ * flush's transaction, or the ambient list (released at the seam). */ function register(e) {
86
+ mark(e);
87
+ const t = flushTransaction;
88
+ if (t === null) ambient.push(e); else {
89
+ const r = resolveTx(t);
90
+ (r.T ??= []).push(e);
91
+ }
92
+ repoll(e);
80
93
  }
81
94
 
82
- /**
83
- * Releases one registration. When the node's last mark drops, re-derives
84
- * every downstream verdict through the settlement snap (committed, not
85
- * transition-scoped — release runs inside queue finalization, where a
86
- * setSignal would open a fresh override window that nothing settles).
87
- */ function releaseAffectsMark(e) {
88
- shiftAffectsMarks(-1);
89
- e.o.t--;
90
- if (!e.o.t) {
91
- GlobalQueue.k !== null && GlobalQueue.k(e, true);
92
- GlobalQueue.p?.(e);
93
- }
95
+ function mark(e) {
96
+ ext(e).T++;
97
+ active++;
94
98
  }
95
99
 
96
- /**
97
- * Releases one batch of affects marks (a settling transaction's, or the
98
- * ambient batch at a plain flush end).
99
- */ function releaseAffectsMarks(e) {
100
- for (let r = 0; r < e.length; r++) releaseAffectsMark(e[r]);
101
- e.length = 0;
100
+ function affects(e, t) {
101
+ // A store (the store half, store/affects.ts): the slot's leaf, or the
102
+ // record's carrier and every live node under it.
103
+ const r = e?.[$TARGET];
104
+ if (r !== undefined) {
105
+ installStoreAffects();
106
+ const e = storeMarks(r, t);
107
+ for (let t = 0; t < e.length; t++) register(e[t]);
108
+ schedule();
109
+ return;
110
+ }
111
+ const n = e?.[$REFRESH];
112
+ if (!n) {
113
+ return;
114
+ }
115
+ register(n);
116
+ schedule();
102
117
  }
103
118
 
104
- // Late installation (same pattern as `GlobalQueue._update`): the mark engine
105
- // lives with the feature so graphs that never declare a mark never ship it.
106
- // Each call site is gated by state only this module creates (a non-empty
107
- // `_affectsNodes` batch, a live scope in the store's `affectsScopes`), so the
108
- // hooks are installed before the first time any of them can fire.
109
- GlobalQueue.G = releaseAffectsMarks;
119
+ GlobalQueue.N = e => active !== 0 && marked(e, new Set);
110
120
 
111
- GlobalQueue.M = markAffects;
121
+ GlobalQueue.O = mark;
112
122
 
113
- GlobalQueue.j = releaseAffectsMark;
123
+ GlobalQueue.k = release;
114
124
 
115
- function affects(e, r) {
116
- const t = e?.[$TARGET];
117
- if (t) {
118
- const e = getStoreAffectsNodes(t, r);
119
- for (let r = 0; r < e.length; r++) registerAffectsMark(e[r]);
125
+ GlobalQueue.A = e => {
126
+ if (ambient.length === 0) return;
127
+ // The flush parked: the declaration's window is the frame's — the marks
128
+ // are its transaction's ("nothing async below ⇒ no window").
129
+ if (e !== null) {
130
+ const t = e.T ??= [];
131
+ for (let e = 0; e < ambient.length; e++) t.push(ambient[e]);
132
+ ambient.length = 0;
120
133
  return;
121
134
  }
122
- const o = e?.[$REFRESH];
123
- if (o) {
124
- registerAffectsMark(o);
125
- return;
135
+ // Nothing parked, but a marked node's own flight is up (a declared
136
+ // reload's quiet re-ask — the node's, or a store leaf's family derive):
137
+ // the window is the flight's; the mark stays to the seam after the
138
+ // landing. The rest release: verdict-only, nothing to show.
139
+ let t = 0;
140
+ const r = [];
141
+ for (let e = 0; e < ambient.length; e++) {
142
+ const n = ambient[e];
143
+ if (inFlight(n)) ambient[t++] = n; else r.push(n);
126
144
  }
145
+ ambient.length = t;
146
+ if (r.length !== 0) release(r);
147
+ };
148
+
149
+ function inFlight(e) {
150
+ return (e.S & STATUS_PENDING) !== 0 || (e.i & CONFIG_SLOT_NODE) !== 0 && GlobalQueue.C?.(e) === true;
127
151
  }
128
152
 
129
153
  export { affects };