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