xstate 5.32.2 → 6.0.0-alpha.10

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 (121) hide show
  1. package/README.md +25 -24
  2. package/dist/StateMachine-0aa98f54.development.esm.js +746 -0
  3. package/dist/StateMachine-aef700df.cjs.js +732 -0
  4. package/dist/StateMachine-d4931336.esm.js +729 -0
  5. package/dist/StateMachine-da872dde.development.cjs.js +749 -0
  6. package/dist/declarations/src/State.d.ts +11 -13
  7. package/dist/declarations/src/StateMachine.d.ts +40 -26
  8. package/dist/declarations/src/StateNode.d.ts +18 -54
  9. package/dist/declarations/src/actions.d.ts +14 -9
  10. package/dist/declarations/src/actors/callback.d.ts +42 -16
  11. package/dist/declarations/src/actors/index.d.ts +9 -6
  12. package/dist/declarations/src/actors/listener.d.ts +18 -0
  13. package/dist/declarations/src/actors/logic.d.ts +105 -0
  14. package/dist/declarations/src/actors/observable.d.ts +72 -27
  15. package/dist/declarations/src/actors/promise.d.ts +133 -48
  16. package/dist/declarations/src/actors/subscription.d.ts +22 -0
  17. package/dist/declarations/src/createActor.d.ts +33 -34
  18. package/dist/declarations/src/createMachine.d.ts +38 -7
  19. package/dist/declarations/src/createMachineFromConfig.d.ts +177 -0
  20. package/dist/declarations/src/graph/graph.d.ts +6 -4
  21. package/dist/declarations/src/graph/shortestPaths.d.ts +2 -2
  22. package/dist/declarations/src/graph/simplePaths.d.ts +2 -2
  23. package/dist/declarations/src/index.d.ts +13 -9
  24. package/dist/declarations/src/inspection.d.ts +84 -30
  25. package/dist/declarations/src/mapState.d.ts +4 -2
  26. package/dist/declarations/src/schema.types.d.ts +90 -0
  27. package/dist/declarations/src/serialize.d.ts +50 -0
  28. package/dist/declarations/src/setup.d.ts +396 -136
  29. package/dist/declarations/src/spawn.d.ts +7 -32
  30. package/dist/declarations/src/stateUtils.d.ts +22 -19
  31. package/dist/declarations/src/system.d.ts +8 -7
  32. package/dist/declarations/src/transition.d.ts +8 -5
  33. package/dist/declarations/src/transitionActions.d.ts +4 -0
  34. package/dist/declarations/src/types.d.ts +494 -429
  35. package/dist/declarations/src/types.v6.d.ts +423 -0
  36. package/dist/declarations/src/utils.d.ts +5 -3
  37. package/dist/index-219cb621.development.cjs.js +4476 -0
  38. package/dist/index-2f2fbd9b.development.esm.js +4421 -0
  39. package/dist/index-559ceab3.cjs.js +4437 -0
  40. package/dist/index-8828376f.esm.js +4382 -0
  41. package/dist/xstate-actors.cjs.js +12 -838
  42. package/dist/xstate-actors.cjs.mjs +10 -5
  43. package/dist/xstate-actors.development.cjs.js +12 -838
  44. package/dist/xstate-actors.development.cjs.mjs +10 -5
  45. package/dist/xstate-actors.development.esm.js +1 -836
  46. package/dist/xstate-actors.esm.js +1 -836
  47. package/dist/xstate-actors.umd.min.js +1 -1
  48. package/dist/xstate-actors.umd.min.js.map +1 -1
  49. package/dist/xstate-graph.cjs.js +18 -29
  50. package/dist/xstate-graph.development.cjs.js +18 -29
  51. package/dist/xstate-graph.development.esm.js +15 -26
  52. package/dist/xstate-graph.esm.js +15 -26
  53. package/dist/xstate-graph.umd.min.js +1 -1
  54. package/dist/xstate-graph.umd.min.js.map +1 -1
  55. package/dist/xstate.cjs.js +1477 -122
  56. package/dist/xstate.cjs.mjs +19 -22
  57. package/dist/xstate.development.cjs.js +1477 -122
  58. package/dist/xstate.development.cjs.mjs +19 -22
  59. package/dist/xstate.development.esm.js +1442 -86
  60. package/dist/xstate.esm.js +1442 -86
  61. package/dist/xstate.umd.min.js +1 -1
  62. package/dist/xstate.umd.min.js.map +1 -1
  63. package/package.json +3 -47
  64. package/dist/StateMachine-23c204bb.development.esm.js +0 -566
  65. package/dist/StateMachine-67a0f463.development.cjs.js +0 -569
  66. package/dist/StateMachine-94d215e3.cjs.js +0 -563
  67. package/dist/StateMachine-d1d80308.esm.js +0 -560
  68. package/dist/assign-43b1b558.development.esm.js +0 -133
  69. package/dist/assign-54b312bc.esm.js +0 -127
  70. package/dist/assign-b5bc78f7.cjs.js +0 -129
  71. package/dist/assign-f8f66278.development.cjs.js +0 -135
  72. package/dist/declarations/src/actions/assign.d.ts +0 -45
  73. package/dist/declarations/src/actions/cancel.d.ts +0 -39
  74. package/dist/declarations/src/actions/emit.d.ts +0 -44
  75. package/dist/declarations/src/actions/enqueueActions.d.ts +0 -57
  76. package/dist/declarations/src/actions/log.d.ts +0 -16
  77. package/dist/declarations/src/actions/raise.d.ts +0 -21
  78. package/dist/declarations/src/actions/send.d.ts +0 -42
  79. package/dist/declarations/src/actions/spawnChild.d.ts +0 -34
  80. package/dist/declarations/src/actions/stopChild.d.ts +0 -19
  81. package/dist/declarations/src/actors/transition.d.ts +0 -143
  82. package/dist/declarations/src/dev/index.d.ts +0 -14
  83. package/dist/declarations/src/guards.d.ts +0 -128
  84. package/dist/log-9b02c355.esm.js +0 -401
  85. package/dist/log-c94995c7.cjs.js +0 -409
  86. package/dist/log-d9f3f459.development.cjs.js +0 -437
  87. package/dist/log-db444cad.development.esm.js +0 -429
  88. package/dist/raise-235108c6.esm.js +0 -2762
  89. package/dist/raise-45f11c00.development.esm.js +0 -2824
  90. package/dist/raise-c445379d.cjs.js +0 -2817
  91. package/dist/raise-eca73993.development.cjs.js +0 -2879
  92. package/dist/xstate-actions.cjs.d.mts +0 -2
  93. package/dist/xstate-actions.cjs.d.ts +0 -2
  94. package/dist/xstate-actions.cjs.js +0 -23
  95. package/dist/xstate-actions.cjs.mjs +0 -14
  96. package/dist/xstate-actions.development.cjs.js +0 -23
  97. package/dist/xstate-actions.development.cjs.mjs +0 -14
  98. package/dist/xstate-actions.development.esm.js +0 -4
  99. package/dist/xstate-actions.esm.js +0 -4
  100. package/dist/xstate-actions.umd.min.js +0 -2
  101. package/dist/xstate-actions.umd.min.js.map +0 -1
  102. package/dist/xstate-dev.cjs.d.mts +0 -2
  103. package/dist/xstate-dev.cjs.d.ts +0 -2
  104. package/dist/xstate-dev.cjs.js +0 -48
  105. package/dist/xstate-dev.cjs.mjs +0 -5
  106. package/dist/xstate-dev.development.cjs.js +0 -51
  107. package/dist/xstate-dev.development.cjs.mjs +0 -5
  108. package/dist/xstate-dev.development.esm.js +0 -45
  109. package/dist/xstate-dev.esm.js +0 -42
  110. package/dist/xstate-dev.umd.min.js +0 -2
  111. package/dist/xstate-dev.umd.min.js.map +0 -1
  112. package/dist/xstate-guards.cjs.d.mts +0 -2
  113. package/dist/xstate-guards.cjs.d.ts +0 -2
  114. package/dist/xstate-guards.cjs.js +0 -14
  115. package/dist/xstate-guards.cjs.mjs +0 -7
  116. package/dist/xstate-guards.development.cjs.js +0 -14
  117. package/dist/xstate-guards.development.cjs.mjs +0 -7
  118. package/dist/xstate-guards.development.esm.js +0 -2
  119. package/dist/xstate-guards.esm.js +0 -2
  120. package/dist/xstate-guards.umd.min.js +0 -2
  121. package/dist/xstate-guards.umd.min.js.map +0 -1
@@ -2,12 +2,8 @@
2
2
 
3
3
  Object.defineProperty(exports, '__esModule', { value: true });
4
4
 
5
- var dist_xstateActors = require('./xstate-actors.development.cjs.js');
6
- var dist_xstateGuards = require('./raise-eca73993.development.cjs.js');
7
- var StateMachine = require('./StateMachine-67a0f463.development.cjs.js');
8
- var assign = require('./assign-f8f66278.development.cjs.js');
9
- var log = require('./log-d9f3f459.development.cjs.js');
10
- require('./xstate-dev.development.cjs.js');
5
+ var dist_xstateActors = require('./index-219cb621.development.cjs.js');
6
+ var StateMachine = require('./StateMachine-da872dde.development.cjs.js');
11
7
 
12
8
  /**
13
9
  * Asserts that the given event object is of the specified type or types. Throws
@@ -33,8 +29,8 @@ require('./xstate-dev.development.cjs.js');
33
29
  * ```
34
30
  */
