xstate 6.0.0-alpha.47 → 6.0.0-alpha.49
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 +30 -1
- package/dist/{StateMachine-7046f677.cjs.js → StateMachine-0adb3a70.cjs.js} +15 -12
- package/dist/{StateMachine-70c06bdd.development.cjs.js → StateMachine-29450e6d.development.cjs.js} +15 -12
- package/dist/{StateMachine-74929087.esm.js → StateMachine-2af31c11.esm.js} +10 -7
- package/dist/{StateMachine-ee10f67e.development.esm.js → StateMachine-faf50c5c.development.esm.js} +10 -7
- package/dist/{createActor-915ea40c.esm.js → createActor-268165d4.esm.js} +79 -23
- package/dist/{createActor-ff132afa.development.esm.js → createActor-88709f74.development.esm.js} +79 -23
- package/dist/{createActor-6736cbbe.development.cjs.js → createActor-a1e0dffb.development.cjs.js} +78 -25
- package/dist/{createActor-bfe8b6bd.cjs.js → createActor-b4dd05ae.cjs.js} +78 -25
- package/dist/declarations/src/createMachineFromConfig.d.ts +5 -77
- package/dist/declarations/src/fsm/createFSMActor.d.ts +67 -0
- package/dist/declarations/src/fsm/index.d.ts +2 -0
- package/dist/declarations/src/fsm.d.ts +5 -4
- package/dist/declarations/src/scxml/index.d.ts +1 -0
- package/dist/declarations/src/scxml/runtime.d.ts +251 -0
- package/dist/declarations/src/scxml/scxml.d.ts +19 -0
- package/dist/declarations/src/types.d.ts +1 -0
- package/dist/{effectDescriptor-8be60443.esm.js → effectDescriptor-30c9a744.esm.js} +1 -1
- package/dist/{effectDescriptor-fbe67d5a.development.esm.js → effectDescriptor-39d22100.development.esm.js} +1 -1
- package/dist/{effectDescriptor-3c699328.development.cjs.js → effectDescriptor-7ff6802f.development.cjs.js} +1 -1
- package/dist/{effectDescriptor-a7e2d4d1.cjs.js → effectDescriptor-be348e50.cjs.js} +1 -1
- package/dist/fsm-7a2e9697.cjs.js +777 -0
- package/dist/fsm-b804b3e9.esm.js +775 -0
- package/dist/fsm-c1316948.development.cjs.js +777 -0
- package/dist/fsm-e18a7cb4.development.esm.js +775 -0
- package/dist/types-3c3455f7.esm.js +185 -0
- package/dist/types-adda3842.development.esm.js +185 -0
- package/dist/types-b3fea5bd.development.cjs.js +189 -0
- package/dist/types-fbabaeee.cjs.js +189 -0
- package/dist/validation-05f1d517.esm.js +8 -0
- package/dist/validation-4561b43c.cjs.js +10 -0
- package/dist/validation-e69470ad.development.esm.js +8 -0
- package/dist/validation-f2714a35.development.cjs.js +10 -0
- package/dist/xstate-actors.cjs.js +934 -9
- package/dist/xstate-actors.development.cjs.js +934 -9
- package/dist/xstate-actors.development.esm.js +932 -2
- package/dist/xstate-actors.esm.js +932 -2
- package/dist/xstate-durable.cjs.js +2 -2
- package/dist/xstate-durable.development.cjs.js +2 -2
- package/dist/xstate-durable.development.esm.js +2 -2
- package/dist/xstate-durable.esm.js +2 -2
- package/dist/xstate-fsm.cjs.d.mts +2 -0
- package/dist/xstate-fsm.cjs.d.ts +2 -0
- package/dist/xstate-fsm.cjs.js +409 -0
- package/dist/xstate-fsm.cjs.mjs +5 -0
- package/dist/xstate-fsm.development.cjs.js +409 -0
- package/dist/xstate-fsm.development.cjs.mjs +5 -0
- package/dist/xstate-fsm.development.esm.js +403 -0
- package/dist/xstate-fsm.esm.js +403 -0
- package/dist/xstate-fsm.umd.min.js +2 -0
- package/dist/xstate-fsm.umd.min.js.map +1 -0
- package/dist/xstate-graph.cjs.js +4 -3
- package/dist/xstate-graph.development.cjs.js +4 -3
- package/dist/xstate-graph.development.esm.js +4 -3
- package/dist/xstate-graph.esm.js +4 -3
- package/dist/xstate-graph.umd.min.js +1 -1
- package/dist/xstate-graph.umd.min.js.map +1 -1
- package/dist/xstate-scxml.cjs.d.mts +2 -0
- package/dist/xstate-scxml.cjs.d.ts +2 -0
- package/dist/xstate-scxml.cjs.js +2387 -0
- package/dist/xstate-scxml.cjs.mjs +3 -0
- package/dist/xstate-scxml.development.cjs.js +2387 -0
- package/dist/xstate-scxml.development.cjs.mjs +3 -0
- package/dist/xstate-scxml.development.esm.js +2383 -0
- package/dist/xstate-scxml.esm.js +2383 -0
- package/dist/xstate-scxml.umd.min.js +26 -0
- package/dist/xstate-scxml.umd.min.js.map +1 -0
- package/dist/xstate-validation.cjs.js +1 -1
- package/dist/xstate-validation.development.cjs.js +1 -1
- package/dist/xstate-validation.development.esm.js +1 -1
- package/dist/xstate-validation.esm.js +1 -1
- package/dist/xstate.cjs.js +143 -1412
- package/dist/xstate.development.cjs.js +143 -1412
- package/dist/xstate.development.esm.js +143 -1411
- package/dist/xstate.esm.js +143 -1411
- package/dist/xstate.umd.min.js +1 -1
- package/dist/xstate.umd.min.js.map +1 -1
- package/fsm/package.json +8 -0
- package/package.json +37 -3
- package/scxml/package.json +8 -0
- package/dist/index-0f498ef2.development.cjs.js +0 -946
- package/dist/index-70d56425.development.esm.js +0 -937
- package/dist/index-b051c924.esm.js +0 -937
- package/dist/index-b3fe59bc.cjs.js +0 -946
|
@@ -1,9 +1,13 @@
|
|
|
1
|
-
export {
|
|
2
|
-
import { m as matchesEventDescriptor, t as toArray
|
|
3
|
-
export { A as Actor,
|
|
4
|
-
import {
|
|
5
|
-
export { S as
|
|
6
|
-
export { c as
|
|
1
|
+
export { TimeoutError, createAsyncLogic, createCallbackLogic, createEmptyActor, createEventObservableLogic, createLogic, createObservableLogic } from './xstate-actors.development.esm.js';
|
|
2
|
+
import { m as matchesEventDescriptor, t as toArray, p as parseDelayToMilliseconds, i as isAtomicStateNode, c as createActor } from './createActor-88709f74.development.esm.js';
|
|
3
|
+
export { A as Actor, h as __unsafe_getAllOwnEventDescriptors, k as checkStateIn, c as createActor, a as createListenerLogic, b as createSubscriptionLogic, u as deliverEvent, q as executeEffects, g as getInitialSnapshot, d as getNextSnapshot, f as getStateNodes, r as isBuiltInExecutableAction, e as isMachineSnapshot, l as listenerLogic, j as matchesState, n as pathToStateValue, v as runStep, w as stopActor, s as subscriptionLogic, x as terminateActor, o as toObserver } from './createActor-88709f74.development.esm.js';
|
|
4
|
+
import { c as createMachine } from './types-adda3842.development.esm.js';
|
|
5
|
+
export { S as SpecialTargets, c as createMachine, a as createStateConfig } from './types-adda3842.development.esm.js';
|
|
6
|
+
export { c as createFSM } from './fsm-e18a7cb4.development.esm.js';
|
|
7
|
+
import { S as StateMachine } from './StateMachine-faf50c5c.development.esm.js';
|
|
8
|
+
export { S as StateMachine, a as StateNode } from './StateMachine-faf50c5c.development.esm.js';
|
|
9
|
+
export { c as getEffectDescriptor, a as getInitialMicrosteps, g as getMicrosteps, b as getNextTransitions, i as initialTransition, t as transition } from './effectDescriptor-39d22100.development.esm.js';
|
|
10
|
+
import './validation-e69470ad.development.esm.js';
|
|
7
11
|
|
|
8
12
|
/**
|
|
9
13
|
* Asserts that the given event object is of the specified type or types. Throws
|
|
@@ -29,7 +33,7 @@ export { c as getEffectDescriptor, a as getInitialMicrosteps, g as getMicrosteps
|
|
|
29
33
|
* ```
|
|
30
34
|
*/
|
|
31
35
|
function assertEvent(event, type) {
|
|
32
|
-
const types = toArray
|
|
36
|
+
const types = toArray(type);
|
|
33
37
|
const matches = types.some(descriptor => matchesEventDescriptor(event.type, descriptor));
|
|
34
38
|
if (!matches) {
|
|
35
39
|
const typesText = types.length === 1 ? `type matching "${types[0]}"` : `one of types matching "${types.join('", "')}"`;
|
|
@@ -37,453 +41,11 @@ function assertEvent(event, type) {
|
|
|
37
41
|
}
|
|
38
42
|
}
|
|
39
43
|
|
|
40
|
-
/**
|
|
41
|
-
* Creates a state machine (statechart) with the given configuration.
|
|
42
|
-
*
|
|
43
|
-
* The state machine represents the pure logic of a state machine actor.
|
|
44
|
-
*
|
|
45
|
-
* @example
|
|
46
|
-
*
|
|
47
|
-
* ```ts
|
|
48
|
-
* import { createMachine } from 'xstate';
|
|
49
|
-
*
|
|
50
|
-
* const lightMachine = createMachine({
|
|
51
|
-
* id: 'light',
|
|
52
|
-
* initial: 'green',
|
|
53
|
-
* states: {
|
|
54
|
-
* green: {
|
|
55
|
-
* on: {
|
|
56
|
-
* TIMER: { target: 'yellow' }
|
|
57
|
-
* }
|
|
58
|
-
* },
|
|
59
|
-
* yellow: {
|
|
60
|
-
* on: {
|
|
61
|
-
* TIMER: { target: 'red' }
|
|
62
|
-
* }
|
|
63
|
-
* },
|
|
64
|
-
* red: {
|
|
65
|
-
* on: {
|
|
66
|
-
* TIMER: { target: 'green' }
|
|
67
|
-
* }
|
|
68
|
-
* }
|
|
69
|
-
* }
|
|
70
|
-
* });
|
|
71
|
-
*
|
|
72
|
-
* const lightActor = createActor(lightMachine);
|
|
73
|
-
* lightActor.start();
|
|
74
|
-
*
|
|
75
|
-
* lightActor.send({ type: 'TIMER' });
|
|
76
|
-
* ```
|
|
77
|
-
*
|
|
78
|
-
* @param config The state machine configuration.
|
|
79
|
-
* @param options DEPRECATED: use `setup({ ... })` or `machine.provide({ ... })`
|
|
80
|
-
* to provide machine sources instead.
|
|
81
|
-
*/
|
|
82
|
-
// Overload 1: With schemas.context — context type inferred from schema
|
|
83
|
-
|
|
84
|
-
// Overload 2: Without schemas.context — context type inferred from config.context
|
|
85
|
-
|
|
86
|
-
// Implementation
|
|
87
|
-
function createMachine(config) {
|
|
88
|
-
return new StateMachine(config);
|
|
89
|
-
}
|
|
90
|
-
function createStateConfig(config) {
|
|
91
|
-
return config;
|
|
92
|
-
}
|
|
93
|
-
|
|
94
|
-
const emptySources = {
|
|
95
|
-
actions: {},
|
|
96
|
-
actors: {},
|
|
97
|
-
guards: {},
|
|
98
|
-
delays: {}
|
|
99
|
-
};
|
|
100
|
-
const emptyExecutableActions = [];
|
|
101
|
-
const emptyRawActions = [];
|
|
102
|
-
const builtInActionSet = new Set(Object.values(builtInActions));
|
|
103
|
-
function toArray(value) {
|
|
104
|
-
return value === undefined ? [] : Array.isArray(value) ? value : [value];
|
|
105
|
-
}
|
|
106
|
-
function resolveContext(context, input) {
|
|
107
|
-
return typeof context === 'function' ? context({
|
|
108
|
-
input
|
|
109
|
-
}) : context ?? {};
|
|
110
|
-
}
|
|
111
|
-
function resolveTransitionContext(context, args) {
|
|
112
|
-
return typeof context === 'function' ? context(args) : context;
|
|
113
|
-
}
|
|
114
|
-
function resolveInput(input, context, event) {
|
|
115
|
-
return typeof input === 'function' ? input({
|
|
116
|
-
context,
|
|
117
|
-
event
|
|
118
|
-
}) : input;
|
|
119
|
-
}
|
|
120
|
-
function mergeContextPatch(context, patch) {
|
|
121
|
-
for (const key of Object.keys(patch)) {
|
|
122
|
-
if (!Object.prototype.hasOwnProperty.call(context, key) || !Object.is(context[key], patch[key])) {
|
|
123
|
-
return {
|
|
124
|
-
...context,
|
|
125
|
-
...patch
|
|
126
|
-
};
|
|
127
|
-
}
|
|
128
|
-
}
|
|
129
|
-
return context;
|
|
130
|
-
}
|
|
131
|
-
function createSnapshot(value, context, input, machine, stateInput) {
|
|
132
|
-
return {
|
|
133
|
-
status: 'active',
|
|
134
|
-
output: undefined,
|
|
135
|
-
error: undefined,
|
|
136
|
-
value,
|
|
137
|
-
context,
|
|
138
|
-
input,
|
|
139
|
-
children: {},
|
|
140
|
-
timers: {},
|
|
141
|
-
_nextTimerId: 0,
|
|
142
|
-
_stateInput: stateInput,
|
|
143
|
-
machine
|
|
144
|
-
};
|
|
145
|
-
}
|
|
146
|
-
function cloneSnapshot(snapshot, value, context, stateInput) {
|
|
147
|
-
return {
|
|
148
|
-
status: snapshot.status,
|
|
149
|
-
output: snapshot.output,
|
|
150
|
-
error: snapshot.error,
|
|
151
|
-
value,
|
|
152
|
-
context,
|
|
153
|
-
input: snapshot.input,
|
|
154
|
-
children: snapshot.children,
|
|
155
|
-
timers: snapshot.timers,
|
|
156
|
-
_nextTimerId: snapshot._nextTimerId,
|
|
157
|
-
// Carried across state changes: dropping these would let a later spawn
|
|
158
|
-
// reuse the id of a still-running child.
|
|
159
|
-
_nextActorIds: snapshot._nextActorIds,
|
|
160
|
-
_stateInput: stateInput,
|
|
161
|
-
machine: snapshot.machine
|
|
162
|
-
};
|
|
163
|
-
}
|
|
164
|
-
function stopSnapshot(snapshot) {
|
|
165
|
-
return {
|
|
166
|
-
status: 'stopped',
|
|
167
|
-
output: undefined,
|
|
168
|
-
error: undefined,
|
|
169
|
-
value: snapshot.value,
|
|
170
|
-
context: snapshot.context,
|
|
171
|
-
input: undefined,
|
|
172
|
-
children: snapshot.children,
|
|
173
|
-
timers: snapshot.timers,
|
|
174
|
-
_nextTimerId: snapshot._nextTimerId,
|
|
175
|
-
_nextActorIds: snapshot._nextActorIds,
|
|
176
|
-
_stateInput: snapshot._stateInput,
|
|
177
|
-
machine: snapshot.machine
|
|
178
|
-
};
|
|
179
|
-
}
|
|
180
|
-
function assertNoStringTransitions(config) {
|
|
181
|
-
for (const [stateKey, stateConfig] of Object.entries(config.states)) {
|
|
182
|
-
for (const [eventType, transitionConfig] of Object.entries(stateConfig.on ?? {})) {
|
|
183
|
-
for (const transition of toArray(transitionConfig)) {
|
|
184
|
-
if (typeof transition === 'string') {
|
|
185
|
-
const target = transition;
|
|
186
|
-
throw new Error(`Invalid transition for "${stateKey}.${eventType}": use { target: "${target}" } instead of a string target.`);
|
|
187
|
-
}
|
|
188
|
-
}
|
|
189
|
-
}
|
|
190
|
-
}
|
|
191
|
-
}
|
|
192
|
-
function resolveSimpleEnqueuedActions(rawActions) {
|
|
193
|
-
const executableActions = [];
|
|
194
|
-
for (const action of rawActions) {
|
|
195
|
-
if (!action || typeof action !== 'object' || !('action' in action) || typeof action.action !== 'function' || builtInActionSet.has(action.action) || '_special' in action.action) {
|
|
196
|
-
return undefined;
|
|
197
|
-
}
|
|
198
|
-
executableActions.push({
|
|
199
|
-
kind: 'action',
|
|
200
|
-
type: action.action.name || '(anonymous)',
|
|
201
|
-
params: undefined,
|
|
202
|
-
args: action.args,
|
|
203
|
-
action: action.action,
|
|
204
|
-
exec() {
|
|
205
|
-
return this.action?.(...this.args);
|
|
206
|
-
}
|
|
207
|
-
});
|
|
208
|
-
}
|
|
209
|
-
return executableActions;
|
|
210
|
-
}
|
|
211
|
-
function createFSM(config) {
|
|
212
|
-
const machine = {
|
|
213
|
-
id: config.id ?? '(fsm)',
|
|
214
|
-
sources: emptySources
|
|
215
|
-
};
|
|
216
|
-
assertNoStringTransitions(config);
|
|
217
|
-
const runActions = (snapshot, event, actorScope, rawActions) => {
|
|
218
|
-
if (!rawActions?.length) {
|
|
219
|
-
return [snapshot, emptyExecutableActions];
|
|
220
|
-
}
|
|
221
|
-
const simpleExecutableActions = resolveSimpleEnqueuedActions(rawActions);
|
|
222
|
-
if (simpleExecutableActions) {
|
|
223
|
-
return [snapshot, simpleExecutableActions];
|
|
224
|
-
}
|
|
225
|
-
return resolveActionsWithContext(snapshot, event, actorScope, rawActions);
|
|
226
|
-
};
|
|
227
|
-
const runStateActions = (snapshot, event, actorScope, actionsConfig, stateInput, internalQueue) => {
|
|
228
|
-
if (!actionsConfig) {
|
|
229
|
-
return [snapshot, emptyExecutableActions];
|
|
230
|
-
}
|
|
231
|
-
const actions = [];
|
|
232
|
-
const enq = createTransitionEnqueue(actorScope, actions, internalQueue, true);
|
|
233
|
-
let context;
|
|
234
|
-
const actionCount = Array.isArray(actionsConfig) ? actionsConfig.length : 1;
|
|
235
|
-
for (let i = 0; i < actionCount; i++) {
|
|
236
|
-
const action = Array.isArray(actionsConfig) ? actionsConfig[i] : actionsConfig;
|
|
237
|
-
const result = action(withActorScope({
|
|
238
|
-
context: context ?? snapshot.context,
|
|
239
|
-
event: event,
|
|
240
|
-
input: stateInput,
|
|
241
|
-
value: snapshot.value,
|
|
242
|
-
children: snapshot.children
|
|
243
|
-
}, actorScope), enq);
|
|
244
|
-
if (result?.context !== undefined) {
|
|
245
|
-
const currentContext = context ?? snapshot.context;
|
|
246
|
-
const nextContext = mergeContextPatch(currentContext, result.context);
|
|
247
|
-
if (nextContext !== currentContext) {
|
|
248
|
-
context = nextContext;
|
|
249
|
-
}
|
|
250
|
-
}
|
|
251
|
-
}
|
|
252
|
-
const nextSnapshot = context !== undefined ? cloneSnapshot(snapshot, snapshot.value, context, snapshot._stateInput) : snapshot;
|
|
253
|
-
return runActions(nextSnapshot, event, actorScope, actions);
|
|
254
|
-
};
|
|
255
|
-
const selectTransition = (snapshot, event, actorScope, internalQueue) => {
|
|
256
|
-
const state = config.states[snapshot.value];
|
|
257
|
-
const transitionsConfig = state?.on?.[event.type];
|
|
258
|
-
if (!transitionsConfig) {
|
|
259
|
-
return undefined;
|
|
260
|
-
}
|
|
261
|
-
const transitionCount = Array.isArray(transitionsConfig) ? transitionsConfig.length : 1;
|
|
262
|
-
for (let i = 0; i < transitionCount; i++) {
|
|
263
|
-
const transition = Array.isArray(transitionsConfig) ? transitionsConfig[i] : transitionsConfig;
|
|
264
|
-
const args = withActorScope({
|
|
265
|
-
context: snapshot.context,
|
|
266
|
-
event,
|
|
267
|
-
input: snapshot.input,
|
|
268
|
-
value: snapshot.value,
|
|
269
|
-
children: snapshot.children
|
|
270
|
-
}, actorScope);
|
|
271
|
-
if (typeof transition === 'function') {
|
|
272
|
-
const actions = [];
|
|
273
|
-
const enq = createTransitionEnqueue(actorScope, actions, internalQueue, true);
|
|
274
|
-
const result = transition(args, enq);
|
|
275
|
-
if (!result) {
|
|
276
|
-
if (actions.length) {
|
|
277
|
-
return {
|
|
278
|
-
actions
|
|
279
|
-
};
|
|
280
|
-
}
|
|
281
|
-
continue;
|
|
282
|
-
}
|
|
283
|
-
return {
|
|
284
|
-
target: result.target,
|
|
285
|
-
context: result.context,
|
|
286
|
-
input: result.input,
|
|
287
|
-
actions
|
|
288
|
-
};
|
|
289
|
-
}
|
|
290
|
-
if ('guard' in transition && transition.guard && !transition.guard(args)) {
|
|
291
|
-
continue;
|
|
292
|
-
}
|
|
293
|
-
return {
|
|
294
|
-
target: transition.target,
|
|
295
|
-
context: resolveTransitionContext(transition.context, args),
|
|
296
|
-
input: transition.input,
|
|
297
|
-
actions: 'actions' in transition && transition.actions ? toArray(transition.actions) : emptyRawActions
|
|
298
|
-
};
|
|
299
|
-
}
|
|
300
|
-
return undefined;
|
|
301
|
-
};
|
|
302
|
-
const transitionCore = (snapshot, event, actorScope) => {
|
|
303
|
-
if (snapshot.status !== 'active') {
|
|
304
|
-
return [snapshot, []];
|
|
305
|
-
}
|
|
306
|
-
if (event.type === XSTATE_STOP) {
|
|
307
|
-
const actions = [];
|
|
308
|
-
const enqueue = createTransitionEnqueue(actorScope, actions, []);
|
|
309
|
-
for (const id of Object.keys(snapshot.timers)) {
|
|
310
|
-
enqueue.cancel(id);
|
|
311
|
-
}
|
|
312
|
-
const [withoutTimers, cancelEffects] = resolveActionsWithContext(snapshot, event, actorScope, actions);
|
|
313
|
-
return [stopSnapshot(withoutTimers), cancelEffects];
|
|
314
|
-
}
|
|
315
|
-
if (event.type === XSTATE_TIMER) {
|
|
316
|
-
const timer = snapshot.timers[event.id];
|
|
317
|
-
if (!timer) {
|
|
318
|
-
return [snapshot, emptyExecutableActions];
|
|
319
|
-
}
|
|
320
|
-
const timers = {
|
|
321
|
-
...snapshot.timers
|
|
322
|
-
};
|
|
323
|
-
delete timers[timer.id];
|
|
324
|
-
const nextSnapshot = {
|
|
325
|
-
...snapshot,
|
|
326
|
-
timers
|
|
327
|
-
};
|
|
328
|
-
if (timer.type === '@xstate.raise') {
|
|
329
|
-
return transitionCore(nextSnapshot, timer.event, actorScope);
|
|
330
|
-
}
|
|
331
|
-
const target = timer.target === 'self' ? actorScope.self : timer.target;
|
|
332
|
-
return [nextSnapshot, [createSendToEffect(actorScope, target, timer.event)]];
|
|
333
|
-
}
|
|
334
|
-
const stateConfig = config.states[snapshot.value];
|
|
335
|
-
const directTransition = stateConfig?.on?.[event.type];
|
|
336
|
-
if (!directTransition) {
|
|
337
|
-
return [snapshot, emptyExecutableActions];
|
|
338
|
-
}
|
|
339
|
-
if (!Array.isArray(directTransition) && typeof directTransition !== 'function' && !('guard' in directTransition) && !('actions' in directTransition && directTransition.actions) && typeof directTransition.input !== 'function') {
|
|
340
|
-
const target = directTransition.target ?? snapshot.value;
|
|
341
|
-
const stateChanged = target !== snapshot.value;
|
|
342
|
-
if (stateChanged && (stateConfig.exit || config.states[target]?.entry)) ; else {
|
|
343
|
-
const hasContext = directTransition.context !== undefined;
|
|
344
|
-
const hasInput = directTransition.input !== undefined;
|
|
345
|
-
const resolvedContext = !isLazyActorScope(actorScope) ? resolveTransitionContext(directTransition.context, {
|
|
346
|
-
context: snapshot.context,
|
|
347
|
-
event,
|
|
348
|
-
input: snapshot.input,
|
|
349
|
-
value: snapshot.value,
|
|
350
|
-
self: actorScope.self,
|
|
351
|
-
system: actorScope.system,
|
|
352
|
-
parent: actorScope.self._parent,
|
|
353
|
-
children: snapshot.children
|
|
354
|
-
}) : typeof directTransition.context === 'function' ? directTransition.context(withActorScope({
|
|
355
|
-
context: snapshot.context,
|
|
356
|
-
event,
|
|
357
|
-
input: snapshot.input,
|
|
358
|
-
value: snapshot.value,
|
|
359
|
-
children: snapshot.children
|
|
360
|
-
}, actorScope)) : directTransition.context;
|
|
361
|
-
const context = hasContext && resolvedContext ? mergeContextPatch(snapshot.context, resolvedContext) : snapshot.context;
|
|
362
|
-
if (!stateChanged && context === snapshot.context && !hasInput && snapshot._stateInput === undefined) {
|
|
363
|
-
return [snapshot, emptyExecutableActions];
|
|
364
|
-
}
|
|
365
|
-
return [cloneSnapshot(snapshot, target, context, hasInput ? resolveInput(directTransition.input, context, event) : undefined), emptyExecutableActions];
|
|
366
|
-
}
|
|
367
|
-
}
|
|
368
|
-
if (typeof directTransition === 'function' && directTransition.length < 2 && !stateConfig?.exit) {
|
|
369
|
-
const result = directTransition(withActorScope({
|
|
370
|
-
context: snapshot.context,
|
|
371
|
-
event,
|
|
372
|
-
input: snapshot.input,
|
|
373
|
-
value: snapshot.value,
|
|
374
|
-
children: snapshot.children
|
|
375
|
-
}, actorScope), undefined);
|
|
376
|
-
if (result) {
|
|
377
|
-
const target = result.target ?? snapshot.value;
|
|
378
|
-
if (!config.states[target]?.entry) {
|
|
379
|
-
const hasContext = result.context !== undefined;
|
|
380
|
-
const hasInput = result.input !== undefined;
|
|
381
|
-
const context = hasContext && result.context ? mergeContextPatch(snapshot.context, result.context) : snapshot.context;
|
|
382
|
-
if (target === snapshot.value && context === snapshot.context && !hasInput && snapshot._stateInput === undefined) {
|
|
383
|
-
return [snapshot, emptyExecutableActions];
|
|
384
|
-
}
|
|
385
|
-
return [cloneSnapshot(snapshot, target, context, hasInput ? resolveInput(result.input, context, event) : undefined), emptyExecutableActions];
|
|
386
|
-
}
|
|
387
|
-
}
|
|
388
|
-
}
|
|
389
|
-
let nextSnapshot = snapshot;
|
|
390
|
-
const executableActions = [];
|
|
391
|
-
const internalQueue = [event];
|
|
392
|
-
let iterations = 0;
|
|
393
|
-
while (internalQueue.length) {
|
|
394
|
-
if (++iterations > 1000) {
|
|
395
|
-
throw new Error('FSM microstep count exceeded 1000');
|
|
396
|
-
}
|
|
397
|
-
const nextEvent = internalQueue.shift();
|
|
398
|
-
const selected = selectTransition(nextSnapshot, nextEvent, actorScope, internalQueue);
|
|
399
|
-
if (!selected) {
|
|
400
|
-
continue;
|
|
401
|
-
}
|
|
402
|
-
const nextValue = selected.target ?? nextSnapshot.value;
|
|
403
|
-
const stateChanged = nextValue !== nextSnapshot.value;
|
|
404
|
-
if (stateChanged) {
|
|
405
|
-
const [exited, exitActions] = runStateActions(nextSnapshot, nextEvent, actorScope, config.states[nextSnapshot.value]?.exit, nextSnapshot._stateInput, internalQueue);
|
|
406
|
-
nextSnapshot = exited;
|
|
407
|
-
executableActions.push(...exitActions);
|
|
408
|
-
}
|
|
409
|
-
let context = nextSnapshot.context;
|
|
410
|
-
if (selected.context !== undefined) {
|
|
411
|
-
context = mergeContextPatch(context, selected.context);
|
|
412
|
-
}
|
|
413
|
-
const hasInput = selected.input !== undefined;
|
|
414
|
-
const stateInput = hasInput ? resolveInput(selected.input, context, nextEvent) : undefined;
|
|
415
|
-
if (stateChanged || context !== nextSnapshot.context || hasInput || nextSnapshot._stateInput !== undefined) {
|
|
416
|
-
nextSnapshot = cloneSnapshot(nextSnapshot, nextValue, context, stateInput);
|
|
417
|
-
}
|
|
418
|
-
const [afterTransition, transitionActions] = runActions(nextSnapshot, nextEvent, actorScope, selected.actions);
|
|
419
|
-
nextSnapshot = afterTransition;
|
|
420
|
-
executableActions.push(...transitionActions);
|
|
421
|
-
if (stateChanged) {
|
|
422
|
-
const [entered, entryActions] = runStateActions(nextSnapshot, nextEvent, actorScope, config.states[nextValue]?.entry, stateInput, internalQueue);
|
|
423
|
-
nextSnapshot = entered;
|
|
424
|
-
executableActions.push(...entryActions);
|
|
425
|
-
}
|
|
426
|
-
}
|
|
427
|
-
return [nextSnapshot, executableActions];
|
|
428
|
-
};
|
|
429
|
-
const transition = (...args) => {
|
|
430
|
-
beginSpawnAllocation(args[2]);
|
|
431
|
-
const [nextSnapshot, effects] = transitionCore(...args);
|
|
432
|
-
return finalizeTransitionResult(args[2], args[0], [nextSnapshot, [...effects, ...deriveDeferredStarts(effects)]]);
|
|
433
|
-
};
|
|
434
|
-
const logic = {
|
|
435
|
-
id: config.id,
|
|
436
|
-
config,
|
|
437
|
-
transition,
|
|
438
|
-
initialTransition: (input, actorScope) => {
|
|
439
|
-
beginSpawnAllocation(actorScope);
|
|
440
|
-
const context = resolveContext(config.context, input);
|
|
441
|
-
const snapshot = createSnapshot(config.initial, context, input, machine);
|
|
442
|
-
const internalQueue = [];
|
|
443
|
-
let [nextSnapshot, actions] = runStateActions(snapshot, {
|
|
444
|
-
type: XSTATE_INIT
|
|
445
|
-
}, actorScope, config.states[config.initial]?.entry, undefined, internalQueue);
|
|
446
|
-
if (!actions.length) {
|
|
447
|
-
actions = [];
|
|
448
|
-
}
|
|
449
|
-
while (internalQueue.length) {
|
|
450
|
-
const [raisedSnapshot, raisedActions] = transitionCore(nextSnapshot, internalQueue.shift(), actorScope);
|
|
451
|
-
nextSnapshot = raisedSnapshot;
|
|
452
|
-
actions.push(...raisedActions);
|
|
453
|
-
}
|
|
454
|
-
return finalizeTransitionResult(actorScope, undefined, [nextSnapshot, [...actions, ...deriveDeferredStarts(actions)]]);
|
|
455
|
-
},
|
|
456
|
-
getInitialSnapshot: (actorScope, input) => logic.initialTransition(input, actorScope)[0],
|
|
457
|
-
getPersistedSnapshot: ({
|
|
458
|
-
machine: _,
|
|
459
|
-
...snapshot
|
|
460
|
-
}) => snapshot,
|
|
461
|
-
restoreSnapshot: snapshot => ({
|
|
462
|
-
...snapshot,
|
|
463
|
-
machine: machine
|
|
464
|
-
})
|
|
465
|
-
};
|
|
466
|
-
return logic;
|
|
467
|
-
}
|
|
468
|
-
|
|
469
44
|
function delayToMs(delay) {
|
|
470
45
|
const parsedDelay = parseDelayToMilliseconds(delay);
|
|
471
46
|
if (parsedDelay !== undefined) return parsedDelay;
|
|
472
47
|
return typeof delay === 'string' ? parseFloat(delay) || 0 : delay;
|
|
473
48
|
}
|
|
474
|
-
function normalizeScxmlEventType(eventType) {
|
|
475
|
-
return /^error(\.|$)/.test(eventType) ? `xstate.${eventType}` : eventType;
|
|
476
|
-
}
|
|
477
|
-
function toScxmlEventName(eventType) {
|
|
478
|
-
return eventType.startsWith('xstate.error.') ? eventType.slice('xstate.'.length) : eventType;
|
|
479
|
-
}
|
|
480
|
-
|
|
481
|
-
/**
|
|
482
|
-
* Isolated executable-content block. Errors in nested actions stop this block
|
|
483
|
-
* but do not propagate to the surrounding action list. Used to model SCXML's
|
|
484
|
-
* separate <onentry>/<onexit> blocks: each is its own block per spec.
|
|
485
|
-
*/
|
|
486
|
-
|
|
487
49
|
function isExpression(value) {
|
|
488
50
|
return !!value && typeof value === 'object' && typeof value['@expr'] === 'string';
|
|
489
51
|
}
|
|
@@ -496,9 +58,6 @@ function isResolvable(value) {
|
|
|
496
58
|
function isBuiltInActionType(type) {
|
|
497
59
|
return type.startsWith('@xstate.');
|
|
498
60
|
}
|
|
499
|
-
function isScxmlActionType(type) {
|
|
500
|
-
return type.startsWith('scxml.');
|
|
501
|
-
}
|
|
502
61
|
function toPath(parent, key) {
|
|
503
62
|
return typeof key === 'number' ? `${parent}[${key}]` : `${parent}.${key}`;
|
|
504
63
|
}
|
|
@@ -639,7 +198,7 @@ function assertMachineJSON(json, resolvedSources, expressionResolver) {
|
|
|
639
198
|
assertCondition(json.guards[condition.type].when, `$.guards.${condition.type}.when`);
|
|
640
199
|
return;
|
|
641
200
|
}
|
|
642
|
-
if (!resolvedSources.guards[condition.type] && !['
|
|
201
|
+
if (!resolvedSources.guards[condition.type] && !['xstate.stateIn', 'xstate.not'].includes(condition.type)) {
|
|
643
202
|
throw new Error(`Missing guard source "${condition.type}"`);
|
|
644
203
|
}
|
|
645
204
|
}
|
|
@@ -652,7 +211,7 @@ function assertMachineJSON(json, resolvedSources, expressionResolver) {
|
|
|
652
211
|
throw new Error(`Invalid action at ${path}`);
|
|
653
212
|
}
|
|
654
213
|
assertResolvable(action.params, `${path}.params`);
|
|
655
|
-
if (isBuiltInActionType(action.type)
|
|
214
|
+
if (isBuiltInActionType(action.type)) {
|
|
656
215
|
assertResolvable(action, path);
|
|
657
216
|
return;
|
|
658
217
|
}
|
|
@@ -718,8 +277,7 @@ function assertMachineJSON(json, resolvedSources, expressionResolver) {
|
|
|
718
277
|
const invokes = Array.isArray(node.invoke) ? node.invoke : [node.invoke];
|
|
719
278
|
invokes.forEach((invoke, index) => {
|
|
720
279
|
const invokePath = `${path}.invoke${Array.isArray(node.invoke) ? `[${index}]` : ''}`;
|
|
721
|
-
|
|
722
|
-
if (!extInv._nestedMachineJSON && !resolvedSources.actors[invoke.src]) {
|
|
280
|
+
if (!resolvedSources.actors[invoke.src]) {
|
|
723
281
|
throw new Error(`Missing actor source "${invoke.src}"`);
|
|
724
282
|
}
|
|
725
283
|
assertResolvable(invoke.input, `${invokePath}.input`);
|
|
@@ -771,78 +329,6 @@ function assertMachineJSON(json, resolvedSources, expressionResolver) {
|
|
|
771
329
|
}
|
|
772
330
|
assertStateNode(json, '$');
|
|
773
331
|
}
|
|
774
|
-
let _scxmlSessionId = 'session_scxml';
|
|
775
|
-
let _scxmlMachineName = '';
|
|
776
|
-
|
|
777
|
-
/** Evaluates an SCXML expression with context variables available via `with`. */
|
|
778
|
-
function evaluateExpr(context, expr, event, self) {
|
|
779
|
-
const fnBody = `
|
|
780
|
-
with (context) {
|
|
781
|
-
return (${expr});
|
|
782
|
-
}
|
|
783
|
-
`.trim();
|
|
784
|
-
// eslint-disable-next-line @typescript-eslint/no-implied-eval
|
|
785
|
-
const fn = new Function('context', '_event', '_sessionid', '_name', '_ioprocessors', 'In', fnBody);
|
|
786
|
-
const In = stateId => {
|
|
787
|
-
if (!self) return false;
|
|
788
|
-
try {
|
|
789
|
-
const snap = self.getSnapshot?.();
|
|
790
|
-
if (snap?.nodes) {
|
|
791
|
-
const sanitized = stateId.replace(/\./g, '$');
|
|
792
|
-
return snap.nodes.some(node => node.id === sanitized || node.id.endsWith('.' + sanitized));
|
|
793
|
-
}
|
|
794
|
-
} catch {
|
|
795
|
-
// ignore
|
|
796
|
-
}
|
|
797
|
-
return false;
|
|
798
|
-
};
|
|
799
|
-
const SCXML_ORIGIN = `#_scxml_${_scxmlSessionId}`;
|
|
800
|
-
const SCXML_ORIGIN_TYPE = 'http://www.w3.org/TR/scxml/#SCXMLEventProcessor';
|
|
801
|
-
const isExternal = event && event._scxmlExternal;
|
|
802
|
-
const isInitEvent = event && event.type === '@xstate.init';
|
|
803
|
-
// Per SCXML spec, _event has these fields. Fields that don't apply to a
|
|
804
|
-
// particular event are present with value `undefined` (so `'name' in _event`
|
|
805
|
-
// is true but `typeof _event.name === 'undefined'` for unset fields).
|
|
806
|
-
// For xstate.done.* events, _event.data is the `output` payload (matches
|
|
807
|
-
// SCXML's done event semantics where data is the donedata).
|
|
808
|
-
const isDoneEvent = event && typeof event.type === 'string' && event.type.startsWith('xstate.done.');
|
|
809
|
-
const explicitType = event && event._scxmlEventType;
|
|
810
|
-
const scxmlEvent = event && !isInitEvent ? {
|
|
811
|
-
name: event._scxmlEventName ?? toScxmlEventName(event.type),
|
|
812
|
-
type: explicitType || (isExternal ? 'external' : 'internal'),
|
|
813
|
-
sendid: event._scxmlSendId,
|
|
814
|
-
origin: isExternal ? SCXML_ORIGIN : undefined,
|
|
815
|
-
origintype: isExternal ? SCXML_ORIGIN_TYPE : undefined,
|
|
816
|
-
invokeid: event._scxmlInvokeId,
|
|
817
|
-
data: isDoneEvent ? event.output : event._scxmlEventData !== undefined ? event._scxmlEventData : event
|
|
818
|
-
} : undefined;
|
|
819
|
-
const result = fn(context, scxmlEvent, _scxmlSessionId, _scxmlMachineName, {
|
|
820
|
-
scxml: {
|
|
821
|
-
location: `#_scxml_${_scxmlSessionId}`
|
|
822
|
-
}
|
|
823
|
-
}, In);
|
|
824
|
-
return result;
|
|
825
|
-
}
|
|
826
|
-
|
|
827
|
-
/** Executes an SCXML script block and returns updated context values. */
|
|
828
|
-
function executeScript(context, code) {
|
|
829
|
-
// Create a proxy to track which properties are modified
|
|
830
|
-
const updates = {};
|
|
831
|
-
const contextKeys = Object.keys(context);
|
|
832
|
-
|
|
833
|
-
// Build variable declarations and reassignment capture
|
|
834
|
-
const varDeclarations = contextKeys.map(k => `let ${k} = context.${k};`).join('\n');
|
|
835
|
-
const captureUpdates = contextKeys.map(k => `updates.${k} = ${k};`).join('\n');
|
|
836
|
-
const fnBody = `
|
|
837
|
-
${varDeclarations}
|
|
838
|
-
${code}
|
|
839
|
-
${captureUpdates}
|
|
840
|
-
return updates;
|
|
841
|
-
`;
|
|
842
|
-
// eslint-disable-next-line @typescript-eslint/no-implied-eval
|
|
843
|
-
const fn = new Function('context', 'updates', fnBody);
|
|
844
|
-
return fn(context, updates);
|
|
845
|
-
}
|
|
846
332
|
function createMachineFromConfig(json, sources = {}) {
|
|
847
333
|
const resolvedSources = mergeSources(json, sources);
|
|
848
334
|
const expressionResolver = createExpressionResolver(json['@exprLang'], resolvedSources);
|
|
@@ -853,9 +339,7 @@ function createMachineFromConfig(json, sources = {}) {
|
|
|
853
339
|
getDurationConfig
|
|
854
340
|
} = expressionResolver;
|
|
855
341
|
function resolveCondition(condition, slot, path) {
|
|
856
|
-
if (!condition)
|
|
857
|
-
return undefined;
|
|
858
|
-
}
|
|
342
|
+
if (!condition) return undefined;
|
|
859
343
|
if (isResolvable(condition)) {
|
|
860
344
|
return args => !!evaluateResolvable(condition, slot, makeScope(args), path);
|
|
861
345
|
}
|
|
@@ -876,10 +360,11 @@ function createMachineFromConfig(json, sources = {}) {
|
|
|
876
360
|
return guardImpl(args, params);
|
|
877
361
|
};
|
|
878
362
|
}
|
|
363
|
+
function getMissingGuardMessage(type, guards) {
|
|
364
|
+
return `Guard '${type}' is not implemented in machine '${json.id ?? '(machine)'}'. Available guards: ${Object.keys(guards).map(key => `'${key}'`).join(', ') || '(none)'}.`;
|
|
365
|
+
}
|
|
879
366
|
function makeChoiceConfig(choice, path) {
|
|
880
|
-
if (!choice)
|
|
881
|
-
return undefined;
|
|
882
|
-
}
|
|
367
|
+
if (!choice) return undefined;
|
|
883
368
|
if (isResolvable(choice)) {
|
|
884
369
|
return args => evaluateResolvable(choice, 'choice', makeScope(args), path);
|
|
885
370
|
}
|
|
@@ -902,32 +387,8 @@ function createMachineFromConfig(json, sources = {}) {
|
|
|
902
387
|
throw new Error(`Choice state at ${path} did not match any branch.`);
|
|
903
388
|
};
|
|
904
389
|
}
|
|
905
|
-
|
|
906
|
-
// Pending transition actions: set by .to functions, consumed by entry functions.
|
|
907
|
-
// This bridges SCXML's exit→transition→entry action ordering with XState's
|
|
908
|
-
// .to function receiving pre-exit context.
|
|
909
|
-
// Map keyed by target state ID so parallel transitions don't overwrite each other.
|
|
910
|
-
const pendingTransitionActionsMap = {};
|
|
911
|
-
|
|
912
|
-
// Ordered queue of ALL transition actions (targeted + targetless) for parallel
|
|
913
|
-
// context sharing. In SCXML, all transition actions execute sequentially in
|
|
914
|
-
// document order with a shared evolving data model.
|
|
915
|
-
const allTransitionActions = [];
|
|
916
|
-
// Pre-transition context saved when a targetless .to executes. Used by entry
|
|
917
|
-
// functions to re-execute all transition actions from scratch when parallel
|
|
918
|
-
// targetless transitions coexist with targeted transitions.
|
|
919
|
-
let contextBeforeTargetless = null;
|
|
920
|
-
// Platform errors collected during transition selection (e.g., failing
|
|
921
|
-
// <transition cond>). Drained by the next state's entry into the internal
|
|
922
|
-
// event queue so they're processed before any external events.
|
|
923
|
-
const pendingPlatformErrors = [];
|
|
924
|
-
function getMissingGuardMessage(type, guards) {
|
|
925
|
-
return `Guard '${type}' is not implemented in machine '${json.id ?? '(machine)'}'. Available guards: ${Object.keys(guards).map(key => `'${key}'`).join(', ') || '(none)'}.`;
|
|
926
|
-
}
|
|
927
390
|
function resolveRouteConfig(route, path) {
|
|
928
|
-
if (!route || typeof route === 'function')
|
|
929
|
-
return route;
|
|
930
|
-
}
|
|
391
|
+
if (!route || typeof route === 'function') return route;
|
|
931
392
|
if (isResolvable(route)) {
|
|
932
393
|
return args => evaluateResolvable(route, 'transition', makeScope(args), path);
|
|
933
394
|
}
|
|
@@ -935,263 +396,15 @@ function createMachineFromConfig(json, sources = {}) {
|
|
|
935
396
|
guard,
|
|
936
397
|
...routeConfig
|
|
937
398
|
} = route;
|
|
938
|
-
if (!guard)
|
|
939
|
-
return routeConfig;
|
|
940
|
-
}
|
|
399
|
+
if (!guard) return routeConfig;
|
|
941
400
|
const resolvedGuard = resolveCondition({
|
|
942
401
|
type: guard
|
|
943
402
|
}, 'guard', path);
|
|
944
403
|
return args => resolvedGuard(args) ? routeConfig : undefined;
|
|
945
404
|
}
|
|
946
|
-
function
|
|
947
|
-
const originalEntryActions = toActionArray(node.entry);
|
|
948
|
-
const stateId = node.id || nodeKey;
|
|
949
|
-
|
|
950
|
-
// Wrap entry to first execute any pending transition actions, then normal entry.
|
|
951
|
-
// This ensures SCXML execution order: exit → transition_actions → entry_actions
|
|
952
|
-
// because pending transition actions are set by .to (before exit) but executed
|
|
953
|
-
// in entry (after exit), thus seeing post-exit context.
|
|
954
|
-
const entryFn = (x, enq) => {
|
|
955
|
-
// Drain any platform errors queued during transition selection (e.g.,
|
|
956
|
-
// failing <transition cond="..."> evaluations). These must be raised
|
|
957
|
-
// internally so they're processed before subsequent external events.
|
|
958
|
-
while (pendingPlatformErrors.length) {
|
|
959
|
-
const err = pendingPlatformErrors.shift();
|
|
960
|
-
enq.raise({
|
|
961
|
-
type: 'xstate.error.execution',
|
|
962
|
-
error: err,
|
|
963
|
-
_scxmlEventType: 'platform',
|
|
964
|
-
_scxmlEventName: 'error.execution',
|
|
965
|
-
_scxmlEventData: err
|
|
966
|
-
});
|
|
967
|
-
}
|
|
968
|
-
let context;
|
|
969
|
-
|
|
970
|
-
// If targetless transitions were interleaved with targeted transitions
|
|
971
|
-
// (parallel state), re-execute ALL transition actions from the original
|
|
972
|
-
// pre-transition context. This overrides any .to-produced context with
|
|
973
|
-
// the correct SCXML document-order sequential execution.
|
|
974
|
-
// Only trigger when BOTH targeted (pending in map) and targetless fired
|
|
975
|
-
// in the same microstep — prevents stale data from previous events.
|
|
976
|
-
if (contextBeforeTargetless && allTransitionActions.length > 0 && Object.keys(pendingTransitionActionsMap).length > 0) {
|
|
977
|
-
let ctx = contextBeforeTargetless;
|
|
978
|
-
for (const actions of allTransitionActions) {
|
|
979
|
-
const mergedX = {
|
|
980
|
-
...x,
|
|
981
|
-
context: ctx
|
|
982
|
-
};
|
|
983
|
-
const result = executeActions(actions, mergedX, enq);
|
|
984
|
-
if (result.context) {
|
|
985
|
-
ctx = result.context;
|
|
986
|
-
}
|
|
987
|
-
}
|
|
988
|
-
allTransitionActions.length = 0;
|
|
989
|
-
contextBeforeTargetless = null;
|
|
990
|
-
// Clear per-target map since we re-processed everything
|
|
991
|
-
for (const key of Object.keys(pendingTransitionActionsMap)) {
|
|
992
|
-
delete pendingTransitionActionsMap[key];
|
|
993
|
-
}
|
|
994
|
-
context = ctx;
|
|
995
|
-
} else {
|
|
996
|
-
// Normal path: consume pending transition actions for THIS state.
|
|
997
|
-
// In parallel states, each target gets its own pending actions.
|
|
998
|
-
const transActions = stateId ? pendingTransitionActionsMap[stateId] : undefined;
|
|
999
|
-
if (transActions) {
|
|
1000
|
-
delete pendingTransitionActionsMap[stateId];
|
|
1001
|
-
const result = executeActions(transActions, x, enq);
|
|
1002
|
-
if (result.context) {
|
|
1003
|
-
context = result.context;
|
|
1004
|
-
}
|
|
1005
|
-
}
|
|
1006
|
-
// Clear stale targetless data from previous microsteps
|
|
1007
|
-
contextBeforeTargetless = null;
|
|
1008
|
-
allTransitionActions.length = 0;
|
|
1009
|
-
}
|
|
1010
|
-
|
|
1011
|
-
// Execute normal entry actions
|
|
1012
|
-
if (originalEntryActions.length) {
|
|
1013
|
-
const mergedX = context ? {
|
|
1014
|
-
...x,
|
|
1015
|
-
context
|
|
1016
|
-
} : x;
|
|
1017
|
-
const result = executeActions(originalEntryActions, mergedX, enq);
|
|
1018
|
-
if (result.context) {
|
|
1019
|
-
context = result.context;
|
|
1020
|
-
}
|
|
1021
|
-
}
|
|
1022
|
-
return {
|
|
1023
|
-
context
|
|
1024
|
-
};
|
|
1025
|
-
};
|
|
1026
|
-
const nodeConfig = {
|
|
1027
|
-
id: node.id,
|
|
1028
|
-
initial: node.initial,
|
|
1029
|
-
type: node.type,
|
|
1030
|
-
history: node.history,
|
|
1031
|
-
target: node.target,
|
|
1032
|
-
description: node.description,
|
|
1033
|
-
tags: node.tags,
|
|
1034
|
-
input: node.input,
|
|
1035
|
-
timeout: getDurationConfig(node.timeout, `$.states.${nodeKey}.timeout`),
|
|
1036
|
-
states: node.states ? Object.entries(node.states).reduce((acc, [key, value]) => {
|
|
1037
|
-
acc[key] = iterNode(value, key);
|
|
1038
|
-
return acc;
|
|
1039
|
-
}, {}) : undefined,
|
|
1040
|
-
on: node.on ? Object.entries(node.on).reduce((acc, [key, value]) => {
|
|
1041
|
-
acc[key] = getTransitionConfig(value);
|
|
1042
|
-
return acc;
|
|
1043
|
-
}, {}) : undefined,
|
|
1044
|
-
always: node.always ? getTransitionConfig(node.always) : undefined,
|
|
1045
|
-
onError: node.onError ? getTransitionConfig(node.onError) : undefined,
|
|
1046
|
-
choice: makeChoiceConfig(node.choice, `$.states.${nodeKey}.choice`),
|
|
1047
|
-
route: resolveRouteConfig(node.route, `$.states.${nodeKey}.route`),
|
|
1048
|
-
after: node.after ? Object.entries(node.after).reduce((acc, [key, value]) => {
|
|
1049
|
-
acc[key] = getTransitionConfig(value);
|
|
1050
|
-
return acc;
|
|
1051
|
-
}, {}) : undefined,
|
|
1052
|
-
onTimeout: node.onTimeout ? getTransitionConfig(node.onTimeout) : undefined,
|
|
1053
|
-
entry: node.type === 'choice' ? undefined : entryFn,
|
|
1054
|
-
exit: node.exit ? iterActions(toActionArray(node.exit)) : undefined,
|
|
1055
|
-
invoke: node.invoke ? iterInvokeConfigs(node.invoke) : undefined,
|
|
1056
|
-
meta: node.meta,
|
|
1057
|
-
output: node._scxmlDonedata ? makeDonedataOutput(node._scxmlDonedata) : isResolvable(node.output) ? ({
|
|
1058
|
-
context,
|
|
1059
|
-
event,
|
|
1060
|
-
self
|
|
1061
|
-
}) => evaluateResolvable(node.output, 'output', {
|
|
1062
|
-
context,
|
|
1063
|
-
event,
|
|
1064
|
-
self
|
|
1065
|
-
}, `$.states.${nodeKey}.output`) : node.output
|
|
1066
|
-
};
|
|
1067
|
-
return nodeConfig;
|
|
1068
|
-
}
|
|
1069
|
-
function makeDonedataOutput(donedata) {
|
|
1070
|
-
return ({
|
|
1071
|
-
context,
|
|
1072
|
-
event,
|
|
1073
|
-
self
|
|
1074
|
-
}) => {
|
|
1075
|
-
try {
|
|
1076
|
-
if (donedata.params && donedata.params.length) {
|
|
1077
|
-
const out = {};
|
|
1078
|
-
for (const param of donedata.params) {
|
|
1079
|
-
out[param.name] = evaluateExpr(context, param.expr, event, self);
|
|
1080
|
-
}
|
|
1081
|
-
return out;
|
|
1082
|
-
}
|
|
1083
|
-
if (donedata.contentExpr !== undefined) {
|
|
1084
|
-
return evaluateExpr(context, donedata.contentExpr, event, self);
|
|
1085
|
-
}
|
|
1086
|
-
if (donedata.contentText !== undefined) {
|
|
1087
|
-
// Try parsing as a JS expression (number/object/array literals);
|
|
1088
|
-
// fall back to the raw string.
|
|
1089
|
-
try {
|
|
1090
|
-
return evaluateExpr(context, donedata.contentText, event, self);
|
|
1091
|
-
} catch {
|
|
1092
|
-
return donedata.contentText;
|
|
1093
|
-
}
|
|
1094
|
-
}
|
|
1095
|
-
} catch (err) {
|
|
1096
|
-
// Per SCXML, donedata expression errors raise error.execution and
|
|
1097
|
-
// result in undefined event.data. Queue for the next entry to drain.
|
|
1098
|
-
const message = err instanceof Error ? err.message : typeof err === 'string' ? err : 'unknown error';
|
|
1099
|
-
pendingPlatformErrors.push({
|
|
1100
|
-
tagname: 'donedata',
|
|
1101
|
-
message,
|
|
1102
|
-
line: NaN,
|
|
1103
|
-
column: NaN,
|
|
1104
|
-
reason: message
|
|
1105
|
-
});
|
|
1106
|
-
}
|
|
1107
|
-
return undefined;
|
|
1108
|
-
};
|
|
1109
|
-
}
|
|
1110
|
-
function iterInvokeConfigs(invokes) {
|
|
1111
|
-
const invokeArray = Array.isArray(invokes) ? invokes : [invokes];
|
|
1112
|
-
return invokeArray.map(inv => {
|
|
1113
|
-
const extInv = inv;
|
|
1114
|
-
// Create child machine from nested SCXML JSON
|
|
1115
|
-
let src;
|
|
1116
|
-
if (extInv._nestedMachineJSON) {
|
|
1117
|
-
src = createMachineFromConfig(extInv._nestedMachineJSON, resolvedSources);
|
|
1118
|
-
} else {
|
|
1119
|
-
src = resolvedSources.actors[inv.src] ?? inv.src;
|
|
1120
|
-
}
|
|
1121
|
-
return {
|
|
1122
|
-
src,
|
|
1123
|
-
id: inv.id,
|
|
1124
|
-
registryKey: inv.registryKey,
|
|
1125
|
-
input: inv.input !== undefined ? args => resolveValue(inv.input, 'input', makeScope(args), '$.invoke.input') : undefined,
|
|
1126
|
-
onDone: inv.onDone ? getTransitionConfig(inv.onDone) : undefined,
|
|
1127
|
-
onError: inv.onError ? getTransitionConfig(inv.onError) : undefined,
|
|
1128
|
-
onSnapshot: inv.onSnapshot ? getTransitionConfig(inv.onSnapshot) : undefined,
|
|
1129
|
-
timeout: getDurationConfig(inv.timeout, '$.invoke.timeout'),
|
|
1130
|
-
onTimeout: inv.onTimeout ? getTransitionConfig(inv.onTimeout) : undefined
|
|
1131
|
-
};
|
|
1132
|
-
});
|
|
1133
|
-
}
|
|
1134
|
-
|
|
1135
|
-
/**
|
|
1136
|
-
* Raise an SCXML error.execution platform event onto the internal queue. Per
|
|
1137
|
-
* spec, error.execution is type='platform' and _event.data contains error
|
|
1138
|
-
* info. The surrounding block of executable content stops.
|
|
1139
|
-
*/
|
|
1140
|
-
function raiseErrorExecution(state, tagname, err) {
|
|
1141
|
-
const message = err instanceof Error ? err.message : typeof err === 'string' ? err : 'unknown error';
|
|
1142
|
-
state.enq.raise({
|
|
1143
|
-
type: 'xstate.error.execution',
|
|
1144
|
-
error: {
|
|
1145
|
-
tagname,
|
|
1146
|
-
message,
|
|
1147
|
-
line: NaN,
|
|
1148
|
-
column: NaN,
|
|
1149
|
-
reason: message
|
|
1150
|
-
},
|
|
1151
|
-
_scxmlEventType: 'platform',
|
|
1152
|
-
_scxmlEventName: 'error.execution',
|
|
1153
|
-
_scxmlEventData: {
|
|
1154
|
-
tagname,
|
|
1155
|
-
message,
|
|
1156
|
-
line: NaN,
|
|
1157
|
-
column: NaN,
|
|
1158
|
-
reason: message
|
|
1159
|
-
}
|
|
1160
|
-
});
|
|
1161
|
-
state.errored = true;
|
|
1162
|
-
}
|
|
1163
|
-
function executeActionDefinition(action, x, enq, params, parentState, stack) {
|
|
1164
|
-
const definition = json.actions?.[action.type];
|
|
1165
|
-
if (!definition) {
|
|
1166
|
-
enq(x.actions[action.type], params);
|
|
1167
|
-
return {
|
|
1168
|
-
context: undefined,
|
|
1169
|
-
errored: parentState.errored
|
|
1170
|
-
};
|
|
1171
|
-
}
|
|
1172
|
-
if (stack.includes(action.type)) {
|
|
1173
|
-
raiseErrorExecution(parentState, 'action', new Error(`Circular action reference: ${stack.concat(action.type).join(' -> ')}`));
|
|
1174
|
-
return {
|
|
1175
|
-
context: undefined,
|
|
1176
|
-
errored: true
|
|
1177
|
-
};
|
|
1178
|
-
}
|
|
1179
|
-
const definitions = Array.isArray(definition) ? definition : [definition];
|
|
1180
|
-
return executeActions(definitions, {
|
|
1181
|
-
...x,
|
|
1182
|
-
params
|
|
1183
|
-
}, enq, parentState, stack.concat(action.type));
|
|
1184
|
-
}
|
|
1185
|
-
|
|
1186
|
-
/** Execute an array of SCXML action JSON descriptors with context and enqueue. */
|
|
1187
|
-
function executeActions(actions, x, enq, parentState, stack = []) {
|
|
1188
|
-
const state = parentState ?? {
|
|
1189
|
-
enq,
|
|
1190
|
-
errored: false
|
|
1191
|
-
};
|
|
405
|
+
function executeActions(actions, x, enq, stack = []) {
|
|
1192
406
|
let context;
|
|
1193
407
|
for (const action of actions) {
|
|
1194
|
-
if (state.errored) break;
|
|
1195
408
|
if (isResolvable(action)) {
|
|
1196
409
|
const result = evaluateResolvable(action, 'action', makeScope(x, {
|
|
1197
410
|
params: x.params,
|
|
@@ -1201,31 +414,18 @@ function createMachineFromConfig(json, sources = {}) {
|
|
|
1201
414
|
context ??= {};
|
|
1202
415
|
Object.assign(context, result.context);
|
|
1203
416
|
}
|
|
1204
|
-
|
|
417
|
+
continue;
|
|
418
|
+
}
|
|
419
|
+
if (isBuiltInActionJSON(action)) {
|
|
1205
420
|
switch (action.type) {
|
|
1206
421
|
case '@xstate.raise':
|
|
1207
|
-
{
|
|
1208
|
-
|
|
1209
|
-
|
|
1210
|
-
|
|
1211
|
-
|
|
1212
|
-
|
|
1213
|
-
|
|
1214
|
-
const event = isExternal || action.id !== undefined ? {
|
|
1215
|
-
...resolvedEvent,
|
|
1216
|
-
...(isExternal ? {
|
|
1217
|
-
_scxmlExternal: true
|
|
1218
|
-
} : {}),
|
|
1219
|
-
...(action.id !== undefined ? {
|
|
1220
|
-
_scxmlSendId: action.id
|
|
1221
|
-
} : {})
|
|
1222
|
-
} : resolvedEvent;
|
|
1223
|
-
enq.raise(event, {
|
|
1224
|
-
id: action.id,
|
|
1225
|
-
delay: action.delay
|
|
1226
|
-
});
|
|
1227
|
-
break;
|
|
1228
|
-
}
|
|
422
|
+
enq.raise(resolveValue(action.event, 'actionParams', makeScope(x, {
|
|
423
|
+
params: x.params
|
|
424
|
+
}), '$.actions.event'), {
|
|
425
|
+
id: action.id,
|
|
426
|
+
delay: action.delay
|
|
427
|
+
});
|
|
428
|
+
break;
|
|
1229
429
|
case '@xstate.cancel':
|
|
1230
430
|
enq.cancel(action.id);
|
|
1231
431
|
break;
|
|
@@ -1243,501 +443,161 @@ function createMachineFromConfig(json, sources = {}) {
|
|
|
1243
443
|
params: x.params
|
|
1244
444
|
}), '$.actions.context'));
|
|
1245
445
|
break;
|
|
1246
|
-
default:
|
|
1247
|
-
throw new Error(`Unknown built-in action: ${action.type}`);
|
|
1248
|
-
}
|
|
1249
|
-
} else if (action.type === 'scxml.assign') {
|
|
1250
|
-
const scxmlAction = action;
|
|
1251
|
-
const mergedContext = {
|
|
1252
|
-
...x.context,
|
|
1253
|
-
...context
|
|
1254
|
-
};
|
|
1255
|
-
let value;
|
|
1256
|
-
try {
|
|
1257
|
-
value = evaluateExpr(mergedContext, scxmlAction.expr, x.event, x.self);
|
|
1258
|
-
} catch (err) {
|
|
1259
|
-
raiseErrorExecution(state, 'assign', err);
|
|
1260
|
-
continue;
|
|
1261
|
-
}
|
|
1262
|
-
// Per SCXML, assigning to a location that doesn't exist on the
|
|
1263
|
-
// datamodel is an error. Allow setting an own property via context;
|
|
1264
|
-
// detect deep paths (a.b.c) which we don't support.
|
|
1265
|
-
if (scxmlAction.location.includes('.')) {
|
|
1266
|
-
raiseErrorExecution(state, 'assign', new Error(`Invalid assign location: ${scxmlAction.location}`));
|
|
1267
|
-
continue;
|
|
1268
|
-
}
|
|
1269
|
-
context ??= {};
|
|
1270
|
-
context[scxmlAction.location] = value;
|
|
1271
|
-
} else if (action.type === 'scxml.raise') {
|
|
1272
|
-
const scxmlAction = action;
|
|
1273
|
-
const mergedContext = {
|
|
1274
|
-
...x.context,
|
|
1275
|
-
...context
|
|
1276
|
-
};
|
|
1277
|
-
let eventType;
|
|
1278
|
-
let eventData;
|
|
1279
|
-
let target;
|
|
1280
|
-
let delay;
|
|
1281
|
-
try {
|
|
1282
|
-
eventType = scxmlAction.eventexpr ? evaluateExpr(mergedContext, scxmlAction.eventexpr, x.event, x.self) : scxmlAction.event || 'unknown';
|
|
1283
|
-
eventType = normalizeScxmlEventType(eventType);
|
|
1284
|
-
eventData = {
|
|
1285
|
-
type: eventType,
|
|
1286
|
-
_scxmlEventName: toScxmlEventName(eventType)
|
|
1287
|
-
};
|
|
1288
|
-
if (scxmlAction.params) {
|
|
1289
|
-
for (const param of scxmlAction.params) {
|
|
1290
|
-
eventData[param.name] = evaluateExpr(mergedContext, param.expr, x.event, x.self);
|
|
1291
|
-
}
|
|
1292
|
-
}
|
|
1293
|
-
target = scxmlAction.targetexpr ? evaluateExpr(mergedContext, scxmlAction.targetexpr, x.event, x.self) : scxmlAction.target;
|
|
1294
|
-
const isInternalTarget = target === '#_internal';
|
|
1295
|
-
delay = scxmlAction.delayexpr ? delayToMs(evaluateExpr(mergedContext, scxmlAction.delayexpr, x.event, x.self)) : isInternalTarget ? undefined : scxmlAction.delay;
|
|
1296
|
-
} catch (err) {
|
|
1297
|
-
raiseErrorExecution(state, 'send', err);
|
|
1298
|
-
continue;
|
|
1299
|
-
}
|
|
1300
|
-
const isInternalTarget = target === '#_internal';
|
|
1301
|
-
const isParentTarget = target === '#_parent';
|
|
1302
|
-
|
|
1303
|
-
// Validate target. SCXML targets must be '#_internal', '#_parent',
|
|
1304
|
-
// or '#_<id>'. A bare string without the '#_' prefix is invalid and
|
|
1305
|
-
// raises error.execution.
|
|
1306
|
-
if (typeof target === 'string' && target.length > 0 && !target.startsWith('#_')) {
|
|
1307
|
-
raiseErrorExecution(state, 'send', new Error(`Invalid send target: ${target}`));
|
|
1308
|
-
continue;
|
|
1309
|
-
}
|
|
1310
|
-
// Attach send id so _event.sendid can be read in expressions.
|
|
1311
|
-
if (scxmlAction.id !== undefined) {
|
|
1312
|
-
eventData._scxmlSendId = scxmlAction.id;
|
|
1313
|
-
}
|
|
1314
|
-
// Resolve target at runtime: parent, child, or self
|
|
1315
|
-
if (isParentTarget && x.parent) {
|
|
1316
|
-
// Send to parent via sendTo; pass delay if present
|
|
1317
|
-
enq.sendTo(x.parent, eventData, delay !== undefined ? {
|
|
1318
|
-
delay
|
|
1319
|
-
} : undefined);
|
|
1320
|
-
} else if (typeof target === 'string' && target.startsWith('#_') && !isParentTarget && !isInternalTarget) {
|
|
1321
|
-
// #_<invokeId> → try to send to child actor, fall back to self-raise
|
|
1322
|
-
const childId = target.slice(2); // strip '#_'
|
|
1323
|
-
const childRef = x.children?.[childId];
|
|
1324
|
-
if (childRef) {
|
|
1325
|
-
enq.sendTo(childRef, eventData);
|
|
1326
|
-
} else if (childId.startsWith('scxml_') && childId !== `scxml_${_scxmlSessionId}`) {
|
|
1327
|
-
const message = `Unable to dispatch event to target: ${target}`;
|
|
1328
|
-
enq.raise({
|
|
1329
|
-
type: 'xstate.error.communication',
|
|
1330
|
-
error: {
|
|
1331
|
-
tagname: 'send',
|
|
1332
|
-
message,
|
|
1333
|
-
line: NaN,
|
|
1334
|
-
column: NaN,
|
|
1335
|
-
reason: message
|
|
1336
|
-
},
|
|
1337
|
-
_scxmlEventType: 'platform',
|
|
1338
|
-
_scxmlEventName: 'error.communication',
|
|
1339
|
-
_scxmlEventData: {
|
|
1340
|
-
tagname: 'send',
|
|
1341
|
-
message,
|
|
1342
|
-
line: NaN,
|
|
1343
|
-
column: NaN,
|
|
1344
|
-
reason: message
|
|
1345
|
-
}
|
|
1346
|
-
});
|
|
1347
|
-
} else {
|
|
1348
|
-
// This SCXML session id uses the external event queue.
|
|
1349
|
-
eventData._scxmlExternal = true;
|
|
1350
|
-
enq.sendTo(x.self, eventData, {
|
|
1351
|
-
id: scxmlAction.id,
|
|
1352
|
-
delay
|
|
1353
|
-
});
|
|
1354
|
-
}
|
|
1355
|
-
} else {
|
|
1356
|
-
// #_internal uses the internal queue; self-send/no target use the
|
|
1357
|
-
// external event queue.
|
|
1358
|
-
if (isInternalTarget) {
|
|
1359
|
-
enq.raise(eventData, {
|
|
1360
|
-
id: scxmlAction.id,
|
|
1361
|
-
delay
|
|
1362
|
-
});
|
|
1363
|
-
} else {
|
|
1364
|
-
eventData._scxmlExternal = true;
|
|
1365
|
-
enq.sendTo(x.self, eventData, {
|
|
1366
|
-
id: scxmlAction.id,
|
|
1367
|
-
delay
|
|
1368
|
-
});
|
|
1369
|
-
}
|
|
1370
|
-
}
|
|
1371
|
-
} else if (action.type === 'scxml.cancel') {
|
|
1372
|
-
const scxmlAction = action;
|
|
1373
|
-
const mergedContext = {
|
|
1374
|
-
...x.context,
|
|
1375
|
-
...context
|
|
1376
|
-
};
|
|
1377
|
-
try {
|
|
1378
|
-
const sendId = evaluateExpr(mergedContext, scxmlAction.sendidexpr, x.event, x.self);
|
|
1379
|
-
if (sendId) {
|
|
1380
|
-
enq.cancel(sendId);
|
|
1381
|
-
}
|
|
1382
|
-
} catch {
|
|
1383
|
-
// ignore evaluation errors
|
|
1384
|
-
}
|
|
1385
|
-
} else if (action.type === 'scxml.script') {
|
|
1386
|
-
const scxmlAction = action;
|
|
1387
|
-
const mergedContext = {
|
|
1388
|
-
...x.context,
|
|
1389
|
-
...context
|
|
1390
|
-
};
|
|
1391
|
-
try {
|
|
1392
|
-
const updatedContext = executeScript(mergedContext, scxmlAction.code);
|
|
1393
|
-
context ??= {};
|
|
1394
|
-
Object.assign(context, updatedContext);
|
|
1395
|
-
} catch (err) {
|
|
1396
|
-
raiseErrorExecution(state, 'script', err);
|
|
1397
|
-
}
|
|
1398
|
-
} else if (action.type === 'scxml.foreach') {
|
|
1399
|
-
const scxmlAction = action;
|
|
1400
|
-
const mergedContext = {
|
|
1401
|
-
...x.context,
|
|
1402
|
-
...context
|
|
1403
|
-
};
|
|
1404
|
-
// SCXML: `item` (and `index` if present) must be valid datamodel
|
|
1405
|
-
// locations — i.e. legal identifiers. Reject things like 'continue'
|
|
1406
|
-
// (string literal) or '7' (number).
|
|
1407
|
-
const isLegalIdentifier = s => /^[$_a-zA-Z][$_a-zA-Z0-9]*$/.test(s);
|
|
1408
|
-
if (!isLegalIdentifier(scxmlAction.item) || scxmlAction.index && !isLegalIdentifier(scxmlAction.index)) {
|
|
1409
|
-
raiseErrorExecution(state, 'foreach', new Error('foreach item/index is not a legal location'));
|
|
1410
|
-
continue;
|
|
1411
|
-
}
|
|
1412
|
-
let arr;
|
|
1413
|
-
try {
|
|
1414
|
-
arr = evaluateExpr(mergedContext, scxmlAction.array, x.event, x.self);
|
|
1415
|
-
} catch (err) {
|
|
1416
|
-
raiseErrorExecution(state, 'foreach', err);
|
|
1417
|
-
continue;
|
|
1418
|
-
}
|
|
1419
|
-
if (!Array.isArray(arr)) {
|
|
1420
|
-
raiseErrorExecution(state, 'foreach', new Error('foreach array is not iterable'));
|
|
1421
|
-
continue;
|
|
1422
446
|
}
|
|
1423
|
-
|
|
1424
|
-
|
|
1425
|
-
|
|
1426
|
-
|
|
1427
|
-
|
|
1428
|
-
|
|
1429
|
-
|
|
1430
|
-
|
|
1431
|
-
|
|
1432
|
-
|
|
1433
|
-
|
|
1434
|
-
|
|
1435
|
-
|
|
1436
|
-
|
|
1437
|
-
|
|
1438
|
-
|
|
1439
|
-
|
|
1440
|
-
if (state.errored) break;
|
|
1441
|
-
}
|
|
1442
|
-
} else if (action.type === 'scxml.block') {
|
|
1443
|
-
const scxmlAction = action;
|
|
1444
|
-
const blockX = {
|
|
1445
|
-
...x,
|
|
1446
|
-
context: {
|
|
1447
|
-
...x.context,
|
|
1448
|
-
...context
|
|
1449
|
-
}
|
|
1450
|
-
};
|
|
1451
|
-
// Block has its own ExecState — errors don't propagate to parent.
|
|
1452
|
-
const blockResult = executeActions(scxmlAction.actions, blockX, enq);
|
|
1453
|
-
if (blockResult.context) {
|
|
1454
|
-
context ??= {};
|
|
1455
|
-
for (const key of Object.keys(blockResult.context)) {
|
|
1456
|
-
if (blockResult.context[key] !== x.context[key]) {
|
|
1457
|
-
context[key] = blockResult.context[key];
|
|
1458
|
-
}
|
|
1459
|
-
}
|
|
1460
|
-
}
|
|
1461
|
-
} else if (action.type === 'scxml.if') {
|
|
1462
|
-
const scxmlAction = action;
|
|
1463
|
-
const mergedContext = {
|
|
447
|
+
continue;
|
|
448
|
+
}
|
|
449
|
+
const params = resolveValue(action.params, 'actionParams', makeScope(x, {
|
|
450
|
+
params: x.params
|
|
451
|
+
}), '$.actions.params');
|
|
452
|
+
const definition = json.actions?.[action.type];
|
|
453
|
+
if (!definition) {
|
|
454
|
+
enq(x.actions[action.type], params);
|
|
455
|
+
continue;
|
|
456
|
+
}
|
|
457
|
+
if (stack.includes(action.type)) {
|
|
458
|
+
throw new Error(`Circular action reference: ${stack.concat(action.type).join(' -> ')}`);
|
|
459
|
+
}
|
|
460
|
+
const definitions = Array.isArray(definition) ? definition : [definition];
|
|
461
|
+
const result = executeActions(definitions, {
|
|
462
|
+
...x,
|
|
463
|
+
context: {
|
|
1464
464
|
...x.context,
|
|
1465
465
|
...context
|
|
1466
|
-
}
|
|
1467
|
-
|
|
1468
|
-
|
|
1469
|
-
|
|
1470
|
-
try {
|
|
1471
|
-
condResult = !!evaluateExpr(mergedContext, branch.cond, x.event, x.self);
|
|
1472
|
-
} catch (err) {
|
|
1473
|
-
raiseErrorExecution(state, 'if', err);
|
|
1474
|
-
condResult = false;
|
|
1475
|
-
}
|
|
1476
|
-
} else {
|
|
1477
|
-
condResult = true;
|
|
1478
|
-
}
|
|
1479
|
-
if (condResult) {
|
|
1480
|
-
if (branch.actions.length) {
|
|
1481
|
-
const branchX = {
|
|
1482
|
-
...x,
|
|
1483
|
-
context: mergedContext
|
|
1484
|
-
};
|
|
1485
|
-
const branchResult = executeActions(branch.actions, branchX, enq, state);
|
|
1486
|
-
if (branchResult.context) {
|
|
1487
|
-
context ??= {};
|
|
1488
|
-
for (const key of Object.keys(branchResult.context)) {
|
|
1489
|
-
if (branchResult.context[key] !== x.context[key]) {
|
|
1490
|
-
context[key] = branchResult.context[key];
|
|
1491
|
-
}
|
|
1492
|
-
}
|
|
1493
|
-
}
|
|
1494
|
-
}
|
|
1495
|
-
break;
|
|
1496
|
-
}
|
|
1497
|
-
}
|
|
1498
|
-
} else {
|
|
1499
|
-
const params = resolveValue(action.params, 'actionParams', makeScope(x, {
|
|
1500
|
-
params: x.params
|
|
1501
|
-
}), '$.actions.params');
|
|
1502
|
-
const result = executeActionDefinition(action, x, enq, params, state, stack);
|
|
1503
|
-
if (result.context) {
|
|
1504
|
-
context ??= {};
|
|
1505
|
-
Object.assign(context, result.context);
|
|
1506
|
-
}
|
|
1507
|
-
}
|
|
466
|
+
},
|
|
467
|
+
params
|
|
468
|
+
}, enq, stack.concat(action.type));
|
|
469
|
+
if (result.context) context = result.context;
|
|
1508
470
|
}
|
|
1509
471
|
return {
|
|
1510
472
|
context: context ? {
|
|
1511
473
|
...x.context,
|
|
1512
474
|
...context
|
|
1513
|
-
} : undefined
|
|
1514
|
-
errored: state.errored
|
|
475
|
+
} : undefined
|
|
1515
476
|
};
|
|
1516
477
|
}
|
|
1517
478
|
function iterActions(actions) {
|
|
1518
|
-
|
|
479
|
+
const actionArray = toActionArray(actions);
|
|
480
|
+
return (x, enq) => executeActions(actionArray, x, enq);
|
|
1519
481
|
}
|
|
1520
482
|
function getTransitionConfig(transition) {
|
|
1521
483
|
const transitions = Array.isArray(transition) ? transition : [transition];
|
|
1522
|
-
|
|
1523
|
-
|
|
1524
|
-
|
|
1525
|
-
// This ensures guards are evaluated by XState's evaluateCandidate (once,
|
|
1526
|
-
// with pre-exit context) and NOT re-evaluated in computeEntrySet.
|
|
1527
|
-
return transitions.map((t, index) => {
|
|
1528
|
-
if (isResolvable(t)) {
|
|
1529
|
-
return (x, enq) => evaluateResolvable(t, 'transition', makeScope(x, {
|
|
484
|
+
return transitions.map((item, index) => {
|
|
485
|
+
if (isResolvable(item)) {
|
|
486
|
+
return (x, enq) => evaluateResolvable(item, 'transition', makeScope(x, {
|
|
1530
487
|
enq
|
|
1531
488
|
}), `$.transition${transitions.length > 1 ? `[${index}]` : ''}`);
|
|
1532
489
|
}
|
|
1533
|
-
const
|
|
1534
|
-
const
|
|
1535
|
-
const
|
|
1536
|
-
const resolveTransitionContext = x => t.context ? resolveValue(t.context, 'transitionContext', makeScope(x), '$.transition.context') : undefined;
|
|
1537
|
-
const resolveTransitionInput = x => t.input !== undefined ? resolveValue(t.input, 'input', makeScope(x), '$.transition.input') : undefined;
|
|
1538
|
-
|
|
1539
|
-
// No guard and no actions: simple static config
|
|
1540
|
-
if (!guard && !t.actions?.length) {
|
|
1541
|
-
if (t.context) {
|
|
1542
|
-
return {
|
|
1543
|
-
matches: t.matches,
|
|
1544
|
-
to: x => ({
|
|
1545
|
-
target: targetConfig,
|
|
1546
|
-
context: resolveTransitionContext(x),
|
|
1547
|
-
reenter: t.reenter
|
|
1548
|
-
}),
|
|
1549
|
-
description: t.description,
|
|
1550
|
-
meta: t.meta,
|
|
1551
|
-
input: t.input !== undefined ? resolveTransitionInput : undefined
|
|
1552
|
-
};
|
|
1553
|
-
}
|
|
1554
|
-
return {
|
|
1555
|
-
matches: t.matches,
|
|
1556
|
-
target: targetConfig,
|
|
1557
|
-
description: t.description,
|
|
1558
|
-
reenter: t.reenter,
|
|
1559
|
-
meta: t.meta,
|
|
1560
|
-
input: t.input !== undefined ? resolveTransitionInput : undefined
|
|
1561
|
-
};
|
|
1562
|
-
}
|
|
1563
|
-
|
|
1564
|
-
// Guard but no actions: static config with guard
|
|
1565
|
-
if (guard && !t.actions?.length) {
|
|
1566
|
-
if (t.context) {
|
|
1567
|
-
return {
|
|
1568
|
-
matches: t.matches,
|
|
1569
|
-
guard,
|
|
1570
|
-
to: x => ({
|
|
1571
|
-
target: targetConfig,
|
|
1572
|
-
context: resolveTransitionContext(x),
|
|
1573
|
-
reenter: t.reenter
|
|
1574
|
-
}),
|
|
1575
|
-
description: t.description,
|
|
1576
|
-
meta: t.meta,
|
|
1577
|
-
input: t.input !== undefined ? resolveTransitionInput : undefined
|
|
1578
|
-
};
|
|
1579
|
-
}
|
|
1580
|
-
return {
|
|
1581
|
-
matches: t.matches,
|
|
1582
|
-
target: targetConfig,
|
|
1583
|
-
guard,
|
|
1584
|
-
description: t.description,
|
|
1585
|
-
reenter: t.reenter,
|
|
1586
|
-
meta: t.meta,
|
|
1587
|
-
input: t.input !== undefined ? resolveTransitionInput : undefined
|
|
1588
|
-
};
|
|
1589
|
-
}
|
|
1590
|
-
|
|
1591
|
-
// Targetless transitions: execute actions directly in .to AND track for
|
|
1592
|
-
// parallel re-execution. For non-parallel, .to result is used directly.
|
|
1593
|
-
// For parallel (entries exist), first entry re-executes all in document order.
|
|
1594
|
-
if (!target) {
|
|
1595
|
-
return {
|
|
1596
|
-
matches: t.matches,
|
|
1597
|
-
guard,
|
|
1598
|
-
description: t.description,
|
|
1599
|
-
reenter: t.reenter,
|
|
1600
|
-
meta: t.meta,
|
|
1601
|
-
input: t.input !== undefined ? resolveTransitionInput : undefined,
|
|
1602
|
-
to: (x, enq) => {
|
|
1603
|
-
const context = resolveTransitionContext(x);
|
|
1604
|
-
if (t.actions?.length) {
|
|
1605
|
-
// Track for parallel re-execution (dedup by reference)
|
|
1606
|
-
if (!allTransitionActions.includes(t.actions)) {
|
|
1607
|
-
allTransitionActions.push(t.actions);
|
|
1608
|
-
}
|
|
1609
|
-
// Save pre-transition context for parallel override
|
|
1610
|
-
contextBeforeTargetless ??= x.context;
|
|
1611
|
-
// Execute immediately (fallback for non-parallel case)
|
|
1612
|
-
const result = executeActions(t.actions, x, enq);
|
|
1613
|
-
if (result.context) {
|
|
1614
|
-
return {
|
|
1615
|
-
context: {
|
|
1616
|
-
...context,
|
|
1617
|
-
...result.context
|
|
1618
|
-
}
|
|
1619
|
-
};
|
|
1620
|
-
}
|
|
1621
|
-
}
|
|
1622
|
-
return context ? {
|
|
1623
|
-
context
|
|
1624
|
-
} : {};
|
|
1625
|
-
}
|
|
1626
|
-
};
|
|
1627
|
-
}
|
|
1628
|
-
|
|
1629
|
-
// Has target + actions: use guard (for XState evaluation) + .to (for pending actions).
|
|
1630
|
-
// The .to function does NOT re-check the guard — XState's evaluateCandidate
|
|
1631
|
-
// already validated it. The .to just stores actions for entry to execute.
|
|
1632
|
-
// Map by target state ID so parallel transitions each get their own actions.
|
|
490
|
+
const context = item.context ? x => resolveValue(item.context, 'transitionContext', makeScope(x), '$.transition.context') : undefined;
|
|
491
|
+
const input = item.input !== undefined ? x => resolveValue(item.input, 'input', makeScope(x), '$.transition.input') : undefined;
|
|
492
|
+
const dynamic = !!context || !!item.actions?.length;
|
|
1633
493
|
return {
|
|
1634
|
-
matches:
|
|
1635
|
-
|
|
1636
|
-
|
|
1637
|
-
|
|
1638
|
-
|
|
1639
|
-
|
|
1640
|
-
|
|
1641
|
-
|
|
1642
|
-
|
|
1643
|
-
const targetId = target.replace(/^#/, '');
|
|
1644
|
-
pendingTransitionActionsMap[targetId] = t.actions;
|
|
1645
|
-
// Track for parallel re-execution (dedup by reference)
|
|
1646
|
-
if (!allTransitionActions.includes(t.actions)) {
|
|
1647
|
-
allTransitionActions.push(t.actions);
|
|
494
|
+
matches: item.matches,
|
|
495
|
+
target: dynamic ? undefined : item.target,
|
|
496
|
+
to: dynamic ? (x, enq) => {
|
|
497
|
+
const resolvedContext = context?.(x);
|
|
498
|
+
const result = item.actions?.length ? executeActions(item.actions, resolvedContext ? {
|
|
499
|
+
...x,
|
|
500
|
+
context: {
|
|
501
|
+
...x.context,
|
|
502
|
+
...resolvedContext
|
|
1648
503
|
}
|
|
1649
|
-
}
|
|
504
|
+
} : x, enq) : undefined;
|
|
1650
505
|
return {
|
|
1651
|
-
target:
|
|
1652
|
-
context,
|
|
1653
|
-
reenter:
|
|
506
|
+
target: item.target,
|
|
507
|
+
context: result?.context ?? resolvedContext,
|
|
508
|
+
reenter: item.reenter
|
|
1654
509
|
};
|
|
1655
|
-
}
|
|
510
|
+
} : undefined,
|
|
511
|
+
guard: resolveCondition(item.guard, 'guard', '$.transition.guard'),
|
|
512
|
+
description: item.description,
|
|
513
|
+
reenter: item.reenter,
|
|
514
|
+
meta: item.meta,
|
|
515
|
+
input
|
|
1656
516
|
};
|
|
1657
517
|
});
|
|
1658
518
|
}
|
|
519
|
+
function iterInvokeConfigs(invokes) {
|
|
520
|
+
return (Array.isArray(invokes) ? invokes : [invokes]).map(inv => ({
|
|
521
|
+
src: resolvedSources.actors[inv.src] ?? inv.src,
|
|
522
|
+
id: inv.id,
|
|
523
|
+
registryKey: inv.registryKey,
|
|
524
|
+
input: inv.input !== undefined ? args => resolveValue(inv.input, 'input', makeScope(args), '$.invoke.input') : undefined,
|
|
525
|
+
onDone: inv.onDone ? getTransitionConfig(inv.onDone) : undefined,
|
|
526
|
+
onError: inv.onError ? getTransitionConfig(inv.onError) : undefined,
|
|
527
|
+
onSnapshot: inv.onSnapshot ? getTransitionConfig(inv.onSnapshot) : undefined,
|
|
528
|
+
timeout: getDurationConfig(inv.timeout, '$.invoke.timeout'),
|
|
529
|
+
onTimeout: inv.onTimeout ? getTransitionConfig(inv.onTimeout) : undefined
|
|
530
|
+
}));
|
|
531
|
+
}
|
|
532
|
+
function iterNode(node, nodeKey) {
|
|
533
|
+
return {
|
|
534
|
+
id: node.id,
|
|
535
|
+
initial: node.initial,
|
|
536
|
+
type: node.type,
|
|
537
|
+
history: node.history,
|
|
538
|
+
target: node.target,
|
|
539
|
+
description: node.description,
|
|
540
|
+
tags: node.tags,
|
|
541
|
+
input: node.input,
|
|
542
|
+
timeout: getDurationConfig(node.timeout, `$.states.${nodeKey}.timeout`),
|
|
543
|
+
states: node.states ? Object.fromEntries(Object.entries(node.states).map(([key, value]) => [key, iterNode(value, key)])) : undefined,
|
|
544
|
+
on: node.on ? Object.fromEntries(Object.entries(node.on).map(([key, value]) => [key, getTransitionConfig(value)])) : undefined,
|
|
545
|
+
always: node.always ? getTransitionConfig(node.always) : undefined,
|
|
546
|
+
onError: node.onError ? getTransitionConfig(node.onError) : undefined,
|
|
547
|
+
choice: makeChoiceConfig(node.choice, `$.states.${nodeKey}.choice`),
|
|
548
|
+
route: resolveRouteConfig(node.route, `$.states.${nodeKey}.route`),
|
|
549
|
+
after: node.after ? Object.fromEntries(Object.entries(node.after).map(([key, value]) => [key, getTransitionConfig(value)])) : undefined,
|
|
550
|
+
onTimeout: node.onTimeout ? getTransitionConfig(node.onTimeout) : undefined,
|
|
551
|
+
entry: node.entry ? iterActions(node.entry) : undefined,
|
|
552
|
+
exit: node.exit ? iterActions(node.exit) : undefined,
|
|
553
|
+
invoke: node.invoke ? iterInvokeConfigs(node.invoke) : undefined,
|
|
554
|
+
meta: node.meta,
|
|
555
|
+
output: isResolvable(node.output) ? ({
|
|
556
|
+
context,
|
|
557
|
+
event,
|
|
558
|
+
self
|
|
559
|
+
}) => evaluateResolvable(node.output, 'output', {
|
|
560
|
+
context,
|
|
561
|
+
event,
|
|
562
|
+
self
|
|
563
|
+
}, `$.states.${nodeKey}.output`) : node.output
|
|
564
|
+
};
|
|
565
|
+
}
|
|
1659
566
|
if (json.delays) {
|
|
1660
|
-
for (const key of Object.
|
|
1661
|
-
|
|
1662
|
-
if (typeof delay === 'number') {
|
|
1663
|
-
resolvedSources.delays[key] = delay;
|
|
1664
|
-
} else if (typeof delay === 'string') {
|
|
1665
|
-
resolvedSources.delays[key] = delayToMs(delay);
|
|
1666
|
-
} else if (delay && typeof delay === 'object') {
|
|
567
|
+
for (const [key, delay] of Object.entries(json.delays)) {
|
|
568
|
+
if (typeof delay === 'number') resolvedSources.delays[key] = delay;else if (typeof delay === 'string') resolvedSources.delays[key] = delayToMs(delay);else if (delay && typeof delay === 'object') {
|
|
1667
569
|
resolvedSources.delays[key] = args => delayToMs(resolveValue(delay.duration, 'delay', makeScope(args), `$.delays.${key}.duration`));
|
|
1668
570
|
}
|
|
1669
571
|
}
|
|
1670
572
|
}
|
|
1671
573
|
assertMachineJSON(json, resolvedSources, expressionResolver);
|
|
1672
|
-
const rootNodeConfig = iterNode(json);
|
|
1673
574
|
const contextConfig = json.context ? {
|
|
1674
575
|
context: args => resolveValue(json.context, 'context', args, '$.context')
|
|
1675
576
|
} : {};
|
|
1676
|
-
_scxmlMachineName = json.id || '';
|
|
1677
|
-
_scxmlSessionId = 'session_scxml';
|
|
1678
577
|
const machine = createMachine({
|
|
1679
|
-
...
|
|
578
|
+
...iterNode(json),
|
|
1680
579
|
...contextConfig,
|
|
1681
580
|
version: json.version
|
|
1682
581
|
});
|
|
1683
|
-
|
|
1684
|
-
// Register SCXML guard sources
|
|
1685
|
-
const providedGuards = {
|
|
1686
|
-
'scxml.cond': ({
|
|
1687
|
-
context,
|
|
1688
|
-
event,
|
|
1689
|
-
self
|
|
1690
|
-
}, params) => {
|
|
1691
|
-
const expr = params?.expr;
|
|
1692
|
-
if (!expr) return true;
|
|
1693
|
-
try {
|
|
1694
|
-
return !!evaluateExpr(context, expr, event, self);
|
|
1695
|
-
} catch (err) {
|
|
1696
|
-
// Per SCXML spec, a cond that fails to evaluate is treated as false
|
|
1697
|
-
// AND raises error.execution. We can't enqueue from a guard, so
|
|
1698
|
-
// queue it for the next entry to drain.
|
|
1699
|
-
const message = err instanceof Error ? err.message : typeof err === 'string' ? err : 'unknown error';
|
|
1700
|
-
pendingPlatformErrors.push({
|
|
1701
|
-
tagname: 'cond',
|
|
1702
|
-
message,
|
|
1703
|
-
line: NaN,
|
|
1704
|
-
column: NaN,
|
|
1705
|
-
reason: message
|
|
1706
|
-
});
|
|
1707
|
-
return false;
|
|
1708
|
-
}
|
|
1709
|
-
},
|
|
1710
|
-
'xstate.stateIn': (args, params) => {
|
|
1711
|
-
const stateId = params?.stateId;
|
|
1712
|
-
if (!stateId) return false;
|
|
1713
|
-
const normalizedId = stateId.replace(/^#/, '');
|
|
1714
|
-
const snapshot = args._snapshot;
|
|
1715
|
-
if (snapshot?.nodes) {
|
|
1716
|
-
return snapshot.nodes.some(node => node.id === normalizedId);
|
|
1717
|
-
}
|
|
1718
|
-
return false;
|
|
1719
|
-
},
|
|
1720
|
-
'xstate.not': (args, params) => {
|
|
1721
|
-
const inner = params?.guard;
|
|
1722
|
-
const innerImpl = inner && args.guards?.[inner.type];
|
|
1723
|
-
if (!innerImpl) {
|
|
1724
|
-
throw new Error(`Guard '${inner?.type}' referenced by 'xstate.not' is not implemented.`);
|
|
1725
|
-
}
|
|
1726
|
-
return !innerImpl(args, inner.params);
|
|
1727
|
-
}
|
|
1728
|
-
};
|
|
1729
582
|
const provided = machine.provide({
|
|
1730
583
|
actions: resolvedSources.actions,
|
|
1731
584
|
actors: resolvedSources.actors,
|
|
1732
585
|
guards: {
|
|
1733
|
-
|
|
586
|
+
'xstate.stateIn': (args, params) => {
|
|
587
|
+
const stateId = params?.stateId;
|
|
588
|
+
const snapshot = args._snapshot;
|
|
589
|
+
return !!stateId && !!snapshot?.nodes?.some(node => node.id === stateId.replace(/^#/, ''));
|
|
590
|
+
},
|
|
591
|
+
'xstate.not': (args, params) => {
|
|
592
|
+
const inner = params?.guard;
|
|
593
|
+
const impl = inner && args.guards?.[inner.type];
|
|
594
|
+
if (!impl) throw new Error(`Guard '${inner?.type}' referenced by 'xstate.not' is not implemented.`);
|
|
595
|
+
return !impl(args, inner.params);
|
|
596
|
+
},
|
|
1734
597
|
...resolvedSources.guards
|
|
1735
598
|
},
|
|
1736
599
|
delays: resolvedSources.delays
|
|
1737
600
|
});
|
|
1738
|
-
|
|
1739
|
-
// Keep the original JSON so `serializeMachine(machine)`
|
|
1740
|
-
// round-trip losslessly.
|
|
1741
601
|
provided._json = json;
|
|
1742
602
|
return provided;
|
|
1743
603
|
}
|
|
@@ -2626,134 +1486,6 @@ function toPromise(actor) {
|
|
|
2626
1486
|
});
|
|
2627
1487
|
}
|
|
2628
1488
|
|
|
2629
|
-
// this is needed to make JSDoc `@link` work properly
|
|
2630
|
-
// oxlint-disable-next-line no-unused-vars
|
|
2631
|
-
|
|
2632
|
-
/**
|
|
2633
|
-
* @remarks
|
|
2634
|
-
* `T | unknown` reduces to `unknown` and that can be problematic when it comes
|
|
2635
|
-
* to contextual typing. It especially is a problem when the union has a
|
|
2636
|
-
* function member, like here:
|
|
2637
|
-
*
|
|
2638
|
-
* ```ts
|
|
2639
|
-
* declare function test(
|
|
2640
|
-
* cbOrVal: ((arg: number) => unknown) | unknown
|
|
2641
|
-
* ): void;
|
|
2642
|
-
* test((arg) => {}); // oops, implicit any
|
|
2643
|
-
* ```
|
|
2644
|
-
*
|
|
2645
|
-
* This type can be used to avoid this problem. This union represents the same
|
|
2646
|
-
* value space as `unknown`.
|
|
2647
|
-
*/
|
|
2648
|
-
|
|
2649
|
-
// https://github.com/microsoft/TypeScript/issues/23182#issuecomment-379091887
|
|
2650
|
-
|
|
2651
|
-
// @TODO: we can't use native `NoInfer` as we need those:
|
|
2652
|
-
// https://github.com/microsoft/TypeScript/pull/61092
|
|
2653
|
-
// https://github.com/microsoft/TypeScript/pull/61077
|
|
2654
|
-
// but even with those fixes native NoInfer still doesn't work - further issues have to be reproduced and fixed
|
|
2655
|
-
|
|
2656
|
-
/** @deprecated Use the built-in `NoInfer` type instead */
|
|
2657
|
-
|
|
2658
|
-
/** The full definition of an event, with a string `type`. */
|
|
2659
|
-
|
|
2660
|
-
/**
|
|
2661
|
-
* The string or object representing the state value relative to the parent
|
|
2662
|
-
* state node.
|
|
2663
|
-
*
|
|
2664
|
-
* @remarks
|
|
2665
|
-
* - For a child atomic state node, this is a string, e.g., `"pending"`.
|
|
2666
|
-
* - For complex state nodes, this is an object, e.g., `{ success:
|
|
2667
|
-
* "someChildState" }`.
|
|
2668
|
-
*/
|
|
2669
|
-
|
|
2670
|
-
// Accept any StateNode instance regardless of generic parameters
|
|
2671
|
-
// Using a union type to handle variance issues with machine.resolveState
|
|
2672
|
-
|
|
2673
|
-
let SpecialTargets = /*#__PURE__*/function (SpecialTargets) {
|
|
2674
|
-
SpecialTargets["Internal"] = "#_internal";
|
|
2675
|
-
return SpecialTargets;
|
|
2676
|
-
}({});
|
|
2677
|
-
|
|
2678
|
-
/** A deterministic delayed-delivery declaration owned by a logic snapshot. */
|
|
2679
|
-
|
|
2680
|
-
/** The logical input delivered to a timer's source when its runtime delay ends. */
|
|
2681
|
-
|
|
2682
|
-
/** A persisted snapshot tied to a versioned actor logic identity. */
|
|
2683
|
-
|
|
2684
|
-
/**
|
|
2685
|
-
* A persisted snapshot restorable into the given actor logic: any snapshot
|
|
2686
|
-
* created by logic with the same machine `id` is accepted, regardless of
|
|
2687
|
-
* version (version mismatches are handled at runtime, e.g. by `migrate`).
|
|
2688
|
-
*/
|
|
2689
|
-
|
|
2690
|
-
/** @deprecated Use `AnyActor` instead. */
|
|
2691
|
-
|
|
2692
|
-
// Based on RxJS types
|
|
2693
|
-
|
|
2694
|
-
/**
|
|
2695
|
-
* A consumer-facing actor handle.
|
|
2696
|
-
*
|
|
2697
|
-
* `ActorRef` describes the contract a consumer needs: which events can be sent
|
|
2698
|
-
* to the actor, which snapshot it publishes for observation, and which emitted
|
|
2699
|
-
* events can be listened to. It intentionally does not expose lifecycle control
|
|
2700
|
-
* or runtime internals. A concrete `Actor` satisfies this interface, so APIs
|
|
2701
|
-
* should accept `ActorRef` whenever they only need to send events, read
|
|
2702
|
-
* snapshots, or listen to emitted events.
|
|
2703
|
-
*/
|
|
2704
|
-
|
|
2705
|
-
/**
|
|
2706
|
-
* Runtime-only actor capabilities.
|
|
2707
|
-
*
|
|
2708
|
-
* These members are needed by the interpreter, scheduler, inspection, and child
|
|
2709
|
-
* management code. Public consumer APIs should prefer `ActorRef` unless they
|
|
2710
|
-
* genuinely need lifecycle control such as starting, stopping, or accessing
|
|
2711
|
-
* system-owned runtime state.
|
|
2712
|
-
*/
|
|
2713
|
-
|
|
2714
|
-
/**
|
|
2715
|
-
* A concrete actor instance type.
|
|
2716
|
-
*
|
|
2717
|
-
* `ActorInstance` combines the consumer `ActorRef` contract with runtime
|
|
2718
|
-
* lifecycle capabilities. Values returned by `createActor(...)` and
|
|
2719
|
-
* `spawn(...)` naturally satisfy narrower `ActorRef` contracts.
|
|
2720
|
-
*/
|
|
2721
|
-
|
|
2722
|
-
/**
|
|
2723
|
-
* The actor's own full self handle.
|
|
2724
|
-
*
|
|
2725
|
-
* Internals and action/guard sources receive this shape because `self` can
|
|
2726
|
-
* participate in runtime-owned behavior while still being usable wherever an
|
|
2727
|
-
* `ActorRef` is expected.
|
|
2728
|
-
*/
|
|
2729
|
-
|
|
2730
|
-
// TODO: in v6, this should only accept AnyActorLogic, like ActorRefFromLogic
|
|
2731
|
-
|
|
2732
|
-
/** The concrete actor instance type produced from actor logic. */
|
|
2733
|
-
|
|
2734
|
-
/**
|
|
2735
|
-
* Represents logic which can be used by an actor.
|
|
2736
|
-
*
|
|
2737
|
-
* @template TSnapshot - The type of the snapshot.
|
|
2738
|
-
* @template TEvent - The type of the event object.
|
|
2739
|
-
* @template TInput - The type of the input.
|
|
2740
|
-
* @template TSystem - The type of the actor system.
|
|
2741
|
-
*/
|
|
2742
|
-
|
|
2743
|
-
// Actors that don't have literal string IDs — these are the only ones
|
|
2744
|
-
// that should appear in the index signature fallback, since actors with
|
|
2745
|
-
// literal IDs are already covered by ToConcreteChildren.
|
|
2746
|
-
|
|
2747
|
-
/** Maps state IDs to their input types based on the StateSchema. */
|
|
2748
|
-
|
|
2749
|
-
/** @deprecated */
|
|
2750
|
-
|
|
2751
|
-
/** The terminal result published when an actor completes or errors. */
|
|
2752
|
-
|
|
2753
|
-
/** An executable effect that publishes an actor's terminal result. */
|
|
2754
|
-
|
|
2755
|
-
/** Mappers for subscribeTo - maps lifecycle events to machine events */
|
|
2756
|
-
|
|
2757
1489
|
const defaultWaitForOptions = {
|
|
2758
1490
|
timeout: Infinity // much more than 10 seconds
|
|
2759
1491
|
};
|
|
@@ -2858,4 +1590,4 @@ function waitFor(actorRef, predicate, options) {
|
|
|
2858
1590
|
});
|
|
2859
1591
|
}
|
|
2860
1592
|
|
|
2861
|
-
export { SimulatedClock,
|
|
1593
|
+
export { SimulatedClock, assertEvent, createMachineFromConfig, createSystem, isTypeSchema, machineConfigToJSON, machineVersions, mapState, serializeMachine, setup, toPromise, types, waitFor };
|