xstate 4.20.0 → 4.23.0

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.
Files changed (94) hide show
  1. package/CHANGELOG.md +205 -0
  2. package/dist/xstate.interpreter.js +1 -1
  3. package/dist/xstate.js +1 -1
  4. package/dist/xstate.web.js +2 -2
  5. package/es/Actor.d.ts +6 -5
  6. package/es/Actor.js +22 -7
  7. package/es/Machine.d.ts +10 -5
  8. package/es/Machine.js +3 -6
  9. package/es/State.js +3 -5
  10. package/es/StateNode.d.ts +4 -3
  11. package/es/StateNode.js +34 -28
  12. package/es/_virtual/_tslib.js +59 -73
  13. package/es/actionTypes.js +3 -2
  14. package/es/actions.d.ts +1 -1
  15. package/es/actions.js +51 -37
  16. package/es/behaviors.d.ts +37 -0
  17. package/es/behaviors.js +65 -0
  18. package/es/constants.js +2 -1
  19. package/es/devTools.js +1 -1
  20. package/es/environment.js +2 -1
  21. package/es/index.js +3 -1
  22. package/es/interpreter.d.ts +15 -8
  23. package/es/interpreter.js +48 -22
  24. package/es/invokeUtils.js +4 -3
  25. package/es/mapState.js +1 -1
  26. package/es/match.js +1 -1
  27. package/es/model.d.ts +2 -36
  28. package/es/model.types.d.ts +37 -0
  29. package/es/registry.js +2 -1
  30. package/es/scheduler.js +2 -1
  31. package/es/schema.js +1 -1
  32. package/es/serviceScope.js +1 -3
  33. package/es/stateUtils.d.ts +1 -0
  34. package/es/stateUtils.js +14 -8
  35. package/es/types.d.ts +35 -9
  36. package/es/types.js +1 -1
  37. package/es/utils.d.ts +3 -2
  38. package/es/utils.js +4 -40
  39. package/lib/Actor.d.ts +25 -24
  40. package/lib/Actor.js +87 -53
  41. package/lib/Machine.d.ts +17 -12
  42. package/lib/Machine.js +14 -14
  43. package/lib/SimulatedClock.d.ts +16 -16
  44. package/lib/State.d.ts +108 -108
  45. package/lib/State.js +246 -236
  46. package/lib/StateNode.d.ts +279 -278
  47. package/lib/StateNode.js +1535 -1350
  48. package/lib/_virtual/_tslib.js +81 -0
  49. package/lib/actionTypes.d.ts +19 -19
  50. package/lib/actionTypes.js +43 -23
  51. package/lib/actions.d.ts +138 -138
  52. package/lib/actions.js +465 -387
  53. package/lib/behaviors.d.ts +37 -0
  54. package/lib/behaviors.js +69 -0
  55. package/lib/constants.d.ts +5 -5
  56. package/lib/constants.js +13 -7
  57. package/lib/devTools.d.ts +15 -15
  58. package/lib/devTools.js +37 -26
  59. package/lib/each.d.ts +3 -3
  60. package/lib/environment.d.ts +1 -1
  61. package/lib/environment.js +7 -4
  62. package/lib/index.d.ts +30 -30
  63. package/lib/index.js +67 -57
  64. package/lib/interpreter.d.ts +205 -198
  65. package/lib/interpreter.js +1307 -1052
  66. package/lib/invoke.d.ts +10 -10
  67. package/lib/invokeUtils.d.ts +6 -6
  68. package/lib/invokeUtils.js +40 -37
  69. package/lib/json.d.ts +30 -30
  70. package/lib/mapState.d.ts +3 -3
  71. package/lib/mapState.js +31 -32
  72. package/lib/match.d.ts +8 -8
  73. package/lib/match.js +33 -47
  74. package/lib/model.d.ts +4 -38
  75. package/lib/model.js +5 -1
  76. package/lib/model.types.d.ts +37 -0
  77. package/lib/model.types.js +2 -0
  78. package/lib/patterns.d.ts +13 -13
  79. package/lib/registry.d.ts +8 -8
  80. package/lib/registry.js +21 -18
  81. package/lib/scheduler.d.ts +16 -16
  82. package/lib/scheduler.js +79 -70
  83. package/lib/schema.d.ts +1 -1
  84. package/lib/schema.js +6 -4
  85. package/lib/scxml.d.ts +5 -5
  86. package/lib/serviceScope.d.ts +3 -3
  87. package/lib/serviceScope.js +16 -12
  88. package/lib/stateUtils.d.ts +14 -13
  89. package/lib/stateUtils.js +232 -190
  90. package/lib/types.d.ts +928 -902
  91. package/lib/types.js +29 -29
  92. package/lib/utils.d.ts +68 -67
  93. package/lib/utils.js +530 -529
  94. package/package.json +5 -5
