@solidjs/signals 2.0.0-rc.6 → 2.0.0-rc.8

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 (131) hide show
  1. package/dist/dev-shared.js +5243 -0
  2. package/dist/dev.attribution.js +2333 -0
  3. package/dist/dev.js +1758 -6621
  4. package/dist/observe/affects.js +127 -0
  5. package/dist/observe/attribution.js +1 -0
  6. package/dist/observe/boundaries.js +586 -0
  7. package/dist/observe/core/action.js +167 -0
  8. package/dist/observe/core/async.js +736 -0
  9. package/dist/observe/core/attribution-hooks.js +60 -0
  10. package/dist/observe/core/attribution.js +2318 -0
  11. package/dist/{types-cjs/core/constants.d.cts → observe/core/constants.js} +135 -71
  12. package/dist/{types-cjs/core/context.d.cts → observe/core/context.js} +37 -12
  13. package/dist/observe/core/core.js +1289 -0
  14. package/dist/observe/core/dev.js +232 -0
  15. package/dist/observe/core/effect.js +179 -0
  16. package/dist/observe/core/error.js +80 -0
  17. package/dist/observe/core/external.js +98 -0
  18. package/dist/observe/core/graph.js +155 -0
  19. package/dist/observe/core/heap.js +147 -0
  20. package/dist/observe/core/invariants.js +43 -0
  21. package/dist/observe/core/lanes.js +168 -0
  22. package/dist/observe/core/optimistic.js +438 -0
  23. package/dist/observe/core/owner.js +308 -0
  24. package/dist/observe/core/scheduler.js +1190 -0
  25. package/dist/observe/core/verdict.js +551 -0
  26. package/dist/observe/index.js +55 -0
  27. package/dist/observe/map.js +482 -0
  28. package/dist/{types-cjs/signals.d.cts → observe/signals.js} +305 -317
  29. package/dist/observe/store/index.js +38 -0
  30. package/dist/observe/store/next/optimistic.js +651 -0
  31. package/dist/observe/store/next/projection.js +242 -0
  32. package/dist/observe/store/next/reconcile.js +373 -0
  33. package/dist/observe/store/next/store.js +2213 -0
  34. package/dist/observe/store/next/target.js +51 -0
  35. package/dist/observe/store/store.js +323 -0
  36. package/dist/observe/store/storePath.js +103 -0
  37. package/dist/observe/store/utils.js +210 -0
  38. package/dist/prod/attribution.js +32 -0
  39. package/dist/prod/boundaries.js +3 -1
  40. package/dist/prod/core/action.js +52 -32
  41. package/dist/prod/core/async.js +177 -128
  42. package/dist/prod/core/attribution-hooks.js +3 -0
  43. package/dist/prod/core/constants.js +32 -1
  44. package/dist/prod/core/context.js +10 -16
  45. package/dist/prod/core/core.js +505 -286
  46. package/dist/prod/core/dev.js +2 -0
  47. package/dist/prod/core/effect.js +72 -43
  48. package/dist/prod/core/external.js +2 -2
  49. package/dist/prod/core/graph.js +40 -36
  50. package/dist/prod/core/heap.js +50 -51
  51. package/dist/prod/core/lanes.js +43 -22
  52. package/dist/prod/core/optimistic.js +224 -80
  53. package/dist/prod/core/owner.js +43 -39
  54. package/dist/prod/core/scheduler.js +347 -232
  55. package/dist/prod/core/verdict.js +71 -74
  56. package/dist/prod/index.js +9 -5
  57. package/dist/prod/map.js +311 -150
  58. package/dist/prod/signals.js +52 -38
  59. package/dist/prod/store/next/optimistic.js +127 -131
  60. package/dist/prod/store/next/projection.js +3 -3
  61. package/dist/prod/store/next/reconcile.js +149 -294
  62. package/dist/prod/store/next/store.js +694 -380
  63. package/dist/prod/store/next/target.js +32 -10
  64. package/dist/prod/store/store.js +12 -14
  65. package/dist/prod/store/utils.js +36 -27
  66. package/dist/types/attribution.d.ts +15 -0
  67. package/dist/types/attribution.prod.d.ts +13 -0
  68. package/dist/types/core/async.d.ts +1 -1
  69. package/dist/types/core/attribution-hooks.d.ts +183 -6
  70. package/dist/types/core/attribution.d.ts +435 -24
  71. package/dist/types/core/constants.d.ts +31 -0
  72. package/dist/types/core/core.d.ts +19 -3
  73. package/dist/types/core/dev.d.ts +165 -26
  74. package/dist/types/core/effect.d.ts +8 -1
  75. package/dist/types/core/heap.d.ts +5 -3
  76. package/dist/types/core/index.d.ts +2 -1
  77. package/dist/types/core/invariants.d.ts +1 -1
  78. package/dist/types/core/lanes.d.ts +17 -0
  79. package/dist/types/core/scheduler.d.ts +69 -4
  80. package/dist/types/core/types.d.ts +29 -9
  81. package/dist/types/index.d.ts +9 -2
  82. package/dist/types/map.d.ts +2 -0
  83. package/dist/types/signals.d.ts +10 -0
  84. package/dist/types/store/index.d.ts +4 -6
  85. package/dist/types/store/next/optimistic.d.ts +4 -2
  86. package/dist/types/store/next/reconcile.d.ts +5 -12
  87. package/dist/types/store/next/store.d.ts +8 -9
  88. package/dist/types/store/next/target.d.ts +56 -55
  89. package/dist/types/store/store.d.ts +14 -9
  90. package/dist/types/store/utils.d.ts +7 -0
  91. package/package.json +21 -16
  92. package/dist/node.cjs +0 -11121
  93. package/dist/prod/store/next/patch-hooks.js +0 -13
  94. package/dist/prod/store/next/patch.js +0 -614
  95. package/dist/types/store/next/patch-hooks.d.ts +0 -41
  96. package/dist/types/store/next/patch.d.ts +0 -91
  97. package/dist/types-cjs/affects.d.cts +0 -47
  98. package/dist/types-cjs/boundaries.d.cts +0 -175
  99. package/dist/types-cjs/core/action.d.cts +0 -64
  100. package/dist/types-cjs/core/async.d.cts +0 -23
  101. package/dist/types-cjs/core/attribution-hooks.d.cts +0 -63
  102. package/dist/types-cjs/core/attribution.d.cts +0 -239
  103. package/dist/types-cjs/core/core.d.cts +0 -176
  104. package/dist/types-cjs/core/dev.d.cts +0 -95
  105. package/dist/types-cjs/core/effect.d.cts +0 -30
  106. package/dist/types-cjs/core/error.d.cts +0 -56
  107. package/dist/types-cjs/core/external.d.cts +0 -15
  108. package/dist/types-cjs/core/graph.d.cts +0 -28
  109. package/dist/types-cjs/core/heap.d.cts +0 -22
  110. package/dist/types-cjs/core/index.d.cts +0 -13
  111. package/dist/types-cjs/core/invariants.d.cts +0 -59
  112. package/dist/types-cjs/core/lanes.d.cts +0 -44
  113. package/dist/types-cjs/core/optimistic.d.cts +0 -6
  114. package/dist/types-cjs/core/owner.d.cts +0 -124
  115. package/dist/types-cjs/core/scheduler.d.cts +0 -231
  116. package/dist/types-cjs/core/types.d.cts +0 -204
  117. package/dist/types-cjs/core/verdict.d.cts +0 -2
  118. package/dist/types-cjs/index.d.cts +0 -10
  119. package/dist/types-cjs/map.d.cts +0 -69
  120. package/dist/types-cjs/package.json +0 -3
  121. package/dist/types-cjs/store/index.d.cts +0 -21
  122. package/dist/types-cjs/store/next/optimistic.d.cts +0 -23
  123. package/dist/types-cjs/store/next/patch-hooks.d.cts +0 -41
  124. package/dist/types-cjs/store/next/patch.d.cts +0 -91
  125. package/dist/types-cjs/store/next/projection.d.cts +0 -8
  126. package/dist/types-cjs/store/next/reconcile.d.cts +0 -17
  127. package/dist/types-cjs/store/next/store.d.cts +0 -127
  128. package/dist/types-cjs/store/next/target.d.cts +0 -192
  129. package/dist/types-cjs/store/store.d.cts +0 -138
  130. package/dist/types-cjs/store/storePath.d.cts +0 -58
  131. package/dist/types-cjs/store/utils.d.cts +0 -74
