@solidjs/signals 2.0.0-rc.4 → 2.0.0-rc.5

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 (53) hide show
  1. package/dist/dev.js +1169 -186
  2. package/dist/node.cjs +2041 -1167
  3. package/dist/prod/boundaries.js +4 -1
  4. package/dist/prod/core/async.js +124 -95
  5. package/dist/prod/core/constants.js +55 -1
  6. package/dist/prod/core/core.js +297 -222
  7. package/dist/prod/core/effect.js +28 -28
  8. package/dist/prod/core/error.js +13 -1
  9. package/dist/prod/core/external.js +2 -2
  10. package/dist/prod/core/graph.js +27 -27
  11. package/dist/prod/core/heap.js +30 -30
  12. package/dist/prod/core/lanes.js +32 -32
  13. package/dist/prod/core/optimistic.js +54 -54
  14. package/dist/prod/core/owner.js +34 -34
  15. package/dist/prod/core/scheduler.js +318 -137
  16. package/dist/prod/core/verdict.js +112 -59
  17. package/dist/prod/index.js +3 -3
  18. package/dist/prod/map.js +106 -106
  19. package/dist/prod/signals.js +253 -25
  20. package/dist/prod/store/next/optimistic.js +262 -123
  21. package/dist/prod/store/next/patch.js +6 -6
  22. package/dist/prod/store/next/projection.js +23 -19
  23. package/dist/prod/store/next/store.js +129 -35
  24. package/dist/prod/store/store.js +2 -2
  25. package/dist/types/core/async.d.ts +2 -0
  26. package/dist/types/core/attribution.d.ts +9 -4
  27. package/dist/types/core/constants.d.ts +54 -0
  28. package/dist/types/core/core.d.ts +19 -20
  29. package/dist/types/core/error.d.ts +9 -0
  30. package/dist/types/core/index.d.ts +2 -2
  31. package/dist/types/core/scheduler.d.ts +34 -0
  32. package/dist/types/core/types.d.ts +12 -0
  33. package/dist/types/index.d.ts +3 -3
  34. package/dist/types/signals.d.ts +108 -0
  35. package/dist/types/store/next/optimistic.d.ts +13 -10
  36. package/dist/types/store/next/projection.d.ts +1 -1
  37. package/dist/types/store/next/store.d.ts +22 -0
  38. package/dist/types/store/next/target.d.ts +15 -0
  39. package/dist/types-cjs/core/async.d.cts +2 -0
  40. package/dist/types-cjs/core/attribution.d.cts +9 -4
  41. package/dist/types-cjs/core/constants.d.cts +54 -0
  42. package/dist/types-cjs/core/core.d.cts +19 -20
  43. package/dist/types-cjs/core/error.d.cts +9 -0
  44. package/dist/types-cjs/core/index.d.cts +2 -2
  45. package/dist/types-cjs/core/scheduler.d.cts +34 -0
  46. package/dist/types-cjs/core/types.d.cts +12 -0
  47. package/dist/types-cjs/index.d.cts +3 -3
  48. package/dist/types-cjs/signals.d.cts +108 -0
  49. package/dist/types-cjs/store/next/optimistic.d.cts +13 -10
  50. package/dist/types-cjs/store/next/projection.d.cts +1 -1
  51. package/dist/types-cjs/store/next/store.d.cts +22 -0
  52. package/dist/types-cjs/store/next/target.d.cts +15 -0
  53. package/package.json +1 -1
@@ -1,6 +1,6 @@
1
- import { handleAsync, clearStatus, parkLoadingWindow, notifyStatus, settleErroredDependents } from "./async.js";
1
+ import { releaseFlightTeardown, handleAsync, clearStatus, parkLoadingWindow, notifyStatus, settleErroredDependents, settlePendingSource } from "./async.js";
2
2
 
3
- import { EFFECT_TRACKED, REACTIVE_OPTIMISTIC_DIRTY, CONFIG_OPTIMISTIC, NOT_PENDING, STATUS_UNINITIALIZED, STATUS_ERROR, REACTIVE_REASK, REACTIVE_RECOMPUTING_DEPS, CONFIG_SYNC, CONFIG_HAS_LANE, STATUS_PENDING, REACTIVE_MISSED_WAKE, REACTIVE_NONE, REACTIVE_SNAPSHOT_STALE, unwrapOverride, OVERRIDE_UNDEFINED, CONFIG_HAS_COMPANIONS, REACTIVE_LAZY, REACTIVE_DISPOSED, CONFIG_AUTO_DISPOSE, CONFIG_CHILDREN_FORBIDDEN, REACTIVE_CHECK, REACTIVE_DIRTY, REACTIVE_IN_HEAP, REACTIVE_IN_HEAP_HEIGHT, defaultContext, CONFIG_IN_SNAPSHOT_SCOPE, CONFIG_TRANSPARENT, CONFIG_OWNED_WRITE, CONFIG_NO_SNAPSHOT, $REFRESH, REACTIVE_MANUAL_WRITE, CONFIG_FW_CHILDREN, NO_SNAPSHOT, CONFIG_HAS_SNAPSHOT, STORE_SNAPSHOT_PROPS, EFFECT_USER } from "./constants.js";
3
+ import { EFFECT_TRACKED, REACTIVE_OPTIMISTIC_DIRTY, CONFIG_OPTIMISTIC, NOT_PENDING, STATUS_UNINITIALIZED, STATUS_ERROR, STATUS_PENDING, REACTIVE_REASK, REACTIVE_RECOMPUTING_DEPS, CONFIG_SYNC, CONFIG_HAS_LANE, REACTIVE_MISSED_WAKE, REACTIVE_NONE, REACTIVE_SNAPSHOT_STALE, unwrapOverride, CONFIG_DIRECT_COMMIT, OVERRIDE_UNDEFINED, CONFIG_AUTHORITATIVE_OBSERVED, CONFIG_HAS_COMPANIONS, REACTIVE_LAZY, REACTIVE_DISPOSED, CONFIG_AUTO_DISPOSE, CONFIG_CHILDREN_FORBIDDEN, CONFIG_FRESH_READ, CONFIG_AUTHORITATIVE_READ, CONFIG_HELD_TRUTH, REACTIVE_CHECK, REACTIVE_DIRTY, REACTIVE_IN_HEAP, REACTIVE_IN_HEAP_HEIGHT, defaultContext, CONFIG_IN_SNAPSHOT_SCOPE, CONFIG_TRANSPARENT, CONFIG_OWNED_WRITE, CONFIG_NO_SNAPSHOT, CONFIG_FW_CHILDREN, NO_SNAPSHOT, CONFIG_HAS_SNAPSHOT, REACTIVE_MANUAL_WRITE, STORE_SNAPSHOT_PROPS, EFFECT_USER } from "./constants.js";
4
4
 
5
5
  import { NotReadyError } from "./error.js";
6
6
 
@@ -8,15 +8,15 @@ import { trimStaleDeps, link, dormantNodes } from "./graph.js";
8
8
 
9
9
  import { deleteFromHeap, queueFor, insertIntoHeapHeight, enqueueSub, markNode, markHeap, insertIntoHeap } from "./heap.js";
10
10
 
11
- import { GlobalQueue, activeTransition, globalQueue, clock, insertSubs, queuePendingNode, runInTransition, schedule, notifyEpoch, dirtyQueue, bumpNotifyEpoch, projectionWriteActive, reaskArmed, armReaskClear } from "./scheduler.js";
11
+ import { GlobalQueue, bumpNotifyEpoch, activeTransition, globalQueue, clock, insertSubs, queuePendingNode, runInTransition, schedule, notifyEpoch, dirtyQueue, projectionWriteActive, reaskArmed, armReaskClear } from "./scheduler.js";
12
12
 
13
13
  import "./invariants.js";
14
14
 
15
15
  import { disposeChildren, markDisposal, inheritId } from "./owner.js";
16
16
 
17
- GlobalQueue.Ce = recompute;
17
+ GlobalQueue.Fe = recompute;
18
18
 
