xstate 5.0.0-beta.20 → 5.0.0-beta.22
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/dev/dist/xstate-dev.umd.min.js.map +1 -1
- package/dist/{actions-d1c41ed3.development.cjs.js → actions-4b70fc8d.development.cjs.js} +174 -82
- package/dist/{actions-069d9805.cjs.js → actions-8f2e997e.cjs.js} +172 -83
- package/dist/{actions-b299d008.development.esm.js → actions-d4305983.development.esm.js} +171 -82
- package/dist/{actions-a8a9433c.esm.js → actions-fb7384f8.esm.js} +169 -83
- package/dist/declarations/src/Machine.d.ts +2 -2
- package/dist/declarations/src/State.d.ts +4 -7
- package/dist/declarations/src/StateMachine.d.ts +7 -6
- package/dist/declarations/src/StateNode.d.ts +3 -3
- package/dist/declarations/src/actions/send.d.ts +1 -1
- package/dist/declarations/src/actions/stop.d.ts +1 -1
- package/dist/declarations/src/actions.d.ts +2 -2
- package/dist/declarations/src/actors/callback.d.ts +4 -4
- package/dist/declarations/src/actors/observable.d.ts +7 -4
- package/dist/declarations/src/actors/promise.d.ts +4 -4
- package/dist/declarations/src/dev/index.d.ts +6 -6
- package/dist/declarations/src/index.d.ts +3 -2
- package/dist/declarations/src/interpreter.d.ts +30 -16
- package/dist/declarations/src/types.d.ts +52 -33
- package/dist/declarations/src/utils.d.ts +2 -2
- package/dist/xstate.cjs.js +17 -14
- package/dist/xstate.cjs.mjs +3 -1
- package/dist/xstate.development.cjs.js +17 -14
- package/dist/xstate.development.cjs.mjs +3 -1
- package/dist/xstate.development.esm.js +14 -13
- package/dist/xstate.esm.js +14 -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
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"xstate-dev.umd.min.js","sources":["../../src/dev/index.ts"],"sourcesContent":["import isDevelopment from '#is-development';\nimport {
|
|
1
|
+
{"version":3,"file":"xstate-dev.umd.min.js","sources":["../../src/dev/index.ts"],"sourcesContent":["import isDevelopment from '#is-development';\nimport { AnyActor, DevToolsAdapter } from '../types.ts';\n\ninterface DevInterface {\n services: Set<AnyActor>;\n register(service: AnyActor): void;\n onRegister(listener: ServiceListener): void;\n}\ntype ServiceListener = (service: AnyActor) => void;\n\nexport interface XStateDevInterface {\n register: (service: AnyActor) => void;\n unregister: (service: AnyActor) => void;\n onRegister: (listener: ServiceListener) => {\n unsubscribe: () => void;\n };\n services: Set<AnyActor>;\n}\n\n// From https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/globalThis\nexport function getGlobal(): typeof globalThis | undefined {\n if (typeof globalThis !== 'undefined') {\n return globalThis;\n }\n if (typeof self !== 'undefined') {\n return self;\n }\n if (typeof window !== 'undefined') {\n return window;\n }\n if (typeof global !== 'undefined') {\n return global;\n }\n if (isDevelopment) {\n console.warn(\n 'XState could not find a global object in this environment. Please let the maintainers know and raise an issue here: https://github.com/statelyai/xstate/issues'\n );\n }\n}\n\nfunction getDevTools(): DevInterface | undefined {\n const w = getGlobal();\n if (!!(w as any).__xstate__) {\n return (w as any).__xstate__;\n }\n\n return undefined;\n}\n\nexport function registerService(service: AnyActor) {\n if (typeof window === 'undefined') {\n return;\n }\n\n const devTools = getDevTools();\n\n if (devTools) {\n devTools.register(service);\n }\n}\n\nexport const devToolsAdapter: DevToolsAdapter = (service) => {\n if (typeof window === 'undefined') {\n return;\n }\n\n const devTools = getDevTools();\n\n if (devTools) {\n devTools.register(service);\n }\n};\n"],"names":["getGlobal","globalThis","self","window","getDevTools","w","__xstate__","service","devTools","register"],"mappings":"iPAoBO,SAASA,IACd,MAA0B,oBAAfC,WACFA,WAEW,oBAATC,KACFA,KAGAC,MAUX,CAEA,SAASC,IACP,MAAMC,EAAIL,IACV,GAAOK,EAAUC,WACf,OAAQD,EAAUC,UAItB,mBAciDC,IAK/C,MAAMC,EAAWJ,IAEbI,GACFA,EAASC,SAASF,EACpB,kCArBK,SAAyBA,GAK9B,MAAMC,EAAWJ,IAEbI,GACFA,EAASC,SAASF,EAEtB"}
|
|
@@ -2,6 +2,18 @@
|
|
|
2
2
|
|
|
3
3
|
var dev_dist_xstateDev = require('../dev/dist/xstate-dev.development.cjs.js');
|
|
4
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
|
+
|
|
5
17
|
// https://github.com/microsoft/TypeScript/issues/23182#issuecomment-379091887
|
|
6
18
|
|
|
7
19
|
/**
|
|
@@ -422,27 +434,18 @@ function toArray(value) {
|
|
|
422
434
|
}
|
|
423
435
|
return toArrayStrict(value);
|
|
424
436
|
}
|
|
425
|
-
function mapContext(mapper, context, event) {
|
|
437
|
+
function mapContext(mapper, context, event, self) {
|
|
426
438
|
if (typeof mapper === 'function') {
|
|
427
439
|
return mapper({
|
|
428
440
|
context,
|
|
429
|
-
event
|
|
441
|
+
event,
|
|
442
|
+
self
|
|
430
443
|
});
|
|
431
444
|
}
|
|
432
|
-
|
|
433
|
-
|
|
434
|
-
context,
|
|
435
|
-
event
|
|
436
|
-
};
|
|
437
|
-
for (const key of Object.keys(mapper)) {
|
|
438
|
-
const subMapper = mapper[key];
|
|
439
|
-
if (typeof subMapper === 'function') {
|
|
440
|
-
result[key] = subMapper(args);
|
|
441
|
-
} else {
|
|
442
|
-
result[key] = subMapper;
|
|
443
|
-
}
|
|
445
|
+
if (typeof mapper === 'object' && Object.values(mapper).some(val => typeof val === 'function')) {
|
|
446
|
+
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('')}`);
|
|
444
447
|
}
|
|
445
|
-
return
|
|
448
|
+
return mapper;
|
|
446
449
|
}
|
|
447
450
|
function isPromiseLike(value) {
|
|
448
451
|
if (value instanceof Promise) {
|
|
@@ -494,13 +497,12 @@ function toInvokeConfig(invocable, id) {
|
|
|
494
497
|
};
|
|
495
498
|
}
|
|
496
499
|
function toObserver(nextHandler, errorHandler, completionHandler) {
|
|
497
|
-
const noop = () => {};
|
|
498
500
|
const isObserver = typeof nextHandler === 'object';
|
|
499
|
-
const self = isObserver ? nextHandler :
|
|
501
|
+
const self = isObserver ? nextHandler : undefined;
|
|
500
502
|
return {
|
|
501
|
-
next: (
|
|
502
|
-
error: (
|
|
503
|
-
complete: (
|
|
503
|
+
next: (isObserver ? nextHandler.next : nextHandler)?.bind(self),
|
|
504
|
+
error: (isObserver ? nextHandler.error : errorHandler)?.bind(self),
|
|
505
|
+
complete: (isObserver ? nextHandler.complete : completionHandler)?.bind(self)
|
|
504
506
|
};
|
|
505
507
|
}
|
|
506
508
|
function createInvokeId(stateNodeId, index) {
|
|
@@ -514,7 +516,7 @@ function resolveReferencedActor(referenced) {
|
|
|
514
516
|
}
|
|
515
517
|
|
|
516
518
|
function fromCallback(invokeCallback) {
|
|
517
|
-
|
|
519
|
+
return {
|
|
518
520
|
config: invokeCallback,
|
|
519
521
|
start: (_state, {
|
|
520
522
|
self
|
|
@@ -580,19 +582,20 @@ function fromCallback(invokeCallback) {
|
|
|
580
582
|
},
|
|
581
583
|
getSnapshot: () => undefined,
|
|
582
584
|
getPersistedState: ({
|
|
583
|
-
input
|
|
584
|
-
|
|
585
|
+
input,
|
|
586
|
+
canceled
|
|
587
|
+
}) => ({
|
|
588
|
+
input,
|
|
589
|
+
canceled
|
|
590
|
+
})
|
|
585
591
|
};
|
|
586
|
-
return logic;
|
|
587
592
|
}
|
|
588
593
|
|
|
589
594
|
function fromObservable(observableCreator) {
|
|
590
595
|
const nextEventType = '$$xstate.next';
|
|
591
596
|
const errorEventType = '$$xstate.error';
|
|
592
597
|
const completeEventType = '$$xstate.complete';
|
|
593
|
-
|
|
594
|
-
// TODO: add event types
|
|
595
|
-
const logic = {
|
|
598
|
+
return {
|
|
596
599
|
config: observableCreator,
|
|
597
600
|
transition: (state, event, {
|
|
598
601
|
self,
|
|
@@ -622,6 +625,7 @@ function fromObservable(observableCreator) {
|
|
|
622
625
|
status: 'error',
|
|
623
626
|
input: undefined,
|
|
624
627
|
data: event.data,
|
|
628
|
+
// TODO: if we keep this as `data` we should reflect this in the type
|
|
625
629
|
subscription: undefined
|
|
626
630
|
};
|
|
627
631
|
case completeEventType:
|
|
@@ -699,7 +703,6 @@ function fromObservable(observableCreator) {
|
|
|
699
703
|
subscription: undefined
|
|
700
704
|
})
|
|
701
705
|
};
|
|
702
|
-
return logic;
|
|
703
706
|
}
|
|
704
707
|
|
|
705
708
|
/**
|
|
@@ -716,7 +719,7 @@ function fromEventObservable(lazyObservable) {
|
|
|
716
719
|
const completeEventType = '$$xstate.complete';
|
|
717
720
|
|
|
718
721
|
// TODO: event types
|
|
719
|
-
|
|
722
|
+
return {
|
|
720
723
|
config: lazyObservable,
|
|
721
724
|
transition: (state, event) => {
|
|
722
725
|
if (state.status !== 'active') {
|
|
@@ -729,6 +732,7 @@ function fromEventObservable(lazyObservable) {
|
|
|
729
732
|
status: 'error',
|
|
730
733
|
input: undefined,
|
|
731
734
|
data: event.data,
|
|
735
|
+
// TODO: if we keep this as `data` we should reflect this in the type
|
|
732
736
|
subscription: undefined
|
|
733
737
|
};
|
|
734
738
|
case completeEventType:
|
|
@@ -803,7 +807,6 @@ function fromEventObservable(lazyObservable) {
|
|
|
803
807
|
subscription: undefined
|
|
804
808
|
})
|
|
805
809
|
};
|
|
806
|
-
return logic;
|
|
807
810
|
}
|
|
808
811
|
|
|
809
812
|
const resolveEventType = '$$xstate.resolve';
|
|
@@ -831,6 +834,7 @@ promiseCreator) {
|
|
|
831
834
|
...state,
|
|
832
835
|
status: 'error',
|
|
833
836
|
data: event.data,
|
|
837
|
+
// TODO: if we keep this as `data` we should reflect this in the type
|
|
834
838
|
input: undefined
|
|
835
839
|
};
|
|
836
840
|
case stopSignalType:
|
|
@@ -937,7 +941,20 @@ function toActorRef(actorRefLike) {
|
|
|
937
941
|
}
|
|
938
942
|
const emptyLogic = fromTransition(_ => undefined, undefined);
|
|
939
943
|
function createEmptyActor() {
|
|
940
|
-
return
|
|
944
|
+
return createActor(emptyLogic);
|
|
945
|
+
}
|
|
946
|
+
|
|
947
|
+
/**
|
|
948
|
+
* This function makes sure that unhandled errors are thrown in a separate macrotask.
|
|
949
|
+
* It allows those errors to be detected by global error handlers and reported to bug tracking services
|
|
950
|
+
* without interrupting our own stack of execution.
|
|
951
|
+
*
|
|
952
|
+
* @param err error to be thrown
|
|
953
|
+
*/
|
|
954
|
+
function reportUnhandledError(err) {
|
|
955
|
+
setTimeout(() => {
|
|
956
|
+
throw err;
|
|
957
|
+
});
|
|
941
958
|
}
|
|
942
959
|
|
|
943
960
|
function createSystem() {
|
|
@@ -980,6 +997,11 @@ let ActorStatus = /*#__PURE__*/function (ActorStatus) {
|
|
|
980
997
|
ActorStatus[ActorStatus["Stopped"] = 2] = "Stopped";
|
|
981
998
|
return ActorStatus;
|
|
982
999
|
}({});
|
|
1000
|
+
|
|
1001
|
+
/**
|
|
1002
|
+
* @deprecated Use `ActorStatus` instead.
|
|
1003
|
+
*/
|
|
1004
|
+
const InterpreterStatus = ActorStatus;
|
|
983
1005
|
const defaultOptions = {
|
|
984
1006
|
deferEvents: true,
|
|
985
1007
|
clock: {
|
|
@@ -993,9 +1015,9 @@ const defaultOptions = {
|
|
|
993
1015
|
logger: console.log.bind(console),
|
|
994
1016
|
devTools: false
|
|
995
1017
|
};
|
|
996
|
-
class
|
|
1018
|
+
class Actor {
|
|
997
1019
|
/**
|
|
998
|
-
* The current state of the
|
|
1020
|
+
* The current internal state of the actor.
|
|
999
1021
|
*/
|
|
1000
1022
|
|
|
1001
1023
|
/**
|
|
@@ -1019,10 +1041,10 @@ class Interpreter {
|
|
|
1019
1041
|
*/
|
|
1020
1042
|
|
|
1021
1043
|
/**
|
|
1022
|
-
* Creates a new
|
|
1044
|
+
* Creates a new actor instance for the given logic with the provided options, if any.
|
|
1023
1045
|
*
|
|
1024
|
-
* @param logic The logic to
|
|
1025
|
-
* @param options
|
|
1046
|
+
* @param logic The logic to create an actor from
|
|
1047
|
+
* @param options Actor options
|
|
1026
1048
|
*/
|
|
1027
1049
|
constructor(logic, options) {
|
|
1028
1050
|
this.logic = logic;
|
|
@@ -1086,7 +1108,7 @@ class Interpreter {
|
|
|
1086
1108
|
}
|
|
1087
1109
|
};
|
|
1088
1110
|
|
|
1089
|
-
// Ensure that the send method is bound to this
|
|
1111
|
+
// Ensure that the send method is bound to this Actor instance
|
|
1090
1112
|
// if destructured
|
|
1091
1113
|
this.send = this.send.bind(this);
|
|
1092
1114
|
this._initState();
|
|
@@ -1108,29 +1130,38 @@ class Interpreter {
|
|
|
1108
1130
|
deferredFn();
|
|
1109
1131
|
}
|
|
1110
1132
|
for (const observer of this.observers) {
|
|
1111
|
-
|
|
1133
|
+
// TODO: should observers be notified in case of the error?
|
|
1134
|
+
try {
|
|
1135
|
+
observer.next?.(snapshot);
|
|
1136
|
+
} catch (err) {
|
|
1137
|
+
reportUnhandledError(err);
|
|
1138
|
+
}
|
|
1112
1139
|
}
|
|
1113
1140
|
const status = this.logic.getStatus?.(state);
|
|
1114
1141
|
switch (status?.status) {
|
|
1115
1142
|
case 'done':
|
|
1116
1143
|
this._stopProcedure();
|
|
1144
|
+
this._complete();
|
|
1117
1145
|
this._doneEvent = doneInvoke(this.id, status.data);
|
|
1118
1146
|
this._parent?.send(this._doneEvent);
|
|
1119
|
-
this._complete();
|
|
1120
1147
|
break;
|
|
1121
1148
|
case 'error':
|
|
1122
1149
|
this._stopProcedure();
|
|
1123
|
-
this._parent?.send(error(this.id, status.data));
|
|
1124
1150
|
this._error(status.data);
|
|
1151
|
+
this._parent?.send(error(this.id, status.data));
|
|
1125
1152
|
break;
|
|
1126
1153
|
}
|
|
1127
1154
|
}
|
|
1128
1155
|
subscribe(nextListenerOrObserver, errorListener, completeListener) {
|
|
1129
1156
|
const observer = toObserver(nextListenerOrObserver, errorListener, completeListener);
|
|
1130
|
-
this.
|
|
1131
|
-
|
|
1132
|
-
|
|
1133
|
-
|
|
1157
|
+
if (this.status !== ActorStatus.Stopped) {
|
|
1158
|
+
this.observers.add(observer);
|
|
1159
|
+
} else {
|
|
1160
|
+
try {
|
|
1161
|
+
observer.complete?.();
|
|
1162
|
+
} catch (err) {
|
|
1163
|
+
reportUnhandledError(err);
|
|
1164
|
+
}
|
|
1134
1165
|
}
|
|
1135
1166
|
return {
|
|
1136
1167
|
unsubscribe: () => {
|
|
@@ -1140,7 +1171,7 @@ class Interpreter {
|
|
|
1140
1171
|
}
|
|
1141
1172
|
|
|
1142
1173
|
/**
|
|
1143
|
-
* Starts the
|
|
1174
|
+
* Starts the Actor from the initial state
|
|
1144
1175
|
*/
|
|
1145
1176
|
start() {
|
|
1146
1177
|
if (this.status === ActorStatus.Running) {
|
|
@@ -1152,8 +1183,26 @@ class Interpreter {
|
|
|
1152
1183
|
this.system._set(this._systemId, this);
|
|
1153
1184
|
}
|
|
1154
1185
|
this.status = ActorStatus.Running;
|
|
1186
|
+
const status = this.logic.getStatus?.(this._state);
|
|
1187
|
+
switch (status?.status) {
|
|
1188
|
+
case 'done':
|
|
1189
|
+
// a state machine can be "done" upon intialization (it could reach a final state using initial microsteps)
|
|
1190
|
+
// we still need to complete observers, flush deferreds etc
|
|
1191
|
+
this.update(this._state);
|
|
1192
|
+
// fallthrough
|
|
1193
|
+
case 'error':
|
|
1194
|
+
// TODO: rethink cleanup of observers, mailbox, etc
|
|
1195
|
+
return this;
|
|
1196
|
+
}
|
|
1155
1197
|
if (this.logic.start) {
|
|
1156
|
-
|
|
1198
|
+
try {
|
|
1199
|
+
this.logic.start(this._state, this._actorContext);
|
|
1200
|
+
} catch (err) {
|
|
1201
|
+
this._stopProcedure();
|
|
1202
|
+
this._error(err);
|
|
1203
|
+
this._parent?.send(error(this.id, err));
|
|
1204
|
+
return this;
|
|
1205
|
+
}
|
|
1157
1206
|
}
|
|
1158
1207
|
|
|
1159
1208
|
// TODO: this notifies all subscribers but usually this is redundant
|
|
@@ -1167,23 +1216,30 @@ class Interpreter {
|
|
|
1167
1216
|
return this;
|
|
1168
1217
|
}
|
|
1169
1218
|
_process(event) {
|
|
1219
|
+
// TODO: reexamine what happens when an action (or a guard or smth) throws
|
|
1220
|
+
let nextState;
|
|
1221
|
+
let caughtError;
|
|
1170
1222
|
try {
|
|
1171
|
-
|
|
1172
|
-
this.update(nextState);
|
|
1173
|
-
if (event.type === stopSignalType) {
|
|
1174
|
-
this._stopProcedure();
|
|
1175
|
-
this._complete();
|
|
1176
|
-
}
|
|
1223
|
+
nextState = this.logic.transition(this._state, event, this._actorContext);
|
|
1177
1224
|
} catch (err) {
|
|
1178
|
-
//
|
|
1179
|
-
|
|
1180
|
-
|
|
1181
|
-
|
|
1182
|
-
|
|
1183
|
-
|
|
1184
|
-
|
|
1185
|
-
|
|
1186
|
-
}
|
|
1225
|
+
// we wrap it in a box so we can rethrow it later even if falsy value gets caught here
|
|
1226
|
+
caughtError = {
|
|
1227
|
+
err
|
|
1228
|
+
};
|
|
1229
|
+
}
|
|
1230
|
+
if (caughtError) {
|
|
1231
|
+
const {
|
|
1232
|
+
err
|
|
1233
|
+
} = caughtError;
|
|
1234
|
+
this._stopProcedure();
|
|
1235
|
+
this._error(err);
|
|
1236
|
+
this._parent?.send(error(this.id, err));
|
|
1237
|
+
return;
|
|
1238
|
+
}
|
|
1239
|
+
this.update(nextState);
|
|
1240
|
+
if (event.type === stopSignalType) {
|
|
1241
|
+
this._stopProcedure();
|
|
1242
|
+
this._complete();
|
|
1187
1243
|
}
|
|
1188
1244
|
}
|
|
1189
1245
|
_stop() {
|
|
@@ -1202,7 +1258,7 @@ class Interpreter {
|
|
|
1202
1258
|
}
|
|
1203
1259
|
|
|
1204
1260
|
/**
|
|
1205
|
-
* Stops the
|
|
1261
|
+
* Stops the Actor and unsubscribe all listeners.
|
|
1206
1262
|
*/
|
|
1207
1263
|
stop() {
|
|
1208
1264
|
if (this._parent) {
|
|
@@ -1212,19 +1268,39 @@ class Interpreter {
|
|
|
1212
1268
|
}
|
|
1213
1269
|
_complete() {
|
|
1214
1270
|
for (const observer of this.observers) {
|
|
1215
|
-
|
|
1271
|
+
try {
|
|
1272
|
+
observer.complete?.();
|
|
1273
|
+
} catch (err) {
|
|
1274
|
+
reportUnhandledError(err);
|
|
1275
|
+
}
|
|
1216
1276
|
}
|
|
1217
1277
|
this.observers.clear();
|
|
1218
1278
|
}
|
|
1219
|
-
_error(
|
|
1279
|
+
_error(err) {
|
|
1280
|
+
if (!this.observers.size) {
|
|
1281
|
+
if (!this._parent) {
|
|
1282
|
+
reportUnhandledError(err);
|
|
1283
|
+
}
|
|
1284
|
+
return;
|
|
1285
|
+
}
|
|
1286
|
+
let reportError = false;
|
|
1220
1287
|
for (const observer of this.observers) {
|
|
1221
|
-
observer.error
|
|
1288
|
+
const errorListener = observer.error;
|
|
1289
|
+
reportError ||= !errorListener;
|
|
1290
|
+
try {
|
|
1291
|
+
errorListener?.(err);
|
|
1292
|
+
} catch (err2) {
|
|
1293
|
+
reportUnhandledError(err2);
|
|
1294
|
+
}
|
|
1222
1295
|
}
|
|
1223
1296
|
this.observers.clear();
|
|
1297
|
+
if (reportError) {
|
|
1298
|
+
reportUnhandledError(err);
|
|
1299
|
+
}
|
|
1224
1300
|
}
|
|
1225
1301
|
_stopProcedure() {
|
|
1226
1302
|
if (this.status !== ActorStatus.Running) {
|
|
1227
|
-
//
|
|
1303
|
+
// Actor already stopped; do nothing
|
|
1228
1304
|
return this;
|
|
1229
1305
|
}
|
|
1230
1306
|
|
|
@@ -1246,7 +1322,7 @@ class Interpreter {
|
|
|
1246
1322
|
}
|
|
1247
1323
|
|
|
1248
1324
|
/**
|
|
1249
|
-
* Sends an event to the running
|
|
1325
|
+
* Sends an event to the running Actor to trigger a transition.
|
|
1250
1326
|
*
|
|
1251
1327
|
* @param event The event to send
|
|
1252
1328
|
*/
|
|
@@ -1322,17 +1398,28 @@ class Interpreter {
|
|
|
1322
1398
|
}
|
|
1323
1399
|
|
|
1324
1400
|
/**
|
|
1325
|
-
* Creates a new
|
|
1401
|
+
* Creates a new `ActorRef` instance for the given machine with the provided options, if any.
|
|
1326
1402
|
*
|
|
1327
|
-
* @param machine The machine to
|
|
1328
|
-
* @param options
|
|
1403
|
+
* @param machine The machine to create an actor from
|
|
1404
|
+
* @param options `ActorRef` options
|
|
1329
1405
|
*/
|
|
1330
1406
|
|
|
1331
|
-
function
|
|
1332
|
-
const interpreter = new
|
|
1407
|
+
function createActor(logic, options) {
|
|
1408
|
+
const interpreter = new Actor(logic, options);
|
|
1333
1409
|
return interpreter;
|
|
1334
1410
|
}
|
|
1335
1411
|
|
|
1412
|
+
/**
|
|
1413
|
+
* Creates a new Interpreter instance for the given machine with the provided options, if any.
|
|
1414
|
+
*
|
|
1415
|
+
* @deprecated Use `createActor` instead
|
|
1416
|
+
*/
|
|
1417
|
+
const interpret = createActor;
|
|
1418
|
+
|
|
1419
|
+
/**
|
|
1420
|
+
* @deprecated Use `Actor` instead.
|
|
1421
|
+
*/
|
|
1422
|
+
|
|
1336
1423
|
function resolve$6(actorContext, state, actionArgs, {
|
|
1337
1424
|
id,
|
|
1338
1425
|
systemId,
|
|
@@ -1344,7 +1431,7 @@ function resolve$6(actorContext, state, actionArgs, {
|
|
|
1344
1431
|
if (referenced) {
|
|
1345
1432
|
// TODO: inline `input: undefined` should win over the referenced one
|
|
1346
1433
|
const configuredInput = input || referenced.input;
|
|
1347
|
-
actorRef =
|
|
1434
|
+
actorRef = createActor(referenced.src, {
|
|
1348
1435
|
id,
|
|
1349
1436
|
src,
|
|
1350
1437
|
parent: actorContext?.self,
|
|
@@ -1553,10 +1640,10 @@ function toGuardDefinition(guardConfig, getPredicate) {
|
|
|
1553
1640
|
}
|
|
1554
1641
|
}
|
|
1555
1642
|
|
|
1556
|
-
function getOutput(configuration, context, event) {
|
|
1643
|
+
function getOutput(configuration, context, event, self) {
|
|
1557
1644
|
const machine = configuration[0].machine;
|
|
1558
1645
|
const finalChildStateNode = configuration.find(stateNode => stateNode.type === 'final' && stateNode.parent === machine.root);
|
|
1559
|
-
return finalChildStateNode && finalChildStateNode.output ? mapContext(finalChildStateNode.output, context, event) : undefined;
|
|
1646
|
+
return finalChildStateNode && finalChildStateNode.output ? mapContext(finalChildStateNode.output, context, event, self) : undefined;
|
|
1560
1647
|
}
|
|
1561
1648
|
const isAtomicStateNode = stateNode => stateNode.type === 'atomic' || stateNode.type === 'final';
|
|
1562
1649
|
function getChildren(stateNode) {
|
|
@@ -2183,7 +2270,7 @@ function microstepProcedure(transitions, currentState, mutConfiguration, event,
|
|
|
2183
2270
|
actions.push(...filteredTransitions.flatMap(t => t.actions));
|
|
2184
2271
|
|
|
2185
2272
|
// Enter states
|
|
2186
|
-
enterStates(event, filteredTransitions, mutConfiguration, actions, internalQueue, currentState, historyValue, isInitial);
|
|
2273
|
+
enterStates(event, filteredTransitions, mutConfiguration, actions, internalQueue, currentState, historyValue, isInitial, actorCtx);
|
|
2187
2274
|
const nextConfiguration = [...mutConfiguration];
|
|
2188
2275
|
const done = isInFinalState(nextConfiguration);
|
|
2189
2276
|
if (done) {
|
|
@@ -2192,7 +2279,7 @@ function microstepProcedure(transitions, currentState, mutConfiguration, event,
|
|
|
2192
2279
|
}
|
|
2193
2280
|
try {
|
|
2194
2281
|
const nextState = resolveActionsAndContext(actions, event, currentState, actorCtx);
|
|
2195
|
-
const output = done ? getOutput(nextConfiguration, nextState.context, event) : undefined;
|
|
2282
|
+
const output = done ? getOutput(nextConfiguration, nextState.context, event, actorCtx.self) : undefined;
|
|
2196
2283
|
internalQueue.push(...nextState._internalQueue);
|
|
2197
2284
|
return cloneState(currentState, {
|
|
2198
2285
|
configuration: nextConfiguration,
|
|
@@ -2209,7 +2296,7 @@ function microstepProcedure(transitions, currentState, mutConfiguration, event,
|
|
|
2209
2296
|
throw e;
|
|
2210
2297
|
}
|
|
2211
2298
|
}
|
|
2212
|
-
function enterStates(event, filteredTransitions, mutConfiguration, actions, internalQueue, currentState, historyValue, isInitial) {
|
|
2299
|
+
function enterStates(event, filteredTransitions, mutConfiguration, actions, internalQueue, currentState, historyValue, isInitial, actorContext) {
|
|
2213
2300
|
const statesToEnter = new Set();
|
|
2214
2301
|
const statesForDefaultEntry = new Set();
|
|
2215
2302
|
computeEntrySet(filteredTransitions, historyValue, statesForDefaultEntry, statesToEnter);
|
|
@@ -2237,7 +2324,7 @@ function enterStates(event, filteredTransitions, mutConfiguration, actions, inte
|
|
|
2237
2324
|
if (!parent.parent) {
|
|
2238
2325
|
continue;
|
|
2239
2326
|
}
|
|
2240
|
-
internalQueue.push(done(parent.id, stateNodeToEnter.output ? mapContext(stateNodeToEnter.output, currentState.context, event) : undefined));
|
|
2327
|
+
internalQueue.push(done(parent.id, stateNodeToEnter.output ? mapContext(stateNodeToEnter.output, currentState.context, event, actorContext.self) : undefined));
|
|
2241
2328
|
if (parent.parent) {
|
|
2242
2329
|
const grandparent = parent.parent;
|
|
2243
2330
|
if (grandparent.type === 'parallel') {
|
|
@@ -2560,6 +2647,7 @@ class State {
|
|
|
2560
2647
|
this.value = void 0;
|
|
2561
2648
|
this.done = void 0;
|
|
2562
2649
|
this.output = void 0;
|
|
2650
|
+
this.error = void 0;
|
|
2563
2651
|
this.context = void 0;
|
|
2564
2652
|
this.historyValue = {};
|
|
2565
2653
|
this._internalQueue = void 0;
|
|
@@ -2576,6 +2664,7 @@ class State {
|
|
|
2576
2664
|
this.tags = new Set(flatten(this.configuration.map(sn => sn.tags)));
|
|
2577
2665
|
this.done = config.done ?? false;
|
|
2578
2666
|
this.output = config.output;
|
|
2667
|
+
this.error = config.error;
|
|
2579
2668
|
}
|
|
2580
2669
|
|
|
2581
2670
|
/**
|
|
@@ -2797,7 +2886,7 @@ function createSpawner(actorContext, {
|
|
|
2797
2886
|
const input = 'input' in options ? options.input : referenced.input;
|
|
2798
2887
|
|
|
2799
2888
|
// TODO: this should also receive `src`
|
|
2800
|
-
const actor =
|
|
2889
|
+
const actor = createActor(referenced.src, {
|
|
2801
2890
|
id: options.id,
|
|
2802
2891
|
parent: actorContext.self,
|
|
2803
2892
|
input: typeof input === 'function' ? input({
|
|
@@ -2811,7 +2900,7 @@ function createSpawner(actorContext, {
|
|
|
2811
2900
|
return actor;
|
|
2812
2901
|
} else {
|
|
2813
2902
|
// TODO: this should also receive `src`
|
|
2814
|
-
return
|
|
2903
|
+
return createActor(src, {
|
|
2815
2904
|
id: options.id,
|
|
2816
2905
|
parent: actorContext.self,
|
|
2817
2906
|
input: options.input,
|
|
@@ -3046,9 +3135,10 @@ function createInitEvent(input) {
|
|
|
3046
3135
|
};
|
|
3047
3136
|
}
|
|
3048
3137
|
|
|
3138
|
+
exports.Actor = Actor;
|
|
3049
3139
|
exports.ActorStatus = ActorStatus;
|
|
3050
3140
|
exports.ConstantPrefix = ConstantPrefix;
|
|
3051
|
-
exports.
|
|
3141
|
+
exports.InterpreterStatus = InterpreterStatus;
|
|
3052
3142
|
exports.NULL_EVENT = NULL_EVENT;
|
|
3053
3143
|
exports.STATE_DELIMITER = STATE_DELIMITER;
|
|
3054
3144
|
exports.SpecialTargets = SpecialTargets;
|
|
@@ -3058,7 +3148,9 @@ exports.and = and;
|
|
|
3058
3148
|
exports.assign = assign;
|
|
3059
3149
|
exports.cancel = cancel;
|
|
3060
3150
|
exports.choose = choose;
|
|
3151
|
+
exports.cloneState = cloneState;
|
|
3061
3152
|
exports.constantPrefixes = constantPrefixes;
|
|
3153
|
+
exports.createActor = createActor;
|
|
3062
3154
|
exports.createEmptyActor = createEmptyActor;
|
|
3063
3155
|
exports.createInitEvent = createInitEvent;
|
|
3064
3156
|
exports.createInvokeId = createInvokeId;
|