xstate 5.0.0-beta.43 → 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 (46) 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 +6 -6
  8. package/actors/dist/xstate-actors.development.cjs.js +6 -6
  9. package/actors/dist/xstate-actors.development.esm.js +1 -1
  10. package/actors/dist/xstate-actors.esm.js +1 -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 +3 -7
  14. package/dist/declarations/src/actions/spawn.d.ts +11 -16
  15. package/dist/declarations/src/guards.d.ts +2 -2
  16. package/dist/declarations/src/index.d.ts +1 -1
  17. package/dist/declarations/src/spawn.d.ts +9 -13
  18. package/dist/declarations/src/stateUtils.d.ts +4 -4
  19. package/dist/declarations/src/types.d.ts +15 -16
  20. package/dist/declarations/src/utils.d.ts +1 -3
  21. package/dist/{raise-e0fe5c2d.cjs.js → raise-348cc74e.development.esm.js} +946 -68
  22. package/dist/{raise-f4ad5a87.development.esm.js → raise-5854eaca.esm.js} +860 -49
  23. package/dist/{raise-23dea0d7.development.cjs.js → raise-ed700d14.development.cjs.js} +922 -36
  24. package/dist/{raise-8dc8e1aa.esm.js → raise-fb6f017b.cjs.js} +907 -2
  25. package/dist/{send-0174c155.development.cjs.js → send-00466e37.development.cjs.js} +11 -12
  26. package/dist/{send-87bbaaab.cjs.js → send-53e5693c.cjs.js} +11 -12
  27. package/dist/{send-5d129d95.development.esm.js → send-a0193bdb.development.esm.js} +2 -3
  28. package/dist/{send-84e2e742.esm.js → send-b7b4befa.esm.js} +2 -3
  29. package/dist/xstate.cjs.js +25 -25
  30. package/dist/xstate.cjs.mjs +1 -0
  31. package/dist/xstate.development.cjs.js +25 -25
  32. package/dist/xstate.development.cjs.mjs +1 -0
  33. package/dist/xstate.development.esm.js +4 -6
  34. package/dist/xstate.esm.js +4 -6
  35. package/dist/xstate.umd.min.js +1 -1
  36. package/dist/xstate.umd.min.js.map +1 -1
  37. package/guards/dist/xstate-guards.cjs.js +1 -2
  38. package/guards/dist/xstate-guards.development.cjs.js +1 -2
  39. package/guards/dist/xstate-guards.development.esm.js +1 -2
  40. package/guards/dist/xstate-guards.esm.js +1 -2
  41. package/guards/dist/xstate-guards.umd.min.js.map +1 -1
  42. package/package.json +1 -1
  43. package/dist/interpreter-36d5556e.cjs.js +0 -887
  44. package/dist/interpreter-4e8e2a0d.development.cjs.js +0 -898
  45. package/dist/interpreter-63c80754.esm.js +0 -857
  46. package/dist/interpreter-80eb3bec.development.esm.js +0 -868
