xstate 4.32.0 → 4.33.1

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/es/interpreter.js CHANGED
@@ -1,13 +1,12 @@
1
1
  import { __values, __spreadArray, __read, __assign } from './_virtual/_tslib.js';
2
- import { ActionTypes, SpecialTargets } from './types.js';
2
+ import { SpecialTargets, ActionTypes } from './types.js';
3
3
  import { isStateConfig, State, bindActionToState } from './State.js';
4
- import { errorPlatform, log, stop, start, cancel, send, update, error as error$1 } from './actionTypes.js';
5
- import { doneInvoke, initEvent, getActionFunction, error } from './actions.js';
4
+ import { raise, send, errorPlatform, update, error as error$1, log, stop, start, cancel } from './actionTypes.js';
5
+ import { initEvent, doneInvoke, toActionObjects, resolveActions, error, getActionFunction } from './actions.js';
6
6
  import { IS_PRODUCTION } from './environment.js';
7
- import { warn, mapContext, isFunction, toSCXMLEvent, toInvokeSource, isMachine, isPromiseLike, isObservable, isBehavior, reportUnhandledExceptionOnInvocation, symbolObservable, isArray, toEventObject, isString, isActor, uniqueId, toObserver } from './utils.js';
7
+ import { warn, mapContext, toObserver, toSCXMLEvent, flatten, isFunction, isPromiseLike, isObservable, isMachine, isBehavior, reportUnhandledExceptionOnInvocation, symbolObservable, isArray, toEventObject, isString, isActor, toInvokeSource, uniqueId } from './utils.js';
8
8
  import { Scheduler } from './scheduler.js';
9
- import { isSpawnedActor, createDeferredActor } from './Actor.js';
10
- import { isInFinalState } from './stateUtils.js';
9
+ import { createDeferredActor, isSpawnedActor } from './Actor.js';
11
10
  import { registry } from './registry.js';
12
11
  import { getGlobal, registerService } from './devTools.js';
13
12
  import { provide, consume } from './serviceScope.js';
@@ -101,7 +100,7 @@ function () {
101
100
  // Forward copy of event to child actors
102
101
  _this.forward(_event);
103
102
 
104
- var nextState = _this.nextState(_event);
103
+ var nextState = _this._nextState(_event);
105
104
 
106
105
  _this.update(nextState, _event);
107
106
  });
@@ -128,17 +127,176 @@ function () {
128
127
  }
129
128
 
130
129
  if ('machine' in target) {
131
- // Send SCXML events to machines
132
- target.send(__assign(__assign({}, event), {
133
- name: event.name === error$1 ? "".concat(error(_this.id)) : event.name,
134
- origin: _this.sessionId
135
- }));
130
+ // perhaps those events should be rejected in the parent
131
+ // but atm it doesn't have easy access to all of the information that is required to do it reliably
132
+ if (_this.status !== InterpreterStatus.Stopped || _this.parent !== target || // we need to send events to the parent from exit handlers of a machine that reached its final state
133
+ _this.state.done) {
134
+ // Send SCXML events to machines
135
+ target.send(__assign(__assign({}, event), {
136
+ name: event.name === error$1 ? "".concat(error(_this.id)) : event.name,
137
+ origin: _this.sessionId
138
+ }));
139
+ }
136
140
  } else {
137
141
  // Send normal events to other targets
138
142
  target.send(event.data);
139
143
  }
140
144
  };
141
145
 
