xstate 5.0.0-beta.19 → 5.0.0-beta.21
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 +1 -1
- package/actions/dist/xstate-actions.development.cjs.js +1 -1
- package/actions/dist/xstate-actions.development.esm.js +1 -1
- package/actions/dist/xstate-actions.esm.js +1 -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 +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/{actions-72105f77.development.esm.js → actions-49f0501e.development.esm.js} +421 -352
- package/dist/{actions-3b74fb92.esm.js → actions-5039c951.esm.js} +489 -423
- package/dist/{actions-bce11b97.development.cjs.js → actions-a95d2e66.development.cjs.js} +421 -351
- package/dist/{actions-2d912781.cjs.js → actions-c619a105.cjs.js} +489 -422
- package/dist/declarations/src/Machine.d.ts +2 -2
- package/dist/declarations/src/State.d.ts +12 -4
- package/dist/declarations/src/StateMachine.d.ts +17 -16
- package/dist/declarations/src/StateNode.d.ts +6 -6
- package/dist/declarations/src/actions/send.d.ts +1 -1
- package/dist/declarations/src/actions.d.ts +2 -2
- package/dist/declarations/src/actors/callback.d.ts +16 -6
- package/dist/declarations/src/actors/index.d.ts +4 -4
- package/dist/declarations/src/actors/observable.d.ts +14 -11
- package/dist/declarations/src/actors/promise.d.ts +14 -8
- package/dist/declarations/src/actors/transition.d.ts +6 -6
- package/dist/declarations/src/guards.d.ts +2 -2
- package/dist/declarations/src/stateUtils.d.ts +8 -8
- package/dist/declarations/src/typegenTypes.d.ts +15 -17
- package/dist/declarations/src/types.d.ts +131 -79
- package/dist/declarations/src/utils.d.ts +3 -3
- package/dist/xstate.cjs.js +12 -12
- package/dist/xstate.development.cjs.js +12 -12
- package/dist/xstate.development.esm.js +13 -13
- package/dist/xstate.esm.js +13 -13
- package/dist/xstate.umd.min.js +1 -1
- package/dist/xstate.umd.min.js.map +1 -1
- package/guards/dist/xstate-guards.cjs.js +1 -1
- package/guards/dist/xstate-guards.development.cjs.js +1 -1
- package/guards/dist/xstate-guards.development.esm.js +1 -1
- package/guards/dist/xstate-guards.esm.js +1 -1
- package/guards/dist/xstate-guards.umd.min.js.map +1 -1
- package/package.json +1 -1
|
@@ -2,10 +2,19 @@
|
|
|
2
2
|
|
|
3
3
|
var dev_dist_xstateDev = require('../dev/dist/xstate-dev.cjs.js');
|
|
4
4
|
|
|
5
|
-
|
|
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
|
+
*/
|
|
6
16
|
|
|
7
|
-
//
|
|
8
|
-
// export type IndexByType<T extends { type: string }> = { [E in T as E['type']]: E; };
|
|
17
|
+
// https://github.com/microsoft/TypeScript/issues/23182#issuecomment-379091887
|
|
9
18
|
|
|
10
19
|
/**
|
|
11
20
|
* The full definition of an event, with a string `type`.
|
|
@@ -15,8 +24,6 @@ var dev_dist_xstateDev = require('../dev/dist/xstate-dev.cjs.js');
|
|
|
15
24
|
// we should also accept a raw machine as actor logic here
|
|
16
25
|
// or just make machine actor logic
|
|
17
26
|
|
|
18
|
-
// TODO: narrow this to logic from machine
|
|
19
|
-
|
|
20
27
|
/**
|
|
21
28
|
* The string or object representing the state value relative to the parent state node.
|
|
22
29
|
*
|
|
@@ -307,7 +314,7 @@ const symbolObservable = (() => typeof Symbol === 'function' && Symbol.observabl
|
|
|
307
314
|
* @returns Actor logic
|
|
308
315
|
*/
|
|
309
316
|
function fromTransition(transition, initialState) {
|
|
310
|
-
|
|
317
|
+
return {
|
|
311
318
|
config: transition,
|
|
312
319
|
transition: (state, event, actorContext) => {
|
|
313
320
|
return transition(state, event, actorContext);
|
|
@@ -321,103 +328,255 @@ function fromTransition(transition, initialState) {
|
|
|
321
328
|
getPersistedState: state => state,
|
|
322
329
|
restoreState: state => state
|
|
323
330
|
};
|
|
324
|
-
return logic;
|
|
325
331
|
}
|
|
326
332
|
|
|
327
|
-
|
|
328
|
-
const
|
|
329
|
-
|
|
330
|
-
|
|
331
|
-
|
|
332
|
-
|
|
333
|
-
|
|
334
|
-
|
|
335
|
-
|
|
336
|
-
|
|
337
|
-
|
|
338
|
-
|
|
339
|
-
|
|
340
|
-
|
|
341
|
-
|
|
342
|
-
|
|
343
|
-
|
|
344
|
-
|
|
345
|
-
|
|
346
|
-
|
|
347
|
-
|
|
348
|
-
|
|
349
|
-
|
|
350
|
-
|
|
351
|
-
|
|
352
|
-
|
|
353
|
-
|
|
354
|
-
|
|
355
|
-
|
|
356
|
-
|
|
357
|
-
|
|
358
|
-
|
|
359
|
-
|
|
360
|
-
|
|
361
|
-
|
|
362
|
-
|
|
333
|
+
function matchesState(parentStateId, childStateId) {
|
|
334
|
+
const parentStateValue = toStateValue(parentStateId);
|
|
335
|
+
const childStateValue = toStateValue(childStateId);
|
|
336
|
+
if (typeof childStateValue === 'string') {
|
|
337
|
+
if (typeof parentStateValue === 'string') {
|
|
338
|
+
return childStateValue === parentStateValue;
|
|
339
|
+
}
|
|
340
|
+
|
|
341
|
+
// Parent more specific than child
|
|
342
|
+
return false;
|
|
343
|
+
}
|
|
344
|
+
if (typeof parentStateValue === 'string') {
|
|
345
|
+
return parentStateValue in childStateValue;
|
|
346
|
+
}
|
|
347
|
+
return Object.keys(parentStateValue).every(key => {
|
|
348
|
+
if (!(key in childStateValue)) {
|
|
349
|
+
return false;
|
|
350
|
+
}
|
|
351
|
+
return matchesState(parentStateValue[key], childStateValue[key]);
|
|
352
|
+
});
|
|
353
|
+
}
|
|
354
|
+
function toStatePath(stateId) {
|
|
355
|
+
try {
|
|
356
|
+
if (isArray(stateId)) {
|
|
357
|
+
return stateId;
|
|
358
|
+
}
|
|
359
|
+
return stateId.toString().split(STATE_DELIMITER);
|
|
360
|
+
} catch (e) {
|
|
361
|
+
throw new Error(`'${stateId}' is not a valid state path.`);
|
|
362
|
+
}
|
|
363
|
+
}
|
|
364
|
+
function isStateLike(state) {
|
|
365
|
+
return typeof state === 'object' && 'value' in state && 'context' in state && 'event' in state;
|
|
366
|
+
}
|
|
367
|
+
function toStateValue(stateValue) {
|
|
368
|
+
if (isStateLike(stateValue)) {
|
|
369
|
+
return stateValue.value;
|
|
370
|
+
}
|
|
371
|
+
if (isArray(stateValue)) {
|
|
372
|
+
return pathToStateValue(stateValue);
|
|
373
|
+
}
|
|
374
|
+
if (typeof stateValue !== 'string') {
|
|
375
|
+
return stateValue;
|
|
376
|
+
}
|
|
377
|
+
const statePath = toStatePath(stateValue);
|
|
378
|
+
return pathToStateValue(statePath);
|
|
379
|
+
}
|
|
380
|
+
function pathToStateValue(statePath) {
|
|
381
|
+
if (statePath.length === 1) {
|
|
382
|
+
return statePath[0];
|
|
383
|
+
}
|
|
384
|
+
const value = {};
|
|
385
|
+
let marker = value;
|
|
386
|
+
for (let i = 0; i < statePath.length - 1; i++) {
|
|
387
|
+
if (i === statePath.length - 2) {
|
|
388
|
+
marker[statePath[i]] = statePath[i + 1];
|
|
389
|
+
} else {
|
|
390
|
+
const previous = marker;
|
|
391
|
+
marker = {};
|
|
392
|
+
previous[statePath[i]] = marker;
|
|
393
|
+
}
|
|
394
|
+
}
|
|
395
|
+
return value;
|
|
396
|
+
}
|
|
397
|
+
function mapValues(collection, iteratee) {
|
|
398
|
+
const result = {};
|
|
399
|
+
const collectionKeys = Object.keys(collection);
|
|
400
|
+
for (let i = 0; i < collectionKeys.length; i++) {
|
|
401
|
+
const key = collectionKeys[i];
|
|
402
|
+
result[key] = iteratee(collection[key], key, collection, i);
|
|
403
|
+
}
|
|
404
|
+
return result;
|
|
405
|
+
}
|
|
406
|
+
function flatten(array) {
|
|
407
|
+
return [].concat(...array);
|
|
408
|
+
}
|
|
409
|
+
function toArrayStrict(value) {
|
|
410
|
+
if (isArray(value)) {
|
|
411
|
+
return value;
|
|
412
|
+
}
|
|
413
|
+
return [value];
|
|
414
|
+
}
|
|
415
|
+
function toArray(value) {
|
|
416
|
+
if (value === undefined) {
|
|
417
|
+
return [];
|
|
418
|
+
}
|
|
419
|
+
return toArrayStrict(value);
|
|
420
|
+
}
|
|
421
|
+
function mapContext(mapper, context, event, self) {
|
|
422
|
+
if (typeof mapper === 'function') {
|
|
423
|
+
return mapper({
|
|
424
|
+
context,
|
|
425
|
+
event,
|
|
426
|
+
self
|
|
427
|
+
});
|
|
428
|
+
}
|
|
429
|
+
return mapper;
|
|
430
|
+
}
|
|
431
|
+
function isPromiseLike(value) {
|
|
432
|
+
if (value instanceof Promise) {
|
|
433
|
+
return true;
|
|
434
|
+
}
|
|
435
|
+
// Check if shape matches the Promise/A+ specification for a "thenable".
|
|
436
|
+
if (value !== null && (typeof value === 'function' || typeof value === 'object') && typeof value.then === 'function') {
|
|
437
|
+
return true;
|
|
438
|
+
}
|
|
439
|
+
return false;
|
|
440
|
+
}
|
|
441
|
+
function isArray(value) {
|
|
442
|
+
return Array.isArray(value);
|
|
443
|
+
}
|
|
444
|
+
function isErrorEvent(event) {
|
|
445
|
+
return typeof event.type === 'string' && (event.type === errorExecution || event.type.startsWith(errorPlatform));
|
|
446
|
+
}
|
|
447
|
+
function toTransitionConfigArray(configLike) {
|
|
448
|
+
return toArrayStrict(configLike).map(transitionLike => {
|
|
449
|
+
if (typeof transitionLike === 'undefined' || typeof transitionLike === 'string') {
|
|
450
|
+
return {
|
|
451
|
+
target: transitionLike
|
|
452
|
+
};
|
|
453
|
+
}
|
|
454
|
+
return transitionLike;
|
|
455
|
+
});
|
|
456
|
+
}
|
|
457
|
+
function normalizeTarget(target) {
|
|
458
|
+
if (target === undefined || target === TARGETLESS_KEY) {
|
|
459
|
+
return undefined;
|
|
460
|
+
}
|
|
461
|
+
return toArray(target);
|
|
462
|
+
}
|
|
463
|
+
function toInvokeConfig(invocable, id) {
|
|
464
|
+
if (typeof invocable === 'object') {
|
|
465
|
+
if ('src' in invocable) {
|
|
466
|
+
return invocable;
|
|
467
|
+
}
|
|
468
|
+
if ('transition' in invocable) {
|
|
469
|
+
return {
|
|
470
|
+
id,
|
|
471
|
+
src: invocable
|
|
472
|
+
};
|
|
473
|
+
}
|
|
474
|
+
}
|
|
475
|
+
return {
|
|
476
|
+
id,
|
|
477
|
+
src: invocable
|
|
478
|
+
};
|
|
479
|
+
}
|
|
480
|
+
function toObserver(nextHandler, errorHandler, completionHandler) {
|
|
481
|
+
const isObserver = typeof nextHandler === 'object';
|
|
482
|
+
const self = isObserver ? nextHandler : undefined;
|
|
483
|
+
return {
|
|
484
|
+
next: (isObserver ? nextHandler.next : nextHandler)?.bind(self),
|
|
485
|
+
error: (isObserver ? nextHandler.error : errorHandler)?.bind(self),
|
|
486
|
+
complete: (isObserver ? nextHandler.complete : completionHandler)?.bind(self)
|
|
487
|
+
};
|
|
488
|
+
}
|
|
489
|
+
function createInvokeId(stateNodeId, index) {
|
|
490
|
+
return `${stateNodeId}:invocation[${index}]`;
|
|
491
|
+
}
|
|
492
|
+
function resolveReferencedActor(referenced) {
|
|
493
|
+
return referenced ? 'transition' in referenced ? {
|
|
494
|
+
src: referenced,
|
|
495
|
+
input: undefined
|
|
496
|
+
} : referenced : undefined;
|
|
497
|
+
}
|
|
498
|
+
|
|
499
|
+
function fromCallback(invokeCallback) {
|
|
500
|
+
return {
|
|
501
|
+
config: invokeCallback,
|
|
502
|
+
start: (_state, {
|
|
503
|
+
self
|
|
504
|
+
}) => {
|
|
505
|
+
self.send({
|
|
506
|
+
type: startSignalType
|
|
507
|
+
});
|
|
363
508
|
},
|
|
364
|
-
|
|
509
|
+
transition: (state, event, {
|
|
365
510
|
self,
|
|
511
|
+
id,
|
|
366
512
|
system
|
|
367
513
|
}) => {
|
|
368
|
-
|
|
369
|
-
|
|
370
|
-
|
|
371
|
-
|
|
514
|
+
if (event.type === startSignalType) {
|
|
515
|
+
const sendBack = eventForParent => {
|
|
516
|
+
if (state.canceled) {
|
|
517
|
+
return;
|
|
518
|
+
}
|
|
519
|
+
self._parent?.send(eventForParent);
|
|
520
|
+
};
|
|
521
|
+
const receive = newListener => {
|
|
522
|
+
state.receivers.add(newListener);
|
|
523
|
+
};
|
|
524
|
+
state.dispose = invokeCallback({
|
|
525
|
+
input: state.input,
|
|
526
|
+
system,
|
|
527
|
+
self: self,
|
|
528
|
+
sendBack,
|
|
529
|
+
receive
|
|
530
|
+
});
|
|
531
|
+
if (isPromiseLike(state.dispose)) {
|
|
532
|
+
state.dispose.then(resolved => {
|
|
533
|
+
self._parent?.send(doneInvoke(id, resolved));
|
|
534
|
+
state.canceled = true;
|
|
535
|
+
}, errorData => {
|
|
536
|
+
state.canceled = true;
|
|
537
|
+
self._parent?.send(error(id, errorData));
|
|
538
|
+
});
|
|
539
|
+
}
|
|
540
|
+
return state;
|
|
372
541
|
}
|
|
373
|
-
|
|
374
|
-
|
|
375
|
-
|
|
376
|
-
|
|
377
|
-
}));
|
|
378
|
-
resolvedPromise.then(response => {
|
|
379
|
-
// TODO: remove this condition once dead letter queue lands
|
|
380
|
-
if (self._state.status !== 'active') {
|
|
381
|
-
return;
|
|
542
|
+
if (event.type === stopSignalType) {
|
|
543
|
+
state.canceled = true;
|
|
544
|
+
if (typeof state.dispose === 'function') {
|
|
545
|
+
state.dispose();
|
|
382
546
|
}
|
|
383
|
-
|
|
384
|
-
|
|
385
|
-
|
|
386
|
-
|
|
387
|
-
|
|
388
|
-
|
|
389
|
-
|
|
390
|
-
|
|
391
|
-
}
|
|
392
|
-
self.send({
|
|
393
|
-
type: rejectEventType,
|
|
394
|
-
data: errorData
|
|
395
|
-
});
|
|
396
|
-
});
|
|
547
|
+
return state;
|
|
548
|
+
}
|
|
549
|
+
if (isSignal(event)) {
|
|
550
|
+
// TODO: unrecognized signal
|
|
551
|
+
return state;
|
|
552
|
+
}
|
|
553
|
+
state.receivers.forEach(receiver => receiver(event));
|
|
554
|
+
return state;
|
|
397
555
|
},
|
|
398
556
|
getInitialState: (_, input) => {
|
|
399
557
|
return {
|
|
400
|
-
|
|
401
|
-
|
|
558
|
+
canceled: false,
|
|
559
|
+
receivers: new Set(),
|
|
560
|
+
dispose: undefined,
|
|
402
561
|
input
|
|
403
562
|
};
|
|
404
563
|
},
|
|
405
|
-
getSnapshot:
|
|
406
|
-
|
|
407
|
-
|
|
408
|
-
|
|
564
|
+
getSnapshot: () => undefined,
|
|
565
|
+
getPersistedState: ({
|
|
566
|
+
input,
|
|
567
|
+
canceled
|
|
568
|
+
}) => ({
|
|
569
|
+
input,
|
|
570
|
+
canceled
|
|
571
|
+
})
|
|
409
572
|
};
|
|
410
|
-
return logic;
|
|
411
573
|
}
|
|
412
574
|
|
|
413
|
-
// TODO: this likely shouldn't accept TEvent, observable actor doesn't accept external events
|
|
414
575
|
function fromObservable(observableCreator) {
|
|
415
576
|
const nextEventType = '$$xstate.next';
|
|
416
577
|
const errorEventType = '$$xstate.error';
|
|
417
578
|
const completeEventType = '$$xstate.complete';
|
|
418
|
-
|
|
419
|
-
// TODO: add event types
|
|
420
|
-
const logic = {
|
|
579
|
+
return {
|
|
421
580
|
config: observableCreator,
|
|
422
581
|
transition: (state, event, {
|
|
423
582
|
self,
|
|
@@ -447,6 +606,7 @@ function fromObservable(observableCreator) {
|
|
|
447
606
|
status: 'error',
|
|
448
607
|
input: undefined,
|
|
449
608
|
data: event.data,
|
|
609
|
+
// TODO: if we keep this as `data` we should reflect this in the type
|
|
450
610
|
subscription: undefined
|
|
451
611
|
};
|
|
452
612
|
case completeEventType:
|
|
@@ -524,7 +684,6 @@ function fromObservable(observableCreator) {
|
|
|
524
684
|
subscription: undefined
|
|
525
685
|
})
|
|
526
686
|
};
|
|
527
|
-
return logic;
|
|
528
687
|
}
|
|
529
688
|
|
|
530
689
|
/**
|
|
@@ -541,7 +700,7 @@ function fromEventObservable(lazyObservable) {
|
|
|
541
700
|
const completeEventType = '$$xstate.complete';
|
|
542
701
|
|
|
543
702
|
// TODO: event types
|
|
544
|
-
|
|
703
|
+
return {
|
|
545
704
|
config: lazyObservable,
|
|
546
705
|
transition: (state, event) => {
|
|
547
706
|
if (state.status !== 'active') {
|
|
@@ -554,329 +713,166 @@ function fromEventObservable(lazyObservable) {
|
|
|
554
713
|
status: 'error',
|
|
555
714
|
input: undefined,
|
|
556
715
|
data: event.data,
|
|
557
|
-
|
|
558
|
-
|
|
559
|
-
|
|
560
|
-
|
|
561
|
-
|
|
562
|
-
|
|
563
|
-
|
|
564
|
-
|
|
565
|
-
|
|
566
|
-
|
|
567
|
-
|
|
568
|
-
|
|
569
|
-
|
|
570
|
-
|
|
571
|
-
|
|
572
|
-
|
|
573
|
-
|
|
574
|
-
|
|
575
|
-
|
|
576
|
-
|
|
577
|
-
|
|
578
|
-
|
|
579
|
-
|
|
580
|
-
subscription: undefined,
|
|
581
|
-
status: 'active',
|
|
582
|
-
data: undefined,
|
|
583
|
-
input
|
|
584
|
-
};
|
|
585
|
-
},
|
|
586
|
-
start: (state, {
|
|
587
|
-
self,
|
|
588
|
-
system
|
|
589
|
-
}) => {
|
|
590
|
-
if (state.status === 'done') {
|
|
591
|
-
// Do not restart a completed observable
|
|
592
|
-
return;
|
|
593
|
-
}
|
|
594
|
-
state.subscription = lazyObservable({
|
|
595
|
-
input: state.input,
|
|
596
|
-
system,
|
|
597
|
-
self
|
|
598
|
-
}).subscribe({
|
|
599
|
-
next: value => {
|
|
600
|
-
self._parent?.send(value);
|
|
601
|
-
},
|
|
602
|
-
error: err => {
|
|
603
|
-
self.send({
|
|
604
|
-
type: errorEventType,
|
|
605
|
-
data: err
|
|
606
|
-
});
|
|
607
|
-
},
|
|
608
|
-
complete: () => {
|
|
609
|
-
self.send({
|
|
610
|
-
type: completeEventType
|
|
611
|
-
});
|
|
612
|
-
}
|
|
613
|
-
});
|
|
614
|
-
},
|
|
615
|
-
getSnapshot: _ => undefined,
|
|
616
|
-
getPersistedState: ({
|
|
617
|
-
status,
|
|
618
|
-
data,
|
|
619
|
-
input
|
|
620
|
-
}) => ({
|
|
621
|
-
status,
|
|
622
|
-
data,
|
|
623
|
-
input
|
|
624
|
-
}),
|
|
625
|
-
getStatus: state => state,
|
|
626
|
-
restoreState: state => ({
|
|
627
|
-
...state,
|
|
628
|
-
subscription: undefined
|
|
629
|
-
})
|
|
630
|
-
};
|
|
631
|
-
return logic;
|
|
632
|
-
}
|
|
633
|
-
|
|
634
|
-
function matchesState(parentStateId, childStateId) {
|
|
635
|
-
const parentStateValue = toStateValue(parentStateId);
|
|
636
|
-
const childStateValue = toStateValue(childStateId);
|
|
637
|
-
if (typeof childStateValue === 'string') {
|
|
638
|
-
if (typeof parentStateValue === 'string') {
|
|
639
|
-
return childStateValue === parentStateValue;
|
|
640
|
-
}
|
|
641
|
-
|
|
642
|
-
// Parent more specific than child
|
|
643
|
-
return false;
|
|
644
|
-
}
|
|
645
|
-
if (typeof parentStateValue === 'string') {
|
|
646
|
-
return parentStateValue in childStateValue;
|
|
647
|
-
}
|
|
648
|
-
return Object.keys(parentStateValue).every(key => {
|
|
649
|
-
if (!(key in childStateValue)) {
|
|
650
|
-
return false;
|
|
651
|
-
}
|
|
652
|
-
return matchesState(parentStateValue[key], childStateValue[key]);
|
|
653
|
-
});
|
|
654
|
-
}
|
|
655
|
-
function toStatePath(stateId) {
|
|
656
|
-
try {
|
|
657
|
-
if (isArray(stateId)) {
|
|
658
|
-
return stateId;
|
|
659
|
-
}
|
|
660
|
-
return stateId.toString().split(STATE_DELIMITER);
|
|
661
|
-
} catch (e) {
|
|
662
|
-
throw new Error(`'${stateId}' is not a valid state path.`);
|
|
663
|
-
}
|
|
664
|
-
}
|
|
665
|
-
function isStateLike(state) {
|
|
666
|
-
return typeof state === 'object' && 'value' in state && 'context' in state && 'event' in state;
|
|
667
|
-
}
|
|
668
|
-
function toStateValue(stateValue) {
|
|
669
|
-
if (isStateLike(stateValue)) {
|
|
670
|
-
return stateValue.value;
|
|
671
|
-
}
|
|
672
|
-
if (isArray(stateValue)) {
|
|
673
|
-
return pathToStateValue(stateValue);
|
|
674
|
-
}
|
|
675
|
-
if (typeof stateValue !== 'string') {
|
|
676
|
-
return stateValue;
|
|
677
|
-
}
|
|
678
|
-
const statePath = toStatePath(stateValue);
|
|
679
|
-
return pathToStateValue(statePath);
|
|
680
|
-
}
|
|
681
|
-
function pathToStateValue(statePath) {
|
|
682
|
-
if (statePath.length === 1) {
|
|
683
|
-
return statePath[0];
|
|
684
|
-
}
|
|
685
|
-
const value = {};
|
|
686
|
-
let marker = value;
|
|
687
|
-
for (let i = 0; i < statePath.length - 1; i++) {
|
|
688
|
-
if (i === statePath.length - 2) {
|
|
689
|
-
marker[statePath[i]] = statePath[i + 1];
|
|
690
|
-
} else {
|
|
691
|
-
const previous = marker;
|
|
692
|
-
marker = {};
|
|
693
|
-
previous[statePath[i]] = marker;
|
|
694
|
-
}
|
|
695
|
-
}
|
|
696
|
-
return value;
|
|
697
|
-
}
|
|
698
|
-
function mapValues(collection, iteratee) {
|
|
699
|
-
const result = {};
|
|
700
|
-
const collectionKeys = Object.keys(collection);
|
|
701
|
-
for (let i = 0; i < collectionKeys.length; i++) {
|
|
702
|
-
const key = collectionKeys[i];
|
|
703
|
-
result[key] = iteratee(collection[key], key, collection, i);
|
|
704
|
-
}
|
|
705
|
-
return result;
|
|
706
|
-
}
|
|
707
|
-
function flatten(array) {
|
|
708
|
-
return [].concat(...array);
|
|
709
|
-
}
|
|
710
|
-
function toArrayStrict(value) {
|
|
711
|
-
if (isArray(value)) {
|
|
712
|
-
return value;
|
|
713
|
-
}
|
|
714
|
-
return [value];
|
|
715
|
-
}
|
|
716
|
-
function toArray(value) {
|
|
717
|
-
if (value === undefined) {
|
|
718
|
-
return [];
|
|
719
|
-
}
|
|
720
|
-
return toArrayStrict(value);
|
|
721
|
-
}
|
|
722
|
-
function mapContext(mapper, context, event) {
|
|
723
|
-
if (typeof mapper === 'function') {
|
|
724
|
-
return mapper({
|
|
725
|
-
context,
|
|
726
|
-
event
|
|
727
|
-
});
|
|
728
|
-
}
|
|
729
|
-
const result = {};
|
|
730
|
-
const args = {
|
|
731
|
-
context,
|
|
732
|
-
event
|
|
733
|
-
};
|
|
734
|
-
for (const key of Object.keys(mapper)) {
|
|
735
|
-
const subMapper = mapper[key];
|
|
736
|
-
if (typeof subMapper === 'function') {
|
|
737
|
-
result[key] = subMapper(args);
|
|
738
|
-
} else {
|
|
739
|
-
result[key] = subMapper;
|
|
740
|
-
}
|
|
741
|
-
}
|
|
742
|
-
return result;
|
|
743
|
-
}
|
|
744
|
-
function isPromiseLike(value) {
|
|
745
|
-
if (value instanceof Promise) {
|
|
746
|
-
return true;
|
|
747
|
-
}
|
|
748
|
-
// Check if shape matches the Promise/A+ specification for a "thenable".
|
|
749
|
-
if (value !== null && (typeof value === 'function' || typeof value === 'object') && typeof value.then === 'function') {
|
|
750
|
-
return true;
|
|
751
|
-
}
|
|
752
|
-
return false;
|
|
753
|
-
}
|
|
754
|
-
function isArray(value) {
|
|
755
|
-
return Array.isArray(value);
|
|
756
|
-
}
|
|
757
|
-
function isErrorEvent(event) {
|
|
758
|
-
return typeof event.type === 'string' && (event.type === errorExecution || event.type.startsWith(errorPlatform));
|
|
759
|
-
}
|
|
760
|
-
function toTransitionConfigArray(configLike) {
|
|
761
|
-
return toArrayStrict(configLike).map(transitionLike => {
|
|
762
|
-
if (typeof transitionLike === 'undefined' || typeof transitionLike === 'string') {
|
|
763
|
-
return {
|
|
764
|
-
target: transitionLike
|
|
765
|
-
};
|
|
766
|
-
}
|
|
767
|
-
return transitionLike;
|
|
768
|
-
});
|
|
769
|
-
}
|
|
770
|
-
function normalizeTarget(target) {
|
|
771
|
-
if (target === undefined || target === TARGETLESS_KEY) {
|
|
772
|
-
return undefined;
|
|
773
|
-
}
|
|
774
|
-
return toArray(target);
|
|
775
|
-
}
|
|
776
|
-
function toInvokeConfig(invocable, id) {
|
|
777
|
-
if (typeof invocable === 'object') {
|
|
778
|
-
if ('src' in invocable) {
|
|
779
|
-
return invocable;
|
|
780
|
-
}
|
|
781
|
-
if ('transition' in invocable) {
|
|
716
|
+
// TODO: if we keep this as `data` we should reflect this in the type
|
|
717
|
+
subscription: undefined
|
|
718
|
+
};
|
|
719
|
+
case completeEventType:
|
|
720
|
+
return {
|
|
721
|
+
...state,
|
|
722
|
+
status: 'done',
|
|
723
|
+
input: undefined,
|
|
724
|
+
subscription: undefined
|
|
725
|
+
};
|
|
726
|
+
case stopSignalType:
|
|
727
|
+
state.subscription.unsubscribe();
|
|
728
|
+
return {
|
|
729
|
+
...state,
|
|
730
|
+
status: 'canceled',
|
|
731
|
+
input: undefined,
|
|
732
|
+
subscription: undefined
|
|
733
|
+
};
|
|
734
|
+
default:
|
|
735
|
+
return state;
|
|
736
|
+
}
|
|
737
|
+
},
|
|
738
|
+
getInitialState: (_, input) => {
|
|
782
739
|
return {
|
|
783
|
-
|
|
784
|
-
|
|
740
|
+
subscription: undefined,
|
|
741
|
+
status: 'active',
|
|
742
|
+
data: undefined,
|
|
743
|
+
input
|
|
785
744
|
};
|
|
786
|
-
}
|
|
787
|
-
}
|
|
788
|
-
return {
|
|
789
|
-
id,
|
|
790
|
-
src: invocable
|
|
791
|
-
};
|
|
792
|
-
}
|
|
793
|
-
function toObserver(nextHandler, errorHandler, completionHandler) {
|
|
794
|
-
const noop = () => {};
|
|
795
|
-
const isObserver = typeof nextHandler === 'object';
|
|
796
|
-
const self = isObserver ? nextHandler : null;
|
|
797
|
-
return {
|
|
798
|
-
next: ((isObserver ? nextHandler.next : nextHandler) || noop).bind(self),
|
|
799
|
-
error: ((isObserver ? nextHandler.error : errorHandler) || noop).bind(self),
|
|
800
|
-
complete: ((isObserver ? nextHandler.complete : completionHandler) || noop).bind(self)
|
|
801
|
-
};
|
|
802
|
-
}
|
|
803
|
-
function createInvokeId(stateNodeId, index) {
|
|
804
|
-
return `${stateNodeId}:invocation[${index}]`;
|
|
805
|
-
}
|
|
806
|
-
function resolveReferencedActor(referenced) {
|
|
807
|
-
return referenced ? 'transition' in referenced ? {
|
|
808
|
-
src: referenced,
|
|
809
|
-
input: undefined
|
|
810
|
-
} : referenced : undefined;
|
|
811
|
-
}
|
|
812
|
-
|
|
813
|
-
function fromCallback(invokeCallback) {
|
|
814
|
-
const logic = {
|
|
815
|
-
config: invokeCallback,
|
|
816
|
-
start: (_state, {
|
|
817
|
-
self
|
|
818
|
-
}) => {
|
|
819
|
-
self.send({
|
|
820
|
-
type: startSignalType
|
|
821
|
-
});
|
|
822
745
|
},
|
|
823
|
-
|
|
746
|
+
start: (state, {
|
|
824
747
|
self,
|
|
825
|
-
id,
|
|
826
748
|
system
|
|
827
749
|
}) => {
|
|
828
|
-
if (
|
|
829
|
-
|
|
830
|
-
|
|
831
|
-
|
|
832
|
-
|
|
833
|
-
|
|
834
|
-
|
|
835
|
-
|
|
836
|
-
|
|
837
|
-
|
|
838
|
-
|
|
839
|
-
|
|
840
|
-
|
|
841
|
-
self
|
|
842
|
-
|
|
843
|
-
|
|
844
|
-
|
|
845
|
-
|
|
846
|
-
|
|
847
|
-
|
|
848
|
-
|
|
849
|
-
self._parent?.send(error(id, errorData));
|
|
750
|
+
if (state.status === 'done') {
|
|
751
|
+
// Do not restart a completed observable
|
|
752
|
+
return;
|
|
753
|
+
}
|
|
754
|
+
state.subscription = lazyObservable({
|
|
755
|
+
input: state.input,
|
|
756
|
+
system,
|
|
757
|
+
self
|
|
758
|
+
}).subscribe({
|
|
759
|
+
next: value => {
|
|
760
|
+
self._parent?.send(value);
|
|
761
|
+
},
|
|
762
|
+
error: err => {
|
|
763
|
+
self.send({
|
|
764
|
+
type: errorEventType,
|
|
765
|
+
data: err
|
|
766
|
+
});
|
|
767
|
+
},
|
|
768
|
+
complete: () => {
|
|
769
|
+
self.send({
|
|
770
|
+
type: completeEventType
|
|
850
771
|
});
|
|
851
772
|
}
|
|
773
|
+
});
|
|
774
|
+
},
|
|
775
|
+
getSnapshot: _ => undefined,
|
|
776
|
+
getPersistedState: ({
|
|
777
|
+
status,
|
|
778
|
+
data,
|
|
779
|
+
input
|
|
780
|
+
}) => ({
|
|
781
|
+
status,
|
|
782
|
+
data,
|
|
783
|
+
input
|
|
784
|
+
}),
|
|
785
|
+
getStatus: state => state,
|
|
786
|
+
restoreState: state => ({
|
|
787
|
+
...state,
|
|
788
|
+
subscription: undefined
|
|
789
|
+
})
|
|
790
|
+
};
|
|
791
|
+
}
|
|
792
|
+
|
|
793
|
+
const resolveEventType = '$$xstate.resolve';
|
|
794
|
+
const rejectEventType = '$$xstate.reject';
|
|
795
|
+
function fromPromise(
|
|
796
|
+
// TODO: add types
|
|
797
|
+
promiseCreator) {
|
|
798
|
+
// TODO: add event types
|
|
799
|
+
const logic = {
|
|
800
|
+
config: promiseCreator,
|
|
801
|
+
transition: (state, event) => {
|
|
802
|
+
if (state.status !== 'active') {
|
|
852
803
|
return state;
|
|
853
804
|
}
|
|
854
|
-
|
|
855
|
-
|
|
856
|
-
|
|
857
|
-
|
|
858
|
-
|
|
859
|
-
|
|
805
|
+
switch (event.type) {
|
|
806
|
+
case resolveEventType:
|
|
807
|
+
return {
|
|
808
|
+
...state,
|
|
809
|
+
status: 'done',
|
|
810
|
+
data: event.data,
|
|
811
|
+
input: undefined
|
|
812
|
+
};
|
|
813
|
+
case rejectEventType:
|
|
814
|
+
return {
|
|
815
|
+
...state,
|
|
816
|
+
status: 'error',
|
|
817
|
+
data: event.data,
|
|
818
|
+
// TODO: if we keep this as `data` we should reflect this in the type
|
|
819
|
+
input: undefined
|
|
820
|
+
};
|
|
821
|
+
case stopSignalType:
|
|
822
|
+
return {
|
|
823
|
+
...state,
|
|
824
|
+
status: 'canceled',
|
|
825
|
+
input: undefined
|
|
826
|
+
};
|
|
827
|
+
default:
|
|
828
|
+
return state;
|
|
860
829
|
}
|
|
861
|
-
|
|
862
|
-
|
|
863
|
-
|
|
830
|
+
},
|
|
831
|
+
start: (state, {
|
|
832
|
+
self,
|
|
833
|
+
system
|
|
834
|
+
}) => {
|
|
835
|
+
// TODO: determine how to allow customizing this so that promises
|
|
836
|
+
// can be restarted if necessary
|
|
837
|
+
if (state.status !== 'active') {
|
|
838
|
+
return;
|
|
864
839
|
}
|
|
865
|
-
|
|
866
|
-
|
|
840
|
+
const resolvedPromise = Promise.resolve(promiseCreator({
|
|
841
|
+
input: state.input,
|
|
842
|
+
system,
|
|
843
|
+
self
|
|
844
|
+
}));
|
|
845
|
+
resolvedPromise.then(response => {
|
|
846
|
+
// TODO: remove this condition once dead letter queue lands
|
|
847
|
+
if (self._state.status !== 'active') {
|
|
848
|
+
return;
|
|
849
|
+
}
|
|
850
|
+
self.send({
|
|
851
|
+
type: resolveEventType,
|
|
852
|
+
data: response
|
|
853
|
+
});
|
|
854
|
+
}, errorData => {
|
|
855
|
+
// TODO: remove this condition once dead letter queue lands
|
|
856
|
+
if (self._state.status !== 'active') {
|
|
857
|
+
return;
|
|
858
|
+
}
|
|
859
|
+
self.send({
|
|
860
|
+
type: rejectEventType,
|
|
861
|
+
data: errorData
|
|
862
|
+
});
|
|
863
|
+
});
|
|
867
864
|
},
|
|
868
865
|
getInitialState: (_, input) => {
|
|
869
866
|
return {
|
|
870
|
-
|
|
871
|
-
|
|
872
|
-
dispose: undefined,
|
|
867
|
+
status: 'active',
|
|
868
|
+
data: undefined,
|
|
873
869
|
input
|
|
874
870
|
};
|
|
875
871
|
},
|
|
876
|
-
getSnapshot:
|
|
877
|
-
|
|
878
|
-
|
|
879
|
-
|
|
872
|
+
getSnapshot: state => state.data,
|
|
873
|
+
getStatus: state => state,
|
|
874
|
+
getPersistedState: state => state,
|
|
875
|
+
restoreState: state => state
|
|
880
876
|
};
|
|
881
877
|
return logic;
|
|
882
878
|
}
|
|
@@ -915,6 +911,7 @@ function toActorRef(actorRefLike) {
|
|
|
915
911
|
id: 'anonymous',
|
|
916
912
|
sessionId: '',
|
|
917
913
|
getSnapshot: () => undefined,
|
|
914
|
+
// TODO: this isn't safe
|
|
918
915
|
[symbolObservable]: function () {
|
|
919
916
|
return this;
|
|
920
917
|
},
|
|
@@ -928,6 +925,19 @@ function createEmptyActor() {
|
|
|
928
925
|
return interpret(emptyLogic);
|
|
929
926
|
}
|
|
930
927
|
|
|
928
|
+
/**
|
|
929
|
+
* This function makes sure that unhandled errors are thrown in a separate macrotask.
|
|
930
|
+
* It allows those errors to be detected by global error handlers and reported to bug tracking services
|
|
931
|
+
* without interrupting our own stack of execution.
|
|
932
|
+
*
|
|
933
|
+
* @param err error to be thrown
|
|
934
|
+
*/
|
|
935
|
+
function reportUnhandledError(err) {
|
|
936
|
+
setTimeout(() => {
|
|
937
|
+
throw err;
|
|
938
|
+
});
|
|
939
|
+
}
|
|
940
|
+
|
|
931
941
|
function createSystem() {
|
|
932
942
|
let sessionIdCounter = 0;
|
|
933
943
|
const children = new Map();
|
|
@@ -1096,29 +1106,38 @@ class Interpreter {
|
|
|
1096
1106
|
deferredFn();
|
|
1097
1107
|
}
|
|
1098
1108
|
for (const observer of this.observers) {
|
|
1099
|
-
|
|
1109
|
+
// TODO: should observers be notified in case of the error?
|
|
1110
|
+
try {
|
|
1111
|
+
observer.next?.(snapshot);
|
|
1112
|
+
} catch (err) {
|
|
1113
|
+
reportUnhandledError(err);
|
|
1114
|
+
}
|
|
1100
1115
|
}
|
|
1101
1116
|
const status = this.logic.getStatus?.(state);
|
|
1102
1117
|
switch (status?.status) {
|
|
1103
1118
|
case 'done':
|
|
1104
1119
|
this._stopProcedure();
|
|
1120
|
+
this._complete();
|
|
1105
1121
|
this._doneEvent = doneInvoke(this.id, status.data);
|
|
1106
1122
|
this._parent?.send(this._doneEvent);
|
|
1107
|
-
this._complete();
|
|
1108
1123
|
break;
|
|
1109
1124
|
case 'error':
|
|
1110
1125
|
this._stopProcedure();
|
|
1111
|
-
this._parent?.send(error(this.id, status.data));
|
|
1112
1126
|
this._error(status.data);
|
|
1127
|
+
this._parent?.send(error(this.id, status.data));
|
|
1113
1128
|
break;
|
|
1114
1129
|
}
|
|
1115
1130
|
}
|
|
1116
1131
|
subscribe(nextListenerOrObserver, errorListener, completeListener) {
|
|
1117
1132
|
const observer = toObserver(nextListenerOrObserver, errorListener, completeListener);
|
|
1118
|
-
this.
|
|
1119
|
-
|
|
1120
|
-
|
|
1121
|
-
|
|
1133
|
+
if (this.status !== ActorStatus.Stopped) {
|
|
1134
|
+
this.observers.add(observer);
|
|
1135
|
+
} else {
|
|
1136
|
+
try {
|
|
1137
|
+
observer.complete?.();
|
|
1138
|
+
} catch (err) {
|
|
1139
|
+
reportUnhandledError(err);
|
|
1140
|
+
}
|
|
1122
1141
|
}
|
|
1123
1142
|
return {
|
|
1124
1143
|
unsubscribe: () => {
|
|
@@ -1140,8 +1159,26 @@ class Interpreter {
|
|
|
1140
1159
|
this.system._set(this._systemId, this);
|
|
1141
1160
|
}
|
|
1142
1161
|
this.status = ActorStatus.Running;
|
|
1162
|
+
const status = this.logic.getStatus?.(this._state);
|
|
1163
|
+
switch (status?.status) {
|
|
1164
|
+
case 'done':
|
|
1165
|
+
// a state machine can be "done" upon intialization (it could reach a final state using initial microsteps)
|
|
1166
|
+
// we still need to complete observers, flush deferreds etc
|
|
1167
|
+
this.update(this._state);
|
|
1168
|
+
// fallthrough
|
|
1169
|
+
case 'error':
|
|
1170
|
+
// TODO: rethink cleanup of observers, mailbox, etc
|
|
1171
|
+
return this;
|
|
1172
|
+
}
|
|
1143
1173
|
if (this.logic.start) {
|
|
1144
|
-
|
|
1174
|
+
try {
|
|
1175
|
+
this.logic.start(this._state, this._actorContext);
|
|
1176
|
+
} catch (err) {
|
|
1177
|
+
this._stopProcedure();
|
|
1178
|
+
this._error(err);
|
|
1179
|
+
this._parent?.send(error(this.id, err));
|
|
1180
|
+
return this;
|
|
1181
|
+
}
|
|
1145
1182
|
}
|
|
1146
1183
|
|
|
1147
1184
|
// TODO: this notifies all subscribers but usually this is redundant
|
|
@@ -1155,23 +1192,30 @@ class Interpreter {
|
|
|
1155
1192
|
return this;
|
|
1156
1193
|
}
|
|
1157
1194
|
_process(event) {
|
|
1195
|
+
// TODO: reexamine what happens when an action (or a guard or smth) throws
|
|
1196
|
+
let nextState;
|
|
1197
|
+
let caughtError;
|
|
1158
1198
|
try {
|
|
1159
|
-
|
|
1160
|
-
this.update(nextState);
|
|
1161
|
-
if (event.type === stopSignalType) {
|
|
1162
|
-
this._stopProcedure();
|
|
1163
|
-
this._complete();
|
|
1164
|
-
}
|
|
1199
|
+
nextState = this.logic.transition(this._state, event, this._actorContext);
|
|
1165
1200
|
} catch (err) {
|
|
1166
|
-
//
|
|
1167
|
-
|
|
1168
|
-
|
|
1169
|
-
|
|
1170
|
-
|
|
1171
|
-
|
|
1172
|
-
|
|
1173
|
-
|
|
1174
|
-
}
|
|
1201
|
+
// we wrap it in a box so we can rethrow it later even if falsy value gets caught here
|
|
1202
|
+
caughtError = {
|
|
1203
|
+
err
|
|
1204
|
+
};
|
|
1205
|
+
}
|
|
1206
|
+
if (caughtError) {
|
|
1207
|
+
const {
|
|
1208
|
+
err
|
|
1209
|
+
} = caughtError;
|
|
1210
|
+
this._stopProcedure();
|
|
1211
|
+
this._error(err);
|
|
1212
|
+
this._parent?.send(error(this.id, err));
|
|
1213
|
+
return;
|
|
1214
|
+
}
|
|
1215
|
+
this.update(nextState);
|
|
1216
|
+
if (event.type === stopSignalType) {
|
|
1217
|
+
this._stopProcedure();
|
|
1218
|
+
this._complete();
|
|
1175
1219
|
}
|
|
1176
1220
|
}
|
|
1177
1221
|
_stop() {
|
|
@@ -1200,15 +1244,35 @@ class Interpreter {
|
|
|
1200
1244
|
}
|
|
1201
1245
|
_complete() {
|
|
1202
1246
|
for (const observer of this.observers) {
|
|
1203
|
-
|
|
1247
|
+
try {
|
|
1248
|
+
observer.complete?.();
|
|
1249
|
+
} catch (err) {
|
|
1250
|
+
reportUnhandledError(err);
|
|
1251
|
+
}
|
|
1204
1252
|
}
|
|
1205
1253
|
this.observers.clear();
|
|
1206
1254
|
}
|
|
1207
|
-
_error(
|
|
1255
|
+
_error(err) {
|
|
1256
|
+
if (!this.observers.size) {
|
|
1257
|
+
if (!this._parent) {
|
|
1258
|
+
reportUnhandledError(err);
|
|
1259
|
+
}
|
|
1260
|
+
return;
|
|
1261
|
+
}
|
|
1262
|
+
let reportError = false;
|
|
1208
1263
|
for (const observer of this.observers) {
|
|
1209
|
-
observer.error
|
|
1264
|
+
const errorListener = observer.error;
|
|
1265
|
+
reportError ||= !errorListener;
|
|
1266
|
+
try {
|
|
1267
|
+
errorListener?.(err);
|
|
1268
|
+
} catch (err2) {
|
|
1269
|
+
reportUnhandledError(err2);
|
|
1270
|
+
}
|
|
1210
1271
|
}
|
|
1211
1272
|
this.observers.clear();
|
|
1273
|
+
if (reportError) {
|
|
1274
|
+
reportUnhandledError(err);
|
|
1275
|
+
}
|
|
1212
1276
|
}
|
|
1213
1277
|
_stopProcedure() {
|
|
1214
1278
|
if (this.status !== ActorStatus.Running) {
|
|
@@ -1530,10 +1594,10 @@ function toGuardDefinition(guardConfig, getPredicate) {
|
|
|
1530
1594
|
}
|
|
1531
1595
|
}
|
|
1532
1596
|
|
|
1533
|
-
function getOutput(configuration, context, event) {
|
|
1597
|
+
function getOutput(configuration, context, event, self) {
|
|
1534
1598
|
const machine = configuration[0].machine;
|
|
1535
1599
|
const finalChildStateNode = configuration.find(stateNode => stateNode.type === 'final' && stateNode.parent === machine.root);
|
|
1536
|
-
return finalChildStateNode && finalChildStateNode.output ? mapContext(finalChildStateNode.output, context, event) : undefined;
|
|
1600
|
+
return finalChildStateNode && finalChildStateNode.output ? mapContext(finalChildStateNode.output, context, event, self) : undefined;
|
|
1537
1601
|
}
|
|
1538
1602
|
const isAtomicStateNode = stateNode => stateNode.type === 'atomic' || stateNode.type === 'final';
|
|
1539
1603
|
function getChildren(stateNode) {
|
|
@@ -2149,7 +2213,7 @@ function microstepProcedure(transitions, currentState, mutConfiguration, event,
|
|
|
2149
2213
|
actions.push(...filteredTransitions.flatMap(t => t.actions));
|
|
2150
2214
|
|
|
2151
2215
|
// Enter states
|
|
2152
|
-
enterStates(event, filteredTransitions, mutConfiguration, actions, internalQueue, currentState, historyValue, isInitial);
|
|
2216
|
+
enterStates(event, filteredTransitions, mutConfiguration, actions, internalQueue, currentState, historyValue, isInitial, actorCtx);
|
|
2153
2217
|
const nextConfiguration = [...mutConfiguration];
|
|
2154
2218
|
const done = isInFinalState(nextConfiguration);
|
|
2155
2219
|
if (done) {
|
|
@@ -2158,7 +2222,7 @@ function microstepProcedure(transitions, currentState, mutConfiguration, event,
|
|
|
2158
2222
|
}
|
|
2159
2223
|
try {
|
|
2160
2224
|
const nextState = resolveActionsAndContext(actions, event, currentState, actorCtx);
|
|
2161
|
-
const output = done ? getOutput(nextConfiguration, nextState.context, event) : undefined;
|
|
2225
|
+
const output = done ? getOutput(nextConfiguration, nextState.context, event, actorCtx.self) : undefined;
|
|
2162
2226
|
internalQueue.push(...nextState._internalQueue);
|
|
2163
2227
|
return cloneState(currentState, {
|
|
2164
2228
|
configuration: nextConfiguration,
|
|
@@ -2175,7 +2239,7 @@ function microstepProcedure(transitions, currentState, mutConfiguration, event,
|
|
|
2175
2239
|
throw e;
|
|
2176
2240
|
}
|
|
2177
2241
|
}
|
|
2178
|
-
function enterStates(event, filteredTransitions, mutConfiguration, actions, internalQueue, currentState, historyValue, isInitial) {
|
|
2242
|
+
function enterStates(event, filteredTransitions, mutConfiguration, actions, internalQueue, currentState, historyValue, isInitial, actorContext) {
|
|
2179
2243
|
const statesToEnter = new Set();
|
|
2180
2244
|
const statesForDefaultEntry = new Set();
|
|
2181
2245
|
computeEntrySet(filteredTransitions, historyValue, statesForDefaultEntry, statesToEnter);
|
|
@@ -2203,7 +2267,7 @@ function enterStates(event, filteredTransitions, mutConfiguration, actions, inte
|
|
|
2203
2267
|
if (!parent.parent) {
|
|
2204
2268
|
continue;
|
|
2205
2269
|
}
|
|
2206
|
-
internalQueue.push(done(parent.id, stateNodeToEnter.output ? mapContext(stateNodeToEnter.output, currentState.context, event) : undefined));
|
|
2270
|
+
internalQueue.push(done(parent.id, stateNodeToEnter.output ? mapContext(stateNodeToEnter.output, currentState.context, event, actorContext.self) : undefined));
|
|
2207
2271
|
if (parent.parent) {
|
|
2208
2272
|
const grandparent = parent.parent;
|
|
2209
2273
|
if (grandparent.type === 'parallel') {
|
|
@@ -2523,6 +2587,7 @@ class State {
|
|
|
2523
2587
|
this.value = void 0;
|
|
2524
2588
|
this.done = void 0;
|
|
2525
2589
|
this.output = void 0;
|
|
2590
|
+
this.error = void 0;
|
|
2526
2591
|
this.context = void 0;
|
|
2527
2592
|
this.historyValue = {};
|
|
2528
2593
|
this._internalQueue = void 0;
|
|
@@ -2539,6 +2604,7 @@ class State {
|
|
|
2539
2604
|
this.tags = new Set(flatten(this.configuration.map(sn => sn.tags)));
|
|
2540
2605
|
this.done = config.done ?? false;
|
|
2541
2606
|
this.output = config.output;
|
|
2607
|
+
this.error = config.error;
|
|
2542
2608
|
}
|
|
2543
2609
|
|
|
2544
2610
|
/**
|
|
@@ -2774,7 +2840,7 @@ function createSpawner(actorContext, {
|
|
|
2774
2840
|
}
|
|
2775
2841
|
};
|
|
2776
2842
|
return (src, options) => {
|
|
2777
|
-
const actorRef = spawn(src, options);
|
|
2843
|
+
const actorRef = spawn(src, options); // TODO: fix types
|
|
2778
2844
|
spawnedChildren[actorRef.id] = actorRef;
|
|
2779
2845
|
actorContext.defer(() => {
|
|
2780
2846
|
if (actorRef.status === ActorStatus.Stopped) {
|
|
@@ -3000,6 +3066,7 @@ exports.and = and;
|
|
|
3000
3066
|
exports.assign = assign;
|
|
3001
3067
|
exports.cancel = cancel;
|
|
3002
3068
|
exports.choose = choose;
|
|
3069
|
+
exports.cloneState = cloneState;
|
|
3003
3070
|
exports.constantPrefixes = constantPrefixes;
|
|
3004
3071
|
exports.createEmptyActor = createEmptyActor;
|
|
3005
3072
|
exports.createInitEvent = createInitEvent;
|