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,885 @@
1
1
  'use strict';
2
2
 
3
- var interpreter = require('./interpreter-4e8e2a0d.development.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.development.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
+ if (!!mapper && typeof mapper === 'object' && Object.values(mapper).some(val => typeof val === 'function')) {
277
+ console.warn(`Dynamically mapping values to individual properties is deprecated. Use a single function that returns the mapped object instead.\nFound object containing properties whose values are possibly mapping functions: ${Object.entries(mapper).filter(([key, value]) => typeof value === 'function').map(([key, value]) => `\n - ${key}: ${value.toString().replace(/\n\s*/g, '')}`).join('')}`);
278
+ }
279
+ return mapper;
280
+ }
281
+ function isArray(value) {
282
+ return Array.isArray(value);
283
+ }
284
+ function isErrorActorEvent(event) {
285
+ return event.type.startsWith('xstate.error.actor');
286
+ }
287
+ function toTransitionConfigArray(configLike) {
288
+ return toArrayStrict(configLike).map(transitionLike => {
289
+ if (typeof transitionLike === 'undefined' || typeof transitionLike === 'string') {
290
+ return {
291
+ target: transitionLike
292
+ };
293
+ }
294
+ return transitionLike;
295
+ });
296
+ }
297
+ function normalizeTarget(target) {
298
+ if (target === undefined || target === TARGETLESS_KEY) {
299
+ return undefined;
300
+ }
301
+ return toArray(target);
302
+ }
303
+ function toObserver(nextHandler, errorHandler, completionHandler) {
304
+ const isObserver = typeof nextHandler === 'object';
305
+ const self = isObserver ? nextHandler : undefined;
306
+ return {
307
+ next: (isObserver ? nextHandler.next : nextHandler)?.bind(self),
308
+ error: (isObserver ? nextHandler.error : errorHandler)?.bind(self),
309
+ complete: (isObserver ? nextHandler.complete : completionHandler)?.bind(self)
310
+ };
311
+ }
312
+ function createInvokeId(stateNodeId, index) {
313
+ return `${stateNodeId}[${index}]`;
314
+ }
315
+ function resolveReferencedActor(machine, src) {
316
+ if (src.startsWith('xstate#')) {
317
+ const [, indexStr] = src.match(/\[(\d+)\]$/);
318
+ const node = machine.getStateNodeById(src.slice(7, -(indexStr.length + 2)));
319
+ const invokeConfig = node.config.invoke;
320
+ return (Array.isArray(invokeConfig) ? invokeConfig[indexStr] : invokeConfig).src;
321
+ }
322
+ return machine.implementations.actors[src];
323
+ }
324
+
325
+ const $$ACTOR_TYPE = 1;
326
+ // those values are currently used by @xstate/react directly so it's important to keep the assigned values in sync
327
+ let ProcessingStatus = /*#__PURE__*/function (ProcessingStatus) {
328
+ ProcessingStatus[ProcessingStatus["NotStarted"] = 0] = "NotStarted";
329
+ ProcessingStatus[ProcessingStatus["Running"] = 1] = "Running";
330
+ ProcessingStatus[ProcessingStatus["Stopped"] = 2] = "Stopped";
331
+ return ProcessingStatus;
332
+ }({});
333
+ const defaultOptions = {
334
+ clock: {
335
+ setTimeout: (fn, ms) => {
336
+ return setTimeout(fn, ms);
337
+ },
338
+ clearTimeout: id => {
339
+ return clearTimeout(id);
340
+ }
341
+ },
342
+ logger: console.log.bind(console),
343
+ devTools: false
344
+ };
345
+
346
+ /**
347
+ * 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.
348
+ */
349
+ class Actor {
350
+ /**
351
+ * The current internal state of the actor.
352
+ */
353
+
354
+ /**
355
+ * The clock that is responsible for setting and clearing timeouts, such as delayed events and transitions.
356
+ */
357
+
358
+ /**
359
+ * The unique identifier for this actor relative to its parent.
360
+ */
361
+
362
+ /** @internal */
363
+
364
+ // Actor Ref
365
+
366
+ // TODO: add typings for system
367
+
368
+ /**
369
+ * The globally unique process ID for this invocation.
370
+ */
371
+
372
+ /**
373
+ * The system to which this actor belongs.
374
+ */
375
+
376
+ /**
377
+ * Creates a new actor instance for the given logic with the provided options, if any.
378
+ *
379
+ * @param logic The logic to create an actor from
380
+ * @param options Actor options
381
+ */
382
+ constructor(logic, options) {
383
+ this.logic = logic;
384
+ this._state = void 0;
385
+ this.clock = void 0;
386
+ this.options = void 0;
387
+ this.id = void 0;
388
+ this.mailbox = new Mailbox(this._process.bind(this));
389
+ this.delayedEventsMap = {};
390
+ this.observers = new Set();
391
+ this.logger = void 0;
392
+ this._processingStatus = ProcessingStatus.NotStarted;
393
+ this._parent = void 0;
394
+ this._syncSnapshot = void 0;
395
+ this.ref = void 0;
396
+ this._actorScope = void 0;
397
+ this._systemId = void 0;
398
+ this.sessionId = void 0;
399
+ this.system = void 0;
400
+ this._doneEvent = void 0;
401
+ this.src = void 0;
402
+ this._deferred = [];
403
+ const resolvedOptions = {
404
+ ...defaultOptions,
405
+ ...options
406
+ };
407
+ const {
408
+ clock,
409
+ logger,
410
+ parent,
411
+ syncSnapshot,
412
+ id,
413
+ systemId,
414
+ inspect
415
+ } = resolvedOptions;
416
+ this.system = parent?.system ?? createSystem(this);
417
+ if (inspect && !parent) {
418
+ // Always inspect at the system-level
419
+ this.system.inspect(toObserver(inspect));
420
+ }
421
+ this.sessionId = this.system._bookId();
422
+ this.id = id ?? this.sessionId;
423
+ this.logger = logger;
424
+ this.clock = clock;
425
+ this._parent = parent;
426
+ this._syncSnapshot = syncSnapshot;
427
+ this.options = resolvedOptions;
428
+ this.src = resolvedOptions.src ?? logic;
429
+ this.ref = this;
430
+ this._actorScope = {
431
+ self: this,
432
+ id: this.id,
433
+ sessionId: this.sessionId,
434
+ logger: this.logger,
435
+ defer: fn => {
436
+ this._deferred.push(fn);
437
+ },
438
+ system: this.system,
439
+ stopChild: child => {
440
+ if (child._parent !== this) {
441
+ throw new Error(`Cannot stop child actor ${child.id} of ${this.id} because it is not a child`);
442
+ }
443
+ child._stop();
444
+ }
445
+ };
446
+
447
+ // Ensure that the send method is bound to this Actor instance
448
+ // if destructured
449
+ this.send = this.send.bind(this);
450
+ this.system._sendInspectionEvent({
451
+ type: '@xstate.actor',
452
+ actorRef: this
453
+ });
454
+ if (systemId) {
455
+ this._systemId = systemId;
456
+ this.system._set(systemId, this);
457
+ }
458
+ this._initState(options?.state);
459
+ if (systemId && this._state.status !== 'active') {
460
+ this.system._unregister(this);
461
+ }
462
+ }
463
+ _initState(persistedState) {
464
+ this._state = persistedState ? this.logic.restoreState ? this.logic.restoreState(persistedState, this._actorScope) : persistedState : this.logic.getInitialState(this._actorScope, this.options?.input);
465
+ }
466
+
467
+ // array of functions to defer
468
+
469
+ update(snapshot, event) {
470
+ // Update state
471
+ this._state = snapshot;
472
+
473
+ // Execute deferred effects
474
+ let deferredFn;
475
+ while (deferredFn = this._deferred.shift()) {
476
+ deferredFn();
477
+ }
478
+ for (const observer of this.observers) {
479
+ try {
480
+ observer.next?.(snapshot);
481
+ } catch (err) {
482
+ reportUnhandledError(err);
483
+ }
484
+ }
485
+ switch (this._state.status) {
486
+ case 'done':
487
+ this._stopProcedure();
488
+ this._complete();
489
+ this._doneEvent = createDoneActorEvent(this.id, this._state.output);
490
+ if (this._parent) {
491
+ this.system._relay(this, this._parent, this._doneEvent);
492
+ }
493
+ break;
494
+ case 'error':
495
+ this._stopProcedure();
496
+ this._error(this._state.error);
497
+ if (this._parent) {
498
+ this.system._relay(this, this._parent, createErrorActorEvent(this.id, this._state.error));
499
+ }
500
+ break;
501
+ }
502
+ this.system._sendInspectionEvent({
503
+ type: '@xstate.snapshot',
504
+ actorRef: this,
505
+ event,
506
+ snapshot
507
+ });
508
+ }
509
+
510
+ /**
511
+ * Subscribe an observer to an actor’s snapshot values.
512
+ *
513
+ * @remarks
514
+ * The observer will receive the actor’s snapshot value when it is emitted. The observer can be:
515
+ * - A plain function that receives the latest snapshot, or
516
+ * - An observer object whose `.next(snapshot)` method receives the latest snapshot
517
+ *
518
+ * @example
519
+ * ```ts
520
+ * // Observer as a plain function
521
+ * const subscription = actor.subscribe((snapshot) => {
522
+ * console.log(snapshot);
523
+ * });
524
+ * ```
525
+ *
526
+ * @example
527
+ * ```ts
528
+ * // Observer as an object
529
+ * const subscription = actor.subscribe({
530
+ * next(snapshot) {
531
+ * console.log(snapshot);
532
+ * },
533
+ * error(err) {
534
+ * // ...
535
+ * },
536
+ * complete() {
537
+ * // ...
538
+ * },
539
+ * });
540
+ * ```
541
+ *
542
+ * 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:
543
+ *
544
+ * @example
545
+ * ```ts
546
+ * const subscription = actor.subscribe((snapshot) => {
547
+ * // ...
548
+ * });
549
+ *
550
+ * // Unsubscribe the observer
551
+ * subscription.unsubscribe();
552
+ * ```
553
+ *
554
+ * When the actor is stopped, all of its observers will automatically be unsubscribed.
555
+ *
556
+ * @param observer - Either a plain function that receives the latest snapshot, or an observer object whose `.next(snapshot)` method receives the latest snapshot
557
+ */
558
+
559
+ subscribe(nextListenerOrObserver, errorListener, completeListener) {
560
+ const observer = toObserver(nextListenerOrObserver, errorListener, completeListener);
561
+ if (this._processingStatus !== ProcessingStatus.Stopped) {
562
+ this.observers.add(observer);
563
+ } else {
564
+ try {
565
+ observer.complete?.();
566
+ } catch (err) {
567
+ reportUnhandledError(err);
568
+ }
569
+ }
570
+ return {
571
+ unsubscribe: () => {
572
+ this.observers.delete(observer);
573
+ }
11
574
  };
12
- cache.set(object, memoizedData);
13
- } else if (!(key in memoizedData)) {
14
- memoizedData[key] = fn();
15
575
  }
16
- return memoizedData[key];
576
+
577
+ /**
578
+ * Starts the Actor from the initial state
579
+ */
580
+ start() {
581
+ if (this._processingStatus === ProcessingStatus.Running) {
582
+ // Do not restart the service if it is already started
583
+ return this;
584
+ }
585
+ if (this._syncSnapshot) {
586
+ this.subscribe({
587
+ next: snapshot => {
588
+ if (snapshot.status === 'active') {
589
+ this._parent.send({
590
+ type: `xstate.snapshot.${this.id}`,
591
+ snapshot
592
+ });
593
+ }
594
+ },
595
+ error: () => {}
596
+ });
597
+ }
598
+ this.system._register(this.sessionId, this);
599
+ if (this._systemId) {
600
+ this.system._set(this._systemId, this);
601
+ }
602
+ this._processingStatus = ProcessingStatus.Running;
603
+
604
+ // TODO: this isn't correct when rehydrating
605
+ const initEvent = createInitEvent(this.options.input);
606
+ this.system._sendInspectionEvent({
607
+ type: '@xstate.event',
608
+ sourceRef: this._parent,
609
+ actorRef: this,
610
+ event: initEvent
611
+ });
612
+ const status = this._state.status;
613
+ switch (status) {
614
+ case 'done':
615
+ // a state machine can be "done" upon initialization (it could reach a final state using initial microsteps)
616
+ // we still need to complete observers, flush deferreds etc
617
+ this.update(this._state, initEvent);
618
+ // fallthrough
619
+ case 'error':
620
+ // TODO: rethink cleanup of observers, mailbox, etc
621
+ return this;
622
+ }
623
+ if (this.logic.start) {
624
+ try {
625
+ this.logic.start(this._state, this._actorScope);
626
+ } catch (err) {
627
+ this._stopProcedure();
628
+ this._error(err);
629
+ this._parent?.send(createErrorActorEvent(this.id, err));
630
+ return this;
631
+ }
632
+ }
633
+
634
+ // TODO: this notifies all subscribers but usually this is redundant
635
+ // there is no real change happening here
636
+ // we need to rethink if this needs to be refactored
637
+ this.update(this._state, initEvent);
638
+ if (this.options.devTools) {
639
+ this.attachDevTools();
640
+ }
641
+ this.mailbox.start();
642
+ return this;
643
+ }
644
+ _process(event) {
645
+ // TODO: reexamine what happens when an action (or a guard or smth) throws
646
+ let nextState;
647
+ let caughtError;
648
+ try {
649
+ nextState = this.logic.transition(this._state, event, this._actorScope);
650
+ } catch (err) {
651
+ // we wrap it in a box so we can rethrow it later even if falsy value gets caught here
652
+ caughtError = {
653
+ err
654
+ };
655
+ }
656
+ if (caughtError) {
657
+ const {
658
+ err
659
+ } = caughtError;
660
+ this._stopProcedure();
661
+ this._error(err);
662
+ this._parent?.send(createErrorActorEvent(this.id, err));
663
+ return;
664
+ }
665
+ this.update(nextState, event);
666
+ if (event.type === XSTATE_STOP) {
667
+ this._stopProcedure();
668
+ this._complete();
669
+ }
670
+ }
671
+ _stop() {
672
+ if (this._processingStatus === ProcessingStatus.Stopped) {
673
+ return this;
674
+ }
675
+ this.mailbox.clear();
676
+ if (this._processingStatus === ProcessingStatus.NotStarted) {
677
+ this._processingStatus = ProcessingStatus.Stopped;
678
+ return this;
679
+ }
680
+ this.mailbox.enqueue({
681
+ type: XSTATE_STOP
682
+ });
683
+ return this;
684
+ }
685
+
686
+ /**
687
+ * Stops the Actor and unsubscribe all listeners.
688
+ */
689
+ stop() {
690
+ if (this._parent) {
691
+ throw new Error('A non-root actor cannot be stopped directly.');
692
+ }
693
+ return this._stop();
694
+ }
695
+ _complete() {
696
+ for (const observer of this.observers) {
697
+ try {
698
+ observer.complete?.();
699
+ } catch (err) {
700
+ reportUnhandledError(err);
701
+ }
702
+ }
703
+ this.observers.clear();
704
+ }
705
+ _error(err) {
706
+ if (!this.observers.size) {
707
+ if (!this._parent) {
708
+ reportUnhandledError(err);
709
+ }
710
+ return;
711
+ }
712
+ let reportError = false;
713
+ for (const observer of this.observers) {
714
+ const errorListener = observer.error;
715
+ reportError ||= !errorListener;
716
+ try {
717
+ errorListener?.(err);
718
+ } catch (err2) {
719
+ reportUnhandledError(err2);
720
+ }
721
+ }
722
+ this.observers.clear();
723
+ if (reportError) {
724
+ reportUnhandledError(err);
725
+ }
726
+ }
727
+ _stopProcedure() {
728
+ if (this._processingStatus !== ProcessingStatus.Running) {
729
+ // Actor already stopped; do nothing
730
+ return this;
731
+ }
732
+
733
+ // Cancel all delayed events
734
+ for (const key of Object.keys(this.delayedEventsMap)) {
735
+ this.clock.clearTimeout(this.delayedEventsMap[key]);
736
+ }
737
+
738
+ // TODO: mailbox.reset
739
+ this.mailbox.clear();
740
+ // TODO: after `stop` we must prepare ourselves for receiving events again
741
+ // events sent *after* stop signal must be queued
742
+ // it seems like this should be the common behavior for all of our consumers
743
+ // so perhaps this should be unified somehow for all of them
744
+ this.mailbox = new Mailbox(this._process.bind(this));
745
+ this._processingStatus = ProcessingStatus.Stopped;
746
+ this.system._unregister(this);
747
+ return this;
748
+ }
749
+
750
+ /**
751
+ * @internal
752
+ */
753
+ _send(event) {
754
+ if (this._processingStatus === ProcessingStatus.Stopped) {
755
+ // do nothing
756
+ {
757
+ const eventString = JSON.stringify(event);
758
+ console.warn(`Event "${event.type}" was sent to stopped actor "${this.id} (${this.sessionId})". This actor has already reached its final state, and will not transition.\nEvent: ${eventString}`);
759
+ }
760
+ return;
761
+ }
762
+ this.mailbox.enqueue(event);
763
+ }
764
+
765
+ /**
766
+ * Sends an event to the running Actor to trigger a transition.
767
+ *
768
+ * @param event The event to send
769
+ */
770
+ send(event) {
771
+ if (typeof event === 'string') {
772
+ throw new Error(`Only event objects may be sent to actors; use .send({ type: "${event}" }) instead`);
773
+ }
774
+ this.system._relay(undefined, this, event);
775
+ }
776
+
777
+ /**
778
+ * TODO: figure out a way to do this within the machine
779
+ * @internal
780
+ */
781
+ delaySend(params) {
782
+ const {
783
+ event,
784
+ id,
785
+ delay
786
+ } = params;
787
+ const timerId = this.clock.setTimeout(() => {
788
+ this.system._relay(this, params.to ?? this, event);
789
+ }, delay);
790
+
791
+ // TODO: consider the rehydration story here
792
+ if (id) {
793
+ this.delayedEventsMap[id] = timerId;
794
+ }
795
+ }
796
+
797
+ /**
798
+ * TODO: figure out a way to do this within the machine
799
+ * @internal
800
+ */
801
+ cancel(sendId) {
802
+ this.clock.clearTimeout(this.delayedEventsMap[sendId]);
803
+ delete this.delayedEventsMap[sendId];
804
+ }
805
+ attachDevTools() {
806
+ const {
807
+ devTools
808
+ } = this.options;
809
+ if (devTools) {
810
+ const resolvedDevToolsAdapter = typeof devTools === 'function' ? devTools : dev_dist_xstateDev.devToolsAdapter;
811
+ resolvedDevToolsAdapter(this);
812
+ }
813
+ }
814
+ toJSON() {
815
+ return {
816
+ xstate$$type: $$ACTOR_TYPE,
817
+ id: this.id
818
+ };
819
+ }
820
+
821
+ /**
822
+ * Obtain the internal state of the actor, which can be persisted.
823
+ *
824
+ * @remarks
825
+ * The internal state can be persisted from any actor, not only machines.
826
+ *
827
+ * 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.
828
+ *
829
+ * Can be restored with {@link ActorOptions.state}
830
+ *
831
+ * @see https://stately.ai/docs/persistence
832
+ */
833
+
834
+ getPersistedState(options) {
835
+ return this.logic.getPersistedState(this._state, options);
836
+ }
837
+ [symbolObservable]() {
838
+ return this;
839
+ }
840
+
841
+ /**
842
+ * Read an actor’s snapshot synchronously.
843
+ *
844
+ * @remarks
845
+ * The snapshot represent an actor's last emitted value.
846
+ *
847
+ * When an actor receives an event, its internal state may change.
848
+ * An actor may emit a snapshot when a state transition occurs.
849
+ *
850
+ * Note that some actors, such as callback actors generated with `fromCallback`, will not emit snapshots.
851
+ *
852
+ * @see {@link Actor.subscribe} to subscribe to an actor’s snapshot values.
853
+ * @see {@link Actor.getPersistedState} to persist the internal state of an actor (which is more than just a snapshot).
854
+ */
855
+ getSnapshot() {
856
+ return this._state;
857
+ }
17
858
  }
