xstate 5.30.0 → 5.31.0

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-d3e2432b.cjs.js → StateMachine-37420c93.cjs.js} +8 -2
  12. package/dist/{StateMachine-a5d156db.development.esm.js → StateMachine-880c1b22.development.esm.js} +8 -2
  13. package/dist/{StateMachine-89436b8f.development.cjs.js → StateMachine-a2514a01.development.cjs.js} +8 -2
  14. package/dist/{StateMachine-bf2cec8d.esm.js → StateMachine-b9937861.esm.js} +8 -2
  15. package/dist/{assign-4254ecc7.development.esm.js → assign-4f7ce317.development.esm.js} +1 -1
  16. package/dist/{assign-f10db67b.cjs.js → assign-53a98e5d.cjs.js} +1 -1
  17. package/dist/{assign-8c16ea04.development.cjs.js → assign-6da0bff4.development.cjs.js} +1 -1
  18. package/dist/{assign-128c3f01.esm.js → assign-c15c199c.esm.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-279b177f.cjs.js} +18 -2
  24. package/dist/{log-0e01d593.development.esm.js → log-3e4dba89.development.esm.js} +18 -2
  25. package/dist/{log-f3a45f9f.development.cjs.js → log-8ca142b5.development.cjs.js} +18 -2
  26. package/dist/{log-678e6837.esm.js → log-ce7cb9aa.esm.js} +18 -2
  27. package/dist/{raise-b47daa89.esm.js → raise-56f87e05.esm.js} +7 -1
  28. package/dist/{raise-f051f097.cjs.js → raise-69f5aed0.cjs.js} +6 -0
  29. package/dist/{raise-f3874442.development.cjs.js → raise-6e65c93f.development.cjs.js} +6 -0
  30. package/dist/{raise-964ef086.development.esm.js → raise-b724c245.development.esm.js} +7 -1
  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-f3874442.development.cjs.js');
