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-1301970f.cjs.js');
3
+ var interpreter = require('./interpreter-69605bf0.cjs.js');
4
4
 
5
5
  const cache = new WeakMap();
6
6
  function memo(object, key, fn) {
@@ -279,20 +279,6 @@ function evaluateGuard(guard, context, event, state) {
279
279
  );
280
280
  }
281
281
 
282
- function getOutput(configuration, context, event, self) {
283
- const {
284
- machine
285
- } = configuration[0];
286
- const {
287
- root
288
- } = machine;
289
- if (!root.output) {
290
- return undefined;
291
- }
292
- const finalChildStateNode = configuration.find(stateNode => stateNode.type === 'final' && stateNode.parent === machine.root);
293
- const doneStateEvent = interpreter.createDoneStateEvent(finalChildStateNode.id, finalChildStateNode.output ? interpreter.resolveOutput(finalChildStateNode.output, context, event, self) : undefined);
294
- return interpreter.resolveOutput(root.output, context, doneStateEvent, self);
295
- }
296
282
  const isAtomicStateNode = stateNode => stateNode.type === 'atomic' || stateNode.type === 'final';
297
283
  function getChildren(stateNode) {
298
284
  return Object.values(stateNode.states).filter(sn => sn.type !== 'history');
@@ -317,7 +303,7 @@ function getConfiguration(stateNodes) {
317
303
  for (const s of configuration) {
318
304
  // if previously active, add existing child nodes
319
305
  if (s.type === 'compound' && (!adjList.get(s) || !adjList.get(s).length)) {
320
- getInitialStateNodes(s).forEach(sn => configurationSet.add(sn));
306
+ getInitialStateNodesWithTheirAncestors(s).forEach(sn => configurationSet.add(sn));
321
307
  } else {
322
308
  if (s.type === 'parallel') {
323
309
  for (const child of getChildren(s)) {
@@ -325,7 +311,8 @@ function getConfiguration(stateNodes) {
325
311
  continue;
326
312
  }
327
313
  if (!configurationSet.has(child)) {
328
- for (const initialStateNode of getInitialStateNodes(child)) {
314
+ const initialStates = getInitialStateNodesWithTheirAncestors(child);
315
+ for (const initialStateNode of initialStates) {
329
316
  configurationSet.add(initialStateNode);
330
317
  }
331
318
  }
@@ -385,14 +372,14 @@ function getStateValue(rootNode, configuration) {
385
372
  const config = getConfiguration(configuration);
386
373
  return getValueFromAdj(rootNode, getAdjList(config));
387
374
  }
388
- function isInFinalState(configuration, stateNode = configuration[0].machine.root) {
375
+ function isInFinalState(configuration, stateNode) {
389
376
  if (stateNode.type === 'compound') {
390
- return getChildren(stateNode).some(s => s.type === 'final' && configuration.includes(s));
377
+ return getChildren(stateNode).some(s => s.type === 'final' && configuration.has(s));
391
378
  }
392
379
  if (stateNode.type === 'parallel') {
393
380
  return getChildren(stateNode).every(sn => isInFinalState(configuration, sn));
394
381
  }
395
- return false;
382
+ return stateNode.type === 'final';
396
383
  }
397
384
  const isStateId = str => str[0] === interpreter.STATE_IDENTIFIER;
398
385
  function getCandidates(stateNode, receivedEventType) {
@@ -442,13 +429,7 @@ function getDelayedTransitions(stateNode) {
442
429
  stateNode.exit.push(cancel(eventType));
443
430
  return eventType;
444
431
  };
445
- const delayedTransitions = interpreter.isArray(afterConfig) ? afterConfig.map((transition, i) => {
446
- const eventType = mutateEntryExit(transition.delay, i);
447
- return {
448
- ...transition,
449
- event: eventType
450
- };
451
- }) : Object.keys(afterConfig).flatMap((delay, i) => {
432
+ const delayedTransitions = Object.keys(afterConfig).flatMap((delay, i) => {
452
433
  const configTransition = afterConfig[delay];
453
434
  const resolvedTransition = typeof configTransition === 'string' ? {
454
435
  target: configTransition
@@ -531,43 +512,23 @@ function formatTransitions(stateNode) {
531
512
  return transitions;
532
513
  }
533
514
  function formatInitialTransition(stateNode, _target) {
534
- if (typeof _target === 'string' || interpreter.isArray(_target)) {
535
- const targets = interpreter.toArray(_target).map(t => {
536
- // Resolve state string keys (which represent children)
537
- // to their state node
538
- const descStateNode = typeof t === 'string' ? isStateId(t) ? stateNode.machine.getStateNodeById(t) : stateNode.states[t] : t;
539
- if (!descStateNode) {
540
- throw new Error(`Initial state node "${t}" not found on parent state node #${stateNode.id}`);
541
- }
542
- if (!isDescendant(descStateNode, stateNode)) {
543
- throw new Error(`Invalid initial target: state node #${descStateNode.id} is not a descendant of #${stateNode.id}`);
544
- }
545
- return descStateNode;
546
- });
547
- const resolvedTarget = resolveTarget(stateNode, targets);
548
- const transition = {
549
- source: stateNode,
550
- actions: [],
551
- eventType: null,
552
- reenter: false,
553
- target: resolvedTarget,
554
- toJSON: () => ({
555
- ...transition,
556
- source: `#${stateNode.id}`,
557
- target: resolvedTarget ? resolvedTarget.map(t => `#${t.id}`) : undefined
558
- })
559
- };
560
- return transition;
515
+ const resolvedTarget = typeof _target === 'string' ? stateNode.states[_target] : _target ? stateNode.states[_target.target] : undefined;
516
+ if (!resolvedTarget && _target) {
517
+ throw new Error(`Initial state node "${_target}" not found on parent state node #${stateNode.id}`);
561
518
  }
562
- return formatTransition(stateNode, '__INITIAL__', {
563
- target: interpreter.toArray(_target.target).map(t => {
564
- if (typeof t === 'string') {
565
- return isStateId(t) ? t : `${interpreter.STATE_DELIMITER}${t}`;
566
- }
567
- return t;
568
- }),
569
- actions: _target.actions
570
- });
519
+ const transition = {
520
+ source: stateNode,
521
+ actions: !_target || typeof _target === 'string' ? [] : interpreter.toArray(_target.actions),
522
+ eventType: null,
523
+ reenter: false,
524
+ target: resolvedTarget ? [resolvedTarget] : [],
525
+ toJSON: () => ({
526
+ ...transition,
527
+ source: `#${stateNode.id}`,
528
+ target: resolvedTarget ? [`#${resolvedTarget.id}`] : []
529
+ })
530
+ };
531
+ return transition;
571
532
  }
572
533
  function resolveTarget(stateNode, targets) {
573
534
  if (targets === undefined) {
@@ -610,6 +571,15 @@ function resolveHistoryTarget(stateNode) {
610
571
  function isHistoryNode(stateNode) {
611
572
  return stateNode.type === 'history';
612
573
  }
574
+ function getInitialStateNodesWithTheirAncestors(stateNode) {
575
+ const states = getInitialStateNodes(stateNode);
576
+ for (const initialState of states) {
577
+ for (const ancestor of getProperAncestors(initialState, stateNode)) {
578
+ states.add(ancestor);
579
+ }
580
+ }
581
+ return states;
582
+ }
613
583
  function getInitialStateNodes(stateNode) {
614
584
  const set = new Set();
615
585
  function iter(descStateNode) {
@@ -618,12 +588,7 @@ function getInitialStateNodes(stateNode) {
618
588
  }
619
589
  set.add(descStateNode);
620
590
  if (descStateNode.type === 'compound') {
621
- for (const targetStateNode of descStateNode.initial.target) {
622
- for (const a of getProperAncestors(targetStateNode, stateNode)) {
623
- set.add(a);
624
- }
625
- iter(targetStateNode);
626
- }
591
+ iter(descStateNode.initial.target[0]);
627
592
  } else if (descStateNode.type === 'parallel') {
628
593
  for (const child of getChildren(descStateNode)) {
629
594
  iter(child);
@@ -631,7 +596,7 @@ function getInitialStateNodes(stateNode) {
631
596
  }
632
597
  }
633
598
  iter(stateNode);
634
- return [...set];
599
+ return set;
635
600
  }
636
601
  /**
637
602
  * Returns the child state node from its relative `stateKey`, or throws.
@@ -909,21 +874,15 @@ function microstepProcedure(transitions, currentState, mutConfiguration, event,
909
874
  // Enter states
910
875
  nextState = enterStates(nextState, event, actorCtx, filteredTransitions, mutConfiguration, internalQueue, historyValue, isInitial);
911
876
  const nextConfiguration = [...mutConfiguration];
912
- const done = isInFinalState(nextConfiguration);
913
- if (done) {
877
+ if (nextState.status === 'done') {
914
878
  nextState = resolveActionsAndContext(nextState, event, actorCtx, nextConfiguration.sort((a, b) => b.order - a.order).flatMap(state => state.exit));
915
879
  }
916
880
  try {
917
- const output = done ? getOutput(nextConfiguration, nextState.context, event, actorCtx.self) : undefined;
918
881
  internalQueue.push(...nextState._internalQueue);
919
- return cloneState(currentState, {
882
+ return cloneState(nextState, {
920
883
  configuration: nextConfiguration,
921
884
  historyValue,
922
- _internalQueue: internalQueue,
923
- context: nextState.context,
924
- status: done ? 'done' : currentState.status,
925
- output,
926
- children: nextState.children
885
+ _internalQueue: internalQueue
927
886
  });
928
887
  } catch (e) {
929
888
  // TODO: Refactor this once proper error handling is implemented.
@@ -931,6 +890,13 @@ function microstepProcedure(transitions, currentState, mutConfiguration, event,
931
890
  throw e;
932
891
  }
933
892
  }
893
+ function getMachineOutput(state, event, actorCtx, rootNode, rootCompletionNode) {
894
+ if (!rootNode.output) {
895
+ return;
896
+ }
897
+ const doneStateEvent = interpreter.createDoneStateEvent(rootCompletionNode.id, rootCompletionNode.output && rootCompletionNode.parent ? interpreter.resolveOutput(rootCompletionNode.output, state.context, event, actorCtx.self) : undefined);
898
+ return interpreter.resolveOutput(rootNode.output, state.context, doneStateEvent, actorCtx.self);
899
+ }
934
900
  function enterStates(currentState, event, actorCtx, filteredTransitions, mutConfiguration, internalQueue, historyValue, isInitial) {
935
901
  let nextState = currentState;
936
902
  const statesToEnter = new Set();
@@ -941,6 +907,7 @@ function enterStates(currentState, event, actorCtx, filteredTransitions, mutConf
941
907
  if (isInitial) {
942
908
  statesForDefaultEntry.add(currentState.machine.root);
943
909
  }
910
+ const completedNodes = new Set();
944
911
  for (const stateNodeToEnter of [...statesToEnter].sort((a, b) => a.order - b.order)) {
945
912
  mutConfiguration.add(stateNodeToEnter);
946
913
  const actions = [];
@@ -951,26 +918,34 @@ function enterStates(currentState, event, actorCtx, filteredTransitions, mutConf
951
918
  actions.push(invoke(invokeDef));
952
919
  }
953
920
  if (statesForDefaultEntry.has(stateNodeToEnter)) {
954
- for (const stateNode of statesForDefaultEntry) {
955
- const initialActions = stateNode.initial.actions;
956
- actions.push(...initialActions);
957
- }
921
+ const initialActions = stateNodeToEnter.initial.actions;
922
+ actions.push(...initialActions);
958
923
  }
959
924
  nextState = resolveActionsAndContext(nextState, event, actorCtx, actions, stateNodeToEnter.invoke.map(invokeDef => invokeDef.id));
960
925
  if (stateNodeToEnter.type === 'final') {
961
926
  const parent = stateNodeToEnter.parent;
962
- if (!parent.parent) {
927
+ if (completedNodes.has(parent)) {
963
928
  continue;
964
929
  }
965
- internalQueue.push(interpreter.createDoneStateEvent(parent.id, stateNodeToEnter.output ? interpreter.resolveOutput(stateNodeToEnter.output, nextState.context, event, actorCtx.self) : undefined));
966
- if (parent.parent) {
967
- const grandparent = parent.parent;
968
- if (grandparent.type === 'parallel') {
969
- if (getChildren(grandparent).every(parentNode => isInFinalState([...mutConfiguration], parentNode))) {
970
- internalQueue.push(interpreter.createDoneStateEvent(grandparent.id));
971
- }
930
+ completedNodes.add(parent);
931
+ let rootCompletionNode = parent?.type === 'parallel' ? parent : stateNodeToEnter;
932
+ let ancestorMarker = parent?.parent;
933
+ if (ancestorMarker) {
934
+ internalQueue.push(interpreter.createDoneStateEvent(parent.id, stateNodeToEnter.output ? interpreter.resolveOutput(stateNodeToEnter.output, nextState.context, event, actorCtx.self) : undefined));
935
+ while (ancestorMarker?.type === 'parallel' && !completedNodes.has(ancestorMarker) && isInFinalState(mutConfiguration, ancestorMarker)) {
936
+ completedNodes.add(ancestorMarker);
937
+ internalQueue.push(interpreter.createDoneStateEvent(ancestorMarker.id));
938
+ rootCompletionNode = ancestorMarker;
939
+ ancestorMarker = ancestorMarker.parent;
972
940
  }
973
941
  }
942
+ if (ancestorMarker) {
943
+ continue;
944
+ }
945
+ nextState = cloneState(nextState, {
946
+ status: 'done',
947
+ output: getMachineOutput(nextState, event, actorCtx, currentState.configuration[0].machine.root, rootCompletionNode)
948
+ });
974
949
  }
975
950
  }
976
951
  return nextState;
@@ -1016,13 +991,9 @@ function addDescendantStatesToEnter(stateNode, historyValue, statesForDefaultEnt
1016
991
  statesToEnter.add(stateNode);
1017
992
  if (stateNode.type === 'compound') {
1018
993
  statesForDefaultEntry.add(stateNode);
1019
- const initialStates = stateNode.initial.target;
1020
- for (const initialState of initialStates) {
1021
- addDescendantStatesToEnter(initialState, historyValue, statesForDefaultEntry, statesToEnter);
1022
- }
1023
- for (const initialState of initialStates) {
1024
- addAncestorStatesToEnter(initialState, stateNode, statesToEnter, historyValue, statesForDefaultEntry);
1025
- }
994
+ const [initialState] = stateNode.initial.target;
995
+ addDescendantStatesToEnter(initialState, historyValue, statesForDefaultEntry, statesToEnter);
996
+ addAncestorStatesToEnter(initialState, stateNode, statesToEnter, historyValue, statesForDefaultEntry);
1026
997
  } else {
1027
998
  if (stateNode.type === 'parallel') {
1028
999
  for (const child of getChildren(stateNode).filter(sn => !isHistoryNode(sn))) {
@@ -1410,6 +1381,7 @@ function getPersistedState(state) {
1410
1381
  tags,
1411
1382
  machine,
1412
1383
  children,
1384
+ context,
1413
1385
  ...jsonValues
1414
1386
  } = state;
1415
1387
  const childrenJson = {};
@@ -1422,9 +1394,38 @@ function getPersistedState(state) {
1422
1394
  }
1423
1395
  return {
1424
1396
  ...jsonValues,
1397
+ // TODO: this makes `PersistedMachineState`'s type kind of a lie
1398
+ // it doesn't truly use `TContext` but rather some kind of a derived form of it
1399
+ context: persistContext(context),
1425
1400
  children: childrenJson
1426
1401
  };
1427
1402
  }
1403
+ function persistContext(contextPart) {
1404
+ let copy;
1405
+ for (const key in contextPart) {
1406
+ const value = contextPart[key];
1407
+ if (value && typeof value === 'object') {
1408
+ if ('sessionId' in value && 'send' in value && 'ref' in value) {
1409
+ copy ??= Array.isArray(contextPart) ? contextPart.slice() : {
1410
+ ...contextPart
1411
+ };
1412
+ copy[key] = {
1413
+ xstate$$type: interpreter.$$ACTOR_TYPE,
1414
+ id: value.id
1415
+ };
1416
+ } else {
1417
+ const result = persistContext(value);
1418
+ if (result !== value) {
1419
+ copy ??= Array.isArray(contextPart) ? contextPart.slice() : {
1420
+ ...contextPart
1421
+ };
1422
+ copy[key] = result;
1423
+ }
1424
+ }
1425
+ }
1426
+ }
1427
+ return copy ?? contextPart;
1428
+ }
1428
1429
 
1429
1430
  function resolveRaise(_, state, args, {
1430
1431
  event: eventOrExpr,
@@ -1487,10 +1488,10 @@ exports.getCandidates = getCandidates;
1487
1488
  exports.getConfiguration = getConfiguration;
1488
1489
  exports.getDelayedTransitions = getDelayedTransitions;
1489
1490
  exports.getInitialConfiguration = getInitialConfiguration;
1491
+ exports.getInitialStateNodes = getInitialStateNodes;
1490
1492
  exports.getPersistedState = getPersistedState;
1491
1493
  exports.getStateNodeByPath = getStateNodeByPath;
1492
1494
  exports.getStateNodes = getStateNodes;
1493
- exports.isAtomicStateNode = isAtomicStateNode;
1494
1495
  exports.isInFinalState = isInFinalState;
1495
1496
  exports.isStateId = isStateId;
1496
1497
  exports.macrostep = macrostep;