Files
30-seconds-of-code/node_modules/xstate/lib/StateTree.js
2019-08-20 15:52:05 +02:00

385 lines
15 KiB
JavaScript

"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