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