xstate 6.0.0-alpha.3 → 6.0.0-alpha.32

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 (76) hide show
  1. package/README.md +19 -17
  2. package/bin/xstate.js +36 -0
  3. package/dist/StateMachine-33eec203.development.esm.js +1112 -0
  4. package/dist/StateMachine-d073209c.esm.js +1080 -0
  5. package/dist/StateMachine-d3243bd1.development.cjs.js +1120 -0
  6. package/dist/StateMachine-ff580dd5.cjs.js +1088 -0
  7. package/dist/declarations/src/State.d.ts +16 -3
  8. package/dist/declarations/src/StateMachine.d.ts +30 -16
  9. package/dist/declarations/src/StateNode.d.ts +5 -2
  10. package/dist/declarations/src/actions.d.ts +10 -7
  11. package/dist/declarations/src/actors/callback.d.ts +2 -0
  12. package/dist/declarations/src/actors/logic.d.ts +7 -21
  13. package/dist/declarations/src/actors/observable.d.ts +3 -0
  14. package/dist/declarations/src/actors/promise.d.ts +6 -2
  15. package/dist/declarations/src/createActor.d.ts +21 -14
  16. package/dist/declarations/src/createMachine.d.ts +24 -13
  17. package/dist/declarations/src/createMachineFromConfig.d.ts +64 -30
  18. package/dist/declarations/src/fsm.d.ts +76 -0
  19. package/dist/declarations/src/graph/graph.d.ts +3 -3
  20. package/dist/declarations/src/graph/shortestPaths.d.ts +2 -2
  21. package/dist/declarations/src/graph/simplePaths.d.ts +2 -2
  22. package/dist/declarations/src/index.d.ts +9 -4
  23. package/dist/declarations/src/machineVersions.d.ts +51 -0
  24. package/dist/declarations/src/schema.types.d.ts +5 -0
  25. package/dist/declarations/src/serialize.d.ts +9 -22
  26. package/dist/declarations/src/setup.d.ts +361 -70
  27. package/dist/declarations/src/spawn.d.ts +5 -5
  28. package/dist/declarations/src/stateUtils.d.ts +17 -5
  29. package/dist/declarations/src/system.d.ts +38 -11
  30. package/dist/declarations/src/transition.d.ts +8 -5
  31. package/dist/declarations/src/transitionActions.d.ts +16 -0
  32. package/dist/declarations/src/types.d.ts +346 -144
  33. package/dist/declarations/src/types.v6.d.ts +294 -58
  34. package/dist/declarations/src/utils.d.ts +5 -3
  35. package/dist/declarations/src/validation/index.d.ts +37 -0
  36. package/dist/declarations/src/validation.types.d.ts +22 -0
  37. package/dist/{index-269d256d.development.cjs.js → index-691f27b9.development.cjs.js} +2358 -1116
  38. package/dist/{index-66ff64a6.development.esm.js → index-92227865.development.esm.js} +2335 -1115
  39. package/dist/{index-dda021d5.cjs.js → index-9939f02a.cjs.js} +2356 -1114
  40. package/dist/{index-a7e3d8b3.esm.js → index-ab93831d.esm.js} +2333 -1113
  41. package/dist/xstate-actors.cjs.js +1 -1
  42. package/dist/xstate-actors.development.cjs.js +1 -1
  43. package/dist/xstate-actors.development.esm.js +1 -1
  44. package/dist/xstate-actors.esm.js +1 -1
  45. package/dist/xstate-actors.umd.min.js +1 -1
  46. package/dist/xstate-actors.umd.min.js.map +1 -1
  47. package/dist/xstate-graph.cjs.js +10 -14
  48. package/dist/xstate-graph.development.cjs.js +10 -14
  49. package/dist/xstate-graph.development.esm.js +10 -14
  50. package/dist/xstate-graph.esm.js +10 -14
  51. package/dist/xstate-graph.umd.min.js +1 -1
  52. package/dist/xstate-graph.umd.min.js.map +1 -1
  53. package/dist/xstate-validation.cjs.d.mts +2 -0
  54. package/dist/xstate-validation.cjs.d.ts +2 -0
  55. package/dist/xstate-validation.cjs.js +277 -0
  56. package/dist/xstate-validation.cjs.mjs +5 -0
  57. package/dist/xstate-validation.development.cjs.js +277 -0
  58. package/dist/xstate-validation.development.cjs.mjs +5 -0
  59. package/dist/xstate-validation.development.esm.js +271 -0
  60. package/dist/xstate-validation.esm.js +271 -0
  61. package/dist/xstate-validation.umd.min.js +2 -0
  62. package/dist/xstate-validation.umd.min.js.map +1 -0
  63. package/dist/xstate.cjs.js +1299 -294
  64. package/dist/xstate.cjs.mjs +6 -0
  65. package/dist/xstate.development.cjs.js +1299 -294
  66. package/dist/xstate.development.cjs.mjs +6 -0
  67. package/dist/xstate.development.esm.js +1293 -294
  68. package/dist/xstate.esm.js +1293 -294
  69. package/dist/xstate.umd.min.js +1 -1
  70. package/dist/xstate.umd.min.js.map +1 -1
  71. package/package.json +23 -3
  72. package/validation/package.json +8 -0
  73. package/dist/StateMachine-0770ac71.development.cjs.js +0 -740
  74. package/dist/StateMachine-8249d511.esm.js +0 -720
  75. package/dist/StateMachine-e1048cd6.cjs.js +0 -723
  76. package/dist/StateMachine-e6ad61d0.development.esm.js +0 -737
