xstate 5.30.0 → 5.31.1

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 (50) hide show
  1. package/actions/dist/xstate-actions.cjs.js +3 -3
  2. package/actions/dist/xstate-actions.development.cjs.js +3 -3
  3. package/actions/dist/xstate-actions.development.esm.js +3 -3
  4. package/actions/dist/xstate-actions.esm.js +3 -3
  5. package/actions/dist/xstate-actions.umd.min.js.map +1 -1
  6. package/actors/dist/xstate-actors.cjs.js +1 -1
  7. package/actors/dist/xstate-actors.development.cjs.js +1 -1
  8. package/actors/dist/xstate-actors.development.esm.js +1 -1
  9. package/actors/dist/xstate-actors.esm.js +1 -1
  10. package/actors/dist/xstate-actors.umd.min.js.map +1 -1
  11. package/dist/{StateMachine-bf2cec8d.esm.js → StateMachine-1a16eef4.esm.js} +8 -2
  12. package/dist/{StateMachine-a5d156db.development.esm.js → StateMachine-36648f20.development.esm.js} +8 -2
  13. package/dist/{StateMachine-d3e2432b.cjs.js → StateMachine-4c92941f.cjs.js} +8 -2
  14. package/dist/{StateMachine-89436b8f.development.cjs.js → StateMachine-d247dfb8.development.cjs.js} +8 -2
  15. package/dist/{assign-128c3f01.esm.js → assign-03301f6f.esm.js} +1 -1
  16. package/dist/{assign-4254ecc7.development.esm.js → assign-1581c3f4.development.esm.js} +1 -1
  17. package/dist/{assign-8c16ea04.development.cjs.js → assign-1a3370ea.development.cjs.js} +1 -1
  18. package/dist/{assign-f10db67b.cjs.js → assign-9f37914d.cjs.js} +1 -1
  19. package/dist/declarations/src/StateMachine.d.ts +3 -1
  20. package/dist/declarations/src/index.d.ts +1 -0
  21. package/dist/declarations/src/mapState.d.ts +25 -0
  22. package/dist/declarations/src/types.d.ts +28 -0
  23. package/dist/{log-30abbb83.cjs.js → log-03b339e6.cjs.js} +18 -2
  24. package/dist/{log-f3a45f9f.development.cjs.js → log-51d9b5be.development.cjs.js} +18 -2
  25. package/dist/{log-0e01d593.development.esm.js → log-81184701.development.esm.js} +18 -2
  26. package/dist/{log-678e6837.esm.js → log-d1983b9c.esm.js} +18 -2
  27. package/dist/{raise-964ef086.development.esm.js → raise-746c22f6.development.esm.js} +11 -14
  28. package/dist/{raise-f3874442.development.cjs.js → raise-7e345a71.development.cjs.js} +10 -13
  29. package/dist/{raise-b47daa89.esm.js → raise-81f39c84.esm.js} +11 -14
  30. package/dist/{raise-f051f097.cjs.js → raise-eb8e9de6.cjs.js} +10 -13
  31. package/dist/xstate.cjs.js +51 -4
  32. package/dist/xstate.cjs.mjs +1 -0
  33. package/dist/xstate.development.cjs.js +51 -4
  34. package/dist/xstate.development.cjs.mjs +1 -0
  35. package/dist/xstate.development.esm.js +55 -9
  36. package/dist/xstate.esm.js +55 -9
  37. package/dist/xstate.umd.min.js +1 -1
  38. package/dist/xstate.umd.min.js.map +1 -1
  39. package/graph/dist/xstate-graph.cjs.js +3 -3
  40. package/graph/dist/xstate-graph.development.cjs.js +3 -3
  41. package/graph/dist/xstate-graph.development.esm.js +3 -3
  42. package/graph/dist/xstate-graph.esm.js +3 -3
  43. package/graph/dist/xstate-graph.umd.min.js +1 -1
  44. package/graph/dist/xstate-graph.umd.min.js.map +1 -1
  45. package/guards/dist/xstate-guards.cjs.js +1 -1
  46. package/guards/dist/xstate-guards.development.cjs.js +1 -1
  47. package/guards/dist/xstate-guards.development.esm.js +1 -1
  48. package/guards/dist/xstate-guards.esm.js +1 -1
  49. package/guards/dist/xstate-guards.umd.min.js.map +1 -1
  50. package/package.json +1 -1
@@ -1,7 +1,7 @@
1
1
  'use strict';
2
2
 
3
- var guards_dist_xstateGuards = require('./raise-f051f097.cjs.js');
4
- var assign = require('./assign-f10db67b.cjs.js');
3
+ var guards_dist_xstateGuards = require('./raise-eb8e9de6.cjs.js');
4
+ var assign = require('./assign-9f37914d.cjs.js');
5
5
 
6
6
  const cache = new WeakMap();
