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