4
- var assign = require('./assign-8c16ea04.development.cjs.js');
3
+ var guards_dist_xstateGuards = require('./raise-6e65c93f.development.cjs.js');
4
+ var assign = require('./assign-6da0bff4.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,5 +1,5 @@
1
- import { S as STATE_DELIMITER, y as mapValues, t as toArray, z as formatTransitions, B as toTransitionConfigArray, C as formatTransition, N as NULL_EVENT, D as evaluateGuard, E as createInvokeId, F as getDelayedTransitions, G as formatInitialTransition, H as getCandidates, I as formatRouteTransitions, J as resolveStateValue, K as getAllStateNodes, p as getStateNodes, L as createMachineSnapshot, M as isInFinalState, d as macrostep, O as transitionNode, P as resolveActionsAndContext, e as createInitEvent, i as initialMicrostep, Q as toStatePath, R as isStateId, T as getStateNodeByPath, U as getPersistedSnapshot, V as resolveReferencedActor, c as createActor, $ as $$ACTOR_TYPE } from './raise-b47daa89.esm.js';
2
- import { a as assign } from './assign-128c3f01.esm.js';
1
+ import { S as STATE_DELIMITER, y as mapValues, t as toArray, z as formatTransitions, B as toTransitionConfigArray, C as formatTransition, N as NULL_EVENT, D as evaluateGuard, E as createInvokeId, F as getDelayedTransitions, G as formatInitialTransition, H as getCandidates, I as formatRouteTransitions, J as resolveStateValue, K as getAllStateNodes, p as getStateNodes, L as createMachineSnapshot, M as isInFinalState, d as macrostep, O as transitionNode, P as resolveActionsAndContext, e as createInitEvent, f as initialMicrostep, Q as toStatePath, R as isStateId, T as getStateNodeByPath, U as getPersistedSnapshot, V as resolveReferencedActor, c as createActor, $ as $$ACTOR_TYPE } from './raise-56f87e05.esm.js';
2
+ import { a as assign } from './assign-c15c199c.esm.js';
3
3
 
4
4
  const cache = new WeakMap();
5
5
  function memo(object, key, fn) {
@@ -299,6 +299,8 @@ class StateMachine {
299
299
  this.version = void 0;
300
300
  this.schemas = void 0;
301
301
  this.implementations = void 0;
302
+ /** Runtime options for machine execution. */
303
+ this.options = void 0;
302
304
  /** @internal */
303
305
  this.__xstatenode = true;
304
306
  /** @internal */
@@ -316,6 +318,10 @@ class StateMachine {
316
318
  };
317
319
  this.version = this.config.version;
318
320
  this.schemas = this.config.schemas;
321
+ this.options = {
322
+ maxIterations: Infinity,
323
+ ...this.config.options
324
+ };
319
325
  this.transition = this.transition.bind(this);
320
326
  this.getInitialSnapshot = this.getInitialSnapshot.bind(this);
321
327
  this.getPersistedSnapshot = this.getPersistedSnapshot.bind(this);
@@ -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-b724c245.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-f051f097.cjs.js');
3
+ var guards_dist_xstateGuards = require('./raise-69f5aed0.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-f3874442.development.cjs.js');
3
+ var guards_dist_xstateGuards = require('./raise-6e65c93f.development.cjs.js');
4
4
 
5
5
  function createSpawner(actorScope, {
6
6
  machine,
@@ -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-56f87e05.esm.js';
2
2
 
3
3
  function createSpawner(actorScope, {
4
4
  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-69f5aed0.cjs.js');
4
+ var assign = require('./assign-53a98e5d.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,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-b724c245.development.esm.js';
2
+ import { a as assign } from './assign-4f7ce317.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,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-6e65c93f.development.cjs.js');
4
+ var assign = require('./assign-6da0bff4.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 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-56f87e05.esm.js';
2
+ import { a as assign } from './assign-c15c199c.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";
@@ -2498,7 +2498,13 @@ function macrostep(snapshot, event, actorScope, internalQueue) {
2498
2498
  addMicrostep(step, currentEvent, transitions);
2499
2499
  }
2500
2500
  let shouldSelectEventlessTransitions = true;
2501
+ const maxIterations = snapshot.machine.options?.maxIterations ?? Infinity;
2502
+ let iterationCount = 0;
2501
2503
  while (nextSnapshot.status === 'active') {
2504
+ iterationCount++;
2505
+ if (iterationCount > maxIterations) {
2506
+ 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).`);
2507
+ }
2502
2508
  let enabledTransitions = shouldSelectEventlessTransitions ? selectEventlessTransitions(nextSnapshot, nextEvent) : [];
2503
2509
 
2504
2510
  // eventless transitions should always be selected after selecting *regular* transitions
@@ -2761,4 +2767,4 @@ function raise(eventOrExpr, options) {
2761
2767
  return raise;
2762
2768
  }
2763
2769
 
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 };
2770
+ 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 };
@@ -2500,7 +2500,13 @@ function macrostep(snapshot, event, actorScope, internalQueue) {
2500
2500
  addMicrostep(step, currentEvent, transitions);
2501
2501
  }
2502
2502
  let shouldSelectEventlessTransitions = true;
2503
+ const maxIterations = snapshot.machine.options?.maxIterations ?? Infinity;
2504
+ let iterationCount = 0;
2503
2505
  while (nextSnapshot.status === 'active') {
2506
+ iterationCount++;
2507
+ if (iterationCount > maxIterations) {
2508
+ 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).`);
2509
+ }
2504
2510
  let enabledTransitions = shouldSelectEventlessTransitions ? selectEventlessTransitions(nextSnapshot, nextEvent) : [];
2505
2511
 
2506
2512
  // eventless transitions should always be selected after selecting *regular* transitions
@@ -2550,7 +2550,13 @@ function macrostep(snapshot, event, actorScope, internalQueue) {
2550
2550
  addMicrostep(step, currentEvent, transitions);
2551
2551
  }
2552
2552
  let shouldSelectEventlessTransitions = true;
2553
+ const maxIterations = snapshot.machine.options?.maxIterations ?? Infinity;
2554
+ let iterationCount = 0;
2553
2555
  while (nextSnapshot.status === 'active') {
2556
+ iterationCount++;
2557
+ if (iterationCount > maxIterations) {
2558
+ 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).`);
2559
+ }
2554
2560
  let enabledTransitions = shouldSelectEventlessTransitions ? selectEventlessTransitions(nextSnapshot, nextEvent) : [];
2555
2561
 
2556
2562
  // eventless transitions should always be selected after selecting *regular* transitions
@@ -2548,7 +2548,13 @@ function macrostep(snapshot, event, actorScope, internalQueue) {
2548
2548
  addMicrostep(step, currentEvent, transitions);
2549
2549
  }
2550
2550
  let shouldSelectEventlessTransitions = true;
2551
+ const maxIterations = snapshot.machine.options?.maxIterations ?? Infinity;
2552
+ let iterationCount = 0;
2551
2553
  while (nextSnapshot.status === 'active') {
2554
+ iterationCount++;
2555
+ if (iterationCount > maxIterations) {
2556
+ 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).`);
2557
+ }
2552
2558
  let enabledTransitions = shouldSelectEventlessTransitions ? selectEventlessTransitions(nextSnapshot, nextEvent) : [];
2553
2559
 
2554
2560
  // eventless transitions should always be selected after selecting *regular* transitions
@@ -2823,4 +2829,4 @@ function raise(eventOrExpr, options) {
2823
2829
  return raise;
2824
2830
  }
2825
2831
 
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 };
2832
+ 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 };
@@ -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-69f5aed0.cjs.js');
7
+ var StateMachine = require('./StateMachine-37420c93.cjs.js');
8
+ var assign = require('./assign-53a98e5d.cjs.js');
9
+ var log = require('./log-279b177f.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,
@@ -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.development.cjs.js');
6
- var guards_dist_xstateGuards = require('./raise-f3874442.development.cjs.js');
7
- var StateMachine = require('./StateMachine-89436b8f.development.cjs.js');
8
- var assign = require('./assign-8c16ea04.development.cjs.js');
9
- var log = require('./log-f3a45f9f.development.cjs.js');
6
+ var guards_dist_xstateGuards = require('./raise-6e65c93f.development.cjs.js');
7
+ var StateMachine = require('./StateMachine-a2514a01.development.cjs.js');
8
+ var assign = require('./assign-6da0bff4.development.cjs.js');
9
+ var log = require('./log-8ca142b5.development.cjs.js');
10
10
  require('../dev/dist/xstate-dev.development.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);
@@ -574,6 +620,7 @@ exports.getMicrosteps = getMicrosteps;
574
620
  exports.getNextSnapshot = getNextSnapshot;
575
621
  exports.getNextTransitions = getNextTransitions;
576
622
  exports.initialTransition = initialTransition;
623
+ exports.mapState = mapState;
577
624
  exports.setup = setup;
578
625
  exports.toPromise = toPromise;
579
626
  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,