@solidjs/signals 2.0.0-rc.7 → 2.0.0-rc.9

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 (134) hide show
  1. package/dist/dev-shared.js +6357 -0
  2. package/dist/dev.attribution.js +2485 -0
  3. package/dist/dev.js +2851 -7027
  4. package/dist/observe/affects.js +129 -0
  5. package/dist/observe/attribution.js +7 -0
  6. package/dist/observe/boundaries.js +641 -0
  7. package/dist/observe/core/action.js +177 -0
  8. package/dist/observe/core/async.js +846 -0
  9. package/dist/observe/core/attribution-costs.js +66 -0
  10. package/dist/observe/core/attribution-feedback.js +282 -0
  11. package/dist/observe/core/attribution-hooks.js +82 -0
  12. package/dist/observe/core/attribution-queries.js +28 -0
  13. package/dist/observe/core/attribution.js +2095 -0
  14. package/dist/observe/core/constants.js +248 -0
  15. package/dist/{types-cjs/core/context.d.cts → observe/core/context.js} +37 -12
  16. package/dist/observe/core/core.js +1789 -0
  17. package/dist/observe/core/dev.js +293 -0
  18. package/dist/observe/core/effect.js +195 -0
  19. package/dist/observe/core/error-hooks.js +71 -0
  20. package/dist/observe/core/error.js +80 -0
  21. package/dist/observe/core/external.js +98 -0
  22. package/dist/observe/core/graph.js +155 -0
  23. package/dist/observe/core/heap.js +147 -0
  24. package/dist/observe/core/invariants.js +45 -0
  25. package/dist/observe/core/lanes.js +205 -0
  26. package/dist/observe/core/optimistic.js +585 -0
  27. package/dist/observe/core/owner.js +322 -0
  28. package/dist/observe/core/scheduler.js +1428 -0
  29. package/dist/observe/core/verdict.js +669 -0
  30. package/dist/observe/index.js +59 -0
  31. package/dist/observe/map.js +484 -0
  32. package/dist/{types-cjs/signals.d.cts → observe/signals.js} +311 -317
  33. package/dist/observe/store/index.js +40 -0
  34. package/dist/observe/store/next/optimistic.js +660 -0
  35. package/dist/observe/store/next/projection.js +255 -0
  36. package/dist/observe/store/next/reconcile.js +375 -0
  37. package/dist/observe/store/next/store.js +2327 -0
  38. package/dist/observe/store/next/target.js +51 -0
  39. package/dist/observe/store/store.js +325 -0
  40. package/dist/observe/store/storePath.js +103 -0
  41. package/dist/observe/store/utils.js +1023 -0
  42. package/dist/prod/attribution.js +41 -0
  43. package/dist/prod/boundaries.js +128 -76
  44. package/dist/prod/core/action.js +65 -37
  45. package/dist/prod/core/async.js +324 -172
  46. package/dist/prod/core/constants.js +57 -1
  47. package/dist/prod/core/context.js +3 -3
  48. package/dist/prod/core/core.js +1003 -364
  49. package/dist/prod/core/dev.js +17 -1
  50. package/dist/prod/core/effect.js +76 -42
  51. package/dist/prod/core/error-hooks.js +71 -0
  52. package/dist/prod/core/external.js +4 -4
  53. package/dist/prod/core/graph.js +37 -37
  54. package/dist/prod/core/heap.js +61 -56
  55. package/dist/prod/core/lanes.js +107 -63
  56. package/dist/prod/core/optimistic.js +374 -93
  57. package/dist/prod/core/owner.js +62 -46
  58. package/dist/prod/core/scheduler.js +653 -286
  59. package/dist/prod/core/verdict.js +245 -127
  60. package/dist/prod/index.js +15 -5
  61. package/dist/prod/map.js +292 -141
  62. package/dist/prod/signals.js +29 -16
  63. package/dist/prod/store/next/optimistic.js +77 -55
  64. package/dist/prod/store/next/projection.js +31 -20
  65. package/dist/prod/store/next/reconcile.js +87 -84
  66. package/dist/prod/store/next/store.js +718 -401
  67. package/dist/prod/store/next/target.js +32 -10
  68. package/dist/prod/store/store.js +12 -14
  69. package/dist/prod/store/utils.js +950 -130
  70. package/dist/types/attribution.d.ts +20 -0
  71. package/dist/types/attribution.prod.d.ts +22 -0
  72. package/dist/types/boundaries.d.ts +10 -1
  73. package/dist/types/core/action.d.ts +12 -5
  74. package/dist/types/core/async.d.ts +1 -1
  75. package/dist/types/core/attribution-costs.d.ts +35 -0
  76. package/dist/types/core/attribution-feedback.d.ts +133 -0
  77. package/dist/types/core/attribution-hooks.d.ts +147 -9
  78. package/dist/types/core/attribution-queries.d.ts +10 -0
  79. package/dist/types/core/attribution.d.ts +216 -182
  80. package/dist/types/core/constants.d.ts +56 -0
  81. package/dist/types/core/core.d.ts +190 -2
  82. package/dist/types/core/dev.d.ts +246 -28
  83. package/dist/types/core/effect.d.ts +8 -1
  84. package/dist/types/core/error-hooks.d.ts +71 -0
  85. package/dist/types/core/index.d.ts +4 -1
  86. package/dist/types/core/invariants.d.ts +4 -0
  87. package/dist/types/core/lanes.d.ts +39 -5
  88. package/dist/types/core/scheduler.d.ts +153 -0
  89. package/dist/types/core/types.d.ts +32 -9
  90. package/dist/types/index.d.ts +10 -3
  91. package/dist/types/map.d.ts +2 -0
  92. package/dist/types/signals.d.ts +8 -0
  93. package/dist/types/store/index.d.ts +2 -0
  94. package/dist/types/store/next/optimistic.d.ts +1 -1
  95. package/dist/types/store/next/store.d.ts +11 -5
  96. package/dist/types/store/next/target.d.ts +37 -10
  97. package/dist/types/store/utils.d.ts +178 -0
  98. package/package.json +21 -17
  99. package/dist/node.cjs +0 -10541
  100. package/dist/node.dev.cjs +0 -13724
  101. package/dist/types-cjs/affects.d.cts +0 -47
  102. package/dist/types-cjs/boundaries.d.cts +0 -175
  103. package/dist/types-cjs/core/action.d.cts +0 -64
  104. package/dist/types-cjs/core/async.d.cts +0 -23
  105. package/dist/types-cjs/core/attribution-hooks.d.cts +0 -127
  106. package/dist/types-cjs/core/attribution.d.cts +0 -495
  107. package/dist/types-cjs/core/constants.d.cts +0 -159
  108. package/dist/types-cjs/core/core.d.cts +0 -185
  109. package/dist/types-cjs/core/dev.d.cts +0 -136
  110. package/dist/types-cjs/core/effect.d.cts +0 -30
  111. package/dist/types-cjs/core/error.d.cts +0 -56
  112. package/dist/types-cjs/core/external.d.cts +0 -15
  113. package/dist/types-cjs/core/graph.d.cts +0 -28
  114. package/dist/types-cjs/core/heap.d.cts +0 -24
  115. package/dist/types-cjs/core/index.d.cts +0 -13
  116. package/dist/types-cjs/core/invariants.d.cts +0 -59
  117. package/dist/types-cjs/core/lanes.d.cts +0 -54
  118. package/dist/types-cjs/core/optimistic.d.cts +0 -6
  119. package/dist/types-cjs/core/owner.d.cts +0 -124
  120. package/dist/types-cjs/core/scheduler.d.cts +0 -236
  121. package/dist/types-cjs/core/types.d.cts +0 -204
  122. package/dist/types-cjs/core/verdict.d.cts +0 -2
  123. package/dist/types-cjs/index.d.cts +0 -10
  124. package/dist/types-cjs/map.d.cts +0 -69
  125. package/dist/types-cjs/package.json +0 -3
  126. package/dist/types-cjs/store/index.d.cts +0 -18
  127. package/dist/types-cjs/store/next/optimistic.d.cts +0 -25
  128. package/dist/types-cjs/store/next/projection.d.cts +0 -8
  129. package/dist/types-cjs/store/next/reconcile.d.cts +0 -10
  130. package/dist/types-cjs/store/next/store.d.cts +0 -121
  131. package/dist/types-cjs/store/next/target.d.cts +0 -166
  132. package/dist/types-cjs/store/store.d.cts +0 -143
  133. package/dist/types-cjs/store/storePath.d.cts +0 -58
  134. package/dist/types-cjs/store/utils.d.cts +0 -74