@@ -1,4 +1,855 @@
1
- import { r as resolveReferencedActor, d as createActor, P as ProcessingStatus, h as createErrorActorEvent, j as STATE_IDENTIFIER, n as normalizeTarget, t as toArray, N as NULL_EVENT, a as toTransitionConfigArray, S as STATE_DELIMITER, k as toStatePath, l as createDoneStateEvent, o as resolveOutput, W as WILDCARD, X as XSTATE_STOP, q as XSTATE_INIT, s as createAfterEvent, u as flatten, $ as $$ACTOR_TYPE, f as matchesState } from './interpreter-80eb3bec.development.esm.js';
1
+ import { devToolsAdapter } from '../dev/dist/xstate-dev.esm.js';
2
+
3
+ class Mailbox {
4
+ constructor(_process) {
5
+ this._process = _process;
6
+ this._active = false;
7
+ this._current = null;
8
+ this._last = null;
9
+ }
10
+ start() {
11
+ this._active = true;
12
+ this.flush();
13
+ }
14
+ clear() {
15
+ // we can't set _current to null because we might be currently processing
16
+ // and enqueue following clear shouldnt start processing the enqueued item immediately
17
+ if (this._current) {
18
+ this._current.next = null;
19
+ this._last = this._current;
20
+ }
21
+ }
22
+ enqueue(event) {
23
+ const enqueued = {
24
+ value: event,
25
+ next: null
26
+ };
27
+ if (this._current) {
28
+ this._last.next = enqueued;
29
+ this._last = enqueued;
30
+ return;
31
+ }
32
+ this._current = enqueued;
33
+ this._last = enqueued;
34
+ if (this._active) {
35
+ this.flush();
36
+ }
37
+ }
38
+ flush() {
39
+ while (this._current) {
40
+ // atm the given _process is responsible for implementing proper try/catch handling
41
+ // we assume here that this won't throw in a way that can affect this mailbox
42
+ const consumed = this._current;
43
+ this._process(consumed.value);
44
+ this._current = consumed.next;
45
+ }
46
+ this._last = null;
47
+ }
48
+ }
49
+
50
+ const STATE_DELIMITER = '.';
51
+ const TARGETLESS_KEY = '';
52
+ const NULL_EVENT = '';
53
+ const STATE_IDENTIFIER = '#';
54
+ const WILDCARD = '*';
55
+ const XSTATE_INIT = 'xstate.init';
56
+ const XSTATE_ERROR = 'xstate.error';
57
+ const XSTATE_STOP = 'xstate.stop';
58
+
59
+ /**
60
+ * Returns an event that represents an implicit event that
61
+ * is sent after the specified `delay`.
62
+ *
63
+ * @param delayRef The delay in milliseconds
64
+ * @param id The state node ID where this event is handled
65
+ */
66
+ function createAfterEvent(delayRef, id) {
67
+ const idSuffix = id ? `#${id}` : '';
68
+ return {
69
+ type: `xstate.after(${delayRef})${idSuffix}`
70
+ };
71
+ }
72
+
73
+ /**
74
+ * Returns an event that represents that a final state node
75
+ * has been reached in the parent state node.
76
+ *
77
+ * @param id The final state node's parent state node `id`
78
+ * @param output The data to pass into the event
79
+ */
80
+ function createDoneStateEvent(id, output) {
81
+ return {
82
+ type: `xstate.done.state.${id}`,
83
+ output
84
+ };
85
+ }
86
+
87
+ /**
88
+ * Returns an event that represents that an invoked service has terminated.
89
+ *
90
+ * An invoked service is terminated when it has reached a top-level final state node,
91
+ * but not when it is canceled.
92
+ *
93
+ * @param invokeId The invoked service ID
94
+ * @param output The data to pass into the event
95
+ */
96
+ function createDoneActorEvent(invokeId, output) {
97
+ return {
98
+ type: `xstate.done.actor.${invokeId}`,
99
+ output
100
+ };
101
+ }
102
+ function createErrorActorEvent(id, data) {
103
+ return {
104
+ type: `xstate.error.actor.${id}`,
105
+ data
106
+ };
107
+ }
108
+ function createInitEvent(input) {
109
+ return {
110
+ type: XSTATE_INIT,
111
+ input
112
+ };
113
+ }
114
+
115
+ /**
116
+ * This function makes sure that unhandled errors are thrown in a separate macrotask.
117
+ * It allows those errors to be detected by global error handlers and reported to bug tracking services
118
+ * without interrupting our own stack of execution.
119
+ *
120
+ * @param err error to be thrown
121
+ */
122
+ function reportUnhandledError(err) {
123
+ setTimeout(() => {
124
+ throw err;
125
+ });
126
+ }
127
+
128
+ const symbolObservable = (() => typeof Symbol === 'function' && Symbol.observable || '@@observable')();
129
+
130
+ let idCounter = 0;
131
+ function createSystem(rootActor) {
132
+ const children = new Map();
133
+ const keyedActors = new Map();
134
+ const reverseKeyedActors = new WeakMap();
135
+ const observers = new Set();
136
+ const system = {
137
+ _bookId: () => `x:${idCounter++}`,
138
+ _register: (sessionId, actorRef) => {
139
+ children.set(sessionId, actorRef);
140
+ return sessionId;
141
+ },
142
+ _unregister: actorRef => {
143
+ children.delete(actorRef.sessionId);
144
+ const systemId = reverseKeyedActors.get(actorRef);
145
+ if (systemId !== undefined) {
146
+ keyedActors.delete(systemId);
147
+ reverseKeyedActors.delete(actorRef);
148
+ }
149
+ },
150
+ get: systemId => {
151
+ return keyedActors.get(systemId);
152
+ },
153
+ _set: (systemId, actorRef) => {
154
+ const existing = keyedActors.get(systemId);
155
+ if (existing && existing !== actorRef) {
156
+ throw new Error(`Actor with system ID '${systemId}' already exists.`);
157
+ }
158
+ keyedActors.set(systemId, actorRef);
159
+ reverseKeyedActors.set(actorRef, systemId);
160
+ },
161
+ inspect: observer => {
162
+ observers.add(observer);
163
+ },
164
+ _sendInspectionEvent: event => {
165
+ const resolvedInspectionEvent = {
166
+ ...event,
167
+ rootId: rootActor.sessionId
168
+ };
169
+ observers.forEach(observer => observer.next?.(resolvedInspectionEvent));
170
+ },
171
+ _relay: (source, target, event) => {
172
+ system._sendInspectionEvent({
173
+ type: '@xstate.event',
174
+ sourceRef: source,
175
+ actorRef: target,
176
+ event
177
+ });
178
+ target._send(event);
179
+ }
180
+ };
181
+ return system;
182
+ }
183
+
184
+ function matchesState(parentStateId, childStateId) {
185
+ const parentStateValue = toStateValue(parentStateId);
186
+ const childStateValue = toStateValue(childStateId);
187
+ if (typeof childStateValue === 'string') {
188
+ if (typeof parentStateValue === 'string') {
189
+ return childStateValue === parentStateValue;
190
+ }
191
+
192
+ // Parent more specific than child
193
+ return false;
194
+ }
195
+ if (typeof parentStateValue === 'string') {
196
+ return parentStateValue in childStateValue;
197
+ }
198
+ return Object.keys(parentStateValue).every(key => {
199
+ if (!(key in childStateValue)) {
200
+ return false;
201
+ }
202
+ return matchesState(parentStateValue[key], childStateValue[key]);
203
+ });
204
+ }
205
+ function toStatePath(stateId) {
206
+ try {
207
+ if (isArray(stateId)) {
208
+ return stateId;
209
+ }
210
+ return stateId.split(STATE_DELIMITER);
211
+ } catch (e) {
212
+ throw new Error(`'${stateId}' is not a valid state path.`);
213
+ }
214
+ }
215
+ function toStateValue(stateValue) {
216
+ if (isMachineSnapshot(stateValue)) {
217
+ return stateValue.value;
218
+ }
219
+ if (typeof stateValue !== 'string') {
220
+ return stateValue;
221
+ }
222
+ const statePath = toStatePath(stateValue);
223
+ return pathToStateValue(statePath);
224
+ }
225
+ function pathToStateValue(statePath) {
226
+ if (statePath.length === 1) {
227
+ return statePath[0];
228
+ }
229
+ const value = {};
230
+ let marker = value;
231
+ for (let i = 0; i < statePath.length - 1; i++) {
232
+ if (i === statePath.length - 2) {
233
+ marker[statePath[i]] = statePath[i + 1];
234
+ } else {
235
+ const previous = marker;
236
+ marker = {};
237
+ previous[statePath[i]] = marker;
238
+ }
239
+ }
240
+ return value;
241
+ }
242
+ function mapValues(collection, iteratee) {
243
+ const result = {};
244
+ const collectionKeys = Object.keys(collection);
245
+ for (let i = 0; i < collectionKeys.length; i++) {
246
+ const key = collectionKeys[i];
247
+ result[key] = iteratee(collection[key], key, collection, i);
248
+ }
249
+ return result;
250
+ }
251
+ function flatten(array) {
252
+ return [].concat(...array);
253
+ }
254
+ function toArrayStrict(value) {
255
+ if (isArray(value)) {
256
+ return value;
257
+ }
258
+ return [value];
259
+ }
260
+ function toArray(value) {
261
+ if (value === undefined) {
262
+ return [];
263
+ }
264
+ return toArrayStrict(value);
265
+ }
266
+ function resolveOutput(mapper, context, event, self) {
267
+ if (typeof mapper === 'function') {
268
+ return mapper({
269
+ context,
270
+ event,
271
+ self
272
+ });
273
+ }
274
+ return mapper;
275
+ }
276
+ function isArray(value) {
277
+ return Array.isArray(value);
278
+ }
279
+ function isErrorActorEvent(event) {
280
+ return event.type.startsWith('xstate.error.actor');
281
+ }
282
+ function toTransitionConfigArray(configLike) {
283
+ return toArrayStrict(configLike).map(transitionLike => {
284
+ if (typeof transitionLike === 'undefined' || typeof transitionLike === 'string') {
285
+ return {
286
+ target: transitionLike
287
+ };
288
+ }
289
+ return transitionLike;
290
+ });
291
+ }
292
+ function normalizeTarget(target) {
293
+ if (target === undefined || target === TARGETLESS_KEY) {
294
+ return undefined;
295
+ }
296
+ return toArray(target);
297
+ }
298
+ function toObserver(nextHandler, errorHandler, completionHandler) {
299
+ const isObserver = typeof nextHandler === 'object';
300
+ const self = isObserver ? nextHandler : undefined;
301
+ return {
302
+ next: (isObserver ? nextHandler.next : nextHandler)?.bind(self),
303
+ error: (isObserver ? nextHandler.error : errorHandler)?.bind(self),
304
+ complete: (isObserver ? nextHandler.complete : completionHandler)?.bind(self)
305
+ };
306
+ }
307
+ function createInvokeId(stateNodeId, index) {
308
+ return `${stateNodeId}[${index}]`;
309
+ }
310
+ function resolveReferencedActor(machine, src) {
311
+ if (src.startsWith('xstate#')) {
312
+ const [, indexStr] = src.match(/\[(\d+)\]$/);
313
+ const node = machine.getStateNodeById(src.slice(7, -(indexStr.length + 2)));
314
+ const invokeConfig = node.config.invoke;
315
+ return (Array.isArray(invokeConfig) ? invokeConfig[indexStr] : invokeConfig).src;
316
+ }
317
+ return machine.implementations.actors[src];
318
+ }
319
+
320
+ const $$ACTOR_TYPE = 1;
321
+ // those values are currently used by @xstate/react directly so it's important to keep the assigned values in sync
322
+ let ProcessingStatus = /*#__PURE__*/function (ProcessingStatus) {
323
+ ProcessingStatus[ProcessingStatus["NotStarted"] = 0] = "NotStarted";
324
+ ProcessingStatus[ProcessingStatus["Running"] = 1] = "Running";
325
+ ProcessingStatus[ProcessingStatus["Stopped"] = 2] = "Stopped";
326
+ return ProcessingStatus;
327
+ }({});
328
+ const defaultOptions = {
329
+ clock: {
330
+ setTimeout: (fn, ms) => {
331
+ return setTimeout(fn, ms);
332
+ },
333
+ clearTimeout: id => {
334
+ return clearTimeout(id);
335
+ }
336
+ },
337
+ logger: console.log.bind(console),
338
+ devTools: false
339
+ };
340
+
341
+ /**
342
+ * 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.
343
+ */
344
+ class Actor {
345
+ /**
346
+ * The current internal state of the actor.
347
+ */
348
+
349
+ /**
350
+ * The clock that is responsible for setting and clearing timeouts, such as delayed events and transitions.
351
+ */
352
+
353
+ /**
354
+ * The unique identifier for this actor relative to its parent.
355
+ */
356
+
357
+ /** @internal */
358
+
359
+ // Actor Ref
360
+
361
+ // TODO: add typings for system
362
+
363
+ /**
364
+ * The globally unique process ID for this invocation.
365
+ */
366
+
367
+ /**
368
+ * The system to which this actor belongs.
369
+ */
370
+
371
+ /**
372
+ * Creates a new actor instance for the given logic with the provided options, if any.
373
+ *
374
+ * @param logic The logic to create an actor from
375
+ * @param options Actor options
376
+ */
377
+ constructor(logic, options) {
378
+ this.logic = logic;
379
+ this._state = void 0;
380
+ this.clock = void 0;
381
+ this.options = void 0;
382
+ this.id = void 0;
383
+ this.mailbox = new Mailbox(this._process.bind(this));
384
+ this.delayedEventsMap = {};
385
+ this.observers = new Set();
386
+ this.logger = void 0;
387
+ this._processingStatus = ProcessingStatus.NotStarted;
388
+ this._parent = void 0;
389
+ this.ref = void 0;
390
+ this._actorScope = void 0;
391
+ this._systemId = void 0;
392
+ this.sessionId = void 0;
393
+ this.system = void 0;
394
+ this._doneEvent = void 0;
395
+ this.src = void 0;
396
+ this._deferred = [];
397
+ const resolvedOptions = {
398
+ ...defaultOptions,
399
+ ...options
400
+ };
401
+ const {
402
+ clock,
403
+ logger,
404
+ parent,
405
+ id,
406
+ systemId,
407
+ inspect
408
+ } = resolvedOptions;
409
+ this.system = parent?.system ?? createSystem(this);
410
+ if (inspect && !parent) {
411
+ // Always inspect at the system-level
412
+ this.system.inspect(toObserver(inspect));
413
+ }
414
+ this.sessionId = this.system._bookId();
415
+ this.id = id ?? this.sessionId;
416
+ this.logger = logger;
417
+ this.clock = clock;
418
+ this._parent = parent;
419
+ this.options = resolvedOptions;
420
+ this.src = resolvedOptions.src ?? logic;
421
+ this.ref = this;
422
+ this._actorScope = {
423
+ self: this,
424
+ id: this.id,
425
+ sessionId: this.sessionId,
426
+ logger: this.logger,
427
+ defer: fn => {
428
+ this._deferred.push(fn);
429
+ },
430
+ system: this.system,
431
+ stopChild: child => {
432
+ if (child._parent !== this) {
433
+ throw new Error(`Cannot stop child actor ${child.id} of ${this.id} because it is not a child`);
434
+ }
435
+ child._stop();
436
+ }
437
+ };
438
+
439
+ // Ensure that the send method is bound to this Actor instance
440
+ // if destructured
441
+ this.send = this.send.bind(this);
442
+ this.system._sendInspectionEvent({
443
+ type: '@xstate.actor',
444
+ actorRef: this
445
+ });
446
+ if (systemId) {
447
+ this._systemId = systemId;
448
+ this.system._set(systemId, this);
449
+ }
450
+ this._initState(options?.state);
451
+ if (systemId && this._state.status !== 'active') {
452
+ this.system._unregister(this);
453
+ }
454
+ }
455
+ _initState(persistedState) {
456
+ this._state = persistedState ? this.logic.restoreState ? this.logic.restoreState(persistedState, this._actorScope) : persistedState : this.logic.getInitialState(this._actorScope, this.options?.input);
457
+ }
458
+
459
+ // array of functions to defer
460
+
461
+ update(snapshot, event) {
462
+ // Update state
463
+ this._state = snapshot;
464
+
465
+ // Execute deferred effects
466
+ let deferredFn;
467
+ while (deferredFn = this._deferred.shift()) {
468
+ deferredFn();
469
+ }
470
+ for (const observer of this.observers) {
471
+ try {
472
+ observer.next?.(snapshot);
473
+ } catch (err) {
474
+ reportUnhandledError(err);
475
+ }
476
+ }
477
+ switch (this._state.status) {
478
+ case 'done':
479
+ this._stopProcedure();
480
+ this._complete();
481
+ this._doneEvent = createDoneActorEvent(this.id, this._state.output);
482
+ if (this._parent) {
483
+ this.system._relay(this, this._parent, this._doneEvent);
484
+ }
485
+ break;
486
+ case 'error':
487
+ this._stopProcedure();
488
+ this._error(this._state.error);
489
+ if (this._parent) {
490
+ this.system._relay(this, this._parent, createErrorActorEvent(this.id, this._state.error));
491
+ }
492
+ break;
493
+ }
494
+ this.system._sendInspectionEvent({
495
+ type: '@xstate.snapshot',
496
+ actorRef: this,
497
+ event,
498
+ snapshot
499
+ });
500
+ }
501
+
502
+ /**
503
+ * Subscribe an observer to an actor’s snapshot values.
504
+ *
505
+ * @remarks
506
+ * The observer will receive the actor’s snapshot value when it is emitted. The observer can be:
507
+ * - A plain function that receives the latest snapshot, or
508
+ * - An observer object whose `.next(snapshot)` method receives the latest snapshot
509
+ *
510
+ * @example
511
+ * ```ts
512
+ * // Observer as a plain function
513
+ * const subscription = actor.subscribe((snapshot) => {
514
+ * console.log(snapshot);
515
+ * });
516
+ * ```
517
+ *
518
+ * @example
519
+ * ```ts
520
+ * // Observer as an object
521
+ * const subscription = actor.subscribe({
522
+ * next(snapshot) {
523
+ * console.log(snapshot);
524
+ * },
525
+ * error(err) {
526
+ * // ...
527
+ * },
528
+ * complete() {
529
+ * // ...
530
+ * },
531
+ * });
532
+ * ```
533
+ *
534
+ * 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:
535
+ *
536
+ * @example
537
+ * ```ts
538
+ * const subscription = actor.subscribe((snapshot) => {
539
+ * // ...
540
+ * });
541
+ *
542
+ * // Unsubscribe the observer
543
+ * subscription.unsubscribe();
544
+ * ```
545
+ *
546
+ * When the actor is stopped, all of its observers will automatically be unsubscribed.
547
+ *
548
+ * @param observer - Either a plain function that receives the latest snapshot, or an observer object whose `.next(snapshot)` method receives the latest snapshot
549
+ */
550
+
551
+ subscribe(nextListenerOrObserver, errorListener, completeListener) {
552
+ const observer = toObserver(nextListenerOrObserver, errorListener, completeListener);
553
+ if (this._processingStatus !== ProcessingStatus.Stopped) {
554
+ this.observers.add(observer);
555
+ } else {
556
+ try {
557
+ observer.complete?.();
558
+ } catch (err) {
559
+ reportUnhandledError(err);
560
+ }
561
+ }
562
+ return {
563
+ unsubscribe: () => {
564
+ this.observers.delete(observer);
565
+ }
566
+ };
567
+ }
568
+
569
+ /**
570
+ * Starts the Actor from the initial state
571
+ */
572
+ start() {
573
+ if (this._processingStatus === ProcessingStatus.Running) {
574
+ // Do not restart the service if it is already started
575
+ return this;
576
+ }
577
+ this.system._register(this.sessionId, this);
578
+ if (this._systemId) {
579
+ this.system._set(this._systemId, this);
580
+ }
581
+ this._processingStatus = ProcessingStatus.Running;
582
+
583
+ // TODO: this isn't correct when rehydrating
584
+ const initEvent = createInitEvent(this.options.input);
585
+ this.system._sendInspectionEvent({
586
+ type: '@xstate.event',
587
+ sourceRef: this._parent,
588
+ actorRef: this,
589
+ event: initEvent
590
+ });
591
+ const status = this._state.status;
592
+ switch (status) {
593
+ case 'done':
594
+ // a state machine can be "done" upon initialization (it could reach a final state using initial microsteps)
595
+ // we still need to complete observers, flush deferreds etc
596
+ this.update(this._state, initEvent);
597
+ // fallthrough
598
+ case 'error':
599
+ // TODO: rethink cleanup of observers, mailbox, etc
600
+ return this;
601
+ }
602
+ if (this.logic.start) {
603
+ try {
604
+ this.logic.start(this._state, this._actorScope);
605
+ } catch (err) {
606
+ this._stopProcedure();
607
+ this._error(err);
608
+ this._parent?.send(createErrorActorEvent(this.id, err));
609
+ return this;
610
+ }
611
+ }
612
+
613
+ // TODO: this notifies all subscribers but usually this is redundant
614
+ // there is no real change happening here
615
+ // we need to rethink if this needs to be refactored
616
+ this.update(this._state, initEvent);
617
+ if (this.options.devTools) {
618
+ this.attachDevTools();
619
+ }
620
+ this.mailbox.start();
621
+ return this;
622
+ }
623
+ _process(event) {
624
+ // TODO: reexamine what happens when an action (or a guard or smth) throws
625
+ let nextState;
626
+ let caughtError;
627
+ try {
628
+ nextState = this.logic.transition(this._state, event, this._actorScope);
629
+ } catch (err) {
630
+ // we wrap it in a box so we can rethrow it later even if falsy value gets caught here
631
+ caughtError = {
632
+ err
633
+ };
634
+ }
635
+ if (caughtError) {
636
+ const {
637
+ err
638
+ } = caughtError;
639
+ this._stopProcedure();
640
+ this._error(err);
641
+ this._parent?.send(createErrorActorEvent(this.id, err));
642
+ return;
643
+ }
644
+ this.update(nextState, event);
645
+ if (event.type === XSTATE_STOP) {
646
+ this._stopProcedure();
647
+ this._complete();
648
+ }
649
+ }
650
+ _stop() {
651
+ if (this._processingStatus === ProcessingStatus.Stopped) {
652
+ return this;
653
+ }
654
+ this.mailbox.clear();
655
+ if (this._processingStatus === ProcessingStatus.NotStarted) {
656
+ this._processingStatus = ProcessingStatus.Stopped;
657
+ return this;
658
+ }
659
+ this.mailbox.enqueue({
660
+ type: XSTATE_STOP
661
+ });
662
+ return this;
663
+ }
664
+
665
+ /**
666
+ * Stops the Actor and unsubscribe all listeners.
667
+ */
668
+ stop() {
669
+ if (this._parent) {
670
+ throw new Error('A non-root actor cannot be stopped directly.');
671
+ }
672
+ return this._stop();
673
+ }
674
+ _complete() {
675
+ for (const observer of this.observers) {
676
+ try {
677
+ observer.complete?.();
678
+ } catch (err) {
679
+ reportUnhandledError(err);
680
+ }
681
+ }
682
+ this.observers.clear();
683
+ }
684
+ _error(err) {
685
+ if (!this.observers.size) {
686
+ if (!this._parent) {
687
+ reportUnhandledError(err);
688
+ }
689
+ return;
690
+ }
691
+ let reportError = false;
692
+ for (const observer of this.observers) {
693
+ const errorListener = observer.error;
694
+ reportError ||= !errorListener;
695
+ try {
696
+ errorListener?.(err);
697
+ } catch (err2) {
698
+ reportUnhandledError(err2);
699
+ }
700
+ }
701
+ this.observers.clear();
702
+ if (reportError) {
703
+ reportUnhandledError(err);
704
+ }
705
+ }
706
+ _stopProcedure() {
707
+ if (this._processingStatus !== ProcessingStatus.Running) {
708
+ // Actor already stopped; do nothing
709
+ return this;
710
+ }
711
+
712
+ // Cancel all delayed events
713
+ for (const key of Object.keys(this.delayedEventsMap)) {
714
+ this.clock.clearTimeout(this.delayedEventsMap[key]);
715
+ }
716
+
717
+ // TODO: mailbox.reset
718
+ this.mailbox.clear();
719
+ // TODO: after `stop` we must prepare ourselves for receiving events again
720
+ // events sent *after* stop signal must be queued
721
+ // it seems like this should be the common behavior for all of our consumers
722
+ // so perhaps this should be unified somehow for all of them
723
+ this.mailbox = new Mailbox(this._process.bind(this));
724
+ this._processingStatus = ProcessingStatus.Stopped;
725
+ this.system._unregister(this);
726
+ return this;
727
+ }
728
+
729
+ /**
730
+ * @internal
731
+ */
732
+ _send(event) {
733
+ if (this._processingStatus === ProcessingStatus.Stopped) {
734
+ return;
735
+ }
736
+ this.mailbox.enqueue(event);
737
+ }
738
+
739
+ /**
740
+ * Sends an event to the running Actor to trigger a transition.
741
+ *
742
+ * @param event The event to send
743
+ */
744
+ send(event) {
745
+ this.system._relay(undefined, this, event);
746
+ }
747
+
748
+ /**
749
+ * TODO: figure out a way to do this within the machine
750
+ * @internal
751
+ */
752
+ delaySend(params) {
753
+ const {
754
+ event,
755
+ id,
756
+ delay
757
+ } = params;
758
+ const timerId = this.clock.setTimeout(() => {
759
+ this.system._relay(this, params.to ?? this, event);
760
+ }, delay);
761
+
762
+ // TODO: consider the rehydration story here
763
+ if (id) {
764
+ this.delayedEventsMap[id] = timerId;
765
+ }
766
+ }
767
+
768
+ /**
769
+ * TODO: figure out a way to do this within the machine
770
+ * @internal
771
+ */
772
+ cancel(sendId) {
773
+ this.clock.clearTimeout(this.delayedEventsMap[sendId]);
774
+ delete this.delayedEventsMap[sendId];
775
+ }
776
+ attachDevTools() {
777
+ const {
778
+ devTools
779
+ } = this.options;
780
+ if (devTools) {
781
+ const resolvedDevToolsAdapter = typeof devTools === 'function' ? devTools : devToolsAdapter;
782
+ resolvedDevToolsAdapter(this);
783
+ }
784
+ }
785
+ toJSON() {
786
+ return {
787
+ xstate$$type: $$ACTOR_TYPE,
788
+ id: this.id
789
+ };
790
+ }
791
+
792
+ /**
793
+ * Obtain the internal state of the actor, which can be persisted.
794
+ *
795
+ * @remarks
796
+ * The internal state can be persisted from any actor, not only machines.
797
+ *
798
+ * 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.
799
+ *
800
+ * Can be restored with {@link ActorOptions.state}
801
+ *
802
+ * @see https://stately.ai/docs/persistence
803
+ */
804
+
805
+ getPersistedState(options) {
806
+ return this.logic.getPersistedState(this._state, options);
807
+ }
808
+ [symbolObservable]() {
809
+ return this;
810
+ }
811
+
812
+ /**
813
+ * Read an actor’s snapshot synchronously.
814
+ *
815
+ * @remarks
816
+ * The snapshot represent an actor's last emitted value.
817
+ *
818
+ * When an actor receives an event, its internal state may change.
819
+ * An actor may emit a snapshot when a state transition occurs.
820
+ *
821
+ * Note that some actors, such as callback actors generated with `fromCallback`, will not emit snapshots.
822
+ *
823
+ * @see {@link Actor.subscribe} to subscribe to an actor’s snapshot values.
824
+ * @see {@link Actor.getPersistedState} to persist the internal state of an actor (which is more than just a snapshot).
825
+ */
826
+ getSnapshot() {
827
+ return this._state;
828
+ }
829
+ }
830
+
831
+ /**
832
+ * Creates a new `ActorRef` instance for the given machine with the provided options, if any.
833
+ *
834
+ * @param machine The machine to create an actor from
835
+ * @param options `ActorRef` options
836
+ */
837
+
838
+ function createActor(logic, options) {
839
+ const interpreter = new Actor(logic, options);
840
+ return interpreter;
841
+ }
842
+
843
+ /**
844
+ * Creates a new Interpreter instance for the given machine with the provided options, if any.
845
+ *
846
+ * @deprecated Use `createActor` instead
847
+ */
848
+ const interpret = createActor;
849
+
850
+ /**
851
+ * @deprecated Use `Actor` instead.
852
+ */
2
853
 
