xstate 5.0.0-beta.43 → 5.0.0-beta.45

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 (55) hide show
  1. package/actions/dist/xstate-actions.cjs.js +2 -3
  2. package/actions/dist/xstate-actions.development.cjs.js +2 -3
  3. package/actions/dist/xstate-actions.development.esm.js +2 -3
  4. package/actions/dist/xstate-actions.esm.js +2 -3
  5. package/actions/dist/xstate-actions.umd.min.js +1 -1
  6. package/actions/dist/xstate-actions.umd.min.js.map +1 -1
  7. package/actors/dist/xstate-actors.cjs.js +98 -10
  8. package/actors/dist/xstate-actors.development.cjs.js +98 -10
  9. package/actors/dist/xstate-actors.development.esm.js +93 -5
  10. package/actors/dist/xstate-actors.esm.js +93 -5
  11. package/actors/dist/xstate-actors.umd.min.js +1 -1
  12. package/actors/dist/xstate-actors.umd.min.js.map +1 -1
  13. package/dist/declarations/src/State.d.ts +14 -18
  14. package/dist/declarations/src/StateMachine.d.ts +1 -1
  15. package/dist/declarations/src/actions/choose.d.ts +3 -3
  16. package/dist/declarations/src/actions/pure.d.ts +4 -4
  17. package/dist/declarations/src/actions/spawn.d.ts +11 -16
  18. package/dist/declarations/src/actors/observable.d.ts +39 -0
  19. package/dist/declarations/src/actors/transition.d.ts +53 -4
  20. package/dist/declarations/src/{Machine.d.ts → createMachine.d.ts} +1 -1
  21. package/dist/declarations/src/guards.d.ts +27 -5
  22. package/dist/declarations/src/index.d.ts +3 -2
  23. package/dist/declarations/src/interpreter.d.ts +1 -0
  24. package/dist/declarations/src/setup.d.ts +32 -0
  25. package/dist/declarations/src/spawn.d.ts +9 -13
  26. package/dist/declarations/src/stateUtils.d.ts +11 -11
  27. package/dist/declarations/src/types.d.ts +31 -29
  28. package/dist/declarations/src/utils.d.ts +1 -3
  29. package/dist/{raise-8dc8e1aa.esm.js → raise-2b5a4e4c.esm.js} +934 -103
  30. package/dist/{raise-f4ad5a87.development.esm.js → raise-90139fbc.development.esm.js} +945 -103
  31. package/dist/{raise-23dea0d7.development.cjs.js → raise-b3fb3c65.development.cjs.js} +999 -137
  32. package/dist/{raise-e0fe5c2d.cjs.js → raise-fabffc3d.cjs.js} +986 -135
  33. package/dist/{send-5d129d95.development.esm.js → send-24cc8018.development.esm.js} +4 -30
  34. package/dist/{send-84e2e742.esm.js → send-8e7e41e7.esm.js} +4 -30
  35. package/dist/{send-87bbaaab.cjs.js → send-c124176f.cjs.js} +13 -39
  36. package/dist/{send-0174c155.development.cjs.js → send-d0bc7eed.development.cjs.js} +13 -39
  37. package/dist/xstate.cjs.js +67 -35
  38. package/dist/xstate.cjs.mjs +2 -0
  39. package/dist/xstate.development.cjs.js +67 -35
  40. package/dist/xstate.development.cjs.mjs +2 -0
  41. package/dist/xstate.development.esm.js +42 -13
  42. package/dist/xstate.esm.js +42 -13
  43. package/dist/xstate.umd.min.js +1 -1
  44. package/dist/xstate.umd.min.js.map +1 -1
  45. package/guards/dist/xstate-guards.cjs.js +1 -2
  46. package/guards/dist/xstate-guards.development.cjs.js +1 -2
  47. package/guards/dist/xstate-guards.development.esm.js +1 -2
  48. package/guards/dist/xstate-guards.esm.js +1 -2
  49. package/guards/dist/xstate-guards.umd.min.js +1 -1
  50. package/guards/dist/xstate-guards.umd.min.js.map +1 -1
  51. package/package.json +1 -1
  52. package/dist/interpreter-36d5556e.cjs.js +0 -887
  53. package/dist/interpreter-4e8e2a0d.development.cjs.js +0 -898
  54. package/dist/interpreter-63c80754.esm.js +0 -857
  55. package/dist/interpreter-80eb3bec.development.esm.js +0 -868
@@ -1,21 +1,874 @@
1
1
  'use strict';
2
2
 
