@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
@@ -1,8 +1,10 @@
1
- import { CONFIG_HAS_LANE, NOT_PENDING } from "./constants.js";
1
+ import { CONFIG_DERIVED_OVERRIDE, CONFIG_HAS_LANE, REACTIVE_DISPOSED } from "./constants.js";
2
2
 
3
- import { ext } from "./core.js";
3
+ import { hasActiveOverride, ext, ownsHold, currentOptimisticLane } from "./core.js";
4
4
 
5
- import { currentTransition, activeTransition } from "./scheduler.js";
5
+ import { enqueueSub } from "./heap.js";
6
+
7
+ import { currentTransition, activeTransition, waitingTransition } from "./scheduler.js";
6
8
 
7
9
  // Map from optimistic signal to its lane (reused for multiple writes to same signal)
8
10
  const signalLanes = new WeakMap;
@@ -20,16 +22,16 @@ const activeLanes = new Set;
20
22
  }
21
23
  // Detect parent lane: _parentSource chains from pendingSignal → pendingValueComputed → original.
22
24
  // The child lane should not merge with the parent lane.
23
- const t = n.o?.St;
24
- const i = t?.o?.$e;
25
- const r = i ? findLane(i) : null;
25
+ const i = n.o?.Ht;
26
+ const t = i?.o?.Ue;
27
+ const r = t ? findLane(t) : null;
26
28
  e = {
27
- nn: n,
28
- Oe: new Set,
29
- tn: [ [], [] ],
30
- rn: null,
31
- Ae: activeTransition,
32
- an: r
29
+ an: n,
30
+ ye: new Set,
31
+ fn: [ [], [] ],
32
+ cn: null,
33
+ Ge: activeTransition,
34
+ Ln: r
33
35
  };
34
36
  signalLanes.set(n, e);
35
37
  activeLanes.add(e);
@@ -39,69 +41,117 @@ const activeLanes = new Set;
39
41
  // parent-child is a property of the nodes, not of write order — otherwise
40
42
  // the owner's write merges the companion's subscribers into this lane and
41
43
  // their effects wait on its async instead of flushing immediately.
42
- adoptCompanionLane(n.o?.ye, e);
43
- adoptCompanionLane(n.o?.Ce, e);
44
+ adoptCompanionLane(n.o?.je, e);
45
+ adoptCompanionLane(n.o?.xe, e);
44
46
  return e;
45
47
  }
46
48
 
47
49
  function adoptCompanionLane(n, e) {
48
50
  if (!n) return;
49
- const t = signalLanes.get(n);
50
- if (!t) return;
51
- const i = findLane(t);
51
+ const i = signalLanes.get(n);
52
+ if (!i) return;
53
+ const t = findLane(i);
52
54
  // Only the companion's own unmerged root is safely re-parentable: a root
53
55
  // that absorbed other lanes carries work that is not a child of this owner.
54
- if (i !== e && i.nn === n && !i.an) i.an = e;
56
+ if (t !== e && t.an === n && !t.Ln) t.Ln = e;
55
57
  }
56
58
 
57
59
  /**
58
60
  * Union-find: find the root lane.
59
61
  */ function findLane(n) {
60
- while (n.rn) n = n.rn;
62
+ while (n.cn) n = n.cn;
61
63
  return n;
62
64
  }
63
65
 
64
66
  /**
65
67
  * Is the lane held? `_pendingAsync` records the async the lane OWNS (derived
66
- * under it); the transaction's reporter map records the async a render effect
68
+ * under it); a transaction's reporter map records the async a render effect
67
69
  * OBSERVED pending with no boundary taking it (INV-3, the one registration
68
70
  * site). A hold needs both — the same rule the transaction itself uses, so a
69
71
  * memo nobody renders, or one a fallback-showing boundary caught, cannot tear
70
72
  * a frame and holds nothing (#3289). An orphan lane has no observation record
71
73
  * and never holds.
74
+ *
75
+ * The observation is looked up per NODE, in whichever live transaction
76
+ * recorded it — not in this lane's transaction. Lanes merge across
77
+ * transactions (#2912: ownership never travels through lanes), so after a
78
+ * merge the root's transaction holds the observations of only one member;
79
+ * the async the other member's transaction observed must hold the merged
80
+ * reveal just the same (A15 for lanes, #3335).
72
81
  */ function laneHeld(n) {
73
- const e = n.Ae;
74
- if (e) for (const t of n.Oe) if (currentTransition(e)._e.has(t)) return true;
82
+ if (!n.Ge) return false;
83
+ for (const e of n.ye) if (waitingTransition(e) !== null) return true;
75
84
  return false;
76
85
  }
