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

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 (118) hide show
  1. package/dist/dev-shared.js +2056 -3773
  2. package/dist/dev.attribution.js +159 -91
  3. package/dist/dev.js +7263 -8384
  4. package/dist/observe/affects.js +125 -104
  5. package/dist/observe/boundaries.js +458 -665
  6. package/dist/observe/core/action.js +63 -66
  7. package/dist/observe/core/async.js +240 -383
  8. package/dist/observe/core/attribution-queries.js +1 -1
  9. package/dist/observe/core/attribution.js +271 -199
  10. package/dist/observe/core/constants.js +115 -178
  11. package/dist/observe/core/context.js +3 -3
  12. package/dist/observe/core/core.js +840 -1428
  13. package/dist/observe/core/dev.js +41 -18
  14. package/dist/observe/core/effect.js +75 -86
  15. package/dist/observe/core/external.js +5 -5
  16. package/dist/observe/core/graph.js +61 -70
  17. package/dist/observe/core/heap.js +75 -98
  18. package/dist/observe/core/invariants.js +1 -34
  19. package/dist/observe/core/lanes.js +704 -181
  20. package/dist/observe/core/owner.js +80 -101
  21. package/dist/observe/core/scheduler.js +708 -1351
  22. package/dist/observe/core/verdict.js +302 -621
  23. package/dist/observe/flatten.js +79 -0
  24. package/dist/observe/index.js +15 -13
  25. package/dist/observe/map.js +232 -235
  26. package/dist/observe/reveal.js +212 -0
  27. package/dist/observe/signals.js +133 -215
  28. package/dist/observe/store/affects.js +135 -0
  29. package/dist/observe/store/index.js +29 -24
  30. package/dist/observe/store/optimistic.js +538 -0
  31. package/dist/observe/store/projection.js +302 -0
  32. package/dist/observe/store/reconcile.js +257 -0
  33. package/dist/observe/store/store.js +1945 -277
  34. package/dist/observe/store/storePath.js +1 -1
  35. package/dist/{prod/store/next → observe/store}/target.js +17 -18
  36. package/dist/observe/store/types.js +73 -0
  37. package/dist/observe/store/utils.js +1 -13
  38. package/dist/prod/affects.js +127 -106
  39. package/dist/prod/boundaries.js +442 -654
  40. package/dist/prod/core/action.js +71 -74
  41. package/dist/prod/core/async.js +307 -442
  42. package/dist/prod/core/constants.js +112 -177
  43. package/dist/prod/core/context.js +3 -3
  44. package/dist/prod/core/core.js +852 -1448
  45. package/dist/prod/core/effect.js +88 -99
  46. package/dist/prod/core/external.js +5 -5
  47. package/dist/prod/core/graph.js +61 -70
  48. package/dist/prod/core/heap.js +75 -98
  49. package/dist/prod/core/invariants.js +1 -32
  50. package/dist/prod/core/lanes.js +666 -181
  51. package/dist/prod/core/owner.js +75 -96
  52. package/dist/prod/core/scheduler.js +677 -1332
  53. package/dist/prod/core/verdict.js +297 -621
  54. package/dist/prod/flatten.js +77 -0
  55. package/dist/prod/index.js +15 -13
  56. package/dist/prod/map.js +143 -146
  57. package/dist/prod/reveal.js +212 -0
  58. package/dist/prod/signals.js +144 -226
  59. package/dist/prod/store/affects.js +135 -0
  60. package/dist/prod/store/index.js +28 -19
  61. package/dist/prod/store/optimistic.js +533 -0
  62. package/dist/prod/store/projection.js +295 -0
  63. package/dist/prod/store/reconcile.js +257 -0
  64. package/dist/prod/store/store.js +1840 -272
  65. package/dist/prod/store/storePath.js +1 -1
  66. package/dist/{observe/store/next → prod/store}/target.js +13 -17
  67. package/dist/prod/store/types.js +73 -0
  68. package/dist/prod/store/utils.js +1 -11
  69. package/dist/types/affects.d.ts +11 -30
  70. package/dist/types/boundaries.d.ts +62 -176
  71. package/dist/types/carved.d.ts +1 -0
  72. package/dist/types/core/action.d.ts +5 -6
  73. package/dist/types/core/async.d.ts +10 -5
  74. package/dist/types/core/attribution-hooks.d.ts +48 -1
  75. package/dist/types/core/attribution.d.ts +29 -9
  76. package/dist/types/core/constants.d.ts +125 -171
  77. package/dist/types/core/core.d.ts +104 -264
  78. package/dist/types/core/dev.d.ts +60 -7
  79. package/dist/types/core/effect.d.ts +0 -7
  80. package/dist/types/core/graph.d.ts +7 -1
  81. package/dist/types/core/heap.d.ts +5 -7
  82. package/dist/types/core/index.d.ts +6 -6
  83. package/dist/types/core/invariants.d.ts +0 -29
  84. package/dist/types/core/lanes.d.ts +65 -87
  85. package/dist/types/core/owner.d.ts +3 -3
  86. package/dist/types/core/scheduler.d.ts +249 -331
  87. package/dist/types/core/types.d.ts +51 -85
  88. package/dist/types/core/verdict.d.ts +3 -0
  89. package/dist/types/flatten.d.ts +8 -0
  90. package/dist/types/index.d.ts +7 -5
  91. package/dist/types/reveal.d.ts +19 -0
  92. package/dist/types/signals.d.ts +53 -92
  93. package/dist/types/store/affects.d.ts +1 -0
  94. package/dist/types/store/index.d.ts +35 -15
  95. package/dist/types/store/optimistic.d.ts +23 -0
  96. package/dist/types/store/projection.d.ts +18 -0
  97. package/dist/types/store/reconcile.d.ts +3 -0
  98. package/dist/types/store/store.d.ts +165 -143
  99. package/dist/types/store/storePath.d.ts +1 -1
  100. package/dist/types/store/target.d.ts +151 -0
  101. package/dist/types/store/types.d.ts +84 -0
  102. package/package.json +1 -1
  103. package/dist/observe/core/optimistic.js +0 -669
  104. package/dist/observe/store/next/optimistic.js +0 -717
  105. package/dist/observe/store/next/projection.js +0 -266
  106. package/dist/observe/store/next/reconcile.js +0 -375
  107. package/dist/observe/store/next/store.js +0 -2480
  108. package/dist/prod/core/optimistic.js +0 -658
  109. package/dist/prod/store/next/optimistic.js +0 -710
  110. package/dist/prod/store/next/projection.js +0 -257
  111. package/dist/prod/store/next/reconcile.js +0 -373
  112. package/dist/prod/store/next/store.js +0 -2356
  113. package/dist/types/core/optimistic.d.ts +0 -6
  114. package/dist/types/store/next/optimistic.d.ts +0 -25
  115. package/dist/types/store/next/projection.d.ts +0 -27
  116. package/dist/types/store/next/reconcile.d.ts +0 -10
  117. package/dist/types/store/next/store.d.ts +0 -143
  118. package/dist/types/store/next/target.d.ts +0 -196
