interpreter.js 43 KB

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