@systemfsoftware/xstate 0.0.0-stage → 6.0.0-beta.65

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.
@@ -0,0 +1,258 @@
1
+ import { D as createSpawnEffect, K as setInertActorScopeSnapshot, S as beginSpawnAllocation, U as attachSnapshotActorRef, W as createInertActorScope, c as getProperAncestors, h as macrostep, it as isAtomicStateNode, j as finalizeTransitionResult, lt as getActorIdPrefix, p as initialMicrostep, rt as isRemoteActorRef, wt as createInitEvent, yt as hasAmbientInspector } from "./createActor-BGHd7i8Q.mjs";
2
+ // src/effectDescriptor.ts
3
+ /**
4
+ * Returns the serializable descriptor for an executable effect: the same
5
+ * discriminants (`kind`, `type`) with actor references replaced by logical
6
+ * addresses and actor sources by source keys. Payload fields pass through by
7
+ * reference.
8
+ *
9
+ * @experimental
10
+ */
11
+ function getEffectDescriptor(effect) {
12
+ if (effect.kind === "action") return {
13
+ kind: "action",
14
+ type: effect.type,
15
+ params: effect.params
16
+ };
17
+ if (effect.kind === "emit") return {
18
+ kind: "emit",
19
+ type: effect.type,
20
+ source: effect.source.address,
21
+ event: effect.event
22
+ };
23
+ switch (effect.type) {
24
+ case "@xstate.spawn": return {
25
+ kind: "builtin",
26
+ type: "@xstate.spawn",
27
+ source: effect.source?.address,
28
+ actor: effect.actor.address,
29
+ id: effect.id,
30
+ src: getActorIdPrefix(effect.src),
31
+ input: effect.input
32
+ };
33
+ case "@xstate.start": return {
34
+ kind: "builtin",
35
+ type: "@xstate.start",
36
+ source: effect.source?.address,
37
+ actor: effect.actor.address,
38
+ id: effect.id
39
+ };
40
+ case "@xstate.raise": return {
41
+ kind: "builtin",
42
+ type: "@xstate.raise",
43
+ source: effect.source.address,
44
+ event: effect.event,
45
+ id: effect.id,
46
+ delay: effect.delay
47
+ };
48
+ case "@xstate.sendTo": return {
49
+ kind: "builtin",
50
+ type: "@xstate.sendTo",
51
+ source: effect.source.address,
52
+ target: effect.target?.address,
53
+ incarnation: isRemoteActorRef(effect.target) ? effect.target.sessionId : void 0,
54
+ event: effect.event,
55
+ id: effect.id,
56
+ delay: effect.delay
57
+ };
58
+ case "@xstate.cancel": return {
59
+ kind: "builtin",
60
+ type: "@xstate.cancel",
61
+ source: effect.source.address,
62
+ id: effect.id
63
+ };
64
+ case "@xstate.stop": return {
65
+ kind: "builtin",
66
+ type: "@xstate.stop",
67
+ source: effect.source.address,
68
+ actor: effect.actor.address,
69
+ id: effect.id
70
+ };
71
+ case "@xstate.terminate": return {
72
+ kind: "builtin",
73
+ type: "@xstate.terminate",
74
+ source: effect.source.address,
75
+ actor: effect.actor.address,
76
+ id: effect.id,
77
+ status: effect.status,
78
+ output: effect.output,
79
+ error: effect.error
80
+ };
81
+ case "@xstate.deadLetter": return {
82
+ kind: "builtin",
83
+ type: "@xstate.deadLetter",
84
+ source: effect.source?.address,
85
+ target: effect.target?.address,
86
+ event: effect.event,
87
+ reason: effect.reason,
88
+ issues: effect.detail?.issues,
89
+ error: effect.detail?.error
90
+ };
91
+ }
92
+ }
93
+ // src/transition.ts
94
+ function attachMicrostepActorRefs(microsteps, actorScope, inputSnapshot) {
95
+ const result = microsteps.map(([snapshot, actions, transitions]) => [
96
+ snapshot,
97
+ actions,
98
+ transitions ?? []
99
+ ]);
100
+ if (!result.length) return result;
101
+ const finalSnapshot = result.at(-1)[0];
102
+ setInertActorScopeSnapshot(actorScope, finalSnapshot, false);
103
+ if (finalSnapshot !== inputSnapshot) attachSnapshotActorRef(actorScope, finalSnapshot);
104
+ for (const [snapshot] of result) if (snapshot !== inputSnapshot && snapshot !== finalSnapshot) {
105
+ const snapshotScope = createInertActorScope(snapshot.machine, snapshot, void 0, actorScope);
106
+ attachSnapshotActorRef(snapshotScope, snapshot);
107
+ }
108
+ return result;
109
+ }
110
+ /**
111
+ * Given actor `logic`, a `snapshot`, and an `event`, returns a tuple of the
112
+ * `nextSnapshot` and `actions` to execute.
113
+ *
114
+ * This is a pure function that does not execute `actions`.
115
+ *
116
+ * @public
117
+ */
118
+ function transition(logic, snapshot, event) {
119
+ const actorScope = createInertActorScope(logic, snapshot);
120
+ setInertActorScopeSnapshot(actorScope, snapshot, false);
121
+ const [nextSnapshot, effects] = finalizeTransitionResult(actorScope, snapshot, logic.transition(snapshot, event, actorScope));
122
+ setInertActorScopeSnapshot(actorScope, nextSnapshot, false);
123
+ const returnedSnapshot = nextSnapshot === snapshot ? nextSnapshot : attachSnapshotActorRef(actorScope, nextSnapshot);
124
+ inspectPureTransition(actorScope, returnedSnapshot, event);
125
+ return [returnedSnapshot, effects];
126
+ }
127
+ /**
128
+ * Returns `true` when `result` (from {@link transition}) means no transition
129
+ * handled the event: the snapshot is the same object as `previousSnapshot`
130
+ * and there are no effects. A handled event always yields a new snapshot
131
+ * object, even when nothing in it changed.
132
+ *
133
+ * @example
134
+ *
135
+ * ```ts
136
+ * const result = transition(machine, snapshot, event);
137
+ * if (isUnhandled(snapshot, result)) {
138
+ * console.warn(`Unhandled event: ${event.type}`);
139
+ * }
140
+ * ```
141
+ *
142
+ * @public
143
+ */
144
+ function isUnhandled(previousSnapshot, result) {
145
+ return result[0] === previousSnapshot && result[1].length === 0;
146
+ }
147
+ /**
148
+ * Given actor `logic` and optional `input`, returns a tuple of the
149
+ * `nextSnapshot` and `actions` to execute from the initial transition (no
150
+ * previous state).
151
+ *
152
+ * This is a pure function that does not execute `actions`.
153
+ *
154
+ * @public
155
+ */
156
+ function initialTransition(logic, ...[input]) {
157
+ const actorScope = createInertActorScope(logic);
158
+ const [nextSnapshot, executableActions] = finalizeTransitionResult(actorScope, void 0, logic.initialTransition(input, actorScope));
159
+ setInertActorScopeSnapshot(actorScope, nextSnapshot, false);
160
+ const returnedSnapshot = attachSnapshotActorRef(actorScope, nextSnapshot);
161
+ inspectPureTransition(actorScope, returnedSnapshot, createInitEvent(input));
162
+ return [returnedSnapshot, executableActions];
163
+ }
164
+ /**
165
+ * Emits the `@xstate.transition` inspection event for a snapshot produced by
166
+ * the pure transition path, where no live actor loop does it. Free unless an
167
+ * inspector is ambiently installed (a durable execution created with
168
+ * `inspect`): only then is the snapshot's actor ref materialized to emit.
169
+ */
170
+ function inspectPureTransition(actorScope, snapshot, event) {
171
+ if (!hasAmbientInspector()) return;
172
+ const self = actorScope.self;
173
+ if (self?.system._hasInspectionObservers?.()) self._inspectTransition(snapshot, event);
174
+ }
175
+ /**
176
+ * Given a state `machine`, a `snapshot`, and an `event`, returns an array of
177
+ * microsteps, where each microstep is a tuple of
178
+ * `[snapshot, actions, transitions]`. `transitions` are the transitions taken
179
+ * in that microstep,
180
+ * including eventless transitions and transitions for raised events; it is
181
+ * empty for microsteps that take no transition (for example, a stop or timer
182
+ * microstep).
183
+ *
184
+ * This is a pure function that does not execute `actions`.
185
+ *
186
+ * @public
187
+ */
188
+ function getMicrosteps(machine, snapshot, event) {
189
+ const actorScope = createInertActorScope(machine, snapshot);
190
+ beginSpawnAllocation(actorScope);
191
+ const { microsteps } = macrostep(snapshot, event, actorScope, []);
192
+ return attachMicrostepActorRefs(microsteps, actorScope, snapshot);
193
+ }
194
+ /**
195
+ * Given a state `machine` and optional `input`, returns an array of microsteps
196
+ * from the initial transition, where each microstep is a tuple of
197
+ * `[snapshot, actions, transitions]`. `transitions` are the transitions taken
198
+ * in that microstep (see {@link getMicrosteps}); it is empty for the first
199
+ * microstep, which enters the initial states.
200
+ *
201
+ * This is a pure function that does not execute `actions`.
202
+ *
203
+ * @public
204
+ */
205
+ function getInitialMicrosteps(machine, ...[input]) {
206
+ const actorScope = createInertActorScope(machine);
207
+ beginSpawnAllocation(actorScope);
208
+ const initEvent = createInitEvent(input);
209
+ const internalQueue = [];
210
+ const preInitialSnapshot = machine._getPreInitialState(actorScope, initEvent);
211
+ const contextSpawnEffects = Object.values(preInitialSnapshot.children).filter(Boolean).map((actor) => createSpawnEffect(actor));
212
+ const first = initialMicrostep(machine.root, preInitialSnapshot, actorScope, initEvent, internalQueue);
213
+ const { microsteps } = macrostep(first[0], initEvent, actorScope, internalQueue, [[
214
+ first[0],
215
+ [...contextSpawnEffects, ...first[1]],
216
+ []
217
+ ]]);
218
+ return attachMicrostepActorRefs(microsteps, actorScope);
219
+ }
220
+ /**
221
+ * Gets all potential next transitions from the current state.
222
+ *
223
+ * Returns all transitions that are available from the current state, including:
224
+ *
225
+ * - All transitions from atomic states (leaf states in the current state
226
+ * configuration)
227
+ * - All transitions from ancestor states (parent states that may handle events)
228
+ * - All guarded transitions (regardless of whether their guards would pass)
229
+ * - Always (eventless) transitions
230
+ * - After (delayed) transitions
231
+ *
232
+ * The order of transitions is deterministic:
233
+ *
234
+ * 1. Atomic states are processed in document order
235
+ * 2. For each atomic state, transitions are collected from the state itself first,
236
+ * then its ancestors
237
+ * 3. Within each state node, transitions are in the order they appear in the state
238
+ * definition
239
+ *
240
+ * @param state - The current machine snapshot
241
+ * @returns Array of transition definitions from the current state, in
242
+ * deterministic order
243
+ * @public
244
+ */
245
+ function getNextTransitions(state) {
246
+ if (state.status !== "active") return [];
247
+ const potentialTransitions = [];
248
+ const atomicStates = state.nodes.filter(isAtomicStateNode);
249
+ const visited = /* @__PURE__ */ new Set();
250
+ for (const stateNode of atomicStates) for (const s of [stateNode].concat(getProperAncestors(stateNode, void 0))) {
251
+ if (visited.has(s.id)) continue;
252
+ visited.add(s.id);
253
+ for (const [, transitions] of s.transitions.entries()) potentialTransitions.push(...transitions);
254
+ if (s.always) potentialTransitions.push(...s.always);
255
+ }
256
+ return potentialTransitions;
257
+ }
258
+ export { isUnhandled as a, initialTransition as i, getMicrosteps as n, transition as o, getNextTransitions as r, getEffectDescriptor as s, getInitialMicrosteps as t };