xstate 5.0.0-beta.34 → 5.0.0-beta.36

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 (41) hide show
  1. package/README.md +1 -1
  2. package/actions/dist/xstate-actions.cjs.js +3 -3
  3. package/actions/dist/xstate-actions.development.cjs.js +3 -3
  4. package/actions/dist/xstate-actions.development.esm.js +3 -3
  5. package/actions/dist/xstate-actions.esm.js +3 -3
  6. package/actions/dist/xstate-actions.umd.min.js +1 -1
  7. package/actions/dist/xstate-actions.umd.min.js.map +1 -1
  8. package/actors/dist/xstate-actors.cjs.js +1 -1
  9. package/actors/dist/xstate-actors.development.cjs.js +1 -1
  10. package/actors/dist/xstate-actors.development.esm.js +1 -1
  11. package/actors/dist/xstate-actors.esm.js +1 -1
  12. package/actors/dist/xstate-actors.umd.min.js +1 -1
  13. package/actors/dist/xstate-actors.umd.min.js.map +1 -1
  14. package/dist/declarations/src/State.d.ts +0 -1
  15. package/dist/declarations/src/interpreter.d.ts +2 -0
  16. package/dist/declarations/src/stateUtils.d.ts +8 -7
  17. package/dist/declarations/src/types.d.ts +3 -6
  18. package/dist/{interpreter-dee56dc8.development.esm.js → interpreter-5c4e6634.development.esm.js} +59 -57
  19. package/dist/{interpreter-1301970f.cjs.js → interpreter-69605bf0.cjs.js} +59 -57
  20. package/dist/{interpreter-70ed62f2.development.cjs.js → interpreter-d3567419.development.cjs.js} +59 -57
  21. package/dist/{interpreter-83f7f2d4.esm.js → interpreter-de5217bc.esm.js} +59 -57
  22. package/dist/{raise-38b707c0.development.cjs.js → raise-106ea558.development.cjs.js} +160 -160
  23. package/dist/{raise-05f8b2a6.development.esm.js → raise-5b7ad3b7.development.esm.js} +160 -160
  24. package/dist/{raise-1dd65455.cjs.js → raise-c51b81a3.cjs.js} +157 -160
  25. package/dist/{raise-b5cfe1bb.esm.js → raise-ffe1014a.esm.js} +157 -160
  26. package/dist/{send-0b5eda0c.esm.js → send-0a7aa74e.esm.js} +5 -3
  27. package/dist/{send-3764c866.development.cjs.js → send-25e70bd4.development.cjs.js} +5 -3
  28. package/dist/{send-fe94de2b.cjs.js → send-778692de.cjs.js} +5 -3
  29. package/dist/{send-9526366e.development.esm.js → send-e93554d6.development.esm.js} +5 -3
  30. package/dist/xstate.cjs.js +32 -13
  31. package/dist/xstate.development.cjs.js +32 -13
  32. package/dist/xstate.development.esm.js +35 -16
  33. package/dist/xstate.esm.js +35 -16
  34. package/dist/xstate.umd.min.js +1 -1
  35. package/dist/xstate.umd.min.js.map +1 -1
  36. package/guards/dist/xstate-guards.cjs.js +2 -2
  37. package/guards/dist/xstate-guards.development.cjs.js +2 -2
  38. package/guards/dist/xstate-guards.development.esm.js +2 -2
  39. package/guards/dist/xstate-guards.esm.js +2 -2
  40. package/guards/dist/xstate-guards.umd.min.js.map +1 -1
  41. package/package.json +1 -1
@@ -1,4 +1,4 @@
1
- import { r as resolveReferencedActor, d as createActor, f as ActorStatus, j as createErrorActorEvent, k as toStateValue, l as STATE_IDENTIFIER, n as normalizeTarget, t as toArray, N as NULL_EVENT, a as toTransitionConfigArray, S as STATE_DELIMITER, o as toStatePath, q as createDoneStateEvent, s as resolveOutput, W as WILDCARD, X as XSTATE_STOP, u as XSTATE_INIT, v as isArray, w as createAfterEvent, x as flatten, e as matchesState } from './interpreter-dee56dc8.development.esm.js';
1
+ import { r as resolveReferencedActor, d as createActor, f as ActorStatus, j as createErrorActorEvent, k as toStateValue, l as STATE_IDENTIFIER, n as normalizeTarget, t as toArray, N as NULL_EVENT, a as toTransitionConfigArray, S as STATE_DELIMITER, o as toStatePath, q as createDoneStateEvent, s as resolveOutput, W as WILDCARD, X as XSTATE_STOP, u as XSTATE_INIT, v as createAfterEvent, w as flatten, e as matchesState, $ as $$ACTOR_TYPE } from './interpreter-5c4e6634.development.esm.js';
2
2
 
