xstate 5.0.0-beta.42 → 5.0.0-beta.44

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 (47) 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 +50 -6
  8. package/actors/dist/xstate-actors.development.cjs.js +50 -6
  9. package/actors/dist/xstate-actors.development.esm.js +45 -1
  10. package/actors/dist/xstate-actors.esm.js +45 -1
  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 +8 -12
  14. package/dist/declarations/src/actions/spawn.d.ts +11 -16
  15. package/dist/declarations/src/actors/promise.d.ts +53 -0
  16. package/dist/declarations/src/guards.d.ts +2 -2
  17. package/dist/declarations/src/index.d.ts +1 -1
  18. package/dist/declarations/src/spawn.d.ts +9 -13
  19. package/dist/declarations/src/stateUtils.d.ts +4 -4
  20. package/dist/declarations/src/types.d.ts +56 -22
  21. package/dist/declarations/src/utils.d.ts +2 -10
  22. package/dist/{raise-6b64c553.cjs.js → raise-348cc74e.development.esm.js} +1007 -116
  23. package/dist/{raise-51ae36e5.development.esm.js → raise-5854eaca.esm.js} +925 -101
  24. package/dist/{raise-8f482ce9.development.cjs.js → raise-ed700d14.development.cjs.js} +986 -87
  25. package/dist/{raise-d2084327.esm.js → raise-fb6f017b.cjs.js} +972 -54
  26. package/dist/{send-cc8f864e.development.cjs.js → send-00466e37.development.cjs.js} +14 -17
  27. package/dist/{send-85b562d8.cjs.js → send-53e5693c.cjs.js} +14 -17
  28. package/dist/{send-7a350091.development.esm.js → send-a0193bdb.development.esm.js} +7 -10
  29. package/dist/{send-4e732fa5.esm.js → send-b7b4befa.esm.js} +7 -10
  30. package/dist/xstate.cjs.js +25 -25
  31. package/dist/xstate.cjs.mjs +1 -0
  32. package/dist/xstate.development.cjs.js +25 -25
  33. package/dist/xstate.development.cjs.mjs +1 -0
  34. package/dist/xstate.development.esm.js +5 -7
  35. package/dist/xstate.esm.js +5 -7
  36. package/dist/xstate.umd.min.js +1 -1
  37. package/dist/xstate.umd.min.js.map +1 -1
  38. package/guards/dist/xstate-guards.cjs.js +1 -2
  39. package/guards/dist/xstate-guards.development.cjs.js +1 -2
  40. package/guards/dist/xstate-guards.development.esm.js +1 -2
  41. package/guards/dist/xstate-guards.esm.js +1 -2
  42. package/guards/dist/xstate-guards.umd.min.js.map +1 -1
  43. package/package.json +1 -1
  44. package/dist/interpreter-23e4041c.development.cjs.js +0 -905
  45. package/dist/interpreter-3d0c0ff2.esm.js +0 -864
  46. package/dist/interpreter-b6bdd134.cjs.js +0 -894
  47. package/dist/interpreter-f2620ea7.development.esm.js +0 -875
@@ -1,6 +1,868 @@
1
1
  'use strict';
2
2
 