77
86
 
87
+ /**
88
+ * Lanes mirror transitions (#3460): a render effect OFF a HELD lane that reads
89
+ * a value the lane is revealing — an override, a `latest()` shadow — sees the
90
+ * committed value, exactly as a stale reader of a held transaction does
91
+ * (A15 reveal corollary): it publishes now, with the frame that is on screen
92
+ * (the lane defers its own readers' runs, so the committed value is what is
93
+ * visible), entangles nothing — a sync write is never held by a lane — and
94
+ * re-derives at the release. The release re-run rides the lane's own render
95
+ * queue, which runs when the lane reveals (runLaneEffects) or its transaction
96
+ * commits (cleanupCompletedLanes). A reader ON the lane computes the lane's
97
+ * reveal and takes the value as before.
98
+ *
99
+ * OFF the lane is provenance, not membership — the transaction mirror
100
+ * exactly: a stale reader of a transaction is a pass that runs outside it. A
101
+ * pass under the lane's own transaction is the lane's work — its write (lane
102
+ * posture), or the landing of its async, which re-enters the transaction
103
+ * (#3334) and runs a member with no ambient lane. Read as an outsider, that
104
+ * pass published the committed view and queued a replay that revealed the
105
+ * override beside its unready derivation at the release (`1:0` for an
106
+ * optimistic frame that never became ready; #3479 review). Membership is the
107
+ * wrong test the other way: a member re-run by a sibling's sync write is a
108
+ * mainline pass and shows the committed view.
109
+ */ function readsHeldCommitted(n, e) {
110
+ const i = resolveLane(n);
111
+ if (!i || !laneHeld(i)) return false;
112
+ if (ownsLane(i, n)) return false;
113
+ i.fn[0].push(() => e.ue & REACTIVE_DISPOSED || enqueueSub(e));
114
+ return true;
115
+ }
116
+
117
+ /** The ownership relation for a lane hold (core `ownsHold`, §6 ruling 2): the
118
+ * running pass owns `lane`'s hold if it runs under the transition that owns
119
+ * the lane (the node's, resolved through override ownership and merges) or
120
+ * inside the lane itself. */ function ownsLane(n, e) {
121
+ if (activeTransition !== null) {
122
+ const n = resolveTransition(e);
123
+ if (n && ownsHold(n)) return true;
124
+ }
125
+ return currentOptimisticLane !== null && findLane(currentOptimisticLane) === n;
126
+ }
127
+
78
128
  /**
79
129
  * Merge two lanes when their dependency graphs overlap.
80
130
  */ function mergeLanes(n, e) {
81
131
  n = findLane(n);
82
132
  e = findLane(e);
83
133
  if (n === e) return n;
84
- e.rn = n;
134
+ e.cn = n;
85
135
  // Move (not copy) the merged lane's work: after the merge all routing goes
86
136
  // through findLane() to the root, so anything left behind here is dead —
87
137
  // and anything *added* here later is a routing bug (INV-5).
88
- for (const t of e.Oe) n.Oe.add(t);
89
- e.Oe.clear();
90
- n.tn[0].push(...e.tn[0]);
91
- n.tn[1].push(...e.tn[1]);
92
- e.tn[0].length = 0;
93
- e.tn[1].length = 0;
138
+ for (const i of e.ye) n.ye.add(i);
139
+ e.ye.clear();
140
+ n.fn[0].push(...e.fn[0]);
141
+ n.fn[1].push(...e.fn[1]);
142
+ e.fn[0].length = 0;
143
+ e.fn[1].length = 0;
94
144
  return n;
95
145
  }
96
146
 
97
147
  /**
98
148
  * Resolve a node's lane: follow union-find chain, verify active, clear if stale.
99
149
  */ function resolveLane(n) {
100
- const e = n.o?.$e;
150
+ const e = n.o?.Ue;
101
151
  if (!e) return undefined;
102
- const t = findLane(e);
103
- if (activeLanes.has(t)) return t;
104
- if (n.o !== null) n.o.$e = undefined;
152
+ const i = findLane(e);
153
+ if (activeLanes.has(i)) return i;
154
+ if (n.o !== null) n.o.Ue = undefined;
105
155
  return undefined;
106
156
  }