35
31
  function assertEvent(event, type) {
36
- const types = dist_xstateGuards.toArray(type);
37
- const matches = types.some(descriptor => dist_xstateGuards.matchesEventDescriptor(event.type, descriptor));
32
+ const types = dist_xstateActors.toArray(type);
33
+ const matches = types.some(descriptor => dist_xstateActors.matchesEventDescriptor(event.type, descriptor));
38
34
  if (!matches) {
39
35
  const typesText = types.length === 1 ? `type matching "${types[0]}"` : `one of types matching "${types.join('", "')}"`;
40
36
  throw new Error(`Expected event ${JSON.stringify(event)} to have ${typesText}`);
@@ -83,8 +79,1063 @@ function assertEvent(event, type) {
83
79
  * @param options DEPRECATED: use `setup({ ... })` or `machine.provide({ ... })`
84
80
  * to provide machine implementations instead.
85
81
  */
86
- function createMachine(config, implementations) {
87
- return new StateMachine.StateMachine(config, implementations);
82
+ // Overload 1: With schemas.context — context type inferred from schema
83
+
84
+ // Overload 2: Without schemas.context — context type inferred from config.context
85
+
86
+ // Implementation
87
+ function createMachine(config) {
88
+ return new StateMachine.StateMachine(config);
89
+ }
90
+ function createStateConfig(config) {
91
+ return config;
92
+ }
93
+
94
+ function delayToMs(delay) {
95
+ const parsedDelay = dist_xstateActors.parseDelayToMilliseconds(delay);
96
+ if (parsedDelay !== undefined) return parsedDelay;
97
+ return typeof delay === 'string' ? parseFloat(delay) || 0 : delay;
98
+ }
99
+
100
+ /**
101
+ * Isolated executable-content block. Errors in nested actions stop this block
102
+ * but do not propagate to the surrounding action list. Used to model SCXML's
103
+ * separate <onentry>/<onexit> blocks: each is its own block per spec.
104
+ */
105
+
106
+ function isUnserializableMarker(value) {
107
+ return !!value && typeof value === 'object' && '$unserializable' in value && typeof value.$unserializable === 'string';
108
+ }
109
+ function assertNoUnresolvedMarkers(value, path = '$') {
110
+ if (isUnserializableMarker(value)) {
111
+ if (value.$unserializable === 'actor' && path.endsWith('.src')) {
112
+ return;
113
+ }
114
+ throw new Error(`Unresolved ${value.$unserializable} at ${path}`);
115
+ }
116
+ if (!value || typeof value !== 'object') {
117
+ return;
118
+ }
119
+ if (Array.isArray(value)) {
120
+ value.forEach((item, index) => assertNoUnresolvedMarkers(item, `${path}[${index}]`));
121
+ return;
122
+ }
123
+ for (const key of Object.keys(value)) {
124
+ const child = value[key];
125
+ const isImplementationMarker = path === '$' && (key === 'actions' || key === 'guards' || key === 'actorSources' || key === 'delays' || key === 'schemas');
126
+ if (isImplementationMarker) {
127
+ continue;
128
+ }
129
+ assertNoUnresolvedMarkers(child, `${path}.${key}`);
130
+ }
131
+ }
132
+ function assertRootImplementationMarkers(json, implementations) {
133
+ for (const kind of ['actions', 'guards', 'actorSources', 'delays']) {
134
+ const map = json[kind];
135
+ if (!map) {
136
+ continue;
137
+ }
138
+ for (const key of Object.keys(map)) {
139
+ const value = map[key];
140
+ if (!isUnserializableMarker(value)) {
141
+ continue;
142
+ }
143
+ if (!implementations[kind]?.[key]) {
144
+ throw new Error(`Missing ${kind}.${key}`);
145
+ }
146
+ }
147
+ }
148
+ }
149
+ function extractSerializableDelays(delays) {
150
+ const result = {};
151
+ if (!delays) {
152
+ return result;
153
+ }
154
+ for (const key of Object.keys(delays)) {
155
+ const value = delays[key];
156
+ if (typeof value === 'number') {
157
+ result[key] = value;
158
+ }
159
+ }
160
+ return result;
161
+ }
162
+ function mergeImplementations(json, implementations) {
163
+ return {
164
+ actions: implementations.actions ?? {},
165
+ guards: implementations.guards ?? {},
166
+ actorSources: implementations.actorSources ?? {},
167
+ delays: {
168
+ ...extractSerializableDelays(json.delays),
169
+ ...(implementations.delays ?? {})
170
+ }
171
+ };
172
+ }
173
+ let _scxmlSessionId = 'session_' + Math.random().toString(36).slice(2);
174
+ let _scxmlMachineName = '';
175
+
176
+ /** Evaluates an SCXML expression with context variables available via `with`. */
177
+ function evaluateExpr(context, expr, event, self) {
178
+ const fnBody = `
179
+ with (context) {
180
+ return (${expr});
181
+ }
182
+ `.trim();
183
+ // eslint-disable-next-line @typescript-eslint/no-implied-eval
184
+ const fn = new Function('context', '_event', '_sessionid', '_name', '_ioprocessors', 'In', fnBody);
185
+ const In = stateId => {
186
+ if (!self) return false;
187
+ try {
188
+ const snap = self.getSnapshot?.();
189
+ if (snap?._nodes) {
190
+ const sanitized = stateId.replace(/\./g, '$');
191
+ return snap._nodes.some(node => node.id === sanitized || node.id.endsWith('.' + sanitized));
192
+ }
193
+ } catch {
194
+ // ignore
195
+ }
196
+ return false;
197
+ };
198
+ const SCXML_ORIGIN = '#_scxml_session';
199
+ const SCXML_ORIGIN_TYPE = 'http://www.w3.org/TR/scxml/#SCXMLEventProcessor';
200
+ const isExternal = event && event._scxmlExternal;
201
+ const isInitEvent = event && event.type === '@xstate.init';
202
+ // Per SCXML spec, _event has these fields. Fields that don't apply to a
203
+ // particular event are present with value `undefined` (so `'name' in _event`
204
+ // is true but `typeof _event.name === 'undefined'` for unset fields).
205
+ // For xstate.done.* events, _event.data is the `output` payload (matches
206
+ // SCXML's done event semantics where data is the donedata).
207
+ const isDoneEvent = event && typeof event.type === 'string' && event.type.startsWith('xstate.done.');
208
+ const explicitType = event && event._scxmlEventType;
209
+ const scxmlEvent = event && !isInitEvent ? {
210
+ name: event.type,
211
+ type: explicitType || (isExternal ? 'external' : 'internal'),
212
+ sendid: event._scxmlSendId,
213
+ origin: isExternal ? SCXML_ORIGIN : undefined,
214
+ origintype: isExternal ? SCXML_ORIGIN_TYPE : undefined,
215
+ invokeid: event._scxmlInvokeId,
216
+ data: isDoneEvent ? event.output : event._scxmlEventData !== undefined ? event._scxmlEventData : event
217
+ } : undefined;
218
+ const result = fn(context, scxmlEvent, _scxmlSessionId, _scxmlMachineName, {
219
+ scxml: {
220
+ location: `#_scxml_${_scxmlSessionId}`
221
+ }
222
+ }, In);
223
+ return result;
224
+ }
225
+
226
+ /** Executes an SCXML script block and returns updated context values. */
227
+ function executeScript(context, code) {
228
+ // Create a proxy to track which properties are modified
229
+ const updates = {};
230
+ const contextKeys = Object.keys(context);
231
+
232
+ // Build variable declarations and reassignment capture
233
+ const varDeclarations = contextKeys.map(k => `let ${k} = context.${k};`).join('\n');
234
+ const captureUpdates = contextKeys.map(k => `updates.${k} = ${k};`).join('\n');
235
+ const fnBody = `
236
+ ${varDeclarations}
237
+ ${code}
238
+ ${captureUpdates}
239
+ return updates;
240
+ `;
241
+ // eslint-disable-next-line @typescript-eslint/no-implied-eval
242
+ const fn = new Function('context', 'updates', fnBody);
243
+ return fn(context, updates);
244
+ }
245
+ function createMachineFromConfig(json, implementations = {}) {
246
+ assertRootImplementationMarkers(json, implementations);
247
+ assertNoUnresolvedMarkers(json);
248
+ const resolvedImplementations = mergeImplementations(json, implementations);
249
+
250
+ // Pending transition actions: set by .to functions, consumed by entry functions.
251
+ // This bridges SCXML's exit→transition→entry action ordering with XState's
252
+ // .to function receiving pre-exit context.
253
+ // Map keyed by target state ID so parallel transitions don't overwrite each other.
254
+ const pendingTransitionActionsMap = {};
255
+
256
+ // Ordered queue of ALL transition actions (targeted + targetless) for parallel
257
+ // context sharing. In SCXML, all transition actions execute sequentially in
258
+ // document order with a shared evolving data model.
259
+ const allTransitionActions = [];
260
+ // Pre-transition context saved when a targetless .to executes. Used by entry
261
+ // functions to re-execute all transition actions from scratch when parallel
262
+ // targetless transitions coexist with targeted transitions.
263
+ let contextBeforeTargetless = null;
264
+ // Platform errors collected during transition selection (e.g., failing
265
+ // <transition cond>). Drained by the next state's entry into the internal
266
+ // event queue so they're processed before any external events.
267
+ const pendingPlatformErrors = [];
268
+ function getMissingGuardMessage(type, guards) {
269
+ return `Guard '${type}' is not implemented in machine '${json.id ?? '(machine)'}'. Available guards: ${Object.keys(guards).map(key => `'${key}'`).join(', ') || '(none)'}.`;
270
+ }
271
+ function resolveGuardConfig(guard) {
272
+ if (!guard) {
273
+ return undefined;
274
+ }
275
+ return args => {
276
+ const guardImpl = args.guards?.[guard.type];
277
+ if (!guardImpl) {
278
+ throw new Error(getMissingGuardMessage(guard.type, args.guards ?? {}));
279
+ }
280
+ return guardImpl(args, guard.params);
281
+ };
282
+ }
283
+ function resolveRouteConfig(route) {
284
+ if (!route || typeof route === 'function') {
285
+ return route;
286
+ }
287
+ const {
288
+ guard,
289
+ ...routeConfig
290
+ } = route;
291
+ if (!guard) {
292
+ return routeConfig;
293
+ }
294
+ const resolvedGuard = resolveGuardConfig({
295
+ type: guard
296
+ });
297
+ return args => resolvedGuard(args) ? routeConfig : undefined;
298
+ }
299
+ function iterNode(node, nodeKey) {
300
+ const originalEntryActions = node.entry;
301
+ const stateId = node.id || nodeKey;
302
+
303
+ // Wrap entry to first execute any pending transition actions, then normal entry.
304
+ // This ensures SCXML execution order: exit → transition_actions → entry_actions
305
+ // because pending transition actions are set by .to (before exit) but executed
306
+ // in entry (after exit), thus seeing post-exit context.
307
+ const entryFn = (x, enq) => {
308
+ // Drain any platform errors queued during transition selection (e.g.,
309
+ // failing <transition cond="..."> evaluations). These must be raised
310
+ // internally so they're processed before subsequent external events.
311
+ while (pendingPlatformErrors.length) {
312
+ const err = pendingPlatformErrors.shift();
313
+ enq.raise({
314
+ type: 'error.execution',
315
+ _scxmlEventType: 'platform',
316
+ _scxmlEventData: err
317
+ });
318
+ }
319
+ let context;
320
+
321
+ // If targetless transitions were interleaved with targeted transitions
322
+ // (parallel state), re-execute ALL transition actions from the original
323
+ // pre-transition context. This overrides any .to-produced context with
324
+ // the correct SCXML document-order sequential execution.
325
+ // Only trigger when BOTH targeted (pending in map) and targetless fired
326
+ // in the same microstep — prevents stale data from previous events.
327
+ if (contextBeforeTargetless && allTransitionActions.length > 0 && Object.keys(pendingTransitionActionsMap).length > 0) {
328
+ let ctx = contextBeforeTargetless;
329
+ for (const actions of allTransitionActions) {
330
+ const mergedX = {
331
+ ...x,
332
+ context: ctx
333
+ };
334
+ const result = executeActions(actions, mergedX, enq);
335
+ if (result.context) {
336
+ ctx = result.context;
337
+ }
338
+ }
339
+ allTransitionActions.length = 0;
340
+ contextBeforeTargetless = null;
341
+ // Clear per-target map since we re-processed everything
342
+ for (const key of Object.keys(pendingTransitionActionsMap)) {
343
+ delete pendingTransitionActionsMap[key];
344
+ }
345
+ context = ctx;
346
+ } else {
347
+ // Normal path: consume pending transition actions for THIS state.
348
+ // In parallel states, each target gets its own pending actions.
349
+ const transActions = stateId ? pendingTransitionActionsMap[stateId] : undefined;
350
+ if (transActions) {
351
+ delete pendingTransitionActionsMap[stateId];
352
+ const result = executeActions(transActions, x, enq);
353
+ if (result.context) {
354
+ context = result.context;
355
+ }
356
+ }
357
+ // Clear stale targetless data from previous microsteps
358
+ contextBeforeTargetless = null;
359
+ allTransitionActions.length = 0;
360
+ }
361
+
362
+ // Execute normal entry actions
363
+ if (originalEntryActions?.length) {
364
+ const mergedX = context ? {
365
+ ...x,
366
+ context
367
+ } : x;
368
+ const result = executeActions(originalEntryActions, mergedX, enq);
369
+ if (result.context) {
370
+ context = result.context;
371
+ }
372
+ }
373
+ return {
374
+ context
375
+ };
376
+ };
377
+ const nodeConfig = {
378
+ id: node.id,
379
+ initial: node.initial,
380
+ type: node.type,
381
+ history: node.history,
382
+ target: node.target,
383
+ description: node.description,
384
+ tags: node.tags,
385
+ input: node.input,
386
+ timeout: node.timeout,
387
+ states: node.states ? Object.entries(node.states).reduce((acc, [key, value]) => {
388
+ acc[key] = iterNode(value, key);
389
+ return acc;
390
+ }, {}) : undefined,
391
+ on: node.on ? Object.entries(node.on).reduce((acc, [key, value]) => {
392
+ acc[key] = getTransitionConfig(value);
393
+ return acc;
394
+ }, {}) : undefined,
395
+ always: node.always ? getTransitionConfig(node.always) : undefined,
396
+ choice: node.choice ? getTransitionConfig(node.choice) : undefined,
397
+ route: resolveRouteConfig(node.route),
398
+ after: node.after ? Object.entries(node.after).reduce((acc, [key, value]) => {
399
+ acc[key] = getTransitionConfig(value);
400
+ return acc;
401
+ }, {}) : undefined,
402
+ onTimeout: node.onTimeout ? getTransitionConfig(node.onTimeout) : undefined,
403
+ entry: entryFn,
404
+ exit: node.exit ? iterActions(node.exit) : undefined,
405
+ invoke: node.invoke ? iterInvokeConfigs(node.invoke) : undefined,
406
+ meta: node.meta,
407
+ output: node._scxmlDonedata ? makeDonedataOutput(node._scxmlDonedata) : node.output
408
+ };
409
+ return nodeConfig;
410
+ }
411
+ function makeDonedataOutput(donedata) {
412
+ return ({
413
+ context,
414
+ event,
415
+ self
416
+ }) => {
417
+ try {
418
+ if (donedata.params && donedata.params.length) {
419
+ const out = {};
420
+ for (const param of donedata.params) {
421
+ out[param.name] = evaluateExpr(context, param.expr, event, self);
422
+ }
423
+ return out;
424
+ }
425
+ if (donedata.contentExpr !== undefined) {
426
+ return evaluateExpr(context, donedata.contentExpr, event, self);
427
+ }
428
+ if (donedata.contentText !== undefined) {
429
+ // Try parsing as a JS expression (number/object/array literals);
430
+ // fall back to the raw string.
431
+ try {
432
+ return evaluateExpr(context, donedata.contentText, event, self);
433
+ } catch {
434
+ return donedata.contentText;
435
+ }
436
+ }
437
+ } catch (err) {
438
+ // Per SCXML, donedata expression errors raise error.execution and
439
+ // result in undefined event.data. Queue for the next entry to drain.
440
+ const message = err instanceof Error ? err.message : typeof err === 'string' ? err : 'unknown error';
441
+ pendingPlatformErrors.push({
442
+ tagname: 'donedata',
443
+ message,
444
+ line: NaN,
445
+ column: NaN,
446
+ reason: message
447
+ });
448
+ }
449
+ return undefined;
450
+ };
451
+ }
452
+ function iterInvokeConfigs(invokes) {
453
+ const invokeArray = Array.isArray(invokes) ? invokes : [invokes];
454
+ return invokeArray.map(inv => {
455
+ const extInv = inv;
456
+ // Create child machine from nested SCXML JSON
457
+ let src;
458
+ if (extInv._nestedMachineJSON) {
459
+ src = createMachineFromConfig(extInv._nestedMachineJSON, resolvedImplementations);
460
+ } else if (isUnserializableMarker(inv.src)) {
461
+ src = inv.src.id ? resolvedImplementations.actorSources[inv.src.id] : undefined;
462
+ if (!src) {
463
+ throw new Error(`Missing actorSources.${inv.src.id ?? ''}`);
464
+ }
465
+ } else {
466
+ src = inv.src;
467
+ }
468
+ return {
469
+ src,
470
+ id: inv.id,
471
+ registryKey: inv.registryKey,
472
+ input: inv.input,
473
+ onDone: inv.onDone ? getTransitionConfig(inv.onDone) : undefined,
474
+ onError: inv.onError ? getTransitionConfig(inv.onError) : undefined,
475
+ onSnapshot: inv.onSnapshot ? getTransitionConfig(inv.onSnapshot) : undefined,
476
+ timeout: inv.timeout,
477
+ onTimeout: inv.onTimeout ? getTransitionConfig(inv.onTimeout) : undefined
478
+ };
479
+ });
480
+ }
481
+
482
+ /**
483
+ * Raise an SCXML error.execution platform event onto the internal queue. Per
484
+ * spec, error.execution is type='platform' and _event.data contains error
485
+ * info. The surrounding block of executable content stops.
486
+ */
487
+ function raiseErrorExecution(state, tagname, err) {
488
+ const message = err instanceof Error ? err.message : typeof err === 'string' ? err : 'unknown error';
489
+ state.enq.raise({
490
+ type: 'error.execution',
491
+ _scxmlEventType: 'platform',
492
+ _scxmlEventData: {
493
+ tagname,
494
+ message,
495
+ line: NaN,
496
+ column: NaN,
497
+ reason: message
498
+ }
499
+ });
500
+ state.errored = true;
501
+ }
502
+ /** Execute an array of SCXML action JSON descriptors with context and enqueue. */
503
+ function executeActions(actions, x, enq, parentState) {
504
+ const state = parentState ?? {
505
+ enq,
506
+ errored: false
507
+ };
508
+ let context;
509
+ for (const action of actions) {
510
+ if (state.errored) break;
511
+ if (isBuiltInActionJSON(action)) {
512
+ switch (action.type) {
513
+ case '@xstate.raise':
514
+ {
515
+ // Tag as external if it has a delay (from <send>, not <raise>).
516
+ // Attach _scxmlSendId so _event.sendid can be read in expressions.
517
+ const isExternal = action.delay !== undefined;
518
+ const event = isExternal || action.id !== undefined ? {
519
+ ...action.event,
520
+ ...(isExternal ? {
521
+ _scxmlExternal: true
522
+ } : {}),
523
+ ...(action.id !== undefined ? {
524
+ _scxmlSendId: action.id
525
+ } : {})
526
+ } : action.event;
527
+ enq.raise(event, {
528
+ id: action.id,
529
+ delay: action.delay
530
+ });
531
+ break;
532
+ }
533
+ case '@xstate.cancel':
534
+ enq.cancel(action.id);
535
+ break;
536
+ case '@xstate.log':
537
+ enq.log(...action.args);
538
+ break;
539
+ case '@xstate.emit':
540
+ enq.emit(action.event);
541
+ break;
542
+ case '@xstate.assign':
543
+ context ??= {};
544
+ Object.assign(context, action.context);
545
+ break;
546
+ default:
547
+ throw new Error(`Unknown built-in action: ${action.type}`);
548
+ }
549
+ } else if (action.type === 'scxml.assign') {
550
+ const scxmlAction = action;
551
+ const mergedContext = {
552
+ ...x.context,
553
+ ...context
554
+ };
555
+ let value;
556
+ try {
557
+ value = evaluateExpr(mergedContext, scxmlAction.expr, x.event, x.self);
558
+ } catch (err) {
559
+ raiseErrorExecution(state, 'assign', err);
560
+ continue;
561
+ }
562
+ // Per SCXML, assigning to a location that doesn't exist on the
563
+ // datamodel is an error. Allow setting an own property via context;
564
+ // detect deep paths (a.b.c) which we don't support.
565
+ if (scxmlAction.location.includes('.')) {
566
+ raiseErrorExecution(state, 'assign', new Error(`Invalid assign location: ${scxmlAction.location}`));
567
+ continue;
568
+ }
569
+ context ??= {};
570
+ context[scxmlAction.location] = value;
571
+ } else if (action.type === 'scxml.raise') {
572
+ const scxmlAction = action;
573
+ const mergedContext = {
574
+ ...x.context,
575
+ ...context
576
+ };
577
+ let eventType;
578
+ let eventData;
579
+ let target;
580
+ let delay;
581
+ try {
582
+ eventType = scxmlAction.eventexpr ? evaluateExpr(mergedContext, scxmlAction.eventexpr, x.event, x.self) : scxmlAction.event || 'unknown';
583
+ eventData = {
584
+ type: eventType
585
+ };
586
+ if (scxmlAction.params) {
587
+ for (const param of scxmlAction.params) {
588
+ eventData[param.name] = evaluateExpr(mergedContext, param.expr, x.event, x.self);
589
+ }
590
+ }
591
+ target = scxmlAction.targetexpr ? evaluateExpr(mergedContext, scxmlAction.targetexpr, x.event, x.self) : scxmlAction.target;
592
+ const isInternalTarget = target === '#_internal';
593
+ delay = scxmlAction.delayexpr ? delayToMs(evaluateExpr(mergedContext, scxmlAction.delayexpr, x.event, x.self)) : isInternalTarget ? undefined : scxmlAction.delay;
594
+ } catch (err) {
595
+ raiseErrorExecution(state, 'send', err);
596
+ continue;
597
+ }
598
+ const isInternalTarget = target === '#_internal';
599
+ const isParentTarget = target === '#_parent';
600
+
601
+ // Validate target. SCXML targets must be '#_internal', '#_parent',
602
+ // or '#_<id>'. A bare string without the '#_' prefix is invalid and
603
+ // raises error.execution.
604
+ if (typeof target === 'string' && target.length > 0 && !target.startsWith('#_')) {
605
+ raiseErrorExecution(state, 'send', new Error(`Invalid send target: ${target}`));
606
+ continue;
607
+ }
608
+ // Attach send id so _event.sendid can be read in expressions.
609
+ if (scxmlAction.id !== undefined) {
610
+ eventData._scxmlSendId = scxmlAction.id;
611
+ }
612
+ // Resolve target at runtime: parent, child, or self
613
+ if (isParentTarget && x.parent) {
614
+ // Send to parent via sendTo; pass delay if present
615
+ enq.sendTo(x.parent, eventData, delay !== undefined ? {
616
+ delay
617
+ } : undefined);
618
+ } else if (typeof target === 'string' && target.startsWith('#_') && !isParentTarget && !isInternalTarget) {
619
+ // #_<invokeId> → try to send to child actor, fall back to self-raise
620
+ const childId = target.slice(2); // strip '#_'
621
+ const childRef = x.children?.[childId];
622
+ if (childRef) {
623
+ enq.sendTo(childRef, eventData);
624
+ } else {
625
+ // Not a known child (e.g. #_scxml_sessionid) → self-raise
626
+ if (delay !== undefined) {
627
+ eventData._scxmlExternal = true;
628
+ }
629
+ enq.raise(eventData, {
630
+ id: scxmlAction.id,
631
+ delay
632
+ });
633
+ }
634
+ } else {
635
+ // Self-send or no special target: raise as external event
636
+ if (delay !== undefined) {
637
+ eventData._scxmlExternal = true;
638
+ }
639
+ enq.raise(eventData, {
640
+ id: scxmlAction.id,
641
+ delay
642
+ });
643
+ }
644
+ } else if (action.type === 'scxml.cancel') {
645
+ const scxmlAction = action;
646
+ const mergedContext = {
647
+ ...x.context,
648
+ ...context
649
+ };
650
+ try {
651
+ const sendId = evaluateExpr(mergedContext, scxmlAction.sendidexpr, x.event, x.self);
652
+ if (sendId) {
653
+ enq.cancel(sendId);
654
+ }
655
+ } catch {
656
+ // ignore evaluation errors
657
+ }
658
+ } else if (action.type === 'scxml.script') {
659
+ const scxmlAction = action;
660
+ const mergedContext = {
661
+ ...x.context,
662
+ ...context
663
+ };
664
+ try {
665
+ const updatedContext = executeScript(mergedContext, scxmlAction.code);
666
+ context ??= {};
667
+ Object.assign(context, updatedContext);
668
+ } catch (err) {
669
+ raiseErrorExecution(state, 'script', err);
670
+ }
671
+ } else if (action.type === 'scxml.foreach') {
672
+ const scxmlAction = action;
673
+ const mergedContext = {
674
+ ...x.context,
675
+ ...context
676
+ };
677
+ // SCXML: `item` (and `index` if present) must be valid datamodel
678
+ // locations — i.e. legal identifiers. Reject things like 'continue'
679
+ // (string literal) or '7' (number).
680
+ const isLegalIdentifier = s => /^[$_a-zA-Z][$_a-zA-Z0-9]*$/.test(s);
681
+ if (!isLegalIdentifier(scxmlAction.item) || scxmlAction.index && !isLegalIdentifier(scxmlAction.index)) {
682
+ raiseErrorExecution(state, 'foreach', new Error('foreach item/index is not a legal location'));
683
+ continue;
684
+ }
685
+ let arr;
686
+ try {
687
+ arr = evaluateExpr(mergedContext, scxmlAction.array, x.event, x.self);
688
+ } catch (err) {
689
+ raiseErrorExecution(state, 'foreach', err);
690
+ continue;
691
+ }
692
+ if (!Array.isArray(arr)) {
693
+ raiseErrorExecution(state, 'foreach', new Error('foreach array is not iterable'));
694
+ continue;
695
+ }
696
+ context ??= {};
697
+ for (let i = 0; i < arr.length; i++) {
698
+ context[scxmlAction.item] = arr[i];
699
+ if (scxmlAction.index) {
700
+ context[scxmlAction.index] = i;
701
+ }
702
+ const iterX = {
703
+ ...x,
704
+ context: {
705
+ ...x.context,
706
+ ...context
707
+ }
708
+ };
709
+ const iterResult = executeActions(scxmlAction.actions, iterX, enq, state);
710
+ if (iterResult.context) {
711
+ Object.assign(context, iterResult.context);
712
+ }
713
+ if (state.errored) break;
714
+ }
715
+ } else if (action.type === 'scxml.block') {
716
+ const scxmlAction = action;
717
+ const blockX = {
718
+ ...x,
719
+ context: {
720
+ ...x.context,
721
+ ...context
722
+ }
723
+ };
724
+ // Block has its own ExecState — errors don't propagate to parent.
725
+ const blockResult = executeActions(scxmlAction.actions, blockX, enq);
726
+ if (blockResult.context) {
727
+ context ??= {};
728
+ for (const key of Object.keys(blockResult.context)) {
729
+ if (blockResult.context[key] !== x.context[key]) {
730
+ context[key] = blockResult.context[key];
731
+ }
732
+ }
733
+ }
734
+ } else if (action.type === 'scxml.if') {
735
+ const scxmlAction = action;
736
+ const mergedContext = {
737
+ ...x.context,
738
+ ...context
739
+ };
740
+ for (const branch of scxmlAction.branches) {
741
+ let condResult;
742
+ if (branch.cond) {
743
+ try {
744
+ condResult = !!evaluateExpr(mergedContext, branch.cond, x.event, x.self);
745
+ } catch (err) {
746
+ raiseErrorExecution(state, 'if', err);
747
+ condResult = false;
748
+ }
749
+ } else {
750
+ condResult = true;
751
+ }
752
+ if (condResult) {
753
+ if (branch.actions.length) {
754
+ const branchX = {
755
+ ...x,
756
+ context: mergedContext
757
+ };
758
+ const branchResult = executeActions(branch.actions, branchX, enq, state);
759
+ if (branchResult.context) {
760
+ context ??= {};
761
+ for (const key of Object.keys(branchResult.context)) {
762
+ if (branchResult.context[key] !== x.context[key]) {
763
+ context[key] = branchResult.context[key];
764
+ }
765
+ }
766
+ }
767
+ }
768
+ break;
769
+ }
770
+ }
771
+ } else {
772
+ enq(x.actions[action.type], action.params);
773
+ }
774
+ }
775
+ return {
776
+ context: context ? {
777
+ ...x.context,
778
+ ...context
779
+ } : undefined,
780
+ errored: state.errored
781
+ };
782
+ }
783
+ function iterActions(actions) {
784
+ return (x, enq) => executeActions(actions, x, enq);
785
+ }
786
+ function getTransitionConfig(transition) {
787
+ const transitions = Array.isArray(transition) ? transition : [transition];
788
+
789
+ // Return an array of transition configs. Each SCXML transition becomes
790
+ // a separate XState transition with its own guard and optional .to.
791
+ // This ensures guards are evaluated by XState's evaluateCandidate (once,
792
+ // with pre-exit context) and NOT re-evaluated in computeEntrySet.
793
+ return transitions.map(t => {
794
+ const target = Array.isArray(t.target) ? t.target[0] : t.target;
795
+ const targetConfig = t.target;
796
+ const guard = resolveGuardConfig(t.guard);
797
+
798
+ // No guard and no actions: simple static config
799
+ if (!guard && !t.actions?.length) {
800
+ return {
801
+ target: targetConfig,
802
+ description: t.description,
803
+ reenter: t.reenter,
804
+ meta: t.meta,
805
+ input: t.input
806
+ };
807
+ }
808
+
809
+ // Guard but no actions: static config with guard
810
+ if (guard && !t.actions?.length) {
811
+ return {
812
+ target: targetConfig,
813
+ guard,
814
+ description: t.description,
815
+ reenter: t.reenter,
816
+ meta: t.meta,
817
+ input: t.input
818
+ };
819
+ }
820
+
821
+ // Targetless transitions: execute actions directly in .to AND track for
822
+ // parallel re-execution. For non-parallel, .to result is used directly.
823
+ // For parallel (entries exist), first entry re-executes all in document order.
824
+ if (!target) {
825
+ return {
826
+ guard,
827
+ description: t.description,
828
+ reenter: t.reenter,
829
+ meta: t.meta,
830
+ input: t.input,
831
+ to: (x, enq) => {
832
+ if (t.actions?.length) {
833
+ // Track for parallel re-execution (dedup by reference)
834
+ if (!allTransitionActions.includes(t.actions)) {
835
+ allTransitionActions.push(t.actions);
836
+ }
837
+ // Save pre-transition context for parallel override
838
+ contextBeforeTargetless ??= x.context;
839
+ // Execute immediately (fallback for non-parallel case)
840
+ const result = executeActions(t.actions, x, enq);
841
+ if (result.context) {
842
+ return {
843
+ context: result.context
844
+ };
845
+ }
846
+ }
847
+ return {};
848
+ }
849
+ };
850
+ }
851
+
852
+ // Has target + actions: use guard (for XState evaluation) + .to (for pending actions).
853
+ // The .to function does NOT re-check the guard — XState's evaluateCandidate
854
+ // already validated it. The .to just stores actions for entry to execute.
855
+ // Map by target state ID so parallel transitions each get their own actions.
856
+ return {
857
+ guard,
858
+ description: t.description,
859
+ reenter: t.reenter,
860
+ meta: t.meta,
861
+ input: t.input,
862
+ to: (_x, _enq) => {
863
+ if (t.actions?.length) {
864
+ const targetId = target.replace(/^#/, '');
865
+ pendingTransitionActionsMap[targetId] = t.actions;
866
+ // Track for parallel re-execution (dedup by reference)
867
+ if (!allTransitionActions.includes(t.actions)) {
868
+ allTransitionActions.push(t.actions);
869
+ }
870
+ }
871
+ return {
872
+ target: targetConfig,
873
+ reenter: t.reenter
874
+ };
875
+ }
876
+ };
877
+ });
878
+ }
879
+ const rootNodeConfig = iterNode(json);
880
+ const contextConfig = json.context ? {
881
+ context: json.context
882
+ } : {};
883
+ _scxmlMachineName = json.id || '';
884
+ _scxmlSessionId = 'session_' + Math.random().toString(36).slice(2);
885
+ const machine = createMachine({
886
+ ...rootNodeConfig,
887
+ ...contextConfig,
888
+ version: json.version
889
+ });
890
+
891
+ // Register SCXML guard implementations
892
+ const providedGuards = {
893
+ 'scxml.cond': ({
894
+ context,
895
+ event,
896
+ self
897
+ }, params) => {
898
+ const expr = params?.expr;
899
+ if (!expr) return true;
900
+ try {
901
+ return !!evaluateExpr(context, expr, event, self);
902
+ } catch (err) {
903
+ // Per SCXML spec, a cond that fails to evaluate is treated as false
904
+ // AND raises error.execution. We can't enqueue from a guard, so
905
+ // queue it for the next entry to drain.
906
+ const message = err instanceof Error ? err.message : typeof err === 'string' ? err : 'unknown error';
907
+ pendingPlatformErrors.push({
908
+ tagname: 'cond',
909
+ message,
910
+ line: NaN,
911
+ column: NaN,
912
+ reason: message
913
+ });
914
+ return false;
915
+ }
916
+ },
917
+ 'xstate.stateIn': (args, params) => {
918
+ const stateId = params?.stateId;
919
+ if (!stateId) return false;
920
+ const normalizedId = stateId.replace(/^#/, '');
921
+ const snapshot = args._snapshot;
922
+ if (snapshot?._nodes) {
923
+ return snapshot._nodes.some(node => node.id === normalizedId);
924
+ }
925
+ return false;
926
+ },
927
+ 'xstate.not': (args, params) => {
928
+ const inner = params?.guard;
929
+ const innerImpl = inner && args.guards?.[inner.type];
930
+ if (!innerImpl) {
931
+ throw new Error(`Guard '${inner?.type}' referenced by 'xstate.not' is not implemented.`);
932
+ }
933
+ return !innerImpl(args, inner.params);
934
+ }
935
+ };
936
+ const provided = machine.provide({
937
+ actions: resolvedImplementations.actions,
938
+ actorSources: resolvedImplementations.actorSources,
939
+ guards: {
940
+ ...providedGuards,
941
+ ...resolvedImplementations.guards
942
+ },
943
+ delays: resolvedImplementations.delays
944
+ });
945
+
946
+ // Keep the original JSON so `serializeMachine(machine)`
947
+ // round-trip losslessly.
948
+ provided._json = json;
949
+ return provided;
950
+ }
951
+ function isBuiltInActionJSON(action) {
952
+ return action.type.startsWith('@xstate.');
953
+ }
954
+
955
+ /**
956
+ * Machine-definition serialization.
957
+ *
958
+ * `machineConfigToJSON` converts a machine config into a JSON-safe structure
959
+ * (the `MachineJSON` shape accepted by `createMachineFromConfig`). The boundary
960
+ * between serializable structure and runtime implementations is explicit:
961
+ * functions are represented as code expressions, while actor logic, runtime
962
+ * schemas, and other non-code runtime values are replaced with an `{
963
+ * "$unserializable": <kind> }` marker rather than silently dropped.
964
+ *
965
+ * A machine definition is fully portable iff its JSON contains no
966
+ * `$unserializable` markers; reviving a definition that has markers requires
967
+ * re-providing those implementations (e.g. via `machine.provide(...)` or the
968
+ * `actions`/`guards`/`actorSources` maps on `createMachineFromConfig`
969
+ * revival).
970
+ */
971
+
972
+ /**
973
+ * Returns the JSON-serializable definition of a machine.
974
+ *
975
+ * Inline functions are represented as `{ "@type": "code", lang: "ts", expr }`.
976
+ * Actor logic and runtime schemas appear as `{ "$unserializable": ... }`
977
+ * markers. A machine created via `createMachineFromConfig` returns its original
978
+ * JSON config (lossless round-trip):
979
+ *
980
+ * ```ts
981
+ * import { serializeMachine, createMachineFromConfig } from 'xstate';
982
+ *
983
+ * const json = serializeMachine(machine);
984
+ * const revived = createMachineFromConfig(
985
+ * JSON.parse(JSON.stringify(json))
986
+ * );
987
+ * ```
988
+ */
989
+ function serializeMachine(machine) {
990
+ return machine._json ?? machineConfigToJSON(machine.config);
991
+ }
992
+ function marker(kind, id) {
993
+ const m = {
994
+ $unserializable: kind
995
+ };
996
+ if (id) {
997
+ m.id = id;
998
+ }
999
+ return m;
1000
+ }
1001
+
1002
+ // eslint-disable-next-line @typescript-eslint/no-unsafe-function-type
1003
+ function codeExpression(fn) {
1004
+ return {
1005
+ '@type': 'code',
1006
+ lang: 'ts',
1007
+ expr: fn.toString()
1008
+ };
1009
+ }
1010
+ function isActorLogic(value) {
1011
+ return !!value && typeof value === 'object' && typeof value.transition === 'function' && typeof value.getInitialSnapshot === 'function';
1012
+ }
1013
+ function isRuntimeSchema(value) {
1014
+ return !!value && typeof value === 'object' && '~standard' in value;
1015
+ }
1016
+
1017
+ /** JSON-safe deep copy of a plain value; functions become code expressions. */
1018
+ function valueToJSON(value) {
1019
+ if (typeof value === 'function') {
1020
+ return codeExpression(value);
1021
+ }
1022
+ if (value === null || typeof value !== 'object') {
1023
+ return typeof value === 'bigint' || typeof value === 'symbol' ? marker('value') : value;
1024
+ }
1025
+ if (isActorLogic(value)) {
1026
+ return marker('actor', value.id);
1027
+ }
1028
+ if (isRuntimeSchema(value)) {
1029
+ return marker('schema');
1030
+ }
1031
+ if (Array.isArray(value)) {
1032
+ return value.map(valueToJSON);
1033
+ }
1034
+ if (value.constructor !== Object && value.constructor !== undefined) {
1035
+ // Class instances (actor logic, schemas, dates, ...) are not portable.
1036
+ return marker('value');
1037
+ }
1038
+ const result = {};
1039
+ for (const key of Object.keys(value)) {
1040
+ const v = value[key];
1041
+ if (v !== undefined) {
1042
+ result[key] = valueToJSON(v);
1043
+ }
1044
+ }
1045
+ return result;
1046
+ }
1047
+ function invokeToJSON(invoke) {
1048
+ if (Array.isArray(invoke)) {
1049
+ return invoke.map(invokeToJSON);
1050
+ }
1051
+ const def = invoke;
1052
+ const result = {};
1053
+ for (const key of Object.keys(def)) {
1054
+ const value = def[key];
1055
+ if (value === undefined) {
1056
+ continue;
1057
+ }
1058
+ result[key] = key === 'src' && typeof value !== 'string' ?
1059
+ // Actor logic keeps its dedicated marker kind so revival knows the
1060
+ // contract is an actor, not a plain function.
1061
+ marker('actor', value.id) : valueToJSON(value);
1062
+ }
1063
+ return result;
1064
+ }
1065
+ function implementationsToJSON(map, kind) {
1066
+ if (!map) {
1067
+ return undefined;
1068
+ }
1069
+ // Keys are preserved — they are the contract a revived machine must
1070
+ // fulfill via provide() — while values become markers (or stay, for
1071
+ // JSON-safe values like numeric delays).
1072
+ const result = {};
1073
+ for (const key of Object.keys(map)) {
1074
+ const value = map[key];
1075
+ if (kind === 'schema') {
1076
+ result[key] = marker('schema', key);
1077
+ } else if (typeof value === 'function') {
1078
+ result[key] = codeExpression(value);
1079
+ } else if (kind === 'actor' && value && typeof value === 'object') {
1080
+ result[key] = marker('actor', key);
1081
+ } else {
1082
+ result[key] = valueToJSON(value);
1083
+ }
1084
+ }
1085
+ return result;
1086
+ }
1087
+ function stateNodeConfigToJSON(config) {
1088
+ const result = {};
1089
+ for (const key of Object.keys(config)) {
1090
+ if (key === 'states' || key === 'invoke') {
1091
+ continue;
1092
+ }
1093
+ const value = config[key];
1094
+ if (value !== undefined) {
1095
+ result[key] = valueToJSON(value);
1096
+ }
1097
+ }
1098
+ if (config.invoke !== undefined) {
1099
+ result.invoke = invokeToJSON(config.invoke);
1100
+ }
1101
+ if (config.states) {
1102
+ const states = {};
1103
+ for (const key of Object.keys(config.states)) {
1104
+ states[key] = stateNodeConfigToJSON(config.states[key]);
1105
+ }
1106
+ result.states = states;
1107
+ }
1108
+ return result;
1109
+ }
1110
+
1111
+ /**
1112
+ * Converts a machine config (as passed to `createMachine`) to its JSON-safe
1113
+ * definition. See module docs for the `$unserializable` marker contract.
1114
+ */
1115
+ function machineConfigToJSON(config) {
1116
+ const result = stateNodeConfigToJSON(config);
1117
+ if (config.internalEvents !== undefined) {
1118
+ result.internalEvents = valueToJSON(config.internalEvents);
1119
+ }
1120
+ if (config.schemas) {
1121
+ const schemas = {};
1122
+ for (const key of Object.keys(config.schemas)) {
1123
+ const value = config.schemas[key];
1124
+ if (value && typeof value === 'object' && !('~standard' in value)) {
1125
+ // Map-form schemas (events/emitted): preserve event-type keys.
1126
+ schemas[key] = implementationsToJSON(value, 'schema');
1127
+ } else {
1128
+ schemas[key] = marker('schema', key);
1129
+ }
1130
+ }
1131
+ result.schemas = schemas;
1132
+ }
1133
+ for (const key of ['actions', 'guards', 'actorSources', 'delays']) {
1134
+ if (config[key]) {
1135
+ result[key] = implementationsToJSON(config[key], key === 'actorSources' ? 'actor' : 'function');
1136
+ }
1137
+ }
1138
+ return result;
88
1139
  }
89
1140
 
90
1141
  /**
@@ -116,7 +1167,7 @@ function mapState(snapshot, mapper) {
116
1167
  return mapper;
117
1168
  };
118
1169
  const visited = new Set();
119
- for (const atomicNode of snapshot._nodes.filter(dist_xstateGuards.isAtomicStateNode)) {
1170
+ for (const atomicNode of snapshot._nodes.filter(dist_xstateActors.isAtomicStateNode)) {
120
1171
  let current = atomicNode;
121
1172
  while (current && !visited.has(current)) {
122
1173
  visited.add(current);
@@ -133,11 +1184,245 @@ function mapState(snapshot, mapper) {
133
1184
  return results;
134
1185
  }
135
1186
 
1187
+ /** The Standard Schema interface. */
1188
+
1189
+ /** A type-only Standard Schema produced by {@link types}. */
1190
+
1191
+ /**
1192
+ * Declares schema types for inference only — no runtime validation.
1193
+ *
1194
+ * Use in a machine's `schemas` when you want TypeScript types without pulling
1195
+ * in a schema library like Zod. The returned value is a valid Standard Schema
1196
+ * whose validation is the identity function, so it carries types but never
1197
+ * rejects input.
1198
+ *
1199
+ * @example
1200
+ *
1201
+ * ```ts
1202
+ * import { createMachine, types } from 'xstate';
1203
+ *
1204
+ * const machine = createMachine({
1205
+ * schemas: {
1206
+ * context: types<{ count: number }>(),
1207
+ * events: {
1208
+ * inc: types<{ by: number }>(),
1209
+ * reset: types<{}>()
1210
+ * }
1211
+ * },
1212
+ * context: { count: 0 }
1213
+ * // ...
1214
+ * });
1215
+ * ```
1216
+ */
1217
+ function types() {
1218
+ return {
1219
+ '~standard': {
1220
+ version: 1,
1221
+ vendor: 'xstate.types',
1222
+ validate: value => ({
1223
+ value: value
1224
+ })
1225
+ }
1226
+ };
1227
+ }
1228
+
1229
+ /** Returns true if the value is a type-only schema created by {@link types}. */
1230
+ function isTypeSchema(value) {
1231
+ return !!value && typeof value === 'object' && '~standard' in value && value['~standard'].vendor === 'xstate.types';
1232
+ }
1233
+
1234
+ // eslint-disable-next-line @typescript-eslint/no-namespace
1235
+
1236
+ /** State schema with optional schemas.input and nested states */
1237
+
1238
+ /** Extracts input type from a state schema */
1239
+
1240
+ /**
1241
+ * Converts SetupStateSchema to StateSchema with input types included. This
1242
+ * allows getInputs() to be strongly typed.
1243
+ */
1244
+
1245
+ /** Converts the root setup states config to a StateSchema. */
1246
+
1247
+ /** Machine config with typed state input */
1248
+
1249
+ /** States config type that provides typed input for known states */
1250
+
1251
+ /** State node config that recursively applies typed input for nested states */
1252
+
1253
+ /** Initial transition with typed input based on target state */
1254
+
1255
+ /** Return type of setup() */
1256
+
1257
+ /**
1258
+ * Sets up a state machine with state input schemas and other configuration.
1259
+ *
1260
+ * @example
1261
+ *
1262
+ * ```ts
1263
+ * import { setup } from 'xstate';
1264
+ * import z from 'zod';
1265
+ *
1266
+ * const s = setup({
1267
+ * states: {
1268
+ * loading: {
1269
+ * schemas: {
1270
+ * input: z.object({
1271
+ * userId: z.string()
1272
+ * })
1273
+ * }
1274
+ * }
1275
+ * }
1276
+ * });
1277
+ *
1278
+ * const machine = s.createMachine({
1279
+ * initial: {
1280
+ * target: 'loading',
1281
+ * input: { userId: '123' }
1282
+ * },
1283
+ * states: {
1284
+ * loading: {
1285
+ * entry: ({ input }) => {
1286
+ * console.log(input.userId);
1287
+ * }
1288
+ * }
1289
+ * }
1290
+ * });
1291
+ * ```
1292
+ */
1293
+
1294
+ function setup(config = {}) {
1295
+ const {
1296
+ states = {},
1297
+ schemas,
1298
+ actions,
1299
+ actorSources,
1300
+ guards,
1301
+ delays
1302
+ } = config;
1303
+ return {
1304
+ extend(extension) {
1305
+ return setup(mergeSetupConfigs(config, extension));
1306
+ },
1307
+ createMachine(machineConfig) {
1308
+ const configSchemas = machineConfig.schemas;
1309
+ const mergedSchemas = mergeSchemas(configSchemas, schemas);
1310
+ const mergedActions = mergeMaps(actions, machineConfig.actions);
1311
+ const mergedActorSources = mergeMaps(actorSources, machineConfig.actorSources);
1312
+ const mergedGuards = mergeMaps(guards, machineConfig.guards);
1313
+ const mergedDelays = mergeMaps(delays, machineConfig.delays);
1314
+ return new StateMachine.StateMachine({
1315
+ ...machineConfig,
1316
+ ...(mergedSchemas ? {
1317
+ schemas: mergedSchemas
1318
+ } : undefined),
1319
+ ...(mergedActions ? {
1320
+ actions: mergedActions
1321
+ } : undefined),
1322
+ ...(mergedActorSources ? {
1323
+ actorSources: mergedActorSources
1324
+ } : undefined),
1325
+ ...(mergedGuards ? {
1326
+ guards: mergedGuards
1327
+ } : undefined),
1328
+ ...(mergedDelays ? {
1329
+ delays: mergedDelays
1330
+ } : undefined)
1331
+ });
1332
+ },
1333
+ createStateConfig(stateConfig) {
1334
+ return stateConfig;
1335
+ },
1336
+ states
1337
+ };
1338
+ }
1339
+ function createSystem(_config = {}) {
1340
+ const runtimeRef = {};
1341
+ const pendingObservers = [];
1342
+ const flushObservers = () => {
1343
+ const runtime = runtimeRef.current;
1344
+ if (!runtime) {
1345
+ return;
1346
+ }
1347
+ for (const entry of pendingObservers) {
1348
+ if (entry.active && !entry.subscription) {
1349
+ entry.subscription = runtime.inspect(entry.observer);
1350
+ }
1351
+ }
1352
+ };
1353
+ return {
1354
+ createActor(logic, options) {
1355
+ const actor = dist_xstateActors.createActor(logic, {
1356
+ ...options,
1357
+ _systemRef: runtimeRef
1358
+ });
1359
+ flushObservers();
1360
+ return actor;
1361
+ },
1362
+ get(key) {
1363
+ return runtimeRef.current?.get(key);
1364
+ },
1365
+ getAll() {
1366
+ return runtimeRef.current?.getAll() ?? {};
1367
+ },
1368
+ inspect(observer) {
1369
+ const runtime = runtimeRef.current;
1370
+ if (runtime) {
1371
+ return runtime.inspect(observer);
1372
+ }
1373
+ const entry = {
1374
+ observer: observer,
1375
+ active: true
1376
+ };
1377
+ pendingObservers.push(entry);
1378
+ return {
1379
+ unsubscribe() {
1380
+ entry.active = false;
1381
+ entry.subscription?.unsubscribe();
1382
+ }
1383
+ };
1384
+ },
1385
+ setup(config) {
1386
+ return config ? setup(config) : setup();
1387
+ }
1388
+ };
1389
+ }
1390
+ function mergeMaps(left, right) {
1391
+ return left || right ? {
1392
+ ...left,
1393
+ ...right
1394
+ } : undefined;
1395
+ }
1396
+ function mergeSchemas(left, right) {
1397
+ if (!left && !right) {
1398
+ return undefined;
1399
+ }
1400
+ return {
1401
+ ...left,
1402
+ ...right,
1403
+ events: mergeMaps(left?.events, right?.events),
1404
+ emitted: mergeMaps(left?.emitted, right?.emitted),
1405
+ children: mergeMaps(left?.children, right?.children)
1406
+ };
1407
+ }
1408
+ function mergeSetupConfigs(base, extension) {
1409
+ return {
1410
+ ...base,
1411
+ ...extension,
1412
+ schemas: mergeSchemas(base.schemas, extension.schemas),
1413
+ states: mergeMaps(base.states, extension.states),
1414
+ actions: mergeMaps(base.actions, extension.actions),
1415
+ actorSources: mergeMaps(base.actorSources, extension.actorSources),
1416
+ guards: mergeMaps(base.guards, extension.guards),
1417
+ delays: mergeMaps(base.delays, extension.delays)
1418
+ };
1419
+ }
1420
+
136
1421
  /** @internal */
137
1422
  function createInertActorScope(actorLogic) {
138
- const self = dist_xstateGuards.createActor(actorLogic);
1423
+ const self = dist_xstateActors.createActor(actorLogic);
139
1424
  const inertActorScope = {
140
- self,
1425
+ self: self,
141
1426
  defer: () => {},
142
1427
  id: '',
143
1428
  logger: () => {},
@@ -153,7 +1438,7 @@ function createInertActorScope(actorLogic) {
153
1438
  /** @deprecated Use `initialTransition(…)` instead. */
154
1439
  function getInitialSnapshot(actorLogic, ...[input]) {
155
1440
  const actorScope = createInertActorScope(actorLogic);
156
- return actorLogic.getInitialSnapshot(actorScope, input);
1441
+ return actorLogic.initialTransition(input, actorScope)[0];
157
1442
  }
158
1443
 
159
1444
  /**
@@ -192,64 +1477,8 @@ function getInitialSnapshot(actorLogic, ...[input]) {
192
1477
  function getNextSnapshot(actorLogic, snapshot, event) {
193
1478
  const inertActorScope = createInertActorScope(actorLogic);
194
1479
  inertActorScope.self._snapshot = snapshot;
195
- return actorLogic.transition(snapshot, event, inertActorScope);
196
- }
197
-
198
- // at the moment we allow extra actors - ones that are not specified by `children`
199
- // this could be reconsidered in the future
200
-
201
- // used to keep only StateSchema relevant keys
202
- // this helps with type serialization as it makes the inferred type much shorter when dealing with huge configs
203
-
204
- // Extract { [invokeId]: src } mappings from a machine config's invoke entries.
205
- // This allows createMachine to infer TChildrenMap from the invoke config
206
- // when types.children is not explicitly provided.
207
-
208
- function setup({
209
- schemas,
210
- actors,
211
- actions,
212
- guards,
213
- delays
214
- }) {
215
- return {
216
- assign: assign.assign,
217
- sendTo: log.sendTo,
218
- raise: dist_xstateGuards.raise,
219
- log: log.log,
220
- cancel: dist_xstateGuards.cancel,
221
- stopChild: dist_xstateGuards.stopChild,
222
- enqueueActions: log.enqueueActions,
223
- emit: log.emit,
224
- spawnChild: dist_xstateGuards.spawnChild,
225
- createStateConfig: config => config,
226
- createAction: fn => fn,
227
- createMachine: config => createMachine({
228
- ...config,
229
- schemas
230
- }, {
231
- actors,
232
- actions,
233
- guards,
234
- delays
235
- }),
236
- extend: extended => setup({
237
- schemas,
238
- actors,
239
- actions: {
240
- ...actions,
241
- ...extended.actions
242
- },
243
- guards: {
244
- ...guards,
245
- ...extended.guards
246
- },
247
- delays: {
248
- ...delays,
249
- ...extended.delays
250
- }
251
- })
252
- };
1480
+ const transitionResult = actorLogic.transition(snapshot, event, inertActorScope);
1481
+ return Array.isArray(transitionResult) ? transitionResult[0] : transitionResult;
253
1482
  }
254
1483
 
255
1484
  // eslint-disable-next-line @typescript-eslint/no-unsafe-declaration-merging
@@ -314,6 +1543,11 @@ class SimulatedClock {
314
1543
  }
315
1544
  }
316
1545
  this._flushing = false;
1546
+ // Check if new timeouts were added during the last iteration
1547
+ if (this._flushingInvalidated) {
1548
+ this._flushingInvalidated = false;
1549
+ this.flushTimeouts();
1550
+ }
317
1551
  }
318
1552
  increment(ms) {
319
1553
  this._now += ms;
@@ -355,6 +1589,138 @@ function toPromise(actor) {
355
1589
  });
356
1590
  }
357
1591
 
1592
+ // this is needed to make JSDoc `@link` work properly
1593
+
1594
+ /**
1595
+ * @remarks
1596
+ * `T | unknown` reduces to `unknown` and that can be problematic when it comes
1597
+ * to contextual typing. It especially is a problem when the union has a
1598
+ * function member, like here:
1599
+ *
1600
+ * ```ts
1601
+ * declare function test(
1602
+ * cbOrVal: ((arg: number) => unknown) | unknown
1603
+ * ): void;
1604
+ * test((arg) => {}); // oops, implicit any
1605
+ * ```
1606
+ *
1607
+ * This type can be used to avoid this problem. This union represents the same
1608
+ * value space as `unknown`.
1609
+ */
1610
+
1611
+ // https://github.com/microsoft/TypeScript/issues/23182#issuecomment-379091887
1612
+
1613
+ // @TODO: we can't use native `NoInfer` as we need those:
1614
+ // https://github.com/microsoft/TypeScript/pull/61092
1615
+ // https://github.com/microsoft/TypeScript/pull/61077
1616
+ // but even with those fixes native NoInfer still doesn't work - further issues have to be reproduced and fixed
1617
+
1618
+ /** @deprecated Use the built-in `NoInfer` type instead */
1619
+
1620
+ /** The full definition of an event, with a string `type`. */
1621
+
1622
+ /**
1623
+ * The string or object representing the state value relative to the parent
1624
+ * state node.
1625
+ *
1626
+ * @remarks
1627
+ * - For a child atomic state node, this is a string, e.g., `"pending"`.
1628
+ * - For complex state nodes, this is an object, e.g., `{ success:
1629
+ * "someChildState" }`.
1630
+ */
1631
+
1632
+ // Accept any StateNode instance regardless of generic parameters
1633
+ // Using a union type to handle variance issues with machine.resolveState
1634
+
1635
+ let SpecialTargets = /*#__PURE__*/function (SpecialTargets) {
1636
+ SpecialTargets["Internal"] = "#_internal";
1637
+ return SpecialTargets;
1638
+ }({});
1639
+
1640
+ /**
1641
+ * A pending effect (delayed event/transition that has not fired yet) captured
1642
+ * in a persisted snapshot — a serialized built-in action descriptor plus its
1643
+ * runtime progress, with enough information to restore it under any strategy.
1644
+ */
1645
+
1646
+ /**
1647
+ * How pending effects (timers) from a persisted snapshot are restored on
1648
+ * `actor.start()`:
1649
+ *
1650
+ * - `'resume'` (default) — the clock was "frozen" while persisted: a 5-minute
1651
+ * timer persisted with 1 minute elapsed fires after 4 more minutes.
1652
+ * - `'restart'` — timers start over with their full delay.
1653
+ * - `'absolute'` — timers honor the original wall-clock expiry (`startedAt +
1654
+ * delay`); already-expired timers fire immediately.
1655
+ * - A custom function receiving the pending effect and returning the remaining
1656
+ * delay in ms.
1657
+ */
1658
+
1659
+ /** @deprecated Use `AnyActor` instead. */
1660
+
1661
+ // Based on RxJS types
1662
+
1663
+ /**
1664
+ * A consumer-facing actor handle.
1665
+ *
1666
+ * `ActorRef` describes the contract a consumer needs: which events can be sent
1667
+ * to the actor, which snapshot it publishes for observation, and which emitted
1668
+ * events can be listened to. It intentionally does not expose lifecycle control
1669
+ * or runtime internals. A concrete `Actor` satisfies this interface, so APIs
1670
+ * should accept `ActorRef` whenever they only need to send events, read
1671
+ * snapshots, or listen to emitted events.
1672
+ */
1673
+
1674
+ /**
1675
+ * Runtime-only actor capabilities.
1676
+ *
1677
+ * These members are needed by the interpreter, scheduler, inspection, and child
1678
+ * management code. Public consumer APIs should prefer `ActorRef` unless they
1679
+ * genuinely need lifecycle control such as starting, stopping, or accessing
1680
+ * system-owned runtime state.
1681
+ */
1682
+
1683
+ /**
1684
+ * A concrete actor instance type.
1685
+ *
1686
+ * `ActorInstance` combines the consumer `ActorRef` contract with runtime
1687
+ * lifecycle capabilities. Values returned by `createActor(...)` and
1688
+ * `spawn(...)` naturally satisfy narrower `ActorRef` contracts.
1689
+ */
1690
+
1691
+ /**
1692
+ * The actor's own full self handle.
1693
+ *
1694
+ * Internals and action/guard implementations receive this shape because `self`
1695
+ * can participate in runtime-owned behavior while still being usable wherever
1696
+ * an `ActorRef` is expected.
1697
+ */
1698
+
1699
+ // TODO: in v6, this should only accept AnyActorLogic, like ActorRefFromLogic
1700
+
1701
+ /** The concrete actor instance type produced from actor logic. */
1702
+
1703
+ // TODO: in v6, this should only accept AnyActorLogic, like ActorRefFromLogic
1704
+
1705
+ /**
1706
+ * Represents logic which can be used by an actor.
1707
+ *
1708
+ * @template TSnapshot - The type of the snapshot.
1709
+ * @template TEvent - The type of the event object.
1710
+ * @template TInput - The type of the input.
1711
+ * @template TSystem - The type of the actor system.
1712
+ */
1713
+
1714
+ // Actors that don't have literal string IDs — these are the only ones
1715
+ // that should appear in the index signature fallback, since actors with
1716
+ // literal IDs are already covered by ToConcreteChildren.
1717
+
1718
+ /** Maps state IDs to their input types based on the StateSchema. */
1719
+
1720
+ /** @deprecated */
1721
+
1722
+ /** Mappers for subscribeTo - maps lifecycle events to machine events */
1723
+
358
1724
  /**
359
1725
  * Given actor `logic`, a `snapshot`, and an `event`, returns a tuple of the
360
1726
  * `nextSnapshot` and `actions` to execute.
@@ -362,13 +1728,9 @@ function toPromise(actor) {
362
1728
  * This is a pure function that does not execute `actions`.
363
1729
  */
364
1730
  function transition(logic, snapshot, event) {
365
- const executableActions = [];
366
1731
  const actorScope = createInertActorScope(logic);
367
- actorScope.actionExecutor = action => {
368
- executableActions.push(action);
369
- };
370
- const nextSnapshot = logic.transition(snapshot, event, actorScope);
371
- return [nextSnapshot, executableActions];
1732
+ const [nextSnapshot, effects] = logic.transition(snapshot, event, actorScope);
1733
+ return [nextSnapshot, effects];
372
1734
  }
373
1735
 
374
1736
  /**
@@ -379,12 +1741,8 @@ function transition(logic, snapshot, event) {
379
1741
  * This is a pure function that does not execute `actions`.
380
1742
  */
381
1743
  function initialTransition(logic, ...[input]) {
382
- const executableActions = [];
383
1744
  const actorScope = createInertActorScope(logic);
384
- actorScope.actionExecutor = action => {
385
- executableActions.push(action);
386
- };
387
- const nextSnapshot = logic.getInitialSnapshot(actorScope, input);
1745
+ const [nextSnapshot, executableActions] = logic.initialTransition(input, actorScope);
388
1746
  return [nextSnapshot, executableActions];
389
1747
  }
390
1748
 
@@ -398,7 +1756,7 @@ function getMicrosteps(machine, snapshot, event) {
398
1756
  const actorScope = createInertActorScope(machine);
399
1757
  const {
400
1758
  microsteps
401
- } = dist_xstateGuards.macrostep(snapshot, event, actorScope, []);
1759
+ } = dist_xstateActors.macrostep(snapshot, event, actorScope, []);
402
1760
  return microsteps;
403
1761
  }
404
1762
 
@@ -411,13 +1769,13 @@ function getMicrosteps(machine, snapshot, event) {
411
1769
  */
412
1770
  function getInitialMicrosteps(machine, ...[input]) {
413
1771
  const actorScope = createInertActorScope(machine);
414
- const initEvent = dist_xstateGuards.createInitEvent(input);
1772
+ const initEvent = dist_xstateActors.createInitEvent(input);
415
1773
  const internalQueue = [];
416
- const preInitialSnapshot = machine._getPreInitialState(actorScope, initEvent, internalQueue);
417
- const first = dist_xstateGuards.initialMicrostep(machine.root, preInitialSnapshot, actorScope, initEvent, internalQueue);
1774
+ const preInitialSnapshot = machine._getPreInitialState(actorScope, initEvent);
1775
+ const first = dist_xstateActors.initialMicrostep(machine.root, preInitialSnapshot, actorScope, initEvent, internalQueue);
418
1776
  const {
419
1777
  microsteps
420
- } = dist_xstateGuards.macrostep(first[0], initEvent, actorScope, internalQueue);
1778
+ } = dist_xstateActors.macrostep(first[0], initEvent, actorScope, internalQueue);
421
1779
  return [first, ...microsteps];
422
1780
  }
423
1781
 
@@ -447,7 +1805,7 @@ function getInitialMicrosteps(machine, ...[input]) {
447
1805
  */
448
1806
  function getNextTransitions(state) {
449
1807
  const potentialTransitions = [];
450
- const atomicStates = state._nodes.filter(dist_xstateGuards.isAtomicStateNode);
1808
+ const atomicStates = state._nodes.filter(dist_xstateActors.isAtomicStateNode);
451
1809
  const visited = new Set();
452
1810
 
453
1811
  // Collect all transitions from atomic states and their ancestors
@@ -455,7 +1813,7 @@ function getNextTransitions(state) {
455
1813
  for (const stateNode of atomicStates) {
456
1814
  // For each atomic state, process the state itself first, then its ancestors
457
1815
  // This ensures child state transitions come before parent state transitions
458
- for (const s of [stateNode].concat(dist_xstateGuards.getProperAncestors(stateNode, undefined))) {
1816
+ for (const s of [stateNode].concat(dist_xstateActors.getProperAncestors(stateNode, undefined))) {
459
1817
  if (visited.has(s.id)) {
460
1818
  continue;
461
1819
  }
@@ -464,7 +1822,7 @@ function getNextTransitions(state) {
464
1822
  // Get all transitions for each event type
465
1823
  // Include ALL transitions, even if the same event type appears in multiple state nodes
466
1824
  // This is important for guarded transitions - all are "potential" regardless of guard evaluation
467
- for (const [, transitions] of s.transitions) {
1825
+ for (const [, transitions] of s.transitions.entries()) {
468
1826
  potentialTransitions.push(...transitions);
469
1827
  }
470
1828
 
@@ -581,51 +1939,48 @@ function waitFor(actorRef, predicate, options) {
581
1939
  });
582
1940
  }
583
1941
 
1942
+ exports.Actor = dist_xstateActors.Actor;
1943
+ exports.TimeoutError = dist_xstateActors.TimeoutError;
1944
+ exports.__unsafe_getAllOwnEventDescriptors = dist_xstateActors.getAllOwnEventDescriptors;
1945
+ exports.checkStateIn = dist_xstateActors.checkStateIn;
1946
+ exports.createActor = dist_xstateActors.createActor;
1947
+ exports.createAsyncLogic = dist_xstateActors.createAsyncLogic;
1948
+ exports.createCallbackLogic = dist_xstateActors.createCallbackLogic;
584
1949
  exports.createEmptyActor = dist_xstateActors.createEmptyActor;
585
- exports.fromCallback = dist_xstateActors.fromCallback;
586
- exports.fromEventObservable = dist_xstateActors.fromEventObservable;
587
- exports.fromObservable = dist_xstateActors.fromObservable;
588
- exports.fromPromise = dist_xstateActors.fromPromise;
589
- exports.fromTransition = dist_xstateActors.fromTransition;
590
- exports.Actor = dist_xstateGuards.Actor;
591
- exports.__unsafe_getAllOwnEventDescriptors = dist_xstateGuards.getAllOwnEventDescriptors;
592
- exports.and = dist_xstateGuards.and;
593
- exports.cancel = dist_xstateGuards.cancel;
594
- exports.createActor = dist_xstateGuards.createActor;
595
- exports.getStateNodes = dist_xstateGuards.getStateNodes;
596
- exports.interpret = dist_xstateGuards.interpret;
597
- exports.isMachineSnapshot = dist_xstateGuards.isMachineSnapshot;
598
- exports.matchesState = dist_xstateGuards.matchesState;
599
- exports.not = dist_xstateGuards.not;
600
- exports.or = dist_xstateGuards.or;
601
- exports.pathToStateValue = dist_xstateGuards.pathToStateValue;
602
- exports.raise = dist_xstateGuards.raise;
603
- exports.spawnChild = dist_xstateGuards.spawnChild;
604
- exports.stateIn = dist_xstateGuards.stateIn;
605
- exports.stop = dist_xstateGuards.stop;
606
- exports.stopChild = dist_xstateGuards.stopChild;
607
- exports.toObserver = dist_xstateGuards.toObserver;
1950
+ exports.createEventObservableLogic = dist_xstateActors.createEventObservableLogic;
1951
+ exports.createListenerLogic = dist_xstateActors.createListenerLogic;
1952
+ exports.createLogic = dist_xstateActors.createLogic;
1953
+ exports.createObservableLogic = dist_xstateActors.createObservableLogic;
1954
+ exports.createSubscriptionLogic = dist_xstateActors.createSubscriptionLogic;
1955
+ exports.getStateNodes = dist_xstateActors.getStateNodes;
1956
+ exports.isBuiltInExecutableAction = dist_xstateActors.isBuiltInExecutableAction;
1957
+ exports.isMachineSnapshot = dist_xstateActors.isMachineSnapshot;
1958
+ exports.listenerLogic = dist_xstateActors.listenerLogic;
1959
+ exports.matchesState = dist_xstateActors.matchesState;
1960
+ exports.pathToStateValue = dist_xstateActors.pathToStateValue;
1961
+ exports.subscriptionLogic = dist_xstateActors.subscriptionLogic;
1962
+ exports.toObserver = dist_xstateActors.toObserver;
608
1963
  exports.StateMachine = StateMachine.StateMachine;
609
1964
  exports.StateNode = StateMachine.StateNode;
610
- exports.assign = assign.assign;
611
- exports.SpecialTargets = log.SpecialTargets;
612
- exports.emit = log.emit;
613
- exports.enqueueActions = log.enqueueActions;
614
- exports.forwardTo = log.forwardTo;
615
- exports.log = log.log;
616
- exports.sendParent = log.sendParent;
617
- exports.sendTo = log.sendTo;
618
1965
  exports.SimulatedClock = SimulatedClock;
1966
+ exports.SpecialTargets = SpecialTargets;
619
1967
  exports.assertEvent = assertEvent;
620
1968
  exports.createMachine = createMachine;
1969
+ exports.createMachineFromConfig = createMachineFromConfig;
1970
+ exports.createStateConfig = createStateConfig;
1971
+ exports.createSystem = createSystem;
621
1972
  exports.getInitialMicrosteps = getInitialMicrosteps;
622
1973
  exports.getInitialSnapshot = getInitialSnapshot;
623
1974
  exports.getMicrosteps = getMicrosteps;
624
1975
  exports.getNextSnapshot = getNextSnapshot;
625
1976
  exports.getNextTransitions = getNextTransitions;
626
1977
  exports.initialTransition = initialTransition;
1978
+ exports.isTypeSchema = isTypeSchema;
1979
+ exports.machineConfigToJSON = machineConfigToJSON;
627
1980
  exports.mapState = mapState;
1981
+ exports.serializeMachine = serializeMachine;
628
1982
  exports.setup = setup;
629
1983
  exports.toPromise = toPromise;
630
1984
  exports.transition = transition;
1985
+ exports.types = types;
631
1986
  exports.waitFor = waitFor;