@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.
- package/dist/dev-shared.js +6357 -0
- package/dist/dev.attribution.js +2485 -0
- package/dist/dev.js +2851 -7027
- package/dist/observe/affects.js +129 -0
- package/dist/observe/attribution.js +7 -0
- package/dist/observe/boundaries.js +641 -0
- package/dist/observe/core/action.js +177 -0
- package/dist/observe/core/async.js +846 -0
- package/dist/observe/core/attribution-costs.js +66 -0
- package/dist/observe/core/attribution-feedback.js +282 -0
- package/dist/observe/core/attribution-hooks.js +82 -0
- package/dist/observe/core/attribution-queries.js +28 -0
- package/dist/observe/core/attribution.js +2095 -0
- package/dist/observe/core/constants.js +248 -0
- package/dist/{types-cjs/core/context.d.cts → observe/core/context.js} +37 -12
- package/dist/observe/core/core.js +1789 -0
- package/dist/observe/core/dev.js +293 -0
- package/dist/observe/core/effect.js +195 -0
- package/dist/observe/core/error-hooks.js +71 -0
- package/dist/observe/core/error.js +80 -0
- package/dist/observe/core/external.js +98 -0
- package/dist/observe/core/graph.js +155 -0
- package/dist/observe/core/heap.js +147 -0
- package/dist/observe/core/invariants.js +45 -0
- package/dist/observe/core/lanes.js +205 -0
- package/dist/observe/core/optimistic.js +585 -0
- package/dist/observe/core/owner.js +322 -0
- package/dist/observe/core/scheduler.js +1428 -0
- package/dist/observe/core/verdict.js +669 -0
- package/dist/observe/index.js +59 -0
- package/dist/observe/map.js +484 -0
- package/dist/{types-cjs/signals.d.cts → observe/signals.js} +311 -317
- package/dist/observe/store/index.js +40 -0
- package/dist/observe/store/next/optimistic.js +660 -0
- package/dist/observe/store/next/projection.js +255 -0
- package/dist/observe/store/next/reconcile.js +375 -0
- package/dist/observe/store/next/store.js +2327 -0
- package/dist/observe/store/next/target.js +51 -0
- package/dist/observe/store/store.js +325 -0
- package/dist/observe/store/storePath.js +103 -0
- package/dist/observe/store/utils.js +1023 -0
- package/dist/prod/attribution.js +41 -0
- package/dist/prod/boundaries.js +128 -76
- package/dist/prod/core/action.js +65 -37
- package/dist/prod/core/async.js +324 -172
- package/dist/prod/core/constants.js +57 -1
- package/dist/prod/core/context.js +3 -3
- package/dist/prod/core/core.js +1003 -364
- package/dist/prod/core/dev.js +17 -1
- package/dist/prod/core/effect.js +76 -42
- package/dist/prod/core/error-hooks.js +71 -0
- package/dist/prod/core/external.js +4 -4
- package/dist/prod/core/graph.js +37 -37
- package/dist/prod/core/heap.js +61 -56
- package/dist/prod/core/lanes.js +107 -63
- package/dist/prod/core/optimistic.js +374 -93
- package/dist/prod/core/owner.js +62 -46
- package/dist/prod/core/scheduler.js +653 -286
- package/dist/prod/core/verdict.js +245 -127
- package/dist/prod/index.js +15 -5
- package/dist/prod/map.js +292 -141
- package/dist/prod/signals.js +29 -16
- package/dist/prod/store/next/optimistic.js +77 -55
- package/dist/prod/store/next/projection.js +31 -20
- package/dist/prod/store/next/reconcile.js +87 -84
- package/dist/prod/store/next/store.js +718 -401
- package/dist/prod/store/next/target.js +32 -10
- package/dist/prod/store/store.js +12 -14
- package/dist/prod/store/utils.js +950 -130
- package/dist/types/attribution.d.ts +20 -0
- package/dist/types/attribution.prod.d.ts +22 -0
- package/dist/types/boundaries.d.ts +10 -1
- package/dist/types/core/action.d.ts +12 -5
- package/dist/types/core/async.d.ts +1 -1
- package/dist/types/core/attribution-costs.d.ts +35 -0
- package/dist/types/core/attribution-feedback.d.ts +133 -0
- package/dist/types/core/attribution-hooks.d.ts +147 -9
- package/dist/types/core/attribution-queries.d.ts +10 -0
- package/dist/types/core/attribution.d.ts +216 -182
- package/dist/types/core/constants.d.ts +56 -0
- package/dist/types/core/core.d.ts +190 -2
- package/dist/types/core/dev.d.ts +246 -28
- package/dist/types/core/effect.d.ts +8 -1
- package/dist/types/core/error-hooks.d.ts +71 -0
- package/dist/types/core/index.d.ts +4 -1
- package/dist/types/core/invariants.d.ts +4 -0
- package/dist/types/core/lanes.d.ts +39 -5
- package/dist/types/core/scheduler.d.ts +153 -0
- package/dist/types/core/types.d.ts +32 -9
- package/dist/types/index.d.ts +10 -3
- package/dist/types/map.d.ts +2 -0
- package/dist/types/signals.d.ts +8 -0
- package/dist/types/store/index.d.ts +2 -0
- package/dist/types/store/next/optimistic.d.ts +1 -1
- package/dist/types/store/next/store.d.ts +11 -5
- package/dist/types/store/next/target.d.ts +37 -10
- package/dist/types/store/utils.d.ts +178 -0
- package/package.json +21 -17
- package/dist/node.cjs +0 -10541
- package/dist/node.dev.cjs +0 -13724
- package/dist/types-cjs/affects.d.cts +0 -47
- package/dist/types-cjs/boundaries.d.cts +0 -175
- package/dist/types-cjs/core/action.d.cts +0 -64
- package/dist/types-cjs/core/async.d.cts +0 -23
- package/dist/types-cjs/core/attribution-hooks.d.cts +0 -127
- package/dist/types-cjs/core/attribution.d.cts +0 -495
- package/dist/types-cjs/core/constants.d.cts +0 -159
- package/dist/types-cjs/core/core.d.cts +0 -185
- package/dist/types-cjs/core/dev.d.cts +0 -136
- package/dist/types-cjs/core/effect.d.cts +0 -30
- package/dist/types-cjs/core/error.d.cts +0 -56
- package/dist/types-cjs/core/external.d.cts +0 -15
- package/dist/types-cjs/core/graph.d.cts +0 -28
- package/dist/types-cjs/core/heap.d.cts +0 -24
- package/dist/types-cjs/core/index.d.cts +0 -13
- package/dist/types-cjs/core/invariants.d.cts +0 -59
- package/dist/types-cjs/core/lanes.d.cts +0 -54
- package/dist/types-cjs/core/optimistic.d.cts +0 -6
- package/dist/types-cjs/core/owner.d.cts +0 -124
- package/dist/types-cjs/core/scheduler.d.cts +0 -236
- package/dist/types-cjs/core/types.d.cts +0 -204
- package/dist/types-cjs/core/verdict.d.cts +0 -2
- package/dist/types-cjs/index.d.cts +0 -10
- package/dist/types-cjs/map.d.cts +0 -69
- package/dist/types-cjs/package.json +0 -3
- package/dist/types-cjs/store/index.d.cts +0 -18
- package/dist/types-cjs/store/next/optimistic.d.cts +0 -25
- package/dist/types-cjs/store/next/projection.d.cts +0 -8
- package/dist/types-cjs/store/next/reconcile.d.cts +0 -10
- package/dist/types-cjs/store/next/store.d.cts +0 -121
- package/dist/types-cjs/store/next/target.d.cts +0 -166
- package/dist/types-cjs/store/store.d.cts +0 -143
- package/dist/types-cjs/store/storePath.d.cts +0 -58
- 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 };
|