107
157
 
@@ -111,51 +161,45 @@ function resolveTransition(n) {
111
161
  // transactions (#2912) — the merged root's _transition would hand this
112
162
  // node's override to whichever action wrote last through the shared
113
163
  // reader. Chase merge chains; a dead owner settled through another path.
114
- if (hasActiveOverride(n) && n.o?.Tt) {
115
- const e = ext(n).Tt = currentTransition(n.o?.Tt);
116
- if (e.sn !== true) return e;
117
- if (n.o !== null) n.o.Tt = null;
164
+ if (hasActiveOverride(n) && n.o?.Ft) {
165
+ const e = ext(n).Ft = currentTransition(n.o?.Ft);
166
+ if (e.Tt !== true) return e;
167
+ if (n.o !== null) n.o.Ft = null;
118
168
  }
119
- return resolveLane(n)?.Ae ?? n.Ae;
120
- }
121
-
122
- /**
123
- * Check if a node has an active optimistic override.
124
- */ function hasActiveOverride(n) {
125
- const e = n.o;
126
- return e !== null && e.Pe !== undefined && e.Pe !== NOT_PENDING;
169
+ return resolveLane(n)?.Ge ?? n.Ge;
127
170
  }
128
171
 
129
172
  /**
130
173
  * Assign or merge a lane onto a node. At convergence points (node already has
131
174
  * a different active lane), merge unless the node has an active override.
132
175
  */ function assignOrMergeLane(n, e) {
133
- const t = findLane(e);
134
- const i = n.o?.$e;
135
- if (i) {
136
- // If the subscriber's lane was merged into another lane, it's stale
137
- // replace it with the new source lane instead of following the merge chain
138
- // (which would incorrectly merge the new lane into the old group)
139
- if (i.rn) {
140
- ext(n).$e = e;
141
- n.T |= CONFIG_HAS_LANE;
142
- return;
143
- }
144
- const r = findLane(i);
176
+ const i = findLane(e);
177
+ const t = n.o?.Ue;
178
+ if (t) {
179
+ // A merged lane is followed to its root like any other: the root is where
180
+ // the subscriber's affinity lives now. Replacing it with the source lane
181
+ // outright (as this once did) skipped the parent/child check below an
182
+ // isPending reader of two async siblings had their two companion lanes
183
+ // merge, and the next parent-lane notification then moved it onto the
184
+ // held parent, where its verdict waited on the async it reports (#3409).
185
+ const r = findLane(t);
145
186
  if (activeLanes.has(r)) {
146
- if (r !== t && !hasActiveOverride(n)) {
187
+ // A WRITTEN override is its own lane's source and merges nothing
188
+ // through it; a derived one (lanes stage, #3479) is a plain member —
189
+ // the shared reader that merges two writers' lanes carries one.
190
+ if (r !== i && (!hasActiveOverride(n) || n.T & CONFIG_DERIVED_OVERRIDE)) {
147
191
  // Parent-child lanes stay independent so isPending resolves without
148
192
  // waiting for the parent's async. The child keeps ownership.
149
- if (t.an && findLane(t.an) === r) {
150
- ext(n).$e = e;
193
+ if (i.Ln && findLane(i.Ln) === r) {
194
+ ext(n).Ue = e;
151
195
  n.T |= CONFIG_HAS_LANE;
152
- } else if (r.an && findLane(r.an) === t) ; else mergeLanes(t, r);
196
+ } else if (r.Ln && findLane(r.Ln) === i) ; else mergeLanes(i, r);
153
197
  }
154
198
  return;
155
199
  }
156
200
  }
157
- ext(n).$e = e;
201
+ ext(n).Ue = e;
158
202
  n.T |= CONFIG_HAS_LANE;
159
203
  }
160
204
 
161
- export { activeLanes, assignOrMergeLane, findLane, getOrCreateLane, hasActiveOverride, laneHeld, mergeLanes, resolveLane, resolveTransition, signalLanes };
205
+ export { activeLanes, assignOrMergeLane, findLane, getOrCreateLane, hasActiveOverride, laneHeld, mergeLanes, ownsLane, readsHeldCommitted, resolveLane, resolveTransition, signalLanes };