18
859
 
860
+ /**
861
+ * Creates a new `ActorRef` instance for the given machine with the provided options, if any.
862
+ *
863
+ * @param machine The machine to create an actor from
864
+ * @param options `ActorRef` options
865
+ */
866
+
867
+ function createActor(logic, options) {
868
+ const interpreter = new Actor(logic, options);
869
+ return interpreter;
870
+ }
871
+
872
+ /**
873
+ * Creates a new Interpreter instance for the given machine with the provided options, if any.
874
+ *
875
+ * @deprecated Use `createActor` instead
876
+ */
877
+ const interpret = createActor;
878
+
879
+ /**
880
+ * @deprecated Use `Actor` instead.
881
+ */
882
+
19
883
  function resolveCancel(_, state, actionArgs, actionParams, {
20
884
  sendId
21
885
  }) {
@@ -52,14 +916,15 @@ function resolveSpawn(actorScope, state, actionArgs, _actionParams, {
52
916
  input,
53
917
  syncSnapshot
54
918
  }) {
55
- const logic = typeof src === 'string' ? interpreter.resolveReferencedActor(state.machine, src) : src;
919
+ const logic = typeof src === 'string' ? resolveReferencedActor(state.machine, src) : src;
56
920
  const resolvedId = typeof id === 'function' ? id(actionArgs) : id;
57
921
  let actorRef;
58
922
  if (logic) {
59
- actorRef = interpreter.createActor(logic, {
923
+ actorRef = createActor(logic, {
60
924
  id: resolvedId,
61
925
  src,
62
926
  parent: actorScope?.self,
927
+ syncSnapshot,
63
928
  systemId,
64
929
  input: typeof input === 'function' ? input({
65
930
  context: state.context,
@@ -67,19 +932,6 @@ function resolveSpawn(actorScope, state, actionArgs, _actionParams, {
67
932
  self: actorScope?.self
68
933
  }) : input
69
934
  });
70
- if (syncSnapshot) {
71
- actorRef.subscribe({
72
- next: snapshot => {
73
- if (snapshot.status === 'active') {
74
- actorScope.self.send({
75
- type: `xstate.snapshot.${id}`,
76
- snapshot
77
- });
78
- }
79
- },
80
- error: () => {}
81
- });
82
- }
83
935
  }
84
936
  if (!actorRef) {
85
937
  console.warn(`Actor type '${src}' not found in machine '${actorScope.id}'.`);
@@ -102,13 +954,13 @@ function executeSpawn(actorScope, {
102
954
  return;
103
955
  }
104
956
  actorScope.defer(() => {
105
- if (actorRef._processingStatus === interpreter.ProcessingStatus.Stopped) {
957
+ if (actorRef._processingStatus === ProcessingStatus.Stopped) {
106
958
  return;
107
959
  }
108
960
  try {
109
961
  actorRef.start?.();
110
962
  } catch (err) {
111
- actorScope.self.send(interpreter.createErrorActorEvent(id, err));
963
+ actorScope.self.send(createErrorActorEvent(id, err));
112
964
  return;
113
965
  }
114
966
  });
@@ -163,7 +1015,7 @@ function executeStop(actorScope, actorRef) {
163
1015
 
164
1016
  // this allows us to prevent an actor from being started if it gets stopped within the same macrostep
165
1017
  // this can happen, for example, when the invoking state is being exited immediately by an always transition
166
- if (actorRef._processingStatus !== interpreter.ProcessingStatus.Running) {
1018
+ if (actorRef._processingStatus !== ProcessingStatus.Running) {
167
1019
  actorScope.stopChild(actorRef);
168
1020
  return;
169
1021
  }
@@ -198,7 +1050,7 @@ function checkStateIn(state, _, {
198
1050
  }) {
199
1051
  if (typeof stateValue === 'string' && isStateId(stateValue)) {
200
1052
  const target = state.machine.getStateNodeById(stateValue);
201
- return state.configuration.some(sn => sn === target);
1053
+ return state._nodes.some(sn => sn === target);
202
1054
  }
203
1055
  return state.matches(stateValue);
204
1056
  }
@@ -317,26 +1169,25 @@ function getProperAncestors(stateNode, toStateNode) {
317
1169
  }
318
1170
  return ancestors;
319
1171
  }
320
- function getConfiguration(stateNodes) {
321
- const configuration = new Set(stateNodes);
322
- const configurationSet = new Set(stateNodes);
323
- const adjList = getAdjList(configurationSet);
1172
+ function getAllStateNodes(stateNodes) {
1173
+ const nodeSet = new Set(stateNodes);
1174
+ const adjList = getAdjList(nodeSet);
324
1175
 
325
1176
  // add descendants
326
- for (const s of configuration) {
1177
+ for (const s of nodeSet) {
327
1178
  // if previously active, add existing child nodes
328
1179
  if (s.type === 'compound' && (!adjList.get(s) || !adjList.get(s).length)) {
329
- getInitialStateNodesWithTheirAncestors(s).forEach(sn => configurationSet.add(sn));
1180
+ getInitialStateNodesWithTheirAncestors(s).forEach(sn => nodeSet.add(sn));
330
1181
  } else {
331
1182
  if (s.type === 'parallel') {
332
1183
  for (const child of getChildren(s)) {
333
1184
  if (child.type === 'history') {
334
1185
  continue;
335
1186
  }
336
- if (!configurationSet.has(child)) {
1187
+ if (!nodeSet.has(child)) {
337
1188
  const initialStates = getInitialStateNodesWithTheirAncestors(child);
338
1189
  for (const initialStateNode of initialStates) {
339
- configurationSet.add(initialStateNode);
1190
+ nodeSet.add(initialStateNode);
340
1191
  }
341
1192
  }
342
1193
  }
@@ -345,14 +1196,14 @@ function getConfiguration(stateNodes) {
345
1196
  }
346
1197
 
347
1198
  // add all ancestors
348
- for (const s of configurationSet) {
1199
+ for (const s of nodeSet) {
349
1200
  let m = s.parent;
350
1201
  while (m) {
351
- configurationSet.add(m);
1202
+ nodeSet.add(m);
352
1203
  m = m.parent;
353
1204
  }
354
1205
  }
355
- return configurationSet;
1206
+ return nodeSet;
356
1207
  }
357
1208
  function getValueFromAdj(baseNode, adjList) {
358
1209
  const childStateNodes = adjList.get(baseNode);
@@ -376,9 +1227,9 @@ function getValueFromAdj(baseNode, adjList) {
376
1227
  }
377
1228
  return stateValue;
378
1229
  }
379
- function getAdjList(configuration) {
1230
+ function getAdjList(stateNodes) {
380
1231
  const adjList = new Map();
381
- for (const s of configuration) {
1232
+ for (const s of stateNodes) {
382
1233
  if (!adjList.has(s)) {
383
1234
  adjList.set(s, []);
384
1235
  }
@@ -391,25 +1242,25 @@ function getAdjList(configuration) {
391
1242
  }
392
1243
  return adjList;
393
1244
  }
394
- function getStateValue(rootNode, configuration) {
395
- const config = getConfiguration(configuration);
1245
+ function getStateValue(rootNode, stateNodes) {
1246
+ const config = getAllStateNodes(stateNodes);
396
1247
  return getValueFromAdj(rootNode, getAdjList(config));
397
1248
  }
398
- function isInFinalState(configuration, stateNode) {
1249
+ function isInFinalState(stateNodeSet, stateNode) {
399
1250
  if (stateNode.type === 'compound') {
400
- return getChildren(stateNode).some(s => s.type === 'final' && configuration.has(s));
1251
+ return getChildren(stateNode).some(s => s.type === 'final' && stateNodeSet.has(s));
401
1252
  }
402
1253
  if (stateNode.type === 'parallel') {
403
- return getChildren(stateNode).every(sn => isInFinalState(configuration, sn));
1254
+ return getChildren(stateNode).every(sn => isInFinalState(stateNodeSet, sn));
404
1255
  }
405
1256
  return stateNode.type === 'final';
406
1257
  }
407
- const isStateId = str => str[0] === interpreter.STATE_IDENTIFIER;
1258
+ const isStateId = str => str[0] === STATE_IDENTIFIER;
408
1259
  function getCandidates(stateNode, receivedEventType) {
409
1260
  const candidates = stateNode.transitions.get(receivedEventType) || [...stateNode.transitions.keys()].filter(descriptor => {
410
1261
  // check if transition is a wildcard transition,
411
1262
  // which matches any non-transient events
412
- if (descriptor === interpreter.WILDCARD) {
1263
+ if (descriptor === WILDCARD) {
413
1264
  return true;
414
1265
  }
415
1266
  if (!descriptor.endsWith('.*')) {
@@ -449,7 +1300,7 @@ function getDelayedTransitions(stateNode) {
449
1300
  }
450
1301
  const mutateEntryExit = (delay, i) => {
451
1302
  const delayRef = typeof delay === 'function' ? `${stateNode.id}:delay[${i}]` : delay;
452
- const afterEvent = interpreter.createAfterEvent(delayRef, stateNode.id);
1303
+ const afterEvent = createAfterEvent(delayRef, stateNode.id);
453
1304
  const eventType = afterEvent.type;
454
1305
  stateNode.entry.push(raise(afterEvent, {
455
1306
  id: eventType,
@@ -465,7 +1316,7 @@ function getDelayedTransitions(stateNode) {
465
1316
  } : configTransition;
466
1317
  const resolvedDelay = !isNaN(+delay) ? +delay : delay;
467
1318
  const eventType = mutateEntryExit(resolvedDelay, i);
468
- return interpreter.toArray(resolvedTransition).map(transition => ({
1319
+ return toArray(resolvedTransition).map(transition => ({
469
1320
  ...transition,
470
1321
  event: eventType,
471
1322
  delay: resolvedDelay
@@ -482,7 +1333,7 @@ function getDelayedTransitions(stateNode) {
482
1333
  });
483
1334
  }
484
1335
  function formatTransition(stateNode, descriptor, transitionConfig) {
485
- const normalizedTarget = interpreter.normalizeTarget(transitionConfig.target);
1336
+ const normalizedTarget = normalizeTarget(transitionConfig.target);
486
1337
  const reenter = transitionConfig.reenter ?? false;
487
1338
  const target = resolveTarget(stateNode, normalizedTarget);
488
1339
 
@@ -492,7 +1343,7 @@ function formatTransition(stateNode, descriptor, transitionConfig) {
492
1343
  }
493
1344
  const transition = {
494
1345
  ...transitionConfig,
495
- actions: interpreter.toArray(transitionConfig.actions),
1346
+ actions: toArray(transitionConfig.actions),
496
1347
  guard: transitionConfig.guard,
497
1348
  target,
498
1349
  source: stateNode,
@@ -510,29 +1361,29 @@ function formatTransitions(stateNode) {
510
1361
  const transitions = new Map();
511
1362
  if (stateNode.config.on) {
512
1363
  for (const descriptor of Object.keys(stateNode.config.on)) {
513
- if (descriptor === interpreter.NULL_EVENT) {
1364
+ if (descriptor === NULL_EVENT) {
514
1365
  throw new Error('Null events ("") cannot be specified as a transition key. Use `always: { ... }` instead.');
515
1366
  }
516
1367
  const transitionsConfig = stateNode.config.on[descriptor];
517
- transitions.set(descriptor, interpreter.toTransitionConfigArray(transitionsConfig).map(t => formatTransition(stateNode, descriptor, t)));
1368
+ transitions.set(descriptor, toTransitionConfigArray(transitionsConfig).map(t => formatTransition(stateNode, descriptor, t)));
518
1369
  }
519
1370
  }
520
1371
  if (stateNode.config.onDone) {
521
1372
  const descriptor = `xstate.done.state.${stateNode.id}`;
522
- transitions.set(descriptor, interpreter.toTransitionConfigArray(stateNode.config.onDone).map(t => formatTransition(stateNode, descriptor, t)));
1373
+ transitions.set(descriptor, toTransitionConfigArray(stateNode.config.onDone).map(t => formatTransition(stateNode, descriptor, t)));
523
1374
  }
524
1375
  for (const invokeDef of stateNode.invoke) {
525
1376
  if (invokeDef.onDone) {
526
1377
  const descriptor = `xstate.done.actor.${invokeDef.id}`;
527
- transitions.set(descriptor, interpreter.toTransitionConfigArray(invokeDef.onDone).map(t => formatTransition(stateNode, descriptor, t)));
1378
+ transitions.set(descriptor, toTransitionConfigArray(invokeDef.onDone).map(t => formatTransition(stateNode, descriptor, t)));
528
1379
  }
529
1380
  if (invokeDef.onError) {
530
1381
  const descriptor = `xstate.error.actor.${invokeDef.id}`;
531
- transitions.set(descriptor, interpreter.toTransitionConfigArray(invokeDef.onError).map(t => formatTransition(stateNode, descriptor, t)));
1382
+ transitions.set(descriptor, toTransitionConfigArray(invokeDef.onError).map(t => formatTransition(stateNode, descriptor, t)));
532
1383
  }
533
1384
  if (invokeDef.onSnapshot) {
534
1385
  const descriptor = `xstate.snapshot.${invokeDef.id}`;
535
- transitions.set(descriptor, interpreter.toTransitionConfigArray(invokeDef.onSnapshot).map(t => formatTransition(stateNode, descriptor, t)));
1386
+ transitions.set(descriptor, toTransitionConfigArray(invokeDef.onSnapshot).map(t => formatTransition(stateNode, descriptor, t)));
536
1387
  }
537
1388
  }
538
1389
  for (const delayedTransition of stateNode.after) {
@@ -552,7 +1403,7 @@ function formatInitialTransition(stateNode, _target) {
552
1403
  }
553
1404
  const transition = {
554
1405
  source: stateNode,
555
- actions: !_target || typeof _target === 'string' ? [] : interpreter.toArray(_target.actions),
1406
+ actions: !_target || typeof _target === 'string' ? [] : toArray(_target.actions),
556
1407
  eventType: null,
557
1408
  reenter: false,
558
1409
  target: resolvedTarget ? [resolvedTarget] : [],
@@ -576,7 +1427,7 @@ function resolveTarget(stateNode, targets) {
576
1427
  if (isStateId(target)) {
577
1428
  return stateNode.machine.getStateNodeById(target);
578
1429
  }
579
- const isInternalTarget = target[0] === interpreter.STATE_DELIMITER;
1430
+ const isInternalTarget = target[0] === STATE_DELIMITER;
580
1431
  // If internal target is defined on machine,
581
1432
  // do not include machine key on target
582
1433
  if (isInternalTarget && !stateNode.parent) {
@@ -596,7 +1447,7 @@ function resolveTarget(stateNode, targets) {
596
1447
  });
597
1448
  }
598
1449
  function resolveHistoryDefaultTransition(stateNode) {
599
- const normalizedTarget = interpreter.normalizeTarget(stateNode.config.target);
1450
+ const normalizedTarget = normalizeTarget(stateNode.config.target);
600
1451
  if (!normalizedTarget) {
601
1452
  return stateNode.parent.initial;
602
1453
  }
@@ -665,7 +1516,7 @@ function getStateNodeByPath(stateNode, statePath) {
665
1516
  // throw e;
666
1517
  }
667
1518
  }
668
- const arrayStatePath = interpreter.toStatePath(statePath).slice();
1519
+ const arrayStatePath = toStatePath(statePath).slice();
669
1520
  let currentStateNode = stateNode;
670
1521
  while (arrayStatePath.length) {
671
1522
  const key = arrayStatePath.shift();
@@ -771,13 +1622,13 @@ function hasIntersection(s1, s2) {
771
1622
  }
772
1623
  return false;
773
1624
  }
774
- function removeConflictingTransitions(enabledTransitions, configuration, historyValue) {
1625
+ function removeConflictingTransitions(enabledTransitions, stateNodeSet, historyValue) {
775
1626
  const filteredTransitions = new Set();
776
1627
  for (const t1 of enabledTransitions) {
777
1628
  let t1Preempted = false;
778
1629
  const transitionsToRemove = new Set();
779
1630
  for (const t2 of filteredTransitions) {
780
- if (hasIntersection(computeExitSet([t1], configuration, historyValue), computeExitSet([t2], configuration, historyValue))) {
1631
+ if (hasIntersection(computeExitSet([t1], stateNodeSet, historyValue), computeExitSet([t2], stateNodeSet, historyValue))) {
781
1632
  if (isDescendant(t1.source, t2.source)) {
782
1633
  transitionsToRemove.add(t2);
783
1634
  } else {
@@ -844,7 +1695,7 @@ function getTransitionDomain(transition, historyValue) {
844
1695
  }
845
1696
  return transition.source.machine.root;
846
1697
  }
847
- function computeExitSet(transitions, configuration, historyValue) {
1698
+ function computeExitSet(transitions, stateNodeSet, historyValue) {
848
1699
  const statesToExit = new Set();
849
1700
  for (const t of transitions) {
850
1701
  if (t.target?.length) {
@@ -852,7 +1703,7 @@ function computeExitSet(transitions, configuration, historyValue) {
852
1703
  if (t.reenter && t.source === domain) {
853
1704
  statesToExit.add(domain);
854
1705
  }
855
- for (const stateNode of configuration) {
1706
+ for (const stateNode of stateNodeSet) {
856
1707
  if (isDescendant(stateNode, domain)) {
857
1708
  statesToExit.add(stateNode);
858
1709
  }
@@ -861,12 +1712,12 @@ function computeExitSet(transitions, configuration, historyValue) {
861
1712
  }
862
1713
  return [...statesToExit];
863
1714
  }
864
- function areConfigurationsEqual(previousConfiguration, nextConfigurationSet) {
865
- if (previousConfiguration.length !== nextConfigurationSet.size) {
1715
+ function areStateNodeCollectionsEqual(prevStateNodes, nextStateNodeSet) {
1716
+ if (prevStateNodes.length !== nextStateNodeSet.size) {
866
1717
  return false;
867
1718
  }
868
- for (const node of previousConfiguration) {
869
- if (!nextConfigurationSet.has(node)) {
1719
+ for (const node of prevStateNodes) {
1720
+ if (!nextStateNodeSet.has(node)) {
870
1721
  return false;
871
1722
  }
872
1723
  }
@@ -880,31 +1731,31 @@ function microstep(transitions, currentState, actorScope, event, isInitial, inte
880
1731
  if (!transitions.length) {
881
1732
  return currentState;
882
1733
  }
883
- const mutConfiguration = new Set(currentState.configuration);
1734
+ const mutStateNodeSet = new Set(currentState._nodes);
884
1735
  let historyValue = currentState.historyValue;
885
- const filteredTransitions = removeConflictingTransitions(transitions, mutConfiguration, historyValue);
1736
+ const filteredTransitions = removeConflictingTransitions(transitions, mutStateNodeSet, historyValue);
886
1737
  let nextState = currentState;
887
1738
 
888
1739
  // Exit states
889
1740
  if (!isInitial) {
890
- [nextState, historyValue] = exitStates(nextState, event, actorScope, filteredTransitions, mutConfiguration, historyValue, internalQueue);
1741
+ [nextState, historyValue] = exitStates(nextState, event, actorScope, filteredTransitions, mutStateNodeSet, historyValue, internalQueue);
891
1742
  }
892
1743
 
893
1744
  // Execute transition content
894
1745
  nextState = resolveActionsAndContext(nextState, event, actorScope, filteredTransitions.flatMap(t => t.actions), internalQueue);
895
1746
 
896
1747
  // Enter states
897
- nextState = enterStates(nextState, event, actorScope, filteredTransitions, mutConfiguration, internalQueue, historyValue, isInitial);
898
- const nextConfiguration = [...mutConfiguration];
1748
+ nextState = enterStates(nextState, event, actorScope, filteredTransitions, mutStateNodeSet, internalQueue, historyValue, isInitial);
1749
+ const nextStateNodes = [...mutStateNodeSet];
899
1750
  if (nextState.status === 'done') {
900
- nextState = resolveActionsAndContext(nextState, event, actorScope, nextConfiguration.sort((a, b) => b.order - a.order).flatMap(state => state.exit), internalQueue);
1751
+ nextState = resolveActionsAndContext(nextState, event, actorScope, nextStateNodes.sort((a, b) => b.order - a.order).flatMap(state => state.exit), internalQueue);
901
1752
  }
902
1753
  try {
903
- if (historyValue === currentState.historyValue && areConfigurationsEqual(currentState.configuration, mutConfiguration)) {
1754
+ if (historyValue === currentState.historyValue && areStateNodeCollectionsEqual(currentState._nodes, mutStateNodeSet)) {
904
1755
  return nextState;
905
1756
  }
906
1757
  return cloneMachineSnapshot(nextState, {
907
- configuration: nextConfiguration,
1758
+ _nodes: nextStateNodes,
908
1759
  historyValue
909
1760
  });
910
1761
  } catch (e) {
@@ -917,10 +1768,10 @@ function getMachineOutput(state, event, actorScope, rootNode, rootCompletionNode
917
1768
  if (!rootNode.output) {
918
1769
  return;
919
1770
  }
920
- const doneStateEvent = interpreter.createDoneStateEvent(rootCompletionNode.id, rootCompletionNode.output && rootCompletionNode.parent ? interpreter.resolveOutput(rootCompletionNode.output, state.context, event, actorScope.self) : undefined);
921
- return interpreter.resolveOutput(rootNode.output, state.context, doneStateEvent, actorScope.self);
1771
+ const doneStateEvent = createDoneStateEvent(rootCompletionNode.id, rootCompletionNode.output && rootCompletionNode.parent ? resolveOutput(rootCompletionNode.output, state.context, event, actorScope.self) : undefined);
1772
+ return resolveOutput(rootNode.output, state.context, doneStateEvent, actorScope.self);
922
1773
  }
923
- function enterStates(currentState, event, actorScope, filteredTransitions, mutConfiguration, internalQueue, historyValue, isInitial) {
1774
+ function enterStates(currentState, event, actorScope, filteredTransitions, mutStateNodeSet, internalQueue, historyValue, isInitial) {
924
1775
  let nextState = currentState;
925
1776
  const statesToEnter = new Set();
926
1777
  // those are states that were directly targeted or indirectly targeted by the explicit target
@@ -935,7 +1786,7 @@ function enterStates(currentState, event, actorScope, filteredTransitions, mutCo
935
1786
  }
936
1787
  const completedNodes = new Set();
937
1788
  for (const stateNodeToEnter of [...statesToEnter].sort((a, b) => a.order - b.order)) {
938
- mutConfiguration.add(stateNodeToEnter);
1789
+ mutStateNodeSet.add(stateNodeToEnter);
939
1790
  const actions = [];
940
1791
 
941
1792
  // Add entry actions
@@ -956,11 +1807,11 @@ function enterStates(currentState, event, actorScope, filteredTransitions, mutCo
956
1807
  let ancestorMarker = parent?.type === 'parallel' ? parent : parent?.parent;
957
1808
  let rootCompletionNode = ancestorMarker || stateNodeToEnter;
958
1809
  if (parent?.type === 'compound') {
959
- internalQueue.push(interpreter.createDoneStateEvent(parent.id, stateNodeToEnter.output ? interpreter.resolveOutput(stateNodeToEnter.output, nextState.context, event, actorScope.self) : undefined));
1810
+ internalQueue.push(createDoneStateEvent(parent.id, stateNodeToEnter.output ? resolveOutput(stateNodeToEnter.output, nextState.context, event, actorScope.self) : undefined));
960
1811
  }
961
- while (ancestorMarker?.type === 'parallel' && !completedNodes.has(ancestorMarker) && isInFinalState(mutConfiguration, ancestorMarker)) {
1812
+ while (ancestorMarker?.type === 'parallel' && !completedNodes.has(ancestorMarker) && isInFinalState(mutStateNodeSet, ancestorMarker)) {
962
1813
  completedNodes.add(ancestorMarker);
963
- internalQueue.push(interpreter.createDoneStateEvent(ancestorMarker.id));
1814
+ internalQueue.push(createDoneStateEvent(ancestorMarker.id));
964
1815
  rootCompletionNode = ancestorMarker;
965
1816
  ancestorMarker = ancestorMarker.parent;
966
1817
  }
@@ -1068,9 +1919,9 @@ function addAncestorStatesToEnter(statesToEnter, historyValue, statesForDefaultE
1068
1919
  function addProperAncestorStatesToEnter(stateNode, toStateNode, statesToEnter, historyValue, statesForDefaultEntry) {
1069
1920
  addAncestorStatesToEnter(statesToEnter, historyValue, statesForDefaultEntry, getProperAncestors(stateNode, toStateNode));
1070
1921
  }
1071
- function exitStates(currentState, event, actorScope, transitions, mutConfiguration, historyValue, internalQueue) {
1922
+ function exitStates(currentState, event, actorScope, transitions, mutStateNodeSet, historyValue, internalQueue) {
1072
1923
  let nextState = currentState;
1073
- const statesToExit = computeExitSet(transitions, mutConfiguration, historyValue);
1924
+ const statesToExit = computeExitSet(transitions, mutStateNodeSet, historyValue);
1074
1925
  statesToExit.sort((a, b) => b.order - a.order);
1075
1926
  let changedHistory;
1076
1927
 
@@ -1088,12 +1939,12 @@ function exitStates(currentState, event, actorScope, transitions, mutConfigurati
1088
1939
  changedHistory ??= {
1089
1940
  ...historyValue
1090
1941
  };
1091
- changedHistory[historyNode.id] = Array.from(mutConfiguration).filter(predicate);
1942
+ changedHistory[historyNode.id] = Array.from(mutStateNodeSet).filter(predicate);
1092
1943
  }
1093
1944
  }
1094
1945
  for (const s of statesToExit) {
1095
1946
  nextState = resolveActionsAndContext(nextState, event, actorScope, [...s.exit, ...s.invoke.map(def => stop(def.id))], internalQueue);
1096
- mutConfiguration.delete(s);
1947
+ mutStateNodeSet.delete(s);
1097
1948
  }
1098
1949
  return [nextState, changedHistory || historyValue];
1099
1950
  }
@@ -1123,7 +1974,7 @@ function resolveActionsAndContextWorker(currentState, event, actorScope, actions
1123
1974
  event
1124
1975
  }) : action.params : undefined;
1125
1976
  if (!('resolve' in resolvedAction)) {
1126
- if (actorScope?.self._processingStatus === interpreter.ProcessingStatus.Running) {
1977
+ if (actorScope?.self._processingStatus === ProcessingStatus.Running) {
1127
1978
  resolvedAction(actionArgs, actionParams);
1128
1979
  } else {
1129
1980
  actorScope?.defer(() => {
@@ -1141,7 +1992,7 @@ function resolveActionsAndContextWorker(currentState, event, actorScope, actions
1141
1992
  retries?.push([builtinAction, params]);
1142
1993
  }
1143
1994
  if ('execute' in builtinAction) {
1144
- if (actorScope?.self._processingStatus === interpreter.ProcessingStatus.Running) {
1995
+ if (actorScope?.self._processingStatus === ProcessingStatus.Running) {
1145
1996
  builtinAction.execute(actorScope, params);
1146
1997
  } else {
1147
1998
  actorScope?.defer(builtinAction.execute.bind(null, actorScope, params));
@@ -1165,14 +2016,14 @@ function resolveActionsAndContext(currentState, event, actorScope, actions, inte
1165
2016
  return nextState;
1166
2017
  }
1167
2018
  function macrostep(state, event, actorScope, internalQueue = []) {
1168
- if (event.type === interpreter.WILDCARD) {
1169
- throw new Error(`An event cannot have the wildcard type ('${interpreter.WILDCARD}')`);
2019
+ if (event.type === WILDCARD) {
2020
+ throw new Error(`An event cannot have the wildcard type ('${WILDCARD}')`);
1170
2021
  }
1171
2022
  let nextState = state;
1172
2023
  const states = [];
1173
2024
 
1174
2025
  // Handle stop event
1175
- if (event.type === interpreter.XSTATE_STOP) {
2026
+ if (event.type === XSTATE_STOP) {
1176
2027
  nextState = cloneMachineSnapshot(stopChildren(nextState, event, actorScope), {
1177
2028
  status: 'stopped'
1178
2029
  });
@@ -1186,7 +2037,7 @@ function macrostep(state, event, actorScope, internalQueue = []) {
1186
2037
 
1187
2038
  // Assume the state is at rest (no raised events)
1188
2039
  // Determine the next state based on the next microstep
1189
- if (nextEvent.type !== interpreter.XSTATE_INIT) {
2040
+ if (nextEvent.type !== XSTATE_INIT) {
1190
2041
  const transitions = selectTransitions(nextEvent, nextState);
1191
2042
  nextState = microstep(transitions, state, actorScope, nextEvent, false, internalQueue);
1192
2043
  states.push(nextState);
@@ -1225,7 +2076,7 @@ function selectTransitions(event, nextState) {
1225
2076
  }
1226
2077
  function selectEventlessTransitions(nextState, event) {
1227
2078
  const enabledTransitionSet = new Set();
1228
- const atomicStates = nextState.configuration.filter(isAtomicStateNode);
2079
+ const atomicStates = nextState._nodes.filter(isAtomicStateNode);
1229
2080
  for (const stateNode of atomicStates) {
1230
2081
  loop: for (const s of [stateNode].concat(getProperAncestors(stateNode, undefined))) {
1231
2082
  if (!s.always) {
@@ -1239,7 +2090,7 @@ function selectEventlessTransitions(nextState, event) {
1239
2090
  }
1240
2091
  }
1241
2092
  }
1242
- return removeConflictingTransitions(Array.from(enabledTransitionSet), new Set(nextState.configuration), nextState.historyValue);
2093
+ return removeConflictingTransitions(Array.from(enabledTransitionSet), new Set(nextState._nodes), nextState.historyValue);
1243
2094
  }
1244
2095
 
1245
2096
  /**
@@ -1248,12 +2099,15 @@ function selectEventlessTransitions(nextState, event) {
1248
2099
  * @param stateValue The partial state value to resolve.
1249
2100
  */
1250
2101
  function resolveStateValue(rootNode, stateValue) {
1251
- const configuration = getConfiguration(getStateNodes(rootNode, stateValue));
1252
- return getStateValue(rootNode, [...configuration]);
2102
+ const allStateNodes = getAllStateNodes(getStateNodes(rootNode, stateValue));
2103
+ return getStateValue(rootNode, [...allStateNodes]);
1253
2104
  }
1254
2105
 
2106
+ function isMachineSnapshot(value) {
2107
+ return !!value && typeof value === 'object' && 'machine' in value && 'value' in value;
2108
+ }
1255
2109
  const machineSnapshotMatches = function matches(testValue) {
1256
- return interpreter.matchesState(testValue, this.value);
2110
+ return matchesState(testValue, this.value);
1257
2111
  };
1258
2112
  const machineSnapshotHasTag = function hasTag(tag) {
1259
2113
  return this.tags.has(tag);
@@ -1269,10 +2123,11 @@ const machineSnapshotCan = function can(event) {
1269
2123
  };
1270
2124
  const machineSnapshotToJSON = function toJSON() {
1271
2125
  const {
1272
- configuration,
2126
+ _nodes: nodes,
1273
2127
  tags,
1274
2128
  machine,
1275
- nextEvents,
2129
+ getNextEvents,
2130
+ getMeta,
1276
2131
  toJSON,
1277
2132
  can,
1278
2133
  hasTag,
@@ -1284,13 +2139,11 @@ const machineSnapshotToJSON = function toJSON() {
1284
2139
  tags: Array.from(tags)
1285
2140
  };
1286
2141
  };
1287
- const machineSnapshotNextEvents = function nextEvents() {
1288
- return memo(this, 'nextEvents', () => {
1289
- return [...new Set(interpreter.flatten([...this.configuration.map(sn => sn.ownEvents)]))];
1290
- });
2142
+ const machineSnapshotGetNextEvents = function getNextEvents() {
2143
+ return [...new Set(flatten([...this._nodes.map(sn => sn.ownEvents)]))];
1291
2144
  };
1292
- const machineSnapshotMeta = function nextEvents() {
1293
- return this.configuration.reduce((acc, stateNode) => {
2145
+ const machineSnapshotGetMeta = function getMeta() {
2146
+ return this._nodes.reduce((acc, stateNode) => {
1294
2147
  if (stateNode.meta !== undefined) {
1295
2148
  acc[stateNode.id] = stateNode.meta;
1296
2149
  }
@@ -1298,48 +2151,35 @@ const machineSnapshotMeta = function nextEvents() {
1298
2151
  }, {});
1299
2152
  };
1300
2153
  function createMachineSnapshot(config, machine) {
1301
- const snapshot = {
2154
+ return {
1302
2155
  status: config.status,
1303
2156
  output: config.output,
1304
2157
  error: config.error,
1305
2158
  machine,
1306
2159
  context: config.context,
1307
- configuration: config.configuration,
1308
- value: getStateValue(machine.root, config.configuration),
1309
- tags: new Set(interpreter.flatten(config.configuration.map(sn => sn.tags))),
2160
+ _nodes: config._nodes,
2161
+ value: getStateValue(machine.root, config._nodes),
2162
+ tags: new Set(flatten(config._nodes.map(sn => sn.tags))),
1310
2163
  children: config.children,
1311
2164
  historyValue: config.historyValue || {},
1312
2165
  // this one is generic in the target and it's hard to create a matching non-generic source signature
1313
2166
  matches: machineSnapshotMatches,
1314
2167
  hasTag: machineSnapshotHasTag,
1315
2168
  can: machineSnapshotCan,
2169
+ getNextEvents: machineSnapshotGetNextEvents,
2170
+ getMeta: machineSnapshotGetMeta,
1316
2171
  toJSON: machineSnapshotToJSON
1317
2172
  };
1318
- Object.defineProperties(snapshot, {
1319
- nextEvents: {
1320
- get: machineSnapshotNextEvents,
1321
- configurable: true,
1322
- enumerable: true
1323
- },
1324
- meta: {
1325
- get: machineSnapshotMeta,
1326
- configurable: true,
1327
- enumerable: true
1328
- }
1329
- });
1330
- return snapshot;
1331
2173
  }
1332
2174
  function cloneMachineSnapshot(state, config = {}) {
1333
- return createMachineSnapshot(
1334
- // TODO: it's wasteful that this spread triggers getters
1335
- {
2175
+ return createMachineSnapshot({
1336
2176
  ...state,
1337
2177
  ...config
1338
2178
  }, state.machine);
1339
2179
  }
1340
2180
  function getPersistedState(state, options) {
1341
2181
  const {
1342
- configuration,
2182
+ _nodes: nodes,
1343
2183
  tags,
1344
2184
  machine,
1345
2185
  children,
@@ -1347,8 +2187,9 @@ function getPersistedState(state, options) {
1347
2187
  can,
1348
2188
  hasTag,
1349
2189
  matches,
2190
+ getNextEvents,
2191
+ getMeta,
1350
2192
  toJSON,
1351
- nextEvents,
1352
2193
  ...jsonValues
1353
2194
  } = state;
1354
2195
  const childrenJson = {};
@@ -1360,7 +2201,8 @@ function getPersistedState(state, options) {
1360
2201
  childrenJson[id] = {
1361
2202
  state: child.getPersistedState(options),
1362
2203
  src: child.src,
1363
- systemId: child._systemId
2204
+ systemId: child._systemId,
2205
+ syncSnapshot: child._syncSnapshot
1364
2206
  };
1365
2207
  }
1366
2208
  const persisted = {
@@ -1380,7 +2222,7 @@ function persistContext(contextPart) {
1380
2222
  ...contextPart
1381
2223
  };
1382
2224
  copy[key] = {
1383
- xstate$$type: interpreter.$$ACTOR_TYPE,
2225
+ xstate$$type: $$ACTOR_TYPE,
1384
2226
  id: value.id
1385
2227
  };
1386
2228
  } else {
@@ -1452,32 +2294,52 @@ function raise(eventOrExpr, options) {
1452
2294
  return raise;
1453
2295
  }
1454
2296
 
2297
+ exports.$$ACTOR_TYPE = $$ACTOR_TYPE;
2298
+ exports.Actor = Actor;
2299
+ exports.NULL_EVENT = NULL_EVENT;
2300
+ exports.ProcessingStatus = ProcessingStatus;
2301
+ exports.STATE_DELIMITER = STATE_DELIMITER;
2302
+ exports.XSTATE_ERROR = XSTATE_ERROR;
2303
+ exports.XSTATE_STOP = XSTATE_STOP;
1455
2304
  exports.and = and;
1456
2305
  exports.cancel = cancel;
1457
2306
  exports.cloneMachineSnapshot = cloneMachineSnapshot;
2307
+ exports.createActor = createActor;
2308
+ exports.createErrorActorEvent = createErrorActorEvent;
2309
+ exports.createInitEvent = createInitEvent;
2310
+ exports.createInvokeId = createInvokeId;
1458
2311
  exports.createMachineSnapshot = createMachineSnapshot;
1459
2312
  exports.evaluateGuard = evaluateGuard;
1460
2313
  exports.formatInitialTransition = formatInitialTransition;
1461
2314
  exports.formatTransition = formatTransition;
1462
2315
  exports.formatTransitions = formatTransitions;
2316
+ exports.getAllStateNodes = getAllStateNodes;
1463
2317
  exports.getCandidates = getCandidates;
1464
- exports.getConfiguration = getConfiguration;
1465
2318
  exports.getDelayedTransitions = getDelayedTransitions;
1466
2319
  exports.getInitialStateNodes = getInitialStateNodes;
1467
2320
  exports.getPersistedState = getPersistedState;
1468
2321
  exports.getStateNodeByPath = getStateNodeByPath;
1469
2322
  exports.getStateNodes = getStateNodes;
2323
+ exports.interpret = interpret;
2324
+ exports.isErrorActorEvent = isErrorActorEvent;
1470
2325
  exports.isInFinalState = isInFinalState;
2326
+ exports.isMachineSnapshot = isMachineSnapshot;
1471
2327
  exports.isStateId = isStateId;
1472
2328
  exports.macrostep = macrostep;
1473
- exports.memo = memo;
2329
+ exports.mapValues = mapValues;
2330
+ exports.matchesState = matchesState;
1474
2331
  exports.microstep = microstep;
1475
2332
  exports.not = not;
1476
2333
  exports.or = or;
2334
+ exports.pathToStateValue = pathToStateValue;
1477
2335
  exports.raise = raise;
1478
2336
  exports.resolveActionsAndContext = resolveActionsAndContext;
2337
+ exports.resolveReferencedActor = resolveReferencedActor;
1479
2338
  exports.resolveStateValue = resolveStateValue;
1480
2339
  exports.spawn = spawn;
1481
2340
  exports.stateIn = stateIn;
1482
2341
  exports.stop = stop;
2342
+ exports.toArray = toArray;
2343
+ exports.toObserver = toObserver;
2344
+ exports.toTransitionConfigArray = toTransitionConfigArray;
1483
2345
  exports.transitionNode = transitionNode;