xstate 5.0.0-beta.36 → 5.0.0-beta.37
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/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/typegenTypes.d.ts +2 -0
- package/dist/declarations/src/types.d.ts +1 -1
- package/dist/declarations/src/utils.d.ts +6 -6
- package/dist/declarations/src/waitFor.d.ts +1 -1
- package/dist/{interpreter-5c4e6634.development.esm.js → interpreter-1c52b23c.development.esm.js} +13 -23
- package/dist/{interpreter-de5217bc.esm.js → interpreter-8def682e.esm.js} +13 -23
- package/dist/{interpreter-69605bf0.cjs.js → interpreter-97aff8d2.cjs.js} +13 -23
- package/dist/{interpreter-d3567419.development.cjs.js → interpreter-e58ca48d.development.cjs.js} +13 -23
- package/dist/{raise-106ea558.development.cjs.js → raise-1fd59c65.development.cjs.js} +71 -40
- package/dist/{raise-ffe1014a.esm.js → raise-21c417c1.esm.js} +71 -40
- package/dist/{raise-c51b81a3.cjs.js → raise-800296d7.cjs.js} +71 -40
- package/dist/{raise-5b7ad3b7.development.esm.js → raise-e342a840.development.esm.js} +71 -40
- package/dist/{send-778692de.cjs.js → send-4cc29786.cjs.js} +6 -3
- package/dist/{send-e93554d6.development.esm.js → send-83ccc98b.development.esm.js} +6 -3
- package/dist/{send-0a7aa74e.esm.js → send-92854675.esm.js} +6 -3
- package/dist/{send-25e70bd4.development.cjs.js → send-b309ef4e.development.cjs.js} +6 -3
- package/dist/xstate.cjs.js +5 -13
- package/dist/xstate.development.cjs.js +5 -13
- package/dist/xstate.development.esm.js +8 -16
- package/dist/xstate.esm.js +8 -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 +1 -1
- package/guards/dist/xstate-guards.umd.min.js.map +1 -1
- package/package.json +1 -1
|
@@ -30,22 +30,6 @@ class Mailbox {
|
|
|
30
30
|
this._last = this._current;
|
|
31
31
|
}
|
|
32
32
|
}
|
|
33
|
-
|
|
34
|
-
// TODO: rethink this design
|
|
35
|
-
prepend(event) {
|
|
36
|
-
if (!this._current) {
|
|
37
|
-
this.enqueue(event);
|
|
38
|
-
return;
|
|
39
|
-
}
|
|
40
|
-
|
|
41
|
-
// we know that something is already queued up
|
|
42
|
-
// so the mailbox is already flushing or it's inactive
|
|
43
|
-
// therefore the only thing that we need to do is to reassign `this._current`
|
|
44
|
-
this._current = {
|
|
45
|
-
value: event,
|
|
46
|
-
next: this._current
|
|
47
|
-
};
|
|
48
|
-
}
|
|
49
33
|
enqueue(event) {
|
|
50
34
|
const enqueued = {
|
|
51
35
|
value: event,
|
|
@@ -68,11 +52,7 @@ class Mailbox {
|
|
|
68
52
|
// we assume here that this won't throw in a way that can affect this mailbox
|
|
69
53
|
const consumed = this._current;
|
|
70
54
|
this._process(consumed.value);
|
|
71
|
-
|
|
72
|
-
// so we need to be defensive here to avoid skipping over a prepended item
|
|
73
|
-
if (consumed === this._current) {
|
|
74
|
-
this._current = this._current.next;
|
|
75
|
-
}
|
|
55
|
+
this._current = consumed.next;
|
|
76
56
|
}
|
|
77
57
|
this._last = null;
|
|
78
58
|
}
|
|
@@ -333,9 +313,19 @@ function toObserver(nextHandler, errorHandler, completionHandler) {
|
|
|
333
313
|
};
|
|
334
314
|
}
|
|
335
315
|
function createInvokeId(stateNodeId, index) {
|
|
336
|
-
return `${stateNodeId}
|
|
316
|
+
return `${stateNodeId}[${index}]`;
|
|
337
317
|
}
|
|
338
|
-
function resolveReferencedActor(
|
|
318
|
+
function resolveReferencedActor(machine, src) {
|
|
319
|
+
if (src.startsWith('xstate#')) {
|
|
320
|
+
const [, indexStr] = src.match(/\[(\d+)\]$/);
|
|
321
|
+
const node = machine.getStateNodeById(src.slice(7, -(indexStr.length + 2)));
|
|
322
|
+
const invokeConfig = node.config.invoke;
|
|
323
|
+
return {
|
|
324
|
+
src: (Array.isArray(invokeConfig) ? invokeConfig[indexStr] : invokeConfig).src,
|
|
325
|
+
input: undefined
|
|
326
|
+
};
|
|
327
|
+
}
|
|
328
|
+
const referenced = machine.implementations.actors[src];
|
|
339
329
|
return referenced ? 'transition' in referenced ? {
|
|
340
330
|
src: referenced,
|
|
341
331
|
input: undefined
|
package/dist/{interpreter-d3567419.development.cjs.js → interpreter-e58ca48d.development.cjs.js}
RENAMED
|
@@ -30,22 +30,6 @@ class Mailbox {
|
|
|
30
30
|
this._last = this._current;
|
|
31
31
|
}
|
|
32
32
|
}
|
|
33
|
-
|
|
34
|
-
// TODO: rethink this design
|
|
35
|
-
prepend(event) {
|
|
36
|
-
if (!this._current) {
|
|
37
|
-
this.enqueue(event);
|
|
38
|
-
return;
|
|
39
|
-
}
|
|
40
|
-
|
|
41
|
-
// we know that something is already queued up
|
|
42
|
-
// so the mailbox is already flushing or it's inactive
|
|
43
|
-
// therefore the only thing that we need to do is to reassign `this._current`
|
|
44
|
-
this._current = {
|
|
45
|
-
value: event,
|
|
46
|
-
next: this._current
|
|
47
|
-
};
|
|
48
|
-
}
|
|
49
33
|
enqueue(event) {
|
|
50
34
|
const enqueued = {
|
|
51
35
|
value: event,
|
|
@@ -68,11 +52,7 @@ class Mailbox {
|
|
|
68
52
|
// we assume here that this won't throw in a way that can affect this mailbox
|
|
69
53
|
const consumed = this._current;
|
|
70
54
|
this._process(consumed.value);
|
|
71
|
-
|
|
72
|
-
// so we need to be defensive here to avoid skipping over a prepended item
|
|
73
|
-
if (consumed === this._current) {
|
|
74
|
-
this._current = this._current.next;
|
|
75
|
-
}
|
|
55
|
+
this._current = consumed.next;
|
|
76
56
|
}
|
|
77
57
|
this._last = null;
|
|
78
58
|
}
|
|
@@ -336,9 +316,19 @@ function toObserver(nextHandler, errorHandler, completionHandler) {
|
|
|
336
316
|
};
|
|
337
317
|
}
|
|
338
318
|
function createInvokeId(stateNodeId, index) {
|
|
339
|
-
return `${stateNodeId}
|
|
319
|
+
return `${stateNodeId}[${index}]`;
|
|
340
320
|
}
|
|
341
|
-
function resolveReferencedActor(
|
|
321
|
+
function resolveReferencedActor(machine, src) {
|
|
322
|
+
if (src.startsWith('xstate#')) {
|
|
323
|
+
const [, indexStr] = src.match(/\[(\d+)\]$/);
|
|
324
|
+
const node = machine.getStateNodeById(src.slice(7, -(indexStr.length + 2)));
|
|
325
|
+
const invokeConfig = node.config.invoke;
|
|
326
|
+
return {
|
|
327
|
+
src: (Array.isArray(invokeConfig) ? invokeConfig[indexStr] : invokeConfig).src,
|
|
328
|
+
input: undefined
|
|
329
|
+
};
|
|
330
|
+
}
|
|
331
|
+
const referenced = machine.implementations.actors[src];
|
|
342
332
|
return referenced ? 'transition' in referenced ? {
|
|
343
333
|
src: referenced,
|
|
344
334
|
input: undefined
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
'use strict';
|
|
2
2
|
|
|
3
|
-
var interpreter = require('./interpreter-
|
|
3
|
+
var interpreter = require('./interpreter-e58ca48d.development.cjs.js');
|
|
4
4
|
|
|
5
5
|
const cache = new WeakMap();
|
|
6
6
|
function memo(object, key, fn) {
|
|
@@ -52,14 +52,17 @@ function resolveInvoke(actorContext, state, actionArgs, {
|
|
|
52
52
|
input,
|
|
53
53
|
syncSnapshot
|
|
54
54
|
}) {
|
|
55
|
-
const referenced = interpreter.resolveReferencedActor(state.machine
|
|
55
|
+
const referenced = typeof src === 'string' ? interpreter.resolveReferencedActor(state.machine, src) : {
|
|
56
|
+
src,
|
|
57
|
+
input: undefined
|
|
58
|
+
};
|
|
56
59
|
let actorRef;
|
|
57
60
|
if (referenced) {
|
|
58
61
|
// TODO: inline `input: undefined` should win over the referenced one
|
|
59
62
|
const configuredInput = input || referenced.input;
|
|
60
63
|
actorRef = interpreter.createActor(referenced.src, {
|
|
61
64
|
id,
|
|
62
|
-
src,
|
|
65
|
+
src: typeof src === 'string' ? src : undefined,
|
|
63
66
|
parent: actorContext?.self,
|
|
64
67
|
systemId,
|
|
65
68
|
input: typeof configuredInput === 'function' ? configuredInput({
|
|
@@ -162,11 +165,16 @@ function executeStop(actorContext, actorRef) {
|
|
|
162
165
|
if (!actorRef) {
|
|
163
166
|
return;
|
|
164
167
|
}
|
|
168
|
+
// this allows us to prevent an actor from being started if it gets stopped within the same macrostep
|
|
169
|
+
// this can happen, for example, when the invoking state is being exited immediately by an always transition
|
|
165
170
|
if (actorRef.status !== interpreter.ActorStatus.Running) {
|
|
166
171
|
actorContext.stopChild(actorRef);
|
|
167
172
|
return;
|
|
168
173
|
}
|
|
169
|
-
//
|
|
174
|
+
// stopping a child enqueues a stop event in the child actor's mailbox
|
|
175
|
+
// we need for all of the already enqueued events to be processed before we stop the child
|
|
176
|
+
// the parent itself might want to send some events to a child (for example from exit actions on the invoking state)
|
|
177
|
+
// and we don't want to ignore those events
|
|
170
178
|
actorContext.defer(() => {
|
|
171
179
|
actorContext.stopChild(actorRef);
|
|
172
180
|
});
|
|
@@ -193,7 +201,8 @@ function checkStateIn(state, _, {
|
|
|
193
201
|
stateValue
|
|
194
202
|
}) {
|
|
195
203
|
if (typeof stateValue === 'string' && isStateId(stateValue)) {
|
|
196
|
-
|
|
204
|
+
const target = state.machine.getStateNodeById(stateValue);
|
|
205
|
+
return state.configuration.some(sn => sn === target);
|
|
197
206
|
}
|
|
198
207
|
return state.matches(stateValue);
|
|
199
208
|
}
|
|
@@ -305,6 +314,9 @@ function getChildren(stateNode) {
|
|
|
305
314
|
}
|
|
306
315
|
function getProperAncestors(stateNode, toStateNode) {
|
|
307
316
|
const ancestors = [];
|
|
317
|
+
if (toStateNode === stateNode) {
|
|
318
|
+
return ancestors;
|
|
319
|
+
}
|
|
308
320
|
|
|
309
321
|
// add all ancestors
|
|
310
322
|
let m = stateNode.parent;
|
|
@@ -592,12 +604,14 @@ function resolveTarget(stateNode, targets) {
|
|
|
592
604
|
}
|
|
593
605
|
});
|
|
594
606
|
}
|
|
595
|
-
function
|
|
607
|
+
function resolveHistoryDefaultTransition(stateNode) {
|
|
596
608
|
const normalizedTarget = interpreter.normalizeTarget(stateNode.config.target);
|
|
597
609
|
if (!normalizedTarget) {
|
|
598
|
-
return stateNode.parent.initial
|
|
610
|
+
return stateNode.parent.initial;
|
|
599
611
|
}
|
|
600
|
-
return
|
|
612
|
+
return {
|
|
613
|
+
target: normalizedTarget.map(t => typeof t === 'string' ? getStateNodeByPath(stateNode.parent, t) : t)
|
|
614
|
+
};
|
|
601
615
|
}
|
|
602
616
|
function isHistoryNode(stateNode) {
|
|
603
617
|
return stateNode.type === 'history';
|
|
@@ -824,9 +838,7 @@ function getEffectiveTargetStates(transition, historyValue) {
|
|
|
824
838
|
targets.add(node);
|
|
825
839
|
}
|
|
826
840
|
} else {
|
|
827
|
-
for (const node of getEffectiveTargetStates({
|
|
828
|
-
target: resolveHistoryTarget(targetNode)
|
|
829
|
-
}, historyValue)) {
|
|
841
|
+
for (const node of getEffectiveTargetStates(resolveHistoryDefaultTransition(targetNode), historyValue)) {
|
|
830
842
|
targets.add(node);
|
|
831
843
|
}
|
|
832
844
|
}
|
|
@@ -839,9 +851,9 @@ function getEffectiveTargetStates(transition, historyValue) {
|
|
|
839
851
|
function getTransitionDomain(transition, historyValue) {
|
|
840
852
|
const targetStates = getEffectiveTargetStates(transition, historyValue);
|
|
841
853
|
if (!targetStates) {
|
|
842
|
-
return
|
|
854
|
+
return;
|
|
843
855
|
}
|
|
844
|
-
if (!transition.reenter &&
|
|
856
|
+
if (!transition.reenter && targetStates.every(target => target === transition.source || isDescendant(target, transition.source))) {
|
|
845
857
|
return transition.source;
|
|
846
858
|
}
|
|
847
859
|
const lcca = findLCCA(targetStates.concat(transition.source));
|
|
@@ -852,6 +864,9 @@ function computeExitSet(transitions, configuration, historyValue) {
|
|
|
852
864
|
for (const t of transitions) {
|
|
853
865
|
if (t.target?.length) {
|
|
854
866
|
const domain = getTransitionDomain(t, historyValue);
|
|
867
|
+
if (t.reenter && t.source === domain) {
|
|
868
|
+
statesToExit.add(domain);
|
|
869
|
+
}
|
|
855
870
|
for (const stateNode of configuration) {
|
|
856
871
|
if (isDescendant(stateNode, domain)) {
|
|
857
872
|
statesToExit.add(stateNode);
|
|
@@ -928,6 +943,9 @@ function getMachineOutput(state, event, actorCtx, rootNode, rootCompletionNode)
|
|
|
928
943
|
function enterStates(currentState, event, actorCtx, filteredTransitions, mutConfiguration, internalQueue, historyValue, isInitial) {
|
|
929
944
|
let nextState = currentState;
|
|
930
945
|
const statesToEnter = new Set();
|
|
946
|
+
// those are states that were directly targeted or indirectly targeted by the explicit target
|
|
947
|
+
// in other words, those are states for which initial actions should be executed
|
|
948
|
+
// when we target `#deep_child` initial actions of its ancestors shouldn't be executed
|
|
931
949
|
const statesForDefaultEntry = new Set();
|
|
932
950
|
computeEntrySet(filteredTransitions, historyValue, statesForDefaultEntry, statesToEnter);
|
|
933
951
|
|
|
@@ -952,20 +970,16 @@ function enterStates(currentState, event, actorCtx, filteredTransitions, mutConf
|
|
|
952
970
|
nextState = resolveActionsAndContext(nextState, event, actorCtx, actions, internalQueue, stateNodeToEnter.invoke.map(invokeDef => invokeDef.id));
|
|
953
971
|
if (stateNodeToEnter.type === 'final') {
|
|
954
972
|
const parent = stateNodeToEnter.parent;
|
|
955
|
-
|
|
956
|
-
|
|
957
|
-
|
|
958
|
-
completedNodes.add(parent);
|
|
959
|
-
let rootCompletionNode = parent?.type === 'parallel' ? parent : stateNodeToEnter;
|
|
960
|
-
let ancestorMarker = parent?.parent;
|
|
961
|
-
if (ancestorMarker) {
|
|
973
|
+
let ancestorMarker = parent?.type === 'parallel' ? parent : parent?.parent;
|
|
974
|
+
let rootCompletionNode = ancestorMarker || stateNodeToEnter;
|
|
975
|
+
if (parent?.type === 'compound') {
|
|
962
976
|
internalQueue.push(interpreter.createDoneStateEvent(parent.id, stateNodeToEnter.output ? interpreter.resolveOutput(stateNodeToEnter.output, nextState.context, event, actorCtx.self) : undefined));
|
|
963
|
-
|
|
964
|
-
|
|
965
|
-
|
|
966
|
-
|
|
967
|
-
|
|
968
|
-
|
|
977
|
+
}
|
|
978
|
+
while (ancestorMarker?.type === 'parallel' && !completedNodes.has(ancestorMarker) && isInFinalState(mutConfiguration, ancestorMarker)) {
|
|
979
|
+
completedNodes.add(ancestorMarker);
|
|
980
|
+
internalQueue.push(interpreter.createDoneStateEvent(ancestorMarker.id));
|
|
981
|
+
rootCompletionNode = ancestorMarker;
|
|
982
|
+
ancestorMarker = ancestorMarker.parent;
|
|
969
983
|
}
|
|
970
984
|
if (ancestorMarker) {
|
|
971
985
|
continue;
|
|
@@ -980,13 +994,24 @@ function enterStates(currentState, event, actorCtx, filteredTransitions, mutConf
|
|
|
980
994
|
}
|
|
981
995
|
function computeEntrySet(transitions, historyValue, statesForDefaultEntry, statesToEnter) {
|
|
982
996
|
for (const t of transitions) {
|
|
997
|
+
const domain = getTransitionDomain(t, historyValue);
|
|
983
998
|
for (const s of t.target || []) {
|
|
999
|
+
if (!isHistoryNode(s) && (
|
|
1000
|
+
// if the target is different than the source then it will *definitely* be entered
|
|
1001
|
+
t.source !== s ||
|
|
1002
|
+
// we know that the domain can't lie within the source
|
|
1003
|
+
// if it's different than the source then it's outside of it and it means that the target has to be entered as well
|
|
1004
|
+
t.source !== domain ||
|
|
1005
|
+
// reentering transitions always enter the target, even if it's the source itself
|
|
1006
|
+
t.reenter)) {
|
|
1007
|
+
statesToEnter.add(s);
|
|
1008
|
+
statesForDefaultEntry.add(s);
|
|
1009
|
+
}
|
|
984
1010
|
addDescendantStatesToEnter(s, historyValue, statesForDefaultEntry, statesToEnter);
|
|
985
1011
|
}
|
|
986
|
-
const ancestor = getTransitionDomain(t, historyValue);
|
|
987
1012
|
const targetStates = getEffectiveTargetStates(t, historyValue);
|
|
988
1013
|
for (const s of targetStates) {
|
|
989
|
-
addAncestorStatesToEnter(s,
|
|
1014
|
+
addAncestorStatesToEnter(s, domain, statesToEnter, historyValue, statesForDefaultEntry);
|
|
990
1015
|
}
|
|
991
1016
|
}
|
|
992
1017
|
}
|
|
@@ -995,37 +1020,42 @@ function addDescendantStatesToEnter(stateNode, historyValue, statesForDefaultEnt
|
|
|
995
1020
|
if (historyValue[stateNode.id]) {
|
|
996
1021
|
const historyStateNodes = historyValue[stateNode.id];
|
|
997
1022
|
for (const s of historyStateNodes) {
|
|
1023
|
+
statesToEnter.add(s);
|
|
998
1024
|
addDescendantStatesToEnter(s, historyValue, statesForDefaultEntry, statesToEnter);
|
|
999
1025
|
}
|
|
1000
1026
|
for (const s of historyStateNodes) {
|
|
1001
1027
|
addAncestorStatesToEnter(s, stateNode.parent, statesToEnter, historyValue, statesForDefaultEntry);
|
|
1002
|
-
for (const stateForDefaultEntry of statesForDefaultEntry) {
|
|
1003
|
-
statesForDefaultEntry.add(stateForDefaultEntry);
|
|
1004
|
-
}
|
|
1005
1028
|
}
|
|
1006
1029
|
} else {
|
|
1007
|
-
const
|
|
1008
|
-
for (const s of
|
|
1030
|
+
const historyDefaultTransition = resolveHistoryDefaultTransition(stateNode);
|
|
1031
|
+
for (const s of historyDefaultTransition.target) {
|
|
1032
|
+
statesToEnter.add(s);
|
|
1033
|
+
if (historyDefaultTransition === stateNode.parent?.initial) {
|
|
1034
|
+
statesForDefaultEntry.add(stateNode.parent);
|
|
1035
|
+
}
|
|
1009
1036
|
addDescendantStatesToEnter(s, historyValue, statesForDefaultEntry, statesToEnter);
|
|
1010
1037
|
}
|
|
1011
|
-
for (const s of
|
|
1038
|
+
for (const s of historyDefaultTransition.target) {
|
|
1012
1039
|
addAncestorStatesToEnter(s, stateNode, statesToEnter, historyValue, statesForDefaultEntry);
|
|
1013
|
-
for (const stateForDefaultEntry of statesForDefaultEntry) {
|
|
1014
|
-
statesForDefaultEntry.add(stateForDefaultEntry);
|
|
1015
|
-
}
|
|
1016
1040
|
}
|
|
1017
1041
|
}
|
|
1018
1042
|
} else {
|
|
1019
|
-
statesToEnter.add(stateNode);
|
|
1020
1043
|
if (stateNode.type === 'compound') {
|
|
1021
|
-
statesForDefaultEntry.add(stateNode);
|
|
1022
1044
|
const [initialState] = stateNode.initial.target;
|
|
1045
|
+
if (!isHistoryNode(initialState)) {
|
|
1046
|
+
statesToEnter.add(initialState);
|
|
1047
|
+
statesForDefaultEntry.add(initialState);
|
|
1048
|
+
}
|
|
1023
1049
|
addDescendantStatesToEnter(initialState, historyValue, statesForDefaultEntry, statesToEnter);
|
|
1024
1050
|
addAncestorStatesToEnter(initialState, stateNode, statesToEnter, historyValue, statesForDefaultEntry);
|
|
1025
1051
|
} else {
|
|
1026
1052
|
if (stateNode.type === 'parallel') {
|
|
1027
1053
|
for (const child of getChildren(stateNode).filter(sn => !isHistoryNode(sn))) {
|
|
1028
1054
|
if (![...statesToEnter].some(s => isDescendant(s, child))) {
|
|
1055
|
+
if (!isHistoryNode(child)) {
|
|
1056
|
+
statesToEnter.add(child);
|
|
1057
|
+
statesForDefaultEntry.add(child);
|
|
1058
|
+
}
|
|
1029
1059
|
addDescendantStatesToEnter(child, historyValue, statesForDefaultEntry, statesToEnter);
|
|
1030
1060
|
}
|
|
1031
1061
|
}
|
|
@@ -1040,6 +1070,7 @@ function addAncestorStatesToEnter(stateNode, toStateNode, statesToEnter, history
|
|
|
1040
1070
|
if (anc.type === 'parallel') {
|
|
1041
1071
|
for (const child of getChildren(anc).filter(sn => !isHistoryNode(sn))) {
|
|
1042
1072
|
if (![...statesToEnter].some(s => isDescendant(s, child))) {
|
|
1073
|
+
statesToEnter.add(child);
|
|
1043
1074
|
addDescendantStatesToEnter(child, historyValue, statesForDefaultEntry, statesToEnter);
|
|
1044
1075
|
}
|
|
1045
1076
|
}
|
|
@@ -1210,7 +1241,7 @@ function selectEventlessTransitions(nextState, event) {
|
|
|
1210
1241
|
const enabledTransitionSet = new Set();
|
|
1211
1242
|
const atomicStates = nextState.configuration.filter(isAtomicStateNode);
|
|
1212
1243
|
for (const stateNode of atomicStates) {
|
|
1213
|
-
loop: for (const s of [stateNode].concat(getProperAncestors(stateNode,
|
|
1244
|
+
loop: for (const s of [stateNode].concat(getProperAncestors(stateNode, undefined))) {
|
|
1214
1245
|
if (!s.always) {
|
|
1215
1246
|
continue;
|
|
1216
1247
|
}
|
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import { r as resolveReferencedActor, d as createActor, f as ActorStatus, j as createErrorActorEvent, k as toStateValue, l as STATE_IDENTIFIER, n as normalizeTarget, t as toArray, N as NULL_EVENT, a as toTransitionConfigArray, S as STATE_DELIMITER, o as toStatePath, q as createDoneStateEvent, s as resolveOutput, X as XSTATE_STOP, u as XSTATE_INIT, W as WILDCARD, v as createAfterEvent, w as flatten, e as matchesState, $ as $$ACTOR_TYPE } from './interpreter-
|
|
1
|
+
import { r as resolveReferencedActor, d as createActor, f as ActorStatus, j as createErrorActorEvent, k as toStateValue, l as STATE_IDENTIFIER, n as normalizeTarget, t as toArray, N as NULL_EVENT, a as toTransitionConfigArray, S as STATE_DELIMITER, o as toStatePath, q as createDoneStateEvent, s as resolveOutput, X as XSTATE_STOP, u as XSTATE_INIT, W as WILDCARD, v as createAfterEvent, w as flatten, e as matchesState, $ as $$ACTOR_TYPE } from './interpreter-8def682e.esm.js';
|
|
2
2
|
|
|
3
3
|
const cache = new WeakMap();
|
|
4
4
|
function memo(object, key, fn) {
|
|
@@ -47,14 +47,17 @@ function resolveInvoke(actorContext, state, actionArgs, {
|
|
|
47
47
|
input,
|
|
48
48
|
syncSnapshot
|
|
49
49
|
}) {
|
|
50
|
-
const referenced = resolveReferencedActor(state.machine
|
|
50
|
+
const referenced = typeof src === 'string' ? resolveReferencedActor(state.machine, src) : {
|
|
51
|
+
src,
|
|
52
|
+
input: undefined
|
|
53
|
+
};
|
|
51
54
|
let actorRef;
|
|
52
55
|
if (referenced) {
|
|
53
56
|
// TODO: inline `input: undefined` should win over the referenced one
|
|
54
57
|
const configuredInput = input || referenced.input;
|
|
55
58
|
actorRef = createActor(referenced.src, {
|
|
56
59
|
id,
|
|
57
|
-
src,
|
|
60
|
+
src: typeof src === 'string' ? src : undefined,
|
|
58
61
|
parent: actorContext?.self,
|
|
59
62
|
systemId,
|
|
60
63
|
input: typeof configuredInput === 'function' ? configuredInput({
|
|
@@ -151,11 +154,16 @@ function executeStop(actorContext, actorRef) {
|
|
|
151
154
|
if (!actorRef) {
|
|
152
155
|
return;
|
|
153
156
|
}
|
|
157
|
+
// this allows us to prevent an actor from being started if it gets stopped within the same macrostep
|
|
158
|
+
// this can happen, for example, when the invoking state is being exited immediately by an always transition
|
|
154
159
|
if (actorRef.status !== ActorStatus.Running) {
|
|
155
160
|
actorContext.stopChild(actorRef);
|
|
156
161
|
return;
|
|
157
162
|
}
|
|
158
|
-
//
|
|
163
|
+
// stopping a child enqueues a stop event in the child actor's mailbox
|
|
164
|
+
// we need for all of the already enqueued events to be processed before we stop the child
|
|
165
|
+
// the parent itself might want to send some events to a child (for example from exit actions on the invoking state)
|
|
166
|
+
// and we don't want to ignore those events
|
|
159
167
|
actorContext.defer(() => {
|
|
160
168
|
actorContext.stopChild(actorRef);
|
|
161
169
|
});
|
|
@@ -179,7 +187,8 @@ function checkStateIn(state, _, {
|
|
|
179
187
|
stateValue
|
|
180
188
|
}) {
|
|
181
189
|
if (typeof stateValue === 'string' && isStateId(stateValue)) {
|
|
182
|
-
|
|
190
|
+
const target = state.machine.getStateNodeById(stateValue);
|
|
191
|
+
return state.configuration.some(sn => sn === target);
|
|
183
192
|
}
|
|
184
193
|
return state.matches(stateValue);
|
|
185
194
|
}
|
|
@@ -283,6 +292,9 @@ function getChildren(stateNode) {
|
|
|
283
292
|
}
|
|
284
293
|
function getProperAncestors(stateNode, toStateNode) {
|
|
285
294
|
const ancestors = [];
|
|
295
|
+
if (toStateNode === stateNode) {
|
|
296
|
+
return ancestors;
|
|
297
|
+
}
|
|
286
298
|
|
|
287
299
|
// add all ancestors
|
|
288
300
|
let m = stateNode.parent;
|
|
@@ -559,12 +571,14 @@ function resolveTarget(stateNode, targets) {
|
|
|
559
571
|
}
|
|
560
572
|
});
|
|
561
573
|
}
|
|
562
|
-
function
|
|
574
|
+
function resolveHistoryDefaultTransition(stateNode) {
|
|
563
575
|
const normalizedTarget = normalizeTarget(stateNode.config.target);
|
|
564
576
|
if (!normalizedTarget) {
|
|
565
|
-
return stateNode.parent.initial
|
|
577
|
+
return stateNode.parent.initial;
|
|
566
578
|
}
|
|
567
|
-
return
|
|
579
|
+
return {
|
|
580
|
+
target: normalizedTarget.map(t => typeof t === 'string' ? getStateNodeByPath(stateNode.parent, t) : t)
|
|
581
|
+
};
|
|
568
582
|
}
|
|
569
583
|
function isHistoryNode(stateNode) {
|
|
570
584
|
return stateNode.type === 'history';
|
|
@@ -791,9 +805,7 @@ function getEffectiveTargetStates(transition, historyValue) {
|
|
|
791
805
|
targets.add(node);
|
|
792
806
|
}
|
|
793
807
|
} else {
|
|
794
|
-
for (const node of getEffectiveTargetStates({
|
|
795
|
-
target: resolveHistoryTarget(targetNode)
|
|
796
|
-
}, historyValue)) {
|
|
808
|
+
for (const node of getEffectiveTargetStates(resolveHistoryDefaultTransition(targetNode), historyValue)) {
|
|
797
809
|
targets.add(node);
|
|
798
810
|
}
|
|
799
811
|
}
|
|
@@ -806,9 +818,9 @@ function getEffectiveTargetStates(transition, historyValue) {
|
|
|
806
818
|
function getTransitionDomain(transition, historyValue) {
|
|
807
819
|
const targetStates = getEffectiveTargetStates(transition, historyValue);
|
|
808
820
|
if (!targetStates) {
|
|
809
|
-
return
|
|
821
|
+
return;
|
|
810
822
|
}
|
|
811
|
-
if (!transition.reenter &&
|
|
823
|
+
if (!transition.reenter && targetStates.every(target => target === transition.source || isDescendant(target, transition.source))) {
|
|
812
824
|
return transition.source;
|
|
813
825
|
}
|
|
814
826
|
const lcca = findLCCA(targetStates.concat(transition.source));
|
|
@@ -819,6 +831,9 @@ function computeExitSet(transitions, configuration, historyValue) {
|
|
|
819
831
|
for (const t of transitions) {
|
|
820
832
|
if (t.target?.length) {
|
|
821
833
|
const domain = getTransitionDomain(t, historyValue);
|
|
834
|
+
if (t.reenter && t.source === domain) {
|
|
835
|
+
statesToExit.add(domain);
|
|
836
|
+
}
|
|
822
837
|
for (const stateNode of configuration) {
|
|
823
838
|
if (isDescendant(stateNode, domain)) {
|
|
824
839
|
statesToExit.add(stateNode);
|
|
@@ -895,6 +910,9 @@ function getMachineOutput(state, event, actorCtx, rootNode, rootCompletionNode)
|
|
|
895
910
|
function enterStates(currentState, event, actorCtx, filteredTransitions, mutConfiguration, internalQueue, historyValue, isInitial) {
|
|
896
911
|
let nextState = currentState;
|
|
897
912
|
const statesToEnter = new Set();
|
|
913
|
+
// those are states that were directly targeted or indirectly targeted by the explicit target
|
|
914
|
+
// in other words, those are states for which initial actions should be executed
|
|
915
|
+
// when we target `#deep_child` initial actions of its ancestors shouldn't be executed
|
|
898
916
|
const statesForDefaultEntry = new Set();
|
|
899
917
|
computeEntrySet(filteredTransitions, historyValue, statesForDefaultEntry, statesToEnter);
|
|
900
918
|
|
|
@@ -919,20 +937,16 @@ function enterStates(currentState, event, actorCtx, filteredTransitions, mutConf
|
|
|
919
937
|
nextState = resolveActionsAndContext(nextState, event, actorCtx, actions, internalQueue, stateNodeToEnter.invoke.map(invokeDef => invokeDef.id));
|
|
920
938
|
if (stateNodeToEnter.type === 'final') {
|
|
921
939
|
const parent = stateNodeToEnter.parent;
|
|
922
|
-
|
|
923
|
-
|
|
924
|
-
|
|
925
|
-
completedNodes.add(parent);
|
|
926
|
-
let rootCompletionNode = parent?.type === 'parallel' ? parent : stateNodeToEnter;
|
|
927
|
-
let ancestorMarker = parent?.parent;
|
|
928
|
-
if (ancestorMarker) {
|
|
940
|
+
let ancestorMarker = parent?.type === 'parallel' ? parent : parent?.parent;
|
|
941
|
+
let rootCompletionNode = ancestorMarker || stateNodeToEnter;
|
|
942
|
+
if (parent?.type === 'compound') {
|
|
929
943
|
internalQueue.push(createDoneStateEvent(parent.id, stateNodeToEnter.output ? resolveOutput(stateNodeToEnter.output, nextState.context, event, actorCtx.self) : undefined));
|
|
930
|
-
|
|
931
|
-
|
|
932
|
-
|
|
933
|
-
|
|
934
|
-
|
|
935
|
-
|
|
944
|
+
}
|
|
945
|
+
while (ancestorMarker?.type === 'parallel' && !completedNodes.has(ancestorMarker) && isInFinalState(mutConfiguration, ancestorMarker)) {
|
|
946
|
+
completedNodes.add(ancestorMarker);
|
|
947
|
+
internalQueue.push(createDoneStateEvent(ancestorMarker.id));
|
|
948
|
+
rootCompletionNode = ancestorMarker;
|
|
949
|
+
ancestorMarker = ancestorMarker.parent;
|
|
936
950
|
}
|
|
937
951
|
if (ancestorMarker) {
|
|
938
952
|
continue;
|
|
@@ -947,13 +961,24 @@ function enterStates(currentState, event, actorCtx, filteredTransitions, mutConf
|
|
|
947
961
|
}
|
|
948
962
|
function computeEntrySet(transitions, historyValue, statesForDefaultEntry, statesToEnter) {
|
|
949
963
|
for (const t of transitions) {
|
|
964
|
+
const domain = getTransitionDomain(t, historyValue);
|
|
950
965
|
for (const s of t.target || []) {
|
|
966
|
+
if (!isHistoryNode(s) && (
|
|
967
|
+
// if the target is different than the source then it will *definitely* be entered
|
|
968
|
+
t.source !== s ||
|
|
969
|
+
// we know that the domain can't lie within the source
|
|
970
|
+
// if it's different than the source then it's outside of it and it means that the target has to be entered as well
|
|
971
|
+
t.source !== domain ||
|
|
972
|
+
// reentering transitions always enter the target, even if it's the source itself
|
|
973
|
+
t.reenter)) {
|
|
974
|
+
statesToEnter.add(s);
|
|
975
|
+
statesForDefaultEntry.add(s);
|
|
976
|
+
}
|
|
951
977
|
addDescendantStatesToEnter(s, historyValue, statesForDefaultEntry, statesToEnter);
|
|
952
978
|
}
|
|
953
|
-
const ancestor = getTransitionDomain(t, historyValue);
|
|
954
979
|
const targetStates = getEffectiveTargetStates(t, historyValue);
|
|
955
980
|
for (const s of targetStates) {
|
|
956
|
-
addAncestorStatesToEnter(s,
|
|
981
|
+
addAncestorStatesToEnter(s, domain, statesToEnter, historyValue, statesForDefaultEntry);
|
|
957
982
|
}
|
|
958
983
|
}
|
|
959
984
|
}
|
|
@@ -962,37 +987,42 @@ function addDescendantStatesToEnter(stateNode, historyValue, statesForDefaultEnt
|
|
|
962
987
|
if (historyValue[stateNode.id]) {
|
|
963
988
|
const historyStateNodes = historyValue[stateNode.id];
|
|
964
989
|
for (const s of historyStateNodes) {
|
|
990
|
+
statesToEnter.add(s);
|
|
965
991
|
addDescendantStatesToEnter(s, historyValue, statesForDefaultEntry, statesToEnter);
|
|
966
992
|
}
|
|
967
993
|
for (const s of historyStateNodes) {
|
|
968
994
|
addAncestorStatesToEnter(s, stateNode.parent, statesToEnter, historyValue, statesForDefaultEntry);
|
|
969
|
-
for (const stateForDefaultEntry of statesForDefaultEntry) {
|
|
970
|
-
statesForDefaultEntry.add(stateForDefaultEntry);
|
|
971
|
-
}
|
|
972
995
|
}
|
|
973
996
|
} else {
|
|
974
|
-
const
|
|
975
|
-
for (const s of
|
|
997
|
+
const historyDefaultTransition = resolveHistoryDefaultTransition(stateNode);
|
|
998
|
+
for (const s of historyDefaultTransition.target) {
|
|
999
|
+
statesToEnter.add(s);
|
|
1000
|
+
if (historyDefaultTransition === stateNode.parent?.initial) {
|
|
1001
|
+
statesForDefaultEntry.add(stateNode.parent);
|
|
1002
|
+
}
|
|
976
1003
|
addDescendantStatesToEnter(s, historyValue, statesForDefaultEntry, statesToEnter);
|
|
977
1004
|
}
|
|
978
|
-
for (const s of
|
|
1005
|
+
for (const s of historyDefaultTransition.target) {
|
|
979
1006
|
addAncestorStatesToEnter(s, stateNode, statesToEnter, historyValue, statesForDefaultEntry);
|
|
980
|
-
for (const stateForDefaultEntry of statesForDefaultEntry) {
|
|
981
|
-
statesForDefaultEntry.add(stateForDefaultEntry);
|
|
982
|
-
}
|
|
983
1007
|
}
|
|
984
1008
|
}
|
|
985
1009
|
} else {
|
|
986
|
-
statesToEnter.add(stateNode);
|
|
987
1010
|
if (stateNode.type === 'compound') {
|
|
988
|
-
statesForDefaultEntry.add(stateNode);
|
|
989
1011
|
const [initialState] = stateNode.initial.target;
|
|
1012
|
+
if (!isHistoryNode(initialState)) {
|
|
1013
|
+
statesToEnter.add(initialState);
|
|
1014
|
+
statesForDefaultEntry.add(initialState);
|
|
1015
|
+
}
|
|
990
1016
|
addDescendantStatesToEnter(initialState, historyValue, statesForDefaultEntry, statesToEnter);
|
|
991
1017
|
addAncestorStatesToEnter(initialState, stateNode, statesToEnter, historyValue, statesForDefaultEntry);
|
|
992
1018
|
} else {
|
|
993
1019
|
if (stateNode.type === 'parallel') {
|
|
994
1020
|
for (const child of getChildren(stateNode).filter(sn => !isHistoryNode(sn))) {
|
|
995
1021
|
if (![...statesToEnter].some(s => isDescendant(s, child))) {
|
|
1022
|
+
if (!isHistoryNode(child)) {
|
|
1023
|
+
statesToEnter.add(child);
|
|
1024
|
+
statesForDefaultEntry.add(child);
|
|
1025
|
+
}
|
|
996
1026
|
addDescendantStatesToEnter(child, historyValue, statesForDefaultEntry, statesToEnter);
|
|
997
1027
|
}
|
|
998
1028
|
}
|
|
@@ -1007,6 +1037,7 @@ function addAncestorStatesToEnter(stateNode, toStateNode, statesToEnter, history
|
|
|
1007
1037
|
if (anc.type === 'parallel') {
|
|
1008
1038
|
for (const child of getChildren(anc).filter(sn => !isHistoryNode(sn))) {
|
|
1009
1039
|
if (![...statesToEnter].some(s => isDescendant(s, child))) {
|
|
1040
|
+
statesToEnter.add(child);
|
|
1010
1041
|
addDescendantStatesToEnter(child, historyValue, statesForDefaultEntry, statesToEnter);
|
|
1011
1042
|
}
|
|
1012
1043
|
}
|
|
@@ -1174,7 +1205,7 @@ function selectEventlessTransitions(nextState, event) {
|
|
|
1174
1205
|
const enabledTransitionSet = new Set();
|
|
1175
1206
|
const atomicStates = nextState.configuration.filter(isAtomicStateNode);
|
|
1176
1207
|
for (const stateNode of atomicStates) {
|
|
1177
|
-
loop: for (const s of [stateNode].concat(getProperAncestors(stateNode,
|
|
1208
|
+
loop: for (const s of [stateNode].concat(getProperAncestors(stateNode, undefined))) {
|
|
1178
1209
|
if (!s.always) {
|
|
1179
1210
|
continue;
|
|
1180
1211
|
}
|