xstate 5.0.0-beta.34 → 5.0.0-beta.35

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 (40) hide show
  1. package/README.md +1 -1
  2. package/actions/dist/xstate-actions.cjs.js +3 -3
  3. package/actions/dist/xstate-actions.development.cjs.js +3 -3
  4. package/actions/dist/xstate-actions.development.esm.js +3 -3
  5. package/actions/dist/xstate-actions.esm.js +3 -3
  6. package/actions/dist/xstate-actions.umd.min.js +1 -1
  7. package/actions/dist/xstate-actions.umd.min.js.map +1 -1
  8. package/actors/dist/xstate-actors.cjs.js +1 -1
  9. package/actors/dist/xstate-actors.development.cjs.js +1 -1
  10. package/actors/dist/xstate-actors.development.esm.js +1 -1
  11. package/actors/dist/xstate-actors.esm.js +1 -1
  12. package/actors/dist/xstate-actors.umd.min.js +1 -1
  13. package/actors/dist/xstate-actors.umd.min.js.map +1 -1
  14. package/dist/declarations/src/interpreter.d.ts +2 -0
  15. package/dist/declarations/src/stateUtils.d.ts +5 -4
  16. package/dist/declarations/src/types.d.ts +3 -5
  17. package/dist/{interpreter-dee56dc8.development.esm.js → interpreter-5c4e6634.development.esm.js} +59 -57
  18. package/dist/{interpreter-1301970f.cjs.js → interpreter-69605bf0.cjs.js} +59 -57
  19. package/dist/{interpreter-70ed62f2.development.cjs.js → interpreter-d3567419.development.cjs.js} +59 -57
  20. package/dist/{interpreter-83f7f2d4.esm.js → interpreter-de5217bc.esm.js} +59 -57
  21. package/dist/{raise-1dd65455.cjs.js → raise-0ff57677.cjs.js} +100 -99
  22. package/dist/{raise-38b707c0.development.cjs.js → raise-26e4d83c.development.cjs.js} +103 -99
  23. package/dist/{raise-b5cfe1bb.esm.js → raise-511399cc.esm.js} +100 -99
  24. package/dist/{raise-05f8b2a6.development.esm.js → raise-cdcdf834.development.esm.js} +103 -99
  25. package/dist/{send-fe94de2b.cjs.js → send-19ffc568.cjs.js} +4 -2
  26. package/dist/{send-9526366e.development.esm.js → send-1de74f4d.development.esm.js} +4 -2
  27. package/dist/{send-0b5eda0c.esm.js → send-211a2a94.esm.js} +4 -2
  28. package/dist/{send-3764c866.development.cjs.js → send-894c4b18.development.cjs.js} +4 -2
  29. package/dist/xstate.cjs.js +26 -7
  30. package/dist/xstate.development.cjs.js +26 -7
  31. package/dist/xstate.development.esm.js +29 -10
  32. package/dist/xstate.esm.js +29 -10
  33. package/dist/xstate.umd.min.js +1 -1
  34. package/dist/xstate.umd.min.js.map +1 -1
  35. package/guards/dist/xstate-guards.cjs.js +2 -2
  36. package/guards/dist/xstate-guards.development.cjs.js +2 -2
  37. package/guards/dist/xstate-guards.development.esm.js +2 -2
  38. package/guards/dist/xstate-guards.esm.js +2 -2
  39. package/guards/dist/xstate-guards.umd.min.js.map +1 -1
  40. package/package.json +1 -1
@@ -1,6 +1,6 @@
1
1
  'use strict';
2
2
 
3
- var interpreter = require('./interpreter-70ed62f2.development.cjs.js');
3
+ var interpreter = require('./interpreter-d3567419.development.cjs.js');
4
4
 
5
5
  const cache = new WeakMap();
6
6
  function memo(object, key, fn) {
@@ -299,20 +299,6 @@ function evaluateGuard(guard, context, event, state) {
299
299
  );
300
300
  }
301
301
 
302
- function getOutput(configuration, context, event, self) {
303
- const {
304
- machine
305
- } = configuration[0];
306
- const {
307
- root
308
- } = machine;
309
- if (!root.output) {
310
- return undefined;
311
- }
312
- const finalChildStateNode = configuration.find(stateNode => stateNode.type === 'final' && stateNode.parent === machine.root);
313
- const doneStateEvent = interpreter.createDoneStateEvent(finalChildStateNode.id, finalChildStateNode.output ? interpreter.resolveOutput(finalChildStateNode.output, context, event, self) : undefined);
314
- return interpreter.resolveOutput(root.output, context, doneStateEvent, self);
315
- }
316
302
  const isAtomicStateNode = stateNode => stateNode.type === 'atomic' || stateNode.type === 'final';
