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

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (66) hide show
  1. package/dist/dev-shared.js +248 -189
  2. package/dist/dev.attribution.js +124 -41
  3. package/dist/dev.js +553 -322
  4. package/dist/observe/affects.js +34 -31
  5. package/dist/observe/boundaries.js +166 -132
  6. package/dist/observe/core/async.js +90 -83
  7. package/dist/observe/core/attribution-queries.js +1 -1
  8. package/dist/observe/core/attribution.js +281 -197
  9. package/dist/observe/core/constants.js +7 -2
  10. package/dist/observe/core/context.js +3 -3
  11. package/dist/observe/core/core.js +277 -245
  12. package/dist/observe/core/dev.js +3 -3
  13. package/dist/observe/core/effect.js +21 -21
  14. package/dist/observe/core/external.js +2 -2
  15. package/dist/observe/core/graph.js +25 -25
  16. package/dist/observe/core/heap.js +9 -9
  17. package/dist/observe/core/lanes.js +206 -160
  18. package/dist/observe/core/owner.js +27 -27
  19. package/dist/observe/core/scheduler.js +92 -86
  20. package/dist/observe/core/verdict.js +66 -54
  21. package/dist/observe/map.js +35 -35
  22. package/dist/observe/reveal.js +24 -24
  23. package/dist/observe/signals.js +38 -28
  24. package/dist/observe/store/affects.js +75 -68
  25. package/dist/observe/store/hooks.js +13 -0
  26. package/dist/observe/store/index.js +0 -2
  27. package/dist/observe/store/optimistic.js +67 -34
  28. package/dist/observe/store/projection.js +37 -31
  29. package/dist/observe/store/reconcile.js +32 -30
  30. package/dist/observe/store/store.js +128 -85
  31. package/dist/prod/affects.js +34 -31
  32. package/dist/prod/boundaries.js +143 -109
  33. package/dist/prod/core/async.js +64 -67
  34. package/dist/prod/core/constants.js +7 -2
  35. package/dist/prod/core/context.js +3 -3
  36. package/dist/prod/core/core.js +302 -270
  37. package/dist/prod/core/effect.js +38 -38
  38. package/dist/prod/core/external.js +4 -4
  39. package/dist/prod/core/graph.js +27 -27
  40. package/dist/prod/core/heap.js +30 -30
  41. package/dist/prod/core/lanes.js +257 -211
  42. package/dist/prod/core/owner.js +39 -39
  43. package/dist/prod/core/scheduler.js +125 -119
  44. package/dist/prod/core/verdict.js +70 -58
  45. package/dist/prod/map.js +73 -73
  46. package/dist/prod/reveal.js +38 -38
  47. package/dist/prod/signals.js +30 -20
  48. package/dist/prod/store/affects.js +75 -68
  49. package/dist/prod/store/hooks.js +13 -0
  50. package/dist/prod/store/index.js +0 -2
  51. package/dist/prod/store/optimistic.js +114 -81
  52. package/dist/prod/store/projection.js +30 -24
  53. package/dist/prod/store/reconcile.js +32 -30
  54. package/dist/prod/store/store.js +136 -93
  55. package/dist/types/boundaries.d.ts +4 -0
  56. package/dist/types/core/attribution.d.ts +6 -2
  57. package/dist/types/core/constants.d.ts +5 -0
  58. package/dist/types/core/core.d.ts +33 -3
  59. package/dist/types/core/lanes.d.ts +10 -0
  60. package/dist/types/core/scheduler.d.ts +12 -6
  61. package/dist/types/core/types.d.ts +0 -6
  62. package/dist/types/store/affects.d.ts +11 -0
  63. package/dist/types/store/hooks.d.ts +48 -0
  64. package/dist/types/store/index.d.ts +0 -1
  65. package/dist/types/store/store.d.ts +3 -38
  66. package/package.json +1 -1
@@ -149,7 +149,7 @@ const CONFIG_SYNC = 1 << 6;
149
149
  // CONFIG_HELD_CHILDREN, CONFIG_INPUTS_PUBLISHED and CONFIG_ADOPTED_UNFLUSHED
150
150
  // (transaction holds, zombies, until()'s authoritative view) went with the
151
151
  // transactions.
152
- // L2 (step 2): three bits, all maintained by the node's commit.
152
+ // L2 (step 2): four bits, all maintained by the node's commit.
153
153
  /** The node has a pass awaiting commit: its live children (and `_disposal`)
154
154
  * are that pass's and were never shown — a re-pass tears them down on the
155
155
  * spot, while the frame parked on `_x._pendingFirstChild` keeps waiting for
@@ -162,6 +162,11 @@ const CONFIG_STAGED = 1 << 7;
162
162
  * parking flush they see the committed value and hold nothing, and are
163
163
  * re-derived at the landing. Set at the park seam on every staged node. */
164
164
  const CONFIG_HELD = 1 << 8;