3
- var interpreter = require('./interpreter-23e4041c.development.cjs.js');
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.ref = void 0;
395
+ this._actorScope = void 0;
396
+ this._systemId = void 0;
397
+ this.sessionId = void 0;
398
+ this.system = void 0;
399
+ this._doneEvent = void 0;
400
+ this.src = void 0;
401
+ this._deferred = [];
402
+ const resolvedOptions = {
403
+ ...defaultOptions,
404
+ ...options
405
+ };
406
+ const {
407
+ clock,
408
+ logger,
409
+ parent,
410
+ id,
411
+ systemId,
412
+ inspect
413
+ } = resolvedOptions;
414
+ this.system = parent?.system ?? createSystem(this);
415
+ if (inspect && !parent) {
416
+ // Always inspect at the system-level
417
+ this.system.inspect(toObserver(inspect));
418
+ }
419
+ this.sessionId = this.system._bookId();
420
+ this.id = id ?? this.sessionId;
421
+ this.logger = logger;
422
+ this.clock = clock;
423
+ this._parent = parent;
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
+ }
571
+ };
572
+ }
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
+ this.system._register(this.sessionId, this);
583
+ if (this._systemId) {
584
+ this.system._set(this._systemId, this);
585
+ }
586
+ this._processingStatus = ProcessingStatus.Running;
587
+
588
+ // TODO: this isn't correct when rehydrating
589
+ const initEvent = createInitEvent(this.options.input);
590
+ this.system._sendInspectionEvent({
591
+ type: '@xstate.event',
592
+ sourceRef: this._parent,
593
+ actorRef: this,
594
+ event: initEvent
595
+ });
596
+ const status = this._state.status;
597
+ switch (status) {
598
+ case 'done':
599
+ // a state machine can be "done" upon initialization (it could reach a final state using initial microsteps)
600
+ // we still need to complete observers, flush deferreds etc
601
+ this.update(this._state, initEvent);
602
+ // fallthrough
603
+ case 'error':
604
+ // TODO: rethink cleanup of observers, mailbox, etc
605
+ return this;
606
+ }
607
+ if (this.logic.start) {
608
+ try {
609
+ this.logic.start(this._state, this._actorScope);
610
+ } catch (err) {
611
+ this._stopProcedure();
612
+ this._error(err);
613
+ this._parent?.send(createErrorActorEvent(this.id, err));
614
+ return this;
615
+ }
616
+ }
617
+
618
+ // TODO: this notifies all subscribers but usually this is redundant
619
+ // there is no real change happening here
620
+ // we need to rethink if this needs to be refactored
621
+ this.update(this._state, initEvent);
622
+ if (this.options.devTools) {
623
+ this.attachDevTools();
624
+ }
625
+ this.mailbox.start();
626
+ return this;
627
+ }
628
+ _process(event) {
629
+ // TODO: reexamine what happens when an action (or a guard or smth) throws
630
+ let nextState;
631
+ let caughtError;
632
+ try {
633
+ nextState = this.logic.transition(this._state, event, this._actorScope);
634
+ } catch (err) {
635
+ // we wrap it in a box so we can rethrow it later even if falsy value gets caught here
636
+ caughtError = {
637
+ err
638
+ };
639
+ }
640
+ if (caughtError) {
641
+ const {
642
+ err
643
+ } = caughtError;
644
+ this._stopProcedure();
645
+ this._error(err);
646
+ this._parent?.send(createErrorActorEvent(this.id, err));
647
+ return;
648
+ }
649
+ this.update(nextState, event);
650
+ if (event.type === XSTATE_STOP) {
651
+ this._stopProcedure();
652
+ this._complete();
653
+ }
654
+ }
655
+ _stop() {
656
+ if (this._processingStatus === ProcessingStatus.Stopped) {
657
+ return this;
658
+ }
659
+ this.mailbox.clear();
660
+ if (this._processingStatus === ProcessingStatus.NotStarted) {
661
+ this._processingStatus = ProcessingStatus.Stopped;
662
+ return this;
663
+ }
664
+ this.mailbox.enqueue({
665
+ type: XSTATE_STOP
666
+ });
667
+ return this;
668
+ }
669
+
670
+ /**
671
+ * Stops the Actor and unsubscribe all listeners.
672
+ */
673
+ stop() {
674
+ if (this._parent) {
675
+ throw new Error('A non-root actor cannot be stopped directly.');
676
+ }
677
+ return this._stop();
678
+ }
679
+ _complete() {
680
+ for (const observer of this.observers) {
681
+ try {
682
+ observer.complete?.();
683
+ } catch (err) {
684
+ reportUnhandledError(err);
685
+ }
686
+ }
687
+ this.observers.clear();
688
+ }
689
+ _error(err) {
690
+ if (!this.observers.size) {
691
+ if (!this._parent) {
692
+ reportUnhandledError(err);
693
+ }
694
+ return;
695
+ }
696
+ let reportError = false;
697
+ for (const observer of this.observers) {
698
+ const errorListener = observer.error;
699
+ reportError ||= !errorListener;
700
+ try {
701
+ errorListener?.(err);
702
+ } catch (err2) {
703
+ reportUnhandledError(err2);
704
+ }
705
+ }
706
+ this.observers.clear();
707
+ if (reportError) {
708
+ reportUnhandledError(err);
709
+ }
710
+ }
711
+ _stopProcedure() {
712
+ if (this._processingStatus !== ProcessingStatus.Running) {
713
+ // Actor already stopped; do nothing
714
+ return this;
715
+ }
716
+
717
+ // Cancel all delayed events
718
+ for (const key of Object.keys(this.delayedEventsMap)) {
719
+ this.clock.clearTimeout(this.delayedEventsMap[key]);
720
+ }
721
+
722
+ // TODO: mailbox.reset
723
+ this.mailbox.clear();
724
+ // TODO: after `stop` we must prepare ourselves for receiving events again
725
+ // events sent *after* stop signal must be queued
726
+ // it seems like this should be the common behavior for all of our consumers
727
+ // so perhaps this should be unified somehow for all of them
728
+ this.mailbox = new Mailbox(this._process.bind(this));
729
+ this._processingStatus = ProcessingStatus.Stopped;
730
+ this.system._unregister(this);
731
+ return this;
732
+ }
733
+
734
+ /**
735
+ * @internal
736
+ */
737
+ _send(event) {
738
+ if (this._processingStatus === ProcessingStatus.Stopped) {
739
+ // do nothing
740
+ {
741
+ const eventString = JSON.stringify(event);
742
+ 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}`);
743
+ }
744
+ return;
745
+ }
746
+ this.mailbox.enqueue(event);
747
+ }
748
+
749
+ /**
750
+ * Sends an event to the running Actor to trigger a transition.
751
+ *
752
+ * @param event The event to send
753
+ */
754
+ send(event) {
755
+ if (typeof event === 'string') {
756
+ throw new Error(`Only event objects may be sent to actors; use .send({ type: "${event}" }) instead`);
757
+ }
758
+ this.system._relay(undefined, this, event);
759
+ }
760
+
761
+ /**
762
+ * TODO: figure out a way to do this within the machine
763
+ * @internal
764
+ */
765
+ delaySend(params) {
766
+ const {
767
+ event,
768
+ id,
769
+ delay
770
+ } = params;
771
+ const timerId = this.clock.setTimeout(() => {
772
+ this.system._relay(this, params.to ?? this, event);
773
+ }, delay);
774
+
775
+ // TODO: consider the rehydration story here
776
+ if (id) {
777
+ this.delayedEventsMap[id] = timerId;
778
+ }
779
+ }
780
+
781
+ /**
782
+ * TODO: figure out a way to do this within the machine
783
+ * @internal
784
+ */
785
+ cancel(sendId) {
786
+ this.clock.clearTimeout(this.delayedEventsMap[sendId]);
787
+ delete this.delayedEventsMap[sendId];
788
+ }
789
+ attachDevTools() {
790
+ const {
791
+ devTools
792
+ } = this.options;
793
+ if (devTools) {
794
+ const resolvedDevToolsAdapter = typeof devTools === 'function' ? devTools : dev_dist_xstateDev.devToolsAdapter;
795
+ resolvedDevToolsAdapter(this);
796
+ }
797
+ }
798
+ toJSON() {
799
+ return {
800
+ xstate$$type: $$ACTOR_TYPE,
801
+ id: this.id
802
+ };
803
+ }
804
+
805
+ /**
806
+ * Obtain the internal state of the actor, which can be persisted.
807
+ *
808
+ * @remarks
809
+ * The internal state can be persisted from any actor, not only machines.
810
+ *
811
+ * 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.
812
+ *
813
+ * Can be restored with {@link ActorOptions.state}
814
+ *
815
+ * @see https://stately.ai/docs/persistence
816
+ */
817
+
818
+ getPersistedState(options) {
819
+ return this.logic.getPersistedState(this._state, options);
820
+ }
821
+ [symbolObservable]() {
822
+ return this;
823
+ }
824
+
825
+ /**
826
+ * Read an actor’s snapshot synchronously.
827
+ *
828
+ * @remarks
829
+ * The snapshot represent an actor's last emitted value.
830
+ *
831
+ * When an actor receives an event, its internal state may change.
832
+ * An actor may emit a snapshot when a state transition occurs.
833
+ *
834
+ * Note that some actors, such as callback actors generated with `fromCallback`, will not emit snapshots.
835
+ *
836
+ * @see {@link Actor.subscribe} to subscribe to an actor’s snapshot values.
837
+ * @see {@link Actor.getPersistedState} to persist the internal state of an actor (which is more than just a snapshot).
838
+ */
839
+ getSnapshot() {
840
+ return this._state;
841
+ }
842
+ }
843
+
844
+ /**
845
+ * Creates a new `ActorRef` instance for the given machine with the provided options, if any.
846
+ *
847
+ * @param machine The machine to create an actor from
848
+ * @param options `ActorRef` options
849
+ */
850
+
851
+ function createActor(logic, options) {
852
+ const interpreter = new Actor(logic, options);
853
+ return interpreter;
854
+ }
855
+
856
+ /**
857
+ * Creates a new Interpreter instance for the given machine with the provided options, if any.
858
+ *
859
+ * @deprecated Use `createActor` instead
860
+ */
861
+ const interpret = createActor;
862
+
863
+ /**
864
+ * @deprecated Use `Actor` instead.
865
+ */
4
866
 
5
867
  const cache = new WeakMap();
6
868
  function memo(object, key, fn) {
@@ -52,25 +914,20 @@ function resolveSpawn(actorScope, state, actionArgs, _actionParams, {
52
914
  input,
53
915
  syncSnapshot
54
916
  }) {
55
- const referenced = typeof src === 'string' ? interpreter.resolveReferencedActor(state.machine, src) : {
56
- src,
57
- input: undefined
58
- };
917
+ const logic = typeof src === 'string' ? resolveReferencedActor(state.machine, src) : src;
59
918
  const resolvedId = typeof id === 'function' ? id(actionArgs) : id;
60
919
  let actorRef;
61
- if (referenced) {
62
- // TODO: inline `input: undefined` should win over the referenced one
63
- const configuredInput = input || referenced.input;
64
- actorRef = interpreter.createActor(referenced.src, {
920
+ if (logic) {
921
+ actorRef = createActor(logic, {
65
922
  id: resolvedId,
66
923
  src,
67
924
  parent: actorScope?.self,
68
925
  systemId,
69
- input: typeof configuredInput === 'function' ? configuredInput({
926
+ input: typeof input === 'function' ? input({
70
927
  context: state.context,
71
928
  event: actionArgs.event,
72
929
  self: actorScope?.self
73
- }) : configuredInput
930
+ }) : input
74
931
  });
75
932
  if (syncSnapshot) {
76
933
  actorRef.subscribe({
@@ -107,13 +964,13 @@ function executeSpawn(actorScope, {
107
964
  return;
108
965
  }
109
966
  actorScope.defer(() => {
110
- if (actorRef._processingStatus === interpreter.ProcessingStatus.Stopped) {
967
+ if (actorRef._processingStatus === ProcessingStatus.Stopped) {
111
968
  return;
112
969
  }
113
970
  try {
114
971
  actorRef.start?.();
115
972
  } catch (err) {
116
- actorScope.self.send(interpreter.createErrorActorEvent(id, err));
973
+ actorScope.self.send(createErrorActorEvent(id, err));
117
974
  return;
118
975
  }
119
976
  });
@@ -168,7 +1025,7 @@ function executeStop(actorScope, actorRef) {
168
1025
 
169
1026
  // this allows us to prevent an actor from being started if it gets stopped within the same macrostep
170
1027
  // this can happen, for example, when the invoking state is being exited immediately by an always transition
171
- if (actorRef._processingStatus !== interpreter.ProcessingStatus.Running) {
1028
+ if (actorRef._processingStatus !== ProcessingStatus.Running) {
172
1029
  actorScope.stopChild(actorRef);
173
1030
  return;
174
1031
  }
@@ -409,12 +1266,12 @@ function isInFinalState(configuration, stateNode) {
409
1266
  }
410
1267
  return stateNode.type === 'final';
411
1268
  }
412
- const isStateId = str => str[0] === interpreter.STATE_IDENTIFIER;
1269
+ const isStateId = str => str[0] === STATE_IDENTIFIER;
413
1270
  function getCandidates(stateNode, receivedEventType) {
414
1271
  const candidates = stateNode.transitions.get(receivedEventType) || [...stateNode.transitions.keys()].filter(descriptor => {
415
1272
  // check if transition is a wildcard transition,
416
1273
  // which matches any non-transient events
417
- if (descriptor === interpreter.WILDCARD) {
1274
+ if (descriptor === WILDCARD) {
418
1275
  return true;
419
1276
  }
420
1277
  if (!descriptor.endsWith('.*')) {
@@ -454,7 +1311,7 @@ function getDelayedTransitions(stateNode) {
454
1311
  }
455
1312
  const mutateEntryExit = (delay, i) => {
456
1313
  const delayRef = typeof delay === 'function' ? `${stateNode.id}:delay[${i}]` : delay;
457
- const afterEvent = interpreter.createAfterEvent(delayRef, stateNode.id);
1314
+ const afterEvent = createAfterEvent(delayRef, stateNode.id);
458
1315
  const eventType = afterEvent.type;
459
1316
  stateNode.entry.push(raise(afterEvent, {
460
1317
  id: eventType,
@@ -470,7 +1327,7 @@ function getDelayedTransitions(stateNode) {
470
1327
  } : configTransition;
471
1328
  const resolvedDelay = !isNaN(+delay) ? +delay : delay;
472
1329
  const eventType = mutateEntryExit(resolvedDelay, i);
473
- return interpreter.toArray(resolvedTransition).map(transition => ({
1330
+ return toArray(resolvedTransition).map(transition => ({
474
1331
  ...transition,
475
1332
  event: eventType,
476
1333
  delay: resolvedDelay
@@ -487,7 +1344,7 @@ function getDelayedTransitions(stateNode) {
487
1344
  });
488
1345
  }
489
1346
  function formatTransition(stateNode, descriptor, transitionConfig) {
490
- const normalizedTarget = interpreter.normalizeTarget(transitionConfig.target);
1347
+ const normalizedTarget = normalizeTarget(transitionConfig.target);
491
1348
  const reenter = transitionConfig.reenter ?? false;
492
1349
  const target = resolveTarget(stateNode, normalizedTarget);
493
1350
 
@@ -497,7 +1354,7 @@ function formatTransition(stateNode, descriptor, transitionConfig) {
497
1354
  }
498
1355
  const transition = {
499
1356
  ...transitionConfig,
500
- actions: interpreter.toArray(transitionConfig.actions),
1357
+ actions: toArray(transitionConfig.actions),
501
1358
  guard: transitionConfig.guard,
502
1359
  target,
503
1360
  source: stateNode,
@@ -515,29 +1372,29 @@ function formatTransitions(stateNode) {
515
1372
  const transitions = new Map();
516
1373
  if (stateNode.config.on) {
517
1374
  for (const descriptor of Object.keys(stateNode.config.on)) {
518
- if (descriptor === interpreter.NULL_EVENT) {
1375
+ if (descriptor === NULL_EVENT) {
519
1376
  throw new Error('Null events ("") cannot be specified as a transition key. Use `always: { ... }` instead.');
520
1377
  }
521
1378
  const transitionsConfig = stateNode.config.on[descriptor];
522
- transitions.set(descriptor, interpreter.toTransitionConfigArray(transitionsConfig).map(t => formatTransition(stateNode, descriptor, t)));
1379
+ transitions.set(descriptor, toTransitionConfigArray(transitionsConfig).map(t => formatTransition(stateNode, descriptor, t)));
523
1380
  }
524
1381
  }
525
1382
  if (stateNode.config.onDone) {
526
1383
  const descriptor = `xstate.done.state.${stateNode.id}`;
527
- transitions.set(descriptor, interpreter.toTransitionConfigArray(stateNode.config.onDone).map(t => formatTransition(stateNode, descriptor, t)));
1384
+ transitions.set(descriptor, toTransitionConfigArray(stateNode.config.onDone).map(t => formatTransition(stateNode, descriptor, t)));
528
1385
  }
529
1386
  for (const invokeDef of stateNode.invoke) {
530
1387
  if (invokeDef.onDone) {
531
1388
  const descriptor = `xstate.done.actor.${invokeDef.id}`;
532
- transitions.set(descriptor, interpreter.toTransitionConfigArray(invokeDef.onDone).map(t => formatTransition(stateNode, descriptor, t)));
1389
+ transitions.set(descriptor, toTransitionConfigArray(invokeDef.onDone).map(t => formatTransition(stateNode, descriptor, t)));
533
1390
  }
534
1391
  if (invokeDef.onError) {
535
1392
  const descriptor = `xstate.error.actor.${invokeDef.id}`;
536
- transitions.set(descriptor, interpreter.toTransitionConfigArray(invokeDef.onError).map(t => formatTransition(stateNode, descriptor, t)));
1393
+ transitions.set(descriptor, toTransitionConfigArray(invokeDef.onError).map(t => formatTransition(stateNode, descriptor, t)));
537
1394
  }
538
1395
  if (invokeDef.onSnapshot) {
539
1396
  const descriptor = `xstate.snapshot.${invokeDef.id}`;
540
- transitions.set(descriptor, interpreter.toTransitionConfigArray(invokeDef.onSnapshot).map(t => formatTransition(stateNode, descriptor, t)));
1397
+ transitions.set(descriptor, toTransitionConfigArray(invokeDef.onSnapshot).map(t => formatTransition(stateNode, descriptor, t)));
541
1398
  }
542
1399
  }
543
1400
  for (const delayedTransition of stateNode.after) {
@@ -557,7 +1414,7 @@ function formatInitialTransition(stateNode, _target) {
557
1414
  }
558
1415
  const transition = {
559
1416
  source: stateNode,
560
- actions: !_target || typeof _target === 'string' ? [] : interpreter.toArray(_target.actions),
1417
+ actions: !_target || typeof _target === 'string' ? [] : toArray(_target.actions),
561
1418
  eventType: null,
562
1419
  reenter: false,
563
1420
  target: resolvedTarget ? [resolvedTarget] : [],
@@ -581,7 +1438,7 @@ function resolveTarget(stateNode, targets) {
581
1438
  if (isStateId(target)) {
582
1439
  return stateNode.machine.getStateNodeById(target);
583
1440
  }
584
- const isInternalTarget = target[0] === interpreter.STATE_DELIMITER;
1441
+ const isInternalTarget = target[0] === STATE_DELIMITER;
585
1442
  // If internal target is defined on machine,
586
1443
  // do not include machine key on target
587
1444
  if (isInternalTarget && !stateNode.parent) {
@@ -601,7 +1458,7 @@ function resolveTarget(stateNode, targets) {
601
1458
  });
602
1459
  }
603
1460
  function resolveHistoryDefaultTransition(stateNode) {
604
- const normalizedTarget = interpreter.normalizeTarget(stateNode.config.target);
1461
+ const normalizedTarget = normalizeTarget(stateNode.config.target);
605
1462
  if (!normalizedTarget) {
606
1463
  return stateNode.parent.initial;
607
1464
  }
@@ -670,7 +1527,7 @@ function getStateNodeByPath(stateNode, statePath) {
670
1527
  // throw e;
671
1528
  }
672
1529
  }
673
- const arrayStatePath = interpreter.toStatePath(statePath).slice();
1530
+ const arrayStatePath = toStatePath(statePath).slice();
674
1531
  let currentStateNode = stateNode;
675
1532
  while (arrayStatePath.length) {
676
1533
  const key = arrayStatePath.shift();
@@ -922,8 +1779,8 @@ function getMachineOutput(state, event, actorScope, rootNode, rootCompletionNode
922
1779
  if (!rootNode.output) {
923
1780
  return;
924
1781
  }
925
- const doneStateEvent = interpreter.createDoneStateEvent(rootCompletionNode.id, rootCompletionNode.output && rootCompletionNode.parent ? interpreter.resolveOutput(rootCompletionNode.output, state.context, event, actorScope.self) : undefined);
926
- return interpreter.resolveOutput(rootNode.output, state.context, doneStateEvent, actorScope.self);
1782
+ const doneStateEvent = createDoneStateEvent(rootCompletionNode.id, rootCompletionNode.output && rootCompletionNode.parent ? resolveOutput(rootCompletionNode.output, state.context, event, actorScope.self) : undefined);
1783
+ return resolveOutput(rootNode.output, state.context, doneStateEvent, actorScope.self);
927
1784
  }
928
1785
  function enterStates(currentState, event, actorScope, filteredTransitions, mutConfiguration, internalQueue, historyValue, isInitial) {
929
1786
  let nextState = currentState;
@@ -961,11 +1818,11 @@ function enterStates(currentState, event, actorScope, filteredTransitions, mutCo
961
1818
  let ancestorMarker = parent?.type === 'parallel' ? parent : parent?.parent;
962
1819
  let rootCompletionNode = ancestorMarker || stateNodeToEnter;
963
1820
  if (parent?.type === 'compound') {
964
- internalQueue.push(interpreter.createDoneStateEvent(parent.id, stateNodeToEnter.output ? interpreter.resolveOutput(stateNodeToEnter.output, nextState.context, event, actorScope.self) : undefined));
1821
+ internalQueue.push(createDoneStateEvent(parent.id, stateNodeToEnter.output ? resolveOutput(stateNodeToEnter.output, nextState.context, event, actorScope.self) : undefined));
965
1822
  }
966
1823
  while (ancestorMarker?.type === 'parallel' && !completedNodes.has(ancestorMarker) && isInFinalState(mutConfiguration, ancestorMarker)) {
967
1824
  completedNodes.add(ancestorMarker);
968
- internalQueue.push(interpreter.createDoneStateEvent(ancestorMarker.id));
1825
+ internalQueue.push(createDoneStateEvent(ancestorMarker.id));
969
1826
  rootCompletionNode = ancestorMarker;
970
1827
  ancestorMarker = ancestorMarker.parent;
971
1828
  }
@@ -1128,7 +1985,7 @@ function resolveActionsAndContextWorker(currentState, event, actorScope, actions
1128
1985
  event
1129
1986
  }) : action.params : undefined;
1130
1987
  if (!('resolve' in resolvedAction)) {
1131
- if (actorScope?.self._processingStatus === interpreter.ProcessingStatus.Running) {
1988
+ if (actorScope?.self._processingStatus === ProcessingStatus.Running) {
1132
1989
  resolvedAction(actionArgs, actionParams);
1133
1990
  } else {
1134
1991
  actorScope?.defer(() => {
@@ -1146,7 +2003,7 @@ function resolveActionsAndContextWorker(currentState, event, actorScope, actions
1146
2003
  retries?.push([builtinAction, params]);
1147
2004
  }
1148
2005
  if ('execute' in builtinAction) {
1149
- if (actorScope?.self._processingStatus === interpreter.ProcessingStatus.Running) {
2006
+ if (actorScope?.self._processingStatus === ProcessingStatus.Running) {
1150
2007
  builtinAction.execute(actorScope, params);
1151
2008
  } else {
1152
2009
  actorScope?.defer(builtinAction.execute.bind(null, actorScope, params));
@@ -1170,14 +2027,14 @@ function resolveActionsAndContext(currentState, event, actorScope, actions, inte
1170
2027
  return nextState;
1171
2028
  }
1172
2029
  function macrostep(state, event, actorScope, internalQueue = []) {
1173
- if (event.type === interpreter.WILDCARD) {
1174
- throw new Error(`An event cannot have the wildcard type ('${interpreter.WILDCARD}')`);
2030
+ if (event.type === WILDCARD) {
2031
+ throw new Error(`An event cannot have the wildcard type ('${WILDCARD}')`);
1175
2032
  }
1176
2033
  let nextState = state;
1177
2034
  const states = [];
1178
2035
 
1179
2036
  // Handle stop event
1180
- if (event.type === interpreter.XSTATE_STOP) {
2037
+ if (event.type === XSTATE_STOP) {
1181
2038
  nextState = cloneMachineSnapshot(stopChildren(nextState, event, actorScope), {
1182
2039
  status: 'stopped'
1183
2040
  });
@@ -1191,7 +2048,7 @@ function macrostep(state, event, actorScope, internalQueue = []) {
1191
2048
 
1192
2049
  // Assume the state is at rest (no raised events)
1193
2050
  // Determine the next state based on the next microstep
1194
- if (nextEvent.type !== interpreter.XSTATE_INIT) {
2051
+ if (nextEvent.type !== XSTATE_INIT) {
1195
2052
  const transitions = selectTransitions(nextEvent, nextState);
1196
2053
  nextState = microstep(transitions, state, actorScope, nextEvent, false, internalQueue);
1197
2054
  states.push(nextState);
@@ -1257,8 +2114,56 @@ function resolveStateValue(rootNode, stateValue) {
1257
2114
  return getStateValue(rootNode, [...configuration]);
1258
2115
  }
1259
2116
 
1260
- function createMachineSnapshot(config, machine) {
2117
+ function isMachineSnapshot(value) {
2118
+ return !!value && typeof value === 'object' && 'machine' in value && 'value' in value;
2119
+ }
2120
+ const machineSnapshotMatches = function matches(testValue) {
2121
+ return matchesState(testValue, this.value);
2122
+ };
2123
+ const machineSnapshotHasTag = function hasTag(tag) {
2124
+ return this.tags.has(tag);
2125
+ };
2126
+ const machineSnapshotCan = function can(event) {
2127
+ if (!this.machine) {
2128
+ console.warn(`state.can(...) used outside of a machine-created State object; this will always return false.`);
2129
+ }
2130
+ const transitionData = this.machine.getTransitionData(this, event);
2131
+ return !!transitionData?.length &&
2132
+ // Check that at least one transition is not forbidden
2133
+ transitionData.some(t => t.target !== undefined || t.actions.length);
2134
+ };
2135
+ const machineSnapshotToJSON = function toJSON() {
2136
+ const {
2137
+ configuration,
2138
+ tags,
2139
+ machine,
2140
+ nextEvents,
2141
+ toJSON,
2142
+ can,
2143
+ hasTag,
2144
+ matches,
2145
+ ...jsonValues
2146
+ } = this;
1261
2147
  return {
2148
+ ...jsonValues,
2149
+ tags: Array.from(tags)
2150
+ };
2151
+ };
2152
+ const machineSnapshotNextEvents = function nextEvents() {
2153
+ return memo(this, 'nextEvents', () => {
2154
+ return [...new Set(flatten([...this.configuration.map(sn => sn.ownEvents)]))];
2155
+ });
2156
+ };
2157
+ const machineSnapshotMeta = function nextEvents() {
2158
+ return this.configuration.reduce((acc, stateNode) => {
2159
+ if (stateNode.meta !== undefined) {
2160
+ acc[stateNode.id] = stateNode.meta;
2161
+ }
2162
+ return acc;
2163
+ }, {});
2164
+ };
2165
+ function createMachineSnapshot(config, machine) {
2166
+ const snapshot = {
1262
2167
  status: config.status,
1263
2168
  output: config.output,
1264
2169
  error: config.error,
@@ -1266,55 +2171,28 @@ function createMachineSnapshot(config, machine) {
1266
2171
  context: config.context,
1267
2172
  configuration: config.configuration,
1268
2173
  value: getStateValue(machine.root, config.configuration),
1269
- tags: new Set(interpreter.flatten(config.configuration.map(sn => sn.tags))),
2174
+ tags: new Set(flatten(config.configuration.map(sn => sn.tags))),
1270
2175
  children: config.children,
1271
2176
  historyValue: config.historyValue || {},
1272
- matches(parentStateValue) {
1273
- return interpreter.matchesState(parentStateValue, this.value);
1274
- },
1275
- hasTag(tag) {
1276
- return this.tags.has(tag);
1277
- },
1278
- can(event) {
1279
- if (!this.machine) {
1280
- console.warn(`state.can(...) used outside of a machine-created State object; this will always return false.`);
1281
- }
1282
- const transitionData = this.machine.getTransitionData(this, event);
1283
- return !!transitionData?.length &&
1284
- // Check that at least one transition is not forbidden
1285
- transitionData.some(t => t.target !== undefined || t.actions.length);
1286
- },
1287
- get nextEvents() {
1288
- return memo(this, 'nextEvents', () => {
1289
- return [...new Set(interpreter.flatten([...this.configuration.map(sn => sn.ownEvents)]))];
1290
- });
1291
- },
1292
- get meta() {
1293
- return this.configuration.reduce((acc, stateNode) => {
1294
- if (stateNode.meta !== undefined) {
1295
- acc[stateNode.id] = stateNode.meta;
1296
- }
1297
- return acc;
1298
- }, {});
2177
+ // this one is generic in the target and it's hard to create a matching non-generic source signature
2178
+ matches: machineSnapshotMatches,
2179
+ hasTag: machineSnapshotHasTag,
2180
+ can: machineSnapshotCan,
2181
+ toJSON: machineSnapshotToJSON
2182
+ };
2183
+ Object.defineProperties(snapshot, {
2184
+ nextEvents: {
2185
+ get: machineSnapshotNextEvents,
2186
+ configurable: true,
2187
+ enumerable: true
1299
2188
  },
1300
- toJSON() {
1301
- const {
1302
- configuration,
1303
- tags,
1304
- machine,
1305
- nextEvents,
1306
- toJSON,
1307
- can,
1308
- hasTag,
1309
- matches,
1310
- ...jsonValues
1311
- } = this;
1312
- return {
1313
- ...jsonValues,
1314
- tags: Array.from(tags)
1315
- };
2189
+ meta: {
2190
+ get: machineSnapshotMeta,
2191
+ configurable: true,
2192
+ enumerable: true
1316
2193
  }
1317
- };
2194
+ });
2195
+ return snapshot;
1318
2196
  }
1319
2197
  function cloneMachineSnapshot(state, config = {}) {
1320
2198
  return createMachineSnapshot(
@@ -1367,7 +2245,7 @@ function persistContext(contextPart) {
1367
2245
  ...contextPart
1368
2246
  };
1369
2247
  copy[key] = {
1370
- xstate$$type: interpreter.$$ACTOR_TYPE,
2248
+ xstate$$type: $$ACTOR_TYPE,
1371
2249
  id: value.id
1372
2250
  };
1373
2251
  } else {
@@ -1439,9 +2317,20 @@ function raise(eventOrExpr, options) {
1439
2317
  return raise;
1440
2318
  }
1441
2319
 
2320
+ exports.$$ACTOR_TYPE = $$ACTOR_TYPE;
2321
+ exports.Actor = Actor;
2322
+ exports.NULL_EVENT = NULL_EVENT;
2323
+ exports.ProcessingStatus = ProcessingStatus;
2324
+ exports.STATE_DELIMITER = STATE_DELIMITER;
2325
+ exports.XSTATE_ERROR = XSTATE_ERROR;
2326
+ exports.XSTATE_STOP = XSTATE_STOP;
1442
2327
  exports.and = and;
1443
2328
  exports.cancel = cancel;
1444
2329
  exports.cloneMachineSnapshot = cloneMachineSnapshot;
2330
+ exports.createActor = createActor;
2331
+ exports.createErrorActorEvent = createErrorActorEvent;
2332
+ exports.createInitEvent = createInitEvent;
2333
+ exports.createInvokeId = createInvokeId;
1445
2334
  exports.createMachineSnapshot = createMachineSnapshot;
1446
2335
  exports.evaluateGuard = evaluateGuard;
1447
2336
  exports.formatInitialTransition = formatInitialTransition;
@@ -1454,17 +2343,27 @@ exports.getInitialStateNodes = getInitialStateNodes;
1454
2343
  exports.getPersistedState = getPersistedState;
1455
2344
  exports.getStateNodeByPath = getStateNodeByPath;
1456
2345
  exports.getStateNodes = getStateNodes;
2346
+ exports.interpret = interpret;
2347
+ exports.isErrorActorEvent = isErrorActorEvent;
1457
2348
  exports.isInFinalState = isInFinalState;
2349
+ exports.isMachineSnapshot = isMachineSnapshot;
1458
2350
  exports.isStateId = isStateId;
1459
2351
  exports.macrostep = macrostep;
2352
+ exports.mapValues = mapValues;
2353
+ exports.matchesState = matchesState;
1460
2354
  exports.memo = memo;
1461
2355
  exports.microstep = microstep;
1462
2356
  exports.not = not;
1463
2357
  exports.or = or;
2358
+ exports.pathToStateValue = pathToStateValue;
1464
2359
  exports.raise = raise;
1465
2360
  exports.resolveActionsAndContext = resolveActionsAndContext;
2361
+ exports.resolveReferencedActor = resolveReferencedActor;
1466
2362
  exports.resolveStateValue = resolveStateValue;
1467
2363
  exports.spawn = spawn;
1468
2364
  exports.stateIn = stateIn;
1469
2365
  exports.stop = stop;
2366
+ exports.toArray = toArray;
2367
+ exports.toObserver = toObserver;
2368
+ exports.toTransitionConfigArray = toTransitionConfigArray;
1470
2369
  exports.transitionNode = transitionNode;