UNPKG

@scion-scxml/core

Version:

StateCharts Interpretation and Optimization eNgine (SCION) CORE is an implementation of Statecharts in JavaScript.

1,222 lines (1,064 loc) 167 kB
(function (global, factory) { if (typeof define === "function" && define.amd) { define(["module", "exports"], factory); } else if (typeof exports !== "undefined") { factory(module, exports); } else { var mod = { exports: {} }; factory(mod, mod.exports); global.scion = global.scion || {}; global.scion.core = mod.exports; } })(this, function (module, exports) { "use strict"; var _typeof2 = typeof Symbol === "function" && typeof Symbol.iterator === "symbol" ? function (obj) { return typeof obj; } : function (obj) { return obj && typeof Symbol === "function" && obj.constructor === Symbol && obj !== Symbol.prototype ? "symbol" : typeof obj; }; (function (f) { if ((typeof exports === "undefined" ? "undefined" : _typeof2(exports)) === "object" && typeof module !== "undefined") { module.exports = f(); } else if (typeof define === "function" && define.amd) { define([], f); } else { var g;if (typeof window !== "undefined") { g = window; } else if (typeof global !== "undefined") { g = global; } else if (typeof self !== "undefined") { g = self; } else { g = this; }g.core = f(); } })(function () { var define, module, exports;return function () { function r(e, n, t) { function o(i, f) { if (!n[i]) { if (!e[i]) { var c = "function" == typeof require && require;if (!f && c) return c(i, !0);if (u) return u(i, !0);var a = new Error("Cannot find module '" + i + "'");throw a.code = "MODULE_NOT_FOUND", a; }var p = n[i] = { exports: {} };e[i][0].call(p.exports, function (r) { var n = e[i][1][r];return o(n || r); }, p, p.exports, r, e, n, t); }return n[i].exports; }for (var u = "function" == typeof require && require, i = 0; i < t.length; i++) { o(t[i]); }return o; }return r; }()({ 1: [function (require, module, exports) { (function (setImmediate) { 'use strict'; var _createClass = function () { function defineProperties(target, props) { for (var i = 0; i < props.length; i++) { var descriptor = props[i];descriptor.enumerable = descriptor.enumerable || false;descriptor.configurable = true;if ("value" in descriptor) descriptor.writable = true;Object.defineProperty(target, descriptor.key, descriptor); } }return function (Constructor, protoProps, staticProps) { if (protoProps) defineProperties(Constructor.prototype, protoProps);if (staticProps) defineProperties(Constructor, staticProps);return Constructor; }; }(); function _toConsumableArray(arr) { if (Array.isArray(arr)) { for (var i = 0, arr2 = Array(arr.length); i < arr.length; i++) { arr2[i] = arr[i]; }return arr2; } else { return Array.from(arr); } } function _classCallCheck(instance, Constructor) { if (!(instance instanceof Constructor)) { throw new TypeError("Cannot call a class as a function"); } } function _possibleConstructorReturn(self, call) { if (!self) { throw new ReferenceError("this hasn't been initialised - super() hasn't been called"); }return call && ((typeof call === "undefined" ? "undefined" : _typeof2(call)) === "object" || typeof call === "function") ? call : self; } function _inherits(subClass, superClass) { if (typeof superClass !== "function" && superClass !== null) { throw new TypeError("Super expression must either be null or a function, not " + (typeof superClass === "undefined" ? "undefined" : _typeof2(superClass))); }subClass.prototype = Object.create(superClass && superClass.prototype, { constructor: { value: subClass, enumerable: false, writable: true, configurable: true } });if (superClass) Object.setPrototypeOf ? Object.setPrototypeOf(subClass, superClass) : subClass.__proto__ = superClass; } var base = require('@scion-scxml/core-base'), helpers = base.helpers, query = base.query, transitionComparator = base.helpers.transitionComparator; /** * @description Implements semantics described in Algorithm D of the SCXML specification. * See {@link scion.BaseInterpreter} for information on the constructor arguments. * @class SCInterpreter * @extends BaseInterpreter */ var Statechart = function (_base$BaseInterpreter) { _inherits(Statechart, _base$BaseInterpreter); function Statechart(modelOrModelFactory, opts) { _classCallCheck(this, Statechart); opts = opts || {}; opts.legacySemantics = false; return _possibleConstructorReturn(this, (Statechart.__proto__ || Object.getPrototypeOf(Statechart)).call(this, modelOrModelFactory, opts)); } /** @private */ _createClass(Statechart, [{ key: '_selectTransitions', value: function _selectTransitions(currentEvent, selectEventlessTransitions) { var transitionSelector = this.opts.transitionSelector; var enabledTransitions = new this.opts.Set(); var e = this._evaluateAction.bind(this, currentEvent); var atomicStates = this._configuration.iter().sort(transitionComparator); var _iteratorNormalCompletion = true; var _didIteratorError = false; var _iteratorError = undefined; try { for (var _iterator = atomicStates[Symbol.iterator](), _step; !(_iteratorNormalCompletion = (_step = _iterator.next()).done); _iteratorNormalCompletion = true) { var state = _step.value; var _iteratorNormalCompletion2 = true; var _didIteratorError2 = false; var _iteratorError2 = undefined; try { loop: for (var _iterator2 = [state].concat(query.getAncestors(state))[Symbol.iterator](), _step2; !(_iteratorNormalCompletion2 = (_step2 = _iterator2.next()).done); _iteratorNormalCompletion2 = true) { var s = _step2.value; var _iteratorNormalCompletion3 = true; var _didIteratorError3 = false; var _iteratorError3 = undefined; try { for (var _iterator3 = s.transitions[Symbol.iterator](), _step3; !(_iteratorNormalCompletion3 = (_step3 = _iterator3.next()).done); _iteratorNormalCompletion3 = true) { var t = _step3.value; if (transitionSelector(t, currentEvent, e, selectEventlessTransitions)) { enabledTransitions.add(t); break loop; } } } catch (err) { _didIteratorError3 = true; _iteratorError3 = err; } finally { try { if (!_iteratorNormalCompletion3 && _iterator3.return) { _iterator3.return(); } } finally { if (_didIteratorError3) { throw _iteratorError3; } } } } } catch (err) { _didIteratorError2 = true; _iteratorError2 = err; } finally { try { if (!_iteratorNormalCompletion2 && _iterator2.return) { _iterator2.return(); } } finally { if (_didIteratorError2) { throw _iteratorError2; } } } } } catch (err) { _didIteratorError = true; _iteratorError = err; } finally { try { if (!_iteratorNormalCompletion && _iterator.return) { _iterator.return(); } } finally { if (_didIteratorError) { throw _iteratorError; } } } var priorityEnabledTransitions = this._removeConflictingTransition(enabledTransitions); this._log("priorityEnabledTransitions", priorityEnabledTransitions); return priorityEnabledTransitions; } /** @private */ }, { key: '_removeConflictingTransition', value: function _removeConflictingTransition(enabledTransitions) { var _this2 = this; var filteredTransitions = new this.opts.Set(); //toList sorts the transitions in the order of the states that selected them var _iteratorNormalCompletion4 = true; var _didIteratorError4 = false; var _iteratorError4 = undefined; try { for (var _iterator4 = enabledTransitions.iter()[Symbol.iterator](), _step4; !(_iteratorNormalCompletion4 = (_step4 = _iterator4.next()).done); _iteratorNormalCompletion4 = true) { var t1 = _step4.value; var t1Preempted = false; var transitionsToRemove = new Set(); var _iteratorNormalCompletion5 = true; var _didIteratorError5 = false; var _iteratorError5 = undefined; try { var _loop = function _loop() { var t2 = _step5.value; //TODO: can we compute this statically? for example, by checking if the transition scopes are arena orthogonal? var t1ExitSet = _this2._computeExitSet([t1]); var t2ExitSet = _this2._computeExitSet([t2]); var hasIntersection = [].concat(_toConsumableArray(t1ExitSet)).some(function (s) { return t2ExitSet.has(s); }) || [].concat(_toConsumableArray(t2ExitSet)).some(function (s) { return t1ExitSet.has(s); }); _this2._log('t1ExitSet', t1.source.id, [].concat(_toConsumableArray(t1ExitSet)).map(function (s) { return s.id; })); _this2._log('t2ExitSet', t2.source.id, [].concat(_toConsumableArray(t2ExitSet)).map(function (s) { return s.id; })); _this2._log('hasIntersection', hasIntersection); if (hasIntersection) { if (t2.source.descendants.indexOf(t1.source) > -1) { //is this the same as being ancestrally related? transitionsToRemove.add(t2); } else { t1Preempted = true; return 'break'; } } }; for (var _iterator5 = filteredTransitions.iter()[Symbol.iterator](), _step5; !(_iteratorNormalCompletion5 = (_step5 = _iterator5.next()).done); _iteratorNormalCompletion5 = true) { var _ret = _loop(); if (_ret === 'break') break; } } catch (err) { _didIteratorError5 = true; _iteratorError5 = err; } finally { try { if (!_iteratorNormalCompletion5 && _iterator5.return) { _iterator5.return(); } } finally { if (_didIteratorError5) { throw _iteratorError5; } } } if (!t1Preempted) { var _iteratorNormalCompletion6 = true; var _didIteratorError6 = false; var _iteratorError6 = undefined; try { for (var _iterator6 = transitionsToRemove[Symbol.iterator](), _step6; !(_iteratorNormalCompletion6 = (_step6 = _iterator6.next()).done); _iteratorNormalCompletion6 = true) { var t3 = _step6.value; filteredTransitions.remove(t3); } } catch (err) { _didIteratorError6 = true; _iteratorError6 = err; } finally { try { if (!_iteratorNormalCompletion6 && _iterator6.return) { _iterator6.return(); } } finally { if (_didIteratorError6) { throw _iteratorError6; } } } filteredTransitions.add(t1); } } } catch (err) { _didIteratorError4 = true; _iteratorError4 = err; } finally { try { if (!_iteratorNormalCompletion4 && _iterator4.return) { _iterator4.return(); } } finally { if (_didIteratorError4) { throw _iteratorError4; } } } return filteredTransitions; } }]); return Statechart; }(base.BaseInterpreter); base.Statechart = Statechart; //simple default invoker base.InterpreterScriptingContext.invokers = { "http://www.w3.org/TR/scxml/": function httpWwwW3OrgTRScxml(invokingSession, invokeObj, invokerExecutionContext, cb) { //put invoke logic here: var method = void 0, arg = void 0; if (invokeObj.constructorFunction) { var fnModel = invokeObj.constructorFunction; var options = { invokeid: invokeObj.id, params: invokeObj.params, parentSession: invokingSession, docUrl: invokeObj.docUrl //sessionid : //TODO: construct or generate a sessionid for invoked session }; var model = invokerExecutionContext; var interpreter = void 0; if (options.parentSession instanceof Statechart) { interpreter = new Statechart(fnModel, options); } cb(null, interpreter, fnModel, model); //we introduce a delay here before starting the interpreter to give clients that are subscribed to onInvokedSessionInitialized event a chance to subscribe to events on the newly instantiated interpreter setImmediate(function () { return interpreter.start(); }); } else { throw new Error('Invoke object needs a constructorFunction property'); } } }; base.InterpreterScriptingContext.invokers[undefined] = base.InterpreterScriptingContext.invokers[null] = base.InterpreterScriptingContext.invokers['scxml'] = base.InterpreterScriptingContext.invokers["http://www.w3.org/TR/scxml/"]; module.exports = base; }).call(this, require("timers").setImmediate); }, { "@scion-scxml/core-base": 6, "timers": 9 }], 2: [function (require, module, exports) { 'use strict'; /* begin ArraySet */ /** @constructor */ function ArraySet(l) { l = l || []; this.o = new Set(l); } ArraySet.prototype = { add: function add(x) { this.o.add(x); }, remove: function remove(x) { return this.o.delete(x); }, union: function union(l) { var _iteratorNormalCompletion = true; var _didIteratorError = false; var _iteratorError = undefined; try { for (var _iterator = l.o[Symbol.iterator](), _step; !(_iteratorNormalCompletion = (_step = _iterator.next()).done); _iteratorNormalCompletion = true) { var v = _step.value; this.o.add(v); } } catch (err) { _didIteratorError = true; _iteratorError = err; } finally { try { if (!_iteratorNormalCompletion && _iterator.return) { _iterator.return(); } } finally { if (_didIteratorError) { throw _iteratorError; } } } return this; }, difference: function difference(l) { var _iteratorNormalCompletion2 = true; var _didIteratorError2 = false; var _iteratorError2 = undefined; try { for (var _iterator2 = l.o[Symbol.iterator](), _step2; !(_iteratorNormalCompletion2 = (_step2 = _iterator2.next()).done); _iteratorNormalCompletion2 = true) { var v = _step2.value; this.o.delete(v); } } catch (err) { _didIteratorError2 = true; _iteratorError2 = err; } finally { try { if (!_iteratorNormalCompletion2 && _iterator2.return) { _iterator2.return(); } } finally { if (_didIteratorError2) { throw _iteratorError2; } } } return this; }, contains: function contains(x) { return this.o.has(x); }, iter: function iter() { return Array.from(this.o); }, isEmpty: function isEmpty() { return !this.o.size; }, size: function size() { return this.o.size; }, equals: function equals(s2) { if (this.o.size !== s2.size()) { return false; } var _iteratorNormalCompletion3 = true; var _didIteratorError3 = false; var _iteratorError3 = undefined; try { for (var _iterator3 = this.o[Symbol.iterator](), _step3; !(_iteratorNormalCompletion3 = (_step3 = _iterator3.next()).done); _iteratorNormalCompletion3 = true) { var v = _step3.value; if (!s2.contains(v)) { return false; } } } catch (err) { _didIteratorError3 = true; _iteratorError3 = err; } finally { try { if (!_iteratorNormalCompletion3 && _iterator3.return) { _iterator3.return(); } } finally { if (_didIteratorError3) { throw _iteratorError3; } } } return true; }, toString: function toString() { return this.o.size === 0 ? '<empty>' : Array.from(this.o).join(',\n'); } }; module.exports = ArraySet; }, {}], 3: [function (require, module, exports) { 'use strict'; var STATE_TYPES = { BASIC: 0, COMPOSITE: 1, PARALLEL: 2, HISTORY: 3, INITIAL: 4, FINAL: 5 }; var SCXML_IOPROCESSOR_TYPE = 'http://www.w3.org/TR/scxml/#SCXMLEventProcessor'; var HTTP_IOPROCESSOR_TYPE = 'http://www.w3.org/TR/scxml/#BasicHTTPEventProcessor'; var RX_TRAILING_WILDCARD = /\.\*$/; module.exports = { STATE_TYPES: STATE_TYPES, SCXML_IOPROCESSOR_TYPE: SCXML_IOPROCESSOR_TYPE, HTTP_IOPROCESSOR_TYPE: HTTP_IOPROCESSOR_TYPE, RX_TRAILING_WILDCARD: RX_TRAILING_WILDCARD }; }, {}], 4: [function (require, module, exports) { 'use strict'; var _typeof = typeof Symbol === "function" && _typeof2(Symbol.iterator) === "symbol" ? function (obj) { return typeof obj === "undefined" ? "undefined" : _typeof2(obj); } : function (obj) { return obj && typeof Symbol === "function" && obj.constructor === Symbol && obj !== Symbol.prototype ? "symbol" : typeof obj === "undefined" ? "undefined" : _typeof2(obj); }; var constants = require('./constants'), STATE_TYPES = constants.STATE_TYPES, RX_TRAILING_WILDCARD = constants.RX_TRAILING_WILDCARD; var printTrace = false; module.exports = { extend: extend, transitionWithTargets: transitionWithTargets, transitionComparator: transitionComparator, initializeModel: initializeModel, isEventPrefixMatch: isEventPrefixMatch, isTransitionMatch: isTransitionMatch, scxmlPrefixTransitionSelector: scxmlPrefixTransitionSelector, eventlessTransitionSelector: eventlessTransitionSelector, getTransitionWithHigherSourceChildPriority: getTransitionWithHigherSourceChildPriority, sortInEntryOrder: sortInEntryOrder, getStateWithHigherSourceChildPriority: getStateWithHigherSourceChildPriority, initializeModelGeneratorFn: initializeModelGeneratorFn, deserializeSerializedConfiguration: deserializeSerializedConfiguration, deserializeHistory: deserializeHistory }; function extend(to, from) { Object.keys(from).forEach(function (k) { to[k] = from[k]; }); return to; }; function transitionWithTargets(t) { return t.targets; } function transitionComparator(t1, t2) { return t1.documentOrder - t2.documentOrder; } function initializeModel(rootState, opts) { var transitions = [], idToStateMap = new Map(), documentOrder = 0; //TODO: need to add fake ids to anyone that doesn't have them //FIXME: make this safer - break into multiple passes var idCount = {}; function generateId(type) { if (idCount[type] === undefined) idCount[type] = 0; do { var count = idCount[type]++; var id = '$generated-' + type + '-' + count; } while (idToStateMap.has(id)); return id; } function wrapInFakeRootState(state) { return { $deserializeDatamodel: state.$deserializeDatamodel || function () {}, $serializeDatamodel: state.$serializeDatamodel || function () { return null; }, $idToStateMap: idToStateMap, //keep this for handy deserialization of serialized configuration docUrl: state.docUrl, name: state.name, states: [{ $type: 'initial', transitions: [{ target: state }] }, state], modelFnName: state.modelFnName }; } var statesWithInitialAttributes = []; /** @this {SCTransition} */ function transitionToString(sourceState) { return sourceState + ' -- ' + (this.events ? '(' + this.events.join(',') + ')' : null) + (this.cond ? '[' + this.cond.name + ']' : '') + ' --> ' + (this.targets ? this.targets.join(',') : null); } /** @this {SCState} */ function stateToString() { return this.id; } function populateStateIdMap(state) { //populate state id map if (state.id) { idToStateMap.set(state.id, state); } if (state.states) { for (var j = 0, len = state.states.length; j < len; j++) { populateStateIdMap(state.states[j]); } } } function traverse(ancestors, state) { if (printTrace) state.toString = stateToString; //add to global transition and state id caches if (state.transitions) transitions.push.apply(transitions, state.transitions); //create a default type, just to normalize things //this way we can check for unsupported types below state.$type = state.$type || 'state'; //add ancestors and depth properties state.ancestors = ancestors; state.depth = ancestors.length; state.parent = ancestors[0]; state.documentOrder = documentOrder++; //add some information to transitions state.transitions = state.transitions || []; for (var j = 0, len = state.transitions.length; j < len; j++) { var transition = state.transitions[j]; transition.documentOrder = documentOrder++; transition.source = state; if (printTrace) transition.toString = transitionToString.bind(transition, state); }; //recursive step if (state.states) { var ancs = [state].concat(ancestors); for (var j = 0, len = state.states.length; j < len; j++) { traverse(ancs, state.states[j]); } } //setup fast state type switch (state.$type) { case 'parallel': state.typeEnum = STATE_TYPES.PARALLEL; state.isAtomic = false; break; case 'initial': state.typeEnum = STATE_TYPES.INITIAL; state.isAtomic = true; break; case 'history': state.typeEnum = STATE_TYPES.HISTORY; state.isAtomic = true; break; case 'final': state.typeEnum = STATE_TYPES.FINAL; state.isAtomic = true; break; case 'state': case 'scxml': if (state.states && state.states.length) { state.typeEnum = STATE_TYPES.COMPOSITE; state.isAtomic = false; } else { state.typeEnum = STATE_TYPES.BASIC; state.isAtomic = true; } break; default: throw new Error('Unknown state type: ' + state.$type); } //descendants property on states will now be populated. add descendants to this state if (state.states) { state.descendants = state.states.concat(state.states.map(function (s) { return s.descendants; }).reduce(function (a, b) { return a.concat(b); }, [])); } else { state.descendants = []; } var initialChildren; if (state.typeEnum === STATE_TYPES.COMPOSITE) { //set up initial state if (Array.isArray(state.initial) || typeof state.initial === 'string') { statesWithInitialAttributes.push(state); } else { //take the first child that has initial type, or first child initialChildren = state.states.filter(function (child) { return child.$type === 'initial'; }); state.initialRef = [initialChildren.length ? initialChildren[0] : state.states[0]]; checkInitialRef(state); } } //hook up history if (state.typeEnum === STATE_TYPES.COMPOSITE || state.typeEnum === STATE_TYPES.PARALLEL) { var historyChildren = state.states.filter(function (s) { return s.$type === 'history'; }); state.historyRef = historyChildren; } //now it's safe to fill in fake state ids if (!state.id) { state.id = generateId(state.$type); idToStateMap.set(state.id, state); } //normalize onEntry/onExit, which can be single fn or array, or array of arrays (blocks) ['onEntry', 'onExit'].forEach(function (prop) { if (state[prop]) { if (!Array.isArray(state[prop])) { state[prop] = [state[prop]]; } if (!state[prop].every(function (handler) { return Array.isArray(handler); })) { state[prop] = [state[prop]]; } } }); if (state.invokes && !Array.isArray(state.invokes)) { state.invokes = [state.invokes]; state.invokes.forEach(function (invoke) { if (invoke.finalize && !Array.isArray(invoke.finalize)) { invoke.finalize = [invoke.finalize]; } }); } } //TODO: convert events to regular expressions in advance function checkInitialRef(state) { if (!state.initialRef) throw new Error('Unable to locate initial state for composite state: ' + state.id); } function connectIntialAttributes() { for (var j = 0, len = statesWithInitialAttributes.length; j < len; j++) { var s = statesWithInitialAttributes[j]; var initialStates = Array.isArray(s.initial) ? s.initial : [s.initial]; s.initialRef = initialStates.map(function (initialState) { return idToStateMap.get(initialState); }); checkInitialRef(s); } } var RX_WHITESPACE = /\s+/; function connectTransitionGraph() { //normalize as with onEntry/onExit for (var i = 0, len = transitions.length; i < len; i++) { var t = transitions[i]; if (t.onTransition && !Array.isArray(t.onTransition)) { t.onTransition = [t.onTransition]; } //normalize "event" attribute into "events" attribute if (typeof t.event === 'string') { t.events = t.event.trim().split(RX_WHITESPACE); } delete t.event; if (t.targets || typeof t.target === 'undefined') { //targets have already been set up continue; } if (typeof t.target === 'string') { var target = idToStateMap.get(t.target); if (!target) throw new Error('Unable to find target state with id ' + t.target); t.target = target; t.targets = [t.target]; } else if (Array.isArray(t.target)) { t.targets = t.target.map(function (target) { if (typeof target === 'string') { target = idToStateMap.get(target); if (!target) throw new Error('Unable to find target state with id ' + t.target); return target; } else { return target; } }); } else if (_typeof(t.target) === 'object') { t.targets = [t.target]; } else { throw new Error('Transition target has unknown type: ' + t.target); } } //hook up LCA - optimization for (var i = 0, len = transitions.length; i < len; i++) { var t = transitions[i]; if (t.targets) t.lcca = getLCCA(t.source, t.targets[0]); //FIXME: we technically do not need to hang onto the lcca. only the scope is used by the algorithm t.scope = getScope(t); } } function getScope(transition) { //Transition scope is normally the least common compound ancestor (lcca). //Internal transitions have a scope equal to the source state. var transitionIsReallyInternal = transition.type === 'internal' && transition.source.typeEnum === STATE_TYPES.COMPOSITE && //is transition source a composite state transition.source.parent && //root state won't have parent transition.targets && //does it target its descendants transition.targets.every(function (target) { return transition.source.descendants.indexOf(target) > -1; }); if (!transition.targets) { return null; } else if (transitionIsReallyInternal) { return transition.source; } else { return transition.lcca; } } function getLCCA(s1, s2) { var commonAncestors = []; for (var j = 0, len = s1.ancestors.length; j < len; j++) { var anc = s1.ancestors[j]; if ((opts && opts.legacySemantics ? anc.typeEnum === STATE_TYPES.COMPOSITE : anc.typeEnum === STATE_TYPES.COMPOSITE || anc.typeEnum === STATE_TYPES.PARALLEL) && anc.descendants.indexOf(s2) > -1) { commonAncestors.push(anc); } }; if (!commonAncestors.length) throw new Error("Could not find LCA for states."); return commonAncestors[0]; } //main execution starts here //FIXME: only wrap in root state if it's not a compound state populateStateIdMap(rootState); var fakeRootState = wrapInFakeRootState(rootState); //I wish we had pointer semantics and could make this a C-style "out argument". Instead we return him traverse([], fakeRootState); connectTransitionGraph(); connectIntialAttributes(); return fakeRootState; } function isEventPrefixMatch(prefix, fullName) { prefix = prefix.replace(RX_TRAILING_WILDCARD, ''); if (prefix === fullName) { return true; } if (prefix.length > fullName.length) { return false; } if (fullName.charAt(prefix.length) !== '.') { return false; } return fullName.indexOf(prefix) === 0; } function isTransitionMatch(t, eventName) { return t.events.some(function (tEvent) { return tEvent === '*' || isEventPrefixMatch(tEvent, eventName); }); } function scxmlPrefixTransitionSelector(t, event, evaluator, selectEventlessTransitions) { return (selectEventlessTransitions ? !t.events : t.events && event && event.name && isTransitionMatch(t, event.name)) && (!t.cond || evaluator(t.cond)); } function eventlessTransitionSelector(state) { return state.transitions.filter(function (transition) { return !transition.events || transition.events && transition.events.length === 0; }); } //priority comparison functions function getTransitionWithHigherSourceChildPriority(_args) { var t1 = _args[0], t2 = _args[1]; var r = getStateWithHigherSourceChildPriority(t1.source, t2.source); //compare transitions based first on depth, then based on document order if (t1.source.depth < t2.source.depth) { return t2; } else if (t2.source.depth < t1.source.depth) { return t1; } else { if (t1.documentOrder < t2.documentOrder) { return t1; } else { return t2; } } } function sortInEntryOrder(s1, s2) { return getStateWithHigherSourceChildPriority(s1, s2) * -1; } function getStateWithHigherSourceChildPriority(s1, s2) { //compare states based first on depth, then based on document order if (s1.depth > s2.depth) { return -1; } else if (s1.depth < s2.depth) { return 1; } else { //Equality if (s1.documentOrder < s2.documentOrder) { return 1; } else if (s1.documentOrder > s2.documentOrder) { return -1; } else { return 0; } } } function initializeModelGeneratorFn(modelFn, opts, interpreter) { var model = modelFn.call(interpreter, opts._x, opts._x._sessionid, opts._x._ioprocessors, interpreter.isIn.bind(interpreter)); model.modelFnName = modelFn.name; return model; } function deserializeSerializedConfiguration(serializedConfiguration, idToStateMap) { return serializedConfiguration.map(function (id) { var state = idToStateMap.get(id); if (!state) throw new Error('Error loading serialized configuration. Unable to locate state with id ' + id); return state; }); } function deserializeHistory(serializedHistory, idToStateMap) { var o = {}; Object.keys(serializedHistory).forEach(function (sid) { o[sid] = serializedHistory[sid].map(function (id) { var state = idToStateMap.get(id); if (!state) throw new Error('Error loading serialized history. Unable to locate state with id ' + id); return state; }); }); return o; } }, { "./constants": 3 }], 5: [function (require, module, exports) { 'use strict'; var constants = require('./constants'); //model accessor functions var query = { isDescendant: function isDescendant(s1, s2) { //Returns 'true' if state1 is a descendant of state2 (a child, or a child of a child, or a child of a child of a child, etc.) Otherwise returns 'false'. return s2.descendants.indexOf(s1) > -1; }, getAncestors: function getAncestors(s, root) { var ancestors, index, state; index = s.ancestors.indexOf(root); if (index > -1) { return s.ancestors.slice(0, index); } else { return s.ancestors; } }, isOrthogonalTo: function isOrthogonalTo(s1, s2) { //Two control states are orthogonal if they are not ancestrally //related, and their smallest, mutual parent is a Concurrent-state. return !this.isAncestrallyRelatedTo(s1, s2) && this.getLCA(s1, s2).typeEnum === constants.STATE_TYPES.PARALLEL; }, isAncestrallyRelatedTo: function isAncestrallyRelatedTo(s1, s2) { //Two control states are ancestrally related if one is child/grandchild of another. return this.getAncestorsOrSelf(s2).indexOf(s1) > -1 || this.getAncestorsOrSelf(s1).indexOf(s2) > -1; }, getAncestorsOrSelf: function getAncestorsOrSelf(s, root) { return [s].concat(query.getAncestors(s, root)); }, getDescendantsOrSelf: function getDescendantsOrSelf(s) { return [s].concat(s.descendants); }, getLCA: function getLCA(s1, s2) { var commonAncestors = this.getAncestors(s1).filter(function (a) { return a.descendants.indexOf(s2) > -1; }, this); return commonAncestors[0]; } }; module.exports = query; }, { "./constants": 3 }], 6: [function (require, module, exports) { (function (process, setImmediate) { // Copyright 2012-2012 Jacob Beard, INFICON, and other SCION contributors // // Licensed under the Apache License, Version 2.0 (the "License"); // you may not use this file except in compliance with the License. // You may obtain a copy of the License at // // http://www.apache.org/licenses/LICENSE-2.0 // // Unless required by applicable law or agreed to in writing, software // distributed under the License is distributed on an "AS IS" BASIS, // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. // See the License for the specific language governing permissions and // limitations under the License. /** * SCION-CORE global object * @namespace scion */ /** * An Array of strings representing the ids all of the basic states the * interpreter is in after a big-step completes. * @typedef {Array<string>} Configuration */ /** * A set of basic and composite state ids. * @typedef {Array<string>} FullConfiguration */ /** * A set of basic and composite state ids. * @typedef {Array<string>} FullConfiguration */ "use strict"; var _slicedToArray = function () { function sliceIterator(arr, i) { var _arr = [];var _n = true;var _d = false;var _e = undefined;try { for (var _i = arr[Symbol.iterator](), _s; !(_n = (_s = _i.next()).done); _n = true) { _arr.push(_s.value);if (i && _arr.length === i) break; } } catch (err) { _d = true;_e = err; } finally { try { if (!_n && _i["return"]) _i["return"](); } finally { if (_d) throw _e; } }return _arr; }return function (arr, i) { if (Array.isArray(arr)) { return arr; } else if (Symbol.iterator in Object(arr)) { return sliceIterator(arr, i); } else { throw new TypeError("Invalid attempt to destructure non-iterable instance"); } }; }(); var _typeof = typeof Symbol === "function" && _typeof2(Symbol.iterator) === "symbol" ? function (obj) { return typeof obj === "undefined" ? "undefined" : _typeof2(obj); } : function (obj) { return obj && typeof Symbol === "function" && obj.constructor === Symbol && obj !== Symbol.prototype ? "symbol" : typeof obj === "undefined" ? "undefined" : _typeof2(obj); }; var _createClass = function () { function defineProperties(target, props) { for (var i = 0; i < props.length; i++) { var descriptor = props[i];descriptor.enumerable = descriptor.enumerable || false;descriptor.configurable = true;if ("value" in descriptor) descriptor.writable = true;Object.defineProperty(target, descriptor.key, descriptor); } }return function (Constructor, protoProps, staticProps) { if (protoProps) defineProperties(Constructor.prototype, protoProps);if (staticProps) defineProperties(Constructor, staticProps);return Constructor; }; }(); function _toConsumableArray(arr) { if (Array.isArray(arr)) { for (var i = 0, arr2 = Array(arr.length); i < arr.length; i++) { arr2[i] = arr[i]; }return arr2; } else { return Array.from(arr); } } function _classCallCheck(instance, Constructor) { if (!(instance instanceof Constructor)) { throw new TypeError("Cannot call a class as a function"); } } function _possibleConstructorReturn(self, call) { if (!self) { throw new ReferenceError("this hasn't been initialised - super() hasn't been called"); }return call && ((typeof call === "undefined" ? "undefined" : _typeof2(call)) === "object" || typeof call === "function") ? call : self; } function _inherits(subClass, superClass) { if (typeof superClass !== "function" && superClass !== null) { throw new TypeError("Super expression must either be null or a function, not " + (typeof superClass === "undefined" ? "undefined" : _typeof2(superClass))); }subClass.prototype = Object.create(superClass && superClass.prototype, { constructor: { value: subClass, enumerable: false, writable: true, configurable: true } });if (superClass) Object.setPrototypeOf ? Object.setPrototypeOf(subClass, superClass) : subClass.__proto__ = superClass; } var EventEmitter = require('tiny-events').EventEmitter, util = require('util'), ArraySet = require('./ArraySet'), constants = require('./constants'), helpers = require('./helpers'), query = require('./query'), extend = helpers.extend, transitionWithTargets = helpers.transitionWithTargets, transitionComparator = helpers.transitionComparator, initializeModel = helpers.initializeModel, isEventPrefixMatch = helpers.isEventPrefixMatch, isTransitionMatch = helpers.isTransitionMatch, scxmlPrefixTransitionSelector = helpers.scxmlPrefixTransitionSelector, eventlessTransitionSelector = helpers.eventlessTransitionSelector, getTransitionWithHigherSourceChildPriority = helpers.getTransitionWithHigherSourceChildPriority, sortInEntryOrder = helpers.sortInEntryOrder, getStateWithHigherSourceChildPriority = helpers.getStateWithHigherSourceChildPriority, initializeModelGeneratorFn = helpers.initializeModelGeneratorFn, deserializeSerializedConfiguration = helpers.deserializeSerializedConfiguration, deserializeHistory = helpers.deserializeHistory, BASIC = constants.STATE_TYPES.BASIC, COMPOSITE = constants.STATE_TYPES.COMPOSITE, PARALLEL = constants.STATE_TYPES.PARALLEL, HISTORY = constants.STATE_TYPES.HISTORY, INITIAL = constants.STATE_TYPES.INITIAL, FINAL = constants.STATE_TYPES.FINAL, SCXML_IOPROCESSOR_TYPE = constants.SCXML_IOPROCESSOR_TYPE; var printTrace = typeof process !== 'undefined' && !!process.env.DEBUG; /** * @interface EventEmitter */ /** * @event scion.BaseInterpreter#onError * @property {string} tagname The name of the element that produced the error. * @property {number} line The line in the source file in which the error occurred. * @property {number} column The column in the source file in which the error occurred. * @property {string} reason An informative error message. The text is platform-specific and subject to change. */ /** * @function * @name EventEmitter.prototype#on * @param {string} type * @param {callback} listener */ /** * @function * @name EventEmitter.prototype#once * @param {string} type * @param {callback} listener */ /** * @function * @name EventEmitter.prototype#off * @param {string} type * @param {callback} listener */ /** * @function * @name EventEmitter.prototype#emit * @param {string} type * @param {any} args */ /** * @description The SCXML constructor creates an interpreter instance from a model object. * @abstract * @class BaseInterpreter * @memberof scion * @extends EventEmitter * @param {SCJSON | scxml.ModelFactory} modelOrModelFactory Either an SCJSON root state; or an scxml.ModelFactory, which is a function which returns an SCJSON object. * @param opts * @param {string} [opts.sessionid] Used to populate SCXML _sessionid. * @param {function} [opts.generateSessionid] Factory used to generate sessionid if sessionid keyword is not specified * @param {Map<string, BaseInterpreter>} [opts.sessionRegistry] Map used to map sessionid strings to Statechart instances. * @param [opts.Set] Class to use as an ArraySet. Defaults to ES6 Set. * @param {object} [opts.params]