xstate 5.0.0-beta.26 → 5.0.0-beta.28

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.
Files changed (71) hide show
  1. package/README.md +9 -7
  2. package/actions/dist/xstate-actions.cjs.js +14 -18
  3. package/actions/dist/xstate-actions.cjs.mjs +0 -6
  4. package/actions/dist/xstate-actions.development.cjs.js +14 -18
  5. package/actions/dist/xstate-actions.development.cjs.mjs +0 -6
  6. package/actions/dist/xstate-actions.development.esm.js +3 -1
  7. package/actions/dist/xstate-actions.esm.js +3 -1
  8. package/actions/dist/xstate-actions.umd.min.js +1 -1
  9. package/actions/dist/xstate-actions.umd.min.js.map +1 -1
  10. package/actors/dist/xstate-actors.cjs.js +439 -14
  11. package/actors/dist/xstate-actors.cjs.mjs +0 -5
  12. package/actors/dist/xstate-actors.development.cjs.js +439 -14
  13. package/actors/dist/xstate-actors.development.cjs.mjs +0 -5
  14. package/actors/dist/xstate-actors.development.esm.js +435 -1
  15. package/actors/dist/xstate-actors.esm.js +435 -1
  16. package/actors/dist/xstate-actors.umd.min.js +1 -1
  17. package/actors/dist/xstate-actors.umd.min.js.map +1 -1
  18. package/dist/declarations/src/Machine.d.ts +4 -3
  19. package/dist/declarations/src/State.d.ts +1 -1
  20. package/dist/declarations/src/StateNode.d.ts +3 -12
  21. package/dist/declarations/src/actions/assign.d.ts +11 -11
  22. package/dist/declarations/src/actions/cancel.d.ts +5 -12
  23. package/dist/declarations/src/actions/choose.d.ts +9 -7
  24. package/dist/declarations/src/actions/log.d.ts +5 -20
  25. package/dist/declarations/src/actions/pure.d.ts +11 -9
  26. package/dist/declarations/src/actions/raise.d.ts +6 -5
  27. package/dist/declarations/src/actions/send.d.ts +7 -12
  28. package/dist/declarations/src/actions/stop.d.ts +5 -12
  29. package/dist/declarations/src/actions.d.ts +8 -42
  30. package/dist/declarations/src/actors/index.d.ts +2 -22
  31. package/dist/declarations/src/actors/promise.d.ts +2 -1
  32. package/dist/declarations/src/constants.d.ts +8 -0
  33. package/dist/declarations/src/guards.d.ts +2 -2
  34. package/dist/declarations/src/index.d.ts +11 -18
  35. package/dist/declarations/src/spawn.d.ts +25 -0
  36. package/dist/declarations/src/stateUtils.d.ts +1 -1
  37. package/dist/declarations/src/typegenTypes.d.ts +5 -5
  38. package/dist/declarations/src/types.d.ts +81 -108
  39. package/dist/declarations/src/utils.d.ts +2 -3
  40. package/dist/interpreter-672794ae.cjs.js +792 -0
  41. package/dist/interpreter-a1432c7d.development.cjs.js +800 -0
  42. package/dist/interpreter-a77bb0ec.development.esm.js +765 -0
  43. package/dist/interpreter-b5203bcb.esm.js +757 -0
  44. package/dist/raise-436a57a2.cjs.js +1458 -0
  45. package/dist/raise-74b72ca5.development.cjs.js +1498 -0
  46. package/dist/raise-a60c9290.development.esm.js +1468 -0
  47. package/dist/raise-b9c9a234.esm.js +1428 -0
  48. package/dist/send-35e1a689.cjs.js +349 -0
  49. package/dist/send-4192e7bc.esm.js +339 -0
  50. package/dist/send-e63b7b83.development.esm.js +364 -0
  51. package/dist/send-e8b55d00.development.cjs.js +374 -0
  52. package/dist/xstate.cjs.js +140 -160
  53. package/dist/xstate.cjs.mjs +4 -2
  54. package/dist/xstate.development.cjs.js +140 -160
  55. package/dist/xstate.development.cjs.mjs +4 -2
  56. package/dist/xstate.development.esm.js +75 -95
  57. package/dist/xstate.esm.js +75 -95
  58. package/dist/xstate.umd.min.js +1 -1
  59. package/dist/xstate.umd.min.js.map +1 -1
  60. package/guards/dist/xstate-guards.cjs.js +7 -6
  61. package/guards/dist/xstate-guards.development.cjs.js +7 -6
  62. package/guards/dist/xstate-guards.development.esm.js +2 -1
  63. package/guards/dist/xstate-guards.esm.js +2 -1
  64. package/guards/dist/xstate-guards.umd.min.js +1 -1
  65. package/guards/dist/xstate-guards.umd.min.js.map +1 -1
  66. package/package.json +1 -1
  67. package/dist/actions-0971b43d.development.cjs.js +0 -3168
  68. package/dist/actions-319cefe7.cjs.js +0 -3095
  69. package/dist/actions-5943a9db.esm.js +0 -3018
  70. package/dist/actions-cf69419d.development.esm.js +0 -3091
  71. package/dist/declarations/src/constantPrefixes.d.ts +0 -6