@@ -1,1113 +1,1368 @@
1
- "use strict";
2
- var __assign = (this && this.__assign) || function () {
3
- __assign = Object.assign || function(t) {
4
- for (var s, i = 1, n = arguments.length; i < n; i++) {
5
- s = arguments[i];
6
- for (var p in s) if (Object.prototype.hasOwnProperty.call(s, p))
7
- t[p] = s[p];
8
- }
9
- return t;
10
- };
11
- return __assign.apply(this, arguments);
12
- };
13
- var __values = (this && this.__values) || function(o) {
14
- var s = typeof Symbol === "function" && Symbol.iterator, m = s && o[s], i = 0;
15
- if (m) return m.call(o);
16
- if (o && typeof o.length === "number") return {
17
- next: function () {
18
- if (o && i >= o.length) o = void 0;
19
- return { value: o && o[i++], done: !o };
20
- }
21
- };
22
- throw new TypeError(s ? "Object is not iterable." : "Symbol.iterator is not defined.");
23
- };
24
- var __read = (this && this.__read) || function (o, n) {
25
- var m = typeof Symbol === "function" && o[Symbol.iterator];
26
- if (!m) return o;
27
- var i = m.call(o), r, ar = [], e;
28
- try {
29
- while ((n === void 0 || n-- > 0) && !(r = i.next()).done) ar.push(r.value);
30
- }
31
- catch (error) { e = { error: error }; }
32
- finally {
33
- try {
34
- if (r && !r.done && (m = i["return"])) m.call(i);
35
- }
36
- finally { if (e) throw e.error; }
37
- }
38
- return ar;
39
- };
40
- var __spreadArray = (this && this.__spreadArray) || function (to, from) {
41
- for (var i = 0, il = from.length, j = to.length; i < il; i++, j++)
42
- to[j] = from[i];
43
- return to;
1
+ 'use strict';
2
+
3
+ Object.defineProperty(exports, '__esModule', { value: true });
4
+
5
+ var _tslib = require('./_virtual/_tslib.js');
6
+ var environment = require('./environment.js');
7
+ var utils = require('./utils.js');
8
+ var types = require('./types.js');
9
+ var stateUtils = require('./stateUtils.js');
10
+ var actionTypes = require('./actionTypes.js');
11
+ var actions = require('./actions.js');
12
+ var State = require('./State.js');
13
+ var serviceScope = require('./serviceScope.js');
14
+ var Actor = require('./Actor.js');
15
+ var scheduler = require('./scheduler.js');
16
+ var registry = require('./registry.js');
17
+ var devTools = require('./devTools.js');
18
+ var behaviors = require('./behaviors.js');
19
+
20
+ var DEFAULT_SPAWN_OPTIONS = {
21
+ sync: false,
22
+ autoForward: false
44
23
  };
45
- Object.defineProperty(exports, "__esModule", { value: true });
46
- exports.interpret = exports.spawn = exports.Interpreter = exports.InterpreterStatus = void 0;
47
- var types_1 = require("./types");
48
- var State_1 = require("./State");
49
- var actionTypes = require("./actionTypes");
50
- var actions_1 = require("./actions");
51
- var environment_1 = require("./environment");
52
- var utils_1 = require("./utils");
53
- var scheduler_1 = require("./scheduler");
54
- var Actor_1 = require("./Actor");
55
- var stateUtils_1 = require("./stateUtils");
56
- var registry_1 = require("./registry");
57
- var devTools_1 = require("./devTools");
58
- var serviceScope = require("./serviceScope");
59
- var DEFAULT_SPAWN_OPTIONS = { sync: false, autoForward: false };
60
- var InterpreterStatus;
24
+
61
25
  (function (InterpreterStatus) {
62
- InterpreterStatus[InterpreterStatus["NotStarted"] = 0] = "NotStarted";
63
- InterpreterStatus[InterpreterStatus["Running"] = 1] = "Running";
64
- InterpreterStatus[InterpreterStatus["Stopped"] = 2] = "Stopped";
65
- })(InterpreterStatus = exports.InterpreterStatus || (exports.InterpreterStatus = {}));
66
- var Interpreter = /** @class */ (function () {
67
- /**
68
- * Creates a new Interpreter instance (i.e., service) for the given machine with the provided options, if any.
69
- *
70
- * @param machine The machine to be interpreted
71
- * @param options Interpreter options
72
- */
73
- function Interpreter(machine, options) {
74
- var _this = this;
75
- if (options === void 0) { options = Interpreter.defaultOptions; }
76
- this.machine = machine;
77
- this.scheduler = new scheduler_1.Scheduler();
78
- this.delayedEventsMap = {};
79
- this.listeners = new Set();
80
- this.contextListeners = new Set();
81
- this.stopListeners = new Set();
82
- this.doneListeners = new Set();
83
- this.eventListeners = new Set();
84
- this.sendListeners = new Set();
85
- /**
86
- * Whether the service is started.
87
- */
88
- this.initialized = false;
89
- this.status = InterpreterStatus.NotStarted;
90
- this.children = new Map();
91
- this.forwardTo = new Set();
92
- /**
93
- * Alias for Interpreter.prototype.start
94
- */
95
- this.init = this.start;
96
- /**
97
- * Sends an event to the running interpreter to trigger a transition.
98
- *
99
- * An array of events (batched) can be sent as well, which will send all
100
- * batched events to the running interpreter. The listeners will be
101
- * notified only **once** when all events are processed.
102
- *
103
- * @param event The event(s) to send
104
- */
105
- this.send = function (event, payload) {
106
- if (utils_1.isArray(event)) {
107
- _this.batch(event);
108
- return _this.state;
109
- }
110
- var _event = utils_1.toSCXMLEvent(utils_1.toEventObject(event, payload));
111
- if (_this.status === InterpreterStatus.Stopped) {
112
- // do nothing
113
- if (!environment_1.IS_PRODUCTION) {
114
- utils_1.warn(false, "Event \"" + _event.name + "\" was sent to stopped service \"" + _this.machine.id + "\". This service has already reached its final state, and will not transition.\nEvent: " + JSON.stringify(_event.data));
115
- }
116
- return _this.state;
117
- }
118
- if (_this.status !== InterpreterStatus.Running &&
119
- !_this.options.deferEvents) {
120
- throw new Error("Event \"" + _event.name + "\" was sent to uninitialized service \"" + _this.machine.id + "\". Make sure .start() is called for this service, or set { deferEvents: true } in the service options.\nEvent: " + JSON.stringify(_event.data));
121
- }
122
- _this.scheduler.schedule(function () {
123
- // Forward copy of event to child actors
124
- _this.forward(_event);
125
- var nextState = _this.nextState(_event);
126
- _this.update(nextState, _event);
127
- });
128
- return _this._state; // TODO: deprecate (should return void)
129
- // tslint:disable-next-line:semicolon
130
- };
131
- this.sendTo = function (event, to) {
132
- var isParent = _this.parent && (to === types_1.SpecialTargets.Parent || _this.parent.id === to);
133
- var target = isParent
134
- ? _this.parent
135
- : utils_1.isString(to)
136
- ? _this.children.get(to) || registry_1.registry.get(to)
137
- : utils_1.isActor(to)
138
- ? to
139
- : undefined;
140
- if (!target) {
141
- if (!isParent) {
142
- throw new Error("Unable to send event to child '" + to + "' from service '" + _this.id + "'.");
143
- }
144
- // tslint:disable-next-line:no-console
145
- if (!environment_1.IS_PRODUCTION) {
146
- utils_1.warn(false, "Service '" + _this.id + "' has no parent: unable to send event " + event.type);
147
- }
148
- return;
149
- }
150
- if ('machine' in target) {
151
- // Send SCXML events to machines
152
- target.send(__assign(__assign({}, event), { name: event.name === actionTypes.error ? "" + actions_1.error(_this.id) : event.name, origin: _this.sessionId }));
153
- }
154
- else {
155
- // Send normal events to other targets
156
- target.send(event.data);
157
- }
158
- };
159
- var resolvedOptions = __assign(__assign({}, Interpreter.defaultOptions), options);
160
- var clock = resolvedOptions.clock, logger = resolvedOptions.logger, parent = resolvedOptions.parent, id = resolvedOptions.id;
161
- var resolvedId = id !== undefined ? id : machine.id;
162
- this.id = resolvedId;
163
- this.logger = logger;
164
- this.clock = clock;
165
- this.parent = parent;
166
- this.options = resolvedOptions;
167
- this.scheduler = new scheduler_1.Scheduler({
168
- deferEvents: this.options.deferEvents
169
- });
170
- this.sessionId = registry_1.registry.bookId();
26
+ InterpreterStatus[InterpreterStatus["NotStarted"] = 0] = "NotStarted";
27
+ InterpreterStatus[InterpreterStatus["Running"] = 1] = "Running";
28
+ InterpreterStatus[InterpreterStatus["Stopped"] = 2] = "Stopped";
29
+ })(exports.InterpreterStatus || (exports.InterpreterStatus = {}));
30
+
31
+ var Interpreter =
32
+ /*#__PURE__*/
33
+
34
+ /** @class */
35
+ function () {
36
+ /**
37
+ * Creates a new Interpreter instance (i.e., service) for the given machine with the provided options, if any.
38
+ *
39
+ * @param machine The machine to be interpreted
40
+ * @param options Interpreter options
41
+ */
42
+ function Interpreter(machine, options) {
43
+ var _this = this;
44
+
45
+ if (options === void 0) {
46
+ options = Interpreter.defaultOptions;
171
47
  }
172
- Object.defineProperty(Interpreter.prototype, "initialState", {
173
- get: function () {
174
- var _this = this;
175
- if (this._initialState) {
176
- return this._initialState;
177
- }
178
- return serviceScope.provide(this, function () {
179
- _this._initialState = _this.machine.initialState;
180
- return _this._initialState;
181
- });
182
- },
183
- enumerable: false,
184
- configurable: true
185
- });
186
- Object.defineProperty(Interpreter.prototype, "state", {
187
- get: function () {
188
- if (!environment_1.IS_PRODUCTION) {
189
- utils_1.warn(this.status !== InterpreterStatus.NotStarted, "Attempted to read state from uninitialized service '" + this.id + "'. Make sure the service is started first.");
190
- }
191
- return this._state;
192
- },
193
- enumerable: false,
194
- configurable: true
195
- });
196
- /**
197
- * Executes the actions of the given state, with that state's `context` and `event`.
198
- *
199
- * @param state The state whose actions will be executed
200
- * @param actionsConfig The action implementations to use
48
+
49
+ this.machine = machine;
50
+ this.scheduler = new scheduler.Scheduler();
51
+ this.delayedEventsMap = {};
52
+ this.listeners = new Set();
53
+ this.contextListeners = new Set();
54
+ this.stopListeners = new Set();
55
+ this.doneListeners = new Set();
56
+ this.eventListeners = new Set();
57
+ this.sendListeners = new Set();
58
+ /**
59
+ * Whether the service is started.
201
60
  */
202
- Interpreter.prototype.execute = function (state, actionsConfig) {
203
- var e_1, _a;
204
- try {
205
- for (var _b = __values(state.actions), _c = _b.next(); !_c.done; _c = _b.next()) {
206
- var action = _c.value;
207
- this.exec(action, state, actionsConfig);
208
- }
209
- }
210
- catch (e_1_1) { e_1 = { error: e_1_1 }; }
211
- finally {
212
- try {
213
- if (_c && !_c.done && (_a = _b.return)) _a.call(_b);
214
- }
215
- finally { if (e_1) throw e_1.error; }
61
+
62
+ this.initialized = false;
63
+ this.status = exports.InterpreterStatus.NotStarted;
64
+ this.children = new Map();
65
+ this.forwardTo = new Set();
66
+ /**
67
+ * Alias for Interpreter.prototype.start
68
+ */
69
+
70
+ this.init = this.start;
71
+ /**
72
+ * Sends an event to the running interpreter to trigger a transition.
73
+ *
74
+ * An array of events (batched) can be sent as well, which will send all
75
+ * batched events to the running interpreter. The listeners will be
76
+ * notified only **once** when all events are processed.
77
+ *
78
+ * @param event The event(s) to send
79
+ */
80
+
81
+ this.send = function (event, payload) {
82
+ if (utils.isArray(event)) {
83
+ _this.batch(event);
84
+
85
+ return _this.state;
86
+ }
87
+
88
+ var _event = utils.toSCXMLEvent(utils.toEventObject(event, payload));
89
+
90
+ if (_this.status === exports.InterpreterStatus.Stopped) {
91
+ // do nothing
92
+ if (!environment.IS_PRODUCTION) {
93
+ utils.warn(false, "Event \"" + _event.name + "\" was sent to stopped service \"" + _this.machine.id + "\". This service has already reached its final state, and will not transition.\nEvent: " + JSON.stringify(_event.data));
216
94
  }
95
+
96
+ return _this.state;
97
+ }
98
+
99
+ if (_this.status !== exports.InterpreterStatus.Running && !_this.options.deferEvents) {
100
+ throw new Error("Event \"" + _event.name + "\" was sent to uninitialized service \"" + _this.machine.id + "\". Make sure .start() is called for this service, or set { deferEvents: true } in the service options.\nEvent: " + JSON.stringify(_event.data));
101
+ }
102
+
103
+ _this.scheduler.schedule(function () {
104
+ // Forward copy of event to child actors
105
+ _this.forward(_event);
106
+
107
+ var nextState = _this.nextState(_event);
108
+
109
+ _this.update(nextState, _event);
110
+ });
111
+
112
+ return _this._state; // TODO: deprecate (should return void)
113
+ // tslint:disable-next-line:semicolon
217
114
  };
218
- Interpreter.prototype.update = function (state, _event) {
219
- var e_2, _a, e_3, _b, e_4, _c, e_5, _d;
220
- var _this = this;
221
- // Attach session ID to state
222
- state._sessionid = this.sessionId;
223
- // Update state
224
- this._state = state;
225
- // Execute actions
226
- if (this.options.execute) {
227
- this.execute(this.state);
228
- }
229
- // Update children
230
- this.children.forEach(function (child) {
231
- _this.state.children[child.id] = child;
232
- });
233
- // Dev tools
234
- if (this.devTools) {
235
- this.devTools.send(_event.data, state);
115
+
116
+ this.sendTo = function (event, to) {
117
+ var isParent = _this.parent && (to === types.SpecialTargets.Parent || _this.parent.id === to);
118
+ var target = isParent ? _this.parent : utils.isString(to) ? _this.children.get(to) || registry.registry.get(to) : utils.isActor(to) ? to : undefined;
119
+
120
+ if (!target) {
121
+ if (!isParent) {
122
+ throw new Error("Unable to send event to child '" + to + "' from service '" + _this.id + "'.");
123
+ } // tslint:disable-next-line:no-console
124
+
125
+
126
+ if (!environment.IS_PRODUCTION) {
127
+ utils.warn(false, "Service '" + _this.id + "' has no parent: unable to send event " + event.type);
236
128
  }
237
- // Execute listeners
238
- if (state.event) {
239
- try {
240
- for (var _e = __values(this.eventListeners), _f = _e.next(); !_f.done; _f = _e.next()) {
241
- var listener = _f.value;
242
- listener(state.event);
243
- }
244
- }
245
- catch (e_2_1) { e_2 = { error: e_2_1 }; }
246
- finally {
247
- try {
248
- if (_f && !_f.done && (_a = _e.return)) _a.call(_e);
249
- }
250
- finally { if (e_2) throw e_2.error; }
251
- }
129
+
130
+ return;
131
+ }
132
+
133
+ if ('machine' in target) {
134
+ // Send SCXML events to machines
135
+ target.send(_tslib.__assign(_tslib.__assign({}, event), {
136
+ name: event.name === actionTypes.error ? "" + actions.error(_this.id) : event.name,
137
+ origin: _this.sessionId
138
+ }));
139
+ } else {
140
+ // Send normal events to other targets
141
+ target.send(event.data);
142
+ }
143
+ };
144
+
145
+ var resolvedOptions = _tslib.__assign(_tslib.__assign({}, Interpreter.defaultOptions), options);
146
+
147
+ var clock = resolvedOptions.clock,
148
+ logger = resolvedOptions.logger,
149
+ parent = resolvedOptions.parent,
150
+ id = resolvedOptions.id;
151
+ var resolvedId = id !== undefined ? id : machine.id;
152
+ this.id = resolvedId;
153
+ this.logger = logger;
154
+ this.clock = clock;
155
+ this.parent = parent;
156
+ this.options = resolvedOptions;
157
+ this.scheduler = new scheduler.Scheduler({
158
+ deferEvents: this.options.deferEvents
159
+ });
160
+ this.sessionId = registry.registry.bookId();
161
+ }
162
+
163
+ Object.defineProperty(Interpreter.prototype, "initialState", {
164
+ get: function () {
165
+ var _this = this;
166
+
167
+ if (this._initialState) {
168
+ return this._initialState;
169
+ }
170
+
171
+ return serviceScope.provide(this, function () {
172
+ _this._initialState = _this.machine.initialState;
173
+ return _this._initialState;
174
+ });
175
+ },
176
+ enumerable: false,
177
+ configurable: true
178
+ });
179
+ Object.defineProperty(Interpreter.prototype, "state", {
180
+ get: function () {
181
+ if (!environment.IS_PRODUCTION) {
182
+ utils.warn(this.status !== exports.InterpreterStatus.NotStarted, "Attempted to read state from uninitialized service '" + this.id + "'. Make sure the service is started first.");
183
+ }
184
+
185
+ return this._state;
186
+ },
187
+ enumerable: false,
188
+ configurable: true
189
+ });
190
+ /**
191
+ * Executes the actions of the given state, with that state's `context` and `event`.
192
+ *
193
+ * @param state The state whose actions will be executed
194
+ * @param actionsConfig The action implementations to use
195
+ */
196
+
197
+ Interpreter.prototype.execute = function (state, actionsConfig) {
198
+ var e_1, _a;
199
+
200
+ try {
201
+ for (var _b = _tslib.__values(state.actions), _c = _b.next(); !_c.done; _c = _b.next()) {
202
+ var action = _c.value;
203
+ this.exec(action, state, actionsConfig);
204
+ }
205
+ } catch (e_1_1) {
206
+ e_1 = {
207
+ error: e_1_1
208
+ };
209
+ } finally {
210
+ try {
211
+ if (_c && !_c.done && (_a = _b.return)) _a.call(_b);
212
+ } finally {
213
+ if (e_1) throw e_1.error;
214
+ }
215
+ }
216
+ };
217
+
218
+ Interpreter.prototype.update = function (state, _event) {
219
+ var e_2, _a, e_3, _b, e_4, _c, e_5, _d;
220
+
221
+ var _this = this; // Attach session ID to state
222
+
223
+
224
+ state._sessionid = this.sessionId; // Update state
225
+
226
+ this._state = state; // Execute actions
227
+
228
+ if (this.options.execute) {
229
+ this.execute(this.state);
230
+ } // Update children
231
+
232
+
233
+ this.children.forEach(function (child) {
234
+ _this.state.children[child.id] = child;
235
+ }); // Dev tools
236
+
237
+ if (this.devTools) {
238
+ this.devTools.send(_event.data, state);
239
+ } // Execute listeners
240
+
241
+
242
+ if (state.event) {
243
+ try {
244
+ for (var _e = _tslib.__values(this.eventListeners), _f = _e.next(); !_f.done; _f = _e.next()) {
245
+ var listener = _f.value;
246
+ listener(state.event);
252
247
  }
248
+ } catch (e_2_1) {
249
+ e_2 = {
250
+ error: e_2_1
251
+ };
252
+ } finally {
253
253
  try {
254
- for (var _g = __values(this.listeners), _h = _g.next(); !_h.done; _h = _g.next()) {
255
- var listener = _h.value;
256
- listener(state, state.event);
257
- }
254
+ if (_f && !_f.done && (_a = _e.return)) _a.call(_e);
255
+ } finally {
256
+ if (e_2) throw e_2.error;
258
257
  }
259
- catch (e_3_1) { e_3 = { error: e_3_1 }; }
260
- finally {
261
- try {
262
- if (_h && !_h.done && (_b = _g.return)) _b.call(_g);
263
- }
264
- finally { if (e_3) throw e_3.error; }
258
+ }
259
+ }
260
+
261
+ try {
262
+ for (var _g = _tslib.__values(this.listeners), _h = _g.next(); !_h.done; _h = _g.next()) {
263
+ var listener = _h.value;
264
+ listener(state, state.event);
265
+ }
266
+ } catch (e_3_1) {
267
+ e_3 = {
268
+ error: e_3_1
269
+ };
270
+ } finally {
271
+ try {
272
+ if (_h && !_h.done && (_b = _g.return)) _b.call(_g);
273
+ } finally {
274
+ if (e_3) throw e_3.error;
275
+ }
276
+ }
277
+
278
+ try {
279
+ for (var _j = _tslib.__values(this.contextListeners), _k = _j.next(); !_k.done; _k = _j.next()) {
280
+ var contextListener = _k.value;
281
+ contextListener(this.state.context, this.state.history ? this.state.history.context : undefined);
282
+ }
283
+ } catch (e_4_1) {
284
+ e_4 = {
285
+ error: e_4_1
286
+ };
287
+ } finally {
288
+ try {
289
+ if (_k && !_k.done && (_c = _j.return)) _c.call(_j);
290
+ } finally {
291
+ if (e_4) throw e_4.error;
292
+ }
293
+ }
294
+
295
+ var isDone = stateUtils.isInFinalState(state.configuration || [], this.machine);
296
+
297
+ if (this.state.configuration && isDone) {
298
+ // get final child state node
299
+ var finalChildStateNode = state.configuration.find(function (sn) {
300
+ return sn.type === 'final' && sn.parent === _this.machine;
301
+ });
302
+ var doneData = finalChildStateNode && finalChildStateNode.doneData ? utils.mapContext(finalChildStateNode.doneData, state.context, _event) : undefined;
303
+
304
+ try {
305
+ for (var _l = _tslib.__values(this.doneListeners), _m = _l.next(); !_m.done; _m = _l.next()) {
306
+ var listener = _m.value;
307
+ listener(actions.doneInvoke(this.id, doneData));
265
308
  }
309
+ } catch (e_5_1) {
310
+ e_5 = {
311
+ error: e_5_1
312
+ };
313
+ } finally {
266
314
  try {
267
- for (var _j = __values(this.contextListeners), _k = _j.next(); !_k.done; _k = _j.next()) {
268
- var contextListener = _k.value;
269
- contextListener(this.state.context, this.state.history ? this.state.history.context : undefined);
270
- }
271
- }
272
- catch (e_4_1) { e_4 = { error: e_4_1 }; }
273
- finally {
274
- try {
275
- if (_k && !_k.done && (_c = _j.return)) _c.call(_j);
276
- }
277
- finally { if (e_4) throw e_4.error; }
278
- }
279
- var isDone = stateUtils_1.isInFinalState(state.configuration || [], this.machine);
280
- if (this.state.configuration && isDone) {
281
- // get final child state node
282
- var finalChildStateNode = state.configuration.find(function (sn) { return sn.type === 'final' && sn.parent === _this.machine; });
283
- var doneData = finalChildStateNode && finalChildStateNode.doneData
284
- ? utils_1.mapContext(finalChildStateNode.doneData, state.context, _event)
285
- : undefined;
286
- try {
287
- for (var _l = __values(this.doneListeners), _m = _l.next(); !_m.done; _m = _l.next()) {
288
- var listener = _m.value;
289
- listener(actions_1.doneInvoke(this.id, doneData));
290
- }
291
- }
292
- catch (e_5_1) { e_5 = { error: e_5_1 }; }
293
- finally {
294
- try {
295
- if (_m && !_m.done && (_d = _l.return)) _d.call(_l);
296
- }
297
- finally { if (e_5) throw e_5.error; }
298
- }
299
- this.stop();
300
- }
301
- };
302
- /*
303
- * Adds a listener that is notified whenever a state transition happens. The listener is called with
304
- * the next state and the event object that caused the state transition.
305
- *
306
- * @param listener The state listener
307
- */
308
- Interpreter.prototype.onTransition = function (listener) {
309
- this.listeners.add(listener);
310
- // Send current state to listener
311
- if (this.status === InterpreterStatus.Running) {
312
- listener(this.state, this.state.event);
313
- }
314
- return this;
315
- };
316
- Interpreter.prototype.subscribe = function (nextListenerOrObserver, _, // TODO: error listener
317
- completeListener) {
318
- var _this = this;
319
- if (!nextListenerOrObserver) {
320
- return { unsubscribe: function () { return void 0; } };
321
- }
322
- var listener;
323
- var resolvedCompleteListener = completeListener;
324
- if (typeof nextListenerOrObserver === 'function') {
325
- listener = nextListenerOrObserver;
315
+ if (_m && !_m.done && (_d = _l.return)) _d.call(_l);
316
+ } finally {
317
+ if (e_5) throw e_5.error;
326
318
  }
327
- else {
328
- listener = nextListenerOrObserver.next.bind(nextListenerOrObserver);
329
- resolvedCompleteListener = nextListenerOrObserver.complete.bind(nextListenerOrObserver);
330
- }
331
- this.listeners.add(listener);
332
- // Send current state to listener
333
- if (this.status === InterpreterStatus.Running) {
334
- listener(this.state);
335
- }
336
- if (resolvedCompleteListener) {
337
- this.onDone(resolvedCompleteListener);
319
+ }
320
+
321
+ this.stop();
322
+ }
323
+ };
324
+ /*
325
+ * Adds a listener that is notified whenever a state transition happens. The listener is called with
326
+ * the next state and the event object that caused the state transition.
327
+ *
328
+ * @param listener The state listener
329
+ */
330
+
331
+
332
+ Interpreter.prototype.onTransition = function (listener) {
333
+ this.listeners.add(listener); // Send current state to listener
334
+
335
+ if (this.status === exports.InterpreterStatus.Running) {
336
+ listener(this.state, this.state.event);
337
+ }
338
+
339
+ return this;
340
+ };
341
+
342
+ Interpreter.prototype.subscribe = function (nextListenerOrObserver, _, // TODO: error listener
343
+ completeListener) {
344
+ var _this = this;
345
+
346
+ if (!nextListenerOrObserver) {
347
+ return {
348
+ unsubscribe: function () {
349
+ return void 0;
338
350
  }
339
- return {
340
- unsubscribe: function () {
341
- listener && _this.listeners.delete(listener);
342
- resolvedCompleteListener &&
343
- _this.doneListeners.delete(resolvedCompleteListener);
344
- }
345
- };
346
- };
347
- /**
348
- * Adds an event listener that is notified whenever an event is sent to the running interpreter.
349
- * @param listener The event listener
350
- */
351
- Interpreter.prototype.onEvent = function (listener) {
352
- this.eventListeners.add(listener);
353
- return this;
354
- };
355
- /**
356
- * Adds an event listener that is notified whenever a `send` event occurs.
357
- * @param listener The event listener
358
- */
359
- Interpreter.prototype.onSend = function (listener) {
360
- this.sendListeners.add(listener);
361
- return this;
362
- };
363
- /**
364
- * Adds a context listener that is notified whenever the state context changes.
365
- * @param listener The context listener
366
- */
367
- Interpreter.prototype.onChange = function (listener) {
368
- this.contextListeners.add(listener);
369
- return this;
370
- };
371
- /**
372
- * Adds a listener that is notified when the machine is stopped.
373
- * @param listener The listener
374
- */
375
- Interpreter.prototype.onStop = function (listener) {
376
- this.stopListeners.add(listener);
377
- return this;
378
- };
379
- /**
380
- * Adds a state listener that is notified when the statechart has reached its final state.
381
- * @param listener The state listener
382
- */
383
- Interpreter.prototype.onDone = function (listener) {
384
- this.doneListeners.add(listener);
385
- return this;
351
+ };
352
+ }
353
+
354
+ var listener;
355
+ var resolvedCompleteListener = completeListener;
356
+
357
+ if (typeof nextListenerOrObserver === 'function') {
358
+ listener = nextListenerOrObserver;
359
+ } else {
360
+ listener = nextListenerOrObserver.next.bind(nextListenerOrObserver);
361
+ resolvedCompleteListener = nextListenerOrObserver.complete.bind(nextListenerOrObserver);
362
+ }
363
+
364
+ this.listeners.add(listener); // Send current state to listener
365
+
366
+ if (this.status === exports.InterpreterStatus.Running) {
367
+ listener(this.state);
368
+ }
369
+
370
+ if (resolvedCompleteListener) {
371
+ this.onDone(resolvedCompleteListener);
372
+ }
373
+
374
+ return {
375
+ unsubscribe: function () {
376
+ listener && _this.listeners.delete(listener);
377
+ resolvedCompleteListener && _this.doneListeners.delete(resolvedCompleteListener);
378
+ }
386
379
  };
387
- /**
388
- * Removes a listener.
389
- * @param listener The listener to remove
390
- */
391
- Interpreter.prototype.off = function (listener) {
380
+ };
381
+ /**
382
+ * Adds an event listener that is notified whenever an event is sent to the running interpreter.
383
+ * @param listener The event listener
384
+ */
385
+
386
+
387
+ Interpreter.prototype.onEvent = function (listener) {
388
+ this.eventListeners.add(listener);
389
+ return this;
390
+ };
391
+ /**
392
+ * Adds an event listener that is notified whenever a `send` event occurs.
393
+ * @param listener The event listener
394
+ */
395
+
396
+
397
+ Interpreter.prototype.onSend = function (listener) {
398
+ this.sendListeners.add(listener);
399
+ return this;
400
+ };
401
+ /**
402
+ * Adds a context listener that is notified whenever the state context changes.
403
+ * @param listener The context listener
404
+ */
405
+
406
+
407
+ Interpreter.prototype.onChange = function (listener) {
408
+ this.contextListeners.add(listener);
409
+ return this;
410
+ };
411
+ /**
412
+ * Adds a listener that is notified when the machine is stopped.
413
+ * @param listener The listener
414
+ */
415
+
416
+
417
+ Interpreter.prototype.onStop = function (listener) {
418
+ this.stopListeners.add(listener);
419
+ return this;
420
+ };
421
+ /**
422
+ * Adds a state listener that is notified when the statechart has reached its final state.
423
+ * @param listener The state listener
424
+ */
425
+
426
+
427
+ Interpreter.prototype.onDone = function (listener) {
428
+ this.doneListeners.add(listener);
429
+ return this;
430
+ };
431
+ /**
432
+ * Removes a listener.
433
+ * @param listener The listener to remove
434
+ */
435
+
436
+
437
+ Interpreter.prototype.off = function (listener) {
438
+ this.listeners.delete(listener);
439
+ this.eventListeners.delete(listener);
440
+ this.sendListeners.delete(listener);
441
+ this.stopListeners.delete(listener);
442
+ this.doneListeners.delete(listener);
443
+ this.contextListeners.delete(listener);
444
+ return this;
445
+ };
446
+ /**
447
+ * Starts the interpreter from the given state, or the initial state.
448
+ * @param initialState The state to start the statechart from
449
+ */
450
+
451
+
452
+ Interpreter.prototype.start = function (initialState) {
453
+ var _this = this;
454
+
455
+ if (this.status === exports.InterpreterStatus.Running) {
456
+ // Do not restart the service if it is already started
457
+ return this;
458
+ }
459
+
460
+ registry.registry.register(this.sessionId, this);
461
+ this.initialized = true;
462
+ this.status = exports.InterpreterStatus.Running;
463
+ var resolvedState = initialState === undefined ? this.initialState : serviceScope.provide(this, function () {
464
+ return State.isState(initialState) ? _this.machine.resolveState(initialState) : _this.machine.resolveState(State.State.from(initialState, _this.machine.context));
465
+ });
466
+
467
+ if (this.options.devTools) {
468
+ this.attachDev();
469
+ }
470
+
471
+ this.scheduler.initialize(function () {
472
+ _this.update(resolvedState, actions.initEvent);
473
+ });
474
+ return this;
475
+ };
476
+ /**
477
+ * Stops the interpreter and unsubscribe all listeners.
478
+ *
479
+ * This will also notify the `onStop` listeners.
480
+ */
481
+
482
+
483
+ Interpreter.prototype.stop = function () {
484
+ var e_6, _a, e_7, _b, e_8, _c, e_9, _d, e_10, _e;
485
+
486
+ var _this = this;
487
+
488
+ try {
489
+ for (var _f = _tslib.__values(this.listeners), _g = _f.next(); !_g.done; _g = _f.next()) {
490
+ var listener = _g.value;
392
491
  this.listeners.delete(listener);
393
- this.eventListeners.delete(listener);
394
- this.sendListeners.delete(listener);
492
+ }
493
+ } catch (e_6_1) {
494
+ e_6 = {
495
+ error: e_6_1
496
+ };
497
+ } finally {
498
+ try {
499
+ if (_g && !_g.done && (_a = _f.return)) _a.call(_f);
500
+ } finally {
501
+ if (e_6) throw e_6.error;
502
+ }
503
+ }
504
+
505
+ try {
506
+ for (var _h = _tslib.__values(this.stopListeners), _j = _h.next(); !_j.done; _j = _h.next()) {
507
+ var listener = _j.value; // call listener, then remove
508
+
509
+ listener();
395
510
  this.stopListeners.delete(listener);
396
- this.doneListeners.delete(listener);
511
+ }
512
+ } catch (e_7_1) {
513
+ e_7 = {
514
+ error: e_7_1
515
+ };
516
+ } finally {
517
+ try {
518
+ if (_j && !_j.done && (_b = _h.return)) _b.call(_h);
519
+ } finally {
520
+ if (e_7) throw e_7.error;
521
+ }
522
+ }
523
+
524
+ try {
525
+ for (var _k = _tslib.__values(this.contextListeners), _l = _k.next(); !_l.done; _l = _k.next()) {
526
+ var listener = _l.value;
397
527
  this.contextListeners.delete(listener);
398
- return this;
399
- };
400
- /**
401
- * Starts the interpreter from the given state, or the initial state.
402
- * @param initialState The state to start the statechart from
403
- */
404
- Interpreter.prototype.start = function (initialState) {
405
- var _this = this;
406
- if (this.status === InterpreterStatus.Running) {
407
- // Do not restart the service if it is already started
408
- return this;
409
- }
410
- registry_1.registry.register(this.sessionId, this);
411
- this.initialized = true;
412
- this.status = InterpreterStatus.Running;
413
- var resolvedState = initialState === undefined
414
- ? this.initialState
415
- : serviceScope.provide(this, function () {
416
- return State_1.isState(initialState)
417
- ? _this.machine.resolveState(initialState)
418
- : _this.machine.resolveState(State_1.State.from(initialState, _this.machine.context));
419
- });
420
- if (this.options.devTools) {
421
- this.attachDev();
422
- }
423
- this.scheduler.initialize(function () {
424
- _this.update(resolvedState, actions_1.initEvent);
425
- });
426
- return this;
427
- };
428
- /**
429
- * Stops the interpreter and unsubscribe all listeners.
430
- *
431
- * This will also notify the `onStop` listeners.
432
- */
433
- Interpreter.prototype.stop = function () {
434
- var e_6, _a, e_7, _b, e_8, _c, e_9, _d, e_10, _e;
435
- var _this = this;
436
- try {
437
- for (var _f = __values(this.listeners), _g = _f.next(); !_g.done; _g = _f.next()) {
438
- var listener = _g.value;
439
- this.listeners.delete(listener);
440
- }
441
- }
442
- catch (e_6_1) { e_6 = { error: e_6_1 }; }
443
- finally {
444
- try {
445
- if (_g && !_g.done && (_a = _f.return)) _a.call(_f);
446
- }
447
- finally { if (e_6) throw e_6.error; }
448
- }
449
- try {
450
- for (var _h = __values(this.stopListeners), _j = _h.next(); !_j.done; _j = _h.next()) {
451
- var listener = _j.value;
452
- // call listener, then remove
453
- listener();
454
- this.stopListeners.delete(listener);
455
- }
456
- }
457
- catch (e_7_1) { e_7 = { error: e_7_1 }; }
458
- finally {
459
- try {
460
- if (_j && !_j.done && (_b = _h.return)) _b.call(_h);
461
- }
462
- finally { if (e_7) throw e_7.error; }
463
- }
464
- try {
465
- for (var _k = __values(this.contextListeners), _l = _k.next(); !_l.done; _l = _k.next()) {
466
- var listener = _l.value;
467
- this.contextListeners.delete(listener);
468
- }
469
- }
470
- catch (e_8_1) { e_8 = { error: e_8_1 }; }
471
- finally {
472
- try {
473
- if (_l && !_l.done && (_c = _k.return)) _c.call(_k);
474
- }
475
- finally { if (e_8) throw e_8.error; }
528
+ }
529
+ } catch (e_8_1) {
530
+ e_8 = {
531
+ error: e_8_1
532
+ };
533
+ } finally {
534
+ try {
535
+ if (_l && !_l.done && (_c = _k.return)) _c.call(_k);
536
+ } finally {
537
+ if (e_8) throw e_8.error;
538
+ }
539
+ }
540
+
541
+ try {
542
+ for (var _m = _tslib.__values(this.doneListeners), _o = _m.next(); !_o.done; _o = _m.next()) {
543
+ var listener = _o.value;
544
+ this.doneListeners.delete(listener);
545
+ }
546
+ } catch (e_9_1) {
547
+ e_9 = {
548
+ error: e_9_1
549
+ };
550
+ } finally {
551
+ try {
552
+ if (_o && !_o.done && (_d = _m.return)) _d.call(_m);
553
+ } finally {
554
+ if (e_9) throw e_9.error;
555
+ }
556
+ }
557
+
558
+ if (!this.initialized) {
559
+ // Interpreter already stopped; do nothing
560
+ return this;
561
+ }
562
+
563
+ this.state.configuration.forEach(function (stateNode) {
564
+ var e_11, _a;
565
+
566
+ try {
567
+ for (var _b = _tslib.__values(stateNode.definition.exit), _c = _b.next(); !_c.done; _c = _b.next()) {
568
+ var action = _c.value;
569
+
570
+ _this.exec(action, _this.state);
476
571
  }
572
+ } catch (e_11_1) {
573
+ e_11 = {
574
+ error: e_11_1
575
+ };
576
+ } finally {
477
577
  try {
478
- for (var _m = __values(this.doneListeners), _o = _m.next(); !_o.done; _o = _m.next()) {
479
- var listener = _o.value;
480
- this.doneListeners.delete(listener);
481
- }
482
- }
483
- catch (e_9_1) { e_9 = { error: e_9_1 }; }
484
- finally {
485
- try {
486
- if (_o && !_o.done && (_d = _m.return)) _d.call(_m);
487
- }
488
- finally { if (e_9) throw e_9.error; }
489
- }
490
- if (!this.initialized) {
491
- // Interpreter already stopped; do nothing
492
- return this;
578
+ if (_c && !_c.done && (_a = _b.return)) _a.call(_b);
579
+ } finally {
580
+ if (e_11) throw e_11.error;
493
581
  }
494
- this.state.configuration.forEach(function (stateNode) {
495
- var e_11, _a;
496
- try {
497
- for (var _b = __values(stateNode.definition.exit), _c = _b.next(); !_c.done; _c = _b.next()) {
498
- var action = _c.value;
499
- _this.exec(action, _this.state);
500
- }
501
- }
502
- catch (e_11_1) { e_11 = { error: e_11_1 }; }
503
- finally {
504
- try {
505
- if (_c && !_c.done && (_a = _b.return)) _a.call(_b);
506
- }
507
- finally { if (e_11) throw e_11.error; }
508
- }
509
- });
510
- // Stop all children
511
- this.children.forEach(function (child) {
512
- if (utils_1.isFunction(child.stop)) {
513
- child.stop();
514
- }
582
+ }
583
+ }); // Stop all children
584
+
585
+ this.children.forEach(function (child) {
586
+ if (utils.isFunction(child.stop)) {
587
+ child.stop();
588
+ }
589
+ });
590
+
591
+ try {
592
+ // Cancel all delayed events
593
+ for (var _p = _tslib.__values(utils.keys(this.delayedEventsMap)), _q = _p.next(); !_q.done; _q = _p.next()) {
594
+ var key = _q.value;
595
+ this.clock.clearTimeout(this.delayedEventsMap[key]);
596
+ }
597
+ } catch (e_10_1) {
598
+ e_10 = {
599
+ error: e_10_1
600
+ };
601
+ } finally {
602
+ try {
603
+ if (_q && !_q.done && (_e = _p.return)) _e.call(_p);
604
+ } finally {
605
+ if (e_10) throw e_10.error;
606
+ }
607
+ }
608
+
609
+ this.scheduler.clear();
610
+ this.initialized = false;
611
+ this.status = exports.InterpreterStatus.Stopped;
612
+ registry.registry.free(this.sessionId);
613
+ return this;
614
+ };
615
+
616
+ Interpreter.prototype.batch = function (events) {
617
+ var _this = this;
618
+
619
+ if (this.status === exports.InterpreterStatus.NotStarted && this.options.deferEvents) {
620
+ // tslint:disable-next-line:no-console
621
+ if (!environment.IS_PRODUCTION) {
622
+ utils.warn(false, events.length + " event(s) were sent to uninitialized service \"" + this.machine.id + "\" and are deferred. Make sure .start() is called for this service.\nEvent: " + JSON.stringify(event));
623
+ }
624
+ } else if (this.status !== exports.InterpreterStatus.Running) {
625
+ throw new Error( // tslint:disable-next-line:max-line-length
626
+ events.length + " event(s) were sent to uninitialized service \"" + this.machine.id + "\". Make sure .start() is called for this service, or set { deferEvents: true } in the service options.");
627
+ }
628
+
629
+ this.scheduler.schedule(function () {
630
+ var e_12, _a;
631
+
632
+ var nextState = _this.state;
633
+ var batchChanged = false;
634
+ var batchedActions = [];
635
+
636
+ var _loop_1 = function (event_1) {
637
+ var _event = utils.toSCXMLEvent(event_1);
638
+
639
+ _this.forward(_event);
640
+
641
+ nextState = serviceScope.provide(_this, function () {
642
+ return _this.machine.transition(nextState, _event);
515
643
  });
516
- try {
517
- // Cancel all delayed events
518
- for (var _p = __values(utils_1.keys(this.delayedEventsMap)), _q = _p.next(); !_q.done; _q = _p.next()) {
519
- var key = _q.value;
520
- this.clock.clearTimeout(this.delayedEventsMap[key]);
521
- }
522
- }
523
- catch (e_10_1) { e_10 = { error: e_10_1 }; }
524
- finally {
525
- try {
526
- if (_q && !_q.done && (_e = _p.return)) _e.call(_p);
527
- }
528
- finally { if (e_10) throw e_10.error; }
644
+ batchedActions.push.apply(batchedActions, _tslib.__spreadArray([], _tslib.__read(nextState.actions.map(function (a) {
645
+ return State.bindActionToState(a, nextState);
646
+ }))));
647
+ batchChanged = batchChanged || !!nextState.changed;
648
+ };
649
+
650
+ try {
651
+ for (var events_1 = _tslib.__values(events), events_1_1 = events_1.next(); !events_1_1.done; events_1_1 = events_1.next()) {
652
+ var event_1 = events_1_1.value;
653
+
654
+ _loop_1(event_1);
529
655
  }
530
- this.scheduler.clear();
531
- this.initialized = false;
532
- this.status = InterpreterStatus.Stopped;
533
- registry_1.registry.free(this.sessionId);
534
- return this;
535
- };
536
- Interpreter.prototype.batch = function (events) {
537
- var _this = this;
538
- if (this.status === InterpreterStatus.NotStarted &&
539
- this.options.deferEvents) {
540
- // tslint:disable-next-line:no-console
541
- if (!environment_1.IS_PRODUCTION) {
542
- utils_1.warn(false, events.length + " event(s) were sent to uninitialized service \"" + this.machine.id + "\" and are deferred. Make sure .start() is called for this service.\nEvent: " + JSON.stringify(event));
543
- }
656
+ } catch (e_12_1) {
657
+ e_12 = {
658
+ error: e_12_1
659
+ };
660
+ } finally {
661
+ try {
662
+ if (events_1_1 && !events_1_1.done && (_a = events_1.return)) _a.call(events_1);
663
+ } finally {
664
+ if (e_12) throw e_12.error;
544
665
  }
545
- else if (this.status !== InterpreterStatus.Running) {
546
- throw new Error(
547
- // tslint:disable-next-line:max-line-length
548
- events.length + " event(s) were sent to uninitialized service \"" + this.machine.id + "\". Make sure .start() is called for this service, or set { deferEvents: true } in the service options.");
666
+ }
667
+
668
+ nextState.changed = batchChanged;
669
+ nextState.actions = batchedActions;
670
+
671
+ _this.update(nextState, utils.toSCXMLEvent(events[events.length - 1]));
672
+ });
673
+ };
674
+ /**
675
+ * Returns a send function bound to this interpreter instance.
676
+ *
677
+ * @param event The event to be sent by the sender.
678
+ */
679
+
680
+
681
+ Interpreter.prototype.sender = function (event) {
682
+ return this.send.bind(this, event);
683
+ };
684
+ /**
685
+ * Returns the next state given the interpreter's current state and the event.
686
+ *
687
+ * This is a pure method that does _not_ update the interpreter's state.
688
+ *
689
+ * @param event The event to determine the next state
690
+ */
691
+
692
+
693
+ Interpreter.prototype.nextState = function (event) {
694
+ var _this = this;
695
+
696
+ var _event = utils.toSCXMLEvent(event);
697
+
698
+ if (_event.name.indexOf(actionTypes.errorPlatform) === 0 && !this.state.nextEvents.some(function (nextEvent) {
699
+ return nextEvent.indexOf(actionTypes.errorPlatform) === 0;
700
+ })) {
701
+ throw _event.data.data;
702
+ }
703
+
704
+ var nextState = serviceScope.provide(this, function () {
705
+ return _this.machine.transition(_this.state, _event);
706
+ });
707
+ return nextState;
708
+ };
709
+
710
+ Interpreter.prototype.forward = function (event) {
711
+ var e_13, _a;
712
+
713
+ try {
714
+ for (var _b = _tslib.__values(this.forwardTo), _c = _b.next(); !_c.done; _c = _b.next()) {
715
+ var id = _c.value;
716
+ var child = this.children.get(id);
717
+
718
+ if (!child) {
719
+ throw new Error("Unable to forward event '" + event + "' from interpreter '" + this.id + "' to nonexistant child '" + id + "'.");
549
720
  }
550
- this.scheduler.schedule(function () {
551
- var e_12, _a;
552
- var nextState = _this.state;
553
- var batchChanged = false;
554
- var batchedActions = [];
555
- var _loop_1 = function (event_1) {
556
- var _event = utils_1.toSCXMLEvent(event_1);
557
- _this.forward(_event);
558
- nextState = serviceScope.provide(_this, function () {
559
- return _this.machine.transition(nextState, _event);
560
- });
561
- batchedActions.push.apply(batchedActions, __spreadArray([], __read(nextState.actions.map(function (a) {
562
- return State_1.bindActionToState(a, nextState);
563
- }))));
564
- batchChanged = batchChanged || !!nextState.changed;
565
- };
566
- try {
567
- for (var events_1 = __values(events), events_1_1 = events_1.next(); !events_1_1.done; events_1_1 = events_1.next()) {
568
- var event_1 = events_1_1.value;
569
- _loop_1(event_1);
570
- }
571
- }
572
- catch (e_12_1) { e_12 = { error: e_12_1 }; }
573
- finally {
574
- try {
575
- if (events_1_1 && !events_1_1.done && (_a = events_1.return)) _a.call(events_1);
576
- }
577
- finally { if (e_12) throw e_12.error; }
578
- }
579
- nextState.changed = batchChanged;
580
- nextState.actions = batchedActions;
581
- _this.update(nextState, utils_1.toSCXMLEvent(events[events.length - 1]));
721
+
722
+ child.send(event);
723
+ }
724
+ } catch (e_13_1) {
725
+ e_13 = {
726
+ error: e_13_1
727
+ };
728
+ } finally {
729
+ try {
730
+ if (_c && !_c.done && (_a = _b.return)) _a.call(_b);
731
+ } finally {
732
+ if (e_13) throw e_13.error;
733
+ }
734
+ }
735
+ };
736
+
737
+ Interpreter.prototype.defer = function (sendAction) {
738
+ var _this = this;
739
+
740
+ this.delayedEventsMap[sendAction.id] = this.clock.setTimeout(function () {
741
+ if (sendAction.to) {
742
+ _this.sendTo(sendAction._event, sendAction.to);
743
+ } else {
744
+ _this.send(sendAction._event);
745
+ }
746
+ }, sendAction.delay);
747
+ };
748
+
749
+ Interpreter.prototype.cancel = function (sendId) {
750
+ this.clock.clearTimeout(this.delayedEventsMap[sendId]);
751
+ delete this.delayedEventsMap[sendId];
752
+ };
753
+
754
+ Interpreter.prototype.exec = function (action, state, actionFunctionMap) {
755
+ if (actionFunctionMap === void 0) {
756
+ actionFunctionMap = this.machine.options.actions;
757
+ }
758
+
759
+ var context = state.context,
760
+ _event = state._event;
761
+ var actionOrExec = action.exec || actions.getActionFunction(action.type, actionFunctionMap);
762
+ var exec = utils.isFunction(actionOrExec) ? actionOrExec : actionOrExec ? actionOrExec.exec : action.exec;
763
+
764
+ if (exec) {
765
+ try {
766
+ return exec(context, _event.data, {
767
+ action: action,
768
+ state: this.state,
769
+ _event: _event
582
770
  });
583
- };
584
- /**
585
- * Returns a send function bound to this interpreter instance.
586
- *
587
- * @param event The event to be sent by the sender.
588
- */
589
- Interpreter.prototype.sender = function (event) {
590
- return this.send.bind(this, event);
591
- };
592
- /**
593
- * Returns the next state given the interpreter's current state and the event.
594
- *
595
- * This is a pure method that does _not_ update the interpreter's state.
596
- *
597
- * @param event The event to determine the next state
598
- */
599
- Interpreter.prototype.nextState = function (event) {
600
- var _this = this;
601
- var _event = utils_1.toSCXMLEvent(event);
602
- if (_event.name.indexOf(actionTypes.errorPlatform) === 0 &&
603
- !this.state.nextEvents.some(function (nextEvent) { return nextEvent.indexOf(actionTypes.errorPlatform) === 0; })) {
604
- throw _event.data.data;
771
+ } catch (err) {
772
+ if (this.parent) {
773
+ this.parent.send({
774
+ type: 'xstate.error',
775
+ data: err
776
+ });
605
777
  }
606
- var nextState = serviceScope.provide(this, function () {
607
- return _this.machine.transition(_this.state, _event);
608
- });
609
- return nextState;
610
- };
611
- Interpreter.prototype.forward = function (event) {
612
- var e_13, _a;
613
- try {
614
- for (var _b = __values(this.forwardTo), _c = _b.next(); !_c.done; _c = _b.next()) {
615
- var id = _c.value;
616
- var child = this.children.get(id);
617
- if (!child) {
618
- throw new Error("Unable to forward event '" + event + "' from interpreter '" + this.id + "' to nonexistant child '" + id + "'.");
619
- }
620
- child.send(event);
621
- }
622
- }
623
- catch (e_13_1) { e_13 = { error: e_13_1 }; }
624
- finally {
625
- try {
626
- if (_c && !_c.done && (_a = _b.return)) _a.call(_b);
627
- }
628
- finally { if (e_13) throw e_13.error; }
778
+
779
+ throw err;
780
+ }
781
+ }
782
+
783
+ switch (action.type) {
784
+ case actionTypes.send:
785
+ var sendAction = action;
786
+
787
+ if (typeof sendAction.delay === 'number') {
788
+ this.defer(sendAction);
789
+ return;
790
+ } else {
791
+ if (sendAction.to) {
792
+ this.sendTo(sendAction._event, sendAction.to);
793
+ } else {
794
+ this.send(sendAction._event);
795
+ }
629
796
  }
630
- };
631
- Interpreter.prototype.defer = function (sendAction) {
632
- var _this = this;
633
- this.delayedEventsMap[sendAction.id] = this.clock.setTimeout(function () {
634
- if (sendAction.to) {
635
- _this.sendTo(sendAction._event, sendAction.to);
797
+
798
+ break;
799
+
800
+ case actionTypes.cancel:
801
+ this.cancel(action.sendId);
802
+ break;
803
+
804
+ case actionTypes.start:
805
+ {
806
+ var activity = action.activity; // If the activity will be stopped right after it's started
807
+ // (such as in transient states)
808
+ // don't bother starting the activity.
809
+
810
+ if (!this.state.activities[activity.id || activity.type]) {
811
+ break;
812
+ } // Invoked services
813
+
814
+
815
+ if (activity.type === types.ActionTypes.Invoke) {
816
+ var invokeSource = utils.toInvokeSource(activity.src);
817
+ var serviceCreator = this.machine.options.services ? this.machine.options.services[invokeSource.type] : undefined;
818
+ var id = activity.id,
819
+ data = activity.data;
820
+
821
+ if (!environment.IS_PRODUCTION) {
822
+ utils.warn(!('forward' in activity), // tslint:disable-next-line:max-line-length
823
+ "`forward` property is deprecated (found in invocation of '" + activity.src + "' in in machine '" + this.machine.id + "'). " + "Please use `autoForward` instead.");
636
824
  }
637
- else {
638
- _this.send(sendAction._event);
639
- }
640
- }, sendAction.delay);
641
- };
642
- Interpreter.prototype.cancel = function (sendId) {
643
- this.clock.clearTimeout(this.delayedEventsMap[sendId]);
644
- delete this.delayedEventsMap[sendId];
645
- };
646
- Interpreter.prototype.exec = function (action, state, actionFunctionMap) {
647
- if (actionFunctionMap === void 0) { actionFunctionMap = this.machine
648
- .options.actions; }
649
- var context = state.context, _event = state._event;
650
- var actionOrExec = action.exec || actions_1.getActionFunction(action.type, actionFunctionMap);
651
- var exec = utils_1.isFunction(actionOrExec)
652
- ? actionOrExec
653
- : actionOrExec
654
- ? actionOrExec.exec
655
- : action.exec;
656
- if (exec) {
657
- try {
658
- return exec(context, _event.data, {
659
- action: action,
660
- state: this.state,
661
- _event: _event
662
- });
825
+
826
+ var autoForward = 'autoForward' in activity ? activity.autoForward : !!activity.forward;
827
+
828
+ if (!serviceCreator) {
829
+ // tslint:disable-next-line:no-console
830
+ if (!environment.IS_PRODUCTION) {
831
+ utils.warn(false, "No service found for invocation '" + activity.src + "' in machine '" + this.machine.id + "'.");
832
+ }
833
+
834
+ return;
663
835
  }
664
- catch (err) {
665
- if (this.parent) {
666
- this.parent.send({
667
- type: 'xstate.error',
668
- data: err
669
- });
670
- }
671
- throw err;
836
+
837
+ var resolvedData = data ? utils.mapContext(data, context, _event) : undefined;
838
+
839
+ if (typeof serviceCreator === 'string') {
840
+ // TODO: warn
841
+ return;
672
842
  }
673
- }
674
- switch (action.type) {
675
- case actionTypes.send:
676
- var sendAction = action;
677
- if (typeof sendAction.delay === 'number') {
678
- this.defer(sendAction);
679
- return;
680
- }
681
- else {
682
- if (sendAction.to) {
683
- this.sendTo(sendAction._event, sendAction.to);
684
- }
685
- else {
686
- this.send(sendAction._event);
687
- }
688
- }
689
- break;
690
- case actionTypes.cancel:
691
- this.cancel(action.sendId);
692
- break;
693
- case actionTypes.start: {
694
- var activity = action
695
- .activity;
696
- // If the activity will be stopped right after it's started
697
- // (such as in transient states)
698
- // don't bother starting the activity.
699
- if (!this.state.activities[activity.id || activity.type]) {
700
- break;
701
- }
702
- // Invoked services
703
- if (activity.type === types_1.ActionTypes.Invoke) {
704
- var invokeSource = utils_1.toInvokeSource(activity.src);
705
- var serviceCreator = this.machine.options.services
706
- ? this.machine.options.services[invokeSource.type]
707
- : undefined;
708
- var id = activity.id, data = activity.data;
709
- if (!environment_1.IS_PRODUCTION) {
710
- utils_1.warn(!('forward' in activity),
711
- // tslint:disable-next-line:max-line-length
712
- "`forward` property is deprecated (found in invocation of '" + activity.src + "' in in machine '" + this.machine.id + "'). " +
713
- "Please use `autoForward` instead.");
714
- }
715
- var autoForward = 'autoForward' in activity
716
- ? activity.autoForward
717
- : !!activity.forward;
718
- if (!serviceCreator) {
719
- // tslint:disable-next-line:no-console
720
- if (!environment_1.IS_PRODUCTION) {
721
- utils_1.warn(false, "No service found for invocation '" + activity.src + "' in machine '" + this.machine.id + "'.");
722
- }
723
- return;
724
- }
725
- var resolvedData = data
726
- ? utils_1.mapContext(data, context, _event)
727
- : undefined;
728
- var source = utils_1.isFunction(serviceCreator)
729
- ? serviceCreator(context, _event.data, {
730
- data: resolvedData,
731
- src: invokeSource
732
- })
733
- : serviceCreator;
734
- if (utils_1.isPromiseLike(source)) {
735
- this.spawnPromise(Promise.resolve(source), id);
736
- }
737
- else if (utils_1.isFunction(source)) {
738
- this.spawnCallback(source, id);
739
- }
740
- else if (utils_1.isObservable(source)) {
741
- this.spawnObservable(source, id);
742
- }
743
- else if (utils_1.isMachine(source)) {
744
- // TODO: try/catch here
745
- this.spawnMachine(resolvedData ? source.withContext(resolvedData) : source, {
746
- id: id,
747
- autoForward: autoForward
748
- });
749
- }
750
- else {
751
- // service is string
752
- }
753
- }
754
- else {
755
- this.spawnActivity(activity);
756
- }
757
- break;
843
+
844
+ var source = utils.isFunction(serviceCreator) ? serviceCreator(context, _event.data, {
845
+ data: resolvedData,
846
+ src: invokeSource
847
+ }) : serviceCreator;
848
+
849
+ if (!source) {
850
+ // TODO: warn?
851
+ return;
758
852
  }
759
- case actionTypes.stop: {
760
- this.stopChild(action.activity.id);
761
- break;
853
+
854
+ var options = void 0;
855
+
856
+ if (utils.isMachine(source)) {
857
+ source = resolvedData ? source.withContext(resolvedData) : source;
858
+ options = {
859
+ autoForward: autoForward
860
+ };
762
861
  }
763
- case actionTypes.log:
764
- var label = action.label, value = action.value;
765
- if (label) {
766
- this.logger(label, value);
767
- }
768
- else {
769
- this.logger(value);
770
- }
771
- break;
772
- default:
773
- if (!environment_1.IS_PRODUCTION) {
774
- utils_1.warn(false, "No implementation found for action type '" + action.type + "'");
775
- }
776
- break;
862
+
863
+ this.spawn(source, id, options);
864
+ } else {
865
+ this.spawnActivity(activity);
866
+ }
867
+
868
+ break;
777
869
  }
778
- return undefined;
779
- };
780
- Interpreter.prototype.removeChild = function (childId) {
781
- this.children.delete(childId);
782
- this.forwardTo.delete(childId);
783
- delete this.state.children[childId];
784
- };
785
- Interpreter.prototype.stopChild = function (childId) {
786
- var child = this.children.get(childId);
787
- if (!child) {
788
- return;
870
+
871
+ case actionTypes.stop:
872
+ {
873
+ this.stopChild(action.activity.id);
874
+ break;
789
875
  }
790
- this.removeChild(childId);
791
- if (utils_1.isFunction(child.stop)) {
792
- child.stop();
876
+
877
+ case actionTypes.log:
878
+ var label = action.label,
879
+ value = action.value;
880
+
881
+ if (label) {
882
+ this.logger(label, value);
883
+ } else {
884
+ this.logger(value);
793
885
  }
794
- };
795
- Interpreter.prototype.spawn = function (entity, name, options) {
796
- if (utils_1.isPromiseLike(entity)) {
797
- return this.spawnPromise(Promise.resolve(entity), name);
886
+
887
+ break;
888
+
889
+ default:
890
+ if (!environment.IS_PRODUCTION) {
891
+ utils.warn(false, "No implementation found for action type '" + action.type + "'");
798
892
  }
799
- else if (utils_1.isFunction(entity)) {
800
- return this.spawnCallback(entity, name);
801
- }
802
- else if (Actor_1.isSpawnedActor(entity)) {
803
- return this.spawnActor(entity);
804
- }
805
- else if (utils_1.isObservable(entity)) {
806
- return this.spawnObservable(entity, name);
807
- }
808
- else if (utils_1.isMachine(entity)) {
809
- return this.spawnMachine(entity, __assign(__assign({}, options), { id: name }));
810
- }
811
- else {
812
- throw new Error("Unable to spawn entity \"" + name + "\" of type \"" + typeof entity + "\".");
813
- }
814
- };
815
- Interpreter.prototype.spawnMachine = function (machine, options) {
816
- var _this = this;
817
- if (options === void 0) { options = {}; }
818
- var childService = new Interpreter(machine, __assign(__assign({}, this.options), { parent: this, id: options.id || machine.id }));
819
- var resolvedOptions = __assign(__assign({}, DEFAULT_SPAWN_OPTIONS), options);
820
- if (resolvedOptions.sync) {
821
- childService.onTransition(function (state) {
822
- _this.send(actionTypes.update, {
823
- state: state,
824
- id: childService.id
825
- });
826
- });
827
- }
828
- var actor = childService;
829
- this.children.set(childService.id, actor);
830
- if (resolvedOptions.autoForward) {
831
- this.forwardTo.add(childService.id);
832
- }
833
- childService
834
- .onDone(function (doneEvent) {
835
- _this.removeChild(childService.id);
836
- _this.send(utils_1.toSCXMLEvent(doneEvent, { origin: childService.id }));
837
- })
838
- .start();
839
- return actor;
840
- };
841
- Interpreter.prototype.spawnPromise = function (promise, id) {
842
- var _this = this;
843
- var canceled = false;
844
- var resolvedData = undefined;
845
- promise.then(function (response) {
846
- if (!canceled) {
847
- resolvedData = response;
848
- _this.removeChild(id);
849
- _this.send(utils_1.toSCXMLEvent(actions_1.doneInvoke(id, response), { origin: id }));
850
- }
851
- }, function (errorData) {
852
- if (!canceled) {
853
- _this.removeChild(id);
854
- var errorEvent = actions_1.error(id, errorData);
855
- try {
856
- // Send "error.platform.id" to this (parent).
857
- _this.send(utils_1.toSCXMLEvent(errorEvent, { origin: id }));
858
- }
859
- catch (error) {
860
- utils_1.reportUnhandledExceptionOnInvocation(errorData, error, id);
861
- if (_this.devTools) {
862
- _this.devTools.send(errorEvent, _this.state);
863
- }
864
- if (_this.machine.strict) {
865
- // it would be better to always stop the state machine if unhandled
866
- // exception/promise rejection happens but because we don't want to
867
- // break existing code so enforce it on strict mode only especially so
868
- // because documentation says that onError is optional
869
- _this.stop();
870
- }
871
- }
872
- }
893
+
894
+ break;
895
+ }
896
+
897
+ return undefined;
898
+ };
899
+
900
+ Interpreter.prototype.removeChild = function (childId) {
901
+ this.children.delete(childId);
902
+ this.forwardTo.delete(childId);
903
+ delete this.state.children[childId];
904
+ };
905
+
906
+ Interpreter.prototype.stopChild = function (childId) {
907
+ var child = this.children.get(childId);
908
+
909
+ if (!child) {
910
+ return;
911
+ }
912
+
913
+ this.removeChild(childId);
914
+
915
+ if (utils.isFunction(child.stop)) {
916
+ child.stop();
917
+ }
918
+ };
919
+
920
+ Interpreter.prototype.spawn = function (entity, name, options) {
921
+ if (utils.isPromiseLike(entity)) {
922
+ return this.spawnPromise(Promise.resolve(entity), name);
923
+ } else if (utils.isFunction(entity)) {
924
+ return this.spawnCallback(entity, name);
925
+ } else if (Actor.isSpawnedActor(entity)) {
926
+ return this.spawnActor(entity, name);
927
+ } else if (utils.isObservable(entity)) {
928
+ return this.spawnObservable(entity, name);
929
+ } else if (utils.isMachine(entity)) {
930
+ return this.spawnMachine(entity, _tslib.__assign(_tslib.__assign({}, options), {
931
+ id: name
932
+ }));
933
+ } else if (utils.isBehavior(entity)) {
934
+ return this.spawnBehavior(entity, name);
935
+ } else {
936
+ throw new Error("Unable to spawn entity \"" + name + "\" of type \"" + typeof entity + "\".");
937
+ }
938
+ };
939
+
940
+ Interpreter.prototype.spawnMachine = function (machine, options) {
941
+ var _this = this;
942
+
943
+ if (options === void 0) {
944
+ options = {};
945
+ }
946
+
947
+ var childService = new Interpreter(machine, _tslib.__assign(_tslib.__assign({}, this.options), {
948
+ parent: this,
949
+ id: options.id || machine.id
950
+ }));
951
+
952
+ var resolvedOptions = _tslib.__assign(_tslib.__assign({}, DEFAULT_SPAWN_OPTIONS), options);
953
+
954
+ if (resolvedOptions.sync) {
955
+ childService.onTransition(function (state) {
956
+ _this.send(actionTypes.update, {
957
+ state: state,
958
+ id: childService.id
873
959
  });
874
- var actor = {
875
- id: id,
876
- send: function () { return void 0; },
877
- subscribe: function (next, handleError, complete) {
878
- var observer = utils_1.toObserver(next, handleError, complete);
879
- var unsubscribed = false;
880
- promise.then(function (response) {
881
- if (unsubscribed) {
882
- return;
883
- }
884
- observer.next(response);
885
- if (unsubscribed) {
886
- return;
887
- }
888
- observer.complete();
889
- }, function (err) {
890
- if (unsubscribed) {
891
- return;
892
- }
893
- observer.error(err);
894
- });
895
- return {
896
- unsubscribe: function () { return (unsubscribed = true); }
897
- };
898
- },
899
- stop: function () {
900
- canceled = true;
901
- },
902
- toJSON: function () {
903
- return { id: id };
904
- },
905
- getSnapshot: function () { return resolvedData; }
906
- };
907
- this.children.set(id, actor);
908
- return actor;
909
- };
910
- Interpreter.prototype.spawnCallback = function (callback, id) {
911
- var _this = this;
912
- var canceled = false;
913
- var receivers = new Set();
914
- var listeners = new Set();
915
- var emitted = undefined;
916
- var receive = function (e) {
917
- emitted = e;
918
- listeners.forEach(function (listener) { return listener(e); });
919
- if (canceled) {
920
- return;
921
- }
922
- _this.send(utils_1.toSCXMLEvent(e, { origin: id }));
923
- };
924
- var callbackStop;
960
+ });
961
+ }
962
+
963
+ var actor = childService;
964
+ this.children.set(childService.id, actor);
965
+
966
+ if (resolvedOptions.autoForward) {
967
+ this.forwardTo.add(childService.id);
968
+ }
969
+
970
+ childService.onDone(function (doneEvent) {
971
+ _this.removeChild(childService.id);
972
+
973
+ _this.send(utils.toSCXMLEvent(doneEvent, {
974
+ origin: childService.id
975
+ }));
976
+ }).start();
977
+ return actor;
978
+ };
979
+
980
+ Interpreter.prototype.spawnBehavior = function (behavior, id) {
981
+ var actorRef = behaviors.spawnBehavior(behavior, {
982
+ id: id,
983
+ parent: this
984
+ });
985
+ this.children.set(id, actorRef);
986
+ return actorRef;
987
+ };
988
+
989
+ Interpreter.prototype.spawnPromise = function (promise, id) {
990
+ var _this = this;
991
+
992
+ var canceled = false;
993
+ var resolvedData;
994
+ promise.then(function (response) {
995
+ if (!canceled) {
996
+ resolvedData = response;
997
+
998
+ _this.removeChild(id);
999
+
1000
+ _this.send(utils.toSCXMLEvent(actions.doneInvoke(id, response), {
1001
+ origin: id
1002
+ }));
1003
+ }
1004
+ }, function (errorData) {
1005
+ if (!canceled) {
1006
+ _this.removeChild(id);
1007
+
1008
+ var errorEvent = actions.error(id, errorData);
1009
+
925
1010
  try {
926
- callbackStop = callback(receive, function (newListener) {
927
- receivers.add(newListener);
928
- });
929
- }
930
- catch (err) {
931
- this.send(actions_1.error(id, err));
1011
+ // Send "error.platform.id" to this (parent).
1012
+ _this.send(utils.toSCXMLEvent(errorEvent, {
1013
+ origin: id
1014
+ }));
1015
+ } catch (error) {
1016
+ utils.reportUnhandledExceptionOnInvocation(errorData, error, id);
1017
+
1018
+ if (_this.devTools) {
1019
+ _this.devTools.send(errorEvent, _this.state);
1020
+ }
1021
+
1022
+ if (_this.machine.strict) {
1023
+ // it would be better to always stop the state machine if unhandled
1024
+ // exception/promise rejection happens but because we don't want to
1025
+ // break existing code so enforce it on strict mode only especially so
1026
+ // because documentation says that onError is optional
1027
+ _this.stop();
1028
+ }
932
1029
  }
933
- if (utils_1.isPromiseLike(callbackStop)) {
934
- // it turned out to be an async function, can't reliably check this before calling `callback`
935
- // because transpiled async functions are not recognizable
936
- return this.spawnPromise(callbackStop, id);
937
- }
938
- var actor = {
939
- id: id,
940
- send: function (event) { return receivers.forEach(function (receiver) { return receiver(event); }); },
941
- subscribe: function (next) {
942
- listeners.add(next);
943
- return {
944
- unsubscribe: function () {
945
- listeners.delete(next);
946
- }
947
- };
948
- },
949
- stop: function () {
950
- canceled = true;
951
- if (utils_1.isFunction(callbackStop)) {
952
- callbackStop();
953
- }
954
- },
955
- toJSON: function () {
956
- return { id: id };
957
- },
958
- getSnapshot: function () { return emitted; }
959
- };
960
- this.children.set(id, actor);
961
- return actor;
962
- };
963
- Interpreter.prototype.spawnObservable = function (source, id) {
964
- var _this = this;
965
- var emitted = undefined;
966
- var subscription = source.subscribe(function (value) {
967
- emitted = value;
968
- _this.send(utils_1.toSCXMLEvent(value, { origin: id }));
1030
+ }
1031
+ });
1032
+ var actor = {
1033
+ id: id,
1034
+ send: function () {
1035
+ return void 0;
1036
+ },
1037
+ subscribe: function (next, handleError, complete) {
1038
+ var observer = utils.toObserver(next, handleError, complete);
1039
+ var unsubscribed = false;
1040
+ promise.then(function (response) {
1041
+ if (unsubscribed) {
1042
+ return;
1043
+ }
1044
+
1045
+ observer.next(response);
1046
+
1047
+ if (unsubscribed) {
1048
+ return;
1049
+ }
1050
+
1051
+ observer.complete();
969
1052
  }, function (err) {
970
- _this.removeChild(id);
971
- _this.send(utils_1.toSCXMLEvent(actions_1.error(id, err), { origin: id }));
972
- }, function () {
973
- _this.removeChild(id);
974
- _this.send(utils_1.toSCXMLEvent(actions_1.doneInvoke(id), { origin: id }));
1053
+ if (unsubscribed) {
1054
+ return;
1055
+ }
1056
+
1057
+ observer.error(err);
975
1058
  });
976
- var actor = {
977
- id: id,
978
- send: function () { return void 0; },
979
- subscribe: function (next, handleError, complete) {
980
- return source.subscribe(next, handleError, complete);
981
- },
982
- stop: function () { return subscription.unsubscribe(); },
983
- getSnapshot: function () { return emitted; },
984
- toJSON: function () {
985
- return { id: id };
986
- }
1059
+ return {
1060
+ unsubscribe: function () {
1061
+ return unsubscribed = true;
1062
+ }
987
1063
  };
988
- this.children.set(id, actor);
989
- return actor;
990
- };
991
- Interpreter.prototype.spawnActor = function (actor) {
992
- this.children.set(actor.id, actor);
993
- return actor;
1064
+ },
1065
+ stop: function () {
1066
+ canceled = true;
1067
+ },
1068
+ toJSON: function () {
1069
+ return {
1070
+ id: id
1071
+ };
1072
+ },
1073
+ getSnapshot: function () {
1074
+ return resolvedData;
1075
+ }
994
1076
  };
995
- Interpreter.prototype.spawnActivity = function (activity) {
996
- var implementation = this.machine.options && this.machine.options.activities
997
- ? this.machine.options.activities[activity.type]
998
- : undefined;
999
- if (!implementation) {
1000
- if (!environment_1.IS_PRODUCTION) {
1001
- utils_1.warn(false, "No implementation found for activity '" + activity.type + "'");
1002
- }
1003
- // tslint:disable-next-line:no-console
1004
- return;
1005
- }
1006
- // Start implementation
1007
- var dispose = implementation(this.state.context, activity);
1008
- this.spawnEffect(activity.id, dispose);
1077
+ this.children.set(id, actor);
1078
+ return actor;
1079
+ };
1080
+
1081
+ Interpreter.prototype.spawnCallback = function (callback, id) {
1082
+ var _this = this;
1083
+
1084
+ var canceled = false;
1085
+ var receivers = new Set();
1086
+ var listeners = new Set();
1087
+ var emitted;
1088
+
1089
+ var receive = function (e) {
1090
+ emitted = e;
1091
+ listeners.forEach(function (listener) {
1092
+ return listener(e);
1093
+ });
1094
+
1095
+ if (canceled) {
1096
+ return;
1097
+ }
1098
+
1099
+ _this.send(utils.toSCXMLEvent(e, {
1100
+ origin: id
1101
+ }));
1009
1102
  };
1010
- Interpreter.prototype.spawnEffect = function (id, dispose) {
1011
- this.children.set(id, {
1012
- id: id,
1013
- send: function () { return void 0; },
1014
- subscribe: function () {
1015
- return { unsubscribe: function () { return void 0; } };
1016
- },
1017
- stop: dispose || undefined,
1018
- getSnapshot: function () { return undefined; },
1019
- toJSON: function () {
1020
- return { id: id };
1021
- }
1103
+
1104
+ var callbackStop;
1105
+
1106
+ try {
1107
+ callbackStop = callback(receive, function (newListener) {
1108
+ receivers.add(newListener);
1109
+ });
1110
+ } catch (err) {
1111
+ this.send(actions.error(id, err));
1112
+ }
1113
+
1114
+ if (utils.isPromiseLike(callbackStop)) {
1115
+ // it turned out to be an async function, can't reliably check this before calling `callback`
1116
+ // because transpiled async functions are not recognizable
1117
+ return this.spawnPromise(callbackStop, id);
1118
+ }
1119
+
1120
+ var actor = {
1121
+ id: id,
1122
+ send: function (event) {
1123
+ return receivers.forEach(function (receiver) {
1124
+ return receiver(event);
1022
1125
  });
1023
- };
1024
- Interpreter.prototype.attachDev = function () {
1025
- var global = devTools_1.getGlobal();
1026
- if (this.options.devTools && global) {
1027
- if (global.__REDUX_DEVTOOLS_EXTENSION__) {
1028
- var devToolsOptions = typeof this.options.devTools === 'object'
1029
- ? this.options.devTools
1030
- : undefined;
1031
- this.devTools = global.__REDUX_DEVTOOLS_EXTENSION__.connect(__assign(__assign({ name: this.id, autoPause: true, stateSanitizer: function (state) {
1032
- return {
1033
- value: state.value,
1034
- context: state.context,
1035
- actions: state.actions
1036
- };
1037
- } }, devToolsOptions), { features: __assign({ jump: false, skip: false }, (devToolsOptions
1038
- ? devToolsOptions.features
1039
- : undefined)) }), this.machine);
1040
- this.devTools.init(this.state);
1041
- }
1042
- // add XState-specific dev tooling hook
1043
- devTools_1.registerService(this);
1126
+ },
1127
+ subscribe: function (next) {
1128
+ listeners.add(next);
1129
+ return {
1130
+ unsubscribe: function () {
1131
+ listeners.delete(next);
1132
+ }
1133
+ };
1134
+ },
1135
+ stop: function () {
1136
+ canceled = true;
1137
+
1138
+ if (utils.isFunction(callbackStop)) {
1139
+ callbackStop();
1044
1140
  }
1045
- };
1046
- Interpreter.prototype.toJSON = function () {
1141
+ },
1142
+ toJSON: function () {
1047
1143
  return {
1048
- id: this.id
1144
+ id: id
1049
1145
  };
1146
+ },
1147
+ getSnapshot: function () {
1148
+ return emitted;
1149
+ }
1050
1150
  };
1051
- Interpreter.prototype[utils_1.symbolObservable] = function () {
1052
- return this;
1151
+ this.children.set(id, actor);
1152
+ return actor;
1153
+ };
1154
+
1155
+ Interpreter.prototype.spawnObservable = function (source, id) {
1156
+ var _this = this;
1157
+
1158
+ var emitted;
1159
+ var subscription = source.subscribe(function (value) {
1160
+ emitted = value;
1161
+
1162
+ _this.send(utils.toSCXMLEvent(value, {
1163
+ origin: id
1164
+ }));
1165
+ }, function (err) {
1166
+ _this.removeChild(id);
1167
+
1168
+ _this.send(utils.toSCXMLEvent(actions.error(id, err), {
1169
+ origin: id
1170
+ }));
1171
+ }, function () {
1172
+ _this.removeChild(id);
1173
+
1174
+ _this.send(utils.toSCXMLEvent(actions.doneInvoke(id), {
1175
+ origin: id
1176
+ }));
1177
+ });
1178
+ var actor = {
1179
+ id: id,
1180
+ send: function () {
1181
+ return void 0;
1182
+ },
1183
+ subscribe: function (next, handleError, complete) {
1184
+ return source.subscribe(next, handleError, complete);
1185
+ },
1186
+ stop: function () {
1187
+ return subscription.unsubscribe();
1188
+ },
1189
+ getSnapshot: function () {
1190
+ return emitted;
1191
+ },
1192
+ toJSON: function () {
1193
+ return {
1194
+ id: id
1195
+ };
1196
+ }
1053
1197
  };
1054
- Interpreter.prototype.getSnapshot = function () {
1055
- return this._state;
1198
+ this.children.set(id, actor);
1199
+ return actor;
1200
+ };
1201
+
1202
+ Interpreter.prototype.spawnActor = function (actor, name) {
1203
+ this.children.set(name, actor);
1204
+ return actor;
1205
+ };
1206
+
1207
+ Interpreter.prototype.spawnActivity = function (activity) {
1208
+ var implementation = this.machine.options && this.machine.options.activities ? this.machine.options.activities[activity.type] : undefined;
1209
+
1210
+ if (!implementation) {
1211
+ if (!environment.IS_PRODUCTION) {
1212
+ utils.warn(false, "No implementation found for activity '" + activity.type + "'");
1213
+ } // tslint:disable-next-line:no-console
1214
+
1215
+
1216
+ return;
1217
+ } // Start implementation
1218
+
1219
+
1220
+ var dispose = implementation(this.state.context, activity);
1221
+ this.spawnEffect(activity.id, dispose);
1222
+ };
1223
+
1224
+ Interpreter.prototype.spawnEffect = function (id, dispose) {
1225
+ this.children.set(id, {
1226
+ id: id,
1227
+ send: function () {
1228
+ return void 0;
1229
+ },
1230
+ subscribe: function () {
1231
+ return {
1232
+ unsubscribe: function () {
1233
+ return void 0;
1234
+ }
1235
+ };
1236
+ },
1237
+ stop: dispose || undefined,
1238
+ getSnapshot: function () {
1239
+ return undefined;
1240
+ },
1241
+ toJSON: function () {
1242
+ return {
1243
+ id: id
1244
+ };
1245
+ }
1246
+ });
1247
+ };
1248
+
1249
+ Interpreter.prototype.attachDev = function () {
1250
+ var global = devTools.getGlobal();
1251
+
1252
+ if (this.options.devTools && global) {
1253
+ if (global.__REDUX_DEVTOOLS_EXTENSION__) {
1254
+ var devToolsOptions = typeof this.options.devTools === 'object' ? this.options.devTools : undefined;
1255
+ this.devTools = global.__REDUX_DEVTOOLS_EXTENSION__.connect(_tslib.__assign(_tslib.__assign({
1256
+ name: this.id,
1257
+ autoPause: true,
1258
+ stateSanitizer: function (state) {
1259
+ return {
1260
+ value: state.value,
1261
+ context: state.context,
1262
+ actions: state.actions
1263
+ };
1264
+ }
1265
+ }, devToolsOptions), {
1266
+ features: _tslib.__assign({
1267
+ jump: false,
1268
+ skip: false
1269
+ }, devToolsOptions ? devToolsOptions.features : undefined)
1270
+ }), this.machine);
1271
+ this.devTools.init(this.state);
1272
+ } // add XState-specific dev tooling hook
1273
+
1274
+
1275
+ devTools.registerService(this);
1276
+ }
1277
+ };
1278
+
1279
+ Interpreter.prototype.toJSON = function () {
1280
+ return {
1281
+ id: this.id
1056
1282
  };
1057
- /**
1058
- * The default interpreter options:
1059
- *
1060
- * - `clock` uses the global `setTimeout` and `clearTimeout` functions
1061
- * - `logger` uses the global `console.log()` method
1062
- */
1063
- Interpreter.defaultOptions = (function (global) { return ({
1064
- execute: true,
1065
- deferEvents: true,
1066
- clock: {
1067
- setTimeout: function (fn, ms) {
1068
- return setTimeout(fn, ms);
1069
- },
1070
- clearTimeout: function (id) {
1071
- return clearTimeout(id);
1072
- }
1283
+ };
1284
+
1285
+ Interpreter.prototype[utils.symbolObservable] = function () {
1286
+ return this;
1287
+ }; // this gets stripped by Babel to avoid having "undefined" property in environments without this non-standard Symbol
1288
+ // it has to be here to be included in the generated .d.ts
1289
+
1290
+
1291
+ Interpreter.prototype.getSnapshot = function () {
1292
+ if (this.status === exports.InterpreterStatus.NotStarted) {
1293
+ return this.initialState;
1294
+ }
1295
+
1296
+ return this._state;
1297
+ };
1298
+ /**
1299
+ * The default interpreter options:
1300
+ *
1301
+ * - `clock` uses the global `setTimeout` and `clearTimeout` functions
1302
+ * - `logger` uses the global `console.log()` method
1303
+ */
1304
+
1305
+
1306
+ Interpreter.defaultOptions = /*#__PURE__*/function (global) {
1307
+ return {
1308
+ execute: true,
1309
+ deferEvents: true,
1310
+ clock: {
1311
+ setTimeout: function (fn, ms) {
1312
+ return setTimeout(fn, ms);
1073
1313
  },
1074
- logger: global.console.log.bind(console),
1075
- devTools: false
1076
- }); })(typeof self !== 'undefined' ? self : global);
1077
- Interpreter.interpret = interpret;
1078
- return Interpreter;
1079
- }());
1080
- exports.Interpreter = Interpreter;
1314
+ clearTimeout: function (id) {
1315
+ return clearTimeout(id);
1316
+ }
1317
+ },
1318
+ logger: global.console.log.bind(console),
1319
+ devTools: false
1320
+ };
1321
+ }(typeof self !== 'undefined' ? self : global);
1322
+
1323
+ Interpreter.interpret = interpret;
1324
+ return Interpreter;
1325
+ }();
1326
+
1081
1327
  var resolveSpawnOptions = function (nameOrOptions) {
1082
- if (utils_1.isString(nameOrOptions)) {
1083
- return __assign(__assign({}, DEFAULT_SPAWN_OPTIONS), { name: nameOrOptions });
1084
- }
1085
- return __assign(__assign(__assign({}, DEFAULT_SPAWN_OPTIONS), { name: utils_1.uniqueId() }), nameOrOptions);
1328
+ if (utils.isString(nameOrOptions)) {
1329
+ return _tslib.__assign(_tslib.__assign({}, DEFAULT_SPAWN_OPTIONS), {
1330
+ name: nameOrOptions
1331
+ });
1332
+ }
1333
+
1334
+ return _tslib.__assign(_tslib.__assign(_tslib.__assign({}, DEFAULT_SPAWN_OPTIONS), {
1335
+ name: utils.uniqueId()
1336
+ }), nameOrOptions);
1086
1337
  };
1338
+
1087
1339
  function spawn(entity, nameOrOptions) {
1088
- var resolvedOptions = resolveSpawnOptions(nameOrOptions);
1089
- return serviceScope.consume(function (service) {
1090
- if (!environment_1.IS_PRODUCTION) {
1091
- var isLazyEntity = utils_1.isMachine(entity) || utils_1.isFunction(entity);
1092
- utils_1.warn(!!service || isLazyEntity, "Attempted to spawn an Actor (ID: \"" + (utils_1.isMachine(entity) ? entity.id : 'undefined') + "\") outside of a service. This will have no effect.");
1093
- }
1094
- if (service) {
1095
- return service.spawn(entity, resolvedOptions.name, resolvedOptions);
1096
- }
1097
- else {
1098
- return Actor_1.createDeferredActor(entity, resolvedOptions.name);
1099
- }
1100
- });
1340
+ var resolvedOptions = resolveSpawnOptions(nameOrOptions);
1341
+ return serviceScope.consume(function (service) {
1342
+ if (!environment.IS_PRODUCTION) {
1343
+ var isLazyEntity = utils.isMachine(entity) || utils.isFunction(entity);
1344
+ utils.warn(!!service || isLazyEntity, "Attempted to spawn an Actor (ID: \"" + (utils.isMachine(entity) ? entity.id : 'undefined') + "\") outside of a service. This will have no effect.");
1345
+ }
1346
+
1347
+ if (service) {
1348
+ return service.spawn(entity, resolvedOptions.name, resolvedOptions);
1349
+ } else {
1350
+ return Actor.createDeferredActor(entity, resolvedOptions.name);
1351
+ }
1352
+ });
1101
1353
  }
1102
- exports.spawn = spawn;
1103
- /**
1104
- * Creates a new Interpreter instance for the given machine with the provided options, if any.
1105
- *
1106
- * @param machine The machine to interpret
1107
- * @param options Interpreter options
1354
+ /**
1355
+ * Creates a new Interpreter instance for the given machine with the provided options, if any.
1356
+ *
1357
+ * @param machine The machine to interpret
1358
+ * @param options Interpreter options
1108
1359
  */
1360
+
1109
1361
  function interpret(machine, options) {
1110
- var interpreter = new Interpreter(machine, options);
1111
- return interpreter;
1362
+ var interpreter = new Interpreter(machine, options);
1363
+ return interpreter;
1112
1364
  }
1365
+
1366
+ exports.Interpreter = Interpreter;
1113
1367
  exports.interpret = interpret;
1368
+ exports.spawn = spawn;