7
7
  function memo(object, key, fn) {
@@ -301,6 +301,8 @@ class StateMachine {
301
301
  this.version = void 0;
302
302
  this.schemas = void 0;
303
303
  this.implementations = void 0;
304
+ /** Runtime options for machine execution. */
305
+ this.options = void 0;
304
306
  /** @internal */
305
307
  this.__xstatenode = true;
306
308
  /** @internal */
@@ -318,6 +320,10 @@ class StateMachine {
318
320
  };
319
321
  this.version = this.config.version;
320
322
  this.schemas = this.config.schemas;
323
+ this.options = {
324
+ maxIterations: Infinity,
325
+ ...this.config.options
326
+ };
321
327
  this.transition = this.transition.bind(this);
322
328
  this.getInitialSnapshot = this.getInitialSnapshot.bind(this);
323
329
  this.getPersistedSnapshot = this.getPersistedSnapshot.bind(this);
@@ -1,7 +1,7 @@
1
1
  'use strict';
2
2
 
3
- var guards_dist_xstateGuards = require('./raise-f3874442.development.cjs.js');
4
- var assign = require('./assign-8c16ea04.development.cjs.js');
3
+ var guards_dist_xstateGuards = require('./raise-7e345a71.development.cjs.js');
4
+ var assign = require('./assign-1a3370ea.development.cjs.js');
5
5
 
6
6
  const cache = new WeakMap();
7
7
  function memo(object, key, fn) {
@@ -301,6 +301,8 @@ class StateMachine {
301
301
  this.version = void 0;
302
302
  this.schemas = void 0;
303
303
  this.implementations = void 0;
304
+ /** Runtime options for machine execution. */
305
+ this.options = void 0;
304
306
  /** @internal */
305
307
  this.__xstatenode = true;
306
308
  /** @internal */
@@ -318,6 +320,10 @@ class StateMachine {
318
320
  };
319
321
  this.version = this.config.version;
320
322
  this.schemas = this.config.schemas;
323
+ this.options = {
324
+ maxIterations: Infinity,
325
+ ...this.config.options
326
+ };
321
327
  this.transition = this.transition.bind(this);
322
328
  this.getInitialSnapshot = this.getInitialSnapshot.bind(this);
323
329
  this.getPersistedSnapshot = this.getPersistedSnapshot.bind(this);
@@ -1,4 +1,4 @@
1
- import { Z as ProcessingStatus, V as resolveReferencedActor, c as createActor, _ as cloneMachineSnapshot } from './raise-b47daa89.esm.js';
1
+ import { Z as ProcessingStatus, V as resolveReferencedActor, c as createActor, _ as cloneMachineSnapshot } from './raise-81f39c84.esm.js';
2
2
 
3
3
  function createSpawner(actorScope, {
4
4
  machine,
@@ -1,4 +1,4 @@
1
- import { _ as ProcessingStatus, V as resolveReferencedActor, c as createActor, a0 as cloneMachineSnapshot, W as executingCustomAction } from './raise-964ef086.development.esm.js';
1
+ import { _ as ProcessingStatus, V as resolveReferencedActor, c as createActor, a0 as cloneMachineSnapshot, W as executingCustomAction } from './raise-746c22f6.development.esm.js';
2
2
 
3
3
  function createSpawner(actorScope, {
4
4
  machine,
@@ -1,6 +1,6 @@
1
1
  'use strict';
2
2
 
3
- var guards_dist_xstateGuards = require('./raise-f3874442.development.cjs.js');
3
+ var guards_dist_xstateGuards = require('./raise-7e345a71.development.cjs.js');
4
4
 
5
5
  function createSpawner(actorScope, {
6
6
  machine,
@@ -1,6 +1,6 @@
1
1
  'use strict';
2
2
 
3
- var guards_dist_xstateGuards = require('./raise-f051f097.cjs.js');
3
+ var guards_dist_xstateGuards = require('./raise-eb8e9de6.cjs.js');
4
4
 
5
5
  function createSpawner(actorScope, {
6
6
  machine,
@@ -1,7 +1,7 @@
1
1
  import { MachineSnapshot } from "./State.js";
2
2
  import { StateNode } from "./StateNode.js";
3
3
  import { AnyActorSystem } from "./system.js";
4
- import type { ActorLogic, ActorScope, AnyActorRef, AnyActorScope, DoNotInfer, Equals, EventDescriptor, EventObject, HistoryValue, InternalMachineImplementations, MachineConfig, MachineContext, MachineImplementationsSimplified, MetaObject, ParameterizedObject, ProvidedActor, Snapshot, StateMachineDefinition, StateValue, TransitionDefinition, ResolvedStateMachineTypes, StateSchema, SnapshotStatus } from "./types.js";
4
+ import type { ActorLogic, ActorScope, AnyActorRef, AnyActorScope, DoNotInfer, Equals, EventDescriptor, EventObject, HistoryValue, InternalMachineImplementations, MachineConfig, MachineContext, MachineImplementationsSimplified, MachineOptions, MetaObject, ParameterizedObject, ProvidedActor, Snapshot, StateMachineDefinition, StateValue, TransitionDefinition, ResolvedStateMachineTypes, StateSchema, SnapshotStatus } from "./types.js";
5
5
  export declare class StateMachine<TContext extends MachineContext, TEvent extends EventObject, TChildren extends Record<string, AnyActorRef | undefined>, TActor extends ProvidedActor, TAction extends ParameterizedObject, TGuard extends ParameterizedObject, TDelay extends string, TStateValue extends StateValue, TTag extends string, TInput, TOutput, TEmitted extends EventObject, TMeta extends MetaObject, TStateSchema extends StateSchema> implements ActorLogic<MachineSnapshot<TContext, TEvent, TChildren, TStateValue, TTag, TOutput, TMeta, TStateSchema>, TEvent, TInput, AnyActorSystem, TEmitted> {
6
6
  /** The raw config used to create the machine. */
7
7
  config: MachineConfig<TContext, TEvent, any, any, any, any, any, any, TOutput, any, // TEmitted
@@ -12,6 +12,8 @@ export declare class StateMachine<TContext extends MachineContext, TEvent extend
12
12
  version?: string;
13
13
  schemas: unknown;
14
14
  implementations: MachineImplementationsSimplified<TContext, TEvent>;
15
+ /** Runtime options for machine execution. */
16
+ options: MachineOptions;
15
17
  root: StateNode<TContext, TEvent>;
16
18
  id: string;
17
19
  states: StateNode<TContext, TEvent>['states'];
@@ -3,6 +3,7 @@ export * from "./actors/index.js";
3
3
  export { assertEvent } from "./assert.js";
4
4
  export { Actor, createActor, interpret, type Interpreter, type RequiredActorOptionsKeys as RequiredActorOptionsKeys } from "./createActor.js";
5
5
  export { createMachine } from "./createMachine.js";
6
+ export { mapState } from "./mapState.js";
6
7
  export { getInitialSnapshot, getNextSnapshot } from "./getNextSnapshot.js";
7
8
  export { and, not, or, stateIn } from "./guards.js";
8
9
  export type { GuardPredicate, GuardArgs } from "./guards.js";
@@ -0,0 +1,25 @@
1
+ import { AnyMachineSnapshot, AnyStateNode, StateSchema, StateSchemaFrom } from "./types.js";
2
+ /**
3
+ * A mapper object that defines how to transform a snapshot based on its state.
4
+ * Can be nested to match the state hierarchy of the machine.
5
+ */
6
+ type StateSchemaMapper<TSnapshot extends AnyMachineSnapshot, T extends StateSchema, TResult> = {
7
+ /** Maps the snapshot to a value when this state is active. */
8
+ map?: (snapshot: TSnapshot) => TResult;
9
+ /** Nested mappers for child states. */
10
+ states?: {
11
+ [K in keyof T['states']]?: T['states'][K] extends StateSchema ? StateSchemaMapper<TSnapshot, T['states'][K], TResult> : never;
12
+ };
13
+ };
14
+ /**
15
+ * Maps a machine snapshot to an array of result objects based on active states.
16
+ *
17
+ * Traverses all active state nodes (from atomic/leaf states up to root) and
18
+ * collects results from matching `map` functions in the mapper object. Results
19
+ * are ordered leaf-to-root (most specific state first).
20
+ */
21
+ export declare function mapState<T extends AnyMachineSnapshot, TResult>(snapshot: T, mapper: StateSchemaMapper<T, StateSchemaFrom<T['machine']>, TResult>): {
22
+ stateNode: AnyStateNode;
23
+ result: TResult;
24
+ }[];
25
+ export {};
@@ -455,11 +455,38 @@ export type ContextFactory<TContext extends MachineContext, TActor extends Provi
455
455
  StateValue, string, unknown, TODO, // TMeta
456
456
  TODO>, TEvent, AnyEventObject>;
457
457
  }) => TContext;
458
+ /**
459
+ * Runtime options for state machine execution.
460
+ *
461
+ * @example
462
+ *
463
+ * ```ts
464
+ * const machine = createMachine({
465
+ * // ... machine config
466
+ * options: {
467
+ * maxIterations: 5000
468
+ * // other runtime options can be added here
469
+ * }
470
+ * });
471
+ * ```
472
+ */
473
+ export interface MachineOptions {
474
+ /**
475
+ * Maximum number of microsteps allowed before throwing an infinite loop
476
+ * error. Defaults to `Infinity` (no limit). Set to a finite number to enable
477
+ * infinite loop detection.
478
+ *
479
+ * @default Infinity
480
+ */
481
+ maxIterations?: number;
482
+ }
458
483
  export type MachineConfig<TContext extends MachineContext, TEvent extends EventObject, TActor extends ProvidedActor = ProvidedActor, TAction extends ParameterizedObject = ParameterizedObject, TGuard extends ParameterizedObject = ParameterizedObject, TDelay extends string = string, TTag extends string = string, TInput = any, TOutput = unknown, TEmitted extends EventObject = EventObject, TMeta extends MetaObject = MetaObject> = (Omit<StateNodeConfig<DoNotInfer<TContext>, DoNotInfer<TEvent>, DoNotInfer<TActor>, DoNotInfer<TAction>, DoNotInfer<TGuard>, DoNotInfer<TDelay>, DoNotInfer<TTag>, DoNotInfer<TOutput>, DoNotInfer<TEmitted>, DoNotInfer<TMeta>>, 'output'> & {
459
484
  /** The initial context (extended state) */
460
485
  /** The machine's own version. */
461
486
  version?: string;
462
487
  output?: Mapper<TContext, DoneStateEvent, TOutput, TEvent> | TOutput;
488
+ /** Runtime options for machine execution. */
489
+ options?: MachineOptions;
463
490
  }) & (MachineContext extends TContext ? {
464
491
  context?: InitialContext<LowInfer<TContext>, TActor, TInput, TEvent>;
465
492
  } : {
@@ -933,6 +960,7 @@ export type StateSchema = {
933
960
  tags?: unknown;
934
961
  description?: unknown;
935
962
  };
963
+ export type StateSchemaFrom<T extends AnyStateMachine> = T extends StateMachine<infer _TContext, infer _TEvent, infer _TChildren, infer _TActor, infer _TAction, infer _TGuard, infer _TDelay, infer _TStateValue, infer _TTag, infer _TInput, infer _TOutput, infer _TEmitted, infer _TMeta, infer TStateSchema> ? TStateSchema : never;
936
964
  export type StateId<TSchema extends StateSchema, TKey extends string = '(machine)', TParentKey extends string | null = null> = (TSchema extends {
937
965
  id: string;
938
966
  } ? TSchema['id'] : TParentKey extends null ? TKey : `${TParentKey}.${TKey}`) | (TSchema['states'] extends Record<string, any> ? Values<{
@@ -1,7 +1,7 @@
1
1
  'use strict';
2
2
 
3
- var guards_dist_xstateGuards = require('./raise-f051f097.cjs.js');
4
- var assign = require('./assign-f10db67b.cjs.js');
3
+ var guards_dist_xstateGuards = require('./raise-eb8e9de6.cjs.js');
4
+ var assign = require('./assign-9f37914d.cjs.js');
5
5
 
6
6
  function resolveEmit(_, snapshot, args, actionParams, {
7
7
  event: eventOrExpr
@@ -108,6 +108,22 @@ eventOrExpr) {
108
108
  // TODO: possibly refactor this somehow, use even a simpler type, and maybe even make `machine.options` private or something
109
109
  /** @ignore */
110
110
 
111
+ /**
112
+ * Runtime options for state machine execution.
113
+ *
114
+ * @example
115
+ *
116
+ * ```ts
117
+ * const machine = createMachine({
118
+ * // ... machine config
119
+ * options: {
120
+ * maxIterations: 5000
121
+ * // other runtime options can be added here
122
+ * }
123
+ * });
124
+ * ```
125
+ */
126
+
111
127
  let SpecialTargets = /*#__PURE__*/function (SpecialTargets) {
112
128
  SpecialTargets["Parent"] = "#_parent";
113
129
  SpecialTargets["Internal"] = "#_internal";
@@ -1,7 +1,7 @@
1
1
  'use strict';
2
2
 
3
- var guards_dist_xstateGuards = require('./raise-f3874442.development.cjs.js');
4
- var assign = require('./assign-8c16ea04.development.cjs.js');
3
+ var guards_dist_xstateGuards = require('./raise-7e345a71.development.cjs.js');
4
+ var assign = require('./assign-1a3370ea.development.cjs.js');
5
5
 
6
6
  function resolveEmit(_, snapshot, args, actionParams, {
7
7
  event: eventOrExpr
@@ -114,6 +114,22 @@ eventOrExpr) {
114
114
  // TODO: possibly refactor this somehow, use even a simpler type, and maybe even make `machine.options` private or something
115
115
  /** @ignore */
116
116
 
117
+ /**
118
+ * Runtime options for state machine execution.
119
+ *
120
+ * @example
121
+ *
122
+ * ```ts
123
+ * const machine = createMachine({
124
+ * // ... machine config
125
+ * options: {
126
+ * maxIterations: 5000
127
+ * // other runtime options can be added here
128
+ * }
129
+ * });
130
+ * ```
131
+ */
132
+
117
133
  let SpecialTargets = /*#__PURE__*/function (SpecialTargets) {
118
134
  SpecialTargets["Parent"] = "#_parent";
119
135
  SpecialTargets["Internal"] = "#_internal";
@@ -1,5 +1,5 @@
1
- import { W as executingCustomAction, Y as XSTATE_ERROR, Z as createErrorActorEvent, D as evaluateGuard, a as cancel, r as raise, b as spawnChild, s as stopChild } from './raise-964ef086.development.esm.js';
2
- import { a as assign } from './assign-4254ecc7.development.esm.js';
1
+ import { W as executingCustomAction, Y as XSTATE_ERROR, Z as createErrorActorEvent, D as evaluateGuard, a as cancel, r as raise, b as spawnChild, s as stopChild } from './raise-746c22f6.development.esm.js';
2
+ import { a as assign } from './assign-1581c3f4.development.esm.js';
3
3
 
4
4
  function resolveEmit(_, snapshot, args, actionParams, {
5
5
  event: eventOrExpr
@@ -112,6 +112,22 @@ eventOrExpr) {
112
112
  // TODO: possibly refactor this somehow, use even a simpler type, and maybe even make `machine.options` private or something
113
113
  /** @ignore */
114
114
 
115
+ /**
116
+ * Runtime options for state machine execution.
117
+ *
118
+ * @example
119
+ *
120
+ * ```ts
121
+ * const machine = createMachine({
122
+ * // ... machine config
123
+ * options: {
124
+ * maxIterations: 5000
125
+ * // other runtime options can be added here
126
+ * }
127
+ * });
128
+ * ```
129
+ */
130
+
115
131
  let SpecialTargets = /*#__PURE__*/function (SpecialTargets) {
116
132
  SpecialTargets["Parent"] = "#_parent";
117
133
  SpecialTargets["Internal"] = "#_internal";
@@ -1,5 +1,5 @@
1
- import { W as XSTATE_ERROR, Y as createErrorActorEvent, D as evaluateGuard, a as cancel, r as raise, b as spawnChild, s as stopChild } from './raise-b47daa89.esm.js';
2
- import { a as assign } from './assign-128c3f01.esm.js';
1
+ import { W as XSTATE_ERROR, Y as createErrorActorEvent, D as evaluateGuard, a as cancel, r as raise, b as spawnChild, s as stopChild } from './raise-81f39c84.esm.js';
2
+ import { a as assign } from './assign-03301f6f.esm.js';
3
3
 
4
4
  function resolveEmit(_, snapshot, args, actionParams, {
5
5
  event: eventOrExpr
@@ -106,6 +106,22 @@ eventOrExpr) {
106
106
  // TODO: possibly refactor this somehow, use even a simpler type, and maybe even make `machine.options` private or something
107
107
  /** @ignore */
108
108
 
109
+ /**
110
+ * Runtime options for state machine execution.
111
+ *
112
+ * @example
113
+ *
114
+ * ```ts
115
+ * const machine = createMachine({
116
+ * // ... machine config
117
+ * options: {
118
+ * maxIterations: 5000
119
+ * // other runtime options can be added here
120
+ * }
121
+ * });
122
+ * ```
123
+ */
124
+
109
125
  let SpecialTargets = /*#__PURE__*/function (SpecialTargets) {
110
126
  SpecialTargets["Parent"] = "#_parent";
111
127
  SpecialTargets["Internal"] = "#_internal";
@@ -1818,21 +1818,12 @@ function formatRouteTransitions(rootStateNode) {
1818
1818
  if (sn.config.route && sn.config.id) {
1819
1819
  const routeId = sn.config.id;
1820
1820
  const userGuard = sn.config.route.guard;
1821
- const routeGuard = (args, params) => {
1822
- if (args.event.to !== `#${routeId}`) {
1823
- return false;
1824
- }
1825
- if (!userGuard) {
1826
- return true;
1827
- }
1828
- if (typeof userGuard === 'function') {
1829
- return userGuard(args, params);
1830
- }
1831
- return true;
1832
- };
1821
+ const routeMatches = ({
1822
+ event
1823
+ }) => event.to === `#${routeId}`;
1833
1824
  const transition = {
1834
1825
  ...sn.config.route,
1835
- guard: routeGuard,
1826
+ guard: userGuard ? and([routeMatches, userGuard]) : routeMatches,
1836
1827
  target: `#${routeId}`
1837
1828
  };
1838
1829
  routeTransitions.push(formatTransition(rootStateNode, 'xstate.route', transition));
@@ -2548,7 +2539,13 @@ function macrostep(snapshot, event, actorScope, internalQueue) {
2548
2539
  addMicrostep(step, currentEvent, transitions);
2549
2540
  }
2550
2541
  let shouldSelectEventlessTransitions = true;
2542
+ const maxIterations = snapshot.machine.options?.maxIterations ?? Infinity;
2543
+ let iterationCount = 0;
2551
2544
  while (nextSnapshot.status === 'active') {
2545
+ iterationCount++;
2546
+ if (iterationCount > maxIterations) {
2547
+ throw new Error(`Infinite loop detected: the machine has processed more than ${maxIterations} microsteps without reaching a stable state. This usually happens when there's a cycle of transitions (e.g., eventless transitions or raised events causing state A -> B -> C -> A).`);
2548
+ }
2552
2549
  let enabledTransitions = shouldSelectEventlessTransitions ? selectEventlessTransitions(nextSnapshot, nextEvent) : [];
2553
2550
 
2554
2551
  // eventless transitions should always be selected after selecting *regular* transitions
@@ -2823,4 +2820,4 @@ function raise(eventOrExpr, options) {
2823
2820
  return raise;
2824
2821
  }
2825
2822
 
2826
- export { $$ACTOR_TYPE as $, Actor as A, toTransitionConfigArray as B, formatTransition as C, evaluateGuard as D, createInvokeId as E, getDelayedTransitions as F, formatInitialTransition as G, getCandidates as H, formatRouteTransitions as I, resolveStateValue as J, getAllStateNodes as K, createMachineSnapshot as L, isInFinalState as M, NULL_EVENT as N, transitionNode as O, resolveActionsAndContext as P, toStatePath as Q, isStateId as R, STATE_DELIMITER as S, getStateNodeByPath as T, getPersistedSnapshot as U, resolveReferencedActor as V, executingCustomAction as W, XSTATE_STOP as X, XSTATE_ERROR as Y, createErrorActorEvent as Z, ProcessingStatus as _, cancel as a, cloneMachineSnapshot as a0, spawnChild as b, createActor as c, macrostep as d, createInitEvent as e, isAtomicStateNode as f, getProperAncestors as g, interpret as h, initialMicrostep as i, and as j, stateIn as k, isMachineSnapshot as l, matchesEventDescriptor as m, not as n, or as o, getStateNodes as p, getAllOwnEventDescriptors as q, raise as r, stopChild as s, toArray as t, matchesState as u, pathToStateValue as v, toObserver as w, stop as x, mapValues as y, formatTransitions as z };
2823
+ export { $$ACTOR_TYPE as $, Actor as A, toTransitionConfigArray as B, formatTransition as C, evaluateGuard as D, createInvokeId as E, getDelayedTransitions as F, formatInitialTransition as G, getCandidates as H, formatRouteTransitions as I, resolveStateValue as J, getAllStateNodes as K, createMachineSnapshot as L, isInFinalState as M, NULL_EVENT as N, transitionNode as O, resolveActionsAndContext as P, toStatePath as Q, isStateId as R, STATE_DELIMITER as S, getStateNodeByPath as T, getPersistedSnapshot as U, resolveReferencedActor as V, executingCustomAction as W, XSTATE_STOP as X, XSTATE_ERROR as Y, createErrorActorEvent as Z, ProcessingStatus as _, cancel as a, cloneMachineSnapshot as a0, spawnChild as b, createActor as c, macrostep as d, createInitEvent as e, initialMicrostep as f, getProperAncestors as g, interpret as h, isAtomicStateNode as i, and as j, stateIn as k, isMachineSnapshot as l, matchesEventDescriptor as m, not as n, or as o, getStateNodes as p, getAllOwnEventDescriptors as q, raise as r, stopChild as s, toArray as t, matchesState as u, pathToStateValue as v, toObserver as w, stop as x, mapValues as y, formatTransitions as z };
@@ -1820,21 +1820,12 @@ function formatRouteTransitions(rootStateNode) {
1820
1820
  if (sn.config.route && sn.config.id) {
1821
1821
  const routeId = sn.config.id;
1822
1822
  const userGuard = sn.config.route.guard;
1823
- const routeGuard = (args, params) => {
1824
- if (args.event.to !== `#${routeId}`) {
1825
- return false;
1826
- }
1827
- if (!userGuard) {
1828
- return true;
1829
- }
1830
- if (typeof userGuard === 'function') {
1831
- return userGuard(args, params);
1832
- }
1833
- return true;
1834
- };
1823
+ const routeMatches = ({
1824
+ event
1825
+ }) => event.to === `#${routeId}`;
1835
1826
  const transition = {
1836
1827
  ...sn.config.route,
1837
- guard: routeGuard,
1828
+ guard: userGuard ? and([routeMatches, userGuard]) : routeMatches,
1838
1829
  target: `#${routeId}`
1839
1830
  };
1840
1831
  routeTransitions.push(formatTransition(rootStateNode, 'xstate.route', transition));
@@ -2550,7 +2541,13 @@ function macrostep(snapshot, event, actorScope, internalQueue) {
2550
2541
  addMicrostep(step, currentEvent, transitions);
2551
2542
  }
2552
2543
  let shouldSelectEventlessTransitions = true;
2544
+ const maxIterations = snapshot.machine.options?.maxIterations ?? Infinity;
2545
+ let iterationCount = 0;
2553
2546
  while (nextSnapshot.status === 'active') {
2547
+ iterationCount++;
2548
+ if (iterationCount > maxIterations) {
2549
+ throw new Error(`Infinite loop detected: the machine has processed more than ${maxIterations} microsteps without reaching a stable state. This usually happens when there's a cycle of transitions (e.g., eventless transitions or raised events causing state A -> B -> C -> A).`);
2550
+ }
2554
2551
  let enabledTransitions = shouldSelectEventlessTransitions ? selectEventlessTransitions(nextSnapshot, nextEvent) : [];
2555
2552
 
2556
2553
  // eventless transitions should always be selected after selecting *regular* transitions
@@ -1771,21 +1771,12 @@ function formatRouteTransitions(rootStateNode) {
1771
1771
  if (sn.config.route && sn.config.id) {
1772
1772
  const routeId = sn.config.id;
1773
1773
  const userGuard = sn.config.route.guard;
1774
- const routeGuard = (args, params) => {
1775
- if (args.event.to !== `#${routeId}`) {
1776
- return false;
1777
- }
1778
- if (!userGuard) {
1779
- return true;
1780
- }
1781
- if (typeof userGuard === 'function') {
1782
- return userGuard(args, params);
1783
- }
1784
- return true;
1785
- };
1774
+ const routeMatches = ({
1775
+ event
1776
+ }) => event.to === `#${routeId}`;
1786
1777
  const transition = {
1787
1778
  ...sn.config.route,
1788
- guard: routeGuard,
1779
+ guard: userGuard ? and([routeMatches, userGuard]) : routeMatches,
1789
1780
  target: `#${routeId}`
1790
1781
  };
1791
1782
  routeTransitions.push(formatTransition(rootStateNode, 'xstate.route', transition));
@@ -2498,7 +2489,13 @@ function macrostep(snapshot, event, actorScope, internalQueue) {
2498
2489
  addMicrostep(step, currentEvent, transitions);
2499
2490
  }
2500
2491
  let shouldSelectEventlessTransitions = true;
2492
+ const maxIterations = snapshot.machine.options?.maxIterations ?? Infinity;
2493
+ let iterationCount = 0;
2501
2494
  while (nextSnapshot.status === 'active') {
2495
+ iterationCount++;
2496
+ if (iterationCount > maxIterations) {
2497
+ throw new Error(`Infinite loop detected: the machine has processed more than ${maxIterations} microsteps without reaching a stable state. This usually happens when there's a cycle of transitions (e.g., eventless transitions or raised events causing state A -> B -> C -> A).`);
2498
+ }
2502
2499
  let enabledTransitions = shouldSelectEventlessTransitions ? selectEventlessTransitions(nextSnapshot, nextEvent) : [];
2503
2500
 
2504
2501
  // eventless transitions should always be selected after selecting *regular* transitions
@@ -2761,4 +2758,4 @@ function raise(eventOrExpr, options) {
2761
2758
  return raise;
2762
2759
  }
2763
2760
 
2764
- export { $$ACTOR_TYPE as $, Actor as A, toTransitionConfigArray as B, formatTransition as C, evaluateGuard as D, createInvokeId as E, getDelayedTransitions as F, formatInitialTransition as G, getCandidates as H, formatRouteTransitions as I, resolveStateValue as J, getAllStateNodes as K, createMachineSnapshot as L, isInFinalState as M, NULL_EVENT as N, transitionNode as O, resolveActionsAndContext as P, toStatePath as Q, isStateId as R, STATE_DELIMITER as S, getStateNodeByPath as T, getPersistedSnapshot as U, resolveReferencedActor as V, XSTATE_ERROR as W, XSTATE_STOP as X, createErrorActorEvent as Y, ProcessingStatus as Z, cloneMachineSnapshot as _, cancel as a, spawnChild as b, createActor as c, macrostep as d, createInitEvent as e, isAtomicStateNode as f, getProperAncestors as g, interpret as h, initialMicrostep as i, and as j, stateIn as k, isMachineSnapshot as l, matchesEventDescriptor as m, not as n, or as o, getStateNodes as p, getAllOwnEventDescriptors as q, raise as r, stopChild as s, toArray as t, matchesState as u, pathToStateValue as v, toObserver as w, stop as x, mapValues as y, formatTransitions as z };
2761
+ export { $$ACTOR_TYPE as $, Actor as A, toTransitionConfigArray as B, formatTransition as C, evaluateGuard as D, createInvokeId as E, getDelayedTransitions as F, formatInitialTransition as G, getCandidates as H, formatRouteTransitions as I, resolveStateValue as J, getAllStateNodes as K, createMachineSnapshot as L, isInFinalState as M, NULL_EVENT as N, transitionNode as O, resolveActionsAndContext as P, toStatePath as Q, isStateId as R, STATE_DELIMITER as S, getStateNodeByPath as T, getPersistedSnapshot as U, resolveReferencedActor as V, XSTATE_ERROR as W, XSTATE_STOP as X, createErrorActorEvent as Y, ProcessingStatus as Z, cloneMachineSnapshot as _, cancel as a, spawnChild as b, createActor as c, macrostep as d, createInitEvent as e, initialMicrostep as f, getProperAncestors as g, interpret as h, isAtomicStateNode as i, and as j, stateIn as k, isMachineSnapshot as l, matchesEventDescriptor as m, not as n, or as o, getStateNodes as p, getAllOwnEventDescriptors as q, raise as r, stopChild as s, toArray as t, matchesState as u, pathToStateValue as v, toObserver as w, stop as x, mapValues as y, formatTransitions as z };
@@ -1773,21 +1773,12 @@ function formatRouteTransitions(rootStateNode) {
1773
1773
  if (sn.config.route && sn.config.id) {
1774
1774
  const routeId = sn.config.id;
1775
1775
  const userGuard = sn.config.route.guard;
1776
- const routeGuard = (args, params) => {
1777
- if (args.event.to !== `#${routeId}`) {
1778
- return false;
1779
- }
1780
- if (!userGuard) {
1781
- return true;
1782
- }
1783
- if (typeof userGuard === 'function') {
1784
- return userGuard(args, params);
1785
- }
1786
- return true;
1787
- };
1776
+ const routeMatches = ({
1777
+ event
1778
+ }) => event.to === `#${routeId}`;
1788
1779
  const transition = {
1789
1780
  ...sn.config.route,
1790
- guard: routeGuard,
1781
+ guard: userGuard ? and([routeMatches, userGuard]) : routeMatches,
1791
1782
  target: `#${routeId}`
1792
1783
  };
1793
1784
  routeTransitions.push(formatTransition(rootStateNode, 'xstate.route', transition));
@@ -2500,7 +2491,13 @@ function macrostep(snapshot, event, actorScope, internalQueue) {
2500
2491
  addMicrostep(step, currentEvent, transitions);
2501
2492
  }
2502
2493
  let shouldSelectEventlessTransitions = true;
2494
+ const maxIterations = snapshot.machine.options?.maxIterations ?? Infinity;
2495
+ let iterationCount = 0;
2503
2496
  while (nextSnapshot.status === 'active') {
2497
+ iterationCount++;
2498
+ if (iterationCount > maxIterations) {
2499
+ throw new Error(`Infinite loop detected: the machine has processed more than ${maxIterations} microsteps without reaching a stable state. This usually happens when there's a cycle of transitions (e.g., eventless transitions or raised events causing state A -> B -> C -> A).`);
2500
+ }
2504
2501
  let enabledTransitions = shouldSelectEventlessTransitions ? selectEventlessTransitions(nextSnapshot, nextEvent) : [];
2505
2502
 
2506
2503
  // eventless transitions should always be selected after selecting *regular* transitions
@@ -3,10 +3,10 @@
3
3
  Object.defineProperty(exports, '__esModule', { value: true });
4
4
 
5
5
  var actors_dist_xstateActors = require('../actors/dist/xstate-actors.cjs.js');
6
- var guards_dist_xstateGuards = require('./raise-f051f097.cjs.js');
7
- var StateMachine = require('./StateMachine-d3e2432b.cjs.js');
8
- var assign = require('./assign-f10db67b.cjs.js');
9
- var log = require('./log-30abbb83.cjs.js');
6
+ var guards_dist_xstateGuards = require('./raise-eb8e9de6.cjs.js');
7
+ var StateMachine = require('./StateMachine-4c92941f.cjs.js');
8
+ var assign = require('./assign-9f37914d.cjs.js');
9
+ var log = require('./log-03b339e6.cjs.js');
10
10
  require('../dev/dist/xstate-dev.cjs.js');
11
11
 
12
12
  /**
@@ -87,6 +87,52 @@ function createMachine(config, implementations) {
87
87
  return new StateMachine.StateMachine(config, implementations);
88
88
  }
89
89
 
90
+ /**
91
+ * A mapper object that defines how to transform a snapshot based on its state.
92
+ * Can be nested to match the state hierarchy of the machine.
93
+ */
94
+
95
+ /**
96
+ * Maps a machine snapshot to an array of result objects based on active states.
97
+ *
98
+ * Traverses all active state nodes (from atomic/leaf states up to root) and
99
+ * collects results from matching `map` functions in the mapper object. Results
100
+ * are ordered leaf-to-root (most specific state first).
101
+ */
102
+ function mapState(snapshot, mapper) {
103
+ const results = [];
104
+ const findMapper = (currentMapper, nodePath) => {
105
+ let mapper = currentMapper;
106
+ for (const key of nodePath) {
107
+ if (!mapper?.states) {
108
+ return undefined;
109
+ }
110
+ const states = mapper.states;
111
+ if (!(key in states)) {
112
+ return undefined;
113
+ }
114
+ mapper = states[key];
115
+ }
116
+ return mapper;
117
+ };
118
+ const visited = new Set();
119
+ for (const atomicNode of snapshot._nodes.filter(guards_dist_xstateGuards.isAtomicStateNode)) {
120
+ let current = atomicNode;
121
+ while (current && !visited.has(current)) {
122
+ visited.add(current);
123
+ const nodeMapper = findMapper(mapper, current.path);
124
+ if (nodeMapper?.map) {
125
+ results.push({
126
+ stateNode: current,
127
+ result: nodeMapper.map(snapshot)
128
+ });
129
+ }
130
+ current = current.parent;
131
+ }
132
+ }
133
+ return results;
134
+ }
135
+
90
136
  /** @internal */
91
137
  function createInertActorScope(actorLogic) {
92
138
  const self = guards_dist_xstateGuards.createActor(actorLogic);
@@ -571,6 +617,7 @@ exports.getMicrosteps = getMicrosteps;
571
617
  exports.getNextSnapshot = getNextSnapshot;
572
618
  exports.getNextTransitions = getNextTransitions;
573
619
  exports.initialTransition = initialTransition;
620
+ exports.mapState = mapState;
574
621
  exports.setup = setup;
575
622
  exports.toPromise = toPromise;
576
623
  exports.transition = transition;
@@ -30,6 +30,7 @@ export {
30
30
  interpret,
31
31
  isMachineSnapshot,
32
32
  log,
33
+ mapState,
33
34
  matchesState,
34
35
  not,
35
36
  or,