317
303
  function getChildren(stateNode) {
318
304
  return Object.values(stateNode.states).filter(sn => sn.type !== 'history');
@@ -337,7 +323,7 @@ function getConfiguration(stateNodes) {
337
323
  for (const s of configuration) {
338
324
  // if previously active, add existing child nodes
339
325
  if (s.type === 'compound' && (!adjList.get(s) || !adjList.get(s).length)) {
340
- getInitialStateNodes(s).forEach(sn => configurationSet.add(sn));
326
+ getInitialStateNodesWithTheirAncestors(s).forEach(sn => configurationSet.add(sn));
341
327
  } else {
342
328
  if (s.type === 'parallel') {
343
329
  for (const child of getChildren(s)) {
@@ -345,7 +331,8 @@ function getConfiguration(stateNodes) {
345
331
  continue;
346
332
  }
347
333
  if (!configurationSet.has(child)) {
348
- for (const initialStateNode of getInitialStateNodes(child)) {
334
+ const initialStates = getInitialStateNodesWithTheirAncestors(child);
335
+ for (const initialStateNode of initialStates) {
349
336
  configurationSet.add(initialStateNode);
350
337
  }
351
338
  }
@@ -405,14 +392,14 @@ function getStateValue(rootNode, configuration) {
405
392
  const config = getConfiguration(configuration);
406
393
  return getValueFromAdj(rootNode, getAdjList(config));
407
394
  }
408
- function isInFinalState(configuration, stateNode = configuration[0].machine.root) {
395
+ function isInFinalState(configuration, stateNode) {
409
396
  if (stateNode.type === 'compound') {
410
- return getChildren(stateNode).some(s => s.type === 'final' && configuration.includes(s));
397
+ return getChildren(stateNode).some(s => s.type === 'final' && configuration.has(s));
411
398
  }
412
399
  if (stateNode.type === 'parallel') {
413
400
  return getChildren(stateNode).every(sn => isInFinalState(configuration, sn));
414
401
  }
415
- return false;
402
+ return stateNode.type === 'final';
416
403
  }
417
404
  const isStateId = str => str[0] === interpreter.STATE_IDENTIFIER;
418
405
  function getCandidates(stateNode, receivedEventType) {
@@ -468,13 +455,7 @@ function getDelayedTransitions(stateNode) {
468
455
  stateNode.exit.push(cancel(eventType));
469
456
  return eventType;
470
457
  };
471
- const delayedTransitions = interpreter.isArray(afterConfig) ? afterConfig.map((transition, i) => {
472
- const eventType = mutateEntryExit(transition.delay, i);
473
- return {
474
- ...transition,
475
- event: eventType
476
- };
477
- }) : Object.keys(afterConfig).flatMap((delay, i) => {
458
+ const delayedTransitions = Object.keys(afterConfig).flatMap((delay, i) => {
478
459
  const configTransition = afterConfig[delay];
479
460
  const resolvedTransition = typeof configTransition === 'string' ? {
480
461
  target: configTransition
@@ -562,43 +543,23 @@ function formatTransitions(stateNode) {
562
543
  return transitions;
563
544
  }
564
545
  function formatInitialTransition(stateNode, _target) {
565
- if (typeof _target === 'string' || interpreter.isArray(_target)) {
566
- const targets = interpreter.toArray(_target).map(t => {
567
- // Resolve state string keys (which represent children)
568
- // to their state node
569
- const descStateNode = typeof t === 'string' ? isStateId(t) ? stateNode.machine.getStateNodeById(t) : stateNode.states[t] : t;
570
- if (!descStateNode) {
571
- throw new Error(`Initial state node "${t}" not found on parent state node #${stateNode.id}`);
572
- }
573
- if (!isDescendant(descStateNode, stateNode)) {
574
- throw new Error(`Invalid initial target: state node #${descStateNode.id} is not a descendant of #${stateNode.id}`);
575
- }
576
- return descStateNode;
577
- });
578
- const resolvedTarget = resolveTarget(stateNode, targets);
579
- const transition = {
580
- source: stateNode,
581
- actions: [],
582
- eventType: null,
583
- reenter: false,
584
- target: resolvedTarget,
585
- toJSON: () => ({
586
- ...transition,
587
- source: `#${stateNode.id}`,
588
- target: resolvedTarget ? resolvedTarget.map(t => `#${t.id}`) : undefined
589
- })
590
- };
591
- return transition;
546
+ const resolvedTarget = typeof _target === 'string' ? stateNode.states[_target] : _target ? stateNode.states[_target.target] : undefined;
547
+ if (!resolvedTarget && _target) {
548
+ throw new Error(`Initial state node "${_target}" not found on parent state node #${stateNode.id}`);
592
549
  }
593
- return formatTransition(stateNode, '__INITIAL__', {
594
- target: interpreter.toArray(_target.target).map(t => {
595
- if (typeof t === 'string') {
596
- return isStateId(t) ? t : `${interpreter.STATE_DELIMITER}${t}`;
597
- }
598
- return t;
599
- }),
600
- actions: _target.actions
601
- });
550
+ const transition = {
551
+ source: stateNode,
552
+ actions: !_target || typeof _target === 'string' ? [] : interpreter.toArray(_target.actions),
553
+ eventType: null,
554
+ reenter: false,
555
+ target: resolvedTarget ? [resolvedTarget] : [],
556
+ toJSON: () => ({
557
+ ...transition,
558
+ source: `#${stateNode.id}`,
559
+ target: resolvedTarget ? [`#${resolvedTarget.id}`] : []
560
+ })
561
+ };
562
+ return transition;
602
563
  }
603
564
  function resolveTarget(stateNode, targets) {
604
565
  if (targets === undefined) {
@@ -641,6 +602,15 @@ function resolveHistoryTarget(stateNode) {
641
602
  function isHistoryNode(stateNode) {
642
603
  return stateNode.type === 'history';
643
604
  }
605
+ function getInitialStateNodesWithTheirAncestors(stateNode) {
606
+ const states = getInitialStateNodes(stateNode);
607
+ for (const initialState of states) {
608
+ for (const ancestor of getProperAncestors(initialState, stateNode)) {
609
+ states.add(ancestor);
610
+ }
611
+ }
612
+ return states;
613
+ }
644
614
  function getInitialStateNodes(stateNode) {
645
615
  const set = new Set();
646
616
  function iter(descStateNode) {
@@ -649,12 +619,7 @@ function getInitialStateNodes(stateNode) {
649
619
  }
650
620
  set.add(descStateNode);
651
621
  if (descStateNode.type === 'compound') {
652
- for (const targetStateNode of descStateNode.initial.target) {
653
- for (const a of getProperAncestors(targetStateNode, stateNode)) {
654
- set.add(a);
655
- }
656
- iter(targetStateNode);
657
- }
622
+ iter(descStateNode.initial.target[0]);
658
623
  } else if (descStateNode.type === 'parallel') {
659
624
  for (const child of getChildren(descStateNode)) {
660
625
  iter(child);
@@ -662,7 +627,7 @@ function getInitialStateNodes(stateNode) {
662
627
  }
663
628
  }
664
629
  iter(stateNode);
665
- return [...set];
630
+ return set;
666
631
  }
667
632
  /**
668
633
  * Returns the child state node from its relative `stateKey`, or throws.
@@ -940,21 +905,15 @@ function microstepProcedure(transitions, currentState, mutConfiguration, event,
940
905
  // Enter states
941
906
  nextState = enterStates(nextState, event, actorCtx, filteredTransitions, mutConfiguration, internalQueue, historyValue, isInitial);
942
907
  const nextConfiguration = [...mutConfiguration];
943
- const done = isInFinalState(nextConfiguration);
944
- if (done) {
908
+ if (nextState.status === 'done') {
945
909
  nextState = resolveActionsAndContext(nextState, event, actorCtx, nextConfiguration.sort((a, b) => b.order - a.order).flatMap(state => state.exit));
946
910
  }
947
911
  try {
948
- const output = done ? getOutput(nextConfiguration, nextState.context, event, actorCtx.self) : undefined;
949
912
  internalQueue.push(...nextState._internalQueue);
950
- return cloneState(currentState, {
913
+ return cloneState(nextState, {
951
914
  configuration: nextConfiguration,
952
915
  historyValue,
953
- _internalQueue: internalQueue,
954
- context: nextState.context,
955
- status: done ? 'done' : currentState.status,
956
- output,
957
- children: nextState.children
916
+ _internalQueue: internalQueue
958
917
  });
959
918
  } catch (e) {
960
919
  // TODO: Refactor this once proper error handling is implemented.
@@ -962,6 +921,13 @@ function microstepProcedure(transitions, currentState, mutConfiguration, event,
962
921
  throw e;
963
922
  }
964
923
  }
924
+ function getMachineOutput(state, event, actorCtx, rootNode, rootCompletionNode) {
925
+ if (!rootNode.output) {
926
+ return;
927
+ }
928
+ const doneStateEvent = interpreter.createDoneStateEvent(rootCompletionNode.id, rootCompletionNode.output && rootCompletionNode.parent ? interpreter.resolveOutput(rootCompletionNode.output, state.context, event, actorCtx.self) : undefined);
929
+ return interpreter.resolveOutput(rootNode.output, state.context, doneStateEvent, actorCtx.self);
930
+ }
965
931
  function enterStates(currentState, event, actorCtx, filteredTransitions, mutConfiguration, internalQueue, historyValue, isInitial) {
966
932
  let nextState = currentState;
967
933
  const statesToEnter = new Set();
@@ -972,6 +938,7 @@ function enterStates(currentState, event, actorCtx, filteredTransitions, mutConf
972
938
  if (isInitial) {
973
939
  statesForDefaultEntry.add(currentState.machine.root);
974
940
  }
941
+ const completedNodes = new Set();
975
942
  for (const stateNodeToEnter of [...statesToEnter].sort((a, b) => a.order - b.order)) {
976
943
  mutConfiguration.add(stateNodeToEnter);
977
944
  const actions = [];
@@ -982,26 +949,34 @@ function enterStates(currentState, event, actorCtx, filteredTransitions, mutConf
982
949
  actions.push(invoke(invokeDef));
983
950
  }
984
951
  if (statesForDefaultEntry.has(stateNodeToEnter)) {
985
- for (const stateNode of statesForDefaultEntry) {
986
- const initialActions = stateNode.initial.actions;
987
- actions.push(...initialActions);
988
- }
952
+ const initialActions = stateNodeToEnter.initial.actions;
953
+ actions.push(...initialActions);
989
954
  }
990
955
  nextState = resolveActionsAndContext(nextState, event, actorCtx, actions, stateNodeToEnter.invoke.map(invokeDef => invokeDef.id));
991
956
  if (stateNodeToEnter.type === 'final') {
992
957
  const parent = stateNodeToEnter.parent;
993
- if (!parent.parent) {
958
+ if (completedNodes.has(parent)) {
994
959
  continue;
995
960
  }
996
- internalQueue.push(interpreter.createDoneStateEvent(parent.id, stateNodeToEnter.output ? interpreter.resolveOutput(stateNodeToEnter.output, nextState.context, event, actorCtx.self) : undefined));
997
- if (parent.parent) {
998
- const grandparent = parent.parent;
999
- if (grandparent.type === 'parallel') {
1000
- if (getChildren(grandparent).every(parentNode => isInFinalState([...mutConfiguration], parentNode))) {
1001
- internalQueue.push(interpreter.createDoneStateEvent(grandparent.id));
1002
- }
961
+ completedNodes.add(parent);
962
+ let rootCompletionNode = parent?.type === 'parallel' ? parent : stateNodeToEnter;
963
+ let ancestorMarker = parent?.parent;
964
+ if (ancestorMarker) {
965
+ internalQueue.push(interpreter.createDoneStateEvent(parent.id, stateNodeToEnter.output ? interpreter.resolveOutput(stateNodeToEnter.output, nextState.context, event, actorCtx.self) : undefined));
966
+ while (ancestorMarker?.type === 'parallel' && !completedNodes.has(ancestorMarker) && isInFinalState(mutConfiguration, ancestorMarker)) {
967
+ completedNodes.add(ancestorMarker);
968
+ internalQueue.push(interpreter.createDoneStateEvent(ancestorMarker.id));
969
+ rootCompletionNode = ancestorMarker;
970
+ ancestorMarker = ancestorMarker.parent;
1003
971
  }
1004
972
  }
973
+ if (ancestorMarker) {
974
+ continue;
975
+ }
976
+ nextState = cloneState(nextState, {
977
+ status: 'done',
978
+ output: getMachineOutput(nextState, event, actorCtx, currentState.configuration[0].machine.root, rootCompletionNode)
979
+ });
1005
980
  }
1006
981
  }
1007
982
  return nextState;
@@ -1047,13 +1022,9 @@ function addDescendantStatesToEnter(stateNode, historyValue, statesForDefaultEnt
1047
1022
  statesToEnter.add(stateNode);
1048
1023
  if (stateNode.type === 'compound') {
1049
1024
  statesForDefaultEntry.add(stateNode);
1050
- const initialStates = stateNode.initial.target;
1051
- for (const initialState of initialStates) {
1052
- addDescendantStatesToEnter(initialState, historyValue, statesForDefaultEntry, statesToEnter);
1053
- }
1054
- for (const initialState of initialStates) {
1055
- addAncestorStatesToEnter(initialState, stateNode, statesToEnter, historyValue, statesForDefaultEntry);
1056
- }
1025
+ const [initialState] = stateNode.initial.target;
1026
+ addDescendantStatesToEnter(initialState, historyValue, statesForDefaultEntry, statesToEnter);
1027
+ addAncestorStatesToEnter(initialState, stateNode, statesToEnter, historyValue, statesForDefaultEntry);
1057
1028
  } else {
1058
1029
  if (stateNode.type === 'parallel') {
1059
1030
  for (const child of getChildren(stateNode).filter(sn => !isHistoryNode(sn))) {
@@ -1447,11 +1418,15 @@ function getPersistedState(state) {
1447
1418
  tags,
1448
1419
  machine,
1449
1420
  children,
1421
+ context,
1450
1422
  ...jsonValues
1451
1423
  } = state;
1452
1424
  const childrenJson = {};
1453
1425
  for (const id in children) {
1454
1426
  const child = children[id];
1427
+ if (typeof child.src !== 'string') {
1428
+ throw new Error('An inline child actor cannot be persisted.');
1429
+ }
1455
1430
  childrenJson[id] = {
1456
1431
  state: child.getPersistedState?.(),
1457
1432
  src: child.src
@@ -1459,9 +1434,38 @@ function getPersistedState(state) {
1459
1434
  }
1460
1435
  return {
1461
1436
  ...jsonValues,
1437
+ // TODO: this makes `PersistedMachineState`'s type kind of a lie
1438
+ // it doesn't truly use `TContext` but rather some kind of a derived form of it
1439
+ context: persistContext(context),
1462
1440
  children: childrenJson
1463
1441
  };
1464
1442
  }
1443
+ function persistContext(contextPart) {
1444
+ let copy;
1445
+ for (const key in contextPart) {
1446
+ const value = contextPart[key];
1447
+ if (value && typeof value === 'object') {
1448
+ if ('sessionId' in value && 'send' in value && 'ref' in value) {
1449
+ copy ??= Array.isArray(contextPart) ? contextPart.slice() : {
1450
+ ...contextPart
1451
+ };
1452
+ copy[key] = {
1453
+ xstate$$type: interpreter.$$ACTOR_TYPE,
1454
+ id: value.id
1455
+ };
1456
+ } else {
1457
+ const result = persistContext(value);
1458
+ if (result !== value) {
1459
+ copy ??= Array.isArray(contextPart) ? contextPart.slice() : {
1460
+ ...contextPart
1461
+ };
1462
+ copy[key] = result;
1463
+ }
1464
+ }
1465
+ }
1466
+ }
1467
+ return copy ?? contextPart;
1468
+ }
1465
1469
 
1466
1470
  function resolveRaise(_, state, args, {
1467
1471
  event: eventOrExpr,
@@ -1527,10 +1531,10 @@ exports.getCandidates = getCandidates;
1527
1531
  exports.getConfiguration = getConfiguration;
1528
1532
  exports.getDelayedTransitions = getDelayedTransitions;
1529
1533
  exports.getInitialConfiguration = getInitialConfiguration;
1534
+ exports.getInitialStateNodes = getInitialStateNodes;
1530
1535
  exports.getPersistedState = getPersistedState;
1531
1536
  exports.getStateNodeByPath = getStateNodeByPath;
1532
1537
  exports.getStateNodes = getStateNodes;
1533
- exports.isAtomicStateNode = isAtomicStateNode;
1534
1538
  exports.isInFinalState = isInFinalState;
1535
1539
  exports.isStateId = isStateId;
1536
1540
  exports.macrostep = macrostep;