xstate 6.0.0-alpha.47 → 6.0.0-alpha.49

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 (84) hide show
  1. package/README.md +30 -1
  2. package/dist/{StateMachine-7046f677.cjs.js → StateMachine-0adb3a70.cjs.js} +15 -12
  3. package/dist/{StateMachine-70c06bdd.development.cjs.js → StateMachine-29450e6d.development.cjs.js} +15 -12
  4. package/dist/{StateMachine-74929087.esm.js → StateMachine-2af31c11.esm.js} +10 -7
  5. package/dist/{StateMachine-ee10f67e.development.esm.js → StateMachine-faf50c5c.development.esm.js} +10 -7
  6. package/dist/{createActor-915ea40c.esm.js → createActor-268165d4.esm.js} +79 -23
  7. package/dist/{createActor-ff132afa.development.esm.js → createActor-88709f74.development.esm.js} +79 -23
  8. package/dist/{createActor-6736cbbe.development.cjs.js → createActor-a1e0dffb.development.cjs.js} +78 -25
  9. package/dist/{createActor-bfe8b6bd.cjs.js → createActor-b4dd05ae.cjs.js} +78 -25
  10. package/dist/declarations/src/createMachineFromConfig.d.ts +5 -77
  11. package/dist/declarations/src/fsm/createFSMActor.d.ts +67 -0
  12. package/dist/declarations/src/fsm/index.d.ts +2 -0
  13. package/dist/declarations/src/fsm.d.ts +5 -4
  14. package/dist/declarations/src/scxml/index.d.ts +1 -0
  15. package/dist/declarations/src/scxml/runtime.d.ts +251 -0
  16. package/dist/declarations/src/scxml/scxml.d.ts +19 -0
  17. package/dist/declarations/src/types.d.ts +1 -0
  18. package/dist/{effectDescriptor-8be60443.esm.js → effectDescriptor-30c9a744.esm.js} +1 -1
  19. package/dist/{effectDescriptor-fbe67d5a.development.esm.js → effectDescriptor-39d22100.development.esm.js} +1 -1
  20. package/dist/{effectDescriptor-3c699328.development.cjs.js → effectDescriptor-7ff6802f.development.cjs.js} +1 -1
  21. package/dist/{effectDescriptor-a7e2d4d1.cjs.js → effectDescriptor-be348e50.cjs.js} +1 -1
  22. package/dist/fsm-7a2e9697.cjs.js +777 -0
  23. package/dist/fsm-b804b3e9.esm.js +775 -0
  24. package/dist/fsm-c1316948.development.cjs.js +777 -0
  25. package/dist/fsm-e18a7cb4.development.esm.js +775 -0
  26. package/dist/types-3c3455f7.esm.js +185 -0
  27. package/dist/types-adda3842.development.esm.js +185 -0
  28. package/dist/types-b3fea5bd.development.cjs.js +189 -0
  29. package/dist/types-fbabaeee.cjs.js +189 -0
  30. package/dist/validation-05f1d517.esm.js +8 -0
  31. package/dist/validation-4561b43c.cjs.js +10 -0
  32. package/dist/validation-e69470ad.development.esm.js +8 -0
  33. package/dist/validation-f2714a35.development.cjs.js +10 -0
  34. package/dist/xstate-actors.cjs.js +934 -9
  35. package/dist/xstate-actors.development.cjs.js +934 -9
  36. package/dist/xstate-actors.development.esm.js +932 -2
  37. package/dist/xstate-actors.esm.js +932 -2
  38. package/dist/xstate-durable.cjs.js +2 -2
  39. package/dist/xstate-durable.development.cjs.js +2 -2
  40. package/dist/xstate-durable.development.esm.js +2 -2
  41. package/dist/xstate-durable.esm.js +2 -2
  42. package/dist/xstate-fsm.cjs.d.mts +2 -0
  43. package/dist/xstate-fsm.cjs.d.ts +2 -0
  44. package/dist/xstate-fsm.cjs.js +409 -0
  45. package/dist/xstate-fsm.cjs.mjs +5 -0
  46. package/dist/xstate-fsm.development.cjs.js +409 -0
  47. package/dist/xstate-fsm.development.cjs.mjs +5 -0
  48. package/dist/xstate-fsm.development.esm.js +403 -0
  49. package/dist/xstate-fsm.esm.js +403 -0
  50. package/dist/xstate-fsm.umd.min.js +2 -0
  51. package/dist/xstate-fsm.umd.min.js.map +1 -0
  52. package/dist/xstate-graph.cjs.js +4 -3
  53. package/dist/xstate-graph.development.cjs.js +4 -3
  54. package/dist/xstate-graph.development.esm.js +4 -3
  55. package/dist/xstate-graph.esm.js +4 -3
  56. package/dist/xstate-graph.umd.min.js +1 -1
  57. package/dist/xstate-graph.umd.min.js.map +1 -1
  58. package/dist/xstate-scxml.cjs.d.mts +2 -0
  59. package/dist/xstate-scxml.cjs.d.ts +2 -0
  60. package/dist/xstate-scxml.cjs.js +2387 -0
  61. package/dist/xstate-scxml.cjs.mjs +3 -0
  62. package/dist/xstate-scxml.development.cjs.js +2387 -0
  63. package/dist/xstate-scxml.development.cjs.mjs +3 -0
  64. package/dist/xstate-scxml.development.esm.js +2383 -0
  65. package/dist/xstate-scxml.esm.js +2383 -0
  66. package/dist/xstate-scxml.umd.min.js +26 -0
  67. package/dist/xstate-scxml.umd.min.js.map +1 -0
  68. package/dist/xstate-validation.cjs.js +1 -1
  69. package/dist/xstate-validation.development.cjs.js +1 -1
  70. package/dist/xstate-validation.development.esm.js +1 -1
  71. package/dist/xstate-validation.esm.js +1 -1
  72. package/dist/xstate.cjs.js +143 -1412
  73. package/dist/xstate.development.cjs.js +143 -1412
  74. package/dist/xstate.development.esm.js +143 -1411
  75. package/dist/xstate.esm.js +143 -1411
  76. package/dist/xstate.umd.min.js +1 -1
  77. package/dist/xstate.umd.min.js.map +1 -1
  78. package/fsm/package.json +8 -0
  79. package/package.json +37 -3
  80. package/scxml/package.json +8 -0
  81. package/dist/index-0f498ef2.development.cjs.js +0 -946
  82. package/dist/index-70d56425.development.esm.js +0 -937
  83. package/dist/index-b051c924.esm.js +0 -937
  84. package/dist/index-b3fe59bc.cjs.js +0 -946
@@ -2,10 +2,13 @@
2
2
 
3
3
  Object.defineProperty(exports, '__esModule', { value: true });
4
4
 
5
- var dist_xstateActors = require('./index-0f498ef2.development.cjs.js');
6
- var createActor = require('./createActor-6736cbbe.development.cjs.js');
7
- var StateMachine = require('./StateMachine-70c06bdd.development.cjs.js');
8
- var effectDescriptor = require('./effectDescriptor-3c699328.development.cjs.js');
5
+ var dist_xstateActors = require('./xstate-actors.development.cjs.js');
6
+ var createActor = require('./createActor-a1e0dffb.development.cjs.js');
7
+ var types$1 = require('./types-b3fea5bd.development.cjs.js');
8
+ var fsm = require('./fsm-c1316948.development.cjs.js');
9
+ var StateMachine = require('./StateMachine-29450e6d.development.cjs.js');
10
+ var effectDescriptor = require('./effectDescriptor-7ff6802f.development.cjs.js');
11
+ require('./validation-f2714a35.development.cjs.js');
9
12
 
