xstate 6.0.0-alpha.21 → 6.0.0-alpha.22

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 (40) hide show
  1. package/dist/{StateMachine-550ff7f2.development.cjs.js → StateMachine-1888d034.development.cjs.js} +178 -27
  2. package/dist/{StateMachine-1b155670.cjs.js → StateMachine-610fe929.cjs.js} +178 -27
  3. package/dist/{StateMachine-e25dd61f.development.esm.js → StateMachine-9fad7a2b.development.esm.js} +174 -28
  4. package/dist/{StateMachine-3c17fe3e.esm.js → StateMachine-ddb5d007.esm.js} +174 -28
  5. package/dist/declarations/src/State.d.ts +4 -2
  6. package/dist/declarations/src/StateMachine.d.ts +5 -4
  7. package/dist/declarations/src/actions.d.ts +10 -8
  8. package/dist/declarations/src/actors/logic.d.ts +5 -21
  9. package/dist/declarations/src/createActor.d.ts +3 -1
  10. package/dist/declarations/src/fsm.d.ts +3 -1
  11. package/dist/declarations/src/index.d.ts +2 -2
  12. package/dist/declarations/src/stateUtils.d.ts +1 -1
  13. package/dist/declarations/src/system.d.ts +34 -9
  14. package/dist/declarations/src/transitionActions.d.ts +5 -1
  15. package/dist/declarations/src/types.d.ts +70 -51
  16. package/dist/{index-3f87408c.esm.js → index-2fe11873.esm.js} +782 -389
  17. package/dist/{index-ec7c7a2d.development.cjs.js → index-41c0375c.development.cjs.js} +790 -390
  18. package/dist/{index-e694228c.cjs.js → index-434fac23.cjs.js} +789 -389
  19. package/dist/{index-d39fb138.development.esm.js → index-44d8c2d1.development.esm.js} +783 -390
  20. package/dist/xstate-actors.cjs.js +1 -1
  21. package/dist/xstate-actors.development.cjs.js +1 -1
  22. package/dist/xstate-actors.development.esm.js +1 -1
  23. package/dist/xstate-actors.esm.js +1 -1
  24. package/dist/xstate-actors.umd.min.js +1 -1
  25. package/dist/xstate-actors.umd.min.js.map +1 -1
  26. package/dist/xstate-graph.cjs.js +2 -2
  27. package/dist/xstate-graph.development.cjs.js +2 -2
  28. package/dist/xstate-graph.development.esm.js +2 -2
  29. package/dist/xstate-graph.esm.js +2 -2
  30. package/dist/xstate-graph.umd.min.js +1 -1
  31. package/dist/xstate-graph.umd.min.js.map +1 -1
  32. package/dist/xstate.cjs.js +82 -101
  33. package/dist/xstate.cjs.mjs +1 -0
  34. package/dist/xstate.development.cjs.js +82 -101
  35. package/dist/xstate.development.cjs.mjs +1 -0
  36. package/dist/xstate.development.esm.js +80 -100
  37. package/dist/xstate.esm.js +80 -100
  38. package/dist/xstate.umd.min.js +1 -1
  39. package/dist/xstate.umd.min.js.map +1 -1
  40. package/package.json +1 -1
@@ -1,4 +1,4 @@
1
- import { P as ProcessingStatus, H as resolveReferencedActor, e as createActor, S as STATE_DELIMITER, I as mapValues, t as toArray, J as createInvokeId, K as getDelayedTransitions, L as evaluateCandidate, M as formatTransition, N as NULL_EVENT, O as toTransitionConfigArray, Q as createInvokeTimeoutEvent, R as getCandidates, U as formatRouteTransitions, V as resolveStateValue, W as getAllStateNodes, l as getStateNodes, Y as createMachineSnapshot, Z as isInFinalState, f as macrostep, d as deriveDeferredStarts, _ as cloneMachineSnapshot, $ as transitionNode, m as matchesEventDescriptor, a0 as getTransitionResult, a1 as hasEffect, a2 as createErrorPlatformEvent, r as resolveActionsWithContext, g as createInitEvent, h as initialMicrostep, a3 as toStatePath, a4 as isStateId, a5 as getStateNodeByPath, a6 as getPersistedSnapshot, a7 as $$ACTOR_TYPE } from './index-d39fb138.development.esm.js';
1
+ import { M as resolveReferencedActor, N as setSnapshotActorRef, O as getSnapshotActorRef, P as createSnapshotSystem, q as isMachineSnapshot, h as createActor, S as STATE_DELIMITER, Q as mapValues, t as toArray, R as createInvokeId, U as getDelayedTransitions, V as evaluateCandidate, W as formatTransition, Y as NULL_EVENT, Z as toTransitionConfigArray, _ as createInvokeTimeoutEvent, $ as getCandidates, a0 as formatRouteTransitions, a1 as resolveStateValue, a2 as getAllStateNodes, s as getStateNodes, a3 as createMachineSnapshot, a4 as isInFinalState, j as macrostep, a5 as cloneMachineSnapshot, a6 as transitionNode, e as XSTATE_TIMER, m as matchesEventDescriptor, a7 as getTransitionResult, a8 as hasEffect, a9 as createErrorPlatformEvent, r as resolveActionsWithContext, k as createInitEvent, l as createSpawnEffect, n as initialMicrostep, aa as toStatePath, ab as isStateId, ac as getStateNodeByPath, ad as getPersistedSnapshot, ae as $$ACTOR_TYPE } from './index-44d8c2d1.development.esm.js';
2
2
 