3
3
  const cache = new WeakMap();
4
4
  function memo(object, key, fn) {
@@ -297,20 +297,6 @@ function evaluateGuard(guard, context, event, state) {
297
297
  );
298
298
  }
299
299
 
300
- function getOutput(configuration, context, event, self) {
301
- const {
302
- machine
303
- } = configuration[0];
304
- const {
305
- root
306
- } = machine;
307
- if (!root.output) {
308
- return undefined;
309
- }
310
- const finalChildStateNode = configuration.find(stateNode => stateNode.type === 'final' && stateNode.parent === machine.root);
311
- const doneStateEvent = createDoneStateEvent(finalChildStateNode.id, finalChildStateNode.output ? resolveOutput(finalChildStateNode.output, context, event, self) : undefined);
312
- return resolveOutput(root.output, context, doneStateEvent, self);
313
- }
314
300
  const isAtomicStateNode = stateNode => stateNode.type === 'atomic' || stateNode.type === 'final';
315
301
  function getChildren(stateNode) {
316
302
  return Object.values(stateNode.states).filter(sn => sn.type !== 'history');
@@ -335,7 +321,7 @@ function getConfiguration(stateNodes) {
335
321
  for (const s of configuration) {
336
322
  // if previously active, add existing child nodes
337
323
  if (s.type === 'compound' && (!adjList.get(s) || !adjList.get(s).length)) {
338
- getInitialStateNodes(s).forEach(sn => configurationSet.add(sn));
324
+ getInitialStateNodesWithTheirAncestors(s).forEach(sn => configurationSet.add(sn));
339
325
  } else {
340
326
  if (s.type === 'parallel') {
341
327
  for (const child of getChildren(s)) {
@@ -343,7 +329,8 @@ function getConfiguration(stateNodes) {
343
329
  continue;
344
330
  }
345
331
  if (!configurationSet.has(child)) {
346
- for (const initialStateNode of getInitialStateNodes(child)) {
332
+ const initialStates = getInitialStateNodesWithTheirAncestors(child);
333
+ for (const initialStateNode of initialStates) {
347
334
  configurationSet.add(initialStateNode);
348
335
  }
349
336
  }
@@ -403,14 +390,14 @@ function getStateValue(rootNode, configuration) {
403
390
  const config = getConfiguration(configuration);
404
391
  return getValueFromAdj(rootNode, getAdjList(config));
405
392
  }
406
- function isInFinalState(configuration, stateNode = configuration[0].machine.root) {
393
+ function isInFinalState(configuration, stateNode) {
407
394
  if (stateNode.type === 'compound') {
408
- return getChildren(stateNode).some(s => s.type === 'final' && configuration.includes(s));
395
+ return getChildren(stateNode).some(s => s.type === 'final' && configuration.has(s));
409
396
  }
410
397
  if (stateNode.type === 'parallel') {
411
398
  return getChildren(stateNode).every(sn => isInFinalState(configuration, sn));
412
399
  }
413
- return false;
400
+ return stateNode.type === 'final';
414
401
  }
415
402
  const isStateId = str => str[0] === STATE_IDENTIFIER;
416
403
  function getCandidates(stateNode, receivedEventType) {
@@ -466,13 +453,7 @@ function getDelayedTransitions(stateNode) {
466
453
  stateNode.exit.push(cancel(eventType));
467
454
  return eventType;
468
455
  };
469
- const delayedTransitions = isArray(afterConfig) ? afterConfig.map((transition, i) => {
470
- const eventType = mutateEntryExit(transition.delay, i);
471
- return {
472
- ...transition,
473
- event: eventType
474
- };
475
- }) : Object.keys(afterConfig).flatMap((delay, i) => {
456
+ const delayedTransitions = Object.keys(afterConfig).flatMap((delay, i) => {
476
457
  const configTransition = afterConfig[delay];
477
458
  const resolvedTransition = typeof configTransition === 'string' ? {
478
459
  target: configTransition
@@ -560,43 +541,23 @@ function formatTransitions(stateNode) {
560
541
  return transitions;
561
542
  }
562
543
  function formatInitialTransition(stateNode, _target) {
563
- if (typeof _target === 'string' || isArray(_target)) {
564
- const targets = toArray(_target).map(t => {
565
- // Resolve state string keys (which represent children)
566
- // to their state node
567
- const descStateNode = typeof t === 'string' ? isStateId(t) ? stateNode.machine.getStateNodeById(t) : stateNode.states[t] : t;
568
- if (!descStateNode) {
569
- throw new Error(`Initial state node "${t}" not found on parent state node #${stateNode.id}`);
570
- }
571
- if (!isDescendant(descStateNode, stateNode)) {
572
- throw new Error(`Invalid initial target: state node #${descStateNode.id} is not a descendant of #${stateNode.id}`);
573
- }
574
- return descStateNode;
575
- });
576
- const resolvedTarget = resolveTarget(stateNode, targets);
577
- const transition = {
578
- source: stateNode,
579
- actions: [],
580
- eventType: null,
581
- reenter: false,
582
- target: resolvedTarget,
583
- toJSON: () => ({
584
- ...transition,
585
- source: `#${stateNode.id}`,
586
- target: resolvedTarget ? resolvedTarget.map(t => `#${t.id}`) : undefined
587
- })
588
- };
589
- return transition;
544
+ const resolvedTarget = typeof _target === 'string' ? stateNode.states[_target] : _target ? stateNode.states[_target.target] : undefined;
545
+ if (!resolvedTarget && _target) {
546
+ throw new Error(`Initial state node "${_target}" not found on parent state node #${stateNode.id}`);
590
547
  }
591
- return formatTransition(stateNode, '__INITIAL__', {
592
- target: toArray(_target.target).map(t => {
593
- if (typeof t === 'string') {
594
- return isStateId(t) ? t : `${STATE_DELIMITER}${t}`;
595
- }
596
- return t;
597
- }),
598
- actions: _target.actions
599
- });
548
+ const transition = {
549
+ source: stateNode,
550
+ actions: !_target || typeof _target === 'string' ? [] : toArray(_target.actions),
551
+ eventType: null,
552
+ reenter: false,
553
+ target: resolvedTarget ? [resolvedTarget] : [],
554
+ toJSON: () => ({
555
+ ...transition,
556
+ source: `#${stateNode.id}`,
557
+ target: resolvedTarget ? [`#${resolvedTarget.id}`] : []
558
+ })
559
+ };
560
+ return transition;
600
561
  }
601
562
  function resolveTarget(stateNode, targets) {
602
563
  if (targets === undefined) {
@@ -639,6 +600,15 @@ function resolveHistoryTarget(stateNode) {
639
600
  function isHistoryNode(stateNode) {
640
601
  return stateNode.type === 'history';
641
602
  }
603
+ function getInitialStateNodesWithTheirAncestors(stateNode) {
604
+ const states = getInitialStateNodes(stateNode);
605
+ for (const initialState of states) {
606
+ for (const ancestor of getProperAncestors(initialState, stateNode)) {
607
+ states.add(ancestor);
608
+ }
609
+ }
610
+ return states;
611
+ }
642
612
  function getInitialStateNodes(stateNode) {
643
613
  const set = new Set();
644
614
  function iter(descStateNode) {
@@ -647,12 +617,7 @@ function getInitialStateNodes(stateNode) {
647
617
  }
648
618
  set.add(descStateNode);
649
619
  if (descStateNode.type === 'compound') {
650
- for (const targetStateNode of descStateNode.initial.target) {
651
- for (const a of getProperAncestors(targetStateNode, stateNode)) {
652
- set.add(a);
653
- }
654
- iter(targetStateNode);
655
- }
620
+ iter(descStateNode.initial.target[0]);
656
621
  } else if (descStateNode.type === 'parallel') {
657
622
  for (const child of getChildren(descStateNode)) {
658
623
  iter(child);
@@ -660,7 +625,7 @@ function getInitialStateNodes(stateNode) {
660
625
  }
661
626
  }
662
627
  iter(stateNode);
663
- return [...set];
628
+ return set;
664
629
  }
665
630
  /**
666
631
  * Returns the child state node from its relative `stateKey`, or throws.
@@ -894,6 +859,17 @@ function computeExitSet(transitions, configuration, historyValue) {
894
859
  }
895
860
  return [...statesToExit];
896
861
  }
862
+ function areConfigurationsEqual(previousConfiguration, nextConfigurationSet) {
863
+ if (previousConfiguration.length !== nextConfigurationSet.size) {
864
+ return false;
865
+ }
866
+ for (const node of previousConfiguration) {
867
+ if (!nextConfigurationSet.has(node)) {
868
+ return false;
869
+ }
870
+ }
871
+ return true;
872
+ }
897
873
 
898
874
  /**
899
875
  * https://www.w3.org/TR/scxml/#microstepProcedure
@@ -903,56 +879,36 @@ function computeExitSet(transitions, configuration, historyValue) {
903
879
  * @param currentState
904
880
  * @param mutConfiguration
905
881
  */
906
-
907
- function microstep(transitions, currentState, actorCtx, event, isInitial) {
908
- const mutConfiguration = new Set(currentState.configuration);
882
+ function microstep(transitions, currentState, actorCtx, event, isInitial, internalQueue) {
909
883
  if (!transitions.length) {
910
884
  return currentState;
911
885
  }
912
- const microstate = microstepProcedure(transitions, currentState, mutConfiguration, event, actorCtx, isInitial);
913
- return cloneState(microstate, {
914
- value: {} // TODO: make optional
915
- });
916
- }
917
-
918
- function microstepProcedure(transitions, currentState, mutConfiguration, event, actorCtx, isInitial) {
919
- const historyValue = {
920
- ...currentState.historyValue
921
- };
886
+ const mutConfiguration = new Set(currentState.configuration);
887
+ let historyValue = currentState.historyValue;
922
888
  const filteredTransitions = removeConflictingTransitions(transitions, mutConfiguration, historyValue);
923
- const internalQueue = [...currentState._internalQueue];
924
- // TODO: this `cloneState` is really just a hack to prevent infinite loops
925
- // we need to take another look at how internal queue is managed
926
- let nextState = cloneState(currentState, {
927
- _internalQueue: []
928
- });
889
+ let nextState = currentState;
929
890
 
930
891
  // Exit states
931
892
  if (!isInitial) {
932
- nextState = exitStates(nextState, event, actorCtx, filteredTransitions, mutConfiguration, historyValue);
893
+ [nextState, historyValue] = exitStates(nextState, event, actorCtx, filteredTransitions, mutConfiguration, historyValue, internalQueue);
933
894
  }
934
895
 
935
896
  // Execute transition content
936
- nextState = resolveActionsAndContext(nextState, event, actorCtx, filteredTransitions.flatMap(t => t.actions));
897
+ nextState = resolveActionsAndContext(nextState, event, actorCtx, filteredTransitions.flatMap(t => t.actions), internalQueue);
937
898
 
938
899
  // Enter states
939
900
  nextState = enterStates(nextState, event, actorCtx, filteredTransitions, mutConfiguration, internalQueue, historyValue, isInitial);
940
901
  const nextConfiguration = [...mutConfiguration];
941
- const done = isInFinalState(nextConfiguration);
942
- if (done) {
943
- nextState = resolveActionsAndContext(nextState, event, actorCtx, nextConfiguration.sort((a, b) => b.order - a.order).flatMap(state => state.exit));
902
+ if (nextState.status === 'done') {
903
+ nextState = resolveActionsAndContext(nextState, event, actorCtx, nextConfiguration.sort((a, b) => b.order - a.order).flatMap(state => state.exit), internalQueue);
944
904
  }
945
905
  try {
946
- const output = done ? getOutput(nextConfiguration, nextState.context, event, actorCtx.self) : undefined;
947
- internalQueue.push(...nextState._internalQueue);
948
- return cloneState(currentState, {
906
+ if (historyValue === currentState.historyValue && areConfigurationsEqual(currentState.configuration, mutConfiguration)) {
907
+ return nextState;
908
+ }
909
+ return cloneState(nextState, {
949
910
  configuration: nextConfiguration,
950
- historyValue,
951
- _internalQueue: internalQueue,
952
- context: nextState.context,
953
- status: done ? 'done' : currentState.status,
954
- output,
955
- children: nextState.children
911
+ historyValue
956
912
  });
957
913
  } catch (e) {
958
914
  // TODO: Refactor this once proper error handling is implemented.
@@ -960,6 +916,13 @@ function microstepProcedure(transitions, currentState, mutConfiguration, event,
960
916
  throw e;
961
917
  }
962
918
  }
919
+ function getMachineOutput(state, event, actorCtx, rootNode, rootCompletionNode) {
920
+ if (!rootNode.output) {
921
+ return;
922
+ }
923
+ const doneStateEvent = createDoneStateEvent(rootCompletionNode.id, rootCompletionNode.output && rootCompletionNode.parent ? resolveOutput(rootCompletionNode.output, state.context, event, actorCtx.self) : undefined);
924
+ return resolveOutput(rootNode.output, state.context, doneStateEvent, actorCtx.self);
925
+ }
963
926
  function enterStates(currentState, event, actorCtx, filteredTransitions, mutConfiguration, internalQueue, historyValue, isInitial) {
964
927
  let nextState = currentState;
965
928
  const statesToEnter = new Set();
@@ -970,6 +933,7 @@ function enterStates(currentState, event, actorCtx, filteredTransitions, mutConf
970
933
  if (isInitial) {
971
934
  statesForDefaultEntry.add(currentState.machine.root);
972
935
  }
936
+ const completedNodes = new Set();
973
937
  for (const stateNodeToEnter of [...statesToEnter].sort((a, b) => a.order - b.order)) {
974
938
  mutConfiguration.add(stateNodeToEnter);
975
939
  const actions = [];
@@ -980,26 +944,34 @@ function enterStates(currentState, event, actorCtx, filteredTransitions, mutConf
980
944
  actions.push(invoke(invokeDef));
981
945
  }
982
946
  if (statesForDefaultEntry.has(stateNodeToEnter)) {
983
- for (const stateNode of statesForDefaultEntry) {
984
- const initialActions = stateNode.initial.actions;
985
- actions.push(...initialActions);
986
- }
947
+ const initialActions = stateNodeToEnter.initial.actions;
948
+ actions.push(...initialActions);
987
949
  }
988
- nextState = resolveActionsAndContext(nextState, event, actorCtx, actions, stateNodeToEnter.invoke.map(invokeDef => invokeDef.id));
950
+ nextState = resolveActionsAndContext(nextState, event, actorCtx, actions, internalQueue, stateNodeToEnter.invoke.map(invokeDef => invokeDef.id));
989
951
  if (stateNodeToEnter.type === 'final') {
990
952
  const parent = stateNodeToEnter.parent;
991
- if (!parent.parent) {
953
+ if (completedNodes.has(parent)) {
992
954
  continue;
993
955
  }
994
- internalQueue.push(createDoneStateEvent(parent.id, stateNodeToEnter.output ? resolveOutput(stateNodeToEnter.output, nextState.context, event, actorCtx.self) : undefined));
995
- if (parent.parent) {
996
- const grandparent = parent.parent;
997
- if (grandparent.type === 'parallel') {
998
- if (getChildren(grandparent).every(parentNode => isInFinalState([...mutConfiguration], parentNode))) {
999
- internalQueue.push(createDoneStateEvent(grandparent.id));
1000
- }
956
+ completedNodes.add(parent);
957
+ let rootCompletionNode = parent?.type === 'parallel' ? parent : stateNodeToEnter;
958
+ let ancestorMarker = parent?.parent;
959
+ if (ancestorMarker) {
960
+ internalQueue.push(createDoneStateEvent(parent.id, stateNodeToEnter.output ? resolveOutput(stateNodeToEnter.output, nextState.context, event, actorCtx.self) : undefined));
961
+ while (ancestorMarker?.type === 'parallel' && !completedNodes.has(ancestorMarker) && isInFinalState(mutConfiguration, ancestorMarker)) {
962
+ completedNodes.add(ancestorMarker);
963
+ internalQueue.push(createDoneStateEvent(ancestorMarker.id));
964
+ rootCompletionNode = ancestorMarker;
965
+ ancestorMarker = ancestorMarker.parent;
1001
966
  }
1002
967
  }
968
+ if (ancestorMarker) {
969
+ continue;
970
+ }
971
+ nextState = cloneState(nextState, {
972
+ status: 'done',
973
+ output: getMachineOutput(nextState, event, actorCtx, currentState.configuration[0].machine.root, rootCompletionNode)
974
+ });
1003
975
  }
1004
976
  }
1005
977
  return nextState;
@@ -1045,13 +1017,9 @@ function addDescendantStatesToEnter(stateNode, historyValue, statesForDefaultEnt
1045
1017
  statesToEnter.add(stateNode);
1046
1018
  if (stateNode.type === 'compound') {
1047
1019
  statesForDefaultEntry.add(stateNode);
1048
- const initialStates = stateNode.initial.target;
1049
- for (const initialState of initialStates) {
1050
- addDescendantStatesToEnter(initialState, historyValue, statesForDefaultEntry, statesToEnter);
1051
- }
1052
- for (const initialState of initialStates) {
1053
- addAncestorStatesToEnter(initialState, stateNode, statesToEnter, historyValue, statesForDefaultEntry);
1054
- }
1020
+ const [initialState] = stateNode.initial.target;
1021
+ addDescendantStatesToEnter(initialState, historyValue, statesForDefaultEntry, statesToEnter);
1022
+ addAncestorStatesToEnter(initialState, stateNode, statesToEnter, historyValue, statesForDefaultEntry);
1055
1023
  } else {
1056
1024
  if (stateNode.type === 'parallel') {
1057
1025
  for (const child of getChildren(stateNode).filter(sn => !isHistoryNode(sn))) {
@@ -1076,10 +1044,11 @@ function addAncestorStatesToEnter(stateNode, toStateNode, statesToEnter, history
1076
1044
  }
1077
1045
  }
1078
1046
  }
1079
- function exitStates(currentState, event, actorCtx, transitions, mutConfiguration, historyValue) {
1047
+ function exitStates(currentState, event, actorCtx, transitions, mutConfiguration, historyValue, internalQueue) {
1080
1048
  let nextState = currentState;
1081
1049
  const statesToExit = computeExitSet(transitions, mutConfiguration, historyValue);
1082
1050
  statesToExit.sort((a, b) => b.order - a.order);
1051
+ let changedHistory;
1083
1052
 
1084
1053
  // From SCXML algorithm: https://www.w3.org/TR/scxml/#exitStates
1085
1054
  for (const exitStateNode of statesToExit) {
@@ -1092,14 +1061,17 @@ function exitStates(currentState, event, actorCtx, transitions, mutConfiguration
1092
1061
  return sn.parent === exitStateNode;
1093
1062
  };
1094
1063
  }
1095
- historyValue[historyNode.id] = Array.from(mutConfiguration).filter(predicate);
1064
+ changedHistory ??= {
1065
+ ...historyValue
1066
+ };
1067
+ changedHistory[historyNode.id] = Array.from(mutConfiguration).filter(predicate);
1096
1068
  }
1097
1069
  }
1098
1070
  for (const s of statesToExit) {
1099
- nextState = resolveActionsAndContext(nextState, event, actorCtx, [...s.exit, ...s.invoke.map(def => stop(def.id))]);
1071
+ nextState = resolveActionsAndContext(nextState, event, actorCtx, [...s.exit, ...s.invoke.map(def => stop(def.id))], internalQueue);
1100
1072
  mutConfiguration.delete(s);
1101
1073
  }
1102
- return nextState;
1074
+ return [nextState, changedHistory || historyValue];
1103
1075
  }
1104
1076
  function resolveActionsAndContextWorker(currentState, event, actorCtx, actions, extra, retries) {
1105
1077
  const {
@@ -1164,9 +1136,10 @@ function resolveActionsAndContextWorker(currentState, event, actorCtx, actions,
1164
1136
  }
1165
1137
  return intermediateState;
1166
1138
  }
1167
- function resolveActionsAndContext(currentState, event, actorCtx, actions, deferredActorIds) {
1139
+ function resolveActionsAndContext(currentState, event, actorCtx, actions, internalQueue, deferredActorIds) {
1168
1140
  const retries = deferredActorIds ? [] : undefined;
1169
- const nextState = resolveActionsAndContextWorker(currentState, event, actorCtx, actions, deferredActorIds && {
1141
+ const nextState = resolveActionsAndContextWorker(currentState, event, actorCtx, actions, {
1142
+ internalQueue,
1170
1143
  deferredActorIds
1171
1144
  }, retries);
1172
1145
  retries?.forEach(([builtinAction, params]) => {
@@ -1174,7 +1147,7 @@ function resolveActionsAndContext(currentState, event, actorCtx, actions, deferr
1174
1147
  });
1175
1148
  return nextState;
1176
1149
  }
1177
- function macrostep(state, event, actorCtx) {
1150
+ function macrostep(state, event, actorCtx, internalQueue = []) {
1178
1151
  if (event.type === WILDCARD) {
1179
1152
  throw new Error(`An event cannot have the wildcard type ('${WILDCARD}')`);
1180
1153
  }
@@ -1183,7 +1156,7 @@ function macrostep(state, event, actorCtx) {
1183
1156
 
1184
1157
  // Handle stop event
1185
1158
  if (event.type === XSTATE_STOP) {
1186
- nextState = stopStep(event, nextState, actorCtx);
1159
+ nextState = stopChildren(nextState, event, actorCtx);
1187
1160
  states.push(nextState);
1188
1161
  return {
1189
1162
  state: nextState,
@@ -1196,44 +1169,37 @@ function macrostep(state, event, actorCtx) {
1196
1169
  // Determine the next state based on the next microstep
1197
1170
  if (nextEvent.type !== XSTATE_INIT) {
1198
1171
  const transitions = selectTransitions(nextEvent, nextState);
1199
- nextState = microstep(transitions, state, actorCtx, nextEvent, false);
1172
+ nextState = microstep(transitions, state, actorCtx, nextEvent, false, internalQueue);
1200
1173
  states.push(nextState);
1201
1174
  }
1175
+ let shouldSelectEventlessTransitions = true;
1202
1176
  while (nextState.status === 'active') {
1203
- let enabledTransitions = selectEventlessTransitions(nextState, nextEvent);
1177
+ let enabledTransitions = shouldSelectEventlessTransitions ? selectEventlessTransitions(nextState, nextEvent) : [];
1178
+
1179
+ // eventless transitions should always be selected after selecting *regular* transitions
1180
+ // by assigning `undefined` to `previousState` we ensure that `shouldSelectEventlessTransitions` gets always computed to true in such a case
1181
+ const previousState = enabledTransitions.length ? nextState : undefined;
1204
1182
  if (!enabledTransitions.length) {
1205
- if (!nextState._internalQueue.length) {
1183
+ if (!internalQueue.length) {
1206
1184
  break;
1207
- } else {
1208
- nextEvent = nextState._internalQueue[0];
1209
- const transitions = selectTransitions(nextEvent, nextState);
1210
- nextState = microstep(transitions, nextState, actorCtx, nextEvent, false);
1211
- nextState._internalQueue.shift();
1212
- states.push(nextState);
1213
1185
  }
1214
- } else {
1215
- nextState = microstep(enabledTransitions, nextState, actorCtx, nextEvent, false);
1216
- states.push(nextState);
1186
+ nextEvent = internalQueue.shift();
1187
+ enabledTransitions = selectTransitions(nextEvent, nextState);
1217
1188
  }
1189
+ nextState = microstep(enabledTransitions, nextState, actorCtx, nextEvent, false, internalQueue);
1190
+ shouldSelectEventlessTransitions = nextState !== previousState;
1191
+ states.push(nextState);
1218
1192
  }
1219
1193
  if (nextState.status !== 'active') {
1220
- // Perform the stop step to ensure that child actors are stopped
1221
- stopStep(nextEvent, nextState, actorCtx);
1194
+ stopChildren(nextState, nextEvent, actorCtx);
1222
1195
  }
1223
1196
  return {
1224
1197
  state: nextState,
1225
1198
  microstates: states
1226
1199
  };
1227
1200
  }
1228
- function stopStep(event, nextState, actorCtx) {
1229
- const actions = [];
1230
- for (const stateNode of nextState.configuration.sort((a, b) => b.order - a.order)) {
1231
- actions.push(...stateNode.exit);
1232
- }
1233
- for (const child of Object.values(nextState.children)) {
1234
- actions.push(stop(child));
1235
- }
1236
- return resolveActionsAndContext(nextState, event, actorCtx, actions);
1201
+ function stopChildren(nextState, event, actorCtx) {
1202
+ return resolveActionsAndContext(nextState, event, actorCtx, Object.values(nextState.children).map(child => stop(child)), []);
1237
1203
  }
1238
1204
  function selectTransitions(event, nextState) {
1239
1205
  return nextState.machine.getTransitionData(nextState, event);
@@ -1339,11 +1305,9 @@ class State {
1339
1305
  this.error = void 0;
1340
1306
  this.context = void 0;
1341
1307
  this.historyValue = {};
1342
- this._internalQueue = void 0;
1343
1308
  this.configuration = void 0;
1344
1309
  this.children = void 0;
1345
1310
  this.context = config.context;
1346
- this._internalQueue = config._internalQueue ?? [];
1347
1311
  this.historyValue = config.historyValue || {};
1348
1312
  this.matches = this.matches.bind(this);
1349
1313
  this.toStrings = this.toStrings.bind(this);
@@ -1445,11 +1409,15 @@ function getPersistedState(state) {
1445
1409
  tags,
1446
1410
  machine,
1447
1411
  children,
1412
+ context,
1448
1413
  ...jsonValues
1449
1414
  } = state;
1450
1415
  const childrenJson = {};
1451
1416
  for (const id in children) {
1452
1417
  const child = children[id];
1418
+ if (typeof child.src !== 'string') {
1419
+ throw new Error('An inline child actor cannot be persisted.');
1420
+ }
1453
1421
  childrenJson[id] = {
1454
1422
  state: child.getPersistedState?.(),
1455
1423
  src: child.src
@@ -1457,14 +1425,45 @@ function getPersistedState(state) {
1457
1425
  }
1458
1426
  return {
1459
1427
  ...jsonValues,
1428
+ // TODO: this makes `PersistedMachineState`'s type kind of a lie
1429
+ // it doesn't truly use `TContext` but rather some kind of a derived form of it
1430
+ context: persistContext(context),
1460
1431
  children: childrenJson
1461
1432
  };
1462
1433
  }
1434
+ function persistContext(contextPart) {
1435
+ let copy;
1436
+ for (const key in contextPart) {
1437
+ const value = contextPart[key];
1438
+ if (value && typeof value === 'object') {
1439
+ if ('sessionId' in value && 'send' in value && 'ref' in value) {
1440
+ copy ??= Array.isArray(contextPart) ? contextPart.slice() : {
1441
+ ...contextPart
1442
+ };
1443
+ copy[key] = {
1444
+ xstate$$type: $$ACTOR_TYPE,
1445
+ id: value.id
1446
+ };
1447
+ } else {
1448
+ const result = persistContext(value);
1449
+ if (result !== value) {
1450
+ copy ??= Array.isArray(contextPart) ? contextPart.slice() : {
1451
+ ...contextPart
1452
+ };
1453
+ copy[key] = result;
1454
+ }
1455
+ }
1456
+ }
1457
+ }
1458
+ return copy ?? contextPart;
1459
+ }
1463
1460
 
1464
1461
  function resolveRaise(_, state, args, {
1465
1462
  event: eventOrExpr,
1466
1463
  id,
1467
1464
  delay
1465
+ }, {
1466
+ internalQueue
1468
1467
  }) {
1469
1468
  const delaysMap = state.machine.implementations.delays;
1470
1469
  if (typeof eventOrExpr === 'string') {
@@ -1478,9 +1477,10 @@ function resolveRaise(_, state, args, {
1478
1477
  } else {
1479
1478
  resolvedDelay = typeof delay === 'function' ? delay(args) : delay;
1480
1479
  }
1481
- return [typeof resolvedDelay !== 'number' ? cloneState(state, {
1482
- _internalQueue: state._internalQueue.concat(resolvedEvent)
1483
- }) : state, {
1480
+ if (typeof resolvedDelay !== 'number') {
1481
+ internalQueue.push(resolvedEvent);
1482
+ }
1483
+ return [state, {
1484
1484
  event: resolvedEvent,
1485
1485
  id,
1486
1486
  delay: resolvedDelay
@@ -1513,4 +1513,4 @@ function raise(eventOrExpr, options) {
1513
1513
  return raise;
1514
1514
  }
1515
1515
 
1516
- 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 };
1516
+ 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, getInitialStateNodes 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 };