@solidjs/signals 2.0.0-rc.7 → 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 (117) hide show
  1. package/dist/dev-shared.js +5243 -0
  2. package/dist/dev.attribution.js +2333 -0
  3. package/dist/dev.js +1229 -6834
  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} +129 -73
  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} +295 -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/core/action.js +52 -32
  40. package/dist/prod/core/async.js +171 -127
  41. package/dist/prod/core/constants.js +24 -1
  42. package/dist/prod/core/context.js +3 -3
  43. package/dist/prod/core/core.js +434 -291
  44. package/dist/prod/core/effect.js +54 -34
  45. package/dist/prod/core/external.js +2 -2
  46. package/dist/prod/core/graph.js +32 -32
  47. package/dist/prod/core/heap.js +49 -44
  48. package/dist/prod/core/lanes.js +45 -38
  49. package/dist/prod/core/optimistic.js +207 -73
  50. package/dist/prod/core/owner.js +43 -39
  51. package/dist/prod/core/scheduler.js +319 -190
  52. package/dist/prod/core/verdict.js +67 -67
  53. package/dist/prod/index.js +9 -3
  54. package/dist/prod/map.js +292 -141
  55. package/dist/prod/signals.js +7 -10
  56. package/dist/prod/store/next/optimistic.js +140 -125
  57. package/dist/prod/store/next/projection.js +3 -3
  58. package/dist/prod/store/next/reconcile.js +87 -84
  59. package/dist/prod/store/next/store.js +524 -280
  60. package/dist/prod/store/next/target.js +32 -10
  61. package/dist/prod/store/store.js +12 -14
  62. package/dist/prod/store/utils.js +36 -27
  63. package/dist/types/attribution.d.ts +15 -0
  64. package/dist/types/attribution.prod.d.ts +13 -0
  65. package/dist/types/core/async.d.ts +1 -1
  66. package/dist/types/core/attribution-hooks.d.ts +119 -6
  67. package/dist/types/core/attribution.d.ts +208 -53
  68. package/dist/types/core/constants.d.ts +23 -0
  69. package/dist/types/core/core.d.ts +7 -0
  70. package/dist/types/core/dev.d.ts +124 -26
  71. package/dist/types/core/effect.d.ts +8 -1
  72. package/dist/types/core/index.d.ts +2 -1
  73. package/dist/types/core/lanes.d.ts +8 -1
  74. package/dist/types/core/scheduler.d.ts +60 -0
  75. package/dist/types/core/types.d.ts +29 -9
  76. package/dist/types/index.d.ts +9 -2
  77. package/dist/types/map.d.ts +2 -0
  78. package/dist/types/store/index.d.ts +1 -0
  79. package/dist/types/store/next/store.d.ts +5 -0
  80. package/dist/types/store/next/target.d.ts +36 -9
  81. package/dist/types/store/utils.d.ts +7 -0
  82. package/package.json +21 -17
  83. package/dist/node.cjs +0 -10541
  84. package/dist/node.dev.cjs +0 -13724
  85. package/dist/types-cjs/affects.d.cts +0 -47
  86. package/dist/types-cjs/boundaries.d.cts +0 -175
  87. package/dist/types-cjs/core/action.d.cts +0 -64
  88. package/dist/types-cjs/core/async.d.cts +0 -23
  89. package/dist/types-cjs/core/attribution-hooks.d.cts +0 -127
  90. package/dist/types-cjs/core/attribution.d.cts +0 -495
  91. package/dist/types-cjs/core/core.d.cts +0 -185
  92. package/dist/types-cjs/core/dev.d.cts +0 -136
  93. package/dist/types-cjs/core/effect.d.cts +0 -30
  94. package/dist/types-cjs/core/error.d.cts +0 -56
  95. package/dist/types-cjs/core/external.d.cts +0 -15
  96. package/dist/types-cjs/core/graph.d.cts +0 -28
  97. package/dist/types-cjs/core/heap.d.cts +0 -24
  98. package/dist/types-cjs/core/index.d.cts +0 -13
  99. package/dist/types-cjs/core/invariants.d.cts +0 -59
  100. package/dist/types-cjs/core/lanes.d.cts +0 -54
  101. package/dist/types-cjs/core/optimistic.d.cts +0 -6
  102. package/dist/types-cjs/core/owner.d.cts +0 -124
  103. package/dist/types-cjs/core/scheduler.d.cts +0 -236
  104. package/dist/types-cjs/core/types.d.cts +0 -204
  105. package/dist/types-cjs/core/verdict.d.cts +0 -2
  106. package/dist/types-cjs/index.d.cts +0 -10
  107. package/dist/types-cjs/map.d.cts +0 -69
  108. package/dist/types-cjs/package.json +0 -3
  109. package/dist/types-cjs/store/index.d.cts +0 -18
  110. package/dist/types-cjs/store/next/optimistic.d.cts +0 -25
  111. package/dist/types-cjs/store/next/projection.d.cts +0 -8
  112. package/dist/types-cjs/store/next/reconcile.d.cts +0 -10
  113. package/dist/types-cjs/store/next/store.d.cts +0 -121
  114. package/dist/types-cjs/store/next/target.d.cts +0 -166
  115. package/dist/types-cjs/store/store.d.cts +0 -143
  116. package/dist/types-cjs/store/storePath.d.cts +0 -58
  117. 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,32 +301,35 @@ 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