@@ -0,0 +1,1112 @@
1
+ import { M as setSnapshotActorRef, N as getSnapshotActorRef, O as createSnapshotSystem, q as isMachineSnapshot, h as createActor, S as STATE_DELIMITER, P as mapValues, t as toArray, Q as createInvokeId, R as getDelayedTransitions, U as getEventDescriptorKey, V as getCandidates, W as evaluateCandidate, Y as formatTransition, Z as NULL_EVENT, _ as toTransitionConfigArray, $ as createInvokeTimeoutEventId, a0 as matchesActorSession, a1 as formatRouteTransitions, a2 as resolveStateValue, a3 as getAllStateNodes, s as getStateNodes, a4 as createMachineSnapshot, a5 as isInFinalState, a6 as assertValid, j as macrostep, a7 as cloneMachineSnapshot, a8 as transitionNode, e as XSTATE_TIMER, m as matchesEventDescriptor, a9 as getTransitionResult, aa as hasEffect, ab as createErrorPlatformEvent, r as resolveActionsWithContext, k as createInitEvent, l as createSpawnEffect, n as initialMicrostep, ac as toStatePath, ad as isStateId, ae as getStateNodeByPath, af as getPersistedSnapshot, ag as resolveReferencedActor, ah as createInvokeTimeoutEvent, ai as $$ACTOR_TYPE } from './index-92227865.development.esm.js';
2
+
3
+ function createSpawner(actorScope, actors, spawnedChildren) {
4
+ return (src, options) => {
5
+ const referencedSrc = Object.entries(actors).find(([, logic]) => logic === src)?.[0];
6
+ const actor = actorScope.system.createActorRef(src, {
7
+ id: options?.id,
8
+ parent: actorScope.self,
9
+ syncSnapshot: options?.syncSnapshot,
10
+ input: options?.input,
11
+ src: referencedSrc ?? src,
12
+ registryKey: options?.registryKey
13
+ });
14
+ spawnedChildren[actor.id] = actor;
15
+ return actor;
16
+ };
17
+ }
18
+
19
+ /** @internal */
20
+ function setInertActorScopeSnapshot(actorScope, snapshot, attachActorRef = true) {
21
+ actorScope.self._snapshot = snapshot;
22
+ if (attachActorRef && snapshot && typeof snapshot === 'object') {
23
+ setSnapshotActorRef(snapshot, actorScope.self);
24
+ }
25
+ return snapshot;
26
+ }
27
+
28
+ /** @internal */
29
+ function isInertActorScope(actorScope) {
30
+ return !!actorScope.self.options?._inert;
31
+ }
32
+
33
+ /** @internal */
34
+ function attachSnapshotActorRef(actorLogic, actorScope, snapshot) {
35
+ const snapshotScope = createInertActorScope(actorLogic, snapshot, actorScope.self);
36
+ return setInertActorScopeSnapshot(snapshotScope, snapshot);
37
+ }
38
+
39
+ /** @internal */
40
+ function createInertActorScope(actorLogic, snapshot, sourceSelf) {
41
+ const snapshotRef = snapshot ? getSnapshotActorRef(snapshot) : undefined;
42
+ const previousSelf = sourceSelf ?? snapshotRef?.actor;
43
+ const baseSystem = previousSelf?.system;
44
+ const system = previousSelf && baseSystem ? createSnapshotSystem(baseSystem, isMachineSnapshot(snapshot) ? snapshot.children : {}, sourceSelf ? undefined : snapshotRef?.systemState) : undefined;
45
+ const self = createActor(actorLogic, {
46
+ _inert: true,
47
+ ...(previousSelf ? {
48
+ id: previousSelf.id,
49
+ _sessionId: previousSelf.sessionId
50
+ } : {}),
51
+ ...(system ? {
52
+ _systemRef: {
53
+ current: system
54
+ }
55
+ } : {})
56
+ });
57
+ if (previousSelf?._parent) {
58
+ self._parent = previousSelf._parent;
59
+ }
60
+ if (snapshot) {
61
+ self._snapshot = snapshot;
62
+ }
63
+ const actorScope = {
64
+ self: self,
65
+ defer: () => {},
66
+ id: self.id,
67
+ logger: self.system._logger,
68
+ sessionId: self.sessionId,
69
+ stopChild: child => child._stop(),
70
+ system: self.system,
71
+ emit: event => self.system.emitEvent(self, event),
72
+ actionExecutor: () => {}
73
+ };
74
+ return actorScope;
75
+ }
76
+
77
+ /** @deprecated Use `initialTransition(…)` instead. */
78
+ function getInitialSnapshot(actorLogic, ...[input]) {
79
+ const actorScope = createInertActorScope(actorLogic);
80
+ return actorLogic.initialTransition(input, actorScope)[0];
81
+ }
82
+
83
+ /**
84
+ * Determines the next snapshot for the given `actorLogic` based on the given
85
+ * `snapshot` and `event`.
86
+ *
87
+ * If the `snapshot` is `undefined`, the initial snapshot of the `actorLogic` is
88
+ * used.
89
+ *
90
+ * @deprecated Use `transition(…)` instead.
91
+ * @example
92
+ *
93
+ * ```ts
94
+ * import { getNextSnapshot } from 'xstate';
95
+ * import { trafficLightMachine } from './trafficLightMachine.ts';
96
+ *
97
+ * const nextSnapshot = getNextSnapshot(
98
+ * trafficLightMachine, // actor logic
99
+ * undefined, // snapshot (or initial state if undefined)
100
+ * { type: 'TIMER' }
101
+ * ); // event object
102
+ *
103
+ * console.log(nextSnapshot.value);
104
+ * // => 'yellow'
105
+ *
106
+ * const nextSnapshot2 = getNextSnapshot(
107
+ * trafficLightMachine, // actor logic
108
+ * nextSnapshot, // snapshot
109
+ * { type: 'TIMER' }
110
+ * ); // event object
111
+ *
112
+ * console.log(nextSnapshot2.value);
113
+ * // =>'red'
114
+ * ```
115
+ */
116
+ function getNextSnapshot(actorLogic, snapshot, event) {
117
+ const actorScope = createInertActorScope(actorLogic, snapshot);
118
+ const transitionResult = actorLogic.transition(snapshot, event, actorScope);
119
+ const nextSnapshot = Array.isArray(transitionResult) ? transitionResult[0] : transitionResult;
120
+ setInertActorScopeSnapshot(actorScope, nextSnapshot, false);
121
+ return nextSnapshot === snapshot ? nextSnapshot : attachSnapshotActorRef(actorLogic, actorScope, nextSnapshot);
122
+ }
123
+
124
+ const cache = new WeakMap();
125
+ function memo(object, key, fn) {
126
+ let memoizedData = cache.get(object);
127
+ if (!memoizedData) {
128
+ memoizedData = {
129
+ [key]: fn()
130
+ };
131
+ cache.set(object, memoizedData);
132
+ } else if (!(key in memoizedData)) {
133
+ memoizedData[key] = fn();
134
+ }
135
+ return memoizedData[key];
136
+ }
137
+
138
+ const EMPTY_OBJECT = {};
139
+ const CHOICE_CONFIG_KEYS = ['invoke', 'after', 'on', 'entry', 'exit', 'always', 'states', 'initial', 'onDone', 'timeout', 'onTimeout', 'history', 'target', 'output'];
140
+ class StateNode {
141
+ constructor(/** The raw config used to create the machine. */
142
+ config, options) {
143
+ this.config = config;
144
+ /**
145
+ * The relative key of the state node, which represents its location in the
146
+ * overall state value.
147
+ */
148
+ this.key = void 0;
149
+ /** The unique ID of the state node. */
150
+ this.id = void 0;
151
+ /**
152
+ * The type of this state node:
153
+ *
154
+ * - `'atomic'` - no child state nodes
155
+ * - `'compound'` - nested child state nodes (XOR)
156
+ * - `'parallel'` - orthogonal nested child state nodes (AND)
157
+ * - `'history'` - history state node
158
+ * - `'choice'` - pure routing decision state node
159
+ * - `'final'` - final state node
160
+ */
161
+ this.type = void 0;
162
+ /** The string path from the root machine node to this node. */
163
+ this.path = void 0;
164
+ /** The child state nodes. */
165
+ this.states = void 0;
166
+ /**
167
+ * The type of history on this state node. Can be:
168
+ *
169
+ * - `'shallow'` - recalls only top-level historical state value
170
+ * - `'deep'` - recalls historical state value at all levels
171
+ */
172
+ this.history = void 0;
173
+ /** The action(s) to be executed upon entering the state node. */
174
+ this.entry = void 0;
175
+ /** The action(s) to be executed upon exiting the state node. */
176
+ this.exit = void 0;
177
+ /** The parent state node. */
178
+ this.parent = void 0;
179
+ /** The root machine node. */
180
+ this.machine = void 0;
181
+ /**
182
+ * The meta data associated with this state node, which will be returned in
183
+ * State instances.
184
+ */
185
+ this.meta = void 0;
186
+ /**
187
+ * The output data sent with the `xstate.done.state` event if this is a final
188
+ * state node.
189
+ */
190
+ this.output = void 0;
191
+ /**
192
+ * The order this state node appears. Corresponds to the implicit document
193
+ * order.
194
+ */
195
+ this.order = -1;
196
+ this.description = void 0;
197
+ this.schemas = void 0;
198
+ this.tags = [];
199
+ this.transitions = void 0;
200
+ this.always = void 0;
201
+ this.invoke = void 0;
202
+ this.on = void 0;
203
+ this.after = void 0;
204
+ this.events = void 0;
205
+ this.ownEvents = void 0;
206
+ this._candidateCache = void 0;
207
+ this.parent = options._parent;
208
+ this.key = options._key;
209
+ this.machine = options._machine;
210
+ this.path = this.parent ? this.parent.path.concat(this.key) : [];
211
+ const firstStateKey = this.config.states ? Object.keys(this.config.states)[0] : undefined;
212
+ this.id = this.config.id || [this.machine.id, ...this.path].join(STATE_DELIMITER);
213
+ this.type = this.config.type || (firstStateKey !== undefined ? 'compound' : this.config.history ? 'history' : 'atomic');
214
+ this.description = this.config.description;
215
+ this.schemas = this.config.schemas;
216
+ validateStateNodeConfig(this);
217
+ this.order = this.machine.idMap.size;
218
+ this.machine.idMap.set(this.id, this);
219
+ this.states = this.config.states ? mapValues(this.config.states, (stateConfig, key) => {
220
+ const stateNode = new StateNode(stateConfig, {
221
+ _parent: this,
222
+ _key: key,
223
+ _machine: this.machine
224
+ });
225
+ return stateNode;
226
+ }) : EMPTY_OBJECT;
227
+ if (this.type === 'compound' && !this.config.initial) {
228
+ throw new Error(`No initial state specified for compound state node "#${this.id}". Try adding { initial: "${firstStateKey}" } to the state config.` );
229
+ }
230
+
231
+ // History config
232
+ this.history = this.config.history === true ? 'shallow' : this.config.history || false;
233
+ this.entry = this.config.entry;
234
+ this.exit = this.config.exit;
235
+ if (this.entry) {
236
+ // @ts-expect-error _special is an internal marker not on the Action type
237
+ this.entry._special = true;
238
+ }
239
+ if (this.exit) {
240
+ // @ts-expect-error _special is an internal marker not on the Action type
241
+ this.exit._special = true;
242
+ }
243
+ this.meta = this.config.meta;
244
+ this.output = this.type === 'final' || !this.parent ? this.config.output : undefined;
245
+ this.tags = toArray(config.tags).slice();
246
+ this.invoke = toArray(this.config.invoke).map((invokeConfig, i) => {
247
+ const {
248
+ src,
249
+ registryKey
250
+ } = invokeConfig;
251
+ const invokeId = createInvokeId(this.id, i);
252
+ const resolvedId = invokeConfig.id ?? invokeId;
253
+ // Referenced (string) actors keep their logical name so persisted
254
+ // snapshots reference `src: 'fetchUser'` rather than a positional id;
255
+ // only inline logic gets the synthetic source name.
256
+ const sourceName = typeof src === 'string' ? src : `xstate.invoke.${invokeId}`;
257
+ return {
258
+ ...invokeConfig,
259
+ src: sourceName,
260
+ logic: src,
261
+ id: resolvedId,
262
+ registryKey
263
+ };
264
+ });
265
+ }
266
+
267
+ /** @internal */
268
+ _initialize() {
269
+ this.after = getDelayedTransitions(this);
270
+ this.transitions = formatTransitions(this);
271
+ if (this.type === 'choice') {
272
+ this.always = formatChoiceTransitions(this);
273
+ } else if (this.config.always) {
274
+ this.always = mapTransitionConfigs(this.config.always, transition => formatTransition(this, NULL_EVENT, transition));
275
+ }
276
+ for (const key of Object.keys(this.states)) {
277
+ this.states[key]._initialize();
278
+ }
279
+ this._refreshEventMetadata();
280
+ }
281
+
282
+ /** @internal */
283
+ _refreshEventMetadata() {
284
+ const on = {};
285
+ const ownEvents = [];
286
+ for (const [descriptor, transitions] of this.transitions) {
287
+ on[descriptor] = transitions.slice();
288
+ if (transitions.some(transition => transition.target || transition.reenter || transition.to)) {
289
+ ownEvents.push(descriptor);
290
+ }
291
+ }
292
+ this.on = on;
293
+ this.ownEvents = ownEvents;
294
+ const events = new Set(ownEvents);
295
+ for (const state of Object.values(this.states)) {
296
+ for (const event of state.events) {
297
+ events.add(event);
298
+ }
299
+ }
300
+ this.events = Array.from(events);
301
+ }
302
+ get initial() {
303
+ return memo(this, 'initial', () => formatInitialTransition(this, this.config.initial));
304
+ }
305
+
306
+ /** @internal */
307
+ next(snapshot, event, self, selectionResults) {
308
+ const descriptorKey = getEventDescriptorKey(event);
309
+ let candidates = this._candidateCache?.get(descriptorKey);
310
+ if (!candidates) {
311
+ candidates = getCandidates(this, event);
312
+ (this._candidateCache ??= new Map()).set(descriptorKey, candidates);
313
+ }
314
+ for (const candidate of candidates) {
315
+ const guardPassed = evaluateCandidate(candidate, event, snapshot, this, self, selectionResults);
316
+ if (guardPassed) {
317
+ return [candidate];
318
+ }
319
+ }
320
+ return undefined;
321
+ }
322
+ }
323
+ function validateStateNodeConfig(stateNode) {
324
+ const config = stateNode.config;
325
+ if (stateNode.type === 'history' && !(typeof config.target === 'string' && config.target.trim().length > 0 || Array.isArray(config.target) && config.target.length > 0 && config.target.every(target => typeof target === 'string' && target.trim().length > 0))) {
326
+ throw new Error(`History state "${stateNode.id}" must declare a non-empty \`target\`.` );
327
+ }
328
+ if (stateNode.type !== 'choice') {
329
+ if (config.choice !== undefined) {
330
+ throw new Error(`State "${stateNode.id}" has \`choice\`, but \`choice\` can only be used with \`type: 'choice'\`.`);
331
+ }
332
+ return;
333
+ }
334
+ if (typeof config.choice !== 'function') {
335
+ throw new Error(`Choice state "${stateNode.id}" must declare a \`choice\` function.` );
336
+ }
337
+ {
338
+ for (const key of CHOICE_CONFIG_KEYS) {
339
+ if (config[key] !== undefined) {
340
+ throw new Error(`Choice state "${stateNode.id}" cannot declare \`${key}\`.`);
341
+ }
342
+ }
343
+ }
344
+ }
345
+ function formatChoiceTransitions(stateNode) {
346
+ const choice = stateNode.config.choice;
347
+ const validateChoiceResult = result => {
348
+ if (!result || result.target === undefined) {
349
+ throw new Error(`Choice state "${stateNode.id}" must resolve to a target.` );
350
+ }
351
+ {
352
+ for (const key of ['actions', 'to']) {
353
+ if (result[key] !== undefined) {
354
+ throw new Error(`Choice state "${stateNode.id}" cannot declare \`${key}\` on a choice.`);
355
+ }
356
+ }
357
+ }
358
+ return result;
359
+ };
360
+ return [formatTransition(stateNode, NULL_EVENT, {
361
+ to: args => validateChoiceResult(choice(args))
362
+ })];
363
+ }
364
+ function mapTransitionConfigs(transitionsConfig, mapper) {
365
+ const transitionConfigs = toTransitionConfigArray(transitionsConfig);
366
+ const transitions = new Array(transitionConfigs.length);
367
+ for (let i = 0; i < transitionConfigs.length; i++) {
368
+ transitions[i] = mapper(transitionConfigs[i]);
369
+ }
370
+ return transitions;
371
+ }
372
+ function formatTransitions(stateNode) {
373
+ const transitions = new Map();
374
+ const addTransitions = (descriptor, additions) => {
375
+ transitions.set(descriptor, [...(transitions.get(descriptor) ?? []), ...additions]);
376
+ };
377
+ if (stateNode.config.on) {
378
+ for (const descriptor of Object.keys(stateNode.config.on)) {
379
+ if (descriptor === NULL_EVENT) {
380
+ throw new Error('Null events ("") cannot be specified as a transition key. Use `always: { ... }` instead.' );
381
+ }
382
+ const transitionsConfig = stateNode.config.on[descriptor];
383
+ transitions.set(descriptor, mapTransitionConfigs(transitionsConfig, transition => formatTransition(stateNode, descriptor, transition)));
384
+ }
385
+ }
386
+ if (stateNode.config.onDone) {
387
+ const descriptor = 'xstate.done.state';
388
+ addTransitions(descriptor, mapTransitionConfigs(stateNode.config.onDone, transition => formatTransition(stateNode, descriptor, {
389
+ ...transition,
390
+ matches: {
391
+ ...transition.matches,
392
+ stateId: stateNode.id
393
+ }
394
+ })));
395
+ }
396
+ if (stateNode.config.onError) {
397
+ const descriptor = 'xstate.error.*';
398
+ transitions.set(descriptor, mapTransitionConfigs(stateNode.config.onError, transition => formatTransition(stateNode, descriptor, transition)));
399
+ }
400
+ const createCancelInvokeTimeoutTransition = (descriptor, timeoutEventId, actorId) => formatTransition(stateNode, descriptor, {
401
+ matches: {
402
+ actorId
403
+ },
404
+ _eventMatcher: (event, snapshot) => matchesActorSession(event, snapshot, actorId),
405
+ to: (_args, enq) => {
406
+ enq.cancel(timeoutEventId);
407
+ return {};
408
+ }
409
+ });
410
+ const formatInvokeCompletionTransition = (descriptor, transitionConfig, timeoutEventId) => {
411
+ const {
412
+ target,
413
+ to,
414
+ reenter,
415
+ ...rest
416
+ } = transitionConfig;
417
+ return formatTransition(stateNode, descriptor, {
418
+ ...rest,
419
+ reenter,
420
+ to: (args, enq) => {
421
+ if (to) {
422
+ let didEnqueue = false;
423
+ const trackingEnqueue = new Proxy(enq, {
424
+ apply(target, thisArg, argArray) {
425
+ didEnqueue = true;
426
+ return Reflect.apply(target, thisArg, argArray);
427
+ },
428
+ get(target, prop, receiver) {
429
+ const value = Reflect.get(target, prop, receiver);
430
+ if (typeof value !== 'function') {
431
+ return value;
432
+ }
433
+ return (...argArray) => {
434
+ didEnqueue = true;
435
+ return value.apply(target, argArray);
436
+ };
437
+ }
438
+ });
439
+ const result = to(args, trackingEnqueue);
440
+ if (result !== undefined || didEnqueue) {
441
+ enq.cancel(timeoutEventId);
442
+ }
443
+ return result;
444
+ }
445
+ enq.cancel(timeoutEventId);
446
+ return {
447
+ target,
448
+ reenter
449
+ };
450
+ }
451
+ });
452
+ };
453
+ for (const invokeDef of stateNode.invoke) {
454
+ const withInvokeMatch = transition => ({
455
+ ...transition,
456
+ matches: {
457
+ ...transition.matches,
458
+ actorId: invokeDef.id
459
+ },
460
+ _eventMatcher: (event, snapshot) => matchesActorSession(event, snapshot, invokeDef.id)
461
+ });
462
+ const invokeTimeoutEventId = invokeDef.timeout !== undefined ? createInvokeTimeoutEventId(invokeDef.id) : undefined;
463
+ if (invokeDef.onDone) {
464
+ const descriptor = 'xstate.done.actor';
465
+ const invokeDoneTransitions = mapTransitionConfigs(invokeDef.onDone, rawTransition => {
466
+ const transition = withInvokeMatch(rawTransition);
467
+ return invokeTimeoutEventId ? formatInvokeCompletionTransition(descriptor, transition, invokeTimeoutEventId) : formatTransition(stateNode, descriptor, transition);
468
+ });
469
+ if (invokeTimeoutEventId) {
470
+ invokeDoneTransitions.push(createCancelInvokeTimeoutTransition(descriptor, invokeTimeoutEventId, invokeDef.id));
471
+ }
472
+ addTransitions(descriptor, invokeDoneTransitions);
473
+ } else if (invokeTimeoutEventId) {
474
+ const descriptor = 'xstate.done.actor';
475
+ addTransitions(descriptor, [createCancelInvokeTimeoutTransition(descriptor, invokeTimeoutEventId, invokeDef.id)]);
476
+ }
477
+ if (invokeDef.onError) {
478
+ const descriptor = 'xstate.error.actor';
479
+ addTransitions(descriptor, mapTransitionConfigs(invokeDef.onError, rawTransition => {
480
+ const transition = withInvokeMatch(rawTransition);
481
+ return invokeTimeoutEventId ? formatInvokeCompletionTransition(descriptor, transition, invokeTimeoutEventId) : formatTransition(stateNode, descriptor, transition);
482
+ }));
483
+ }
484
+ if (invokeDef.onSnapshot) {
485
+ const descriptor = 'xstate.snapshot.actor';
486
+ addTransitions(descriptor, mapTransitionConfigs(invokeDef.onSnapshot, transition => formatTransition(stateNode, descriptor, withInvokeMatch(transition))));
487
+ }
488
+ }
489
+ for (const delayedTransition of stateNode.after) {
490
+ let existing = transitions.get(delayedTransition.eventType);
491
+ if (!existing) {
492
+ existing = [];
493
+ transitions.set(delayedTransition.eventType, existing);
494
+ }
495
+ existing.push(delayedTransition);
496
+ }
497
+ return transitions;
498
+ }
499
+ function formatInitialTransition(stateNode, _target) {
500
+ const targetString = typeof _target === 'object' && _target !== null ? _target.target : _target;
501
+ const input = typeof _target === 'object' && _target !== null ? _target.input : undefined;
502
+ const resolvedTarget = typeof targetString === 'string' ? stateNode.states[targetString] : undefined;
503
+ if (!resolvedTarget && targetString) {
504
+ throw new Error(`Initial state node "${targetString}" not found on parent state node #${stateNode.id}` );
505
+ }
506
+ const transition = {
507
+ source: stateNode,
508
+ target: resolvedTarget ? [resolvedTarget] : undefined,
509
+ input
510
+ };
511
+ return transition;
512
+ }
513
+
514
+ const STATE_IDENTIFIER = '#';
515
+ let emptyCanActor;
516
+ let emptyCanActorScope;
517
+ function getEmptyCanActor() {
518
+ // A minimal inert actor used purely as the `self`/`parent` argument when
519
+ // dry-running transitions for `snapshot.can(...)`. Intentionally not built
520
+ // on `createLogic` so `can()` does not pull that machinery into bundles.
521
+ return emptyCanActor ??= createActor({
522
+ transition: snapshot => [snapshot, []],
523
+ initialTransition: () => [{
524
+ status: 'active',
525
+ output: undefined,
526
+ error: undefined
527
+ }, []],
528
+ getInitialSnapshot: () => ({
529
+ status: 'active',
530
+ output: undefined,
531
+ error: undefined
532
+ }),
533
+ getPersistedSnapshot: snapshot => snapshot
534
+ });
535
+ }
536
+ function getEmptyCanActorScope() {
537
+ if (emptyCanActorScope) {
538
+ return emptyCanActorScope;
539
+ }
540
+ const actor = getEmptyCanActor();
541
+ emptyCanActorScope = {
542
+ self: actor,
543
+ logger: () => {},
544
+ id: '',
545
+ sessionId: '',
546
+ defer: () => {},
547
+ system: actor.system,
548
+ stopChild: () => {},
549
+ emit: () => {},
550
+ actionExecutor: () => {}
551
+ };
552
+ return emptyCanActorScope;
553
+ }
554
+ class StateMachine {
555
+ constructor(/** The raw config used to create the machine. */
556
+ config, sources, validator) {
557
+ this.config = config;
558
+ this.validator = validator;
559
+ /** The machine's own version. */
560
+ this.version = void 0;
561
+ this.schemas = void 0;
562
+ this.sources = void 0;
563
+ /** Runtime options for machine execution. */
564
+ this.options = void 0;
565
+ /** @internal */
566
+ this.idMap = new Map();
567
+ this.root = void 0;
568
+ this.id = void 0;
569
+ this.states = void 0;
570
+ this.events = void 0;
571
+ this.internalEventDescriptors = void 0;
572
+ /** @internal Skips eventless-selection scans for machines without `always`. */
573
+ this._hasEventlessTransitions = void 0;
574
+ /**
575
+ * The original JSON definition this machine was created from (set by
576
+ * `createMachineFromConfig`), if any. Used by `serializeMachine` for lossless
577
+ * round-trips.
578
+ *
579
+ * @internal
580
+ */
581
+ this._json = void 0;
582
+ this.id = config.id || '(machine)';
583
+ this.sources = {
584
+ actors: config.actors ?? {},
585
+ actions: config.actions ?? {},
586
+ delays: config.delays ?? {},
587
+ guards: config.guards ?? {},
588
+ ...sources
589
+ };
590
+ {
591
+ // The `@xstate.` prefix is reserved for built-in serialized action and
592
+ // guard descriptors — user source names must not collide.
593
+ for (const kind of ['actions', 'guards', 'actors', 'delays']) {
594
+ for (const key of Object.keys(this.sources[kind])) {
595
+ if (key.startsWith('@xstate.')) {
596
+ throw new Error(`Invalid ${kind} name '${key}': the '@xstate.' prefix is reserved for built-in descriptors.`);
597
+ }
598
+ }
599
+ }
600
+ }
601
+ this.version = this.config.version;
602
+ this.schemas = this.config.schemas;
603
+ this.internalEventDescriptors = this.config.internalEvents ?? [];
604
+ this.options = {
605
+ maxIterations: Infinity,
606
+ ...this.config.options
607
+ };
608
+ this.transition = this.transition.bind(this);
609
+ this.initialTransition = this.initialTransition.bind(this);
610
+ this.getInitialSnapshot = this.getInitialSnapshot.bind(this);
611
+ this.getPersistedSnapshot = this.getPersistedSnapshot.bind(this);
612
+ this.restoreSnapshot = this.restoreSnapshot.bind(this);
613
+ this.start = this.start.bind(this);
614
+ this.root = new StateNode(config, {
615
+ _key: this.id,
616
+ _machine: this
617
+ });
618
+ this.root._initialize();
619
+ formatRouteTransitions(this.root);
620
+ this.root._refreshEventMetadata();
621
+ this._hasEventlessTransitions = Array.from(this.idMap.values()).some(stateNode => !!stateNode.always?.length);
622
+ this.states = this.root.states; // TODO: remove!
623
+ this.events = this.root.events;
624
+ }
625
+
626
+ /**
627
+ * Clones this state machine with the provided sources.
628
+ *
629
+ * @param sources Options (`actions`, `guards`, `actors`, `delays`) to
630
+ * recursively merge with the existing options.
631
+ * @returns A new `StateMachine` instance with the provided sources.
632
+ */
633
+ provide(sources) {
634
+ const {
635
+ actions,
636
+ guards,
637
+ actors,
638
+ delays
639
+ } = this.sources;
640
+ const provided = new StateMachine(this.config, {
641
+ actions: {
642
+ ...actions,
643
+ ...sources.actions
644
+ },
645
+ guards: {
646
+ ...guards,
647
+ ...sources.guards
648
+ },
649
+ actors: {
650
+ ...actors,
651
+ ...sources.actors
652
+ },
653
+ delays: {
654
+ ...delays,
655
+ ...sources.delays
656
+ }
657
+ }, this.validator);
658
+ // Providing sources does not change the serializable definition.
659
+ provided._json = this._json;
660
+ return provided;
661
+ }
662
+ resolveState(config) {
663
+ const resolvedStateValue = resolveStateValue(this.root, config.value);
664
+ const nodeSet = getAllStateNodes(getStateNodes(this.root, resolvedStateValue));
665
+ const nodes = [...nodeSet];
666
+ return createMachineSnapshot({
667
+ _nodes: nodes,
668
+ value: resolvedStateValue,
669
+ context: config.context || {},
670
+ children: {},
671
+ status: isInFinalState(nodeSet, this.root) ? 'done' : config.status || 'active',
672
+ output: config.output,
673
+ error: config.error,
674
+ historyValue: config.historyValue
675
+ }, this);
676
+ }
677
+
678
+ /**
679
+ * Determines the next snapshot given the current `snapshot` and received
680
+ * `event`. Calculates a full macrostep from all microsteps.
681
+ *
682
+ * @param snapshot The current snapshot
683
+ * @param event The received event
684
+ */
685
+ transition(snapshot, event, actorScope) {
686
+ const usesInertScope = !actorScope;
687
+ const resolvedActorScope = actorScope ?? createInertActorScope(this, snapshot);
688
+ if (this.validator) {
689
+ assertValid(this.validator, {
690
+ kind: 'event',
691
+ logic: this,
692
+ event,
693
+ eventOrigin: actorScope && actorScope.self._lastSourceRef ? 'actor' : 'external'
694
+ });
695
+ }
696
+ if (usesInertScope) {
697
+ setInertActorScopeSnapshot(resolvedActorScope, snapshot, false);
698
+ }
699
+ const fastSnapshot = this._transitionFast(snapshot, event, resolvedActorScope);
700
+ if (fastSnapshot) {
701
+ if (usesInertScope) {
702
+ setInertActorScopeSnapshot(resolvedActorScope, fastSnapshot, false);
703
+ }
704
+ const returnedSnapshot = usesInertScope && fastSnapshot !== snapshot ? attachSnapshotActorRef(this, resolvedActorScope, fastSnapshot) : this._attachPureActorRef(fastSnapshot, resolvedActorScope);
705
+ if (this.validator) {
706
+ assertValid(this.validator, {
707
+ kind: 'result',
708
+ logic: this,
709
+ snapshot: returnedSnapshot,
710
+ effects: []
711
+ });
712
+ }
713
+ return [returnedSnapshot, []];
714
+ }
715
+ const {
716
+ snapshot: nextSnapshot,
717
+ microsteps
718
+ } = macrostep(snapshot, event, resolvedActorScope, []);
719
+ if (usesInertScope) {
720
+ setInertActorScopeSnapshot(resolvedActorScope, nextSnapshot, false);
721
+ }
722
+ const returnedSnapshot = usesInertScope ? nextSnapshot === snapshot ? nextSnapshot : attachSnapshotActorRef(this, resolvedActorScope, nextSnapshot) : this._attachPureActorRef(nextSnapshot, resolvedActorScope);
723
+ const effects = this._collectEffects(microsteps);
724
+ if (this.validator) {
725
+ assertValid(this.validator, {
726
+ kind: 'result',
727
+ logic: this,
728
+ snapshot: returnedSnapshot,
729
+ effects
730
+ });
731
+ }
732
+ return [returnedSnapshot, effects];
733
+ }
734
+ _collectEffects(microsteps) {
735
+ return microsteps.flatMap(([, actions]) => actions);
736
+ }
737
+ _attachPureActorRef(snapshot, actorScope) {
738
+ if (isInertActorScope(actorScope)) {
739
+ return snapshot;
740
+ }
741
+ setSnapshotActorRef(snapshot, actorScope.self, actorScope.system);
742
+ return snapshot;
743
+ }
744
+ _transitionFast(snapshot, event, actorScope) {
745
+ if (snapshot.status !== 'active' || typeof snapshot.value !== 'string' || this.root.always?.length) {
746
+ return undefined;
747
+ }
748
+ const sourceNode = this.root.states[snapshot.value];
749
+ if (!sourceNode || sourceNode.type !== 'atomic' || sourceNode.exit || sourceNode.invoke.length || sourceNode.always?.length || sourceNode.after?.length) {
750
+ return undefined;
751
+ }
752
+ const transitions = sourceNode.transitions.get(event.type);
753
+ if (transitions?.length !== 1) {
754
+ return undefined;
755
+ }
756
+ const selected = transitions[0];
757
+ if (selected.guard || selected.actions || selected.to || selected.reenter || selected.input || typeof selected.context === 'function' || selected.target && selected.target.length !== 1) {
758
+ return undefined;
759
+ }
760
+ const targetNode = selected.target?.[0] ?? sourceNode;
761
+ const stateChanged = targetNode !== sourceNode;
762
+ if (targetNode.parent !== this.root || targetNode.type !== 'atomic' || stateChanged && (targetNode.entry || targetNode.invoke.length || targetNode.always?.length || targetNode.after?.length)) {
763
+ return undefined;
764
+ }
765
+ const context = selected.context !== undefined ? {
766
+ ...snapshot.context,
767
+ ...selected.context
768
+ } : snapshot.context;
769
+ const collectedMicrosteps = actorScope.self._collectedMicrosteps || [];
770
+ collectedMicrosteps.push(selected);
771
+ actorScope.self._collectedMicrosteps = collectedMicrosteps;
772
+ return cloneMachineSnapshot(snapshot, {
773
+ ...(context !== snapshot.context ? {
774
+ context
775
+ } : {}),
776
+ ...(stateChanged ? {
777
+ _nodes: [this.root, targetNode]
778
+ } : {})
779
+ });
780
+ }
781
+
782
+ /**
783
+ * Determines the next state given the current `state` and `event`. Calculates
784
+ * a microstep.
785
+ *
786
+ * @param state The current state
787
+ * @param event The received event
788
+ */
789
+ microstep(snapshot, event, actorScope) {
790
+ const {
791
+ microsteps
792
+ } = macrostep(snapshot, event, actorScope, []);
793
+ const snapshots = new Array(microsteps.length);
794
+ for (let i = 0; i < microsteps.length; i++) {
795
+ snapshots[i] = microsteps[i][0];
796
+ }
797
+ return snapshots;
798
+ }
799
+ getTransitionData(snapshot, event, self, selectionResults) {
800
+ return transitionNode(this.root, snapshot.value, snapshot, event, self, selectionResults) || [];
801
+ }
802
+ isInternalEventType(eventType) {
803
+ if (eventType === XSTATE_TIMER) {
804
+ return true;
805
+ }
806
+ for (const descriptor of this.internalEventDescriptors) {
807
+ if (matchesEventDescriptor(eventType, descriptor)) {
808
+ return true;
809
+ }
810
+ }
811
+ return false;
812
+ }
813
+
814
+ /**
815
+ * Determines whether sending the `event` to the given snapshot would select a
816
+ * non-forbidden transition. Backs `snapshot.can(...)`; lives here so that
817
+ * non-machine bundles don't pay for the transition-resolution machinery.
818
+ *
819
+ * @internal
820
+ */
821
+ _canTransition(snapshot, event) {
822
+ const emptyActor = getEmptyCanActor();
823
+ const emptyActorScope = getEmptyCanActorScope();
824
+ const transitionData = this.getTransitionData(snapshot, event, emptyActor);
825
+ if (!transitionData?.length) {
826
+ return false;
827
+ }
828
+
829
+ // Check that at least one transition is not forbidden
830
+ for (const transition of transitionData) {
831
+ if (transition.target !== undefined) {
832
+ return true;
833
+ }
834
+ const res = getTransitionResult(transition, snapshot, event, emptyActorScope, {
835
+ resolveActions: false
836
+ });
837
+ if (res.targets?.length || res.context || hasEffect(transition, snapshot.context, event, snapshot, emptyActor)) {
838
+ return true;
839
+ }
840
+ }
841
+ return false;
842
+ }
843
+
844
+ /**
845
+ * Returns the error event that the actor should transition with to recover
846
+ * from an execution error, if any active state node declares `onError`.
847
+ *
848
+ * @internal
849
+ */
850
+ getExecutionErrorEvent(snapshot, error) {
851
+ if (snapshot?.status !== 'active' || !snapshot._nodes?.some(stateNode => stateNode.config.onError)) {
852
+ return undefined;
853
+ }
854
+ return createErrorPlatformEvent('execution', error);
855
+ }
856
+
857
+ /**
858
+ * The initial state _before_ evaluating any microsteps. This "pre-initial"
859
+ * state is provided to initial actions executed in the initial state.
860
+ *
861
+ * @internal
862
+ */
863
+ _getPreInitialState(actorScope, initEvent) {
864
+ const {
865
+ context
866
+ } = this.config;
867
+ const preInitial = createMachineSnapshot({
868
+ context: typeof context !== 'function' && context ? context : {},
869
+ _nodes: [this.root],
870
+ children: {},
871
+ status: 'active'
872
+ }, this);
873
+ if (typeof context === 'function') {
874
+ const children = {};
875
+ const spawn = createSpawner(actorScope, this.sources.actors, children);
876
+ const resolvedContext = context({
877
+ spawn,
878
+ input: initEvent.input,
879
+ self: actorScope.self,
880
+ actors: this.sources.actors
881
+ });
882
+ const [nextState] = resolveActionsWithContext(preInitial, initEvent, actorScope, []);
883
+ if (resolvedContext) {
884
+ nextState.context = resolvedContext;
885
+ }
886
+ if (Object.keys(children).length > 0) {
887
+ nextState.children = {
888
+ ...nextState.children,
889
+ ...children
890
+ };
891
+ }
892
+ return nextState;
893
+ }
894
+ return preInitial;
895
+ }
896
+
897
+ /**
898
+ * Returns the initial `State` instance, with reference to `self` as an
899
+ * `ActorRef`.
900
+ */
901
+ getInitialSnapshot(actorScope, input) {
902
+ return this.initialTransition(input, actorScope)[0];
903
+ }
904
+ initialTransition(input, actorScope) {
905
+ if (this.validator) {
906
+ assertValid(this.validator, {
907
+ kind: 'input',
908
+ logic: this,
909
+ input
910
+ });
911
+ }
912
+ const usesInertScope = !actorScope;
913
+ const resolvedActorScope = actorScope ?? createInertActorScope(this);
914
+ const initEvent = createInitEvent(input); // TODO: fix;
915
+ const internalQueue = [];
916
+ const preInitialState = this._getPreInitialState(resolvedActorScope, initEvent);
917
+ const contextSpawnEffects = Object.values(preInitialState.children).filter(Boolean).map(actor => createSpawnEffect(actor));
918
+ const finalizeInitialResult = (macroState, microsteps) => {
919
+ if (usesInertScope) {
920
+ setInertActorScopeSnapshot(resolvedActorScope, macroState, false);
921
+ }
922
+ const returnedSnapshot = usesInertScope ? attachSnapshotActorRef(this, resolvedActorScope, macroState) : this._attachPureActorRef(macroState, resolvedActorScope);
923
+ const effects = this._collectEffects(microsteps);
924
+ if (this.validator) {
925
+ assertValid(this.validator, {
926
+ kind: 'result',
927
+ logic: this,
928
+ snapshot: returnedSnapshot,
929
+ effects
930
+ });
931
+ }
932
+ return [returnedSnapshot, effects];
933
+ };
934
+ try {
935
+ const [nextState, initialActions] = initialMicrostep(this.root, preInitialState, resolvedActorScope, initEvent, internalQueue);
936
+ const {
937
+ snapshot: macroState,
938
+ microsteps
939
+ } = macrostep(nextState, initEvent, resolvedActorScope, internalQueue, [[nextState, [...contextSpawnEffects, ...initialActions]]]);
940
+ return finalizeInitialResult(macroState, microsteps);
941
+ } catch (err) {
942
+ if (!this.root.config.onError) {
943
+ throw err;
944
+ }
945
+ const errorEvent = createErrorPlatformEvent('execution', err);
946
+ const errorMacrostep = macrostep(preInitialState, errorEvent, resolvedActorScope, [], [[preInitialState, contextSpawnEffects]]);
947
+ return finalizeInitialResult(errorMacrostep.snapshot, errorMacrostep.microsteps);
948
+ }
949
+ }
950
+ start(snapshot) {
951
+ // Start rehydrated children that were active when persisted. Freshly
952
+ // invoked/spawned children are NOT started here — they start via deferred
953
+ // `@xstate.start` actions so sync start errors route to `onError`.
954
+ if (!snapshot?.children) {
955
+ return;
956
+ }
957
+ for (const child of Object.values(snapshot.children)) {
958
+ if (child._rehydrated && child.getSnapshot?.().status === 'active') {
959
+ child.start();
960
+ }
961
+ }
962
+ }
963
+ getStateNodeById(stateId) {
964
+ const fullPath = toStatePath(stateId);
965
+ const relativePath = fullPath.slice(1);
966
+ const resolvedStateId = isStateId(fullPath[0]) ? fullPath[0].slice(STATE_IDENTIFIER.length) : fullPath[0];
967
+ const stateNode = this.idMap.get(resolvedStateId);
968
+ if (!stateNode) {
969
+ throw new Error(`Child state node '#${resolvedStateId}' does not exist on machine '${this.id}'`);
970
+ }
971
+ return getStateNodeByPath(stateNode, relativePath);
972
+ }
973
+ getPersistedSnapshot(snapshot, options) {
974
+ return getPersistedSnapshot(snapshot, options);
975
+ }
976
+ restoreSnapshot(snapshot, actorScope) {
977
+ const usesInertScope = !actorScope;
978
+ const resolvedActorScope = actorScope ?? createInertActorScope(this);
979
+ const persistedMachine = snapshot.machine;
980
+ const legacyPersistedVersion = snapshot.version;
981
+ const persistedVersion = typeof persistedMachine?.version === 'string' ? persistedMachine.version : legacyPersistedVersion;
982
+ if (legacyPersistedVersion !== undefined && persistedMachine?.version !== undefined && persistedMachine.version !== legacyPersistedVersion) {
983
+ throw new Error(`Persisted snapshot version '${legacyPersistedVersion}' conflicts with machine version '${persistedMachine.version}'.`);
984
+ }
985
+ if (persistedMachine && typeof persistedMachine.id === 'string' && persistedMachine.id !== this.id) {
986
+ throw new Error(`Machine ID mismatch: persisted snapshot was created by machine '${persistedMachine.id}', but machine '${this.id}' was provided.` );
987
+ }
988
+ if (persistedVersion !== this.version) {
989
+ const migrate = this.config.migrate;
990
+ if (typeof migrate !== 'function') {
991
+ throw new Error(`Persisted snapshot version '${persistedVersion}' does not match machine version '${this.version}' for machine '${this.id}'. Provide a \`migrate(persistedSnapshot, fromVersion)\` function in the machine config to migrate old snapshots.` );
992
+ }
993
+ snapshot = migrate(snapshot, persistedVersion);
994
+ }
995
+ const snapshotData = snapshot;
996
+ const children = {};
997
+ const snapshotChildren = snapshotData.children;
998
+ for (const actorId of Object.keys(snapshotChildren)) {
999
+ const actorData = snapshotChildren[actorId];
1000
+ const childState = actorData.snapshot;
1001
+ const src = actorData.src;
1002
+ const logic = typeof src === 'string' ? resolveReferencedActor(this, src) : src;
1003
+ if (!logic) {
1004
+ const sourceId = typeof src === 'string' ? src : '<unknown>';
1005
+ throw new Error(`Unable to restore child actor '${actorId}': child source '${sourceId}' is not provided in machine '${this.id}'.`);
1006
+ }
1007
+ const actor = resolvedActorScope.system.createActorRef(logic, {
1008
+ id: actorId,
1009
+ parent: resolvedActorScope.self,
1010
+ syncSnapshot: actorData.syncSnapshot,
1011
+ snapshot: childState,
1012
+ src,
1013
+ registryKey: actorData.registryKey
1014
+ });
1015
+ // Mark so `start()` knows to start this child (freshly invoked/spawned
1016
+ // children are started via deferred `@xstate.start` actions instead).
1017
+ actor._rehydrated = true;
1018
+ children[actorId] = actor;
1019
+ }
1020
+ const timers = {};
1021
+ const persistedTimers = snapshotData.timers ?? {};
1022
+ for (const [id, timer] of Object.entries(persistedTimers)) {
1023
+ let event = timer.event;
1024
+ if (event.type === 'xstate.timeout.actor') {
1025
+ const actorId = event.actorId;
1026
+ const child = children[actorId];
1027
+ if (child) {
1028
+ event = createInvokeTimeoutEvent(actorId, child.sessionId);
1029
+ }
1030
+ }
1031
+ const target = typeof timer.target === 'string' ? timer.target === 'self' ? 'self' : children[timer.target] : resolvedActorScope.self._parent;
1032
+ if (!target) {
1033
+ const targetDescription = typeof timer.target === 'string' ? timer.target : timer.target.type;
1034
+ throw new Error(`Unable to restore timer '${id}': target actor '${targetDescription}' is unavailable.`);
1035
+ }
1036
+ timers[id] = {
1037
+ ...timer,
1038
+ event,
1039
+ target
1040
+ };
1041
+ }
1042
+ const reviveHistoryValue = historyValue => {
1043
+ if (!historyValue || typeof historyValue !== 'object') {
1044
+ return {};
1045
+ }
1046
+ const revived = {};
1047
+ for (const key of Object.keys(historyValue)) {
1048
+ const arr = historyValue[key];
1049
+ for (const item of arr) {
1050
+ let resolved;
1051
+ if (item instanceof StateNode) {
1052
+ resolved = item;
1053
+ } else {
1054
+ try {
1055
+ resolved = this.root.machine.getStateNodeById(item.id);
1056
+ } catch {
1057
+ {
1058
+ console.warn(`Could not resolve StateNode for id: ${item.id}`);
1059
+ }
1060
+ }
1061
+ }
1062
+ if (!resolved) {
1063
+ continue;
1064
+ }
1065
+ revived[key] ??= [];
1066
+ revived[key].push(resolved);
1067
+ }
1068
+ }
1069
+ return revived;
1070
+ };
1071
+ const revivedHistoryValue = reviveHistoryValue(snapshotData.historyValue);
1072
+ const nodes = Array.from(getAllStateNodes(getStateNodes(this.root, snapshotData.value)));
1073
+ const {
1074
+ version: _persistedSnapshotVersion,
1075
+ ...persistedRest
1076
+ } = snapshot;
1077
+ const restoredSnapshot = createMachineSnapshot({
1078
+ ...persistedRest,
1079
+ children,
1080
+ timers,
1081
+ _nodes: nodes,
1082
+ value: snapshotData.value,
1083
+ historyValue: revivedHistoryValue,
1084
+ _stateInputs: snapshotData.stateInputs ?? {}
1085
+ }, this, resolvedActorScope.self);
1086
+ const seen = new WeakSet();
1087
+ function reviveContext(contextPart) {
1088
+ if (seen.has(contextPart)) {
1089
+ return;
1090
+ }
1091
+ seen.add(contextPart);
1092
+ for (const key of Object.keys(contextPart)) {
1093
+ const value = contextPart[key];
1094
+ if (value && typeof value === 'object') {
1095
+ if ('xstate$$type' in value && value.xstate$$type === $$ACTOR_TYPE) {
1096
+ contextPart[key] = children[value.id];
1097
+ continue;
1098
+ }
1099
+ reviveContext(value);
1100
+ }
1101
+ }
1102
+ }
1103
+ reviveContext(restoredSnapshot.context);
1104
+ if (usesInertScope) {
1105
+ setInertActorScopeSnapshot(resolvedActorScope, restoredSnapshot, false);
1106
+ return attachSnapshotActorRef(this, resolvedActorScope, restoredSnapshot);
1107
+ }
1108
+ return this._attachPureActorRef(restoredSnapshot, resolvedActorScope);
1109
+ }
1110
+ }
1111
+
1112
+ export { StateMachine as S, attachSnapshotActorRef as a, getNextSnapshot as b, createInertActorScope as c, StateNode as d, getInitialSnapshot as g, setInertActorScopeSnapshot as s };