xstate 5.0.0-beta.33 → 5.0.0-beta.35

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 +3 -3
  9. package/actors/dist/xstate-actors.development.cjs.js +3 -3
  10. package/actors/dist/xstate-actors.development.esm.js +3 -3
  11. package/actors/dist/xstate-actors.esm.js +3 -3
  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/index.d.ts +1 -0
  15. package/dist/declarations/src/interpreter.d.ts +3 -1
  16. package/dist/declarations/src/stateUtils.d.ts +6 -5
  17. package/dist/declarations/src/types.d.ts +3 -5
  18. package/dist/{interpreter-825f3d6e.development.esm.js → interpreter-5c4e6634.development.esm.js} +67 -65
  19. package/dist/{interpreter-054e9fb7.cjs.js → interpreter-69605bf0.cjs.js} +67 -65
  20. package/dist/{interpreter-0c630f66.development.cjs.js → interpreter-d3567419.development.cjs.js} +67 -65
  21. package/dist/{interpreter-03737810.esm.js → interpreter-de5217bc.esm.js} +67 -65
  22. package/dist/{raise-987c242e.cjs.js → raise-0ff57677.cjs.js} +142 -124
  23. package/dist/{raise-4c6a5a96.development.cjs.js → raise-26e4d83c.development.cjs.js} +145 -124
  24. package/dist/{raise-2d92eae8.esm.js → raise-511399cc.esm.js} +142 -124
  25. package/dist/{raise-46f122aa.development.esm.js → raise-cdcdf834.development.esm.js} +145 -124
  26. package/dist/{send-bd1bd0e3.cjs.js → send-19ffc568.cjs.js} +16 -8
  27. package/dist/{send-4d5b92dc.development.esm.js → send-1de74f4d.development.esm.js} +16 -8
  28. package/dist/{send-0edee2b4.esm.js → send-211a2a94.esm.js} +16 -8
  29. package/dist/{send-0e8675c8.development.cjs.js → send-894c4b18.development.cjs.js} +16 -8
  30. package/dist/xstate.cjs.js +28 -9
  31. package/dist/xstate.development.cjs.js +28 -9
  32. package/dist/xstate.development.esm.js +31 -12
  33. package/dist/xstate.esm.js +31 -12
  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,6 +1,6 @@
1
1
  'use strict';
2
2
 
3
- var interpreter = require('./interpreter-0c630f66.development.cjs.js');
3
+ var interpreter = require('./interpreter-d3567419.development.cjs.js');
4
4
 
5
5
  const cache = new WeakMap();
6
6
  function memo(object, key, fn) {
@@ -299,20 +299,6 @@ function evaluateGuard(guard, context, event, state) {
299
299
  );
300
300
  }
301
301
 
302
- function getOutput(configuration, context, event, self) {
303
- const {
304
- machine
305
- } = configuration[0];
306
- const {
307
- root
308
- } = machine;
309
- if (!root.output) {
310
- return undefined;
311
- }
312
- const finalChildStateNode = configuration.find(stateNode => stateNode.type === 'final' && stateNode.parent === machine.root);
313
- const doneStateEvent = interpreter.createDoneStateEvent(finalChildStateNode.id, finalChildStateNode.output ? interpreter.resolveOutput(finalChildStateNode.output, context, event, self) : undefined);
314
- return interpreter.resolveOutput(root.output, context, doneStateEvent, self);
315
- }
316
302
  const isAtomicStateNode = stateNode => stateNode.type === 'atomic' || stateNode.type === 'final';
