xstate 5.0.0-beta.34 → 5.0.0-beta.36
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.
- package/README.md +1 -1
- package/actions/dist/xstate-actions.cjs.js +3 -3
- package/actions/dist/xstate-actions.development.cjs.js +3 -3
- package/actions/dist/xstate-actions.development.esm.js +3 -3
- package/actions/dist/xstate-actions.esm.js +3 -3
- package/actions/dist/xstate-actions.umd.min.js +1 -1
- package/actions/dist/xstate-actions.umd.min.js.map +1 -1
- package/actors/dist/xstate-actors.cjs.js +1 -1
- package/actors/dist/xstate-actors.development.cjs.js +1 -1
- package/actors/dist/xstate-actors.development.esm.js +1 -1
- package/actors/dist/xstate-actors.esm.js +1 -1
- package/actors/dist/xstate-actors.umd.min.js +1 -1
- package/actors/dist/xstate-actors.umd.min.js.map +1 -1
- package/dist/declarations/src/State.d.ts +0 -1
- package/dist/declarations/src/interpreter.d.ts +2 -0
- package/dist/declarations/src/stateUtils.d.ts +8 -7
- package/dist/declarations/src/types.d.ts +3 -6
- package/dist/{interpreter-dee56dc8.development.esm.js → interpreter-5c4e6634.development.esm.js} +59 -57
- package/dist/{interpreter-1301970f.cjs.js → interpreter-69605bf0.cjs.js} +59 -57
- package/dist/{interpreter-70ed62f2.development.cjs.js → interpreter-d3567419.development.cjs.js} +59 -57
- package/dist/{interpreter-83f7f2d4.esm.js → interpreter-de5217bc.esm.js} +59 -57
- package/dist/{raise-38b707c0.development.cjs.js → raise-106ea558.development.cjs.js} +160 -160
- package/dist/{raise-05f8b2a6.development.esm.js → raise-5b7ad3b7.development.esm.js} +160 -160
- package/dist/{raise-1dd65455.cjs.js → raise-c51b81a3.cjs.js} +157 -160
- package/dist/{raise-b5cfe1bb.esm.js → raise-ffe1014a.esm.js} +157 -160
- package/dist/{send-0b5eda0c.esm.js → send-0a7aa74e.esm.js} +5 -3
- package/dist/{send-3764c866.development.cjs.js → send-25e70bd4.development.cjs.js} +5 -3
- package/dist/{send-fe94de2b.cjs.js → send-778692de.cjs.js} +5 -3
- package/dist/{send-9526366e.development.esm.js → send-e93554d6.development.esm.js} +5 -3
- package/dist/xstate.cjs.js +32 -13
- package/dist/xstate.development.cjs.js +32 -13
- package/dist/xstate.development.esm.js +35 -16
- package/dist/xstate.esm.js +35 -16
- package/dist/xstate.umd.min.js +1 -1
- package/dist/xstate.umd.min.js.map +1 -1
- package/guards/dist/xstate-guards.cjs.js +2 -2
- package/guards/dist/xstate-guards.development.cjs.js +2 -2
- package/guards/dist/xstate-guards.development.esm.js +2 -2
- package/guards/dist/xstate-guards.esm.js +2 -2
- package/guards/dist/xstate-guards.umd.min.js.map +1 -1
- package/package.json +1 -1
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
'use strict';
|
|
2
2
|
|
|
3
|
-
var interpreter = require('./interpreter-
|
|
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
|
-
|
|
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
|
-
|
|
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
|
|
395
|
+
function isInFinalState(configuration, stateNode) {
|
|
409
396
|
if (stateNode.type === 'compound') {
|
|
410
|
-
return getChildren(stateNode).some(s => s.type === 'final' && configuration.
|
|
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
|
|
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 =
|
|
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
|
-
|
|
566
|
-
|
|
567
|
-
|
|
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
|
-
|
|
594
|
-
|
|
595
|
-
|
|
596
|
-
|
|
597
|
-
|
|
598
|
-
|
|
599
|
-
|
|
600
|
-
|
|
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
|
-
|
|
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
|
|
630
|
+
return set;
|
|
666
631
|
}
|
|
667
632
|
/**
|
|
668
633
|
* Returns the child state node from its relative `stateKey`, or throws.
|
|
@@ -896,6 +861,17 @@ function computeExitSet(transitions, configuration, historyValue) {
|
|
|
896
861
|
}
|
|
897
862
|
return [...statesToExit];
|
|
898
863
|
}
|
|
864
|
+
function areConfigurationsEqual(previousConfiguration, nextConfigurationSet) {
|
|
865
|
+
if (previousConfiguration.length !== nextConfigurationSet.size) {
|
|
866
|
+
return false;
|
|
867
|
+
}
|
|
868
|
+
for (const node of previousConfiguration) {
|
|
869
|
+
if (!nextConfigurationSet.has(node)) {
|
|
870
|
+
return false;
|
|
871
|
+
}
|
|
872
|
+
}
|
|
873
|
+
return true;
|
|
874
|
+
}
|
|
899
875
|
|
|
900
876
|
/**
|
|
901
877
|
* https://www.w3.org/TR/scxml/#microstepProcedure
|
|
@@ -905,56 +881,36 @@ function computeExitSet(transitions, configuration, historyValue) {
|
|
|
905
881
|
* @param currentState
|
|
906
882
|
* @param mutConfiguration
|
|
907
883
|
*/
|
|
908
|
-
|
|
909
|
-
function microstep(transitions, currentState, actorCtx, event, isInitial) {
|
|
910
|
-
const mutConfiguration = new Set(currentState.configuration);
|
|
884
|
+
function microstep(transitions, currentState, actorCtx, event, isInitial, internalQueue) {
|
|
911
885
|
if (!transitions.length) {
|
|
912
886
|
return currentState;
|
|
913
887
|
}
|
|
914
|
-
const
|
|
915
|
-
|
|
916
|
-
value: {} // TODO: make optional
|
|
917
|
-
});
|
|
918
|
-
}
|
|
919
|
-
|
|
920
|
-
function microstepProcedure(transitions, currentState, mutConfiguration, event, actorCtx, isInitial) {
|
|
921
|
-
const historyValue = {
|
|
922
|
-
...currentState.historyValue
|
|
923
|
-
};
|
|
888
|
+
const mutConfiguration = new Set(currentState.configuration);
|
|
889
|
+
let historyValue = currentState.historyValue;
|
|
924
890
|
const filteredTransitions = removeConflictingTransitions(transitions, mutConfiguration, historyValue);
|
|
925
|
-
|
|
926
|
-
// TODO: this `cloneState` is really just a hack to prevent infinite loops
|
|
927
|
-
// we need to take another look at how internal queue is managed
|
|
928
|
-
let nextState = cloneState(currentState, {
|
|
929
|
-
_internalQueue: []
|
|
930
|
-
});
|
|
891
|
+
let nextState = currentState;
|
|
931
892
|
|
|
932
893
|
// Exit states
|
|
933
894
|
if (!isInitial) {
|
|
934
|
-
nextState = exitStates(nextState, event, actorCtx, filteredTransitions, mutConfiguration, historyValue);
|
|
895
|
+
[nextState, historyValue] = exitStates(nextState, event, actorCtx, filteredTransitions, mutConfiguration, historyValue, internalQueue);
|
|
935
896
|
}
|
|
936
897
|
|
|
937
898
|
// Execute transition content
|
|
938
|
-
nextState = resolveActionsAndContext(nextState, event, actorCtx, filteredTransitions.flatMap(t => t.actions));
|
|
899
|
+
nextState = resolveActionsAndContext(nextState, event, actorCtx, filteredTransitions.flatMap(t => t.actions), internalQueue);
|
|
939
900
|
|
|
940
901
|
// Enter states
|
|
941
902
|
nextState = enterStates(nextState, event, actorCtx, filteredTransitions, mutConfiguration, internalQueue, historyValue, isInitial);
|
|
942
903
|
const nextConfiguration = [...mutConfiguration];
|
|
943
|
-
|
|
944
|
-
|
|
945
|
-
nextState = resolveActionsAndContext(nextState, event, actorCtx, nextConfiguration.sort((a, b) => b.order - a.order).flatMap(state => state.exit));
|
|
904
|
+
if (nextState.status === 'done') {
|
|
905
|
+
nextState = resolveActionsAndContext(nextState, event, actorCtx, nextConfiguration.sort((a, b) => b.order - a.order).flatMap(state => state.exit), internalQueue);
|
|
946
906
|
}
|
|
947
907
|
try {
|
|
948
|
-
|
|
949
|
-
|
|
950
|
-
|
|
908
|
+
if (historyValue === currentState.historyValue && areConfigurationsEqual(currentState.configuration, mutConfiguration)) {
|
|
909
|
+
return nextState;
|
|
910
|
+
}
|
|
911
|
+
return cloneState(nextState, {
|
|
951
912
|
configuration: nextConfiguration,
|
|
952
|
-
historyValue
|
|
953
|
-
_internalQueue: internalQueue,
|
|
954
|
-
context: nextState.context,
|
|
955
|
-
status: done ? 'done' : currentState.status,
|
|
956
|
-
output,
|
|
957
|
-
children: nextState.children
|
|
913
|
+
historyValue
|
|
958
914
|
});
|
|
959
915
|
} catch (e) {
|
|
960
916
|
// TODO: Refactor this once proper error handling is implemented.
|
|
@@ -962,6 +918,13 @@ function microstepProcedure(transitions, currentState, mutConfiguration, event,
|
|
|
962
918
|
throw e;
|
|
963
919
|
}
|
|
964
920
|
}
|
|
921
|
+
function getMachineOutput(state, event, actorCtx, rootNode, rootCompletionNode) {
|
|
922
|
+
if (!rootNode.output) {
|
|
923
|
+
return;
|
|
924
|
+
}
|
|
925
|
+
const doneStateEvent = interpreter.createDoneStateEvent(rootCompletionNode.id, rootCompletionNode.output && rootCompletionNode.parent ? interpreter.resolveOutput(rootCompletionNode.output, state.context, event, actorCtx.self) : undefined);
|
|
926
|
+
return interpreter.resolveOutput(rootNode.output, state.context, doneStateEvent, actorCtx.self);
|
|
927
|
+
}
|
|
965
928
|
function enterStates(currentState, event, actorCtx, filteredTransitions, mutConfiguration, internalQueue, historyValue, isInitial) {
|
|
966
929
|
let nextState = currentState;
|
|
967
930
|
const statesToEnter = new Set();
|
|
@@ -972,6 +935,7 @@ function enterStates(currentState, event, actorCtx, filteredTransitions, mutConf
|
|
|
972
935
|
if (isInitial) {
|
|
973
936
|
statesForDefaultEntry.add(currentState.machine.root);
|
|
974
937
|
}
|
|
938
|
+
const completedNodes = new Set();
|
|
975
939
|
for (const stateNodeToEnter of [...statesToEnter].sort((a, b) => a.order - b.order)) {
|
|
976
940
|
mutConfiguration.add(stateNodeToEnter);
|
|
977
941
|
const actions = [];
|
|
@@ -982,26 +946,34 @@ function enterStates(currentState, event, actorCtx, filteredTransitions, mutConf
|
|
|
982
946
|
actions.push(invoke(invokeDef));
|
|
983
947
|
}
|
|
984
948
|
if (statesForDefaultEntry.has(stateNodeToEnter)) {
|
|
985
|
-
|
|
986
|
-
|
|
987
|
-
actions.push(...initialActions);
|
|
988
|
-
}
|
|
949
|
+
const initialActions = stateNodeToEnter.initial.actions;
|
|
950
|
+
actions.push(...initialActions);
|
|
989
951
|
}
|
|
990
|
-
nextState = resolveActionsAndContext(nextState, event, actorCtx, actions, stateNodeToEnter.invoke.map(invokeDef => invokeDef.id));
|
|
952
|
+
nextState = resolveActionsAndContext(nextState, event, actorCtx, actions, internalQueue, stateNodeToEnter.invoke.map(invokeDef => invokeDef.id));
|
|
991
953
|
if (stateNodeToEnter.type === 'final') {
|
|
992
954
|
const parent = stateNodeToEnter.parent;
|
|
993
|
-
if (
|
|
955
|
+
if (completedNodes.has(parent)) {
|
|
994
956
|
continue;
|
|
995
957
|
}
|
|
996
|
-
|
|
997
|
-
|
|
998
|
-
|
|
999
|
-
|
|
1000
|
-
|
|
1001
|
-
|
|
1002
|
-
|
|
958
|
+
completedNodes.add(parent);
|
|
959
|
+
let rootCompletionNode = parent?.type === 'parallel' ? parent : stateNodeToEnter;
|
|
960
|
+
let ancestorMarker = parent?.parent;
|
|
961
|
+
if (ancestorMarker) {
|
|
962
|
+
internalQueue.push(interpreter.createDoneStateEvent(parent.id, stateNodeToEnter.output ? interpreter.resolveOutput(stateNodeToEnter.output, nextState.context, event, actorCtx.self) : undefined));
|
|
963
|
+
while (ancestorMarker?.type === 'parallel' && !completedNodes.has(ancestorMarker) && isInFinalState(mutConfiguration, ancestorMarker)) {
|
|
964
|
+
completedNodes.add(ancestorMarker);
|
|
965
|
+
internalQueue.push(interpreter.createDoneStateEvent(ancestorMarker.id));
|
|
966
|
+
rootCompletionNode = ancestorMarker;
|
|
967
|
+
ancestorMarker = ancestorMarker.parent;
|
|
1003
968
|
}
|
|
1004
969
|
}
|
|
970
|
+
if (ancestorMarker) {
|
|
971
|
+
continue;
|
|
972
|
+
}
|
|
973
|
+
nextState = cloneState(nextState, {
|
|
974
|
+
status: 'done',
|
|
975
|
+
output: getMachineOutput(nextState, event, actorCtx, currentState.configuration[0].machine.root, rootCompletionNode)
|
|
976
|
+
});
|
|
1005
977
|
}
|
|
1006
978
|
}
|
|
1007
979
|
return nextState;
|
|
@@ -1047,13 +1019,9 @@ function addDescendantStatesToEnter(stateNode, historyValue, statesForDefaultEnt
|
|
|
1047
1019
|
statesToEnter.add(stateNode);
|
|
1048
1020
|
if (stateNode.type === 'compound') {
|
|
1049
1021
|
statesForDefaultEntry.add(stateNode);
|
|
1050
|
-
const
|
|
1051
|
-
|
|
1052
|
-
|
|
1053
|
-
}
|
|
1054
|
-
for (const initialState of initialStates) {
|
|
1055
|
-
addAncestorStatesToEnter(initialState, stateNode, statesToEnter, historyValue, statesForDefaultEntry);
|
|
1056
|
-
}
|
|
1022
|
+
const [initialState] = stateNode.initial.target;
|
|
1023
|
+
addDescendantStatesToEnter(initialState, historyValue, statesForDefaultEntry, statesToEnter);
|
|
1024
|
+
addAncestorStatesToEnter(initialState, stateNode, statesToEnter, historyValue, statesForDefaultEntry);
|
|
1057
1025
|
} else {
|
|
1058
1026
|
if (stateNode.type === 'parallel') {
|
|
1059
1027
|
for (const child of getChildren(stateNode).filter(sn => !isHistoryNode(sn))) {
|
|
@@ -1078,10 +1046,11 @@ function addAncestorStatesToEnter(stateNode, toStateNode, statesToEnter, history
|
|
|
1078
1046
|
}
|
|
1079
1047
|
}
|
|
1080
1048
|
}
|
|
1081
|
-
function exitStates(currentState, event, actorCtx, transitions, mutConfiguration, historyValue) {
|
|
1049
|
+
function exitStates(currentState, event, actorCtx, transitions, mutConfiguration, historyValue, internalQueue) {
|
|
1082
1050
|
let nextState = currentState;
|
|
1083
1051
|
const statesToExit = computeExitSet(transitions, mutConfiguration, historyValue);
|
|
1084
1052
|
statesToExit.sort((a, b) => b.order - a.order);
|
|
1053
|
+
let changedHistory;
|
|
1085
1054
|
|
|
1086
1055
|
// From SCXML algorithm: https://www.w3.org/TR/scxml/#exitStates
|
|
1087
1056
|
for (const exitStateNode of statesToExit) {
|
|
@@ -1094,14 +1063,17 @@ function exitStates(currentState, event, actorCtx, transitions, mutConfiguration
|
|
|
1094
1063
|
return sn.parent === exitStateNode;
|
|
1095
1064
|
};
|
|
1096
1065
|
}
|
|
1097
|
-
|
|
1066
|
+
changedHistory ??= {
|
|
1067
|
+
...historyValue
|
|
1068
|
+
};
|
|
1069
|
+
changedHistory[historyNode.id] = Array.from(mutConfiguration).filter(predicate);
|
|
1098
1070
|
}
|
|
1099
1071
|
}
|
|
1100
1072
|
for (const s of statesToExit) {
|
|
1101
|
-
nextState = resolveActionsAndContext(nextState, event, actorCtx, [...s.exit, ...s.invoke.map(def => stop(def.id))]);
|
|
1073
|
+
nextState = resolveActionsAndContext(nextState, event, actorCtx, [...s.exit, ...s.invoke.map(def => stop(def.id))], internalQueue);
|
|
1102
1074
|
mutConfiguration.delete(s);
|
|
1103
1075
|
}
|
|
1104
|
-
return nextState;
|
|
1076
|
+
return [nextState, changedHistory || historyValue];
|
|
1105
1077
|
}
|
|
1106
1078
|
function resolveActionsAndContextWorker(currentState, event, actorCtx, actions, extra, retries) {
|
|
1107
1079
|
const {
|
|
@@ -1166,9 +1138,10 @@ function resolveActionsAndContextWorker(currentState, event, actorCtx, actions,
|
|
|
1166
1138
|
}
|
|
1167
1139
|
return intermediateState;
|
|
1168
1140
|
}
|
|
1169
|
-
function resolveActionsAndContext(currentState, event, actorCtx, actions, deferredActorIds) {
|
|
1141
|
+
function resolveActionsAndContext(currentState, event, actorCtx, actions, internalQueue, deferredActorIds) {
|
|
1170
1142
|
const retries = deferredActorIds ? [] : undefined;
|
|
1171
|
-
const nextState = resolveActionsAndContextWorker(currentState, event, actorCtx, actions,
|
|
1143
|
+
const nextState = resolveActionsAndContextWorker(currentState, event, actorCtx, actions, {
|
|
1144
|
+
internalQueue,
|
|
1172
1145
|
deferredActorIds
|
|
1173
1146
|
}, retries);
|
|
1174
1147
|
retries?.forEach(([builtinAction, params]) => {
|
|
@@ -1176,7 +1149,7 @@ function resolveActionsAndContext(currentState, event, actorCtx, actions, deferr
|
|
|
1176
1149
|
});
|
|
1177
1150
|
return nextState;
|
|
1178
1151
|
}
|
|
1179
|
-
function macrostep(state, event, actorCtx) {
|
|
1152
|
+
function macrostep(state, event, actorCtx, internalQueue = []) {
|
|
1180
1153
|
if (event.type === interpreter.WILDCARD) {
|
|
1181
1154
|
throw new Error(`An event cannot have the wildcard type ('${interpreter.WILDCARD}')`);
|
|
1182
1155
|
}
|
|
@@ -1185,7 +1158,7 @@ function macrostep(state, event, actorCtx) {
|
|
|
1185
1158
|
|
|
1186
1159
|
// Handle stop event
|
|
1187
1160
|
if (event.type === interpreter.XSTATE_STOP) {
|
|
1188
|
-
nextState =
|
|
1161
|
+
nextState = stopChildren(nextState, event, actorCtx);
|
|
1189
1162
|
states.push(nextState);
|
|
1190
1163
|
return {
|
|
1191
1164
|
state: nextState,
|
|
@@ -1198,44 +1171,37 @@ function macrostep(state, event, actorCtx) {
|
|
|
1198
1171
|
// Determine the next state based on the next microstep
|
|
1199
1172
|
if (nextEvent.type !== interpreter.XSTATE_INIT) {
|
|
1200
1173
|
const transitions = selectTransitions(nextEvent, nextState);
|
|
1201
|
-
nextState = microstep(transitions, state, actorCtx, nextEvent, false);
|
|
1174
|
+
nextState = microstep(transitions, state, actorCtx, nextEvent, false, internalQueue);
|
|
1202
1175
|
states.push(nextState);
|
|
1203
1176
|
}
|
|
1177
|
+
let shouldSelectEventlessTransitions = true;
|
|
1204
1178
|
while (nextState.status === 'active') {
|
|
1205
|
-
let enabledTransitions = selectEventlessTransitions(nextState, nextEvent);
|
|
1179
|
+
let enabledTransitions = shouldSelectEventlessTransitions ? selectEventlessTransitions(nextState, nextEvent) : [];
|
|
1180
|
+
|
|
1181
|
+
// eventless transitions should always be selected after selecting *regular* transitions
|
|
1182
|
+
// by assigning `undefined` to `previousState` we ensure that `shouldSelectEventlessTransitions` gets always computed to true in such a case
|
|
1183
|
+
const previousState = enabledTransitions.length ? nextState : undefined;
|
|
1206
1184
|
if (!enabledTransitions.length) {
|
|
1207
|
-
if (!
|
|
1185
|
+
if (!internalQueue.length) {
|
|
1208
1186
|
break;
|
|
1209
|
-
} else {
|
|
1210
|
-
nextEvent = nextState._internalQueue[0];
|
|
1211
|
-
const transitions = selectTransitions(nextEvent, nextState);
|
|
1212
|
-
nextState = microstep(transitions, nextState, actorCtx, nextEvent, false);
|
|
1213
|
-
nextState._internalQueue.shift();
|
|
1214
|
-
states.push(nextState);
|
|
1215
1187
|
}
|
|
1216
|
-
|
|
1217
|
-
|
|
1218
|
-
states.push(nextState);
|
|
1188
|
+
nextEvent = internalQueue.shift();
|
|
1189
|
+
enabledTransitions = selectTransitions(nextEvent, nextState);
|
|
1219
1190
|
}
|
|
1191
|
+
nextState = microstep(enabledTransitions, nextState, actorCtx, nextEvent, false, internalQueue);
|
|
1192
|
+
shouldSelectEventlessTransitions = nextState !== previousState;
|
|
1193
|
+
states.push(nextState);
|
|
1220
1194
|
}
|
|
1221
1195
|
if (nextState.status !== 'active') {
|
|
1222
|
-
|
|
1223
|
-
stopStep(nextEvent, nextState, actorCtx);
|
|
1196
|
+
stopChildren(nextState, nextEvent, actorCtx);
|
|
1224
1197
|
}
|
|
1225
1198
|
return {
|
|
1226
1199
|
state: nextState,
|
|
1227
1200
|
microstates: states
|
|
1228
1201
|
};
|
|
1229
1202
|
}
|
|
1230
|
-
function
|
|
1231
|
-
|
|
1232
|
-
for (const stateNode of nextState.configuration.sort((a, b) => b.order - a.order)) {
|
|
1233
|
-
actions.push(...stateNode.exit);
|
|
1234
|
-
}
|
|
1235
|
-
for (const child of Object.values(nextState.children)) {
|
|
1236
|
-
actions.push(stop(child));
|
|
1237
|
-
}
|
|
1238
|
-
return resolveActionsAndContext(nextState, event, actorCtx, actions);
|
|
1203
|
+
function stopChildren(nextState, event, actorCtx) {
|
|
1204
|
+
return resolveActionsAndContext(nextState, event, actorCtx, Object.values(nextState.children).map(child => stop(child)), []);
|
|
1239
1205
|
}
|
|
1240
1206
|
function selectTransitions(event, nextState) {
|
|
1241
1207
|
return nextState.machine.getTransitionData(nextState, event);
|
|
@@ -1341,11 +1307,9 @@ class State {
|
|
|
1341
1307
|
this.error = void 0;
|
|
1342
1308
|
this.context = void 0;
|
|
1343
1309
|
this.historyValue = {};
|
|
1344
|
-
this._internalQueue = void 0;
|
|
1345
1310
|
this.configuration = void 0;
|
|
1346
1311
|
this.children = void 0;
|
|
1347
1312
|
this.context = config.context;
|
|
1348
|
-
this._internalQueue = config._internalQueue ?? [];
|
|
1349
1313
|
this.historyValue = config.historyValue || {};
|
|
1350
1314
|
this.matches = this.matches.bind(this);
|
|
1351
1315
|
this.toStrings = this.toStrings.bind(this);
|
|
@@ -1447,11 +1411,15 @@ function getPersistedState(state) {
|
|
|
1447
1411
|
tags,
|
|
1448
1412
|
machine,
|
|
1449
1413
|
children,
|
|
1414
|
+
context,
|
|
1450
1415
|
...jsonValues
|
|
1451
1416
|
} = state;
|
|
1452
1417
|
const childrenJson = {};
|
|
1453
1418
|
for (const id in children) {
|
|
1454
1419
|
const child = children[id];
|
|
1420
|
+
if (typeof child.src !== 'string') {
|
|
1421
|
+
throw new Error('An inline child actor cannot be persisted.');
|
|
1422
|
+
}
|
|
1455
1423
|
childrenJson[id] = {
|
|
1456
1424
|
state: child.getPersistedState?.(),
|
|
1457
1425
|
src: child.src
|
|
@@ -1459,14 +1427,45 @@ function getPersistedState(state) {
|
|
|
1459
1427
|
}
|
|
1460
1428
|
return {
|
|
1461
1429
|
...jsonValues,
|
|
1430
|
+
// TODO: this makes `PersistedMachineState`'s type kind of a lie
|
|
1431
|
+
// it doesn't truly use `TContext` but rather some kind of a derived form of it
|
|
1432
|
+
context: persistContext(context),
|
|
1462
1433
|
children: childrenJson
|
|
1463
1434
|
};
|
|
1464
1435
|
}
|
|
1436
|
+
function persistContext(contextPart) {
|
|
1437
|
+
let copy;
|
|
1438
|
+
for (const key in contextPart) {
|
|
1439
|
+
const value = contextPart[key];
|
|
1440
|
+
if (value && typeof value === 'object') {
|
|
1441
|
+
if ('sessionId' in value && 'send' in value && 'ref' in value) {
|
|
1442
|
+
copy ??= Array.isArray(contextPart) ? contextPart.slice() : {
|
|
1443
|
+
...contextPart
|
|
1444
|
+
};
|
|
1445
|
+
copy[key] = {
|
|
1446
|
+
xstate$$type: interpreter.$$ACTOR_TYPE,
|
|
1447
|
+
id: value.id
|
|
1448
|
+
};
|
|
1449
|
+
} else {
|
|
1450
|
+
const result = persistContext(value);
|
|
1451
|
+
if (result !== value) {
|
|
1452
|
+
copy ??= Array.isArray(contextPart) ? contextPart.slice() : {
|
|
1453
|
+
...contextPart
|
|
1454
|
+
};
|
|
1455
|
+
copy[key] = result;
|
|
1456
|
+
}
|
|
1457
|
+
}
|
|
1458
|
+
}
|
|
1459
|
+
}
|
|
1460
|
+
return copy ?? contextPart;
|
|
1461
|
+
}
|
|
1465
1462
|
|
|
1466
1463
|
function resolveRaise(_, state, args, {
|
|
1467
1464
|
event: eventOrExpr,
|
|
1468
1465
|
id,
|
|
1469
1466
|
delay
|
|
1467
|
+
}, {
|
|
1468
|
+
internalQueue
|
|
1470
1469
|
}) {
|
|
1471
1470
|
const delaysMap = state.machine.implementations.delays;
|
|
1472
1471
|
if (typeof eventOrExpr === 'string') {
|
|
@@ -1480,9 +1479,10 @@ function resolveRaise(_, state, args, {
|
|
|
1480
1479
|
} else {
|
|
1481
1480
|
resolvedDelay = typeof delay === 'function' ? delay(args) : delay;
|
|
1482
1481
|
}
|
|
1483
|
-
|
|
1484
|
-
|
|
1485
|
-
}
|
|
1482
|
+
if (typeof resolvedDelay !== 'number') {
|
|
1483
|
+
internalQueue.push(resolvedEvent);
|
|
1484
|
+
}
|
|
1485
|
+
return [state, {
|
|
1486
1486
|
event: resolvedEvent,
|
|
1487
1487
|
id,
|
|
1488
1488
|
delay: resolvedDelay
|
|
@@ -1527,10 +1527,10 @@ exports.getCandidates = getCandidates;
|
|
|
1527
1527
|
exports.getConfiguration = getConfiguration;
|
|
1528
1528
|
exports.getDelayedTransitions = getDelayedTransitions;
|
|
1529
1529
|
exports.getInitialConfiguration = getInitialConfiguration;
|
|
1530
|
+
exports.getInitialStateNodes = getInitialStateNodes;
|
|
1530
1531
|
exports.getPersistedState = getPersistedState;
|
|
1531
1532
|
exports.getStateNodeByPath = getStateNodeByPath;
|
|
1532
1533
|
exports.getStateNodes = getStateNodes;
|
|
1533
|
-
exports.isAtomicStateNode = isAtomicStateNode;
|
|
1534
1534
|
exports.isInFinalState = isInFinalState;
|
|
1535
1535
|
exports.isStateId = isStateId;
|
|
1536
1536
|
exports.macrostep = macrostep;
|