146
+ this._exec = function (action, context, _event, actionFunctionMap) {
147
+ if (actionFunctionMap === void 0) {
148
+ actionFunctionMap = _this.machine.options.actions;
149
+ }
150
+
151
+ var actionOrExec = action.exec || getActionFunction(action.type, actionFunctionMap);
152
+ var exec = isFunction(actionOrExec) ? actionOrExec : actionOrExec ? actionOrExec.exec : action.exec;
153
+
154
+ if (exec) {
155
+ try {
156
+ return exec(context, _event.data, !_this.machine.config.predictableActionArguments ? {
157
+ action: action,
158
+ state: _this.state,
159
+ _event: _event
160
+ } : {
161
+ action: action,
162
+ _event: _event
163
+ });
164
+ } catch (err) {
165
+ if (_this.parent) {
166
+ _this.parent.send({
167
+ type: 'xstate.error',
168
+ data: err
169
+ });
170
+ }
171
+
172
+ throw err;
173
+ }
174
+ }
175
+
176
+ switch (action.type) {
177
+ case send:
178
+ var sendAction = action;
179
+
180
+ if (typeof sendAction.delay === 'number') {
181
+ _this.defer(sendAction);
182
+
183
+ return;
184
+ } else {
185
+ if (sendAction.to) {
186
+ _this.sendTo(sendAction._event, sendAction.to);
187
+ } else {
188
+ _this.send(sendAction._event);
189
+ }
190
+ }
191
+
192
+ break;
193
+
194
+ case cancel:
195
+ _this.cancel(action.sendId);
196
+
197
+ break;
198
+
199
+ case start:
200
+ {
201
+ if (_this.status !== InterpreterStatus.Running) {
202
+ return;
203
+ }
204
+
205
+ var activity = action.activity; // If the activity will be stopped right after it's started
206
+ // (such as in transient states)
207
+ // don't bother starting the activity.
208
+
209
+ if ( // in v4 with `predictableActionArguments` invokes are called eagerly when the `this.state` still points to the previous state
210
+ !_this.machine.config.predictableActionArguments && !_this.state.activities[activity.id || activity.type]) {
211
+ break;
212
+ } // Invoked services
213
+
214
+
215
+ if (activity.type === ActionTypes.Invoke) {
216
+ var invokeSource = toInvokeSource(activity.src);
217
+ var serviceCreator = _this.machine.options.services ? _this.machine.options.services[invokeSource.type] : undefined;
218
+ var id = activity.id,
219
+ data = activity.data;
220
+
221
+ if (!IS_PRODUCTION) {
222
+ warn(!('forward' in activity), // tslint:disable-next-line:max-line-length
223
+ "`forward` property is deprecated (found in invocation of '".concat(activity.src, "' in in machine '").concat(_this.machine.id, "'). ") + "Please use `autoForward` instead.");
224
+ }
225
+
226
+ var autoForward = 'autoForward' in activity ? activity.autoForward : !!activity.forward;
227
+
228
+ if (!serviceCreator) {
229
+ // tslint:disable-next-line:no-console
230
+ if (!IS_PRODUCTION) {
231
+ warn(false, "No service found for invocation '".concat(activity.src, "' in machine '").concat(_this.machine.id, "'."));
232
+ }
233
+
234
+ return;
235
+ }
236
+
237
+ var resolvedData = data ? mapContext(data, context, _event) : undefined;
238
+
239
+ if (typeof serviceCreator === 'string') {
240
+ // TODO: warn
241
+ return;
242
+ }
243
+
244
+ var source = isFunction(serviceCreator) ? serviceCreator(context, _event.data, {
245
+ data: resolvedData,
246
+ src: invokeSource,
247
+ meta: activity.meta
248
+ }) : serviceCreator;
249
+
250
+ if (!source) {
251
+ // TODO: warn?
252
+ return;
253
+ }
254
+
255
+ var options = void 0;
256
+
257
+ if (isMachine(source)) {
258
+ source = resolvedData ? source.withContext(resolvedData) : source;
259
+ options = {
260
+ autoForward: autoForward
261
+ };
262
+ }
263
+
264
+ _this.spawn(source, id, options);
265
+ } else {
266
+ _this.spawnActivity(activity);
267
+ }
268
+
269
+ break;
270
+ }
271
+
272
+ case stop:
273
+ {
274
+ _this.stopChild(action.activity.id);
275
+
276
+ break;
277
+ }
278
+
279
+ case log:
280
+ var label = action.label,
281
+ value = action.value;
282
+
283
+ if (label) {
284
+ _this.logger(label, value);
285
+ } else {
286
+ _this.logger(value);
287
+ }
288
+
289
+ break;
290
+
291
+ default:
292
+ if (!IS_PRODUCTION) {
293
+ warn(false, "No implementation found for action type '".concat(action.type, "'"));
294
+ }
295
+
296
+ break;
297
+ }
298
+ };
299
+
142
300
  var resolvedOptions = __assign(__assign({}, Interpreter.defaultOptions), options);
143
301
 
144
302
  var clock = resolvedOptions.clock,