@@ -0,0 +1,177 @@
1
+ import { setOrigin, globalQueue, activeTransition, currentTransition, schedule, actionStepDepth, flush, enterActionStep, exitActionStep } from "./scheduler.js";
2
+
3
+ import { isThenable } from "./async.js";
4
+
5
+ import "./core.js";
6
+
7
+ import "./dev.js";
8
+
9
+ import { attrHooks } from "./attribution-hooks.js";
10
+
11
+ /** Invocation order across all actions — the provenance every slice of an
12
+ * action runs under (scheduler `origin`): the flights and overrides its
13
+ * ambient windows issue are stamped with it, so a later action's override
14
+ * can tell this action's late answer from its own (#3331). */ let actionSeq = 0;
15
+
16
+ function restoreTransition(t, e, r) {
17
+ const n = setOrigin(t);
18
+ globalQueue.initTransition(e);
19
+ const i = r();
20
+ // A nested action resuming synchronously (its body yielded a non-thenable)
21
+ // runs this inside the OUTER action's slice: draining here would park the
22
+ // shared transaction and detach the outer body's remaining writes (the
23
+ // flush() rule, scheduler.ts). The outer step's own return drains.
24
+ if (actionStepDepth === 0) flush();
25
+ setOrigin(n);
26
+ return i;
27
+ }
28
+
29
+ /**
30
+ * The primitive for mutations: imperative async workflows whose *writes span
31
+ * an async gap* — optimistic write, server round-trip, reconciling write —
32
+ * where intermediate state must not leak and failure must revert cleanly
33
+ * (pair with `createOptimistic` / `createOptimisticStore`).
34
+ *
35
+ * Navigation-shaped updates do not need an action. A plain setter call is
36
+ * enough: reads pull the async, and downstream async computeds hold their
37
+ * previous values per-node until the new ones are ready (`isPending` /
38
+ * `latest` expose the in-flight state). Reach for `action` only when writes
39
+ * happen *after* async work, not merely upstream of it.
40
+ *
41
+ * Framework-level actions (router form actions, server actions) are
42
+ * specializations of this primitive: they are actions in exactly this sense —
43
+ * the same transactional semantics — with form binding, serialization, and
44
+ * submission tracking layered on top. The shared name is deliberate.
45
+ *
46
+ * Wraps a generator function so each invocation runs as a single transaction
47
+ * (a "transition") that batches every signal/store write between yields. The
48
+ * surrounding UI sees one atomic update per yielded step; nothing is committed
49
+ * until the action either completes or the next `yield` resolves.
50
+ *
51
+ * `yield` is the transaction-safe suspension point: the action waits for a
52
+ * yielded promise and re-enters the transaction before running the code after
53
+ * it. A plain `await` does NOT — the runtime has no hook into an async
54
+ * generator's internal await continuations, so code between an `await` and
55
+ * the next `yield` runs OUTSIDE the transaction: writes to fresh signals
56
+ * commit immediately, and anything that creates a reader there — `until()`,
57
+ * `latest()`, a memo or effect, a mount — is created mainline, where a read of
58
+ * this action's held state makes it born held (A29): staged with the
59
+ * transaction and replayed at its commit. For `until()` that commit is the
60
+ * settle its own promise holds open (#3482). `await` is still the ergonomic
61
+ * choice for typed results; just put a bare `yield` before any write or
62
+ * reader creation that follows it — including the expression of the next
63
+ * `yield`, which is evaluated before the step re-enters:
64
+ *
65
+ * ```ts
66
+ * const saved = await api.createTodo(text); // typed result
67
+ * yield; // re-enter the transaction before writing or reading
68
+ * setTodos(t => { ... });
69
+ * yield until(() => todos.some(t => t.id === saved.id));
70
+ * ```
71
+ *
72
+ * (For the same reason, don't call `flush()` inside an action body — it
73
+ * drains the transaction mid-step.)
74
+ *
75
+ * Each call returns a `Promise` that resolves with the generator's return
76
+ * value, or rejects if it throws. Pair with `createOptimistic` /
77
+ * `createOptimisticStore` to apply tentative writes that auto-revert if the
78
+ * action fails.
79
+ *
80
+ * @example
81
+ * ```ts
82
+ * const [todos, setTodos] = createOptimisticStore<Todo[]>([]);
83
+ *
84
+ * const addTodo = action(async function* (text: string) {
85
+ * const tempId = crypto.randomUUID();
86
+ * setTodos(t => { t.push({ id: tempId, text, pending: true }); }); // optimistic
87
+ * const saved = await api.createTodo(text); // network round-trip, typed
88
+ * yield; // re-enter the transaction
89
+ * setTodos(t => {
90
+ * const i = t.findIndex(x => x.id === tempId);
91
+ * if (i >= 0) t[i] = saved;
92
+ * });
93
+ * return saved;
94
+ * });
95
+ *
96
+ * await addTodo("buy milk");
97
+ * ```
98
+ */ function action(t) {
99
+ return (...e) => new Promise((r, n) => {
100
+ const i = t(...e);
101
+ const o = ++actionSeq;
102
+ // The first slice's window runs to the scheduled flush, which clears
103
+ // the provenance with the window — no restore here.
104
+ setOrigin(o);
105
+ globalQueue.initTransition();
106
+ let s = activeTransition;
107
+ s.dt.push(i);
108
+ s.Tt = true;
109
+ const done = (t, e, o = false) => {
110
+ s = currentTransition(s);
111
+ const u = s.dt.indexOf(i);
112
+ if (u >= 0) s.dt.splice(u, 1);
113
+ // Re-adopt through initTransition like every other resumption site:
114
+ // a bare setActiveTransition leaves globalQueue._batch as a detached
115
+ // ambient batch, and anything registered before the scheduled flush
116
+ // (held writes on a merging transition, optimistic overrides,
117
+ // affects() marks) lands there with nothing to ever finalize it.
118
+ globalQueue.initTransition(s);
119
+ schedule();
120
+ o ? n(e) : r(t);
121
+ };
122
+ const step = (e, r) => {
123
+ let n;
124
+ // Attribution hooks bracket the synchronous slice of generator body
125
+ // this step runs (up to the next yield): writes inside are the
126
+ // action's. Both sites sit outside the try (attribution-hooks.ts).
127
+ if (attrHooks !== null) attrHooks.actionStepStart(i, t.name || undefined);
128
+ // The body is on the stack between these brackets: flush() is
129
+ // refused inside (FLUSH_IN_ACTION, scheduler.ts).
130
+ enterActionStep();
131
+ try {
132
+ n = r ? i.throw(e) : i.next(e);
133
+ } catch (t) {
134
+ exitActionStep();
135
+ if (attrHooks !== null) attrHooks.actionStepEnd(i);
136
+ return done(undefined, t, true);
137
+ }
138
+ exitActionStep();
139
+ if (attrHooks !== null) attrHooks.actionStepEnd(i);
140
+ // A rejected iterator result (async generators) means the error already
141
+ // escaped the generator body — it is completed, and throwing back in
142
+ // would just reject again forever. Settle instead.
143
+ if (isThenable(n)) return void n.then(run, t => done(undefined, t, true));
144
+ run(n);
145
+ };
146
+ const run = t => {
147
+ if (t.done) return done(t.value);
148
+ // Thenable assimilation can itself throw synchronously (a `then`
149
+ // getter, or a `then()` method that throws — #2918). Match `await`
150
+ // semantics: the failure is thrown back into the generator at the
151
+ // yield point (catchable there); if uncaught, step()'s guard settles
152
+ // the action so its iterator never leaks in the transition. The
153
+ // settled flag implements A+ 2.3.3.3.4.1: a throw after the thenable
154
+ // already called a callback is ignored.
155
+ let e = false;
156
+ try {
157
+ if (isThenable(t.value)) return void t.value.then(t => {
158
+ if (e) return;
159
+ e = true;
160
+ restoreTransition(o, s, () => step(t));
161
+ }, t => {
162
+ if (e) return;
163
+ e = true;
164
+ restoreTransition(o, s, () => step(t, true));
165
+ });
166
+ } catch (t) {
167
+ if (e) return;
168
+ e = true;
169
+ return void restoreTransition(o, s, () => step(t, true));
170
+ }
171
+ restoreTransition(o, s, () => step(t.value));
172
+ };
173
+ step();
174
+ });
175
+ }
176
+
177
+ export { action };