165
+ /** A member of the uncommitted frame a held pass built (ruling A): set at
166
+ * the park seam on every computed under a staged node (`holdFrame`). Never
167
+ * shown, it has no screen: its reads are its transaction's, whichever flush
168
+ * runs it (`bornInto`, #4010). Cleared by its commit. */
169
+ const CONFIG_HELD_FRAME = 1 << 20;
165
170
  /** A15's reveal corollary (#3305): a commit published this flight's inputs
166
171
  * beneath it — the node was pending, nothing staged, when it committed — so
167
172
  * its committed value is torn against the visible frame. A render effect
@@ -1262,7 +1267,7 @@ function blockedBy(nodes, owner, own = false) {
1262
1267
  // shows nothing — a mount the frame has not revealed — and holds
1263
1268
  // nothing.
1264
1269
  if (
1265
- (r._type === EFFECT_RENDER ||
1270
+ ((r._type === EFFECT_RENDER && r._statusFlags & STATUS_PENDING) ||
1266
1271
  r._flags & REACTIVE_FRAME_READ ||
1267
1272
  (r._config & CONFIG_REDERIVE && r._statusFlags === STATUS_PENDING)) &&
1268
1273
  (s._gen === r._depGen || r._x?._error != null) &&
@@ -1355,7 +1360,10 @@ function list(n, t) {
1355
1360
  function holdFrame(owner, t) {
1356
1361
  for (let c = owner._firstChild; c !== null; c = c._nextSibling) {
1357
1362
  if (c._x?._transaction?._lane) continue;
1358
- if (c._fn !== undefined && !(c._config & CONFIG_HELD)) holdNode(c, t);
1363
+ if (c._fn !== undefined) {
1364
+ if (!(c._config & CONFIG_HELD)) holdNode(c, t);
1365
+ c._config |= CONFIG_HELD_FRAME;
1366
+ }
1359
1367
  holdFrame(c, t);
1360
1368
  }
1361
1369
  }
@@ -1684,7 +1692,8 @@ class GlobalQueue {
1684
1692
  // parked (something async below) — the window is the frame's, the marks
1685
1693
  // are its transaction's; else they release at the seam, verdict-only,
1686
1694
  // nothing to show (affects.ts).
1687
- GlobalQueue._releaseAmbientMarks?.(t !== null && transactions.indexOf(t) !== -1 ? t : null);
1695
+ const live = t && liveTx(t);
1696
+ GlobalQueue._releaseAmbientMarks?.(live);
1688
1697
  // The effect phase: lane work first (displayed ahead of the frame), then
1689
1698
  // this flush's runs, then the runs the landings held from earlier
1690
1699
  // flushes — as one pass would have queued them (#3540: a shell
@@ -1692,18 +1701,17 @@ class GlobalQueue {
1692
1701
  // write; #3528: a display-ahead swap before the count it is shown
1693
1702
  // beside). A parked frame's runs wait with its transaction instead: the
1694
1703
  // effect phase applies a committed frame.
1695
- const u = t && liveTx(t);
1696
- const parked = u !== null;
1704
+ const parked = live !== null;
1697
1705
  // Attribution hook: this flush found its transaction incomplete — its
1698
1706
  // writes stay staged, its runs are stashed below. Before the effect
1699
1707
  // phase (the lanes' display-ahead runs are the visible acknowledgers);
1700
1708
  // `holdEnd` fires after it (`flush`).
1701
1709
  if (parked && attrHooks !== null) {
1702
- attrHooks.holdStart(u);
1710
+ attrHooks.holdStart(live);
1703
1711
  holding = true;
1704
1712
  }
1705
1713
  for (let i = 0; i < 2; i++) {
1706
- if (parked) append(u._queues[i], own[i]);
1714
+ if (parked) append(live._queues[i], own[i]);
1707
1715
  // The plain flush — no reveal, no landing, not parked — has nothing to
1708
1716
  // order around its own runs: they are the queue as they stand (the
1709
1717
  // same array, not a copy; `run` takes it whole). Every other seam
@@ -1792,8 +1800,11 @@ class GlobalQueue {
1792
1800
  function reruns(u) {
1793
1801
  for (let i = 0; i < u._reruns.length; i++) {
1794
1802
  const r = u._reruns[i];
1795
- if (r._flags & REACTIVE_DISPOSED) continue;
1796
- if (r._flags & REACTIVE_FRAME_READ) {
1803
+ // An errored reader's display is its error (D-39): the landing gives it
1804
+ // nothing to re-derive, and a re-run would be a read that retries the
1805
+ // errored source (#3945).
1806
+ if (r._flags & REACTIVE_DISPOSED || r._statusFlags & STATUS_ERROR) continue;
1807
+ if (r._flags & REACTIVE_FRAME_READ || r._config & CONFIG_VERDICT) {
1797
1808
  r._flags &= ~REACTIVE_FRAME_READ;
1798
1809
  r._modified = false;
1799
1810
  // Its frame is replaced by the re-derivation: a run one of its
@@ -1940,7 +1951,7 @@ function commitPendingNode(n) {
1940
1951
  // commit beneath a flight publishes its inputs (A15 reveal corollary,
1941
1952
  // #3305): a reveal of it must observe, not show the pre-flight value.
1942
1953
  const inFlight = n._pendingValue === NOT_PENDING && (c._statusFlags & STATUS_PENDING) !== 0;
1943
- n._config = inFlight ? (n._config & ~CONFIG_HELD) | CONFIG_INPUTS_PUBLISHED : n._config & -1409;
1954
+ n._config = inFlight ? (n._config & -1048833) | CONFIG_INPUTS_PUBLISHED : n._config & -1049985;
1944
1955
  if (n._pendingValue !== NOT_PENDING) {
1945
1956
  n._value = n._pendingValue;
1946
1957
  n._pendingValue = NOT_PENDING;
@@ -3094,14 +3105,21 @@ function handleAsync(
3094
3105
  return;
3095
3106
  }
3096
3107
  if (wasUninitialized) landStatus(el, true);
3108
+ // Attribution hook: this path landed through the setter (derived
3109
+ // stores, projections), which does not go through setSignal, so the
3110
+ // plain branch's asyncEnd never ran and the flight stayed open — the
3111
+ // next flight counted a committed answer as abandoned (#3947).
3112
+ // direct=true: asyncEnd finalizes either way and stamps an async write
3113
+ // only if the commit moved `_value`/`_time` or parked `_pendingValue`.
3114
+ // A store setter does not move this node's `_value`, so no stamp is
3115
+ // recorded and waterfall chaining through derived stores stays
3116
+ // unmeasured. Outside the try (#2883 — see attribution-hooks.ts).
3117
+ if (attrHooks !== null) attrHooks.asyncEnd(el, undefined, value, true);
3097
3118
  } else {
3098
3119
  // CARVE 2: the override-covered landing (hold + A18 supersession) and the
3099
3120
  // lane-routed landing (derived override, lane effect queue) went with
3100
- // the optimistic engine; every landing is the plain setSignal. A first
3101
- // answer born into a hold still live lands into it (A29, #3800).
3102
- let t = el._x._bornIn;
3103
- el._x._bornIn = null;
3104
- if (wasUninitialized && t && (t = liveTx(t))) holdNode(el, t);
3121
+ // the optimistic engine; every landing is the plain setSignal. A node
3122
+ // already held stages its answer into that hold (`setSignal`).
3105
3123
  try {
3106
3124
  setSignal(el, () => value);
3107
3125
  } catch (e) {
@@ -3691,9 +3709,16 @@ function recompute(el, create = false) {
3691
3709
  // joins all the same. Not a render effect (rule 3): it is the frame.
3692
3710
  // Re-run outside its transaction's flush it publishes mainline — the
3693
3711
  // value it staged there is superseded (`frameRead` remembers it for the
3694
- // landing). A frame born into the transaction (uninitialized: never run,
3695
- // A29) keeps staging: live writes keep it current, it effects at the
3696
- // swap (ruling A).
3712
+ // landing). A frame born into the transaction (`bornInto`: never run,
3713
+ // A29, or mounted by a pass of it still awaiting its commit, #4010) keeps
3714
+ // staging: live writes keep it current, it effects at the swap (ruling
3715
+ // A).
3716
+ // A pending flight is the transition's own work (#3884). A probe on an
3717
+ // earlier pass left CONFIG_VERDICT, and a frame read here would serve the
3718
+ // committed screen, settle the flight and drop the hold — a superseding
3719
+ // write's verdict would depend on that probe. Cleared for this pass; a
3720
+ // probe in the body re-stamps it after the plain reads.
3721
+ if (el._statusFlags & STATUS_PENDING) el._config &= ~CONFIG_VERDICT;
3697
3722
  if (el._config & CONFIG_HELD) {
3698
3723
  const tx = txOf(el);
3699
3724
  // Held by a blocked lane: the frame joins nothing — a lane never holds
@@ -3701,7 +3726,10 @@ function recompute(el, create = false) {
3701
3726
  // world (`read`), and has left it otherwise.
3702
3727
  if (tx._lane);
3703
3728
  else if (isEffect !== EFFECT_RENDER && !(el._config & CONFIG_VERDICT)) joinPassTx(tx);
3704
- else if (tx !== flushTransaction && !(el._statusFlags & STATUS_UNINITIALIZED)) {
3729
+ else if (
3730
+ tx !== flushTransaction &&
3731
+ !(el._statusFlags & STATUS_UNINITIALIZED || el._config & CONFIG_HELD_FRAME)
3732
+ ) {
3705
3733
  // Published mainline, it is not held: the frame this pass builds is
3706
3734
  // replaced on the spot (#3404) — this flush's commit retires the
3707
3735
  // committed frame the held pass had parked (`commitPendingNode`),
@@ -3751,12 +3779,12 @@ function recompute(el, create = false) {
3751
3779
  // — here, the finally below, updateIfNecessary — carries it (#3543).
3752
3780
  el._flags = REACTIVE_RECOMPUTING_DEPS | (el._flags & REACTIVE_ZOMBIE);
3753
3781
  el._time = clock;
3754
- // The pass's previous value: its staging, else the lane's value for a
3755
- // lane's node (lanes.ts), else the committed one.
3782
+ // The pass's previous value: its staging, else a lane node's lane value
3783
+ // when it has one (lanes.ts), else the committed one.
3756
3784
  let value =
3757
3785
  el._pendingValue !== NOT_PENDING
3758
3786
  ? el._pendingValue
3759
- : el._config & CONFIG_OVERRIDE
3787
+ : el._config & CONFIG_OVERRIDE && el._x._lane !== NOT_PENDING
3760
3788
  ? el._x._lane
3761
3789
  : el._value;
3762
3790
  let oldHeight = el._height;
@@ -4035,6 +4063,10 @@ function recompute(el, create = false) {
4035
4063
  // derives from the future (`read`), an untracked one throws
4036
4064
  // (A19 exc. 1).
4037
4065
  el._statusFlags |= STATUS_UNINITIALIZED;
4066
+ // A boundary that has not shown content catches it: its fallback
4067
+ // waits for the commit (#3540). (The pass's own status clear above
4068
+ // dropped what the read recorded.)
4069
+ GlobalQueue._fresh?.(el);
4038
4070
  }
4039
4071
  }
4040
4072
  // insertSubs only walks _subs (no scheduling of its own), so a
@@ -4068,16 +4100,18 @@ function recompute(el, create = false) {
4068
4100
  }
4069
4101
  // A first pass that went pending where the born-held arm would have held
4070
4102
  // its value (it read a held node, or a verdict lane's mount read a staging,
4071
- // #3851) is born into that transaction without holding it: the hold never
4072
- // waits for a first load (the direction rule), but the answer lands into it
4073
- // while it is live (A29, #3800).
4103
+ // #3851) is held like it: its answer is the hold's, and the hold waits
4104
+ // for it (A29, #3800) — unless a boundary that has not shown content
4105
+ // catches it: then it is the boundary's, and the hold does not wait (#3540).
4074
4106
  if (
4075
4107
  create &&
4076
4108
  lane === null &&
4077
4109
  (joined || (prevLane && el._flags & REACTIVE_STAGED_READ)) &&
4078
4110
  el._statusFlags & STATUS_PENDING
4079
- )
4080
- ext(el)._bornIn = flushTransaction ?? passTx;
4111
+ ) {
4112
+ const t = flushTransaction ?? passTx;
4113
+ if (t !== null && !t._lane && !GlobalQueue._fresh?.(el)) holdNode(el, t);
4114
+ }
4081
4115
  // Dependencies are the committed frame's until it is replaced (A30, #3410):
4082
4116
  // a pass that staged its value leaves the previous pass's tail linked for
4083
4117
  // `commitPendingNode` to trim, so a write to a dependency the committed
@@ -4261,7 +4295,6 @@ function ext(el) {
4261
4295
  _pendingFirstChild: null,
4262
4296
  _pendingDisposal: null,
4263
4297
  _transaction: null,
4264
- _bornIn: null,
4265
4298
  _reask: false,
4266
4299
  _flushed: NOT_PENDING,
4267
4300
  _flushedAt: -1,
@@ -4283,8 +4316,16 @@ function ext(el) {
4283
4316
  * boundary's, not the tick's (A29's boundary exemption, #3540). */