19
- GlobalQueue.Fe = disposeChildren;
19
+ GlobalQueue.He = disposeChildren;
20
20
 
21
21
  let tracking = false;
22
22
 
@@ -48,7 +48,7 @@ let snapshotSources = null;
48
48
 
49
49
  function ownerInSnapshotScope(e) {
50
50
  while (e) {
51
- if (e.He) return true;
51
+ if (e.Ve) return true;
52
52
  e = e.ke;
53
53
  }
54
54
  return false;
@@ -60,20 +60,20 @@ function setSnapshotCapture(e) {
60
60
  }
61
61
 
62
62
  function markSnapshotScope(e) {
63
- e.He = true;
63
+ e.Ve = true;
64
64
  }
65
65
 
66
66
  function releaseSnapshotScope(e) {
67
- e.He = false;
67
+ e.Ve = false;
68
68
  releaseSubtree(e);
69
69
  schedule();
70
70
  }
71
71
 
72
72
  function releaseSubtree(e) {
73
- let t = e.ve;
73
+ let t = e.xe;
74
74
  while (t) {
75
- if (t.He) {
76
- t = t.Ve;
75
+ if (t.Ve) {
76
+ t = t.Le;
77
77
  continue;
78
78
  }
79
79
  if (t.oe) {
@@ -82,19 +82,19 @@ function releaseSubtree(e) {
82
82
  if (e.ie & REACTIVE_SNAPSHOT_STALE) {
83
83
  e.ie &= ~REACTIVE_SNAPSHOT_STALE;
84
84
  e.ie |= REACTIVE_DIRTY;
85
- if (dirtyQueue.xe > e.Le) dirtyQueue.xe = e.Le;
85
+ if (dirtyQueue.Qe > e.Me) dirtyQueue.Qe = e.Me;
86
86
  insertIntoHeap(e, dirtyQueue);
87
87
  }
88
88
  }
89
89
  releaseSubtree(t);
90
- t = t.Ve;
90
+ t = t.Le;
91
91
  }
92
92
  }
93
93
 
94
94
  function clearSnapshots() {
95
95
  if (snapshotSources) {
96
96
  for (const e of snapshotSources) {
97
- delete e.o?.Qe;
97
+ delete e.o?.We;
98
98
  // StoreNode targets share one pre-initialized hidden class (see
99
99
  // createStoreProxy) — assign undefined instead of deleting, and only
100
100
  // when present so signal-node sources don't grow the field.
@@ -108,48 +108,63 @@ function clearSnapshots() {
108
108
  function recompute(e, t = false) {
109
109
  // §12d: any recompute can clean a marked subscriber — invalidate skips.
110
110
  bumpNotifyEpoch();
111
- const n = e.Re;
111
+ const n = e.he;
112
112
  if (!t) {
113
- if (e._e && (!n || activeTransition) && activeTransition !== e._e) globalQueue.initTransition(e._e);
113
+ if (e.Ae && (!n || activeTransition) && activeTransition !== e.Ae) globalQueue.initTransition(e.Ae);
114
114
  deleteFromHeap(e, queueFor(e));
115
- if (e.o !== null) e.o.Ee = null;
115
+ if (e.o !== null) {
116
+ e.o.Ie = null;
117
+ // Supersede is where an iterator flight dies (#3122): close it now.
118
+ // Its cleanup(close) registration may sit in a zombie-deferred
119
+ // disposal list that a held transition only drains when the
120
+ // SUPERSEDING flight settles — cancellation must not wait for the
121
+ // work that replaced it. Idempotent with the cleanup-channel close.
122
+ releaseFlightTeardown(e);
123
+ }
116
124
  // Tracked effects run after finalizePureQueue, so dispose immediately instead of deferring
117
- if (e._e || n === EFFECT_TRACKED) disposeChildren(e); else if (e.ve !== null || e.he !== null) {
125
+ if (e.Ae || n === EFFECT_TRACKED) disposeChildren(e); else if (e.xe !== null || e.pe !== null) {
118
126
  markDisposal(e);
119
127
  const t = ext(e);
120
- t.We = e.he;
121
- t.qe = e.ve;
122
- e.he = null;
123
- e.ve = null;
124
- e.Me = 0;
128
+ t.qe = e.pe;
129
+ t.Ye = e.xe;
130
+ e.pe = null;
131
+ e.xe = null;
132
+ e.Ze = 0;
125
133
  } else ;
126
134
  }
127
135
  let i = !!(e.ie & REACTIVE_OPTIMISTIC_DIRTY);
128
- const u = (e.T & CONFIG_OPTIMISTIC) !== 0 && e.o?.De !== NOT_PENDING && e.o?.De !== undefined;
136
+ const u = (e.T & CONFIG_OPTIMISTIC) !== 0 && e.o?.Oe !== NOT_PENDING && e.o?.Oe !== undefined;
129
137
  const l = !!(e.S & STATUS_UNINITIALIZED);
130
138
  // Outgoing error, captured before the compute clears status: if this run
131
139
  // recovers to an unchanged value, dependents still holding this object must
132
140
  // be swept (settleErroredDependents, #2949).
133
141
  const o = e.S & STATUS_ERROR ? e.o?._ : undefined;
142
+ // Pending SOURCE-hood, captured before the compute clears status: a node
143
+ // whose own flight parked dependents self-registers in _pendingSources
144
+ // (notifyStatus, isSource). If this recompute supersedes that flight and
145
+ // settles synchronously, those dependents settle HERE — asyncWrite's
146
+ // settlePendingSource walk never runs for a landing that was preempted
147
+ // (#3181).
148
+ const s = (e.S & STATUS_PENDING) !== 0 && e.o?.le?.has(e) === true;
134
149
  // Re-ask classification lives in the verdict module; capture the flag before
135
150
  // the recompute wipes _flags below.
136
- const s = (e.ie & REACTIVE_REASK) !== 0;
151
+ const a = (e.ie & REACTIVE_REASK) !== 0;
137
152
  // Captured before the compute clears it on a sync landing: if that landing
138
153
  // is transition-held below, the window must stay open until the hold
139
154
  // commits (commitPendingNode) — a closed window plus a held value reads as
140
155
  // a pending frame to live observers of the verdict (#2990).
141
- const a = e.Ie;
142
- const r = context;
156
+ const r = e.Ne;
157
+ const c = context;
143
158
  context = e;
144
- e.Ye = null;
145
- e.Ze++;
159
+ e.je = null;
160
+ e.Ke++;
146
161
  e.ie = REACTIVE_RECOMPUTING_DEPS;
147
162
  e.Te = clock;
148
- let c = e.Pe === NOT_PENDING ? e.be : e.Pe;
149
- let _ = e.Le;
150
- let f = false;
151
- let N = tracking;
152
- let E = currentOptimisticLane;
163
+ let _ = e.Pe === NOT_PENDING ? e.be : e.Pe;
164
+ let f = e.Me;
165
+ let I = false;
166
+ let E = tracking;
167
+ let N = currentOptimisticLane;
153
168
  tracking = true;
154
169
  // A computed's fn establishes its OWN dependencies, so it must never run
155
170
  // inside a latest() read window: read() short-circuits through the
@@ -157,54 +172,54 @@ function recompute(e, t = false) {
157
172
  // computed) inside latest(fn) came out permanently dependency-less (#2926).
158
173
  // latestRead() already suspends the flag for its pull-recomputes; this
159
174
  // covers creation-time computes and flushes that run inside the window.
160
- const I = latestReadActive;
175
+ const T = latestReadActive;
161
176
  latestReadActive = false;
162
177
  // Lane posture lives with the engine: OPTIMISTIC_DIRTY is only ever set by
163
178
  // engine-driven paths, and _optimisticNodes is only pushed by
164
179
  // _optimisticWrite, so the hook is installed whenever either gate holds.
165
180
  if (i) {
166
- const t = GlobalQueue.je(e, true);
181
+ const t = GlobalQueue.Be(e, true);
167
182
  if (t) currentOptimisticLane = t;
168
183
  // `false` = wake-only lane demotion: recompute plain so a mid-tick
169
184
  // latest()/isPending() pull stages instead of direct-committing (#3009).
170
185
  // The predicate lives with the engine (recomputeLane).
171
186
  else if (t === false) i = false;
172
- } else if (activeTransition && !t && activeTransition.Ke.length) {
187
+ } else if (activeTransition && !t && activeTransition.ze.length) {
173
188
  // Lane adoption: parent-deeper-than-owned-child can run before its OPT-dirty
174
189
  // child propagates. Walk deps once and inherit the OPT lane so this node
175
190
  // recomputes under the right posture and propagates correctly.
176
- const t = GlobalQueue.je(e, false);
191
+ const t = GlobalQueue.Be(e, false);
177
192
  if (t) {
178
193
  i = true;
179
194
  currentOptimisticLane = t;
180
195
  }
181
196
  }
182
- const d = n && n !== EFFECT_USER;
183
- const T = stale;
184
- if (d) stale = true;
197
+ const S = n && n !== EFFECT_USER;
198
+ const d = stale;
199
+ if (S) stale = true;
185
200
  try {
186
201
  if (!false && e.T & CONFIG_SYNC) {
187
- c = e.oe(c);
188
- if (e.o !== null) e.o.Ee = null;
189
- e.Ie = false;
202
+ _ = e.oe(_);
203
+ if (e.o !== null) e.o.Ie = null;
204
+ e.Ne = false;
190
205
  } else {
191
206
  // Snapshot `_inFlight` so we can detect whether `_fn` self-registered an async
192
207
  // subscription (e.g. `createProjection` calls `handleAsync` from inside its body
193
208
  // with a setter callback). In that case, the outer `handleAsync` call below would
194
209
  // clobber the fresh subscription, so we skip it and let the internally-registered
195
210
  // iteration drive updates.
196
- const t = e.o?.Ee;
197
- const n = e.oe(c);
211
+ const t = e.o?.Ie;
212
+ const n = e.oe(_);
198
213
  const i = typeof n === "object" && n !== null;
199
- const u = e.o?.Ee !== t;
200
- c = u || !i ? n : handleAsync(e, n);
214
+ const u = e.o?.Ie !== t;
215
+ _ = u || !i ? n : handleAsync(e, n);
201
216
  if (!u && !i) {
202
- if (e.o !== null) e.o.Ee = null;
217
+ if (e.o !== null) e.o.Ie = null;
203
218
  // A sync (non-object) return is the first real answer; async-shaped
204
219
  // results clear inside handleAsync at their own landing points, and a
205
220
  // self-registered flight (inFlightChanged — projections) clears when
206
221
  // its internal handleAsync lands.
207
- e.Ie = false;
222
+ e.Ne = false;
208
223
  }
209
224
  }
210
225
  // On a status-free node clearStatus is a guaranteed no-op: every field
@@ -214,10 +229,10 @@ function recompute(e, t = false) {
214
229
  if (e.S !== 0 || e.o !== null) clearStatus(e, t);
215
230
  // _optimisticLane is only ever assigned by engine paths (CONFIG_HAS_LANE
216
231
  // is their sticky presence mark).
217
- if (e.T & CONFIG_HAS_LANE && e.o?.Be) GlobalQueue.ze(e);
232
+ if (e.T & CONFIG_HAS_LANE && e.o?.Je) GlobalQueue.Xe(e);
218
233
  } catch (t) {
219
234
  const n = t instanceof NotReadyError;
220
- if (n && e.Ie) {
235
+ if (n && e.Ne) {
221
236
  // Loading window with an unready sync dependency: register for the
222
237
  // source's settle (the settlePendingSource walk runs off
223
238
  // _pendingSources + _blocked alone) but take NO read-visible pending
@@ -233,30 +248,30 @@ function recompute(e, t = false) {
233
248
  let i = false;
234
249
  if (n) {
235
250
  ext(e).fe = true;
236
- if (GlobalQueue.Je !== null) i = GlobalQueue.Je(e, s);
251
+ if (GlobalQueue.et !== null) i = GlobalQueue.et(e, a);
237
252
  }
238
- notifyStatus(e, n ? STATUS_PENDING : STATUS_ERROR, t, undefined, n ? e.o?.Be : undefined);
253
+ notifyStatus(e, n ? STATUS_PENDING : STATUS_ERROR, t, undefined, n ? e.o?.Je : undefined);
239
254
  if (i) GlobalQueue.k(e);
240
255
  }
241
256
  } finally {
242
- tracking = N;
243
- latestReadActive = I;
244
- if (d) stale = T;
257
+ tracking = E;
258
+ latestReadActive = T;
259
+ if (S) stale = d;
245
260
  // Consume the missed-wake latch (#3037, set by insertSubs): a dep write
246
261
  // landed beneath this pass on a link it had already validated. The wipe
247
262
  // below must not key off DIRTY/CHECK — the read-time pull protocol
248
263
  // (markNode(c) in read()) marks the running node as part of ordinary
249
264
  // bookkeeping, and those marks are correctly discarded here.
250
- f = (e.ie & REACTIVE_MISSED_WAKE) !== 0;
265
+ I = (e.ie & REACTIVE_MISSED_WAKE) !== 0;
251
266
  e.ie = REACTIVE_NONE | (t ? e.ie & REACTIVE_SNAPSHOT_STALE : 0);
252
- context = r;
267
+ context = c;
253
268
  }
254
269
  if (!e.o?._) {
255
270
  trimStaleDeps(e);
256
- const s = u ? unwrapOverride(e.o?.De) : e.Pe === NOT_PENDING ? e.be : e.Pe;
257
- let r = false;
271
+ const a = u ? unwrapOverride(e.o?.Oe) : e.Pe === NOT_PENDING ? e.be : e.Pe;
272
+ let c = false;
258
273
  try {
259
- r = !n && l || !e.Ue || !e.Ue(s, c);
274
+ c = !n && l || !e.ge || !e.ge(a, _);
260
275
  } catch (t) {
261
276
  // A throwing user comparator is an error of this node's computation.
262
277
  // Route it through the same status path as a compute-phase throw so
@@ -269,53 +284,63 @@ function recompute(e, t = false) {
269
284
  // its runner — happen here instead. `!create` matches the previous `initialized`
270
285
  // gate: the explicit recompute(node, true) inside effect() does not enqueue, so
271
286
  // effect() can call its runner synchronously for the first run.
272
- if (n && r) {
273
- e.Xe = !e.o?._;
287
+ if (n && c) {
288
+ e.tt = !e.o?._;
274
289
  // Reuse one bound runner per effect — runEffect no-ops on a stale
275
290
  // `_modified`, so re-enqueueing the same function is harmless.
276
- if (!t) e.C.enqueue(n, e.et ??= GlobalQueue.tt.bind(null, e));
291
+ if (!t) e.C.enqueue(n, e.nt ??= GlobalQueue.it.bind(null, e));
277
292
  }
278
- if (e.o?._) ; else if (r) {
279
- const l = u ? e.o?.De : undefined;
293
+ if (e.o?._) ; else if (c) {
294
+ const l = u ? e.o?.Oe : undefined;
280
295
  if (t ||
281
296
  // Plain sync flush (no transition on either side) commits effect
282
297
  // values directly — the pending round-trip (queuePendingNode +
283
298
  // commitPendingNodes) exists to sequence transition reveals, and
284
299
  // paying it per effect on the plain path is pure overhead.
285
- n && (activeTransition !== e._e || activeTransition === null) || i) {
286
- e.be = c;
300
+ // DIRECT_COMMIT effects (resolve/until) commit directly even under
301
+ // their own held transition: their applies deliver on a microtask,
302
+ // not the stashed queues, so a staged value would hand the immediate
303
+ // apply stale state — see CONFIG_DIRECT_COMMIT.
304
+ n && (activeTransition !== e.Ae || activeTransition === null || e.T & CONFIG_DIRECT_COMMIT) || i) {
305
+ e.be = _;
287
306
  // Lane-propagated correction: upstream data is fresh, correct the
288
307
  // override unconditionally. The direct _value commit is the lane's
289
308
  // own reveal schedule; drop any superseded older hold so its queued
290
309
  // commit can't clobber the fresh value.
291
310
  if (u && i) {
292
- ext(e).De = c === undefined ? OVERRIDE_UNDEFINED : c;
311
+ ext(e).Oe = _ === undefined ? OVERRIDE_UNDEFINED : _;
293
312
  e.Pe = NOT_PENDING;
294
313
  }
295
314
  } else {
296
- e.Pe = c;
315
+ e.Pe = _;
297
316
  // A window landing that gets held re-opens the window until the hold
298
317
  // commits — the verdict's held-value branch is window-gated (#2990).
299
- if (a) e.Ie = true;
318
+ if (r) e.Ne = true;
300
319
  // Transition-held sync recompute is a write path like setSignal/asyncWrite,
301
320
  // so sync derivations of held sources stay visible to isPending()/latest()
302
321
  // (#2831). Both companion writes are transition-scoped (optimistic) and
303
322
  // auto-revert/re-derive at commit. Skipped for plain flushes where the
304
323
  // pending value commits before effects run.
305
- if ((activeTransition || e._e) && GlobalQueue.Oe !== null) GlobalQueue.Oe(e, c);
324
+ if ((activeTransition || e.Ae) && GlobalQueue.Re !== null) GlobalQueue.Re(e, _);
306
325
  }
307
326
  // insertSubs only walks _subs (no scheduling of its own), so a
308
327
  // subscriber-less node has nothing to notify.
309
- if (e.u !== null && (!u || i || e.o?.De !== l)) insertSubs(e, i || u);
328
+ if (e.u !== null && (!u || i || e.o?.Oe !== l)) insertSubs(e, i || u);
310
329
  } else if (u) {
311
330
  // Unchanged value (equals the override) recomputed while the override
312
331
  // is active: _value may still be stale, so hold the authoritative value
313
332
  // for commit on its own transition's schedule — invisibly (A17/A18).
314
333
  if (e.Pe === NOT_PENDING) queuePendingNode(e);
315
- e.Pe = c;
316
- if (a) e.Ie = true;
334
+ e.Pe = _;
335
+ if (r) e.Ne = true;
317
336
  // see the held branch above (#2990)
318
- } else if (e.Le != _) {
337
+ // A authoritative-view reader (until()) observed this node past its
338
+ // override — and "authoritative arrival equal to the override" is
339
+ // exactly the acknowledgment it waits for. Wake those readers only;
340
+ // A17 silence holds for every ordinary subscriber. (Hook installed by
341
+ // until(), the only setter of the gating bit.)
342
+ if (e.T & CONFIG_AUTHORITATIVE_OBSERVED) GlobalQueue.Ue(e);
343
+ } else if (e.Me != f) {
319
344
  for (let t = e.u; t !== null; t = t.ae) {
320
345
  insertIntoHeapHeight(t.ce, queueFor(t.ce));
321
346
  }
@@ -325,23 +350,34 @@ function recompute(e, t = false) {
325
350
  // in an errored run and may sit on stale commits (#2949). Changed-value
326
351
  // recoveries ride insertSubs above; a comparator throw re-errored the node
327
352
  // (el._x?._error re-set), so this only runs on a genuinely clean recovery.
328
- if (o !== undefined && !r && !e.o?._) settleErroredDependents(e, o);
353
+ if (o !== undefined && !c && !e.o?._) settleErroredDependents(e, o);
354
+ // Pending twin of the sweep above (#3181): a flight superseded by this
355
+ // synchronous settle leaves every registered dependent still flagged
356
+ // STATUS_PENDING with a pending source that will never land — asyncWrite
357
+ // owns the walk only for flights that actually land. An unchanged value
358
+ // is the dangerous shape (a projection reconciling in place: a memo over
359
+ // it re-throws its cached NotReadyError forever, and every reader that
360
+ // suspended through that memo re-parks on the dead source), but the walk
361
+ // runs on the changed shape too, exactly as the landing path does —
362
+ // insertSubs notifies value SUBSCRIBERS, not pending REGISTRANTS, and
363
+ // the two sets only partially overlap.
364
+ if (s && !(e.S & STATUS_PENDING)) settlePendingSource(e);
329
365
  }
330
- currentOptimisticLane = E;
331
- const S = e.Pe !== NOT_PENDING || e.o !== null && (e.o.qe !== null || e.o.We !== null) || (e.S & (STATUS_PENDING | STATUS_UNINITIALIZED)) !== 0;
366
+ currentOptimisticLane = N;
367
+ const A = e.Pe !== NOT_PENDING || e.o !== null && (e.o.Ye !== null || e.o.qe !== null) || (e.S & (STATUS_PENDING | STATUS_UNINITIALIZED)) !== 0;
332
368
  // Override-covered holds (hasOverride) always queue: their commit belongs
333
369
  // to their own transition's schedule (A18 re-rule) and is unobservable
334
370
  // under the override (A17). Revert no longer commits anything, so an
335
371
  // unqueued covered hold would leak (INV-7) once the revert clears
336
372
  // _transition.
337
- S && (!t || e.S & STATUS_PENDING) && (!e._e || u) && queuePendingNode(e);
338
- e._e && n && activeTransition !== e._e && runInTransition(e._e, () => recompute(e));
373
+ A && (!t || e.S & STATUS_PENDING) && (!e.Ae || u) && queuePendingNode(e);
374
+ e.Ae && n && activeTransition !== e.Ae && runInTransition(e.Ae, () => recompute(e));
339
375
  // Missed-wake reschedule (see the finally above): values this pass read
340
376
  // before the nested commit are stale, so run again now that the heap will
341
377
  // accept the node. Equality gates stop same-value landings from cascading,
342
378
  // and a re-run only latches again if another nested commit changes a dep
343
379
  // beneath it — convergent unless deps genuinely keep changing.
344
- if (f) {
380
+ if (I) {
345
381
  enqueueSub(e);
346
382
  schedule();
347
383
  }
@@ -352,11 +388,13 @@ function updateIfNecessary(e) {
352
388
  // (_depsTail/_depGen) is live, and a nested recompute would corrupt it.
353
389
  // A mid-pass mark stays latched for recompute's own tail to reschedule
354
390
  // (#3037); readers meanwhile serve the values the pass has so far.
355
- if (e.ie & REACTIVE_RECOMPUTING_DEPS) return;
391
+ // Never recompute a DISPOSED node either: recompute rewrites _flags and
392
+ // would resurrect it (#2983) — readers serve its last value.
393
+ if (e.ie & (REACTIVE_RECOMPUTING_DEPS | REACTIVE_DISPOSED)) return;
356
394
  if (e.ie & REACTIVE_CHECK) {
357
- for (let t = e.nt; t; t = t.it) {
358
- const n = t.ut;
359
- const i = n.lt || n;
395
+ for (let t = e.ut; t; t = t.lt) {
396
+ const n = t.ot;
397
+ const i = n.st || n;
360
398
  if (i.oe) {
361
399
  updateIfNecessary(i);
362
400
  }
@@ -365,7 +403,7 @@ function updateIfNecessary(e) {
365
403
  }
366
404
  }
367
405
  }
368
- if (e.ie & (REACTIVE_DIRTY | REACTIVE_OPTIMISTIC_DIRTY) || e.o?._ && e.Te < clock && !e.o?.Ee) {
406
+ if (e.ie & (REACTIVE_DIRTY | REACTIVE_OPTIMISTIC_DIRTY) || e.o?._ && e.Te < clock && !e.o?.Ie) {
369
407
  recompute(e);
370
408
  }
371
409
  e.ie = e.ie & (REACTIVE_SNAPSHOT_STALE | REACTIVE_IN_HEAP | REACTIVE_IN_HEAP_HEIGHT);
@@ -380,40 +418,40 @@ function computed(e, t) {
380
418
  const u = {
381
419
  id: inheritId(t, n, context),
382
420
  T: (n ? CONFIG_TRANSPARENT : 0) | (t?.ownedWrite ? CONFIG_OWNED_WRITE : 0) | (!context || t?.lazy ? CONFIG_AUTO_DISPOSE : 0) | (t?.sync ? CONFIG_SYNC : 0) | (t?.H ? CONFIG_NO_SNAPSHOT : 0) | (snapshotCaptureActive && ownerInSnapshotScope(context) ? CONFIG_IN_SNAPSHOT_SCOPE : 0),
383
- Ue: t?.equals != null ? t.equals : isEqual,
384
- he: null,
421
+ ge: t?.equals ?? isEqual,
422
+ pe: null,
385
423
  C: context?.C ?? globalQueue,
386
424
  we: context?.we ?? defaultContext,
387
- Me: 0,
425
+ Ze: 0,
388
426
  oe: e,
389
427
  be: i ? t.loadingValue : undefined,
390
- Le: 0,
391
- ot: undefined,
392
- st: null,
393
- nt: null,
394
- Ye: null,
395
- Ze: 0,
428
+ Me: 0,
429
+ rt: undefined,
430
+ ct: null,
431
+ ut: null,
432
+ je: null,
433
+ Ke: 0,
396
434
  u: null,
397
- rt: null,
435
+ _t: null,
398
436
  ke: context,
399
- Ve: null,
400
- ct: null,
401
- ve: null,
437
+ Le: null,
438
+ ft: null,
439
+ xe: null,
402
440
  ie: t?.lazy ? REACTIVE_LAZY : REACTIVE_NONE,
403
441
  // A loadingValue node is born committed: commit #0 is already in _value.
404
442
  S: i ? 0 : STATUS_UNINITIALIZED,
405
443
  Te: clock,
406
444
  Pe: NOT_PENDING,
407
- _e: null,
408
- _t: -1,
409
- Ie: i,
445
+ Ae: null,
446
+ It: -1,
447
+ Ne: i,
410
448
  // Cold machinery (async/transition/optimistic/verdict slots) lives one
411
449
  // hop away in the lazily-allocated extension — the core literal MUST
412
450
  // stay under V8's in-object boundary (§12: past ~39 fields every
413
451
  // allocation spills to a backing store and creation cost ~4x's).
414
452
  o: null
415
453
  };
416
- if (t?.unobserved) ext(u).ft = t.unobserved;
454
+ if (t?.unobserved) ext(u).Et = t.unobserved;
417
455
  setupComputedNode(u, t);
418
456
  return u;
419
457
  }
@@ -423,25 +461,26 @@ function computed(e, t) {
423
461
  * this; hot paths read `el._x?._field` gated by the _config presence bits.
424
462
  * Never call ext() just to store a field's default. */ function ext(e) {
425
463
  return e.o ??= {
426
- De: undefined,
464
+ Oe: undefined,
427
465
  Nt: undefined,
428
- Be: undefined,
429
- Ge: undefined,
430
- ge: undefined,
431
- Et: undefined,
466
+ Je: undefined,
467
+ ye: undefined,
468
+ Ce: undefined,
469
+ Tt: undefined,
432
470
  t: 0,
471
+ Ie: null,
433
472
  Ee: null,
434
473
  _: undefined,
435
474
  fe: undefined,
436
475
  le: undefined,
437
476
  h: undefined,
438
- pe: false,
477
+ Ge: false,
439
478
  i: null,
440
- ft: undefined,
441
- Qe: undefined,
442
- We: null,
479
+ Et: undefined,
480
+ We: undefined,
443
481
  qe: null,
444
- It: undefined
482
+ Ye: null,
483
+ St: undefined
445
484
  };
446
485
  }
447
486
 
@@ -454,39 +493,39 @@ function computed(e, t) {
454
493
  const l = u?.transparent ?? false;
455
494
  const o = {
456
495
  id: inheritId(u, l, context),
457
- T: (l ? CONFIG_TRANSPARENT : 0) | (u?.ownedWrite ? CONFIG_OWNED_WRITE : 0) | (u?.sync ? CONFIG_SYNC : 0) | (snapshotCaptureActive && ownerInSnapshotScope(context) ? CONFIG_IN_SNAPSHOT_SCOPE : 0),
458
- Ue: false,
459
- he: null,
496
+ T: (l ? CONFIG_TRANSPARENT : 0) | (u?.ownedWrite ? CONFIG_OWNED_WRITE : 0) | (u?.sync ? CONFIG_SYNC : 0) | (u?.dt ?? 0) | (snapshotCaptureActive && ownerInSnapshotScope(context) ? CONFIG_IN_SNAPSHOT_SCOPE : 0),
497
+ ge: false,
498
+ pe: null,
460
499
  C: context?.C ?? globalQueue,
461
500
  we: context?.we ?? defaultContext,
462
- Me: 0,
501
+ Ze: 0,
463
502
  oe: e,
464
503
  be: undefined,
465
- Le: 0,
466
- ot: undefined,
467
- st: null,
468
- nt: null,
469
- Ye: null,
470
- Ze: 0,
504
+ Me: 0,
505
+ rt: undefined,
506
+ ct: null,
507
+ ut: null,
508
+ je: null,
509
+ Ke: 0,
471
510
  u: null,
472
- rt: null,
511
+ _t: null,
473
512
  ke: context,
474
- Ve: null,
475
- ct: null,
476
- ve: null,
513
+ Le: null,
514
+ ft: null,
515
+ xe: null,
477
516
  ie: REACTIVE_LAZY,
478
517
  S: STATUS_UNINITIALIZED,
479
518
  Te: clock,
480
519
  Pe: NOT_PENDING,
481
- _e: null,
482
- _t: -1,
483
- Ie: false,
484
- Xe: false,
485
- dt: undefined,
486
- Tt: t,
487
- St: n,
520
+ Ae: null,
521
+ It: -1,
522
+ Ne: false,
523
+ tt: false,
488
524
  At: undefined,
489
- Re: i,
525
+ Ot: t,
526
+ Ct: n,
527
+ Rt: undefined,
528
+ he: i,
490
529
  o: null
491
530
  };
492
531
  // Effects dispatch status through the SHARED notifier (statusNotifierOf,
@@ -494,7 +533,7 @@ function computed(e, t) {
494
533
  // allocation on EVERY effect at creation (an alloc + 19 field stores,
495
534
  // +23% effect creation, caught by the creation benches). Only genuinely
496
535
  // per-node channels (boundaries) live on _x.
497
- if (u?.unobserved) ext(o).ft = u.unobserved;
536
+ if (u?.unobserved) ext(o).Et = u.unobserved;
498
537
  setupComputedNode(o, lazyOptions);
499
538
  return o;
500
539
  }
@@ -515,10 +554,9 @@ function setEffectStatusNotify(e) {
515
554
  * the field) fall back to the shared notifier. Presence doubles as the
516
555
  * "display consumer" membership test in the status walks, exactly as the
517
556
  * per-node field did when every effect carried one. */ function statusNotifierOf(e) {
518
- const t = e.o;
519
- const n = t !== null && t !== undefined ? t.h : undefined;
520
- if (n !== undefined) return n;
521
- return e.Re ? effectStatusNotify ?? undefined : undefined;
557
+ const t = e.o?.h;
558
+ if (t !== undefined) return t;
559
+ return e.he ? effectStatusNotify ?? undefined : undefined;
522
560
  }
523
561
 
524
562
  const lazyOptions = {
@@ -526,24 +564,24 @@ const lazyOptions = {
526
564
  };
527
565
 
528
566
  function setupComputedNode(e, t) {
529
- e.st = e;
530
- const n = context?.Ct ? context.Ot : context;
567
+ e.ct = e;
568
+ const n = context?.Gt ? context.Dt : context;
531
569
  if (context) {
532
- const t = context.ve;
570
+ const t = context.xe;
533
571
  if (t === null) {
534
- context.ve = e;
572
+ context.xe = e;
535
573
  } else {
536
- e.Ve = t;
537
- t.ct = e;
538
- context.ve = e;
574
+ e.Le = t;
575
+ t.ft = e;
576
+ context.xe = e;
539
577
  }
540
578
  }
541
- if (n) e.Le = n.Le + 1;
542
- if (GlobalQueue.Rt !== null) GlobalQueue.Rt(e);
579
+ if (n) e.Me = n.Me + 1;
580
+ if (GlobalQueue.Pt !== null) GlobalQueue.Pt(e);
543
581
  !t?.lazy && recompute(e, true);
544
582
  if (snapshotCaptureActive && !t?.lazy) {
545
583
  if (!(e.S & STATUS_PENDING) && !(e.T & CONFIG_NO_SNAPSHOT)) {
546
- ext(e).Qe = e.be === undefined ? NO_SNAPSHOT : e.be;
584
+ ext(e).We = e.be === undefined ? NO_SNAPSHOT : e.be;
547
585
  e.T |= CONFIG_HAS_SNAPSHOT;
548
586
  snapshotSources.add(e);
549
587
  }
@@ -552,13 +590,13 @@ function setupComputedNode(e, t) {
552
590
 
553
591
  function signal(e, t, n = null) {
554
592
  const i = {
555
- Ue: t?.equals != null ? t.equals : isEqual,
593
+ ge: t?.equals ?? isEqual,
556
594
  T: (t?.ownedWrite ? CONFIG_OWNED_WRITE : 0) | (t?.H ? CONFIG_NO_SNAPSHOT : 0),
557
595
  be: e,
558
596
  u: null,
559
- rt: null,
597
+ _t: null,
560
598
  Te: clock,
561
- lt: n,
599
+ st: n,
562
600
  Se: n?.o?.i || null,
563
601
  Pe: NOT_PENDING,
564
602
  // Signal-literal diet (§12e): NO _time/_fn/_statusFlags slots. Stores
@@ -566,17 +604,17 @@ function signal(e, t, n = null) {
566
604
  // bytes. _time is write-only on signals (every read site is computed-
567
605
  // typed error-retry gating); _fn/_statusFlags read falsy-identically as
568
606
  // missing properties on the shared paths (undefined masks to 0).
569
- _e: null,
570
- _t: -1,
607
+ Ae: null,
608
+ It: -1,
571
609
  o: null
572
610
  };
573
- if (t?.unobserved) ext(i).ft = t.unobserved;
611
+ if (t?.unobserved) ext(i).Et = t.unobserved;
574
612
  if (n) {
575
613
  ext(n).i = i;
576
614
  n.T |= CONFIG_FW_CHILDREN;
577
615
  }
578
616
  if (snapshotCaptureActive && !(i.T & CONFIG_NO_SNAPSHOT) && !((n?.S ?? 0) & STATUS_PENDING)) {
579
- ext(i).Qe = e === undefined ? NO_SNAPSHOT : e;
617
+ ext(i).We = e === undefined ? NO_SNAPSHOT : e;
580
618
  i.T |= CONFIG_HAS_SNAPSHOT;
581
619
  snapshotSources.add(i);
582
620
  }
@@ -585,14 +623,14 @@ function signal(e, t, n = null) {
585
623
 
586
624
  function optimisticSignal(e, t) {
587
625
  const n = signal(e, t);
588
- ext(n).De = NOT_PENDING;
626
+ ext(n).Oe = NOT_PENDING;
589
627
  n.T |= CONFIG_OPTIMISTIC;
590
628
  return n;
591
629
  }
592
630
 
593
631
  function optimisticComputed(e, t) {
594
632
  const n = computed(e, t);
595
- ext(n).De = NOT_PENDING;
633
+ ext(n).Oe = NOT_PENDING;
596
634
  n.T |= CONFIG_OPTIMISTIC;
597
635
  return n;
598
636
  }
@@ -623,11 +661,11 @@ function isEqual(e, t) {
623
661
  * );
624
662
  * ```
625
663
  */ function untrack(e, t) {
626
- if (GlobalQueue.Gt === null && !tracking && true) return e();
664
+ if (GlobalQueue.ht === null && !tracking && true) return e();
627
665
  const n = tracking;
628
666
  tracking = false;
629
667
  try {
630
- if (GlobalQueue.Gt !== null) return GlobalQueue.Gt(e);
668
+ if (GlobalQueue.ht !== null) return GlobalQueue.ht(e);
631
669
  return e();
632
670
  } finally {
633
671
  tracking = n;
@@ -668,10 +706,38 @@ function isEqual(e, t) {
668
706
  * fast path, `_fn` nodes need prepareComputed, and firewall / override /
669
707
  * snapshot / transition / lane / dev-strictRead state all take the full
670
708
  * resolution. Anything slow returns READ_SLOW; the caller then calls read().
671
- */ function readNodeFast(e) {
672
- if (latestReadActive || pendingCheckActive || e.oe || e.lt || e.o?.De !== undefined || e.o?.Qe !== undefined || activeTransition !== null || currentOptimisticLane !== null || snapshotCaptureActive || false) return READ_SLOW;
709
+ */
710
+ /**
711
+ * Wake only authoritative-view readers (until() predicates) subscribed to `el`.
712
+ * The A17-silent ack paths — an authoritative arrival equal to the active
713
+ * override — use this so the predicate re-evaluates without re-firing
714
+ * ordinary subscribers whose visible (override) value did not change.
715
+ * Pay-for-use: reached through GlobalQueue._notifyAuthoritativeObservers,
716
+ * installed at first until() call — apps that never use until() shake it.
717
+ */ function notifyAuthoritativeObservers(e) {
718
+ for (let t = e.u; t !== null; t = t.ae) {
719
+ const e = t.ce;
720
+ if (!(e.T & CONFIG_AUTHORITATIVE_READ)) continue;
721
+ // Missed-wake latch (#3037), same contract as insertSubs: the reader may
722
+ // itself have pulled this recompute (updateIfNecessary from its own
723
+ // read), and the heap refuses RECOMPUTING nodes — latch so recompute's
724
+ // tail reschedules it with the staged value visible.
725
+ if (e.ie & REACTIVE_RECOMPUTING_DEPS && t.Ft === e.Ke && t !== e.je) e.ie |= REACTIVE_MISSED_WAKE;
726
+ enqueueSub(e);
727
+ }
728
+ schedule();
729
+ }
730
+
731
+ /** Installs the until() machinery hook. Idempotent; called by until() before
732
+ * any authoritative-view read happens (same late-binding contract as the
733
+ * optimistic engine). */ function installAuthoritativeRead() {
734
+ if (GlobalQueue.Ue === null) GlobalQueue.Ue = notifyAuthoritativeObservers;
735
+ }
736
+
737
+ function readNodeFast(e) {
738
+ if (latestReadActive || pendingCheckActive || e.oe || e.st || e.o?.Oe !== undefined || e.o?.We !== undefined || activeTransition !== null || currentOptimisticLane !== null || snapshotCaptureActive || false) return READ_SLOW;
673
739
  let t = context;
674
- if (t?.Ct) t = t.Ot;
740
+ if (t?.Gt) t = t.Dt;
675
741
  if (t && tracking) link(e, t);
676
742
  // Children-forbidden readers (createTrackedEffect / onSettled callbacks) get
677
743
  // committed visibility: like the effect half of createEffect and event
@@ -685,21 +751,21 @@ function read(e) {
685
751
  // Checked before isPending so that isPending(() => latest(x)) checks
686
752
  // the _pendingSignal of _latestValueComputed (async in flight) rather
687
753
  // than the original node (which stays "pending" while held in a transition).
688
- if (latestReadActive) return GlobalQueue.Pt(e);
754
+ if (latestReadActive) return GlobalQueue.gt(e);
689
755
  let t = context;
690
- if (t?.Ct) t = t.Ot;
756
+ if (t?.Gt) t = t.Dt;
691
757
  const n = e;
692
- const i = e.lt;
758
+ const i = e.st;
693
759
  const u = i || e;
694
760
  // Handle isPending() mode: collect pending state while preserving normal read semantics.
695
761
  // Probe mode is suspended while preparing the node so nested reads during a
696
762
  // recompute don't collect into the probe.
697
763
  if (pendingCheckActive) {
698
- GlobalQueue.Dt(e, t, u, i);
764
+ GlobalQueue.Ht(e, t, u, i);
699
765
  } else if (typeof n.oe === "function") {
700
766
  prepareComputed(e, false);
701
767
  }
702
- if (!n.oe && u === e && e.o?.De === undefined && e.o?.Qe === undefined && activeTransition === null && currentOptimisticLane === null && !snapshotCaptureActive && true) {
768
+ if (!n.oe && u === e && e.o?.Oe === undefined && e.o?.We === undefined && activeTransition === null && currentOptimisticLane === null && !snapshotCaptureActive && true) {
703
769
  if (t && tracking) link(e, t);
704
770
  // Committed visibility for children-forbidden readers — see readNodeFast.
705
771
  return !t || e.Pe === NOT_PENDING || t.T & CONFIG_CHILDREN_FORBIDDEN ? e.be : e.Pe;
@@ -708,24 +774,31 @@ function read(e) {
708
774
  link(e, t, pendingCheckActive);
709
775
  if (u.oe) {
710
776
  const n = queueFor(e);
711
- if (u.Le >= n.xe) {
777
+ if (u.Me >= n.Qe) {
712
778
  markNode(t);
713
779
  markHeap(n);
714
780
  updateIfNecessary(u);
715
781
  }
716
- const i = u.Le;
782
+ // Fresh-pull readers (awaitable refresh's waiter) recompute a dirty
783
+ // source inline even when the height gate defers to the flush: the
784
+ // waiter must park on the re-ask's window (or serve its sync answer),
785
+ // never read the PRE-re-ask value as settled. Self-guarded: a clean
786
+ // node no-ops and updateIfNecessary refuses disposed nodes (#2983) —
787
+ // a dead target serves its last value, which is already quiescent.
788
+ else if (t.T & CONFIG_FRESH_READ) updateIfNecessary(u);
789
+ const i = u.Me;
717
790
  // parent check is shallow, might need to be recursive
718
- if (i >= t.Le && e.ke !== t) {
719
- t.Le = i + 1;
791
+ if (i >= t.Me && e.ke !== t) {
792
+ t.Me = i + 1;
720
793
  }
721
794
  }
722
795
  }
723
796
  if (u.S & STATUS_PENDING) {
724
- if (t && !(stale && u._e && activeTransition !== u._e)) {
797
+ if (t && !(stale && u.Ae && activeTransition !== u.Ae)) {
725
798
  // Per-lane suspension lives with the engine (a non-null lane implies it
726
799
  // is installed): under a lane, only same-lane pending async without an
727
800
  // active override throws.
728
- if (currentOptimisticLane === null || GlobalQueue.ht(u)) {
801
+ if (currentOptimisticLane === null || GlobalQueue.Vt(u)) {
729
802
  if (!tracking && e !== t) link(e, t);
730
803
  throw u.o?._;
731
804
  }
@@ -761,7 +834,7 @@ function read(e) {
761
834
  } else throw u.o?._;
762
835
  }
763
836
  if (snapshotCaptureActive && t && t.T & CONFIG_IN_SNAPSHOT_SCOPE) {
764
- const n = e.o?.Qe;
837
+ const n = e.o?.We;
765
838
  if (n !== undefined) {
766
839
  const i = n === NO_SNAPSHOT ? undefined : n;
767
840
  const u = e.Pe !== NOT_PENDING ? e.Pe : e.be;
@@ -769,9 +842,19 @@ function read(e) {
769
842
  return i;
770
843
  }
771
844
  }
772
- if (e.o?.De !== undefined && e.o?.De !== NOT_PENDING) {
773
- // A17: the override IS the value for every reader.
774
- return unwrapOverride(e.o?.De);
845
+ if (e.o?.Oe !== undefined && e.o?.Oe !== NOT_PENDING) {
846
+ // A17: the override IS the value for every reader — except an authoritative
847
+ // reader (until()'s predicate carries CONFIG_AUTHORITATIVE_READ): it must
848
+ // observe independently-arriving truth, and serving it the caller's own
849
+ // tentative write would trivially satisfy the predicate. The bit is checked
850
+ // on the reading computation itself, so a shared computed the predicate
851
+ // pulls recomputes as ITSELF (context = the memo, no bit) under the normal
852
+ // view. Fall through to normal value selection (staged `_pendingValue` is
853
+ // authoritative — optimism never lives there); the sticky mark makes the
854
+ // A17-silent "landing equals override" paths notify this node's subs so
855
+ // the reader re-runs when truth arrives.
856
+ if (!(t && t.T & CONFIG_AUTHORITATIVE_READ)) return unwrapOverride(e.o?.Oe);
857
+ e.T |= CONFIG_AUTHORITATIVE_OBSERVED;
775
858
  }
776
859
  // Entanglement gate: a reader recomputing under an optimistic lane that reads
777
860
  // a pending mid-transition write sees the committed value. Projection-store
@@ -780,7 +863,7 @@ function read(e) {
780
863
  // _pendingValue for correct fetching. The sub is recorded for replay at commit
781
864
  // so it re-runs with the new committed view. (Gate details live with the
782
865
  // engine — a non-null lane implies it is installed.)
783
- if (currentOptimisticLane !== null && activeTransition !== null && t !== null && GlobalQueue.Ft(e, u, t)) {
866
+ if (currentOptimisticLane !== null && activeTransition !== null && t !== null && GlobalQueue.vt(e, u, t)) {
784
867
  return e.be;
785
868
  }
786
869
  // In optimistic lane context, return _value for optimistic/lane-assigned signals
@@ -789,10 +872,19 @@ function read(e) {
789
872
  // (The lane-context clause lives with the engine.) Children-forbidden readers
790
873
  // (createTrackedEffect / onSettled callbacks) get committed visibility — see
791
874
  // readNodeFast (#3006).
792
- const l = !t || currentOptimisticLane !== null && GlobalQueue.gt(e, u, t) || e.Pe === NOT_PENDING || t.T & CONFIG_CHILDREN_FORBIDDEN || stale && e._e && activeTransition !== e._e ? e.be : e.Pe;
875
+ const l = !t || currentOptimisticLane !== null && GlobalQueue.bt(e, u, t) || e.Pe === NOT_PENDING || t.T & CONFIG_CHILDREN_FORBIDDEN || stale && e.Ae && activeTransition !== e.Ae ||
876
+ // A17 for HELD truth (#3164, see CONFIG_HELD_TRUTH): staged confirming
877
+ // truth — fold-staged onto an armed family, or entangle-stolen by an
878
+ // awaited until() — is masked from ordinary readers until its
879
+ // transaction's reveal; the retaining transaction's own speculative
880
+ // recomputes included (partial override coverage would otherwise
881
+ // compose override + staged truth into a state no timeline contains).
882
+ // Authoritative readers (until()'s predicate) and latest() see the
883
+ // staged truth — the tunnel that keeps the hold deadlock-free.
884
+ e.T & CONFIG_HELD_TRUTH && !latestReadActive && !(t.T & CONFIG_AUTHORITATIVE_READ) ? e.be : e.Pe;
793
885
  // Record that this isPending() probe observed the fresh pending value, so
794
886
  // the probe doesn't pair "pending" with the new value (#2831).
795
- if (pendingCheckActive) GlobalQueue.Ht(e, l);
887
+ if (pendingCheckActive) GlobalQueue.kt(e, l);
796
888
  if (!t && u === e && typeof n.oe === "function" && e.T & CONFIG_AUTO_DISPOSE && !(u.S & STATUS_PENDING) && !e.u) {
797
889
  // Deferred, not inline (#3078): an inline unobserved() here made untracked
798
890
  // reads destructive — dispose on this read, full revival recompute on the
@@ -807,18 +899,18 @@ function read(e) {
807
899
  }
808
900
 
809
901
  function setSignal(e, t) {
810
- if (e._e && activeTransition !== e._e) globalQueue.initTransition(e._e);
902
+ if (e.Ae && activeTransition !== e.Ae) globalQueue.initTransition(e.Ae);
811
903
  // The optimistic write path lives with the engine: only optimisticSignal /
812
904
  // optimisticComputed callers and optimistic store nodes carry an
813
905
  // _overrideValue slot (flagged by CONFIG_OPTIMISTIC — a masked read of the
814
906
  // always-present config instead of a missing-property probe), and every
815
907
  // module that installs one installs the engine first.
816
- if (e.T & CONFIG_OPTIMISTIC && !projectionWriteActive) return GlobalQueue.kt(e, t);
908
+ if (e.T & CONFIG_OPTIMISTIC && !projectionWriteActive) return GlobalQueue.xt(e, t);
817
909
  const n = e.Pe === NOT_PENDING ? e.be : e.Pe;
818
910
  if (typeof t === "function") t = t(n);
819
911
  // Uninitialized check first: the first commit has no previous value, so the
820
912
  // user comparator must not run against `undefined` (matches recompute).
821
- const i = !!(e.S & STATUS_UNINITIALIZED) || !e.Ue || !e.Ue(n, t);
913
+ const i = !!(e.S & STATUS_UNINITIALIZED) || !e.ge || !e.ge(n, t);
822
914
  if (!i) return t;
823
915
  const u = e.Pe !== NOT_PENDING;
824
916
  if (!u) queuePendingNode(e);
@@ -828,7 +920,7 @@ function setSignal(e, t) {
828
920
  // only ever created, never removed, and creating one installs the hook and
829
921
  // sets CONFIG_HAS_COMPANIONS — one masked read replaces two optional-field
830
922
  // probes on every write).
831
- e.T & CONFIG_HAS_COMPANIONS && GlobalQueue.Oe !== null && GlobalQueue.Oe(e, t);
923
+ e.T & CONFIG_HAS_COMPANIONS && GlobalQueue.Re !== null && GlobalQueue.Re(e, t);
832
924
  // _time is a computed-only slot (§12e): writing it on a signal would fork
833
925
  // the lean shape. Every read site is computed-typed.
834
926
  if (e.oe !== undefined) e.Te = clock;
@@ -837,7 +929,7 @@ function setSignal(e, t) {
837
929
  // (epoch) — re-stages the value and stops. The walk is idempotent (subs
838
930
  // marked, heap entries flag-guarded, effects queued once); lane and reask
839
931
  // contexts change what a walk MEANS, so they always walk.
840
- if (u && e._t === notifyEpoch && currentOptimisticLane === null && !reaskArmed) return t;
932
+ if (u && e.It === notifyEpoch && currentOptimisticLane === null && !reaskArmed) return t;
841
933
  insertSubs(e);
842
934
  schedule();
843
935
  return t;
@@ -856,7 +948,7 @@ function setSignal(e, t) {
856
948
  schedule();
857
949
  }
858
950
  e.ie = e.ie & -4 | REACTIVE_MANUAL_WRITE;
859
- e.vt = clock;
951
+ e.Ut = clock;
860
952
  }
861
953
 
862
954
  /**
@@ -912,39 +1004,22 @@ function staleValues(e, t = true) {
912
1004
  }
913
1005
 
914
1006
  /**
915
- * Invalidates one reactive source, forcing it to re-execute even if its inputs
916
- * haven't changed.
917
- *
918
- * Pass either a Solid-created accessor or a projected store created from
919
- * `createStore(fn, ...)` / `createProjection(...)`. `refresh()` is a
920
- * write-like invalidation operation: it does not read the target's value, and
921
- * refreshing a plain signal accessor is a no-op.
922
- *
923
- * Use it to invalidate cached async values (e.g. force a re-fetch) without
924
- * tearing the consumer down.
925
- *
926
- * @example
927
- * ```ts
928
- * const user = createMemo(async () => fetch(`/users/${id()}`).then(r => r.json()));
929
- *
930
- * // Re-fetch on demand
931
- * <button onClick={() => refresh(user)}>Reload</button>
932
- * ```
933
- */ function refresh(e) {
934
- const t = e?.[$REFRESH];
935
- if (!t) {
936
- return;
937
- }
938
- if (typeof t.oe === "function" && !(t.ie & REACTIVE_DISPOSED)) {
939
- if (t.ie & REACTIVE_MANUAL_WRITE) {
1007
+ * Core marking half of `refresh()` (the public wrapper lives in signals.ts
1008
+ * it validates the target, marks through here, then builds the quiescence
1009
+ * promise on the resolve()/until() effect machinery). Flags the node's next
1010
+ * recompute as a quiet re-ask and schedules it; no-ops for non-derived or
1011
+ * disposed targets and for same-tick manual writes.
1012
+ */ function markRefresh(e) {
1013
+ if (typeof e.oe === "function" && !(e.ie & REACTIVE_DISPOSED)) {
1014
+ if (e.ie & REACTIVE_MANUAL_WRITE) {
940
1015
  // A manual write in the CURRENT tick wins over the refresh (#2692).
941
1016
  // A mask stamped in an earlier tick only survives because a
942
1017
  // transaction (action) is holding the pending drain open; there the
943
1018
  // refresh is a later, explicit re-ask and lifts the mask — otherwise
944
1019
  // any setStore early in an action silently swallows every refresh()
945
1020
  // for the rest of the transaction (#3026).
946
- if (t.vt === clock) return;
947
- t.ie &= ~REACTIVE_MANUAL_WRITE;
1021
+ if (e.Ut === clock) return;
1022
+ e.ie &= ~REACTIVE_MANUAL_WRITE;
948
1023
  // No REASK below: the batch carries a manual value change, so the
949
1024
  // recompute is not a quiet re-ask of an unchanged question.
950
1025
  }
@@ -955,14 +1030,14 @@ function staleValues(e, t = true) {
955
1030
  // REACTIVE_IN_HEAP counts as dirt: insertSubs schedules subscribers by
956
1031
  // heap insertion alone (no DIRTY/CHECK flag), so a same-batch value
957
1032
  // change followed by refresh() must not be laundered into a quiet re-ask.
958
- else if (!(t.ie & (REACTIVE_DIRTY | REACTIVE_CHECK | REACTIVE_IN_HEAP))) {
959
- t.ie |= REACTIVE_REASK;
1033
+ else if (!(e.ie & (REACTIVE_DIRTY | REACTIVE_CHECK | REACTIVE_IN_HEAP))) {
1034
+ e.ie |= REACTIVE_REASK;
960
1035
  armReaskClear();
961
1036
  }
962
- t.ie = t.ie & ~REACTIVE_CHECK | REACTIVE_DIRTY;
963
- insertIntoHeap(t, queueFor(t));
1037
+ e.ie = e.ie & ~REACTIVE_CHECK | REACTIVE_DIRTY;
1038
+ insertIntoHeap(e, queueFor(e));
964
1039
  schedule();
965
1040
  }
966
1041
  }
967
1042
 
968
- export { READ_SLOW, clearSnapshots, computed, context, createEffectNode, currentOptimisticLane, effectStatusNotify, ext, isEqual, latestReadActive, markSnapshotScope, optimisticComputed, optimisticSignal, pendingCheckActive, prepareComputed, read, readNodeFast, recompute, refresh, releaseSnapshotScope, runWithOwner, setContextInternal, setEffectStatusNotify, setLatestReadActive, setMemo, setPendingCheckActive, setSignal, setSnapshotCapture, signal, snapshotCaptureActive, snapshotSources, stale, staleValues, statusNotifierOf, suppressComputedRecompute, tracking, untrack };
1043
+ export { READ_SLOW, clearSnapshots, computed, context, createEffectNode, currentOptimisticLane, effectStatusNotify, ext, installAuthoritativeRead, isEqual, latestReadActive, markRefresh, markSnapshotScope, notifyAuthoritativeObservers, optimisticComputed, optimisticSignal, pendingCheckActive, prepareComputed, read, readNodeFast, recompute, releaseSnapshotScope, runWithOwner, setContextInternal, setEffectStatusNotify, setLatestReadActive, setMemo, setPendingCheckActive, setSignal, setSnapshotCapture, signal, snapshotCaptureActive, snapshotSources, stale, staleValues, statusNotifierOf, suppressComputedRecompute, tracking, untrack };