xstate 6.0.0-alpha.15 → 6.0.0-alpha.16

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 (33) hide show
  1. package/dist/{StateMachine-e3b1aa2d.cjs.js → StateMachine-18299be7.cjs.js} +29 -24
  2. package/dist/{StateMachine-8dbd20ad.esm.js → StateMachine-4a0a8848.esm.js} +29 -24
  3. package/dist/{StateMachine-98411dc5.development.cjs.js → StateMachine-7572fbeb.development.cjs.js} +39 -16
  4. package/dist/{StateMachine-0fa9c094.development.esm.js → StateMachine-dfe616b4.development.esm.js} +39 -16
  5. package/dist/declarations/src/createActor.d.ts +1 -0
  6. package/dist/declarations/src/createMachineFromConfig.d.ts +1 -0
  7. package/dist/declarations/src/transitionActions.d.ts +3 -1
  8. package/dist/declarations/src/types.d.ts +40 -20
  9. package/dist/declarations/src/types.v6.d.ts +7 -1
  10. package/dist/declarations/src/utils.d.ts +2 -2
  11. package/dist/{index-07b19ed0.development.cjs.js → index-4a0afbfa.development.cjs.js} +308 -272
  12. package/dist/{index-362125ce.development.esm.js → index-5d18ec0c.development.esm.js} +308 -273
  13. package/dist/{index-0d940f2c.cjs.js → index-64839116.cjs.js} +307 -271
  14. package/dist/{index-2635a437.esm.js → index-9fc97b9e.esm.js} +307 -272
  15. package/dist/xstate-actors.cjs.js +1 -1
  16. package/dist/xstate-actors.development.cjs.js +1 -1
  17. package/dist/xstate-actors.development.esm.js +1 -1
  18. package/dist/xstate-actors.esm.js +1 -1
  19. package/dist/xstate-actors.umd.min.js +1 -1
  20. package/dist/xstate-actors.umd.min.js.map +1 -1
  21. package/dist/xstate-graph.cjs.js +2 -2
  22. package/dist/xstate-graph.development.cjs.js +2 -2
  23. package/dist/xstate-graph.development.esm.js +2 -2
  24. package/dist/xstate-graph.esm.js +2 -2
  25. package/dist/xstate-graph.umd.min.js +1 -1
  26. package/dist/xstate-graph.umd.min.js.map +1 -1
  27. package/dist/xstate.cjs.js +65 -20
  28. package/dist/xstate.development.cjs.js +65 -20
  29. package/dist/xstate.development.esm.js +67 -22
  30. package/dist/xstate.esm.js +67 -22
  31. package/dist/xstate.umd.min.js +1 -1
  32. package/dist/xstate.umd.min.js.map +1 -1
  33. package/package.json +1 -1
@@ -1,6 +1,6 @@
1
1
  'use strict';
2
2
 
3
- var dist_xstateActors = require('./index-0d940f2c.cjs.js');
3
+ var dist_xstateActors = require('./index-64839116.cjs.js');
4
4
 
