xstate 5.0.0-beta.35 → 5.0.0-beta.37

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 (43) hide show
  1. package/actions/dist/xstate-actions.cjs.js +3 -3
  2. package/actions/dist/xstate-actions.development.cjs.js +3 -3
  3. package/actions/dist/xstate-actions.development.esm.js +3 -3
  4. package/actions/dist/xstate-actions.esm.js +3 -3
  5. package/actions/dist/xstate-actions.umd.min.js +1 -1
  6. package/actions/dist/xstate-actions.umd.min.js.map +1 -1
  7. package/actors/dist/xstate-actors.cjs.js +1 -1
  8. package/actors/dist/xstate-actors.development.cjs.js +1 -1
  9. package/actors/dist/xstate-actors.development.esm.js +1 -1
  10. package/actors/dist/xstate-actors.esm.js +1 -1
  11. package/actors/dist/xstate-actors.umd.min.js +1 -1
  12. package/actors/dist/xstate-actors.umd.min.js.map +1 -1
  13. package/dist/declarations/src/State.d.ts +0 -1
  14. package/dist/declarations/src/stateUtils.d.ts +3 -3
  15. package/dist/declarations/src/typegenTypes.d.ts +2 -0
  16. package/dist/declarations/src/types.d.ts +1 -2
  17. package/dist/declarations/src/utils.d.ts +6 -6
  18. package/dist/declarations/src/waitFor.d.ts +1 -1
  19. package/dist/{interpreter-5c4e6634.development.esm.js → interpreter-1c52b23c.development.esm.js} +13 -23
  20. package/dist/{interpreter-de5217bc.esm.js → interpreter-8def682e.esm.js} +13 -23
  21. package/dist/{interpreter-69605bf0.cjs.js → interpreter-97aff8d2.cjs.js} +13 -23
  22. package/dist/{interpreter-d3567419.development.cjs.js → interpreter-e58ca48d.development.cjs.js} +13 -23
  23. package/dist/{raise-26e4d83c.development.cjs.js → raise-1fd59c65.development.cjs.js} +129 -102
  24. package/dist/{raise-511399cc.esm.js → raise-21c417c1.esm.js} +129 -102
  25. package/dist/{raise-0ff57677.cjs.js → raise-800296d7.cjs.js} +129 -102
  26. package/dist/{raise-cdcdf834.development.esm.js → raise-e342a840.development.esm.js} +129 -102
  27. package/dist/{send-19ffc568.cjs.js → send-4cc29786.cjs.js} +7 -4
  28. package/dist/{send-1de74f4d.development.esm.js → send-83ccc98b.development.esm.js} +7 -4
  29. package/dist/{send-211a2a94.esm.js → send-92854675.esm.js} +7 -4
  30. package/dist/{send-894c4b18.development.cjs.js → send-b309ef4e.development.cjs.js} +7 -4
  31. package/dist/xstate.cjs.js +11 -19
  32. package/dist/xstate.development.cjs.js +11 -19
  33. package/dist/xstate.development.esm.js +14 -22
  34. package/dist/xstate.esm.js +14 -22
  35. package/dist/xstate.umd.min.js +1 -1
  36. package/dist/xstate.umd.min.js.map +1 -1
  37. package/guards/dist/xstate-guards.cjs.js +2 -2
  38. package/guards/dist/xstate-guards.development.cjs.js +2 -2
  39. package/guards/dist/xstate-guards.development.esm.js +2 -2
  40. package/guards/dist/xstate-guards.esm.js +2 -2
  41. package/guards/dist/xstate-guards.umd.min.js +1 -1
  42. package/guards/dist/xstate-guards.umd.min.js.map +1 -1
  43. 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, X as XSTATE_STOP, u as XSTATE_INIT, W as WILDCARD, v as createAfterEvent, w as flatten, e as matchesState, $ as $$ACTOR_TYPE } from './interpreter-de5217bc.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, X as XSTATE_STOP, u as XSTATE_INIT, W as WILDCARD, v as createAfterEvent, w as flatten, e as matchesState, $ as $$ACTOR_TYPE } from './interpreter-8def682e.esm.js';