3
854
  const cache = new WeakMap();
4
855
  function memo(object, key, fn) {
@@ -32,9 +883,6 @@ function executeCancel(actorScope, resolvedSendId) {
32
883
  */
33
884
  function cancel(sendId) {
34
885
  function cancel(args, params) {
35
- {
36
- throw new Error(`This isn't supposed to be called`);
37
- }
38
886
  }
39
887
  cancel.type = 'xstate.cancel';
40
888
  cancel.sendId = sendId;
@@ -79,9 +927,6 @@ function resolveSpawn(actorScope, state, actionArgs, _actionParams, {
79
927
  });
80
928
  }
81
929
  }
82
- if (!actorRef) {
83
- console.warn(`Actor type '${src}' not found in machine '${actorScope.id}'.`);
84
- }
85
930
  return [cloneMachineSnapshot(state, {
86
931
  children: {
87
932
  ...state.children,
@@ -118,9 +963,6 @@ function spawn(...[src, {
118
963
  syncSnapshot = false
119
964
  } = {}]) {
120
965
  function spawn(args, params) {
121
- {
122
- throw new Error(`This isn't supposed to be called`);
123
- }
124
966
  }
125
967
  spawn.type = 'xstate.spawn';
126
968
  spawn.id = id;
@@ -180,9 +1022,6 @@ function executeStop(actorScope, actorRef) {
180
1022
  */
181
1023
  function stop(actorRef) {
182
1024
  function stop(args, params) {
183
- {
184
- throw new Error(`This isn't supposed to be called`);
185
- }
186
1025
  }
187
1026
  stop.type = 'xstate.stop';
188
1027
  stop.actorRef = actorRef;
@@ -202,9 +1041,7 @@ function checkStateIn(state, _, {
202
1041
  }
203
1042
  function stateIn(stateValue) {
204
1043
  function stateIn(args, params) {
205
- {
206
- throw new Error(`This isn't supposed to be called`);
207
- }
1044
+ return false;
208
1045
  }
209
1046
  stateIn.check = checkStateIn;
210
1047
  stateIn.stateValue = stateValue;
@@ -220,9 +1057,7 @@ function checkNot(state, {
220
1057
  }
221
1058
  function not(guard) {
222
1059
  function not(args, params) {
223
- {
224
- throw new Error(`This isn't supposed to be called`);
225
- }
1060
+ return false;
226
1061
  }
227
1062
  not.check = checkNot;
228
1063
  not.guards = [guard];
@@ -238,9 +1073,7 @@ function checkAnd(state, {
238
1073
  }
239
1074
  function and(guards) {
240
1075
  function and(args, params) {
241
- {
242
- throw new Error(`This isn't supposed to be called`);
243
- }
1076
+ return false;
244
1077
  }
245
1078
  and.check = checkAnd;
246
1079
  and.guards = guards;
@@ -256,9 +1089,7 @@ function checkOr(state, {
256
1089
  }
257
1090
  function or(guards) {
258
1091
  function or(args, params) {
259
- {
260
- throw new Error(`This isn't supposed to be called`);
261
- }
1092
+ return false;
262
1093
  }
263
1094
  or.check = checkOr;
264
1095
  or.guards = guards;
@@ -413,9 +1244,6 @@ function getCandidates(stateNode, receivedEventType) {
413
1244
  if (!descriptor.endsWith('.*')) {
414
1245
  return false;
415
1246
  }
416
- if (/.*\*.+/.test(descriptor)) {
417
- console.warn(`Wildcards can only be the last token of an event descriptor (e.g., "event.*") or the entire event descriptor ("*"). Check the "${descriptor}" event.`);
418
- }
419
1247
  const partialEventTokens = descriptor.split('.');
420
1248
  const eventTokens = receivedEventType.split('.');
421
1249
  for (let tokenIndex = 0; tokenIndex < partialEventTokens.length; tokenIndex++) {
@@ -423,9 +1251,6 @@ function getCandidates(stateNode, receivedEventType) {
423
1251
  const eventToken = eventTokens[tokenIndex];
424
1252
  if (partialEventToken === '*') {
425
1253
  const isLastToken = tokenIndex === partialEventTokens.length - 1;
426
- if (!isLastToken) {
427
- console.warn(`Infix wildcards in transition events are not allowed. Check the "${descriptor}" transition.`);
428
- }
429
1254
  return isLastToken;
430
1255
  }
431
1256
  if (partialEventToken !== eventToken) {
@@ -483,11 +1308,6 @@ function formatTransition(stateNode, descriptor, transitionConfig) {
483
1308
  const normalizedTarget = normalizeTarget(transitionConfig.target);
484
1309
  const reenter = transitionConfig.reenter ?? false;
485
1310
  const target = resolveTarget(stateNode, normalizedTarget);
486
-
487
- // TODO: should this be part of a lint rule instead?
488
- if (transitionConfig.cond) {
489
- throw new Error(`State "${stateNode.id}" has declared \`cond\` for one of its transitions. This property has been renamed to \`guard\`. Please update your code.`);
490
- }
491
1311
  const transition = {
492
1312
  ...transitionConfig,
493
1313
  actions: toArray(transitionConfig.actions),
@@ -1163,9 +1983,6 @@ function resolveActionsAndContext(currentState, event, actorScope, actions, inte
1163
1983
  return nextState;
1164
1984
  }
1165
1985
  function macrostep(state, event, actorScope, internalQueue = []) {
1166
- if (event.type === WILDCARD) {
1167
- throw new Error(`An event cannot have the wildcard type ('${WILDCARD}')`);
1168
- }
1169
1986
  let nextState = state;
1170
1987
  const states = [];
1171
1988
 
@@ -1250,6 +2067,9 @@ function resolveStateValue(rootNode, stateValue) {
1250
2067
  return getStateValue(rootNode, [...configuration]);
1251
2068
  }
1252
2069
 
2070
+ function isMachineSnapshot(value) {
2071
+ return !!value && typeof value === 'object' && 'machine' in value && 'value' in value;
2072
+ }
1253
2073
  const machineSnapshotMatches = function matches(testValue) {
1254
2074
  return matchesState(testValue, this.value);
1255
2075
  };
@@ -1257,9 +2077,6 @@ const machineSnapshotHasTag = function hasTag(tag) {
1257
2077
  return this.tags.has(tag);
1258
2078
  };
1259
2079
  const machineSnapshotCan = function can(event) {
1260
- if (!this.machine) {
1261
- console.warn(`state.can(...) used outside of a machine-created State object; this will always return false.`);
1262
- }
1263
2080
  const transitionData = this.machine.getTransitionData(this, event);
1264
2081
  return !!transitionData?.length &&
1265
2082
  // Check that at least one transition is not forbidden
@@ -1352,9 +2169,6 @@ function getPersistedState(state, options) {
1352
2169
  const childrenJson = {};
1353
2170
  for (const id in children) {
1354
2171
  const child = children[id];
1355
- if (typeof child.src !== 'string' && (!options || !('__unsafeAllowInlineActors' in options))) {
1356
- throw new Error('An inline child actor cannot be persisted.');
1357
- }
1358
2172
  childrenJson[id] = {
1359
2173
  state: child.getPersistedState(options),
1360
2174
  src: child.src,
@@ -1437,9 +2251,6 @@ function executeRaise(actorScope, params) {
1437
2251
  */
1438
2252
  function raise(eventOrExpr, options) {
1439
2253
  function raise(args, params) {
1440
- {
1441
- throw new Error(`This isn't supposed to be called`);
1442
- }
1443
2254
  }
1444
2255
  raise.type = 'xstate.raise';
1445
2256
  raise.event = eventOrExpr;
@@ -1450,4 +2261,4 @@ function raise(eventOrExpr, options) {
1450
2261
  return raise;
1451
2262
  }
1452
2263
 
1453
- export { raise as A, stop as B, spawn as C, formatTransition as a, formatInitialTransition as b, getCandidates as c, getConfiguration as d, evaluateGuard as e, formatTransitions as f, getDelayedTransitions as g, getStateNodes as h, createMachineSnapshot as i, isInFinalState as j, cloneMachineSnapshot as k, macrostep as l, memo as m, resolveActionsAndContext as n, microstep as o, getInitialStateNodes as p, isStateId as q, resolveStateValue as r, getStateNodeByPath as s, transitionNode as t, getPersistedState as u, and as v, not as w, or as x, stateIn as y, cancel as z };
2264
+ export { $$ACTOR_TYPE as $, getPersistedState as A, resolveReferencedActor as B, createActor as C, Actor as D, interpret as E, isMachineSnapshot as F, matchesState as G, pathToStateValue as H, toObserver as I, and as J, not as K, or as L, stateIn as M, NULL_EVENT as N, cancel as O, raise as P, stop as Q, spawn as R, STATE_DELIMITER as S, ProcessingStatus as T, createErrorActorEvent as U, XSTATE_ERROR as V, XSTATE_STOP as X, toTransitionConfigArray as a, formatTransition as b, memo as c, createInvokeId as d, evaluateGuard as e, formatTransitions as f, getDelayedTransitions as g, formatInitialTransition as h, getCandidates as i, getConfiguration as j, getStateNodes as k, createMachineSnapshot as l, mapValues as m, isInFinalState as n, isErrorActorEvent as o, cloneMachineSnapshot as p, macrostep as q, resolveStateValue as r, transitionNode as s, toArray as t, resolveActionsAndContext as u, createInitEvent as v, microstep as w, getInitialStateNodes as x, isStateId as y, getStateNodeByPath as z };