xstate 5.0.0-beta.27 → 5.0.0-beta.29
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 +9 -7
- package/actions/dist/xstate-actions.cjs.js +11 -17
- package/actions/dist/xstate-actions.cjs.mjs +0 -8
- package/actions/dist/xstate-actions.development.cjs.js +11 -17
- package/actions/dist/xstate-actions.development.cjs.mjs +0 -8
- package/actions/dist/xstate-actions.development.esm.js +3 -1
- package/actions/dist/xstate-actions.esm.js +3 -1
- 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 +395 -28
- package/actors/dist/xstate-actors.cjs.mjs +1 -3
- package/actors/dist/xstate-actors.development.cjs.js +395 -28
- package/actors/dist/xstate-actors.development.cjs.mjs +1 -3
- package/actors/dist/xstate-actors.development.esm.js +389 -21
- package/actors/dist/xstate-actors.esm.js +389 -21
- 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/StateNode.d.ts +3 -3
- package/dist/declarations/src/actions/assign.d.ts +9 -4
- package/dist/declarations/src/actions/cancel.d.ts +4 -4
- package/dist/declarations/src/actions/choose.d.ts +5 -4
- package/dist/declarations/src/actions/log.d.ts +4 -4
- package/dist/declarations/src/actions/pure.d.ts +6 -5
- package/dist/declarations/src/actions/raise.d.ts +2 -2
- package/dist/declarations/src/actions/send.d.ts +7 -7
- package/dist/declarations/src/actions/stop.d.ts +4 -4
- package/dist/declarations/src/actions.d.ts +8 -44
- package/dist/declarations/src/actors/callback.d.ts +2 -2
- package/dist/declarations/src/actors/index.d.ts +3 -5
- package/dist/declarations/src/constants.d.ts +1 -0
- package/dist/declarations/src/index.d.ts +9 -16
- package/dist/declarations/src/spawn.d.ts +25 -0
- package/dist/declarations/src/stateUtils.d.ts +1 -1
- package/dist/declarations/src/typegenTypes.d.ts +4 -4
- package/dist/declarations/src/types.d.ts +92 -122
- package/dist/declarations/src/utils.d.ts +2 -2
- package/dist/interpreter-498891b2.esm.js +741 -0
- package/dist/interpreter-6e7909c8.development.esm.js +749 -0
- package/dist/interpreter-c357bc50.cjs.js +773 -0
- package/dist/interpreter-e2c6a579.development.cjs.js +781 -0
- package/dist/{actions-9754d2ca.development.esm.js → raise-03e57569.cjs.js} +130 -1307
- package/dist/{actions-d1dba4ac.cjs.js → raise-59f2c242.esm.js} +65 -1267
- package/dist/{actions-020463e9.esm.js → raise-e778a828.development.esm.js} +109 -1203
- package/dist/{actions-ca622922.development.cjs.js → raise-f751dfac.development.cjs.js} +101 -1306
- package/dist/send-42c83fb2.development.esm.js +364 -0
- package/dist/send-51717e53.cjs.js +349 -0
- package/dist/send-f53778f6.development.cjs.js +374 -0
- package/dist/send-fff224db.esm.js +339 -0
- package/dist/xstate.cjs.js +114 -112
- package/dist/xstate.cjs.mjs +2 -2
- package/dist/xstate.development.cjs.js +114 -112
- package/dist/xstate.development.cjs.mjs +2 -2
- package/dist/xstate.development.esm.js +78 -74
- package/dist/xstate.esm.js +78 -74
- 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 -1
- package/guards/dist/xstate-guards.development.cjs.js +2 -1
- package/guards/dist/xstate-guards.development.esm.js +2 -1
- package/guards/dist/xstate-guards.esm.js +2 -1
- package/guards/dist/xstate-guards.umd.min.js.map +1 -1
- package/package.json +1 -1
- package/dist/declarations/src/constantPrefixes.d.ts +0 -6
- package/dist/promise-2ad94e3b.development.esm.js +0 -406
- package/dist/promise-3b7e3357.development.cjs.js +0 -412
- package/dist/promise-5b07c38e.esm.js +0 -406
- package/dist/promise-7a8c1768.cjs.js +0 -412
|
@@ -1,211 +1,6 @@
|
|
|
1
1
|
'use strict';
|
|
2
2
|
|
|
3
|
-
var
|
|
4
|
-
|
|
5
|
-
/**
|
|
6
|
-
* `T | unknown` reduces to `unknown` and that can be problematic when it comes to contextual typing.
|
|
7
|
-
* It especially is a problem when the union has a function member, like here:
|
|
8
|
-
*
|
|
9
|
-
* ```ts
|
|
10
|
-
* declare function test(cbOrVal: ((arg: number) => unknown) | unknown): void;
|
|
11
|
-
* test((arg) => {}) // oops, implicit any
|
|
12
|
-
* ```
|
|
13
|
-
*
|
|
14
|
-
* This type can be used to avoid this problem. This union represents the same value space as `unknown`.
|
|
15
|
-
*/
|
|
16
|
-
|
|
17
|
-
// https://github.com/microsoft/TypeScript/issues/23182#issuecomment-379091887
|
|
18
|
-
|
|
19
|
-
/**
|
|
20
|
-
* The full definition of an event, with a string `type`.
|
|
21
|
-
*/
|
|
22
|
-
|
|
23
|
-
// TODO: do not accept machines without all implementations
|
|
24
|
-
// we should also accept a raw machine as actor logic here
|
|
25
|
-
// or just make machine actor logic
|
|
26
|
-
|
|
27
|
-
/**
|
|
28
|
-
* The string or object representing the state value relative to the parent state node.
|
|
29
|
-
*
|
|
30
|
-
* - For a child atomic state node, this is a string, e.g., `"pending"`.
|
|
31
|
-
* - For complex state nodes, this is an object, e.g., `{ success: "someChildState" }`.
|
|
32
|
-
*/
|
|
33
|
-
|
|
34
|
-
// TODO: remove once TS fixes this type-widening issue
|
|
35
|
-
|
|
36
|
-
// TODO: possibly refactor this somehow, use even a simpler type, and maybe even make `machine.options` private or something
|
|
37
|
-
|
|
38
|
-
let ConstantPrefix = /*#__PURE__*/function (ConstantPrefix) {
|
|
39
|
-
ConstantPrefix["After"] = "xstate.after";
|
|
40
|
-
ConstantPrefix["DoneState"] = "done.state";
|
|
41
|
-
ConstantPrefix["DoneInvoke"] = "done.invoke";
|
|
42
|
-
ConstantPrefix["ErrorExecution"] = "error.execution";
|
|
43
|
-
ConstantPrefix["ErrorCommunication"] = "error.communication";
|
|
44
|
-
ConstantPrefix["ErrorPlatform"] = "error.platform";
|
|
45
|
-
ConstantPrefix["ErrorCustom"] = "xstate.error";
|
|
46
|
-
return ConstantPrefix;
|
|
47
|
-
}({});
|
|
48
|
-
let SpecialTargets = /*#__PURE__*/function (SpecialTargets) {
|
|
49
|
-
SpecialTargets["Parent"] = "#_parent";
|
|
50
|
-
SpecialTargets["Internal"] = "#_internal";
|
|
51
|
-
return SpecialTargets;
|
|
52
|
-
}({});
|
|
53
|
-
|
|
54
|
-
const after$1 = ConstantPrefix.After;
|
|
55
|
-
const doneState = ConstantPrefix.DoneState;
|
|
56
|
-
const errorExecution = ConstantPrefix.ErrorExecution;
|
|
57
|
-
const errorPlatform = ConstantPrefix.ErrorPlatform;
|
|
58
|
-
const error$1 = ConstantPrefix.ErrorCustom;
|
|
59
|
-
|
|
60
|
-
var constantPrefixes = /*#__PURE__*/Object.freeze({
|
|
61
|
-
__proto__: null,
|
|
62
|
-
after: after$1,
|
|
63
|
-
doneState: doneState,
|
|
64
|
-
errorExecution: errorExecution,
|
|
65
|
-
errorPlatform: errorPlatform,
|
|
66
|
-
error: error$1
|
|
67
|
-
});
|
|
68
|
-
|
|
69
|
-
const STATE_DELIMITER = '.';
|
|
70
|
-
const TARGETLESS_KEY = '';
|
|
71
|
-
const NULL_EVENT = '';
|
|
72
|
-
const STATE_IDENTIFIER = '#';
|
|
73
|
-
const WILDCARD = '*';
|
|
74
|
-
const XSTATE_INIT = 'xstate.init';
|
|
75
|
-
const XSTATE_STOP = 'xstate.stop';
|
|
76
|
-
|
|
77
|
-
function resolve$8(actorContext, state, args, {
|
|
78
|
-
to,
|
|
79
|
-
event: eventOrExpr,
|
|
80
|
-
id,
|
|
81
|
-
delay
|
|
82
|
-
}) {
|
|
83
|
-
const delaysMap = state.machine.implementations.delays;
|
|
84
|
-
if (typeof eventOrExpr === 'string') {
|
|
85
|
-
throw new Error(`Only event objects may be used with sendTo; use sendTo({ type: "${eventOrExpr}" }) instead`);
|
|
86
|
-
}
|
|
87
|
-
const resolvedEvent = typeof eventOrExpr === 'function' ? eventOrExpr(args) : eventOrExpr;
|
|
88
|
-
let resolvedDelay;
|
|
89
|
-
if (typeof delay === 'string') {
|
|
90
|
-
const configDelay = delaysMap && delaysMap[delay];
|
|
91
|
-
resolvedDelay = typeof configDelay === 'function' ? configDelay(args) : configDelay;
|
|
92
|
-
} else {
|
|
93
|
-
resolvedDelay = typeof delay === 'function' ? delay(args) : delay;
|
|
94
|
-
}
|
|
95
|
-
const resolvedTarget = typeof to === 'function' ? to(args) : to;
|
|
96
|
-
let targetActorRef;
|
|
97
|
-
if (typeof resolvedTarget === 'string') {
|
|
98
|
-
if (resolvedTarget === SpecialTargets.Parent) {
|
|
99
|
-
targetActorRef = actorContext?.self._parent;
|
|
100
|
-
} else if (resolvedTarget === SpecialTargets.Internal) {
|
|
101
|
-
targetActorRef = actorContext?.self;
|
|
102
|
-
} else if (resolvedTarget.startsWith('#_')) {
|
|
103
|
-
// SCXML compatibility: https://www.w3.org/TR/scxml/#SCXMLEventProcessor
|
|
104
|
-
// #_invokeid. If the target is the special term '#_invokeid', where invokeid is the invokeid of an SCXML session that the sending session has created by <invoke>, the Processor must add the event to the external queue of that session.
|
|
105
|
-
targetActorRef = state.children[resolvedTarget.slice(2)];
|
|
106
|
-
} else {
|
|
107
|
-
targetActorRef = state.children[resolvedTarget];
|
|
108
|
-
}
|
|
109
|
-
if (!targetActorRef) {
|
|
110
|
-
throw new Error(`Unable to send event to actor '${resolvedTarget}' from machine '${state.machine.id}'.`);
|
|
111
|
-
}
|
|
112
|
-
} else {
|
|
113
|
-
targetActorRef = resolvedTarget || actorContext?.self;
|
|
114
|
-
}
|
|
115
|
-
return [state, {
|
|
116
|
-
to: targetActorRef,
|
|
117
|
-
event: resolvedEvent,
|
|
118
|
-
id,
|
|
119
|
-
delay: resolvedDelay
|
|
120
|
-
}];
|
|
121
|
-
}
|
|
122
|
-
function execute$5(actorContext, params) {
|
|
123
|
-
if (typeof params.delay === 'number') {
|
|
124
|
-
actorContext.self.delaySend(params);
|
|
125
|
-
return;
|
|
126
|
-
}
|
|
127
|
-
const {
|
|
128
|
-
to,
|
|
129
|
-
event
|
|
130
|
-
} = params;
|
|
131
|
-
actorContext.defer(() => {
|
|
132
|
-
to.send(event.type === error$1 ? {
|
|
133
|
-
type: `${error(actorContext.self.id)}`,
|
|
134
|
-
data: event.data
|
|
135
|
-
} : event);
|
|
136
|
-
});
|
|
137
|
-
}
|
|
138
|
-
/**
|
|
139
|
-
* Sends an event to an actor.
|
|
140
|
-
*
|
|
141
|
-
* @param actor The `ActorRef` to send the event to.
|
|
142
|
-
* @param event The event to send, or an expression that evaluates to the event to send
|
|
143
|
-
* @param options Send action options
|
|
144
|
-
* - `id` - The unique send event identifier (used with `cancel()`).
|
|
145
|
-
* - `delay` - The number of milliseconds to delay the sending of the event.
|
|
146
|
-
*/
|
|
147
|
-
function sendTo(to, eventOrExpr, options) {
|
|
148
|
-
function sendTo(_) {
|
|
149
|
-
{
|
|
150
|
-
throw new Error(`This isn't supposed to be called`);
|
|
151
|
-
}
|
|
152
|
-
}
|
|
153
|
-
sendTo.type = 'xstate.sendTo';
|
|
154
|
-
sendTo.to = to;
|
|
155
|
-
sendTo.event = eventOrExpr;
|
|
156
|
-
sendTo.id = options?.id;
|
|
157
|
-
sendTo.delay = options?.delay;
|
|
158
|
-
sendTo.resolve = resolve$8;
|
|
159
|
-
sendTo.execute = execute$5;
|
|
160
|
-
return sendTo;
|
|
161
|
-
}
|
|
162
|
-
|
|
163
|
-
/**
|
|
164
|
-
* Sends an event to this machine's parent.
|
|
165
|
-
*
|
|
166
|
-
* @param event The event to send to the parent machine.
|
|
167
|
-
* @param options Options to pass into the send event.
|
|
168
|
-
*/
|
|
169
|
-
function sendParent(event, options) {
|
|
170
|
-
return sendTo(SpecialTargets.Parent, event, options);
|
|
171
|
-
}
|
|
172
|
-
/**
|
|
173
|
-
* Forwards (sends) an event to a specified service.
|
|
174
|
-
*
|
|
175
|
-
* @param target The target service to forward the event to.
|
|
176
|
-
* @param options Options to pass into the send action creator.
|
|
177
|
-
*/
|
|
178
|
-
function forwardTo(target, options) {
|
|
179
|
-
if ((!target || typeof target === 'function')) {
|
|
180
|
-
const originalTarget = target;
|
|
181
|
-
target = (...args) => {
|
|
182
|
-
const resolvedTarget = typeof originalTarget === 'function' ? originalTarget(...args) : originalTarget;
|
|
183
|
-
if (!resolvedTarget) {
|
|
184
|
-
throw new Error(`Attempted to forward event to undefined actor. This risks an infinite loop in the sender.`);
|
|
185
|
-
}
|
|
186
|
-
return resolvedTarget;
|
|
187
|
-
};
|
|
188
|
-
}
|
|
189
|
-
return sendTo(target, ({
|
|
190
|
-
event
|
|
191
|
-
}) => event, options);
|
|
192
|
-
}
|
|
193
|
-
|
|
194
|
-
/**
|
|
195
|
-
* Escalates an error by sending it as an event to this machine's parent.
|
|
196
|
-
*
|
|
197
|
-
* @param errorData The error data to send, or the expression function that
|
|
198
|
-
* takes in the `context`, `event`, and `meta`, and returns the error data to send.
|
|
199
|
-
* @param options Options to pass into the send action creator.
|
|
200
|
-
*/
|
|
201
|
-
function escalate(errorData, options) {
|
|
202
|
-
return sendParent(arg => {
|
|
203
|
-
return {
|
|
204
|
-
type: error$1,
|
|
205
|
-
data: typeof errorData === 'function' ? errorData(arg) : errorData
|
|
206
|
-
};
|
|
207
|
-
}, options);
|
|
208
|
-
}
|
|
3
|
+
var interpreter = require('./interpreter-e2c6a579.development.cjs.js');
|
|
209
4
|
|
|
210
5
|
const cache = new WeakMap();
|
|
211
6
|
function memo(object, key, fn) {
|
|
@@ -221,13 +16,13 @@ function memo(object, key, fn) {
|
|
|
221
16
|
return memoizedData[key];
|
|
222
17
|
}
|
|
223
18
|
|
|
224
|
-
function resolve$
|
|
19
|
+
function resolve$3(_, state, actionArgs, {
|
|
225
20
|
sendId
|
|
226
21
|
}) {
|
|
227
22
|
const resolvedSendId = typeof sendId === 'function' ? sendId(actionArgs) : sendId;
|
|
228
23
|
return [state, resolvedSendId];
|
|
229
24
|
}
|
|
230
|
-
function execute$
|
|
25
|
+
function execute$3(actorContext, resolvedSendId) {
|
|
231
26
|
actorContext.self.cancel(resolvedSendId);
|
|
232
27
|
}
|
|
233
28
|
/**
|
|
@@ -245,720 +40,23 @@ function cancel(sendId) {
|
|
|
245
40
|
}
|
|
246
41
|
cancel.type = 'xstate.cancel';
|
|
247
42
|
cancel.sendId = sendId;
|
|
248
|
-
cancel.resolve = resolve$
|
|
249
|
-
cancel.execute = execute$
|
|
43
|
+
cancel.resolve = resolve$3;
|
|
44
|
+
cancel.execute = execute$3;
|
|
250
45
|
return cancel;
|
|
251
46
|
}
|
|
252
47
|
|
|
253
|
-
|
|
254
|
-
constructor(_process) {
|
|
255
|
-
this._process = _process;
|
|
256
|
-
this._active = false;
|
|
257
|
-
this._current = null;
|
|
258
|
-
this._last = null;
|
|
259
|
-
}
|
|
260
|
-
start() {
|
|
261
|
-
this._active = true;
|
|
262
|
-
this.flush();
|
|
263
|
-
}
|
|
264
|
-
clear() {
|
|
265
|
-
// we can't set _current to null because we might be currently processing
|
|
266
|
-
// and enqueue following clear shouldnt start processing the enqueued item immediately
|
|
267
|
-
if (this._current) {
|
|
268
|
-
this._current.next = null;
|
|
269
|
-
this._last = this._current;
|
|
270
|
-
}
|
|
271
|
-
}
|
|
272
|
-
|
|
273
|
-
// TODO: rethink this design
|
|
274
|
-
prepend(event) {
|
|
275
|
-
if (!this._current) {
|
|
276
|
-
this.enqueue(event);
|
|
277
|
-
return;
|
|
278
|
-
}
|
|
279
|
-
|
|
280
|
-
// we know that something is already queued up
|
|
281
|
-
// so the mailbox is already flushing or it's inactive
|
|
282
|
-
// therefore the only thing that we need to do is to reassign `this._current`
|
|
283
|
-
this._current = {
|
|
284
|
-
value: event,
|
|
285
|
-
next: this._current
|
|
286
|
-
};
|
|
287
|
-
}
|
|
288
|
-
enqueue(event) {
|
|
289
|
-
const enqueued = {
|
|
290
|
-
value: event,
|
|
291
|
-
next: null
|
|
292
|
-
};
|
|
293
|
-
if (this._current) {
|
|
294
|
-
this._last.next = enqueued;
|
|
295
|
-
this._last = enqueued;
|
|
296
|
-
return;
|
|
297
|
-
}
|
|
298
|
-
this._current = enqueued;
|
|
299
|
-
this._last = enqueued;
|
|
300
|
-
if (this._active) {
|
|
301
|
-
this.flush();
|
|
302
|
-
}
|
|
303
|
-
}
|
|
304
|
-
flush() {
|
|
305
|
-
while (this._current) {
|
|
306
|
-
// atm the given _process is responsible for implementing proper try/catch handling
|
|
307
|
-
// we assume here that this won't throw in a way that can affect this mailbox
|
|
308
|
-
const consumed = this._current;
|
|
309
|
-
this._process(consumed.value);
|
|
310
|
-
// something could have been prepended in the meantime
|
|
311
|
-
// so we need to be defensive here to avoid skipping over a prepended item
|
|
312
|
-
if (consumed === this._current) {
|
|
313
|
-
this._current = this._current.next;
|
|
314
|
-
}
|
|
315
|
-
}
|
|
316
|
-
this._last = null;
|
|
317
|
-
}
|
|
318
|
-
}
|
|
319
|
-
|
|
320
|
-
/**
|
|
321
|
-
* This function makes sure that unhandled errors are thrown in a separate macrotask.
|
|
322
|
-
* It allows those errors to be detected by global error handlers and reported to bug tracking services
|
|
323
|
-
* without interrupting our own stack of execution.
|
|
324
|
-
*
|
|
325
|
-
* @param err error to be thrown
|
|
326
|
-
*/
|
|
327
|
-
function reportUnhandledError(err) {
|
|
328
|
-
setTimeout(() => {
|
|
329
|
-
throw err;
|
|
330
|
-
});
|
|
331
|
-
}
|
|
332
|
-
|
|
333
|
-
const symbolObservable = (() => typeof Symbol === 'function' && Symbol.observable || '@@observable')();
|
|
334
|
-
|
|
335
|
-
function createSystem() {
|
|
336
|
-
let sessionIdCounter = 0;
|
|
337
|
-
const children = new Map();
|
|
338
|
-
const keyedActors = new Map();
|
|
339
|
-
const reverseKeyedActors = new WeakMap();
|
|
340
|
-
const system = {
|
|
341
|
-
_bookId: () => `x:${sessionIdCounter++}`,
|
|
342
|
-
_register: (sessionId, actorRef) => {
|
|
343
|
-
children.set(sessionId, actorRef);
|
|
344
|
-
return sessionId;
|
|
345
|
-
},
|
|
346
|
-
_unregister: actorRef => {
|
|
347
|
-
children.delete(actorRef.sessionId);
|
|
348
|
-
const systemId = reverseKeyedActors.get(actorRef);
|
|
349
|
-
if (systemId !== undefined) {
|
|
350
|
-
keyedActors.delete(systemId);
|
|
351
|
-
reverseKeyedActors.delete(actorRef);
|
|
352
|
-
}
|
|
353
|
-
},
|
|
354
|
-
get: systemId => {
|
|
355
|
-
return keyedActors.get(systemId);
|
|
356
|
-
},
|
|
357
|
-
_set: (systemId, actorRef) => {
|
|
358
|
-
const existing = keyedActors.get(systemId);
|
|
359
|
-
if (existing && existing !== actorRef) {
|
|
360
|
-
throw new Error(`Actor with system ID '${systemId}' already exists.`);
|
|
361
|
-
}
|
|
362
|
-
keyedActors.set(systemId, actorRef);
|
|
363
|
-
reverseKeyedActors.set(actorRef, systemId);
|
|
364
|
-
}
|
|
365
|
-
};
|
|
366
|
-
return system;
|
|
367
|
-
}
|
|
368
|
-
|
|
369
|
-
function matchesState(parentStateId, childStateId) {
|
|
370
|
-
const parentStateValue = toStateValue(parentStateId);
|
|
371
|
-
const childStateValue = toStateValue(childStateId);
|
|
372
|
-
if (typeof childStateValue === 'string') {
|
|
373
|
-
if (typeof parentStateValue === 'string') {
|
|
374
|
-
return childStateValue === parentStateValue;
|
|
375
|
-
}
|
|
376
|
-
|
|
377
|
-
// Parent more specific than child
|
|
378
|
-
return false;
|
|
379
|
-
}
|
|
380
|
-
if (typeof parentStateValue === 'string') {
|
|
381
|
-
return parentStateValue in childStateValue;
|
|
382
|
-
}
|
|
383
|
-
return Object.keys(parentStateValue).every(key => {
|
|
384
|
-
if (!(key in childStateValue)) {
|
|
385
|
-
return false;
|
|
386
|
-
}
|
|
387
|
-
return matchesState(parentStateValue[key], childStateValue[key]);
|
|
388
|
-
});
|
|
389
|
-
}
|
|
390
|
-
function toStatePath(stateId) {
|
|
391
|
-
try {
|
|
392
|
-
if (isArray(stateId)) {
|
|
393
|
-
return stateId;
|
|
394
|
-
}
|
|
395
|
-
return stateId.toString().split(STATE_DELIMITER);
|
|
396
|
-
} catch (e) {
|
|
397
|
-
throw new Error(`'${stateId}' is not a valid state path.`);
|
|
398
|
-
}
|
|
399
|
-
}
|
|
400
|
-
function isStateLike(state) {
|
|
401
|
-
return typeof state === 'object' && 'value' in state && 'context' in state && 'event' in state;
|
|
402
|
-
}
|
|
403
|
-
function toStateValue(stateValue) {
|
|
404
|
-
if (isStateLike(stateValue)) {
|
|
405
|
-
return stateValue.value;
|
|
406
|
-
}
|
|
407
|
-
if (isArray(stateValue)) {
|
|
408
|
-
return pathToStateValue(stateValue);
|
|
409
|
-
}
|
|
410
|
-
if (typeof stateValue !== 'string') {
|
|
411
|
-
return stateValue;
|
|
412
|
-
}
|
|
413
|
-
const statePath = toStatePath(stateValue);
|
|
414
|
-
return pathToStateValue(statePath);
|
|
415
|
-
}
|
|
416
|
-
function pathToStateValue(statePath) {
|
|
417
|
-
if (statePath.length === 1) {
|
|
418
|
-
return statePath[0];
|
|
419
|
-
}
|
|
420
|
-
const value = {};
|
|
421
|
-
let marker = value;
|
|
422
|
-
for (let i = 0; i < statePath.length - 1; i++) {
|
|
423
|
-
if (i === statePath.length - 2) {
|
|
424
|
-
marker[statePath[i]] = statePath[i + 1];
|
|
425
|
-
} else {
|
|
426
|
-
const previous = marker;
|
|
427
|
-
marker = {};
|
|
428
|
-
previous[statePath[i]] = marker;
|
|
429
|
-
}
|
|
430
|
-
}
|
|
431
|
-
return value;
|
|
432
|
-
}
|
|
433
|
-
function mapValues(collection, iteratee) {
|
|
434
|
-
const result = {};
|
|
435
|
-
const collectionKeys = Object.keys(collection);
|
|
436
|
-
for (let i = 0; i < collectionKeys.length; i++) {
|
|
437
|
-
const key = collectionKeys[i];
|
|
438
|
-
result[key] = iteratee(collection[key], key, collection, i);
|
|
439
|
-
}
|
|
440
|
-
return result;
|
|
441
|
-
}
|
|
442
|
-
function flatten(array) {
|
|
443
|
-
return [].concat(...array);
|
|
444
|
-
}
|
|
445
|
-
function toArrayStrict(value) {
|
|
446
|
-
if (isArray(value)) {
|
|
447
|
-
return value;
|
|
448
|
-
}
|
|
449
|
-
return [value];
|
|
450
|
-
}
|
|
451
|
-
function toArray(value) {
|
|
452
|
-
if (value === undefined) {
|
|
453
|
-
return [];
|
|
454
|
-
}
|
|
455
|
-
return toArrayStrict(value);
|
|
456
|
-
}
|
|
457
|
-
function mapContext(mapper, context, event, self) {
|
|
458
|
-
if (typeof mapper === 'function') {
|
|
459
|
-
return mapper({
|
|
460
|
-
context,
|
|
461
|
-
event,
|
|
462
|
-
self
|
|
463
|
-
});
|
|
464
|
-
}
|
|
465
|
-
if (typeof mapper === 'object' && Object.values(mapper).some(val => typeof val === 'function')) {
|
|
466
|
-
console.warn(`Dynamically mapping values to individual properties is deprecated. Use a single function that returns the mapped object instead.\nFound object containing properties whose values are possibly mapping functions: ${Object.entries(mapper).filter(([key, value]) => typeof value === 'function').map(([key, value]) => `\n - ${key}: ${value.toString().replace(/\n\s*/g, '')}`).join('')}`);
|
|
467
|
-
}
|
|
468
|
-
return mapper;
|
|
469
|
-
}
|
|
470
|
-
function isPromiseLike(value) {
|
|
471
|
-
if (value instanceof Promise) {
|
|
472
|
-
return true;
|
|
473
|
-
}
|
|
474
|
-
// Check if shape matches the Promise/A+ specification for a "thenable".
|
|
475
|
-
if (value !== null && (typeof value === 'function' || typeof value === 'object') && typeof value.then === 'function') {
|
|
476
|
-
return true;
|
|
477
|
-
}
|
|
478
|
-
return false;
|
|
479
|
-
}
|
|
480
|
-
function isArray(value) {
|
|
481
|
-
return Array.isArray(value);
|
|
482
|
-
}
|
|
483
|
-
function isErrorEvent(event) {
|
|
484
|
-
return typeof event.type === 'string' && (event.type === errorExecution || event.type.startsWith(errorPlatform));
|
|
485
|
-
}
|
|
486
|
-
function toTransitionConfigArray(configLike) {
|
|
487
|
-
return toArrayStrict(configLike).map(transitionLike => {
|
|
488
|
-
if (typeof transitionLike === 'undefined' || typeof transitionLike === 'string') {
|
|
489
|
-
return {
|
|
490
|
-
target: transitionLike
|
|
491
|
-
};
|
|
492
|
-
}
|
|
493
|
-
return transitionLike;
|
|
494
|
-
});
|
|
495
|
-
}
|
|
496
|
-
function normalizeTarget(target) {
|
|
497
|
-
if (target === undefined || target === TARGETLESS_KEY) {
|
|
498
|
-
return undefined;
|
|
499
|
-
}
|
|
500
|
-
return toArray(target);
|
|
501
|
-
}
|
|
502
|
-
function toObserver(nextHandler, errorHandler, completionHandler) {
|
|
503
|
-
const isObserver = typeof nextHandler === 'object';
|
|
504
|
-
const self = isObserver ? nextHandler : undefined;
|
|
505
|
-
return {
|
|
506
|
-
next: (isObserver ? nextHandler.next : nextHandler)?.bind(self),
|
|
507
|
-
error: (isObserver ? nextHandler.error : errorHandler)?.bind(self),
|
|
508
|
-
complete: (isObserver ? nextHandler.complete : completionHandler)?.bind(self)
|
|
509
|
-
};
|
|
510
|
-
}
|
|
511
|
-
function createInvokeId(stateNodeId, index) {
|
|
512
|
-
return `${stateNodeId}:invocation[${index}]`;
|
|
513
|
-
}
|
|
514
|
-
function resolveReferencedActor(referenced) {
|
|
515
|
-
return referenced ? 'transition' in referenced ? {
|
|
516
|
-
src: referenced,
|
|
517
|
-
input: undefined
|
|
518
|
-
} : referenced : undefined;
|
|
519
|
-
}
|
|
520
|
-
|
|
521
|
-
let ActorStatus = /*#__PURE__*/function (ActorStatus) {
|
|
522
|
-
ActorStatus[ActorStatus["NotStarted"] = 0] = "NotStarted";
|
|
523
|
-
ActorStatus[ActorStatus["Running"] = 1] = "Running";
|
|
524
|
-
ActorStatus[ActorStatus["Stopped"] = 2] = "Stopped";
|
|
525
|
-
return ActorStatus;
|
|
526
|
-
}({});
|
|
527
|
-
|
|
528
|
-
/**
|
|
529
|
-
* @deprecated Use `ActorStatus` instead.
|
|
530
|
-
*/
|
|
531
|
-
const InterpreterStatus = ActorStatus;
|
|
532
|
-
const defaultOptions = {
|
|
533
|
-
deferEvents: true,
|
|
534
|
-
clock: {
|
|
535
|
-
setTimeout: (fn, ms) => {
|
|
536
|
-
return setTimeout(fn, ms);
|
|
537
|
-
},
|
|
538
|
-
clearTimeout: id => {
|
|
539
|
-
return clearTimeout(id);
|
|
540
|
-
}
|
|
541
|
-
},
|
|
542
|
-
logger: console.log.bind(console),
|
|
543
|
-
devTools: false
|
|
544
|
-
};
|
|
545
|
-
class Actor {
|
|
546
|
-
/**
|
|
547
|
-
* The current internal state of the actor.
|
|
548
|
-
*/
|
|
549
|
-
|
|
550
|
-
/**
|
|
551
|
-
* The clock that is responsible for setting and clearing timeouts, such as delayed events and transitions.
|
|
552
|
-
*/
|
|
553
|
-
|
|
554
|
-
/**
|
|
555
|
-
* The unique identifier for this actor relative to its parent.
|
|
556
|
-
*/
|
|
557
|
-
|
|
558
|
-
/**
|
|
559
|
-
* Whether the service is started.
|
|
560
|
-
*/
|
|
561
|
-
|
|
562
|
-
// Actor Ref
|
|
563
|
-
|
|
564
|
-
// TODO: add typings for system
|
|
565
|
-
|
|
566
|
-
/**
|
|
567
|
-
* The globally unique process ID for this invocation.
|
|
568
|
-
*/
|
|
569
|
-
|
|
570
|
-
/**
|
|
571
|
-
* Creates a new actor instance for the given logic with the provided options, if any.
|
|
572
|
-
*
|
|
573
|
-
* @param logic The logic to create an actor from
|
|
574
|
-
* @param options Actor options
|
|
575
|
-
*/
|
|
576
|
-
constructor(logic, options) {
|
|
577
|
-
this.logic = logic;
|
|
578
|
-
this._state = void 0;
|
|
579
|
-
this.clock = void 0;
|
|
580
|
-
this.options = void 0;
|
|
581
|
-
this.id = void 0;
|
|
582
|
-
this.mailbox = new Mailbox(this._process.bind(this));
|
|
583
|
-
this.delayedEventsMap = {};
|
|
584
|
-
this.observers = new Set();
|
|
585
|
-
this.logger = void 0;
|
|
586
|
-
this.status = ActorStatus.NotStarted;
|
|
587
|
-
this._parent = void 0;
|
|
588
|
-
this.ref = void 0;
|
|
589
|
-
this._actorContext = void 0;
|
|
590
|
-
this._systemId = void 0;
|
|
591
|
-
this.sessionId = void 0;
|
|
592
|
-
this.system = void 0;
|
|
593
|
-
this._doneEvent = void 0;
|
|
594
|
-
this.src = void 0;
|
|
595
|
-
this._deferred = [];
|
|
596
|
-
const resolvedOptions = {
|
|
597
|
-
...defaultOptions,
|
|
598
|
-
...options
|
|
599
|
-
};
|
|
600
|
-
const {
|
|
601
|
-
clock,
|
|
602
|
-
logger,
|
|
603
|
-
parent,
|
|
604
|
-
id,
|
|
605
|
-
systemId
|
|
606
|
-
} = resolvedOptions;
|
|
607
|
-
const self = this;
|
|
608
|
-
this.system = parent?.system ?? createSystem();
|
|
609
|
-
if (systemId) {
|
|
610
|
-
this._systemId = systemId;
|
|
611
|
-
this.system._set(systemId, this);
|
|
612
|
-
}
|
|
613
|
-
this.sessionId = this.system._bookId();
|
|
614
|
-
this.id = id ?? this.sessionId;
|
|
615
|
-
this.logger = logger;
|
|
616
|
-
this.clock = clock;
|
|
617
|
-
this._parent = parent;
|
|
618
|
-
this.options = resolvedOptions;
|
|
619
|
-
this.src = resolvedOptions.src;
|
|
620
|
-
this.ref = this;
|
|
621
|
-
this._actorContext = {
|
|
622
|
-
self,
|
|
623
|
-
id: this.id,
|
|
624
|
-
sessionId: this.sessionId,
|
|
625
|
-
logger: this.logger,
|
|
626
|
-
defer: fn => {
|
|
627
|
-
this._deferred.push(fn);
|
|
628
|
-
},
|
|
629
|
-
system: this.system,
|
|
630
|
-
stopChild: child => {
|
|
631
|
-
if (child._parent !== this) {
|
|
632
|
-
throw new Error(`Cannot stop child actor ${child.id} of ${this.id} because it is not a child`);
|
|
633
|
-
}
|
|
634
|
-
child._stop();
|
|
635
|
-
}
|
|
636
|
-
};
|
|
637
|
-
|
|
638
|
-
// Ensure that the send method is bound to this Actor instance
|
|
639
|
-
// if destructured
|
|
640
|
-
this.send = this.send.bind(this);
|
|
641
|
-
this._initState();
|
|
642
|
-
}
|
|
643
|
-
_initState() {
|
|
644
|
-
this._state = this.options.state ? this.logic.restoreState ? this.logic.restoreState(this.options.state, this._actorContext) : this.options.state : this.logic.getInitialState(this._actorContext, this.options?.input);
|
|
645
|
-
}
|
|
646
|
-
|
|
647
|
-
// array of functions to defer
|
|
648
|
-
|
|
649
|
-
update(state) {
|
|
650
|
-
// Update state
|
|
651
|
-
this._state = state;
|
|
652
|
-
const snapshot = this.getSnapshot();
|
|
653
|
-
|
|
654
|
-
// Execute deferred effects
|
|
655
|
-
let deferredFn;
|
|
656
|
-
while (deferredFn = this._deferred.shift()) {
|
|
657
|
-
deferredFn();
|
|
658
|
-
}
|
|
659
|
-
for (const observer of this.observers) {
|
|
660
|
-
// TODO: should observers be notified in case of the error?
|
|
661
|
-
try {
|
|
662
|
-
observer.next?.(snapshot);
|
|
663
|
-
} catch (err) {
|
|
664
|
-
reportUnhandledError(err);
|
|
665
|
-
}
|
|
666
|
-
}
|
|
667
|
-
const status = this.logic.getStatus?.(state);
|
|
668
|
-
switch (status?.status) {
|
|
669
|
-
case 'done':
|
|
670
|
-
this._stopProcedure();
|
|
671
|
-
this._complete();
|
|
672
|
-
this._doneEvent = doneInvoke(this.id, status.data);
|
|
673
|
-
this._parent?.send(this._doneEvent);
|
|
674
|
-
break;
|
|
675
|
-
case 'error':
|
|
676
|
-
this._stopProcedure();
|
|
677
|
-
this._error(status.data);
|
|
678
|
-
this._parent?.send(error(this.id, status.data));
|
|
679
|
-
break;
|
|
680
|
-
}
|
|
681
|
-
}
|
|
682
|
-
subscribe(nextListenerOrObserver, errorListener, completeListener) {
|
|
683
|
-
const observer = toObserver(nextListenerOrObserver, errorListener, completeListener);
|
|
684
|
-
if (this.status !== ActorStatus.Stopped) {
|
|
685
|
-
this.observers.add(observer);
|
|
686
|
-
} else {
|
|
687
|
-
try {
|
|
688
|
-
observer.complete?.();
|
|
689
|
-
} catch (err) {
|
|
690
|
-
reportUnhandledError(err);
|
|
691
|
-
}
|
|
692
|
-
}
|
|
693
|
-
return {
|
|
694
|
-
unsubscribe: () => {
|
|
695
|
-
this.observers.delete(observer);
|
|
696
|
-
}
|
|
697
|
-
};
|
|
698
|
-
}
|
|
699
|
-
|
|
700
|
-
/**
|
|
701
|
-
* Starts the Actor from the initial state
|
|
702
|
-
*/
|
|
703
|
-
start() {
|
|
704
|
-
if (this.status === ActorStatus.Running) {
|
|
705
|
-
// Do not restart the service if it is already started
|
|
706
|
-
return this;
|
|
707
|
-
}
|
|
708
|
-
this.system._register(this.sessionId, this);
|
|
709
|
-
if (this._systemId) {
|
|
710
|
-
this.system._set(this._systemId, this);
|
|
711
|
-
}
|
|
712
|
-
this.status = ActorStatus.Running;
|
|
713
|
-
const status = this.logic.getStatus?.(this._state);
|
|
714
|
-
switch (status?.status) {
|
|
715
|
-
case 'done':
|
|
716
|
-
// a state machine can be "done" upon intialization (it could reach a final state using initial microsteps)
|
|
717
|
-
// we still need to complete observers, flush deferreds etc
|
|
718
|
-
this.update(this._state);
|
|
719
|
-
// fallthrough
|
|
720
|
-
case 'error':
|
|
721
|
-
// TODO: rethink cleanup of observers, mailbox, etc
|
|
722
|
-
return this;
|
|
723
|
-
}
|
|
724
|
-
if (this.logic.start) {
|
|
725
|
-
try {
|
|
726
|
-
this.logic.start(this._state, this._actorContext);
|
|
727
|
-
} catch (err) {
|
|
728
|
-
this._stopProcedure();
|
|
729
|
-
this._error(err);
|
|
730
|
-
this._parent?.send(error(this.id, err));
|
|
731
|
-
return this;
|
|
732
|
-
}
|
|
733
|
-
}
|
|
734
|
-
|
|
735
|
-
// TODO: this notifies all subscribers but usually this is redundant
|
|
736
|
-
// there is no real change happening here
|
|
737
|
-
// we need to rethink if this needs to be refactored
|
|
738
|
-
this.update(this._state);
|
|
739
|
-
if (this.options.devTools) {
|
|
740
|
-
this.attachDevTools();
|
|
741
|
-
}
|
|
742
|
-
this.mailbox.start();
|
|
743
|
-
return this;
|
|
744
|
-
}
|
|
745
|
-
_process(event) {
|
|
746
|
-
// TODO: reexamine what happens when an action (or a guard or smth) throws
|
|
747
|
-
let nextState;
|
|
748
|
-
let caughtError;
|
|
749
|
-
try {
|
|
750
|
-
nextState = this.logic.transition(this._state, event, this._actorContext);
|
|
751
|
-
} catch (err) {
|
|
752
|
-
// we wrap it in a box so we can rethrow it later even if falsy value gets caught here
|
|
753
|
-
caughtError = {
|
|
754
|
-
err
|
|
755
|
-
};
|
|
756
|
-
}
|
|
757
|
-
if (caughtError) {
|
|
758
|
-
const {
|
|
759
|
-
err
|
|
760
|
-
} = caughtError;
|
|
761
|
-
this._stopProcedure();
|
|
762
|
-
this._error(err);
|
|
763
|
-
this._parent?.send(error(this.id, err));
|
|
764
|
-
return;
|
|
765
|
-
}
|
|
766
|
-
this.update(nextState);
|
|
767
|
-
if (event.type === XSTATE_STOP) {
|
|
768
|
-
this._stopProcedure();
|
|
769
|
-
this._complete();
|
|
770
|
-
}
|
|
771
|
-
}
|
|
772
|
-
_stop() {
|
|
773
|
-
if (this.status === ActorStatus.Stopped) {
|
|
774
|
-
return this;
|
|
775
|
-
}
|
|
776
|
-
this.mailbox.clear();
|
|
777
|
-
if (this.status === ActorStatus.NotStarted) {
|
|
778
|
-
this.status = ActorStatus.Stopped;
|
|
779
|
-
return this;
|
|
780
|
-
}
|
|
781
|
-
this.mailbox.enqueue({
|
|
782
|
-
type: XSTATE_STOP
|
|
783
|
-
});
|
|
784
|
-
return this;
|
|
785
|
-
}
|
|
786
|
-
|
|
787
|
-
/**
|
|
788
|
-
* Stops the Actor and unsubscribe all listeners.
|
|
789
|
-
*/
|
|
790
|
-
stop() {
|
|
791
|
-
if (this._parent) {
|
|
792
|
-
throw new Error('A non-root actor cannot be stopped directly.');
|
|
793
|
-
}
|
|
794
|
-
return this._stop();
|
|
795
|
-
}
|
|
796
|
-
_complete() {
|
|
797
|
-
for (const observer of this.observers) {
|
|
798
|
-
try {
|
|
799
|
-
observer.complete?.();
|
|
800
|
-
} catch (err) {
|
|
801
|
-
reportUnhandledError(err);
|
|
802
|
-
}
|
|
803
|
-
}
|
|
804
|
-
this.observers.clear();
|
|
805
|
-
}
|
|
806
|
-
_error(err) {
|
|
807
|
-
if (!this.observers.size) {
|
|
808
|
-
if (!this._parent) {
|
|
809
|
-
reportUnhandledError(err);
|
|
810
|
-
}
|
|
811
|
-
return;
|
|
812
|
-
}
|
|
813
|
-
let reportError = false;
|
|
814
|
-
for (const observer of this.observers) {
|
|
815
|
-
const errorListener = observer.error;
|
|
816
|
-
reportError ||= !errorListener;
|
|
817
|
-
try {
|
|
818
|
-
errorListener?.(err);
|
|
819
|
-
} catch (err2) {
|
|
820
|
-
reportUnhandledError(err2);
|
|
821
|
-
}
|
|
822
|
-
}
|
|
823
|
-
this.observers.clear();
|
|
824
|
-
if (reportError) {
|
|
825
|
-
reportUnhandledError(err);
|
|
826
|
-
}
|
|
827
|
-
}
|
|
828
|
-
_stopProcedure() {
|
|
829
|
-
if (this.status !== ActorStatus.Running) {
|
|
830
|
-
// Actor already stopped; do nothing
|
|
831
|
-
return this;
|
|
832
|
-
}
|
|
833
|
-
|
|
834
|
-
// Cancel all delayed events
|
|
835
|
-
for (const key of Object.keys(this.delayedEventsMap)) {
|
|
836
|
-
this.clock.clearTimeout(this.delayedEventsMap[key]);
|
|
837
|
-
}
|
|
838
|
-
|
|
839
|
-
// TODO: mailbox.reset
|
|
840
|
-
this.mailbox.clear();
|
|
841
|
-
// TODO: after `stop` we must prepare ourselves for receiving events again
|
|
842
|
-
// events sent *after* stop signal must be queued
|
|
843
|
-
// it seems like this should be the common behavior for all of our consumers
|
|
844
|
-
// so perhaps this should be unified somehow for all of them
|
|
845
|
-
this.mailbox = new Mailbox(this._process.bind(this));
|
|
846
|
-
this.status = ActorStatus.Stopped;
|
|
847
|
-
this.system._unregister(this);
|
|
848
|
-
return this;
|
|
849
|
-
}
|
|
850
|
-
|
|
851
|
-
/**
|
|
852
|
-
* Sends an event to the running Actor to trigger a transition.
|
|
853
|
-
*
|
|
854
|
-
* @param event The event to send
|
|
855
|
-
*/
|
|
856
|
-
send(event) {
|
|
857
|
-
if (typeof event === 'string') {
|
|
858
|
-
throw new Error(`Only event objects may be sent to actors; use .send({ type: "${event}" }) instead`);
|
|
859
|
-
}
|
|
860
|
-
if (this.status === ActorStatus.Stopped) {
|
|
861
|
-
// do nothing
|
|
862
|
-
{
|
|
863
|
-
const eventString = JSON.stringify(event);
|
|
864
|
-
console.warn(`Event "${event.type.toString()}" was sent to stopped actor "${this.id} (${this.sessionId})". This actor has already reached its final state, and will not transition.\nEvent: ${eventString}`);
|
|
865
|
-
}
|
|
866
|
-
return;
|
|
867
|
-
}
|
|
868
|
-
if (this.status !== ActorStatus.Running && !this.options.deferEvents) {
|
|
869
|
-
throw new Error(`Event "${event.type}" was sent to uninitialized actor "${this.id
|
|
870
|
-
// tslint:disable-next-line:max-line-length
|
|
871
|
-
}". Make sure .start() is called for this actor, or set { deferEvents: true } in the actor options.\nEvent: ${JSON.stringify(event)}`);
|
|
872
|
-
}
|
|
873
|
-
this.mailbox.enqueue(event);
|
|
874
|
-
}
|
|
875
|
-
|
|
876
|
-
// TODO: make private (and figure out a way to do this within the machine)
|
|
877
|
-
delaySend({
|
|
878
|
-
event,
|
|
879
|
-
id,
|
|
880
|
-
delay,
|
|
881
|
-
to
|
|
882
|
-
}) {
|
|
883
|
-
const timerId = this.clock.setTimeout(() => {
|
|
884
|
-
if (to) {
|
|
885
|
-
to.send(event);
|
|
886
|
-
} else {
|
|
887
|
-
this.send(event);
|
|
888
|
-
}
|
|
889
|
-
}, delay);
|
|
890
|
-
|
|
891
|
-
// TODO: consider the rehydration story here
|
|
892
|
-
if (id) {
|
|
893
|
-
this.delayedEventsMap[id] = timerId;
|
|
894
|
-
}
|
|
895
|
-
}
|
|
896
|
-
|
|
897
|
-
// TODO: make private (and figure out a way to do this within the machine)
|
|
898
|
-
cancel(sendId) {
|
|
899
|
-
this.clock.clearTimeout(this.delayedEventsMap[sendId]);
|
|
900
|
-
delete this.delayedEventsMap[sendId];
|
|
901
|
-
}
|
|
902
|
-
attachDevTools() {
|
|
903
|
-
const {
|
|
904
|
-
devTools
|
|
905
|
-
} = this.options;
|
|
906
|
-
if (devTools) {
|
|
907
|
-
const resolvedDevToolsAdapter = typeof devTools === 'function' ? devTools : dev_dist_xstateDev.devToolsAdapter;
|
|
908
|
-
resolvedDevToolsAdapter(this);
|
|
909
|
-
}
|
|
910
|
-
}
|
|
911
|
-
toJSON() {
|
|
912
|
-
return {
|
|
913
|
-
id: this.id
|
|
914
|
-
};
|
|
915
|
-
}
|
|
916
|
-
getPersistedState() {
|
|
917
|
-
return this.logic.getPersistedState?.(this._state);
|
|
918
|
-
}
|
|
919
|
-
[symbolObservable]() {
|
|
920
|
-
return this;
|
|
921
|
-
}
|
|
922
|
-
getSnapshot() {
|
|
923
|
-
return this.logic.getSnapshot ? this.logic.getSnapshot(this._state) : this._state;
|
|
924
|
-
}
|
|
925
|
-
}
|
|
926
|
-
|
|
927
|
-
/**
|
|
928
|
-
* Creates a new `ActorRef` instance for the given machine with the provided options, if any.
|
|
929
|
-
*
|
|
930
|
-
* @param machine The machine to create an actor from
|
|
931
|
-
* @param options `ActorRef` options
|
|
932
|
-
*/
|
|
933
|
-
|
|
934
|
-
function createActor(logic, options) {
|
|
935
|
-
const interpreter = new Actor(logic, options);
|
|
936
|
-
return interpreter;
|
|
937
|
-
}
|
|
938
|
-
|
|
939
|
-
/**
|
|
940
|
-
* Creates a new Interpreter instance for the given machine with the provided options, if any.
|
|
941
|
-
*
|
|
942
|
-
* @deprecated Use `createActor` instead
|
|
943
|
-
*/
|
|
944
|
-
const interpret = createActor;
|
|
945
|
-
|
|
946
|
-
/**
|
|
947
|
-
* @deprecated Use `Actor` instead.
|
|
948
|
-
*/
|
|
949
|
-
|
|
950
|
-
function resolve$6(actorContext, state, actionArgs, {
|
|
48
|
+
function resolve$2(actorContext, state, actionArgs, {
|
|
951
49
|
id,
|
|
952
50
|
systemId,
|
|
953
51
|
src,
|
|
954
52
|
input
|
|
955
53
|
}) {
|
|
956
|
-
const referenced = resolveReferencedActor(state.machine.implementations.actors[src]);
|
|
54
|
+
const referenced = interpreter.resolveReferencedActor(state.machine.implementations.actors[src]);
|
|
957
55
|
let actorRef;
|
|
958
56
|
if (referenced) {
|
|
959
57
|
// TODO: inline `input: undefined` should win over the referenced one
|
|
960
58
|
const configuredInput = input || referenced.input;
|
|
961
|
-
actorRef = createActor(referenced.src, {
|
|
59
|
+
actorRef = interpreter.createActor(referenced.src, {
|
|
962
60
|
id,
|
|
963
61
|
src,
|
|
964
62
|
parent: actorContext?.self,
|
|
@@ -983,7 +81,7 @@ function resolve$6(actorContext, state, actionArgs, {
|
|
|
983
81
|
actorRef
|
|
984
82
|
}];
|
|
985
83
|
}
|
|
986
|
-
function execute$
|
|
84
|
+
function execute$2(actorContext, {
|
|
987
85
|
id,
|
|
988
86
|
actorRef
|
|
989
87
|
}) {
|
|
@@ -991,13 +89,13 @@ function execute$3(actorContext, {
|
|
|
991
89
|
return;
|
|
992
90
|
}
|
|
993
91
|
actorContext.defer(() => {
|
|
994
|
-
if (actorRef.status === ActorStatus.Stopped) {
|
|
92
|
+
if (actorRef.status === interpreter.ActorStatus.Stopped) {
|
|
995
93
|
return;
|
|
996
94
|
}
|
|
997
95
|
try {
|
|
998
96
|
actorRef.start?.();
|
|
999
97
|
} catch (err) {
|
|
1000
|
-
actorContext.self.send(
|
|
98
|
+
actorContext.self.send(interpreter.createErrorActorEvent(id, err));
|
|
1001
99
|
return;
|
|
1002
100
|
}
|
|
1003
101
|
});
|
|
@@ -1021,11 +119,58 @@ function invoke({
|
|
|
1021
119
|
invoke.systemId = systemId;
|
|
1022
120
|
invoke.src = src;
|
|
1023
121
|
invoke.input = input;
|
|
1024
|
-
invoke.resolve = resolve$
|
|
1025
|
-
invoke.execute = execute$
|
|
122
|
+
invoke.resolve = resolve$2;
|
|
123
|
+
invoke.execute = execute$2;
|
|
1026
124
|
return invoke;
|
|
1027
125
|
}
|
|
1028
126
|
|
|
127
|
+
function resolve$1(_, state, args, {
|
|
128
|
+
actorRef
|
|
129
|
+
}) {
|
|
130
|
+
const actorRefOrString = typeof actorRef === 'function' ? actorRef(args) : actorRef;
|
|
131
|
+
const resolvedActorRef = typeof actorRefOrString === 'string' ? state.children[actorRefOrString] : actorRefOrString;
|
|
132
|
+
let children = state.children;
|
|
133
|
+
if (resolvedActorRef) {
|
|
134
|
+
children = {
|
|
135
|
+
...children
|
|
136
|
+
};
|
|
137
|
+
delete children[resolvedActorRef.id];
|
|
138
|
+
}
|
|
139
|
+
return [cloneState(state, {
|
|
140
|
+
children
|
|
141
|
+
}), resolvedActorRef];
|
|
142
|
+
}
|
|
143
|
+
function execute$1(actorContext, actorRef) {
|
|
144
|
+
if (!actorRef) {
|
|
145
|
+
return;
|
|
146
|
+
}
|
|
147
|
+
if (actorRef.status !== interpreter.ActorStatus.Running) {
|
|
148
|
+
actorContext.stopChild(actorRef);
|
|
149
|
+
return;
|
|
150
|
+
}
|
|
151
|
+
// TODO: recheck why this one has to be deferred
|
|
152
|
+
actorContext.defer(() => {
|
|
153
|
+
actorContext.stopChild(actorRef);
|
|
154
|
+
});
|
|
155
|
+
}
|
|
156
|
+
/**
|
|
157
|
+
* Stops an actor.
|
|
158
|
+
*
|
|
159
|
+
* @param actorRef The actor to stop.
|
|
160
|
+
*/
|
|
161
|
+
function stop(actorRef) {
|
|
162
|
+
function stop(_) {
|
|
163
|
+
{
|
|
164
|
+
throw new Error(`This isn't supposed to be called`);
|
|
165
|
+
}
|
|
166
|
+
}
|
|
167
|
+
stop.type = 'xstate.stop';
|
|
168
|
+
stop.actorRef = actorRef;
|
|
169
|
+
stop.resolve = resolve$1;
|
|
170
|
+
stop.execute = execute$1;
|
|
171
|
+
return stop;
|
|
172
|
+
}
|
|
173
|
+
|
|
1029
174
|
function checkStateIn(state, _, {
|
|
1030
175
|
stateValue
|
|
1031
176
|
}) {
|
|
@@ -1139,7 +284,7 @@ function evaluateGuard(guard, context, event, state) {
|
|
|
1139
284
|
function getOutput(configuration, context, event, self) {
|
|
1140
285
|
const machine = configuration[0].machine;
|
|
1141
286
|
const finalChildStateNode = configuration.find(stateNode => stateNode.type === 'final' && stateNode.parent === machine.root);
|
|
1142
|
-
return finalChildStateNode && finalChildStateNode.output ? mapContext(finalChildStateNode.output, context, event, self) : undefined;
|
|
287
|
+
return finalChildStateNode && finalChildStateNode.output ? interpreter.mapContext(finalChildStateNode.output, context, event, self) : undefined;
|
|
1143
288
|
}
|
|
1144
289
|
const isAtomicStateNode = stateNode => stateNode.type === 'atomic' || stateNode.type === 'final';
|
|
1145
290
|
function getChildren(stateNode) {
|
|
@@ -1242,12 +387,12 @@ function isInFinalState(configuration, stateNode = configuration[0].machine.root
|
|
|
1242
387
|
}
|
|
1243
388
|
return false;
|
|
1244
389
|
}
|
|
1245
|
-
const isStateId = str => str[0] === STATE_IDENTIFIER;
|
|
390
|
+
const isStateId = str => str[0] === interpreter.STATE_IDENTIFIER;
|
|
1246
391
|
function getCandidates(stateNode, receivedEventType) {
|
|
1247
392
|
const candidates = stateNode.transitions.get(receivedEventType) || [...stateNode.transitions.keys()].filter(descriptor => {
|
|
1248
393
|
// check if transition is a wildcard transition,
|
|
1249
394
|
// which matches any non-transient events
|
|
1250
|
-
if (descriptor === WILDCARD) {
|
|
395
|
+
if (descriptor === interpreter.WILDCARD) {
|
|
1251
396
|
return true;
|
|
1252
397
|
}
|
|
1253
398
|
if (!descriptor.endsWith('.*')) {
|
|
@@ -1287,17 +432,16 @@ function getDelayedTransitions(stateNode) {
|
|
|
1287
432
|
}
|
|
1288
433
|
const mutateEntryExit = (delay, i) => {
|
|
1289
434
|
const delayRef = typeof delay === 'function' ? `${stateNode.id}:delay[${i}]` : delay;
|
|
1290
|
-
const
|
|
1291
|
-
|
|
1292
|
-
|
|
1293
|
-
}, {
|
|
435
|
+
const afterEvent = interpreter.createAfterEvent(delayRef, stateNode.id);
|
|
436
|
+
const eventType = afterEvent.type;
|
|
437
|
+
stateNode.entry.push(raise(afterEvent, {
|
|
1294
438
|
id: eventType,
|
|
1295
439
|
delay
|
|
1296
440
|
}));
|
|
1297
441
|
stateNode.exit.push(cancel(eventType));
|
|
1298
442
|
return eventType;
|
|
1299
443
|
};
|
|
1300
|
-
const delayedTransitions = isArray(afterConfig) ? afterConfig.map((transition, i) => {
|
|
444
|
+
const delayedTransitions = interpreter.isArray(afterConfig) ? afterConfig.map((transition, i) => {
|
|
1301
445
|
const eventType = mutateEntryExit(transition.delay, i);
|
|
1302
446
|
return {
|
|
1303
447
|
...transition,
|
|
@@ -1310,7 +454,7 @@ function getDelayedTransitions(stateNode) {
|
|
|
1310
454
|
} : configTransition;
|
|
1311
455
|
const resolvedDelay = !isNaN(+delay) ? +delay : delay;
|
|
1312
456
|
const eventType = mutateEntryExit(resolvedDelay, i);
|
|
1313
|
-
return toArray(resolvedTransition).map(transition => ({
|
|
457
|
+
return interpreter.toArray(resolvedTransition).map(transition => ({
|
|
1314
458
|
...transition,
|
|
1315
459
|
event: eventType,
|
|
1316
460
|
delay: resolvedDelay
|
|
@@ -1327,7 +471,7 @@ function getDelayedTransitions(stateNode) {
|
|
|
1327
471
|
});
|
|
1328
472
|
}
|
|
1329
473
|
function formatTransition(stateNode, descriptor, transitionConfig) {
|
|
1330
|
-
const normalizedTarget = normalizeTarget(transitionConfig.target);
|
|
474
|
+
const normalizedTarget = interpreter.normalizeTarget(transitionConfig.target);
|
|
1331
475
|
const reenter = transitionConfig.reenter ?? false;
|
|
1332
476
|
const target = resolveTarget(stateNode, normalizedTarget);
|
|
1333
477
|
|
|
@@ -1337,7 +481,7 @@ function formatTransition(stateNode, descriptor, transitionConfig) {
|
|
|
1337
481
|
}
|
|
1338
482
|
const transition = {
|
|
1339
483
|
...transitionConfig,
|
|
1340
|
-
actions: toArray(transitionConfig.actions),
|
|
484
|
+
actions: interpreter.toArray(transitionConfig.actions),
|
|
1341
485
|
guard: transitionConfig.guard,
|
|
1342
486
|
target,
|
|
1343
487
|
source: stateNode,
|
|
@@ -1355,29 +499,29 @@ function formatTransitions(stateNode) {
|
|
|
1355
499
|
const transitions = new Map();
|
|
1356
500
|
if (stateNode.config.on) {
|
|
1357
501
|
for (const descriptor of Object.keys(stateNode.config.on)) {
|
|
1358
|
-
if (descriptor === NULL_EVENT) {
|
|
502
|
+
if (descriptor === interpreter.NULL_EVENT) {
|
|
1359
503
|
throw new Error('Null events ("") cannot be specified as a transition key. Use `always: { ... }` instead.');
|
|
1360
504
|
}
|
|
1361
505
|
const transitionsConfig = stateNode.config.on[descriptor];
|
|
1362
|
-
transitions.set(descriptor, toTransitionConfigArray(transitionsConfig).map(t => formatTransition(stateNode, descriptor, t)));
|
|
506
|
+
transitions.set(descriptor, interpreter.toTransitionConfigArray(transitionsConfig).map(t => formatTransition(stateNode, descriptor, t)));
|
|
1363
507
|
}
|
|
1364
508
|
}
|
|
1365
509
|
if (stateNode.config.onDone) {
|
|
1366
|
-
const descriptor =
|
|
1367
|
-
transitions.set(descriptor, toTransitionConfigArray(stateNode.config.onDone).map(t => formatTransition(stateNode, descriptor, t)));
|
|
510
|
+
const descriptor = `xstate.done.state.${stateNode.id}`;
|
|
511
|
+
transitions.set(descriptor, interpreter.toTransitionConfigArray(stateNode.config.onDone).map(t => formatTransition(stateNode, descriptor, t)));
|
|
1368
512
|
}
|
|
1369
513
|
for (const invokeDef of stateNode.invoke) {
|
|
1370
514
|
if (invokeDef.onDone) {
|
|
1371
|
-
const descriptor = `done.
|
|
1372
|
-
transitions.set(descriptor, toTransitionConfigArray(invokeDef.onDone).map(t => formatTransition(stateNode, descriptor, t)));
|
|
515
|
+
const descriptor = `xstate.done.actor.${invokeDef.id}`;
|
|
516
|
+
transitions.set(descriptor, interpreter.toTransitionConfigArray(invokeDef.onDone).map(t => formatTransition(stateNode, descriptor, t)));
|
|
1373
517
|
}
|
|
1374
518
|
if (invokeDef.onError) {
|
|
1375
|
-
const descriptor = `error.
|
|
1376
|
-
transitions.set(descriptor, toTransitionConfigArray(invokeDef.onError).map(t => formatTransition(stateNode, descriptor, t)));
|
|
519
|
+
const descriptor = `xstate.error.actor.${invokeDef.id}`;
|
|
520
|
+
transitions.set(descriptor, interpreter.toTransitionConfigArray(invokeDef.onError).map(t => formatTransition(stateNode, descriptor, t)));
|
|
1377
521
|
}
|
|
1378
522
|
if (invokeDef.onSnapshot) {
|
|
1379
523
|
const descriptor = `xstate.snapshot.${invokeDef.id}`;
|
|
1380
|
-
transitions.set(descriptor, toTransitionConfigArray(invokeDef.onSnapshot).map(t => formatTransition(stateNode, descriptor, t)));
|
|
524
|
+
transitions.set(descriptor, interpreter.toTransitionConfigArray(invokeDef.onSnapshot).map(t => formatTransition(stateNode, descriptor, t)));
|
|
1381
525
|
}
|
|
1382
526
|
}
|
|
1383
527
|
for (const delayedTransition of stateNode.after) {
|
|
@@ -1391,8 +535,8 @@ function formatTransitions(stateNode) {
|
|
|
1391
535
|
return transitions;
|
|
1392
536
|
}
|
|
1393
537
|
function formatInitialTransition(stateNode, _target) {
|
|
1394
|
-
if (typeof _target === 'string' || isArray(_target)) {
|
|
1395
|
-
const targets = toArray(_target).map(t => {
|
|
538
|
+
if (typeof _target === 'string' || interpreter.isArray(_target)) {
|
|
539
|
+
const targets = interpreter.toArray(_target).map(t => {
|
|
1396
540
|
// Resolve state string keys (which represent children)
|
|
1397
541
|
// to their state node
|
|
1398
542
|
const descStateNode = typeof t === 'string' ? isStateId(t) ? stateNode.machine.getStateNodeById(t) : stateNode.states[t] : t;
|
|
@@ -1420,9 +564,9 @@ function formatInitialTransition(stateNode, _target) {
|
|
|
1420
564
|
return transition;
|
|
1421
565
|
}
|
|
1422
566
|
return formatTransition(stateNode, '__INITIAL__', {
|
|
1423
|
-
target: toArray(_target.target).map(t => {
|
|
567
|
+
target: interpreter.toArray(_target.target).map(t => {
|
|
1424
568
|
if (typeof t === 'string') {
|
|
1425
|
-
return isStateId(t) ? t : `${STATE_DELIMITER}${t}`;
|
|
569
|
+
return isStateId(t) ? t : `${interpreter.STATE_DELIMITER}${t}`;
|
|
1426
570
|
}
|
|
1427
571
|
return t;
|
|
1428
572
|
}),
|
|
@@ -1441,7 +585,7 @@ function resolveTarget(stateNode, targets) {
|
|
|
1441
585
|
if (isStateId(target)) {
|
|
1442
586
|
return stateNode.machine.getStateNodeById(target);
|
|
1443
587
|
}
|
|
1444
|
-
const isInternalTarget = target[0] === STATE_DELIMITER;
|
|
588
|
+
const isInternalTarget = target[0] === interpreter.STATE_DELIMITER;
|
|
1445
589
|
// If internal target is defined on machine,
|
|
1446
590
|
// do not include machine key on target
|
|
1447
591
|
if (isInternalTarget && !stateNode.parent) {
|
|
@@ -1461,7 +605,7 @@ function resolveTarget(stateNode, targets) {
|
|
|
1461
605
|
});
|
|
1462
606
|
}
|
|
1463
607
|
function resolveHistoryTarget(stateNode) {
|
|
1464
|
-
const normalizedTarget = normalizeTarget(stateNode.config.target);
|
|
608
|
+
const normalizedTarget = interpreter.normalizeTarget(stateNode.config.target);
|
|
1465
609
|
if (!normalizedTarget) {
|
|
1466
610
|
return stateNode.parent.initial.target;
|
|
1467
611
|
}
|
|
@@ -1524,7 +668,7 @@ function getStateNodeByPath(stateNode, statePath) {
|
|
|
1524
668
|
// throw e;
|
|
1525
669
|
}
|
|
1526
670
|
}
|
|
1527
|
-
const arrayStatePath = toStatePath(statePath).slice();
|
|
671
|
+
const arrayStatePath = interpreter.toStatePath(statePath).slice();
|
|
1528
672
|
let currentStateNode = stateNode;
|
|
1529
673
|
while (arrayStatePath.length) {
|
|
1530
674
|
const key = arrayStatePath.shift();
|
|
@@ -1542,7 +686,7 @@ function getStateNodeByPath(stateNode, statePath) {
|
|
|
1542
686
|
* @param state The state value or State instance
|
|
1543
687
|
*/
|
|
1544
688
|
function getStateNodes(stateNode, state) {
|
|
1545
|
-
const stateValue = state instanceof State ? state.value : toStateValue(state);
|
|
689
|
+
const stateValue = state instanceof State ? state.value : interpreter.toStateValue(state);
|
|
1546
690
|
if (typeof stateValue === 'string') {
|
|
1547
691
|
return [stateNode, stateNode.states[stateValue]];
|
|
1548
692
|
}
|
|
@@ -1817,12 +961,12 @@ function enterStates(event, filteredTransitions, mutConfiguration, actions, inte
|
|
|
1817
961
|
if (!parent.parent) {
|
|
1818
962
|
continue;
|
|
1819
963
|
}
|
|
1820
|
-
internalQueue.push(
|
|
964
|
+
internalQueue.push(interpreter.createDoneStateEvent(parent.id, stateNodeToEnter.output ? interpreter.mapContext(stateNodeToEnter.output, currentState.context, event, actorContext.self) : undefined));
|
|
1821
965
|
if (parent.parent) {
|
|
1822
966
|
const grandparent = parent.parent;
|
|
1823
967
|
if (grandparent.type === 'parallel') {
|
|
1824
968
|
if (getChildren(grandparent).every(parentNode => isInFinalState([...mutConfiguration], parentNode))) {
|
|
1825
|
-
internalQueue.push(
|
|
969
|
+
internalQueue.push(interpreter.createDoneStateEvent(grandparent.id));
|
|
1826
970
|
}
|
|
1827
971
|
}
|
|
1828
972
|
}
|
|
@@ -1961,7 +1105,7 @@ function resolveActionsAndContext(actions, event, currentState, actorCtx) {
|
|
|
1961
1105
|
action
|
|
1962
1106
|
};
|
|
1963
1107
|
if (!('resolve' in resolved)) {
|
|
1964
|
-
if (actorCtx?.self.status === ActorStatus.Running) {
|
|
1108
|
+
if (actorCtx?.self.status === interpreter.ActorStatus.Running) {
|
|
1965
1109
|
resolved(actionArgs);
|
|
1966
1110
|
} else {
|
|
1967
1111
|
actorCtx?.defer(() => resolved(actionArgs));
|
|
@@ -1974,7 +1118,7 @@ function resolveActionsAndContext(actions, event, currentState, actorCtx) {
|
|
|
1974
1118
|
|
|
1975
1119
|
intermediateState = nextState;
|
|
1976
1120
|
if ('execute' in resolved) {
|
|
1977
|
-
if (actorCtx?.self.status === ActorStatus.Running) {
|
|
1121
|
+
if (actorCtx?.self.status === interpreter.ActorStatus.Running) {
|
|
1978
1122
|
builtinAction.execute(actorCtx, params);
|
|
1979
1123
|
} else {
|
|
1980
1124
|
actorCtx?.defer(builtinAction.execute.bind(null, actorCtx, params));
|
|
@@ -1987,14 +1131,14 @@ function resolveActionsAndContext(actions, event, currentState, actorCtx) {
|
|
|
1987
1131
|
return intermediateState;
|
|
1988
1132
|
}
|
|
1989
1133
|
function macrostep(state, event, actorCtx) {
|
|
1990
|
-
if (event.type === WILDCARD) {
|
|
1991
|
-
throw new Error(`An event cannot have the wildcard type ('${WILDCARD}')`);
|
|
1134
|
+
if (event.type === interpreter.WILDCARD) {
|
|
1135
|
+
throw new Error(`An event cannot have the wildcard type ('${interpreter.WILDCARD}')`);
|
|
1992
1136
|
}
|
|
1993
1137
|
let nextState = state;
|
|
1994
1138
|
const states = [];
|
|
1995
1139
|
|
|
1996
1140
|
// Handle stop event
|
|
1997
|
-
if (event.type === XSTATE_STOP) {
|
|
1141
|
+
if (event.type === interpreter.XSTATE_STOP) {
|
|
1998
1142
|
nextState = stopStep(event, nextState, actorCtx);
|
|
1999
1143
|
states.push(nextState);
|
|
2000
1144
|
return {
|
|
@@ -2006,7 +1150,7 @@ function macrostep(state, event, actorCtx) {
|
|
|
2006
1150
|
|
|
2007
1151
|
// Assume the state is at rest (no raised events)
|
|
2008
1152
|
// Determine the next state based on the next microstep
|
|
2009
|
-
if (nextEvent.type !== XSTATE_INIT) {
|
|
1153
|
+
if (nextEvent.type !== interpreter.XSTATE_INIT) {
|
|
2010
1154
|
const transitions = selectTransitions(nextEvent, nextState);
|
|
2011
1155
|
nextState = microstep(transitions, state, actorCtx, nextEvent, false);
|
|
2012
1156
|
states.push(nextState);
|
|
@@ -2161,7 +1305,7 @@ class State {
|
|
|
2161
1305
|
this.configuration = config.configuration ?? Array.from(getConfiguration(getStateNodes(machine.root, config.value)));
|
|
2162
1306
|
this.children = config.children;
|
|
2163
1307
|
this.value = getStateValue(machine.root, this.configuration);
|
|
2164
|
-
this.tags = new Set(flatten(this.configuration.map(sn => sn.tags)));
|
|
1308
|
+
this.tags = new Set(interpreter.flatten(this.configuration.map(sn => sn.tags)));
|
|
2165
1309
|
this.done = config.done ?? false;
|
|
2166
1310
|
this.output = config.output;
|
|
2167
1311
|
this.error = config.error;
|
|
@@ -2177,7 +1321,7 @@ class State {
|
|
|
2177
1321
|
return [stateValue];
|
|
2178
1322
|
}
|
|
2179
1323
|
const valueKeys = Object.keys(stateValue);
|
|
2180
|
-
return valueKeys.concat(...valueKeys.map(key => this.toStrings(stateValue[key]).map(s => key + STATE_DELIMITER + s)));
|
|
1324
|
+
return valueKeys.concat(...valueKeys.map(key => this.toStrings(stateValue[key]).map(s => key + interpreter.STATE_DELIMITER + s)));
|
|
2181
1325
|
}
|
|
2182
1326
|
toJSON() {
|
|
2183
1327
|
const {
|
|
@@ -2198,7 +1342,7 @@ class State {
|
|
|
2198
1342
|
* @param parentStateValue
|
|
2199
1343
|
*/
|
|
2200
1344
|
matches(parentStateValue) {
|
|
2201
|
-
return matchesState(parentStateValue, this.value);
|
|
1345
|
+
return interpreter.matchesState(parentStateValue, this.value);
|
|
2202
1346
|
}
|
|
2203
1347
|
|
|
2204
1348
|
/**
|
|
@@ -2232,7 +1376,7 @@ class State {
|
|
|
2232
1376
|
*/
|
|
2233
1377
|
get nextEvents() {
|
|
2234
1378
|
return memo(this, 'nextEvents', () => {
|
|
2235
|
-
return [...new Set(flatten([...this.configuration.map(sn => sn.ownEvents)]))];
|
|
1379
|
+
return [...new Set(interpreter.flatten([...this.configuration.map(sn => sn.ownEvents)]))];
|
|
2236
1380
|
});
|
|
2237
1381
|
}
|
|
2238
1382
|
get meta() {
|
|
@@ -2271,209 +1415,7 @@ function getPersistedState(state) {
|
|
|
2271
1415
|
};
|
|
2272
1416
|
}
|
|
2273
1417
|
|
|
2274
|
-
function resolve
|
|
2275
|
-
actorRef
|
|
2276
|
-
}) {
|
|
2277
|
-
const actorRefOrString = typeof actorRef === 'function' ? actorRef(args) : actorRef;
|
|
2278
|
-
const resolvedActorRef = typeof actorRefOrString === 'string' ? state.children[actorRefOrString] : actorRefOrString;
|
|
2279
|
-
let children = state.children;
|
|
2280
|
-
if (resolvedActorRef) {
|
|
2281
|
-
children = {
|
|
2282
|
-
...children
|
|
2283
|
-
};
|
|
2284
|
-
delete children[resolvedActorRef.id];
|
|
2285
|
-
}
|
|
2286
|
-
return [cloneState(state, {
|
|
2287
|
-
children
|
|
2288
|
-
}), resolvedActorRef];
|
|
2289
|
-
}
|
|
2290
|
-
function execute$2(actorContext, actorRef) {
|
|
2291
|
-
if (!actorRef) {
|
|
2292
|
-
return;
|
|
2293
|
-
}
|
|
2294
|
-
if (actorRef.status !== ActorStatus.Running) {
|
|
2295
|
-
actorContext.stopChild(actorRef);
|
|
2296
|
-
return;
|
|
2297
|
-
}
|
|
2298
|
-
// TODO: recheck why this one has to be deferred
|
|
2299
|
-
actorContext.defer(() => {
|
|
2300
|
-
actorContext.stopChild(actorRef);
|
|
2301
|
-
});
|
|
2302
|
-
}
|
|
2303
|
-
/**
|
|
2304
|
-
* Stops an actor.
|
|
2305
|
-
*
|
|
2306
|
-
* @param actorRef The actor to stop.
|
|
2307
|
-
*/
|
|
2308
|
-
function stop(actorRef) {
|
|
2309
|
-
function stop(_) {
|
|
2310
|
-
{
|
|
2311
|
-
throw new Error(`This isn't supposed to be called`);
|
|
2312
|
-
}
|
|
2313
|
-
}
|
|
2314
|
-
stop.type = 'xstate.stop';
|
|
2315
|
-
stop.actorRef = actorRef;
|
|
2316
|
-
stop.resolve = resolve$5;
|
|
2317
|
-
stop.execute = execute$2;
|
|
2318
|
-
return stop;
|
|
2319
|
-
}
|
|
2320
|
-
|
|
2321
|
-
function resolve$4(_, state, actionArgs, {
|
|
2322
|
-
value,
|
|
2323
|
-
label
|
|
2324
|
-
}) {
|
|
2325
|
-
return [state, {
|
|
2326
|
-
value: typeof value === 'function' ? value(actionArgs) : value,
|
|
2327
|
-
label
|
|
2328
|
-
}];
|
|
2329
|
-
}
|
|
2330
|
-
function execute$1({
|
|
2331
|
-
logger
|
|
2332
|
-
}, {
|
|
2333
|
-
value,
|
|
2334
|
-
label
|
|
2335
|
-
}) {
|
|
2336
|
-
if (label) {
|
|
2337
|
-
logger(label, value);
|
|
2338
|
-
} else {
|
|
2339
|
-
logger(value);
|
|
2340
|
-
}
|
|
2341
|
-
}
|
|
2342
|
-
/**
|
|
2343
|
-
*
|
|
2344
|
-
* @param expr The expression function to evaluate which will be logged.
|
|
2345
|
-
* Takes in 2 arguments:
|
|
2346
|
-
* - `ctx` - the current state context
|
|
2347
|
-
* - `event` - the event that caused this action to be executed.
|
|
2348
|
-
* @param label The label to give to the logged expression.
|
|
2349
|
-
*/
|
|
2350
|
-
function log(value = ({
|
|
2351
|
-
context,
|
|
2352
|
-
event
|
|
2353
|
-
}) => ({
|
|
2354
|
-
context,
|
|
2355
|
-
event
|
|
2356
|
-
}), label) {
|
|
2357
|
-
function log(_) {
|
|
2358
|
-
{
|
|
2359
|
-
throw new Error(`This isn't supposed to be called`);
|
|
2360
|
-
}
|
|
2361
|
-
}
|
|
2362
|
-
log.type = 'xstate.log';
|
|
2363
|
-
log.value = value;
|
|
2364
|
-
log.label = label;
|
|
2365
|
-
log.resolve = resolve$4;
|
|
2366
|
-
log.execute = execute$1;
|
|
2367
|
-
return log;
|
|
2368
|
-
}
|
|
2369
|
-
|
|
2370
|
-
function createSpawner(actorContext, {
|
|
2371
|
-
machine,
|
|
2372
|
-
context
|
|
2373
|
-
}, event, spawnedChildren) {
|
|
2374
|
-
const spawn = (src, options = {}) => {
|
|
2375
|
-
const {
|
|
2376
|
-
systemId
|
|
2377
|
-
} = options;
|
|
2378
|
-
if (typeof src === 'string') {
|
|
2379
|
-
const referenced = resolveReferencedActor(machine.implementations.actors[src]);
|
|
2380
|
-
if (!referenced) {
|
|
2381
|
-
throw new Error(`Actor logic '${src}' not implemented in machine '${machine.id}'`);
|
|
2382
|
-
}
|
|
2383
|
-
const input = 'input' in options ? options.input : referenced.input;
|
|
2384
|
-
|
|
2385
|
-
// TODO: this should also receive `src`
|
|
2386
|
-
const actor = createActor(referenced.src, {
|
|
2387
|
-
id: options.id,
|
|
2388
|
-
parent: actorContext.self,
|
|
2389
|
-
input: typeof input === 'function' ? input({
|
|
2390
|
-
context,
|
|
2391
|
-
event,
|
|
2392
|
-
self: actorContext.self
|
|
2393
|
-
}) : input,
|
|
2394
|
-
systemId
|
|
2395
|
-
});
|
|
2396
|
-
spawnedChildren[actor.id] = actor;
|
|
2397
|
-
return actor;
|
|
2398
|
-
} else {
|
|
2399
|
-
// TODO: this should also receive `src`
|
|
2400
|
-
return createActor(src, {
|
|
2401
|
-
id: options.id,
|
|
2402
|
-
parent: actorContext.self,
|
|
2403
|
-
input: options.input,
|
|
2404
|
-
systemId
|
|
2405
|
-
});
|
|
2406
|
-
}
|
|
2407
|
-
};
|
|
2408
|
-
return (src, options) => {
|
|
2409
|
-
const actorRef = spawn(src, options); // TODO: fix types
|
|
2410
|
-
spawnedChildren[actorRef.id] = actorRef;
|
|
2411
|
-
actorContext.defer(() => {
|
|
2412
|
-
if (actorRef.status === ActorStatus.Stopped) {
|
|
2413
|
-
return;
|
|
2414
|
-
}
|
|
2415
|
-
try {
|
|
2416
|
-
actorRef.start?.();
|
|
2417
|
-
} catch (err) {
|
|
2418
|
-
actorContext.self.send(error(actorRef.id, err));
|
|
2419
|
-
return;
|
|
2420
|
-
}
|
|
2421
|
-
});
|
|
2422
|
-
return actorRef;
|
|
2423
|
-
};
|
|
2424
|
-
}
|
|
2425
|
-
|
|
2426
|
-
function resolve$3(actorContext, state, actionArgs, {
|
|
2427
|
-
assignment
|
|
2428
|
-
}) {
|
|
2429
|
-
if (!state.context) {
|
|
2430
|
-
throw new Error('Cannot assign to undefined `context`. Ensure that `context` is defined in the machine config.');
|
|
2431
|
-
}
|
|
2432
|
-
const spawnedChildren = {};
|
|
2433
|
-
const assignArgs = {
|
|
2434
|
-
context: state.context,
|
|
2435
|
-
event: actionArgs.event,
|
|
2436
|
-
action: actionArgs.action,
|
|
2437
|
-
spawn: createSpawner(actorContext, state, actionArgs.event, spawnedChildren),
|
|
2438
|
-
self: actorContext?.self,
|
|
2439
|
-
system: actorContext?.system
|
|
2440
|
-
};
|
|
2441
|
-
let partialUpdate = {};
|
|
2442
|
-
if (typeof assignment === 'function') {
|
|
2443
|
-
partialUpdate = assignment(assignArgs);
|
|
2444
|
-
} else {
|
|
2445
|
-
for (const key of Object.keys(assignment)) {
|
|
2446
|
-
const propAssignment = assignment[key];
|
|
2447
|
-
partialUpdate[key] = typeof propAssignment === 'function' ? propAssignment(assignArgs) : propAssignment;
|
|
2448
|
-
}
|
|
2449
|
-
}
|
|
2450
|
-
const updatedContext = Object.assign({}, state.context, partialUpdate);
|
|
2451
|
-
return [cloneState(state, {
|
|
2452
|
-
context: updatedContext,
|
|
2453
|
-
children: Object.keys(spawnedChildren).length ? {
|
|
2454
|
-
...state.children,
|
|
2455
|
-
...spawnedChildren
|
|
2456
|
-
} : state.children
|
|
2457
|
-
})];
|
|
2458
|
-
}
|
|
2459
|
-
/**
|
|
2460
|
-
* Updates the current context of the machine.
|
|
2461
|
-
*
|
|
2462
|
-
* @param assignment An object that represents the partial context to update.
|
|
2463
|
-
*/
|
|
2464
|
-
function assign(assignment) {
|
|
2465
|
-
function assign(_) {
|
|
2466
|
-
{
|
|
2467
|
-
throw new Error(`This isn't supposed to be called`);
|
|
2468
|
-
}
|
|
2469
|
-
}
|
|
2470
|
-
assign.type = 'xstate.assign';
|
|
2471
|
-
assign.assignment = assignment;
|
|
2472
|
-
assign.resolve = resolve$3;
|
|
2473
|
-
return assign;
|
|
2474
|
-
}
|
|
2475
|
-
|
|
2476
|
-
function resolve$2(_, state, args, {
|
|
1418
|
+
function resolve(_, state, args, {
|
|
2477
1419
|
event: eventOrExpr,
|
|
2478
1420
|
id,
|
|
2479
1421
|
delay
|
|
@@ -2520,151 +1462,19 @@ function raise(eventOrExpr, options) {
|
|
|
2520
1462
|
raise.event = eventOrExpr;
|
|
2521
1463
|
raise.id = options?.id;
|
|
2522
1464
|
raise.delay = options?.delay;
|
|
2523
|
-
raise.resolve = resolve
|
|
1465
|
+
raise.resolve = resolve;
|
|
2524
1466
|
raise.execute = execute;
|
|
2525
1467
|
return raise;
|
|
2526
1468
|
}
|
|
2527
1469
|
|
|
2528
|
-
function resolve$1(_, state, actionArgs, {
|
|
2529
|
-
branches
|
|
2530
|
-
}) {
|
|
2531
|
-
const matchedActions = branches.find(condition => {
|
|
2532
|
-
return !condition.guard || evaluateGuard(condition.guard, state.context, actionArgs.event, state);
|
|
2533
|
-
})?.actions;
|
|
2534
|
-
return [state, undefined, toArray(matchedActions)];
|
|
2535
|
-
}
|
|
2536
|
-
function choose(branches) {
|
|
2537
|
-
function choose(_) {
|
|
2538
|
-
{
|
|
2539
|
-
throw new Error(`This isn't supposed to be called`);
|
|
2540
|
-
}
|
|
2541
|
-
}
|
|
2542
|
-
choose.type = 'xstate.choose';
|
|
2543
|
-
choose.branches = branches;
|
|
2544
|
-
choose.resolve = resolve$1;
|
|
2545
|
-
return choose;
|
|
2546
|
-
}
|
|
2547
|
-
|
|
2548
|
-
function resolve(_, state, args, {
|
|
2549
|
-
get
|
|
2550
|
-
}) {
|
|
2551
|
-
return [state, undefined, toArray(get({
|
|
2552
|
-
context: args.context,
|
|
2553
|
-
event: args.event
|
|
2554
|
-
}))];
|
|
2555
|
-
}
|
|
2556
|
-
function pure(getActions) {
|
|
2557
|
-
function pure(_) {
|
|
2558
|
-
{
|
|
2559
|
-
throw new Error(`This isn't supposed to be called`);
|
|
2560
|
-
}
|
|
2561
|
-
}
|
|
2562
|
-
pure.type = 'xstate.pure';
|
|
2563
|
-
pure.get = getActions;
|
|
2564
|
-
pure.resolve = resolve;
|
|
2565
|
-
return pure;
|
|
2566
|
-
}
|
|
2567
|
-
|
|
2568
|
-
/**
|
|
2569
|
-
* Returns an event type that represents an implicit event that
|
|
2570
|
-
* is sent after the specified `delay`.
|
|
2571
|
-
*
|
|
2572
|
-
* @param delayRef The delay in milliseconds
|
|
2573
|
-
* @param id The state node ID where this event is handled
|
|
2574
|
-
*/
|
|
2575
|
-
function after(delayRef, id) {
|
|
2576
|
-
const idSuffix = id ? `#${id}` : '';
|
|
2577
|
-
return `${ConstantPrefix.After}(${delayRef})${idSuffix}`;
|
|
2578
|
-
}
|
|
2579
|
-
|
|
2580
|
-
/**
|
|
2581
|
-
* Returns an event that represents that a final state node
|
|
2582
|
-
* has been reached in the parent state node.
|
|
2583
|
-
*
|
|
2584
|
-
* @param id The final state node's parent state node `id`
|
|
2585
|
-
* @param output The data to pass into the event
|
|
2586
|
-
*/
|
|
2587
|
-
function done(id, output) {
|
|
2588
|
-
const type = `${ConstantPrefix.DoneState}.${id}`;
|
|
2589
|
-
const eventObject = {
|
|
2590
|
-
type,
|
|
2591
|
-
output
|
|
2592
|
-
};
|
|
2593
|
-
eventObject.toString = () => type;
|
|
2594
|
-
return eventObject;
|
|
2595
|
-
}
|
|
2596
|
-
function doneInvokeEventType(invokeId) {
|
|
2597
|
-
return `${ConstantPrefix.DoneInvoke}.${invokeId}`;
|
|
2598
|
-
}
|
|
2599
|
-
|
|
2600
|
-
/**
|
|
2601
|
-
* Returns an event that represents that an invoked service has terminated.
|
|
2602
|
-
*
|
|
2603
|
-
* An invoked service is terminated when it has reached a top-level final state node,
|
|
2604
|
-
* but not when it is canceled.
|
|
2605
|
-
*
|
|
2606
|
-
* @param invokeId The invoked service ID
|
|
2607
|
-
* @param output The data to pass into the event
|
|
2608
|
-
*/
|
|
2609
|
-
function doneInvoke(invokeId, output) {
|
|
2610
|
-
const type = doneInvokeEventType(invokeId);
|
|
2611
|
-
const eventObject = {
|
|
2612
|
-
type,
|
|
2613
|
-
output
|
|
2614
|
-
};
|
|
2615
|
-
eventObject.toString = () => type;
|
|
2616
|
-
return eventObject;
|
|
2617
|
-
}
|
|
2618
|
-
function errorEventType(id) {
|
|
2619
|
-
return `${ConstantPrefix.ErrorPlatform}.${id}`;
|
|
2620
|
-
}
|
|
2621
|
-
function error(id, data) {
|
|
2622
|
-
const type = errorEventType(id);
|
|
2623
|
-
const eventObject = {
|
|
2624
|
-
type,
|
|
2625
|
-
data
|
|
2626
|
-
};
|
|
2627
|
-
eventObject.toString = () => type;
|
|
2628
|
-
return eventObject;
|
|
2629
|
-
}
|
|
2630
|
-
function createInitEvent(input) {
|
|
2631
|
-
return {
|
|
2632
|
-
type: XSTATE_INIT,
|
|
2633
|
-
input
|
|
2634
|
-
};
|
|
2635
|
-
}
|
|
2636
|
-
|
|
2637
|
-
exports.Actor = Actor;
|
|
2638
|
-
exports.ActorStatus = ActorStatus;
|
|
2639
|
-
exports.ConstantPrefix = ConstantPrefix;
|
|
2640
|
-
exports.InterpreterStatus = InterpreterStatus;
|
|
2641
|
-
exports.NULL_EVENT = NULL_EVENT;
|
|
2642
|
-
exports.STATE_DELIMITER = STATE_DELIMITER;
|
|
2643
|
-
exports.SpecialTargets = SpecialTargets;
|
|
2644
1470
|
exports.State = State;
|
|
2645
|
-
exports.XSTATE_INIT = XSTATE_INIT;
|
|
2646
|
-
exports.XSTATE_STOP = XSTATE_STOP;
|
|
2647
|
-
exports.after = after;
|
|
2648
1471
|
exports.and = and;
|
|
2649
|
-
exports.assign = assign;
|
|
2650
1472
|
exports.cancel = cancel;
|
|
2651
|
-
exports.choose = choose;
|
|
2652
1473
|
exports.cloneState = cloneState;
|
|
2653
|
-
exports.constantPrefixes = constantPrefixes;
|
|
2654
|
-
exports.createActor = createActor;
|
|
2655
|
-
exports.createInitEvent = createInitEvent;
|
|
2656
|
-
exports.createInvokeId = createInvokeId;
|
|
2657
|
-
exports.done = done;
|
|
2658
|
-
exports.doneInvoke = doneInvoke;
|
|
2659
|
-
exports.doneInvokeEventType = doneInvokeEventType;
|
|
2660
|
-
exports.error = error;
|
|
2661
|
-
exports.errorEventType = errorEventType;
|
|
2662
|
-
exports.escalate = escalate;
|
|
2663
1474
|
exports.evaluateGuard = evaluateGuard;
|
|
2664
1475
|
exports.formatInitialTransition = formatInitialTransition;
|
|
2665
1476
|
exports.formatTransition = formatTransition;
|
|
2666
1477
|
exports.formatTransitions = formatTransitions;
|
|
2667
|
-
exports.forwardTo = forwardTo;
|
|
2668
1478
|
exports.getCandidates = getCandidates;
|
|
2669
1479
|
exports.getConfiguration = getConfiguration;
|
|
2670
1480
|
exports.getDelayedTransitions = getDelayedTransitions;
|
|
@@ -2672,32 +1482,17 @@ exports.getInitialConfiguration = getInitialConfiguration;
|
|
|
2672
1482
|
exports.getPersistedState = getPersistedState;
|
|
2673
1483
|
exports.getStateNodeByPath = getStateNodeByPath;
|
|
2674
1484
|
exports.getStateNodes = getStateNodes;
|
|
2675
|
-
exports.interpret = interpret;
|
|
2676
1485
|
exports.isAtomicStateNode = isAtomicStateNode;
|
|
2677
|
-
exports.isErrorEvent = isErrorEvent;
|
|
2678
1486
|
exports.isInFinalState = isInFinalState;
|
|
2679
|
-
exports.isPromiseLike = isPromiseLike;
|
|
2680
1487
|
exports.isStateId = isStateId;
|
|
2681
|
-
exports.log = log;
|
|
2682
1488
|
exports.macrostep = macrostep;
|
|
2683
|
-
exports.mapValues = mapValues;
|
|
2684
|
-
exports.matchesState = matchesState;
|
|
2685
1489
|
exports.memo = memo;
|
|
2686
1490
|
exports.microstep = microstep;
|
|
2687
1491
|
exports.not = not;
|
|
2688
1492
|
exports.or = or;
|
|
2689
|
-
exports.pathToStateValue = pathToStateValue;
|
|
2690
|
-
exports.pure = pure;
|
|
2691
1493
|
exports.raise = raise;
|
|
2692
1494
|
exports.resolveActionsAndContext = resolveActionsAndContext;
|
|
2693
|
-
exports.resolveReferencedActor = resolveReferencedActor;
|
|
2694
1495
|
exports.resolveStateValue = resolveStateValue;
|
|
2695
|
-
exports.sendParent = sendParent;
|
|
2696
|
-
exports.sendTo = sendTo;
|
|
2697
1496
|
exports.stateIn = stateIn;
|
|
2698
1497
|
exports.stop = stop;
|
|
2699
|
-
exports.symbolObservable = symbolObservable;
|
|
2700
|
-
exports.toArray = toArray;
|
|
2701
|
-
exports.toObserver = toObserver;
|
|
2702
|
-
exports.toTransitionConfigArray = toTransitionConfigArray;
|
|
2703
1498
|
exports.transitionNode = transitionNode;
|