2
2
 
3
3
  const cache = new WeakMap();
4
4
  function memo(object, key, fn) {
@@ -47,14 +47,17 @@ function resolveInvoke(actorContext, state, actionArgs, {
47
47
  input,
48
48
  syncSnapshot
49
49
  }) {
50
- const referenced = resolveReferencedActor(state.machine.implementations.actors[src]);
50
+ const referenced = typeof src === 'string' ? resolveReferencedActor(state.machine, src) : {
51
+ src,
52
+ input: undefined
53
+ };
51
54
  let actorRef;
52
55
  if (referenced) {
53
56
  // TODO: inline `input: undefined` should win over the referenced one
54
57
  const configuredInput = input || referenced.input;
55
58
  actorRef = createActor(referenced.src, {
56
59
  id,
57
- src,
60
+ src: typeof src === 'string' ? src : undefined,
58
61
  parent: actorContext?.self,
59
62
  systemId,
60
63
  input: typeof configuredInput === 'function' ? configuredInput({
@@ -151,11 +154,16 @@ function executeStop(actorContext, actorRef) {
151
154
  if (!actorRef) {
152
155
  return;
153
156
  }
157
+ // this allows us to prevent an actor from being started if it gets stopped within the same macrostep
158
+ // this can happen, for example, when the invoking state is being exited immediately by an always transition
154
159
  if (actorRef.status !== ActorStatus.Running) {
155
160
  actorContext.stopChild(actorRef);
156
161
  return;
157
162
  }
158
- // TODO: recheck why this one has to be deferred
163
+ // stopping a child enqueues a stop event in the child actor's mailbox
164
+ // we need for all of the already enqueued events to be processed before we stop the child
165
+ // the parent itself might want to send some events to a child (for example from exit actions on the invoking state)
166
+ // and we don't want to ignore those events
159
167
  actorContext.defer(() => {
160
168
  actorContext.stopChild(actorRef);
161
169
  });
@@ -179,7 +187,8 @@ function checkStateIn(state, _, {
179
187
  stateValue
180
188
  }) {
181
189
  if (typeof stateValue === 'string' && isStateId(stateValue)) {
182
- return state.configuration.some(sn => sn.id === stateValue.slice(1));
190
+ const target = state.machine.getStateNodeById(stateValue);
191
+ return state.configuration.some(sn => sn === target);
183
192
  }
184
193
  return state.matches(stateValue);
185
194
  }
@@ -283,6 +292,9 @@ function getChildren(stateNode) {
283
292
  }
284
293
  function getProperAncestors(stateNode, toStateNode) {
285
294
  const ancestors = [];
295
+ if (toStateNode === stateNode) {
296
+ return ancestors;
297
+ }
286
298
 
287
299
  // add all ancestors
288
300
  let m = stateNode.parent;
@@ -559,12 +571,14 @@ function resolveTarget(stateNode, targets) {
559
571
  }
560
572
  });
561
573
  }
562
- function resolveHistoryTarget(stateNode) {
574
+ function resolveHistoryDefaultTransition(stateNode) {
563
575
  const normalizedTarget = normalizeTarget(stateNode.config.target);
564
576
  if (!normalizedTarget) {
565
- return stateNode.parent.initial.target;
577
+ return stateNode.parent.initial;
566
578
  }
567
- return normalizedTarget.map(t => typeof t === 'string' ? getStateNodeByPath(stateNode.parent, t) : t);
579
+ return {
580
+ target: normalizedTarget.map(t => typeof t === 'string' ? getStateNodeByPath(stateNode.parent, t) : t)
581
+ };
568
582
  }
569
583
  function isHistoryNode(stateNode) {
570
584
  return stateNode.type === 'history';
@@ -791,9 +805,7 @@ function getEffectiveTargetStates(transition, historyValue) {
791
805
  targets.add(node);
792
806
  }
793
807
  } else {
794
- for (const node of getEffectiveTargetStates({
795
- target: resolveHistoryTarget(targetNode)
796
- }, historyValue)) {
808
+ for (const node of getEffectiveTargetStates(resolveHistoryDefaultTransition(targetNode), historyValue)) {
797
809
  targets.add(node);
798
810
  }
799
811
  }
@@ -806,9 +818,9 @@ function getEffectiveTargetStates(transition, historyValue) {
806
818
  function getTransitionDomain(transition, historyValue) {
807
819
  const targetStates = getEffectiveTargetStates(transition, historyValue);
808
820
  if (!targetStates) {
809
- return null;
821
+ return;
810
822
  }
811
- if (!transition.reenter && transition.source.type !== 'parallel' && targetStates.every(targetStateNode => isDescendant(targetStateNode, transition.source))) {
823
+ if (!transition.reenter && targetStates.every(target => target === transition.source || isDescendant(target, transition.source))) {
812
824
  return transition.source;
813
825
  }
814
826
  const lcca = findLCCA(targetStates.concat(transition.source));
@@ -819,6 +831,9 @@ function computeExitSet(transitions, configuration, historyValue) {
819
831
  for (const t of transitions) {
820
832
  if (t.target?.length) {
821
833
  const domain = getTransitionDomain(t, historyValue);
834
+ if (t.reenter && t.source === domain) {
835
+ statesToExit.add(domain);
836
+ }
822
837
  for (const stateNode of configuration) {
823
838
  if (isDescendant(stateNode, domain)) {
824
839
  statesToExit.add(stateNode);
@@ -828,6 +843,17 @@ function computeExitSet(transitions, configuration, historyValue) {
828
843
  }
829
844
  return [...statesToExit];
830
845
  }
846
+ function areConfigurationsEqual(previousConfiguration, nextConfigurationSet) {
847
+ if (previousConfiguration.length !== nextConfigurationSet.size) {
848
+ return false;
849
+ }
850
+ for (const node of previousConfiguration) {
851
+ if (!nextConfigurationSet.has(node)) {
852
+ return false;
853
+ }
854
+ }
855
+ return true;
856
+ }
831
857
 
832
858
  /**
833
859
  * https://www.w3.org/TR/scxml/#microstepProcedure
@@ -837,50 +863,36 @@ function computeExitSet(transitions, configuration, historyValue) {
837
863
  * @param currentState
838
864
  * @param mutConfiguration
839
865
  */
840
-
841
- function microstep(transitions, currentState, actorCtx, event, isInitial) {
842
- const mutConfiguration = new Set(currentState.configuration);
866
+ function microstep(transitions, currentState, actorCtx, event, isInitial, internalQueue) {
843
867
  if (!transitions.length) {
844
868
  return currentState;
845
869
  }
846
- const microstate = microstepProcedure(transitions, currentState, mutConfiguration, event, actorCtx, isInitial);
847
- return cloneState(microstate, {
848
- value: {} // TODO: make optional
849
- });
850
- }
851
-
852
- function microstepProcedure(transitions, currentState, mutConfiguration, event, actorCtx, isInitial) {
853
- const historyValue = {
854
- ...currentState.historyValue
855
- };
870
+ const mutConfiguration = new Set(currentState.configuration);
871
+ let historyValue = currentState.historyValue;
856
872
  const filteredTransitions = removeConflictingTransitions(transitions, mutConfiguration, historyValue);
857
- const internalQueue = [...currentState._internalQueue];
858
- // TODO: this `cloneState` is really just a hack to prevent infinite loops
859
- // we need to take another look at how internal queue is managed
860
- let nextState = cloneState(currentState, {
861
- _internalQueue: []
862
- });
873
+ let nextState = currentState;
863
874
 
864
875
  // Exit states
865
876
  if (!isInitial) {
866
- nextState = exitStates(nextState, event, actorCtx, filteredTransitions, mutConfiguration, historyValue);
877
+ [nextState, historyValue] = exitStates(nextState, event, actorCtx, filteredTransitions, mutConfiguration, historyValue, internalQueue);
867
878
  }
868
879
 
869
880
  // Execute transition content
870
- nextState = resolveActionsAndContext(nextState, event, actorCtx, filteredTransitions.flatMap(t => t.actions));
881
+ nextState = resolveActionsAndContext(nextState, event, actorCtx, filteredTransitions.flatMap(t => t.actions), internalQueue);
871
882
 
872
883
  // Enter states
873
884
  nextState = enterStates(nextState, event, actorCtx, filteredTransitions, mutConfiguration, internalQueue, historyValue, isInitial);
874
885
  const nextConfiguration = [...mutConfiguration];
875
886
  if (nextState.status === 'done') {
876
- nextState = resolveActionsAndContext(nextState, event, actorCtx, nextConfiguration.sort((a, b) => b.order - a.order).flatMap(state => state.exit));
887
+ nextState = resolveActionsAndContext(nextState, event, actorCtx, nextConfiguration.sort((a, b) => b.order - a.order).flatMap(state => state.exit), internalQueue);
877
888
  }
878
889
  try {
879
- internalQueue.push(...nextState._internalQueue);
890
+ if (historyValue === currentState.historyValue && areConfigurationsEqual(currentState.configuration, mutConfiguration)) {
891
+ return nextState;
892
+ }
880
893
  return cloneState(nextState, {
881
894
  configuration: nextConfiguration,
882
- historyValue,
883
- _internalQueue: internalQueue
895
+ historyValue
884
896
  });
885
897
  } catch (e) {
886
898
  // TODO: Refactor this once proper error handling is implemented.
@@ -898,6 +910,9 @@ function getMachineOutput(state, event, actorCtx, rootNode, rootCompletionNode)
898
910
  function enterStates(currentState, event, actorCtx, filteredTransitions, mutConfiguration, internalQueue, historyValue, isInitial) {
899
911
  let nextState = currentState;
900
912
  const statesToEnter = new Set();
913
+ // those are states that were directly targeted or indirectly targeted by the explicit target
914
+ // in other words, those are states for which initial actions should be executed
915
+ // when we target `#deep_child` initial actions of its ancestors shouldn't be executed
901
916
  const statesForDefaultEntry = new Set();
902
917
  computeEntrySet(filteredTransitions, historyValue, statesForDefaultEntry, statesToEnter);
903
918
 
@@ -919,23 +934,19 @@ function enterStates(currentState, event, actorCtx, filteredTransitions, mutConf
919
934
  const initialActions = stateNodeToEnter.initial.actions;
920
935
  actions.push(...initialActions);
921
936
  }
922
- nextState = resolveActionsAndContext(nextState, event, actorCtx, actions, stateNodeToEnter.invoke.map(invokeDef => invokeDef.id));
937
+ nextState = resolveActionsAndContext(nextState, event, actorCtx, actions, internalQueue, stateNodeToEnter.invoke.map(invokeDef => invokeDef.id));
923
938
  if (stateNodeToEnter.type === 'final') {
924
939
  const parent = stateNodeToEnter.parent;
925
- if (completedNodes.has(parent)) {
926
- continue;
927
- }
928
- completedNodes.add(parent);
929
- let rootCompletionNode = parent?.type === 'parallel' ? parent : stateNodeToEnter;
930
- let ancestorMarker = parent?.parent;
931
- if (ancestorMarker) {
940
+ let ancestorMarker = parent?.type === 'parallel' ? parent : parent?.parent;
941
+ let rootCompletionNode = ancestorMarker || stateNodeToEnter;
942
+ if (parent?.type === 'compound') {
932
943
  internalQueue.push(createDoneStateEvent(parent.id, stateNodeToEnter.output ? resolveOutput(stateNodeToEnter.output, nextState.context, event, actorCtx.self) : undefined));
933
- while (ancestorMarker?.type === 'parallel' && !completedNodes.has(ancestorMarker) && isInFinalState(mutConfiguration, ancestorMarker)) {
934
- completedNodes.add(ancestorMarker);
935
- internalQueue.push(createDoneStateEvent(ancestorMarker.id));
936
- rootCompletionNode = ancestorMarker;
937
- ancestorMarker = ancestorMarker.parent;
938
- }
944
+ }
945
+ while (ancestorMarker?.type === 'parallel' && !completedNodes.has(ancestorMarker) && isInFinalState(mutConfiguration, ancestorMarker)) {
946
+ completedNodes.add(ancestorMarker);
947
+ internalQueue.push(createDoneStateEvent(ancestorMarker.id));
948
+ rootCompletionNode = ancestorMarker;
949
+ ancestorMarker = ancestorMarker.parent;
939
950
  }
940
951
  if (ancestorMarker) {
941
952
  continue;
@@ -950,13 +961,24 @@ function enterStates(currentState, event, actorCtx, filteredTransitions, mutConf
950
961
  }
951
962
  function computeEntrySet(transitions, historyValue, statesForDefaultEntry, statesToEnter) {
952
963
  for (const t of transitions) {
964
+ const domain = getTransitionDomain(t, historyValue);
953
965
  for (const s of t.target || []) {
966
+ if (!isHistoryNode(s) && (
967
+ // if the target is different than the source then it will *definitely* be entered
968
+ t.source !== s ||
969
+ // we know that the domain can't lie within the source
970
+ // if it's different than the source then it's outside of it and it means that the target has to be entered as well
971
+ t.source !== domain ||
972
+ // reentering transitions always enter the target, even if it's the source itself
973
+ t.reenter)) {
974
+ statesToEnter.add(s);
975
+ statesForDefaultEntry.add(s);
976
+ }
954
977
  addDescendantStatesToEnter(s, historyValue, statesForDefaultEntry, statesToEnter);
955
978
  }
956
- const ancestor = getTransitionDomain(t, historyValue);
957
979
  const targetStates = getEffectiveTargetStates(t, historyValue);
958
980
  for (const s of targetStates) {
959
- addAncestorStatesToEnter(s, ancestor, statesToEnter, historyValue, statesForDefaultEntry);
981
+ addAncestorStatesToEnter(s, domain, statesToEnter, historyValue, statesForDefaultEntry);
960
982
  }
961
983
  }
962
984
  }
@@ -965,37 +987,42 @@ function addDescendantStatesToEnter(stateNode, historyValue, statesForDefaultEnt
965
987
  if (historyValue[stateNode.id]) {
966
988
  const historyStateNodes = historyValue[stateNode.id];
967
989
  for (const s of historyStateNodes) {
990
+ statesToEnter.add(s);
968
991
  addDescendantStatesToEnter(s, historyValue, statesForDefaultEntry, statesToEnter);
969
992
  }
970
993
  for (const s of historyStateNodes) {
971
994
  addAncestorStatesToEnter(s, stateNode.parent, statesToEnter, historyValue, statesForDefaultEntry);
972
- for (const stateForDefaultEntry of statesForDefaultEntry) {
973
- statesForDefaultEntry.add(stateForDefaultEntry);
974
- }
975
995
  }
976
996
  } else {
977
- const targets = resolveHistoryTarget(stateNode);
978
- for (const s of targets) {
997
+ const historyDefaultTransition = resolveHistoryDefaultTransition(stateNode);
998
+ for (const s of historyDefaultTransition.target) {
999
+ statesToEnter.add(s);
1000
+ if (historyDefaultTransition === stateNode.parent?.initial) {
1001
+ statesForDefaultEntry.add(stateNode.parent);
1002
+ }
979
1003
  addDescendantStatesToEnter(s, historyValue, statesForDefaultEntry, statesToEnter);
980
1004
  }
981
- for (const s of targets) {
1005
+ for (const s of historyDefaultTransition.target) {
982
1006
  addAncestorStatesToEnter(s, stateNode, statesToEnter, historyValue, statesForDefaultEntry);
983
- for (const stateForDefaultEntry of statesForDefaultEntry) {
984
- statesForDefaultEntry.add(stateForDefaultEntry);
985
- }
986
1007
  }
987
1008
  }
988
1009
  } else {
989
- statesToEnter.add(stateNode);
990
1010
  if (stateNode.type === 'compound') {
991
- statesForDefaultEntry.add(stateNode);
992
1011
  const [initialState] = stateNode.initial.target;
1012
+ if (!isHistoryNode(initialState)) {
1013
+ statesToEnter.add(initialState);
1014
+ statesForDefaultEntry.add(initialState);
1015
+ }
993
1016
  addDescendantStatesToEnter(initialState, historyValue, statesForDefaultEntry, statesToEnter);
994
1017
  addAncestorStatesToEnter(initialState, stateNode, statesToEnter, historyValue, statesForDefaultEntry);
995
1018
  } else {
996
1019
  if (stateNode.type === 'parallel') {
997
1020
  for (const child of getChildren(stateNode).filter(sn => !isHistoryNode(sn))) {
998
1021
  if (![...statesToEnter].some(s => isDescendant(s, child))) {
1022
+ if (!isHistoryNode(child)) {
1023
+ statesToEnter.add(child);
1024
+ statesForDefaultEntry.add(child);
1025
+ }
999
1026
  addDescendantStatesToEnter(child, historyValue, statesForDefaultEntry, statesToEnter);
1000
1027
  }
1001
1028
  }
@@ -1010,16 +1037,18 @@ function addAncestorStatesToEnter(stateNode, toStateNode, statesToEnter, history
1010
1037
  if (anc.type === 'parallel') {
1011
1038
  for (const child of getChildren(anc).filter(sn => !isHistoryNode(sn))) {
1012
1039
  if (![...statesToEnter].some(s => isDescendant(s, child))) {
1040
+ statesToEnter.add(child);
1013
1041
  addDescendantStatesToEnter(child, historyValue, statesForDefaultEntry, statesToEnter);
1014
1042
  }
1015
1043
  }
1016
1044
  }
1017
1045
  }
1018
1046
  }
1019
- function exitStates(currentState, event, actorCtx, transitions, mutConfiguration, historyValue) {
1047
+ function exitStates(currentState, event, actorCtx, transitions, mutConfiguration, historyValue, internalQueue) {
1020
1048
  let nextState = currentState;
1021
1049
  const statesToExit = computeExitSet(transitions, mutConfiguration, historyValue);
1022
1050
  statesToExit.sort((a, b) => b.order - a.order);
1051
+ let changedHistory;
1023
1052
 
1024
1053
  // From SCXML algorithm: https://www.w3.org/TR/scxml/#exitStates
1025
1054
  for (const exitStateNode of statesToExit) {
@@ -1032,14 +1061,17 @@ function exitStates(currentState, event, actorCtx, transitions, mutConfiguration
1032
1061
  return sn.parent === exitStateNode;
1033
1062
  };
1034
1063
  }
1035
- historyValue[historyNode.id] = Array.from(mutConfiguration).filter(predicate);
1064
+ changedHistory ??= {
1065
+ ...historyValue
1066
+ };
1067
+ changedHistory[historyNode.id] = Array.from(mutConfiguration).filter(predicate);
1036
1068
  }
1037
1069
  }
1038
1070
  for (const s of statesToExit) {
1039
- 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);
1040
1072
  mutConfiguration.delete(s);
1041
1073
  }
1042
- return nextState;
1074
+ return [nextState, changedHistory || historyValue];
1043
1075
  }
1044
1076
  function resolveActionsAndContextWorker(currentState, event, actorCtx, actions, extra, retries) {
1045
1077
  const {
@@ -1104,9 +1136,10 @@ function resolveActionsAndContextWorker(currentState, event, actorCtx, actions,
1104
1136
  }
1105
1137
  return intermediateState;
1106
1138
  }
1107
- function resolveActionsAndContext(currentState, event, actorCtx, actions, deferredActorIds) {
1139
+ function resolveActionsAndContext(currentState, event, actorCtx, actions, internalQueue, deferredActorIds) {
1108
1140
  const retries = deferredActorIds ? [] : undefined;
1109
- const nextState = resolveActionsAndContextWorker(currentState, event, actorCtx, actions, deferredActorIds && {
1141
+ const nextState = resolveActionsAndContextWorker(currentState, event, actorCtx, actions, {
1142
+ internalQueue,
1110
1143
  deferredActorIds
1111
1144
  }, retries);
1112
1145
  retries?.forEach(([builtinAction, params]) => {
@@ -1114,13 +1147,13 @@ function resolveActionsAndContext(currentState, event, actorCtx, actions, deferr
1114
1147
  });
1115
1148
  return nextState;
1116
1149
  }
1117
- function macrostep(state, event, actorCtx) {
1150
+ function macrostep(state, event, actorCtx, internalQueue = []) {
1118
1151
  let nextState = state;
1119
1152
  const states = [];
1120
1153
 
1121
1154
  // Handle stop event
1122
1155
  if (event.type === XSTATE_STOP) {
1123
- nextState = stopStep(event, nextState, actorCtx);
1156
+ nextState = stopChildren(nextState, event, actorCtx);
1124
1157
  states.push(nextState);
1125
1158
  return {
1126
1159
  state: nextState,
@@ -1133,44 +1166,37 @@ function macrostep(state, event, actorCtx) {
1133
1166
  // Determine the next state based on the next microstep
1134
1167
  if (nextEvent.type !== XSTATE_INIT) {
1135
1168
  const transitions = selectTransitions(nextEvent, nextState);
1136
- nextState = microstep(transitions, state, actorCtx, nextEvent, false);
1169
+ nextState = microstep(transitions, state, actorCtx, nextEvent, false, internalQueue);
1137
1170
  states.push(nextState);
1138
1171
  }
1172
+ let shouldSelectEventlessTransitions = true;
1139
1173
  while (nextState.status === 'active') {
1140
- let enabledTransitions = selectEventlessTransitions(nextState, nextEvent);
1174
+ let enabledTransitions = shouldSelectEventlessTransitions ? selectEventlessTransitions(nextState, nextEvent) : [];
1175
+
1176
+ // eventless transitions should always be selected after selecting *regular* transitions
1177
+ // by assigning `undefined` to `previousState` we ensure that `shouldSelectEventlessTransitions` gets always computed to true in such a case
1178
+ const previousState = enabledTransitions.length ? nextState : undefined;
1141
1179
  if (!enabledTransitions.length) {
1142
- if (!nextState._internalQueue.length) {
1180
+ if (!internalQueue.length) {
1143
1181
  break;
1144
- } else {
1145
- nextEvent = nextState._internalQueue[0];
1146
- const transitions = selectTransitions(nextEvent, nextState);
1147
- nextState = microstep(transitions, nextState, actorCtx, nextEvent, false);
1148
- nextState._internalQueue.shift();
1149
- states.push(nextState);
1150
1182
  }
1151
- } else {
1152
- nextState = microstep(enabledTransitions, nextState, actorCtx, nextEvent, false);
1153
- states.push(nextState);
1183
+ nextEvent = internalQueue.shift();
1184
+ enabledTransitions = selectTransitions(nextEvent, nextState);
1154
1185
  }
1186
+ nextState = microstep(enabledTransitions, nextState, actorCtx, nextEvent, false, internalQueue);
1187
+ shouldSelectEventlessTransitions = nextState !== previousState;
1188
+ states.push(nextState);
1155
1189
  }
1156
1190
  if (nextState.status !== 'active') {
1157
- // Perform the stop step to ensure that child actors are stopped
1158
- stopStep(nextEvent, nextState, actorCtx);
1191
+ stopChildren(nextState, nextEvent, actorCtx);
1159
1192
  }
1160
1193
  return {
1161
1194
  state: nextState,
1162
1195
  microstates: states
1163
1196
  };
1164
1197
  }
1165
- function stopStep(event, nextState, actorCtx) {
1166
- const actions = [];
1167
- for (const stateNode of nextState.configuration.sort((a, b) => b.order - a.order)) {
1168
- actions.push(...stateNode.exit);
1169
- }
1170
- for (const child of Object.values(nextState.children)) {
1171
- actions.push(stop(child));
1172
- }
1173
- return resolveActionsAndContext(nextState, event, actorCtx, actions);
1198
+ function stopChildren(nextState, event, actorCtx) {
1199
+ return resolveActionsAndContext(nextState, event, actorCtx, Object.values(nextState.children).map(child => stop(child)), []);
1174
1200
  }
1175
1201
  function selectTransitions(event, nextState) {
1176
1202
  return nextState.machine.getTransitionData(nextState, event);
@@ -1179,7 +1205,7 @@ function selectEventlessTransitions(nextState, event) {
1179
1205
  const enabledTransitionSet = new Set();
1180
1206
  const atomicStates = nextState.configuration.filter(isAtomicStateNode);
1181
1207
  for (const stateNode of atomicStates) {
1182
- loop: for (const s of [stateNode].concat(getProperAncestors(stateNode, null))) {
1208
+ loop: for (const s of [stateNode].concat(getProperAncestors(stateNode, undefined))) {
1183
1209
  if (!s.always) {
1184
1210
  continue;
1185
1211
  }
@@ -1276,11 +1302,9 @@ class State {
1276
1302
  this.error = void 0;
1277
1303
  this.context = void 0;
1278
1304
  this.historyValue = {};
1279
- this._internalQueue = void 0;
1280
1305
  this.configuration = void 0;
1281
1306
  this.children = void 0;
1282
1307
  this.context = config.context;
1283
- this._internalQueue = config._internalQueue ?? [];
1284
1308
  this.historyValue = config.historyValue || {};
1285
1309
  this.matches = this.matches.bind(this);
1286
1310
  this.toStrings = this.toStrings.bind(this);
@@ -1429,6 +1453,8 @@ function resolveRaise(_, state, args, {
1429
1453
  event: eventOrExpr,
1430
1454
  id,
1431
1455
  delay
1456
+ }, {
1457
+ internalQueue
1432
1458
  }) {
1433
1459
  const delaysMap = state.machine.implementations.delays;
1434
1460
  if (typeof eventOrExpr === 'string') {
@@ -1442,9 +1468,10 @@ function resolveRaise(_, state, args, {
1442
1468
  } else {
1443
1469
  resolvedDelay = typeof delay === 'function' ? delay(args) : delay;
1444
1470
  }
1445
- return [typeof resolvedDelay !== 'number' ? cloneState(state, {
1446
- _internalQueue: state._internalQueue.concat(resolvedEvent)
1447
- }) : state, {
1471
+ if (typeof resolvedDelay !== 'number') {
1472
+ internalQueue.push(resolvedEvent);
1473
+ }
1474
+ return [state, {
1448
1475
  event: resolvedEvent,
1449
1476
  id,
1450
1477
  delay: resolvedDelay