10
13
  /**
11
14
  * Asserts that the given event object is of the specified type or types. Throws
@@ -39,453 +42,11 @@ function assertEvent(event, type) {
39
42
  }
40
43
  }
41
44
 
42
- /**
43
- * Creates a state machine (statechart) with the given configuration.
44
- *
45
- * The state machine represents the pure logic of a state machine actor.
46
- *
47
- * @example
48
- *
49
- * ```ts
50
- * import { createMachine } from 'xstate';
51
- *
52
- * const lightMachine = createMachine({
53
- * id: 'light',
54
- * initial: 'green',
55
- * states: {
56
- * green: {
57
- * on: {
58
- * TIMER: { target: 'yellow' }
59
- * }
60
- * },
61
- * yellow: {
62
- * on: {
63
- * TIMER: { target: 'red' }
64
- * }
65
- * },
66
- * red: {
67
- * on: {
68
- * TIMER: { target: 'green' }
69
- * }
70
- * }
71
- * }
72
- * });
73
- *
74
- * const lightActor = createActor(lightMachine);
75
- * lightActor.start();
76
- *
77
- * lightActor.send({ type: 'TIMER' });
78
- * ```
79
- *
80
- * @param config The state machine configuration.
81
- * @param options DEPRECATED: use `setup({ ... })` or `machine.provide({ ... })`
82
- * to provide machine sources instead.
83
- */
84
- // Overload 1: With schemas.context — context type inferred from schema
85
-
86
- // Overload 2: Without schemas.context — context type inferred from config.context
87
-
88
- // Implementation
89
- function createMachine(config) {
90
- return new StateMachine.StateMachine(config);
91
- }
92
- function createStateConfig(config) {
93
- return config;
94
- }
95
-
96
- const emptySources = {
97
- actions: {},
98
- actors: {},
99
- guards: {},
100
- delays: {}
101
- };
102
- const emptyExecutableActions = [];
103
- const emptyRawActions = [];
104
- const builtInActionSet = new Set(Object.values(createActor.builtInActions));
105
- function toArray(value) {
106
- return value === undefined ? [] : Array.isArray(value) ? value : [value];
107
- }
108
- function resolveContext(context, input) {
109
- return typeof context === 'function' ? context({
110
- input
111
- }) : context ?? {};
112
- }
113
- function resolveTransitionContext(context, args) {
114
- return typeof context === 'function' ? context(args) : context;
115
- }
116
- function resolveInput(input, context, event) {
117
- return typeof input === 'function' ? input({
118
- context,
119
- event
120
- }) : input;
121
- }
122
- function mergeContextPatch(context, patch) {
123
- for (const key of Object.keys(patch)) {
124
- if (!Object.prototype.hasOwnProperty.call(context, key) || !Object.is(context[key], patch[key])) {
125
- return {
126
- ...context,
127
- ...patch
128
- };
129
- }
130
- }
131
- return context;
132
- }
133
- function createSnapshot(value, context, input, machine, stateInput) {
134
- return {
135
- status: 'active',
136
- output: undefined,
137
- error: undefined,
138
- value,
139
- context,
140
- input,
141
- children: {},
142
- timers: {},
143
- _nextTimerId: 0,
144
- _stateInput: stateInput,
145
- machine
146
- };
147
- }
148
- function cloneSnapshot(snapshot, value, context, stateInput) {
149
- return {
150
- status: snapshot.status,
151
- output: snapshot.output,
152
- error: snapshot.error,
153
- value,
154
- context,
155
- input: snapshot.input,
156
- children: snapshot.children,
157
- timers: snapshot.timers,
158
- _nextTimerId: snapshot._nextTimerId,
159
- // Carried across state changes: dropping these would let a later spawn
160
- // reuse the id of a still-running child.
161
- _nextActorIds: snapshot._nextActorIds,
162
- _stateInput: stateInput,
163
- machine: snapshot.machine
164
- };
165
- }
166
- function stopSnapshot(snapshot) {
167
- return {
168
- status: 'stopped',
169
- output: undefined,
170
- error: undefined,
171
- value: snapshot.value,
172
- context: snapshot.context,
173
- input: undefined,
174
- children: snapshot.children,
175
- timers: snapshot.timers,
176
- _nextTimerId: snapshot._nextTimerId,
177
- _nextActorIds: snapshot._nextActorIds,
178
- _stateInput: snapshot._stateInput,
179
- machine: snapshot.machine
180
- };
181
- }
182
- function assertNoStringTransitions(config) {
183
- for (const [stateKey, stateConfig] of Object.entries(config.states)) {
184
- for (const [eventType, transitionConfig] of Object.entries(stateConfig.on ?? {})) {
185
- for (const transition of toArray(transitionConfig)) {
186
- if (typeof transition === 'string') {
187
- const target = transition;
188
- throw new Error(`Invalid transition for "${stateKey}.${eventType}": use { target: "${target}" } instead of a string target.`);
189
- }
190
- }
191
- }
192
- }
193
- }
194
- function resolveSimpleEnqueuedActions(rawActions) {
195
- const executableActions = [];
196
- for (const action of rawActions) {
197
- if (!action || typeof action !== 'object' || !('action' in action) || typeof action.action !== 'function' || builtInActionSet.has(action.action) || '_special' in action.action) {
198
- return undefined;
199
- }
200
- executableActions.push({
201
- kind: 'action',
202
- type: action.action.name || '(anonymous)',
203
- params: undefined,
204
- args: action.args,
205
- action: action.action,
206
- exec() {
207
- return this.action?.(...this.args);
208
- }
209
- });
210
- }
211
- return executableActions;
212
- }
213
- function createFSM(config) {
214
- const machine = {
215
- id: config.id ?? '(fsm)',
216
- sources: emptySources
217
- };
218
- assertNoStringTransitions(config);
219
- const runActions = (snapshot, event, actorScope, rawActions) => {
220
- if (!rawActions?.length) {
221
- return [snapshot, emptyExecutableActions];
222
- }
223
- const simpleExecutableActions = resolveSimpleEnqueuedActions(rawActions);
224
- if (simpleExecutableActions) {
225
- return [snapshot, simpleExecutableActions];
226
- }
227
- return createActor.resolveActionsWithContext(snapshot, event, actorScope, rawActions);
228
- };
229
- const runStateActions = (snapshot, event, actorScope, actionsConfig, stateInput, internalQueue) => {
230
- if (!actionsConfig) {
231
- return [snapshot, emptyExecutableActions];
232
- }
233
- const actions = [];
234
- const enq = createActor.createTransitionEnqueue(actorScope, actions, internalQueue, true);
235
- let context;
236
- const actionCount = Array.isArray(actionsConfig) ? actionsConfig.length : 1;
237
- for (let i = 0; i < actionCount; i++) {
238
- const action = Array.isArray(actionsConfig) ? actionsConfig[i] : actionsConfig;
239
- const result = action(createActor.withActorScope({
240
- context: context ?? snapshot.context,
241
- event: event,
242
- input: stateInput,
243
- value: snapshot.value,
244
- children: snapshot.children
245
- }, actorScope), enq);
246
- if (result?.context !== undefined) {
247
- const currentContext = context ?? snapshot.context;
248
- const nextContext = mergeContextPatch(currentContext, result.context);
249
- if (nextContext !== currentContext) {
250
- context = nextContext;
251
- }
252
- }
253
- }
254
- const nextSnapshot = context !== undefined ? cloneSnapshot(snapshot, snapshot.value, context, snapshot._stateInput) : snapshot;
255
- return runActions(nextSnapshot, event, actorScope, actions);
256
- };
257
- const selectTransition = (snapshot, event, actorScope, internalQueue) => {
258
- const state = config.states[snapshot.value];
259
- const transitionsConfig = state?.on?.[event.type];
260
- if (!transitionsConfig) {
261
- return undefined;
262
- }
263
- const transitionCount = Array.isArray(transitionsConfig) ? transitionsConfig.length : 1;
264
- for (let i = 0; i < transitionCount; i++) {
265
- const transition = Array.isArray(transitionsConfig) ? transitionsConfig[i] : transitionsConfig;
266
- const args = createActor.withActorScope({
267
- context: snapshot.context,
268
- event,
269
- input: snapshot.input,
270
- value: snapshot.value,
271
- children: snapshot.children
272
- }, actorScope);
273
- if (typeof transition === 'function') {
274
- const actions = [];
275
- const enq = createActor.createTransitionEnqueue(actorScope, actions, internalQueue, true);
276
- const result = transition(args, enq);
277
- if (!result) {
278
- if (actions.length) {
279
- return {
280
- actions
281
- };
282
- }
283
- continue;
284
- }
285
- return {
286
- target: result.target,
287
- context: result.context,
288
- input: result.input,
289
- actions
290
- };
291
- }
292
- if ('guard' in transition && transition.guard && !transition.guard(args)) {
293
- continue;
294
- }
295
- return {
296
- target: transition.target,
297
- context: resolveTransitionContext(transition.context, args),
298
- input: transition.input,
299
- actions: 'actions' in transition && transition.actions ? toArray(transition.actions) : emptyRawActions
300
- };
301
- }
302
- return undefined;
303
- };
304
- const transitionCore = (snapshot, event, actorScope) => {
305
- if (snapshot.status !== 'active') {
306
- return [snapshot, []];
307
- }
308
- if (event.type === createActor.XSTATE_STOP) {
309
- const actions = [];
310
- const enqueue = createActor.createTransitionEnqueue(actorScope, actions, []);
311
- for (const id of Object.keys(snapshot.timers)) {
312
- enqueue.cancel(id);
313
- }
314
- const [withoutTimers, cancelEffects] = createActor.resolveActionsWithContext(snapshot, event, actorScope, actions);
315
- return [stopSnapshot(withoutTimers), cancelEffects];
316
- }
317
- if (event.type === createActor.XSTATE_TIMER) {
318
- const timer = snapshot.timers[event.id];
319
- if (!timer) {
320
- return [snapshot, emptyExecutableActions];
321
- }
322
- const timers = {
323
- ...snapshot.timers
324
- };
325
- delete timers[timer.id];
326
- const nextSnapshot = {
327
- ...snapshot,
328
- timers
329
- };
330
- if (timer.type === '@xstate.raise') {
331
- return transitionCore(nextSnapshot, timer.event, actorScope);
332
- }
333
- const target = timer.target === 'self' ? actorScope.self : timer.target;
334
- return [nextSnapshot, [createActor.createSendToEffect(actorScope, target, timer.event)]];
335
- }
336
- const stateConfig = config.states[snapshot.value];
337
- const directTransition = stateConfig?.on?.[event.type];
338
- if (!directTransition) {
339
- return [snapshot, emptyExecutableActions];
340
- }
341
- if (!Array.isArray(directTransition) && typeof directTransition !== 'function' && !('guard' in directTransition) && !('actions' in directTransition && directTransition.actions) && typeof directTransition.input !== 'function') {
342
- const target = directTransition.target ?? snapshot.value;
343
- const stateChanged = target !== snapshot.value;
344
- if (stateChanged && (stateConfig.exit || config.states[target]?.entry)) ; else {
345
- const hasContext = directTransition.context !== undefined;
346
- const hasInput = directTransition.input !== undefined;
347
- const resolvedContext = !createActor.isLazyActorScope(actorScope) ? resolveTransitionContext(directTransition.context, {
348
- context: snapshot.context,
349
- event,
350
- input: snapshot.input,
351
- value: snapshot.value,
352
- self: actorScope.self,
353
- system: actorScope.system,
354
- parent: actorScope.self._parent,
355
- children: snapshot.children
356
- }) : typeof directTransition.context === 'function' ? directTransition.context(createActor.withActorScope({
357
- context: snapshot.context,
358
- event,
359
- input: snapshot.input,
360
- value: snapshot.value,
361
- children: snapshot.children
362
- }, actorScope)) : directTransition.context;
363
- const context = hasContext && resolvedContext ? mergeContextPatch(snapshot.context, resolvedContext) : snapshot.context;
364
- if (!stateChanged && context === snapshot.context && !hasInput && snapshot._stateInput === undefined) {
365
- return [snapshot, emptyExecutableActions];
366
- }
367
- return [cloneSnapshot(snapshot, target, context, hasInput ? resolveInput(directTransition.input, context, event) : undefined), emptyExecutableActions];
368
- }
369
- }
370
- if (typeof directTransition === 'function' && directTransition.length < 2 && !stateConfig?.exit) {
371
- const result = directTransition(createActor.withActorScope({
372
- context: snapshot.context,
373
- event,
374
- input: snapshot.input,
375
- value: snapshot.value,
376
- children: snapshot.children
377
- }, actorScope), undefined);
378
- if (result) {
379
- const target = result.target ?? snapshot.value;
380
- if (!config.states[target]?.entry) {
381
- const hasContext = result.context !== undefined;
382
- const hasInput = result.input !== undefined;
383
- const context = hasContext && result.context ? mergeContextPatch(snapshot.context, result.context) : snapshot.context;
384
- if (target === snapshot.value && context === snapshot.context && !hasInput && snapshot._stateInput === undefined) {
385
- return [snapshot, emptyExecutableActions];
386
- }
387
- return [cloneSnapshot(snapshot, target, context, hasInput ? resolveInput(result.input, context, event) : undefined), emptyExecutableActions];
388
- }
389
- }
390
- }
391
- let nextSnapshot = snapshot;
392
- const executableActions = [];
393
- const internalQueue = [event];
394
- let iterations = 0;
395
- while (internalQueue.length) {
396
- if (++iterations > 1000) {
397
- throw new Error('FSM microstep count exceeded 1000');
398
- }
399
- const nextEvent = internalQueue.shift();
400
- const selected = selectTransition(nextSnapshot, nextEvent, actorScope, internalQueue);
401
- if (!selected) {
402
- continue;
403
- }
404
- const nextValue = selected.target ?? nextSnapshot.value;
405
- const stateChanged = nextValue !== nextSnapshot.value;
406
- if (stateChanged) {
407
- const [exited, exitActions] = runStateActions(nextSnapshot, nextEvent, actorScope, config.states[nextSnapshot.value]?.exit, nextSnapshot._stateInput, internalQueue);
408
- nextSnapshot = exited;
409
- executableActions.push(...exitActions);
410
- }
411
- let context = nextSnapshot.context;
412
- if (selected.context !== undefined) {
413
- context = mergeContextPatch(context, selected.context);
414
- }
415
- const hasInput = selected.input !== undefined;
416
- const stateInput = hasInput ? resolveInput(selected.input, context, nextEvent) : undefined;
417
- if (stateChanged || context !== nextSnapshot.context || hasInput || nextSnapshot._stateInput !== undefined) {
418
- nextSnapshot = cloneSnapshot(nextSnapshot, nextValue, context, stateInput);
419
- }
420
- const [afterTransition, transitionActions] = runActions(nextSnapshot, nextEvent, actorScope, selected.actions);
421
- nextSnapshot = afterTransition;
422
- executableActions.push(...transitionActions);
423
- if (stateChanged) {
424
- const [entered, entryActions] = runStateActions(nextSnapshot, nextEvent, actorScope, config.states[nextValue]?.entry, stateInput, internalQueue);
425
- nextSnapshot = entered;
426
- executableActions.push(...entryActions);
427
- }
428
- }
429
- return [nextSnapshot, executableActions];
430
- };
431
- const transition = (...args) => {
432
- createActor.beginSpawnAllocation(args[2]);
433
- const [nextSnapshot, effects] = transitionCore(...args);
434
- return createActor.finalizeTransitionResult(args[2], args[0], [nextSnapshot, [...effects, ...createActor.deriveDeferredStarts(effects)]]);
435
- };
436
- const logic = {
437
- id: config.id,
438
- config,
439
- transition,
440
- initialTransition: (input, actorScope) => {
441
- createActor.beginSpawnAllocation(actorScope);
442
- const context = resolveContext(config.context, input);
443
- const snapshot = createSnapshot(config.initial, context, input, machine);
444
- const internalQueue = [];
445
- let [nextSnapshot, actions] = runStateActions(snapshot, {
446
- type: createActor.XSTATE_INIT
447
- }, actorScope, config.states[config.initial]?.entry, undefined, internalQueue);
448
- if (!actions.length) {
449
- actions = [];
450
- }
451
- while (internalQueue.length) {
452
- const [raisedSnapshot, raisedActions] = transitionCore(nextSnapshot, internalQueue.shift(), actorScope);
453
- nextSnapshot = raisedSnapshot;
454
- actions.push(...raisedActions);
455
- }
456
- return createActor.finalizeTransitionResult(actorScope, undefined, [nextSnapshot, [...actions, ...createActor.deriveDeferredStarts(actions)]]);
457
- },
458
- getInitialSnapshot: (actorScope, input) => logic.initialTransition(input, actorScope)[0],
459
- getPersistedSnapshot: ({
460
- machine: _,
461
- ...snapshot
462
- }) => snapshot,
463
- restoreSnapshot: snapshot => ({
464
- ...snapshot,
465
- machine: machine
466
- })
467
- };
468
- return logic;
469
- }
470
-
471
45
  function delayToMs(delay) {
472
46
  const parsedDelay = createActor.parseDelayToMilliseconds(delay);
473
47
  if (parsedDelay !== undefined) return parsedDelay;
474
48
  return typeof delay === 'string' ? parseFloat(delay) || 0 : delay;
475
49
  }
