"use strict"; var __assign = (this && this.__assign) || function () { __assign = Object.assign || function(t) { for (var s, i = 1, n = arguments.length; i < n; i++) { s = arguments[i]; for (var p in s) if (Object.prototype.hasOwnProperty.call(s, p)) t[p] = s[p]; } return t; }; return __assign.apply(this, arguments); }; var __values = (this && this.__values) || function (o) { var m = typeof Symbol === "function" && o[Symbol.iterator], i = 0; if (m) return m.call(o); return { next: function () { if (o && i >= o.length) o = void 0; return { value: o && o[i++], done: !o }; } }; }; var __read = (this && this.__read) || function (o, n) { var m = typeof Symbol === "function" && o[Symbol.iterator]; if (!m) return o; var i = m.call(o), r, ar = [], e; try { while ((n === void 0 || n-- > 0) && !(r = i.next()).done) ar.push(r.value); } catch (error) { e = { error: error }; } finally { try { if (r && !r.done && (m = i["return"])) m.call(i); } finally { if (e) throw e.error; } } return ar; }; var __spread = (this && this.__spread) || function () { for (var ar = [], i = 0; i < arguments.length; i++) ar = ar.concat(__read(arguments[i])); return ar; }; Object.defineProperty(exports, "__esModule", { value: true }); var types_1 = require("./types"); var State_1 = require("./State"); var actionTypes = require("./actionTypes"); var actions_1 = require("./actions"); var environment_1 = require("./environment"); var utils_1 = require("./utils"); var scheduler_1 = require("./scheduler"); var Actor_1 = require("./Actor"); var DEFAULT_SPAWN_OPTIONS = { sync: false, autoForward: false }; /** * Maintains a stack of the current service in scope. * This is used to provide the correct service to spawn(). * * @private */ var withServiceScope = (function () { var serviceStack = []; return function (service, fn) { service && serviceStack.push(service); var result = fn(service || serviceStack[serviceStack.length - 1]); service && serviceStack.pop(); return result; }; })(); var Interpreter = /** @class */ (function () { /** * Creates a new Interpreter instance (i.e., service) for the given machine with the provided options, if any. * * @param machine The machine to be interpreted * @param options Interpreter options */ function Interpreter(machine, options) { var _this = this; if (options === void 0) { options = Interpreter.defaultOptions; } this.machine = machine; this.scheduler = new scheduler_1.Scheduler(); this.delayedEventsMap = {}; this.listeners = new Set(); this.contextListeners = new Set(); this.stopListeners = new Set(); this.doneListeners = new Set(); this.eventListeners = new Set(); this.sendListeners = new Set(); /** * Whether the service is started. */ this.initialized = false; this.children = new Map(); this.forwardTo = new Set(); /** * Alias for Interpreter.prototype.start */ this.init = this.start; /** * Sends an event to the running interpreter to trigger a transition. * * An array of events (batched) can be sent as well, which will send all * batched events to the running interpreter. The listeners will be * notified only **once** when all events are processed. * * @param event The event(s) to send */ this.send = function (event, payload) { if (utils_1.isArray(event)) { _this.batch(event); return _this.state; } var eventObject = actions_1.toEventObject(event, payload); if (!_this.initialized && _this.options.deferEvents) { // tslint:disable-next-line:no-console if (!environment_1.IS_PRODUCTION) { utils_1.warn(false, "Event \"" + eventObject.type + "\" was sent to uninitialized service \"" + _this.machine.id + "\" and is deferred. Make sure .start() is called for this service.\nEvent: " + JSON.stringify(event)); } } else if (!_this.initialized) { throw new Error("Event \"" + eventObject.type + "\" 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(eventObject)); } _this.scheduler.schedule(function () { var nextState = _this.nextState(eventObject); _this.update(nextState, eventObject); // Forward copy of event to child interpreters _this.forward(eventObject); }); return _this.state; // TODO: deprecate (should return void) // tslint:disable-next-line:semicolon }; this.sendTo = function (event, to) { var isParent = to === types_1.SpecialTargets.Parent; var target = isParent ? _this.parent : Actor_1.isActor(to) ? to : _this.children.get(to); if (!target) { if (!isParent) { throw new Error("Unable to send event to child '" + to + "' from service '" + _this.id + "'."); } // tslint:disable-next-line:no-console if (!environment_1.IS_PRODUCTION) { utils_1.warn(false, "Service '" + _this.id + "' has no parent: unable to send event " + event.type); } return; } target.send(event); }; var resolvedOptions = __assign({}, Interpreter.defaultOptions, options); var clock = resolvedOptions.clock, logger = resolvedOptions.logger, parent = resolvedOptions.parent, id = resolvedOptions.id; var resolvedId = id !== undefined ? id : machine.id; this.id = resolvedId; this.logger = logger; this.clock = clock; this.parent = parent; this.options = resolvedOptions; this.scheduler = new scheduler_1.Scheduler({ deferEvents: this.options.deferEvents }); this.initialState = this.state = withServiceScope(this, function () { return _this.machine.initialState; }); } /** * Executes the actions of the given state, with that state's `context` and `event`. * * @param state The state whose actions will be executed * @param actionsConfig The action implementations to use */ Interpreter.prototype.execute = function (state, actionsConfig) { var e_1, _a; try { for (var _b = __values(state.actions), _c = _b.next(); !_c.done; _c = _b.next()) { var action = _c.value; this.exec(action, state.context, state.event, actionsConfig); } } catch (e_1_1) { e_1 = { error: e_1_1 }; } finally { try { if (_c && !_c.done && (_a = _b.return)) _a.call(_b); } finally { if (e_1) throw e_1.error; } } }; Interpreter.prototype.update = function (state, event) { var e_2, _a, e_3, _b, e_4, _c, e_5, _d; // Update state this.state = state; // Execute actions if (this.options.execute) { this.execute(this.state); } // Dev tools if (this.devTools) { this.devTools.send(event, state); } // Execute listeners if (state.event) { try { for (var _e = __values(this.eventListeners), _f = _e.next(); !_f.done; _f = _e.next()) { var listener = _f.value; listener(state.event); } } catch (e_2_1) { e_2 = { error: e_2_1 }; } finally { try { if (_f && !_f.done && (_a = _e.return)) _a.call(_e); } finally { if (e_2) throw e_2.error; } } } try { for (var _g = __values(this.listeners), _h = _g.next(); !_h.done; _h = _g.next()) { var listener = _h.value; listener(state, state.event); } } catch (e_3_1) { e_3 = { error: e_3_1 }; } finally { try { if (_h && !_h.done && (_b = _g.return)) _b.call(_g); } finally { if (e_3) throw e_3.error; } } try { for (var _j = __values(this.contextListeners), _k = _j.next(); !_k.done; _k = _j.next()) { var contextListener = _k.value; contextListener(this.state.context, this.state.history ? this.state.history.context : undefined); } } catch (e_4_1) { e_4 = { error: e_4_1 }; } finally { try { if (_k && !_k.done && (_c = _j.return)) _c.call(_j); } finally { if (e_4) throw e_4.error; } } if (this.state.tree && this.state.tree.done) { // get donedata var doneData = this.state.tree.getDoneData(this.state.context, actions_1.toEventObject(event)); try { for (var _l = __values(this.doneListeners), _m = _l.next(); !_m.done; _m = _l.next()) { var listener = _m.value; listener(actions_1.doneInvoke(this.id, doneData)); } } catch (e_5_1) { e_5 = { error: e_5_1 }; } finally { try { if (_m && !_m.done && (_d = _l.return)) _d.call(_l); } finally { if (e_5) throw e_5.error; } } this.stop(); } }; /* * Adds a listener that is notified whenever a state transition happens. The listener is called with * the next state and the event object that caused the state transition. * * @param listener The state listener */ Interpreter.prototype.onTransition = function (listener) { this.listeners.add(listener); return this; }; Interpreter.prototype.subscribe = function (nextListener, // @ts-ignore errorListener, completeListener) { var _this = this; if (nextListener) { this.onTransition(nextListener); } if (completeListener) { this.onDone(completeListener); } return { unsubscribe: function () { nextListener && _this.listeners.delete(nextListener); completeListener && _this.doneListeners.delete(completeListener); } }; }; /** * Adds an event listener that is notified whenever an event is sent to the running interpreter. * @param listener The event listener */ Interpreter.prototype.onEvent = function (listener) { this.eventListeners.add(listener); return this; }; /** * Adds an event listener that is notified whenever a `send` event occurs. * @param listener The event listener */ Interpreter.prototype.onSend = function (listener) { this.sendListeners.add(listener); return this; }; /** * Adds a context listener that is notified whenever the state context changes. * @param listener The context listener */ Interpreter.prototype.onChange = function (listener) { this.contextListeners.add(listener); return this; }; /** * Adds a listener that is notified when the machine is stopped. * @param listener The listener */ Interpreter.prototype.onStop = function (listener) { this.stopListeners.add(listener); return this; }; /** * Adds a state listener that is notified when the statechart has reached its final state. * @param listener The state listener */ Interpreter.prototype.onDone = function (listener) { this.doneListeners.add(listener); return this; }; /** * Removes a listener. * @param listener The listener to remove */ Interpreter.prototype.off = function (listener) { this.listeners.delete(listener); this.eventListeners.delete(listener); this.sendListeners.delete(listener); this.stopListeners.delete(listener); this.doneListeners.delete(listener); this.contextListeners.delete(listener); return this; }; /** * Starts the interpreter from the given state, or the initial state. * @param initialState The state to start the statechart from */ Interpreter.prototype.start = function (initialState) { var _this = this; if (this.initialized) { // Do not restart the service if it is already started return this; } this.initialized = true; var resolvedState = withServiceScope(this, function () { return initialState === undefined ? _this.machine.initialState : initialState instanceof State_1.State ? _this.machine.resolveState(initialState) : _this.machine.resolveState(State_1.State.from(initialState)); }); if (this.options.devTools) { this.attachDev(); } this.scheduler.initialize(function () { _this.update(resolvedState, { type: actionTypes.init }); }); return this; }; /** * Stops the interpreter and unsubscribe all listeners. * * This will also notify the `onStop` listeners. */ Interpreter.prototype.stop = function () { var e_6, _a, e_7, _b, e_8, _c, e_9, _d, e_10, _e; try { for (var _f = __values(this.listeners), _g = _f.next(); !_g.done; _g = _f.next()) { var listener = _g.value; this.listeners.delete(listener); } } catch (e_6_1) { e_6 = { error: e_6_1 }; } finally { try { if (_g && !_g.done && (_a = _f.return)) _a.call(_f); } finally { if (e_6) throw e_6.error; } } try { for (var _h = __values(this.stopListeners), _j = _h.next(); !_j.done; _j = _h.next()) { var listener = _j.value; // call listener, then remove listener(); this.stopListeners.delete(listener); } } catch (e_7_1) { e_7 = { error: e_7_1 }; } finally { try { if (_j && !_j.done && (_b = _h.return)) _b.call(_h); } finally { if (e_7) throw e_7.error; } } try { for (var _k = __values(this.contextListeners), _l = _k.next(); !_l.done; _l = _k.next()) { var listener = _l.value; this.contextListeners.delete(listener); } } catch (e_8_1) { e_8 = { error: e_8_1 }; } finally { try { if (_l && !_l.done && (_c = _k.return)) _c.call(_k); } finally { if (e_8) throw e_8.error; } } try { for (var _m = __values(this.doneListeners), _o = _m.next(); !_o.done; _o = _m.next()) { var listener = _o.value; this.doneListeners.delete(listener); } } catch (e_9_1) { e_9 = { error: e_9_1 }; } finally { try { if (_o && !_o.done && (_d = _m.return)) _d.call(_m); } finally { if (e_9) throw e_9.error; } } // Stop all children this.children.forEach(function (child) { if (utils_1.isFunction(child.stop)) { child.stop(); } }); try { // Cancel all delayed events for (var _p = __values(utils_1.keys(this.delayedEventsMap)), _q = _p.next(); !_q.done; _q = _p.next()) { var key = _q.value; this.clock.clearTimeout(this.delayedEventsMap[key]); } } catch (e_10_1) { e_10 = { error: e_10_1 }; } finally { try { if (_q && !_q.done && (_e = _p.return)) _e.call(_p); } finally { if (e_10) throw e_10.error; } } this.initialized = false; return this; }; Interpreter.prototype.batch = function (events) { var _this = this; if (!this.initialized && this.options.deferEvents) { // tslint:disable-next-line:no-console if (!environment_1.IS_PRODUCTION) { 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)); } } else if (!this.initialized) { throw new Error( // tslint:disable-next-line:max-line-length 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."); } this.scheduler.schedule(function () { var e_11, _a, _b; var nextState = _this.state; try { for (var events_1 = __values(events), events_1_1 = events_1.next(); !events_1_1.done; events_1_1 = events_1.next()) { var event_1 = events_1_1.value; var changed = nextState.changed; var eventObject = actions_1.toEventObject(event_1); var actions = nextState.actions.map(function (a) { return utils_1.bindActionToState(a, nextState); }); nextState = _this.machine.transition(nextState, eventObject); (_b = nextState.actions).unshift.apply(_b, __spread(actions)); nextState.changed = nextState.changed || !!changed; _this.forward(eventObject); } } catch (e_11_1) { e_11 = { error: e_11_1 }; } finally { try { if (events_1_1 && !events_1_1.done && (_a = events_1.return)) _a.call(events_1); } finally { if (e_11) throw e_11.error; } } _this.update(nextState, actions_1.toEventObject(events[events.length - 1])); }); }; /** * Returns a send function bound to this interpreter instance. * * @param event The event to be sent by the sender. */ Interpreter.prototype.sender = function (event) { return this.send.bind(this, event); }; /** * Returns the next state given the interpreter's current state and the event. * * This is a pure method that does _not_ update the interpreter's state. * * @param event The event to determine the next state */ Interpreter.prototype.nextState = function (event) { var _this = this; var eventObject = actions_1.toEventObject(event); if (eventObject.type.indexOf(actionTypes.errorPlatform) === 0 && !this.state.nextEvents.some(function (nextEvent) { return nextEvent.indexOf(actionTypes.errorPlatform) === 0; })) { throw eventObject.data; } var nextState = withServiceScope(this, function () { return _this.machine.transition(_this.state, eventObject, _this.state.context); }); return nextState; }; Interpreter.prototype.forward = function (event) { var e_12, _a; try { for (var _b = __values(this.forwardTo), _c = _b.next(); !_c.done; _c = _b.next()) { var id = _c.value; var child = this.children.get(id); if (!child) { throw new Error("Unable to forward event '" + event + "' from interpreter '" + this.id + "' to nonexistant child '" + id + "'."); } child.send(event); } } catch (e_12_1) { e_12 = { error: e_12_1 }; } finally { try { if (_c && !_c.done && (_a = _b.return)) _a.call(_b); } finally { if (e_12) throw e_12.error; } } }; Interpreter.prototype.defer = function (sendAction) { var _this = this; var delay = sendAction.delay; if (utils_1.isString(delay)) { if (!this.machine.options.delays || this.machine.options.delays[delay] === undefined) { // tslint:disable-next-line:no-console if (!environment_1.IS_PRODUCTION) { utils_1.warn(false, // tslint:disable-next-line:max-line-length "No delay reference for delay expression '" + delay + "' was found on machine '" + this.machine.id + "' on service '" + this.id + "'."); } // Do not send anything return; } else { var delayExpr = this.machine.options.delays[delay]; delay = typeof delayExpr === 'number' ? delayExpr : delayExpr(this.state.context, this.state.event); } } this.delayedEventsMap[sendAction.id] = this.clock.setTimeout(function () { if (sendAction.to) { _this.sendTo(sendAction.event, sendAction.to); } else { _this.send(sendAction.event); } }, delay || 0); }; Interpreter.prototype.cancel = function (sendId) { this.clock.clearTimeout(this.delayedEventsMap[sendId]); delete this.delayedEventsMap[sendId]; }; Interpreter.prototype.exec = function (action, context, event, actionFunctionMap) { var actionOrExec = actions_1.getActionFunction(action.type, actionFunctionMap) || action.exec; var exec = utils_1.isFunction(actionOrExec) ? actionOrExec : actionOrExec ? actionOrExec.exec : action.exec; if (exec) { // @ts-ignore (TODO: fix for TypeDoc) return exec(context, event, { action: action, state: this.state }); } switch (action.type) { case actionTypes.send: var sendAction = action; if (sendAction.delay) { this.defer(sendAction); return; } else { if (sendAction.to) { this.sendTo(sendAction.event, sendAction.to); } else { this.send(sendAction.event); } } break; case actionTypes.cancel: this.cancel(action.sendId); break; case actionTypes.start: { var activity = action .activity; // If the activity will be stopped right after it's started // (such as in transient states) // don't bother starting the activity. if (!this.state.activities[activity.type]) { break; } // Invoked services if (activity.type === types_1.ActionTypes.Invoke) { var serviceCreator = this .machine.options.services ? this.machine.options.services[activity.src] : undefined; var id = activity.id, data = activity.data; if (!environment_1.IS_PRODUCTION) { utils_1.warn(!('forward' in activity), // tslint:disable-next-line:max-line-length "`forward` property is deprecated (found in invocation of '" + activity.src + "' in in machine '" + this.machine.id + "'). " + "Please use `autoForward` instead."); } var autoForward = 'autoForward' in activity ? activity.autoForward : !!activity.forward; if (!serviceCreator) { // tslint:disable-next-line:no-console if (!environment_1.IS_PRODUCTION) { utils_1.warn(false, "No service found for invocation '" + activity.src + "' in machine '" + this.machine.id + "'."); } return; } var source = utils_1.isFunction(serviceCreator) ? serviceCreator(context, event) : serviceCreator; if (utils_1.isPromiseLike(source)) { this.spawnPromise(Promise.resolve(source), id); } else if (utils_1.isFunction(source)) { this.spawnCallback(source, id); } else if (utils_1.isObservable(source)) { this.spawnObservable(source, id); } else if (utils_1.isMachine(source)) { // TODO: try/catch here this.spawnMachine(data ? source.withContext(utils_1.mapContext(data, context, event)) : source, { id: id, autoForward: autoForward }); } else { // service is string } } else { this.spawnActivity(activity); } break; } case actionTypes.stop: { this.stopChild(action.activity.id); break; } case actionTypes.log: var expr = action.expr ? action.expr(context, event) : undefined; if (action.label) { this.logger(action.label, expr); } else { this.logger(expr); } break; default: if (!environment_1.IS_PRODUCTION) { utils_1.warn(false, "No implementation found for action type '" + action.type + "'"); } break; } return undefined; }; Interpreter.prototype.stopChild = function (childId) { var child = this.children.get(childId); if (!child) { return; } this.children.delete(childId); this.forwardTo.delete(childId); if (utils_1.isFunction(child.stop)) { child.stop(); } }; Interpreter.prototype.spawn = function (entity, name, options) { if (utils_1.isPromiseLike(entity)) { return this.spawnPromise(Promise.resolve(entity), name); } else if (utils_1.isFunction(entity)) { return this.spawnCallback(entity, name); } else if (utils_1.isObservable(entity)) { return this.spawnObservable(entity, name); } else if (utils_1.isMachine(entity)) { return this.spawnMachine(entity, __assign({}, options, { id: name })); } else { throw new Error("Unable to spawn entity \"" + name + "\" of type \"" + typeof entity + "\"."); } }; Interpreter.prototype.spawnMachine = function (machine, options) { var _this = this; if (options === void 0) { options = {}; } var childService = new Interpreter(machine, __assign({}, this.options, { parent: this, id: options.id || machine.id })); var resolvedOptions = __assign({}, DEFAULT_SPAWN_OPTIONS, options); if (resolvedOptions.sync) { childService.onTransition(function (state) { _this.send(actionTypes.update, { state: state, id: childService.id }); }); } childService .onDone(function (doneEvent) { _this.send(doneEvent); }) .start(); var actor = childService; // const actor = { // id: childService.id, // send: childService.send, // state: childService.state, // subscribe: childService.subscribe, // toJSON() { // return { id: childService.id }; // } // } as Actor>; this.children.set(childService.id, actor); if (resolvedOptions.autoForward) { this.forwardTo.add(childService.id); } return actor; }; Interpreter.prototype.spawnPromise = function (promise, id) { var _this = this; var canceled = false; promise.then(function (response) { if (!canceled) { _this.send(actions_1.doneInvoke(id, response)); } }, function (errorData) { if (!canceled) { var errorEvent = actions_1.error(id, errorData); try { // Send "error.execution" to this (parent). _this.send(errorEvent); } catch (error) { _this.reportUnhandledExceptionOnInvocation(errorData, error, id); if (_this.devTools) { _this.devTools.send(errorEvent, _this.state); } if (_this.machine.strict) { // it would be better to always stop the state machine if unhandled // exception/promise rejection happens but because we don't want to // break existing code so enforce it on strict mode only especially so // because documentation says that onError is optional _this.stop(); } } } }); var actor = { id: id, send: function () { return void 0; }, subscribe: function (next, handleError, complete) { var unsubscribed = false; promise.then(function (response) { if (unsubscribed) { return; } next && next(response); if (unsubscribed) { return; } complete && complete(); }, function (err) { if (unsubscribed) { return; } handleError(err); }); return { unsubscribe: function () { return (unsubscribed = true); } }; }, stop: function () { canceled = true; }, toJSON: function () { return { id: id }; } }; this.children.set(id, actor); return actor; }; Interpreter.prototype.spawnCallback = function (callback, id) { var _this = this; var canceled = false; var receive = function (e) { if (canceled) { return; } _this.send(e); }; var listeners = new Set(); var callbackStop; try { callbackStop = callback(receive, function (newListener) { listeners.add(newListener); }); } catch (err) { this.send(actions_1.error(id, err)); } if (utils_1.isPromiseLike(callbackStop)) { // it turned out to be an async function, can't reliably check this before calling `callback` // because transpiled async functions are not recognizable return this.spawnPromise(callbackStop, id); } var actor = { id: id, send: function (event) { return listeners.forEach(function (listener) { return listener(event); }); }, subscribe: function (next) { listeners.add(next); return { unsubscribe: function () { listeners.delete(next); } }; }, stop: function () { canceled = true; if (utils_1.isFunction(callbackStop)) { callbackStop(); } }, toJSON: function () { return { id: id }; } }; this.children.set(id, actor); return actor; }; Interpreter.prototype.spawnObservable = function (source, id) { var _this = this; var subscription = source.subscribe(function (value) { _this.send(value); }, function (err) { _this.send(actions_1.error(id, err)); }, function () { _this.send(actions_1.doneInvoke(id)); }); var actor = { id: id, send: function () { return void 0; }, subscribe: function (next, handleError, complete) { return source.subscribe(next, handleError, complete); }, stop: function () { return subscription.unsubscribe(); }, toJSON: function () { return { id: id }; } }; this.children.set(id, actor); return actor; }; Interpreter.prototype.spawnActivity = function (activity) { var implementation = this.machine.options && this.machine.options.activities ? this.machine.options.activities[activity.type] : undefined; if (!implementation) { // tslint:disable-next-line:no-console if (!environment_1.IS_PRODUCTION) { utils_1.warn(false, "No implementation found for activity '" + activity.type + "'"); } return; } // Start implementation var dispose = implementation(this.state.context, activity); this.spawnEffect(activity.id, dispose); }; Interpreter.prototype.spawnEffect = function (id, dispose) { this.children.set(id, { id: id, send: function () { return void 0; }, subscribe: function () { return { unsubscribe: function () { return void 0; } }; }, stop: dispose || undefined, toJSON: function () { return { id: id }; } }); }; Interpreter.prototype.reportUnhandledExceptionOnInvocation = function (originalError, currentError, id) { if (!environment_1.IS_PRODUCTION) { var originalStackTrace = originalError.stack ? " Stacktrace was '" + originalError.stack + "'" : ''; if (originalError === currentError) { // tslint:disable-next-line:no-console console.error("Missing onError handler for invocation '" + id + "', error was '" + originalError + "'." + originalStackTrace); } else { var stackTrace = currentError.stack ? " Stacktrace was '" + currentError.stack + "'" : ''; // tslint:disable-next-line:no-console console.error("Missing onError handler and/or unhandled exception/promise rejection for invocation '" + id + "'. " + ("Original error: '" + originalError + "'. " + originalStackTrace + " Current error is '" + currentError + "'." + stackTrace)); } } }; Interpreter.prototype.attachDev = function () { if (this.options.devTools && typeof window !== 'undefined' && window.__REDUX_DEVTOOLS_EXTENSION__) { var devToolsOptions = typeof this.options.devTools === 'object' ? this.options.devTools : undefined; this.devTools = window.__REDUX_DEVTOOLS_EXTENSION__.connect(__assign({ name: this.id, autoPause: true, stateSanitizer: function (state) { return { value: state.value, context: state.context, actions: state.actions }; } }, devToolsOptions, { features: __assign({ jump: false, skip: false }, (devToolsOptions ? devToolsOptions.features : undefined)) })); this.devTools.init(this.state); } }; Interpreter.prototype.toJSON = function () { return { id: this.id }; }; /** * The default interpreter options: * * - `clock` uses the global `setTimeout` and `clearTimeout` functions * - `logger` uses the global `console.log()` method */ Interpreter.defaultOptions = (function (global) { return ({ execute: true, deferEvents: true, clock: { setTimeout: function (fn, ms) { return global.setTimeout.call(null, fn, ms); }, clearTimeout: function (id) { return global.clearTimeout.call(null, id); } }, logger: global.console.log.bind(console), devTools: false }); })(typeof window === 'undefined' ? global : window); Interpreter.interpret = interpret; return Interpreter; }()); exports.Interpreter = Interpreter; var createNullActor = function (name) { if (name === void 0) { name = 'null'; } return ({ id: name, send: function () { return void 0; }, subscribe: function () { // tslint:disable-next-line:no-empty return { unsubscribe: function () { } }; }, toJSON: function () { return ({ id: name }); } }); }; var resolveSpawnOptions = function (nameOrOptions) { if (utils_1.isString(nameOrOptions)) { return __assign({}, DEFAULT_SPAWN_OPTIONS, { name: nameOrOptions }); } return __assign({}, DEFAULT_SPAWN_OPTIONS, { name: utils_1.uniqueId() }, nameOrOptions); }; function spawn(entity, nameOrOptions) { var resolvedOptions = resolveSpawnOptions(nameOrOptions); return withServiceScope(undefined, function (service) { if (!environment_1.IS_PRODUCTION) { utils_1.warn(!!service, "Attempted to spawn an Actor (ID: \"" + (utils_1.isMachine(entity) ? entity.id : 'undefined') + "\") outside of a service. This will have no effect."); } if (service) { return service.spawn(entity, resolvedOptions.name, resolvedOptions); } else { return createNullActor(resolvedOptions.name); } }); } exports.spawn = spawn; /** * Creates a new Interpreter instance for the given machine with the provided options, if any. * * @param machine The machine to interpret * @param options Interpreter options */ function interpret(machine, options) { var interpreter = new Interpreter(machine, options); return interpreter; } exports.interpret = interpret; //# sourceMappingURL=interpreter.js.map