4284
4317
  function joinPass(c, el) {
4285
4318
  c._flags |= REACTIVE_JOINED;
4319
+ // A new memo's first pass is the hold's work (born held) but not the
4320
+ // tick's: a render effect that reads it decides — under a boundary that
4321
+ // catches it, the boundary's; otherwise the tick joins the hold (#3540:
4322
+ // the reader's position, not where the memo was created). Its catch, if
4323
+ // any, is at its staging.
4286
4324
  if (el._statusFlags & STATUS_UNINITIALIZED || c._type !== EFFECT_RENDER)
4287
- joinPassTx(txOf(el), GlobalQueue._fresh?.(c));
4325
+ joinPassTx(
4326
+ txOf(el),
4327
+ (!c._type && c._statusFlags & STATUS_UNINITIALIZED) || GlobalQueue._fresh?.(c)
4328
+ );
4288
4329
  }
4289
4330
  /** A15's stale reader (shared-hole and reveal corollaries): a render effect
4290
4331
  * reading a node held by a transaction that is not the flush's. It is served
@@ -4292,11 +4333,11 @@ function joinPass(c, el) {
4292
4333
  * re-derived after that transaction's landing (`_reruns`,
4293
4334
  * REACTIVE_FRAME_READ) so the frame catches up with it once it is the
4294
4335
  * committed world. Not a frame born into that transaction (held and never
4295
- * committed — created by one of its held passes, A29): that one reads its
4296
- * transaction's values and keeps staging. Not of a flight whose inputs are
4297
- * already visible (CONFIG_INPUTS_PUBLISHED, #3305): its committed value
4298
- * would tear against them, so the reveal observes the flight instead. Once
4299
- * per pass.
4336
+ * committed — created by one of its held passes, A29; `bornInto`): that
4337
+ * one reads its transaction's values and keeps staging. Not of a flight
4338
+ * whose inputs are already visible (CONFIG_INPUTS_PUBLISHED, #3305): its
4339
+ * committed value would tear against them, so the reveal observes the
4340
+ * flight instead. Once per pass.
4300
4341
  *
4301
4342
  * Lane work is a stale reader too (maintainer, 2026-10-01: a lane sees the
4302
4343
  * screen plus its own guesses). A held write is held because showing it
@@ -4333,14 +4374,22 @@ function frameRead(c, el) {
4333
4374
  // Lane work and verdict readers are never the transaction's pass, whichever
4334
4375
  // flush runs it: a node T holds re-enters T when it re-runs (`recompute`'s
4335
4376
  // head), and the pass may then read a guess and become the lane's.
4336
- if (
4337
- (t === flushTransaction && passLane === null && !verdict) ||
4338
- (c._statusFlags & STATUS_UNINITIALIZED && c._config & CONFIG_HELD && txOf(c) === t)
4339
- )
4340
- return false;
4377
+ if ((t === flushTransaction && passLane === null && !verdict) || bornInto(c, t)) return false;
4341
4378
  staleReader(c, t);
4342
4379
  return true;
4343
4380
  }
4381
+ /** A node born into transaction `t`: held by it and never committed (A29,
4382
+ * ruling A) — uninitialized (born held), or a member of the frame one of its
4383
+ * held passes built (CONFIG_HELD_FRAME). Its branch exists only in `t`: it
4384
+ * has no screen to read, so it reads `t`'s values, whichever flush runs it,
4385
+ * and keeps staging (#4010). */
4386
+ function bornInto(c, t) {
4387
+ return (
4388
+ (c._statusFlags & STATUS_UNINITIALIZED || c._config & CONFIG_HELD_FRAME) &&
4389
+ c._config & CONFIG_HELD &&
4390
+ txOf(c) === t
4391
+ );
4392
+ }
4344
4393
  /** The computed whose pass a creation under `owner` belongs to (a root's is
4345
4394
  * its nearest computed ancestor's), or null outside every pass. */