334
  try {
294
335
  t(r);
@@ -296,8 +337,8 @@ function handleAsync(e, n, t) {
296
337
  handleError(e);
297
338
  return;
298
339
  }
299
- if (i) clearStatus(e, true);
300
- } else if (e.o?.Pe !== undefined) {
340
+ if (s) clearStatus(e, true);
341
+ } else if (e.o?.be !== undefined) {
301
342
  // Optimistic node — resting OR covered by an active override — holds
302
343
  // through the shared pending-node path, exactly like a plain async memo,
303
344
  // so the commit clears STATUS_UNINITIALIZED (#2806) and elevation to
@@ -307,8 +348,8 @@ function handleAsync(e, n, t) {
307
348
  // (A17 — every reader sees the override); the revert reveals whatever
308
349
  // has committed by then, so corrections reveal atomically with their
309
350
  // transition rather than escaping it.
310
- if (e.Re === NOT_PENDING) queuePendingNode(e);
311
- e.Re = r;
351
+ if (e.Ge === NOT_PENDING) queuePendingNode(e);
352
+ e.Ge = r;
312
353
  // The hold is a companion-visible write like any other (A13/A19): the
313
354
  // clearStatus() above computed its verdict before the hold existed, so
314
355
  // isPending must re-derive (the value is not final until commit — V1)
@@ -316,35 +357,34 @@ function handleAsync(e, n, t) {
316
357
  // only notified when the hold is visible to them: under an active
317
358
  // override every reader sees the override (A17), so waking subs would
318
359
  // re-show an unchanged view — the revert is the notification point.
319
- 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);
320
371
  if (!hasActiveOverride(e)) {
321
372
  insertSubs(e);
322
- } else if (e.T & CONFIG_AUTHORITATIVE_OBSERVED) {
323
- // A17 silence is stated over ordinary readers; an authoritative-view
324
- // reader (until()'s predicate) observed this node PAST its override
325
- // and is waiting for exactly this staged truth. Without the wake the
326
- // hold deadlocks: the landing waits on the transaction, the
327
- // transaction on the action, the action on an until() that was never
328
- // re-notified (#3164). Same selective wake as the equal-landing
329
- // branch in recompute(). Optional call: the bit implies the
330
- // optimistic engine WAS consulted, but the hook only installs with
331
- // it — a bare-core build must not crash here.
332
- GlobalQueue.he?.(e);
333
- }
334
- e.Te = clock;
335
- } else if (s) {
373
+ } else GlobalQueue.ye(e, r);
374
+ e._e = clock;
375
+ } else if (u) {
336
376
  // Route through lane's effect queue for independent flushing
337
- const n = e.ge;
338
- const t = e.be;
339
- const o = e.pe;
377
+ const n = e.Ce;
378
+ const t = e.me;
379
+ const o = e.ve;
340
380
  try {
341
- if (!n && i || !o || !o(r, t)) {
342
- e.be = r;
343
- e.Te = clock;
381
+ if (!n && s || !o || !o(r, t)) {
382
+ e.me = r;
383
+ e._e = clock;
344
384
  // The latest() shadow write gives latest() effects independent lanes; the
345
385
  // _pendingSignal update is a no-op repeat of the clearStatus() call above
346
386
  // (computePendingState doesn't read _value).
347
- GlobalQueue.Ue?.(e, r);
387
+ GlobalQueue.pe?.(e, r);
348
388
  insertSubs(e, true);
349
389
  }
350
390
  } catch (n) {
@@ -370,9 +410,9 @@ function handleAsync(e, n, t) {
370
410
  // window when the hold commits, so no one-frame isPending pulse can leak
371
411
  // to live observers between the landing and its commit (#2990). The
372
412
  // quiet re-ask classification follows the same schedule (#3178).
373
- if (e.Re === NOT_PENDING) {
374
- e.Ne = false;
375
- if (l) e.o.De = false;
413
+ if (e.Ge === NOT_PENDING) {
414
+ e.Ae = false;
415
+ if (l) e.o.Ue = false;
376
416
  }
377
417
  settlePendingSource(e);
378
418
  schedule();
@@ -406,12 +446,12 @@ function handleAsync(e, n, t) {
406
446
  // meaningful only in the live posture.
407
447
  const consumeIterator = (t, r) => {
408
448
  const o = t[Symbol.asyncIterator]();
449
+ let i = false;
409
450
  let l = false;
410
- let s = false;
411
451
  let u = !r;
412
452
  const close = () => {
413
- if (s) return;
414
- s = true;
453
+ if (l) return;
454
+ l = true;
415
455
  try {
416
456
  const e = o.return?.();
417
457
  if (isThenable(e)) e.then(undefined, () => {});
@@ -422,7 +462,7 @@ function handleAsync(e, n, t) {
422
462
  // owner-death backstop, but its disposal list can be zombie-deferred
423
463
  // until the SUPERSEDING flight settles. The teardown slot fires at the
424
464
  // _inFlight release sites so supersede stops this stream immediately.
425
- ext(e).Ee = close;
465
+ ext(e).De = close;
426
466
  // Release check before each next pull: an unobserved lazy node must tear
427
467
  // down (its close above runs via disposal, closing the iterator) instead
428
468
  // of pumping the stream forever with zero subscribers (#2935).
@@ -451,15 +491,15 @@ function handleAsync(e, n, t) {
451
491
  if (c && u) {
452
492
  t = r;
453
493
  f = true;
454
- if (r.done) s = true;
455
- } else if (e.o?.Ie !== n) {
494
+ if (r.done) l = true;
495
+ } else if (e.o?.Pe !== n) {
456
496
  return;
457
497
  } else if (!r.done) {
458
- l = true;
498
+ i = true;
459
499
  asyncWrite(r.value, iterateOrRelease);
460
500
  } else {
461
- s = true;
462
- if (l) {
501
+ l = true;
502
+ if (i) {
463
503
  schedule();
464
504
  flush();
465
505
  } else {
@@ -472,8 +512,8 @@ function handleAsync(e, n, t) {
472
512
  if (c && u) {
473
513
  r = t;
474
514
  a = true;
475
- } else if (e.o?.Ie === n) {
476
- s = true;
515
+ } else if (e.o?.Pe === n) {
516
+ l = true;
477
517
  handleError(t);
478
518
  settleAutodispose();
479
519
  }
@@ -481,14 +521,14 @@ function handleAsync(e, n, t) {
481
521
  c = false;
482
522
  if (a) {
483
523
  // Match the promise branch, but only rethrow during the initial read.
484
- s = true;
524
+ l = true;
485
525
  handleError(r);
486
526
  if (u) throw r;
487
527
  return true;
488
528
  }
489
529
  if (f && !t.done) {
490
- i = t.value;
491
- l = true;
530
+ s = t.value;
531
+ i = true;
492
532
  return iterate();
493
533
  }
494
534
  return f && t.done;
@@ -496,7 +536,7 @@ function handleAsync(e, n, t) {
496
536
  const f = iterate();
497
537
  // Later iterate() calls run from asyncWrite, where rethrowing would be unhandled.
498
538
  u = false;
499
- return l || f;
539
+ return i || f;
500
540
  };
501
541
  // Landed-synchronously verdict for a LIVE iterator drain; null when no live
502
542
  // drain ran (plain promise flight, or a deferred flatten). Drives the
@@ -520,7 +560,7 @@ function handleAsync(e, n, t) {
520
560
  return true;
521
561
  };
522
562
  if (o) {
523
- let t = false, r = false, o, l = true;
563
+ let t = false, r = false, o, i = true;
524
564
  // Close registration for the flattening path. Consumption starts in a
525
565
  // microtask where the ambient owner is gone (or worse, someone else's),
526
566
  // so `cleanup()` can't be used — the close targets el's disposal list
@@ -532,18 +572,18 @@ function handleAsync(e, n, t) {
532
572
  // becomes disposal-bearing, which is exactly the class a directly
533
573
  // returned iterable already occupies.
534
574
  const registerDeferredClose = n => {
535
- 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 ];
536
576
  };
537
577
  n.then(r => {
538
- if (l) {
539
- i = r;
578
+ if (i) {
579
+ s = r;
540
580
  t = true;
541
- } 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 {
542
582
  asyncWrite(r);
543
583
  settleAutodispose();
544
584
  }
545
585
  }, e => {
546
- if (l) {
586
+ if (i) {
547
587
  o = e;
548
588
  r = true;
549
589
  } else {
@@ -551,7 +591,7 @@ function handleAsync(e, n, t) {
551
591
  settleAutodispose();
552
592
  }
553
593
  });
554
- l = false;
594
+ i = false;
555
595
  if (r) {
556
596
  // Settle through the same status path an async rejection uses, then
557
597
  // unwind the in-progress synchronous read so the errored node isn't
@@ -563,12 +603,12 @@ function handleAsync(e, n, t) {
563
603
  // is opened — first-flight work on a loadingValue node is loading-class
564
604
  // (invisible to boundaries and transitions); the flight itself is
565
605
  // already registered in _inFlight and lands through asyncWrite.
566
- if (e.Ne) return e.be;
606
+ if (e.Ae) return e.me;
567
607
  globalQueue.initTransition(resolveTransition(e));
568
608
  throw new NotReadyError(context);
569
- } else if (!flattenIfIterable(i)) {
609
+ } else if (!flattenIfIterable(s)) {
570
610
  // Synchronously-resolved promise: the first real answer landed.
571
- e.Ne = false;
611
+ e.Ae = false;
572
612
  }
573
613
  // A sync-resolved promise holding an AsyncIterable flattened LIVE (we
574
614
  // are still inside the synchronous read): full initial-drain semantics
@@ -578,30 +618,30 @@ function handleAsync(e, n, t) {
578
618
  if (l !== null) {
579
619
  if (!l) {
580
620
  // Loading window: serve commit #0 (see the promise branch above).
581
- if (e.Ne) return e.be;
621
+ if (e.Ae) return e.me;
582
622
  globalQueue.initTransition(resolveTransition(e));
583
623
  throw new NotReadyError(context);
584
624
  }
585
625
  // A sync first yield (or immediate empty completion) is the first real
586
626
  // answer; async yields clear inside asyncWrite.
587
- e.Ne = false;
627
+ e.Ae = false;
588
628
  }
589
- return i;
629
+ return s;
590
630
  }
591
631
 
592
632
  function clearStatus(e, n = false) {
593
633
  if (e.o?.le) clearPendingSources(e);
594
- 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;
595
635
  // The pending window is over; its quiet classification dies with it.
596
636
  // (Unconditional: _reask is baked into the node literals, so this is a
597
637
  // plain store to an existing slot — no shape change.)
598
- if (e.o !== null) e.o.De = false;
638
+ if (e.o !== null) e.o.Ue = false;
599
639
  e.S = n ? 0 : e.S & STATUS_UNINITIALIZED;
600
640
  if (e.o?._) setPendingError(e);
601
641
  // Update pending signal for isPending() reactivity (companions only exist
602
642
  // once the verdict layer created them, which installs the hooks).
603
- if (e.o?.ye || e.o?.Ce) GlobalQueue.de(e);
604
- 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);
605
645
  const t = statusNotifierOf(e);
606
646
  if (t) t.call(e);
607
647
  }
@@ -610,12 +650,16 @@ function notifyStatus(e, n, t, r, o) {
610
650
  // Wrap regular errors to track source node
611
651
  if (n === STATUS_ERROR && !(t instanceof StatusError) && !(t instanceof NotReadyError)) t = new StatusError(e, t);
612
652
  const i = n === STATUS_PENDING && t instanceof NotReadyError ? t.source : undefined;
613
- const l = i === e;
614
- const s = n === STATUS_PENDING && e.o?.Pe !== undefined && !l;
615
- 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);
616
656
  if (!r) {
617
657
  if (n === STATUS_PENDING && i) {
618
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;
619
663
  e.S = STATUS_PENDING | e.S & STATUS_UNINITIALIZED;
620
664
  // Preserve the current source on this propagation so render-effect notification
621
665
  // can register every distinct pending source with the transition.
@@ -625,14 +669,14 @@ function notifyStatus(e, n, t, r, o) {
625
669
  e.S = n | (n !== STATUS_ERROR ? e.S & STATUS_UNINITIALIZED : 0);
626
670
  ext(e)._ = t;
627
671
  }
628
- GlobalQueue.de?.(e);
629
- 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);
630
674
  }
631
675
  if (o && !r) {
632
676
  assignOrMergeLane(e, o);
633
677
  }
634
678
  const f = r || u;
635
- const a = r || s ? undefined : o;
679
+ const a = r || l ? undefined : o;
636
680
  const c = statusNotifierOf(e);
637
681
  if (c) {
638
682
  if (r && n === STATUS_PENDING) {
@@ -646,19 +690,19 @@ function notifyStatus(e, n, t, r, o) {
646
690
  return;
647
691
  }
648
692
  forEachDependent(e, (e, r) => {
649
- e.Te = clock;
693
+ e._e = clock;
650
694
  if (n === STATUS_PENDING && i && !e.o?.le?.has(i) || n !== STATUS_PENDING && (e.o?._ !== t || e.o?.le)) {
651
695
  // A pending-observer link is the subscription an `isPending` read created.
652
696
  // It exists so the observer re-runs when the source settles, but it must
653
697
  // not carry a real (non-NotReadyError) error — the synchronous `isPending`
654
698
  // read swallows those, and the async path must match. Re-run the observer
655
699
  // so `isPending` re-evaluates (to not-pending) instead of forwarding.
656
- if (r.ve && n !== STATUS_PENDING && !(t instanceof NotReadyError)) {
700
+ if (r.je && n !== STATUS_PENDING && !(t instanceof NotReadyError)) {
657
701
  enqueueSub(e);
658
702
  schedule();
659
703
  return;
660
704
  }
661
- if (!f && !e.Ae) queuePendingNode(e);
705
+ if (!f && !e.ge) queuePendingNode(e);
662
706
  notifyStatus(e, n, t, f, a);
663
707
  }
664
708
  });