"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 __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; }; 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 }; } }; }; Object.defineProperty(exports, "__esModule", { value: true }); var utils_1 = require("./utils"); var utils_2 = require("./utils"); var actions_1 = require("./actions"); var defaultStateTreeOptions = { resolved: false }; var StateTree = /** @class */ (function () { function StateTree(stateNode, stateValue, options, parent) { var _this = this; var _a; if (options === void 0) { options = defaultStateTreeOptions; } this.stateNode = stateNode; this.stateValue = stateValue; this.parent = parent; this.reentryNodes = new Set(); this.root = this.parent ? this.parent.root : this; this.nodes = stateValue ? utils_1.isString(stateValue) ? (_a = {}, _a[stateValue] = new StateTree(stateNode.getStateNode(stateValue), undefined, undefined, this), _a) : utils_1.mapValues(stateValue, function (subValue, key) { return new StateTree(stateNode.getStateNode(key), subValue, undefined, _this); }) : {}; var resolvedOptions = __assign({}, defaultStateTreeOptions, options); this.isResolved = resolvedOptions.resolved; } Object.defineProperty(StateTree.prototype, "done", { get: function () { var _this = this; switch (this.stateNode.type) { case 'final': return true; case 'compound': var childTree = this.nodes[utils_1.keys(this.nodes)[0]]; return childTree.stateNode.type === 'final'; case 'parallel': return utils_1.keys(this.nodes).every(function (key) { return _this.nodes[key].done; }); default: return false; } }, enumerable: true, configurable: true }); StateTree.prototype.getDoneData = function (context, event) { if (!this.done) { return undefined; } if (this.stateNode.type === 'compound') { var childTree = this.nodes[utils_1.keys(this.nodes)[0]]; if (!childTree.stateNode.data) { return undefined; } return utils_1.mapContext(childTree.stateNode.data, context, event); } return undefined; }; Object.defineProperty(StateTree.prototype, "atomicNodes", { get: function () { var _this = this; if (this.stateNode.type === 'atomic' || this.stateNode.type === 'final') { return [this.stateNode]; } return utils_1.flatten(utils_1.keys(this.value).map(function (key) { return _this.value[key].atomicNodes; })); }, enumerable: true, configurable: true }); StateTree.prototype.getDoneEvents = function (entryStateNodes) { var _this = this; // If no state nodes are being entered, no done events will be fired if (!entryStateNodes || !entryStateNodes.size) { return []; } if (entryStateNodes.has(this.stateNode) && this.stateNode.type === 'final') { return [actions_1.done(this.stateNode.id, this.stateNode.data)]; } var childDoneEvents = utils_1.flatten(utils_1.keys(this.nodes).map(function (key) { return _this.nodes[key].getDoneEvents(entryStateNodes); })); if (this.stateNode.type === 'parallel') { var allChildrenDone = utils_1.keys(this.nodes).every(function (key) { return _this.nodes[key].done; }); if (childDoneEvents && allChildrenDone) { return childDoneEvents.concat(actions_1.done(this.stateNode.id)); } else { return childDoneEvents; } } if (!this.done || !childDoneEvents.length) { return childDoneEvents; } // TODO: handle merging strategy // For compound state nodes with final child state, there should be only // one done.state event (potentially with data). var doneData = childDoneEvents.length === 1 ? childDoneEvents[0].data : undefined; return childDoneEvents.concat(actions_1.done(this.stateNode.id, doneData)); }; Object.defineProperty(StateTree.prototype, "resolved", { get: function () { var newStateTree = new StateTree(this.stateNode, this.stateNode.resolve(this.value), { resolved: true }); newStateTree.reentryNodes = this.reentryNodes; return newStateTree; }, enumerable: true, configurable: true }); Object.defineProperty(StateTree.prototype, "paths", { get: function () { return utils_1.toStatePaths(this.value); }, enumerable: true, configurable: true }); Object.defineProperty(StateTree.prototype, "absolute", { get: function () { var _stateValue = this.stateValue; var absoluteStateValue = {}; var marker = absoluteStateValue; for (var i = 0; i < this.stateNode.path.length; i++) { var key = this.stateNode.path[i]; if (i === this.stateNode.path.length - 1) { marker[key] = _stateValue; } else { marker[key] = {}; marker = marker[key]; } } var newStateTree = new StateTree(this.stateNode.machine, absoluteStateValue); newStateTree.reentryNodes = this.reentryNodes; return newStateTree; }, enumerable: true, configurable: true }); Object.defineProperty(StateTree.prototype, "nextEvents", { get: function () { var _this = this; var ownEvents = this.stateNode.ownEvents; var childEvents = utils_1.flatten(utils_1.keys(this.nodes).map(function (key) { var subTree = _this.nodes[key]; return subTree.nextEvents; })); return __spread(new Set(childEvents.concat(ownEvents))); }, enumerable: true, configurable: true }); StateTree.prototype.clone = function () { var newStateTree = new StateTree(this.stateNode, this.value, undefined, this.parent); return newStateTree; }; StateTree.prototype.combine = function (tree) { var _a, e_1, _b; if (tree.stateNode !== this.stateNode) { throw new Error('Cannot combine distinct trees'); } var newTree = this.clone(); tree.root.reentryNodes.forEach(function (reentryNode) { newTree.root.addReentryNode(reentryNode); }); if (this.stateNode.type === 'compound') { // Only combine if no child state is defined var newValue = void 0; if (!utils_1.keys(this.nodes).length || !utils_1.keys(tree.nodes).length) { newValue = Object.assign({}, this.nodes, tree.nodes); newTree.nodes = newValue; return newTree; } else { var childKey = utils_1.keys(this.nodes)[0]; newValue = (_a = {}, _a[childKey] = this.nodes[childKey].combine(tree.nodes[childKey]), _a); newTree.nodes = newValue; return newTree; } } if (this.stateNode.type === 'parallel') { var valueKeys = new Set(__spread(utils_1.keys(this.nodes), utils_1.keys(tree.nodes))); var newValue = {}; try { for (var valueKeys_1 = __values(valueKeys), valueKeys_1_1 = valueKeys_1.next(); !valueKeys_1_1.done; valueKeys_1_1 = valueKeys_1.next()) { var key = valueKeys_1_1.value; if (!this.nodes[key] || !tree.nodes[key]) { newValue[key] = this.nodes[key] || tree.nodes[key]; } else { newValue[key] = this.nodes[key].combine(tree.nodes[key]); } } } catch (e_1_1) { e_1 = { error: e_1_1 }; } finally { try { if (valueKeys_1_1 && !valueKeys_1_1.done && (_b = valueKeys_1.return)) _b.call(valueKeys_1); } finally { if (e_1) throw e_1.error; } } newTree.nodes = newValue; return newTree; } // nothing to do return this; }; Object.defineProperty(StateTree.prototype, "value", { get: function () { if (this.stateNode.type === 'atomic' || this.stateNode.type === 'final') { return {}; } if (this.stateNode.type === 'parallel') { return utils_1.mapValues(this.nodes, function (st) { return st.value; }); } if (this.stateNode.type === 'compound') { if (utils_1.keys(this.nodes).length === 0) { return {}; } var childStateNode = this.nodes[utils_1.keys(this.nodes)[0]].stateNode; if (childStateNode.type === 'atomic' || childStateNode.type === 'final') { return childStateNode.key; } return utils_1.mapValues(this.nodes, function (st) { return st.value; }); } return {}; }, enumerable: true, configurable: true }); StateTree.prototype.matches = function (parentValue) { return utils_2.matchesState(parentValue, this.value); }; StateTree.prototype.getEntryExitStates = function (prevTree) { var _this = this; var e_2, _a; var externalNodes = this.root.reentryNodes; if (!prevTree) { // Initial state return { exit: [], entry: __spread(externalNodes) }; } if (prevTree.stateNode !== this.stateNode) { throw new Error('Cannot compare distinct trees'); } switch (this.stateNode.type) { case 'compound': var compoundResult = { exit: [], entry: [] }; var currentChildKey = utils_1.keys(this.nodes)[0]; var prevChildKey = utils_1.keys(prevTree.nodes)[0]; if (currentChildKey !== prevChildKey) { compoundResult.exit = prevTree.nodes[prevChildKey].getExitStates(); compoundResult.entry = this.nodes[currentChildKey].getEntryStates(); } else { compoundResult = this.nodes[currentChildKey].getEntryExitStates(prevTree.nodes[prevChildKey]); } if (externalNodes && externalNodes.has(this.stateNode)) { compoundResult.exit.push(this.stateNode); compoundResult.entry.unshift(this.stateNode); } return compoundResult; case 'parallel': var all = utils_1.keys(this.nodes).map(function (key) { return _this.nodes[key].getEntryExitStates(prevTree.nodes[key]); }); var parallelResult = { exit: [], entry: [] }; try { for (var all_1 = __values(all), all_1_1 = all_1.next(); !all_1_1.done; all_1_1 = all_1.next()) { var ees = all_1_1.value; parallelResult.exit = __spread(parallelResult.exit, ees.exit); parallelResult.entry = __spread(parallelResult.entry, ees.entry); } } catch (e_2_1) { e_2 = { error: e_2_1 }; } finally { try { if (all_1_1 && !all_1_1.done && (_a = all_1.return)) _a.call(all_1); } finally { if (e_2) throw e_2.error; } } if (externalNodes && externalNodes.has(this.stateNode)) { parallelResult.exit.push(this.stateNode); parallelResult.entry.unshift(this.stateNode); } return parallelResult; case 'atomic': default: if (externalNodes && externalNodes.has(this.stateNode)) { return { exit: [this.stateNode], entry: [this.stateNode] }; } return { exit: [], entry: [] }; } }; StateTree.prototype.getEntryStates = function () { var _this = this; if (!this.nodes) { return [this.stateNode]; } return [this.stateNode].concat(utils_1.flatten(utils_1.keys(this.nodes).map(function (key) { return _this.nodes[key].getEntryStates(); }))); }; StateTree.prototype.getExitStates = function () { var _this = this; if (!this.nodes) { return [this.stateNode]; } return utils_1.flatten(utils_1.keys(this.nodes).map(function (key) { return _this.nodes[key].getExitStates(); })).concat(this.stateNode); }; StateTree.prototype.addReentryNode = function (reentryNode) { this.root.reentryNodes.add(reentryNode); }; return StateTree; }()); exports.StateTree = StateTree; //# sourceMappingURL=StateTree.js.map