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;
@@ -187,7 +174,7 @@ const builtInActions = {
187
174
  ['@xstate.cancel']: (actorScope, sendId) => {
188
175
  actorScope.system.scheduler.cancel(actorScope.self, sendId);
189
176
  },
190
- ['@xstate.stopChild']: (actorScope, actor) => {
177
+ ['@xstate.stop']: (actorScope, actor) => {
191
178
  actorScope.stopChild(actor);
192
179
  }
193
180
  };
@@ -199,15 +186,20 @@ const subscriptions = /* #__PURE__ */new WeakMap();
199
186
  * (`enq.listen()` / `enq.subscribeTo()`) and detaches when stopped.
200
187
  */
201
188
  function createAttachedLogic(attach) {
189
+ const initialTransition = (input, _) => [{
190
+ status: 'active',
191
+ output: undefined,
192
+ error: undefined,
193
+ input
194
+ }, []];
202
195
  return {
203
196
  start: (state, {
204
197
  self,
205
198
  system
206
199
  }) => {
207
- // Don't attach if the target doesn't exist, or (for actors) is stopped.
208
- // Atoms have no `getSnapshot` / lifecycle, so they always attach.
200
+ // Don't attach if the target doesn't exist or is stopped.
209
201
  const target = state.input.actor;
210
- if (!target || typeof target.getSnapshot === 'function' && target.getSnapshot().status === 'stopped') {
202
+ if (!target || target.getSnapshot().status === 'stopped') {
211
203
  return;
212
204
  }
213
205
  const subscription = attach(state.input, {
@@ -250,20 +242,16 @@ function createAttachedLogic(attach) {
250
242
  if (event.type === XSTATE_STOP) {
251
243
  subscriptions.get(self)?.unsubscribe();
252
244
  subscriptions.delete(self);
253
- return {
245
+ return [{
254
246
  ...state,
255
247
  status: 'stopped',
256
248
  error: undefined
257
- };
249
+ }, []];
258
250
  }
259
- return state;
251
+ return [state, []];
260
252
  },
261
- getInitialSnapshot: (_, input) => ({
262
- status: 'active',
263
- output: undefined,
264
- error: undefined,
265
- input
266
- }),
253
+ initialTransition,
254
+ getInitialSnapshot: (actorScope, input) => initialTransition(input)[0],
267
255
  getPersistedSnapshot: snapshot => snapshot,
268
256
  restoreSnapshot: snapshot => snapshot
269
257
  };
@@ -309,620 +297,6 @@ function createListenerLogic() {
309
297
  // Singleton logic instance
310
298
  const listenerLogic = /* #__PURE__ */createListenerLogic();
311
299
 
312
- /* eslint-disable */
313
- // Adapted from Alien Signals
314
- // https://github.com/stackblitz/alien-signals/
315
-
316
- let ReactiveFlags = /*#__PURE__*/function (ReactiveFlags) {
317
- ReactiveFlags[ReactiveFlags["None"] = 0] = "None";
318
- ReactiveFlags[ReactiveFlags["Mutable"] = 1] = "Mutable";
319
- ReactiveFlags[ReactiveFlags["Watching"] = 2] = "Watching";
320
- ReactiveFlags[ReactiveFlags["RecursedCheck"] = 4] = "RecursedCheck";
321
- ReactiveFlags[ReactiveFlags["Recursed"] = 8] = "Recursed";
322
- ReactiveFlags[ReactiveFlags["Dirty"] = 16] = "Dirty";
323
- ReactiveFlags[ReactiveFlags["Pending"] = 32] = "Pending";
324
- return ReactiveFlags;
325
- }({});
326
- function createReactiveSystem({
327
- update,
328
- notify,
329
- unwatched
330
- }) {
331
- return {
332
- link,
333
- unlink,
334
- propagate,
335
- checkDirty,
336
- shallowPropagate
337
- };
338
- function link(dep, sub, version) {
339
- const prevDep = sub.depsTail;
340
- if (prevDep !== undefined && prevDep.dep === dep) {
341
- return;
342
- }
343
- const nextDep = prevDep !== undefined ? prevDep.nextDep : sub.deps;
344
- if (nextDep !== undefined && nextDep.dep === dep) {
345
- nextDep.version = version;
346
- sub.depsTail = nextDep;
347
- return;
348
- }
349
- const prevSub = dep.subsTail;
350
- if (prevSub !== undefined && prevSub.version === version && prevSub.sub === sub) {
351
- return;
352
- }
353
- const newLink = sub.depsTail = dep.subsTail = {
354
- version,
355
- dep,
356
- sub,
357
- prevDep,
358
- nextDep,
359
- prevSub,
360
- nextSub: undefined
361
- };
362
- if (nextDep !== undefined) {
363
- nextDep.prevDep = newLink;
364
- }
365
- if (prevDep !== undefined) {
366
- prevDep.nextDep = newLink;
367
- } else {
368
- sub.deps = newLink;
369
- }
370
- if (prevSub !== undefined) {
371
- prevSub.nextSub = newLink;
372
- } else {
373
- dep.subs = newLink;
374
- }
375
- }
376
- function unlink(link, sub = link.sub) {
377
- const dep = link.dep;
378
- const prevDep = link.prevDep;
379
- const nextDep = link.nextDep;
380
- const nextSub = link.nextSub;
381
- const prevSub = link.prevSub;
382
- if (nextDep !== undefined) {
383
- nextDep.prevDep = prevDep;
384
- } else {
385
- sub.depsTail = prevDep;
386
- }
387
- if (prevDep !== undefined) {
388
- prevDep.nextDep = nextDep;
389
- } else {
390
- sub.deps = nextDep;
391
- }
392
- if (nextSub !== undefined) {
393
- nextSub.prevSub = prevSub;
394
- } else {
395
- dep.subsTail = prevSub;
396
- }
397
- if (prevSub !== undefined) {
398
- prevSub.nextSub = nextSub;
399
- } else if ((dep.subs = nextSub) === undefined) {
400
- unwatched(dep);
401
- }
402
- return nextDep;
403
- }
404
- function propagate(link) {
405
- let next = link.nextSub;
406
- let stack;
407
- top: do {
408
- const sub = link.sub;
409
- let flags = sub.flags;
410
- if (!(flags & (ReactiveFlags.RecursedCheck | ReactiveFlags.Recursed | ReactiveFlags.Dirty | ReactiveFlags.Pending))) {
411
- sub.flags = flags | ReactiveFlags.Pending;
412
- } else if (!(flags & (ReactiveFlags.RecursedCheck | ReactiveFlags.Recursed))) {
413
- flags = ReactiveFlags.None;
414
- } else if (!(flags & ReactiveFlags.RecursedCheck)) {
415
- sub.flags = flags & ~ReactiveFlags.Recursed | ReactiveFlags.Pending;
416
- } else if (!(flags & (ReactiveFlags.Dirty | ReactiveFlags.Pending)) && isValidLink(link, sub)) {
417
- sub.flags = flags | (ReactiveFlags.Recursed | ReactiveFlags.Pending);
418
- flags &= ReactiveFlags.Mutable;
419
- } else {
420
- flags = ReactiveFlags.None;
421
- }
422
- if (flags & ReactiveFlags.Watching) {
423
- notify(sub);
424
- }
425
- if (flags & ReactiveFlags.Mutable) {
426
- const subSubs = sub.subs;
427
- if (subSubs !== undefined) {
428
- const nextSub = (link = subSubs).nextSub;
429
- if (nextSub !== undefined) {
430
- stack = {
431
- value: next,
432
- prev: stack
433
- };
434
- next = nextSub;
435
- }
436
- continue;
437
- }
438
- }
439
- if ((link = next) !== undefined) {
440
- next = link.nextSub;
441
- continue;
442
- }
443
- while (stack !== undefined) {
444
- link = stack.value;
445
- stack = stack.prev;
446
- if (link !== undefined) {
447
- next = link.nextSub;
448
- continue top;
449
- }
450
- }
451
- break;
452
- } while (true);
453
- }
454
- function checkDirty(link, sub) {
455
- let stack;
456
- let checkDepth = 0;
457
- let dirty = false;
458
- top: do {
459
- const dep = link.dep;
460
- const flags = dep.flags;
461
- if (sub.flags & ReactiveFlags.Dirty) {
462
- dirty = true;
463
- } else if ((flags & (ReactiveFlags.Mutable | ReactiveFlags.Dirty)) === (ReactiveFlags.Mutable | ReactiveFlags.Dirty)) {
464
- if (update(dep)) {
465
- const subs = dep.subs;
466
- if (subs.nextSub !== undefined) {
467
- shallowPropagate(subs);
468
- }
469
- dirty = true;
470
- }
471
- } else if ((flags & (ReactiveFlags.Mutable | ReactiveFlags.Pending)) === (ReactiveFlags.Mutable | ReactiveFlags.Pending)) {
472
- if (link.nextSub !== undefined || link.prevSub !== undefined) {
473
- stack = {
474
- value: link,
475
- prev: stack
476
- };
477
- }
478
- link = dep.deps;
479
- sub = dep;
480
- ++checkDepth;
481
- continue;
482
- }
483
- if (!dirty) {
484
- const nextDep = link.nextDep;
485
- if (nextDep !== undefined) {
486
- link = nextDep;
487
- continue;
488
- }
489
- }
490
- while (checkDepth--) {
491
- const firstSub = sub.subs;
492
- const hasMultipleSubs = firstSub.nextSub !== undefined;
493
- if (hasMultipleSubs) {
494
- link = stack.value;
495
- stack = stack.prev;
496
- } else {
497
- link = firstSub;
498
- }
499
- if (dirty) {
500
- if (update(sub)) {
501
- if (hasMultipleSubs) {
502
- shallowPropagate(firstSub);
503
- }
504
- sub = link.sub;
505
- continue;
506
- }
507
- dirty = false;
508
- } else {
509
- sub.flags &= ~ReactiveFlags.Pending;
510
- }
511
- sub = link.sub;
512
- const nextDep = link.nextDep;
513
- if (nextDep !== undefined) {
514
- link = nextDep;
515
- continue top;
516
- }
517
- }
518
- return dirty;
519
- } while (true);
520
- }
521
- function shallowPropagate(link) {
522
- do {
523
- const sub = link.sub;
524
- const flags = sub.flags;
525
- if ((flags & (ReactiveFlags.Pending | ReactiveFlags.Dirty)) === ReactiveFlags.Pending) {
526
- sub.flags = flags | ReactiveFlags.Dirty;
527
- if ((flags & (ReactiveFlags.Watching | ReactiveFlags.RecursedCheck)) === ReactiveFlags.Watching) {
528
- notify(sub);
529
- }
530
- }
531
- } while ((link = link.nextSub) !== undefined);
532
- }
533
- function isValidLink(checkLink, sub) {
534
- let link = sub.depsTail;
535
- while (link !== undefined) {
536
- if (link === checkLink) {
537
- return true;
538
- }
539
- link = link.prevDep;
540
- }
541
- return false;
542
- }
543
- }
544
-
545
- /**
546
- * Nominal brand (phantom, compile-time only) marking a value as an XState atom.
547
- * Real atoms get the runtime brand ({@link $$atom}) in `createAtom`; this type
548
- * brand keeps atom-only APIs (e.g. `enq.subscribeTo`) from structurally
549
- * accepting plain readables like `actor.select(...)` that would be dispatched
550
- * down the non-atom path at runtime.
551
- */
552
-
553
- /** Brand marking an object as an atom, so it can be detected structurally. */
554
- const $$atom = /* #__PURE__ */Symbol.for('xstate.atom');
555
-
556
- /**
557
- * Returns `true` if the value is an atom (writable, computed, async, or
558
- * reducer). Lets actor-consuming APIs (e.g. `enq.subscribeTo`) accept atoms
559
- * directly.
560
- */
561
- function isAtom(value) {
562
- return !!value && typeof value === 'object' && $$atom in value;
563
- }
564
- const queuedEffects = [];
565
- let cycle = 0;
566
- // Initialized lazily on first atom creation (instead of at module evaluation)
567
- // so the reactive system stays tree-shakeable for apps that never use atoms —
568
-
569
- // would be retained by consumer bundlers even when atoms are unused.
570
- let link;
571
- let unlink;
572
- let propagate;
573
- let checkDirty;
574
- let shallowPropagate;
575
- let reactiveSystemInstalled = false;
576
- function ensureReactiveSystem() {
577
- if (reactiveSystemInstalled) {
578
- return;
579
- }
580
- reactiveSystemInstalled = true;
581
- ({
582
- link,
583
- unlink,
584
- propagate,
585
- checkDirty,
586
- shallowPropagate
587
- } = createReactiveSystem({
588
- update(atom) {
589
- return atom._update();
590
- },
591
- notify(effect) {
592
- queuedEffects[queuedEffectsLength++] = effect;
593
- effect.flags &= ~ReactiveFlags.Watching;
594
- },
595
- unwatched(atom) {
596
- if (atom.depsTail !== undefined) {
597
- atom.depsTail = undefined;
598
- atom.flags = ReactiveFlags.Mutable | ReactiveFlags.Dirty;
599
- purgeDeps(atom);
600
- }
601
- }
602
- }));
603
- }
604
- let notifyIndex = 0;
605
- let queuedEffectsLength = 0;
606
- let activeSub;
607
- function purgeDeps(sub) {
608
- const depsTail = sub.depsTail;
609
- let dep = depsTail !== undefined ? depsTail.nextDep : sub.deps;
610
- while (dep !== undefined) {
611
- dep = unlink(dep, sub);
612
- }
613
- }
614
- function flush() {
615
- while (notifyIndex < queuedEffectsLength) {
616
- const effect = queuedEffects[notifyIndex];
617
- queuedEffects[notifyIndex++] = undefined;
618
- effect.notify();
619
- }
620
- notifyIndex = 0;
621
- queuedEffectsLength = 0;
622
- }
623
-
624
- /** The current state of an async atom. */
625
-
626
- /** Options passed to an async atom getter. */
627
-
628
- function compareAsyncAtomState(a, b) {
629
- if (a.status !== b.status) {
630
- return false;
631
- }
632
- if (a.status === 'done' && b.status === 'done') {
633
- return Object.is(a.data, b.data);
634
- }
635
- if (a.status === 'error' && b.status === 'error') {
636
- return Object.is(a.error, b.error);
637
- }
638
- // both 'pending'
639
- return true;
640
- }
641
- function updateAsyncAtom(atom, nextValue) {
642
- if (atom._update(nextValue)) {
643
- const subs = atom.subs;
644
- if (subs !== undefined) {
645
- propagate(subs);
646
- shallowPropagate(subs);
647
- flush();
648
- }
649
- }
650
- }
651
-
652
- /**
653
- * Creates a read-only atom whose value is loaded from an async getter.
654
- *
655
- * The getter receives an `AbortSignal`; when the async atom recomputes, the
656
- * previous signal is aborted and stale resolutions are ignored.
657
- */
658
- function createAsyncAtom(getValue, options) {
659
- const ref = {};
660
- let currentController;
661
- let currentRunId = 0;
662
- const atom = createAtom(() => {
663
- currentController?.abort();
664
- const controller = new AbortController();
665
- const runId = ++currentRunId;
666
- currentController = controller;
667
- getValue({
668
- signal: controller.signal
669
- }).then(data => {
670
- if (runId !== currentRunId || controller.signal.aborted) {
671
- return;
672
- }
673
- updateAsyncAtom(ref.current, {
674
- status: 'done',
675
- data
676
- });
677
- }, error => {
678
- if (runId !== currentRunId || controller.signal.aborted) {
679
- return;
680
- }
681
- updateAsyncAtom(ref.current, {
682
- status: 'error',
683
- error
684
- });
685
- });
686
- return {
687
- status: 'pending'
688
- };
689
- }, {
690
- compare: compareAsyncAtomState,
691
- ...options
692
- });
693
- ref.current = atom;
694
- return atom;
695
- }
696
-
697
- /**
698
- * Mirror atoms that bump a version whenever a tracked actor emits a snapshot,
699
- * letting computed atoms depend on `actor.get()` reads.
700
- *
701
- * The hook is installed lazily on first atom creation (not at module
702
- * evaluation) so that it remains tree-shakeable for apps that never use atoms —
703
- * any tracked read necessarily happens inside an atom computation, so first-use
704
- * installation is always early enough.
705
- */
706
- let actorInteropInstalled = false;
707
- function ensureActorInterop() {
708
- if (actorInteropInstalled) {
709
- return;
710
- }
711
- actorInteropInstalled = true;
712
- const actorVersions = new WeakMap();
713
- installActorReadHook(actorRef => {
714
- if (activeSub === undefined) {
715
- return;
716
- }
717
- let version = actorVersions.get(actorRef);
718
- if (version === undefined) {
719
- version = createAtom(0);
720
- actorVersions.set(actorRef, version);
721
- actorRef.subscribe({
722
- next: () => version.set(v => v + 1),
723
- error: () => {}
724
- });
725
- }
726
- version.get();
727
- });
728
- }
729
-
730
- /**
731
- * Creates an atom.
732
- *
733
- * Pass a value for a writable atom or a getter for a computed read-only atom.
734
- */
735
-
736
- function createAtom(valueOrFn, optionsOrInput) {
737
- ensureReactiveSystem();
738
- ensureActorInterop();
739
- const isComputed = typeof valueOrFn === 'function';
740
- const getter = valueOrFn;
741
-
742
- // Create plain object atom
743
- const atom = {
744
- _snapshot: isComputed ? undefined : valueOrFn,
745
- subs: undefined,
746
- subsTail: undefined,
747
- deps: undefined,
748
- depsTail: undefined,
749
- flags: isComputed ? ReactiveFlags.None : ReactiveFlags.Mutable,
750
- get() {
751
- if (activeSub !== undefined) {
752
- link(atom, activeSub, cycle);
753
- }
754
- return atom._snapshot;
755
- },
756
- subscribe(observerOrFn) {
757
- const observer = typeof observerOrFn === 'function' ? {
758
- next: observerOrFn
759
- } : observerOrFn;
760
- const observed = {
761
- current: false
762
- };
763
- const e = effect(() => {
764
- atom.get();
765
- if (!observed.current) {
766
- observed.current = true;
767
- } else {
768
- const prevSub = activeSub;
769
- activeSub = undefined;
770
- try {
771
- observer.next?.(atom._snapshot);
772
- } catch (err) {
773
- reportUnhandledError(err);
774
- } finally {
775
- activeSub = prevSub;
776
- }
777
-
778
- // If the observer synchronously updates any of our deps we'll be
779
- // marked as dirty preventing this effect from re-running. Request
780
- // the value again to reconcile any dirty deps.
781
- atom.get();
782
- }
783
- });
784
- return {
785
- unsubscribe: () => {
786
- e.stop();
787
- }
788
- };
789
- },
790
- _update(getValue) {
791
- const prevSub = activeSub;
792
- const compare = optionsOrInput?.compare ?? Object.is;
793
- activeSub = atom;
794
- ++cycle;
795
- atom.depsTail = undefined;
796
- if (isComputed) {
797
- atom.flags = ReactiveFlags.Mutable | ReactiveFlags.RecursedCheck;
798
- }
799
- try {
800
- const oldValue = atom._snapshot;
801
- const newValue = typeof getValue === 'function' ? getValue(oldValue) : getValue === undefined && isComputed ? getter(oldValue) : getValue;
802
- if (oldValue === undefined || !compare(oldValue, newValue)) {
803
- atom._snapshot = newValue;
804
- return true;
805
- }
806
- return false;
807
- } finally {
808
- activeSub = prevSub;
809
- if (isComputed) {
810
- atom.flags &= ~ReactiveFlags.RecursedCheck;
811
- }
812
- purgeDeps(atom);
813
- }
814
- }
815
- };
816
- if (isComputed) {
817
- atom.flags = ReactiveFlags.Mutable | ReactiveFlags.Dirty;
818
- atom.get = function () {
819
- const flags = atom.flags;
820
- if (flags & ReactiveFlags.Dirty || flags & ReactiveFlags.Pending && checkDirty(atom.deps, atom)) {
821
- if (atom._update()) {
822
- const subs = atom.subs;
823
- if (subs !== undefined) {
824
- shallowPropagate(subs);
825
- }
826
- }
827
- } else if (flags & ReactiveFlags.Pending) {
828
- atom.flags = flags & ~ReactiveFlags.Pending;
829
- }
830
- if (activeSub !== undefined) {
831
- link(atom, activeSub, cycle);
832
- }
833
- return atom._snapshot;
834
- };
835
- } else {
836
- atom.set = function (valueOrFn) {
837
- if (atom._update(valueOrFn)) {
838
- const subs = atom.subs;
839
- if (subs !== undefined) {
840
- propagate(subs);
841
- shallowPropagate(subs);
842
- flush();
843
- }
844
- }
845
- };
846
- }
847
- atom[$$atom] = true;
848
- return atom;
849
- }
850
-
851
- /**
852
- * Creates an inert atom config that can be instantiated later.
853
- *
854
- * Useful for framework hooks that need to create a stable local atom from
855
- * component input.
856
- */
857
-
858
- function createAtomConfig(initialValueOrFn, options) {
859
- return {
860
- createAtom(input) {
861
- const initialValue = typeof initialValueOrFn === 'function' ? initialValueOrFn(input) : initialValueOrFn;
862
- return createAtom(initialValue, options);
863
- }
864
- };
865
- }
866
-
867
- /** Creates an atom whose updates are handled by a reducer function. */
868
- function createReducerAtom(initialValue, reducer, options) {
869
- const atom = createAtom(initialValue, options);
870
- return {
871
- [$$atom]: true,
872
- get: atom.get.bind(atom),
873
- subscribe: atom.subscribe.bind(atom),
874
- send(event) {
875
- const prevSub = activeSub;
876
- activeSub = undefined;
877
- let nextState;
878
- try {
879
- nextState = reducer(atom.get(), event);
880
- } finally {
881
- activeSub = prevSub;
882
- }
883
- atom.set(nextState);
884
- }
885
- };
886
- }
887
- function effect(fn) {
888
- const run = () => {
889
- const prevSub = activeSub;
890
- activeSub = effectObj;
891
- ++cycle;
892
- effectObj.depsTail = undefined;
893
- effectObj.flags = ReactiveFlags.Watching | ReactiveFlags.RecursedCheck;
894
- try {
895
- return fn();
896
- } finally {
897
- activeSub = prevSub;
898
- effectObj.flags &= ~ReactiveFlags.RecursedCheck;
899
- purgeDeps(effectObj);
900
- }
901
- };
902
- const effectObj = {
903
- deps: undefined,
904
- depsTail: undefined,
905
- subs: undefined,
906
- subsTail: undefined,
907
- flags: ReactiveFlags.Watching | ReactiveFlags.RecursedCheck,
908
- notify() {
909
- const flags = this.flags;
910
- if (flags & ReactiveFlags.Dirty || flags & ReactiveFlags.Pending && checkDirty(this.deps, this)) {
911
- run();
912
- } else {
913
- this.flags = ReactiveFlags.Watching;
914
- }
915
- },
916
- stop() {
917
- this.flags = ReactiveFlags.None;
918
- this.depsTail = undefined;
919
- purgeDeps(this);
920
- }
921
- };
922
- run();
923
- return effectObj;
924
- }
925
-
926
300
  /**
927
301
  * Creates actor logic for subscribing to lifecycle events (done/error/snapshot)
928
302
  * from another actor. Used internally by `enq.subscribeTo()`.
@@ -940,15 +314,6 @@ function createSubscriptionLogic() {
940
314
  error,
941
315
  snapshot: onSnapshot
942
316
  } = mappers;
943
-
944
- // Atoms emit a raw value (no `status`) and have no done/error lifecycle —
945
- // pass the value straight to the `snapshot` mapper.
946
- if (isAtom(actor)) {
947
- if (!onSnapshot) {
948
- return;
949
- }
950
- return actor.subscribe(value => relayMappedToParent(self, system, () => onSnapshot(value)));
951
- }
952
317
  return actor.subscribe({
953
318
  next: snapshot => {
954
319
  if (snapshot.status === 'done' && done) {
@@ -1049,7 +414,7 @@ function createTransitionEnqueue(actorScope, actions, internalEvents, actorSubsc
1049
414
  },
1050
415
  stop: actor => {
1051
416
  if (actor) {
1052
- pushBuiltInAction(actions, builtInActions['@xstate.stopChild'], actorScope, actor);
417
+ pushBuiltInAction(actions, builtInActions['@xstate.stop'], actorScope, actor);
1053
418
  actions.push(unregisterChild(actor));
1054
419
  }
1055
420
  }
@@ -1090,16 +455,65 @@ function createTransitionEnqueue(actorScope, actions, internalEvents, actorSubsc
1090
455
  pushBuiltInAction(actions, action, ...args);
1091
456
  });
1092
457
  }
1093
- function resolveAndExecuteActionsWithContext(currentSnapshot, event, actorScope, actions) {
458
+ function getBuiltInActionFields(action, args) {
459
+ switch (action) {
460
+ case builtInActions['@xstate.start']:
461
+ {
462
+ const [actor] = args;
463
+ return {
464
+ actor,
465
+ id: actor.id,
466
+ logic: actor.logic,
467
+ src: actor.src,
468
+ input: actor.options?.input
469
+ };
470
+ }
471
+ case builtInActions['@xstate.raise']:
472
+ {
473
+ const [, event, options] = args;
474
+ return {
475
+ event,
476
+ id: options?.id,
477
+ delay: options?.delay
478
+ };
479
+ }
480
+ case builtInActions['@xstate.sendTo']:
481
+ {
482
+ const [, target, event, options] = args;
483
+ return {
484
+ target,
485
+ event,
486
+ id: options?.id,
487
+ delay: options?.delay
488
+ };
489
+ }
490
+ case builtInActions['@xstate.cancel']:
491
+ {
492
+ const [, id] = args;
493
+ return {
494
+ id
495
+ };
496
+ }
497
+ case builtInActions['@xstate.stop']:
498
+ {
499
+ const [, actor] = args;
500
+ return {
501
+ actor
502
+ };
503
+ }
504
+ default:
505
+ return undefined;
506
+ }
507
+ }
508
+ function isBuiltInExecutableAction(action) {
509
+ return Object.prototype.hasOwnProperty.call(builtInActions, action.type);
510
+ }
511
+ function resolveActionsWithContext(currentSnapshot, event, actorScope, actions) {
1094
512
  let intermediateSnapshot = currentSnapshot;
513
+ const executableActions = [];
1095
514
  for (const action of actions) {
1096
515
  const isInline = typeof action === 'function';
1097
516
  const resolvedAction = isInline ? action : typeof action === 'object' && 'action' in action && typeof action.action === 'function' ? action.action.bind(null, ...action.args) : false;
1098
- if (!resolvedAction && typeof action === 'object' && action !== null) {
1099
- actorScope.defer(() => {
1100
- actorScope.emit(action);
1101
- });
1102
- }
1103
517
  const actionArgs = {
1104
518
  context: intermediateSnapshot.context,
1105
519
  event,
@@ -1119,7 +533,7 @@ function resolveAndExecuteActionsWithContext(currentSnapshot, event, actorScope,
1119
533
  actionParams = emittedEventParams;
1120
534
  }
1121
535
  if (resolvedAction && '_special' in resolvedAction) {
1122
- actorScope.actionExecutor({
536
+ executableActions.push({
1123
537
  type: typeof action === 'object' ? 'action' in action && typeof action.action === 'function' ? action.action.name ?? '(anonymous)' : action.type ?? '(anonymous)' : action.name || '(anonymous)',
1124
538
  params: actionParams,
1125
539
  args: [],
@@ -1140,16 +554,18 @@ function resolveAndExecuteActionsWithContext(currentSnapshot, event, actorScope,
1140
554
  continue;
1141
555
  }
1142
556
  if (!resolvedAction || !('resolve' in resolvedAction)) {
1143
- actorScope.actionExecutor({
557
+ const builtInFields = typeof action === 'object' && action !== null && 'action' in action && typeof action.action === 'function' ? getBuiltInActionFields(action.action, action.args) : undefined;
558
+ executableActions.push({
1144
559
  type: typeof action === 'object' ? 'action' in action && typeof action.action === 'function' ? action.action.name ?? '(anonymous)' : action.type : action.name || '(anonymous)',
1145
560
  params: actionParams,
1146
561
  args: typeof action === 'object' && 'action' in action ? action.args : [],
1147
- exec: resolvedAction
562
+ exec: resolvedAction || (typeof action === 'object' && action !== null ? () => actorScope.defer(() => actorScope.emit(action)) : undefined),
563
+ ...builtInFields
1148
564
  });
1149
565
  continue;
1150
566
  }
1151
567
  }
1152
- return intermediateSnapshot;
568
+ return [intermediateSnapshot, executableActions];
1153
569
  }
1154
570
  function createEnqueueObject$1(props, action) {
1155
571
  const enqueueFn = (fn, ...args) => {
@@ -1343,22 +759,9 @@ function isInFinalState(stateNodeSet, stateNode) {
1343
759
  }
1344
760
  const isStateId = str => str[0] === STATE_IDENTIFIER;
1345
761
  function getCandidates(stateNode, receivedEventType) {
1346
- const candidates = stateNode.transitions.get(receivedEventType);
1347
- if (candidates) {
1348
- return candidates;
1349
- }
1350
- const matchingDescriptors = [];
1351
- for (const eventDescriptor of stateNode.transitions.keys()) {
1352
- if (matchesEventDescriptor(receivedEventType, eventDescriptor)) {
1353
- matchingDescriptors.push(eventDescriptor);
1354
- }
1355
- }
1356
- matchingDescriptors.sort((a, b) => b.length - a.length);
1357
- const wildcardCandidates = [];
1358
- for (const descriptor of matchingDescriptors) {
1359
- wildcardCandidates.push(...stateNode.transitions.get(descriptor));
1360
- }
1361
- return wildcardCandidates;
762
+ const exactMatch = stateNode.transitions.get(receivedEventType);
763
+ 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));
764
+ return exactMatch ? [...exactMatch, ...wildcardCandidates] : wildcardCandidates;
1362
765
  }
1363
766
  function scheduleDelayedEvent(stateNode, event, resolveScheduledDelay) {
1364
767
  const eventType = event.type;
@@ -1387,61 +790,68 @@ function getDelayedTransitions(stateNode) {
1387
790
  if (!afterConfig && timeoutConfig === undefined && invokeDefs.length === 0) {
1388
791
  return [];
1389
792
  }
1390
- const mutateEntryExitWithDelay = delay => {
1391
- const afterEvent = createAfterEvent(delay, stateNode.id);
1392
- return scheduleDelayedEvent(stateNode, afterEvent, x => resolveDelay(delay, x.delays, {
1393
- context: x.context,
1394
- event: x.event,
1395
- stateNode
1396
- }));
1397
- };
1398
- const delayedTransitions = [];
1399
- const addDelayedTransitions = (transitionsConfig, event, delay) => {
1400
- for (const transition of toTransitionConfigArray(transitionsConfig)) {
1401
- delayedTransitions.push({
1402
- ...transition,
1403
- event,
1404
- delay
1405
- });
1406
- }
1407
- };
793
+
794
+ // Every delayed transition — `after`, state-level `timeout`/`onTimeout`, and
795
+ // invoke-level `timeout`/`onTimeout` has the same shape: an event raised on
796
+ // entry (and cancelled on exit) plus a transition that catches it. They
797
+ // differ only in the event raised, the transition(s) caught, and whether the
798
+ // delay resolves against the machine's `delays` map (invoke timeouts do not).
799
+ //
800
+ // `xstate.timeout.<id>` is a dedicated event so a state-level `timeout` cannot
801
+ // collide with an explicit `after` entry on the same state. Invoke timeouts
802
+ // are scheduled on the enclosing state; completion transitions cancel the
803
+ // timer separately, so it clears even when the parent state stays active.
804
+ const sources = [];
1408
805
  if (afterConfig) {
1409
- for (const delay of Object.keys(afterConfig)) {
1410
- const configTransition = afterConfig[delay];
1411
- const parsedDelay = Number.isNaN(+delay) ? delay : +delay;
1412
- const eventType = mutateEntryExitWithDelay(parsedDelay);
1413
- const resolvedDelay = getConfiguredDelayValue(parsedDelay, stateNode.machine.implementations.delays);
1414
- addDelayedTransitions(configTransition, eventType, resolvedDelay);
806
+ for (const key of Object.keys(afterConfig)) {
807
+ const delay = Number.isNaN(+key) ? key : +key;
808
+ sources.push({
809
+ event: createAfterEvent(delay, stateNode.id),
810
+ delay,
811
+ transitions: afterConfig[key],
812
+ fromDelaysMap: true
813
+ });
1415
814
  }
1416
815
  }
1417
-
1418
- // Desugar state-level `timeout` + `onTimeout` into a delayed transition.
1419
- // Uses a dedicated `xstate.timeout.<id>` event so it cannot collide with
1420
- // explicit `after` entries on the same state.
1421
816
  if (timeoutConfig !== undefined && onTimeoutConfig) {
1422
- const timeoutEvent = createTimeoutEvent(stateNode.id);
1423
- const timeoutEventType = scheduleDelayedEvent(stateNode, timeoutEvent, x => resolveDelay(timeoutConfig, x.delays, {
1424
- context: x.context,
1425
- event: x.event,
1426
- stateNode
1427
- }));
1428
- const resolvedDelay = typeof timeoutConfig === 'function' ? timeoutConfig : getConfiguredDelayValue(timeoutConfig, stateNode.machine.implementations.delays);
1429
- addDelayedTransitions(onTimeoutConfig, timeoutEventType, resolvedDelay);
817
+ sources.push({
818
+ event: createTimeoutEvent(stateNode.id),
819
+ delay: timeoutConfig,
820
+ transitions: onTimeoutConfig,
821
+ fromDelaysMap: true
822
+ });
1430
823
  }
1431
-
1432
- // Desugar invoke-level `timeout` + `onTimeout` into a delayed transition on
1433
- // the enclosing state. Completion transitions cancel this timer separately,
1434
- // so the timeout is cleared even when the parent state stays active.
1435
824
  for (const invokeDef of invokeDefs) {
1436
- const invokeTimeoutEvent = createInvokeTimeoutEvent(invokeDef.id);
1437
- const invokeTimeout = invokeDef.timeout;
1438
- const invokeTimeoutEventType = scheduleDelayedEvent(stateNode, invokeTimeoutEvent, x => resolveDelay(invokeTimeout, {}, {
825
+ sources.push({
826
+ event: createInvokeTimeoutEvent(invokeDef.id),
827
+ delay: invokeDef.timeout,
828
+ transitions: invokeDef.onTimeout,
829
+ fromDelaysMap: false
830
+ });
831
+ }
832
+
833
+ // `delay` here is the raw config value, retained only as metadata on the
834
+ // transition definition — the live delay is resolved at runtime in the
835
+ // scheduled entry action, so no eager resolution is needed.
836
+ const delayedTransitions = [];
837
+ for (const {
838
+ event,
839
+ delay,
840
+ transitions,
841
+ fromDelaysMap
842
+ } of sources) {
843
+ const eventType = scheduleDelayedEvent(stateNode, event, x => resolveDelay(delay, fromDelaysMap ? x.delays : {}, {
1439
844
  context: x.context,
1440
845
  event: x.event,
1441
846
  stateNode
1442
847
  }));
1443
- const invokeOnTimeout = invokeDef.onTimeout;
1444
- addDelayedTransitions(invokeOnTimeout, invokeTimeoutEventType, invokeTimeout);
848
+ for (const transition of toTransitionConfigArray(transitions)) {
849
+ delayedTransitions.push({
850
+ ...transition,
851
+ event: eventType,
852
+ delay
853
+ });
854
+ }
1445
855
  }
1446
856
  return delayedTransitions.map(delayedTransition => ({
1447
857
  ...formatTransition(stateNode, delayedTransition.event, delayedTransition),
@@ -1506,27 +916,13 @@ function formatRouteTransitions(rootStateNode) {
1506
916
  if ('$unserializable' in routeConfig) {
1507
917
  throw new Error(`State "${sn.id}" has a route that is not serializable. Re-provide the route function when reviving this machine.`);
1508
918
  }
1509
-
1510
- // Object-form route. A `guard` (string or function) on the object is
1511
- // only produced by the JSON layer (createMachineFromConfig) —
1512
- // authoring uses the function form above.
1513
- const userGuard = routeConfig.guard;
919
+ const {
920
+ guard: _guard,
921
+ ...routeOptions
922
+ } = routeConfig;
1514
923
  const transition = {
1515
- ...routeConfig,
1516
- guard: userGuard ? args => {
1517
- if (!routeMatches(args)) return false;
1518
- if (typeof userGuard === 'function') return userGuard(args);
1519
- if (typeof userGuard === 'string') {
1520
- const guardImpl = args.guards?.[userGuard];
1521
- if (!guardImpl) {
1522
- // A typo'd guard name must fail loudly — silently passing
1523
- // would allow the route and corrupt machine behavior.
1524
- throw new Error(`Guard '${userGuard}' is not implemented in machine '${rootStateNode.machine.id}'.`);
1525
- }
1526
- return guardImpl(args);
1527
- }
1528
- return true;
1529
- } : routeMatches,
924
+ ...routeOptions,
925
+ guard: routeMatches,
1530
926
  target: `#${routeId}`
1531
927
  };
1532
928
  routeTransitions.push(formatTransition(rootStateNode, 'xstate.route', transition));
@@ -1857,16 +1253,11 @@ function initialMicrostep(root, preInitialState, actorScope, initEvent, internal
1857
1253
 
1858
1254
  /** https://www.w3.org/TR/scxml/#microstepProcedure */
1859
1255
  function microstep(transitions, currentSnapshot, actorScope, event, isInitial, internalQueue) {
1860
- const actions = [];
1256
+ const executableActions = [];
1861
1257
  if (!transitions.length) {
1862
- return [currentSnapshot, actions];
1258
+ return [currentSnapshot, executableActions];
1863
1259
  }
1864
- const originalExecutor = actorScope.actionExecutor;
1865
- actorScope.actionExecutor = action => {
1866
- actions.push(action);
1867
- originalExecutor(action);
1868
- };
1869
- try {
1260
+ {
1870
1261
  const mutStateNodeSet = new Set(currentSnapshot._nodes);
1871
1262
  let historyValue = currentSnapshot.historyValue;
1872
1263
  const originalContext = currentSnapshot.context;
@@ -1939,7 +1330,9 @@ function microstep(transitions, currentSnapshot, actorScope, event, isInitial, i
1939
1330
  context: nextContext
1940
1331
  });
1941
1332
  }
1942
- nextState = resolveAndExecuteActionsWithContext(nextState, event, actorScope, exitActions);
1333
+ const [resolvedState, resolvedActions] = resolveActionsWithContext(nextState, event, actorScope, exitActions);
1334
+ nextState = resolvedState;
1335
+ executableActions.push(...resolvedActions);
1943
1336
  for (const def of exitStateNode.invoke) {
1944
1337
  const childActor = nextState.children[def.id];
1945
1338
  if (childActor && !childActor._isExternal) {
@@ -2174,7 +1567,10 @@ function microstep(transitions, currentSnapshot, actorScope, event, isInitial, i
2174
1567
  }
2175
1568
  }
2176
1569
  }
2177
- nextState = resolveAndExecuteActionsWithContext(nextState, event, actorScope, actions);
1570
+ const [resolvedState, resolvedActions] = resolveActionsWithContext(nextState, event, actorScope, actions);
1571
+ nextState = resolvedState;
1572
+ actions.length = 0;
1573
+ executableActions.push(...resolvedActions);
2178
1574
  if (context) {
2179
1575
  nextState.context = context;
2180
1576
  }
@@ -2225,7 +1621,9 @@ function microstep(transitions, currentSnapshot, actorScope, event, isInitial, i
2225
1621
  };
2226
1622
 
2227
1623
  // Execute transition content
2228
- nextState = resolveAndExecuteActionsWithContext(nextState, event, actorScope, transitionActions);
1624
+ const [resolvedTransitionState, transitionExecutableActions] = resolveActionsWithContext(nextState, event, actorScope, transitionActions);
1625
+ nextState = resolvedTransitionState;
1626
+ executableActions.push(...transitionExecutableActions);
2229
1627
  if (context && context !== currentSnapshot.context) {
2230
1628
  nextState = cloneMachineSnapshot(nextState, {
2231
1629
  context
@@ -2248,22 +1646,22 @@ function microstep(transitions, currentSnapshot, actorScope, event, isInitial, i
2248
1646
  }
2249
1647
  }
2250
1648
  });
2251
- nextState = resolveAndExecuteActionsWithContext(nextState, event, actorScope, allExitActions);
1649
+ const [resolvedState, resolvedActions] = resolveActionsWithContext(nextState, event, actorScope, allExitActions);
1650
+ nextState = resolvedState;
1651
+ executableActions.push(...resolvedActions);
2252
1652
  }
2253
1653
  if (historyValue === currentSnapshot.historyValue && currentSnapshot._nodes.length === mutStateNodeSet.size && currentSnapshot._nodes.every(node => mutStateNodeSet.has(node))) {
2254
1654
  // If context was changed (e.g. by entry actions during self-transition),
2255
1655
  // clone to ensure reference inequality for eventless transition re-evaluation
2256
1656
  if (nextState.context !== originalContext) {
2257
- return [cloneMachineSnapshot(nextState), actions];
1657
+ return [cloneMachineSnapshot(nextState), executableActions];
2258
1658
  }
2259
- return [nextState, actions];
1659
+ return [nextState, executableActions];
2260
1660
  }
2261
1661
  return [cloneMachineSnapshot(nextState, {
2262
1662
  _nodes: nextStateNodes,
2263
1663
  historyValue
2264
- }), actions];
2265
- } finally {
2266
- actorScope.actionExecutor = originalExecutor;
1664
+ }), executableActions];
2267
1665
  }
2268
1666
  }
2269
1667
 
@@ -2524,24 +1922,7 @@ function evaluateCandidate(candidate, event, snapshot, stateNode, self) {
2524
1922
  delays: stateNode.machine.implementations.delays,
2525
1923
  _snapshot: snapshot
2526
1924
  };
2527
- const guardConfig = candidate.guard;
2528
- const guardParams = typeof guardConfig?.params === 'function' ? guardConfig.params({
2529
- context: snapshot.context,
2530
- event
2531
- }) : guardConfig?.params;
2532
- let guardPassed = true;
2533
- if (typeof guardConfig === 'function') {
2534
- guardPassed = guardConfig(guardArgs, guardParams);
2535
- } else if (typeof guardConfig?.type === 'string') {
2536
- const guardImpl = stateNode.machine.implementations.guards[guardConfig.type];
2537
- if (!guardImpl) {
2538
- // A typo'd guard name must fail loudly — silently passing would
2539
- // take the guarded transition and corrupt machine behavior.
2540
- throw new Error(`Guard '${guardConfig.type}' is not implemented in machine '${stateNode.machine.id}'.`);
2541
- }
2542
- guardPassed = guardImpl(guardArgs, guardParams);
2543
- }
2544
- if (!guardPassed) {
1925
+ if (!candidate.guard(guardArgs)) {
2545
1926
  return false;
2546
1927
  }
2547
1928
  }
@@ -3351,7 +2732,7 @@ function createLogic(config) {
3351
2732
  Object.assign(snapshot, nextSnapshot);
3352
2733
  executeLogicEffects(effects, actorScope);
3353
2734
  },
3354
- getInitialSnapshot: (_, input) => {
2735
+ initialTransition: (input, _) => {
3355
2736
  const context = resolveContext(config.context, input);
3356
2737
  const snapshot = {
3357
2738
  status: 'active',
@@ -3362,10 +2743,11 @@ function createLogic(config) {
3362
2743
  if (context !== undefined) {
3363
2744
  snapshot.context = context;
3364
2745
  }
3365
- return {
2746
+ return [{
3366
2747
  ...snapshot
3367
- };
2748
+ }, []];
3368
2749
  },
2750
+ getInitialSnapshot: (actorScope, input) => logic.initialTransition(input, actorScope)[0],
3369
2751
  getPersistedSnapshot: snapshot => snapshot,
3370
2752
  restoreSnapshot: snapshot => snapshot
3371
2753
  };
@@ -3395,6 +2777,23 @@ const defaultOptions = {
3395
2777
  },
3396
2778
  logger: console.log.bind(console)
3397
2779
  };
2780
+ function isExecutableActionObject(effect) {
2781
+ return typeof effect === 'object' && effect !== null && 'args' in effect && 'exec' in effect;
2782
+ }
2783
+ function executeExecutableEffects(effects, actorScope) {
2784
+ if (!effects?.length) {
2785
+ return [];
2786
+ }
2787
+ const logicEffects = [];
2788
+ for (const effect of effects) {
2789
+ if (isExecutableActionObject(effect)) {
2790
+ actorScope.actionExecutor(effect);
2791
+ } else {
2792
+ logicEffects.push(effect);
2793
+ }
2794
+ }
2795
+ return logicEffects;
2796
+ }
3398
2797
 
3399
2798
  /**
3400
2799
  * An Actor is a running process that can receive events, send events and change
@@ -3433,6 +2832,7 @@ class Actor {
3433
2832
  this.logger = void 0;
3434
2833
  /** @internal */
3435
2834
  this._processingStatus = ProcessingStatus.NotStarted;
2835
+ this._forceDeferredActions = false;
3436
2836
  // Actor Ref
3437
2837
  this._parent = void 0;
3438
2838
  /** @internal */
@@ -3448,6 +2848,7 @@ class Actor {
3448
2848
  this._collectedActions = [];
3449
2849
  /** @internal Events relayed to other actors during the in-flight transition. */
3450
2850
  this._collectedSent = [];
2851
+ this._initialEffects = void 0;
3451
2852
  this.systemId = void 0;
3452
2853
  /** The globally unique process ID for this invocation. */
3453
2854
  this.sessionId = void 0;
@@ -3550,7 +2951,7 @@ class Actor {
3550
2951
  executingCustomAction = saveExecutingCustomAction;
3551
2952
  }
3552
2953
  };
3553
- if (this._processingStatus === ProcessingStatus.Running) {
2954
+ if (this._processingStatus === ProcessingStatus.Running && !this._forceDeferredActions) {
3554
2955
  exec();
3555
2956
  } else {
3556
2957
  this._deferred.push(exec);
@@ -3579,7 +2980,7 @@ class Actor {
3579
2980
  this.system._set(systemId, this);
3580
2981
  }
3581
2982
 
3582
- // prepare to collect initial microsteps during getInitialSnapshot
2983
+ // prepare to collect initial microsteps during initialTransition
3583
2984
  this._collectedMicrosteps = [];
3584
2985
  let persistedState = options?.snapshot ?? options?.state;
3585
2986
  if (persistedState && typeof persistedState === 'object' && '_pendingEffects' in persistedState) {
@@ -3593,7 +2994,13 @@ class Actor {
3593
2994
  persistedState = rest;
3594
2995
  }
3595
2996
  try {
3596
- this._snapshot = persistedState ? this.logic.restoreSnapshot ? this.logic.restoreSnapshot(persistedState, this._actorScope) : persistedState : this.logic.getInitialSnapshot(this._actorScope, this.options?.input);
2997
+ if (persistedState) {
2998
+ this._snapshot = this.logic.restoreSnapshot ? this.logic.restoreSnapshot(persistedState, this._actorScope) : persistedState;
2999
+ } else {
3000
+ const [snapshot, effects] = this.logic.initialTransition(this.options?.input, this._actorScope);
3001
+ this._snapshot = snapshot;
3002
+ this._initialEffects = effects;
3003
+ }
3597
3004
  } catch (err) {
3598
3005
  // if we get here then it means that we assign a value to this._snapshot that is not of the correct type
3599
3006
  // we can't get the true `TSnapshot & { status: 'error'; }`, it's impossible
@@ -3702,6 +3109,26 @@ class Actor {
3702
3109
  this._collectedActions = [];
3703
3110
  this._collectedSent = [];
3704
3111
  }
3112
+ _flushInitialEffects() {
3113
+ if (!this._initialEffects) {
3114
+ return true;
3115
+ }
3116
+ this._forceDeferredActions = true;
3117
+ try {
3118
+ const logicEffects = executeExecutableEffects(this._initialEffects, this._actorScope);
3119
+ executeLogicEffects(logicEffects, this._actorScope);
3120
+ this._initialEffects = undefined;
3121
+ return true;
3122
+ } catch (err) {
3123
+ this._initialEffects = undefined;
3124
+ this._deferred.length = 0;
3125
+ this._setErrorSnapshot(err);
3126
+ this._error(err);
3127
+ return false;
3128
+ } finally {
3129
+ this._forceDeferredActions = false;
3130
+ }
3131
+ }
3705
3132
 
3706
3133
  /**
3707
3134
  * Subscribe an observer to an actor’s snapshot values.
@@ -3828,7 +3255,7 @@ class Actor {
3828
3255
  complete: observer.complete
3829
3256
  });
3830
3257
  },
3831
- get: () => selector(this.get())
3258
+ get: () => selector(this.getSnapshot())
3832
3259
  };
3833
3260
  }
3834
3261
 
@@ -3866,6 +3293,9 @@ class Actor {
3866
3293
  case 'done':
3867
3294
  // a state machine can be "done" upon initialization (it could reach a final state using initial microsteps)
3868
3295
  // we still need to complete observers, flush deferreds etc
3296
+ if (!this._flushInitialEffects()) {
3297
+ return this;
3298
+ }
3869
3299
  this.update(this._snapshot, initEvent);
3870
3300
  // TODO: rethink cleanup of observers, mailbox, etc
3871
3301
  return this;
@@ -3885,6 +3315,9 @@ class Actor {
3885
3315
  return this;
3886
3316
  }
3887
3317
  }
3318
+ if (!this._flushInitialEffects()) {
3319
+ return this;
3320
+ }
3888
3321
 
3889
3322
  // TODO: this notifies all subscribers but usually this is redundant
3890
3323
  // there is no real change happening here
@@ -3923,9 +3356,16 @@ class Actor {
3923
3356
  this._error(err);
3924
3357
  return;
3925
3358
  }
3926
- const [snapshot, effects] = Array.isArray(nextState) ? nextState : [nextState, undefined];
3927
- this.update(snapshot, event);
3928
- executeLogicEffects(effects, this._actorScope);
3359
+ try {
3360
+ const [snapshot, effects] = nextState;
3361
+ const logicEffects = executeExecutableEffects(effects, this._actorScope);
3362
+ this.update(snapshot, event);
3363
+ executeLogicEffects(logicEffects, this._actorScope);
3364
+ } catch (err) {
3365
+ this._setErrorSnapshot(err);
3366
+ this._error(err);
3367
+ return;
3368
+ }
3929
3369
  if (event.type === XSTATE_STOP) {
3930
3370
  this._stopProcedure();
3931
3371
  this._complete();
@@ -4107,12 +3547,6 @@ class Actor {
4107
3547
  * @see {@link Actor.getPersistedSnapshot} to persist the internal state of an actor (which is more than just a snapshot).
4108
3548
  */
4109
3549
  getSnapshot() {
4110
- return this.get();
4111
- }
4112
-
4113
- /** Read the actor's current snapshot as an atom value. */
4114
- get() {
4115
- onActorRead?.(this);
4116
3550
  return this._snapshot;
4117
3551
  }
4118
3552
  }
@@ -4551,46 +3985,45 @@ function createEventObservableLogic(lazyObservableOrConfig) {
4551
3985
  config: lazyObservable,
4552
3986
  transition: (state, event) => {
4553
3987
  if (state.status !== 'active') {
4554
- return state;
3988
+ return [state, []];
4555
3989
  }
4556
3990
  switch (event.type) {
4557
3991
  case XSTATE_OBSERVABLE_ERROR:
4558
- return {
3992
+ return [{
4559
3993
  ...state,
4560
3994
  status: 'error',
4561
3995
  error: event.data,
4562
3996
  input: undefined,
4563
3997
  _subscription: undefined
4564
- };
3998
+ }, []];
4565
3999
  case XSTATE_OBSERVABLE_COMPLETE:
4566
- return {
4000
+ return [{
4567
4001
  ...state,
4568
4002
  status: 'done',
4569
4003
  input: undefined,
4570
4004
  _subscription: undefined
4571
- };
4005
+ }, []];
4572
4006
  case XSTATE_STOP:
4573
4007
  state._subscription.unsubscribe();
4574
- return {
4008
+ return [{
4575
4009
  ...state,
4576
4010
  status: 'stopped',
4577
4011
  input: undefined,
4578
4012
  _subscription: undefined
4579
- };
4013
+ }, []];
4580
4014
  default:
4581
- return state;
4015
+ return [state, []];
4582
4016
  }
4583
4017
  },
4584
- getInitialSnapshot: (_, input) => {
4585
- return {
4586
- status: 'active',
4587
- output: undefined,
4588
- error: undefined,
4589
- context: undefined,
4590
- input,
4591
- _subscription: undefined
4592
- };
4593
- },
4018
+ initialTransition: (input, _) => [{
4019
+ status: 'active',
4020
+ output: undefined,
4021
+ error: undefined,
4022
+ context: undefined,
4023
+ input,
4024
+ _subscription: undefined
4025
+ }, []],
4026
+ getInitialSnapshot: (actorScope, input) => logic.initialTransition(input, actorScope)[0],
4594
4027
  start: (state, {
4595
4028
  self,
4596
4029
  system,
@@ -4917,10 +4350,7 @@ exports.TimeoutError = TimeoutError;
4917
4350
  exports.XSTATE_INIT = XSTATE_INIT;
4918
4351
  exports.checkStateIn = checkStateIn;
4919
4352
  exports.createActor = createActor;
4920
- exports.createAsyncAtom = createAsyncAtom;
4921
4353
  exports.createAsyncLogic = createAsyncLogic;
4922
- exports.createAtom = createAtom;
4923
- exports.createAtomConfig = createAtomConfig;
4924
4354
  exports.createCallbackLogic = createCallbackLogic;
4925
4355
  exports.createEmptyActor = createEmptyActor;
4926
4356
  exports.createEventObservableLogic = createEventObservableLogic;
@@ -4931,7 +4361,6 @@ exports.createListenerLogic = createListenerLogic;
4931
4361
  exports.createLogic = createLogic;
4932
4362
  exports.createMachineSnapshot = createMachineSnapshot;
4933
4363
  exports.createObservableLogic = createObservableLogic;
4934
- exports.createReducerAtom = createReducerAtom;
4935
4364
  exports.createSubscriptionLogic = createSubscriptionLogic;
4936
4365
  exports.evaluateCandidate = evaluateCandidate;
4937
4366
  exports.formatRouteTransitions = formatRouteTransitions;
@@ -4945,8 +4374,8 @@ exports.getProperAncestors = getProperAncestors;
4945
4374
  exports.getStateNodeByPath = getStateNodeByPath;
4946
4375
  exports.getStateNodes = getStateNodes;
4947
4376
  exports.initialMicrostep = initialMicrostep;
4948
- exports.isAtom = isAtom;
4949
4377
  exports.isAtomicStateNode = isAtomicStateNode;
4378
+ exports.isBuiltInExecutableAction = isBuiltInExecutableAction;
4950
4379
  exports.isInFinalState = isInFinalState;
4951
4380
  exports.isMachineSnapshot = isMachineSnapshot;
4952
4381
  exports.isStateId = isStateId;
@@ -4957,7 +4386,7 @@ exports.matchesEventDescriptor = matchesEventDescriptor;
4957
4386
  exports.matchesState = matchesState;
4958
4387
  exports.parseDelayToMilliseconds = parseDelayToMilliseconds;
4959
4388
  exports.pathToStateValue = pathToStateValue;
4960
- exports.resolveAndExecuteActionsWithContext = resolveAndExecuteActionsWithContext;
4389
+ exports.resolveActionsWithContext = resolveActionsWithContext;
4961
4390
  exports.resolveReferencedActor = resolveReferencedActor;
4962
4391
  exports.resolveStateValue = resolveStateValue;
4963
4392
  exports.subscriptionLogic = subscriptionLogic;