@@ -1,4 +1,4 @@
1
- import { STATUS_UNINITIALIZED, CONFIG_CHILD_COMPANIONS, STATUS_ERROR, STATUS_PENDING, REACTIVE_DIRTY, REACTIVE_OPTIMISTIC_DIRTY, NOT_PENDING, CONFIG_AUTHORITATIVE_OBSERVED, CONFIG_AUTO_DISPOSE, REACTIVE_ZOMBIE, REACTIVE_DISPOSED } from "./constants.js";
1
+ import { STATUS_UNINITIALIZED, CONFIG_CHILD_COMPANIONS, STATUS_ERROR, STATUS_PENDING, CONFIG_INPUTS_PUBLISHED, REACTIVE_DIRTY, REACTIVE_OPTIMISTIC_DIRTY, NOT_PENDING, CONFIG_AUTO_DISPOSE, REACTIVE_ZOMBIE, REACTIVE_DISPOSED } from "./constants.js";
2
2
 
3
3
  import { untrack, ext, statusNotifierOf, setSignal, context } from "./core.js";
4
4
 
@@ -14,7 +14,7 @@ import { hasActiveOverride, assignOrMergeLane, resolveLane, resolveTransition }
14
14
 
15
15
  import { cleanup } from "./owner.js";
16
16
 
17
- import { GlobalQueue, schedule, flush, queuePendingNode, insertSubs, clock, currentTransition, globalQueue } from "./scheduler.js";
17
+ import { GlobalQueue, schedule, flush, queuePendingNode, insertSubs, clock, waitingTransition, currentTransition, globalQueue, setOrigin, origin } from "./scheduler.js";
18
18
 
19
19
  // The lazily-created Set is the ONE container for pending sources. Its
20
20
  // predecessor — a singular slot promoted to a Set on the second source —
