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

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