@@ -222,7 +380,9 @@ function () {
222
380
 
223
381
  this._state = state; // Execute actions
224
382
 
225
- if (this.options.execute) {
383
+ if ((!this.machine.config.predictableActionArguments || // this is currently required to execute initial actions as the `initialState` gets cached
384
+ // we can't just recompute it (and execute actions while doing so) because we try to preserve identity of actors created within initial assigns
385
+ _event === initEvent) && this.options.execute) {
226
386
  this.execute(this.state);
227
387
  } // Update children
228
388
 
@@ -289,9 +449,7 @@ function () {
289
449
  }
290
450
  }
291
451
 
292
- var isDone = isInFinalState(state.configuration || [], this.machine);
293
-
294
- if (this.state.configuration && isDone) {
452
+ if (this.state.done) {
295
453
  // get final child state node
296
454
  var finalChildStateNode = state.configuration.find(function (sn) {
297
455
  return sn.type === 'final' && sn.parent === _this.machine;
@@ -315,7 +473,7 @@ function () {
315
473
  }
316
474
  }
317
475
 
318
- this.stop();
476
+ this._stop();
319
477
  }
320
478
  };
321
479
  /*
@@ -340,42 +498,35 @@ function () {
340
498
  completeListener) {
341
499
  var _this = this;
342
500
 
343
- if (!nextListenerOrObserver) {
344
- return {
345
- unsubscribe: function () {
346
- return void 0;
347
- }
348
- };
349
- }
501
+ var observer = toObserver(nextListenerOrObserver, _, completeListener);
502
+ this.listeners.add(observer.next); // Send current state to listener
350
503
 
351
- var listener;
352
- var resolvedCompleteListener = completeListener;
353
-
354
- if (typeof nextListenerOrObserver === 'function') {
355
- listener = nextListenerOrObserver;
356
- } else {
357
- listener = nextListenerOrObserver.next.bind(nextListenerOrObserver);
358
- resolvedCompleteListener = nextListenerOrObserver.complete.bind(nextListenerOrObserver);
504
+ if (this.status !== InterpreterStatus.NotStarted) {
505
+ observer.next(this.state);
359
506
  }
360
507
 
361
- this.listeners.add(listener); // Send current state to listener
508
+ var completeOnce = function () {
509
+ _this.doneListeners.delete(completeOnce);
362
510
 
363
- if (this.status !== InterpreterStatus.NotStarted) {
364
- listener(this.state);
365
- }
511
+ _this.stopListeners.delete(completeOnce);
366
512
 
367
- if (resolvedCompleteListener) {
368
- if (this.status === InterpreterStatus.Stopped) {
369
- resolvedCompleteListener();
370
- } else {
371
- this.onDone(resolvedCompleteListener);
372
- }
513
+ observer.complete();
514
+ };
515
+
516
+ if (this.status === InterpreterStatus.Stopped) {
517
+ observer.complete();
518
+ } else {
519
+ this.onDone(completeOnce);
520
+ this.onStop(completeOnce);
373
521
  }
374
522
 
375
523
  return {
376
524
  unsubscribe: function () {
377
- listener && _this.listeners.delete(listener);
378
- resolvedCompleteListener && _this.doneListeners.delete(resolvedCompleteListener);
525
+ _this.listeners.delete(observer.next);
526
+
527
+ _this.doneListeners.delete(completeOnce);
528
+
529
+ _this.stopListeners.delete(completeOnce);
379
530
  }
380
531
  };
381
532
  };
@@ -480,18 +631,10 @@ function () {
480
631
  });
481
632
  return this;
482
633
  };
483
- /**
484
- * Stops the interpreter and unsubscribe all listeners.
485
- *
486
- * This will also notify the `onStop` listeners.
487
- */
488
634
 
489
-
490
- Interpreter.prototype.stop = function () {
635
+ Interpreter.prototype._stop = function () {
491
636
  var e_6, _a, e_7, _b, e_8, _c, e_9, _d, e_10, _e;
492
637
 
493
- var _this = this;
494
-
495
638
  try {
496
639
  for (var _f = __values(this.listeners), _g = _f.next(); !_g.done; _g = _f.next()) {
497
640
  var listener = _g.value;
@@ -567,40 +710,13 @@ function () {
567
710
  return this;
568
711
  }
569
712
 
570
- __spreadArray([], __read(this.state.configuration), false).sort(function (a, b) {
571
- return b.order - a.order;
572
- }).forEach(function (stateNode) {
573
- var e_11, _a;
574
-
575
- try {
576
- for (var _b = __values(stateNode.definition.exit), _c = _b.next(); !_c.done; _c = _b.next()) {
577
- var action = _c.value;
578
-
579
- _this.exec(action, _this.state);
580
- }
581
- } catch (e_11_1) {
582
- e_11 = {
583
- error: e_11_1
584
- };
585
- } finally {
586
- try {
587
- if (_c && !_c.done && (_a = _b.return)) _a.call(_b);
588
- } finally {
589
- if (e_11) throw e_11.error;
590
- }
591
- }
592
- }); // Stop all children
593
-
594
-
595
- this.children.forEach(function (child) {
596
- if (isFunction(child.stop)) {
597
- child.stop();
598
- }
599
- });
600
- this.children.clear();
713
+ this.initialized = false;
714
+ this.status = InterpreterStatus.Stopped;
715
+ this._initialState = undefined;
601
716
 
602
717
  try {
603
- // Cancel all delayed events
718
+ // we are going to stop within the current sync frame
719
+ // so we can safely just cancel this here as nothing async should be fired anyway
604
720
  for (var _p = __values(Object.keys(this.delayedEventsMap)), _q = _p.next(); !_q.done; _q = _p.next()) {
605
721
  var key = _q.value;
606
722
  this.clock.clearTimeout(this.delayedEventsMap[key]);
@@ -615,16 +731,85 @@ function () {
615
731
  } finally {
616
732
  if (e_10) throw e_10.error;
617
733
  }
618
- }
734
+ } // clear everything that might be enqueued
735
+
619
736
 
620
737
  this.scheduler.clear();
621
738
  this.scheduler = new Scheduler({
622
739
  deferEvents: this.options.deferEvents
623
740
  });
624
- this.initialized = false;
625
- this.status = InterpreterStatus.Stopped;
626
- this._initialState = undefined;
627
- registry.free(this.sessionId);
741
+ };
742
+ /**
743
+ * Stops the interpreter and unsubscribe all listeners.
744
+ *
745
+ * This will also notify the `onStop` listeners.
746
+ */
747
+
748
+
749
+ Interpreter.prototype.stop = function () {
750
+ // TODO: add warning for stopping non-root interpreters
751
+ var _this = this; // grab the current scheduler as it will be replaced in _stop
752
+
753
+
754
+ var scheduler = this.scheduler;
755
+
756
+ this._stop(); // let what is currently processed to be finished
757
+
758
+
759
+ scheduler.schedule(function () {
760
+ // it feels weird to handle this here but we need to handle this even slightly "out of band"
761
+ var _event = toSCXMLEvent({
762
+ type: 'xstate.stop'
763
+ });
764
+
765
+ var nextState = provide(_this, function () {
766
+ var exitActions = flatten(__spreadArray([], __read(_this.state.configuration), false).sort(function (a, b) {
767
+ return b.order - a.order;
768
+ }).map(function (stateNode) {
769
+ return toActionObjects(stateNode.onExit, _this.machine.options.actions);
770
+ }));
771
+
772
+ var _a = __read(resolveActions(_this.machine, _this.state, _this.state.context, _event, exitActions, _this.machine.config.predictableActionArguments ? _this._exec : undefined, _this.machine.config.predictableActionArguments || _this.machine.config.preserveActionOrder), 2),
773
+ resolvedActions = _a[0],
774
+ updatedContext = _a[1];
775
+
776
+ var newState = new State({
777
+ value: _this.state.value,
778
+ context: updatedContext,
779
+ _event: _event,
780
+ _sessionid: _this.sessionId,
781
+ historyValue: undefined,
782
+ history: _this.state,
783
+ actions: resolvedActions.filter(function (action) {
784
+ return action.type !== raise && (action.type !== send || !!action.to && action.to !== SpecialTargets.Internal);
785
+ }),
786
+ activities: {},
787
+ events: [],
788
+ configuration: [],
789
+ transitions: [],
790
+ children: {},
791
+ done: _this.state.done,
792
+ tags: _this.state.tags,
793
+ machine: _this.machine
794
+ });
795
+ newState.changed = true;
796
+ return newState;
797
+ });
798
+
799
+ _this.update(nextState, _event); // TODO: think about converting those to actions
800
+ // Stop all children
801
+
802
+
803
+ _this.children.forEach(function (child) {
804
+ if (isFunction(child.stop)) {
805
+ child.stop();
806
+ }
807
+ });
808
+
809
+ _this.children.clear();
810
+
811
+ registry.free(_this.sessionId);
812
+ });
628
813
  return this;
629
814
  };
630
815
 
@@ -642,7 +827,7 @@ function () {
642
827
  }
643
828
 
644
829
  this.scheduler.schedule(function () {
645
- var e_12, _a;
830
+ var e_11, _a;
646
831
 
647
832
  var nextState = _this.state;
648
833
  var batchChanged = false;
@@ -668,15 +853,15 @@ function () {
668
853
 
669
854
  _loop_1(event_1);
670
855
  }
671
- } catch (e_12_1) {
672
- e_12 = {
673
- error: e_12_1
856
+ } catch (e_11_1) {
857
+ e_11 = {
858
+ error: e_11_1
674
859
  };
675
860
  } finally {
676
861
  try {
677
862
  if (events_1_1 && !events_1_1.done && (_a = events_1.return)) _a.call(events_1);
678
863
  } finally {
679
- if (e_12) throw e_12.error;
864
+ if (e_11) throw e_11.error;
680
865
  }
681
866
  }
682
867
 
@@ -696,18 +881,14 @@ function () {
696
881
  Interpreter.prototype.sender = function (event) {
697
882
  return this.send.bind(this, event);
698
883
  };
699
- /**
700
- * Returns the next state given the interpreter's current state and the event.
701
- *
702
- * This is a pure method that does _not_ update the interpreter's state.
703
- *
704
- * @param event The event to determine the next state
705
- */
706
-
707
884
 
708
- Interpreter.prototype.nextState = function (event) {
885
+ Interpreter.prototype._nextState = function (event, exec) {
709
886
  var _this = this;
710
887
 
888
+ if (exec === void 0) {
889
+ exec = !!this.machine.config.predictableActionArguments && this._exec;
890
+ }
891
+
711
892
  var _event = toSCXMLEvent(event);
712
893
 
713
894
  if (_event.name.indexOf(errorPlatform) === 0 && !this.state.nextEvents.some(function (nextEvent) {
@@ -717,13 +898,25 @@ function () {
717
898
  }
718
899
 
719
900
  var nextState = provide(this, function () {
720
- return _this.machine.transition(_this.state, _event);
901
+ return _this.machine.transition(_this.state, _event, undefined, exec || undefined);
721
902
  });
722
903
  return nextState;
723
904
  };
905
+ /**
906
+ * Returns the next state given the interpreter's current state and the event.
907
+ *
908
+ * This is a pure method that does _not_ update the interpreter's state.
909
+ *
910
+ * @param event The event to determine the next state
911
+ */
912
+
913
+
914
+ Interpreter.prototype.nextState = function (event) {
915
+ return this._nextState(event, false);
916
+ };
724
917
 
725
918
  Interpreter.prototype.forward = function (event) {
726
- var e_13, _a;
919
+ var e_12, _a;
727
920
 
728
921
  try {
729
922
  for (var _b = __values(this.forwardTo), _c = _b.next(); !_c.done; _c = _b.next()) {
@@ -736,15 +929,15 @@ function () {
736
929
 
737
930
  child.send(event);
738
931
  }
739
- } catch (e_13_1) {
740
- e_13 = {
741
- error: e_13_1
932
+ } catch (e_12_1) {
933
+ e_12 = {
934
+ error: e_12_1
742
935
  };
743
936
  } finally {
744
937
  try {
745
938
  if (_c && !_c.done && (_a = _b.return)) _a.call(_b);
746
939
  } finally {
747
- if (e_13) throw e_13.error;
940
+ if (e_12) throw e_12.error;
748
941
  }
749
942
  }
750
943
  };
@@ -771,150 +964,7 @@ function () {
771
964
  actionFunctionMap = this.machine.options.actions;
772
965
  }
773
966
 
774
- var context = state.context,
775
- _event = state._event;
776
- var actionOrExec = action.exec || getActionFunction(action.type, actionFunctionMap);
777
- var exec = isFunction(actionOrExec) ? actionOrExec : actionOrExec ? actionOrExec.exec : action.exec;
778
-
779
- if (exec) {
780
- try {
781
- return exec(context, _event.data, {
782
- action: action,
783
- state: this.state,
784
- _event: _event
785
- });
786
- } catch (err) {
787
- if (this.parent) {
788
- this.parent.send({
789
- type: 'xstate.error',
790
- data: err
791
- });
792
- }
793
-
794
- throw err;
795
- }
796
- }
797
-
798
- switch (action.type) {
799
- case send:
800
- var sendAction = action;
801
-
802
- if (typeof sendAction.delay === 'number') {
803
- this.defer(sendAction);
804
- return;
805
- } else {
806
- if (sendAction.to) {
807
- this.sendTo(sendAction._event, sendAction.to);
808
- } else {
809
- this.send(sendAction._event);
810
- }
811
- }
812
-
813
- break;
814
-
815
- case cancel:
816
- this.cancel(action.sendId);
817
- break;
818
-
819
- case start:
820
- {
821
- if (this.status !== InterpreterStatus.Running) {
822
- return;
823
- }
824
-
825
- var activity = action.activity; // If the activity will be stopped right after it's started
826
- // (such as in transient states)
827
- // don't bother starting the activity.
828
-
829
- if (!this.state.activities[activity.id || activity.type]) {
830
- break;
831
- } // Invoked services
832
-
833
-
834
- if (activity.type === ActionTypes.Invoke) {
835
- var invokeSource = toInvokeSource(activity.src);
836
- var serviceCreator = this.machine.options.services ? this.machine.options.services[invokeSource.type] : undefined;
837
- var id = activity.id,
838
- data = activity.data;
839
-
840
- if (!IS_PRODUCTION) {
841
- warn(!('forward' in activity), // tslint:disable-next-line:max-line-length
842
- "`forward` property is deprecated (found in invocation of '".concat(activity.src, "' in in machine '").concat(this.machine.id, "'). ") + "Please use `autoForward` instead.");
843
- }
844
-
845
- var autoForward = 'autoForward' in activity ? activity.autoForward : !!activity.forward;
846
-
847
- if (!serviceCreator) {
848
- // tslint:disable-next-line:no-console
849
- if (!IS_PRODUCTION) {
850
- warn(false, "No service found for invocation '".concat(activity.src, "' in machine '").concat(this.machine.id, "'."));
851
- }
852
-
853
- return;
854
- }
855
-
856
- var resolvedData = data ? mapContext(data, context, _event) : undefined;
857
-
858
- if (typeof serviceCreator === 'string') {
859
- // TODO: warn
860
- return;
861
- }
862
-
863
- var source = isFunction(serviceCreator) ? serviceCreator(context, _event.data, {
864
- data: resolvedData,
865
- src: invokeSource,
866
- meta: activity.meta
867
- }) : serviceCreator;
868
-
869
- if (!source) {
870
- // TODO: warn?
871
- return;
872
- }
873
-
874
- var options = void 0;
875
-
876
- if (isMachine(source)) {
877
- source = resolvedData ? source.withContext(resolvedData) : source;
878
- options = {
879
- autoForward: autoForward
880
- };
881
- }
882
-
883
- this.spawn(source, id, options);
884
- } else {
885
- this.spawnActivity(activity);
886
- }
887
-
888
- break;
889
- }
890
-
891
- case stop:
892
- {
893
- this.stopChild(action.activity.id);
894
- break;
895
- }
896
-
897
- case log:
898
- var label = action.label,
899
- value = action.value;
900
-
901
- if (label) {
902
- this.logger(label, value);
903
- } else {
904
- this.logger(value);
905
- }
906
-
907
- break;
908
-
909
- default:
910
- if (!IS_PRODUCTION) {
911
- warn(false, "No implementation found for action type '".concat(action.type, "'"));
912
- }
913
-
914
- break;
915
- }
916
-
917
- return undefined;
967
+ this._exec(action, state.context, state._event, actionFunctionMap);
918
968
  };
919
969
 
920
970
  Interpreter.prototype.removeChild = function (childId) {
@@ -942,6 +992,10 @@ function () {
942
992
  };
943
993
 
944
994
  Interpreter.prototype.spawn = function (entity, name, options) {
995
+ if (this.status !== InterpreterStatus.Running) {
996
+ return createDeferredActor(entity, name);
997
+ }
998
+
945
999
  if (isPromiseLike(entity)) {
946
1000
  return this.spawnPromise(Promise.resolve(entity), name);
947
1001
  } else if (isFunction(entity)) {