@@ -1,4 +1,4 @@
1
- import { isWrappable, ownEnumerableKeys } from "./store.js";
1
+ import { isWrappable, ownEnumerableKeys } from "./types.js";
2
2
 
3
3
  const DELETE = Symbol(0);
4
4
 
@@ -14,33 +14,29 @@
14
14
  */
15
15
  const $OWNER = Symbol(0);
16
16
 
17
- /** raw → target for UNOWNED backings (user-ingested, adopted); owned
18
- * backings resolve through their `$OWNER` stamp. Boundary mechanism (O8). */ const storeNextLookup = new WeakMap;
17
+ /** raw → target for plain (family-less) stores. Family stores use their own
18
+ * map so one raw can wrap once per family (§7b). */ const storeLookup = new WeakMap;
19
19
 
20
- /** A backing the store allocated and may mutate in place. */ function isOwned(e) {
20
+ function setLookup(e, o) {
21
+ (o.fam?.map ?? storeLookup).set(e, o);
22
+ }
23
+
24
+ function isOwned(e) {
21
25
  return e[$OWNER] !== undefined;
22
26
  }
23
27
 
24
- /** raw → target within a family (`null` = plain stores / the global map).
25
- * The stamp answers for backings owned by a target OF THAT FAMILY; anything
26
- * else (user objects, adoptees, another family's backings the family
27
- * re-registered for its own wrapper) resolves through the family's map. */ function lookupTarget(e, o) {
28
+ /** The target wrapping `raw` in `fam` (or the plain lookup). An owned raw
29
+ * answers from its stamp; a user raw from the map. */ function lookupTarget(e, o) {
28
30
  const t = e[$OWNER];
29
- return t !== undefined && t.fam === o ? t : (o?.map ?? storeNextLookup).get(e);
31
+ return t !== undefined && t.fam === o ? t : (o?.map ?? storeLookup).get(e);
30
32
  }
31
33
 
32
34
  function devAssertNeverUserMutation(e) {
33
35
  return;
34
36
  }
35
37
 
36
- let optHooks = null;
37
-
38
- function setOptHooks(e) {
39
- optHooks = e;
40
- }
41
-
42
- /** Sticky descendants flag walk (§6d): reconcile's keyed pruning descends
43
- * only where subscriptions exist at/below. Nodes AND patches count. */ function markDescendants(e) {
38
+ /** Sticky descendants flag up the parent chain (§6d): adoption descends
39
+ * into a changed child pair only where a target with nodes exists below. */ function markDescendants(e) {
44
40
  let o = e;
45
41
  while (o && !o.d) {
46
42
  o.d = true;
@@ -48,4 +44,4 @@ function setOptHooks(e) {
48
44
  }
49
45
  }
50
46
 
51
- export { $OWNER, devAssertNeverUserMutation, isOwned, lookupTarget, markDescendants, optHooks, setOptHooks, storeNextLookup };
47
+ export { $OWNER, devAssertNeverUserMutation, isOwned, lookupTarget, markDescendants, setLookup, storeLookup };
@@ -0,0 +1,73 @@
1
+ /** Brand keys the proxy answers directly (never user data). */
2
+ const $TRACK = Symbol(0), $TARGET = Symbol(0), $PROXY = Symbol(0), $RECORD = Symbol(0);
3
+
4
+ // ---------------------------------------------------------------------------
5
+ // raw marking (R42 / RUL-12: a value is never both wrapped and raw)
6
+ const rawValues = new WeakSet;
7
+
8
+ let rawValuesUsed = false;
9
+
10
+ function isRawValue(e) {
11
+ return rawValuesUsed && rawValues.has(e);
12
+ }
13
+
14
+ /** Mark a value so no store ever wraps it (sticky; it reads as a leaf). */ function markRaw(e) {
15
+ if (isWrappable(e)) {
16
+ rawValuesUsed = true;
17
+ rawValues.add(e);
18
+ }
19
+ return e;
20
+ }
21
+
22
+ /** A shallow store's ingested record: raw by contract (values served
23
+ * verbatim, slots replaced by reference). */ function markRawOne(e) {
24
+ if (isWrappable(e)) {
25
+ if (e[$TARGET] !== undefined) return;
26
+ rawValuesUsed = true;
27
+ rawValues.add(e);
28
+ }
29
+ }
30
+
31
+ function markRawIngest(e) {
32
+ if (Array.isArray(e)) {
33
+ for (let r = 0, a = e.length; r < a; r++) markRawOne(e[r]);
34
+ } else {
35
+ for (const r in e) markRawOne(e[r]);
36
+ }
37
+ }
38
+
39
+ // ---------------------------------------------------------------------------
40
+ // wrappability
41
+ const OBJECT_PROTO = Object.prototype;
42
+
43
+ const wrappableProtos = new WeakMap;
44
+
45
+ function isWrappable(e) {
46
+ if (e == null || typeof e !== "object" || Object.isFrozen(e)) return false;
47
+ const r = Object.getPrototypeOf(e);
48
+ if (r === OBJECT_PROTO || r === null) return true;
49
+ if (Array.isArray(e)) return true;
50
+ let a = wrappableProtos.get(r);
51
+ if (a === undefined) {
52
+ a = Object.prototype.toString.call(e) === "[object Object]" && (typeof Node === "undefined" || !(e instanceof Node));
53
+ wrappableProtos.set(r, a);
54
+ }
55
+ return a;
56
+ }
57
+
58
+ function ownEnumerableKeys(e) {
59
+ return Reflect.ownKeys(e).filter(r => Object.prototype.propertyIsEnumerable.call(e, r));
60
+ }
61
+
62
+ // ---------------------------------------------------------------------------
63
+ // write override: a projection's draft ops carry it (the derive is the
64
+ // author — its writes must land outside the sync setter scope too, in a
65
+ // continuation after an `await`/`yield`). Projections return in S3; the
66
+ // traps already honour it.
67
+ let writeOverride = false;
68
+
69
+ function setWriteOverride(e) {
70
+ writeOverride = e;
71
+ }
72
+
73
+ export { $PROXY, $RECORD, $TARGET, $TRACK, isRawValue, isWrappable, markRaw, markRawIngest, markRawOne, ownEnumerableKeys, rawValuesUsed, setWriteOverride, writeOverride };
@@ -1,18 +1,8 @@
1
- import "../core/core.js";
2
-
3
1
  import { SUPPORTS_PROXY } from "../core/constants.js";
4
2
 
5
- import "../core/scheduler.js";
6
-
7
- import "../core/invariants.js";
8
-
9
- import "../core/verdict.js";
10
-
11
- import "../core/effect.js";
12
-
13
3
  import { createMemo } from "../signals.js";
14
4
 
15
- import { $PROXY, $RECORD, $TARGET, ownEnumerableKeys } from "./store.js";
5
+ import { $PROXY, $RECORD, $TARGET, ownEnumerableKeys } from "./types.js";
16
6
 
17
7
  function trueFn() {
18
8
  return true;
@@ -1,28 +1,15 @@
1
1
  import type { Accessor } from "./signals.js";
2
- import { type Store } from "./store/store.js";
2
+ import { type Store } from "./store/types.js";
3
3
  /**
4
- * Declares that in-flight work will change the targeted data: the named
5
- * slot(s) — and everything DERIVED from them — read as pending
6
- * (`isPending` → `true`) from the declaration until the surrounding
7
- * transaction settles or reverts. A mark lives on its own channel — a
8
- * refcount on the marked node plus dep-graph reachability in the verdict
9
- * layer — so the marked values themselves stay readable (a mark is a promise
10
- * of change, not an absence of value), no reader ever suspends on one, and
11
- * completion/settlement accounting never sees one. This is the declaration
12
- * verb of the pending model — additive only. A mark can turn pending ON for
13
- * data the graph can't see changing yet; nothing can turn pending OFF while
14
- * a real change is in flight — a quiet `refresh()` re-ask under a mark still
15
- * reads pending (declaring the reload is what makes it a real question).
16
- *
17
- * Targets:
18
- * - `affects(store)` — a store proxy (any record, root or nested): every
19
- * record reachable from it at declaration time reads pending, including
20
- * through captured child proxies (e.g. `<For>` rows). Siblings are
21
- * untouched; records added after the declaration are not covered.
22
- * - `affects(record, key)` — exactly the named slot of the record. One key
23
- * per call (keys do NOT form a path — target the owning record directly).
24
- * - `affects(accessor)` — a source accessor (signal or memo): the source
25
- * reads pending.
4
+ * Declares that in-flight work will change the targeted data: the source —
5
+ * and everything derived from it — reads as pending (`isPending` → `true`)
6
+ * from the declaration until the surrounding transaction settles. A mark is
7
+ * a promise of change, not an absence of value: the marked values stay
8
+ * readable, no reader suspends on one, and it holds nothing — the
9
+ * transaction's completion never waits on a mark. Pendingness is additive:
10
+ * a mark can turn pending on for data the graph cannot see changing yet
11
+ * (a declared reload's `refresh()` is a quiet re-ask on its own); nothing
12
+ * turns it off while the mark is live.
26
13
  *
27
14
  * Typically called at the top of an `action` alongside optimistic writes —
28
15
  * both are up-front declarations about the same mutation. Outside any
@@ -30,14 +17,8 @@ import { type Store } from "./store/store.js";
30
17
  *
31
18
  * @example
32
19
  * ```ts
33
- * const send = action(function* (text: string) {
34
- * setState(s => { s.messages.push({ text, status: "sending" }); });
35
- * affects(state.messages.at(-1)!, "status"); // this slot pends until settle
36
- * yield api.send(text);
37
- * });
38
- *
39
20
  * const reload = action(function* () {
40
- * affects(thing); // the whole store pends…
21
+ * affects(thing); // `thing` and its derivations pend…
41
22
  * refresh(thing); // …over this otherwise-quiet re-ask
42
23
  * yield api.done();
43
24
  * });
@@ -1,109 +1,68 @@
1
- import type { OptimisticLane } from "./core/lanes.js";
2
- import { Queue, type Computed, type Effect, type Owner } from "./core/index.js";
3
- import type { Signal } from "./core/index.js";
1
+ import { type Transaction } from "./core/scheduler.js";
2
+ import type { Computed, Owner, Signal } from "./core/types.js";
4
3
  import { type Accessor } from "./signals.js";
5
- export interface BoundaryComputed<T> extends Computed<T> {
6
- _propagationMask: number;
7
- }
8
- type RevealSlot = CollectionQueue | RevealController;
9
- type BoolAccessor = () => boolean;
10
- export type RevealOrder = "sequential" | "together" | "natural";
11
- type OrderAccessor = () => RevealOrder;
12
- export declare class RevealController {
13
- _orderAccessor: OrderAccessor;
14
- _collapsedAccessor: BoolAccessor;
15
- _slots: RevealSlot[];
16
- _parentController?: RevealController;
17
- _disabled: Signal<boolean>;
18
- _collapsed: Signal<boolean>;
19
- _ready: boolean;
20
- _minimallyReady: boolean;
21
- _evaluating: boolean;
22
- constructor(order: OrderAccessor, collapsed: BoolAccessor);
23
- _forEachOwnedSlot(fn: (slot: RevealSlot) => boolean | void): boolean;
24
- _isReady(): boolean;
25
- /**
26
- * "Minimally ready" = this group has something visible to show under its own policy.
27
- * Used by an enclosing `together` group to decide when it can release.
28
- * - `together`: every direct slot is minimally ready.
29
- * - `sequential`: the first owned slot is minimally ready (frontier can advance).
30
- * - `natural`: any owned slot is minimally ready.
31
- */
32
- _isMinimallyReady(): boolean;
33
- _register(slot: RevealSlot): void;
34
- _unregister(slot: RevealSlot): void;
35
- _evaluate(disabledOverride?: boolean, collapsedOverride?: boolean): void;
36
- }
37
- export declare class CollectionQueue extends Queue {
38
- _collectionType: number;
39
- _sources: Set<Computed<any>>;
40
- _tree?: BoundaryComputed<any>;
41
- /** The output pass — fallback or content (createCollectionBoundary). */
42
- _output?: Computed<any>;
43
- _pending: boolean;
44
- _disabled: Signal<boolean>;
45
- _error?: Signal<unknown>;
46
- _collapsed: Signal<boolean>;
47
- _revealController?: RevealController;
4
+ interface Boundary {
5
+ /** STATUS_PENDING (loading) or STATUS_ERROR. */
6
+ _type: number;
7
+ _parent: Boundary | null;
8
+ _owner: Owner;
9
+ _tree: Computed<any>;
10
+ /** Null during the output's first pass (its post-check decides then). */
11
+ _output: Computed<any> | null;
12
+ /** Frame readers under it carrying its status: caught, or (loading,
13
+ * showing content) forwarded — the `on` re-arm collects those. */
14
+ _readers: Set<Computed<any>>;
15
+ /** Loading: has shown content. Fresh again after an `on` re-arm found
16
+ * something pending. */
48
17
  _initialized: boolean;
49
- /** The boundary's owner — where a `caught` report locates itself, set before the children are built (a creation-time throw arrives before `_tree`). */
50
- _owner?: Owner;
51
- /** The lane the `on` pass that queued this re-arm ran under (onNode), if
52
- * any: the fallback swap is display-ahead — shown through the lane. */
53
- _rearmLane: OptimisticLane | null;
54
- constructor(type: number);
55
- run(type: number): void;
56
- /** An `on` dependency notified (onNode → scheduler `pendingRearms`);
57
- * drained after the heap, before the verdict, under the notifying write's
58
- * transaction (#3540). A boundary showing content is fresh again: it
59
- * releases its hold now and, if anything under it is still pending, swaps
60
- * to its fallback. The swap is staged, so it lands with the write's frame
61
- * — at once when nothing else holds it, with the rest of the new page
62
- * when something outside the boundary does; if the pending lands first,
63
- * `_checkSources` clears it and no fallback is shown. An `on` that read a
64
- * lane (`latest()`, an optimistic write) asked for the change now:
65
- * `_rearmLane` shows the swap through the lane, beside the held frame.
66
- * Children stay alive behind the fallback. */
67
- _rearm(): void;
68
- /** Show the fallback: the swap the output pass selects on. Staged, it is
69
- * the frame's and lands with its commit. Re-armed from a lane pass
70
- * (`lane`), it is the current frame's — committed outright, as the lane's
71
- * view already is on screen — and shown through the lane: the output pass
72
- * publishes a derived override and its readers run from the lane's queue,
73
- * at the park, ahead of the transaction (a lane pass reads staged plain
74
- * writes committed, so a staged swap would be invisible to it). */
75
- _swap(lane: OptimisticLane | null): void;
76
- /** Retry the collected failures of an error boundary: recompute each
77
- * source that threw, so the boundary can recover. */
78
- _retry(): void;
79
- notify(node: Effect<any>, type: number, flags: number, error?: any): boolean;
80
- /** Is `reporter` live and routed to this boundary — under it, with no
81
- * collecting pending-type boundary in between (`reporterBlocksSource`'s test)? */
82
- _holds(reporter: Computed<any>): boolean;
83
- /** Has a collected source stopped counting for this boundary? A source
84
- * with a live affects() mark holds display state for the mark's lifetime
85
- * (the visual channel): the marked node carries no status of its own, so
86
- * the count is the liveness test. The release sweep (finalizePureQueue
87
- * after mark release) re-runs this check. A source born held under this
88
- * boundary (recompute, #3540) carries no status either: it is collected
89
- * while it has a staged value and no committed one, and released by the
90
- * commit that initializes it. */
91
- _settled(source: Computed<any>): boolean;
92
- /** The pre-verdict sweep (scheduler run(), #3540): a collecting boundary
93
- * whose OUTPUT is pending — its fallback read something not ready — is
94
- * judged here, under the transaction. That output is what an initialized
95
- * parent holds the frame on, and it derives from `_disabled`, not the
96
- * tree: the tree settling never re-runs it, only a sweep does, and the
97
- * commit sweep runs after the verdict the output's own read keeps parking
98
- * — the content waited for the fallback's flight. Judged ready here, the
99
- * boundary stages `_disabled` false with the frame and the output re-runs
100
- * in this heap: it reads the tree and drops the fallback's read (recompute
101
- * settles a pass's outgoing pending sources), so the verdict sees the
102
- * release. A boundary showing a ready fallback parks nothing and keeps the
103
- * commit sweep's reveal. */
104
- _judgeHeld(): void;
105
- _checkSources(): void;
18
+ /** Loading: `on` changed this flush — collecting until the seam. */
19
+ _armed: boolean;
20
+ /** The lane the arming pass was work of (a display-ahead read in `on`:
21
+ * `latest`, `isPending`): the swap it causes is that lane's — shown now,
22
+ * beside the held frame — not the frame's. `_lane` is set when the arm
23
+ * flips the boundary and consumed by the swap pass. */
24
+ _armLane: Transaction | null;
25
+ _lane: Transaction | null;
26
+ /** DEV: the arm was display-ahead (a lane) — the fallback shows now,
27
+ * whatever holds the frame; no LOADING_ON_OUTSIDE_HOLD report. */
28
+ _ahead?: boolean;
29
+ /** The output's last pass chose the fallback: readers under it are off
30
+ * screen (`hidden`). */
31
+ _fallback: boolean;
32
+ /** User effects whose run came due behind the fallback: re-queued at the
33
+ * reveal (`heldRun`). */
34
+ _runs: Set<Computed<any>> | null;
35
+ /** Reveal order (reveal.ts): the controller that owns this slot until it
36
+ * has shown content, and the state it forces — the fallback (`_gated`),
37
+ * or nothing at all (`_collapsed`). */
38
+ _reveal: object | null;
39
+ _gated: boolean;
40
+ _collapsed: boolean;
41
+ _error: Signal<unknown> | null;
42
+ _show: (b: Boundary) => unknown;
43
+ }
44
+ /** Context key: the reveal controller a Loading boundary created here is a
45
+ * slot of (reveal.ts); a boundary clears it for its content — only direct
46
+ * children are slots. */
47
+ export declare const REVEAL: unique symbol;
48
+ /** Reveal order (reveal.ts), installed when something imports
49
+ * `createRevealOrder`: a Loading boundary registers as a slot of the
50
+ * controller in its context, tells it when its readiness changed, and
51
+ * leaves it when it has shown content. */
52
+ export interface RevealHooks {
53
+ _register(controller: object, b: Boundary): void;
54
+ _unregister(controller: object, b: Boundary): void;
55
+ _changed(controller: object): void;
106
56
  }
57
+ export declare let revealHooks: RevealHooks | null;
58
+ export declare function setRevealHooks(h: RevealHooks): void;
59
+ export type { Boundary };
60
+ export declare function redraw(b: Boundary): void;
61
+ export declare function prune(b: Boundary, pass: boolean): number;
62
+ /** Reveal order: a slot is ready when its content can show — it has shown
63
+ * content, or nothing under it is unready (the tree neither pending nor
64
+ * born held, no reader waited on). */
65
+ export declare function ready(b: Boundary): boolean;
107
66
  /**
108
67
  * Lower-level primitive that backs the `<Loading>` flow control. Catches
109
68
  * pending async reads inside `fn` and renders `fallback` until they settle.
@@ -173,76 +132,3 @@ export declare function createLoadingBoundary<T, U>(fn: () => T, fallback: () =>
173
132
  * ```
174
133
  */
175
134
  export declare function createErrorBoundary<T, U>(fn: () => T, fallback: (error: Accessor<unknown>, reset: () => void) => U): Accessor<T | U>;
176
- /**
177
- * Coordinate the reveal timing of sibling loading boundaries.
178
- *
179
- * Accepts reactive accessors:
180
- * - `order`: `"sequential"` (default) | `"together"` | `"natural"`.
181
- * - `"sequential"` — classic frontier reveal: siblings reveal in registration order
182
- * as each resolves; later siblings stay hidden until earlier ones complete.
183
- * - `"together"` — every direct slot stays on its fallback until the whole group
184
- * is "minimally ready" (each direct slot has produced its own first visible
185
- * content under its own order), then the whole group releases at once.
186
- * - `"natural"` — children reveal independently (as each resolves). At the top
187
- * level this is a no-op compared to not using `createRevealOrder`; the mode
188
- * exists for nesting, where the group registers as a single composite slot to
189
- * any enclosing `createRevealOrder`.
190
- * - `collapsed`: only meaningful when `order === "sequential"`. When set, tail siblings
191
- * past the frontier suppress their own fallback output. Ignored under `"together"`
192
- * and `"natural"` — those orders have no frontier.
193
- *
194
- * Nested `createRevealOrder` groups compose: the inner controller registers as a
195
- * single slot in the outer controller and is held on its fallbacks until the outer
196
- * releases that slot. Once released, the inner controller runs its own order locally
197
- * over anything still pending. There is no opt-out from an outer hold.
198
- *
199
- * "Minimally ready" is what an order considers its first visible content:
200
- * - `sequential` — frontier-0 is minimally ready (leaf: on resolve; nested: via its
201
- * own minimal signal).
202
- * - `together` — every direct slot is minimally ready.
203
- * - `natural` — any direct slot has visible content (leaves on resolve; nested
204
- * composites via their own minimal signal).
205
- *
206
- * @example
207
- * ```ts
208
- * // Primitive form of `<Reveal>` — coordinate sibling loading boundaries
209
- * // programmatically. App code uses the JSX `<Reveal>` component instead.
210
- * // Both options are accessors so they can react to state changes.
211
- * createRevealOrder(
212
- * () => renderSiblings(),
213
- * { order: () => mode(), collapsed: () => true }
214
- * );
215
- * ```
216
- */
217
- export declare function createRevealOrder<T>(fn: () => T, options?: {
218
- order?: OrderAccessor;
219
- collapsed?: BoolAccessor;
220
- }): T;
221
- /**
222
- * Resolves a children value to its renderable form: unwraps zero-arg functions
223
- * (accessors), recursively flattens arrays, and optionally skips
224
- * non-rendering values (`null`, `undefined`, `true`, `false`, `""`).
225
- *
226
- * Used internally by flow components and by the renderer to walk a children
227
- * tree. App code rarely needs this directly — see `children()` in `solid-js`
228
- * for the user-facing helper that memoizes the result.
229
- *
230
- * @param children value or array of values to flatten
231
- * @param options
232
- * - `skipNonRendered` — drop values that won't render
233
- * - `doNotUnwrap` — leave function children as-is (caller will resolve)
234
- *
235
- * @example
236
- * ```ts
237
- * // Custom renderer walking a children tree manually. Most authors should
238
- * // use `children()` from solid-js, which memoizes the resolved value.
239
- * function renderChildren(value: unknown): unknown {
240
- * return flatten(value, { skipNonRendered: true });
241
- * }
242
- * ```
243
- */
244
- export declare function flatten(children: any, options?: {
245
- skipNonRendered?: boolean;
246
- doNotUnwrap?: boolean;
247
- }): any;
248
- export {};
@@ -0,0 +1 @@
1
+ export {};
@@ -16,9 +16,9 @@
16
16
  * submission tracking layered on top. The shared name is deliberate.
17
17
  *
18
18
  * Wraps a generator function so each invocation runs as a single transaction
19
- * (a "transition") that batches every signal/store write between yields. The
20
- * surrounding UI sees one atomic update per yielded step; nothing is committed
21
- * until the action either completes or the next `yield` resolves.
19
+ * that holds every signal/store write between yields. The surrounding UI sees
20
+ * one atomic update when the action completes; nothing is committed until
21
+ * every action in the transaction has returned.
22
22
  *
23
23
  * `yield` is the transaction-safe suspension point: the action waits for a
24
24
  * yielded promise and re-enters the transaction before running the code after
@@ -28,8 +28,7 @@
28
28
  * commit immediately, and anything that creates a reader there — `until()`,
29
29
  * `latest()`, a memo or effect, a mount — is created mainline, where a read of
30
30
  * this action's held state makes it born held (A29): staged with the
31
- * transaction and replayed at its commit. For `until()` that commit is the
32
- * settle its own promise holds open (#3482). `await` is still the ergonomic
31
+ * transaction and replayed at its commit. `await` is still the ergonomic
33
32
  * choice for typed results; just put a bare `yield` before any write or
34
33
  * reader creation that follows it — including the expression of the next
35
34
  * `yield`, which is evaluated before the step re-enters:
@@ -42,7 +41,7 @@
42
41
  * ```
43
42
  *
44
43
  * (For the same reason, don't call `flush()` inside an action body — it
45
- * drains the transaction mid-step.)
44
+ * cannot reveal the held writes and is refused.)
46
45
  *
47
46
  * Each call returns a `Promise` that resolves with the generator's return
48
47
  * value, or rejects if it throws. Pair with `createOptimistic` /
@@ -1,13 +1,12 @@
1
1
  import { NotReadyError } from "./error.js";
2
- import { type OptimisticLane } from "./lanes.js";
3
2
  import type { Computed, Link } from "./types.js";
4
3
  export declare function addPendingSource(el: Computed<any>, source: Computed<any>): boolean;
5
4
  /**
6
5
  * A loading-window node hit an unready source (sync throw in recompute, or a
7
6
  * NotReadyError-rejected flight): register for the source's settle — the
8
7
  * settlePendingSource walk runs off `_pendingSources` + `_blocked` alone —
9
- * with NO read-visible pending status, no downstream propagation, no
10
- * transition, no lane registration. Commit #0 keeps serving.
8
+ * with NO read-visible pending status and no downstream propagation. Commit
9
+ * #0 keeps serving.
11
10
  */
12
11
  export declare function parkLoadingWindow(el: Computed<any>, e: NotReadyError): void;
13
12
  export declare function setPendingError(el: Computed<any>, source?: Computed<any>, error?: any): void;
@@ -18,6 +17,12 @@ export declare function settlePendingSource(el: Computed<any>, source?: Computed
18
17
  export declare function isThenable<T>(value: T | PromiseLike<T>): value is PromiseLike<T>;
19
18
  /** Fire and clear a node's iterator-flight cancellation hook (#3122). */
20
19
  export declare function releaseFlightTeardown(el: Computed<any>): void;
21
- export declare function handleAsync<T>(el: Computed<T>, result: T | PromiseLike<T> | AsyncIterable<T>, setter?: (value: T) => void): T;
20
+ export declare function handleAsync<T>(el: Computed<T>, result: T | PromiseLike<T> | AsyncIterable<T>, setter?: (value: T) => void, onError?: (error: unknown, pending: boolean) => void): T;
22
21
  export declare function clearStatus(el: Computed<any>, clearUninitialized?: boolean): void;
23
- export declare function notifyStatus(el: Computed<any>, status: number, error: any, blockStatus?: boolean, lane?: OptimisticLane): void;
22
+ export declare function notifyStatus(el: Computed<any>, status: number, error: any, blockStatus?: boolean): void;
23
+ /** The dependents' half of `notifyStatus`: `el`'s status reaches each
24
+ * subscriber as a propagated mark (or a re-derive). On its own for a store
25
+ * family's leaves, which are not the derive's dependents — the family
26
+ * propagates the derive's status from each leaf to the leaf's readers
27
+ * (store/projection.ts `wakeFamily`), exactly as a memo's would reach its. */
28
+ export declare function propagateStatus(el: Computed<any>, status: number, error: any, downstreamBlockStatus?: boolean): void;
@@ -1,6 +1,10 @@
1
1
  import type { ChangeOrigin } from "./attribution.js";
2
- import type { Transition } from "./scheduler.js";
2
+ import type { Transaction } from "./scheduler.js";
3
3
  import type { Computed, Owner, Signal } from "./types.js";
4
+ /** The hold the engine records against (L2: scheduler.ts `Transaction`).
5
+ * Outward-facing language says *holds*; the engine's hook names keep their
6
+ * historical `transition` wording. */
7
+ export type Transition = Transaction;
4
8
  /**
5
9
  * Observe-tier hook points for the reactive core.
6
10
  *
@@ -214,6 +218,21 @@ export interface InteractionRef {
214
218
  target?: string;
215
219
  /** Dispatch time on the `performance.now()` clock; defaults to now. */
216
220
  at?: number;
221
+ /**
222
+ * The dispatch this frame handles — the DOM `Event` itself. Frames with the
223
+ * same `event` are one interaction: the first opens the record (its `type`,
224
+ * `target` and `at` describe it) and every later one re-enters it, so each
225
+ * listener of one dispatch adds its work to one record. Such a record stays
226
+ * open for joining until the next task — every listener of a dispatch runs
227
+ * within its task — and is recorded no earlier; a frame for the event after
228
+ * that opens a new interaction. Without `event` the record is the frame's
229
+ * alone and can settle as it closes.
230
+ *
231
+ * A join key only, compared by identity and held weakly: it is never
232
+ * recorded — no `InteractionEvent`, origin or other record carries it — and
233
+ * the engine keeps no strong reference to it.
234
+ */
235
+ event?: object;
217
236
  }
218
237
  /**
219
238
  * A navigation, as a router describes it to `withOrigin` around the location
@@ -258,6 +277,34 @@ export interface NavigationRef {
258
277
  * a pending navigation to fold onto it opens a navigation of its own.
259
278
  */
260
279
  redirect?: number;
280
+ /**
281
+ * The route the document arrived on — declared by the router around the
282
+ * work that establishes its initial match (building its context), not
283
+ * around a write: there is no location write on a fresh document, and
284
+ * without this a consumer has the route pattern for every navigation
285
+ * but the first. The record opens at `at`, which defaults to `0` (the
286
+ * `performance.now()` origin — the document's own navigation start, so
287
+ * the record joins Navigation Timing); a router mounted long after the
288
+ * document loaded passes its own start. It settles when the frame closes,
289
+ * `committed` with no writes: it declares the route, it does not time the
290
+ * mount — the holds the mount waits in are their own records. `from` is
291
+ * meaningless for it and ignored.
292
+ */
293
+ initial?: boolean;
294
+ /**
295
+ * The interaction the navigation is for, when the router already knows it
296
+ * will not be on the stack at write time. A router that awaits between
297
+ * the request and the write (guards or loaders resolved in its core before
298
+ * it publishes the location) captures `OBSERVE.attribution.currentOrigin()`
299
+ * in the request and hands it back here, and the record — and every hold
300
+ * and re-run its write causes — joins the click as if the write had been
301
+ * synchronous. Any origin will do: the engine takes the interaction it
302
+ * carries. Declared beats ambient: the key's presence is the declaration
303
+ * — `interaction: currentOrigin()` with nothing in effect at the request
304
+ * (`undefined`) declares that the navigation was for no interaction, and an
305
+ * interaction on the stack at write time is used only when the key is absent.
306
+ */
307
+ interaction?: ChangeOrigin;
261
308
  }
262
309
  export declare let attrHooks: AttributionHooks | null;
263
310
  export declare function setAttributionHooks(hooks: AttributionHooks | null): void;