xstate 6.0.0-alpha.2 → 6.0.0-alpha.4

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 (44) hide show
  1. package/dist/{StateMachine-64813f46.cjs.js → StateMachine-445a8480.cjs.js} +15 -6
  2. package/dist/{StateMachine-2ea0a7fa.development.esm.js → StateMachine-4deb4090.development.esm.js} +15 -6
  3. package/dist/{StateMachine-2dcdb1f5.esm.js → StateMachine-f310bc72.esm.js} +15 -6
  4. package/dist/{StateMachine-8d22a79c.development.cjs.js → StateMachine-f83f01f9.development.cjs.js} +15 -6
  5. package/dist/declarations/src/StateMachine.d.ts +9 -8
  6. package/dist/declarations/src/actions.d.ts +1 -1
  7. package/dist/declarations/src/createActor.d.ts +3 -2
  8. package/dist/declarations/src/createMachine.d.ts +10 -7
  9. package/dist/declarations/src/graph/graph.d.ts +3 -3
  10. package/dist/declarations/src/graph/shortestPaths.d.ts +2 -2
  11. package/dist/declarations/src/graph/simplePaths.d.ts +2 -2
  12. package/dist/declarations/src/index.d.ts +2 -3
  13. package/dist/declarations/src/serialize.d.ts +13 -8
  14. package/dist/declarations/src/setup.d.ts +79 -33
  15. package/dist/declarations/src/transition.d.ts +8 -5
  16. package/dist/declarations/src/transitionActions.d.ts +4 -0
  17. package/dist/declarations/src/types.d.ts +69 -21
  18. package/dist/declarations/src/types.v6.d.ts +47 -27
  19. package/dist/{index-9cb3b3a0.cjs.js → index-918ab496.cjs.js} +245 -816
  20. package/dist/{index-93edd3bd.esm.js → index-9cce3480.esm.js} +244 -811
  21. package/dist/{index-e61170ba.development.esm.js → index-ccbe7c0b.development.esm.js} +244 -811
  22. package/dist/{index-f6ef20d1.development.cjs.js → index-ebaf6fd8.development.cjs.js} +245 -816
  23. package/dist/xstate-actors.cjs.js +1 -1
  24. package/dist/xstate-actors.development.cjs.js +1 -1
  25. package/dist/xstate-actors.development.esm.js +1 -1
  26. package/dist/xstate-actors.esm.js +1 -1
  27. package/dist/xstate-actors.umd.min.js +1 -1
  28. package/dist/xstate-actors.umd.min.js.map +1 -1
  29. package/dist/xstate-graph.cjs.js +2 -2
  30. package/dist/xstate-graph.development.cjs.js +2 -2
  31. package/dist/xstate-graph.development.esm.js +2 -2
  32. package/dist/xstate-graph.esm.js +2 -2
  33. package/dist/xstate-graph.umd.min.js +1 -1
  34. package/dist/xstate-graph.umd.min.js.map +1 -1
  35. package/dist/xstate.cjs.js +150 -53
  36. package/dist/xstate.cjs.mjs +1 -5
  37. package/dist/xstate.development.cjs.js +150 -53
  38. package/dist/xstate.development.cjs.mjs +1 -5
  39. package/dist/xstate.development.esm.js +151 -50
  40. package/dist/xstate.esm.js +151 -50
  41. package/dist/xstate.umd.min.js +1 -1
  42. package/dist/xstate.umd.min.js.map +1 -1
  43. package/package.json +1 -1
  44. package/dist/declarations/src/atom.d.ts +0 -81
@@ -1,18 +1,5 @@
1
1
  'use strict';
2
2
 