@@ -0,0 +1,1468 @@
1
+ import { r as resolveReferencedActor, d as createActor, f as ActorStatus, l as createErrorActorEvent, o as toStateValue, q as STATE_IDENTIFIER, u as normalizeTarget, t as toArray, N as NULL_EVENT, a as toTransitionConfigArray, S as STATE_DELIMITER, v as toStatePath, w as createDoneStateEvent, x as mapContext, W as WILDCARD, n as XSTATE_STOP, X as XSTATE_INIT, y as isArray, z as createAfterEvent, B as flatten, e as matchesState } from './interpreter-a77bb0ec.development.esm.js';
2
+
3
+ const cache = new WeakMap();
4
+ function memo(object, key, fn) {
5
+ let memoizedData = cache.get(object);
6
+ if (!memoizedData) {
7
+ memoizedData = {
8
+ [key]: fn()
9
+ };
10
+ cache.set(object, memoizedData);
11
+ } else if (!(key in memoizedData)) {
12
+ memoizedData[key] = fn();
13
+ }
14
+ return memoizedData[key];
15
+ }
16
+
17
+ function resolve$3(_, state, actionArgs, {
18
+ sendId
19
+ }) {
20
+ const resolvedSendId = typeof sendId === 'function' ? sendId(actionArgs) : sendId;
21
+ return [state, resolvedSendId];
22
+ }
23
+ function execute$3(actorContext, resolvedSendId) {
24
+ actorContext.self.cancel(resolvedSendId);
25
+ }
26
+ /**
27
+ * Cancels an in-flight `send(...)` action. A canceled sent action will not
28
+ * be executed, nor will its event be sent, unless it has already been sent
29
+ * (e.g., if `cancel(...)` is called after the `send(...)` action's `delay`).
30
+ *
31
+ * @param sendId The `id` of the `send(...)` action to cancel.
32
+ */
33
+ function cancel(sendId) {
34
+ function cancel(_) {
35
+ {
36
+ throw new Error(`This isn't supposed to be called`);
37
+ }
38
+ }
39
+ cancel.type = 'xstate.cancel';
40
+ cancel.sendId = sendId;
41
+ cancel.resolve = resolve$3;
42
+ cancel.execute = execute$3;
43
+ return cancel;
44
+ }
45
+
46
+ function resolve$2(actorContext, state, actionArgs, {
47
+ id,
48
+ systemId,
49
+ src,
50
+ input
51
+ }) {
52
+ const referenced = resolveReferencedActor(state.machine.implementations.actors[src]);
53
+ let actorRef;
54
+ if (referenced) {
55
+ // TODO: inline `input: undefined` should win over the referenced one
56
+ const configuredInput = input || referenced.input;
57
+ actorRef = createActor(referenced.src, {
58
+ id,
59
+ src,
60
+ parent: actorContext?.self,
61
+ systemId,
62
+ input: typeof configuredInput === 'function' ? configuredInput({
63
+ context: state.context,
64
+ event: actionArgs.event,
65
+ self: actorContext?.self
66
+ }) : configuredInput
67
+ });
68
+ }
69
+ if (!actorRef) {
70
+ console.warn(`Actor type '${src}' not found in machine '${actorContext.id}'.`);
71
+ }
72
+ return [cloneState(state, {
73
+ children: {
74
+ ...state.children,
75
+ [id]: actorRef
76
+ }
77
+ }), {
78
+ id,
79
+ actorRef
80
+ }];
81
+ }
82
+ function execute$2(actorContext, {
83
+ id,
84
+ actorRef
85
+ }) {
86
+ if (!actorRef) {
87
+ return;
88
+ }
89
+ actorContext.defer(() => {
90
+ if (actorRef.status === ActorStatus.Stopped) {
91
+ return;
92
+ }
93
+ try {
94
+ actorRef.start?.();
95
+ } catch (err) {
96
+ actorContext.self.send(createErrorActorEvent(id, err));
97
+ return;
98
+ }
99
+ });
100
+ }
101
+
102
+ // we don't export this since it's an internal action that is not meant to be used in the user's code
103
+
104
+ function invoke({
105
+ id,
106
+ systemId,
107
+ src,
108
+ input
109
+ }) {
110
+ function invoke(_) {
111
+ {
112
+ throw new Error(`This isn't supposed to be called`);
113
+ }
114
+ }
115
+ invoke.type = 'xstate.invoke';
116
+ invoke.id = id;
117
+ invoke.systemId = systemId;
118
+ invoke.src = src;
119
+ invoke.input = input;
120
+ invoke.resolve = resolve$2;
121
+ invoke.execute = execute$2;
122
+ return invoke;
123
+ }
124
+
125
+ function resolve$1(_, state, args, {
126
+ actorRef
127
+ }) {
128
+ const actorRefOrString = typeof actorRef === 'function' ? actorRef(args) : actorRef;
129
+ const resolvedActorRef = typeof actorRefOrString === 'string' ? state.children[actorRefOrString] : actorRefOrString;
130
+ let children = state.children;
131
+ if (resolvedActorRef) {
132
+ children = {
133
+ ...children
134
+ };
135
+ delete children[resolvedActorRef.id];
136
+ }
137
+ return [cloneState(state, {
138
+ children
139
+ }), resolvedActorRef];
140
+ }
141
+ function execute$1(actorContext, actorRef) {
142
+ if (!actorRef) {
143
+ return;
144
+ }
145
+ if (actorRef.status !== ActorStatus.Running) {
146
+ actorContext.stopChild(actorRef);
147
+ return;
148
+ }
149
+ // TODO: recheck why this one has to be deferred
150
+ actorContext.defer(() => {
151
+ actorContext.stopChild(actorRef);
152
+ });
153
+ }
154
+ /**
155
+ * Stops an actor.
156
+ *
157
+ * @param actorRef The actor to stop.
158
+ */
159
+ function stop(actorRef) {
160
+ function stop(_) {
161
+ {
162
+ throw new Error(`This isn't supposed to be called`);
163
+ }
164
+ }
165
+ stop.type = 'xstate.stop';
166
+ stop.actorRef = actorRef;
167
+ stop.resolve = resolve$1;
168
+ stop.execute = execute$1;
169
+ return stop;
170
+ }
171
+
172
+ function checkStateIn(state, _, {
173
+ stateValue
174
+ }) {
175
+ if (typeof stateValue === 'string' && isStateId(stateValue)) {
176
+ return state.configuration.some(sn => sn.id === stateValue.slice(1));
177
+ }
178
+ return state.matches(stateValue);
179
+ }
180
+ function stateIn(stateValue) {
181
+ function stateIn(_) {
182
+ {
183
+ throw new Error(`This isn't supposed to be called`);
184
+ }
185
+ }
186
+ stateIn.check = checkStateIn;
187
+ stateIn.stateValue = stateValue;
188
+ return stateIn;
189
+ }
190
+ function checkNot(state, {
191
+ context,
192
+ event
193
+ }, {
194
+ guards
195
+ }) {
196
+ return !evaluateGuard(guards[0], context, event, state);
197
+ }
198
+ function not(guard) {
199
+ function not(_) {
200
+ {
201
+ throw new Error(`This isn't supposed to be called`);
202
+ }
203
+ }
204
+ not.check = checkNot;
205
+ not.guards = [guard];
206
+ return not;
207
+ }
208
+ function checkAnd(state, {
209
+ context,
210
+ event
211
+ }, {
212
+ guards
213
+ }) {
214
+ return guards.every(guard => evaluateGuard(guard, context, event, state));
215
+ }
216
+ function and(guards) {
217
+ function and(_) {
218
+ {
219
+ throw new Error(`This isn't supposed to be called`);
220
+ }
221
+ }
222
+ and.check = checkAnd;
223
+ and.guards = guards;
224
+ return and;
225
+ }
226
+ function checkOr(state, {
227
+ context,
228
+ event
229
+ }, {
230
+ guards
231
+ }) {
232
+ return guards.some(guard => evaluateGuard(guard, context, event, state));
233
+ }
234
+ function or(guards) {
235
+ function or(_) {
236
+ {
237
+ throw new Error(`This isn't supposed to be called`);
238
+ }
239
+ }
240
+ or.check = checkOr;
241
+ or.guards = guards;
242
+ return or;
243
+ }
244
+
245
+ // TODO: throw on cycles (depth check should be enough)
246
+ function evaluateGuard(guard, context, event, state) {
247
+ const {
248
+ machine
249
+ } = state;
250
+ const isInline = typeof guard === 'function';
251
+ const resolved = isInline ? guard : machine.implementations.guards[typeof guard === 'string' ? guard : guard.type];
252
+ if (!isInline && !resolved) {
253
+ throw new Error(`Guard '${typeof guard === 'string' ? guard : guard.type}' is not implemented.'.`);
254
+ }
255
+ if (typeof resolved !== 'function') {
256
+ return evaluateGuard(resolved, context, event, state);
257
+ }
258
+ const guardArgs = {
259
+ context,
260
+ event,
261
+ guard: isInline ? undefined : typeof guard === 'string' ? {
262
+ type: guard
263
+ } : typeof guard.params === 'function' ? {
264
+ type: guard.type,
265
+ params: guard.params({
266
+ context,
267
+ event
268
+ })
269
+ } : guard
270
+ };
271
+ if (!('check' in resolved)) {
272
+ // the existing type of `.guards` assumes non-nullable `TExpressionGuard`
273
+ // inline guards expect `TExpressionGuard` to be set to `undefined`
274
+ // it's fine to cast this here, our logic makes sure that we call those 2 "variants" correctly
275
+ return resolved(guardArgs);
276
+ }
277
+ const builtinGuard = resolved;
278
+ return builtinGuard.check(state, guardArgs, resolved // this holds all params
279
+ );
280
+ }
281
+
282
+ function getOutput(configuration, context, event, self) {
283
+ const machine = configuration[0].machine;
284
+ const finalChildStateNode = configuration.find(stateNode => stateNode.type === 'final' && stateNode.parent === machine.root);
285
+ return finalChildStateNode && finalChildStateNode.output ? mapContext(finalChildStateNode.output, context, event, self) : undefined;
286
+ }
287
+ const isAtomicStateNode = stateNode => stateNode.type === 'atomic' || stateNode.type === 'final';
288
+ function getChildren(stateNode) {
289
+ return Object.values(stateNode.states).filter(sn => sn.type !== 'history');
290
+ }
291
+ function getProperAncestors(stateNode, toStateNode) {
292
+ const ancestors = [];
293
+
294
+ // add all ancestors
295
+ let m = stateNode.parent;
296
+ while (m && m !== toStateNode) {
297
+ ancestors.push(m);
298
+ m = m.parent;
299
+ }
300
+ return ancestors;
301
+ }
302
+ function getConfiguration(stateNodes) {
303
+ const configuration = new Set(stateNodes);
304
+ const configurationSet = new Set(stateNodes);
305
+ const adjList = getAdjList(configurationSet);
306
+
307
+ // add descendants
308
+ for (const s of configuration) {
309
+ // if previously active, add existing child nodes
310
+ if (s.type === 'compound' && (!adjList.get(s) || !adjList.get(s).length)) {
311
+ getInitialStateNodes(s).forEach(sn => configurationSet.add(sn));
312
+ } else {
313
+ if (s.type === 'parallel') {
314
+ for (const child of getChildren(s)) {
315
+ if (child.type === 'history') {
316
+ continue;
317
+ }
318
+ if (!configurationSet.has(child)) {
319
+ for (const initialStateNode of getInitialStateNodes(child)) {
320
+ configurationSet.add(initialStateNode);
321
+ }
322
+ }
323
+ }
324
+ }
325
+ }
326
+ }
327
+
328
+ // add all ancestors
329
+ for (const s of configurationSet) {
330
+ let m = s.parent;
331
+ while (m) {
332
+ configurationSet.add(m);
333
+ m = m.parent;
334
+ }
335
+ }
336
+ return configurationSet;
337
+ }
338
+ function getValueFromAdj(baseNode, adjList) {
339
+ const childStateNodes = adjList.get(baseNode);
340
+ if (!childStateNodes) {
341
+ return {}; // todo: fix?
342
+ }
343
+
344
+ if (baseNode.type === 'compound') {
345
+ const childStateNode = childStateNodes[0];
346
+ if (childStateNode) {
347
+ if (isAtomicStateNode(childStateNode)) {
348
+ return childStateNode.key;
349
+ }
350
+ } else {
351
+ return {};
352
+ }
353
+ }
354
+ const stateValue = {};
355
+ for (const childStateNode of childStateNodes) {
356
+ stateValue[childStateNode.key] = getValueFromAdj(childStateNode, adjList);
357
+ }
358
+ return stateValue;
359
+ }
360
+ function getAdjList(configuration) {
361
+ const adjList = new Map();
362
+ for (const s of configuration) {
363
+ if (!adjList.has(s)) {
364
+ adjList.set(s, []);
365
+ }
366
+ if (s.parent) {
367
+ if (!adjList.has(s.parent)) {
368
+ adjList.set(s.parent, []);
369
+ }
370
+ adjList.get(s.parent).push(s);
371
+ }
372
+ }
373
+ return adjList;
374
+ }
375
+ function getStateValue(rootNode, configuration) {
376
+ const config = getConfiguration(configuration);
377
+ return getValueFromAdj(rootNode, getAdjList(config));
378
+ }
379
+ function isInFinalState(configuration, stateNode = configuration[0].machine.root) {
380
+ if (stateNode.type === 'compound') {
381
+ return getChildren(stateNode).some(s => s.type === 'final' && configuration.includes(s));
382
+ }
383
+ if (stateNode.type === 'parallel') {
384
+ return getChildren(stateNode).every(sn => isInFinalState(configuration, sn));
385
+ }
386
+ return false;
387
+ }
388
+ const isStateId = str => str[0] === STATE_IDENTIFIER;
389
+ function getCandidates(stateNode, receivedEventType) {
390
+ const candidates = stateNode.transitions.get(receivedEventType) || [...stateNode.transitions.keys()].filter(descriptor => {
391
+ // check if transition is a wildcard transition,
392
+ // which matches any non-transient events
393
+ if (descriptor === WILDCARD) {
394
+ return true;
395
+ }
396
+ if (!descriptor.endsWith('.*')) {
397
+ return false;
398
+ }
399
+ if (/.*\*.+/.test(descriptor)) {
400
+ console.warn(`Wildcards can only be the last token of an event descriptor (e.g., "event.*") or the entire event descriptor ("*"). Check the "${descriptor}" event.`);
401
+ }
402
+ const partialEventTokens = descriptor.split('.');
403
+ const eventTokens = receivedEventType.split('.');
404
+ for (let tokenIndex = 0; tokenIndex < partialEventTokens.length; tokenIndex++) {
405
+ const partialEventToken = partialEventTokens[tokenIndex];
406
+ const eventToken = eventTokens[tokenIndex];
407
+ if (partialEventToken === '*') {
408
+ const isLastToken = tokenIndex === partialEventTokens.length - 1;
409
+ if (!isLastToken) {
410
+ console.warn(`Infix wildcards in transition events are not allowed. Check the "${descriptor}" transition.`);
411
+ }
412
+ return isLastToken;
413
+ }
414
+ if (partialEventToken !== eventToken) {
415
+ return false;
416
+ }
417
+ }
418
+ return true;
419
+ }).sort((a, b) => b.length - a.length).flatMap(key => stateNode.transitions.get(key));
420
+ return candidates;
421
+ }
422
+
423
+ /**
424
+ * All delayed transitions from the config.
425
+ */
426
+ function getDelayedTransitions(stateNode) {
427
+ const afterConfig = stateNode.config.after;
428
+ if (!afterConfig) {
429
+ return [];
430
+ }
431
+ const mutateEntryExit = (delay, i) => {
432
+ const delayRef = typeof delay === 'function' ? `${stateNode.id}:delay[${i}]` : delay;
433
+ const afterEvent = createAfterEvent(delayRef, stateNode.id);
434
+ const eventType = afterEvent.type;
435
+ stateNode.entry.push(raise(afterEvent, {
436
+ id: eventType,
437
+ delay
438
+ }));
439
+ stateNode.exit.push(cancel(eventType));
440
+ return eventType;
441
+ };
442
+ const delayedTransitions = isArray(afterConfig) ? afterConfig.map((transition, i) => {
443
+ const eventType = mutateEntryExit(transition.delay, i);
444
+ return {
445
+ ...transition,
446
+ event: eventType
447
+ };
448
+ }) : Object.keys(afterConfig).flatMap((delay, i) => {
449
+ const configTransition = afterConfig[delay];
450
+ const resolvedTransition = typeof configTransition === 'string' ? {
451
+ target: configTransition
452
+ } : configTransition;
453
+ const resolvedDelay = !isNaN(+delay) ? +delay : delay;
454
+ const eventType = mutateEntryExit(resolvedDelay, i);
455
+ return toArray(resolvedTransition).map(transition => ({
456
+ ...transition,
457
+ event: eventType,
458
+ delay: resolvedDelay
459
+ }));
460
+ });
461
+ return delayedTransitions.map(delayedTransition => {
462
+ const {
463
+ delay
464
+ } = delayedTransition;
465
+ return {
466
+ ...formatTransition(stateNode, delayedTransition.event, delayedTransition),
467
+ delay
468
+ };
469
+ });
470
+ }
471
+ function formatTransition(stateNode, descriptor, transitionConfig) {
472
+ const normalizedTarget = normalizeTarget(transitionConfig.target);
473
+ const reenter = transitionConfig.reenter ?? false;
474
+ const target = resolveTarget(stateNode, normalizedTarget);
475
+
476
+ // TODO: should this be part of a lint rule instead?
477
+ if (transitionConfig.cond) {
478
+ throw new Error(`State "${stateNode.id}" has declared \`cond\` for one of its transitions. This property has been renamed to \`guard\`. Please update your code.`);
479
+ }
480
+ const transition = {
481
+ ...transitionConfig,
482
+ actions: toArray(transitionConfig.actions),
483
+ guard: transitionConfig.guard,
484
+ target,
485
+ source: stateNode,
486
+ reenter,
487
+ eventType: descriptor,
488
+ toJSON: () => ({
489
+ ...transition,
490
+ source: `#${stateNode.id}`,
491
+ target: target ? target.map(t => `#${t.id}`) : undefined
492
+ })
493
+ };
494
+ return transition;
495
+ }
496
+ function formatTransitions(stateNode) {
497
+ const transitions = new Map();
498
+ if (stateNode.config.on) {
499
+ for (const descriptor of Object.keys(stateNode.config.on)) {
500
+ if (descriptor === NULL_EVENT) {
501
+ throw new Error('Null events ("") cannot be specified as a transition key. Use `always: { ... }` instead.');
502
+ }
503
+ const transitionsConfig = stateNode.config.on[descriptor];
504
+ transitions.set(descriptor, toTransitionConfigArray(transitionsConfig).map(t => formatTransition(stateNode, descriptor, t)));
505
+ }
506
+ }
507
+ if (stateNode.config.onDone) {
508
+ const descriptor = `xstate.done.state.${stateNode.id}`;
509
+ transitions.set(descriptor, toTransitionConfigArray(stateNode.config.onDone).map(t => formatTransition(stateNode, descriptor, t)));
510
+ }
511
+ for (const invokeDef of stateNode.invoke) {
512
+ if (invokeDef.onDone) {
513
+ const descriptor = `xstate.done.actor.${invokeDef.id}`;
514
+ transitions.set(descriptor, toTransitionConfigArray(invokeDef.onDone).map(t => formatTransition(stateNode, descriptor, t)));
515
+ }
516
+ if (invokeDef.onError) {
517
+ const descriptor = `xstate.error.actor.${invokeDef.id}`;
518
+ transitions.set(descriptor, toTransitionConfigArray(invokeDef.onError).map(t => formatTransition(stateNode, descriptor, t)));
519
+ }
520
+ if (invokeDef.onSnapshot) {
521
+ const descriptor = `xstate.snapshot.${invokeDef.id}`;
522
+ transitions.set(descriptor, toTransitionConfigArray(invokeDef.onSnapshot).map(t => formatTransition(stateNode, descriptor, t)));
523
+ }
524
+ }
525
+ for (const delayedTransition of stateNode.after) {
526
+ let existing = transitions.get(delayedTransition.eventType);
527
+ if (!existing) {
528
+ existing = [];
529
+ transitions.set(delayedTransition.eventType, existing);
530
+ }
531
+ existing.push(delayedTransition);
532
+ }
533
+ return transitions;
534
+ }
535
+ function formatInitialTransition(stateNode, _target) {
536
+ if (typeof _target === 'string' || isArray(_target)) {
537
+ const targets = toArray(_target).map(t => {
538
+ // Resolve state string keys (which represent children)
539
+ // to their state node
540
+ const descStateNode = typeof t === 'string' ? isStateId(t) ? stateNode.machine.getStateNodeById(t) : stateNode.states[t] : t;
541
+ if (!descStateNode) {
542
+ throw new Error(`Initial state node "${t}" not found on parent state node #${stateNode.id}`);
543
+ }
544
+ if (!isDescendant(descStateNode, stateNode)) {
545
+ throw new Error(`Invalid initial target: state node #${descStateNode.id} is not a descendant of #${stateNode.id}`);
546
+ }
547
+ return descStateNode;
548
+ });
549
+ const resolvedTarget = resolveTarget(stateNode, targets);
550
+ const transition = {
551
+ source: stateNode,
552
+ actions: [],
553
+ eventType: null,
554
+ reenter: false,
555
+ target: resolvedTarget,
556
+ toJSON: () => ({
557
+ ...transition,
558
+ source: `#${stateNode.id}`,
559
+ target: resolvedTarget ? resolvedTarget.map(t => `#${t.id}`) : undefined
560
+ })
561
+ };
562
+ return transition;
563
+ }
564
+ return formatTransition(stateNode, '__INITIAL__', {
565
+ target: toArray(_target.target).map(t => {
566
+ if (typeof t === 'string') {
567
+ return isStateId(t) ? t : `${STATE_DELIMITER}${t}`;
568
+ }
569
+ return t;
570
+ }),
571
+ actions: _target.actions
572
+ });
573
+ }
574
+ function resolveTarget(stateNode, targets) {
575
+ if (targets === undefined) {
576
+ // an undefined target signals that the state node should not transition from that state when receiving that event
577
+ return undefined;
578
+ }
579
+ return targets.map(target => {
580
+ if (typeof target !== 'string') {
581
+ return target;
582
+ }
583
+ if (isStateId(target)) {
584
+ return stateNode.machine.getStateNodeById(target);
585
+ }
586
+ const isInternalTarget = target[0] === STATE_DELIMITER;
587
+ // If internal target is defined on machine,
588
+ // do not include machine key on target
589
+ if (isInternalTarget && !stateNode.parent) {
590
+ return getStateNodeByPath(stateNode, target.slice(1));
591
+ }
592
+ const resolvedTarget = isInternalTarget ? stateNode.key + target : target;
593
+ if (stateNode.parent) {
594
+ try {
595
+ const targetStateNode = getStateNodeByPath(stateNode.parent, resolvedTarget);
596
+ return targetStateNode;
597
+ } catch (err) {
598
+ throw new Error(`Invalid transition definition for state node '${stateNode.id}':\n${err.message}`);
599
+ }
600
+ } else {
601
+ throw new Error(`Invalid target: "${target}" is not a valid target from the root node. Did you mean ".${target}"?`);
602
+ }
603
+ });
604
+ }
605
+ function resolveHistoryTarget(stateNode) {
606
+ const normalizedTarget = normalizeTarget(stateNode.config.target);
607
+ if (!normalizedTarget) {
608
+ return stateNode.parent.initial.target;
609
+ }
610
+ return normalizedTarget.map(t => typeof t === 'string' ? getStateNodeByPath(stateNode.parent, t) : t);
611
+ }
612
+ function isHistoryNode(stateNode) {
613
+ return stateNode.type === 'history';
614
+ }
615
+ function getInitialStateNodes(stateNode) {
616
+ const set = new Set();
617
+ function iter(descStateNode) {
618
+ if (set.has(descStateNode)) {
619
+ return;
620
+ }
621
+ set.add(descStateNode);
622
+ if (descStateNode.type === 'compound') {
623
+ for (const targetStateNode of descStateNode.initial.target) {
624
+ for (const a of getProperAncestors(targetStateNode, stateNode)) {
625
+ set.add(a);
626
+ }
627
+ iter(targetStateNode);
628
+ }
629
+ } else if (descStateNode.type === 'parallel') {
630
+ for (const child of getChildren(descStateNode)) {
631
+ iter(child);
632
+ }
633
+ }
634
+ }
635
+ iter(stateNode);
636
+ return [...set];
637
+ }
638
+ /**
639
+ * Returns the child state node from its relative `stateKey`, or throws.
640
+ */
641
+ function getStateNode(stateNode, stateKey) {
642
+ if (isStateId(stateKey)) {
643
+ return stateNode.machine.getStateNodeById(stateKey);
644
+ }
645
+ if (!stateNode.states) {
646
+ throw new Error(`Unable to retrieve child state '${stateKey}' from '${stateNode.id}'; no child states exist.`);
647
+ }
648
+ const result = stateNode.states[stateKey];
649
+ if (!result) {
650
+ throw new Error(`Child state '${stateKey}' does not exist on '${stateNode.id}'`);
651
+ }
652
+ return result;
653
+ }
654
+
655
+ /**
656
+ * Returns the relative state node from the given `statePath`, or throws.
657
+ *
658
+ * @param statePath The string or string array relative path to the state node.
659
+ */
660
+ function getStateNodeByPath(stateNode, statePath) {
661
+ if (typeof statePath === 'string' && isStateId(statePath)) {
662
+ try {
663
+ return stateNode.machine.getStateNodeById(statePath);
664
+ } catch (e) {
665
+ // try individual paths
666
+ // throw e;
667
+ }
668
+ }
669
+ const arrayStatePath = toStatePath(statePath).slice();
670
+ let currentStateNode = stateNode;
671
+ while (arrayStatePath.length) {
672
+ const key = arrayStatePath.shift();
673
+ if (!key.length) {
674
+ break;
675
+ }
676
+ currentStateNode = getStateNode(currentStateNode, key);
677
+ }
678
+ return currentStateNode;
679
+ }
680
+
681
+ /**
682
+ * Returns the state nodes represented by the current state value.
683
+ *
684
+ * @param state The state value or State instance
685
+ */
686
+ function getStateNodes(stateNode, state) {
687
+ const stateValue = state instanceof State ? state.value : toStateValue(state);
688
+ if (typeof stateValue === 'string') {
689
+ return [stateNode, stateNode.states[stateValue]];
690
+ }
691
+ const childStateKeys = Object.keys(stateValue);
692
+ const childStateNodes = childStateKeys.map(subStateKey => getStateNode(stateNode, subStateKey)).filter(Boolean);
693
+ return [stateNode.machine.root, stateNode].concat(childStateNodes, childStateKeys.reduce((allSubStateNodes, subStateKey) => {
694
+ const subStateNode = getStateNode(stateNode, subStateKey);
695
+ if (!subStateNode) {
696
+ return allSubStateNodes;
697
+ }
698
+ const subStateNodes = getStateNodes(subStateNode, stateValue[subStateKey]);
699
+ return allSubStateNodes.concat(subStateNodes);
700
+ }, []));
701
+ }
702
+ function transitionAtomicNode(stateNode, stateValue, state, event) {
703
+ const childStateNode = getStateNode(stateNode, stateValue);
704
+ const next = childStateNode.next(state, event);
705
+ if (!next || !next.length) {
706
+ return stateNode.next(state, event);
707
+ }
708
+ return next;
709
+ }
710
+ function transitionCompoundNode(stateNode, stateValue, state, event) {
711
+ const subStateKeys = Object.keys(stateValue);
712
+ const childStateNode = getStateNode(stateNode, subStateKeys[0]);
713
+ const next = transitionNode(childStateNode, stateValue[subStateKeys[0]], state, event);
714
+ if (!next || !next.length) {
715
+ return stateNode.next(state, event);
716
+ }
717
+ return next;
718
+ }
719
+ function transitionParallelNode(stateNode, stateValue, state, event) {
720
+ const allInnerTransitions = [];
721
+ for (const subStateKey of Object.keys(stateValue)) {
722
+ const subStateValue = stateValue[subStateKey];
723
+ if (!subStateValue) {
724
+ continue;
725
+ }
726
+ const subStateNode = getStateNode(stateNode, subStateKey);
727
+ const innerTransitions = transitionNode(subStateNode, subStateValue, state, event);
728
+ if (innerTransitions) {
729
+ allInnerTransitions.push(...innerTransitions);
730
+ }
731
+ }
732
+ if (!allInnerTransitions.length) {
733
+ return stateNode.next(state, event);
734
+ }
735
+ return allInnerTransitions;
736
+ }
737
+ function transitionNode(stateNode, stateValue, state, event) {
738
+ // leaf node
739
+ if (typeof stateValue === 'string') {
740
+ return transitionAtomicNode(stateNode, stateValue, state, event);
741
+ }
742
+
743
+ // compound node
744
+ if (Object.keys(stateValue).length === 1) {
745
+ return transitionCompoundNode(stateNode, stateValue, state, event);
746
+ }
747
+
748
+ // parallel node
749
+ return transitionParallelNode(stateNode, stateValue, state, event);
750
+ }
751
+ function getHistoryNodes(stateNode) {
752
+ return Object.keys(stateNode.states).map(key => stateNode.states[key]).filter(sn => sn.type === 'history');
753
+ }
754
+ function isDescendant(childStateNode, parentStateNode) {
755
+ let marker = childStateNode;
756
+ while (marker.parent && marker.parent !== parentStateNode) {
757
+ marker = marker.parent;
758
+ }
759
+ return marker.parent === parentStateNode;
760
+ }
761
+ function getPathFromRootToNode(stateNode) {
762
+ const path = [];
763
+ let marker = stateNode.parent;
764
+ while (marker) {
765
+ path.unshift(marker);
766
+ marker = marker.parent;
767
+ }
768
+ return path;
769
+ }
770
+ function hasIntersection(s1, s2) {
771
+ const set1 = new Set(s1);
772
+ const set2 = new Set(s2);
773
+ for (const item of set1) {
774
+ if (set2.has(item)) {
775
+ return true;
776
+ }
777
+ }
778
+ for (const item of set2) {
779
+ if (set1.has(item)) {
780
+ return true;
781
+ }
782
+ }
783
+ return false;
784
+ }
785
+ function removeConflictingTransitions(enabledTransitions, configuration, historyValue) {
786
+ const filteredTransitions = new Set();
787
+ for (const t1 of enabledTransitions) {
788
+ let t1Preempted = false;
789
+ const transitionsToRemove = new Set();
790
+ for (const t2 of filteredTransitions) {
791
+ if (hasIntersection(computeExitSet([t1], configuration, historyValue), computeExitSet([t2], configuration, historyValue))) {
792
+ if (isDescendant(t1.source, t2.source)) {
793
+ transitionsToRemove.add(t2);
794
+ } else {
795
+ t1Preempted = true;
796
+ break;
797
+ }
798
+ }
799
+ }
800
+ if (!t1Preempted) {
801
+ for (const t3 of transitionsToRemove) {
802
+ filteredTransitions.delete(t3);
803
+ }
804
+ filteredTransitions.add(t1);
805
+ }
806
+ }
807
+ return Array.from(filteredTransitions);
808
+ }
809
+ function findLCCA(stateNodes) {
810
+ const [head] = stateNodes;
811
+ let current = getPathFromRootToNode(head);
812
+ let candidates = [];
813
+ for (const stateNode of stateNodes) {
814
+ const path = getPathFromRootToNode(stateNode);
815
+ candidates = current.filter(sn => path.includes(sn));
816
+ current = candidates;
817
+ candidates = [];
818
+ }
819
+ return current[current.length - 1];
820
+ }
821
+ function getEffectiveTargetStates(transition, historyValue) {
822
+ if (!transition.target) {
823
+ return [];
824
+ }
825
+ const targets = new Set();
826
+ for (const targetNode of transition.target) {
827
+ if (isHistoryNode(targetNode)) {
828
+ if (historyValue[targetNode.id]) {
829
+ for (const node of historyValue[targetNode.id]) {
830
+ targets.add(node);
831
+ }
832
+ } else {
833
+ for (const node of getEffectiveTargetStates({
834
+ target: resolveHistoryTarget(targetNode)
835
+ }, historyValue)) {
836
+ targets.add(node);
837
+ }
838
+ }
839
+ } else {
840
+ targets.add(targetNode);
841
+ }
842
+ }
843
+ return [...targets];
844
+ }
845
+ function getTransitionDomain(transition, historyValue) {
846
+ const targetStates = getEffectiveTargetStates(transition, historyValue);
847
+ if (!targetStates) {
848
+ return null;
849
+ }
850
+ if (!transition.reenter && transition.source.type !== 'parallel' && targetStates.every(targetStateNode => isDescendant(targetStateNode, transition.source))) {
851
+ return transition.source;
852
+ }
853
+ const lcca = findLCCA(targetStates.concat(transition.source));
854
+ return lcca;
855
+ }
856
+ function computeExitSet(transitions, configuration, historyValue) {
857
+ const statesToExit = new Set();
858
+ for (const t of transitions) {
859
+ if (t.target?.length) {
860
+ const domain = getTransitionDomain(t, historyValue);
861
+ for (const stateNode of configuration) {
862
+ if (isDescendant(stateNode, domain)) {
863
+ statesToExit.add(stateNode);
864
+ }
865
+ }
866
+ }
867
+ }
868
+ return [...statesToExit];
869
+ }
870
+
871
+ /**
872
+ * https://www.w3.org/TR/scxml/#microstepProcedure
873
+ *
874
+ * @private
875
+ * @param transitions
876
+ * @param currentState
877
+ * @param mutConfiguration
878
+ */
879
+
880
+ function microstep(transitions, currentState, actorCtx, event, isInitial) {
881
+ const mutConfiguration = new Set(currentState.configuration);
882
+ if (!transitions.length) {
883
+ return currentState;
884
+ }
885
+ const microstate = microstepProcedure(transitions, currentState, mutConfiguration, event, actorCtx, isInitial);
886
+ return cloneState(microstate, {
887
+ value: {} // TODO: make optional
888
+ });
889
+ }
890
+
891
+ function microstepProcedure(transitions, currentState, mutConfiguration, event, actorCtx, isInitial) {
892
+ const actions = [];
893
+ const historyValue = {
894
+ ...currentState.historyValue
895
+ };
896
+ const filteredTransitions = removeConflictingTransitions(transitions, mutConfiguration, historyValue);
897
+ const internalQueue = [...currentState._internalQueue];
898
+
899
+ // Exit states
900
+ if (!isInitial) {
901
+ exitStates(filteredTransitions, mutConfiguration, historyValue, actions);
902
+ }
903
+
904
+ // Execute transition content
905
+ actions.push(...filteredTransitions.flatMap(t => t.actions));
906
+
907
+ // Enter states
908
+ enterStates(event, filteredTransitions, mutConfiguration, actions, internalQueue, currentState, historyValue, isInitial, actorCtx);
909
+ const nextConfiguration = [...mutConfiguration];
910
+ const done = isInFinalState(nextConfiguration);
911
+ if (done) {
912
+ const finalActions = nextConfiguration.sort((a, b) => b.order - a.order).flatMap(state => state.exit);
913
+ actions.push(...finalActions);
914
+ }
915
+ try {
916
+ const nextState = resolveActionsAndContext(actions, event, currentState, actorCtx);
917
+ const output = done ? getOutput(nextConfiguration, nextState.context, event, actorCtx.self) : undefined;
918
+ internalQueue.push(...nextState._internalQueue);
919
+ return cloneState(currentState, {
920
+ configuration: nextConfiguration,
921
+ historyValue,
922
+ _internalQueue: internalQueue,
923
+ context: nextState.context,
924
+ done,
925
+ output,
926
+ children: nextState.children
927
+ });
928
+ } catch (e) {
929
+ // TODO: Refactor this once proper error handling is implemented.
930
+ // See https://github.com/statelyai/rfcs/pull/4
931
+ throw e;
932
+ }
933
+ }
934
+ function enterStates(event, filteredTransitions, mutConfiguration, actions, internalQueue, currentState, historyValue, isInitial, actorContext) {
935
+ const statesToEnter = new Set();
936
+ const statesForDefaultEntry = new Set();
937
+ computeEntrySet(filteredTransitions, historyValue, statesForDefaultEntry, statesToEnter);
938
+
939
+ // In the initial state, the root state node is "entered".
940
+ if (isInitial) {
941
+ statesForDefaultEntry.add(currentState.machine.root);
942
+ }
943
+ for (const stateNodeToEnter of [...statesToEnter].sort((a, b) => a.order - b.order)) {
944
+ mutConfiguration.add(stateNodeToEnter);
945
+ for (const invokeDef of stateNodeToEnter.invoke) {
946
+ actions.push(invoke(invokeDef));
947
+ }
948
+
949
+ // Add entry actions
950
+ actions.push(...stateNodeToEnter.entry);
951
+ if (statesForDefaultEntry.has(stateNodeToEnter)) {
952
+ for (const stateNode of statesForDefaultEntry) {
953
+ const initialActions = stateNode.initial.actions;
954
+ actions.push(...initialActions);
955
+ }
956
+ }
957
+ if (stateNodeToEnter.type === 'final') {
958
+ const parent = stateNodeToEnter.parent;
959
+ if (!parent.parent) {
960
+ continue;
961
+ }
962
+ internalQueue.push(createDoneStateEvent(parent.id, stateNodeToEnter.output ? mapContext(stateNodeToEnter.output, currentState.context, event, actorContext.self) : undefined));
963
+ if (parent.parent) {
964
+ const grandparent = parent.parent;
965
+ if (grandparent.type === 'parallel') {
966
+ if (getChildren(grandparent).every(parentNode => isInFinalState([...mutConfiguration], parentNode))) {
967
+ internalQueue.push(createDoneStateEvent(grandparent.id));
968
+ }
969
+ }
970
+ }
971
+ }
972
+ }
973
+ }
974
+ function computeEntrySet(transitions, historyValue, statesForDefaultEntry, statesToEnter) {
975
+ for (const t of transitions) {
976
+ for (const s of t.target || []) {
977
+ addDescendantStatesToEnter(s, historyValue, statesForDefaultEntry, statesToEnter);
978
+ }
979
+ const ancestor = getTransitionDomain(t, historyValue);
980
+ const targetStates = getEffectiveTargetStates(t, historyValue);
981
+ for (const s of targetStates) {
982
+ addAncestorStatesToEnter(s, ancestor, statesToEnter, historyValue, statesForDefaultEntry);
983
+ }
984
+ }
985
+ }
986
+ function addDescendantStatesToEnter(stateNode, historyValue, statesForDefaultEntry, statesToEnter) {
987
+ if (isHistoryNode(stateNode)) {
988
+ if (historyValue[stateNode.id]) {
989
+ const historyStateNodes = historyValue[stateNode.id];
990
+ for (const s of historyStateNodes) {
991
+ addDescendantStatesToEnter(s, historyValue, statesForDefaultEntry, statesToEnter);
992
+ }
993
+ for (const s of historyStateNodes) {
994
+ addAncestorStatesToEnter(s, stateNode.parent, statesToEnter, historyValue, statesForDefaultEntry);
995
+ for (const stateForDefaultEntry of statesForDefaultEntry) {
996
+ statesForDefaultEntry.add(stateForDefaultEntry);
997
+ }
998
+ }
999
+ } else {
1000
+ const targets = resolveHistoryTarget(stateNode);
1001
+ for (const s of targets) {
1002
+ addDescendantStatesToEnter(s, historyValue, statesForDefaultEntry, statesToEnter);
1003
+ }
1004
+ for (const s of targets) {
1005
+ addAncestorStatesToEnter(s, stateNode, statesToEnter, historyValue, statesForDefaultEntry);
1006
+ for (const stateForDefaultEntry of statesForDefaultEntry) {
1007
+ statesForDefaultEntry.add(stateForDefaultEntry);
1008
+ }
1009
+ }
1010
+ }
1011
+ } else {
1012
+ statesToEnter.add(stateNode);
1013
+ if (stateNode.type === 'compound') {
1014
+ statesForDefaultEntry.add(stateNode);
1015
+ const initialStates = stateNode.initial.target;
1016
+ for (const initialState of initialStates) {
1017
+ addDescendantStatesToEnter(initialState, historyValue, statesForDefaultEntry, statesToEnter);
1018
+ }
1019
+ for (const initialState of initialStates) {
1020
+ addAncestorStatesToEnter(initialState, stateNode, statesToEnter, historyValue, statesForDefaultEntry);
1021
+ }
1022
+ } else {
1023
+ if (stateNode.type === 'parallel') {
1024
+ for (const child of getChildren(stateNode).filter(sn => !isHistoryNode(sn))) {
1025
+ if (![...statesToEnter].some(s => isDescendant(s, child))) {
1026
+ addDescendantStatesToEnter(child, historyValue, statesForDefaultEntry, statesToEnter);
1027
+ }
1028
+ }
1029
+ }
1030
+ }
1031
+ }
1032
+ }
1033
+ function addAncestorStatesToEnter(stateNode, toStateNode, statesToEnter, historyValue, statesForDefaultEntry) {
1034
+ const properAncestors = getProperAncestors(stateNode, toStateNode);
1035
+ for (const anc of properAncestors) {
1036
+ statesToEnter.add(anc);
1037
+ if (anc.type === 'parallel') {
1038
+ for (const child of getChildren(anc).filter(sn => !isHistoryNode(sn))) {
1039
+ if (![...statesToEnter].some(s => isDescendant(s, child))) {
1040
+ addDescendantStatesToEnter(child, historyValue, statesForDefaultEntry, statesToEnter);
1041
+ }
1042
+ }
1043
+ }
1044
+ }
1045
+ }
1046
+ function exitStates(transitions, mutConfiguration, historyValue, actions) {
1047
+ const statesToExit = computeExitSet(transitions, mutConfiguration, historyValue);
1048
+ statesToExit.sort((a, b) => b.order - a.order);
1049
+
1050
+ // From SCXML algorithm: https://www.w3.org/TR/scxml/#exitStates
1051
+ for (const exitStateNode of statesToExit) {
1052
+ for (const historyNode of getHistoryNodes(exitStateNode)) {
1053
+ let predicate;
1054
+ if (historyNode.history === 'deep') {
1055
+ predicate = sn => isAtomicStateNode(sn) && isDescendant(sn, exitStateNode);
1056
+ } else {
1057
+ predicate = sn => {
1058
+ return sn.parent === exitStateNode;
1059
+ };
1060
+ }
1061
+ historyValue[historyNode.id] = Array.from(mutConfiguration).filter(predicate);
1062
+ }
1063
+ }
1064
+ for (const s of statesToExit) {
1065
+ actions.push(...s.exit, ...s.invoke.map(def => stop(def.id)));
1066
+ mutConfiguration.delete(s);
1067
+ }
1068
+ }
1069
+ function resolveActionsAndContext(actions, event, currentState, actorCtx) {
1070
+ const {
1071
+ machine
1072
+ } = currentState;
1073
+ // TODO: this `cloneState` is really just a hack to prevent infinite loops
1074
+ // we need to take another look at how internal queue is managed
1075
+ let intermediateState = cloneState(currentState, {
1076
+ _internalQueue: []
1077
+ });
1078
+ for (const action of actions) {
1079
+ const isInline = typeof action === 'function';
1080
+ const resolved = isInline ? action :
1081
+ // the existing type of `.actions` assumes non-nullable `TExpressionAction`
1082
+ // it's fine to cast this here to get a common type and lack of errors in the rest of the code
1083
+ // our logic below makes sure that we call those 2 "variants" correctly
1084
+ machine.implementations.actions[typeof action === 'string' ? action : action.type];
1085
+ if (!resolved) {
1086
+ continue;
1087
+ }
1088
+ const actionArgs = {
1089
+ context: intermediateState.context,
1090
+ event,
1091
+ self: actorCtx?.self,
1092
+ system: actorCtx?.system,
1093
+ action: isInline ? undefined : typeof action === 'string' ? {
1094
+ type: action
1095
+ } : typeof action.params === 'function' ? {
1096
+ type: action.type,
1097
+ params: action.params({
1098
+ context: intermediateState.context,
1099
+ event
1100
+ })
1101
+ } :
1102
+ // TS isn't able to narrow it down here
1103
+ action
1104
+ };
1105
+ if (!('resolve' in resolved)) {
1106
+ if (actorCtx?.self.status === ActorStatus.Running) {
1107
+ resolved(actionArgs);
1108
+ } else {
1109
+ actorCtx?.defer(() => resolved(actionArgs));
1110
+ }
1111
+ continue;
1112
+ }
1113
+ const builtinAction = resolved;
1114
+ const [nextState, params, actions] = builtinAction.resolve(actorCtx, intermediateState, actionArgs, resolved // this holds all params
1115
+ );
1116
+
1117
+ intermediateState = nextState;
1118
+ if ('execute' in resolved) {
1119
+ if (actorCtx?.self.status === ActorStatus.Running) {
1120
+ builtinAction.execute(actorCtx, params);
1121
+ } else {
1122
+ actorCtx?.defer(builtinAction.execute.bind(null, actorCtx, params));
1123
+ }
1124
+ }
1125
+ if (actions) {
1126
+ intermediateState = resolveActionsAndContext(actions, event, intermediateState, actorCtx);
1127
+ }
1128
+ }
1129
+ return intermediateState;
1130
+ }
1131
+ function macrostep(state, event, actorCtx) {
1132
+ if (event.type === WILDCARD) {
1133
+ throw new Error(`An event cannot have the wildcard type ('${WILDCARD}')`);
1134
+ }
1135
+ let nextState = state;
1136
+ const states = [];
1137
+
1138
+ // Handle stop event
1139
+ if (event.type === XSTATE_STOP) {
1140
+ nextState = stopStep(event, nextState, actorCtx);
1141
+ states.push(nextState);
1142
+ return {
1143
+ state: nextState,
1144
+ microstates: states
1145
+ };
1146
+ }
1147
+ let nextEvent = event;
1148
+
1149
+ // Assume the state is at rest (no raised events)
1150
+ // Determine the next state based on the next microstep
1151
+ if (nextEvent.type !== XSTATE_INIT) {
1152
+ const transitions = selectTransitions(nextEvent, nextState);
1153
+ nextState = microstep(transitions, state, actorCtx, nextEvent, false);
1154
+ states.push(nextState);
1155
+ }
1156
+ while (!nextState.done) {
1157
+ let enabledTransitions = selectEventlessTransitions(nextState, nextEvent);
1158
+ if (!enabledTransitions.length) {
1159
+ if (!nextState._internalQueue.length) {
1160
+ break;
1161
+ } else {
1162
+ nextEvent = nextState._internalQueue[0];
1163
+ const transitions = selectTransitions(nextEvent, nextState);
1164
+ nextState = microstep(transitions, nextState, actorCtx, nextEvent, false);
1165
+ nextState._internalQueue.shift();
1166
+ states.push(nextState);
1167
+ }
1168
+ } else {
1169
+ nextState = microstep(enabledTransitions, nextState, actorCtx, nextEvent, false);
1170
+ states.push(nextState);
1171
+ }
1172
+ }
1173
+ if (nextState.done) {
1174
+ // Perform the stop step to ensure that child actors are stopped
1175
+ stopStep(nextEvent, nextState, actorCtx);
1176
+ }
1177
+ return {
1178
+ state: nextState,
1179
+ microstates: states
1180
+ };
1181
+ }
1182
+ function stopStep(event, nextState, actorCtx) {
1183
+ const actions = [];
1184
+ for (const stateNode of nextState.configuration.sort((a, b) => b.order - a.order)) {
1185
+ actions.push(...stateNode.exit);
1186
+ }
1187
+ for (const child of Object.values(nextState.children)) {
1188
+ actions.push(stop(child));
1189
+ }
1190
+ return resolveActionsAndContext(actions, event, nextState, actorCtx);
1191
+ }
1192
+ function selectTransitions(event, nextState) {
1193
+ return nextState.machine.getTransitionData(nextState, event);
1194
+ }
1195
+ function selectEventlessTransitions(nextState, event) {
1196
+ const enabledTransitionSet = new Set();
1197
+ const atomicStates = nextState.configuration.filter(isAtomicStateNode);
1198
+ for (const stateNode of atomicStates) {
1199
+ loop: for (const s of [stateNode].concat(getProperAncestors(stateNode, null))) {
1200
+ if (!s.always) {
1201
+ continue;
1202
+ }
1203
+ for (const transition of s.always) {
1204
+ if (transition.guard === undefined || evaluateGuard(transition.guard, nextState.context, event, nextState)) {
1205
+ enabledTransitionSet.add(transition);
1206
+ break loop;
1207
+ }
1208
+ }
1209
+ }
1210
+ }
1211
+ return removeConflictingTransitions(Array.from(enabledTransitionSet), new Set(nextState.configuration), nextState.historyValue);
1212
+ }
1213
+
1214
+ /**
1215
+ * Resolves a partial state value with its full representation in the state node's machine.
1216
+ *
1217
+ * @param stateValue The partial state value to resolve.
1218
+ */
1219
+ function resolveStateValue(rootNode, stateValue) {
1220
+ const configuration = getConfiguration(getStateNodes(rootNode, stateValue));
1221
+ return getStateValue(rootNode, [...configuration]);
1222
+ }
1223
+ function getInitialConfiguration(rootNode) {
1224
+ const configuration = [];
1225
+ const initialTransition = rootNode.initial;
1226
+ const statesToEnter = new Set();
1227
+ const statesForDefaultEntry = new Set([rootNode]);
1228
+ computeEntrySet([initialTransition], {}, statesForDefaultEntry, statesToEnter);
1229
+ for (const stateNodeToEnter of [...statesToEnter].sort((a, b) => a.order - b.order)) {
1230
+ configuration.push(stateNodeToEnter);
1231
+ }
1232
+ return configuration;
1233
+ }
1234
+
1235
+ class State {
1236
+ /**
1237
+ * Indicates whether the state is a final state.
1238
+ */
1239
+
1240
+ /**
1241
+ * The output data of the top-level finite state.
1242
+ */
1243
+
1244
+ /**
1245
+ * The enabled state nodes representative of the state value.
1246
+ */
1247
+
1248
+ /**
1249
+ * An object mapping actor names to spawned/invoked actors.
1250
+ */
1251
+
1252
+ /**
1253
+ * Creates a new State instance for the given `stateValue` and `context`.
1254
+ * @param stateValue
1255
+ * @param context
1256
+ */
1257
+ static from(stateValue, context = {}, machine) {
1258
+ if (stateValue instanceof State) {
1259
+ if (stateValue.context !== context) {
1260
+ return new State({
1261
+ value: stateValue.value,
1262
+ context,
1263
+ meta: {},
1264
+ configuration: [],
1265
+ // TODO: fix,
1266
+ children: {}
1267
+ }, machine);
1268
+ }
1269
+ return stateValue;
1270
+ }
1271
+ const configuration = getConfiguration(getStateNodes(machine.root, stateValue));
1272
+ return new State({
1273
+ value: stateValue,
1274
+ context,
1275
+ meta: undefined,
1276
+ configuration: Array.from(configuration),
1277
+ children: {}
1278
+ }, machine);
1279
+ }
1280
+
1281
+ /**
1282
+ * Creates a new `State` instance that represents the current state of a running machine.
1283
+ *
1284
+ * @param config
1285
+ */
1286
+ constructor(config, machine) {
1287
+ this.machine = machine;
1288
+ this.tags = void 0;
1289
+ this.value = void 0;
1290
+ this.done = void 0;
1291
+ this.output = void 0;
1292
+ this.error = void 0;
1293
+ this.context = void 0;
1294
+ this.historyValue = {};
1295
+ this._internalQueue = void 0;
1296
+ this.configuration = void 0;
1297
+ this.children = void 0;
1298
+ this.context = config.context;
1299
+ this._internalQueue = config._internalQueue ?? [];
1300
+ this.historyValue = config.historyValue || {};
1301
+ this.matches = this.matches.bind(this);
1302
+ this.toStrings = this.toStrings.bind(this);
1303
+ this.configuration = config.configuration ?? Array.from(getConfiguration(getStateNodes(machine.root, config.value)));
1304
+ this.children = config.children;
1305
+ this.value = getStateValue(machine.root, this.configuration);
1306
+ this.tags = new Set(flatten(this.configuration.map(sn => sn.tags)));
1307
+ this.done = config.done ?? false;
1308
+ this.output = config.output;
1309
+ this.error = config.error;
1310
+ }
1311
+
1312
+ /**
1313
+ * Returns an array of all the string leaf state node paths.
1314
+ * @param stateValue
1315
+ * @param delimiter The character(s) that separate each subpath in the string state node path.
1316
+ */
1317
+ toStrings(stateValue = this.value) {
1318
+ if (typeof stateValue === 'string') {
1319
+ return [stateValue];
1320
+ }
1321
+ const valueKeys = Object.keys(stateValue);
1322
+ return valueKeys.concat(...valueKeys.map(key => this.toStrings(stateValue[key]).map(s => key + STATE_DELIMITER + s)));
1323
+ }
1324
+ toJSON() {
1325
+ const {
1326
+ configuration,
1327
+ tags,
1328
+ machine,
1329
+ ...jsonValues
1330
+ } = this;
1331
+ return {
1332
+ ...jsonValues,
1333
+ tags: Array.from(tags),
1334
+ meta: this.meta
1335
+ };
1336
+ }
1337
+
1338
+ /**
1339
+ * Whether the current state value is a subset of the given parent state value.
1340
+ * @param parentStateValue
1341
+ */
1342
+ matches(parentStateValue) {
1343
+ return matchesState(parentStateValue, this.value);
1344
+ }
1345
+
1346
+ /**
1347
+ * Whether the current state configuration has a state node with the specified `tag`.
1348
+ * @param tag
1349
+ */
1350
+ hasTag(tag) {
1351
+ return this.tags.has(tag);
1352
+ }
1353
+
1354
+ /**
1355
+ * Determines whether sending the `event` will cause a non-forbidden transition
1356
+ * to be selected, even if the transitions have no actions nor
1357
+ * change the state value.
1358
+ *
1359
+ * @param event The event to test
1360
+ * @returns Whether the event will cause a transition
1361
+ */
1362
+ can(event) {
1363
+ if (!this.machine) {
1364
+ console.warn(`state.can(...) used outside of a machine-created State object; this will always return false.`);
1365
+ }
1366
+ const transitionData = this.machine.getTransitionData(this, event);
1367
+ return !!transitionData?.length &&
1368
+ // Check that at least one transition is not forbidden
1369
+ transitionData.some(t => t.target !== undefined || t.actions.length);
1370
+ }
1371
+
1372
+ /**
1373
+ * The next events that will cause a transition from the current state.
1374
+ */
1375
+ get nextEvents() {
1376
+ return memo(this, 'nextEvents', () => {
1377
+ return [...new Set(flatten([...this.configuration.map(sn => sn.ownEvents)]))];
1378
+ });
1379
+ }
1380
+ get meta() {
1381
+ return this.configuration.reduce((acc, stateNode) => {
1382
+ if (stateNode.meta !== undefined) {
1383
+ acc[stateNode.id] = stateNode.meta;
1384
+ }
1385
+ return acc;
1386
+ }, {});
1387
+ }
1388
+ }
1389
+ function cloneState(state, config = {}) {
1390
+ return new State({
1391
+ ...state,
1392
+ ...config
1393
+ }, state.machine);
1394
+ }
1395
+ function getPersistedState(state) {
1396
+ const {
1397
+ configuration,
1398
+ tags,
1399
+ machine,
1400
+ children,
1401
+ ...jsonValues
1402
+ } = state;
1403
+ const childrenJson = {};
1404
+ for (const id in children) {
1405
+ childrenJson[id] = {
1406
+ state: children[id].getPersistedState?.(),
1407
+ src: children[id].src
1408
+ };
1409
+ }
1410
+ return {
1411
+ ...jsonValues,
1412
+ children: childrenJson
1413
+ };
1414
+ }
1415
+
1416
+ function resolve(_, state, args, {
1417
+ event: eventOrExpr,
1418
+ id,
1419
+ delay
1420
+ }) {
1421
+ const delaysMap = state.machine.implementations.delays;
1422
+ if (typeof eventOrExpr === 'string') {
1423
+ throw new Error(`Only event objects may be used with raise; use raise({ type: "${eventOrExpr}" }) instead`);
1424
+ }
1425
+ const resolvedEvent = typeof eventOrExpr === 'function' ? eventOrExpr(args) : eventOrExpr;
1426
+ let resolvedDelay;
1427
+ if (typeof delay === 'string') {
1428
+ const configDelay = delaysMap && delaysMap[delay];
1429
+ resolvedDelay = typeof configDelay === 'function' ? configDelay(args) : configDelay;
1430
+ } else {
1431
+ resolvedDelay = typeof delay === 'function' ? delay(args) : delay;
1432
+ }
1433
+ return [typeof resolvedDelay !== 'number' ? cloneState(state, {
1434
+ _internalQueue: state._internalQueue.concat(resolvedEvent)
1435
+ }) : state, {
1436
+ event: resolvedEvent,
1437
+ id,
1438
+ delay: resolvedDelay
1439
+ }];
1440
+ }
1441
+ function execute(actorContext, params) {
1442
+ if (typeof params.delay === 'number') {
1443
+ actorContext.self.delaySend(params);
1444
+ return;
1445
+ }
1446
+ }
1447
+ /**
1448
+ * Raises an event. This places the event in the internal event queue, so that
1449
+ * the event is immediately consumed by the machine in the current step.
1450
+ *
1451
+ * @param eventType The event to raise.
1452
+ */
1453
+ function raise(eventOrExpr, options) {
1454
+ function raise(_) {
1455
+ {
1456
+ throw new Error(`This isn't supposed to be called`);
1457
+ }
1458
+ }
1459
+ raise.type = 'xstate.raise';
1460
+ raise.event = eventOrExpr;
1461
+ raise.id = options?.id;
1462
+ raise.delay = options?.delay;
1463
+ raise.resolve = resolve;
1464
+ raise.execute = execute;
1465
+ return raise;
1466
+ }
1467
+
1468
+ export { raise as A, stop as B, State as S, formatTransition as a, formatInitialTransition as b, getCandidates as c, getConfiguration as d, evaluateGuard as e, formatTransitions as f, getDelayedTransitions as g, getStateNodes as h, isInFinalState as i, cloneState as j, macrostep as k, getInitialConfiguration as l, memo as m, resolveActionsAndContext as n, microstep as o, isAtomicStateNode as p, isStateId as q, resolveStateValue as r, getStateNodeByPath as s, transitionNode as t, getPersistedState as u, and as v, not as w, or as x, stateIn as y, cancel as z };