4346
4395
  function creatorPass(owner) {
@@ -4877,7 +4926,8 @@ function read(el) {
4877
4926
  // effect keeps its DOM by throwing, a memo has no DOM and is handed the
4878
4927
  // value. `[isPending(x), x()]` reads `[true, stale]` in either order (A10)
4879
4928
  // — unless the flight committed beneath inputs already on screen
4880
- // (`observeFlight`).
4929
+ // (`observeFlight`), or the reader was born into the flight's transaction
4930
+ // (#4010): it has no screen, and waits on the flight with its frame.
4881
4931
  if (
4882
4932
  owner._statusFlags & STATUS_PENDING &&
4883
4933
  !committed &&
@@ -5017,11 +5067,14 @@ function serve(el, c) {
5017
5067
  * write never shows through the lane. A verdict lane's work likewise: the
5018
5068
  * lane holds verdicts, not the frame's other stagings (#3851) — except a
5019
5069
  * verdict reader, which answered for itself (the lane seam, lanes.ts). Not
5020
- * a read of a node born staged: it has no committed value to re-derive on,
5021
- * and a re-run would read the same staging and re-queue every round. */
5070
+ * a read of a node born staged at all: it has no committed value to
5071
+ * re-derive on, and a re-run would read the same staging and re-queue every
5072
+ * round (#3969: nor does it make a later lane read a re-derive, `enterLane`). */
5022
5073
  function stagedRead(c, el) {
5023
- c._flags |= REACTIVE_STAGED_READ;
5024
- if (passLane !== null && !(el?._statusFlags & STATUS_UNINITIALIZED)) stagedReaders.push(c);
5074
+ if (!(el?._statusFlags & STATUS_UNINITIALIZED)) {
5075
+ c._flags |= REACTIVE_STAGED_READ;
5076
+ if (passLane !== null) stagedReaders.push(c);
5077
+ }
5025
5078
  }
5026
5079
  /** A10 for a staged node: a verdict reader (the pass entered a window) that
5027
5080
  * also reads a frame's proposal plainly sees the screen — `[latest(q), q()]`
@@ -5030,9 +5083,10 @@ function stagedRead(c, el) {
5030
5083
  * #3322 — one run, on the committed world), or with the hold. Before any
5031
5084
  * transaction the answer is the seam's and the reader watches it
5032
5085
  * (verdict.ts). A node born into the future has no screen: its staging is
5033
- * its only value (A29). */
5086
+ * its only value (A29). Nor has a reader born into the flush's transaction
5087
+ * (`bornInto`, #4010): its branch exists only there. */
5034
5088
  function stagedScreen(c) {
5035
- if (flushTransaction === null) return false;
5089
+ if (flushTransaction === null || bornInto(c, flushTransaction)) return false;
5036
5090
  staleReader(c, flushTransaction);
5037
5091
  return true;
5038
5092
  }
@@ -5050,9 +5104,10 @@ function notePromotedWrite(el) {
5050
5104
  el._config |= CONFIG_PROMOTED;
5051
5105
  promotedWrites.push(el);
5052
5106
  }
5053
- /** Cold half of setSignal's snapshot arm (see there): first write during
5054
- * capture to a plain signal without a live snapshot records the pre-write
5055
- * value. Only plain user signals qualify. Computeds reach setSignal from an
5107
+ /** Cold half of setSignal's snapshot arm (see there), shared with a store
5108
+ * container's structural notify: first write during capture to a plain
5109
+ * signal without a live snapshot records the pre-write value. Only plain
5110
+ * user signals qualify. Computeds reach setSignal from an
5056
5111
  * async landing (asyncWrite), and a value arriving from async during the pass
5057
5112
  * REVEALS — the creation-time arm skips pending computeds for the same
5058
5113
  * reason. Firewall leaves belong to a projection whose compute is the tree's
@@ -5268,7 +5323,7 @@ function markRefresh(node) {
5268
5323
  }
5269
5324
 
5270
5325
  export {
5271
- CONFIG_INPUTS_PUBLISHED as $,
5326
+ REACTIVE_CHECK as $,
5272
5327
  list as A,
5273
5328
  clock as B,
5274
5329
  CONFIG_GUESS as C,
@@ -5285,154 +5340,158 @@ export {
5285
5340
  NOT_PENDING as N,
5286
5341
  setPassLane as O,
5287
5342
  REACTIVE_JOINED as P,
5288
- stagedRead as Q,
5343
+ REACTIVE_STAGED_READ as Q,
5289
5344
  REACTIVE_DISPOSED as R,
5290
5345
  STATUS_PENDING as S,
5291
- attrHooks as T,
5292
- holdNode as U,
5293
- joinFuture as V,
5294
- CONFIG_SLOT_NODE as W,
5295
- commitPendingNode as X,
5296
- REACTIVE_IN_HEAP as Y,
5297
- REACTIVE_DIRTY as Z,
5298
- REACTIVE_CHECK as _,
5346
+ stagedRead as T,
5347
+ CONFIG_SLOT_NODE as U,
5348
+ attrHooks as V,
5349
+ holdNode as W,
5350
+ joinFuture as X,
5351
+ commitPendingNode as Y,
5352
+ REACTIVE_IN_HEAP as Z,
5353
+ REACTIVE_DIRTY as _,
5299
5354
  CONFIG_OVERRIDE as a,
5300
- CONFIG_REDERIVE as a$,
5301
- setVerdict as a0,
5302
- context as a1,
5303
- REACTIVE_PROBED as a2,
5304
- globalQueue as a3,
5305
- staleReader as a4,
5306
- REACTIVE_STAGED_READ as a5,
5307
- verdict as a6,
5308
- link as a7,
5309
- pullComputed as a8,
5310
- strictRead as a9,
5311
- EFFECT_USER as aA,
5312
- reportDiagnostic as aB,
5313
- computed as aC,
5314
- staleValues as aD,
5315
- CONFIG_AUTO_DISPOSE as aE,
5316
- EFFECT_TRACKED as aF,
5317
- unwrapStatusError as aG,
5318
- haltReactivity as aH,
5319
- setStrictRead as aI,
5320
- StatusError as aJ,
5321
- trimStaleDeps as aK,
5322
- setTrackedQueueCallback as aL,
5323
- setEffectStatusNotify as aM,
5324
- _hitUnhandledAsync as aN,
5325
- resetUnhandledAsync as aO,
5326
- ROOT_ERROR_HOOK as aP,
5327
- registerGraph as aQ,
5328
- runWithOwner as aR,
5329
- setMemo as aS,
5330
- $REFRESH as aT,
5331
- markRefresh as aU,
5332
- createRoot as aV,
5333
- getObserver as aW,
5334
- dispose as aX,
5335
- TimeoutError as aY,
5336
- untrack as aZ,
5337
- dirtyQueue as a_,
5338
- warnStrictReadUntracked as aa,
5339
- markLateLinker as ab,
5340
- spectating as ac,
5341
- STATUS_ERROR as ad,
5342
- unflushedValue as ae,
5343
- stagedReaders as af,
5344
- enterAction as ag,
5345
- setEffectCallback as ah,
5346
- exitAction as ai,
5347
- isThenable as aj,
5348
- actionDepth as ak,
5349
- flush as al,
5350
- setQuestion as am,
5351
- emitDiagnostic as an,
5352
- enterCallback as ao,
5353
- exitCallback as ap,
5354
- getOwner as aq,
5355
- inEffectCallback as ar,
5356
- signal as as,
5357
- setSignal as at,
5358
- cleanup as au,
5359
- read as av,
5360
- NoOwnerError as aw,
5361
- ContextNotFoundError as ax,
5362
- createEffectNode as ay,
5363
- recompute as az,
5355
+ untrack as a$,
5356
+ CONFIG_INPUTS_PUBLISHED as a0,
5357
+ setVerdict as a1,
5358
+ context as a2,
5359
+ REACTIVE_PROBED as a3,
5360
+ bornInto as a4,
5361
+ globalQueue as a5,
5362
+ staleReader as a6,
5363
+ verdict as a7,
5364
+ link as a8,
5365
+ pullComputed as a9,
5366
+ createEffectNode as aA,
5367
+ recompute as aB,
5368
+ EFFECT_USER as aC,
5369
+ reportDiagnostic as aD,
5370
+ computed as aE,
5371
+ staleValues as aF,
5372
+ CONFIG_AUTO_DISPOSE as aG,
5373
+ EFFECT_TRACKED as aH,
5374
+ unwrapStatusError as aI,
5375
+ haltReactivity as aJ,
5376
+ setStrictRead as aK,
5377
+ StatusError as aL,
5378
+ trimStaleDeps as aM,
5379
+ setTrackedQueueCallback as aN,
5380
+ setEffectStatusNotify as aO,
5381
+ _hitUnhandledAsync as aP,
5382
+ resetUnhandledAsync as aQ,
5383
+ ROOT_ERROR_HOOK as aR,
5384
+ registerGraph as aS,
5385
+ runWithOwner as aT,
5386
+ setMemo as aU,
5387
+ $REFRESH as aV,
5388
+ markRefresh as aW,
5389
+ createRoot as aX,
5390
+ getObserver as aY,
5391
+ dispose as aZ,
5392
+ TimeoutError as a_,
5393
+ strictRead as aa,
5394
+ warnStrictReadUntracked as ab,
5395
+ joinPass as ac,
5396
+ markLateLinker as ad,
5397
+ spectating as ae,
5398
+ STATUS_ERROR as af,
5399
+ unflushedValue as ag,
5400
+ stagedReaders as ah,
5401
+ enterAction as ai,
5402
+ setEffectCallback as aj,
5403
+ exitAction as ak,
5404
+ isThenable as al,
5405
+ actionDepth as am,
5406
+ flush as an,
5407
+ setQuestion as ao,
5408
+ emitDiagnostic as ap,
5409
+ enterCallback as aq,
5410
+ exitCallback as ar,
5411
+ getOwner as as,
5412
+ inEffectCallback as at,
5413
+ signal as au,
5414
+ setSignal as av,
5415
+ cleanup as aw,
5416
+ read as ax,
5417
+ NoOwnerError as ay,
5418
+ ContextNotFoundError as az,
5364
5419
  CONFIG_VERDICT as b,
5365
- passTx as b0,
5366
- CONFIG_FRESH_READ as b1,
5367
- createOwner as b2,
5368
- REACTIVE_WRITE_IN_OWNED_SCOPE_SIGNAL_MESSAGE as b3,
5369
- ownedScopeWriteMessage as b4,
5370
- DEV as b5,
5371
- isEqual as b6,
5372
- CONFIG_MANUAL_WRITE as b7,
5373
- notePromotedWrite as b8,
5374
- slotSignal as b9,
5375
- setSnapshotCapture as bA,
5376
- setAttributionHooks as bB,
5377
- liveRootOwners as bC,
5378
- ownerPath as bD,
5379
- isSuppressed as bE,
5380
- blockersOf as bF,
5381
- CONFIG_PLUMBING as bG,
5382
- anyExcluded as bH,
5383
- isExcluded as bI,
5384
- CONFIG_WIDE as bJ,
5385
- GRAPH_SIZE_WARN_AT as bK,
5386
- noteFanOut as bL,
5387
- CONFIG_SUPERSEDES as bM,
5388
- stagedScreen as ba,
5389
- CONFIG_PROMOTED as bb,
5390
- setSlotUnobserved as bc,
5391
- joinPassTx as bd,
5392
- asyncTailFlights as be,
5393
- untrackDepth as bf,
5394
- checkPostAwaitRead as bg,
5395
- insertIntoHeap as bh,
5396
- isDisposed as bi,
5397
- handleAsync as bj,
5398
- addPendingSource as bk,
5399
- propagateStatus as bl,
5400
- forEachDependent as bm,
5401
- settlePendingSource as bn,
5402
- notifyEpoch as bo,
5403
- SUPPORTS_PROXY as bp,
5404
- REACTIVE_ZOMBIE as bq,
5405
- OBSERVE as br,
5406
- clearSnapshots as bs,
5407
- enforceLoadingBoundary as bt,
5408
- getNextChildId as bu,
5409
- markSnapshotScope as bv,
5410
- peekNextChildId as bw,
5411
- releaseSnapshotScope as bx,
5412
- resetErrorHalt as by,
5413
- setConsoleFooter as bz,
5420
+ dirtyQueue as b0,
5421
+ CONFIG_REDERIVE as b1,
5422
+ passTx as b2,
5423
+ CONFIG_FRESH_READ as b3,
5424
+ createOwner as b4,
5425
+ REACTIVE_WRITE_IN_OWNED_SCOPE_SIGNAL_MESSAGE as b5,
5426
+ ownedScopeWriteMessage as b6,
5427
+ DEV as b7,
5428
+ isEqual as b8,
5429
+ CONFIG_MANUAL_WRITE as b9,
5430
+ peekNextChildId as bA,
5431
+ releaseSnapshotScope as bB,
5432
+ resetErrorHalt as bC,
5433
+ setConsoleFooter as bD,
5434
+ setSnapshotCapture as bE,
5435
+ setAttributionHooks as bF,
5436
+ liveRootOwners as bG,
5437
+ ownerPath as bH,
5438
+ isSuppressed as bI,
5439
+ blockersOf as bJ,
5440
+ CONFIG_PLUMBING as bK,
5441
+ anyExcluded as bL,
5442
+ isExcluded as bM,
5443
+ CONFIG_WIDE as bN,
5444
+ GRAPH_SIZE_WARN_AT as bO,
5445
+ noteFanOut as bP,
5446
+ CONFIG_SUPERSEDES as bQ,
5447
+ snapshotCaptureActive as ba,
5448
+ captureWriteSnapshot as bb,
5449
+ notePromotedWrite as bc,
5450
+ slotSignal as bd,
5451
+ stagedScreen as be,
5452
+ CONFIG_PROMOTED as bf,
5453
+ setSlotUnobserved as bg,
5454
+ joinPassTx as bh,
5455
+ asyncTailFlights as bi,
5456
+ untrackDepth as bj,
5457
+ checkPostAwaitRead as bk,
5458
+ insertIntoHeap as bl,
5459
+ isDisposed as bm,
5460
+ handleAsync as bn,
5461
+ addPendingSource as bo,
5462
+ propagateStatus as bp,
5463
+ forEachDependent as bq,
5464
+ settlePendingSource as br,
5465
+ notifyEpoch as bs,
5466
+ SUPPORTS_PROXY as bt,
5467
+ REACTIVE_ZOMBIE as bu,
5468
+ OBSERVE as bv,
5469
+ clearSnapshots as bw,
5470
+ enforceLoadingBoundary as bx,
5471
+ getNextChildId as by,
5472
+ markSnapshotScope as bz,
5414
5473
  REACTIVE_PROBE_UNANSWERED as c,
5415
5474
  blocked as d,
5416
- enqueueSub as e,
5417
- CONFIG_AUTHORITATIVE as f,
5418
- tracking as g,
5419
- CONFIG_CHILDREN_FORBIDDEN as h,
5420
- sameLane as i,
5421
- CONFIG_HELD as j,
5422
- flushTransaction as k,
5423
- STATUS_UNINITIALIZED as l,
5424
- NotReadyError as m,
5475
+ REACTIVE_LANE_DIRTY as e,
5476
+ enqueueSub as f,
5477
+ CONFIG_AUTHORITATIVE as g,
5478
+ tracking as h,
5479
+ CONFIG_CHILDREN_FORBIDDEN as i,
5480
+ sameLane as j,
5481
+ CONFIG_HELD as k,
5482
+ flushTransaction as l,
5483
+ STATUS_UNINITIALIZED as m,
5425
5484
  nextQuestion as n,
5426
- REACTIVE_SCREEN_READ as o,
5485
+ NotReadyError as o,
5427
5486
  passLane as p,
5428
5487
  question as q,
5429
5488
  resolveTx as r,
5430
5489
  schedule as s,
5431
5490
  txOf as t,
5432
- REACTIVE_FRAME_READ as u,
5433
- REACTIVE_LANE_READ as v,
5434
- ext as w,
5435
- REACTIVE_RECOMPUTING_DEPS as x,
5436
- queuePendingNode as y,
5437
- REACTIVE_LANE_DIRTY as z
5491
+ REACTIVE_SCREEN_READ as u,
5492
+ REACTIVE_FRAME_READ as v,
5493
+ REACTIVE_LANE_READ as w,
5494
+ ext as x,
5495
+ REACTIVE_RECOMPUTING_DEPS as y,
5496
+ queuePendingNode as z
5438
5497
  };