3
3
  function createSpawner(actorScope, {
4
4
  machine,
@@ -10,7 +10,7 @@ function createSpawner(actorScope, {
10
10
  if (!logic) {
11
11
  throw new Error(`Actor logic '${src}' not implemented in machine '${machine.id}'`);
12
12
  }
13
- const actor = createActor(logic, {
13
+ const actor = actorScope.system.createActorRef(logic, {
14
14
  id: options?.id,
15
15
  parent: actorScope.self,
16
16
  syncSnapshot: options?.syncSnapshot,
@@ -25,7 +25,7 @@ function createSpawner(actorScope, {
25
25
  spawnedChildren[actor.id] = actor;
26
26
  return actor;
27
27
  } else {
28
- const actor = createActor(src, {
28
+ const actor = actorScope.system.createActorRef(src, {
29
29
  id: options?.id,
30
30
  parent: actorScope.self,
31
31
  syncSnapshot: options?.syncSnapshot,
@@ -39,16 +39,114 @@ function createSpawner(actorScope, {
39
39
  return (src, options) => {
40
40
  const actor = spawn(src, options); // TODO: fix types
41
41
  spawnedChildren[actor.id] = actor;
42
- actorScope.defer(() => {
43
- if (actor._processingStatus === ProcessingStatus.Stopped) {
44
- return;
45
- }
46
- actor.start();
47
- });
48
42
  return actor;
49
43
  };
50
44
  }
51
45
 
46
+ /** @internal */
47
+ function setInertActorScopeSnapshot(actorScope, snapshot, attachActorRef = true) {
48
+ actorScope.self._snapshot = snapshot;
49
+ if (attachActorRef && snapshot && typeof snapshot === 'object') {
50
+ setSnapshotActorRef(snapshot, actorScope.self);
51
+ }
52
+ return snapshot;
53
+ }
54
+
55
+ /** @internal */
56
+ function isInertActorScope(actorScope) {
57
+ return !!actorScope.self.options?._inert;
58
+ }
59
+
60
+ /** @internal */
61
+ function attachSnapshotActorRef(actorLogic, actorScope, snapshot) {
62
+ const snapshotScope = createInertActorScope(actorLogic, snapshot, actorScope.self);
63
+ return setInertActorScopeSnapshot(snapshotScope, snapshot);
64
+ }
65
+
66
+ /** @internal */
67
+ function createInertActorScope(actorLogic, snapshot, sourceSelf) {
68
+ const snapshotRef = snapshot ? getSnapshotActorRef(snapshot) : undefined;
69
+ const previousSelf = sourceSelf ?? snapshotRef?.actor;
70
+ const baseSystem = previousSelf?.system;
71
+ const system = previousSelf && baseSystem ? createSnapshotSystem(baseSystem, previousSelf, isMachineSnapshot(snapshot) ? snapshot.children : {}, sourceSelf ? undefined : snapshotRef?.systemState) : undefined;
72
+ const self = createActor(actorLogic, {
73
+ _inert: true,
74
+ ...(previousSelf ? {
75
+ id: previousSelf.id
76
+ } : {}),
77
+ ...(system ? {
78
+ _systemRef: {
79
+ current: system
80
+ }
81
+ } : {})
82
+ });
83
+ if (previousSelf?._parent) {
84
+ self._parent = previousSelf._parent;
85
+ }
86
+ if (snapshot) {
87
+ self._snapshot = snapshot;
88
+ }
89
+ const actorScope = {
90
+ self: self,
91
+ defer: () => {},
92
+ id: self.id,
93
+ logger: self.system._logger,
94
+ sessionId: self.sessionId,
95
+ stopChild: child => child._stop(),
96
+ system: self.system,
97
+ emit: event => self.system.emitEvent(self, event),
98
+ actionExecutor: () => {}
99
+ };
100
+ return actorScope;
101
+ }
102
+
103
+ /** @deprecated Use `initialTransition(…)` instead. */
104
+ function getInitialSnapshot(actorLogic, ...[input]) {
105
+ const actorScope = createInertActorScope(actorLogic);
106
+ return actorLogic.initialTransition(input, actorScope)[0];
107
+ }
108
+
109
+ /**
110
+ * Determines the next snapshot for the given `actorLogic` based on the given
111
+ * `snapshot` and `event`.
112
+ *
113
+ * If the `snapshot` is `undefined`, the initial snapshot of the `actorLogic` is
114
+ * used.
115
+ *
116
+ * @deprecated Use `transition(…)` instead.
117
+ * @example
118
+ *
119
+ * ```ts
120
+ * import { getNextSnapshot } from 'xstate';
121
+ * import { trafficLightMachine } from './trafficLightMachine.ts';
122
+ *
123
+ * const nextSnapshot = getNextSnapshot(
124
+ * trafficLightMachine, // actor logic
125
+ * undefined, // snapshot (or initial state if undefined)
126
+ * { type: 'TIMER' }
127
+ * ); // event object
128
+ *
129
+ * console.log(nextSnapshot.value);
130
+ * // => 'yellow'
131
+ *
132
+ * const nextSnapshot2 = getNextSnapshot(
133
+ * trafficLightMachine, // actor logic
134
+ * nextSnapshot, // snapshot
135
+ * { type: 'TIMER' }
136
+ * ); // event object
137
+ *
138
+ * console.log(nextSnapshot2.value);
139
+ * // =>'red'
140
+ * ```
141
+ */
142
+ function getNextSnapshot(actorLogic, snapshot, event) {
143
+ const actorScope = createInertActorScope(actorLogic, snapshot);
144
+ const transitionResult = actorLogic.transition(snapshot, event, actorScope);
145
+ const nextSnapshot = Array.isArray(transitionResult) ? transitionResult[0] : transitionResult;
146
+ setInertActorScopeSnapshot(actorScope, nextSnapshot, false);
147
+ return nextSnapshot === snapshot ? nextSnapshot : attachSnapshotActorRef(actorLogic, actorScope, nextSnapshot);
148
+ }
149
+
52
150
  const cache = new WeakMap();
53
151
  function memo(object, key, fn) {
54
152
  let memoizedData = cache.get(object);
@@ -570,19 +668,37 @@ class StateMachine {
570
668
  * @param event The received event
571
669
  */
572
670
  transition(snapshot, event, actorScope) {
573
- const fastSnapshot = this._transitionFast(snapshot, event, actorScope);
671
+ const usesInertScope = !actorScope;
672
+ const resolvedActorScope = actorScope ?? createInertActorScope(this, snapshot);
673
+ if (usesInertScope) {
674
+ setInertActorScopeSnapshot(resolvedActorScope, snapshot, false);
675
+ }
676
+ const fastSnapshot = this._transitionFast(snapshot, event, resolvedActorScope);
574
677
  if (fastSnapshot) {
575
- return [fastSnapshot, []];
678
+ if (usesInertScope) {
679
+ setInertActorScopeSnapshot(resolvedActorScope, fastSnapshot, false);
680
+ }
681
+ const returnedSnapshot = usesInertScope && fastSnapshot !== snapshot ? attachSnapshotActorRef(this, resolvedActorScope, fastSnapshot) : this._attachPureActorRef(fastSnapshot, resolvedActorScope);
682
+ return [returnedSnapshot, []];
576
683
  }
577
684
  const {
578
685
  snapshot: nextSnapshot,
579
686
  microsteps
580
- } = macrostep(snapshot, event, actorScope, []);
581
- return [nextSnapshot, this._collectEffects(microsteps)];
687
+ } = macrostep(snapshot, event, resolvedActorScope, []);
688
+ if (usesInertScope) {
689
+ setInertActorScopeSnapshot(resolvedActorScope, nextSnapshot, false);
690
+ }
691
+ const returnedSnapshot = usesInertScope ? nextSnapshot === snapshot ? nextSnapshot : attachSnapshotActorRef(this, resolvedActorScope, nextSnapshot) : this._attachPureActorRef(nextSnapshot, resolvedActorScope);
692
+ return [returnedSnapshot, this._collectEffects(microsteps)];
693
+ }
694
+ _collectEffects(microsteps) {
695
+ return microsteps.flatMap(([, actions]) => actions);
582
696
  }
583
- _collectEffects(microsteps, initialActions = []) {
584
- const effects = [...initialActions, ...microsteps.flatMap(([, actions]) => actions)];
585
- return [...effects, ...deriveDeferredStarts(effects)];
697
+ _attachPureActorRef(snapshot, actorScope) {
698
+ if (isInertActorScope(actorScope)) {
699
+ return snapshot;
700
+ }
701
+ return attachSnapshotActorRef(this, actorScope, snapshot);
586
702
  }
587
703
  _transitionFast(snapshot, event, actorScope) {
588
704
  if (snapshot.status !== 'active' || typeof snapshot.value !== 'string' || this.root.always?.length) {
@@ -643,6 +759,9 @@ class StateMachine {
643
759
  return transitionNode(this.root, snapshot.value, snapshot, event, self) || [];
644
760
  }
645
761
  isInternalEventType(eventType) {
762
+ if (eventType === XSTATE_TIMER) {
763
+ return true;
764
+ }
646
765
  for (const descriptor of this.internalEventDescriptors) {
647
766
  if (matchesEventDescriptor(eventType, descriptor)) {
648
767
  return true;
@@ -709,7 +828,7 @@ class StateMachine {
709
828
  _nodes: [this.root],
710
829
  children: {},
711
830
  status: 'active'
712
- }, this);
831
+ }, this, actorScope.self);
713
832
  if (typeof context === 'function') {
714
833
  const children = {};
715
834
  const spawn = createSpawner(actorScope, preInitial, initEvent, children);
@@ -742,30 +861,37 @@ class StateMachine {
742
861
  return this.initialTransition(input, actorScope)[0];
743
862
  }
744
863
  initialTransition(input, actorScope) {
864
+ const usesInertScope = !actorScope;
865
+ const resolvedActorScope = actorScope ?? createInertActorScope(this);
745
866
  const initEvent = createInitEvent(input); // TODO: fix;
746
867
  const internalQueue = [];
747
- const preInitialState = this._getPreInitialState(actorScope, initEvent);
868
+ const preInitialState = this._getPreInitialState(resolvedActorScope, initEvent);
869
+ const contextSpawnEffects = Object.values(preInitialState.children).filter(Boolean).map(actor => createSpawnEffect(actor));
748
870
  let nextState;
749
871
  let initialActions = [];
750
872
  let microsteps = [];
751
873
  let macroState;
752
874
  try {
753
- [nextState, initialActions] = initialMicrostep(this.root, preInitialState, actorScope, initEvent, internalQueue);
875
+ [nextState, initialActions] = initialMicrostep(this.root, preInitialState, resolvedActorScope, initEvent, internalQueue);
754
876
  ({
755
877
  snapshot: macroState,
756
878
  microsteps
757
- } = macrostep(nextState, initEvent, actorScope, internalQueue));
879
+ } = macrostep(nextState, initEvent, resolvedActorScope, internalQueue, [[nextState, [...contextSpawnEffects, ...initialActions]]]));
758
880
  } catch (err) {
759
881
  if (!this.root.config.onError) {
760
882
  throw err;
761
883
  }
762
884
  const errorEvent = createErrorPlatformEvent('execution', err);
763
- const errorMacrostep = macrostep(preInitialState, errorEvent, actorScope, []);
885
+ const errorMacrostep = macrostep(preInitialState, errorEvent, resolvedActorScope, [], [[preInitialState, contextSpawnEffects]]);
764
886
  macroState = errorMacrostep.snapshot;
765
887
  microsteps = errorMacrostep.microsteps;
766
888
  initialActions = [];
767
889
  }
768
- return [macroState, this._collectEffects(microsteps, initialActions)];
890
+ if (usesInertScope) {
891
+ setInertActorScopeSnapshot(resolvedActorScope, macroState, false);
892
+ }
893
+ const returnedSnapshot = usesInertScope ? attachSnapshotActorRef(this, resolvedActorScope, macroState) : this._attachPureActorRef(macroState, resolvedActorScope);
894
+ return [returnedSnapshot, this._collectEffects(microsteps)];
769
895
  }
770
896
  start(snapshot) {
771
897
  // Start rehydrated children that were active when persisted. Freshly
@@ -793,7 +919,9 @@ class StateMachine {
793
919
  getPersistedSnapshot(snapshot, options) {
794
920
  return getPersistedSnapshot(snapshot, options);
795
921
  }
796
- restoreSnapshot(snapshot, _actorScope) {
922
+ restoreSnapshot(snapshot, actorScope) {
923
+ const usesInertScope = !actorScope;
924
+ const resolvedActorScope = actorScope ?? createInertActorScope(this);
797
925
  const persistedVersion = snapshot.version;
798
926
  if (persistedVersion !== this.version) {
799
927
  const migrate = this.config.migrate;
@@ -813,9 +941,9 @@ class StateMachine {
813
941
  if (!logic) {
814
942
  continue;
815
943
  }
816
- const actor = createActor(logic, {
944
+ const actor = resolvedActorScope.system.createActorRef(logic, {
817
945
  id: actorId,
818
- parent: _actorScope.self,
946
+ parent: resolvedActorScope.self,
819
947
  syncSnapshot: actorData.syncSnapshot,
820
948
  snapshot: childState,
821
949
  src,
@@ -826,6 +954,19 @@ class StateMachine {
826
954
  actor._rehydrated = true;
827
955
  children[actorId] = actor;
828
956
  }
957
+ const timers = {};
958
+ const persistedTimers = snapshotData.timers ?? {};
959
+ for (const [id, timer] of Object.entries(persistedTimers)) {
960
+ const target = typeof timer.target === 'string' ? timer.target === 'self' ? 'self' : children[timer.target] : resolvedActorScope.self._parent;
961
+ if (!target) {
962
+ const targetDescription = typeof timer.target === 'string' ? timer.target : timer.target.type;
963
+ throw new Error(`Unable to restore timer '${id}': target actor '${targetDescription}' is unavailable.`);
964
+ }
965
+ timers[id] = {
966
+ ...timer,
967
+ target
968
+ };
969
+ }
829
970
  const reviveHistoryValue = historyValue => {
830
971
  if (!historyValue || typeof historyValue !== 'object') {
831
972
  return {};
@@ -864,11 +1005,12 @@ class StateMachine {
864
1005
  const restoredSnapshot = createMachineSnapshot({
865
1006
  ...persistedRest,
866
1007
  children,
1008
+ timers,
867
1009
  _nodes: nodes,
868
1010
  value: snapshotData.value,
869
1011
  historyValue: revivedHistoryValue,
870
1012
  _stateInputs: snapshotData.stateInputs ?? {}
871
- }, this);
1013
+ }, this, resolvedActorScope.self);
872
1014
  const seen = new WeakSet();
873
1015
  function reviveContext(contextPart) {
874
1016
  if (seen.has(contextPart)) {
@@ -887,8 +1029,12 @@ class StateMachine {
887
1029
  }
888
1030
  }
889
1031
  reviveContext(restoredSnapshot.context);
890
- return restoredSnapshot;
1032
+ if (usesInertScope) {
1033
+ setInertActorScopeSnapshot(resolvedActorScope, restoredSnapshot, false);
1034
+ return attachSnapshotActorRef(this, resolvedActorScope, restoredSnapshot);
1035
+ }
1036
+ return this._attachPureActorRef(restoredSnapshot, resolvedActorScope);
891
1037
  }
892
1038
  }
893
1039
 
894
- export { StateMachine as S, StateNode as a };
1040
+ export { StateMachine as S, attachSnapshotActorRef as a, getNextSnapshot as b, createInertActorScope as c, StateNode as d, getInitialSnapshot as g, setInertActorScopeSnapshot as s };
@@ -1,4 +1,4 @@
1
- import { P as ProcessingStatus, H as resolveReferencedActor, e as createActor, S as STATE_DELIMITER, I as mapValues, t as toArray, J as createInvokeId, K as getDelayedTransitions, L as evaluateCandidate, M as formatTransition, N as NULL_EVENT, O as toTransitionConfigArray, Q as createInvokeTimeoutEvent, R as getCandidates, U as formatRouteTransitions, V as resolveStateValue, W as getAllStateNodes, l as getStateNodes, Y as createMachineSnapshot, Z as isInFinalState, f as macrostep, d as deriveDeferredStarts, _ as cloneMachineSnapshot, $ as transitionNode, m as matchesEventDescriptor, a0 as getTransitionResult, a1 as hasEffect, a2 as createErrorPlatformEvent, r as resolveActionsWithContext, g as createInitEvent, h as initialMicrostep, a3 as toStatePath, a4 as isStateId, a5 as getStateNodeByPath, a6 as getPersistedSnapshot, a7 as $$ACTOR_TYPE } from './index-3f87408c.esm.js';
1
+ import { M as resolveReferencedActor, N as setSnapshotActorRef, O as getSnapshotActorRef, P as createSnapshotSystem, q as isMachineSnapshot, h as createActor, S as STATE_DELIMITER, Q as mapValues, t as toArray, R as createInvokeId, U as getDelayedTransitions, V as evaluateCandidate, W as formatTransition, Y as NULL_EVENT, Z as toTransitionConfigArray, _ as createInvokeTimeoutEvent, $ as getCandidates, a0 as formatRouteTransitions, a1 as resolveStateValue, a2 as getAllStateNodes, s as getStateNodes, a3 as createMachineSnapshot, a4 as isInFinalState, j as macrostep, a5 as cloneMachineSnapshot, a6 as transitionNode, e as XSTATE_TIMER, m as matchesEventDescriptor, a7 as getTransitionResult, a8 as hasEffect, a9 as createErrorPlatformEvent, r as resolveActionsWithContext, k as createInitEvent, l as createSpawnEffect, n as initialMicrostep, aa as toStatePath, ab as isStateId, ac as getStateNodeByPath, ad as getPersistedSnapshot, ae as $$ACTOR_TYPE } from './index-2fe11873.esm.js';
2
2
 
3
3
  function createSpawner(actorScope, {
4
4
  machine,
@@ -10,7 +10,7 @@ function createSpawner(actorScope, {
10
10
  if (!logic) {
11
11
  throw new Error(`Actor logic '${src}' not implemented in machine '${machine.id}'`);
12
12
  }
13
- const actor = createActor(logic, {
13
+ const actor = actorScope.system.createActorRef(logic, {
14
14
  id: options?.id,
15
15
  parent: actorScope.self,
16
16
  syncSnapshot: options?.syncSnapshot,
@@ -25,7 +25,7 @@ function createSpawner(actorScope, {
25
25
  spawnedChildren[actor.id] = actor;
26
26
  return actor;
27
27
  } else {
28
- const actor = createActor(src, {
28
+ const actor = actorScope.system.createActorRef(src, {
29
29
  id: options?.id,
30
30
  parent: actorScope.self,
31
31
  syncSnapshot: options?.syncSnapshot,
@@ -39,16 +39,114 @@ function createSpawner(actorScope, {
39
39
  return (src, options) => {
40
40
  const actor = spawn(src, options); // TODO: fix types
41
41
  spawnedChildren[actor.id] = actor;
42
- actorScope.defer(() => {
43
- if (actor._processingStatus === ProcessingStatus.Stopped) {
44
- return;
45
- }
46
- actor.start();
47
- });
48
42
  return actor;
49
43
  };
50
44
  }
51
45
 
46
+ /** @internal */
47
+ function setInertActorScopeSnapshot(actorScope, snapshot, attachActorRef = true) {
48
+ actorScope.self._snapshot = snapshot;
49
+ if (attachActorRef && snapshot && typeof snapshot === 'object') {
50
+ setSnapshotActorRef(snapshot, actorScope.self);
51
+ }
52
+ return snapshot;
53
+ }
54
+
55
+ /** @internal */
56
+ function isInertActorScope(actorScope) {
57
+ return !!actorScope.self.options?._inert;
58
+ }
59
+
60
+ /** @internal */
61
+ function attachSnapshotActorRef(actorLogic, actorScope, snapshot) {
62
+ const snapshotScope = createInertActorScope(actorLogic, snapshot, actorScope.self);
63
+ return setInertActorScopeSnapshot(snapshotScope, snapshot);
64
+ }
65
+
66
+ /** @internal */
67
+ function createInertActorScope(actorLogic, snapshot, sourceSelf) {
68
+ const snapshotRef = snapshot ? getSnapshotActorRef(snapshot) : undefined;
69
+ const previousSelf = sourceSelf ?? snapshotRef?.actor;
70
+ const baseSystem = previousSelf?.system;
71
+ const system = previousSelf && baseSystem ? createSnapshotSystem(baseSystem, previousSelf, isMachineSnapshot(snapshot) ? snapshot.children : {}, sourceSelf ? undefined : snapshotRef?.systemState) : undefined;
72
+ const self = createActor(actorLogic, {
73
+ _inert: true,
74
+ ...(previousSelf ? {
75
+ id: previousSelf.id
76
+ } : {}),
77
+ ...(system ? {
78
+ _systemRef: {
79
+ current: system
80
+ }
81
+ } : {})
82
+ });
83
+ if (previousSelf?._parent) {
84
+ self._parent = previousSelf._parent;
85
+ }
86
+ if (snapshot) {
87
+ self._snapshot = snapshot;
88
+ }
89
+ const actorScope = {
90
+ self: self,
91
+ defer: () => {},
92
+ id: self.id,
93
+ logger: self.system._logger,
94
+ sessionId: self.sessionId,
95
+ stopChild: child => child._stop(),
96
+ system: self.system,
97
+ emit: event => self.system.emitEvent(self, event),
98
+ actionExecutor: () => {}
99
+ };
100
+ return actorScope;
101
+ }
102
+
103
+ /** @deprecated Use `initialTransition(…)` instead. */
104
+ function getInitialSnapshot(actorLogic, ...[input]) {
105
+ const actorScope = createInertActorScope(actorLogic);
106
+ return actorLogic.initialTransition(input, actorScope)[0];
107
+ }
108
+
109
+ /**
110
+ * Determines the next snapshot for the given `actorLogic` based on the given
111
+ * `snapshot` and `event`.
112
+ *
113
+ * If the `snapshot` is `undefined`, the initial snapshot of the `actorLogic` is
114
+ * used.
115
+ *
116
+ * @deprecated Use `transition(…)` instead.
117
+ * @example
118
+ *
119
+ * ```ts
120
+ * import { getNextSnapshot } from 'xstate';
121
+ * import { trafficLightMachine } from './trafficLightMachine.ts';
122
+ *
123
+ * const nextSnapshot = getNextSnapshot(
124
+ * trafficLightMachine, // actor logic
125
+ * undefined, // snapshot (or initial state if undefined)
126
+ * { type: 'TIMER' }
127
+ * ); // event object
128
+ *
129
+ * console.log(nextSnapshot.value);
130
+ * // => 'yellow'
131
+ *
132
+ * const nextSnapshot2 = getNextSnapshot(
133
+ * trafficLightMachine, // actor logic
134
+ * nextSnapshot, // snapshot
135
+ * { type: 'TIMER' }
136
+ * ); // event object
137
+ *
138
+ * console.log(nextSnapshot2.value);
139
+ * // =>'red'
140
+ * ```
141
+ */
142
+ function getNextSnapshot(actorLogic, snapshot, event) {
143
+ const actorScope = createInertActorScope(actorLogic, snapshot);
144
+ const transitionResult = actorLogic.transition(snapshot, event, actorScope);
145
+ const nextSnapshot = Array.isArray(transitionResult) ? transitionResult[0] : transitionResult;
146
+ setInertActorScopeSnapshot(actorScope, nextSnapshot, false);
147
+ return nextSnapshot === snapshot ? nextSnapshot : attachSnapshotActorRef(actorLogic, actorScope, nextSnapshot);
148
+ }
149
+
52
150
  const cache = new WeakMap();
53
151
  function memo(object, key, fn) {
54
152
  let memoizedData = cache.get(object);
@@ -541,19 +639,37 @@ class StateMachine {
541
639
  * @param event The received event
542
640
  */
543
641
  transition(snapshot, event, actorScope) {
544
- const fastSnapshot = this._transitionFast(snapshot, event, actorScope);
642
+ const usesInertScope = !actorScope;
643
+ const resolvedActorScope = actorScope ?? createInertActorScope(this, snapshot);
644
+ if (usesInertScope) {
645
+ setInertActorScopeSnapshot(resolvedActorScope, snapshot, false);
646
+ }
647
+ const fastSnapshot = this._transitionFast(snapshot, event, resolvedActorScope);
545
648
  if (fastSnapshot) {
546
- return [fastSnapshot, []];
649
+ if (usesInertScope) {
650
+ setInertActorScopeSnapshot(resolvedActorScope, fastSnapshot, false);
651
+ }
652
+ const returnedSnapshot = usesInertScope && fastSnapshot !== snapshot ? attachSnapshotActorRef(this, resolvedActorScope, fastSnapshot) : this._attachPureActorRef(fastSnapshot, resolvedActorScope);
653
+ return [returnedSnapshot, []];
547
654
  }
548
655
  const {
549
656
  snapshot: nextSnapshot,
550
657
  microsteps
551
- } = macrostep(snapshot, event, actorScope, []);
552
- return [nextSnapshot, this._collectEffects(microsteps)];
658
+ } = macrostep(snapshot, event, resolvedActorScope, []);
659
+ if (usesInertScope) {
660
+ setInertActorScopeSnapshot(resolvedActorScope, nextSnapshot, false);
661
+ }
662
+ const returnedSnapshot = usesInertScope ? nextSnapshot === snapshot ? nextSnapshot : attachSnapshotActorRef(this, resolvedActorScope, nextSnapshot) : this._attachPureActorRef(nextSnapshot, resolvedActorScope);
663
+ return [returnedSnapshot, this._collectEffects(microsteps)];
664
+ }
665
+ _collectEffects(microsteps) {
666
+ return microsteps.flatMap(([, actions]) => actions);
553
667
  }
554
- _collectEffects(microsteps, initialActions = []) {
555
- const effects = [...initialActions, ...microsteps.flatMap(([, actions]) => actions)];
556
- return [...effects, ...deriveDeferredStarts(effects)];
668
+ _attachPureActorRef(snapshot, actorScope) {
669
+ if (isInertActorScope(actorScope)) {
670
+ return snapshot;
671
+ }
672
+ return attachSnapshotActorRef(this, actorScope, snapshot);
557
673
  }
558
674
  _transitionFast(snapshot, event, actorScope) {
559
675
  if (snapshot.status !== 'active' || typeof snapshot.value !== 'string' || this.root.always?.length) {
@@ -614,6 +730,9 @@ class StateMachine {
614
730
  return transitionNode(this.root, snapshot.value, snapshot, event, self) || [];
615
731
  }
616
732
  isInternalEventType(eventType) {
733
+ if (eventType === XSTATE_TIMER) {
734
+ return true;
735
+ }
617
736
  for (const descriptor of this.internalEventDescriptors) {
618
737
  if (matchesEventDescriptor(eventType, descriptor)) {
619
738
  return true;
@@ -680,7 +799,7 @@ class StateMachine {
680
799
  _nodes: [this.root],
681
800
  children: {},
682
801
  status: 'active'
683
- }, this);
802
+ }, this, actorScope.self);
684
803
  if (typeof context === 'function') {
685
804
  const children = {};
686
805
  const spawn = createSpawner(actorScope, preInitial, initEvent, children);
@@ -713,30 +832,37 @@ class StateMachine {
713
832
  return this.initialTransition(input, actorScope)[0];
714
833
  }
715
834
  initialTransition(input, actorScope) {
835
+ const usesInertScope = !actorScope;
836
+ const resolvedActorScope = actorScope ?? createInertActorScope(this);
716
837
  const initEvent = createInitEvent(input); // TODO: fix;
717
838
  const internalQueue = [];
718
- const preInitialState = this._getPreInitialState(actorScope, initEvent);
839
+ const preInitialState = this._getPreInitialState(resolvedActorScope, initEvent);
840
+ const contextSpawnEffects = Object.values(preInitialState.children).filter(Boolean).map(actor => createSpawnEffect(actor));
719
841
  let nextState;
720
842
  let initialActions = [];
721
843
  let microsteps = [];
722
844
  let macroState;
723
845
  try {
724
- [nextState, initialActions] = initialMicrostep(this.root, preInitialState, actorScope, initEvent, internalQueue);
846
+ [nextState, initialActions] = initialMicrostep(this.root, preInitialState, resolvedActorScope, initEvent, internalQueue);
725
847
  ({
726
848
  snapshot: macroState,
727
849
  microsteps
728
- } = macrostep(nextState, initEvent, actorScope, internalQueue));
850
+ } = macrostep(nextState, initEvent, resolvedActorScope, internalQueue, [[nextState, [...contextSpawnEffects, ...initialActions]]]));
729
851
  } catch (err) {
730
852
  if (!this.root.config.onError) {
731
853
  throw err;
732
854
  }
733
855
  const errorEvent = createErrorPlatformEvent('execution', err);
734
- const errorMacrostep = macrostep(preInitialState, errorEvent, actorScope, []);
856
+ const errorMacrostep = macrostep(preInitialState, errorEvent, resolvedActorScope, [], [[preInitialState, contextSpawnEffects]]);
735
857
  macroState = errorMacrostep.snapshot;
736
858
  microsteps = errorMacrostep.microsteps;
737
859
  initialActions = [];
738
860
  }
739
- return [macroState, this._collectEffects(microsteps, initialActions)];
861
+ if (usesInertScope) {
862
+ setInertActorScopeSnapshot(resolvedActorScope, macroState, false);
863
+ }
864
+ const returnedSnapshot = usesInertScope ? attachSnapshotActorRef(this, resolvedActorScope, macroState) : this._attachPureActorRef(macroState, resolvedActorScope);
865
+ return [returnedSnapshot, this._collectEffects(microsteps)];
740
866
  }
741
867
  start(snapshot) {
742
868
  // Start rehydrated children that were active when persisted. Freshly
@@ -764,7 +890,9 @@ class StateMachine {
764
890
  getPersistedSnapshot(snapshot, options) {
765
891
  return getPersistedSnapshot(snapshot, options);
766
892
  }
767
- restoreSnapshot(snapshot, _actorScope) {
893
+ restoreSnapshot(snapshot, actorScope) {
894
+ const usesInertScope = !actorScope;
895
+ const resolvedActorScope = actorScope ?? createInertActorScope(this);
768
896
  const persistedVersion = snapshot.version;
769
897
  if (persistedVersion !== this.version) {
770
898
  const migrate = this.config.migrate;
@@ -784,9 +912,9 @@ class StateMachine {
784
912
  if (!logic) {
785
913
  continue;
786
914
  }
787
- const actor = createActor(logic, {
915
+ const actor = resolvedActorScope.system.createActorRef(logic, {
788
916
  id: actorId,
789
- parent: _actorScope.self,
917
+ parent: resolvedActorScope.self,
790
918
  syncSnapshot: actorData.syncSnapshot,
791
919
  snapshot: childState,
792
920
  src,
@@ -797,6 +925,19 @@ class StateMachine {
797
925
  actor._rehydrated = true;
798
926
  children[actorId] = actor;
799
927
  }
928
+ const timers = {};
929
+ const persistedTimers = snapshotData.timers ?? {};
930
+ for (const [id, timer] of Object.entries(persistedTimers)) {
931
+ const target = typeof timer.target === 'string' ? timer.target === 'self' ? 'self' : children[timer.target] : resolvedActorScope.self._parent;
932
+ if (!target) {
933
+ const targetDescription = typeof timer.target === 'string' ? timer.target : timer.target.type;
934
+ throw new Error(`Unable to restore timer '${id}': target actor '${targetDescription}' is unavailable.`);
935
+ }
936
+ timers[id] = {
937
+ ...timer,
938
+ target
939
+ };
940
+ }
800
941
  const reviveHistoryValue = historyValue => {
801
942
  if (!historyValue || typeof historyValue !== 'object') {
802
943
  return {};
@@ -832,11 +973,12 @@ class StateMachine {
832
973
  const restoredSnapshot = createMachineSnapshot({
833
974
  ...persistedRest,
834
975
  children,
976
+ timers,
835
977
  _nodes: nodes,
836
978
  value: snapshotData.value,
837
979
  historyValue: revivedHistoryValue,
838
980
  _stateInputs: snapshotData.stateInputs ?? {}
839
- }, this);
981
+ }, this, resolvedActorScope.self);
840
982
  const seen = new WeakSet();
841
983
  function reviveContext(contextPart) {
842
984
  if (seen.has(contextPart)) {
@@ -855,8 +997,12 @@ class StateMachine {
855
997
  }
856
998
  }
857
999
  reviveContext(restoredSnapshot.context);
858
- return restoredSnapshot;
1000
+ if (usesInertScope) {
1001
+ setInertActorScopeSnapshot(resolvedActorScope, restoredSnapshot, false);
1002
+ return attachSnapshotActorRef(this, resolvedActorScope, restoredSnapshot);
1003
+ }
1004
+ return this._attachPureActorRef(restoredSnapshot, resolvedActorScope);
859
1005
  }
860
1006
  }
861
1007
 
862
- export { StateMachine as S, StateNode as a };
1008
+ export { StateMachine as S, attachSnapshotActorRef as a, getNextSnapshot as b, createInertActorScope as c, StateNode as d, getInitialSnapshot as g, setInertActorScopeSnapshot as s };
@@ -1,4 +1,4 @@
1
- import type { AnyMachineSnapshot, AnyStateMachine, EventObject, HistoryValue, MachineContext, StateConfig, StateValue, StateValueMap, AnyActorRef, Snapshot, MetaObject, StateSchema, StateId, StateIdInputs, StateContextFromStateValue, SnapshotStatus, AnyStateNode } from "./types.js";
1
+ import type { AnyMachineSnapshot, AnyStateMachine, AnyActor, EventObject, HistoryValue, MachineContext, StateConfig, StateValue, StateValueMap, AnyActorRef, Snapshot, MetaObject, StateSchema, StateId, StateIdInputs, StateContextFromStateValue, SnapshotStatus, AnyStateNode, LogicalTimer } from "./types.js";
2
2
  export declare function isMachineSnapshot(value: unknown): value is AnyMachineSnapshot;
3
3
  type Values<T> = T[keyof T];
4
4
  type MatchingObjectStateValue<TStateValue extends Record<string, unknown>, TTestStateValue extends Record<string, unknown>> = false extends Values<{
@@ -45,6 +45,8 @@ interface MachineSnapshotBase<TContext extends MachineContext, TEvent extends Ev
45
45
  _nodes: Array<AnyStateNode>;
46
46
  /** An object mapping actor names to spawned/invoked actors. */
47
47
  children: TChildren;
48
+ /** Pending logical timers owned by this machine snapshot. */
49
+ timers: Readonly<Record<string, LogicalTimer>>;
48
50
  /**
49
51
  * Whether the current state value is a subset of the given partial state
50
52
  * value.
@@ -98,7 +100,7 @@ interface StoppedMachineSnapshot<TContext extends MachineContext, TEvent extends
98
100
  error: undefined;
99
101
  }
100
102
  export type MachineSnapshot<TContext extends MachineContext, TEvent extends EventObject, TChildren extends Record<string, AnyActorRef | undefined>, TStateValue extends StateValue, TTag extends string, TOutput, TMeta extends MetaObject, TStateSchema extends StateSchema> = ActiveMachineSnapshot<TContext, TEvent, TChildren, TStateValue, TTag, TOutput, TMeta, TStateSchema> | DoneMachineSnapshot<TContext, TEvent, TChildren, TStateValue, TTag, TOutput, TMeta, TStateSchema> | ErrorMachineSnapshot<TContext, TEvent, TChildren, TStateValue, TTag, TOutput, TMeta, TStateSchema> | StoppedMachineSnapshot<TContext, TEvent, TChildren, TStateValue, TTag, TOutput, TMeta, TStateSchema>;
101
- export declare function createMachineSnapshot<TContext extends MachineContext, TEvent extends EventObject, TChildren extends Record<string, AnyActorRef | undefined>, TStateValue extends StateValue, TTag extends string, TMeta extends MetaObject, TStateSchema extends StateSchema>(config: StateConfig<TContext, TEvent>, machine: AnyStateMachine): MachineSnapshot<TContext, TEvent, TChildren, TStateValue, TTag, undefined, TMeta, TStateSchema>;
103
+ export declare function createMachineSnapshot<TContext extends MachineContext, TEvent extends EventObject, TChildren extends Record<string, AnyActorRef | undefined>, TStateValue extends StateValue, TTag extends string, TMeta extends MetaObject, TStateSchema extends StateSchema>(config: StateConfig<TContext, TEvent>, machine: AnyStateMachine, actorRef?: AnyActor): MachineSnapshot<TContext, TEvent, TChildren, TStateValue, TTag, undefined, TMeta, TStateSchema>;
102
104
  export declare function cloneMachineSnapshot<TState extends AnyMachineSnapshot>(snapshot: TState, config?: Partial<StateConfig<any, any>>): TState;
103
105
  export declare function getPersistedSnapshot<TContext extends MachineContext, TEvent extends EventObject, TChildren extends Record<string, AnyActorRef | undefined>, TStateValue extends StateValue, TTag extends string, TOutput, TMeta extends MetaObject>(snapshot: MachineSnapshot<TContext, TEvent, TChildren, TStateValue, TTag, TOutput, TMeta, any>, options?: unknown): Snapshot<unknown>;
104
106
  export {};