5
5
  function createSpawner(actorScope, {
6
6
  machine,
@@ -66,7 +66,6 @@ function memo(object, key, fn) {
66
66
  }
67
67
 
68
68
  const EMPTY_OBJECT = {};
69
- const CHOICE_CONFIG_KEYS = ['invoke', 'after', 'on', 'entry', 'exit', 'always', 'states', 'initial', 'onDone', 'timeout', 'onTimeout', 'history', 'target', 'output'];
70
69
  class StateNode {
71
70
  constructor(/** The raw config used to create the machine. */
72
71
  config, options) {
@@ -246,30 +245,17 @@ class StateNode {
246
245
  function validateStateNodeConfig(stateNode) {
247
246
  const config = stateNode.config;
248
247
  if (stateNode.type !== 'choice') {
249
- if (config.choice !== undefined) {
250
- throw new Error(`State "${stateNode.id}" has \`choice\`, but \`choice\` can only be used with \`type: 'choice'\`.`);
251
- }
252
248
  return;
253
249
  }
254
250
  if (typeof config.choice !== 'function') {
255
- throw new Error(`Choice state "${stateNode.id}" must declare a \`choice\` function.`);
256
- }
257
- for (const key of CHOICE_CONFIG_KEYS) {
258
- if (config[key] !== undefined) {
259
- throw new Error(`Choice state "${stateNode.id}" cannot declare \`${key}\`.`);
260
- }
251
+ throw new Error(`Missing \`choice\` function on "${stateNode.id}"`);
261
252
  }
262
253
  }
263
254
  function formatChoiceTransitions(stateNode) {
264
255
  const choice = stateNode.config.choice;
265
256
  const validateChoiceResult = result => {
266
257
  if (!result || result.target === undefined) {
267
- throw new Error(`Choice state "${stateNode.id}" must resolve to a target.`);
268
- }
269
- for (const key of ['actions', 'to']) {
270
- if (result[key] !== undefined) {
271
- throw new Error(`Choice state "${stateNode.id}" cannot declare \`${key}\` on a choice.`);
272
- }
258
+ throw new Error(`Choice "${stateNode.id}" has no target`);
273
259
  }
274
260
  return result;
275
261
  };
@@ -290,7 +276,7 @@ function formatTransitions(stateNode) {
290
276
  if (stateNode.config.on) {
291
277
  for (const descriptor of Object.keys(stateNode.config.on)) {
292
278
  if (descriptor === dist_xstateActors.NULL_EVENT) {
293
- throw new Error('Null events ("") cannot be specified as a transition key. Use `always: { ... }` instead.');
279
+ throw new Error('Null event transition key');
294
280
  }
295
281
  const transitionsConfig = stateNode.config.on[descriptor];
296
282
  transitions.set(descriptor, mapTransitionConfigs(transitionsConfig, transition => dist_xstateActors.formatTransition(stateNode, descriptor, transition)));
@@ -300,6 +286,10 @@ function formatTransitions(stateNode) {
300
286
  const descriptor = `xstate.done.state.${stateNode.id}`;
301
287
  transitions.set(descriptor, mapTransitionConfigs(stateNode.config.onDone, transition => dist_xstateActors.formatTransition(stateNode, descriptor, transition)));
302
288
  }
289
+ if (stateNode.config.onError) {
290
+ const descriptor = 'xstate.error.*';
291
+ transitions.set(descriptor, mapTransitionConfigs(stateNode.config.onError, transition => dist_xstateActors.formatTransition(stateNode, descriptor, transition)));
292
+ }
303
293
  const createCancelInvokeTimeoutTransition = (descriptor, timeoutEventType) => dist_xstateActors.formatTransition(stateNode, descriptor, {
304
294
  to: (_args, enq) => {
305
295
  enq.cancel(timeoutEventType);
@@ -386,7 +376,7 @@ function formatInitialTransition(stateNode, _target) {
386
376
  const input = typeof _target === 'object' && _target !== null ? _target.input : undefined;
387
377
  const resolvedTarget = typeof targetString === 'string' ? stateNode.states[targetString] : undefined;
388
378
  if (!resolvedTarget && targetString) {
389
- throw new Error(`Initial state node "${targetString}" not found on parent state node #${stateNode.id}`);
379
+ throw new Error(`Initial state "${targetString}" not found on "#${stateNode.id}"`);
390
380
  }
391
381
  const transition = {
392
382
  source: stateNode,
@@ -642,11 +632,26 @@ class StateMachine {
642
632
  const initEvent = dist_xstateActors.createInitEvent(input); // TODO: fix;
643
633
  const internalQueue = [];
644
634
  const preInitialState = this._getPreInitialState(actorScope, initEvent);
645
- const [nextState, initialActions] = dist_xstateActors.initialMicrostep(this.root, preInitialState, actorScope, initEvent, internalQueue);
646
- const {
647
- snapshot: macroState,
648
- microsteps
649
- } = dist_xstateActors.macrostep(nextState, initEvent, actorScope, internalQueue);
635
+ let nextState;
636
+ let initialActions = [];
637
+ let microsteps = [];
638
+ let macroState;
639
+ try {
640
+ [nextState, initialActions] = dist_xstateActors.initialMicrostep(this.root, preInitialState, actorScope, initEvent, internalQueue);
641
+ ({
642
+ snapshot: macroState,
643
+ microsteps
644
+ } = dist_xstateActors.macrostep(nextState, initEvent, actorScope, internalQueue));
645
+ } catch (err) {
646
+ if (!this.root.config.onError) {
647
+ throw err;
648
+ }
649
+ const errorEvent = dist_xstateActors.createErrorPlatformEvent('execution', err);
650
+ const errorMacrostep = dist_xstateActors.macrostep(preInitialState, errorEvent, actorScope, []);
651
+ macroState = errorMacrostep.snapshot;
652
+ microsteps = errorMacrostep.microsteps;
653
+ initialActions = [];
654
+ }
650
655
  return [macroState, [...initialActions, ...microsteps.flatMap(([, actions]) => actions)]];
651
656
  }
652
657
  start(snapshot) {
@@ -1,4 +1,4 @@
1
- import { P as ProcessingStatus, G as resolveReferencedActor, d as createActor, S as STATE_DELIMITER, H as mapValues, t as toArray, I as createInvokeId, J as getDelayedTransitions, K as evaluateCandidate, L as formatTransition, N as NULL_EVENT, M as toTransitionConfigArray, O as createInvokeTimeoutEvent, Q as getCandidates, R as formatRouteTransitions, U as resolveStateValue, V as getAllStateNodes, k as getStateNodes, W as createMachineSnapshot, Y as isInFinalState, e as macrostep, Z as cloneMachineSnapshot, _ as transitionNode, m as matchesEventDescriptor, r as resolveActionsWithContext, f as createInitEvent, g as initialMicrostep, $ as toStatePath, a0 as isStateId, a1 as getStateNodeByPath, a2 as getPersistedSnapshot, a3 as $$ACTOR_TYPE } from './index-2635a437.esm.js';
1
+ import { P as ProcessingStatus, G as resolveReferencedActor, d as createActor, S as STATE_DELIMITER, H as mapValues, t as toArray, I as createInvokeId, J as getDelayedTransitions, K as evaluateCandidate, L as formatTransition, N as NULL_EVENT, M as toTransitionConfigArray, O as createInvokeTimeoutEvent, Q as getCandidates, R as formatRouteTransitions, U as resolveStateValue, V as getAllStateNodes, k as getStateNodes, W as createMachineSnapshot, Y as isInFinalState, e as macrostep, Z as cloneMachineSnapshot, _ as transitionNode, m as matchesEventDescriptor, r as resolveActionsWithContext, f as createInitEvent, g as initialMicrostep, $ as toStatePath, a0 as isStateId, a1 as getStateNodeByPath, a2 as getPersistedSnapshot, a3 as $$ACTOR_TYPE, a4 as createErrorPlatformEvent } from './index-9fc97b9e.esm.js';
2
2
 
3
3
  function createSpawner(actorScope, {
4
4
  machine,
@@ -64,7 +64,6 @@ function memo(object, key, fn) {
64
64
  }
65
65
 
66
66
  const EMPTY_OBJECT = {};
67
- const CHOICE_CONFIG_KEYS = ['invoke', 'after', 'on', 'entry', 'exit', 'always', 'states', 'initial', 'onDone', 'timeout', 'onTimeout', 'history', 'target', 'output'];
68
67
  class StateNode {
69
68
  constructor(/** The raw config used to create the machine. */
70
69
  config, options) {
@@ -244,30 +243,17 @@ class StateNode {
244
243
  function validateStateNodeConfig(stateNode) {
245
244
  const config = stateNode.config;
246
245
  if (stateNode.type !== 'choice') {
247
- if (config.choice !== undefined) {
248
- throw new Error(`State "${stateNode.id}" has \`choice\`, but \`choice\` can only be used with \`type: 'choice'\`.`);
249
- }
250
246
  return;
251
247
  }
252
248
  if (typeof config.choice !== 'function') {
253
- throw new Error(`Choice state "${stateNode.id}" must declare a \`choice\` function.`);
254
- }
255
- for (const key of CHOICE_CONFIG_KEYS) {
256
- if (config[key] !== undefined) {
257
- throw new Error(`Choice state "${stateNode.id}" cannot declare \`${key}\`.`);
258
- }
249
+ throw new Error(`Missing \`choice\` function on "${stateNode.id}"`);
259
250
  }
260
251
  }
261
252
  function formatChoiceTransitions(stateNode) {
262
253
  const choice = stateNode.config.choice;
263
254
  const validateChoiceResult = result => {
264
255
  if (!result || result.target === undefined) {
265
- throw new Error(`Choice state "${stateNode.id}" must resolve to a target.`);
266
- }
267
- for (const key of ['actions', 'to']) {
268
- if (result[key] !== undefined) {
269
- throw new Error(`Choice state "${stateNode.id}" cannot declare \`${key}\` on a choice.`);
270
- }
256
+ throw new Error(`Choice "${stateNode.id}" has no target`);
271
257
  }
272
258
  return result;
273
259
  };
@@ -288,7 +274,7 @@ function formatTransitions(stateNode) {
288
274
  if (stateNode.config.on) {
289
275
  for (const descriptor of Object.keys(stateNode.config.on)) {
290
276
  if (descriptor === NULL_EVENT) {
291
- throw new Error('Null events ("") cannot be specified as a transition key. Use `always: { ... }` instead.');
277
+ throw new Error('Null event transition key');
292
278
  }
293
279
  const transitionsConfig = stateNode.config.on[descriptor];
294
280
  transitions.set(descriptor, mapTransitionConfigs(transitionsConfig, transition => formatTransition(stateNode, descriptor, transition)));
@@ -298,6 +284,10 @@ function formatTransitions(stateNode) {
298
284
  const descriptor = `xstate.done.state.${stateNode.id}`;
299
285
  transitions.set(descriptor, mapTransitionConfigs(stateNode.config.onDone, transition => formatTransition(stateNode, descriptor, transition)));
300
286
  }
287
+ if (stateNode.config.onError) {
288
+ const descriptor = 'xstate.error.*';
289
+ transitions.set(descriptor, mapTransitionConfigs(stateNode.config.onError, transition => formatTransition(stateNode, descriptor, transition)));
290
+ }
301
291
  const createCancelInvokeTimeoutTransition = (descriptor, timeoutEventType) => formatTransition(stateNode, descriptor, {
302
292
  to: (_args, enq) => {
303
293
  enq.cancel(timeoutEventType);
@@ -384,7 +374,7 @@ function formatInitialTransition(stateNode, _target) {
384
374
  const input = typeof _target === 'object' && _target !== null ? _target.input : undefined;
385
375
  const resolvedTarget = typeof targetString === 'string' ? stateNode.states[targetString] : undefined;
386
376
  if (!resolvedTarget && targetString) {
387
- throw new Error(`Initial state node "${targetString}" not found on parent state node #${stateNode.id}`);
377
+ throw new Error(`Initial state "${targetString}" not found on "#${stateNode.id}"`);
388
378
  }
389
379
  const transition = {
390
380
  source: stateNode,
@@ -640,11 +630,26 @@ class StateMachine {
640
630
  const initEvent = createInitEvent(input); // TODO: fix;
641
631
  const internalQueue = [];
642
632
  const preInitialState = this._getPreInitialState(actorScope, initEvent);
643
- const [nextState, initialActions] = initialMicrostep(this.root, preInitialState, actorScope, initEvent, internalQueue);
644
- const {
645
- snapshot: macroState,
646
- microsteps
647
- } = macrostep(nextState, initEvent, actorScope, internalQueue);
633
+ let nextState;
634
+ let initialActions = [];
635
+ let microsteps = [];
636
+ let macroState;
637
+ try {
638
+ [nextState, initialActions] = initialMicrostep(this.root, preInitialState, actorScope, initEvent, internalQueue);
639
+ ({
640
+ snapshot: macroState,
641
+ microsteps
642
+ } = macrostep(nextState, initEvent, actorScope, internalQueue));
643
+ } catch (err) {
644
+ if (!this.root.config.onError) {
645
+ throw err;
646
+ }
647
+ const errorEvent = createErrorPlatformEvent('execution', err);
648
+ const errorMacrostep = macrostep(preInitialState, errorEvent, actorScope, []);
649
+ macroState = errorMacrostep.snapshot;
650
+ microsteps = errorMacrostep.microsteps;
651
+ initialActions = [];
652
+ }
648
653
  return [macroState, [...initialActions, ...microsteps.flatMap(([, actions]) => actions)]];
649
654
  }
650
655
  start(snapshot) {
@@ -1,6 +1,6 @@
1
1
  'use strict';
2
2
 
3
- var dist_xstateActors = require('./index-07b19ed0.development.cjs.js');
3
+ var dist_xstateActors = require('./index-4a0afbfa.development.cjs.js');
4
4
 
5
5
  function createSpawner(actorScope, {
6
6
  machine,
@@ -252,11 +252,13 @@ function validateStateNodeConfig(stateNode) {
252
252
  return;
253
253
  }
254
254
  if (typeof config.choice !== 'function') {
255
- throw new Error(`Choice state "${stateNode.id}" must declare a \`choice\` function.`);
255
+ throw new Error(`Choice state "${stateNode.id}" must declare a \`choice\` function.` );
256
256
  }
257
- for (const key of CHOICE_CONFIG_KEYS) {
258
- if (config[key] !== undefined) {
259
- throw new Error(`Choice state "${stateNode.id}" cannot declare \`${key}\`.`);
257
+ {
258
+ for (const key of CHOICE_CONFIG_KEYS) {
259
+ if (config[key] !== undefined) {
260
+ throw new Error(`Choice state "${stateNode.id}" cannot declare \`${key}\`.`);
261
+ }
260
262
  }
261
263
  }
262
264
  }
@@ -264,11 +266,13 @@ function formatChoiceTransitions(stateNode) {
264
266
  const choice = stateNode.config.choice;
265
267
  const validateChoiceResult = result => {
266
268
  if (!result || result.target === undefined) {
267
- throw new Error(`Choice state "${stateNode.id}" must resolve to a target.`);
269
+ throw new Error(`Choice state "${stateNode.id}" must resolve to a target.` );
268
270
  }
269
- for (const key of ['actions', 'to']) {
270
- if (result[key] !== undefined) {
271
- throw new Error(`Choice state "${stateNode.id}" cannot declare \`${key}\` on a choice.`);
271
+ {
272
+ for (const key of ['actions', 'to']) {
273
+ if (result[key] !== undefined) {
274
+ throw new Error(`Choice state "${stateNode.id}" cannot declare \`${key}\` on a choice.`);
275
+ }
272
276
  }
273
277
  }
274
278
  return result;
@@ -290,7 +294,7 @@ function formatTransitions(stateNode) {
290
294
  if (stateNode.config.on) {
291
295
  for (const descriptor of Object.keys(stateNode.config.on)) {
292
296
  if (descriptor === dist_xstateActors.NULL_EVENT) {
293
- throw new Error('Null events ("") cannot be specified as a transition key. Use `always: { ... }` instead.');
297
+ throw new Error('Null events ("") cannot be specified as a transition key. Use `always: { ... }` instead.' );
294
298
  }
295
299
  const transitionsConfig = stateNode.config.on[descriptor];
296
300
  transitions.set(descriptor, mapTransitionConfigs(transitionsConfig, transition => dist_xstateActors.formatTransition(stateNode, descriptor, transition)));
@@ -300,6 +304,10 @@ function formatTransitions(stateNode) {
300
304
  const descriptor = `xstate.done.state.${stateNode.id}`;
301
305
  transitions.set(descriptor, mapTransitionConfigs(stateNode.config.onDone, transition => dist_xstateActors.formatTransition(stateNode, descriptor, transition)));
302
306
  }
307
+ if (stateNode.config.onError) {
308
+ const descriptor = 'xstate.error.*';
309
+ transitions.set(descriptor, mapTransitionConfigs(stateNode.config.onError, transition => dist_xstateActors.formatTransition(stateNode, descriptor, transition)));
310
+ }
303
311
  const createCancelInvokeTimeoutTransition = (descriptor, timeoutEventType) => dist_xstateActors.formatTransition(stateNode, descriptor, {
304
312
  to: (_args, enq) => {
305
313
  enq.cancel(timeoutEventType);
@@ -386,7 +394,7 @@ function formatInitialTransition(stateNode, _target) {
386
394
  const input = typeof _target === 'object' && _target !== null ? _target.input : undefined;
387
395
  const resolvedTarget = typeof targetString === 'string' ? stateNode.states[targetString] : undefined;
388
396
  if (!resolvedTarget && targetString) {
389
- throw new Error(`Initial state node "${targetString}" not found on parent state node #${stateNode.id}`);
397
+ throw new Error(`Initial state node "${targetString}" not found on parent state node #${stateNode.id}` );
390
398
  }
391
399
  const transition = {
392
400
  source: stateNode,
@@ -656,11 +664,26 @@ class StateMachine {
656
664
  const initEvent = dist_xstateActors.createInitEvent(input); // TODO: fix;
657
665
  const internalQueue = [];
658
666
  const preInitialState = this._getPreInitialState(actorScope, initEvent);
659
- const [nextState, initialActions] = dist_xstateActors.initialMicrostep(this.root, preInitialState, actorScope, initEvent, internalQueue);
660
- const {
661
- snapshot: macroState,
662
- microsteps
663
- } = dist_xstateActors.macrostep(nextState, initEvent, actorScope, internalQueue);
667
+ let nextState;
668
+ let initialActions = [];
669
+ let microsteps = [];
670
+ let macroState;
671
+ try {
672
+ [nextState, initialActions] = dist_xstateActors.initialMicrostep(this.root, preInitialState, actorScope, initEvent, internalQueue);
673
+ ({
674
+ snapshot: macroState,
675
+ microsteps
676
+ } = dist_xstateActors.macrostep(nextState, initEvent, actorScope, internalQueue));
677
+ } catch (err) {
678
+ if (!this.root.config.onError) {
679
+ throw err;
680
+ }
681
+ const errorEvent = dist_xstateActors.createErrorPlatformEvent('execution', err);
682
+ const errorMacrostep = dist_xstateActors.macrostep(preInitialState, errorEvent, actorScope, []);
683
+ macroState = errorMacrostep.snapshot;
684
+ microsteps = errorMacrostep.microsteps;
685
+ initialActions = [];
686
+ }
664
687
  return [macroState, [...initialActions, ...microsteps.flatMap(([, actions]) => actions)]];
665
688
  }
666
689
  start(snapshot) {
@@ -1,4 +1,4 @@
1
- import { P as ProcessingStatus, G as resolveReferencedActor, d as createActor, S as STATE_DELIMITER, H as mapValues, t as toArray, I as createInvokeId, J as getDelayedTransitions, K as evaluateCandidate, L as formatTransition, N as NULL_EVENT, M as toTransitionConfigArray, O as createInvokeTimeoutEvent, Q as getCandidates, R as formatRouteTransitions, U as resolveStateValue, V as getAllStateNodes, k as getStateNodes, W as createMachineSnapshot, Y as isInFinalState, e as macrostep, Z as cloneMachineSnapshot, _ as transitionNode, m as matchesEventDescriptor, r as resolveActionsWithContext, f as createInitEvent, g as initialMicrostep, $ as toStatePath, a0 as isStateId, a1 as getStateNodeByPath, a2 as getPersistedSnapshot, a3 as $$ACTOR_TYPE } from './index-362125ce.development.esm.js';
1
+ import { P as ProcessingStatus, G as resolveReferencedActor, d as createActor, S as STATE_DELIMITER, H as mapValues, t as toArray, I as createInvokeId, J as getDelayedTransitions, K as evaluateCandidate, L as formatTransition, N as NULL_EVENT, M as toTransitionConfigArray, O as createInvokeTimeoutEvent, Q as getCandidates, R as formatRouteTransitions, U as resolveStateValue, V as getAllStateNodes, k as getStateNodes, W as createMachineSnapshot, Y as isInFinalState, e as macrostep, Z as cloneMachineSnapshot, _ as transitionNode, m as matchesEventDescriptor, r as resolveActionsWithContext, f as createInitEvent, g as initialMicrostep, $ as toStatePath, a0 as isStateId, a1 as getStateNodeByPath, a2 as getPersistedSnapshot, a3 as $$ACTOR_TYPE, a4 as createErrorPlatformEvent } from './index-5d18ec0c.development.esm.js';
2
2
 
3
3
  function createSpawner(actorScope, {
4
4
  machine,
@@ -250,11 +250,13 @@ function validateStateNodeConfig(stateNode) {
250
250
  return;
251
251
  }
252
252
  if (typeof config.choice !== 'function') {
253
- throw new Error(`Choice state "${stateNode.id}" must declare a \`choice\` function.`);
253
+ throw new Error(`Choice state "${stateNode.id}" must declare a \`choice\` function.` );
254
254
  }
255
- for (const key of CHOICE_CONFIG_KEYS) {
256
- if (config[key] !== undefined) {
257
- throw new Error(`Choice state "${stateNode.id}" cannot declare \`${key}\`.`);
255
+ {
256
+ for (const key of CHOICE_CONFIG_KEYS) {
257
+ if (config[key] !== undefined) {
258
+ throw new Error(`Choice state "${stateNode.id}" cannot declare \`${key}\`.`);
259
+ }
258
260
  }
259
261
  }
260
262
  }
@@ -262,11 +264,13 @@ function formatChoiceTransitions(stateNode) {
262
264
  const choice = stateNode.config.choice;
263
265
  const validateChoiceResult = result => {
264
266
  if (!result || result.target === undefined) {
265
- throw new Error(`Choice state "${stateNode.id}" must resolve to a target.`);
267
+ throw new Error(`Choice state "${stateNode.id}" must resolve to a target.` );
266
268
  }
267
- for (const key of ['actions', 'to']) {
268
- if (result[key] !== undefined) {
269
- throw new Error(`Choice state "${stateNode.id}" cannot declare \`${key}\` on a choice.`);
269
+ {
270
+ for (const key of ['actions', 'to']) {
271
+ if (result[key] !== undefined) {
272
+ throw new Error(`Choice state "${stateNode.id}" cannot declare \`${key}\` on a choice.`);
273
+ }
270
274
  }
271
275
  }
272
276
  return result;
@@ -288,7 +292,7 @@ function formatTransitions(stateNode) {
288
292
  if (stateNode.config.on) {
289
293
  for (const descriptor of Object.keys(stateNode.config.on)) {
290
294
  if (descriptor === NULL_EVENT) {
291
- throw new Error('Null events ("") cannot be specified as a transition key. Use `always: { ... }` instead.');
295
+ throw new Error('Null events ("") cannot be specified as a transition key. Use `always: { ... }` instead.' );
292
296
  }
293
297
  const transitionsConfig = stateNode.config.on[descriptor];
294
298
  transitions.set(descriptor, mapTransitionConfigs(transitionsConfig, transition => formatTransition(stateNode, descriptor, transition)));
@@ -298,6 +302,10 @@ function formatTransitions(stateNode) {
298
302
  const descriptor = `xstate.done.state.${stateNode.id}`;
299
303
  transitions.set(descriptor, mapTransitionConfigs(stateNode.config.onDone, transition => formatTransition(stateNode, descriptor, transition)));
300
304
  }
305
+ if (stateNode.config.onError) {
306
+ const descriptor = 'xstate.error.*';
307
+ transitions.set(descriptor, mapTransitionConfigs(stateNode.config.onError, transition => formatTransition(stateNode, descriptor, transition)));
308
+ }
301
309
  const createCancelInvokeTimeoutTransition = (descriptor, timeoutEventType) => formatTransition(stateNode, descriptor, {
302
310
  to: (_args, enq) => {
303
311
  enq.cancel(timeoutEventType);
@@ -384,7 +392,7 @@ function formatInitialTransition(stateNode, _target) {
384
392
  const input = typeof _target === 'object' && _target !== null ? _target.input : undefined;
385
393
  const resolvedTarget = typeof targetString === 'string' ? stateNode.states[targetString] : undefined;
386
394
  if (!resolvedTarget && targetString) {
387
- throw new Error(`Initial state node "${targetString}" not found on parent state node #${stateNode.id}`);
395
+ throw new Error(`Initial state node "${targetString}" not found on parent state node #${stateNode.id}` );
388
396
  }
389
397
  const transition = {
390
398
  source: stateNode,
@@ -654,11 +662,26 @@ class StateMachine {
654
662
  const initEvent = createInitEvent(input); // TODO: fix;
655
663
  const internalQueue = [];
656
664
  const preInitialState = this._getPreInitialState(actorScope, initEvent);
657
- const [nextState, initialActions] = initialMicrostep(this.root, preInitialState, actorScope, initEvent, internalQueue);
658
- const {
659
- snapshot: macroState,
660
- microsteps
661
- } = macrostep(nextState, initEvent, actorScope, internalQueue);
665
+ let nextState;
666
+ let initialActions = [];
667
+ let microsteps = [];
668
+ let macroState;
669
+ try {
670
+ [nextState, initialActions] = initialMicrostep(this.root, preInitialState, actorScope, initEvent, internalQueue);
671
+ ({
672
+ snapshot: macroState,
673
+ microsteps
674
+ } = macrostep(nextState, initEvent, actorScope, internalQueue));
675
+ } catch (err) {
676
+ if (!this.root.config.onError) {
677
+ throw err;
678
+ }
679
+ const errorEvent = createErrorPlatformEvent('execution', err);
680
+ const errorMacrostep = macrostep(preInitialState, errorEvent, actorScope, []);
681
+ macroState = errorMacrostep.snapshot;
682
+ microsteps = errorMacrostep.microsteps;
683
+ initialActions = [];
684
+ }
662
685
  return [macroState, [...initialActions, ...microsteps.flatMap(([, actions]) => actions)]];
663
686
  }
664
687
  start(snapshot) {
@@ -58,6 +58,7 @@ export declare class Actor<TLogic extends AnyActorLogic> implements ActorInstanc
58
58
  private _deferred;
59
59
  private _pendingEffects?;
60
60
  private _setErrorSnapshot;
61
+ private _tryHandleExecutionError;
61
62
  private _next;
62
63
  private update;
63
64
  private _flushInitialEffects;
@@ -145,6 +145,7 @@ export interface StateNodeJSON {
145
145
  initial?: string;
146
146
  states?: Record<string, StateNodeJSON>;
147
147
  on?: Record<string, TransitionConfigJSON | TransitionConfigJSON[]>;
148
+ onError?: TransitionConfigJSON | TransitionConfigJSON[];
148
149
  after?: Record<string, TransitionConfigJSON | TransitionConfigJSON[]>;
149
150
  always?: TransitionConfigJSON | TransitionConfigJSON[];
150
151
  choice?: ChoiceBranchJSON[] | ResolvableJSON;
@@ -1,4 +1,6 @@
1
- import type { AnyAction, AnyActorScope, AnyEventObject, AnyMachineSnapshot, EnqueueObject, EventObject, ExecutableActionObject, SpecialExecutableAction } from "./types.js";
1
+ import type { AnyAction, AnyActorScope, AnyEventObject, AnyMachineSnapshot, EnqueueObject, EventObject, ExecutableActionObject, MachineContext, SpecialExecutableAction } from "./types.js";
2
+ export declare function mergeContextPatch(context: MachineContext, patch: MachineContext): MachineContext;
2
3
  export declare function createTransitionEnqueue(actorScope: AnyActorScope, actions: any[], internalEvents: EventObject[], actorSubscriptions?: boolean, createActors?: boolean): EnqueueObject<any, any>;
3
4
  export declare function isBuiltInExecutableAction(action: ExecutableActionObject): action is SpecialExecutableAction;
4
5
  export declare function resolveActionsWithContext(currentSnapshot: AnyMachineSnapshot, event: AnyEventObject, actorScope: AnyActorScope, actions: AnyAction[]): [AnyMachineSnapshot, ExecutableActionObject[]];
6
+ export declare function createEnqueueObject(props: Partial<EnqueueObject<any, any>>, action: <T extends (...args: any[]) => any>(fn: T, ...args: Parameters<T>) => void): EnqueueObject<any, any>;
@@ -328,20 +328,23 @@ export type AnyInvokeConfig = InvokeConfig<any, any, any, any, any, any, any, an
328
328
  export type AnyStateNodeConfig = Next_StateNodeConfig<any, any, any, any, any, any, any, any, any, any, any, any>;
329
329
  export type AnyStateNode = StateNode<any, any> | StateNode<never, EventObject> | StateNode<any, EventObject> | StateNode<never, any>;
330
330
  export type AnyMachineSnapshot = MachineSnapshot<any, any, any, any, any, any, any, any>;
331
- export type AnyStateMachine = StateMachine<any, // context
332
- any, // event
333
- any, // children
334
- any, // state value
335
- any, // tag
336
- any, // input
337
- any, // output
338
- any, // emitted
339
- any, // TMeta
340
- any, // TStateSchema,
341
- any, // TActionMap,
342
- any, // TActorMap
343
- any, // TGuardMap
344
- any>;
331
+ export interface AnyStateMachine extends AnyActorLogic {
332
+ id: string;
333
+ root: AnyStateNode;
334
+ options?: {
335
+ maxIterations?: number;
336
+ };
337
+ states: StateNodesConfig<any, any>;
338
+ events: Array<EventDescriptor<any>>;
339
+ implementations: Implementations;
340
+ config: any;
341
+ version?: string;
342
+ provide(implementations: any): AnyStateMachine;
343
+ resolveState(config: any): any;
344
+ getTransitionData(snapshot: any, event: any, actor: AnyActorRef): AnyTransitionDefinition[];
345
+ getStateNodeById(stateId: string): AnyStateNode;
346
+ getPersistedSnapshot(snapshot: any, options?: unknown): Snapshot<unknown>;
347
+ }
345
348
  export type AnyStateConfig = StateConfig<any, AnyEventObject>;
346
349
  export type DelayConfig<TContext extends MachineContext, TExpressionEvent extends EventObject> = number | DelayExpr<TContext, TExpressionEvent>;
347
350
  export type InitialContext<TContext extends MachineContext, TActorMap extends Implementations['actorSources'], TInput, TEvent extends EventObject> = TContext | ContextFactory<TContext, TActorMap, TInput, TEvent>;
@@ -410,6 +413,11 @@ export interface ErrorActorEvent<TErrorData = unknown, TId extends string = stri
410
413
  error: TErrorData;
411
414
  actorId: TId;
412
415
  }
416
+ export interface ErrorPlatformEvent<TErrorData = unknown, TKind extends string = string> extends EventObject {
417
+ type: `xstate.error.${TKind}`;
418
+ error: TErrorData;
419
+ }
420
+ export type ErrorEvent = ErrorActorEvent | ErrorPlatformEvent;
413
421
  export interface SnapshotEvent<TSnapshot extends Snapshot<unknown> = Snapshot<unknown>> extends EventObject {
414
422
  type: `xstate.snapshot.${string}`;
415
423
  snapshot: TSnapshot;
@@ -869,19 +877,30 @@ in TInput = NonReducibleUnknown, TSystem extends AnyActorSystem = AnyActorSystem
869
877
  * @returns The a representation of the internal state to be persisted.
870
878
  */
871
879
  getPersistedSnapshot: (snapshot: TSnapshot, options?: unknown) => Snapshot<unknown>;
880
+ /**
881
+ * Executes the non-action effects returned from `transition` (e.g. the
882
+ * effects produced by `createLogic`-based actors). Actor logic that never
883
+ * returns such effects can omit this.
884
+ */
885
+ executeEffects?: (effects: readonly unknown[], actorScope: ActorScope<TSnapshot, TEvent, TSystem, TEmitted>) => void;
886
+ }
887
+ export interface AnyActorLogic {
888
+ config?: unknown;
889
+ transition(snapshot: any, event: any, actorScope: any): ActorLogicTransitionResult<any>;
890
+ initialTransition(input: any, actorScope: any): ActorLogicTransitionResult<any>;
891
+ getInitialSnapshot(actorScope: any, input: any): any;
892
+ restoreSnapshot?(persistedState: Snapshot<unknown>, actorScope: any): any;
893
+ start?(snapshot: any, actorScope: any): void;
894
+ getPersistedSnapshot(snapshot: any, options?: unknown): Snapshot<unknown>;
895
+ executeEffects?(effects: readonly unknown[], actorScope: any): void;
872
896
  }
873
- export type AnyActorLogic = ActorLogic<any, // snapshot
874
- any, // event
875
- any, // input
876
- any, // system
877
- any>;
878
897
  export type UnknownActorLogic = ActorLogic<any, // snapshot
879
898
  any, // event
880
899
  any, // input
881
900
  AnyActorSystem, any>;
882
901
  export type SnapshotFrom<T> = ReturnTypeOrValue<T> extends infer R ? R extends ActorRef<infer TSnapshot, infer _, infer __> ? TSnapshot : R extends Actor<infer TLogic> ? SnapshotFrom<TLogic> : R extends ActorLogic<infer TSnapshot, infer _TEvent, infer _TInput, infer _TSystem, infer _TEmitted> ? TSnapshot : R extends ActorScope<infer TSnapshot, infer _TEvent, infer _TEmitted, infer _TSystem> ? TSnapshot : never : never;
883
902
  export type EventFromLogic<TLogic extends AnyActorLogic> = TLogic extends ActorLogic<infer _TSnapshot, infer TEvent, infer _TInput, infer _TSystem, infer _TEmitted> ? TEvent : never;
884
- export type EmittedFrom<TLogic extends AnyActorLogic> = TLogic extends ActorLogic<infer _TSnapshot, infer _TEvent, infer _TInput, infer _TSystem, infer TEmitted> ? TEmitted : never;
903
+ export type EmittedFrom<TLogic extends AnyActorLogic> = TLogic extends StateMachine<infer _TContext, infer _TEvent, infer _TChildren, infer _TStateValue, infer _TTag, infer _TInput, infer _TOutput, infer TEmitted, infer _TMeta, infer _TStateSchema, infer _TActionMap, infer _TActorMap, infer _TGuardMap, infer _TDelayMap> ? TEmitted : [TLogic] extends [AnyStateMachine] ? AnyEventObject : TLogic extends ActorLogic<infer _TSnapshot, infer _TEvent, infer _TInput, infer _TSystem, infer TEmitted> ? TEmitted : AnyEventObject;
885
904
  type ResolveEventType<T> = T extends infer R ? R extends StateMachine<infer _TContext, infer TEvent, infer _TChildren, infer _TStateValue, infer _TTag, infer _TInput, infer _TOutput, infer _TEmitted, infer _TMeta, infer _TConfig, infer _TActionMap, infer _TActorMap, infer _TGuardMap, infer _TDelayMap> ? TEvent : R extends MachineSnapshot<infer _TContext, infer TEvent, infer _TChildren, infer _TStateValue, infer _TTag, infer _TOutput, infer _TMeta, infer _TStateSchema> ? TEvent : R extends ActorRef<infer _TSnapshot, infer TEvent, infer _TEmitted> ? TEvent : never : never;
886
905
  export type EventFrom<T, K extends Prop<TEvent, 'type'> = never, TEvent extends EventObject = ResolveEventType<T>> = IsNever<K> extends true ? TEvent : ExtractEvent<TEvent, K>;
887
906
  export type ContextFrom<T> = T extends StateMachine<infer TContext, infer _TEvent, infer _TChildren, infer _TStateValue, infer _TTag, infer _TInput, infer _TOutput, infer _TEmitted, infer _TMeta, infer _TConfig, infer _TActionMap, infer _TActorMap, infer _TGuardMap, infer _TDelayMap> ? TContext : T extends MachineSnapshot<infer TContext, infer _TEvent, infer _TChildren, infer _TStateValue, infer _TTag, infer _TOutput, infer _TMeta, infer _TStateSchema> ? TContext : T extends Actor<infer TActorLogic> ? TActorLogic extends AnyStateMachine ? ContextFrom<TActorLogic> : never : never;
@@ -927,6 +946,7 @@ export type StateSchema = {
927
946
  entry?: unknown;
928
947
  exit?: unknown;
929
948
  onDone?: unknown;
949
+ onError?: unknown;
930
950
  after?: unknown;
931
951
  always?: unknown;
932
952
  choice?: unknown;
@@ -1,6 +1,6 @@
1
1
  import { StandardSchemaV1 } from "./schema.types.js";
2
2
  import { MachineSnapshot } from "./State.js";
3
- import { Action, ActorLogic, ActorRef, ActorRefFromLogic, ActorSelf, AnyActorLogic, AnyActorRef, Compute, DoneActorEvent, DoNotInfer, ErrorActorEvent, EventDescriptor, EventObject, ExtractEvent, InitialContext, InputFrom, IsNever, MetaObject, NonReducibleUnknown, OutputFrom, SingleOrArray, SnapshotEvent, StateValue, TODO, TransitionContextMapper, TransitionContextPatch, TransitionConfigFunction, Values, AnyStateNode, SystemRegistry } from "./types.js";
3
+ import { Action, ActorLogic, ActorRef, ActorRefFromLogic, ActorSelf, AnyActorLogic, AnyActorRef, Compute, DoneActorEvent, DoNotInfer, ErrorActorEvent, EventDescriptor, ErrorEvent, EventObject, ExtractEvent, InitialContext, InputFrom, IsNever, MetaObject, NonReducibleUnknown, OutputFrom, SingleOrArray, SnapshotEvent, StateValue, TODO, TransitionContextMapper, TransitionContextPatch, TransitionConfigFunction, Values, AnyStateNode, SystemRegistry } from "./types.js";
4
4
  import { MachineContext, Mapper } from "./types.js";
5
5
  import { LowInfer } from "./types.js";
6
6
  import { DoneStateEvent } from "./types.js";
@@ -277,6 +277,7 @@ interface Next_ChoiceStateNodeConfig<TContext extends MachineContext, TEvent ext
277
277
  entry?: never;
278
278
  exit?: never;
279
279
  onDone?: never;
280
+ onError?: never;
280
281
  after?: never;
281
282
  timeout?: never;
282
283
  onTimeout?: never;
@@ -341,6 +342,11 @@ interface Next_RegularStateNodeConfig<TContext extends MachineContext, TEvent ex
341
342
  * node's `on` property.
342
343
  */
343
344
  onDone?: Next_TransitionConfigOrTarget<TContext, DoneStateEvent, TEvent, TEmitted, TActionMap, TActorMap, TGuardMap, TDelayMap, TMeta>;
345
+ /**
346
+ * The transition to take when an `xstate.error.*` event is raised while this
347
+ * state node or one of its descendants is active.
348
+ */
349
+ onError?: Next_TransitionConfigOrTarget<TContext, ErrorEvent, TEvent, TEmitted, TActionMap, TActorMap, TGuardMap, TDelayMap, TMeta>;
344
350
  /**
345
351
  * The mapping (or array) of delays (in milliseconds) to their potential
346
352
  * transition(s). The delayed transitions are taken after the specified delay
@@ -1,5 +1,5 @@
1
1
  import type { StateNode } from "./StateNode.js";
2
- import type { AnyActor, AnyEventObject, AnyMachineSnapshot, AnyStateMachine, AnyTransitionConfig, AnyTransitionConfigFunction, ErrorActorEvent, EventObject, MachineContext, Mapper, NonReducibleUnknown, Observer, OutputArg, SingleOrArray, StateValue, TransitionConfigTarget } from "./types.js";
2
+ import type { AnyActor, AnyEventObject, AnyMachineSnapshot, AnyStateMachine, AnyTransitionConfig, AnyTransitionConfigFunction, ErrorEvent, EventObject, MachineContext, Mapper, NonReducibleUnknown, Observer, OutputArg, SingleOrArray, StateValue, TransitionConfigTarget } from "./types.js";
3
3
  export declare function matchesState(parentStateId: StateValue, childStateId: StateValue): boolean;
4
4
  export declare function checkStateIn(snapshot: AnyMachineSnapshot, stateValue: StateValue): boolean;
5
5
  export declare function toStatePath(stateId: string | string[]): string[];
@@ -10,7 +10,7 @@ export declare function mapValues<P, O extends Record<string, unknown>>(collecti
10
10
  export declare function toArray<T>(value: readonly T[] | T | undefined): readonly T[];
11
11
  export declare function resolveOutput<TContext extends MachineContext, TExpressionEvent extends EventObject>(mapper: Mapper<TContext, TExpressionEvent, unknown, EventObject> | NonReducibleUnknown, context: TContext, event: TExpressionEvent, self: AnyActor): unknown;
12
12
  export declare function getEventOutput<TEvent extends EventObject>(event: TEvent): OutputArg<TEvent>['output'];
13
- export declare function isErrorActorEvent(event: AnyEventObject): event is ErrorActorEvent;
13
+ export declare function isErrorEvent(event: AnyEventObject): event is ErrorEvent;
14
14
  export declare function toTransitionConfigArray(configLike: SingleOrArray<AnyTransitionConfig | TransitionConfigTarget | AnyTransitionConfigFunction>): Array<AnyTransitionConfig>;
15
15
  export declare function normalizeTarget<TContext extends MachineContext, TEvent extends EventObject>(target: SingleOrArray<string | StateNode<TContext, TEvent>> | undefined): ReadonlyArray<string | StateNode<TContext, TEvent>> | undefined;
16
16
  export declare function toObserver<T>(nextHandler?: Observer<T> | ((value: T) => void), errorHandler?: (error: any) => void, completionHandler?: () => void): Observer<T>;