xstate 6.0.0-alpha.2 → 6.0.0-alpha.21
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 +19 -17
- package/bin/xstate.js +36 -0
- package/dist/{StateMachine-64813f46.cjs.js → StateMachine-1b155670.cjs.js} +182 -40
- package/dist/{StateMachine-2dcdb1f5.esm.js → StateMachine-3c17fe3e.esm.js} +182 -40
- package/dist/{StateMachine-8d22a79c.development.cjs.js → StateMachine-550ff7f2.development.cjs.js} +193 -36
- package/dist/{StateMachine-2ea0a7fa.development.esm.js → StateMachine-e25dd61f.development.esm.js} +193 -36
- package/dist/declarations/src/State.d.ts +13 -2
- package/dist/declarations/src/StateMachine.d.ts +23 -13
- package/dist/declarations/src/actions.d.ts +2 -1
- package/dist/declarations/src/actors/promise.d.ts +4 -2
- package/dist/declarations/src/createActor.d.ts +9 -11
- package/dist/declarations/src/createMachine.d.ts +14 -11
- package/dist/declarations/src/createMachineFromConfig.d.ts +61 -28
- package/dist/declarations/src/fsm.d.ts +74 -0
- package/dist/declarations/src/graph/graph.d.ts +3 -3
- package/dist/declarations/src/graph/shortestPaths.d.ts +2 -2
- package/dist/declarations/src/graph/simplePaths.d.ts +2 -2
- package/dist/declarations/src/index.d.ts +6 -5
- package/dist/declarations/src/serialize.d.ts +10 -18
- package/dist/declarations/src/setup.d.ts +277 -65
- package/dist/declarations/src/spawn.d.ts +3 -3
- package/dist/declarations/src/stateUtils.d.ts +4 -1
- package/dist/declarations/src/system.d.ts +1 -1
- package/dist/declarations/src/transition.d.ts +8 -5
- package/dist/declarations/src/transitionActions.d.ts +12 -0
- package/dist/declarations/src/types.d.ts +237 -102
- package/dist/declarations/src/types.v6.d.ts +132 -58
- package/dist/declarations/src/utils.d.ts +4 -3
- package/dist/{index-93edd3bd.esm.js → index-3f87408c.esm.js} +936 -1389
- package/dist/{index-e61170ba.development.esm.js → index-d39fb138.development.esm.js} +968 -1421
- package/dist/{index-9cb3b3a0.cjs.js → index-e694228c.cjs.js} +945 -1394
- package/dist/{index-f6ef20d1.development.cjs.js → index-ec7c7a2d.development.cjs.js} +977 -1426
- package/dist/xstate-actors.cjs.js +1 -1
- package/dist/xstate-actors.development.cjs.js +1 -1
- package/dist/xstate-actors.development.esm.js +1 -1
- package/dist/xstate-actors.esm.js +1 -1
- package/dist/xstate-actors.umd.min.js +1 -1
- package/dist/xstate-actors.umd.min.js.map +1 -1
- package/dist/xstate-graph.cjs.js +2 -2
- package/dist/xstate-graph.development.cjs.js +2 -2
- package/dist/xstate-graph.development.esm.js +2 -2
- package/dist/xstate-graph.esm.js +2 -2
- package/dist/xstate-graph.umd.min.js +1 -1
- package/dist/xstate-graph.umd.min.js.map +1 -1
- package/dist/xstate.cjs.js +1100 -182
- package/dist/xstate.cjs.mjs +3 -5
- package/dist/xstate.development.cjs.js +1100 -182
- package/dist/xstate.development.cjs.mjs +3 -5
- package/dist/xstate.development.esm.js +1101 -181
- package/dist/xstate.esm.js +1101 -181
- package/dist/xstate.umd.min.js +1 -1
- package/dist/xstate.umd.min.js.map +1 -1
- package/package.json +6 -2
- package/dist/declarations/src/atom.d.ts +0 -81
package/dist/xstate.cjs.js
CHANGED
|
@@ -2,8 +2,8 @@
|
|
|
2
2
|
|
|
3
3
|
Object.defineProperty(exports, '__esModule', { value: true });
|
|
4
4
|
|
|
5
|
-
var dist_xstateActors = require('./index-
|
|
6
|
-
var StateMachine = require('./StateMachine-
|
|
5
|
+
var dist_xstateActors = require('./index-e694228c.cjs.js');
|
|
6
|
+
var StateMachine = require('./StateMachine-1b155670.cjs.js');
|
|
7
7
|
|
|
8
8
|
/**
|
|
9
9
|
* Asserts that the given event object is of the specified type or types. Throws
|
|
@@ -91,11 +91,354 @@ function createStateConfig(config) {
|
|
|
91
91
|
return config;
|
|
92
92
|
}
|
|
93
93
|
|
|
94
|
+
const emptyImplementations = {
|
|
95
|
+
actions: {},
|
|
96
|
+
actorSources: {},
|
|
97
|
+
guards: {},
|
|
98
|
+
delays: {}
|
|
99
|
+
};
|
|
100
|
+
const emptyExecutableActions = [];
|
|
101
|
+
const emptyRawActions = [];
|
|
102
|
+
const builtInActionSet = new Set(Object.values(dist_xstateActors.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
|
+
_stateInput: stateInput,
|
|
141
|
+
machine
|
|
142
|
+
};
|
|
143
|
+
}
|
|
144
|
+
function cloneSnapshot(snapshot, value, context, stateInput) {
|
|
145
|
+
return {
|
|
146
|
+
status: snapshot.status,
|
|
147
|
+
output: snapshot.output,
|
|
148
|
+
error: snapshot.error,
|
|
149
|
+
value,
|
|
150
|
+
context,
|
|
151
|
+
input: snapshot.input,
|
|
152
|
+
children: snapshot.children,
|
|
153
|
+
_stateInput: stateInput,
|
|
154
|
+
machine: snapshot.machine
|
|
155
|
+
};
|
|
156
|
+
}
|
|
157
|
+
function stopSnapshot(snapshot) {
|
|
158
|
+
return {
|
|
159
|
+
status: 'stopped',
|
|
160
|
+
output: undefined,
|
|
161
|
+
error: undefined,
|
|
162
|
+
value: snapshot.value,
|
|
163
|
+
context: snapshot.context,
|
|
164
|
+
input: undefined,
|
|
165
|
+
children: snapshot.children,
|
|
166
|
+
_stateInput: snapshot._stateInput,
|
|
167
|
+
machine: snapshot.machine
|
|
168
|
+
};
|
|
169
|
+
}
|
|
170
|
+
function assertNoStringTransitions(config) {
|
|
171
|
+
for (const [stateKey, stateConfig] of Object.entries(config.states)) {
|
|
172
|
+
for (const [eventType, transitionConfig] of Object.entries(stateConfig.on ?? {})) {
|
|
173
|
+
for (const transition of toArray(transitionConfig)) {
|
|
174
|
+
if (typeof transition === 'string') {
|
|
175
|
+
const target = transition;
|
|
176
|
+
throw new Error(`Invalid transition for "${stateKey}.${eventType}": use { target: "${target}" } instead of a string target.`);
|
|
177
|
+
}
|
|
178
|
+
}
|
|
179
|
+
}
|
|
180
|
+
}
|
|
181
|
+
}
|
|
182
|
+
function resolveSimpleEnqueuedActions(rawActions) {
|
|
183
|
+
const executableActions = [];
|
|
184
|
+
for (const action of rawActions) {
|
|
185
|
+
if (!action || typeof action !== 'object' || !('action' in action) || typeof action.action !== 'function' || builtInActionSet.has(action.action) || '_special' in action.action) {
|
|
186
|
+
return undefined;
|
|
187
|
+
}
|
|
188
|
+
executableActions.push({
|
|
189
|
+
type: action.action.name || '(anonymous)',
|
|
190
|
+
params: undefined,
|
|
191
|
+
args: action.args,
|
|
192
|
+
exec: action.args.length ? action.action.bind(null, ...action.args) : action.action
|
|
193
|
+
});
|
|
194
|
+
}
|
|
195
|
+
return executableActions;
|
|
196
|
+
}
|
|
197
|
+
function createFSM(config) {
|
|
198
|
+
const machine = {
|
|
199
|
+
id: config.id ?? '(fsm)',
|
|
200
|
+
implementations: emptyImplementations
|
|
201
|
+
};
|
|
202
|
+
assertNoStringTransitions(config);
|
|
203
|
+
const runActions = (snapshot, event, actorScope, rawActions) => {
|
|
204
|
+
if (!rawActions?.length) {
|
|
205
|
+
return [snapshot, emptyExecutableActions];
|
|
206
|
+
}
|
|
207
|
+
const simpleExecutableActions = resolveSimpleEnqueuedActions(rawActions);
|
|
208
|
+
if (simpleExecutableActions) {
|
|
209
|
+
return [snapshot, simpleExecutableActions];
|
|
210
|
+
}
|
|
211
|
+
return dist_xstateActors.resolveActionsWithContext(snapshot, event, actorScope, rawActions);
|
|
212
|
+
};
|
|
213
|
+
const runStateActions = (snapshot, event, actorScope, actionsConfig, stateInput, internalQueue) => {
|
|
214
|
+
if (!actionsConfig) {
|
|
215
|
+
return [snapshot, emptyExecutableActions];
|
|
216
|
+
}
|
|
217
|
+
const actions = [];
|
|
218
|
+
const enq = dist_xstateActors.createTransitionEnqueue(actorScope, actions, internalQueue, true);
|
|
219
|
+
let context;
|
|
220
|
+
const actionCount = Array.isArray(actionsConfig) ? actionsConfig.length : 1;
|
|
221
|
+
for (let i = 0; i < actionCount; i++) {
|
|
222
|
+
const action = Array.isArray(actionsConfig) ? actionsConfig[i] : actionsConfig;
|
|
223
|
+
const result = action({
|
|
224
|
+
context: context ?? snapshot.context,
|
|
225
|
+
event: event,
|
|
226
|
+
input: stateInput,
|
|
227
|
+
value: snapshot.value,
|
|
228
|
+
self: actorScope.self,
|
|
229
|
+
system: actorScope.system,
|
|
230
|
+
parent: actorScope.self._parent,
|
|
231
|
+
children: snapshot.children
|
|
232
|
+
}, enq);
|
|
233
|
+
if (result?.context !== undefined) {
|
|
234
|
+
const currentContext = context ?? snapshot.context;
|
|
235
|
+
const nextContext = mergeContextPatch(currentContext, result.context);
|
|
236
|
+
if (nextContext !== currentContext) {
|
|
237
|
+
context = nextContext;
|
|
238
|
+
}
|
|
239
|
+
}
|
|
240
|
+
}
|
|
241
|
+
const nextSnapshot = context !== undefined ? cloneSnapshot(snapshot, snapshot.value, context, snapshot._stateInput) : snapshot;
|
|
242
|
+
return runActions(nextSnapshot, event, actorScope, actions);
|
|
243
|
+
};
|
|
244
|
+
const selectTransition = (snapshot, event, actorScope, internalQueue) => {
|
|
245
|
+
const state = config.states[snapshot.value];
|
|
246
|
+
const transitionsConfig = state?.on?.[event.type];
|
|
247
|
+
if (!transitionsConfig) {
|
|
248
|
+
return undefined;
|
|
249
|
+
}
|
|
250
|
+
const transitionCount = Array.isArray(transitionsConfig) ? transitionsConfig.length : 1;
|
|
251
|
+
for (let i = 0; i < transitionCount; i++) {
|
|
252
|
+
const transition = Array.isArray(transitionsConfig) ? transitionsConfig[i] : transitionsConfig;
|
|
253
|
+
const args = {
|
|
254
|
+
context: snapshot.context,
|
|
255
|
+
event,
|
|
256
|
+
input: snapshot.input,
|
|
257
|
+
value: snapshot.value,
|
|
258
|
+
self: actorScope.self,
|
|
259
|
+
system: actorScope.system,
|
|
260
|
+
parent: actorScope.self._parent,
|
|
261
|
+
children: snapshot.children
|
|
262
|
+
};
|
|
263
|
+
if (typeof transition === 'function') {
|
|
264
|
+
const actions = [];
|
|
265
|
+
const enq = dist_xstateActors.createTransitionEnqueue(actorScope, actions, internalQueue, true);
|
|
266
|
+
const result = transition(args, enq);
|
|
267
|
+
if (!result) {
|
|
268
|
+
if (actions.length) {
|
|
269
|
+
return {
|
|
270
|
+
actions
|
|
271
|
+
};
|
|
272
|
+
}
|
|
273
|
+
continue;
|
|
274
|
+
}
|
|
275
|
+
return {
|
|
276
|
+
target: result.target,
|
|
277
|
+
context: result.context,
|
|
278
|
+
input: result.input,
|
|
279
|
+
actions
|
|
280
|
+
};
|
|
281
|
+
}
|
|
282
|
+
if ('guard' in transition && transition.guard && !transition.guard(args)) {
|
|
283
|
+
continue;
|
|
284
|
+
}
|
|
285
|
+
return {
|
|
286
|
+
target: transition.target,
|
|
287
|
+
context: resolveTransitionContext(transition.context, args),
|
|
288
|
+
input: transition.input,
|
|
289
|
+
actions: 'actions' in transition && transition.actions ? toArray(transition.actions) : emptyRawActions
|
|
290
|
+
};
|
|
291
|
+
}
|
|
292
|
+
return undefined;
|
|
293
|
+
};
|
|
294
|
+
const transitionCore = (snapshot, event, actorScope) => {
|
|
295
|
+
if (snapshot.status !== 'active') {
|
|
296
|
+
return [snapshot, []];
|
|
297
|
+
}
|
|
298
|
+
if (event.type === dist_xstateActors.XSTATE_STOP) {
|
|
299
|
+
return [stopSnapshot(snapshot), emptyExecutableActions];
|
|
300
|
+
}
|
|
301
|
+
const stateConfig = config.states[snapshot.value];
|
|
302
|
+
const directTransition = stateConfig?.on?.[event.type];
|
|
303
|
+
if (!directTransition) {
|
|
304
|
+
return [snapshot, emptyExecutableActions];
|
|
305
|
+
}
|
|
306
|
+
if (!Array.isArray(directTransition) && typeof directTransition !== 'function' && !('guard' in directTransition) && !('actions' in directTransition && directTransition.actions) && typeof directTransition.input !== 'function') {
|
|
307
|
+
const target = directTransition.target ?? snapshot.value;
|
|
308
|
+
const stateChanged = target !== snapshot.value;
|
|
309
|
+
if (stateChanged && (stateConfig.exit || config.states[target]?.entry)) ; else {
|
|
310
|
+
const hasContext = directTransition.context !== undefined;
|
|
311
|
+
const hasInput = directTransition.input !== undefined;
|
|
312
|
+
const resolvedContext = resolveTransitionContext(directTransition.context, {
|
|
313
|
+
context: snapshot.context,
|
|
314
|
+
event,
|
|
315
|
+
input: snapshot.input,
|
|
316
|
+
value: snapshot.value,
|
|
317
|
+
self: actorScope.self,
|
|
318
|
+
system: actorScope.system,
|
|
319
|
+
parent: actorScope.self._parent,
|
|
320
|
+
children: snapshot.children
|
|
321
|
+
});
|
|
322
|
+
const context = hasContext && resolvedContext ? mergeContextPatch(snapshot.context, resolvedContext) : snapshot.context;
|
|
323
|
+
if (!stateChanged && context === snapshot.context && !hasInput && snapshot._stateInput === undefined) {
|
|
324
|
+
return [snapshot, emptyExecutableActions];
|
|
325
|
+
}
|
|
326
|
+
return [cloneSnapshot(snapshot, target, context, hasInput ? resolveInput(directTransition.input, context, event) : undefined), emptyExecutableActions];
|
|
327
|
+
}
|
|
328
|
+
}
|
|
329
|
+
if (typeof directTransition === 'function' && directTransition.length < 2 && !stateConfig?.exit) {
|
|
330
|
+
const result = directTransition({
|
|
331
|
+
context: snapshot.context,
|
|
332
|
+
event,
|
|
333
|
+
input: snapshot.input,
|
|
334
|
+
value: snapshot.value,
|
|
335
|
+
self: actorScope.self,
|
|
336
|
+
system: actorScope.system,
|
|
337
|
+
parent: actorScope.self._parent,
|
|
338
|
+
children: snapshot.children
|
|
339
|
+
}, undefined);
|
|
340
|
+
if (result) {
|
|
341
|
+
const target = result.target ?? snapshot.value;
|
|
342
|
+
if (!config.states[target]?.entry) {
|
|
343
|
+
const hasContext = result.context !== undefined;
|
|
344
|
+
const hasInput = result.input !== undefined;
|
|
345
|
+
const context = hasContext && result.context ? mergeContextPatch(snapshot.context, result.context) : snapshot.context;
|
|
346
|
+
if (target === snapshot.value && context === snapshot.context && !hasInput && snapshot._stateInput === undefined) {
|
|
347
|
+
return [snapshot, emptyExecutableActions];
|
|
348
|
+
}
|
|
349
|
+
return [cloneSnapshot(snapshot, target, context, hasInput ? resolveInput(result.input, context, event) : undefined), emptyExecutableActions];
|
|
350
|
+
}
|
|
351
|
+
}
|
|
352
|
+
}
|
|
353
|
+
let nextSnapshot = snapshot;
|
|
354
|
+
const executableActions = [];
|
|
355
|
+
const internalQueue = [event];
|
|
356
|
+
let iterations = 0;
|
|
357
|
+
while (internalQueue.length) {
|
|
358
|
+
if (++iterations > 1000) {
|
|
359
|
+
throw new Error('FSM microstep count exceeded 1000');
|
|
360
|
+
}
|
|
361
|
+
const nextEvent = internalQueue.shift();
|
|
362
|
+
const selected = selectTransition(nextSnapshot, nextEvent, actorScope, internalQueue);
|
|
363
|
+
if (!selected) {
|
|
364
|
+
continue;
|
|
365
|
+
}
|
|
366
|
+
const nextValue = selected.target ?? nextSnapshot.value;
|
|
367
|
+
const stateChanged = nextValue !== nextSnapshot.value;
|
|
368
|
+
if (stateChanged) {
|
|
369
|
+
const [exited, exitActions] = runStateActions(nextSnapshot, nextEvent, actorScope, config.states[nextSnapshot.value]?.exit, nextSnapshot._stateInput, internalQueue);
|
|
370
|
+
nextSnapshot = exited;
|
|
371
|
+
executableActions.push(...exitActions);
|
|
372
|
+
}
|
|
373
|
+
let context = nextSnapshot.context;
|
|
374
|
+
if (selected.context !== undefined) {
|
|
375
|
+
context = mergeContextPatch(context, selected.context);
|
|
376
|
+
}
|
|
377
|
+
const hasInput = selected.input !== undefined;
|
|
378
|
+
const stateInput = hasInput ? resolveInput(selected.input, context, nextEvent) : undefined;
|
|
379
|
+
if (stateChanged || context !== nextSnapshot.context || hasInput || nextSnapshot._stateInput !== undefined) {
|
|
380
|
+
nextSnapshot = cloneSnapshot(nextSnapshot, nextValue, context, stateInput);
|
|
381
|
+
}
|
|
382
|
+
const [afterTransition, transitionActions] = runActions(nextSnapshot, nextEvent, actorScope, selected.actions);
|
|
383
|
+
nextSnapshot = afterTransition;
|
|
384
|
+
executableActions.push(...transitionActions);
|
|
385
|
+
if (stateChanged) {
|
|
386
|
+
const [entered, entryActions] = runStateActions(nextSnapshot, nextEvent, actorScope, config.states[nextValue]?.entry, stateInput, internalQueue);
|
|
387
|
+
nextSnapshot = entered;
|
|
388
|
+
executableActions.push(...entryActions);
|
|
389
|
+
}
|
|
390
|
+
}
|
|
391
|
+
return [nextSnapshot, executableActions];
|
|
392
|
+
};
|
|
393
|
+
const transition = (...args) => {
|
|
394
|
+
const [nextSnapshot, effects] = transitionCore(...args);
|
|
395
|
+
return [nextSnapshot, [...effects, ...dist_xstateActors.deriveDeferredStarts(effects)]];
|
|
396
|
+
};
|
|
397
|
+
const logic = {
|
|
398
|
+
id: config.id,
|
|
399
|
+
config,
|
|
400
|
+
transition,
|
|
401
|
+
initialTransition: (input, actorScope) => {
|
|
402
|
+
const context = resolveContext(config.context, input);
|
|
403
|
+
const snapshot = createSnapshot(config.initial, context, input, machine);
|
|
404
|
+
const internalQueue = [];
|
|
405
|
+
let [nextSnapshot, actions] = runStateActions(snapshot, {
|
|
406
|
+
type: dist_xstateActors.XSTATE_INIT
|
|
407
|
+
}, actorScope, config.states[config.initial]?.entry, undefined, internalQueue);
|
|
408
|
+
if (!actions.length) {
|
|
409
|
+
actions = [];
|
|
410
|
+
}
|
|
411
|
+
while (internalQueue.length) {
|
|
412
|
+
const [raisedSnapshot, raisedActions] = transitionCore(nextSnapshot, internalQueue.shift(), actorScope);
|
|
413
|
+
nextSnapshot = raisedSnapshot;
|
|
414
|
+
actions.push(...raisedActions);
|
|
415
|
+
}
|
|
416
|
+
return [nextSnapshot, [...actions, ...dist_xstateActors.deriveDeferredStarts(actions)]];
|
|
417
|
+
},
|
|
418
|
+
getInitialSnapshot: (actorScope, input) => logic.initialTransition(input, actorScope)[0],
|
|
419
|
+
getPersistedSnapshot: ({
|
|
420
|
+
machine: _,
|
|
421
|
+
...snapshot
|
|
422
|
+
}) => snapshot,
|
|
423
|
+
restoreSnapshot: snapshot => ({
|
|
424
|
+
...snapshot,
|
|
425
|
+
machine: machine
|
|
426
|
+
})
|
|
427
|
+
};
|
|
428
|
+
return logic;
|
|
429
|
+
}
|
|
430
|
+
|
|
94
431
|
function delayToMs(delay) {
|
|
95
432
|
const parsedDelay = dist_xstateActors.parseDelayToMilliseconds(delay);
|
|
96
433
|
if (parsedDelay !== undefined) return parsedDelay;
|
|
97
434
|
return typeof delay === 'string' ? parseFloat(delay) || 0 : delay;
|
|
98
435
|
}
|
|
436
|
+
function normalizeScxmlEventType(eventType) {
|
|
437
|
+
return /^error(\.|$)/.test(eventType) ? `xstate.${eventType}` : eventType;
|
|
438
|
+
}
|
|
439
|
+
function toScxmlEventName(eventType) {
|
|
440
|
+
return eventType.startsWith('xstate.error.') ? eventType.slice('xstate.'.length) : eventType;
|
|
441
|
+
}
|
|
99
442
|
|
|
100
443
|
/**
|
|
101
444
|
* Isolated executable-content block. Errors in nested actions stop this block
|
|
@@ -103,48 +446,23 @@ function delayToMs(delay) {
|
|
|
103
446
|
* separate <onentry>/<onexit> blocks: each is its own block per spec.
|
|
104
447
|
*/
|
|
105
448
|
|
|
106
|
-
function
|
|
107
|
-
return !!value && typeof value === 'object' &&
|
|
449
|
+
function isExpression(value) {
|
|
450
|
+
return !!value && typeof value === 'object' && typeof value['@expr'] === 'string';
|
|
108
451
|
}
|
|
109
|
-
function
|
|
110
|
-
|
|
111
|
-
if (value.$unserializable === 'actor' && path.endsWith('.src')) {
|
|
112
|
-
return;
|
|
113
|
-
}
|
|
114
|
-
throw new Error(`Unresolved ${value.$unserializable} at ${path}`);
|
|
115
|
-
}
|
|
116
|
-
if (!value || typeof value !== 'object') {
|
|
117
|
-
return;
|
|
118
|
-
}
|
|
119
|
-
if (Array.isArray(value)) {
|
|
120
|
-
value.forEach((item, index) => assertNoUnresolvedMarkers(item, `${path}[${index}]`));
|
|
121
|
-
return;
|
|
122
|
-
}
|
|
123
|
-
for (const key of Object.keys(value)) {
|
|
124
|
-
const child = value[key];
|
|
125
|
-
const isImplementationMarker = path === '$' && (key === 'actions' || key === 'guards' || key === 'actors' || key === 'delays' || key === 'schemas');
|
|
126
|
-
if (isImplementationMarker) {
|
|
127
|
-
continue;
|
|
128
|
-
}
|
|
129
|
-
assertNoUnresolvedMarkers(child, `${path}.${key}`);
|
|
130
|
-
}
|
|
452
|
+
function isCode(value) {
|
|
453
|
+
return !!value && typeof value === 'object' && typeof value['@code'] === 'string';
|
|
131
454
|
}
|
|
132
|
-
function
|
|
133
|
-
|
|
134
|
-
|
|
135
|
-
|
|
136
|
-
|
|
137
|
-
|
|
138
|
-
|
|
139
|
-
|
|
140
|
-
|
|
141
|
-
|
|
142
|
-
|
|
143
|
-
if (!implementations[kind]?.[key]) {
|
|
144
|
-
throw new Error(`Missing ${kind}.${key}`);
|
|
145
|
-
}
|
|
146
|
-
}
|
|
147
|
-
}
|
|
455
|
+
function isResolvable(value) {
|
|
456
|
+
return isExpression(value) || isCode(value);
|
|
457
|
+
}
|
|
458
|
+
function isBuiltInActionType(type) {
|
|
459
|
+
return type.startsWith('@xstate.');
|
|
460
|
+
}
|
|
461
|
+
function isScxmlActionType(type) {
|
|
462
|
+
return type.startsWith('scxml.');
|
|
463
|
+
}
|
|
464
|
+
function toPath(parent, key) {
|
|
465
|
+
return typeof key === 'number' ? `${parent}[${key}]` : `${parent}.${key}`;
|
|
148
466
|
}
|
|
149
467
|
function extractSerializableDelays(delays) {
|
|
150
468
|
const result = {};
|
|
@@ -155,6 +473,8 @@ function extractSerializableDelays(delays) {
|
|
|
155
473
|
const value = delays[key];
|
|
156
474
|
if (typeof value === 'number') {
|
|
157
475
|
result[key] = value;
|
|
476
|
+
} else if (value && typeof value === 'object' && typeof value.duration === 'number') {
|
|
477
|
+
result[key] = value.duration;
|
|
158
478
|
}
|
|
159
479
|
}
|
|
160
480
|
return result;
|
|
@@ -163,14 +483,254 @@ function mergeImplementations(json, implementations) {
|
|
|
163
483
|
return {
|
|
164
484
|
actions: implementations.actions ?? {},
|
|
165
485
|
guards: implementations.guards ?? {},
|
|
166
|
-
|
|
486
|
+
actorSources: implementations.actorSources ?? {},
|
|
167
487
|
delays: {
|
|
168
488
|
...extractSerializableDelays(json.delays),
|
|
169
489
|
...(implementations.delays ?? {})
|
|
490
|
+
},
|
|
491
|
+
evaluators: implementations.evaluators ?? {}
|
|
492
|
+
};
|
|
493
|
+
}
|
|
494
|
+
function createExpressionResolver(expressionLanguage, implementations) {
|
|
495
|
+
function getEvaluator(value, path) {
|
|
496
|
+
const lang = value['@lang'] ?? expressionLanguage;
|
|
497
|
+
if (!lang) {
|
|
498
|
+
throw new Error(`Missing @exprLang for expression at ${path}`);
|
|
499
|
+
}
|
|
500
|
+
const evaluator = implementations.evaluators[lang];
|
|
501
|
+
if (!evaluator) {
|
|
502
|
+
throw new Error(`Missing evaluator for @lang '${lang}' at ${path}`);
|
|
503
|
+
}
|
|
504
|
+
return evaluator;
|
|
505
|
+
}
|
|
506
|
+
function evaluateResolvable(value, slot, scope, path) {
|
|
507
|
+
const kind = isExpression(value) ? 'expr' : 'code';
|
|
508
|
+
const source = isExpression(value) ? value['@expr'] : value['@code'];
|
|
509
|
+
return getEvaluator(value, path)({
|
|
510
|
+
source,
|
|
511
|
+
kind,
|
|
512
|
+
slot,
|
|
513
|
+
scope,
|
|
514
|
+
path
|
|
515
|
+
});
|
|
516
|
+
}
|
|
517
|
+
function resolveValue(value, slot, scope, path) {
|
|
518
|
+
if (isResolvable(value)) {
|
|
519
|
+
return evaluateResolvable(value, slot, scope, path);
|
|
520
|
+
}
|
|
521
|
+
if (Array.isArray(value)) {
|
|
522
|
+
return value.map((item, index) => resolveValue(item, slot, scope, toPath(path, index)));
|
|
523
|
+
}
|
|
524
|
+
if (!value || typeof value !== 'object') {
|
|
525
|
+
return value;
|
|
526
|
+
}
|
|
527
|
+
const result = {};
|
|
528
|
+
for (const key of Object.keys(value)) {
|
|
529
|
+
result[key] = resolveValue(value[key], slot, scope, toPath(path, key));
|
|
170
530
|
}
|
|
531
|
+
return result;
|
|
532
|
+
}
|
|
533
|
+
function makeScope(x, extra) {
|
|
534
|
+
return {
|
|
535
|
+
context: x.context,
|
|
536
|
+
event: x.event,
|
|
537
|
+
input: x.input,
|
|
538
|
+
self: x.self,
|
|
539
|
+
children: x.children,
|
|
540
|
+
params: x.params,
|
|
541
|
+
...extra
|
|
542
|
+
};
|
|
543
|
+
}
|
|
544
|
+
function getDurationConfig(value, path) {
|
|
545
|
+
if (!isResolvable(value)) {
|
|
546
|
+
return value;
|
|
547
|
+
}
|
|
548
|
+
return args => delayToMs(resolveValue(value, 'delay', makeScope(args), path));
|
|
549
|
+
}
|
|
550
|
+
function assertResolvable(value, path) {
|
|
551
|
+
if (isResolvable(value)) {
|
|
552
|
+
getEvaluator(value, path);
|
|
553
|
+
return;
|
|
554
|
+
}
|
|
555
|
+
if (Array.isArray(value)) {
|
|
556
|
+
value.forEach((item, index) => assertResolvable(item, toPath(path, index)));
|
|
557
|
+
return;
|
|
558
|
+
}
|
|
559
|
+
if (!value || typeof value !== 'object') {
|
|
560
|
+
return;
|
|
561
|
+
}
|
|
562
|
+
for (const key of Object.keys(value)) {
|
|
563
|
+
assertResolvable(value[key], toPath(path, key));
|
|
564
|
+
}
|
|
565
|
+
}
|
|
566
|
+
return {
|
|
567
|
+
evaluateResolvable,
|
|
568
|
+
resolveValue,
|
|
569
|
+
makeScope,
|
|
570
|
+
getDurationConfig,
|
|
571
|
+
assertResolvable
|
|
171
572
|
};
|
|
172
573
|
}
|
|
173
|
-
|
|
574
|
+
function toActionArray(actions) {
|
|
575
|
+
return actions === undefined ? [] : Array.isArray(actions) ? actions : [actions];
|
|
576
|
+
}
|
|
577
|
+
function validateChoiceConfig(choice, path) {
|
|
578
|
+
if (!Array.isArray(choice)) {
|
|
579
|
+
return;
|
|
580
|
+
}
|
|
581
|
+
choice.forEach((branch, index) => {
|
|
582
|
+
if (branch.when === undefined && index !== choice.length - 1) {
|
|
583
|
+
throw new Error(`Choice fallback branch at ${path}[${index}] must be last.`);
|
|
584
|
+
}
|
|
585
|
+
});
|
|
586
|
+
}
|
|
587
|
+
function assertMachineJSON(json, resolvedImplementations, expressionResolver) {
|
|
588
|
+
const {
|
|
589
|
+
assertResolvable
|
|
590
|
+
} = expressionResolver;
|
|
591
|
+
function assertCondition(condition, path) {
|
|
592
|
+
if (!condition) {
|
|
593
|
+
return;
|
|
594
|
+
}
|
|
595
|
+
if (isResolvable(condition)) {
|
|
596
|
+
assertResolvable(condition, path);
|
|
597
|
+
return;
|
|
598
|
+
}
|
|
599
|
+
assertResolvable(condition.params, `${path}.params`);
|
|
600
|
+
if (json.guards?.[condition.type]) {
|
|
601
|
+
assertCondition(json.guards[condition.type].when, `$.guards.${condition.type}.when`);
|
|
602
|
+
return;
|
|
603
|
+
}
|
|
604
|
+
if (!resolvedImplementations.guards[condition.type] && !['scxml.cond', 'xstate.stateIn', 'xstate.not'].includes(condition.type)) {
|
|
605
|
+
throw new Error(`Missing guard implementation "${condition.type}"`);
|
|
606
|
+
}
|
|
607
|
+
}
|
|
608
|
+
function assertAction(action, path, stack = []) {
|
|
609
|
+
if (isResolvable(action)) {
|
|
610
|
+
assertResolvable(action, path);
|
|
611
|
+
return;
|
|
612
|
+
}
|
|
613
|
+
if (!action || typeof action.type !== 'string') {
|
|
614
|
+
throw new Error(`Invalid action at ${path}`);
|
|
615
|
+
}
|
|
616
|
+
assertResolvable(action.params, `${path}.params`);
|
|
617
|
+
if (isBuiltInActionType(action.type) || isScxmlActionType(action.type)) {
|
|
618
|
+
assertResolvable(action, path);
|
|
619
|
+
return;
|
|
620
|
+
}
|
|
621
|
+
const definition = json.actions?.[action.type];
|
|
622
|
+
if (definition) {
|
|
623
|
+
if (stack.includes(action.type)) {
|
|
624
|
+
throw new Error(`Circular action reference: ${stack.concat(action.type).join(' -> ')}`);
|
|
625
|
+
}
|
|
626
|
+
const definitions = Array.isArray(definition) ? definition : [definition];
|
|
627
|
+
definitions.forEach((item, index) => assertAction(item, `${path}.actions.${action.type}${definitions.length > 1 ? `[${index}]` : ''}`, stack.concat(action.type)));
|
|
628
|
+
return;
|
|
629
|
+
}
|
|
630
|
+
if (!resolvedImplementations.actions[action.type]) {
|
|
631
|
+
throw new Error(`Missing action implementation "${action.type}"`);
|
|
632
|
+
}
|
|
633
|
+
}
|
|
634
|
+
function assertActions(actions, path) {
|
|
635
|
+
toActionArray(actions).forEach((action, index) => assertAction(action, `${path}[${index}]`));
|
|
636
|
+
}
|
|
637
|
+
function assertTransition(transition, path) {
|
|
638
|
+
const transitions = Array.isArray(transition) ? transition : transition ? [transition] : [];
|
|
639
|
+
transitions.forEach((t, index) => {
|
|
640
|
+
const transitionPath = Array.isArray(transition) ? `${path}[${index}]` : path;
|
|
641
|
+
if (isResolvable(t)) {
|
|
642
|
+
assertResolvable(t, transitionPath);
|
|
643
|
+
return;
|
|
644
|
+
}
|
|
645
|
+
assertCondition(t.guard, `${transitionPath}.guard`);
|
|
646
|
+
assertActions(t.actions, `${transitionPath}.actions`);
|
|
647
|
+
assertResolvable(t.context, `${transitionPath}.context`);
|
|
648
|
+
assertResolvable(t.input, `${transitionPath}.input`);
|
|
649
|
+
});
|
|
650
|
+
}
|
|
651
|
+
function assertStateNode(node, path) {
|
|
652
|
+
assertResolvable(node.context, `${path}.context`);
|
|
653
|
+
assertResolvable(node.input, `${path}.input`);
|
|
654
|
+
assertResolvable(node.output, `${path}.output`);
|
|
655
|
+
assertResolvable(node.timeout, `${path}.timeout`);
|
|
656
|
+
assertActions(node.entry, `${path}.entry`);
|
|
657
|
+
assertActions(node.exit, `${path}.exit`);
|
|
658
|
+
if (node.type === 'choice') {
|
|
659
|
+
if (!node.choice) {
|
|
660
|
+
throw new Error(`Choice state at ${path} must declare choice.`);
|
|
661
|
+
}
|
|
662
|
+
if (Array.isArray(node.choice)) {
|
|
663
|
+
validateChoiceConfig(node.choice, `${path}.choice`);
|
|
664
|
+
node.choice.forEach((branch, index) => {
|
|
665
|
+
assertCondition(branch.when, `${path}.choice[${index}].when`);
|
|
666
|
+
assertResolvable(branch.context, `${path}.choice[${index}].context`);
|
|
667
|
+
assertResolvable(branch.input, `${path}.choice[${index}].input`);
|
|
668
|
+
});
|
|
669
|
+
} else {
|
|
670
|
+
assertResolvable(node.choice, `${path}.choice`);
|
|
671
|
+
}
|
|
672
|
+
}
|
|
673
|
+
if (isResolvable(node.route)) {
|
|
674
|
+
assertResolvable(node.route, `${path}.route`);
|
|
675
|
+
}
|
|
676
|
+
if (node.invoke) {
|
|
677
|
+
const invokes = Array.isArray(node.invoke) ? node.invoke : [node.invoke];
|
|
678
|
+
invokes.forEach((invoke, index) => {
|
|
679
|
+
const invokePath = `${path}.invoke${Array.isArray(node.invoke) ? `[${index}]` : ''}`;
|
|
680
|
+
const extInv = invoke;
|
|
681
|
+
if (!extInv._nestedMachineJSON && !resolvedImplementations.actorSources[invoke.src]) {
|
|
682
|
+
throw new Error(`Missing actorSource implementation "${invoke.src}"`);
|
|
683
|
+
}
|
|
684
|
+
assertResolvable(invoke.input, `${invokePath}.input`);
|
|
685
|
+
assertResolvable(invoke.timeout, `${invokePath}.timeout`);
|
|
686
|
+
assertTransition(invoke.onDone, `${invokePath}.onDone`);
|
|
687
|
+
assertTransition(invoke.onError, `${invokePath}.onError`);
|
|
688
|
+
assertTransition(invoke.onSnapshot, `${invokePath}.onSnapshot`);
|
|
689
|
+
assertTransition(invoke.onTimeout, `${invokePath}.onTimeout`);
|
|
690
|
+
});
|
|
691
|
+
}
|
|
692
|
+
if (node.on) {
|
|
693
|
+
for (const descriptor of Object.keys(node.on)) {
|
|
694
|
+
assertTransition(node.on[descriptor], `${path}.on.${descriptor}`);
|
|
695
|
+
}
|
|
696
|
+
}
|
|
697
|
+
if (node.after) {
|
|
698
|
+
for (const delay of Object.keys(node.after)) {
|
|
699
|
+
if (Number.isNaN(Number(delay)) && dist_xstateActors.parseDelayToMilliseconds(delay) === undefined && !json.delays?.[delay] && !resolvedImplementations.delays[delay]) {
|
|
700
|
+
throw new Error(`Missing delay implementation "${delay}"`);
|
|
701
|
+
}
|
|
702
|
+
assertTransition(node.after[delay], `${path}.after.${delay}`);
|
|
703
|
+
}
|
|
704
|
+
}
|
|
705
|
+
assertTransition(node.always, `${path}.always`);
|
|
706
|
+
assertTransition(node.onError, `${path}.onError`);
|
|
707
|
+
assertTransition(node.onTimeout, `${path}.onTimeout`);
|
|
708
|
+
if (node.states) {
|
|
709
|
+
for (const key of Object.keys(node.states)) {
|
|
710
|
+
assertStateNode(node.states[key], `${path}.states.${key}`);
|
|
711
|
+
}
|
|
712
|
+
}
|
|
713
|
+
}
|
|
714
|
+
if (json.actions) {
|
|
715
|
+
for (const key of Object.keys(json.actions)) {
|
|
716
|
+
const actions = Array.isArray(json.actions[key]) ? json.actions[key] : [json.actions[key]];
|
|
717
|
+
actions.forEach((action, index) => assertAction(action, `$.actions.${key}${actions.length > 1 ? `[${index}]` : ''}`, [key]));
|
|
718
|
+
}
|
|
719
|
+
}
|
|
720
|
+
if (json.guards) {
|
|
721
|
+
for (const key of Object.keys(json.guards)) {
|
|
722
|
+
assertCondition(json.guards[key].when, `$.guards.${key}.when`);
|
|
723
|
+
}
|
|
724
|
+
}
|
|
725
|
+
if (json.delays) {
|
|
726
|
+
for (const key of Object.keys(json.delays)) {
|
|
727
|
+
const delay = json.delays[key];
|
|
728
|
+
assertResolvable(delay && typeof delay === 'object' && 'duration' in delay ? delay.duration : delay, `$.delays.${key}`);
|
|
729
|
+
}
|
|
730
|
+
}
|
|
731
|
+
assertStateNode(json, '$');
|
|
732
|
+
}
|
|
733
|
+
let _scxmlSessionId = 'session_scxml';
|
|
174
734
|
let _scxmlMachineName = '';
|
|
175
735
|
|
|
176
736
|
/** Evaluates an SCXML expression with context variables available via `with`. */
|
|
@@ -195,7 +755,7 @@ with (context) {
|
|
|
195
755
|
}
|
|
196
756
|
return false;
|
|
197
757
|
};
|
|
198
|
-
const SCXML_ORIGIN =
|
|
758
|
+
const SCXML_ORIGIN = `#_scxml_${_scxmlSessionId}`;
|
|
199
759
|
const SCXML_ORIGIN_TYPE = 'http://www.w3.org/TR/scxml/#SCXMLEventProcessor';
|
|
200
760
|
const isExternal = event && event._scxmlExternal;
|
|
201
761
|
const isInitEvent = event && event.type === '@xstate.init';
|
|
@@ -207,7 +767,7 @@ with (context) {
|
|
|
207
767
|
const isDoneEvent = event && typeof event.type === 'string' && event.type.startsWith('xstate.done.');
|
|
208
768
|
const explicitType = event && event._scxmlEventType;
|
|
209
769
|
const scxmlEvent = event && !isInitEvent ? {
|
|
210
|
-
name: event.type,
|
|
770
|
+
name: event._scxmlEventName ?? toScxmlEventName(event.type),
|
|
211
771
|
type: explicitType || (isExternal ? 'external' : 'internal'),
|
|
212
772
|
sendid: event._scxmlSendId,
|
|
213
773
|
origin: isExternal ? SCXML_ORIGIN : undefined,
|
|
@@ -243,9 +803,64 @@ return updates;
|
|
|
243
803
|
return fn(context, updates);
|
|
244
804
|
}
|
|
245
805
|
function createMachineFromConfig(json, implementations = {}) {
|
|
246
|
-
assertRootImplementationMarkers(json, implementations);
|
|
247
|
-
assertNoUnresolvedMarkers(json);
|
|
248
806
|
const resolvedImplementations = mergeImplementations(json, implementations);
|
|
807
|
+
const expressionResolver = createExpressionResolver(json['@exprLang'], resolvedImplementations);
|
|
808
|
+
const {
|
|
809
|
+
evaluateResolvable,
|
|
810
|
+
resolveValue,
|
|
811
|
+
makeScope,
|
|
812
|
+
getDurationConfig
|
|
813
|
+
} = expressionResolver;
|
|
814
|
+
function resolveCondition(condition, slot, path) {
|
|
815
|
+
if (!condition) {
|
|
816
|
+
return undefined;
|
|
817
|
+
}
|
|
818
|
+
if (isResolvable(condition)) {
|
|
819
|
+
return args => !!evaluateResolvable(condition, slot, makeScope(args), path);
|
|
820
|
+
}
|
|
821
|
+
return args => {
|
|
822
|
+
const params = resolveValue(condition.params, slot, makeScope(args), `${path}.params`);
|
|
823
|
+
const declarativeGuard = json.guards?.[condition.type];
|
|
824
|
+
if (declarativeGuard) {
|
|
825
|
+
const guard = resolveCondition(declarativeGuard.when, 'guard', `$.guards.${condition.type}.when`);
|
|
826
|
+
return !!guard?.({
|
|
827
|
+
...args,
|
|
828
|
+
params
|
|
829
|
+
});
|
|
830
|
+
}
|
|
831
|
+
const guardImpl = args.guards?.[condition.type];
|
|
832
|
+
if (!guardImpl) {
|
|
833
|
+
throw new Error(getMissingGuardMessage(condition.type, args.guards ?? {}));
|
|
834
|
+
}
|
|
835
|
+
return guardImpl(args, params);
|
|
836
|
+
};
|
|
837
|
+
}
|
|
838
|
+
function makeChoiceConfig(choice, path) {
|
|
839
|
+
if (!choice) {
|
|
840
|
+
return undefined;
|
|
841
|
+
}
|
|
842
|
+
if (isResolvable(choice)) {
|
|
843
|
+
return args => evaluateResolvable(choice, 'choice', makeScope(args), path);
|
|
844
|
+
}
|
|
845
|
+
validateChoiceConfig(choice, path);
|
|
846
|
+
return args => {
|
|
847
|
+
for (let index = 0; index < choice.length; index++) {
|
|
848
|
+
const branch = choice[index];
|
|
849
|
+
const guard = resolveCondition(branch.when, 'choice', `${path}[${index}].when`);
|
|
850
|
+
if (!guard || guard(args)) {
|
|
851
|
+
return {
|
|
852
|
+
target: branch.target,
|
|
853
|
+
context: branch.context ? resolveValue(branch.context, 'transitionContext', makeScope(args), `${path}[${index}].context`) : undefined,
|
|
854
|
+
input: branch.input !== undefined ? resolveValue(branch.input, 'input', makeScope(args), `${path}[${index}].input`) : undefined,
|
|
855
|
+
description: branch.description,
|
|
856
|
+
reenter: branch.reenter,
|
|
857
|
+
meta: branch.meta
|
|
858
|
+
};
|
|
859
|
+
}
|
|
860
|
+
}
|
|
861
|
+
throw new Error(`Choice state at ${path} did not match any branch.`);
|
|
862
|
+
};
|
|
863
|
+
}
|
|
249
864
|
|
|
250
865
|
// Pending transition actions: set by .to functions, consumed by entry functions.
|
|
251
866
|
// This bridges SCXML's exit→transition→entry action ordering with XState's
|
|
@@ -265,8 +880,30 @@ function createMachineFromConfig(json, implementations = {}) {
|
|
|
265
880
|
// <transition cond>). Drained by the next state's entry into the internal
|
|
266
881
|
// event queue so they're processed before any external events.
|
|
267
882
|
const pendingPlatformErrors = [];
|
|
883
|
+
function getMissingGuardMessage(type, guards) {
|
|
884
|
+
return `Guard '${type}' is not implemented in machine '${json.id ?? '(machine)'}'. Available guards: ${Object.keys(guards).map(key => `'${key}'`).join(', ') || '(none)'}.`;
|
|
885
|
+
}
|
|
886
|
+
function resolveRouteConfig(route, path) {
|
|
887
|
+
if (!route || typeof route === 'function') {
|
|
888
|
+
return route;
|
|
889
|
+
}
|
|
890
|
+
if (isResolvable(route)) {
|
|
891
|
+
return args => evaluateResolvable(route, 'transition', makeScope(args), path);
|
|
892
|
+
}
|
|
893
|
+
const {
|
|
894
|
+
guard,
|
|
895
|
+
...routeConfig
|
|
896
|
+
} = route;
|
|
897
|
+
if (!guard) {
|
|
898
|
+
return routeConfig;
|
|
899
|
+
}
|
|
900
|
+
const resolvedGuard = resolveCondition({
|
|
901
|
+
type: guard
|
|
902
|
+
}, 'guard', path);
|
|
903
|
+
return args => resolvedGuard(args) ? routeConfig : undefined;
|
|
904
|
+
}
|
|
268
905
|
function iterNode(node, nodeKey) {
|
|
269
|
-
const originalEntryActions = node.entry;
|
|
906
|
+
const originalEntryActions = toActionArray(node.entry);
|
|
270
907
|
const stateId = node.id || nodeKey;
|
|
271
908
|
|
|
272
909
|
// Wrap entry to first execute any pending transition actions, then normal entry.
|
|
@@ -280,8 +917,10 @@ function createMachineFromConfig(json, implementations = {}) {
|
|
|
280
917
|
while (pendingPlatformErrors.length) {
|
|
281
918
|
const err = pendingPlatformErrors.shift();
|
|
282
919
|
enq.raise({
|
|
283
|
-
type: 'error.execution',
|
|
920
|
+
type: 'xstate.error.execution',
|
|
921
|
+
error: err,
|
|
284
922
|
_scxmlEventType: 'platform',
|
|
923
|
+
_scxmlEventName: 'error.execution',
|
|
285
924
|
_scxmlEventData: err
|
|
286
925
|
});
|
|
287
926
|
}
|
|
@@ -329,7 +968,7 @@ function createMachineFromConfig(json, implementations = {}) {
|
|
|
329
968
|
}
|
|
330
969
|
|
|
331
970
|
// Execute normal entry actions
|
|
332
|
-
if (originalEntryActions
|
|
971
|
+
if (originalEntryActions.length) {
|
|
333
972
|
const mergedX = context ? {
|
|
334
973
|
...x,
|
|
335
974
|
context
|
|
@@ -352,7 +991,7 @@ function createMachineFromConfig(json, implementations = {}) {
|
|
|
352
991
|
description: node.description,
|
|
353
992
|
tags: node.tags,
|
|
354
993
|
input: node.input,
|
|
355
|
-
timeout: node.timeout,
|
|
994
|
+
timeout: getDurationConfig(node.timeout, `$.states.${nodeKey}.timeout`),
|
|
356
995
|
states: node.states ? Object.entries(node.states).reduce((acc, [key, value]) => {
|
|
357
996
|
acc[key] = iterNode(value, key);
|
|
358
997
|
return acc;
|
|
@@ -362,18 +1001,27 @@ function createMachineFromConfig(json, implementations = {}) {
|
|
|
362
1001
|
return acc;
|
|
363
1002
|
}, {}) : undefined,
|
|
364
1003
|
always: node.always ? getTransitionConfig(node.always) : undefined,
|
|
365
|
-
|
|
366
|
-
|
|
1004
|
+
onError: node.onError ? getTransitionConfig(node.onError) : undefined,
|
|
1005
|
+
choice: makeChoiceConfig(node.choice, `$.states.${nodeKey}.choice`),
|
|
1006
|
+
route: resolveRouteConfig(node.route, `$.states.${nodeKey}.route`),
|
|
367
1007
|
after: node.after ? Object.entries(node.after).reduce((acc, [key, value]) => {
|
|
368
1008
|
acc[key] = getTransitionConfig(value);
|
|
369
1009
|
return acc;
|
|
370
1010
|
}, {}) : undefined,
|
|
371
1011
|
onTimeout: node.onTimeout ? getTransitionConfig(node.onTimeout) : undefined,
|
|
372
|
-
entry: entryFn,
|
|
373
|
-
exit: node.exit ? iterActions(node.exit) : undefined,
|
|
1012
|
+
entry: node.type === 'choice' ? undefined : entryFn,
|
|
1013
|
+
exit: node.exit ? iterActions(toActionArray(node.exit)) : undefined,
|
|
374
1014
|
invoke: node.invoke ? iterInvokeConfigs(node.invoke) : undefined,
|
|
375
1015
|
meta: node.meta,
|
|
376
|
-
output: node._scxmlDonedata ? makeDonedataOutput(node._scxmlDonedata) : node.output
|
|
1016
|
+
output: node._scxmlDonedata ? makeDonedataOutput(node._scxmlDonedata) : isResolvable(node.output) ? ({
|
|
1017
|
+
context,
|
|
1018
|
+
event,
|
|
1019
|
+
self
|
|
1020
|
+
}) => evaluateResolvable(node.output, 'output', {
|
|
1021
|
+
context,
|
|
1022
|
+
event,
|
|
1023
|
+
self
|
|
1024
|
+
}, `$.states.${nodeKey}.output`) : node.output
|
|
377
1025
|
};
|
|
378
1026
|
return nodeConfig;
|
|
379
1027
|
}
|
|
@@ -426,23 +1074,18 @@ function createMachineFromConfig(json, implementations = {}) {
|
|
|
426
1074
|
let src;
|
|
427
1075
|
if (extInv._nestedMachineJSON) {
|
|
428
1076
|
src = createMachineFromConfig(extInv._nestedMachineJSON, resolvedImplementations);
|
|
429
|
-
} else if (isUnserializableMarker(inv.src)) {
|
|
430
|
-
src = inv.src.id ? resolvedImplementations.actors[inv.src.id] : undefined;
|
|
431
|
-
if (!src) {
|
|
432
|
-
throw new Error(`Missing actors.${inv.src.id ?? ''}`);
|
|
433
|
-
}
|
|
434
1077
|
} else {
|
|
435
|
-
src = inv.src;
|
|
1078
|
+
src = resolvedImplementations.actorSources[inv.src] ?? inv.src;
|
|
436
1079
|
}
|
|
437
1080
|
return {
|
|
438
1081
|
src,
|
|
439
1082
|
id: inv.id,
|
|
440
|
-
|
|
441
|
-
input: inv.input,
|
|
1083
|
+
registryKey: inv.registryKey,
|
|
1084
|
+
input: inv.input !== undefined ? args => resolveValue(inv.input, 'input', makeScope(args), '$.invoke.input') : undefined,
|
|
442
1085
|
onDone: inv.onDone ? getTransitionConfig(inv.onDone) : undefined,
|
|
443
1086
|
onError: inv.onError ? getTransitionConfig(inv.onError) : undefined,
|
|
444
1087
|
onSnapshot: inv.onSnapshot ? getTransitionConfig(inv.onSnapshot) : undefined,
|
|
445
|
-
timeout: inv.timeout,
|
|
1088
|
+
timeout: getDurationConfig(inv.timeout, '$.invoke.timeout'),
|
|
446
1089
|
onTimeout: inv.onTimeout ? getTransitionConfig(inv.onTimeout) : undefined
|
|
447
1090
|
};
|
|
448
1091
|
});
|
|
@@ -456,8 +1099,16 @@ function createMachineFromConfig(json, implementations = {}) {
|
|
|
456
1099
|
function raiseErrorExecution(state, tagname, err) {
|
|
457
1100
|
const message = err instanceof Error ? err.message : typeof err === 'string' ? err : 'unknown error';
|
|
458
1101
|
state.enq.raise({
|
|
459
|
-
type: 'error.execution',
|
|
1102
|
+
type: 'xstate.error.execution',
|
|
1103
|
+
error: {
|
|
1104
|
+
tagname,
|
|
1105
|
+
message,
|
|
1106
|
+
line: NaN,
|
|
1107
|
+
column: NaN,
|
|
1108
|
+
reason: message
|
|
1109
|
+
},
|
|
460
1110
|
_scxmlEventType: 'platform',
|
|
1111
|
+
_scxmlEventName: 'error.execution',
|
|
461
1112
|
_scxmlEventData: {
|
|
462
1113
|
tagname,
|
|
463
1114
|
message,
|
|
@@ -468,8 +1119,31 @@ function createMachineFromConfig(json, implementations = {}) {
|
|
|
468
1119
|
});
|
|
469
1120
|
state.errored = true;
|
|
470
1121
|
}
|
|
1122
|
+
function executeActionDefinition(action, x, enq, params, parentState, stack) {
|
|
1123
|
+
const definition = json.actions?.[action.type];
|
|
1124
|
+
if (!definition) {
|
|
1125
|
+
enq(x.actions[action.type], params);
|
|
1126
|
+
return {
|
|
1127
|
+
context: undefined,
|
|
1128
|
+
errored: parentState.errored
|
|
1129
|
+
};
|
|
1130
|
+
}
|
|
1131
|
+
if (stack.includes(action.type)) {
|
|
1132
|
+
raiseErrorExecution(parentState, 'action', new Error(`Circular action reference: ${stack.concat(action.type).join(' -> ')}`));
|
|
1133
|
+
return {
|
|
1134
|
+
context: undefined,
|
|
1135
|
+
errored: true
|
|
1136
|
+
};
|
|
1137
|
+
}
|
|
1138
|
+
const definitions = Array.isArray(definition) ? definition : [definition];
|
|
1139
|
+
return executeActions(definitions, {
|
|
1140
|
+
...x,
|
|
1141
|
+
params
|
|
1142
|
+
}, enq, parentState, stack.concat(action.type));
|
|
1143
|
+
}
|
|
1144
|
+
|
|
471
1145
|
/** Execute an array of SCXML action JSON descriptors with context and enqueue. */
|
|
472
|
-
function executeActions(actions, x, enq, parentState) {
|
|
1146
|
+
function executeActions(actions, x, enq, parentState, stack = []) {
|
|
473
1147
|
const state = parentState ?? {
|
|
474
1148
|
enq,
|
|
475
1149
|
errored: false
|
|
@@ -477,22 +1151,34 @@ function createMachineFromConfig(json, implementations = {}) {
|
|
|
477
1151
|
let context;
|
|
478
1152
|
for (const action of actions) {
|
|
479
1153
|
if (state.errored) break;
|
|
480
|
-
if (
|
|
1154
|
+
if (isResolvable(action)) {
|
|
1155
|
+
const result = evaluateResolvable(action, 'action', makeScope(x, {
|
|
1156
|
+
params: x.params,
|
|
1157
|
+
enq
|
|
1158
|
+
}), '$.actions');
|
|
1159
|
+
if (result && typeof result === 'object' && 'context' in result && result.context) {
|
|
1160
|
+
context ??= {};
|
|
1161
|
+
Object.assign(context, result.context);
|
|
1162
|
+
}
|
|
1163
|
+
} else if (isBuiltInActionJSON(action)) {
|
|
481
1164
|
switch (action.type) {
|
|
482
1165
|
case '@xstate.raise':
|
|
483
1166
|
{
|
|
484
1167
|
// Tag as external if it has a delay (from <send>, not <raise>).
|
|
485
1168
|
// Attach _scxmlSendId so _event.sendid can be read in expressions.
|
|
486
1169
|
const isExternal = action.delay !== undefined;
|
|
1170
|
+
const resolvedEvent = resolveValue(action.event, 'actionParams', makeScope(x, {
|
|
1171
|
+
params: x.params
|
|
1172
|
+
}), '$.actions.event');
|
|
487
1173
|
const event = isExternal || action.id !== undefined ? {
|
|
488
|
-
...
|
|
1174
|
+
...resolvedEvent,
|
|
489
1175
|
...(isExternal ? {
|
|
490
1176
|
_scxmlExternal: true
|
|
491
1177
|
} : {}),
|
|
492
1178
|
...(action.id !== undefined ? {
|
|
493
1179
|
_scxmlSendId: action.id
|
|
494
1180
|
} : {})
|
|
495
|
-
} :
|
|
1181
|
+
} : resolvedEvent;
|
|
496
1182
|
enq.raise(event, {
|
|
497
1183
|
id: action.id,
|
|
498
1184
|
delay: action.delay
|
|
@@ -506,11 +1192,15 @@ function createMachineFromConfig(json, implementations = {}) {
|
|
|
506
1192
|
enq.log(...action.args);
|
|
507
1193
|
break;
|
|
508
1194
|
case '@xstate.emit':
|
|
509
|
-
enq.emit(action.event
|
|
1195
|
+
enq.emit(resolveValue(action.event, 'actionParams', makeScope(x, {
|
|
1196
|
+
params: x.params
|
|
1197
|
+
}), '$.actions.event'));
|
|
510
1198
|
break;
|
|
511
1199
|
case '@xstate.assign':
|
|
512
1200
|
context ??= {};
|
|
513
|
-
Object.assign(context, action.context
|
|
1201
|
+
Object.assign(context, resolveValue(action.context, 'transitionContext', makeScope(x, {
|
|
1202
|
+
params: x.params
|
|
1203
|
+
}), '$.actions.context'));
|
|
514
1204
|
break;
|
|
515
1205
|
default:
|
|
516
1206
|
throw new Error(`Unknown built-in action: ${action.type}`);
|
|
@@ -549,8 +1239,10 @@ function createMachineFromConfig(json, implementations = {}) {
|
|
|
549
1239
|
let delay;
|
|
550
1240
|
try {
|
|
551
1241
|
eventType = scxmlAction.eventexpr ? evaluateExpr(mergedContext, scxmlAction.eventexpr, x.event, x.self) : scxmlAction.event || 'unknown';
|
|
1242
|
+
eventType = normalizeScxmlEventType(eventType);
|
|
552
1243
|
eventData = {
|
|
553
|
-
type: eventType
|
|
1244
|
+
type: eventType,
|
|
1245
|
+
_scxmlEventName: toScxmlEventName(eventType)
|
|
554
1246
|
};
|
|
555
1247
|
if (scxmlAction.params) {
|
|
556
1248
|
for (const param of scxmlAction.params) {
|
|
@@ -590,25 +1282,50 @@ function createMachineFromConfig(json, implementations = {}) {
|
|
|
590
1282
|
const childRef = x.children?.[childId];
|
|
591
1283
|
if (childRef) {
|
|
592
1284
|
enq.sendTo(childRef, eventData);
|
|
1285
|
+
} else if (childId.startsWith('scxml_') && childId !== `scxml_${_scxmlSessionId}`) {
|
|
1286
|
+
const message = `Unable to dispatch event to target: ${target}`;
|
|
1287
|
+
enq.raise({
|
|
1288
|
+
type: 'xstate.error.communication',
|
|
1289
|
+
error: {
|
|
1290
|
+
tagname: 'send',
|
|
1291
|
+
message,
|
|
1292
|
+
line: NaN,
|
|
1293
|
+
column: NaN,
|
|
1294
|
+
reason: message
|
|
1295
|
+
},
|
|
1296
|
+
_scxmlEventType: 'platform',
|
|
1297
|
+
_scxmlEventName: 'error.communication',
|
|
1298
|
+
_scxmlEventData: {
|
|
1299
|
+
tagname: 'send',
|
|
1300
|
+
message,
|
|
1301
|
+
line: NaN,
|
|
1302
|
+
column: NaN,
|
|
1303
|
+
reason: message
|
|
1304
|
+
}
|
|
1305
|
+
});
|
|
593
1306
|
} else {
|
|
594
|
-
//
|
|
595
|
-
|
|
596
|
-
|
|
597
|
-
}
|
|
598
|
-
enq.raise(eventData, {
|
|
1307
|
+
// This SCXML session id uses the external event queue.
|
|
1308
|
+
eventData._scxmlExternal = true;
|
|
1309
|
+
enq.sendTo(x.self, eventData, {
|
|
599
1310
|
id: scxmlAction.id,
|
|
600
1311
|
delay
|
|
601
1312
|
});
|
|
602
1313
|
}
|
|
603
1314
|
} else {
|
|
604
|
-
//
|
|
605
|
-
|
|
1315
|
+
// #_internal uses the internal queue; self-send/no target use the
|
|
1316
|
+
// external event queue.
|
|
1317
|
+
if (isInternalTarget) {
|
|
1318
|
+
enq.raise(eventData, {
|
|
1319
|
+
id: scxmlAction.id,
|
|
1320
|
+
delay
|
|
1321
|
+
});
|
|
1322
|
+
} else {
|
|
606
1323
|
eventData._scxmlExternal = true;
|
|
1324
|
+
enq.sendTo(x.self, eventData, {
|
|
1325
|
+
id: scxmlAction.id,
|
|
1326
|
+
delay
|
|
1327
|
+
});
|
|
607
1328
|
}
|
|
608
|
-
enq.raise(eventData, {
|
|
609
|
-
id: scxmlAction.id,
|
|
610
|
-
delay
|
|
611
|
-
});
|
|
612
1329
|
}
|
|
613
1330
|
} else if (action.type === 'scxml.cancel') {
|
|
614
1331
|
const scxmlAction = action;
|
|
@@ -738,7 +1455,14 @@ function createMachineFromConfig(json, implementations = {}) {
|
|
|
738
1455
|
}
|
|
739
1456
|
}
|
|
740
1457
|
} else {
|
|
741
|
-
|
|
1458
|
+
const params = resolveValue(action.params, 'actionParams', makeScope(x, {
|
|
1459
|
+
params: x.params
|
|
1460
|
+
}), '$.actions.params');
|
|
1461
|
+
const result = executeActionDefinition(action, x, enq, params, state, stack);
|
|
1462
|
+
if (result.context) {
|
|
1463
|
+
context ??= {};
|
|
1464
|
+
Object.assign(context, result.context);
|
|
1465
|
+
}
|
|
742
1466
|
}
|
|
743
1467
|
}
|
|
744
1468
|
return {
|
|
@@ -759,30 +1483,63 @@ function createMachineFromConfig(json, implementations = {}) {
|
|
|
759
1483
|
// a separate XState transition with its own guard and optional .to.
|
|
760
1484
|
// This ensures guards are evaluated by XState's evaluateCandidate (once,
|
|
761
1485
|
// with pre-exit context) and NOT re-evaluated in computeEntrySet.
|
|
762
|
-
return transitions.map(t => {
|
|
1486
|
+
return transitions.map((t, index) => {
|
|
1487
|
+
if (isResolvable(t)) {
|
|
1488
|
+
return (x, enq) => evaluateResolvable(t, 'transition', makeScope(x, {
|
|
1489
|
+
enq
|
|
1490
|
+
}), `$.transition${transitions.length > 1 ? `[${index}]` : ''}`);
|
|
1491
|
+
}
|
|
763
1492
|
const target = Array.isArray(t.target) ? t.target[0] : t.target;
|
|
764
1493
|
const targetConfig = t.target;
|
|
1494
|
+
const guard = resolveCondition(t.guard, 'guard', '$.transition.guard');
|
|
1495
|
+
const resolveTransitionContext = x => t.context ? resolveValue(t.context, 'transitionContext', makeScope(x), '$.transition.context') : undefined;
|
|
1496
|
+
const resolveTransitionInput = x => t.input !== undefined ? resolveValue(t.input, 'input', makeScope(x), '$.transition.input') : undefined;
|
|
765
1497
|
|
|
766
1498
|
// No guard and no actions: simple static config
|
|
767
|
-
if (!
|
|
1499
|
+
if (!guard && !t.actions?.length) {
|
|
1500
|
+
if (t.context) {
|
|
1501
|
+
return {
|
|
1502
|
+
to: x => ({
|
|
1503
|
+
target: targetConfig,
|
|
1504
|
+
context: resolveTransitionContext(x),
|
|
1505
|
+
reenter: t.reenter
|
|
1506
|
+
}),
|
|
1507
|
+
description: t.description,
|
|
1508
|
+
meta: t.meta,
|
|
1509
|
+
input: t.input !== undefined ? resolveTransitionInput : undefined
|
|
1510
|
+
};
|
|
1511
|
+
}
|
|
768
1512
|
return {
|
|
769
1513
|
target: targetConfig,
|
|
770
1514
|
description: t.description,
|
|
771
1515
|
reenter: t.reenter,
|
|
772
1516
|
meta: t.meta,
|
|
773
|
-
input: t.input
|
|
1517
|
+
input: t.input !== undefined ? resolveTransitionInput : undefined
|
|
774
1518
|
};
|
|
775
1519
|
}
|
|
776
1520
|
|
|
777
1521
|
// Guard but no actions: static config with guard
|
|
778
|
-
if (
|
|
1522
|
+
if (guard && !t.actions?.length) {
|
|
1523
|
+
if (t.context) {
|
|
1524
|
+
return {
|
|
1525
|
+
guard,
|
|
1526
|
+
to: x => ({
|
|
1527
|
+
target: targetConfig,
|
|
1528
|
+
context: resolveTransitionContext(x),
|
|
1529
|
+
reenter: t.reenter
|
|
1530
|
+
}),
|
|
1531
|
+
description: t.description,
|
|
1532
|
+
meta: t.meta,
|
|
1533
|
+
input: t.input !== undefined ? resolveTransitionInput : undefined
|
|
1534
|
+
};
|
|
1535
|
+
}
|
|
779
1536
|
return {
|
|
780
1537
|
target: targetConfig,
|
|
781
|
-
guard
|
|
1538
|
+
guard,
|
|
782
1539
|
description: t.description,
|
|
783
1540
|
reenter: t.reenter,
|
|
784
1541
|
meta: t.meta,
|
|
785
|
-
input: t.input
|
|
1542
|
+
input: t.input !== undefined ? resolveTransitionInput : undefined
|
|
786
1543
|
};
|
|
787
1544
|
}
|
|
788
1545
|
|
|
@@ -791,12 +1548,13 @@ function createMachineFromConfig(json, implementations = {}) {
|
|
|
791
1548
|
// For parallel (entries exist), first entry re-executes all in document order.
|
|
792
1549
|
if (!target) {
|
|
793
1550
|
return {
|
|
794
|
-
guard
|
|
1551
|
+
guard,
|
|
795
1552
|
description: t.description,
|
|
796
1553
|
reenter: t.reenter,
|
|
797
1554
|
meta: t.meta,
|
|
798
|
-
input: t.input,
|
|
1555
|
+
input: t.input !== undefined ? resolveTransitionInput : undefined,
|
|
799
1556
|
to: (x, enq) => {
|
|
1557
|
+
const context = resolveTransitionContext(x);
|
|
800
1558
|
if (t.actions?.length) {
|
|
801
1559
|
// Track for parallel re-execution (dedup by reference)
|
|
802
1560
|
if (!allTransitionActions.includes(t.actions)) {
|
|
@@ -808,11 +1566,16 @@ function createMachineFromConfig(json, implementations = {}) {
|
|
|
808
1566
|
const result = executeActions(t.actions, x, enq);
|
|
809
1567
|
if (result.context) {
|
|
810
1568
|
return {
|
|
811
|
-
context:
|
|
1569
|
+
context: {
|
|
1570
|
+
...context,
|
|
1571
|
+
...result.context
|
|
1572
|
+
}
|
|
812
1573
|
};
|
|
813
1574
|
}
|
|
814
1575
|
}
|
|
815
|
-
return {
|
|
1576
|
+
return context ? {
|
|
1577
|
+
context
|
|
1578
|
+
} : {};
|
|
816
1579
|
}
|
|
817
1580
|
};
|
|
818
1581
|
}
|
|
@@ -822,12 +1585,13 @@ function createMachineFromConfig(json, implementations = {}) {
|
|
|
822
1585
|
// already validated it. The .to just stores actions for entry to execute.
|
|
823
1586
|
// Map by target state ID so parallel transitions each get their own actions.
|
|
824
1587
|
return {
|
|
825
|
-
guard
|
|
1588
|
+
guard,
|
|
826
1589
|
description: t.description,
|
|
827
1590
|
reenter: t.reenter,
|
|
828
1591
|
meta: t.meta,
|
|
829
|
-
input: t.input,
|
|
1592
|
+
input: t.input !== undefined ? resolveTransitionInput : undefined,
|
|
830
1593
|
to: (_x, _enq) => {
|
|
1594
|
+
const context = resolveTransitionContext(_x);
|
|
831
1595
|
if (t.actions?.length) {
|
|
832
1596
|
const targetId = target.replace(/^#/, '');
|
|
833
1597
|
pendingTransitionActionsMap[targetId] = t.actions;
|
|
@@ -838,18 +1602,32 @@ function createMachineFromConfig(json, implementations = {}) {
|
|
|
838
1602
|
}
|
|
839
1603
|
return {
|
|
840
1604
|
target: targetConfig,
|
|
1605
|
+
context,
|
|
841
1606
|
reenter: t.reenter
|
|
842
1607
|
};
|
|
843
1608
|
}
|
|
844
1609
|
};
|
|
845
1610
|
});
|
|
846
1611
|
}
|
|
1612
|
+
if (json.delays) {
|
|
1613
|
+
for (const key of Object.keys(json.delays)) {
|
|
1614
|
+
const delay = json.delays[key];
|
|
1615
|
+
if (typeof delay === 'number') {
|
|
1616
|
+
resolvedImplementations.delays[key] = delay;
|
|
1617
|
+
} else if (typeof delay === 'string') {
|
|
1618
|
+
resolvedImplementations.delays[key] = delayToMs(delay);
|
|
1619
|
+
} else if (delay && typeof delay === 'object') {
|
|
1620
|
+
resolvedImplementations.delays[key] = args => delayToMs(resolveValue(delay.duration, 'delay', makeScope(args), `$.delays.${key}.duration`));
|
|
1621
|
+
}
|
|
1622
|
+
}
|
|
1623
|
+
}
|
|
1624
|
+
assertMachineJSON(json, resolvedImplementations, expressionResolver);
|
|
847
1625
|
const rootNodeConfig = iterNode(json);
|
|
848
1626
|
const contextConfig = json.context ? {
|
|
849
|
-
context: json.context
|
|
1627
|
+
context: args => resolveValue(json.context, 'context', args, '$.context')
|
|
850
1628
|
} : {};
|
|
851
1629
|
_scxmlMachineName = json.id || '';
|
|
852
|
-
_scxmlSessionId = '
|
|
1630
|
+
_scxmlSessionId = 'session_scxml';
|
|
853
1631
|
const machine = createMachine({
|
|
854
1632
|
...rootNodeConfig,
|
|
855
1633
|
...contextConfig,
|
|
@@ -894,7 +1672,7 @@ function createMachineFromConfig(json, implementations = {}) {
|
|
|
894
1672
|
},
|
|
895
1673
|
'xstate.not': (args, params) => {
|
|
896
1674
|
const inner = params?.guard;
|
|
897
|
-
const innerImpl = inner &&
|
|
1675
|
+
const innerImpl = inner && args.guards?.[inner.type];
|
|
898
1676
|
if (!innerImpl) {
|
|
899
1677
|
throw new Error(`Guard '${inner?.type}' referenced by 'xstate.not' is not implemented.`);
|
|
900
1678
|
}
|
|
@@ -903,7 +1681,7 @@ function createMachineFromConfig(json, implementations = {}) {
|
|
|
903
1681
|
};
|
|
904
1682
|
const provided = machine.provide({
|
|
905
1683
|
actions: resolvedImplementations.actions,
|
|
906
|
-
|
|
1684
|
+
actorSources: resolvedImplementations.actorSources,
|
|
907
1685
|
guards: {
|
|
908
1686
|
...providedGuards,
|
|
909
1687
|
...resolvedImplementations.guards
|
|
@@ -917,7 +1695,7 @@ function createMachineFromConfig(json, implementations = {}) {
|
|
|
917
1695
|
return provided;
|
|
918
1696
|
}
|
|
919
1697
|
function isBuiltInActionJSON(action) {
|
|
920
|
-
return action.type.startsWith('@xstate.');
|
|
1698
|
+
return !isResolvable(action) && action.type.startsWith('@xstate.');
|
|
921
1699
|
}
|
|
922
1700
|
|
|
923
1701
|
/**
|
|
@@ -925,24 +1703,17 @@ function isBuiltInActionJSON(action) {
|
|
|
925
1703
|
*
|
|
926
1704
|
* `machineConfigToJSON` converts a machine config into a JSON-safe structure
|
|
927
1705
|
* (the `MachineJSON` shape accepted by `createMachineFromConfig`). The boundary
|
|
928
|
-
* between serializable structure and runtime implementations is explicit:
|
|
929
|
-
*
|
|
930
|
-
* runtime schemas
|
|
931
|
-
* rather than silently dropped.
|
|
932
|
-
*
|
|
933
|
-
* A machine definition is fully portable iff its JSON contains no
|
|
934
|
-
* `$unserializable` markers; reviving a definition that has markers requires
|
|
935
|
-
* re-providing those implementations (e.g. via `machine.provide(...)` or the
|
|
936
|
-
* `actions`/`guards`/`actors` maps on `createMachineFromConfig` revival).
|
|
1706
|
+
* between serializable structure and runtime implementations is explicit:
|
|
1707
|
+
* functions are represented as `@code` source objects, while actor logic,
|
|
1708
|
+
* runtime schemas, and other non-data runtime values are omitted.
|
|
937
1709
|
*/
|
|
938
1710
|
|
|
939
1711
|
/**
|
|
940
1712
|
* Returns the JSON-serializable definition of a machine.
|
|
941
1713
|
*
|
|
942
|
-
* Inline functions
|
|
943
|
-
*
|
|
944
|
-
*
|
|
945
|
-
* round-trip):
|
|
1714
|
+
* Inline functions are represented as `{ "@code": string, "@lang": "ts" }`. A
|
|
1715
|
+
* machine created via `createMachineFromConfig` returns its original JSON
|
|
1716
|
+
* config (lossless round-trip):
|
|
946
1717
|
*
|
|
947
1718
|
* ```ts
|
|
948
1719
|
* import { serializeMachine, createMachineFromConfig } from 'xstate';
|
|
@@ -957,48 +1728,57 @@ function serializeMachine(machine) {
|
|
|
957
1728
|
return machine._json ?? machineConfigToJSON(machine.config);
|
|
958
1729
|
}
|
|
959
1730
|
|
|
960
|
-
|
|
961
|
-
|
|
962
|
-
|
|
963
|
-
|
|
964
|
-
|
|
965
|
-
function marker(kind, id) {
|
|
966
|
-
const m = {
|
|
967
|
-
$unserializable: kind
|
|
1731
|
+
// eslint-disable-next-line @typescript-eslint/no-unsafe-function-type
|
|
1732
|
+
function codeExpression(fn) {
|
|
1733
|
+
return {
|
|
1734
|
+
'@code': fn.toString(),
|
|
1735
|
+
'@lang': 'ts'
|
|
968
1736
|
};
|
|
969
|
-
|
|
970
|
-
|
|
971
|
-
|
|
972
|
-
|
|
1737
|
+
}
|
|
1738
|
+
function isActorLogic(value) {
|
|
1739
|
+
return !!value && typeof value === 'object' && typeof value.transition === 'function' && typeof value.getInitialSnapshot === 'function';
|
|
1740
|
+
}
|
|
1741
|
+
function isRuntimeSchema(value) {
|
|
1742
|
+
return !!value && typeof value === 'object' && '~standard' in value;
|
|
973
1743
|
}
|
|
974
1744
|
|
|
975
|
-
/** JSON-safe deep copy of a plain value; functions become
|
|
1745
|
+
/** JSON-safe deep copy of a plain value; functions become code expressions. */
|
|
976
1746
|
function valueToJSON(value) {
|
|
977
1747
|
if (typeof value === 'function') {
|
|
978
|
-
return
|
|
1748
|
+
return codeExpression(value);
|
|
979
1749
|
}
|
|
980
1750
|
if (value === null || typeof value !== 'object') {
|
|
981
|
-
return typeof value === 'bigint' || typeof value === 'symbol' ?
|
|
1751
|
+
return typeof value === 'bigint' || typeof value === 'symbol' ? undefined : value;
|
|
1752
|
+
}
|
|
1753
|
+
if (isActorLogic(value)) {
|
|
1754
|
+
return undefined;
|
|
1755
|
+
}
|
|
1756
|
+
if (isRuntimeSchema(value)) {
|
|
1757
|
+
return undefined;
|
|
982
1758
|
}
|
|
983
1759
|
if (Array.isArray(value)) {
|
|
984
|
-
return value.map(valueToJSON);
|
|
1760
|
+
return value.map(valueToJSON).filter(item => item !== undefined);
|
|
985
1761
|
}
|
|
986
1762
|
if (value.constructor !== Object && value.constructor !== undefined) {
|
|
987
1763
|
// Class instances (actor logic, schemas, dates, ...) are not portable.
|
|
988
|
-
return
|
|
1764
|
+
return undefined;
|
|
989
1765
|
}
|
|
990
1766
|
const result = {};
|
|
991
1767
|
for (const key of Object.keys(value)) {
|
|
992
1768
|
const v = value[key];
|
|
993
1769
|
if (v !== undefined) {
|
|
994
|
-
|
|
1770
|
+
const jsonValue = valueToJSON(v);
|
|
1771
|
+
if (jsonValue !== undefined) {
|
|
1772
|
+
result[key] = jsonValue;
|
|
1773
|
+
}
|
|
995
1774
|
}
|
|
996
1775
|
}
|
|
997
1776
|
return result;
|
|
998
1777
|
}
|
|
999
1778
|
function invokeToJSON(invoke) {
|
|
1000
1779
|
if (Array.isArray(invoke)) {
|
|
1001
|
-
|
|
1780
|
+
const values = invoke.map(invokeToJSON).filter(value => value !== undefined);
|
|
1781
|
+
return values.length ? values : undefined;
|
|
1002
1782
|
}
|
|
1003
1783
|
const def = invoke;
|
|
1004
1784
|
const result = {};
|
|
@@ -1007,37 +1787,47 @@ function invokeToJSON(invoke) {
|
|
|
1007
1787
|
if (value === undefined) {
|
|
1008
1788
|
continue;
|
|
1009
1789
|
}
|
|
1010
|
-
result[key] = key === 'src' && typeof value !== 'string' ?
|
|
1011
|
-
|
|
1012
|
-
|
|
1013
|
-
|
|
1790
|
+
result[key] = key === 'src' && typeof value !== 'string' ? value.id : valueToJSON(value);
|
|
1791
|
+
if (result[key] === undefined) {
|
|
1792
|
+
delete result[key];
|
|
1793
|
+
}
|
|
1014
1794
|
}
|
|
1015
|
-
return result;
|
|
1795
|
+
return result.src === undefined ? undefined : result;
|
|
1016
1796
|
}
|
|
1017
|
-
function implementationsToJSON(map
|
|
1797
|
+
function implementationsToJSON(map) {
|
|
1018
1798
|
if (!map) {
|
|
1019
1799
|
return undefined;
|
|
1020
1800
|
}
|
|
1021
|
-
// Keys are preserved — they are the contract a revived machine must
|
|
1022
|
-
// fulfill via provide() — while values become markers (or stay, for
|
|
1023
|
-
// JSON-safe values like numeric delays).
|
|
1024
1801
|
const result = {};
|
|
1025
1802
|
for (const key of Object.keys(map)) {
|
|
1026
1803
|
const value = map[key];
|
|
1027
|
-
|
|
1804
|
+
if (typeof value === 'function') {
|
|
1805
|
+
result[key] = undefined;
|
|
1806
|
+
} else {
|
|
1807
|
+
result[key] = valueToJSON(value);
|
|
1808
|
+
}
|
|
1809
|
+
if (result[key] === undefined) {
|
|
1810
|
+
delete result[key];
|
|
1811
|
+
}
|
|
1028
1812
|
}
|
|
1029
1813
|
return result;
|
|
1030
1814
|
}
|
|
1031
1815
|
function stateNodeConfigToJSON(config) {
|
|
1032
1816
|
const result = {};
|
|
1033
|
-
for (const key of
|
|
1817
|
+
for (const key of Object.keys(config)) {
|
|
1818
|
+
if (key === 'states' || key === 'invoke') {
|
|
1819
|
+
continue;
|
|
1820
|
+
}
|
|
1034
1821
|
const value = config[key];
|
|
1035
1822
|
if (value !== undefined) {
|
|
1036
1823
|
result[key] = valueToJSON(value);
|
|
1037
1824
|
}
|
|
1038
1825
|
}
|
|
1039
1826
|
if (config.invoke !== undefined) {
|
|
1040
|
-
|
|
1827
|
+
const invoke = invokeToJSON(config.invoke);
|
|
1828
|
+
if (invoke !== undefined) {
|
|
1829
|
+
result.invoke = invoke;
|
|
1830
|
+
}
|
|
1041
1831
|
}
|
|
1042
1832
|
if (config.states) {
|
|
1043
1833
|
const states = {};
|
|
@@ -1051,7 +1841,7 @@ function stateNodeConfigToJSON(config) {
|
|
|
1051
1841
|
|
|
1052
1842
|
/**
|
|
1053
1843
|
* Converts a machine config (as passed to `createMachine`) to its JSON-safe
|
|
1054
|
-
* definition.
|
|
1844
|
+
* definition.
|
|
1055
1845
|
*/
|
|
1056
1846
|
function machineConfigToJSON(config) {
|
|
1057
1847
|
const result = stateNodeConfigToJSON(config);
|
|
@@ -1064,16 +1854,24 @@ function machineConfigToJSON(config) {
|
|
|
1064
1854
|
const value = config.schemas[key];
|
|
1065
1855
|
if (value && typeof value === 'object' && !('~standard' in value)) {
|
|
1066
1856
|
// Map-form schemas (events/emitted): preserve event-type keys.
|
|
1067
|
-
schemas[key] = implementationsToJSON(value
|
|
1857
|
+
schemas[key] = implementationsToJSON(value);
|
|
1068
1858
|
} else {
|
|
1069
|
-
schemas[key] =
|
|
1859
|
+
schemas[key] = valueToJSON(value);
|
|
1860
|
+
}
|
|
1861
|
+
if (schemas[key] === undefined) {
|
|
1862
|
+
delete schemas[key];
|
|
1070
1863
|
}
|
|
1071
1864
|
}
|
|
1072
1865
|
result.schemas = schemas;
|
|
1073
1866
|
}
|
|
1074
|
-
for (const key of ['actions', 'guards', '
|
|
1867
|
+
for (const key of ['actions', 'guards', 'actorSources', 'delays']) {
|
|
1075
1868
|
if (config[key]) {
|
|
1076
|
-
|
|
1869
|
+
const value = implementationsToJSON(config[key]);
|
|
1870
|
+
if (value && Object.keys(value).length) {
|
|
1871
|
+
result[key] = value;
|
|
1872
|
+
} else {
|
|
1873
|
+
delete result[key];
|
|
1874
|
+
}
|
|
1077
1875
|
}
|
|
1078
1876
|
}
|
|
1079
1877
|
return result;
|
|
@@ -1176,6 +1974,28 @@ function isTypeSchema(value) {
|
|
|
1176
1974
|
|
|
1177
1975
|
/** State schema with optional schemas.input and nested states */
|
|
1178
1976
|
|
|
1977
|
+
/**
|
|
1978
|
+
* The sibling state schemas of a dotted path: the children of the path's
|
|
1979
|
+
* parent. A bare transition target resolves relative to the parent, so the
|
|
1980
|
+
* valid targets for a path's config are its siblings. For a dotless (top-level)
|
|
1981
|
+
* path the siblings are the root states.
|
|
1982
|
+
*/
|
|
1983
|
+
|
|
1984
|
+
// dotless path: siblings are the current level's states
|
|
1985
|
+
|
|
1986
|
+
/**
|
|
1987
|
+
* Resolves a dotted state path (e.g. `'parent.child'`) into the leaf
|
|
1988
|
+
* `SetupStateSchema` it addresses, or `never` if any segment is missing.
|
|
1989
|
+
*/
|
|
1990
|
+
|
|
1991
|
+
/** Union of every addressable dotted path into a setup states tree */
|
|
1992
|
+
|
|
1993
|
+
/**
|
|
1994
|
+
* Shared body of both `createStateConfig` overloads: the
|
|
1995
|
+
* `StateNodeConfigWithNestedInput` instantiation whose only varying parts are
|
|
1996
|
+
* the leading sibling-schemas and state-schema arguments.
|
|
1997
|
+
*/
|
|
1998
|
+
|
|
1179
1999
|
/** Extracts input type from a state schema */
|
|
1180
2000
|
|
|
1181
2001
|
/**
|
|
@@ -1231,33 +2051,142 @@ function isTypeSchema(value) {
|
|
|
1231
2051
|
* });
|
|
1232
2052
|
* ```
|
|
1233
2053
|
*/
|
|
2054
|
+
|
|
1234
2055
|
function setup(config = {}) {
|
|
1235
2056
|
const {
|
|
1236
2057
|
states = {},
|
|
1237
|
-
schemas
|
|
2058
|
+
schemas,
|
|
2059
|
+
actions,
|
|
2060
|
+
actorSources,
|
|
2061
|
+
guards,
|
|
2062
|
+
delays
|
|
1238
2063
|
} = config;
|
|
1239
2064
|
return {
|
|
2065
|
+
extend(extension) {
|
|
2066
|
+
return setup(mergeSetupConfigs(config, extension));
|
|
2067
|
+
},
|
|
1240
2068
|
createMachine(machineConfig) {
|
|
1241
2069
|
const configSchemas = machineConfig.schemas;
|
|
1242
|
-
const mergedSchemas =
|
|
1243
|
-
|
|
1244
|
-
|
|
1245
|
-
|
|
1246
|
-
|
|
2070
|
+
const mergedSchemas = mergeSchemas(configSchemas, schemas);
|
|
2071
|
+
const mergedActions = mergeMaps(actions, machineConfig.actions);
|
|
2072
|
+
const mergedActorSources = mergeMaps(actorSources, machineConfig.actorSources);
|
|
2073
|
+
const mergedGuards = mergeMaps(guards, machineConfig.guards);
|
|
2074
|
+
const mergedDelays = mergeMaps(delays, machineConfig.delays);
|
|
2075
|
+
return new StateMachine.StateMachine({
|
|
1247
2076
|
...machineConfig,
|
|
1248
|
-
|
|
1249
|
-
|
|
2077
|
+
...(mergedSchemas ? {
|
|
2078
|
+
schemas: mergedSchemas
|
|
2079
|
+
} : undefined),
|
|
2080
|
+
...(mergedActions ? {
|
|
2081
|
+
actions: mergedActions
|
|
2082
|
+
} : undefined),
|
|
2083
|
+
...(mergedActorSources ? {
|
|
2084
|
+
actorSources: mergedActorSources
|
|
2085
|
+
} : undefined),
|
|
2086
|
+
...(mergedGuards ? {
|
|
2087
|
+
guards: mergedGuards
|
|
2088
|
+
} : undefined),
|
|
2089
|
+
...(mergedDelays ? {
|
|
2090
|
+
delays: mergedDelays
|
|
2091
|
+
} : undefined)
|
|
2092
|
+
});
|
|
2093
|
+
},
|
|
2094
|
+
createStateConfig(...args) {
|
|
2095
|
+
return args.length > 1 ? args[1] : args[0];
|
|
2096
|
+
},
|
|
2097
|
+
states,
|
|
2098
|
+
schemas: schemas ?? {}
|
|
2099
|
+
};
|
|
2100
|
+
}
|
|
2101
|
+
function createSystem(_config = {}) {
|
|
2102
|
+
const runtimeRef = {};
|
|
2103
|
+
const pendingObservers = [];
|
|
2104
|
+
const flushObservers = () => {
|
|
2105
|
+
const runtime = runtimeRef.current;
|
|
2106
|
+
if (!runtime) {
|
|
2107
|
+
return;
|
|
2108
|
+
}
|
|
2109
|
+
for (const entry of pendingObservers) {
|
|
2110
|
+
if (entry.active && !entry.subscription) {
|
|
2111
|
+
entry.subscription = runtime.inspect(entry.observer);
|
|
2112
|
+
}
|
|
2113
|
+
}
|
|
2114
|
+
};
|
|
2115
|
+
return {
|
|
2116
|
+
createActor(logic, options) {
|
|
2117
|
+
const actor = dist_xstateActors.createActor(logic, {
|
|
2118
|
+
...options,
|
|
2119
|
+
_systemRef: runtimeRef
|
|
2120
|
+
});
|
|
2121
|
+
flushObservers();
|
|
2122
|
+
return actor;
|
|
2123
|
+
},
|
|
2124
|
+
get(key) {
|
|
2125
|
+
return runtimeRef.current?.get(key);
|
|
1250
2126
|
},
|
|
1251
|
-
|
|
1252
|
-
return
|
|
2127
|
+
getAll() {
|
|
2128
|
+
return runtimeRef.current?.getAll() ?? {};
|
|
2129
|
+
},
|
|
2130
|
+
inspect(observer) {
|
|
2131
|
+
const runtime = runtimeRef.current;
|
|
2132
|
+
if (runtime) {
|
|
2133
|
+
return runtime.inspect(observer);
|
|
2134
|
+
}
|
|
2135
|
+
const entry = {
|
|
2136
|
+
observer: observer,
|
|
2137
|
+
active: true
|
|
2138
|
+
};
|
|
2139
|
+
pendingObservers.push(entry);
|
|
2140
|
+
return {
|
|
2141
|
+
unsubscribe() {
|
|
2142
|
+
entry.active = false;
|
|
2143
|
+
entry.subscription?.unsubscribe();
|
|
2144
|
+
}
|
|
2145
|
+
};
|
|
1253
2146
|
},
|
|
1254
|
-
|
|
2147
|
+
setup(config) {
|
|
2148
|
+
return config ? setup(config) : setup();
|
|
2149
|
+
}
|
|
2150
|
+
};
|
|
2151
|
+
}
|
|
2152
|
+
function mergeMaps(left, right) {
|
|
2153
|
+
return left || right ? {
|
|
2154
|
+
...left,
|
|
2155
|
+
...right
|
|
2156
|
+
} : undefined;
|
|
2157
|
+
}
|
|
2158
|
+
function mergeSchemas(left, right) {
|
|
2159
|
+
if (!left && !right) {
|
|
2160
|
+
return undefined;
|
|
2161
|
+
}
|
|
2162
|
+
return {
|
|
2163
|
+
...left,
|
|
2164
|
+
...right,
|
|
2165
|
+
events: mergeMaps(left?.events, right?.events),
|
|
2166
|
+
actions: mergeMaps(left?.actions, right?.actions),
|
|
2167
|
+
guards: mergeMaps(left?.guards, right?.guards),
|
|
2168
|
+
emitted: mergeMaps(left?.emitted, right?.emitted),
|
|
2169
|
+
children: mergeMaps(left?.children, right?.children)
|
|
2170
|
+
};
|
|
2171
|
+
}
|
|
2172
|
+
function mergeSetupConfigs(base, extension) {
|
|
2173
|
+
return {
|
|
2174
|
+
...base,
|
|
2175
|
+
...extension,
|
|
2176
|
+
schemas: mergeSchemas(base.schemas, extension.schemas),
|
|
2177
|
+
states: mergeMaps(base.states, extension.states),
|
|
2178
|
+
actions: mergeMaps(base.actions, extension.actions),
|
|
2179
|
+
actorSources: mergeMaps(base.actorSources, extension.actorSources),
|
|
2180
|
+
guards: mergeMaps(base.guards, extension.guards),
|
|
2181
|
+
delays: mergeMaps(base.delays, extension.delays)
|
|
1255
2182
|
};
|
|
1256
2183
|
}
|
|
1257
2184
|
|
|
1258
2185
|
/** @internal */
|
|
1259
2186
|
function createInertActorScope(actorLogic) {
|
|
1260
|
-
const self = dist_xstateActors.createActor(actorLogic
|
|
2187
|
+
const self = dist_xstateActors.createActor(actorLogic, {
|
|
2188
|
+
_inert: true
|
|
2189
|
+
});
|
|
1261
2190
|
const inertActorScope = {
|
|
1262
2191
|
self: self,
|
|
1263
2192
|
defer: () => {},
|
|
@@ -1275,7 +2204,7 @@ function createInertActorScope(actorLogic) {
|
|
|
1275
2204
|
/** @deprecated Use `initialTransition(…)` instead. */
|
|
1276
2205
|
function getInitialSnapshot(actorLogic, ...[input]) {
|
|
1277
2206
|
const actorScope = createInertActorScope(actorLogic);
|
|
1278
|
-
return actorLogic.
|
|
2207
|
+
return actorLogic.initialTransition(input, actorScope)[0];
|
|
1279
2208
|
}
|
|
1280
2209
|
|
|
1281
2210
|
/**
|
|
@@ -1565,14 +2494,9 @@ let SpecialTargets = /*#__PURE__*/function (SpecialTargets) {
|
|
|
1565
2494
|
* This is a pure function that does not execute `actions`.
|
|
1566
2495
|
*/
|
|
1567
2496
|
function transition(logic, snapshot, event) {
|
|
1568
|
-
const executableActions = [];
|
|
1569
2497
|
const actorScope = createInertActorScope(logic);
|
|
1570
|
-
|
|
1571
|
-
|
|
1572
|
-
};
|
|
1573
|
-
const transitionResult = logic.transition(snapshot, event, actorScope);
|
|
1574
|
-
const [nextSnapshot, effects] = Array.isArray(transitionResult) ? transitionResult : [transitionResult, []];
|
|
1575
|
-
return [nextSnapshot, executableActions.concat(effects)];
|
|
2498
|
+
const [nextSnapshot, effects] = logic.transition(snapshot, event, actorScope);
|
|
2499
|
+
return [nextSnapshot, effects];
|
|
1576
2500
|
}
|
|
1577
2501
|
|
|
1578
2502
|
/**
|
|
@@ -1583,12 +2507,8 @@ function transition(logic, snapshot, event) {
|
|
|
1583
2507
|
* This is a pure function that does not execute `actions`.
|
|
1584
2508
|
*/
|
|
1585
2509
|
function initialTransition(logic, ...[input]) {
|
|
1586
|
-
const executableActions = [];
|
|
1587
2510
|
const actorScope = createInertActorScope(logic);
|
|
1588
|
-
|
|
1589
|
-
executableActions.push(action);
|
|
1590
|
-
};
|
|
1591
|
-
const nextSnapshot = logic.getInitialSnapshot(actorScope, input);
|
|
2511
|
+
const [nextSnapshot, executableActions] = logic.initialTransition(input, actorScope);
|
|
1592
2512
|
return [nextSnapshot, executableActions];
|
|
1593
2513
|
}
|
|
1594
2514
|
|
|
@@ -1787,20 +2707,16 @@ exports.TimeoutError = dist_xstateActors.TimeoutError;
|
|
|
1787
2707
|
exports.__unsafe_getAllOwnEventDescriptors = dist_xstateActors.getAllOwnEventDescriptors;
|
|
1788
2708
|
exports.checkStateIn = dist_xstateActors.checkStateIn;
|
|
1789
2709
|
exports.createActor = dist_xstateActors.createActor;
|
|
1790
|
-
exports.createAsyncAtom = dist_xstateActors.createAsyncAtom;
|
|
1791
2710
|
exports.createAsyncLogic = dist_xstateActors.createAsyncLogic;
|
|
1792
|
-
exports.createAtom = dist_xstateActors.createAtom;
|
|
1793
|
-
exports.createAtomConfig = dist_xstateActors.createAtomConfig;
|
|
1794
2711
|
exports.createCallbackLogic = dist_xstateActors.createCallbackLogic;
|
|
1795
2712
|
exports.createEmptyActor = dist_xstateActors.createEmptyActor;
|
|
1796
2713
|
exports.createEventObservableLogic = dist_xstateActors.createEventObservableLogic;
|
|
1797
2714
|
exports.createListenerLogic = dist_xstateActors.createListenerLogic;
|
|
1798
2715
|
exports.createLogic = dist_xstateActors.createLogic;
|
|
1799
2716
|
exports.createObservableLogic = dist_xstateActors.createObservableLogic;
|
|
1800
|
-
exports.createReducerAtom = dist_xstateActors.createReducerAtom;
|
|
1801
2717
|
exports.createSubscriptionLogic = dist_xstateActors.createSubscriptionLogic;
|
|
1802
2718
|
exports.getStateNodes = dist_xstateActors.getStateNodes;
|
|
1803
|
-
exports.
|
|
2719
|
+
exports.isBuiltInExecutableAction = dist_xstateActors.isBuiltInExecutableAction;
|
|
1804
2720
|
exports.isMachineSnapshot = dist_xstateActors.isMachineSnapshot;
|
|
1805
2721
|
exports.listenerLogic = dist_xstateActors.listenerLogic;
|
|
1806
2722
|
exports.matchesState = dist_xstateActors.matchesState;
|
|
@@ -1812,9 +2728,11 @@ exports.StateNode = StateMachine.StateNode;
|
|
|
1812
2728
|
exports.SimulatedClock = SimulatedClock;
|
|
1813
2729
|
exports.SpecialTargets = SpecialTargets;
|
|
1814
2730
|
exports.assertEvent = assertEvent;
|
|
2731
|
+
exports.createFSM = createFSM;
|
|
1815
2732
|
exports.createMachine = createMachine;
|
|
1816
2733
|
exports.createMachineFromConfig = createMachineFromConfig;
|
|
1817
2734
|
exports.createStateConfig = createStateConfig;
|
|
2735
|
+
exports.createSystem = createSystem;
|
|
1818
2736
|
exports.getInitialMicrosteps = getInitialMicrosteps;
|
|
1819
2737
|
exports.getInitialSnapshot = getInitialSnapshot;
|
|
1820
2738
|
exports.getMicrosteps = getMicrosteps;
|