@@ -40,6 +40,19 @@ function clearPendingSources(e) {
40
40
  if (e.o !== null) e.o.le = undefined;
41
41
  }
42
42
 
43
+ // A rejection-pending only resolves through the settle sweep over the
44
+ // SOURCE's subscribers, so it is retryable iff a tracked read created that
45
+ // edge: a dep that IS the source, or one whose own pending chain carries it
46
+ // (pending sources propagate the origin node, so this covers any depth).
47
+ // Also guards branch-local recovery: another dependency may still need the source.
48
+ function retryReaches(e, n) {
49
+ for (let t = e.fe; t; t = t.ae) {
50
+ const e = t.Se.ce || t.Se;
51
+ if (e === n || e.o?.le?.has(n)) return true;
52
+ }
53
+ return false;
54
+ }
55
+
43
56
  /**
44
57
  * A loading-window node hit an unready source (sync throw in recompute, or a
45
58
  * NotReadyError-rejected flight): register for the source's settle — the
@@ -47,7 +60,7 @@ function clearPendingSources(e) {
47
60
  * with NO read-visible pending status, no downstream propagation, no
48
61
  * transition, no lane registration. Commit #0 keeps serving.
49
62
  */ function parkLoadingWindow(e, n) {
50
- ext(e).fe = true;
63
+ ext(e).de = true;
51
64
  if (n.source) addPendingSource(e, n.source);
52
65
  // A settled error is the node's answer ("the error stays the answer until
53
66
  // this retry can actually run") — the park must not replace it: reads
@@ -72,10 +85,10 @@ function setPendingError(e, n, t) {
72
85
  }
73
86
 
74
87
  function forEachDependent(e, n) {
75
- for (let t = e.u; t !== null; t = t.ae) n(t.ce, t);
88
+ for (let t = e.u; t !== null; t = t.Te) n(t.Ie, t);
76
89
  // `?? null`: affects() marks route plain signals (no `_child` slot) through here.
77
- for (let t = e.o?.i ?? null; t !== null; t = t.Se) {
78
- for (let e = t.u; e !== null; e = e.ae) n(e.ce, e);
90
+ for (let t = e.o?.i ?? null; t !== null; t = t.Ee) {
91
+ for (let e = t.u; e !== null; e = e.Te) n(e.Ie, e);
79
92
  }
80
93
  }
81
94
 
@@ -119,9 +132,9 @@ function releaseSettledDependents(e) {
119
132
  // object identity down the whole dependent tree, and holding it is exactly
120
133
  // the "blocked on this error" marker — re-enqueue those holders so they
121
134
  // re-run: fresh values commit and flow, and a dependent with another
122
- // still-broken source simply re-errors. The async dimension needs no twin of
123
- // its own: recovery there passes through a pending window whose re-runners
124
- // set _blocked and ride settlePendingSource. Walks the full dependent graph
135
+ // still-broken source simply re-errors. Pending recovery uses
136
+ // settlePendingSource to clear inherited status and retry blocked readers.
137
+ // Walks the full dependent graph
125
138
  // (releaseSettledDependents shape): identity holders can sit below an
126
139
  // intermediate whose own error state has since been scrubbed or replaced
127
140
  // (e.g. an error boundary's tree node).
@@ -141,51 +154,63 @@ function settleErroredDependents(e, n) {
141
154
  if (t) schedule();
142
155
  }
143
156
 
144
- function settlePendingSource(e) {
145
- // The normal landing path already cleared the source's own set. Superseded
146
- // re-parks arrive here with an abandoned self entry, which must retire in
147
- // the same walk as its propagated copies.
148
- removePendingSource(e, e);
149
- let n = false;
150
- let t;
151
- const r = new Set;
157
+ // Retire `source` from pending state along the dependent graph rooted at `el`.
158
+ // By default, `el` is the source whose flight settled or was superseded.
159
+ // With a distinct `source`, `el` is a recovered computation that dropped it:
160
+ // the source may still be pending, so dependents with another path to it stay pending.
161
+ function settlePendingSource(e, n = e) {
162
+ // Landing and branch recovery already cleared el's own set. Superseded
163
+ // re-parks can retain an abandoned self entry (source === el), which must
164
+ // retire in the same walk as its propagated copies.
165
+ removePendingSource(e, n);
166
+ let t = false;
167
+ let r;
168
+ const o = new Set;
152
169
  // Companion updates no-op without the verdict layer (null hook).
153
- const o = GlobalQueue.de;
154
- const settle = i => {
155
- if (r.has(i) || !removePendingSource(i, e)) return;
156
- r.add(i);
157
- i.Te = clock;
158
- const l = i.o?.le?.values().next().value;
170
+ const i = GlobalQueue.Ne;
171
+ const settle = s => {
172
+ if (o.has(s)) return;
173
+ // A conditional dropped this source, but another dependency can still
174
+ // carry it. Only retire pending state inherited through the recovered
175
+ // branch. Deliberately NOT marked visited on this early return: the
176
+ // carrying dependency may itself be a later branch of this same walk
177
+ // (two unchanged memos converging), and its visit must be free to
178
+ // re-examine this node once that branch has retired the source.
179
+ if (n !== e && retryReaches(s, n)) return;
180
+ if (!removePendingSource(s, n)) return;
181
+ o.add(s);
182
+ s._e = clock;
183
+ const l = s.o?.le?.values().next().value;
159
184
  // STATUS_ERROR + pending sources only coexist via an errored loading
160
185
  // window's park (notifyStatus(STATUS_ERROR) clears pending sources
161
186
  // otherwise): the settled error stays the answer through the settle —
162
187
  // nulling it here would have reads throw `null` until the re-enqueued
163
188
  // retry lands, or lose it entirely if that retry parks again (#2989).
164
- const s = i.S & STATUS_ERROR;
189
+ const u = s.S & STATUS_ERROR;
165
190
  if (l) {
166
- if (!s) setPendingError(i, l);
167
- o?.(i);
191
+ if (!u) setPendingError(s, l);
192
+ i?.(s);
168
193
  } else {
169
- i.S &= ~STATUS_PENDING;
170
- if (!s) setPendingError(i);
171
- o?.(i);
172
- if (i.o?.fe) {
173
- enqueueSub(i);
174
- n = true;
194
+ s.S &= ~STATUS_PENDING;
195
+ if (!u) setPendingError(s);
196
+ i?.(s);
197
+ if (s.o?.de) {
198
+ enqueueSub(s);
199
+ t = true;
175
200
  }
176
- if (i.o !== null) i.o.fe = false;
201
+ if (s.o !== null) s.o.de = false;
177
202
  // Fully settled with nobody watching: release candidate (#2934). Checked
178
203
  // again at release time — deferred so unobserved() can't unlink subs
179
204
  // lists this walk is still iterating.
180
- if (!i.u && i.T & CONFIG_AUTO_DISPOSE) (t ??= []).push(i);
205
+ if (!s.u && s.T & CONFIG_AUTO_DISPOSE) (r ??= []).push(s);
181
206
  }
182
- forEachDependent(i, settle);
207
+ forEachDependent(s, settle);
183
208
  };
184
209
  forEachDependent(e, settle);
185
210
  // Release before the flush schedule below: unobserved() pulls the node back
186
211
  // out of the heap, so the enqueueSub above never recomputes a released node.
187
- if (t) for (const e of t) releaseIfSettledUnobserved(e);
188
- if (n) schedule();
212
+ if (r) for (const e of r) releaseIfSettledUnobserved(e);
213
+ if (t) schedule();
189
214
  }
190
215
 
191
216
  // Object-thenable detection (Promises/A+ shape).
@@ -194,9 +219,9 @@ function isThenable(e) {
194
219
  }
195
220
 
196
221
  /** Fire and clear a node's iterator-flight cancellation hook (#3122). */ function releaseFlightTeardown(e) {
197
- const n = e.o?.Ee;
222
+ const n = e.o?.De;
198
223
  if (n != null) {
199
- e.o.Ee = null;
224
+ e.o.De = null;
200
225
  n();
201
226
  }
202
227
  }
@@ -211,9 +236,9 @@ function handleAsync(e, n, t) {
211
236
  });
212
237
  }
213
238
  if (!o && !r) {
214
- if (e.o !== null) e.o.Ie = null;
239
+ if (e.o !== null) e.o.Pe = null;
215
240
  // A sync landing is the first real answer for a loadingValue node.
216
- e.Ne = false;
241
+ e.Ae = false;
217
242
  return n;
218
243
  }
219
244
  // Flight replacement relies on recompute's supersede release for iterator
@@ -221,8 +246,13 @@ function handleAsync(e, n, t) {
221
246
  // self-registration — runs during a recompute of `el`, which has already
222
247
  // fired _flightTeardown. A future non-recompute registration path must
223
248
  // release it here before overwriting _inFlight.
224
- ext(e).Ie = n;
225
- let i;
249
+ ext(e).Pe = n;
250
+ // Provenance of the question this flight asks (#3331): the action whose
251
+ // window is registering it, or the flight whose landing is. Its landings
252
+ // propagate under it (asyncWrite) so an override downstream can tell a
253
+ // stale answer from its own.
254
+ const i = origin;
255
+ let s;
226
256
  // Settle-time transition re-entry. The loading rail is invisible to
227
257
  // transactions (#2933): a boundary-caught first load never registers as an
228
258
  // async reporter, so its settle — the boundary's fallback -> content
@@ -234,27 +264,35 @@ function handleAsync(e, n, t) {
234
264
  // keeps transition scheduling; initialized (value-holding) pending settles
235
265
  // are the transaction's reveal machinery and always re-enter.
236
266
  const settleTransition = () => {
237
- const n = resolveTransition(e);
238
- if (n && e.S & STATUS_UNINITIALIZED && !currentTransition(n)._e.has(e)) {
267
+ let n = resolveTransition(e);
268
+ // A lane-routed node's landing is revealed by its lane, ahead of the
269
+ // transaction that owns the lane (whose own commit is only the override's
270
+ // confirm/revert). Entering that owner here would fold every transaction
271
+ // waiting on this flight into it at the landing — a reveal that
272
+ // discovered the flight (#3305) would then wait on the owner's action
273
+ // instead of on the flight (#3334). Enter the waiter: the transaction
274
+ // whose blocker this landing clears.
275
+ if (e.o?.Oe) n = waitingTransition(e) ?? n;
276
+ if (n && e.S & STATUS_UNINITIALIZED && !currentTransition(n).Re.has(e)) {
239
277
  // Drop the stale stamp too: the plain settle write (setSignal) and the
240
278
  // stash-path restamp both re-enter the transaction through it.
241
- e.Ae = null;
279
+ e.ge = null;
242
280
  return;
243
281
  }
244
282
  globalQueue.initTransition(n);
245
283
  };
246
284
  const handleError = t => {
247
- if (e.o?.Ie !== n) return;
285
+ if (e.o?.Pe !== n) return;
248
286
  // NotReadyError from rejected promises should be treated as pending, not error
249
287
  let r = t instanceof NotReadyError;
250
- if (r && e.Ne) {
288
+ if (r && e.Ae) {
251
289
  // Loading window: the flight died waiting on an unready source. Keep
252
290
  // serving commit #0 — same parking as recompute's catch for sync
253
291
  // dependency throws. The dead flight is released so the clock-gated
254
292
  // error-retry pull (updateIfNecessary) can also re-ask.
255
- if (e.o !== null) e.o.Ie = null;
293
+ if (e.o !== null) e.o.Pe = null;
256
294
  parkLoadingWindow(e, t);
257
- e.Te = clock;
295
+ e._e = clock;
258
296
  return;
259
297
  }
260
298
  settleTransition();
@@ -263,36 +301,44 @@ function handleAsync(e, n, t) {
263
301
  // rejected flight will never settle its self entry, so transfer ownership
264
302
  // after notifyStatus has propagated the replacement source.
265
303
  if (r) settlePendingSource(e);
266
- e.Te = clock;
304
+ e._e = clock;
267
305
  // A real error settles derivatively-pending dependents (notifyStatus
268
306
  // cleared their pending sources), so stranded lazy ones release here —
269
307
  // the error twin of settlePendingSource's release (#2934).
270
308
  if (!r) releaseSettledDependents(e);
271
309
  };
272
310
  const asyncWrite = (r, o) => {
273
- if (e.o?.Ie !== n) return;
311
+ if (e.o?.Pe !== n) return;
274
312
  // If the node was dirtied by a newer write (optimistic override or regular),
275
313
  // skip this stale async result — the upcoming flush will recompute the node
276
314
  // with the new value, creating a fresh Promise that supersedes this one.
277
315
  if (e.ie & (REACTIVE_DIRTY | REACTIVE_OPTIMISTIC_DIRTY)) return;
316
+ // The landing propagates under the flight's provenance (#3331) — through
317
+ // the flush below, which clears it.
318
+ setOrigin(i);
278
319
  settleTransition();
279
- const i = !!(e.S & STATUS_UNINITIALIZED);
320
+ const s = !!(e.S & STATUS_UNINITIALIZED);
280
321
  // Captured before clearStatus wipes it: a quiet re-ask's landing may be
281
322
  // transition-held below, and the displayed value keeps answering the same
282
323
  // question until the hold commits — the classification must survive to
283
324
  // that reveal or companion synchronization briefly classifies the held
284
325
  // old value as pending, a one-frame pulse to direct observers (#3178).
285
326
  // A truthy capture implies `_x` exists, so the restore writes it directly.
286
- const l = e.o?.De;
327
+ const l = e.o?.Ue;
287
328
  trimStaleDeps(e);
288
329
  clearStatus(e);
289
- if (l) e.o.De = true;
290
- const s = resolveLane(e);
291
- if (s) s.Oe.delete(e);
330
+ if (l) e.o.Ue = true;
331
+ const u = resolveLane(e);
332
+ if (u) u.he.delete(e);
292
333
  if (t) {
293
- t(r);
294
- if (i) clearStatus(e, true);
295
- } else if (e.o?.Pe !== undefined) {
334
+ try {
335
+ t(r);
336
+ } catch (e) {
337
+ handleError(e);
338
+ return;
339
+ }
340
+ if (s) clearStatus(e, true);
341
+ } else if (e.o?.be !== undefined) {
296
342
  // Optimistic node — resting OR covered by an active override — holds
297
343
  // through the shared pending-node path, exactly like a plain async memo,
298
344
  // so the commit clears STATUS_UNINITIALIZED (#2806) and elevation to
@@ -302,8 +348,8 @@ function handleAsync(e, n, t) {
302
348
  // (A17 — every reader sees the override); the revert reveals whatever
303
349
  // has committed by then, so corrections reveal atomically with their
304
350
  // transition rather than escaping it.
305
- if (e.Re === NOT_PENDING) queuePendingNode(e);
306
- e.Re = r;
351
+ if (e.Ge === NOT_PENDING) queuePendingNode(e);
352
+ e.Ge = r;
307
353
  // The hold is a companion-visible write like any other (A13/A19): the
308
354
  // clearStatus() above computed its verdict before the hold existed, so
309
355
  // isPending must re-derive (the value is not final until commit — V1)
@@ -311,35 +357,34 @@ function handleAsync(e, n, t) {
311
357
  // only notified when the hold is visible to them: under an active
312
358
  // override every reader sees the override (A17), so waking subs would
313
359
  // re-show an unchanged view — the revert is the notification point.
314
- GlobalQueue.Ue?.(e, r);
360
+ // Under an override the landing is handed to the engine's
361
+ // supersedeOverride (A18 supersession, #3331): own-source truth that
362
+ // differs from the override ends the optimism for the graph now (plain
363
+ // channel, lane demoted); a matching arrival is silent except to an
364
+ // authoritative-view reader (until()'s predicate) waiting on exactly
365
+ // this staged truth (#3164 — without the wake the hold deadlocks: the
366
+ // landing waits on the transaction, the transaction on the action, the
367
+ // action on an until() never re-notified). The hook is installed with
368
+ // the engine, which an active override implies. The propagation runs
369
+ // under this flight's provenance (setOrigin above).
370
+ GlobalQueue.pe?.(e, r);
315
371
  if (!hasActiveOverride(e)) {
316
372
  insertSubs(e);
317
- } else if (e.T & CONFIG_AUTHORITATIVE_OBSERVED) {
318
- // A17 silence is stated over ordinary readers; an authoritative-view
319
- // reader (until()'s predicate) observed this node PAST its override
320
- // and is waiting for exactly this staged truth. Without the wake the
321
- // hold deadlocks: the landing waits on the transaction, the
322
- // transaction on the action, the action on an until() that was never
323
- // re-notified (#3164). Same selective wake as the equal-landing
324
- // branch in recompute(). Optional call: the bit implies the
325
- // optimistic engine WAS consulted, but the hook only installs with
326
- // it — a bare-core build must not crash here.
327
- GlobalQueue.he?.(e);
328
- }
329
- e.Te = clock;
330
- } else if (s) {
373
+ } else GlobalQueue.ye(e, r);
374
+ e._e = clock;
375
+ } else if (u) {
331
376
  // Route through lane's effect queue for independent flushing
332
- const n = e.ge;
333
- const t = e.be;
334
- const o = e.pe;
377
+ const n = e.Ce;
378
+ const t = e.me;
379
+ const o = e.ve;
335
380
  try {
336
- if (!n && i || !o || !o(r, t)) {
337
- e.be = r;
338
- e.Te = clock;
381
+ if (!n && s || !o || !o(r, t)) {
382
+ e.me = r;
383
+ e._e = clock;
339
384
  // The latest() shadow write gives latest() effects independent lanes; the
340
385
  // _pendingSignal update is a no-op repeat of the clearStatus() call above
341
386
  // (computePendingState doesn't read _value).
342
- GlobalQueue.Ue?.(e, r);
387
+ GlobalQueue.pe?.(e, r);
343
388
  insertSubs(e, true);
344
389
  }
345
390
  } catch (n) {
@@ -365,9 +410,9 @@ function handleAsync(e, n, t) {
365
410
  // window when the hold commits, so no one-frame isPending pulse can leak
366
411
  // to live observers between the landing and its commit (#2990). The
367
412
  // quiet re-ask classification follows the same schedule (#3178).
368
- if (e.Re === NOT_PENDING) {
369
- e.Ne = false;
370
- if (l) e.o.De = false;
413
+ if (e.Ge === NOT_PENDING) {
414
+ e.Ae = false;
415
+ if (l) e.o.Ue = false;
371
416
  }
372
417
  settlePendingSource(e);
373
418
  schedule();
@@ -401,12 +446,12 @@ function handleAsync(e, n, t) {
401
446
  // meaningful only in the live posture.
402
447
  const consumeIterator = (t, r) => {
403
448
  const o = t[Symbol.asyncIterator]();
449
+ let i = false;
404
450
  let l = false;
405
- let s = false;
406
451
  let u = !r;
407
452
  const close = () => {
408
- if (s) return;
409
- s = true;
453
+ if (l) return;
454
+ l = true;
410
455
  try {
411
456
  const e = o.return?.();
412
457
  if (isThenable(e)) e.then(undefined, () => {});
@@ -417,7 +462,7 @@ function handleAsync(e, n, t) {
417
462
  // owner-death backstop, but its disposal list can be zombie-deferred
418
463
  // until the SUPERSEDING flight settles. The teardown slot fires at the
419
464
  // _inFlight release sites so supersede stops this stream immediately.
420
- ext(e).Ee = close;
465
+ ext(e).De = close;
421
466
  // Release check before each next pull: an unobserved lazy node must tear
422
467
  // down (its close above runs via disposal, closing the iterator) instead
423
468
  // of pumping the stream forever with zero subscribers (#2935).
@@ -446,15 +491,15 @@ function handleAsync(e, n, t) {
446
491
  if (c && u) {
447
492
  t = r;
448
493
  f = true;
449
- if (r.done) s = true;
450
- } else if (e.o?.Ie !== n) {
494
+ if (r.done) l = true;
495
+ } else if (e.o?.Pe !== n) {
451
496
  return;
452
497
  } else if (!r.done) {
453
- l = true;
498
+ i = true;
454
499
  asyncWrite(r.value, iterateOrRelease);
455
500
  } else {
456
- s = true;
457
- if (l) {
501
+ l = true;
502
+ if (i) {
458
503
  schedule();
459
504
  flush();
460
505
  } else {
@@ -467,8 +512,8 @@ function handleAsync(e, n, t) {
467
512
  if (c && u) {
468
513
  r = t;
469
514
  a = true;
470
- } else if (e.o?.Ie === n) {
471
- s = true;
515
+ } else if (e.o?.Pe === n) {
516
+ l = true;
472
517
  handleError(t);
473
518
  settleAutodispose();
474
519
  }
@@ -476,14 +521,14 @@ function handleAsync(e, n, t) {
476
521
  c = false;
477
522
  if (a) {
478
523
  // Match the promise branch, but only rethrow during the initial read.
479
- s = true;
524
+ l = true;
480
525
  handleError(r);
481
526
  if (u) throw r;
482
527
  return true;
483
528
  }
484
529
  if (f && !t.done) {
485
- i = t.value;
486
- l = true;
530
+ s = t.value;
531
+ i = true;
487
532
  return iterate();
488
533
  }
489
534
  return f && t.done;
@@ -491,7 +536,7 @@ function handleAsync(e, n, t) {
491
536
  const f = iterate();
492
537
  // Later iterate() calls run from asyncWrite, where rethrowing would be unhandled.
493
538
  u = false;
494
- return l || f;
539
+ return i || f;
495
540
  };
496
541
  // Landed-synchronously verdict for a LIVE iterator drain; null when no live
497
542
  // drain ran (plain promise flight, or a deferred flatten). Drives the
@@ -515,7 +560,7 @@ function handleAsync(e, n, t) {
515
560
  return true;
516
561
  };
517
562
  if (o) {
518
- let t = false, r = false, o, l = true;
563
+ let t = false, r = false, o, i = true;
519
564
  // Close registration for the flattening path. Consumption starts in a
520
565
  // microtask where the ambient owner is gone (or worse, someone else's),
521
566
  // so `cleanup()` can't be used — the close targets el's disposal list
@@ -527,18 +572,18 @@ function handleAsync(e, n, t) {
527
572
  // becomes disposal-bearing, which is exactly the class a directly
528
573
  // returned iterable already occupies.
529
574
  const registerDeferredClose = n => {
530
- if (!e.Ge) e.Ge = n; else if (Array.isArray(e.Ge)) e.Ge.push(n); else e.Ge = [ e.Ge, n ];
575
+ if (!e.we) e.we = n; else if (Array.isArray(e.we)) e.we.push(n); else e.we = [ e.we, n ];
531
576
  };
532
577
  n.then(r => {
533
- if (l) {
534
- i = r;
578
+ if (i) {
579
+ s = r;
535
580
  t = true;
536
- } else if (e.o?.Ie === n && !(e.ie & REACTIVE_DISPOSED) && flattenIfIterable(r, registerDeferredClose)) ; else {
581
+ } else if (e.o?.Pe === n && !(e.ie & REACTIVE_DISPOSED) && flattenIfIterable(r, registerDeferredClose)) ; else {
537
582
  asyncWrite(r);
538
583
  settleAutodispose();
539
584
  }
540
585
  }, e => {
541
- if (l) {
586
+ if (i) {
542
587
  o = e;
543
588
  r = true;
544
589
  } else {
@@ -546,7 +591,7 @@ function handleAsync(e, n, t) {
546
591
  settleAutodispose();
547
592
  }
548
593
  });
549
- l = false;
594
+ i = false;
550
595
  if (r) {
551
596
  // Settle through the same status path an async rejection uses, then
552
597
  // unwind the in-progress synchronous read so the errored node isn't
@@ -558,12 +603,12 @@ function handleAsync(e, n, t) {
558
603
  // is opened — first-flight work on a loadingValue node is loading-class
559
604
  // (invisible to boundaries and transitions); the flight itself is
560
605
  // already registered in _inFlight and lands through asyncWrite.
561
- if (e.Ne) return e.be;
606
+ if (e.Ae) return e.me;
562
607
  globalQueue.initTransition(resolveTransition(e));
563
608
  throw new NotReadyError(context);
564
- } else if (!flattenIfIterable(i)) {
609
+ } else if (!flattenIfIterable(s)) {
565
610
  // Synchronously-resolved promise: the first real answer landed.
566
- e.Ne = false;
611
+ e.Ae = false;
567
612
  }
568
613
  // A sync-resolved promise holding an AsyncIterable flattened LIVE (we
569
614
  // are still inside the synchronous read): full initial-drain semantics
@@ -573,30 +618,30 @@ function handleAsync(e, n, t) {
573
618
  if (l !== null) {
574
619
  if (!l) {
575
620
  // Loading window: serve commit #0 (see the promise branch above).
576
- if (e.Ne) return e.be;
621
+ if (e.Ae) return e.me;
577
622
  globalQueue.initTransition(resolveTransition(e));
578
623
  throw new NotReadyError(context);
579
624
  }
580
625
  // A sync first yield (or immediate empty completion) is the first real
581
626
  // answer; async yields clear inside asyncWrite.
582
- e.Ne = false;
627
+ e.Ae = false;
583
628
  }
584
- return i;
629
+ return s;
585
630
  }
586
631
 
587
632
  function clearStatus(e, n = false) {
588
633
  if (e.o?.le) clearPendingSources(e);
589
- if (e.o?.fe) if (e.o !== null) e.o.fe = false;
634
+ if (e.o?.de) if (e.o !== null) e.o.de = false;
590
635
  // The pending window is over; its quiet classification dies with it.
591
636
  // (Unconditional: _reask is baked into the node literals, so this is a
592
637
  // plain store to an existing slot — no shape change.)
593
- if (e.o !== null) e.o.De = false;
638
+ if (e.o !== null) e.o.Ue = false;
594
639
  e.S = n ? 0 : e.S & STATUS_UNINITIALIZED;
595
640
  if (e.o?._) setPendingError(e);
596
641
  // Update pending signal for isPending() reactivity (companions only exist
597
642
  // once the verdict layer created them, which installs the hooks).
598
- if (e.o?.ye || e.o?.Ce) GlobalQueue.de(e);
599
- if (e.o?.i && e.T & CONFIG_CHILD_COMPANIONS && GlobalQueue.me !== null) GlobalQueue.me(e);
643
+ if (e.o?.Le || e.o?.Qe) GlobalQueue.Ne(e);
644
+ if (e.o?.i && e.T & CONFIG_CHILD_COMPANIONS && GlobalQueue.ke !== null) GlobalQueue.ke(e);
600
645
  const t = statusNotifierOf(e);
601
646
  if (t) t.call(e);
602
647
  }
@@ -605,12 +650,16 @@ function notifyStatus(e, n, t, r, o) {
605
650
  // Wrap regular errors to track source node
606
651
  if (n === STATUS_ERROR && !(t instanceof StatusError) && !(t instanceof NotReadyError)) t = new StatusError(e, t);
607
652
  const i = n === STATUS_PENDING && t instanceof NotReadyError ? t.source : undefined;
608
- const l = i === e;
609
- const s = n === STATUS_PENDING && e.o?.Pe !== undefined && !l;
610
- const u = s && hasActiveOverride(e);
653
+ const s = i === e;
654
+ const l = n === STATUS_PENDING && e.o?.be !== undefined && !s;
655
+ const u = l && hasActiveOverride(e);
611
656
  if (!r) {
612
657
  if (n === STATUS_PENDING && i) {
613
658
  addPendingSource(e, i);
659
+ // A fresh flight from a settled state starts with its inputs unpublished
660
+ // (a replacement flight while still pending keeps the mark: the first
661
+ // flight's committed inputs are still the frame).
662
+ if (!(e.S & STATUS_PENDING)) e.T &= ~CONFIG_INPUTS_PUBLISHED;
614
663
  e.S = STATUS_PENDING | e.S & STATUS_UNINITIALIZED;
615
664
  // Preserve the current source on this propagation so render-effect notification
616
665
  // can register every distinct pending source with the transition.
@@ -620,14 +669,14 @@ function notifyStatus(e, n, t, r, o) {
620
669
  e.S = n | (n !== STATUS_ERROR ? e.S & STATUS_UNINITIALIZED : 0);
621
670
  ext(e)._ = t;
622
671
  }
623
- GlobalQueue.de?.(e);
624
- if (e.o?.i && e.T & CONFIG_CHILD_COMPANIONS && GlobalQueue.me !== null) GlobalQueue.me(e);
672
+ GlobalQueue.Ne?.(e);
673
+ if (e.o?.i && e.T & CONFIG_CHILD_COMPANIONS && GlobalQueue.ke !== null) GlobalQueue.ke(e);
625
674
  }
626
675
  if (o && !r) {
627
676
  assignOrMergeLane(e, o);
628
677
  }
629
678
  const f = r || u;
630
- const a = r || s ? undefined : o;
679
+ const a = r || l ? undefined : o;
631
680
  const c = statusNotifierOf(e);
632
681
  if (c) {
633
682
  if (r && n === STATUS_PENDING) {
@@ -641,19 +690,19 @@ function notifyStatus(e, n, t, r, o) {
641
690
  return;
642
691
  }
643
692
  forEachDependent(e, (e, r) => {
644
- e.Te = clock;
693
+ e._e = clock;
645
694
  if (n === STATUS_PENDING && i && !e.o?.le?.has(i) || n !== STATUS_PENDING && (e.o?._ !== t || e.o?.le)) {
646
695
  // A pending-observer link is the subscription an `isPending` read created.
647
696
  // It exists so the observer re-runs when the source settles, but it must
648
697
  // not carry a real (non-NotReadyError) error — the synchronous `isPending`
649
698
  // read swallows those, and the async path must match. Re-run the observer
650
699
  // so `isPending` re-evaluates (to not-pending) instead of forwarding.
651
- if (r.ve && n !== STATUS_PENDING && !(t instanceof NotReadyError)) {
700
+ if (r.je && n !== STATUS_PENDING && !(t instanceof NotReadyError)) {
652
701
  enqueueSub(e);
653
702
  schedule();
654
703
  return;
655
704
  }
656
- if (!f && !e.Ae) queuePendingNode(e);
705
+ if (!f && !e.ge) queuePendingNode(e);
657
706
  notifyStatus(e, n, t, f, a);
658
707
  }
659
708
  });
@@ -0,0 +1,3 @@
1
+ let attrHooks = null;
2
+
3
+ export { attrHooks };