@solidjs/signals 2.0.0-beta.9 → 2.0.0-rc.1
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.
- package/README.md +14 -10
- package/dist/dev.js +6740 -2011
- package/dist/node.cjs +7927 -3340
- package/dist/prod/affects.js +126 -0
- package/dist/prod/boundaries.js +572 -0
- package/dist/prod/core/action.js +139 -0
- package/dist/prod/core/async.js +607 -0
- package/dist/prod/core/constants.js +92 -0
- package/dist/prod/core/context.js +67 -0
- package/dist/prod/core/core.js +828 -0
- package/dist/prod/core/dev.js +3 -0
- package/dist/prod/core/effect.js +145 -0
- package/dist/prod/core/error.js +68 -0
- package/dist/prod/core/external.js +98 -0
- package/dist/prod/core/graph.js +104 -0
- package/dist/prod/core/heap.js +140 -0
- package/dist/prod/core/invariants.js +42 -0
- package/dist/prod/core/lanes.js +140 -0
- package/dist/prod/core/optimistic.js +262 -0
- package/dist/prod/core/owner.js +302 -0
- package/dist/prod/core/scheduler.js +757 -0
- package/dist/prod/core/verdict.js +369 -0
- package/dist/prod/index.js +45 -0
- package/dist/prod/map.js +319 -0
- package/dist/prod/signals.js +394 -0
- package/dist/prod/store/index.js +36 -0
- package/dist/prod/store/next/optimistic.js +377 -0
- package/dist/prod/store/next/projection.js +172 -0
- package/dist/prod/store/next/reconcile.js +327 -0
- package/dist/prod/store/next/store.js +1232 -0
- package/dist/prod/store/next/target.js +20 -0
- package/dist/prod/store/store.js +325 -0
- package/dist/prod/store/storePath.js +103 -0
- package/dist/prod/store/utils.js +201 -0
- package/dist/types/affects.d.ts +47 -0
- package/dist/types/boundaries.d.ts +60 -13
- package/dist/types/core/action.d.ts +35 -6
- package/dist/types/core/async.d.ts +16 -1
- package/dist/types/core/constants.d.ts +35 -6
- package/dist/types/core/context.d.ts +10 -2
- package/dist/types/core/core.d.ts +66 -63
- package/dist/types/core/dev.d.ts +17 -2
- package/dist/types/core/effect.d.ts +1 -2
- package/dist/types/core/error.d.ts +33 -0
- package/dist/types/core/external.d.ts +0 -11
- package/dist/types/core/graph.d.ts +2 -1
- package/dist/types/core/heap.d.ts +8 -0
- package/dist/types/core/index.d.ts +3 -2
- package/dist/types/core/invariants.d.ts +59 -0
- package/dist/types/core/lanes.d.ts +2 -0
- package/dist/types/core/optimistic.d.ts +6 -0
- package/dist/types/core/owner.d.ts +50 -3
- package/dist/types/core/scheduler.d.ts +85 -11
- package/dist/types/core/types.d.ts +66 -1
- package/dist/types/core/verdict.d.ts +2 -0
- package/dist/types/index.d.ts +3 -2
- package/dist/types/map.d.ts +21 -5
- package/dist/types/signals.d.ts +183 -12
- package/dist/types/store/index.d.ts +16 -6
- package/dist/types/store/next/optimistic.d.ts +20 -0
- package/dist/types/store/next/projection.d.ts +24 -0
- package/dist/types/store/next/reconcile.d.ts +3 -0
- package/dist/types/store/next/store.d.ts +71 -0
- package/dist/types/store/next/target.d.ts +99 -0
- package/dist/types/store/optimistic.d.ts +3 -3
- package/dist/types/store/projection.d.ts +10 -6
- package/dist/types/store/reconcile.d.ts +31 -8
- package/dist/types/store/store.d.ts +91 -71
- package/dist/types/store/utils.d.ts +0 -40
- package/dist/types-cjs/affects.d.cts +47 -0
- package/dist/types-cjs/boundaries.d.cts +60 -13
- package/dist/types-cjs/core/action.d.cts +35 -6
- package/dist/types-cjs/core/async.d.cts +16 -1
- package/dist/types-cjs/core/constants.d.cts +35 -6
- package/dist/types-cjs/core/context.d.cts +10 -2
- package/dist/types-cjs/core/core.d.cts +66 -63
- package/dist/types-cjs/core/dev.d.cts +17 -2
- package/dist/types-cjs/core/effect.d.cts +1 -2
- package/dist/types-cjs/core/error.d.cts +33 -0
- package/dist/types-cjs/core/external.d.cts +0 -11
- package/dist/types-cjs/core/graph.d.cts +2 -1
- package/dist/types-cjs/core/heap.d.cts +8 -0
- package/dist/types-cjs/core/index.d.cts +3 -2
- package/dist/types-cjs/core/invariants.d.cts +59 -0
- package/dist/types-cjs/core/lanes.d.cts +2 -0
- package/dist/types-cjs/core/optimistic.d.cts +6 -0
- package/dist/types-cjs/core/owner.d.cts +50 -3
- package/dist/types-cjs/core/scheduler.d.cts +85 -11
- package/dist/types-cjs/core/types.d.cts +66 -1
- package/dist/types-cjs/core/verdict.d.cts +2 -0
- package/dist/types-cjs/index.d.cts +3 -2
- package/dist/types-cjs/map.d.cts +21 -5
- package/dist/types-cjs/signals.d.cts +183 -12
- package/dist/types-cjs/store/index.d.cts +16 -6
- package/dist/types-cjs/store/next/optimistic.d.cts +20 -0
- package/dist/types-cjs/store/next/projection.d.cts +24 -0
- package/dist/types-cjs/store/next/reconcile.d.cts +3 -0
- package/dist/types-cjs/store/next/store.d.cts +71 -0
- package/dist/types-cjs/store/next/target.d.cts +99 -0
- package/dist/types-cjs/store/optimistic.d.cts +3 -3
- package/dist/types-cjs/store/projection.d.cts +10 -6
- package/dist/types-cjs/store/reconcile.d.cts +31 -8
- package/dist/types-cjs/store/store.d.cts +91 -71
- package/dist/types-cjs/store/utils.d.cts +0 -40
- package/package.json +12 -9
- package/dist/prod.js +0 -3627
|
@@ -0,0 +1,139 @@
|
|
|
1
|
+
import { globalQueue, activeTransition, currentTransition, schedule, flush } from "./scheduler.js";
|
|
2
|
+
|
|
3
|
+
import { isThenable } from "./async.js";
|
|
4
|
+
|
|
5
|
+
import "./core.js";
|
|
6
|
+
|
|
7
|
+
function restoreTransition(e, r) {
|
|
8
|
+
globalQueue.initTransition(e);
|
|
9
|
+
const t = r();
|
|
10
|
+
flush();
|
|
11
|
+
return t;
|
|
12
|
+
}
|
|
13
|
+
|
|
14
|
+
/**
|
|
15
|
+
* The primitive for mutations: imperative async workflows whose *writes span
|
|
16
|
+
* an async gap* — optimistic write, server round-trip, reconciling write —
|
|
17
|
+
* where intermediate state must not leak and failure must revert cleanly
|
|
18
|
+
* (pair with `createOptimistic` / `createOptimisticStore`).
|
|
19
|
+
*
|
|
20
|
+
* Navigation-shaped updates do not need an action. A plain setter call is
|
|
21
|
+
* enough: reads pull the async, and downstream async computeds hold their
|
|
22
|
+
* previous values per-node until the new ones are ready (`isPending` /
|
|
23
|
+
* `latest` expose the in-flight state). Reach for `action` only when writes
|
|
24
|
+
* happen *after* async work, not merely upstream of it.
|
|
25
|
+
*
|
|
26
|
+
* Framework-level actions (router form actions, server actions) are
|
|
27
|
+
* specializations of this primitive: they are actions in exactly this sense —
|
|
28
|
+
* the same transactional semantics — with form binding, serialization, and
|
|
29
|
+
* submission tracking layered on top. The shared name is deliberate.
|
|
30
|
+
*
|
|
31
|
+
* Wraps a generator function so each invocation runs as a single transaction
|
|
32
|
+
* (a "transition") that batches every signal/store write between yields. The
|
|
33
|
+
* surrounding UI sees one atomic update per yielded step; nothing is committed
|
|
34
|
+
* until the action either completes or the next `yield` resolves.
|
|
35
|
+
*
|
|
36
|
+
* `yield` is the transaction-safe suspension point: the action waits for a
|
|
37
|
+
* yielded promise and re-enters the transaction before running the code after
|
|
38
|
+
* it. A plain `await` does NOT — the runtime has no hook into an async
|
|
39
|
+
* generator's internal await continuations, so writes to fresh signals
|
|
40
|
+
* between an `await` and the next `yield` escape the transaction and commit
|
|
41
|
+
* immediately. `await` is still the ergonomic choice for typed results; just
|
|
42
|
+
* put a bare `yield` before any writes that follow it:
|
|
43
|
+
*
|
|
44
|
+
* ```ts
|
|
45
|
+
* const saved = await api.createTodo(text); // typed result
|
|
46
|
+
* yield; // re-enter the transaction before writing
|
|
47
|
+
* setTodos(t => { ... });
|
|
48
|
+
* ```
|
|
49
|
+
*
|
|
50
|
+
* (For the same reason, don't call `flush()` inside an action body — it
|
|
51
|
+
* drains the transaction mid-step.)
|
|
52
|
+
*
|
|
53
|
+
* Each call returns a `Promise` that resolves with the generator's return
|
|
54
|
+
* value, or rejects if it throws. Pair with `createOptimistic` /
|
|
55
|
+
* `createOptimisticStore` to apply tentative writes that auto-revert if the
|
|
56
|
+
* action fails.
|
|
57
|
+
*
|
|
58
|
+
* @example
|
|
59
|
+
* ```ts
|
|
60
|
+
* const [todos, setTodos] = createOptimisticStore<Todo[]>([]);
|
|
61
|
+
*
|
|
62
|
+
* const addTodo = action(async function* (text: string) {
|
|
63
|
+
* const tempId = crypto.randomUUID();
|
|
64
|
+
* setTodos(t => { t.push({ id: tempId, text, pending: true }); }); // optimistic
|
|
65
|
+
* const saved = await api.createTodo(text); // network round-trip, typed
|
|
66
|
+
* yield; // re-enter the transaction
|
|
67
|
+
* setTodos(t => {
|
|
68
|
+
* const i = t.findIndex(x => x.id === tempId);
|
|
69
|
+
* if (i >= 0) t[i] = saved;
|
|
70
|
+
* });
|
|
71
|
+
* return saved;
|
|
72
|
+
* });
|
|
73
|
+
*
|
|
74
|
+
* await addTodo("buy milk");
|
|
75
|
+
* ```
|
|
76
|
+
*/ function action(e) {
|
|
77
|
+
return (...r) => new Promise((t, n) => {
|
|
78
|
+
const i = e(...r);
|
|
79
|
+
globalQueue.initTransition();
|
|
80
|
+
let o = activeTransition;
|
|
81
|
+
o.ie.push(i);
|
|
82
|
+
const done = (e, r, u = false) => {
|
|
83
|
+
o = currentTransition(o);
|
|
84
|
+
const s = o.ie.indexOf(i);
|
|
85
|
+
if (s >= 0) o.ie.splice(s, 1);
|
|
86
|
+
// Re-adopt through initTransition like every other resumption site:
|
|
87
|
+
// a bare setActiveTransition leaves globalQueue._batch as a detached
|
|
88
|
+
// ambient batch, and anything registered before the scheduled flush
|
|
89
|
+
// (held writes on a merging transition, optimistic overrides,
|
|
90
|
+
// affects() marks) lands there with nothing to ever finalize it.
|
|
91
|
+
globalQueue.initTransition(o);
|
|
92
|
+
schedule();
|
|
93
|
+
u ? n(r) : t(e);
|
|
94
|
+
};
|
|
95
|
+
const step = (e, r) => {
|
|
96
|
+
let t;
|
|
97
|
+
try {
|
|
98
|
+
t = r ? i.throw(e) : i.next(e);
|
|
99
|
+
} catch (e) {
|
|
100
|
+
return done(undefined, e, true);
|
|
101
|
+
}
|
|
102
|
+
// A rejected iterator result (async generators) means the error already
|
|
103
|
+
// escaped the generator body — it is completed, and throwing back in
|
|
104
|
+
// would just reject again forever. Settle instead.
|
|
105
|
+
if (isThenable(t)) return void t.then(run, e => done(undefined, e, true));
|
|
106
|
+
run(t);
|
|
107
|
+
};
|
|
108
|
+
const run = e => {
|
|
109
|
+
if (e.done) return done(e.value);
|
|
110
|
+
// Thenable assimilation can itself throw synchronously (a `then`
|
|
111
|
+
// getter, or a `then()` method that throws — #2918). Match `await`
|
|
112
|
+
// semantics: the failure is thrown back into the generator at the
|
|
113
|
+
// yield point (catchable there); if uncaught, step()'s guard settles
|
|
114
|
+
// the action so its iterator never leaks in the transition. The
|
|
115
|
+
// settled flag implements A+ 2.3.3.3.4.1: a throw after the thenable
|
|
116
|
+
// already called a callback is ignored.
|
|
117
|
+
let r = false;
|
|
118
|
+
try {
|
|
119
|
+
if (isThenable(e.value)) return void e.value.then(e => {
|
|
120
|
+
if (r) return;
|
|
121
|
+
r = true;
|
|
122
|
+
restoreTransition(o, () => step(e));
|
|
123
|
+
}, e => {
|
|
124
|
+
if (r) return;
|
|
125
|
+
r = true;
|
|
126
|
+
restoreTransition(o, () => step(e, true));
|
|
127
|
+
});
|
|
128
|
+
} catch (e) {
|
|
129
|
+
if (r) return;
|
|
130
|
+
r = true;
|
|
131
|
+
return void restoreTransition(o, () => step(e, true));
|
|
132
|
+
}
|
|
133
|
+
restoreTransition(o, () => step(e.value));
|
|
134
|
+
};
|
|
135
|
+
step();
|
|
136
|
+
});
|
|
137
|
+
}
|
|
138
|
+
|
|
139
|
+
export { action };
|