3
- /**
4
- * Reactivity interop between actors and atoms.
5
- *
6
- * `Actor#get()` calls this hook (when installed) so that computed atoms can
7
- * track actor reads as dependencies. The hook is installed by `atom.ts` on
8
- * module evaluation, which only happens when atoms are actually used — apps
9
- * that never import atoms don't bundle the reactive system.
10
- */
11
- let onActorRead;
12
- function installActorReadHook(hook) {
13
- onActorRead = hook;
14
- }
15
-
16
3
  class Mailbox {
17
4
  constructor(_process) {
18
5
  this._process = _process;
@@ -188,7 +175,7 @@ const builtInActions = {
188
175
  ['@xstate.cancel']: (actorScope, sendId) => {
189
176
  actorScope.system.scheduler.cancel(actorScope.self, sendId);
190
177
  },
191
- ['@xstate.stopChild']: (actorScope, actor) => {
178
+ ['@xstate.stop']: (actorScope, actor) => {
192
179
  actorScope.stopChild(actor);
193
180
  }
194
181
  };
@@ -200,15 +187,20 @@ const subscriptions = /* #__PURE__ */new WeakMap();
200
187
  * (`enq.listen()` / `enq.subscribeTo()`) and detaches when stopped.
201
188
  */
202
189
  function createAttachedLogic(attach) {
190
+ const initialTransition = (input, _) => [{
191
+ status: 'active',
192
+ output: undefined,
193
+ error: undefined,
194
+ input
195
+ }, []];
203
196
  return {
204
197
  start: (state, {
205
198
  self,
206
199
  system
207
200
  }) => {
208
- // Don't attach if the target doesn't exist, or (for actors) is stopped.
209
- // Atoms have no `getSnapshot` / lifecycle, so they always attach.
201
+ // Don't attach if the target doesn't exist or is stopped.
210
202
  const target = state.input.actor;
211
- if (!target || typeof target.getSnapshot === 'function' && target.getSnapshot().status === 'stopped') {
203
+ if (!target || target.getSnapshot().status === 'stopped') {
212
204
  return;
213
205
  }
214
206
  const subscription = attach(state.input, {
@@ -251,20 +243,16 @@ function createAttachedLogic(attach) {
251
243
  if (event.type === XSTATE_STOP) {
252
244
  subscriptions.get(self)?.unsubscribe();
253
245
  subscriptions.delete(self);
254
- return {
246
+ return [{
255
247
  ...state,
256
248
  status: 'stopped',
257
249
  error: undefined
258
- };
250
+ }, []];
259
251
  }
260
- return state;
252
+ return [state, []];
261
253
  },
262
- getInitialSnapshot: (_, input) => ({
263
- status: 'active',
264
- output: undefined,
265
- error: undefined,
266
- input
267
- }),
254
+ initialTransition,
255
+ getInitialSnapshot: (actorScope, input) => initialTransition(input)[0],
268
256
  getPersistedSnapshot: snapshot => snapshot,
269
257
  restoreSnapshot: snapshot => snapshot
270
258
  };
@@ -310,620 +298,6 @@ function createListenerLogic() {
310
298
  // Singleton logic instance
311
299
  const listenerLogic = /* #__PURE__ */createListenerLogic();
312
300
 
313
- /* eslint-disable */
314
- // Adapted from Alien Signals
315
- // https://github.com/stackblitz/alien-signals/
316
-
317
- let ReactiveFlags = /*#__PURE__*/function (ReactiveFlags) {
318
- ReactiveFlags[ReactiveFlags["None"] = 0] = "None";
319
- ReactiveFlags[ReactiveFlags["Mutable"] = 1] = "Mutable";
320
- ReactiveFlags[ReactiveFlags["Watching"] = 2] = "Watching";
321
- ReactiveFlags[ReactiveFlags["RecursedCheck"] = 4] = "RecursedCheck";
322
- ReactiveFlags[ReactiveFlags["Recursed"] = 8] = "Recursed";
323
- ReactiveFlags[ReactiveFlags["Dirty"] = 16] = "Dirty";
324
- ReactiveFlags[ReactiveFlags["Pending"] = 32] = "Pending";
325
- return ReactiveFlags;
326
- }({});
327
- function createReactiveSystem({
328
- update,
329
- notify,
330
- unwatched
331
- }) {
332
- return {
333
- link,
334
- unlink,
335
- propagate,
336
- checkDirty,
337
- shallowPropagate
338
- };
339
- function link(dep, sub, version) {
340
- const prevDep = sub.depsTail;
341
- if (prevDep !== undefined && prevDep.dep === dep) {
342
- return;
343
- }
344
- const nextDep = prevDep !== undefined ? prevDep.nextDep : sub.deps;
345
- if (nextDep !== undefined && nextDep.dep === dep) {
346
- nextDep.version = version;
347
- sub.depsTail = nextDep;
348
- return;
349
- }
350
- const prevSub = dep.subsTail;
351
- if (prevSub !== undefined && prevSub.version === version && prevSub.sub === sub) {
352
- return;
353
- }
354
- const newLink = sub.depsTail = dep.subsTail = {
355
- version,
356
- dep,
357
- sub,
358
- prevDep,
359
- nextDep,
360
- prevSub,
361
- nextSub: undefined
362
- };
363
- if (nextDep !== undefined) {
364
- nextDep.prevDep = newLink;
365
- }
366
- if (prevDep !== undefined) {
367
- prevDep.nextDep = newLink;
368
- } else {
369
- sub.deps = newLink;
370
- }
371
- if (prevSub !== undefined) {
372
- prevSub.nextSub = newLink;
373
- } else {
374
- dep.subs = newLink;
375
- }
376
- }
377
- function unlink(link, sub = link.sub) {
378
- const dep = link.dep;
379
- const prevDep = link.prevDep;
380
- const nextDep = link.nextDep;
381
- const nextSub = link.nextSub;
382
- const prevSub = link.prevSub;
383
- if (nextDep !== undefined) {
384
- nextDep.prevDep = prevDep;
385
- } else {
386
- sub.depsTail = prevDep;
387
- }
388
- if (prevDep !== undefined) {
389
- prevDep.nextDep = nextDep;
390
- } else {
391
- sub.deps = nextDep;
392
- }
393
- if (nextSub !== undefined) {
394
- nextSub.prevSub = prevSub;
395
- } else {
396
- dep.subsTail = prevSub;
397
- }
398
- if (prevSub !== undefined) {
399
- prevSub.nextSub = nextSub;
400
- } else if ((dep.subs = nextSub) === undefined) {
401
- unwatched(dep);
402
- }
403
- return nextDep;
404
- }
405
- function propagate(link) {
406
- let next = link.nextSub;
407
- let stack;
408
- top: do {
409
- const sub = link.sub;
410
- let flags = sub.flags;
411
- if (!(flags & (ReactiveFlags.RecursedCheck | ReactiveFlags.Recursed | ReactiveFlags.Dirty | ReactiveFlags.Pending))) {
412
- sub.flags = flags | ReactiveFlags.Pending;
413
- } else if (!(flags & (ReactiveFlags.RecursedCheck | ReactiveFlags.Recursed))) {
414
- flags = ReactiveFlags.None;
415
- } else if (!(flags & ReactiveFlags.RecursedCheck)) {
416
- sub.flags = flags & ~ReactiveFlags.Recursed | ReactiveFlags.Pending;
417
- } else if (!(flags & (ReactiveFlags.Dirty | ReactiveFlags.Pending)) && isValidLink(link, sub)) {
418
- sub.flags = flags | (ReactiveFlags.Recursed | ReactiveFlags.Pending);
419
- flags &= ReactiveFlags.Mutable;
420
- } else {
421
- flags = ReactiveFlags.None;
422
- }
423
- if (flags & ReactiveFlags.Watching) {
424
- notify(sub);
425
- }
426
- if (flags & ReactiveFlags.Mutable) {
427
- const subSubs = sub.subs;
428
- if (subSubs !== undefined) {
429
- const nextSub = (link = subSubs).nextSub;
430
- if (nextSub !== undefined) {
431
- stack = {
432
- value: next,
433
- prev: stack
434
- };
435
- next = nextSub;
436
- }
437
- continue;
438
- }
439
- }
440
- if ((link = next) !== undefined) {
441
- next = link.nextSub;
442
- continue;
443
- }
444
- while (stack !== undefined) {
445
- link = stack.value;
446
- stack = stack.prev;
447
- if (link !== undefined) {
448
- next = link.nextSub;
449
- continue top;
450
- }
451
- }
452
- break;
453
- } while (true);
454
- }
455
- function checkDirty(link, sub) {
456
- let stack;
457
- let checkDepth = 0;
458
- let dirty = false;
459
- top: do {
460
- const dep = link.dep;
461
- const flags = dep.flags;
462
- if (sub.flags & ReactiveFlags.Dirty) {
463
- dirty = true;
464
- } else if ((flags & (ReactiveFlags.Mutable | ReactiveFlags.Dirty)) === (ReactiveFlags.Mutable | ReactiveFlags.Dirty)) {
465
- if (update(dep)) {
466
- const subs = dep.subs;
467
- if (subs.nextSub !== undefined) {
468
- shallowPropagate(subs);
469
- }
470
- dirty = true;
471
- }
472
- } else if ((flags & (ReactiveFlags.Mutable | ReactiveFlags.Pending)) === (ReactiveFlags.Mutable | ReactiveFlags.Pending)) {
473
- if (link.nextSub !== undefined || link.prevSub !== undefined) {
474
- stack = {
475
- value: link,
476
- prev: stack
477
- };
478
- }
479
- link = dep.deps;
480
- sub = dep;
481
- ++checkDepth;
482
- continue;
483
- }
484
- if (!dirty) {
485
- const nextDep = link.nextDep;
486
- if (nextDep !== undefined) {
487
- link = nextDep;
488
- continue;
489
- }
490
- }
491
- while (checkDepth--) {
492
- const firstSub = sub.subs;
493
- const hasMultipleSubs = firstSub.nextSub !== undefined;
494
- if (hasMultipleSubs) {
495
- link = stack.value;
496
- stack = stack.prev;
497
- } else {
498
- link = firstSub;
499
- }
500
- if (dirty) {
501
- if (update(sub)) {
502
- if (hasMultipleSubs) {
503
- shallowPropagate(firstSub);
504
- }
505
- sub = link.sub;
506
- continue;
507
- }
508
- dirty = false;
509
- } else {
510
- sub.flags &= ~ReactiveFlags.Pending;
511
- }
512
- sub = link.sub;
513
- const nextDep = link.nextDep;
514
- if (nextDep !== undefined) {
515
- link = nextDep;
516
- continue top;
517
- }
518
- }
519
- return dirty;
520
- } while (true);
521
- }
522
- function shallowPropagate(link) {
523
- do {
524
- const sub = link.sub;
525
- const flags = sub.flags;
526
- if ((flags & (ReactiveFlags.Pending | ReactiveFlags.Dirty)) === ReactiveFlags.Pending) {
527
- sub.flags = flags | ReactiveFlags.Dirty;
528
- if ((flags & (ReactiveFlags.Watching | ReactiveFlags.RecursedCheck)) === ReactiveFlags.Watching) {
529
- notify(sub);
530
- }
531
- }
532
- } while ((link = link.nextSub) !== undefined);
533
- }
534
- function isValidLink(checkLink, sub) {
535
- let link = sub.depsTail;
536
- while (link !== undefined) {
537
- if (link === checkLink) {
538
- return true;
539
- }
540
- link = link.prevDep;
541
- }
542
- return false;
543
- }
544
- }
545
-
546
- /**
547
- * Nominal brand (phantom, compile-time only) marking a value as an XState atom.
548
- * Real atoms get the runtime brand ({@link $$atom}) in `createAtom`; this type
549
- * brand keeps atom-only APIs (e.g. `enq.subscribeTo`) from structurally
550
- * accepting plain readables like `actor.select(...)` that would be dispatched
551
- * down the non-atom path at runtime.
552
- */
553
-
554
- /** Brand marking an object as an atom, so it can be detected structurally. */
555
- const $$atom = /* #__PURE__ */Symbol.for('xstate.atom');
556
-
557
- /**
558
- * Returns `true` if the value is an atom (writable, computed, async, or
559
- * reducer). Lets actor-consuming APIs (e.g. `enq.subscribeTo`) accept atoms
560
- * directly.
561
- */
562
- function isAtom(value) {
563
- return !!value && typeof value === 'object' && $$atom in value;
564
- }
565
- const queuedEffects = [];
566
- let cycle = 0;
567
- // Initialized lazily on first atom creation (instead of at module evaluation)
568
- // so the reactive system stays tree-shakeable for apps that never use atoms —
569
-
570
- // would be retained by consumer bundlers even when atoms are unused.
571
- let link;
572
- let unlink;
573
- let propagate;
574
- let checkDirty;
575
- let shallowPropagate;
576
- let reactiveSystemInstalled = false;
577
- function ensureReactiveSystem() {
578
- if (reactiveSystemInstalled) {
579
- return;
580
- }
581
- reactiveSystemInstalled = true;
582
- ({
583
- link,
584
- unlink,
585
- propagate,
586
- checkDirty,
587
- shallowPropagate
588
- } = createReactiveSystem({
589
- update(atom) {
590
- return atom._update();
591
- },
592
- notify(effect) {
593
- queuedEffects[queuedEffectsLength++] = effect;
594
- effect.flags &= ~ReactiveFlags.Watching;
595
- },
596
- unwatched(atom) {
597
- if (atom.depsTail !== undefined) {
598
- atom.depsTail = undefined;
599
- atom.flags = ReactiveFlags.Mutable | ReactiveFlags.Dirty;
600
- purgeDeps(atom);
601
- }
602
- }
603
- }));
604
- }
605
- let notifyIndex = 0;
606
- let queuedEffectsLength = 0;
607
- let activeSub;
608
- function purgeDeps(sub) {
609
- const depsTail = sub.depsTail;
610
- let dep = depsTail !== undefined ? depsTail.nextDep : sub.deps;
611
- while (dep !== undefined) {
612
- dep = unlink(dep, sub);
613
- }
614
- }
615
- function flush() {
616
- while (notifyIndex < queuedEffectsLength) {
617
- const effect = queuedEffects[notifyIndex];
618
- queuedEffects[notifyIndex++] = undefined;
619
- effect.notify();
620
- }
621
- notifyIndex = 0;
622
- queuedEffectsLength = 0;
623
- }
624
-
625
- /** The current state of an async atom. */
626
-
627
- /** Options passed to an async atom getter. */
628
-
629
- function compareAsyncAtomState(a, b) {
630
- if (a.status !== b.status) {
631
- return false;
632
- }
633
- if (a.status === 'done' && b.status === 'done') {
634
- return Object.is(a.data, b.data);
635
- }
636
- if (a.status === 'error' && b.status === 'error') {
637
- return Object.is(a.error, b.error);
638
- }
639
- // both 'pending'
640
- return true;
641
- }
642
- function updateAsyncAtom(atom, nextValue) {
643
- if (atom._update(nextValue)) {
644
- const subs = atom.subs;
645
- if (subs !== undefined) {
646
- propagate(subs);
647
- shallowPropagate(subs);
648
- flush();
649
- }
650
- }
651
- }
652
-
653
- /**
654
- * Creates a read-only atom whose value is loaded from an async getter.
655
- *
656
- * The getter receives an `AbortSignal`; when the async atom recomputes, the
657
- * previous signal is aborted and stale resolutions are ignored.
658
- */
659
- function createAsyncAtom(getValue, options) {
660
- const ref = {};
661
- let currentController;
662
- let currentRunId = 0;
663
- const atom = createAtom(() => {
664
- currentController?.abort();
665
- const controller = new AbortController();
666
- const runId = ++currentRunId;
667
- currentController = controller;
668
- getValue({
669
- signal: controller.signal
670
- }).then(data => {
671
- if (runId !== currentRunId || controller.signal.aborted) {
672
- return;
673
- }
674
- updateAsyncAtom(ref.current, {
675
- status: 'done',
676
- data
677
- });
678
- }, error => {
679
- if (runId !== currentRunId || controller.signal.aborted) {
680
- return;
681
- }
682
- updateAsyncAtom(ref.current, {
683
- status: 'error',
684
- error
685
- });
686
- });
687
- return {
688
- status: 'pending'
689
- };
690
- }, {
691
- compare: compareAsyncAtomState,
692
- ...options
693
- });
694
- ref.current = atom;
695
- return atom;
696
- }
697
-
698
- /**
699
- * Mirror atoms that bump a version whenever a tracked actor emits a snapshot,
700
- * letting computed atoms depend on `actor.get()` reads.
701
- *
702
- * The hook is installed lazily on first atom creation (not at module
703
- * evaluation) so that it remains tree-shakeable for apps that never use atoms —
704
- * any tracked read necessarily happens inside an atom computation, so first-use
705
- * installation is always early enough.
706
- */
707
- let actorInteropInstalled = false;
708
- function ensureActorInterop() {
709
- if (actorInteropInstalled) {
710
- return;
711
- }
712
- actorInteropInstalled = true;
713
- const actorVersions = new WeakMap();
714
- installActorReadHook(actorRef => {
715
- if (activeSub === undefined) {
716
- return;
717
- }
718
- let version = actorVersions.get(actorRef);
719
- if (version === undefined) {
720
- version = createAtom(0);
721
- actorVersions.set(actorRef, version);
722
- actorRef.subscribe({
723
- next: () => version.set(v => v + 1),
724
- error: () => {}
725
- });
726
- }
727
- version.get();
728
- });
729
- }
730
-
731
- /**
732
- * Creates an atom.
733
- *
734
- * Pass a value for a writable atom or a getter for a computed read-only atom.
735
- */
736
-
737
- function createAtom(valueOrFn, optionsOrInput) {
738
- ensureReactiveSystem();
739
- ensureActorInterop();
740
- const isComputed = typeof valueOrFn === 'function';
741
- const getter = valueOrFn;
742
-
743
- // Create plain object atom
744
- const atom = {
745
- _snapshot: isComputed ? undefined : valueOrFn,
746
- subs: undefined,
747
- subsTail: undefined,
748
- deps: undefined,
749
- depsTail: undefined,
750
- flags: isComputed ? ReactiveFlags.None : ReactiveFlags.Mutable,
751
- get() {
752
- if (activeSub !== undefined) {
753
- link(atom, activeSub, cycle);
754
- }
755
- return atom._snapshot;
756
- },
757
- subscribe(observerOrFn) {
758
- const observer = typeof observerOrFn === 'function' ? {
759
- next: observerOrFn
760
- } : observerOrFn;
761
- const observed = {
762
- current: false
763
- };
764
- const e = effect(() => {
765
- atom.get();
766
- if (!observed.current) {
767
- observed.current = true;
768
- } else {
769
- const prevSub = activeSub;
770
- activeSub = undefined;
771
- try {
772
- observer.next?.(atom._snapshot);
773
- } catch (err) {
774
- reportUnhandledError(err);
775
- } finally {
776
- activeSub = prevSub;
777
- }
778
-
779
- // If the observer synchronously updates any of our deps we'll be
780
- // marked as dirty preventing this effect from re-running. Request
781
- // the value again to reconcile any dirty deps.
782
- atom.get();
783
- }
784
- });
785
- return {
786
- unsubscribe: () => {
787
- e.stop();
788
- }
789
- };
790
- },
791
- _update(getValue) {
792
- const prevSub = activeSub;
793
- const compare = optionsOrInput?.compare ?? Object.is;
794
- activeSub = atom;
795
- ++cycle;
796
- atom.depsTail = undefined;
797
- if (isComputed) {
798
- atom.flags = ReactiveFlags.Mutable | ReactiveFlags.RecursedCheck;
799
- }
800
- try {
801
- const oldValue = atom._snapshot;
802
- const newValue = typeof getValue === 'function' ? getValue(oldValue) : getValue === undefined && isComputed ? getter(oldValue) : getValue;
803
- if (oldValue === undefined || !compare(oldValue, newValue)) {
804
- atom._snapshot = newValue;
805
- return true;
806
- }
807
- return false;
808
- } finally {
809
- activeSub = prevSub;
810
- if (isComputed) {
811
- atom.flags &= ~ReactiveFlags.RecursedCheck;
812
- }
813
- purgeDeps(atom);
814
- }
815
- }
816
- };
817
- if (isComputed) {
818
- atom.flags = ReactiveFlags.Mutable | ReactiveFlags.Dirty;
819
- atom.get = function () {
820
- const flags = atom.flags;
821
- if (flags & ReactiveFlags.Dirty || flags & ReactiveFlags.Pending && checkDirty(atom.deps, atom)) {
822
- if (atom._update()) {
823
- const subs = atom.subs;
824
- if (subs !== undefined) {
825
- shallowPropagate(subs);
826
- }
827
- }
828
- } else if (flags & ReactiveFlags.Pending) {
829
- atom.flags = flags & ~ReactiveFlags.Pending;
830
- }
831
- if (activeSub !== undefined) {
832
- link(atom, activeSub, cycle);
833
- }
834
- return atom._snapshot;
835
- };
836
- } else {
837
- atom.set = function (valueOrFn) {
838
- if (atom._update(valueOrFn)) {
839
- const subs = atom.subs;
840
- if (subs !== undefined) {
841
- propagate(subs);
842
- shallowPropagate(subs);
843
- flush();
844
- }
845
- }
846
- };
847
- }
848
- atom[$$atom] = true;
849
- return atom;
850
- }
851
-
852
- /**
853
- * Creates an inert atom config that can be instantiated later.
854
- *
855
- * Useful for framework hooks that need to create a stable local atom from
856
- * component input.
857
- */
858
-
859
- function createAtomConfig(initialValueOrFn, options) {
860
- return {
861
- createAtom(input) {
862
- const initialValue = typeof initialValueOrFn === 'function' ? initialValueOrFn(input) : initialValueOrFn;
863
- return createAtom(initialValue, options);
864
- }
865
- };
866
- }
867
-
868
- /** Creates an atom whose updates are handled by a reducer function. */
869
- function createReducerAtom(initialValue, reducer, options) {
870
- const atom = createAtom(initialValue, options);
871
- return {
872
- [$$atom]: true,
873
- get: atom.get.bind(atom),
874
- subscribe: atom.subscribe.bind(atom),
875
- send(event) {
876
- const prevSub = activeSub;
877
- activeSub = undefined;
878
- let nextState;
879
- try {
880
- nextState = reducer(atom.get(), event);
881
- } finally {
882
- activeSub = prevSub;
883
- }
884
- atom.set(nextState);
885
- }
886
- };
887
- }
888
- function effect(fn) {
889
- const run = () => {
890
- const prevSub = activeSub;
891
- activeSub = effectObj;
892
- ++cycle;
893
- effectObj.depsTail = undefined;
894
- effectObj.flags = ReactiveFlags.Watching | ReactiveFlags.RecursedCheck;
895
- try {
896
- return fn();
897
- } finally {
898
- activeSub = prevSub;
899
- effectObj.flags &= ~ReactiveFlags.RecursedCheck;
900
- purgeDeps(effectObj);
901
- }
902
- };
903
- const effectObj = {
904
- deps: undefined,
905
- depsTail: undefined,
906
- subs: undefined,
907
- subsTail: undefined,
908
- flags: ReactiveFlags.Watching | ReactiveFlags.RecursedCheck,
909
- notify() {
910
- const flags = this.flags;
911
- if (flags & ReactiveFlags.Dirty || flags & ReactiveFlags.Pending && checkDirty(this.deps, this)) {
912
- run();
913
- } else {
914
- this.flags = ReactiveFlags.Watching;
915
- }
916
- },
917
- stop() {
918
- this.flags = ReactiveFlags.None;
919
- this.depsTail = undefined;
920
- purgeDeps(this);
921
- }
922
- };
923
- run();
924
- return effectObj;
925
- }
926
-
927
301
  /**
928
302
  * Creates actor logic for subscribing to lifecycle events (done/error/snapshot)
929
303
  * from another actor. Used internally by `enq.subscribeTo()`.
@@ -941,15 +315,6 @@ function createSubscriptionLogic() {
941
315
  error,
942
316
  snapshot: onSnapshot
943
317
  } = mappers;
944
-
945
- // Atoms emit a raw value (no `status`) and have no done/error lifecycle —
946
- // pass the value straight to the `snapshot` mapper.
947
- if (isAtom(actor)) {
948
- if (!onSnapshot) {
949
- return;
950
- }
951
- return actor.subscribe(value => relayMappedToParent(self, system, () => onSnapshot(value)));
952
- }
953
318
  return actor.subscribe({
954
319
  next: snapshot => {
955
320
  if (snapshot.status === 'done' && done) {
@@ -1050,7 +415,7 @@ function createTransitionEnqueue(actorScope, actions, internalEvents, actorSubsc
1050
415
  },
1051
416
  stop: actor => {
1052
417
  if (actor) {
1053
- pushBuiltInAction(actions, builtInActions['@xstate.stopChild'], actorScope, actor);
418
+ pushBuiltInAction(actions, builtInActions['@xstate.stop'], actorScope, actor);
1054
419
  actions.push(unregisterChild(actor));
1055
420
  }
1056
421
  }
@@ -1091,16 +456,65 @@ function createTransitionEnqueue(actorScope, actions, internalEvents, actorSubsc
1091
456
  pushBuiltInAction(actions, action, ...args);
1092
457
  });
1093
458
  }
1094
- function resolveAndExecuteActionsWithContext(currentSnapshot, event, actorScope, actions) {
459
+ function getBuiltInActionFields(action, args) {
460
+ switch (action) {
461
+ case builtInActions['@xstate.start']:
462
+ {
463
+ const [actor] = args;
464
+ return {
465
+ actor,
466
+ id: actor.id,
467
+ logic: actor.logic,
468
+ src: actor.src,
469
+ input: actor.options?.input
470
+ };
471
+ }
472
+ case builtInActions['@xstate.raise']:
473
+ {
474
+ const [, event, options] = args;
475
+ return {
476
+ event,
477
+ id: options?.id,
478
+ delay: options?.delay
479
+ };
480
+ }
481
+ case builtInActions['@xstate.sendTo']:
482
+ {
483
+ const [, target, event, options] = args;
484
+ return {
485
+ target,
486
+ event,
487
+ id: options?.id,
488
+ delay: options?.delay
489
+ };
490
+ }
491
+ case builtInActions['@xstate.cancel']:
492
+ {
493
+ const [, id] = args;
494
+ return {
495
+ id
496
+ };
497
+ }
498
+ case builtInActions['@xstate.stop']:
499
+ {
500
+ const [, actor] = args;
501
+ return {
502
+ actor
503
+ };
504
+ }
505
+ default:
506
+ return undefined;
507
+ }
508
+ }
509
+ function isBuiltInExecutableAction(action) {
510
+ return Object.prototype.hasOwnProperty.call(builtInActions, action.type);
511
+ }
512
+ function resolveActionsWithContext(currentSnapshot, event, actorScope, actions) {
1095
513
  let intermediateSnapshot = currentSnapshot;
514
+ const executableActions = [];
1096
515
  for (const action of actions) {
1097
516
  const isInline = typeof action === 'function';
1098
517
  const resolvedAction = isInline ? action : typeof action === 'object' && 'action' in action && typeof action.action === 'function' ? action.action.bind(null, ...action.args) : false;
1099
- if (!resolvedAction && typeof action === 'object' && action !== null) {
1100
- actorScope.defer(() => {
1101
- actorScope.emit(action);
1102
- });
1103
- }
1104
518
  const actionArgs = {
1105
519
  context: intermediateSnapshot.context,
1106
520
  event,
@@ -1120,7 +534,7 @@ function resolveAndExecuteActionsWithContext(currentSnapshot, event, actorScope,
1120
534
  actionParams = emittedEventParams;
1121
535
  }
1122
536
  if (resolvedAction && '_special' in resolvedAction) {
1123
- actorScope.actionExecutor({
537
+ executableActions.push({
1124
538
  type: typeof action === 'object' ? 'action' in action && typeof action.action === 'function' ? action.action.name ?? '(anonymous)' : action.type ?? '(anonymous)' : action.name || '(anonymous)',
1125
539
  params: actionParams,
1126
540
  args: [],
@@ -1141,16 +555,18 @@ function resolveAndExecuteActionsWithContext(currentSnapshot, event, actorScope,
1141
555
  continue;
1142
556
  }
1143
557
  if (!resolvedAction || !('resolve' in resolvedAction)) {
1144
- actorScope.actionExecutor({
558
+ const builtInFields = typeof action === 'object' && action !== null && 'action' in action && typeof action.action === 'function' ? getBuiltInActionFields(action.action, action.args) : undefined;
559
+ executableActions.push({
1145
560
  type: typeof action === 'object' ? 'action' in action && typeof action.action === 'function' ? action.action.name ?? '(anonymous)' : action.type : action.name || '(anonymous)',
1146
561
  params: actionParams,
1147
562
  args: typeof action === 'object' && 'action' in action ? action.args : [],
1148
- exec: resolvedAction
563
+ exec: resolvedAction || (typeof action === 'object' && action !== null ? () => actorScope.defer(() => actorScope.emit(action)) : undefined),
564
+ ...builtInFields
1149
565
  });
1150
566
  continue;
1151
567
  }
1152
568
  }
1153
- return intermediateSnapshot;
569
+ return [intermediateSnapshot, executableActions];
1154
570
  }
1155
571
  function createEnqueueObject$1(props, action) {
1156
572
  const enqueueFn = (fn, ...args) => {
@@ -1344,22 +760,9 @@ function isInFinalState(stateNodeSet, stateNode) {
1344
760
  }
1345
761
  const isStateId = str => str[0] === STATE_IDENTIFIER;
1346
762
  function getCandidates(stateNode, receivedEventType) {
1347
- const candidates = stateNode.transitions.get(receivedEventType);
1348
- if (candidates) {
1349
- return candidates;
1350
- }
1351
- const matchingDescriptors = [];
1352
- for (const eventDescriptor of stateNode.transitions.keys()) {
1353
- if (matchesEventDescriptor(receivedEventType, eventDescriptor)) {
1354
- matchingDescriptors.push(eventDescriptor);
1355
- }
1356
- }
1357
- matchingDescriptors.sort((a, b) => b.length - a.length);
1358
- const wildcardCandidates = [];
1359
- for (const descriptor of matchingDescriptors) {
1360
- wildcardCandidates.push(...stateNode.transitions.get(descriptor));
1361
- }
1362
- return wildcardCandidates;
763
+ const exactMatch = stateNode.transitions.get(receivedEventType);
764
+ const wildcardCandidates = [...stateNode.transitions.keys()].filter(eventDescriptor => eventDescriptor !== receivedEventType && matchesEventDescriptor(receivedEventType, eventDescriptor)).sort((a, b) => b.length - a.length).flatMap(key => stateNode.transitions.get(key));
765
+ return exactMatch ? [...exactMatch, ...wildcardCandidates] : wildcardCandidates;
1363
766
  }
1364
767
  function scheduleDelayedEvent(stateNode, event, resolveScheduledDelay) {
1365
768
  const eventType = event.type;
@@ -1398,61 +801,68 @@ function getDelayedTransitions(stateNode) {
1398
801
  }
1399
802
  }
1400
803
  }
1401
- const mutateEntryExitWithDelay = delay => {
1402
- const afterEvent = createAfterEvent(delay, stateNode.id);
1403
- return scheduleDelayedEvent(stateNode, afterEvent, x => resolveDelay(delay, x.delays, {
1404
- context: x.context,
1405
- event: x.event,
1406
- stateNode
1407
- }));
1408
- };
1409
- const delayedTransitions = [];
1410
- const addDelayedTransitions = (transitionsConfig, event, delay) => {
1411
- for (const transition of toTransitionConfigArray(transitionsConfig)) {
1412
- delayedTransitions.push({
1413
- ...transition,
1414
- event,
1415
- delay
1416
- });
1417
- }
1418
- };
804
+
805
+ // Every delayed transition — `after`, state-level `timeout`/`onTimeout`, and
806
+ // invoke-level `timeout`/`onTimeout` has the same shape: an event raised on
807
+ // entry (and cancelled on exit) plus a transition that catches it. They
808
+ // differ only in the event raised, the transition(s) caught, and whether the
809
+ // delay resolves against the machine's `delays` map (invoke timeouts do not).
810
+ //
811
+ // `xstate.timeout.<id>` is a dedicated event so a state-level `timeout` cannot
812
+ // collide with an explicit `after` entry on the same state. Invoke timeouts
813
+ // are scheduled on the enclosing state; completion transitions cancel the
814
+ // timer separately, so it clears even when the parent state stays active.
815
+ const sources = [];
1419
816
  if (afterConfig) {
1420
- for (const delay of Object.keys(afterConfig)) {
1421
- const configTransition = afterConfig[delay];
1422
- const parsedDelay = Number.isNaN(+delay) ? delay : +delay;
1423
- const eventType = mutateEntryExitWithDelay(parsedDelay);
1424
- const resolvedDelay = getConfiguredDelayValue(parsedDelay, stateNode.machine.implementations.delays);
1425
- addDelayedTransitions(configTransition, eventType, resolvedDelay);
817
+ for (const key of Object.keys(afterConfig)) {
818
+ const delay = Number.isNaN(+key) ? key : +key;
819
+ sources.push({
820
+ event: createAfterEvent(delay, stateNode.id),
821
+ delay,
822
+ transitions: afterConfig[key],
823
+ fromDelaysMap: true
824
+ });
1426
825
  }
1427
826
  }
1428
-
1429
- // Desugar state-level `timeout` + `onTimeout` into a delayed transition.
1430
- // Uses a dedicated `xstate.timeout.<id>` event so it cannot collide with
1431
- // explicit `after` entries on the same state.
1432
827
  if (timeoutConfig !== undefined && onTimeoutConfig) {
1433
- const timeoutEvent = createTimeoutEvent(stateNode.id);
1434
- const timeoutEventType = scheduleDelayedEvent(stateNode, timeoutEvent, x => resolveDelay(timeoutConfig, x.delays, {
1435
- context: x.context,
1436
- event: x.event,
1437
- stateNode
1438
- }));
1439
- const resolvedDelay = typeof timeoutConfig === 'function' ? timeoutConfig : getConfiguredDelayValue(timeoutConfig, stateNode.machine.implementations.delays);
1440
- addDelayedTransitions(onTimeoutConfig, timeoutEventType, resolvedDelay);
828
+ sources.push({
829
+ event: createTimeoutEvent(stateNode.id),
830
+ delay: timeoutConfig,
831
+ transitions: onTimeoutConfig,
832
+ fromDelaysMap: true
833
+ });
1441
834
  }
1442
-
1443
- // Desugar invoke-level `timeout` + `onTimeout` into a delayed transition on
1444
- // the enclosing state. Completion transitions cancel this timer separately,
1445
- // so the timeout is cleared even when the parent state stays active.
1446
835
  for (const invokeDef of invokeDefs) {
1447
- const invokeTimeoutEvent = createInvokeTimeoutEvent(invokeDef.id);
1448
- const invokeTimeout = invokeDef.timeout;
1449
- const invokeTimeoutEventType = scheduleDelayedEvent(stateNode, invokeTimeoutEvent, x => resolveDelay(invokeTimeout, {}, {
836
+ sources.push({
837
+ event: createInvokeTimeoutEvent(invokeDef.id),
838
+ delay: invokeDef.timeout,
839
+ transitions: invokeDef.onTimeout,
840
+ fromDelaysMap: false
841
+ });
842
+ }
843
+
844
+ // `delay` here is the raw config value, retained only as metadata on the
845
+ // transition definition — the live delay is resolved at runtime in the
846
+ // scheduled entry action, so no eager resolution is needed.
847
+ const delayedTransitions = [];
848
+ for (const {
849
+ event,
850
+ delay,
851
+ transitions,
852
+ fromDelaysMap
853
+ } of sources) {
854
+ const eventType = scheduleDelayedEvent(stateNode, event, x => resolveDelay(delay, fromDelaysMap ? x.delays : {}, {
1450
855
  context: x.context,
1451
856
  event: x.event,
1452
857
  stateNode
1453
858
  }));
1454
- const invokeOnTimeout = invokeDef.onTimeout;
1455
- addDelayedTransitions(invokeOnTimeout, invokeTimeoutEventType, invokeTimeout);
859
+ for (const transition of toTransitionConfigArray(transitions)) {
860
+ delayedTransitions.push({
861
+ ...transition,
862
+ event: eventType,
863
+ delay
864
+ });
865
+ }
1456
866
  }
1457
867
  return delayedTransitions.map(delayedTransition => ({
1458
868
  ...formatTransition(stateNode, delayedTransition.event, delayedTransition),
@@ -1517,27 +927,13 @@ function formatRouteTransitions(rootStateNode) {
1517
927
  if ('$unserializable' in routeConfig) {
1518
928
  throw new Error(`State "${sn.id}" has a route that is not serializable. Re-provide the route function when reviving this machine.`);
1519
929
  }
1520
-
1521
- // Object-form route. A `guard` (string or function) on the object is
1522
- // only produced by the JSON layer (createMachineFromConfig) —
1523
- // authoring uses the function form above.
1524
- const userGuard = routeConfig.guard;
930
+ const {
931
+ guard: _guard,
932
+ ...routeOptions
933
+ } = routeConfig;
1525
934
  const transition = {
1526
- ...routeConfig,
1527
- guard: userGuard ? args => {
1528
- if (!routeMatches(args)) return false;
1529
- if (typeof userGuard === 'function') return userGuard(args);
1530
- if (typeof userGuard === 'string') {
1531
- const guardImpl = args.guards?.[userGuard];
1532
- if (!guardImpl) {
1533
- // A typo'd guard name must fail loudly — silently passing
1534
- // would allow the route and corrupt machine behavior.
1535
- throw new Error(`Guard '${userGuard}' is not implemented in machine '${rootStateNode.machine.id}'. Available guards: ${Object.keys(args.guards ?? {}).map(key => `'${key}'`).join(', ') || '(none)'}.` );
1536
- }
1537
- return guardImpl(args);
1538
- }
1539
- return true;
1540
- } : routeMatches,
935
+ ...routeOptions,
936
+ guard: routeMatches,
1541
937
  target: `#${routeId}`
1542
938
  };
1543
939
  routeTransitions.push(formatTransition(rootStateNode, 'xstate.route', transition));
@@ -1868,16 +1264,11 @@ function initialMicrostep(root, preInitialState, actorScope, initEvent, internal
1868
1264
 
1869
1265
  /** https://www.w3.org/TR/scxml/#microstepProcedure */
1870
1266
  function microstep(transitions, currentSnapshot, actorScope, event, isInitial, internalQueue) {
1871
- const actions = [];
1267
+ const executableActions = [];
1872
1268
  if (!transitions.length) {
1873
- return [currentSnapshot, actions];
1269
+ return [currentSnapshot, executableActions];
1874
1270
  }
1875
- const originalExecutor = actorScope.actionExecutor;
1876
- actorScope.actionExecutor = action => {
1877
- actions.push(action);
1878
- originalExecutor(action);
1879
- };
1880
- try {
1271
+ {
1881
1272
  const mutStateNodeSet = new Set(currentSnapshot._nodes);
1882
1273
  let historyValue = currentSnapshot.historyValue;
1883
1274
  const originalContext = currentSnapshot.context;
@@ -1950,7 +1341,9 @@ function microstep(transitions, currentSnapshot, actorScope, event, isInitial, i
1950
1341
  context: nextContext
1951
1342
  });
1952
1343
  }
1953
- nextState = resolveAndExecuteActionsWithContext(nextState, event, actorScope, exitActions);
1344
+ const [resolvedState, resolvedActions] = resolveActionsWithContext(nextState, event, actorScope, exitActions);
1345
+ nextState = resolvedState;
1346
+ executableActions.push(...resolvedActions);
1954
1347
  for (const def of exitStateNode.invoke) {
1955
1348
  const childActor = nextState.children[def.id];
1956
1349
  if (childActor && !childActor._isExternal) {
@@ -2185,7 +1578,10 @@ function microstep(transitions, currentSnapshot, actorScope, event, isInitial, i
2185
1578
  }
2186
1579
  }
2187
1580
  }
2188
- nextState = resolveAndExecuteActionsWithContext(nextState, event, actorScope, actions);
1581
+ const [resolvedState, resolvedActions] = resolveActionsWithContext(nextState, event, actorScope, actions);
1582
+ nextState = resolvedState;
1583
+ actions.length = 0;
1584
+ executableActions.push(...resolvedActions);
2189
1585
  if (context) {
2190
1586
  nextState.context = context;
2191
1587
  }
@@ -2236,7 +1632,9 @@ function microstep(transitions, currentSnapshot, actorScope, event, isInitial, i
2236
1632
  };
2237
1633
 
2238
1634
  // Execute transition content
2239
- nextState = resolveAndExecuteActionsWithContext(nextState, event, actorScope, transitionActions);
1635
+ const [resolvedTransitionState, transitionExecutableActions] = resolveActionsWithContext(nextState, event, actorScope, transitionActions);
1636
+ nextState = resolvedTransitionState;
1637
+ executableActions.push(...transitionExecutableActions);
2240
1638
  if (context && context !== currentSnapshot.context) {
2241
1639
  nextState = cloneMachineSnapshot(nextState, {
2242
1640
  context
@@ -2259,22 +1657,22 @@ function microstep(transitions, currentSnapshot, actorScope, event, isInitial, i
2259
1657
  }
2260
1658
  }
2261
1659
  });
2262
- nextState = resolveAndExecuteActionsWithContext(nextState, event, actorScope, allExitActions);
1660
+ const [resolvedState, resolvedActions] = resolveActionsWithContext(nextState, event, actorScope, allExitActions);
1661
+ nextState = resolvedState;
1662
+ executableActions.push(...resolvedActions);
2263
1663
  }
2264
1664
  if (historyValue === currentSnapshot.historyValue && currentSnapshot._nodes.length === mutStateNodeSet.size && currentSnapshot._nodes.every(node => mutStateNodeSet.has(node))) {
2265
1665
  // If context was changed (e.g. by entry actions during self-transition),
2266
1666
  // clone to ensure reference inequality for eventless transition re-evaluation
2267
1667
  if (nextState.context !== originalContext) {
2268
- return [cloneMachineSnapshot(nextState), actions];
1668
+ return [cloneMachineSnapshot(nextState), executableActions];
2269
1669
  }
2270
- return [nextState, actions];
1670
+ return [nextState, executableActions];
2271
1671
  }
2272
1672
  return [cloneMachineSnapshot(nextState, {
2273
1673
  _nodes: nextStateNodes,
2274
1674
  historyValue
2275
- }), actions];
2276
- } finally {
2277
- actorScope.actionExecutor = originalExecutor;
1675
+ }), executableActions];
2278
1676
  }
2279
1677
  }
2280
1678
 
@@ -2535,24 +1933,7 @@ function evaluateCandidate(candidate, event, snapshot, stateNode, self) {
2535
1933
  delays: stateNode.machine.implementations.delays,
2536
1934
  _snapshot: snapshot
2537
1935
  };
2538
- const guardConfig = candidate.guard;
2539
- const guardParams = typeof guardConfig?.params === 'function' ? guardConfig.params({
2540
- context: snapshot.context,
2541
- event
2542
- }) : guardConfig?.params;
2543
- let guardPassed = true;
2544
- if (typeof guardConfig === 'function') {
2545
- guardPassed = guardConfig(guardArgs, guardParams);
2546
- } else if (typeof guardConfig?.type === 'string') {
2547
- const guardImpl = stateNode.machine.implementations.guards[guardConfig.type];
2548
- if (!guardImpl) {
2549
- // A typo'd guard name must fail loudly — silently passing would
2550
- // take the guarded transition and corrupt machine behavior.
2551
- throw new Error(`Guard '${guardConfig.type}' is not implemented in machine '${stateNode.machine.id}'. Available guards: ${Object.keys(stateNode.machine.implementations.guards).map(key => `'${key}'`).join(', ') || '(none)'}.` );
2552
- }
2553
- guardPassed = guardImpl(guardArgs, guardParams);
2554
- }
2555
- if (!guardPassed) {
1936
+ if (!candidate.guard(guardArgs)) {
2556
1937
  return false;
2557
1938
  }
2558
1939
  }
@@ -3377,7 +2758,7 @@ function createLogic(config) {
3377
2758
  Object.assign(snapshot, nextSnapshot);
3378
2759
  executeLogicEffects(effects, actorScope);
3379
2760
  },
3380
- getInitialSnapshot: (_, input) => {
2761
+ initialTransition: (input, _) => {
3381
2762
  const context = resolveContext(config.context, input);
3382
2763
  const snapshot = {
3383
2764
  status: 'active',
@@ -3388,10 +2769,11 @@ function createLogic(config) {
3388
2769
  if (context !== undefined) {
3389
2770
  snapshot.context = context;
3390
2771
  }
3391
- return {
2772
+ return [{
3392
2773
  ...snapshot
3393
- };
2774
+ }, []];
3394
2775
  },
2776
+ getInitialSnapshot: (actorScope, input) => logic.initialTransition(input, actorScope)[0],
3395
2777
  getPersistedSnapshot: snapshot => snapshot,
3396
2778
  restoreSnapshot: snapshot => snapshot
3397
2779
  };
@@ -3421,6 +2803,23 @@ const defaultOptions = {
3421
2803
  },
3422
2804
  logger: console.log.bind(console)
3423
2805
  };
2806
+ function isExecutableActionObject(effect) {
2807
+ return typeof effect === 'object' && effect !== null && 'args' in effect && 'exec' in effect;
2808
+ }
2809
+ function executeExecutableEffects(effects, actorScope) {
2810
+ if (!effects?.length) {
2811
+ return [];
2812
+ }
2813
+ const logicEffects = [];
2814
+ for (const effect of effects) {
2815
+ if (isExecutableActionObject(effect)) {
2816
+ actorScope.actionExecutor(effect);
2817
+ } else {
2818
+ logicEffects.push(effect);
2819
+ }
2820
+ }
2821
+ return logicEffects;
2822
+ }
3424
2823
 
3425
2824
  /**
3426
2825
  * An Actor is a running process that can receive events, send events and change
@@ -3459,6 +2858,7 @@ class Actor {
3459
2858
  this.logger = void 0;
3460
2859
  /** @internal */
3461
2860
  this._processingStatus = ProcessingStatus.NotStarted;
2861
+ this._forceDeferredActions = false;
3462
2862
  // Actor Ref
3463
2863
  this._parent = void 0;
3464
2864
  /** @internal */
@@ -3474,6 +2874,7 @@ class Actor {
3474
2874
  this._collectedActions = [];
3475
2875
  /** @internal Events relayed to other actors during the in-flight transition. */
3476
2876
  this._collectedSent = [];
2877
+ this._initialEffects = void 0;
3477
2878
  this.systemId = void 0;
3478
2879
  /** The globally unique process ID for this invocation. */
3479
2880
  this.sessionId = void 0;
@@ -3576,7 +2977,7 @@ class Actor {
3576
2977
  executingCustomAction = saveExecutingCustomAction;
3577
2978
  }
3578
2979
  };
3579
- if (this._processingStatus === ProcessingStatus.Running) {
2980
+ if (this._processingStatus === ProcessingStatus.Running && !this._forceDeferredActions) {
3580
2981
  exec();
3581
2982
  } else {
3582
2983
  this._deferred.push(exec);
@@ -3605,7 +3006,7 @@ class Actor {
3605
3006
  this.system._set(systemId, this);
3606
3007
  }
3607
3008
 
3608
- // prepare to collect initial microsteps during getInitialSnapshot
3009
+ // prepare to collect initial microsteps during initialTransition
3609
3010
  this._collectedMicrosteps = [];
3610
3011
  let persistedState = options?.snapshot ?? options?.state;
3611
3012
  if (persistedState && typeof persistedState === 'object' && '_pendingEffects' in persistedState) {
@@ -3619,7 +3020,13 @@ class Actor {
3619
3020
  persistedState = rest;
3620
3021
  }
3621
3022
  try {
3622
- this._snapshot = persistedState ? this.logic.restoreSnapshot ? this.logic.restoreSnapshot(persistedState, this._actorScope) : persistedState : this.logic.getInitialSnapshot(this._actorScope, this.options?.input);
3023
+ if (persistedState) {
3024
+ this._snapshot = this.logic.restoreSnapshot ? this.logic.restoreSnapshot(persistedState, this._actorScope) : persistedState;
3025
+ } else {
3026
+ const [snapshot, effects] = this.logic.initialTransition(this.options?.input, this._actorScope);
3027
+ this._snapshot = snapshot;
3028
+ this._initialEffects = effects;
3029
+ }
3623
3030
  } catch (err) {
3624
3031
  // if we get here then it means that we assign a value to this._snapshot that is not of the correct type
3625
3032
  // we can't get the true `TSnapshot & { status: 'error'; }`, it's impossible
@@ -3728,6 +3135,26 @@ class Actor {
3728
3135
  this._collectedActions = [];
3729
3136
  this._collectedSent = [];
3730
3137
  }
3138
+ _flushInitialEffects() {
3139
+ if (!this._initialEffects) {
3140
+ return true;
3141
+ }
3142
+ this._forceDeferredActions = true;
3143
+ try {
3144
+ const logicEffects = executeExecutableEffects(this._initialEffects, this._actorScope);
3145
+ executeLogicEffects(logicEffects, this._actorScope);
3146
+ this._initialEffects = undefined;
3147
+ return true;
3148
+ } catch (err) {
3149
+ this._initialEffects = undefined;
3150
+ this._deferred.length = 0;
3151
+ this._setErrorSnapshot(err);
3152
+ this._error(err);
3153
+ return false;
3154
+ } finally {
3155
+ this._forceDeferredActions = false;
3156
+ }
3157
+ }
3731
3158
 
3732
3159
  /**
3733
3160
  * Subscribe an observer to an actor’s snapshot values.
@@ -3854,7 +3281,7 @@ class Actor {
3854
3281
  complete: observer.complete
3855
3282
  });
3856
3283
  },
3857
- get: () => selector(this.get())
3284
+ get: () => selector(this.getSnapshot())
3858
3285
  };
3859
3286
  }
3860
3287
 
@@ -3892,6 +3319,9 @@ class Actor {
3892
3319
  case 'done':
3893
3320
  // a state machine can be "done" upon initialization (it could reach a final state using initial microsteps)
3894
3321
  // we still need to complete observers, flush deferreds etc
3322
+ if (!this._flushInitialEffects()) {
3323
+ return this;
3324
+ }
3895
3325
  this.update(this._snapshot, initEvent);
3896
3326
  // TODO: rethink cleanup of observers, mailbox, etc
3897
3327
  return this;
@@ -3911,6 +3341,9 @@ class Actor {
3911
3341
  return this;
3912
3342
  }
3913
3343
  }
3344
+ if (!this._flushInitialEffects()) {
3345
+ return this;
3346
+ }
3914
3347
 
3915
3348
  // TODO: this notifies all subscribers but usually this is redundant
3916
3349
  // there is no real change happening here
@@ -3949,9 +3382,16 @@ class Actor {
3949
3382
  this._error(err);
3950
3383
  return;
3951
3384
  }
3952
- const [snapshot, effects] = Array.isArray(nextState) ? nextState : [nextState, undefined];
3953
- this.update(snapshot, event);
3954
- executeLogicEffects(effects, this._actorScope);
3385
+ try {
3386
+ const [snapshot, effects] = nextState;
3387
+ const logicEffects = executeExecutableEffects(effects, this._actorScope);
3388
+ this.update(snapshot, event);
3389
+ executeLogicEffects(logicEffects, this._actorScope);
3390
+ } catch (err) {
3391
+ this._setErrorSnapshot(err);
3392
+ this._error(err);
3393
+ return;
3394
+ }
3955
3395
  if (event.type === XSTATE_STOP) {
3956
3396
  this._stopProcedure();
3957
3397
  this._complete();
@@ -4143,15 +3583,9 @@ class Actor {
4143
3583
  * @see {@link Actor.getPersistedSnapshot} to persist the internal state of an actor (which is more than just a snapshot).
4144
3584
  */
4145
3585
  getSnapshot() {
4146
- return this.get();
4147
- }
4148
-
4149
- /** Read the actor's current snapshot as an atom value. */
4150
- get() {
4151
3586
  if (!this._snapshot) {
4152
3587
  throw new Error(`Snapshot can't be read while the actor initializes itself`);
4153
3588
  }
4154
- onActorRead?.(this);
4155
3589
  return this._snapshot;
4156
3590
  }
4157
3591
  }
@@ -4590,46 +4024,45 @@ function createEventObservableLogic(lazyObservableOrConfig) {
4590
4024
  config: lazyObservable,
4591
4025
  transition: (state, event) => {
4592
4026
  if (state.status !== 'active') {
4593
- return state;
4027
+ return [state, []];
4594
4028
  }
4595
4029
  switch (event.type) {
4596
4030
  case XSTATE_OBSERVABLE_ERROR:
4597
- return {
4031
+ return [{
4598
4032
  ...state,
4599
4033
  status: 'error',
4600
4034
  error: event.data,
4601
4035
  input: undefined,
4602
4036
  _subscription: undefined
4603
- };
4037
+ }, []];
4604
4038
  case XSTATE_OBSERVABLE_COMPLETE:
4605
- return {
4039
+ return [{
4606
4040
  ...state,
4607
4041
  status: 'done',
4608
4042
  input: undefined,
4609
4043
  _subscription: undefined
4610
- };
4044
+ }, []];
4611
4045
  case XSTATE_STOP:
4612
4046
  state._subscription.unsubscribe();
4613
- return {
4047
+ return [{
4614
4048
  ...state,
4615
4049
  status: 'stopped',
4616
4050
  input: undefined,
4617
4051
  _subscription: undefined
4618
- };
4052
+ }, []];
4619
4053
  default:
4620
- return state;
4054
+ return [state, []];
4621
4055
  }
4622
4056
  },
4623
- getInitialSnapshot: (_, input) => {
4624
- return {
4625
- status: 'active',
4626
- output: undefined,
4627
- error: undefined,
4628
- context: undefined,
4629
- input,
4630
- _subscription: undefined
4631
- };
4632
- },
4057
+ initialTransition: (input, _) => [{
4058
+ status: 'active',
4059
+ output: undefined,
4060
+ error: undefined,
4061
+ context: undefined,
4062
+ input,
4063
+ _subscription: undefined
4064
+ }, []],
4065
+ getInitialSnapshot: (actorScope, input) => logic.initialTransition(input, actorScope)[0],
4633
4066
  start: (state, {
4634
4067
  self,
4635
4068
  system,
@@ -4956,10 +4389,7 @@ exports.TimeoutError = TimeoutError;
4956
4389
  exports.XSTATE_INIT = XSTATE_INIT;
4957
4390
  exports.checkStateIn = checkStateIn;
4958
4391
  exports.createActor = createActor;
4959
- exports.createAsyncAtom = createAsyncAtom;
4960
4392
  exports.createAsyncLogic = createAsyncLogic;
4961
- exports.createAtom = createAtom;
4962
- exports.createAtomConfig = createAtomConfig;
4963
4393
  exports.createCallbackLogic = createCallbackLogic;
4964
4394
  exports.createEmptyActor = createEmptyActor;
4965
4395
  exports.createEventObservableLogic = createEventObservableLogic;
@@ -4970,7 +4400,6 @@ exports.createListenerLogic = createListenerLogic;
4970
4400
  exports.createLogic = createLogic;
4971
4401
  exports.createMachineSnapshot = createMachineSnapshot;
4972
4402
  exports.createObservableLogic = createObservableLogic;
4973
- exports.createReducerAtom = createReducerAtom;
4974
4403
  exports.createSubscriptionLogic = createSubscriptionLogic;
4975
4404
  exports.evaluateCandidate = evaluateCandidate;
4976
4405
  exports.formatRouteTransitions = formatRouteTransitions;
@@ -4984,8 +4413,8 @@ exports.getProperAncestors = getProperAncestors;
4984
4413
  exports.getStateNodeByPath = getStateNodeByPath;
4985
4414
  exports.getStateNodes = getStateNodes;
4986
4415
  exports.initialMicrostep = initialMicrostep;
4987
- exports.isAtom = isAtom;
4988
4416
  exports.isAtomicStateNode = isAtomicStateNode;
4417
+ exports.isBuiltInExecutableAction = isBuiltInExecutableAction;
4989
4418
  exports.isInFinalState = isInFinalState;
4990
4419
  exports.isMachineSnapshot = isMachineSnapshot;
4991
4420
  exports.isStateId = isStateId;
@@ -4996,7 +4425,7 @@ exports.matchesEventDescriptor = matchesEventDescriptor;
4996
4425
  exports.matchesState = matchesState;
4997
4426
  exports.parseDelayToMilliseconds = parseDelayToMilliseconds;
4998
4427
  exports.pathToStateValue = pathToStateValue;
4999
- exports.resolveAndExecuteActionsWithContext = resolveAndExecuteActionsWithContext;
4428
+ exports.resolveActionsWithContext = resolveActionsWithContext;
5000
4429
  exports.resolveReferencedActor = resolveReferencedActor;
5001
4430
  exports.resolveStateValue = resolveStateValue;
5002
4431
  exports.subscriptionLogic = subscriptionLogic;