xstate 5.0.0-beta.49 → 5.0.0-beta.51
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 +11 -10
- package/actions/dist/xstate-actions.cjs.mjs +1 -0
- package/actions/dist/xstate-actions.development.cjs.js +11 -10
- package/actions/dist/xstate-actions.development.cjs.mjs +1 -0
- package/actions/dist/xstate-actions.development.esm.js +2 -2
- package/actions/dist/xstate-actions.esm.js +2 -2
- 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 +2 -4
- package/actors/dist/xstate-actors.development.cjs.js +2 -4
- package/actors/dist/xstate-actors.development.esm.js +2 -4
- package/actors/dist/xstate-actors.esm.js +2 -4
- 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/actions/enqueueActions.d.ts +32 -0
- package/dist/declarations/src/actions/pure.d.ts +7 -10
- package/dist/declarations/src/actions.d.ts +3 -2
- package/dist/declarations/src/actors/callback.d.ts +5 -5
- package/dist/declarations/src/actors/observable.d.ts +5 -5
- package/dist/declarations/src/actors/promise.d.ts +2 -2
- package/dist/declarations/src/actors/transition.d.ts +3 -3
- package/dist/declarations/src/interpreter.d.ts +1 -0
- package/dist/declarations/src/setup.d.ts +2 -2
- package/dist/declarations/src/types.d.ts +5 -3
- package/dist/declarations/src/utils.d.ts +1 -20
- package/dist/{send-0a381ca2.development.esm.js → pure-296f8ebd.development.esm.js} +114 -77
- package/dist/{send-8d30b415.development.cjs.js → pure-a0f16134.development.cjs.js} +114 -76
- package/dist/{send-22880315.esm.js → pure-aefddc19.esm.js} +108 -71
- package/dist/{send-8ed5c8b2.cjs.js → pure-c5f1b46c.cjs.js} +108 -70
- package/dist/{raise-e4cc6d4f.esm.js → raise-4742bf04.esm.js} +98 -38
- package/dist/{raise-495f4b9f.development.cjs.js → raise-528386de.development.cjs.js} +97 -38
- package/dist/{raise-1873c645.development.esm.js → raise-acaa3884.development.esm.js} +98 -38
- package/dist/{raise-8f9c4a5a.cjs.js → raise-d5633a02.cjs.js} +97 -38
- package/dist/xstate.cjs.js +14 -23
- package/dist/xstate.cjs.mjs +1 -0
- package/dist/xstate.development.cjs.js +14 -23
- package/dist/xstate.development.cjs.mjs +1 -0
- package/dist/xstate.development.esm.js +5 -15
- package/dist/xstate.esm.js +5 -15
- 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
|
@@ -205,14 +205,10 @@ function matchesState(parentStateId, childStateId) {
|
|
|
205
205
|
});
|
|
206
206
|
}
|
|
207
207
|
function toStatePath(stateId) {
|
|
208
|
-
|
|
209
|
-
|
|
210
|
-
return stateId;
|
|
211
|
-
}
|
|
212
|
-
return stateId.split(STATE_DELIMITER);
|
|
213
|
-
} catch (e) {
|
|
214
|
-
throw new Error(`'${stateId}' is not a valid state path.`);
|
|
208
|
+
if (isArray(stateId)) {
|
|
209
|
+
return stateId;
|
|
215
210
|
}
|
|
211
|
+
return stateId.split(STATE_DELIMITER);
|
|
216
212
|
}
|
|
217
213
|
function toStateValue(stateValue) {
|
|
218
214
|
if (isMachineSnapshot(stateValue)) {
|
|
@@ -454,7 +450,18 @@ class Actor {
|
|
|
454
450
|
}
|
|
455
451
|
}
|
|
456
452
|
_initState(persistedState) {
|
|
457
|
-
|
|
453
|
+
try {
|
|
454
|
+
this._state = persistedState ? this.logic.restoreState ? this.logic.restoreState(persistedState, this._actorScope) : persistedState : this.logic.getInitialState(this._actorScope, this.options?.input);
|
|
455
|
+
} catch (err) {
|
|
456
|
+
// if we get here then it means that we assign a value to this._state that is not of the correct type
|
|
457
|
+
// we can't get the true `TSnapshot & { status: 'error'; }`, it's impossible
|
|
458
|
+
// so right now this is a lie of sorts
|
|
459
|
+
this._state = {
|
|
460
|
+
status: 'error',
|
|
461
|
+
output: undefined,
|
|
462
|
+
error: err
|
|
463
|
+
};
|
|
464
|
+
}
|
|
458
465
|
}
|
|
459
466
|
update(snapshot, event) {
|
|
460
467
|
// Update state
|
|
@@ -463,17 +470,46 @@ class Actor {
|
|
|
463
470
|
// Execute deferred effects
|
|
464
471
|
let deferredFn;
|
|
465
472
|
while (deferredFn = this._deferred.shift()) {
|
|
466
|
-
deferredFn();
|
|
467
|
-
}
|
|
468
|
-
for (const observer of this.observers) {
|
|
469
473
|
try {
|
|
470
|
-
|
|
474
|
+
deferredFn();
|
|
471
475
|
} catch (err) {
|
|
472
|
-
|
|
476
|
+
// this error can only be caught when executing *initial* actions
|
|
477
|
+
// it's the only time when we call actions provided by the user through those deferreds
|
|
478
|
+
// when the actor is already running we always execute them synchronously while transitioning
|
|
479
|
+
// no "builtin deferred" should actually throw an error since they are either safe
|
|
480
|
+
// or the control flow is passed through the mailbox and errors should be caught by the `_process` used by the mailbox
|
|
481
|
+
this._deferred.length = 0;
|
|
482
|
+
this._state = {
|
|
483
|
+
...snapshot,
|
|
484
|
+
status: 'error',
|
|
485
|
+
error: err
|
|
486
|
+
};
|
|
473
487
|
}
|
|
474
488
|
}
|
|
475
489
|
switch (this._state.status) {
|
|
490
|
+
case 'active':
|
|
491
|
+
for (const observer of this.observers) {
|
|
492
|
+
try {
|
|
493
|
+
observer.next?.(snapshot);
|
|
494
|
+
} catch (err) {
|
|
495
|
+
reportUnhandledError(err);
|
|
496
|
+
}
|
|
497
|
+
}
|
|
498
|
+
break;
|
|
476
499
|
case 'done':
|
|
500
|
+
// next observers are meant to be notified about done snapshots
|
|
501
|
+
// this can be seen as something that is different from how observable work
|
|
502
|
+
// but with observables `complete` callback is called without any arguments
|
|
503
|
+
// it's more ergonomic for XState to treat a done snapshot as a "next" value
|
|
504
|
+
// and the completion event as something that is separate,
|
|
505
|
+
// something that merely follows emitting that done snapshot
|
|
506
|
+
for (const observer of this.observers) {
|
|
507
|
+
try {
|
|
508
|
+
observer.next?.(snapshot);
|
|
509
|
+
} catch (err) {
|
|
510
|
+
reportUnhandledError(err);
|
|
511
|
+
}
|
|
512
|
+
}
|
|
477
513
|
this._stopProcedure();
|
|
478
514
|
this._complete();
|
|
479
515
|
this._doneEvent = createDoneActorEvent(this.id, this._state.output);
|
|
@@ -482,11 +518,7 @@ class Actor {
|
|
|
482
518
|
}
|
|
483
519
|
break;
|
|
484
520
|
case 'error':
|
|
485
|
-
this._stopProcedure();
|
|
486
521
|
this._error(this._state.error);
|
|
487
|
-
if (this._parent) {
|
|
488
|
-
this.system._relay(this, this._parent, createErrorActorEvent(this.id, this._state.error));
|
|
489
|
-
}
|
|
490
522
|
break;
|
|
491
523
|
}
|
|
492
524
|
this.system._sendInspectionEvent({
|
|
@@ -576,7 +608,7 @@ class Actor {
|
|
|
576
608
|
this.subscribe({
|
|
577
609
|
next: snapshot => {
|
|
578
610
|
if (snapshot.status === 'active') {
|
|
579
|
-
this.
|
|
611
|
+
this.system._relay(this, this._parent, {
|
|
580
612
|
type: `xstate.snapshot.${this.id}`,
|
|
581
613
|
snapshot
|
|
582
614
|
});
|
|
@@ -605,18 +637,22 @@ class Actor {
|
|
|
605
637
|
// a state machine can be "done" upon initialization (it could reach a final state using initial microsteps)
|
|
606
638
|
// we still need to complete observers, flush deferreds etc
|
|
607
639
|
this.update(this._state, initEvent);
|
|
608
|
-
// fallthrough
|
|
609
|
-
case 'error':
|
|
610
640
|
// TODO: rethink cleanup of observers, mailbox, etc
|
|
611
641
|
return this;
|
|
642
|
+
case 'error':
|
|
643
|
+
this._error(this._state.error);
|
|
644
|
+
return this;
|
|
612
645
|
}
|
|
613
646
|
if (this.logic.start) {
|
|
614
647
|
try {
|
|
615
648
|
this.logic.start(this._state, this._actorScope);
|
|
616
649
|
} catch (err) {
|
|
617
|
-
this.
|
|
650
|
+
this._state = {
|
|
651
|
+
...this._state,
|
|
652
|
+
status: 'error',
|
|
653
|
+
error: err
|
|
654
|
+
};
|
|
618
655
|
this._error(err);
|
|
619
|
-
this._parent?.send(createErrorActorEvent(this.id, err));
|
|
620
656
|
return this;
|
|
621
657
|
}
|
|
622
658
|
}
|
|
@@ -632,7 +668,6 @@ class Actor {
|
|
|
632
668
|
return this;
|
|
633
669
|
}
|
|
634
670
|
_process(event) {
|
|
635
|
-
// TODO: reexamine what happens when an action (or a guard or smth) throws
|
|
636
671
|
let nextState;
|
|
637
672
|
let caughtError;
|
|
638
673
|
try {
|
|
@@ -647,9 +682,12 @@ class Actor {
|
|
|
647
682
|
const {
|
|
648
683
|
err
|
|
649
684
|
} = caughtError;
|
|
650
|
-
this.
|
|
685
|
+
this._state = {
|
|
686
|
+
...this._state,
|
|
687
|
+
status: 'error',
|
|
688
|
+
error: err
|
|
689
|
+
};
|
|
651
690
|
this._error(err);
|
|
652
|
-
this._parent?.send(createErrorActorEvent(this.id, err));
|
|
653
691
|
return;
|
|
654
692
|
}
|
|
655
693
|
this.update(nextState, event);
|
|
@@ -692,7 +730,7 @@ class Actor {
|
|
|
692
730
|
}
|
|
693
731
|
this.observers.clear();
|
|
694
732
|
}
|
|
695
|
-
|
|
733
|
+
_reportError(err) {
|
|
696
734
|
if (!this.observers.size) {
|
|
697
735
|
if (!this._parent) {
|
|
698
736
|
reportUnhandledError(err);
|
|
@@ -714,6 +752,18 @@ class Actor {
|
|
|
714
752
|
reportUnhandledError(err);
|
|
715
753
|
}
|
|
716
754
|
}
|
|
755
|
+
_error(err) {
|
|
756
|
+
this._stopProcedure();
|
|
757
|
+
this._reportError(err);
|
|
758
|
+
if (this._parent) {
|
|
759
|
+
this.system._relay(this, this._parent, createErrorActorEvent(this.id, err));
|
|
760
|
+
}
|
|
761
|
+
}
|
|
762
|
+
// TODO: atm children don't belong entirely to the actor so
|
|
763
|
+
// in a way - it's not even super aware of them
|
|
764
|
+
// so we can't stop them from here but we really should!
|
|
765
|
+
// right now, they are being stopped within the machine's transition
|
|
766
|
+
// but that could throw and leave us with "orphaned" active actors
|
|
717
767
|
_stopProcedure() {
|
|
718
768
|
if (this._processingStatus !== ProcessingStatus.Running) {
|
|
719
769
|
// Actor already stopped; do nothing
|
|
@@ -973,12 +1023,7 @@ function executeSpawn(actorScope, {
|
|
|
973
1023
|
if (actorRef._processingStatus === ProcessingStatus.Stopped) {
|
|
974
1024
|
return;
|
|
975
1025
|
}
|
|
976
|
-
|
|
977
|
-
actorRef.start?.();
|
|
978
|
-
} catch (err) {
|
|
979
|
-
actorScope.self.send(createErrorActorEvent(id, err));
|
|
980
|
-
return;
|
|
981
|
-
}
|
|
1026
|
+
actorRef.start();
|
|
982
1027
|
});
|
|
983
1028
|
}
|
|
984
1029
|
function spawnChild(...[src, {
|
|
@@ -1322,8 +1367,7 @@ function getDelayedTransitions(stateNode) {
|
|
|
1322
1367
|
return [];
|
|
1323
1368
|
}
|
|
1324
1369
|
const mutateEntryExit = (delay, i) => {
|
|
1325
|
-
const
|
|
1326
|
-
const afterEvent = createAfterEvent(delayRef, stateNode.id);
|
|
1370
|
+
const afterEvent = createAfterEvent(delay, stateNode.id);
|
|
1327
1371
|
const eventType = afterEvent.type;
|
|
1328
1372
|
stateNode.entry.push(raise(afterEvent, {
|
|
1329
1373
|
id: eventType,
|
|
@@ -1337,8 +1381,8 @@ function getDelayedTransitions(stateNode) {
|
|
|
1337
1381
|
const resolvedTransition = typeof configTransition === 'string' ? {
|
|
1338
1382
|
target: configTransition
|
|
1339
1383
|
} : configTransition;
|
|
1340
|
-
const resolvedDelay =
|
|
1341
|
-
const eventType = mutateEntryExit(resolvedDelay
|
|
1384
|
+
const resolvedDelay = Number.isNaN(+delay) ? delay : +delay;
|
|
1385
|
+
const eventType = mutateEntryExit(resolvedDelay);
|
|
1342
1386
|
return toArray(resolvedTransition).map(transition => ({
|
|
1343
1387
|
...transition,
|
|
1344
1388
|
event: eventType,
|
|
@@ -2061,7 +2105,23 @@ function macrostep(state, event, actorScope, internalQueue = []) {
|
|
|
2061
2105
|
// Assume the state is at rest (no raised events)
|
|
2062
2106
|
// Determine the next state based on the next microstep
|
|
2063
2107
|
if (nextEvent.type !== XSTATE_INIT) {
|
|
2064
|
-
const
|
|
2108
|
+
const currentEvent = nextEvent;
|
|
2109
|
+
const isErr = isErrorActorEvent(currentEvent);
|
|
2110
|
+
const transitions = selectTransitions(currentEvent, nextState);
|
|
2111
|
+
if (isErr && !transitions.length) {
|
|
2112
|
+
// TODO: we should likely only allow transitions selected by very explicit descriptors
|
|
2113
|
+
// `*` shouldn't be matched, likely `xstate.error.*` shouldnt be either
|
|
2114
|
+
// similarly `xstate.error.actor.*` and `xstate.error.actor.todo.*` have to be considered too
|
|
2115
|
+
nextState = cloneMachineSnapshot(state, {
|
|
2116
|
+
status: 'error',
|
|
2117
|
+
error: currentEvent.data
|
|
2118
|
+
});
|
|
2119
|
+
states.push(nextState);
|
|
2120
|
+
return {
|
|
2121
|
+
state: nextState,
|
|
2122
|
+
microstates: states
|
|
2123
|
+
};
|
|
2124
|
+
}
|
|
2065
2125
|
nextState = microstep(transitions, state, actorScope, nextEvent, false, internalQueue);
|
|
2066
2126
|
states.push(nextState);
|
|
2067
2127
|
}
|
|
@@ -2338,7 +2398,6 @@ exports.getPersistedState = getPersistedState;
|
|
|
2338
2398
|
exports.getStateNodeByPath = getStateNodeByPath;
|
|
2339
2399
|
exports.getStateNodes = getStateNodes;
|
|
2340
2400
|
exports.interpret = interpret;
|
|
2341
|
-
exports.isErrorActorEvent = isErrorActorEvent;
|
|
2342
2401
|
exports.isInFinalState = isInFinalState;
|
|
2343
2402
|
exports.isMachineSnapshot = isMachineSnapshot;
|
|
2344
2403
|
exports.isStateId = isStateId;
|
|
@@ -203,14 +203,10 @@ function matchesState(parentStateId, childStateId) {
|
|
|
203
203
|
});
|
|
204
204
|
}
|
|
205
205
|
function toStatePath(stateId) {
|
|
206
|
-
|
|
207
|
-
|
|
208
|
-
return stateId;
|
|
209
|
-
}
|
|
210
|
-
return stateId.split(STATE_DELIMITER);
|
|
211
|
-
} catch (e) {
|
|
212
|
-
throw new Error(`'${stateId}' is not a valid state path.`);
|
|
206
|
+
if (isArray(stateId)) {
|
|
207
|
+
return stateId;
|
|
213
208
|
}
|
|
209
|
+
return stateId.split(STATE_DELIMITER);
|
|
214
210
|
}
|
|
215
211
|
function toStateValue(stateValue) {
|
|
216
212
|
if (isMachineSnapshot(stateValue)) {
|
|
@@ -452,7 +448,18 @@ class Actor {
|
|
|
452
448
|
}
|
|
453
449
|
}
|
|
454
450
|
_initState(persistedState) {
|
|
455
|
-
|
|
451
|
+
try {
|
|
452
|
+
this._state = persistedState ? this.logic.restoreState ? this.logic.restoreState(persistedState, this._actorScope) : persistedState : this.logic.getInitialState(this._actorScope, this.options?.input);
|
|
453
|
+
} catch (err) {
|
|
454
|
+
// if we get here then it means that we assign a value to this._state that is not of the correct type
|
|
455
|
+
// we can't get the true `TSnapshot & { status: 'error'; }`, it's impossible
|
|
456
|
+
// so right now this is a lie of sorts
|
|
457
|
+
this._state = {
|
|
458
|
+
status: 'error',
|
|
459
|
+
output: undefined,
|
|
460
|
+
error: err
|
|
461
|
+
};
|
|
462
|
+
}
|
|
456
463
|
}
|
|
457
464
|
update(snapshot, event) {
|
|
458
465
|
// Update state
|
|
@@ -461,17 +468,46 @@ class Actor {
|
|
|
461
468
|
// Execute deferred effects
|
|
462
469
|
let deferredFn;
|
|
463
470
|
while (deferredFn = this._deferred.shift()) {
|
|
464
|
-
deferredFn();
|
|
465
|
-
}
|
|
466
|
-
for (const observer of this.observers) {
|
|
467
471
|
try {
|
|
468
|
-
|
|
472
|
+
deferredFn();
|
|
469
473
|
} catch (err) {
|
|
470
|
-
|
|
474
|
+
// this error can only be caught when executing *initial* actions
|
|
475
|
+
// it's the only time when we call actions provided by the user through those deferreds
|
|
476
|
+
// when the actor is already running we always execute them synchronously while transitioning
|
|
477
|
+
// no "builtin deferred" should actually throw an error since they are either safe
|
|
478
|
+
// or the control flow is passed through the mailbox and errors should be caught by the `_process` used by the mailbox
|
|
479
|
+
this._deferred.length = 0;
|
|
480
|
+
this._state = {
|
|
481
|
+
...snapshot,
|
|
482
|
+
status: 'error',
|
|
483
|
+
error: err
|
|
484
|
+
};
|
|
471
485
|
}
|
|
472
486
|
}
|
|
473
487
|
switch (this._state.status) {
|
|
488
|
+
case 'active':
|
|
489
|
+
for (const observer of this.observers) {
|
|
490
|
+
try {
|
|
491
|
+
observer.next?.(snapshot);
|
|
492
|
+
} catch (err) {
|
|
493
|
+
reportUnhandledError(err);
|
|
494
|
+
}
|
|
495
|
+
}
|
|
496
|
+
break;
|
|
474
497
|
case 'done':
|
|
498
|
+
// next observers are meant to be notified about done snapshots
|
|
499
|
+
// this can be seen as something that is different from how observable work
|
|
500
|
+
// but with observables `complete` callback is called without any arguments
|
|
501
|
+
// it's more ergonomic for XState to treat a done snapshot as a "next" value
|
|
502
|
+
// and the completion event as something that is separate,
|
|
503
|
+
// something that merely follows emitting that done snapshot
|
|
504
|
+
for (const observer of this.observers) {
|
|
505
|
+
try {
|
|
506
|
+
observer.next?.(snapshot);
|
|
507
|
+
} catch (err) {
|
|
508
|
+
reportUnhandledError(err);
|
|
509
|
+
}
|
|
510
|
+
}
|
|
475
511
|
this._stopProcedure();
|
|
476
512
|
this._complete();
|
|
477
513
|
this._doneEvent = createDoneActorEvent(this.id, this._state.output);
|
|
@@ -480,11 +516,7 @@ class Actor {
|
|
|
480
516
|
}
|
|
481
517
|
break;
|
|
482
518
|
case 'error':
|
|
483
|
-
this._stopProcedure();
|
|
484
519
|
this._error(this._state.error);
|
|
485
|
-
if (this._parent) {
|
|
486
|
-
this.system._relay(this, this._parent, createErrorActorEvent(this.id, this._state.error));
|
|
487
|
-
}
|
|
488
520
|
break;
|
|
489
521
|
}
|
|
490
522
|
this.system._sendInspectionEvent({
|
|
@@ -574,7 +606,7 @@ class Actor {
|
|
|
574
606
|
this.subscribe({
|
|
575
607
|
next: snapshot => {
|
|
576
608
|
if (snapshot.status === 'active') {
|
|
577
|
-
this.
|
|
609
|
+
this.system._relay(this, this._parent, {
|
|
578
610
|
type: `xstate.snapshot.${this.id}`,
|
|
579
611
|
snapshot
|
|
580
612
|
});
|
|
@@ -603,18 +635,22 @@ class Actor {
|
|
|
603
635
|
// a state machine can be "done" upon initialization (it could reach a final state using initial microsteps)
|
|
604
636
|
// we still need to complete observers, flush deferreds etc
|
|
605
637
|
this.update(this._state, initEvent);
|
|
606
|
-
// fallthrough
|
|
607
|
-
case 'error':
|
|
608
638
|
// TODO: rethink cleanup of observers, mailbox, etc
|
|
609
639
|
return this;
|
|
640
|
+
case 'error':
|
|
641
|
+
this._error(this._state.error);
|
|
642
|
+
return this;
|
|
610
643
|
}
|
|
611
644
|
if (this.logic.start) {
|
|
612
645
|
try {
|
|
613
646
|
this.logic.start(this._state, this._actorScope);
|
|
614
647
|
} catch (err) {
|
|
615
|
-
this.
|
|
648
|
+
this._state = {
|
|
649
|
+
...this._state,
|
|
650
|
+
status: 'error',
|
|
651
|
+
error: err
|
|
652
|
+
};
|
|
616
653
|
this._error(err);
|
|
617
|
-
this._parent?.send(createErrorActorEvent(this.id, err));
|
|
618
654
|
return this;
|
|
619
655
|
}
|
|
620
656
|
}
|
|
@@ -630,7 +666,6 @@ class Actor {
|
|
|
630
666
|
return this;
|
|
631
667
|
}
|
|
632
668
|
_process(event) {
|
|
633
|
-
// TODO: reexamine what happens when an action (or a guard or smth) throws
|
|
634
669
|
let nextState;
|
|
635
670
|
let caughtError;
|
|
636
671
|
try {
|
|
@@ -645,9 +680,12 @@ class Actor {
|
|
|
645
680
|
const {
|
|
646
681
|
err
|
|
647
682
|
} = caughtError;
|
|
648
|
-
this.
|
|
683
|
+
this._state = {
|
|
684
|
+
...this._state,
|
|
685
|
+
status: 'error',
|
|
686
|
+
error: err
|
|
687
|
+
};
|
|
649
688
|
this._error(err);
|
|
650
|
-
this._parent?.send(createErrorActorEvent(this.id, err));
|
|
651
689
|
return;
|
|
652
690
|
}
|
|
653
691
|
this.update(nextState, event);
|
|
@@ -690,7 +728,7 @@ class Actor {
|
|
|
690
728
|
}
|
|
691
729
|
this.observers.clear();
|
|
692
730
|
}
|
|
693
|
-
|
|
731
|
+
_reportError(err) {
|
|
694
732
|
if (!this.observers.size) {
|
|
695
733
|
if (!this._parent) {
|
|
696
734
|
reportUnhandledError(err);
|
|
@@ -712,6 +750,18 @@ class Actor {
|
|
|
712
750
|
reportUnhandledError(err);
|
|
713
751
|
}
|
|
714
752
|
}
|
|
753
|
+
_error(err) {
|
|
754
|
+
this._stopProcedure();
|
|
755
|
+
this._reportError(err);
|
|
756
|
+
if (this._parent) {
|
|
757
|
+
this.system._relay(this, this._parent, createErrorActorEvent(this.id, err));
|
|
758
|
+
}
|
|
759
|
+
}
|
|
760
|
+
// TODO: atm children don't belong entirely to the actor so
|
|
761
|
+
// in a way - it's not even super aware of them
|
|
762
|
+
// so we can't stop them from here but we really should!
|
|
763
|
+
// right now, they are being stopped within the machine's transition
|
|
764
|
+
// but that could throw and leave us with "orphaned" active actors
|
|
715
765
|
_stopProcedure() {
|
|
716
766
|
if (this._processingStatus !== ProcessingStatus.Running) {
|
|
717
767
|
// Actor already stopped; do nothing
|
|
@@ -971,12 +1021,7 @@ function executeSpawn(actorScope, {
|
|
|
971
1021
|
if (actorRef._processingStatus === ProcessingStatus.Stopped) {
|
|
972
1022
|
return;
|
|
973
1023
|
}
|
|
974
|
-
|
|
975
|
-
actorRef.start?.();
|
|
976
|
-
} catch (err) {
|
|
977
|
-
actorScope.self.send(createErrorActorEvent(id, err));
|
|
978
|
-
return;
|
|
979
|
-
}
|
|
1024
|
+
actorRef.start();
|
|
980
1025
|
});
|
|
981
1026
|
}
|
|
982
1027
|
function spawnChild(...[src, {
|
|
@@ -1320,8 +1365,7 @@ function getDelayedTransitions(stateNode) {
|
|
|
1320
1365
|
return [];
|
|
1321
1366
|
}
|
|
1322
1367
|
const mutateEntryExit = (delay, i) => {
|
|
1323
|
-
const
|
|
1324
|
-
const afterEvent = createAfterEvent(delayRef, stateNode.id);
|
|
1368
|
+
const afterEvent = createAfterEvent(delay, stateNode.id);
|
|
1325
1369
|
const eventType = afterEvent.type;
|
|
1326
1370
|
stateNode.entry.push(raise(afterEvent, {
|
|
1327
1371
|
id: eventType,
|
|
@@ -1335,8 +1379,8 @@ function getDelayedTransitions(stateNode) {
|
|
|
1335
1379
|
const resolvedTransition = typeof configTransition === 'string' ? {
|
|
1336
1380
|
target: configTransition
|
|
1337
1381
|
} : configTransition;
|
|
1338
|
-
const resolvedDelay =
|
|
1339
|
-
const eventType = mutateEntryExit(resolvedDelay
|
|
1382
|
+
const resolvedDelay = Number.isNaN(+delay) ? delay : +delay;
|
|
1383
|
+
const eventType = mutateEntryExit(resolvedDelay);
|
|
1340
1384
|
return toArray(resolvedTransition).map(transition => ({
|
|
1341
1385
|
...transition,
|
|
1342
1386
|
event: eventType,
|
|
@@ -2059,7 +2103,23 @@ function macrostep(state, event, actorScope, internalQueue = []) {
|
|
|
2059
2103
|
// Assume the state is at rest (no raised events)
|
|
2060
2104
|
// Determine the next state based on the next microstep
|
|
2061
2105
|
if (nextEvent.type !== XSTATE_INIT) {
|
|
2062
|
-
const
|
|
2106
|
+
const currentEvent = nextEvent;
|
|
2107
|
+
const isErr = isErrorActorEvent(currentEvent);
|
|
2108
|
+
const transitions = selectTransitions(currentEvent, nextState);
|
|
2109
|
+
if (isErr && !transitions.length) {
|
|
2110
|
+
// TODO: we should likely only allow transitions selected by very explicit descriptors
|
|
2111
|
+
// `*` shouldn't be matched, likely `xstate.error.*` shouldnt be either
|
|
2112
|
+
// similarly `xstate.error.actor.*` and `xstate.error.actor.todo.*` have to be considered too
|
|
2113
|
+
nextState = cloneMachineSnapshot(state, {
|
|
2114
|
+
status: 'error',
|
|
2115
|
+
error: currentEvent.data
|
|
2116
|
+
});
|
|
2117
|
+
states.push(nextState);
|
|
2118
|
+
return {
|
|
2119
|
+
state: nextState,
|
|
2120
|
+
microstates: states
|
|
2121
|
+
};
|
|
2122
|
+
}
|
|
2063
2123
|
nextState = microstep(transitions, state, actorScope, nextEvent, false, internalQueue);
|
|
2064
2124
|
states.push(nextState);
|
|
2065
2125
|
}
|
|
@@ -2308,4 +2368,4 @@ function raise(eventOrExpr, options) {
|
|
|
2308
2368
|
return raise;
|
|
2309
2369
|
}
|
|
2310
2370
|
|
|
2311
|
-
export { $$ACTOR_TYPE as $,
|
|
2371
|
+
export { $$ACTOR_TYPE as $, Actor as A, interpret as B, isMachineSnapshot as C, matchesState as D, pathToStateValue as E, toObserver as F, getAllOwnEventDescriptors as G, and as H, not as I, or as J, stateIn as K, cancel as L, raise as M, NULL_EVENT as N, spawnChild as O, stop as P, stopChild as Q, ProcessingStatus as R, STATE_DELIMITER as S, cloneMachineSnapshot as T, XSTATE_ERROR as U, createErrorActorEvent as V, XSTATE_STOP as X, toTransitionConfigArray as a, formatTransition as b, createInvokeId as c, formatInitialTransition as d, evaluateGuard as e, formatTransitions as f, getDelayedTransitions as g, getCandidates as h, getAllStateNodes as i, getStateNodes as j, createMachineSnapshot as k, isInFinalState as l, mapValues as m, macrostep as n, transitionNode as o, resolveActionsAndContext as p, createInitEvent as q, resolveStateValue as r, microstep as s, toArray as t, getInitialStateNodes as u, isStateId as v, getStateNodeByPath as w, getPersistedState as x, resolveReferencedActor as y, createActor as z };
|