3
- var interpreter = require('./interpreter-36d5556e.cjs.js');
4
-
5
- const cache = new WeakMap();
6
- function memo(object, key, fn) {
7
- let memoizedData = cache.get(object);
8
- if (!memoizedData) {
9
- memoizedData = {
10
- [key]: fn()
3
+ var dev_dist_xstateDev = require('../dev/dist/xstate-dev.cjs.js');
4
+
5
+ class Mailbox {
6
+ constructor(_process) {
7
+ this._process = _process;
8
+ this._active = false;
9
+ this._current = null;
10
+ this._last = null;
11
+ }
12
+ start() {
13
+ this._active = true;
14
+ this.flush();
15
+ }
16
+ clear() {
17
+ // we can't set _current to null because we might be currently processing
18
+ // and enqueue following clear shouldnt start processing the enqueued item immediately
19
+ if (this._current) {
20
+ this._current.next = null;
21
+ this._last = this._current;
22
+ }
23
+ }
24
+ enqueue(event) {
25
+ const enqueued = {
26
+ value: event,
27
+ next: null
28
+ };
29
+ if (this._current) {
30
+ this._last.next = enqueued;
31
+ this._last = enqueued;
32
+ return;
33
+ }
34
+ this._current = enqueued;
35
+ this._last = enqueued;
36
+ if (this._active) {
37
+ this.flush();
38
+ }
39
+ }
40
+ flush() {
41
+ while (this._current) {
42
+ // atm the given _process is responsible for implementing proper try/catch handling
43
+ // we assume here that this won't throw in a way that can affect this mailbox
44
+ const consumed = this._current;
45
+ this._process(consumed.value);
46
+ this._current = consumed.next;
47
+ }
48
+ this._last = null;
49
+ }
50
+ }
51
+
52
+ const STATE_DELIMITER = '.';
53
+ const TARGETLESS_KEY = '';
54
+ const NULL_EVENT = '';
55
+ const STATE_IDENTIFIER = '#';
56
+ const WILDCARD = '*';
57
+ const XSTATE_INIT = 'xstate.init';
58
+ const XSTATE_ERROR = 'xstate.error';
59
+ const XSTATE_STOP = 'xstate.stop';
60
+
61
+ /**
62
+ * Returns an event that represents an implicit event that
63
+ * is sent after the specified `delay`.
64
+ *
65
+ * @param delayRef The delay in milliseconds
66
+ * @param id The state node ID where this event is handled
67
+ */
68
+ function createAfterEvent(delayRef, id) {
69
+ const idSuffix = id ? `#${id}` : '';
70
+ return {
71
+ type: `xstate.after(${delayRef})${idSuffix}`
72
+ };
73
+ }
74
+
75
+ /**
76
+ * Returns an event that represents that a final state node
77
+ * has been reached in the parent state node.
78
+ *
79
+ * @param id The final state node's parent state node `id`
80
+ * @param output The data to pass into the event
81
+ */
82
+ function createDoneStateEvent(id, output) {
83
+ return {
84
+ type: `xstate.done.state.${id}`,
85
+ output
86
+ };
87
+ }
88
+
89
+ /**
90
+ * Returns an event that represents that an invoked service has terminated.
91
+ *
92
+ * An invoked service is terminated when it has reached a top-level final state node,
93
+ * but not when it is canceled.
94
+ *
95
+ * @param invokeId The invoked service ID
96
+ * @param output The data to pass into the event
97
+ */
98
+ function createDoneActorEvent(invokeId, output) {
99
+ return {
100
+ type: `xstate.done.actor.${invokeId}`,
101
+ output
102
+ };
103
+ }
104
+ function createErrorActorEvent(id, data) {
105
+ return {
106
+ type: `xstate.error.actor.${id}`,
107
+ data
108
+ };
109
+ }
110
+ function createInitEvent(input) {
111
+ return {
112
+ type: XSTATE_INIT,
113
+ input
114
+ };
115
+ }
116
+
117
+ /**
118
+ * This function makes sure that unhandled errors are thrown in a separate macrotask.
119
+ * It allows those errors to be detected by global error handlers and reported to bug tracking services
120
+ * without interrupting our own stack of execution.
121
+ *
122
+ * @param err error to be thrown
123
+ */
124
+ function reportUnhandledError(err) {
125
+ setTimeout(() => {
126
+ throw err;
127
+ });
128
+ }
129
+
130
+ const symbolObservable = (() => typeof Symbol === 'function' && Symbol.observable || '@@observable')();
131
+
132
+ let idCounter = 0;
133
+ function createSystem(rootActor) {
134
+ const children = new Map();
135
+ const keyedActors = new Map();
136
+ const reverseKeyedActors = new WeakMap();
137
+ const observers = new Set();
138
+ const system = {
139
+ _bookId: () => `x:${idCounter++}`,
140
+ _register: (sessionId, actorRef) => {
141
+ children.set(sessionId, actorRef);
142
+ return sessionId;
143
+ },
144
+ _unregister: actorRef => {
145
+ children.delete(actorRef.sessionId);
146
+ const systemId = reverseKeyedActors.get(actorRef);
147
+ if (systemId !== undefined) {
148
+ keyedActors.delete(systemId);
149
+ reverseKeyedActors.delete(actorRef);
150
+ }
151
+ },
152
+ get: systemId => {
153
+ return keyedActors.get(systemId);
154
+ },
155
+ _set: (systemId, actorRef) => {
156
+ const existing = keyedActors.get(systemId);
157
+ if (existing && existing !== actorRef) {
158
+ throw new Error(`Actor with system ID '${systemId}' already exists.`);
159
+ }
160
+ keyedActors.set(systemId, actorRef);
161
+ reverseKeyedActors.set(actorRef, systemId);
162
+ },
163
+ inspect: observer => {
164
+ observers.add(observer);
165
+ },
166
+ _sendInspectionEvent: event => {
167
+ const resolvedInspectionEvent = {
168
+ ...event,
169
+ rootId: rootActor.sessionId
170
+ };
171
+ observers.forEach(observer => observer.next?.(resolvedInspectionEvent));
172
+ },
173
+ _relay: (source, target, event) => {
174
+ system._sendInspectionEvent({
175
+ type: '@xstate.event',
176
+ sourceRef: source,
177
+ actorRef: target,
178
+ event
179
+ });
180
+ target._send(event);
181
+ }
182
+ };
183
+ return system;
184
+ }
185
+
186
+ function matchesState(parentStateId, childStateId) {
187
+ const parentStateValue = toStateValue(parentStateId);
188
+ const childStateValue = toStateValue(childStateId);
189
+ if (typeof childStateValue === 'string') {
190
+ if (typeof parentStateValue === 'string') {
191
+ return childStateValue === parentStateValue;
192
+ }
193
+
194
+ // Parent more specific than child
195
+ return false;
196
+ }
197
+ if (typeof parentStateValue === 'string') {
198
+ return parentStateValue in childStateValue;
199
+ }
200
+ return Object.keys(parentStateValue).every(key => {
201
+ if (!(key in childStateValue)) {
202
+ return false;
203
+ }
204
+ return matchesState(parentStateValue[key], childStateValue[key]);
205
+ });
206
+ }
207
+ function toStatePath(stateId) {
208
+ try {
209
+ if (isArray(stateId)) {
210
+ return stateId;
211
+ }
212
+ return stateId.split(STATE_DELIMITER);
213
+ } catch (e) {
214
+ throw new Error(`'${stateId}' is not a valid state path.`);
215
+ }
216
+ }
217
+ function toStateValue(stateValue) {
218
+ if (isMachineSnapshot(stateValue)) {
219
+ return stateValue.value;
220
+ }
221
+ if (typeof stateValue !== 'string') {
222
+ return stateValue;
223
+ }
224
+ const statePath = toStatePath(stateValue);
225
+ return pathToStateValue(statePath);
226
+ }
227
+ function pathToStateValue(statePath) {
228
+ if (statePath.length === 1) {
229
+ return statePath[0];
230
+ }
231
+ const value = {};
232
+ let marker = value;
233
+ for (let i = 0; i < statePath.length - 1; i++) {
234
+ if (i === statePath.length - 2) {
235
+ marker[statePath[i]] = statePath[i + 1];
236
+ } else {
237
+ const previous = marker;
238
+ marker = {};
239
+ previous[statePath[i]] = marker;
240
+ }
241
+ }
242
+ return value;
243
+ }
244
+ function mapValues(collection, iteratee) {
245
+ const result = {};
246
+ const collectionKeys = Object.keys(collection);
247
+ for (let i = 0; i < collectionKeys.length; i++) {
248
+ const key = collectionKeys[i];
249
+ result[key] = iteratee(collection[key], key, collection, i);
250
+ }
251
+ return result;
252
+ }
253
+ function flatten(array) {
254
+ return [].concat(...array);
255
+ }
256
+ function toArrayStrict(value) {
257
+ if (isArray(value)) {
258
+ return value;
259
+ }
260
+ return [value];
261
+ }
262
+ function toArray(value) {
263
+ if (value === undefined) {
264
+ return [];
265
+ }
266
+ return toArrayStrict(value);
267
+ }
268
+ function resolveOutput(mapper, context, event, self) {
269
+ if (typeof mapper === 'function') {
270
+ return mapper({
271
+ context,
272
+ event,
273
+ self
274
+ });
275
+ }
276
+ return mapper;
277
+ }
278
+ function isArray(value) {
279
+ return Array.isArray(value);
280
+ }
281
+ function isErrorActorEvent(event) {
282
+ return event.type.startsWith('xstate.error.actor');
283
+ }
284
+ function toTransitionConfigArray(configLike) {
285
+ return toArrayStrict(configLike).map(transitionLike => {
286
+ if (typeof transitionLike === 'undefined' || typeof transitionLike === 'string') {
287
+ return {
288
+ target: transitionLike
289
+ };
290
+ }
291
+ return transitionLike;
292
+ });
293
+ }
294
+ function normalizeTarget(target) {
295
+ if (target === undefined || target === TARGETLESS_KEY) {
296
+ return undefined;
297
+ }
298
+ return toArray(target);
299
+ }
300
+ function toObserver(nextHandler, errorHandler, completionHandler) {
301
+ const isObserver = typeof nextHandler === 'object';
302
+ const self = isObserver ? nextHandler : undefined;
303
+ return {
304
+ next: (isObserver ? nextHandler.next : nextHandler)?.bind(self),
305
+ error: (isObserver ? nextHandler.error : errorHandler)?.bind(self),
306
+ complete: (isObserver ? nextHandler.complete : completionHandler)?.bind(self)
307
+ };
308
+ }
309
+ function createInvokeId(stateNodeId, index) {
310
+ return `${stateNodeId}[${index}]`;
311
+ }
312
+ function resolveReferencedActor(machine, src) {
313
+ if (src.startsWith('xstate#')) {
314
+ const [, indexStr] = src.match(/\[(\d+)\]$/);
315
+ const node = machine.getStateNodeById(src.slice(7, -(indexStr.length + 2)));
316
+ const invokeConfig = node.config.invoke;
317
+ return (Array.isArray(invokeConfig) ? invokeConfig[indexStr] : invokeConfig).src;
318
+ }
319
+ return machine.implementations.actors[src];
320
+ }
321
+
322
+ const $$ACTOR_TYPE = 1;
323
+ // those values are currently used by @xstate/react directly so it's important to keep the assigned values in sync
324
+ let ProcessingStatus = /*#__PURE__*/function (ProcessingStatus) {
325
+ ProcessingStatus[ProcessingStatus["NotStarted"] = 0] = "NotStarted";
326
+ ProcessingStatus[ProcessingStatus["Running"] = 1] = "Running";
327
+ ProcessingStatus[ProcessingStatus["Stopped"] = 2] = "Stopped";
328
+ return ProcessingStatus;
329
+ }({});
330
+ const defaultOptions = {
331
+ clock: {
332
+ setTimeout: (fn, ms) => {
333
+ return setTimeout(fn, ms);
334
+ },
335
+ clearTimeout: id => {
336
+ return clearTimeout(id);
337
+ }
338
+ },
339
+ logger: console.log.bind(console),
340
+ devTools: false
341
+ };
342
+
343
+ /**
344
+ * An Actor is a running process that can receive events, send events and change its behavior based on the events it receives, which can cause effects outside of the actor. When you run a state machine, it becomes an actor.
345
+ */
346
+ class Actor {
347
+ /**
348
+ * The current internal state of the actor.
349
+ */
350
+
351
+ /**
352
+ * The clock that is responsible for setting and clearing timeouts, such as delayed events and transitions.
353
+ */
354
+
355
+ /**
356
+ * The unique identifier for this actor relative to its parent.
357
+ */
358
+
359
+ /** @internal */
360
+
361
+ // Actor Ref
362
+
363
+ // TODO: add typings for system
364
+
365
+ /**
366
+ * The globally unique process ID for this invocation.
367
+ */
368
+
369
+ /**
370
+ * The system to which this actor belongs.
371
+ */
372
+
373
+ /**
374
+ * Creates a new actor instance for the given logic with the provided options, if any.
375
+ *
376
+ * @param logic The logic to create an actor from
377
+ * @param options Actor options
378
+ */
379
+ constructor(logic, options) {
380
+ this.logic = logic;
381
+ this._state = void 0;
382
+ this.clock = void 0;
383
+ this.options = void 0;
384
+ this.id = void 0;
385
+ this.mailbox = new Mailbox(this._process.bind(this));
386
+ this.delayedEventsMap = {};
387
+ this.observers = new Set();
388
+ this.logger = void 0;
389
+ this._processingStatus = ProcessingStatus.NotStarted;
390
+ this._parent = void 0;
391
+ this._syncSnapshot = void 0;
392
+ this.ref = void 0;
393
+ this._actorScope = void 0;
394
+ this._systemId = void 0;
395
+ this.sessionId = void 0;
396
+ this.system = void 0;
397
+ this._doneEvent = void 0;
398
+ this.src = void 0;
399
+ this._deferred = [];
400
+ const resolvedOptions = {
401
+ ...defaultOptions,
402
+ ...options
403
+ };
404
+ const {
405
+ clock,
406
+ logger,
407
+ parent,
408
+ syncSnapshot,
409
+ id,
410
+ systemId,
411
+ inspect
412
+ } = resolvedOptions;
413
+ this.system = parent?.system ?? createSystem(this);
414
+ if (inspect && !parent) {
415
+ // Always inspect at the system-level
416
+ this.system.inspect(toObserver(inspect));
417
+ }
418
+ this.sessionId = this.system._bookId();
419
+ this.id = id ?? this.sessionId;
420
+ this.logger = logger;
421
+ this.clock = clock;
422
+ this._parent = parent;
423
+ this._syncSnapshot = syncSnapshot;
424
+ this.options = resolvedOptions;
425
+ this.src = resolvedOptions.src ?? logic;
426
+ this.ref = this;
427
+ this._actorScope = {
428
+ self: this,
429
+ id: this.id,
430
+ sessionId: this.sessionId,
431
+ logger: this.logger,
432
+ defer: fn => {
433
+ this._deferred.push(fn);
434
+ },
435
+ system: this.system,
436
+ stopChild: child => {
437
+ if (child._parent !== this) {
438
+ throw new Error(`Cannot stop child actor ${child.id} of ${this.id} because it is not a child`);
439
+ }
440
+ child._stop();
441
+ }
442
+ };
443
+
444
+ // Ensure that the send method is bound to this Actor instance
445
+ // if destructured
446
+ this.send = this.send.bind(this);
447
+ this.system._sendInspectionEvent({
448
+ type: '@xstate.actor',
449
+ actorRef: this
450
+ });
451
+ if (systemId) {
452
+ this._systemId = systemId;
453
+ this.system._set(systemId, this);
454
+ }
455
+ this._initState(options?.state);
456
+ if (systemId && this._state.status !== 'active') {
457
+ this.system._unregister(this);
458
+ }
459
+ }
460
+ _initState(persistedState) {
461
+ this._state = persistedState ? this.logic.restoreState ? this.logic.restoreState(persistedState, this._actorScope) : persistedState : this.logic.getInitialState(this._actorScope, this.options?.input);
462
+ }
463
+
464
+ // array of functions to defer
465
+
466
+ update(snapshot, event) {
467
+ // Update state
468
+ this._state = snapshot;
469
+
470
+ // Execute deferred effects
471
+ let deferredFn;
472
+ while (deferredFn = this._deferred.shift()) {
473
+ deferredFn();
474
+ }
475
+ for (const observer of this.observers) {
476
+ try {
477
+ observer.next?.(snapshot);
478
+ } catch (err) {
479
+ reportUnhandledError(err);
480
+ }
481
+ }
482
+ switch (this._state.status) {
483
+ case 'done':
484
+ this._stopProcedure();
485
+ this._complete();
486
+ this._doneEvent = createDoneActorEvent(this.id, this._state.output);
487
+ if (this._parent) {
488
+ this.system._relay(this, this._parent, this._doneEvent);
489
+ }
490
+ break;
491
+ case 'error':
492
+ this._stopProcedure();
493
+ this._error(this._state.error);
494
+ if (this._parent) {
495
+ this.system._relay(this, this._parent, createErrorActorEvent(this.id, this._state.error));
496
+ }
497
+ break;
498
+ }
499
+ this.system._sendInspectionEvent({
500
+ type: '@xstate.snapshot',
501
+ actorRef: this,
502
+ event,
503
+ snapshot
504
+ });
505
+ }
506
+
507
+ /**
508
+ * Subscribe an observer to an actor’s snapshot values.
509
+ *
510
+ * @remarks
511
+ * The observer will receive the actor’s snapshot value when it is emitted. The observer can be:
512
+ * - A plain function that receives the latest snapshot, or
513
+ * - An observer object whose `.next(snapshot)` method receives the latest snapshot
514
+ *
515
+ * @example
516
+ * ```ts
517
+ * // Observer as a plain function
518
+ * const subscription = actor.subscribe((snapshot) => {
519
+ * console.log(snapshot);
520
+ * });
521
+ * ```
522
+ *
523
+ * @example
524
+ * ```ts
525
+ * // Observer as an object
526
+ * const subscription = actor.subscribe({
527
+ * next(snapshot) {
528
+ * console.log(snapshot);
529
+ * },
530
+ * error(err) {
531
+ * // ...
532
+ * },
533
+ * complete() {
534
+ * // ...
535
+ * },
536
+ * });
537
+ * ```
538
+ *
539
+ * The return value of `actor.subscribe(observer)` is a subscription object that has an `.unsubscribe()` method. You can call `subscription.unsubscribe()` to unsubscribe the observer:
540
+ *
541
+ * @example
542
+ * ```ts
543
+ * const subscription = actor.subscribe((snapshot) => {
544
+ * // ...
545
+ * });
546
+ *
547
+ * // Unsubscribe the observer
548
+ * subscription.unsubscribe();
549
+ * ```
550
+ *
551
+ * When the actor is stopped, all of its observers will automatically be unsubscribed.
552
+ *
553
+ * @param observer - Either a plain function that receives the latest snapshot, or an observer object whose `.next(snapshot)` method receives the latest snapshot
554
+ */
555
+
556
+ subscribe(nextListenerOrObserver, errorListener, completeListener) {
557
+ const observer = toObserver(nextListenerOrObserver, errorListener, completeListener);
558
+ if (this._processingStatus !== ProcessingStatus.Stopped) {
559
+ this.observers.add(observer);
560
+ } else {
561
+ try {
562
+ observer.complete?.();
563
+ } catch (err) {
564
+ reportUnhandledError(err);
565
+ }
566
+ }
567
+ return {
568
+ unsubscribe: () => {
569
+ this.observers.delete(observer);
570
+ }
11
571
  };
12
- cache.set(object, memoizedData);
13
- } else if (!(key in memoizedData)) {
14
- memoizedData[key] = fn();
15
572
  }
16
- return memoizedData[key];
573
+
574
+ /**
575
+ * Starts the Actor from the initial state
576
+ */
577
+ start() {
578
+ if (this._processingStatus === ProcessingStatus.Running) {
579
+ // Do not restart the service if it is already started
580
+ return this;
581
+ }
582
+ if (this._syncSnapshot) {
583
+ this.subscribe({
584
+ next: snapshot => {
585
+ if (snapshot.status === 'active') {
586
+ this._parent.send({
587
+ type: `xstate.snapshot.${this.id}`,
588
+ snapshot
589
+ });
590
+ }
591
+ },
592
+ error: () => {}
593
+ });
594
+ }
595
+ this.system._register(this.sessionId, this);
596
+ if (this._systemId) {
597
+ this.system._set(this._systemId, this);
598
+ }
599
+ this._processingStatus = ProcessingStatus.Running;
600
+
601
+ // TODO: this isn't correct when rehydrating
602
+ const initEvent = createInitEvent(this.options.input);
603
+ this.system._sendInspectionEvent({
604
+ type: '@xstate.event',
605
+ sourceRef: this._parent,
606
+ actorRef: this,
607
+ event: initEvent
608
+ });
609
+ const status = this._state.status;
610
+ switch (status) {
611
+ case 'done':
612
+ // a state machine can be "done" upon initialization (it could reach a final state using initial microsteps)
613
+ // we still need to complete observers, flush deferreds etc
614
+ this.update(this._state, initEvent);
615
+ // fallthrough
616
+ case 'error':
617
+ // TODO: rethink cleanup of observers, mailbox, etc
618
+ return this;
619
+ }
620
+ if (this.logic.start) {
621
+ try {
622
+ this.logic.start(this._state, this._actorScope);
623
+ } catch (err) {
624
+ this._stopProcedure();
625
+ this._error(err);
626
+ this._parent?.send(createErrorActorEvent(this.id, err));
627
+ return this;
628
+ }
629
+ }
630
+
631
+ // TODO: this notifies all subscribers but usually this is redundant
632
+ // there is no real change happening here
633
+ // we need to rethink if this needs to be refactored
634
+ this.update(this._state, initEvent);
635
+ if (this.options.devTools) {
636
+ this.attachDevTools();
637
+ }
638
+ this.mailbox.start();
639
+ return this;
640
+ }
641
+ _process(event) {
642
+ // TODO: reexamine what happens when an action (or a guard or smth) throws
643
+ let nextState;
644
+ let caughtError;
645
+ try {
646
+ nextState = this.logic.transition(this._state, event, this._actorScope);
647
+ } catch (err) {
648
+ // we wrap it in a box so we can rethrow it later even if falsy value gets caught here
649
+ caughtError = {
650
+ err
651
+ };
652
+ }
653
+ if (caughtError) {
654
+ const {
655
+ err
656
+ } = caughtError;
657
+ this._stopProcedure();
658
+ this._error(err);
659
+ this._parent?.send(createErrorActorEvent(this.id, err));
660
+ return;
661
+ }
662
+ this.update(nextState, event);
663
+ if (event.type === XSTATE_STOP) {
664
+ this._stopProcedure();
665
+ this._complete();
666
+ }
667
+ }
668
+ _stop() {
669
+ if (this._processingStatus === ProcessingStatus.Stopped) {
670
+ return this;
671
+ }
672
+ this.mailbox.clear();
673
+ if (this._processingStatus === ProcessingStatus.NotStarted) {
674
+ this._processingStatus = ProcessingStatus.Stopped;
675
+ return this;
676
+ }
677
+ this.mailbox.enqueue({
678
+ type: XSTATE_STOP
679
+ });
680
+ return this;
681
+ }
682
+
683
+ /**
684
+ * Stops the Actor and unsubscribe all listeners.
685
+ */
686
+ stop() {
687
+ if (this._parent) {
688
+ throw new Error('A non-root actor cannot be stopped directly.');
689
+ }
690
+ return this._stop();
691
+ }
692
+ _complete() {
693
+ for (const observer of this.observers) {
694
+ try {
695
+ observer.complete?.();
696
+ } catch (err) {
697
+ reportUnhandledError(err);
698
+ }
699
+ }
700
+ this.observers.clear();
701
+ }
702
+ _error(err) {
703
+ if (!this.observers.size) {
704
+ if (!this._parent) {
705
+ reportUnhandledError(err);
706
+ }
707
+ return;
708
+ }
709
+ let reportError = false;
710
+ for (const observer of this.observers) {
711
+ const errorListener = observer.error;
712
+ reportError ||= !errorListener;
713
+ try {
714
+ errorListener?.(err);
715
+ } catch (err2) {
716
+ reportUnhandledError(err2);
717
+ }
718
+ }
719
+ this.observers.clear();
720
+ if (reportError) {
721
+ reportUnhandledError(err);
722
+ }
723
+ }
724
+ _stopProcedure() {
725
+ if (this._processingStatus !== ProcessingStatus.Running) {
726
+ // Actor already stopped; do nothing
727
+ return this;
728
+ }
729
+
730
+ // Cancel all delayed events
731
+ for (const key of Object.keys(this.delayedEventsMap)) {
732
+ this.clock.clearTimeout(this.delayedEventsMap[key]);
733
+ }
734
+
735
+ // TODO: mailbox.reset
736
+ this.mailbox.clear();
737
+ // TODO: after `stop` we must prepare ourselves for receiving events again
738
+ // events sent *after* stop signal must be queued
739
+ // it seems like this should be the common behavior for all of our consumers
740
+ // so perhaps this should be unified somehow for all of them
741
+ this.mailbox = new Mailbox(this._process.bind(this));
742
+ this._processingStatus = ProcessingStatus.Stopped;
743
+ this.system._unregister(this);
744
+ return this;
745
+ }
746
+
747
+ /**
748
+ * @internal
749
+ */
750
+ _send(event) {
751
+ if (this._processingStatus === ProcessingStatus.Stopped) {
752
+ return;
753
+ }
754
+ this.mailbox.enqueue(event);
755
+ }
756
+
757
+ /**
758
+ * Sends an event to the running Actor to trigger a transition.
759
+ *
760
+ * @param event The event to send
761
+ */
762
+ send(event) {
763
+ this.system._relay(undefined, this, event);
764
+ }
765
+
766
+ /**
767
+ * TODO: figure out a way to do this within the machine
768
+ * @internal
769
+ */
770
+ delaySend(params) {
771
+ const {
772
+ event,
773
+ id,
774
+ delay
775
+ } = params;
776
+ const timerId = this.clock.setTimeout(() => {
777
+ this.system._relay(this, params.to ?? this, event);
778
+ }, delay);
779
+
780
+ // TODO: consider the rehydration story here
781
+ if (id) {
782
+ this.delayedEventsMap[id] = timerId;
783
+ }
784
+ }
785
+
786
+ /**
787
+ * TODO: figure out a way to do this within the machine
788
+ * @internal
789
+ */
790
+ cancel(sendId) {
791
+ this.clock.clearTimeout(this.delayedEventsMap[sendId]);
792
+ delete this.delayedEventsMap[sendId];
793
+ }
794
+ attachDevTools() {
795
+ const {
796
+ devTools
797
+ } = this.options;
798
+ if (devTools) {
799
+ const resolvedDevToolsAdapter = typeof devTools === 'function' ? devTools : dev_dist_xstateDev.devToolsAdapter;
800
+ resolvedDevToolsAdapter(this);
801
+ }
802
+ }
803
+ toJSON() {
804
+ return {
805
+ xstate$$type: $$ACTOR_TYPE,
806
+ id: this.id
807
+ };
808
+ }
809
+
810
+ /**
811
+ * Obtain the internal state of the actor, which can be persisted.
812
+ *
813
+ * @remarks
814
+ * The internal state can be persisted from any actor, not only machines.
815
+ *
816
+ * Note that the persisted state is not the same as the snapshot from {@link Actor.getSnapshot}. Persisted state represents the internal state of the actor, while snapshots represent the actor's last emitted value.
817
+ *
818
+ * Can be restored with {@link ActorOptions.state}
819
+ *
820
+ * @see https://stately.ai/docs/persistence
821
+ */
822
+
823
+ getPersistedState(options) {
824
+ return this.logic.getPersistedState(this._state, options);
825
+ }
826
+ [symbolObservable]() {
827
+ return this;
828
+ }
829
+
830
+ /**
831
+ * Read an actor’s snapshot synchronously.
832
+ *
833
+ * @remarks
834
+ * The snapshot represent an actor's last emitted value.
835
+ *
836
+ * When an actor receives an event, its internal state may change.
837
+ * An actor may emit a snapshot when a state transition occurs.
838
+ *
839
+ * Note that some actors, such as callback actors generated with `fromCallback`, will not emit snapshots.
840
+ *
841
+ * @see {@link Actor.subscribe} to subscribe to an actor’s snapshot values.
842
+ * @see {@link Actor.getPersistedState} to persist the internal state of an actor (which is more than just a snapshot).
843
+ */
844
+ getSnapshot() {
845
+ return this._state;
846
+ }
17
847
  }
18
848
 
849
+ /**
850
+ * Creates a new `ActorRef` instance for the given machine with the provided options, if any.
851
+ *
852
+ * @param machine The machine to create an actor from
853
+ * @param options `ActorRef` options
854
+ */
855
+
856
+ function createActor(logic, options) {
857
+ const interpreter = new Actor(logic, options);
858
+ return interpreter;
859
+ }
860
+
861
+ /**
862
+ * Creates a new Interpreter instance for the given machine with the provided options, if any.
863
+ *
864
+ * @deprecated Use `createActor` instead
865
+ */
866
+ const interpret = createActor;
867
+
868
+ /**
869
+ * @deprecated Use `Actor` instead.
870
+ */
871
+
19
872
  function resolveCancel(_, state, actionArgs, actionParams, {
20
873
  sendId
21
874
  }) {
@@ -49,14 +902,15 @@ function resolveSpawn(actorScope, state, actionArgs, _actionParams, {
49
902
  input,
50
903
  syncSnapshot
51
904
  }) {
52
- const logic = typeof src === 'string' ? interpreter.resolveReferencedActor(state.machine, src) : src;
905
+ const logic = typeof src === 'string' ? resolveReferencedActor(state.machine, src) : src;
53
906
  const resolvedId = typeof id === 'function' ? id(actionArgs) : id;
54
907
  let actorRef;
55
908
  if (logic) {
56
- actorRef = interpreter.createActor(logic, {
909
+ actorRef = createActor(logic, {
57
910
  id: resolvedId,
58
911
  src,
59
912
  parent: actorScope?.self,
913
+ syncSnapshot,
60
914
  systemId,
61
915
  input: typeof input === 'function' ? input({
62
916
  context: state.context,
@@ -64,19 +918,6 @@ function resolveSpawn(actorScope, state, actionArgs, _actionParams, {
64
918
  self: actorScope?.self
65
919
  }) : input
66
920
  });
67
- if (syncSnapshot) {
68
- actorRef.subscribe({
69
- next: snapshot => {
70
- if (snapshot.status === 'active') {
71
- actorScope.self.send({
72
- type: `xstate.snapshot.${id}`,
73
- snapshot
74
- });
75
- }
76
- },
77
- error: () => {}
78
- });
79
- }
80
921
  }
81
922
  return [cloneMachineSnapshot(state, {
82
923
  children: {
@@ -96,13 +937,13 @@ function executeSpawn(actorScope, {
96
937
  return;
97
938
  }
98
939
  actorScope.defer(() => {
99
- if (actorRef._processingStatus === interpreter.ProcessingStatus.Stopped) {
940
+ if (actorRef._processingStatus === ProcessingStatus.Stopped) {
100
941
  return;
101
942
  }
102
943
  try {
103
944
  actorRef.start?.();
104
945
  } catch (err) {
105
- actorScope.self.send(interpreter.createErrorActorEvent(id, err));
946
+ actorScope.self.send(createErrorActorEvent(id, err));
106
947
  return;
107
948
  }
108
949
  });
@@ -154,7 +995,7 @@ function executeStop(actorScope, actorRef) {
154
995
 
155
996
  // this allows us to prevent an actor from being started if it gets stopped within the same macrostep
156
997
  // this can happen, for example, when the invoking state is being exited immediately by an always transition
157
- if (actorRef._processingStatus !== interpreter.ProcessingStatus.Running) {
998
+ if (actorRef._processingStatus !== ProcessingStatus.Running) {
158
999
  actorScope.stopChild(actorRef);
159
1000
  return;
160
1001
  }
@@ -186,7 +1027,7 @@ function checkStateIn(state, _, {
186
1027
  }) {
187
1028
  if (typeof stateValue === 'string' && isStateId(stateValue)) {
188
1029
  const target = state.machine.getStateNodeById(stateValue);
189
- return state.configuration.some(sn => sn === target);
1030
+ return state._nodes.some(sn => sn === target);
190
1031
  }
191
1032
  return state.matches(stateValue);
192
1033
  }
@@ -297,26 +1138,25 @@ function getProperAncestors(stateNode, toStateNode) {
297
1138
  }
298
1139
  return ancestors;
299
1140
  }
300
- function getConfiguration(stateNodes) {
301
- const configuration = new Set(stateNodes);
302
- const configurationSet = new Set(stateNodes);
303
- const adjList = getAdjList(configurationSet);
1141
+ function getAllStateNodes(stateNodes) {
1142
+ const nodeSet = new Set(stateNodes);
1143
+ const adjList = getAdjList(nodeSet);
304
1144
 
305
1145
  // add descendants
306
- for (const s of configuration) {
1146
+ for (const s of nodeSet) {
307
1147
  // if previously active, add existing child nodes
308
1148
  if (s.type === 'compound' && (!adjList.get(s) || !adjList.get(s).length)) {
309
- getInitialStateNodesWithTheirAncestors(s).forEach(sn => configurationSet.add(sn));
1149
+ getInitialStateNodesWithTheirAncestors(s).forEach(sn => nodeSet.add(sn));
310
1150
  } else {
311
1151
  if (s.type === 'parallel') {
312
1152
  for (const child of getChildren(s)) {
313
1153
  if (child.type === 'history') {
314
1154
  continue;
315
1155
  }
316
- if (!configurationSet.has(child)) {
1156
+ if (!nodeSet.has(child)) {
317
1157
  const initialStates = getInitialStateNodesWithTheirAncestors(child);
318
1158
  for (const initialStateNode of initialStates) {
319
- configurationSet.add(initialStateNode);
1159
+ nodeSet.add(initialStateNode);
320
1160
  }
321
1161
  }
322
1162
  }
@@ -325,14 +1165,14 @@ function getConfiguration(stateNodes) {
325
1165
  }
326
1166
 
327
1167
  // add all ancestors
328
- for (const s of configurationSet) {
1168
+ for (const s of nodeSet) {
329
1169
  let m = s.parent;
330
1170
  while (m) {
331
- configurationSet.add(m);
1171
+ nodeSet.add(m);
332
1172
  m = m.parent;
333
1173
  }
334
1174
  }
335
- return configurationSet;
1175
+ return nodeSet;
336
1176
  }
337
1177
  function getValueFromAdj(baseNode, adjList) {
338
1178
  const childStateNodes = adjList.get(baseNode);
@@ -356,9 +1196,9 @@ function getValueFromAdj(baseNode, adjList) {
356
1196
  }
357
1197
  return stateValue;
358
1198
  }
359
- function getAdjList(configuration) {
1199
+ function getAdjList(stateNodes) {
360
1200
  const adjList = new Map();
361
- for (const s of configuration) {
1201
+ for (const s of stateNodes) {
362
1202
  if (!adjList.has(s)) {
363
1203
  adjList.set(s, []);
364
1204
  }
@@ -371,25 +1211,25 @@ function getAdjList(configuration) {
371
1211
  }
372
1212
  return adjList;
373
1213
  }
374
- function getStateValue(rootNode, configuration) {
375
- const config = getConfiguration(configuration);
1214
+ function getStateValue(rootNode, stateNodes) {
1215
+ const config = getAllStateNodes(stateNodes);
376
1216
  return getValueFromAdj(rootNode, getAdjList(config));
377
1217
  }
378
- function isInFinalState(configuration, stateNode) {
1218
+ function isInFinalState(stateNodeSet, stateNode) {
379
1219
  if (stateNode.type === 'compound') {
380
- return getChildren(stateNode).some(s => s.type === 'final' && configuration.has(s));
1220
+ return getChildren(stateNode).some(s => s.type === 'final' && stateNodeSet.has(s));
381
1221
  }
382
1222
  if (stateNode.type === 'parallel') {
383
- return getChildren(stateNode).every(sn => isInFinalState(configuration, sn));
1223
+ return getChildren(stateNode).every(sn => isInFinalState(stateNodeSet, sn));
384
1224
  }
385
1225
  return stateNode.type === 'final';
386
1226
  }
387
- const isStateId = str => str[0] === interpreter.STATE_IDENTIFIER;
1227
+ const isStateId = str => str[0] === STATE_IDENTIFIER;
388
1228
  function getCandidates(stateNode, receivedEventType) {
389
1229
  const candidates = stateNode.transitions.get(receivedEventType) || [...stateNode.transitions.keys()].filter(descriptor => {
390
1230
  // check if transition is a wildcard transition,
391
1231
  // which matches any non-transient events
392
- if (descriptor === interpreter.WILDCARD) {
1232
+ if (descriptor === WILDCARD) {
393
1233
  return true;
394
1234
  }
395
1235
  if (!descriptor.endsWith('.*')) {
@@ -423,7 +1263,7 @@ function getDelayedTransitions(stateNode) {
423
1263
  }
424
1264
  const mutateEntryExit = (delay, i) => {
425
1265
  const delayRef = typeof delay === 'function' ? `${stateNode.id}:delay[${i}]` : delay;
426
- const afterEvent = interpreter.createAfterEvent(delayRef, stateNode.id);
1266
+ const afterEvent = createAfterEvent(delayRef, stateNode.id);
427
1267
  const eventType = afterEvent.type;
428
1268
  stateNode.entry.push(raise(afterEvent, {
429
1269
  id: eventType,
@@ -439,7 +1279,7 @@ function getDelayedTransitions(stateNode) {
439
1279
  } : configTransition;
440
1280
  const resolvedDelay = !isNaN(+delay) ? +delay : delay;
441
1281
  const eventType = mutateEntryExit(resolvedDelay, i);
442
- return interpreter.toArray(resolvedTransition).map(transition => ({
1282
+ return toArray(resolvedTransition).map(transition => ({
443
1283
  ...transition,
444
1284
  event: eventType,
445
1285
  delay: resolvedDelay
@@ -456,12 +1296,12 @@ function getDelayedTransitions(stateNode) {
456
1296
  });
457
1297
  }
458
1298
  function formatTransition(stateNode, descriptor, transitionConfig) {
459
- const normalizedTarget = interpreter.normalizeTarget(transitionConfig.target);
1299
+ const normalizedTarget = normalizeTarget(transitionConfig.target);
460
1300
  const reenter = transitionConfig.reenter ?? false;
461
1301
  const target = resolveTarget(stateNode, normalizedTarget);
462
1302
  const transition = {
463
1303
  ...transitionConfig,
464
- actions: interpreter.toArray(transitionConfig.actions),
1304
+ actions: toArray(transitionConfig.actions),
465
1305
  guard: transitionConfig.guard,
466
1306
  target,
467
1307
  source: stateNode,
@@ -479,29 +1319,29 @@ function formatTransitions(stateNode) {
479
1319
  const transitions = new Map();
480
1320
  if (stateNode.config.on) {
481
1321
  for (const descriptor of Object.keys(stateNode.config.on)) {
482
- if (descriptor === interpreter.NULL_EVENT) {
1322
+ if (descriptor === NULL_EVENT) {
483
1323
  throw new Error('Null events ("") cannot be specified as a transition key. Use `always: { ... }` instead.');
484
1324
  }
485
1325
  const transitionsConfig = stateNode.config.on[descriptor];
486
- transitions.set(descriptor, interpreter.toTransitionConfigArray(transitionsConfig).map(t => formatTransition(stateNode, descriptor, t)));
1326
+ transitions.set(descriptor, toTransitionConfigArray(transitionsConfig).map(t => formatTransition(stateNode, descriptor, t)));
487
1327
  }
488
1328
  }
489
1329
  if (stateNode.config.onDone) {
490
1330
  const descriptor = `xstate.done.state.${stateNode.id}`;
491
- transitions.set(descriptor, interpreter.toTransitionConfigArray(stateNode.config.onDone).map(t => formatTransition(stateNode, descriptor, t)));
1331
+ transitions.set(descriptor, toTransitionConfigArray(stateNode.config.onDone).map(t => formatTransition(stateNode, descriptor, t)));
492
1332
  }
493
1333
  for (const invokeDef of stateNode.invoke) {
494
1334
  if (invokeDef.onDone) {
495
1335
  const descriptor = `xstate.done.actor.${invokeDef.id}`;
496
- transitions.set(descriptor, interpreter.toTransitionConfigArray(invokeDef.onDone).map(t => formatTransition(stateNode, descriptor, t)));
1336
+ transitions.set(descriptor, toTransitionConfigArray(invokeDef.onDone).map(t => formatTransition(stateNode, descriptor, t)));
497
1337
  }
498
1338
  if (invokeDef.onError) {
499
1339
  const descriptor = `xstate.error.actor.${invokeDef.id}`;
500
- transitions.set(descriptor, interpreter.toTransitionConfigArray(invokeDef.onError).map(t => formatTransition(stateNode, descriptor, t)));
1340
+ transitions.set(descriptor, toTransitionConfigArray(invokeDef.onError).map(t => formatTransition(stateNode, descriptor, t)));
501
1341
  }
502
1342
  if (invokeDef.onSnapshot) {
503
1343
  const descriptor = `xstate.snapshot.${invokeDef.id}`;
504
- transitions.set(descriptor, interpreter.toTransitionConfigArray(invokeDef.onSnapshot).map(t => formatTransition(stateNode, descriptor, t)));
1344
+ transitions.set(descriptor, toTransitionConfigArray(invokeDef.onSnapshot).map(t => formatTransition(stateNode, descriptor, t)));
505
1345
  }
506
1346
  }
507
1347
  for (const delayedTransition of stateNode.after) {
@@ -521,7 +1361,7 @@ function formatInitialTransition(stateNode, _target) {
521
1361
  }
522
1362
  const transition = {
523
1363
  source: stateNode,
524
- actions: !_target || typeof _target === 'string' ? [] : interpreter.toArray(_target.actions),
1364
+ actions: !_target || typeof _target === 'string' ? [] : toArray(_target.actions),
525
1365
  eventType: null,
526
1366
  reenter: false,
527
1367
  target: resolvedTarget ? [resolvedTarget] : [],
@@ -545,7 +1385,7 @@ function resolveTarget(stateNode, targets) {
545
1385
  if (isStateId(target)) {
546
1386
  return stateNode.machine.getStateNodeById(target);
547
1387
  }
548
- const isInternalTarget = target[0] === interpreter.STATE_DELIMITER;
1388
+ const isInternalTarget = target[0] === STATE_DELIMITER;
549
1389
  // If internal target is defined on machine,
550
1390
  // do not include machine key on target
551
1391
  if (isInternalTarget && !stateNode.parent) {
@@ -565,7 +1405,7 @@ function resolveTarget(stateNode, targets) {
565
1405
  });
566
1406
  }
567
1407
  function resolveHistoryDefaultTransition(stateNode) {
568
- const normalizedTarget = interpreter.normalizeTarget(stateNode.config.target);
1408
+ const normalizedTarget = normalizeTarget(stateNode.config.target);
569
1409
  if (!normalizedTarget) {
570
1410
  return stateNode.parent.initial;
571
1411
  }
@@ -634,7 +1474,7 @@ function getStateNodeByPath(stateNode, statePath) {
634
1474
  // throw e;
635
1475
  }
636
1476
  }
637
- const arrayStatePath = interpreter.toStatePath(statePath).slice();
1477
+ const arrayStatePath = toStatePath(statePath).slice();
638
1478
  let currentStateNode = stateNode;
639
1479
  while (arrayStatePath.length) {
640
1480
  const key = arrayStatePath.shift();
@@ -740,13 +1580,13 @@ function hasIntersection(s1, s2) {
740
1580
  }
741
1581
  return false;
742
1582
  }
743
- function removeConflictingTransitions(enabledTransitions, configuration, historyValue) {
1583
+ function removeConflictingTransitions(enabledTransitions, stateNodeSet, historyValue) {
744
1584
  const filteredTransitions = new Set();
745
1585
  for (const t1 of enabledTransitions) {
746
1586
  let t1Preempted = false;
747
1587
  const transitionsToRemove = new Set();
748
1588
  for (const t2 of filteredTransitions) {
749
- if (hasIntersection(computeExitSet([t1], configuration, historyValue), computeExitSet([t2], configuration, historyValue))) {
1589
+ if (hasIntersection(computeExitSet([t1], stateNodeSet, historyValue), computeExitSet([t2], stateNodeSet, historyValue))) {
750
1590
  if (isDescendant(t1.source, t2.source)) {
751
1591
  transitionsToRemove.add(t2);
752
1592
  } else {
@@ -813,7 +1653,7 @@ function getTransitionDomain(transition, historyValue) {
813
1653
  }
814
1654
  return transition.source.machine.root;
815
1655
  }
816
- function computeExitSet(transitions, configuration, historyValue) {
1656
+ function computeExitSet(transitions, stateNodeSet, historyValue) {
817
1657
  const statesToExit = new Set();
818
1658
  for (const t of transitions) {
819
1659
  if (t.target?.length) {
@@ -821,7 +1661,7 @@ function computeExitSet(transitions, configuration, historyValue) {
821
1661
  if (t.reenter && t.source === domain) {
822
1662
  statesToExit.add(domain);
823
1663
  }
824
- for (const stateNode of configuration) {
1664
+ for (const stateNode of stateNodeSet) {
825
1665
  if (isDescendant(stateNode, domain)) {
826
1666
  statesToExit.add(stateNode);
827
1667
  }
@@ -830,12 +1670,12 @@ function computeExitSet(transitions, configuration, historyValue) {
830
1670
  }
831
1671
  return [...statesToExit];
832
1672
  }
833
- function areConfigurationsEqual(previousConfiguration, nextConfigurationSet) {
834
- if (previousConfiguration.length !== nextConfigurationSet.size) {
1673
+ function areStateNodeCollectionsEqual(prevStateNodes, nextStateNodeSet) {
1674
+ if (prevStateNodes.length !== nextStateNodeSet.size) {
835
1675
  return false;
836
1676
  }
837
- for (const node of previousConfiguration) {
838
- if (!nextConfigurationSet.has(node)) {
1677
+ for (const node of prevStateNodes) {
1678
+ if (!nextStateNodeSet.has(node)) {
839
1679
  return false;
840
1680
  }
841
1681
  }
@@ -849,31 +1689,31 @@ function microstep(transitions, currentState, actorScope, event, isInitial, inte
849
1689
  if (!transitions.length) {
850
1690
  return currentState;
851
1691
  }
852
- const mutConfiguration = new Set(currentState.configuration);
1692
+ const mutStateNodeSet = new Set(currentState._nodes);
853
1693
  let historyValue = currentState.historyValue;
854
- const filteredTransitions = removeConflictingTransitions(transitions, mutConfiguration, historyValue);
1694
+ const filteredTransitions = removeConflictingTransitions(transitions, mutStateNodeSet, historyValue);
855
1695
  let nextState = currentState;
856
1696
 
857
1697
  // Exit states
858
1698
  if (!isInitial) {
859
- [nextState, historyValue] = exitStates(nextState, event, actorScope, filteredTransitions, mutConfiguration, historyValue, internalQueue);
1699
+ [nextState, historyValue] = exitStates(nextState, event, actorScope, filteredTransitions, mutStateNodeSet, historyValue, internalQueue);
860
1700
  }
861
1701
 
862
1702
  // Execute transition content
863
1703
  nextState = resolveActionsAndContext(nextState, event, actorScope, filteredTransitions.flatMap(t => t.actions), internalQueue);
864
1704
 
865
1705
  // Enter states
866
- nextState = enterStates(nextState, event, actorScope, filteredTransitions, mutConfiguration, internalQueue, historyValue, isInitial);
867
- const nextConfiguration = [...mutConfiguration];
1706
+ nextState = enterStates(nextState, event, actorScope, filteredTransitions, mutStateNodeSet, internalQueue, historyValue, isInitial);
1707
+ const nextStateNodes = [...mutStateNodeSet];
868
1708
  if (nextState.status === 'done') {
869
- nextState = resolveActionsAndContext(nextState, event, actorScope, nextConfiguration.sort((a, b) => b.order - a.order).flatMap(state => state.exit), internalQueue);
1709
+ nextState = resolveActionsAndContext(nextState, event, actorScope, nextStateNodes.sort((a, b) => b.order - a.order).flatMap(state => state.exit), internalQueue);
870
1710
  }
871
1711
  try {
872
- if (historyValue === currentState.historyValue && areConfigurationsEqual(currentState.configuration, mutConfiguration)) {
1712
+ if (historyValue === currentState.historyValue && areStateNodeCollectionsEqual(currentState._nodes, mutStateNodeSet)) {
873
1713
  return nextState;
874
1714
  }
875
1715
  return cloneMachineSnapshot(nextState, {
876
- configuration: nextConfiguration,
1716
+ _nodes: nextStateNodes,
877
1717
  historyValue
878
1718
  });
879
1719
  } catch (e) {
@@ -886,10 +1726,10 @@ function getMachineOutput(state, event, actorScope, rootNode, rootCompletionNode
886
1726
  if (!rootNode.output) {
887
1727
  return;
888
1728
  }
889
- const doneStateEvent = interpreter.createDoneStateEvent(rootCompletionNode.id, rootCompletionNode.output && rootCompletionNode.parent ? interpreter.resolveOutput(rootCompletionNode.output, state.context, event, actorScope.self) : undefined);
890
- return interpreter.resolveOutput(rootNode.output, state.context, doneStateEvent, actorScope.self);
1729
+ const doneStateEvent = createDoneStateEvent(rootCompletionNode.id, rootCompletionNode.output && rootCompletionNode.parent ? resolveOutput(rootCompletionNode.output, state.context, event, actorScope.self) : undefined);
1730
+ return resolveOutput(rootNode.output, state.context, doneStateEvent, actorScope.self);
891
1731
  }
892
- function enterStates(currentState, event, actorScope, filteredTransitions, mutConfiguration, internalQueue, historyValue, isInitial) {
1732
+ function enterStates(currentState, event, actorScope, filteredTransitions, mutStateNodeSet, internalQueue, historyValue, isInitial) {
893
1733
  let nextState = currentState;
894
1734
  const statesToEnter = new Set();
895
1735
  // those are states that were directly targeted or indirectly targeted by the explicit target
@@ -904,7 +1744,7 @@ function enterStates(currentState, event, actorScope, filteredTransitions, mutCo
904
1744
  }
905
1745
  const completedNodes = new Set();
906
1746
  for (const stateNodeToEnter of [...statesToEnter].sort((a, b) => a.order - b.order)) {
907
- mutConfiguration.add(stateNodeToEnter);
1747
+ mutStateNodeSet.add(stateNodeToEnter);
908
1748
  const actions = [];
909
1749
 
910
1750
  // Add entry actions
@@ -925,11 +1765,11 @@ function enterStates(currentState, event, actorScope, filteredTransitions, mutCo
925
1765
  let ancestorMarker = parent?.type === 'parallel' ? parent : parent?.parent;
926
1766
  let rootCompletionNode = ancestorMarker || stateNodeToEnter;
927
1767
  if (parent?.type === 'compound') {
928
- internalQueue.push(interpreter.createDoneStateEvent(parent.id, stateNodeToEnter.output ? interpreter.resolveOutput(stateNodeToEnter.output, nextState.context, event, actorScope.self) : undefined));
1768
+ internalQueue.push(createDoneStateEvent(parent.id, stateNodeToEnter.output ? resolveOutput(stateNodeToEnter.output, nextState.context, event, actorScope.self) : undefined));
929
1769
  }
930
- while (ancestorMarker?.type === 'parallel' && !completedNodes.has(ancestorMarker) && isInFinalState(mutConfiguration, ancestorMarker)) {
1770
+ while (ancestorMarker?.type === 'parallel' && !completedNodes.has(ancestorMarker) && isInFinalState(mutStateNodeSet, ancestorMarker)) {
931
1771
  completedNodes.add(ancestorMarker);
932
- internalQueue.push(interpreter.createDoneStateEvent(ancestorMarker.id));
1772
+ internalQueue.push(createDoneStateEvent(ancestorMarker.id));
933
1773
  rootCompletionNode = ancestorMarker;
934
1774
  ancestorMarker = ancestorMarker.parent;
935
1775
  }
@@ -1037,9 +1877,9 @@ function addAncestorStatesToEnter(statesToEnter, historyValue, statesForDefaultE
1037
1877
  function addProperAncestorStatesToEnter(stateNode, toStateNode, statesToEnter, historyValue, statesForDefaultEntry) {
1038
1878
  addAncestorStatesToEnter(statesToEnter, historyValue, statesForDefaultEntry, getProperAncestors(stateNode, toStateNode));
1039
1879
  }
1040
- function exitStates(currentState, event, actorScope, transitions, mutConfiguration, historyValue, internalQueue) {
1880
+ function exitStates(currentState, event, actorScope, transitions, mutStateNodeSet, historyValue, internalQueue) {
1041
1881
  let nextState = currentState;
1042
- const statesToExit = computeExitSet(transitions, mutConfiguration, historyValue);
1882
+ const statesToExit = computeExitSet(transitions, mutStateNodeSet, historyValue);
1043
1883
  statesToExit.sort((a, b) => b.order - a.order);
1044
1884
  let changedHistory;
1045
1885
 
@@ -1057,12 +1897,12 @@ function exitStates(currentState, event, actorScope, transitions, mutConfigurati
1057
1897
  changedHistory ??= {
1058
1898
  ...historyValue
1059
1899
  };
1060
- changedHistory[historyNode.id] = Array.from(mutConfiguration).filter(predicate);
1900
+ changedHistory[historyNode.id] = Array.from(mutStateNodeSet).filter(predicate);
1061
1901
  }
1062
1902
  }
1063
1903
  for (const s of statesToExit) {
1064
1904
  nextState = resolveActionsAndContext(nextState, event, actorScope, [...s.exit, ...s.invoke.map(def => stop(def.id))], internalQueue);
1065
- mutConfiguration.delete(s);
1905
+ mutStateNodeSet.delete(s);
1066
1906
  }
1067
1907
  return [nextState, changedHistory || historyValue];
1068
1908
  }
@@ -1092,7 +1932,7 @@ function resolveActionsAndContextWorker(currentState, event, actorScope, actions
1092
1932
  event
1093
1933
  }) : action.params : undefined;
1094
1934
  if (!('resolve' in resolvedAction)) {
1095
- if (actorScope?.self._processingStatus === interpreter.ProcessingStatus.Running) {
1935
+ if (actorScope?.self._processingStatus === ProcessingStatus.Running) {
1096
1936
  resolvedAction(actionArgs, actionParams);
1097
1937
  } else {
1098
1938
  actorScope?.defer(() => {
@@ -1110,7 +1950,7 @@ function resolveActionsAndContextWorker(currentState, event, actorScope, actions
1110
1950
  retries?.push([builtinAction, params]);
1111
1951
  }
1112
1952
  if ('execute' in builtinAction) {
1113
- if (actorScope?.self._processingStatus === interpreter.ProcessingStatus.Running) {
1953
+ if (actorScope?.self._processingStatus === ProcessingStatus.Running) {
1114
1954
  builtinAction.execute(actorScope, params);
1115
1955
  } else {
1116
1956
  actorScope?.defer(builtinAction.execute.bind(null, actorScope, params));
@@ -1138,7 +1978,7 @@ function macrostep(state, event, actorScope, internalQueue = []) {
1138
1978
  const states = [];
1139
1979
 
1140
1980
  // Handle stop event
1141
- if (event.type === interpreter.XSTATE_STOP) {
1981
+ if (event.type === XSTATE_STOP) {
1142
1982
  nextState = cloneMachineSnapshot(stopChildren(nextState, event, actorScope), {
1143
1983
  status: 'stopped'
1144
1984
  });
@@ -1152,7 +1992,7 @@ function macrostep(state, event, actorScope, internalQueue = []) {
1152
1992
 
1153
1993
  // Assume the state is at rest (no raised events)
1154
1994
  // Determine the next state based on the next microstep
1155
- if (nextEvent.type !== interpreter.XSTATE_INIT) {
1995
+ if (nextEvent.type !== XSTATE_INIT) {
1156
1996
  const transitions = selectTransitions(nextEvent, nextState);
1157
1997
  nextState = microstep(transitions, state, actorScope, nextEvent, false, internalQueue);
1158
1998
  states.push(nextState);
@@ -1191,7 +2031,7 @@ function selectTransitions(event, nextState) {
1191
2031
  }
1192
2032
  function selectEventlessTransitions(nextState, event) {
1193
2033
  const enabledTransitionSet = new Set();
1194
- const atomicStates = nextState.configuration.filter(isAtomicStateNode);
2034
+ const atomicStates = nextState._nodes.filter(isAtomicStateNode);
1195
2035
  for (const stateNode of atomicStates) {
1196
2036
  loop: for (const s of [stateNode].concat(getProperAncestors(stateNode, undefined))) {
1197
2037
  if (!s.always) {
@@ -1205,7 +2045,7 @@ function selectEventlessTransitions(nextState, event) {
1205
2045
  }
1206
2046
  }
1207
2047
  }
1208
- return removeConflictingTransitions(Array.from(enabledTransitionSet), new Set(nextState.configuration), nextState.historyValue);
2048
+ return removeConflictingTransitions(Array.from(enabledTransitionSet), new Set(nextState._nodes), nextState.historyValue);
1209
2049
  }
1210
2050
 
1211
2051
  /**
@@ -1214,12 +2054,15 @@ function selectEventlessTransitions(nextState, event) {
1214
2054
  * @param stateValue The partial state value to resolve.
1215
2055
  */
1216
2056
  function resolveStateValue(rootNode, stateValue) {
1217
- const configuration = getConfiguration(getStateNodes(rootNode, stateValue));
1218
- return getStateValue(rootNode, [...configuration]);
2057
+ const allStateNodes = getAllStateNodes(getStateNodes(rootNode, stateValue));
2058
+ return getStateValue(rootNode, [...allStateNodes]);
1219
2059
  }
1220
2060
 
2061
+ function isMachineSnapshot(value) {
2062
+ return !!value && typeof value === 'object' && 'machine' in value && 'value' in value;
2063
+ }
1221
2064
  const machineSnapshotMatches = function matches(testValue) {
1222
- return interpreter.matchesState(testValue, this.value);
2065
+ return matchesState(testValue, this.value);
1223
2066
  };
1224
2067
  const machineSnapshotHasTag = function hasTag(tag) {
1225
2068
  return this.tags.has(tag);
@@ -1232,10 +2075,11 @@ const machineSnapshotCan = function can(event) {
1232
2075
  };
1233
2076
  const machineSnapshotToJSON = function toJSON() {
1234
2077
  const {
1235
- configuration,
2078
+ _nodes: nodes,
1236
2079
  tags,
1237
2080
  machine,
1238
- nextEvents,
2081
+ getNextEvents,
2082
+ getMeta,
1239
2083
  toJSON,
1240
2084
  can,
1241
2085
  hasTag,
@@ -1247,13 +2091,11 @@ const machineSnapshotToJSON = function toJSON() {
1247
2091
  tags: Array.from(tags)
1248
2092
  };
1249
2093
  };
1250
- const machineSnapshotNextEvents = function nextEvents() {
1251
- return memo(this, 'nextEvents', () => {
1252
- return [...new Set(interpreter.flatten([...this.configuration.map(sn => sn.ownEvents)]))];
1253
- });
2094
+ const machineSnapshotGetNextEvents = function getNextEvents() {
2095
+ return [...new Set(flatten([...this._nodes.map(sn => sn.ownEvents)]))];
1254
2096
  };
1255
- const machineSnapshotMeta = function nextEvents() {
1256
- return this.configuration.reduce((acc, stateNode) => {
2097
+ const machineSnapshotGetMeta = function getMeta() {
2098
+ return this._nodes.reduce((acc, stateNode) => {
1257
2099
  if (stateNode.meta !== undefined) {
1258
2100
  acc[stateNode.id] = stateNode.meta;
1259
2101
  }
@@ -1261,48 +2103,35 @@ const machineSnapshotMeta = function nextEvents() {
1261
2103
  }, {});
1262
2104
  };
1263
2105
  function createMachineSnapshot(config, machine) {
1264
- const snapshot = {
2106
+ return {
1265
2107
  status: config.status,
1266
2108
  output: config.output,
1267
2109
  error: config.error,
1268
2110
  machine,
1269
2111
  context: config.context,
1270
- configuration: config.configuration,
1271
- value: getStateValue(machine.root, config.configuration),
1272
- tags: new Set(interpreter.flatten(config.configuration.map(sn => sn.tags))),
2112
+ _nodes: config._nodes,
2113
+ value: getStateValue(machine.root, config._nodes),
2114
+ tags: new Set(flatten(config._nodes.map(sn => sn.tags))),
1273
2115
  children: config.children,
1274
2116
  historyValue: config.historyValue || {},
1275
2117
  // this one is generic in the target and it's hard to create a matching non-generic source signature
1276
2118
  matches: machineSnapshotMatches,
1277
2119
  hasTag: machineSnapshotHasTag,
1278
2120
  can: machineSnapshotCan,
2121
+ getNextEvents: machineSnapshotGetNextEvents,
2122
+ getMeta: machineSnapshotGetMeta,
1279
2123
  toJSON: machineSnapshotToJSON
1280
2124
  };
1281
- Object.defineProperties(snapshot, {
1282
- nextEvents: {
1283
- get: machineSnapshotNextEvents,
1284
- configurable: true,
1285
- enumerable: true
1286
- },
1287
- meta: {
1288
- get: machineSnapshotMeta,
1289
- configurable: true,
1290
- enumerable: true
1291
- }
1292
- });
1293
- return snapshot;
1294
2125
  }
1295
2126
  function cloneMachineSnapshot(state, config = {}) {
1296
- return createMachineSnapshot(
1297
- // TODO: it's wasteful that this spread triggers getters
1298
- {
2127
+ return createMachineSnapshot({
1299
2128
  ...state,
1300
2129
  ...config
1301
2130
  }, state.machine);
1302
2131
  }
1303
2132
  function getPersistedState(state, options) {
1304
2133
  const {
1305
- configuration,
2134
+ _nodes: nodes,
1306
2135
  tags,
1307
2136
  machine,
1308
2137
  children,
@@ -1310,8 +2139,9 @@ function getPersistedState(state, options) {
1310
2139
  can,
1311
2140
  hasTag,
1312
2141
  matches,
2142
+ getNextEvents,
2143
+ getMeta,
1313
2144
  toJSON,
1314
- nextEvents,
1315
2145
  ...jsonValues
1316
2146
  } = state;
1317
2147
  const childrenJson = {};
@@ -1320,7 +2150,8 @@ function getPersistedState(state, options) {
1320
2150
  childrenJson[id] = {
1321
2151
  state: child.getPersistedState(options),
1322
2152
  src: child.src,
1323
- systemId: child._systemId
2153
+ systemId: child._systemId,
2154
+ syncSnapshot: child._syncSnapshot
1324
2155
  };
1325
2156
  }
1326
2157
  const persisted = {
@@ -1340,7 +2171,7 @@ function persistContext(contextPart) {
1340
2171
  ...contextPart
1341
2172
  };
1342
2173
  copy[key] = {
1343
- xstate$$type: interpreter.$$ACTOR_TYPE,
2174
+ xstate$$type: $$ACTOR_TYPE,
1344
2175
  id: value.id
1345
2176
  };
1346
2177
  } else {
@@ -1409,32 +2240,52 @@ function raise(eventOrExpr, options) {
1409
2240
  return raise;
1410
2241
  }
1411
2242
 
2243
+ exports.$$ACTOR_TYPE = $$ACTOR_TYPE;
2244
+ exports.Actor = Actor;
2245
+ exports.NULL_EVENT = NULL_EVENT;
2246
+ exports.ProcessingStatus = ProcessingStatus;
2247
+ exports.STATE_DELIMITER = STATE_DELIMITER;
2248
+ exports.XSTATE_ERROR = XSTATE_ERROR;
2249
+ exports.XSTATE_STOP = XSTATE_STOP;
1412
2250
  exports.and = and;
1413
2251
  exports.cancel = cancel;
1414
2252
  exports.cloneMachineSnapshot = cloneMachineSnapshot;
2253
+ exports.createActor = createActor;
2254
+ exports.createErrorActorEvent = createErrorActorEvent;
2255
+ exports.createInitEvent = createInitEvent;
2256
+ exports.createInvokeId = createInvokeId;
1415
2257
  exports.createMachineSnapshot = createMachineSnapshot;
1416
2258
  exports.evaluateGuard = evaluateGuard;
1417
2259
  exports.formatInitialTransition = formatInitialTransition;
1418
2260
  exports.formatTransition = formatTransition;
1419
2261
  exports.formatTransitions = formatTransitions;
2262
+ exports.getAllStateNodes = getAllStateNodes;
1420
2263
  exports.getCandidates = getCandidates;
1421
- exports.getConfiguration = getConfiguration;
1422
2264
  exports.getDelayedTransitions = getDelayedTransitions;
1423
2265
  exports.getInitialStateNodes = getInitialStateNodes;
1424
2266
  exports.getPersistedState = getPersistedState;
1425
2267
  exports.getStateNodeByPath = getStateNodeByPath;
1426
2268
  exports.getStateNodes = getStateNodes;
2269
+ exports.interpret = interpret;
2270
+ exports.isErrorActorEvent = isErrorActorEvent;
1427
2271
  exports.isInFinalState = isInFinalState;
2272
+ exports.isMachineSnapshot = isMachineSnapshot;
1428
2273
  exports.isStateId = isStateId;
1429
2274
  exports.macrostep = macrostep;
1430
- exports.memo = memo;
2275
+ exports.mapValues = mapValues;
2276
+ exports.matchesState = matchesState;
1431
2277
  exports.microstep = microstep;
1432
2278
  exports.not = not;
1433
2279
  exports.or = or;
2280
+ exports.pathToStateValue = pathToStateValue;
1434
2281
  exports.raise = raise;
1435
2282
  exports.resolveActionsAndContext = resolveActionsAndContext;
2283
+ exports.resolveReferencedActor = resolveReferencedActor;
1436
2284
  exports.resolveStateValue = resolveStateValue;
1437
2285
  exports.spawn = spawn;
1438
2286
  exports.stateIn = stateIn;
1439
2287
  exports.stop = stop;
2288
+ exports.toArray = toArray;
2289
+ exports.toObserver = toObserver;
2290
+ exports.toTransitionConfigArray = toTransitionConfigArray;
1440
2291
  exports.transitionNode = transitionNode;