317
303
  function getChildren(stateNode) {
318
304
  return Object.values(stateNode.states).filter(sn => sn.type !== 'history');
@@ -337,7 +323,7 @@ function getConfiguration(stateNodes) {
337
323
  for (const s of configuration) {
338
324
  // if previously active, add existing child nodes
339
325
  if (s.type === 'compound' && (!adjList.get(s) || !adjList.get(s).length)) {
340
- getInitialStateNodes(s).forEach(sn => configurationSet.add(sn));
326
+ getInitialStateNodesWithTheirAncestors(s).forEach(sn => configurationSet.add(sn));
341
327
  } else {
342
328
  if (s.type === 'parallel') {
343
329
  for (const child of getChildren(s)) {
@@ -345,7 +331,8 @@ function getConfiguration(stateNodes) {
345
331
  continue;
346
332
  }
347
333
  if (!configurationSet.has(child)) {
348
- for (const initialStateNode of getInitialStateNodes(child)) {
334
+ const initialStates = getInitialStateNodesWithTheirAncestors(child);
335
+ for (const initialStateNode of initialStates) {
349
336
  configurationSet.add(initialStateNode);
350
337
  }
351
338
  }
@@ -405,14 +392,14 @@ function getStateValue(rootNode, configuration) {
405
392
  const config = getConfiguration(configuration);
406
393
  return getValueFromAdj(rootNode, getAdjList(config));
407
394
  }
408
- function isInFinalState(configuration, stateNode = configuration[0].machine.root) {
395
+ function isInFinalState(configuration, stateNode) {
409
396
  if (stateNode.type === 'compound') {
410
- return getChildren(stateNode).some(s => s.type === 'final' && configuration.includes(s));
397
+ return getChildren(stateNode).some(s => s.type === 'final' && configuration.has(s));
411
398
  }
412
399
  if (stateNode.type === 'parallel') {
413
400
  return getChildren(stateNode).every(sn => isInFinalState(configuration, sn));
414
401
  }
415
- return false;
402
+ return stateNode.type === 'final';
416
403
  }
417
404
  const isStateId = str => str[0] === interpreter.STATE_IDENTIFIER;
418
405
  function getCandidates(stateNode, receivedEventType) {
@@ -468,13 +455,7 @@ function getDelayedTransitions(stateNode) {
468
455
  stateNode.exit.push(cancel(eventType));
469
456
  return eventType;
470
457
  };
471
- const delayedTransitions = interpreter.isArray(afterConfig) ? afterConfig.map((transition, i) => {
472
- const eventType = mutateEntryExit(transition.delay, i);
473
- return {
474
- ...transition,
475
- event: eventType
476
- };
477
- }) : Object.keys(afterConfig).flatMap((delay, i) => {
458
+ const delayedTransitions = Object.keys(afterConfig).flatMap((delay, i) => {
478
459
  const configTransition = afterConfig[delay];
479
460
  const resolvedTransition = typeof configTransition === 'string' ? {
480
461
  target: configTransition
@@ -562,43 +543,23 @@ function formatTransitions(stateNode) {
562
543
  return transitions;
563
544
  }
564
545
  function formatInitialTransition(stateNode, _target) {
565
- if (typeof _target === 'string' || interpreter.isArray(_target)) {
566
- const targets = interpreter.toArray(_target).map(t => {
567
- // Resolve state string keys (which represent children)
568
- // to their state node
569
- const descStateNode = typeof t === 'string' ? isStateId(t) ? stateNode.machine.getStateNodeById(t) : stateNode.states[t] : t;
570
- if (!descStateNode) {
571
- throw new Error(`Initial state node "${t}" not found on parent state node #${stateNode.id}`);
572
- }
573
- if (!isDescendant(descStateNode, stateNode)) {
574
- throw new Error(`Invalid initial target: state node #${descStateNode.id} is not a descendant of #${stateNode.id}`);
575
- }
576
- return descStateNode;
577
- });
578
- const resolvedTarget = resolveTarget(stateNode, targets);
579
- const transition = {
580
- source: stateNode,
581
- actions: [],
582
- eventType: null,
583
- reenter: false,
584
- target: resolvedTarget,
585
- toJSON: () => ({
586
- ...transition,
587
- source: `#${stateNode.id}`,
588
- target: resolvedTarget ? resolvedTarget.map(t => `#${t.id}`) : undefined
589
- })
590
- };
591
- return transition;
546
+ const resolvedTarget = typeof _target === 'string' ? stateNode.states[_target] : _target ? stateNode.states[_target.target] : undefined;
547
+ if (!resolvedTarget && _target) {
548
+ throw new Error(`Initial state node "${_target}" not found on parent state node #${stateNode.id}`);
592
549
  }
593
- return formatTransition(stateNode, '__INITIAL__', {
594
- target: interpreter.toArray(_target.target).map(t => {
595
- if (typeof t === 'string') {
596
- return isStateId(t) ? t : `${interpreter.STATE_DELIMITER}${t}`;
597
- }
598
- return t;
599
- }),
600
- actions: _target.actions
601
- });
550
+ const transition = {
551
+ source: stateNode,
552
+ actions: !_target || typeof _target === 'string' ? [] : interpreter.toArray(_target.actions),
553
+ eventType: null,
554
+ reenter: false,
555
+ target: resolvedTarget ? [resolvedTarget] : [],
556
+ toJSON: () => ({
557
+ ...transition,
558
+ source: `#${stateNode.id}`,
559
+ target: resolvedTarget ? [`#${resolvedTarget.id}`] : []
560
+ })
561
+ };
562
+ return transition;
602
563
  }
603
564
  function resolveTarget(stateNode, targets) {
604
565
  if (targets === undefined) {
@@ -641,6 +602,15 @@ function resolveHistoryTarget(stateNode) {
641
602
  function isHistoryNode(stateNode) {
642
603
  return stateNode.type === 'history';
643
604
  }
605
+ function getInitialStateNodesWithTheirAncestors(stateNode) {
606
+ const states = getInitialStateNodes(stateNode);
607
+ for (const initialState of states) {
608
+ for (const ancestor of getProperAncestors(initialState, stateNode)) {
609
+ states.add(ancestor);
610
+ }
611
+ }
612
+ return states;
613
+ }
644
614
  function getInitialStateNodes(stateNode) {
645
615
  const set = new Set();
646
616
  function iter(descStateNode) {
@@ -649,12 +619,7 @@ function getInitialStateNodes(stateNode) {
649
619
  }
650
620
  set.add(descStateNode);
651
621
  if (descStateNode.type === 'compound') {
652
- for (const targetStateNode of descStateNode.initial.target) {
653
- for (const a of getProperAncestors(targetStateNode, stateNode)) {
654
- set.add(a);
655
- }
656
- iter(targetStateNode);
657
- }
622
+ iter(descStateNode.initial.target[0]);
658
623
  } else if (descStateNode.type === 'parallel') {
659
624
  for (const child of getChildren(descStateNode)) {
660
625
  iter(child);
@@ -662,7 +627,7 @@ function getInitialStateNodes(stateNode) {
662
627
  }
663
628
  }
664
629
  iter(stateNode);
665
- return [...set];
630
+ return set;
666
631
  }
667
632
  /**
668
633
  * Returns the child state node from its relative `stateKey`, or throws.
@@ -918,41 +883,37 @@ function microstep(transitions, currentState, actorCtx, event, isInitial) {
918
883
  }
919
884
 
920
885
  function microstepProcedure(transitions, currentState, mutConfiguration, event, actorCtx, isInitial) {
921
- const actions = [];
922
886
  const historyValue = {
923
887
  ...currentState.historyValue
924
888
  };
925
889
  const filteredTransitions = removeConflictingTransitions(transitions, mutConfiguration, historyValue);
926
890
  const internalQueue = [...currentState._internalQueue];
891
+ // TODO: this `cloneState` is really just a hack to prevent infinite loops
892
+ // we need to take another look at how internal queue is managed
893
+ let nextState = cloneState(currentState, {
894
+ _internalQueue: []
895
+ });
927
896
 
928
897
  // Exit states
929
898
  if (!isInitial) {
930
- exitStates(filteredTransitions, mutConfiguration, historyValue, actions);
899
+ nextState = exitStates(nextState, event, actorCtx, filteredTransitions, mutConfiguration, historyValue);
931
900
  }
932
901
 
933
902
  // Execute transition content
934
- actions.push(...filteredTransitions.flatMap(t => t.actions));
903
+ nextState = resolveActionsAndContext(nextState, event, actorCtx, filteredTransitions.flatMap(t => t.actions));
935
904
 
936
905
  // Enter states
937
- enterStates(event, filteredTransitions, mutConfiguration, actions, internalQueue, currentState, historyValue, isInitial, actorCtx);
906
+ nextState = enterStates(nextState, event, actorCtx, filteredTransitions, mutConfiguration, internalQueue, historyValue, isInitial);
938
907
  const nextConfiguration = [...mutConfiguration];
939
- const done = isInFinalState(nextConfiguration);
940
- if (done) {
941
- const finalActions = nextConfiguration.sort((a, b) => b.order - a.order).flatMap(state => state.exit);
942
- actions.push(...finalActions);
908
+ if (nextState.status === 'done') {
909
+ nextState = resolveActionsAndContext(nextState, event, actorCtx, nextConfiguration.sort((a, b) => b.order - a.order).flatMap(state => state.exit));
943
910
  }
944
911
  try {
945
- const nextState = resolveActionsAndContext(actions, event, currentState, actorCtx);
946
- const output = done ? getOutput(nextConfiguration, nextState.context, event, actorCtx.self) : undefined;
947
912
  internalQueue.push(...nextState._internalQueue);
948
- return cloneState(currentState, {
913
+ return cloneState(nextState, {
949
914
  configuration: nextConfiguration,
950
915
  historyValue,
951
- _internalQueue: internalQueue,
952
- context: nextState.context,
953
- status: done ? 'done' : currentState.status,
954
- output,
955
- children: nextState.children
916
+ _internalQueue: internalQueue
956
917
  });
957
918
  } catch (e) {
958
919
  // TODO: Refactor this once proper error handling is implemented.
@@ -960,7 +921,15 @@ function microstepProcedure(transitions, currentState, mutConfiguration, event,
960
921
  throw e;
961
922
  }
962
923
  }
963
- function enterStates(event, filteredTransitions, mutConfiguration, actions, internalQueue, currentState, historyValue, isInitial, actorContext) {
924
+ function getMachineOutput(state, event, actorCtx, rootNode, rootCompletionNode) {
925
+ if (!rootNode.output) {
926
+ return;
927
+ }
928
+ const doneStateEvent = interpreter.createDoneStateEvent(rootCompletionNode.id, rootCompletionNode.output && rootCompletionNode.parent ? interpreter.resolveOutput(rootCompletionNode.output, state.context, event, actorCtx.self) : undefined);
929
+ return interpreter.resolveOutput(rootNode.output, state.context, doneStateEvent, actorCtx.self);
930
+ }
931
+ function enterStates(currentState, event, actorCtx, filteredTransitions, mutConfiguration, internalQueue, historyValue, isInitial) {
932
+ let nextState = currentState;
964
933
  const statesToEnter = new Set();
965
934
  const statesForDefaultEntry = new Set();
966
935
  computeEntrySet(filteredTransitions, historyValue, statesForDefaultEntry, statesToEnter);
@@ -969,36 +938,48 @@ function enterStates(event, filteredTransitions, mutConfiguration, actions, inte
969
938
  if (isInitial) {
970
939
  statesForDefaultEntry.add(currentState.machine.root);
971
940
  }
941
+ const completedNodes = new Set();
972
942
  for (const stateNodeToEnter of [...statesToEnter].sort((a, b) => a.order - b.order)) {
973
943
  mutConfiguration.add(stateNodeToEnter);
974
- for (const invokeDef of stateNodeToEnter.invoke) {
975
- actions.push(invoke(invokeDef));
976
- }
944
+ const actions = [];
977
945
 
978
946
  // Add entry actions
979
947
  actions.push(...stateNodeToEnter.entry);
948
+ for (const invokeDef of stateNodeToEnter.invoke) {
949
+ actions.push(invoke(invokeDef));
950
+ }
980
951
  if (statesForDefaultEntry.has(stateNodeToEnter)) {
981
- for (const stateNode of statesForDefaultEntry) {
982
- const initialActions = stateNode.initial.actions;
983
- actions.push(...initialActions);
984
- }
952
+ const initialActions = stateNodeToEnter.initial.actions;
953
+ actions.push(...initialActions);
985
954
  }
955
+ nextState = resolveActionsAndContext(nextState, event, actorCtx, actions, stateNodeToEnter.invoke.map(invokeDef => invokeDef.id));
986
956
  if (stateNodeToEnter.type === 'final') {
987
957
  const parent = stateNodeToEnter.parent;
988
- if (!parent.parent) {
958
+ if (completedNodes.has(parent)) {
989
959
  continue;
990
960
  }
991
- internalQueue.push(interpreter.createDoneStateEvent(parent.id, stateNodeToEnter.output ? interpreter.resolveOutput(stateNodeToEnter.output, currentState.context, event, actorContext.self) : undefined));
992
- if (parent.parent) {
993
- const grandparent = parent.parent;
994
- if (grandparent.type === 'parallel') {
995
- if (getChildren(grandparent).every(parentNode => isInFinalState([...mutConfiguration], parentNode))) {
996
- internalQueue.push(interpreter.createDoneStateEvent(grandparent.id));
997
- }
961
+ completedNodes.add(parent);
962
+ let rootCompletionNode = parent?.type === 'parallel' ? parent : stateNodeToEnter;
963
+ let ancestorMarker = parent?.parent;
964
+ if (ancestorMarker) {
965
+ internalQueue.push(interpreter.createDoneStateEvent(parent.id, stateNodeToEnter.output ? interpreter.resolveOutput(stateNodeToEnter.output, nextState.context, event, actorCtx.self) : undefined));
966
+ while (ancestorMarker?.type === 'parallel' && !completedNodes.has(ancestorMarker) && isInFinalState(mutConfiguration, ancestorMarker)) {
967
+ completedNodes.add(ancestorMarker);
968
+ internalQueue.push(interpreter.createDoneStateEvent(ancestorMarker.id));
969
+ rootCompletionNode = ancestorMarker;
970
+ ancestorMarker = ancestorMarker.parent;
998
971
  }
999
972
  }
973
+ if (ancestorMarker) {
974
+ continue;
975
+ }
976
+ nextState = cloneState(nextState, {
977
+ status: 'done',
978
+ output: getMachineOutput(nextState, event, actorCtx, currentState.configuration[0].machine.root, rootCompletionNode)
979
+ });
1000
980
  }
1001
981
  }
982
+ return nextState;
1002
983
  }
1003
984
  function computeEntrySet(transitions, historyValue, statesForDefaultEntry, statesToEnter) {
1004
985
  for (const t of transitions) {
@@ -1041,13 +1022,9 @@ function addDescendantStatesToEnter(stateNode, historyValue, statesForDefaultEnt
1041
1022
  statesToEnter.add(stateNode);
1042
1023
  if (stateNode.type === 'compound') {
1043
1024
  statesForDefaultEntry.add(stateNode);
1044
- const initialStates = stateNode.initial.target;
1045
- for (const initialState of initialStates) {
1046
- addDescendantStatesToEnter(initialState, historyValue, statesForDefaultEntry, statesToEnter);
1047
- }
1048
- for (const initialState of initialStates) {
1049
- addAncestorStatesToEnter(initialState, stateNode, statesToEnter, historyValue, statesForDefaultEntry);
1050
- }
1025
+ const [initialState] = stateNode.initial.target;
1026
+ addDescendantStatesToEnter(initialState, historyValue, statesForDefaultEntry, statesToEnter);
1027
+ addAncestorStatesToEnter(initialState, stateNode, statesToEnter, historyValue, statesForDefaultEntry);
1051
1028
  } else {
1052
1029
  if (stateNode.type === 'parallel') {
1053
1030
  for (const child of getChildren(stateNode).filter(sn => !isHistoryNode(sn))) {
@@ -1072,7 +1049,8 @@ function addAncestorStatesToEnter(stateNode, toStateNode, statesToEnter, history
1072
1049
  }
1073
1050
  }
1074
1051
  }
1075
- function exitStates(transitions, mutConfiguration, historyValue, actions) {
1052
+ function exitStates(currentState, event, actorCtx, transitions, mutConfiguration, historyValue) {
1053
+ let nextState = currentState;
1076
1054
  const statesToExit = computeExitSet(transitions, mutConfiguration, historyValue);
1077
1055
  statesToExit.sort((a, b) => b.order - a.order);
1078
1056
 
@@ -1091,19 +1069,16 @@ function exitStates(transitions, mutConfiguration, historyValue, actions) {
1091
1069
  }
1092
1070
  }
1093
1071
  for (const s of statesToExit) {
1094
- actions.push(...s.exit, ...s.invoke.map(def => stop(def.id)));
1072
+ nextState = resolveActionsAndContext(nextState, event, actorCtx, [...s.exit, ...s.invoke.map(def => stop(def.id))]);
1095
1073
  mutConfiguration.delete(s);
1096
1074
  }
1075
+ return nextState;
1097
1076
  }
1098
- function resolveActionsAndContext(actions, event, currentState, actorCtx) {
1077
+ function resolveActionsAndContextWorker(currentState, event, actorCtx, actions, extra, retries) {
1099
1078
  const {
1100
1079
  machine
1101
1080
  } = currentState;
1102
- // TODO: this `cloneState` is really just a hack to prevent infinite loops
1103
- // we need to take another look at how internal queue is managed
1104
- let intermediateState = cloneState(currentState, {
1105
- _internalQueue: []
1106
- });
1081
+ let intermediateState = currentState;
1107
1082
  for (const action of actions) {
1108
1083
  const isInline = typeof action === 'function';
1109
1084
  const resolvedAction = isInline ? action :
@@ -1142,11 +1117,14 @@ function resolveActionsAndContext(actions, event, currentState, actorCtx) {
1142
1117
  continue;
1143
1118
  }
1144
1119
  const builtinAction = resolvedAction;
1145
- const [nextState, params, actions] = builtinAction.resolve(actorCtx, intermediateState, actionArgs, resolvedAction // this holds all params
1146
- );
1147
-
1120
+ const [nextState, params, actions] = builtinAction.resolve(actorCtx, intermediateState, actionArgs, resolvedAction,
1121
+ // this holds all params
1122
+ extra);
1148
1123
  intermediateState = nextState;
1149
- if ('execute' in resolvedAction) {
1124
+ if ('retryResolve' in builtinAction) {
1125
+ retries?.push([builtinAction, params]);
1126
+ }
1127
+ if ('execute' in builtinAction) {
1150
1128
  if (actorCtx?.self.status === interpreter.ActorStatus.Running) {
1151
1129
  builtinAction.execute(actorCtx, params);
1152
1130
  } else {
@@ -1154,11 +1132,21 @@ function resolveActionsAndContext(actions, event, currentState, actorCtx) {
1154
1132
  }
1155
1133
  }
1156
1134
  if (actions) {
1157
- intermediateState = resolveActionsAndContext(actions, event, intermediateState, actorCtx);
1135
+ intermediateState = resolveActionsAndContextWorker(intermediateState, event, actorCtx, actions, extra, retries);
1158
1136
  }
1159
1137
  }
1160
1138
  return intermediateState;
1161
1139
  }
1140
+ function resolveActionsAndContext(currentState, event, actorCtx, actions, deferredActorIds) {
1141
+ const retries = deferredActorIds ? [] : undefined;
1142
+ const nextState = resolveActionsAndContextWorker(currentState, event, actorCtx, actions, deferredActorIds && {
1143
+ deferredActorIds
1144
+ }, retries);
1145
+ retries?.forEach(([builtinAction, params]) => {
1146
+ builtinAction.retryResolve(actorCtx, nextState, params);
1147
+ });
1148
+ return nextState;
1149
+ }
1162
1150
  function macrostep(state, event, actorCtx) {
1163
1151
  if (event.type === interpreter.WILDCARD) {
1164
1152
  throw new Error(`An event cannot have the wildcard type ('${interpreter.WILDCARD}')`);
@@ -1218,7 +1206,7 @@ function stopStep(event, nextState, actorCtx) {
1218
1206
  for (const child of Object.values(nextState.children)) {
1219
1207
  actions.push(stop(child));
1220
1208
  }
1221
- return resolveActionsAndContext(actions, event, nextState, actorCtx);
1209
+ return resolveActionsAndContext(nextState, event, actorCtx, actions);
1222
1210
  }
1223
1211
  function selectTransitions(event, nextState) {
1224
1212
  return nextState.machine.getTransitionData(nextState, event);
@@ -1430,11 +1418,15 @@ function getPersistedState(state) {
1430
1418
  tags,
1431
1419
  machine,
1432
1420
  children,
1421
+ context,
1433
1422
  ...jsonValues
1434
1423
  } = state;
1435
1424
  const childrenJson = {};
1436
1425
  for (const id in children) {
1437
1426
  const child = children[id];
1427
+ if (typeof child.src !== 'string') {
1428
+ throw new Error('An inline child actor cannot be persisted.');
1429
+ }
1438
1430
  childrenJson[id] = {
1439
1431
  state: child.getPersistedState?.(),
1440
1432
  src: child.src
@@ -1442,9 +1434,38 @@ function getPersistedState(state) {
1442
1434
  }
1443
1435
  return {
1444
1436
  ...jsonValues,
1437
+ // TODO: this makes `PersistedMachineState`'s type kind of a lie
1438
+ // it doesn't truly use `TContext` but rather some kind of a derived form of it
1439
+ context: persistContext(context),
1445
1440
  children: childrenJson
1446
1441
  };
1447
1442
  }
1443
+ function persistContext(contextPart) {
1444
+ let copy;
1445
+ for (const key in contextPart) {
1446
+ const value = contextPart[key];
1447
+ if (value && typeof value === 'object') {
1448
+ if ('sessionId' in value && 'send' in value && 'ref' in value) {
1449
+ copy ??= Array.isArray(contextPart) ? contextPart.slice() : {
1450
+ ...contextPart
1451
+ };
1452
+ copy[key] = {
1453
+ xstate$$type: interpreter.$$ACTOR_TYPE,
1454
+ id: value.id
1455
+ };
1456
+ } else {
1457
+ const result = persistContext(value);
1458
+ if (result !== value) {
1459
+ copy ??= Array.isArray(contextPart) ? contextPart.slice() : {
1460
+ ...contextPart
1461
+ };
1462
+ copy[key] = result;
1463
+ }
1464
+ }
1465
+ }
1466
+ }
1467
+ return copy ?? contextPart;
1468
+ }
1448
1469
 
1449
1470
  function resolveRaise(_, state, args, {
1450
1471
  event: eventOrExpr,
@@ -1510,10 +1531,10 @@ exports.getCandidates = getCandidates;
1510
1531
  exports.getConfiguration = getConfiguration;
1511
1532
  exports.getDelayedTransitions = getDelayedTransitions;
1512
1533
  exports.getInitialConfiguration = getInitialConfiguration;
1534
+ exports.getInitialStateNodes = getInitialStateNodes;
1513
1535
  exports.getPersistedState = getPersistedState;
1514
1536
  exports.getStateNodeByPath = getStateNodeByPath;
1515
1537
  exports.getStateNodes = getStateNodes;
1516
- exports.isAtomicStateNode = isAtomicStateNode;
1517
1538
  exports.isInFinalState = isInFinalState;
1518
1539
  exports.isStateId = isStateId;
1519
1540
  exports.macrostep = macrostep;