476
- function normalizeScxmlEventType(eventType) {
477
- return /^error(\.|$)/.test(eventType) ? `xstate.${eventType}` : eventType;
478
- }
479
- function toScxmlEventName(eventType) {
480
- return eventType.startsWith('xstate.error.') ? eventType.slice('xstate.'.length) : eventType;
481
- }
482
-
483
- /**
484
- * Isolated executable-content block. Errors in nested actions stop this block
485
- * but do not propagate to the surrounding action list. Used to model SCXML's
486
- * separate <onentry>/<onexit> blocks: each is its own block per spec.
487
- */
488
-
489
50
  function isExpression(value) {
490
51
  return !!value && typeof value === 'object' && typeof value['@expr'] === 'string';
491
52
  }
@@ -498,9 +59,6 @@ function isResolvable(value) {
498
59
  function isBuiltInActionType(type) {
499
60
  return type.startsWith('@xstate.');
500
61
  }
501
- function isScxmlActionType(type) {
502
- return type.startsWith('scxml.');
503
- }
504
62
  function toPath(parent, key) {
505
63
  return typeof key === 'number' ? `${parent}[${key}]` : `${parent}.${key}`;
506
64
  }
@@ -641,7 +199,7 @@ function assertMachineJSON(json, resolvedSources, expressionResolver) {
641
199
  assertCondition(json.guards[condition.type].when, `$.guards.${condition.type}.when`);
642
200
  return;
643
201
  }
644
- if (!resolvedSources.guards[condition.type] && !['scxml.cond', 'xstate.stateIn', 'xstate.not'].includes(condition.type)) {
202
+ if (!resolvedSources.guards[condition.type] && !['xstate.stateIn', 'xstate.not'].includes(condition.type)) {
645
203
  throw new Error(`Missing guard source "${condition.type}"`);
646
204
  }
647
205
  }
@@ -654,7 +212,7 @@ function assertMachineJSON(json, resolvedSources, expressionResolver) {
654
212
  throw new Error(`Invalid action at ${path}`);
655
213
  }
656
214
  assertResolvable(action.params, `${path}.params`);
657
- if (isBuiltInActionType(action.type) || isScxmlActionType(action.type)) {
215
+ if (isBuiltInActionType(action.type)) {
658
216
  assertResolvable(action, path);
659
217
  return;
660
218
  }
@@ -720,8 +278,7 @@ function assertMachineJSON(json, resolvedSources, expressionResolver) {
720
278
  const invokes = Array.isArray(node.invoke) ? node.invoke : [node.invoke];
721
279
  invokes.forEach((invoke, index) => {
722
280
  const invokePath = `${path}.invoke${Array.isArray(node.invoke) ? `[${index}]` : ''}`;
723
- const extInv = invoke;
724
- if (!extInv._nestedMachineJSON && !resolvedSources.actors[invoke.src]) {
281
+ if (!resolvedSources.actors[invoke.src]) {
725
282
  throw new Error(`Missing actor source "${invoke.src}"`);
726
283
  }
727
284
  assertResolvable(invoke.input, `${invokePath}.input`);
@@ -773,78 +330,6 @@ function assertMachineJSON(json, resolvedSources, expressionResolver) {
773
330
  }
774
331
  assertStateNode(json, '$');
775
332
  }
776
- let _scxmlSessionId = 'session_scxml';
777
- let _scxmlMachineName = '';
778
-
779
- /** Evaluates an SCXML expression with context variables available via `with`. */
780
- function evaluateExpr(context, expr, event, self) {
781
- const fnBody = `
782
- with (context) {
783
- return (${expr});
784
- }
785
- `.trim();
786
- // eslint-disable-next-line @typescript-eslint/no-implied-eval
787
- const fn = new Function('context', '_event', '_sessionid', '_name', '_ioprocessors', 'In', fnBody);
788
- const In = stateId => {
789
- if (!self) return false;
790
- try {
791
- const snap = self.getSnapshot?.();
792
- if (snap?.nodes) {
793
- const sanitized = stateId.replace(/\./g, '$');
794
- return snap.nodes.some(node => node.id === sanitized || node.id.endsWith('.' + sanitized));
795
- }
796
- } catch {
797
- // ignore
798
- }
799
- return false;
800
- };
801
- const SCXML_ORIGIN = `#_scxml_${_scxmlSessionId}`;
802
- const SCXML_ORIGIN_TYPE = 'http://www.w3.org/TR/scxml/#SCXMLEventProcessor';
803
- const isExternal = event && event._scxmlExternal;
804
- const isInitEvent = event && event.type === '@xstate.init';
805
- // Per SCXML spec, _event has these fields. Fields that don't apply to a
806
- // particular event are present with value `undefined` (so `'name' in _event`
807
- // is true but `typeof _event.name === 'undefined'` for unset fields).
808
- // For xstate.done.* events, _event.data is the `output` payload (matches
809
- // SCXML's done event semantics where data is the donedata).
810
- const isDoneEvent = event && typeof event.type === 'string' && event.type.startsWith('xstate.done.');
811
- const explicitType = event && event._scxmlEventType;
812
- const scxmlEvent = event && !isInitEvent ? {
813
- name: event._scxmlEventName ?? toScxmlEventName(event.type),
814
- type: explicitType || (isExternal ? 'external' : 'internal'),
815
- sendid: event._scxmlSendId,
816
- origin: isExternal ? SCXML_ORIGIN : undefined,
817
- origintype: isExternal ? SCXML_ORIGIN_TYPE : undefined,
818
- invokeid: event._scxmlInvokeId,
819
- data: isDoneEvent ? event.output : event._scxmlEventData !== undefined ? event._scxmlEventData : event
820
- } : undefined;
821
- const result = fn(context, scxmlEvent, _scxmlSessionId, _scxmlMachineName, {
822
- scxml: {
823
- location: `#_scxml_${_scxmlSessionId}`
824
- }
825
- }, In);
826
- return result;
827
- }
828
-
829
- /** Executes an SCXML script block and returns updated context values. */
830
- function executeScript(context, code) {
831
- // Create a proxy to track which properties are modified
832
- const updates = {};
833
- const contextKeys = Object.keys(context);
834
-
835
- // Build variable declarations and reassignment capture
836
- const varDeclarations = contextKeys.map(k => `let ${k} = context.${k};`).join('\n');
837
- const captureUpdates = contextKeys.map(k => `updates.${k} = ${k};`).join('\n');
838
- const fnBody = `
839
- ${varDeclarations}
840
- ${code}
841
- ${captureUpdates}
842
- return updates;
843
- `;
844
- // eslint-disable-next-line @typescript-eslint/no-implied-eval
845
- const fn = new Function('context', 'updates', fnBody);
846
- return fn(context, updates);
847
- }
848
333
  function createMachineFromConfig(json, sources = {}) {
849
334
  const resolvedSources = mergeSources(json, sources);
850
335
  const expressionResolver = createExpressionResolver(json['@exprLang'], resolvedSources);
@@ -855,9 +340,7 @@ function createMachineFromConfig(json, sources = {}) {
855
340
  getDurationConfig
856
341
  } = expressionResolver;
857
342
  function resolveCondition(condition, slot, path) {
858
- if (!condition) {
859
- return undefined;
860
- }
343
+ if (!condition) return undefined;
861
344
  if (isResolvable(condition)) {
862
345
  return args => !!evaluateResolvable(condition, slot, makeScope(args), path);
863
346
  }
@@ -878,10 +361,11 @@ function createMachineFromConfig(json, sources = {}) {
878
361
  return guardImpl(args, params);
879
362
  };
880
363
  }
364
+ function getMissingGuardMessage(type, guards) {
365
+ return `Guard '${type}' is not implemented in machine '${json.id ?? '(machine)'}'. Available guards: ${Object.keys(guards).map(key => `'${key}'`).join(', ') || '(none)'}.`;
366
+ }
881
367
  function makeChoiceConfig(choice, path) {
882
- if (!choice) {
883
- return undefined;
884
- }
368
+ if (!choice) return undefined;
885
369
  if (isResolvable(choice)) {
886
370
  return args => evaluateResolvable(choice, 'choice', makeScope(args), path);
887
371
  }
@@ -904,32 +388,8 @@ function createMachineFromConfig(json, sources = {}) {
904
388
  throw new Error(`Choice state at ${path} did not match any branch.`);
905
389
  };
906
390
  }
907
-
908
- // Pending transition actions: set by .to functions, consumed by entry functions.
909
- // This bridges SCXML's exit→transition→entry action ordering with XState's
910
- // .to function receiving pre-exit context.
911
- // Map keyed by target state ID so parallel transitions don't overwrite each other.
912
- const pendingTransitionActionsMap = {};
913
-
914
- // Ordered queue of ALL transition actions (targeted + targetless) for parallel
915
- // context sharing. In SCXML, all transition actions execute sequentially in
916
- // document order with a shared evolving data model.
917
- const allTransitionActions = [];
918
- // Pre-transition context saved when a targetless .to executes. Used by entry
919
- // functions to re-execute all transition actions from scratch when parallel
920
- // targetless transitions coexist with targeted transitions.
921
- let contextBeforeTargetless = null;
922
- // Platform errors collected during transition selection (e.g., failing
923
- // <transition cond>). Drained by the next state's entry into the internal
924
- // event queue so they're processed before any external events.
925
- const pendingPlatformErrors = [];
926
- function getMissingGuardMessage(type, guards) {
927
- return `Guard '${type}' is not implemented in machine '${json.id ?? '(machine)'}'. Available guards: ${Object.keys(guards).map(key => `'${key}'`).join(', ') || '(none)'}.`;
928
- }
929
391
  function resolveRouteConfig(route, path) {
930
- if (!route || typeof route === 'function') {
931
- return route;
932
- }
392
+ if (!route || typeof route === 'function') return route;
933
393
  if (isResolvable(route)) {
934
394
  return args => evaluateResolvable(route, 'transition', makeScope(args), path);
935
395
  }
@@ -937,263 +397,15 @@ function createMachineFromConfig(json, sources = {}) {
937
397
  guard,
938
398
  ...routeConfig
939
399
  } = route;
940
- if (!guard) {
941
- return routeConfig;
942
- }
400
+ if (!guard) return routeConfig;
943
401
  const resolvedGuard = resolveCondition({
944
402
  type: guard
945
403
  }, 'guard', path);
946
404
  return args => resolvedGuard(args) ? routeConfig : undefined;
947
405
  }
948
- function iterNode(node, nodeKey) {
949
- const originalEntryActions = toActionArray(node.entry);
950
- const stateId = node.id || nodeKey;
951
-
952
- // Wrap entry to first execute any pending transition actions, then normal entry.
953
- // This ensures SCXML execution order: exit → transition_actions → entry_actions
954
- // because pending transition actions are set by .to (before exit) but executed
955
- // in entry (after exit), thus seeing post-exit context.
956
- const entryFn = (x, enq) => {
957
- // Drain any platform errors queued during transition selection (e.g.,
958
- // failing <transition cond="..."> evaluations). These must be raised
959
- // internally so they're processed before subsequent external events.
960
- while (pendingPlatformErrors.length) {
961
- const err = pendingPlatformErrors.shift();
962
- enq.raise({
963
- type: 'xstate.error.execution',
964
- error: err,
965
- _scxmlEventType: 'platform',
966
- _scxmlEventName: 'error.execution',
967
- _scxmlEventData: err
968
- });
969
- }
970
- let context;
971
-
972
- // If targetless transitions were interleaved with targeted transitions
973
- // (parallel state), re-execute ALL transition actions from the original
974
- // pre-transition context. This overrides any .to-produced context with
975
- // the correct SCXML document-order sequential execution.
976
- // Only trigger when BOTH targeted (pending in map) and targetless fired
977
- // in the same microstep — prevents stale data from previous events.
978
- if (contextBeforeTargetless && allTransitionActions.length > 0 && Object.keys(pendingTransitionActionsMap).length > 0) {
979
- let ctx = contextBeforeTargetless;
980
- for (const actions of allTransitionActions) {
981
- const mergedX = {
982
- ...x,
983
- context: ctx
984
- };
985
- const result = executeActions(actions, mergedX, enq);
986
- if (result.context) {
987
- ctx = result.context;
988
- }
989
- }
990
- allTransitionActions.length = 0;
991
- contextBeforeTargetless = null;
992
- // Clear per-target map since we re-processed everything
993
- for (const key of Object.keys(pendingTransitionActionsMap)) {
994
- delete pendingTransitionActionsMap[key];
995
- }
996
- context = ctx;
997
- } else {
998
- // Normal path: consume pending transition actions for THIS state.
999
- // In parallel states, each target gets its own pending actions.
1000
- const transActions = stateId ? pendingTransitionActionsMap[stateId] : undefined;
1001
- if (transActions) {
1002
- delete pendingTransitionActionsMap[stateId];
1003
- const result = executeActions(transActions, x, enq);
1004
- if (result.context) {
1005
- context = result.context;
1006
- }
1007
- }
1008
- // Clear stale targetless data from previous microsteps
1009
- contextBeforeTargetless = null;
1010
- allTransitionActions.length = 0;
1011
- }
1012
-
1013
- // Execute normal entry actions
1014
- if (originalEntryActions.length) {
1015
- const mergedX = context ? {
1016
- ...x,
1017
- context
1018
- } : x;
1019
- const result = executeActions(originalEntryActions, mergedX, enq);
1020
- if (result.context) {
1021
- context = result.context;
1022
- }
1023
- }
1024
- return {
1025
- context
1026
- };
1027
- };
1028
- const nodeConfig = {
1029
- id: node.id,
1030
- initial: node.initial,
1031
- type: node.type,
1032
- history: node.history,
1033
- target: node.target,
1034
- description: node.description,
1035
- tags: node.tags,
1036
- input: node.input,
1037
- timeout: getDurationConfig(node.timeout, `$.states.${nodeKey}.timeout`),
1038
- states: node.states ? Object.entries(node.states).reduce((acc, [key, value]) => {
1039
- acc[key] = iterNode(value, key);
1040
- return acc;
1041
- }, {}) : undefined,
1042
- on: node.on ? Object.entries(node.on).reduce((acc, [key, value]) => {
1043
- acc[key] = getTransitionConfig(value);
1044
- return acc;
1045
- }, {}) : undefined,
1046
- always: node.always ? getTransitionConfig(node.always) : undefined,
1047
- onError: node.onError ? getTransitionConfig(node.onError) : undefined,
1048
- choice: makeChoiceConfig(node.choice, `$.states.${nodeKey}.choice`),
1049
- route: resolveRouteConfig(node.route, `$.states.${nodeKey}.route`),
1050
- after: node.after ? Object.entries(node.after).reduce((acc, [key, value]) => {
1051
- acc[key] = getTransitionConfig(value);
1052
- return acc;
1053
- }, {}) : undefined,
1054
- onTimeout: node.onTimeout ? getTransitionConfig(node.onTimeout) : undefined,
1055
- entry: node.type === 'choice' ? undefined : entryFn,
1056
- exit: node.exit ? iterActions(toActionArray(node.exit)) : undefined,
1057
- invoke: node.invoke ? iterInvokeConfigs(node.invoke) : undefined,
1058
- meta: node.meta,
1059
- output: node._scxmlDonedata ? makeDonedataOutput(node._scxmlDonedata) : isResolvable(node.output) ? ({
1060
- context,
1061
- event,
1062
- self
1063
- }) => evaluateResolvable(node.output, 'output', {
1064
- context,
1065
- event,
1066
- self
1067
- }, `$.states.${nodeKey}.output`) : node.output
1068
- };
1069
- return nodeConfig;
1070
- }
1071
- function makeDonedataOutput(donedata) {
1072
- return ({
1073
- context,
1074
- event,
1075
- self
1076
- }) => {
1077
- try {
1078
- if (donedata.params && donedata.params.length) {
1079
- const out = {};
1080
- for (const param of donedata.params) {
1081
- out[param.name] = evaluateExpr(context, param.expr, event, self);
1082
- }
1083
- return out;
1084
- }
1085
- if (donedata.contentExpr !== undefined) {
1086
- return evaluateExpr(context, donedata.contentExpr, event, self);
1087
- }
1088
- if (donedata.contentText !== undefined) {
1089
- // Try parsing as a JS expression (number/object/array literals);
1090
- // fall back to the raw string.
1091
- try {
1092
- return evaluateExpr(context, donedata.contentText, event, self);
1093
- } catch {
1094
- return donedata.contentText;
1095
- }
1096
- }
1097
- } catch (err) {
1098
- // Per SCXML, donedata expression errors raise error.execution and
1099
- // result in undefined event.data. Queue for the next entry to drain.
1100
- const message = err instanceof Error ? err.message : typeof err === 'string' ? err : 'unknown error';
1101
- pendingPlatformErrors.push({
1102
- tagname: 'donedata',
1103
- message,
1104
- line: NaN,
1105
- column: NaN,
1106
- reason: message
1107
- });
1108
- }
1109
- return undefined;
1110
- };
1111
- }
1112
- function iterInvokeConfigs(invokes) {
1113
- const invokeArray = Array.isArray(invokes) ? invokes : [invokes];
1114
- return invokeArray.map(inv => {
1115
- const extInv = inv;
1116
- // Create child machine from nested SCXML JSON
1117
- let src;
1118
- if (extInv._nestedMachineJSON) {
1119
- src = createMachineFromConfig(extInv._nestedMachineJSON, resolvedSources);
1120
- } else {
1121
- src = resolvedSources.actors[inv.src] ?? inv.src;
1122
- }
1123
- return {
1124
- src,
1125
- id: inv.id,
1126
- registryKey: inv.registryKey,
1127
- input: inv.input !== undefined ? args => resolveValue(inv.input, 'input', makeScope(args), '$.invoke.input') : undefined,
1128
- onDone: inv.onDone ? getTransitionConfig(inv.onDone) : undefined,
1129
- onError: inv.onError ? getTransitionConfig(inv.onError) : undefined,
1130
- onSnapshot: inv.onSnapshot ? getTransitionConfig(inv.onSnapshot) : undefined,
1131
- timeout: getDurationConfig(inv.timeout, '$.invoke.timeout'),
1132
- onTimeout: inv.onTimeout ? getTransitionConfig(inv.onTimeout) : undefined
1133
- };
1134
- });
1135
- }
1136
-
1137
- /**
1138
- * Raise an SCXML error.execution platform event onto the internal queue. Per
1139
- * spec, error.execution is type='platform' and _event.data contains error
1140
- * info. The surrounding block of executable content stops.
1141
- */
1142
- function raiseErrorExecution(state, tagname, err) {
1143
- const message = err instanceof Error ? err.message : typeof err === 'string' ? err : 'unknown error';
1144
- state.enq.raise({
1145
- type: 'xstate.error.execution',
1146
- error: {
1147
- tagname,
1148
- message,
1149
- line: NaN,
1150
- column: NaN,
1151
- reason: message
1152
- },
1153
- _scxmlEventType: 'platform',
1154
- _scxmlEventName: 'error.execution',
1155
- _scxmlEventData: {
1156
- tagname,
1157
- message,
1158
- line: NaN,
1159
- column: NaN,
1160
- reason: message
1161
- }
1162
- });
1163
- state.errored = true;
1164
- }
1165
- function executeActionDefinition(action, x, enq, params, parentState, stack) {
1166
- const definition = json.actions?.[action.type];
1167
- if (!definition) {
1168
- enq(x.actions[action.type], params);
1169
- return {
1170
- context: undefined,
1171
- errored: parentState.errored
1172
- };
1173
- }
1174
- if (stack.includes(action.type)) {
1175
- raiseErrorExecution(parentState, 'action', new Error(`Circular action reference: ${stack.concat(action.type).join(' -> ')}`));
1176
- return {
1177
- context: undefined,
1178
- errored: true
1179
- };
1180
- }
1181
- const definitions = Array.isArray(definition) ? definition : [definition];
1182
- return executeActions(definitions, {
1183
- ...x,
1184
- params
1185
- }, enq, parentState, stack.concat(action.type));
1186
- }
1187
-
1188
- /** Execute an array of SCXML action JSON descriptors with context and enqueue. */
1189
- function executeActions(actions, x, enq, parentState, stack = []) {
1190
- const state = parentState ?? {
1191
- enq,
1192
- errored: false
1193
- };
406
+ function executeActions(actions, x, enq, stack = []) {
1194
407
  let context;
1195
408
  for (const action of actions) {
1196
- if (state.errored) break;
1197
409
  if (isResolvable(action)) {
1198
410
  const result = evaluateResolvable(action, 'action', makeScope(x, {
1199
411
  params: x.params,
@@ -1203,31 +415,18 @@ function createMachineFromConfig(json, sources = {}) {
1203
415
  context ??= {};
1204
416
  Object.assign(context, result.context);
1205
417
  }
1206
- } else if (isBuiltInActionJSON(action)) {
418
+ continue;
419
+ }
420
+ if (isBuiltInActionJSON(action)) {
1207
421
  switch (action.type) {
1208
422
  case '@xstate.raise':
1209
- {
1210
- // Tag as external if it has a delay (from <send>, not <raise>).
1211
- // Attach _scxmlSendId so _event.sendid can be read in expressions.
1212
- const isExternal = action.delay !== undefined;
1213
- const resolvedEvent = resolveValue(action.event, 'actionParams', makeScope(x, {
1214
- params: x.params
1215
- }), '$.actions.event');
1216
- const event = isExternal || action.id !== undefined ? {
1217
- ...resolvedEvent,
1218
- ...(isExternal ? {
1219
- _scxmlExternal: true
1220
- } : {}),
1221
- ...(action.id !== undefined ? {
1222
- _scxmlSendId: action.id
1223
- } : {})
1224
- } : resolvedEvent;
1225
- enq.raise(event, {
1226
- id: action.id,
1227
- delay: action.delay
1228
- });
1229
- break;
1230
- }
423
+ enq.raise(resolveValue(action.event, 'actionParams', makeScope(x, {
424
+ params: x.params
425
+ }), '$.actions.event'), {
426
+ id: action.id,
427
+ delay: action.delay
428
+ });
429
+ break;
1231
430
  case '@xstate.cancel':
1232
431
  enq.cancel(action.id);
1233
432
  break;
@@ -1245,501 +444,161 @@ function createMachineFromConfig(json, sources = {}) {
1245
444
  params: x.params
1246
445
  }), '$.actions.context'));
1247
446
  break;
1248
- default:
1249
- throw new Error(`Unknown built-in action: ${action.type}`);
1250
- }
1251
- } else if (action.type === 'scxml.assign') {
1252
- const scxmlAction = action;
1253
- const mergedContext = {
1254
- ...x.context,
1255
- ...context
1256
- };
1257
- let value;
1258
- try {
1259
- value = evaluateExpr(mergedContext, scxmlAction.expr, x.event, x.self);
1260
- } catch (err) {
1261
- raiseErrorExecution(state, 'assign', err);
1262
- continue;
1263
- }
1264
- // Per SCXML, assigning to a location that doesn't exist on the
1265
- // datamodel is an error. Allow setting an own property via context;
1266
- // detect deep paths (a.b.c) which we don't support.
1267
- if (scxmlAction.location.includes('.')) {
1268
- raiseErrorExecution(state, 'assign', new Error(`Invalid assign location: ${scxmlAction.location}`));
1269
- continue;
1270
- }
1271
- context ??= {};
1272
- context[scxmlAction.location] = value;
1273
- } else if (action.type === 'scxml.raise') {
1274
- const scxmlAction = action;
1275
- const mergedContext = {
1276
- ...x.context,
1277
- ...context
1278
- };
1279
- let eventType;
1280
- let eventData;
1281
- let target;
1282
- let delay;
1283
- try {
1284
- eventType = scxmlAction.eventexpr ? evaluateExpr(mergedContext, scxmlAction.eventexpr, x.event, x.self) : scxmlAction.event || 'unknown';
1285
- eventType = normalizeScxmlEventType(eventType);
1286
- eventData = {
1287
- type: eventType,
1288
- _scxmlEventName: toScxmlEventName(eventType)
1289
- };
1290
- if (scxmlAction.params) {
1291
- for (const param of scxmlAction.params) {
1292
- eventData[param.name] = evaluateExpr(mergedContext, param.expr, x.event, x.self);
1293
- }
1294
- }
1295
- target = scxmlAction.targetexpr ? evaluateExpr(mergedContext, scxmlAction.targetexpr, x.event, x.self) : scxmlAction.target;
1296
- const isInternalTarget = target === '#_internal';
1297
- delay = scxmlAction.delayexpr ? delayToMs(evaluateExpr(mergedContext, scxmlAction.delayexpr, x.event, x.self)) : isInternalTarget ? undefined : scxmlAction.delay;
1298
- } catch (err) {
1299
- raiseErrorExecution(state, 'send', err);
1300
- continue;
1301
- }
1302
- const isInternalTarget = target === '#_internal';
1303
- const isParentTarget = target === '#_parent';
1304
-
1305
- // Validate target. SCXML targets must be '#_internal', '#_parent',
1306
- // or '#_<id>'. A bare string without the '#_' prefix is invalid and
1307
- // raises error.execution.
1308
- if (typeof target === 'string' && target.length > 0 && !target.startsWith('#_')) {
1309
- raiseErrorExecution(state, 'send', new Error(`Invalid send target: ${target}`));
1310
- continue;
1311
- }
1312
- // Attach send id so _event.sendid can be read in expressions.
1313
- if (scxmlAction.id !== undefined) {
1314
- eventData._scxmlSendId = scxmlAction.id;
1315
- }
1316
- // Resolve target at runtime: parent, child, or self
1317
- if (isParentTarget && x.parent) {
1318
- // Send to parent via sendTo; pass delay if present
1319
- enq.sendTo(x.parent, eventData, delay !== undefined ? {
1320
- delay
1321
- } : undefined);
1322
- } else if (typeof target === 'string' && target.startsWith('#_') && !isParentTarget && !isInternalTarget) {
1323
- // #_<invokeId> → try to send to child actor, fall back to self-raise
1324
- const childId = target.slice(2); // strip '#_'
1325
- const childRef = x.children?.[childId];
1326
- if (childRef) {
1327
- enq.sendTo(childRef, eventData);
1328
- } else if (childId.startsWith('scxml_') && childId !== `scxml_${_scxmlSessionId}`) {
1329
- const message = `Unable to dispatch event to target: ${target}`;
1330
- enq.raise({
1331
- type: 'xstate.error.communication',
1332
- error: {
1333
- tagname: 'send',
1334
- message,
1335
- line: NaN,
1336
- column: NaN,
1337
- reason: message
1338
- },
1339
- _scxmlEventType: 'platform',
1340
- _scxmlEventName: 'error.communication',
1341
- _scxmlEventData: {
1342
- tagname: 'send',
1343
- message,
1344
- line: NaN,
1345
- column: NaN,
1346
- reason: message
1347
- }
1348
- });
1349
- } else {
1350
- // This SCXML session id uses the external event queue.
1351
- eventData._scxmlExternal = true;
1352
- enq.sendTo(x.self, eventData, {
1353
- id: scxmlAction.id,
1354
- delay
1355
- });
1356
- }
1357
- } else {
1358
- // #_internal uses the internal queue; self-send/no target use the
1359
- // external event queue.
1360
- if (isInternalTarget) {
1361
- enq.raise(eventData, {
1362
- id: scxmlAction.id,
1363
- delay
1364
- });
1365
- } else {
1366
- eventData._scxmlExternal = true;
1367
- enq.sendTo(x.self, eventData, {
1368
- id: scxmlAction.id,
1369
- delay
1370
- });
1371
- }
1372
- }
1373
- } else if (action.type === 'scxml.cancel') {
1374
- const scxmlAction = action;
1375
- const mergedContext = {
1376
- ...x.context,
1377
- ...context
1378
- };
1379
- try {
1380
- const sendId = evaluateExpr(mergedContext, scxmlAction.sendidexpr, x.event, x.self);
1381
- if (sendId) {
1382
- enq.cancel(sendId);
1383
- }
1384
- } catch {
1385
- // ignore evaluation errors
1386
- }
1387
- } else if (action.type === 'scxml.script') {
1388
- const scxmlAction = action;
1389
- const mergedContext = {
1390
- ...x.context,
1391
- ...context
1392
- };
1393
- try {
1394
- const updatedContext = executeScript(mergedContext, scxmlAction.code);
1395
- context ??= {};
1396
- Object.assign(context, updatedContext);
1397
- } catch (err) {
1398
- raiseErrorExecution(state, 'script', err);
1399
- }
1400
- } else if (action.type === 'scxml.foreach') {
1401
- const scxmlAction = action;
1402
- const mergedContext = {
1403
- ...x.context,
1404
- ...context
1405
- };
1406
- // SCXML: `item` (and `index` if present) must be valid datamodel
1407
- // locations — i.e. legal identifiers. Reject things like 'continue'
1408
- // (string literal) or '7' (number).
1409
- const isLegalIdentifier = s => /^[$_a-zA-Z][$_a-zA-Z0-9]*$/.test(s);
1410
- if (!isLegalIdentifier(scxmlAction.item) || scxmlAction.index && !isLegalIdentifier(scxmlAction.index)) {
1411
- raiseErrorExecution(state, 'foreach', new Error('foreach item/index is not a legal location'));
1412
- continue;
1413
- }
1414
- let arr;
1415
- try {
1416
- arr = evaluateExpr(mergedContext, scxmlAction.array, x.event, x.self);
1417
- } catch (err) {
1418
- raiseErrorExecution(state, 'foreach', err);
1419
- continue;
1420
- }
1421
- if (!Array.isArray(arr)) {
1422
- raiseErrorExecution(state, 'foreach', new Error('foreach array is not iterable'));
1423
- continue;
1424
447
  }
1425
- context ??= {};
1426
- for (let i = 0; i < arr.length; i++) {
1427
- context[scxmlAction.item] = arr[i];
1428
- if (scxmlAction.index) {
1429
- context[scxmlAction.index] = i;
1430
- }
1431
- const iterX = {
1432
- ...x,
1433
- context: {
1434
- ...x.context,
1435
- ...context
1436
- }
1437
- };
1438
- const iterResult = executeActions(scxmlAction.actions, iterX, enq, state);
1439
- if (iterResult.context) {
1440
- Object.assign(context, iterResult.context);
1441
- }
1442
- if (state.errored) break;
1443
- }
1444
- } else if (action.type === 'scxml.block') {
1445
- const scxmlAction = action;
1446
- const blockX = {
1447
- ...x,
1448
- context: {
1449
- ...x.context,
1450
- ...context
1451
- }
1452
- };
1453
- // Block has its own ExecState — errors don't propagate to parent.
1454
- const blockResult = executeActions(scxmlAction.actions, blockX, enq);
1455
- if (blockResult.context) {
1456
- context ??= {};
1457
- for (const key of Object.keys(blockResult.context)) {
1458
- if (blockResult.context[key] !== x.context[key]) {
1459
- context[key] = blockResult.context[key];
1460
- }
1461
- }
1462
- }
1463
- } else if (action.type === 'scxml.if') {
1464
- const scxmlAction = action;
1465
- const mergedContext = {
448
+ continue;
449
+ }
450
+ const params = resolveValue(action.params, 'actionParams', makeScope(x, {
451
+ params: x.params
452
+ }), '$.actions.params');
453
+ const definition = json.actions?.[action.type];
454
+ if (!definition) {
455
+ enq(x.actions[action.type], params);
456
+ continue;
457
+ }
458
+ if (stack.includes(action.type)) {
459
+ throw new Error(`Circular action reference: ${stack.concat(action.type).join(' -> ')}`);
460
+ }
461
+ const definitions = Array.isArray(definition) ? definition : [definition];
462
+ const result = executeActions(definitions, {
463
+ ...x,
464
+ context: {
1466
465
  ...x.context,
1467
466
  ...context
1468
- };
1469
- for (const branch of scxmlAction.branches) {
1470
- let condResult;
1471
- if (branch.cond) {
1472
- try {
1473
- condResult = !!evaluateExpr(mergedContext, branch.cond, x.event, x.self);
1474
- } catch (err) {
1475
- raiseErrorExecution(state, 'if', err);
1476
- condResult = false;
1477
- }
1478
- } else {
1479
- condResult = true;
1480
- }
1481
- if (condResult) {
1482
- if (branch.actions.length) {
1483
- const branchX = {
1484
- ...x,
1485
- context: mergedContext
1486
- };
1487
- const branchResult = executeActions(branch.actions, branchX, enq, state);
1488
- if (branchResult.context) {
1489
- context ??= {};
1490
- for (const key of Object.keys(branchResult.context)) {
1491
- if (branchResult.context[key] !== x.context[key]) {
1492
- context[key] = branchResult.context[key];
1493
- }
1494
- }
1495
- }
1496
- }
1497
- break;
1498
- }
1499
- }
1500
- } else {
1501
- const params = resolveValue(action.params, 'actionParams', makeScope(x, {
1502
- params: x.params
1503
- }), '$.actions.params');
1504
- const result = executeActionDefinition(action, x, enq, params, state, stack);
1505
- if (result.context) {
1506
- context ??= {};
1507
- Object.assign(context, result.context);
1508
- }
1509
- }
467
+ },
468
+ params
469
+ }, enq, stack.concat(action.type));
470
+ if (result.context) context = result.context;
1510
471
  }
1511
472
  return {
1512
473
  context: context ? {
1513
474
  ...x.context,
1514
475
  ...context
1515
- } : undefined,
1516
- errored: state.errored
476
+ } : undefined
1517
477
  };
1518
478
  }
1519
479
  function iterActions(actions) {
1520
- return (x, enq) => executeActions(actions, x, enq);
480
+ const actionArray = toActionArray(actions);
481
+ return (x, enq) => executeActions(actionArray, x, enq);
1521
482
  }
1522
483
  function getTransitionConfig(transition) {
1523
484
  const transitions = Array.isArray(transition) ? transition : [transition];
1524
-
1525
- // Return an array of transition configs. Each SCXML transition becomes
1526
- // a separate XState transition with its own guard and optional .to.
1527
- // This ensures guards are evaluated by XState's evaluateCandidate (once,
1528
- // with pre-exit context) and NOT re-evaluated in computeEntrySet.
1529
- return transitions.map((t, index) => {
1530
- if (isResolvable(t)) {
1531
- return (x, enq) => evaluateResolvable(t, 'transition', makeScope(x, {
485
+ return transitions.map((item, index) => {
486
+ if (isResolvable(item)) {
487
+ return (x, enq) => evaluateResolvable(item, 'transition', makeScope(x, {
1532
488
  enq
1533
489
  }), `$.transition${transitions.length > 1 ? `[${index}]` : ''}`);
1534
490
  }
1535
- const target = Array.isArray(t.target) ? t.target[0] : t.target;
1536
- const targetConfig = t.target;
1537
- const guard = resolveCondition(t.guard, 'guard', '$.transition.guard');
1538
- const resolveTransitionContext = x => t.context ? resolveValue(t.context, 'transitionContext', makeScope(x), '$.transition.context') : undefined;
1539
- const resolveTransitionInput = x => t.input !== undefined ? resolveValue(t.input, 'input', makeScope(x), '$.transition.input') : undefined;
1540
-
1541
- // No guard and no actions: simple static config
1542
- if (!guard && !t.actions?.length) {
1543
- if (t.context) {
1544
- return {
1545
- matches: t.matches,
1546
- to: x => ({
1547
- target: targetConfig,
1548
- context: resolveTransitionContext(x),
1549
- reenter: t.reenter
1550
- }),
1551
- description: t.description,
1552
- meta: t.meta,
1553
- input: t.input !== undefined ? resolveTransitionInput : undefined
1554
- };
1555
- }
1556
- return {
1557
- matches: t.matches,
1558
- target: targetConfig,
1559
- description: t.description,
1560
- reenter: t.reenter,
1561
- meta: t.meta,
1562
- input: t.input !== undefined ? resolveTransitionInput : undefined
1563
- };
1564
- }
1565
-
1566
- // Guard but no actions: static config with guard
1567
- if (guard && !t.actions?.length) {
1568
- if (t.context) {
1569
- return {
1570
- matches: t.matches,
1571
- guard,
1572
- to: x => ({
1573
- target: targetConfig,
1574
- context: resolveTransitionContext(x),
1575
- reenter: t.reenter
1576
- }),
1577
- description: t.description,
1578
- meta: t.meta,
1579
- input: t.input !== undefined ? resolveTransitionInput : undefined
1580
- };
1581
- }
1582
- return {
1583
- matches: t.matches,
1584
- target: targetConfig,
1585
- guard,
1586
- description: t.description,
1587
- reenter: t.reenter,
1588
- meta: t.meta,
1589
- input: t.input !== undefined ? resolveTransitionInput : undefined
1590
- };
1591
- }
1592
-
1593
- // Targetless transitions: execute actions directly in .to AND track for
1594
- // parallel re-execution. For non-parallel, .to result is used directly.
1595
- // For parallel (entries exist), first entry re-executes all in document order.
1596
- if (!target) {
1597
- return {
1598
- matches: t.matches,
1599
- guard,
1600
- description: t.description,
1601
- reenter: t.reenter,
1602
- meta: t.meta,
1603
- input: t.input !== undefined ? resolveTransitionInput : undefined,
1604
- to: (x, enq) => {
1605
- const context = resolveTransitionContext(x);
1606
- if (t.actions?.length) {
1607
- // Track for parallel re-execution (dedup by reference)
1608
- if (!allTransitionActions.includes(t.actions)) {
1609
- allTransitionActions.push(t.actions);
1610
- }
1611
- // Save pre-transition context for parallel override
1612
- contextBeforeTargetless ??= x.context;
1613
- // Execute immediately (fallback for non-parallel case)
1614
- const result = executeActions(t.actions, x, enq);
1615
- if (result.context) {
1616
- return {
1617
- context: {
1618
- ...context,
1619
- ...result.context
1620
- }
1621
- };
1622
- }
1623
- }
1624
- return context ? {
1625
- context
1626
- } : {};
1627
- }
1628
- };
1629
- }
1630
-
1631
- // Has target + actions: use guard (for XState evaluation) + .to (for pending actions).
1632
- // The .to function does NOT re-check the guard — XState's evaluateCandidate
1633
- // already validated it. The .to just stores actions for entry to execute.
1634
- // Map by target state ID so parallel transitions each get their own actions.
491
+ const context = item.context ? x => resolveValue(item.context, 'transitionContext', makeScope(x), '$.transition.context') : undefined;
492
+ const input = item.input !== undefined ? x => resolveValue(item.input, 'input', makeScope(x), '$.transition.input') : undefined;
493
+ const dynamic = !!context || !!item.actions?.length;
1635
494
  return {
1636
- matches: t.matches,
1637
- guard,
1638
- description: t.description,
1639
- reenter: t.reenter,
1640
- meta: t.meta,
1641
- input: t.input !== undefined ? resolveTransitionInput : undefined,
1642
- to: (_x, _enq) => {
1643
- const context = resolveTransitionContext(_x);
1644
- if (t.actions?.length) {
1645
- const targetId = target.replace(/^#/, '');
1646
- pendingTransitionActionsMap[targetId] = t.actions;
1647
- // Track for parallel re-execution (dedup by reference)
1648
- if (!allTransitionActions.includes(t.actions)) {
1649
- allTransitionActions.push(t.actions);
495
+ matches: item.matches,
496
+ target: dynamic ? undefined : item.target,
497
+ to: dynamic ? (x, enq) => {
498
+ const resolvedContext = context?.(x);
499
+ const result = item.actions?.length ? executeActions(item.actions, resolvedContext ? {
500
+ ...x,
501
+ context: {
502
+ ...x.context,
503
+ ...resolvedContext
1650
504
  }
1651
- }
505
+ } : x, enq) : undefined;
1652
506
  return {
1653
- target: targetConfig,
1654
- context,
1655
- reenter: t.reenter
507
+ target: item.target,
508
+ context: result?.context ?? resolvedContext,
509
+ reenter: item.reenter
1656
510
  };
1657
- }
511
+ } : undefined,
512
+ guard: resolveCondition(item.guard, 'guard', '$.transition.guard'),
513
+ description: item.description,
514
+ reenter: item.reenter,
515
+ meta: item.meta,
516
+ input
1658
517
  };
1659
518
  });
1660
519
  }
520
+ function iterInvokeConfigs(invokes) {
521
+ return (Array.isArray(invokes) ? invokes : [invokes]).map(inv => ({
522
+ src: resolvedSources.actors[inv.src] ?? inv.src,
523
+ id: inv.id,
524
+ registryKey: inv.registryKey,
525
+ input: inv.input !== undefined ? args => resolveValue(inv.input, 'input', makeScope(args), '$.invoke.input') : undefined,
526
+ onDone: inv.onDone ? getTransitionConfig(inv.onDone) : undefined,
527
+ onError: inv.onError ? getTransitionConfig(inv.onError) : undefined,
528
+ onSnapshot: inv.onSnapshot ? getTransitionConfig(inv.onSnapshot) : undefined,
529
+ timeout: getDurationConfig(inv.timeout, '$.invoke.timeout'),
530
+ onTimeout: inv.onTimeout ? getTransitionConfig(inv.onTimeout) : undefined
531
+ }));
532
+ }
533
+ function iterNode(node, nodeKey) {
534
+ return {
535
+ id: node.id,
536
+ initial: node.initial,
537
+ type: node.type,
538
+ history: node.history,
539
+ target: node.target,
540
+ description: node.description,
541
+ tags: node.tags,
542
+ input: node.input,
543
+ timeout: getDurationConfig(node.timeout, `$.states.${nodeKey}.timeout`),
544
+ states: node.states ? Object.fromEntries(Object.entries(node.states).map(([key, value]) => [key, iterNode(value, key)])) : undefined,
545
+ on: node.on ? Object.fromEntries(Object.entries(node.on).map(([key, value]) => [key, getTransitionConfig(value)])) : undefined,
546
+ always: node.always ? getTransitionConfig(node.always) : undefined,
547
+ onError: node.onError ? getTransitionConfig(node.onError) : undefined,
548
+ choice: makeChoiceConfig(node.choice, `$.states.${nodeKey}.choice`),
549
+ route: resolveRouteConfig(node.route, `$.states.${nodeKey}.route`),
550
+ after: node.after ? Object.fromEntries(Object.entries(node.after).map(([key, value]) => [key, getTransitionConfig(value)])) : undefined,
551
+ onTimeout: node.onTimeout ? getTransitionConfig(node.onTimeout) : undefined,
552
+ entry: node.entry ? iterActions(node.entry) : undefined,
553
+ exit: node.exit ? iterActions(node.exit) : undefined,
554
+ invoke: node.invoke ? iterInvokeConfigs(node.invoke) : undefined,
555
+ meta: node.meta,
556
+ output: isResolvable(node.output) ? ({
557
+ context,
558
+ event,
559
+ self
560
+ }) => evaluateResolvable(node.output, 'output', {
561
+ context,
562
+ event,
563
+ self
564
+ }, `$.states.${nodeKey}.output`) : node.output
565
+ };
566
+ }
1661
567
  if (json.delays) {
1662
- for (const key of Object.keys(json.delays)) {
1663
- const delay = json.delays[key];
1664
- if (typeof delay === 'number') {
1665
- resolvedSources.delays[key] = delay;
1666
- } else if (typeof delay === 'string') {
1667
- resolvedSources.delays[key] = delayToMs(delay);
1668
- } else if (delay && typeof delay === 'object') {
568
+ for (const [key, delay] of Object.entries(json.delays)) {
569
+ if (typeof delay === 'number') resolvedSources.delays[key] = delay;else if (typeof delay === 'string') resolvedSources.delays[key] = delayToMs(delay);else if (delay && typeof delay === 'object') {
1669
570
  resolvedSources.delays[key] = args => delayToMs(resolveValue(delay.duration, 'delay', makeScope(args), `$.delays.${key}.duration`));
1670
571
  }
1671
572
  }
1672
573
  }
1673
574
  assertMachineJSON(json, resolvedSources, expressionResolver);
1674
- const rootNodeConfig = iterNode(json);
1675
575
  const contextConfig = json.context ? {
1676
576
  context: args => resolveValue(json.context, 'context', args, '$.context')
1677
577
  } : {};
1678
- _scxmlMachineName = json.id || '';
1679
- _scxmlSessionId = 'session_scxml';
1680
- const machine = createMachine({
1681
- ...rootNodeConfig,
578
+ const machine = types$1.createMachine({
579
+ ...iterNode(json),
1682
580
  ...contextConfig,
1683
581
  version: json.version
1684
582
  });
1685
-
1686
- // Register SCXML guard sources
1687
- const providedGuards = {
1688
- 'scxml.cond': ({
1689
- context,
1690
- event,
1691
- self
1692
- }, params) => {
1693
- const expr = params?.expr;
1694
- if (!expr) return true;
1695
- try {
1696
- return !!evaluateExpr(context, expr, event, self);
1697
- } catch (err) {
1698
- // Per SCXML spec, a cond that fails to evaluate is treated as false
1699
- // AND raises error.execution. We can't enqueue from a guard, so
1700
- // queue it for the next entry to drain.
1701
- const message = err instanceof Error ? err.message : typeof err === 'string' ? err : 'unknown error';
1702
- pendingPlatformErrors.push({
1703
- tagname: 'cond',
1704
- message,
1705
- line: NaN,
1706
- column: NaN,
1707
- reason: message
1708
- });
1709
- return false;
1710
- }
1711
- },
1712
- 'xstate.stateIn': (args, params) => {
1713
- const stateId = params?.stateId;
1714
- if (!stateId) return false;
1715
- const normalizedId = stateId.replace(/^#/, '');
1716
- const snapshot = args._snapshot;
1717
- if (snapshot?.nodes) {
1718
- return snapshot.nodes.some(node => node.id === normalizedId);
1719
- }
1720
- return false;
1721
- },
1722
- 'xstate.not': (args, params) => {
1723
- const inner = params?.guard;
1724
- const innerImpl = inner && args.guards?.[inner.type];
1725
- if (!innerImpl) {
1726
- throw new Error(`Guard '${inner?.type}' referenced by 'xstate.not' is not implemented.`);
1727
- }
1728
- return !innerImpl(args, inner.params);
1729
- }
1730
- };
1731
583
  const provided = machine.provide({
1732
584
  actions: resolvedSources.actions,
1733
585
  actors: resolvedSources.actors,
1734
586
  guards: {
1735
- ...providedGuards,
587
+ 'xstate.stateIn': (args, params) => {
588
+ const stateId = params?.stateId;
589
+ const snapshot = args._snapshot;
590
+ return !!stateId && !!snapshot?.nodes?.some(node => node.id === stateId.replace(/^#/, ''));
591
+ },
592
+ 'xstate.not': (args, params) => {
593
+ const inner = params?.guard;
594
+ const impl = inner && args.guards?.[inner.type];
595
+ if (!impl) throw new Error(`Guard '${inner?.type}' referenced by 'xstate.not' is not implemented.`);
596
+ return !impl(args, inner.params);
597
+ },
1736
598
  ...resolvedSources.guards
1737
599
  },
1738
600
  delays: resolvedSources.delays
1739
601
  });
1740
-
1741
- // Keep the original JSON so `serializeMachine(machine)`
1742
- // round-trip losslessly.
1743
602
  provided._json = json;
1744
603
  return provided;
1745
604
  }
@@ -2628,134 +1487,6 @@ function toPromise(actor) {
2628
1487
  });
2629
1488
  }
2630
1489
 
2631
- // this is needed to make JSDoc `@link` work properly
2632
- // oxlint-disable-next-line no-unused-vars
2633
-
2634
- /**
2635
- * @remarks
2636
- * `T | unknown` reduces to `unknown` and that can be problematic when it comes
2637
- * to contextual typing. It especially is a problem when the union has a
2638
- * function member, like here:
2639
- *
2640
- * ```ts
2641
- * declare function test(
2642
- * cbOrVal: ((arg: number) => unknown) | unknown
2643
- * ): void;
2644
- * test((arg) => {}); // oops, implicit any
2645
- * ```
2646
- *
2647
- * This type can be used to avoid this problem. This union represents the same
2648
- * value space as `unknown`.
2649
- */
2650
-
2651
- // https://github.com/microsoft/TypeScript/issues/23182#issuecomment-379091887
2652
-
2653
- // @TODO: we can't use native `NoInfer` as we need those:
2654
- // https://github.com/microsoft/TypeScript/pull/61092
2655
- // https://github.com/microsoft/TypeScript/pull/61077
2656
- // but even with those fixes native NoInfer still doesn't work - further issues have to be reproduced and fixed
2657
-
2658
- /** @deprecated Use the built-in `NoInfer` type instead */
2659
-
2660
- /** The full definition of an event, with a string `type`. */
2661
-
2662
- /**
2663
- * The string or object representing the state value relative to the parent
2664
- * state node.
2665
- *
2666
- * @remarks
2667
- * - For a child atomic state node, this is a string, e.g., `"pending"`.
2668
- * - For complex state nodes, this is an object, e.g., `{ success:
2669
- * "someChildState" }`.
2670
- */
2671
-
2672
- // Accept any StateNode instance regardless of generic parameters
2673
- // Using a union type to handle variance issues with machine.resolveState
2674
-
2675
- let SpecialTargets = /*#__PURE__*/function (SpecialTargets) {
2676
- SpecialTargets["Internal"] = "#_internal";
2677
- return SpecialTargets;
2678
- }({});
2679
-
2680
- /** A deterministic delayed-delivery declaration owned by a logic snapshot. */
2681
-
2682
- /** The logical input delivered to a timer's source when its runtime delay ends. */
2683
-
2684
- /** A persisted snapshot tied to a versioned actor logic identity. */
2685
-
2686
- /**
2687
- * A persisted snapshot restorable into the given actor logic: any snapshot
2688
- * created by logic with the same machine `id` is accepted, regardless of
2689
- * version (version mismatches are handled at runtime, e.g. by `migrate`).
2690
- */
2691
-
2692
- /** @deprecated Use `AnyActor` instead. */
2693
-
2694
- // Based on RxJS types
2695
-
2696
- /**
2697
- * A consumer-facing actor handle.
2698
- *
2699
- * `ActorRef` describes the contract a consumer needs: which events can be sent
2700
- * to the actor, which snapshot it publishes for observation, and which emitted
2701
- * events can be listened to. It intentionally does not expose lifecycle control
2702
- * or runtime internals. A concrete `Actor` satisfies this interface, so APIs
2703
- * should accept `ActorRef` whenever they only need to send events, read
2704
- * snapshots, or listen to emitted events.
2705
- */
2706
-
2707
- /**
2708
- * Runtime-only actor capabilities.
2709
- *
2710
- * These members are needed by the interpreter, scheduler, inspection, and child
2711
- * management code. Public consumer APIs should prefer `ActorRef` unless they
2712
- * genuinely need lifecycle control such as starting, stopping, or accessing
2713
- * system-owned runtime state.
2714
- */
2715
-
2716
- /**
2717
- * A concrete actor instance type.
2718
- *
2719
- * `ActorInstance` combines the consumer `ActorRef` contract with runtime
2720
- * lifecycle capabilities. Values returned by `createActor(...)` and
2721
- * `spawn(...)` naturally satisfy narrower `ActorRef` contracts.
2722
- */
2723
-
2724
- /**
2725
- * The actor's own full self handle.
2726
- *
2727
- * Internals and action/guard sources receive this shape because `self` can
2728
- * participate in runtime-owned behavior while still being usable wherever an
2729
- * `ActorRef` is expected.
2730
- */
2731
-
2732
- // TODO: in v6, this should only accept AnyActorLogic, like ActorRefFromLogic
2733
-
2734
- /** The concrete actor instance type produced from actor logic. */
2735
-
2736
- /**
2737
- * Represents logic which can be used by an actor.
2738
- *
2739
- * @template TSnapshot - The type of the snapshot.
2740
- * @template TEvent - The type of the event object.
2741
- * @template TInput - The type of the input.
2742
- * @template TSystem - The type of the actor system.
2743
- */
2744
-
2745
- // Actors that don't have literal string IDs — these are the only ones
2746
- // that should appear in the index signature fallback, since actors with
2747
- // literal IDs are already covered by ToConcreteChildren.
2748
-
2749
- /** Maps state IDs to their input types based on the StateSchema. */
2750
-
2751
- /** @deprecated */
2752
-
2753
- /** The terminal result published when an actor completes or errors. */
2754
-
2755
- /** An executable effect that publishes an actor's terminal result. */
2756
-
2757
- /** Mappers for subscribeTo - maps lifecycle events to machine events */
2758
-
2759
1490
  const defaultWaitForOptions = {
2760
1491
  timeout: Infinity // much more than 10 seconds
2761
1492
  };
@@ -2888,6 +1619,10 @@ exports.stopActor = createActor.stopActor;
2888
1619
  exports.subscriptionLogic = createActor.subscriptionLogic;
2889
1620
  exports.terminateActor = createActor.terminateActor;
2890
1621
  exports.toObserver = createActor.toObserver;
1622
+ exports.SpecialTargets = types$1.SpecialTargets;
1623
+ exports.createMachine = types$1.createMachine;
1624
+ exports.createStateConfig = types$1.createStateConfig;
1625
+ exports.createFSM = fsm.createFSM;
2891
1626
  exports.StateMachine = StateMachine.StateMachine;
2892
1627
  exports.StateNode = StateMachine.StateNode;
2893
1628
  exports.getEffectDescriptor = effectDescriptor.getEffectDescriptor;
@@ -2897,12 +1632,8 @@ exports.getNextTransitions = effectDescriptor.getNextTransitions;
2897
1632
  exports.initialTransition = effectDescriptor.initialTransition;
2898
1633
  exports.transition = effectDescriptor.transition;
2899
1634
  exports.SimulatedClock = SimulatedClock;
2900
- exports.SpecialTargets = SpecialTargets;
2901
1635
  exports.assertEvent = assertEvent;
2902
- exports.createFSM = createFSM;
2903
- exports.createMachine = createMachine;
2904
1636
  exports.createMachineFromConfig = createMachineFromConfig;
2905
- exports.createStateConfig = createStateConfig;
2906
1637
  exports.createSystem = createSystem;
2907
1638
  exports.isTypeSchema = isTypeSchema;
2908
1639
  exports.machineConfigToJSON = machineConfigToJSON;