UNPKG

@tacky/store

Version:

State management framework based on react

414 lines (339 loc) 12 kB
"use strict"; var _interopRequireDefault = require("@babel/runtime/helpers/interopRequireDefault"); Object.defineProperty(exports, "__esModule", { value: true }); exports.getTimeTravelStatus = exports.redo = exports.undo = exports.historyCollector = exports.EOperationTypes = exports.depCollector = void 0; var _toConsumableArray2 = _interopRequireDefault(require("@babel/runtime/helpers/toConsumableArray")); var _defineProperty2 = _interopRequireDefault(require("@babel/runtime/helpers/defineProperty")); var _classCallCheck2 = _interopRequireDefault(require("@babel/runtime/helpers/classCallCheck")); var _createClass2 = _interopRequireDefault(require("@babel/runtime/helpers/createClass")); var _common = require("../utils/common"); var _config = require("../const/config"); var _store = require("./store"); var _uuid = _interopRequireDefault(require("../utils/uuid")); var _domain = require("./domain"); var _interfaces = require("../interfaces"); ; var isInBlackList = function isInBlackList(propKey) { var blackList = { constructor: true, properties: true, reactorConfigMap: true, propertyGet: true, propertySet: true, proxySet: true, proxyGet: true, proxyReactive: true, $update: true, illegalAssignmentCheck: true, dispatch: true }; return !!blackList[propKey]; }; /** * collect relation map of the dep key and the component ids */ var DepCollector = /*#__PURE__*/function () { function DepCollector() { (0, _classCallCheck2["default"])(this, DepCollector); this.dependencyMap = new WeakMap(); /** * Using a small amount of memory to improve execute performance */ this.reverseDependencyMap = new WeakMap(); this.componentIdStack = []; } (0, _createClass2["default"])(DepCollector, [{ key: "clearCurrentComponentOldDeps", value: function clearCurrentComponentOldDeps(id) { var _this = this; var targetToKeysMap = this.reverseDependencyMap.get(id); if (targetToKeysMap !== void 0) { targetToKeysMap.forEach(function (propKeys, targetKey) { var keyToComponentIdsMap = _this.dependencyMap.get(targetKey); if (keyToComponentIdsMap !== void 0 && Object.keys(keyToComponentIdsMap).length > 0) { for (var index = 0; index < propKeys.length; index++) { var propKey = propKeys[index]; var componentIds = keyToComponentIdsMap[propKey]; if (componentIds !== void 0 && componentIds.length > 0) { keyToComponentIdsMap[propKey] = componentIds.filter(function (cid) { return cid !== id; }); } else if (componentIds === void 0 || componentIds.length === 0) { delete keyToComponentIdsMap[propKey]; } } } else if (keyToComponentIdsMap === void 0 || Object.keys(keyToComponentIdsMap).length === 0) { _this.dependencyMap["delete"](targetKey); } }); } } }, { key: "start", value: function start(id) { this.clearCurrentComponentOldDeps(id); this.reverseDependencyMap["delete"](id); this.componentIdStack.push(id); } }, { key: "collect", value: function collect(targetKey, propKey) { if (isInBlackList(propKey)) { return; } var stackLength = this.componentIdStack.length; if (stackLength === 0) { return; } var currentComponentId = this.componentIdStack[stackLength - 1]; var targetToKeysMap = this.reverseDependencyMap.get(currentComponentId); if (targetToKeysMap !== void 0) { var keys = targetToKeysMap.get(targetKey); if (keys !== void 0) { if (!(0, _common.includes)(keys, propKey)) keys.push(propKey); } else { targetToKeysMap.set(targetKey, [propKey]); } } else { var wm = new Map(); wm.set(targetKey, [propKey]); this.reverseDependencyMap.set(currentComponentId, wm); } var keyToComponentIdsMap = this.dependencyMap.get(targetKey); if (keyToComponentIdsMap !== void 0) { var idsArray = keyToComponentIdsMap[propKey]; if (idsArray !== void 0) { if (!(0, _common.includes)(idsArray, currentComponentId)) idsArray.push(currentComponentId); } else { keyToComponentIdsMap[propKey] = [currentComponentId]; } } else { this.dependencyMap.set(targetKey, (0, _defineProperty2["default"])({}, propKey, [currentComponentId])); } } }, { key: "end", value: function end() { this.componentIdStack.pop(); } }, { key: "isObserved", value: function isObserved(targetKey, propKey) { var map = this.dependencyMap.get(targetKey); return map !== void 0 && propKey in map; } }]); return DepCollector; }(); var depCollector = new DepCollector(); exports.depCollector = depCollector; var EOperationTypes; exports.EOperationTypes = EOperationTypes; (function (EOperationTypes) { EOperationTypes["SET"] = "set"; EOperationTypes["ADD"] = "add"; EOperationTypes["DELETE"] = "delete"; EOperationTypes["CLEAR"] = "clear"; EOperationTypes["GET"] = "get"; EOperationTypes["HAS"] = "has"; EOperationTypes["ITERATE"] = "iterate"; })(EOperationTypes || (exports.EOperationTypes = EOperationTypes = {})); /** * collect prop diff history record */ var HistoryCollector = /*#__PURE__*/function () { function HistoryCollector() { (0, _classCallCheck2["default"])(this, HistoryCollector); this.transactionHistories = []; this.waitTriggerComponentIds = []; this.cursor = -1; } (0, _createClass2["default"])(HistoryCollector, [{ key: "collect", value: function collect(target, key, payload) { var isNeedRecord = arguments.length > 3 && arguments[3] !== undefined ? arguments[3] : true; var beforeUpdate = payload.beforeUpdate, didUpdate = payload.didUpdate, type = payload.type; this.collectComponentId(target, key, type); if (!_config.ctx.timeTravel.isActive || !isNeedRecord) { return; } if (this.currentHistoryIdSet === void 0) { this.currentHistoryIdSet = new Set(); } if (this.currentHistory === void 0) { this.currentHistory = new WeakMap(); } var keyToDiffChangeMap = this.currentHistory.get(target); if (keyToDiffChangeMap !== void 0) { if (keyToDiffChangeMap[key] !== void 0) { keyToDiffChangeMap[key].didUpdate = didUpdate; } else { keyToDiffChangeMap[key] = { beforeUpdate: beforeUpdate, didUpdate: didUpdate }; } } else { this.currentHistory.set(target, (0, _defineProperty2["default"])({}, key, { beforeUpdate: beforeUpdate, didUpdate: didUpdate })); } this.currentHistoryIdSet.add(target); } }, { key: "collectComponentId", value: function collectComponentId(target, key, type) { var _this$waitTriggerComp; var keyToComponentIdsMap = depCollector.dependencyMap.get(target); if (keyToComponentIdsMap === void 0) { return; } var tempKey = type === "add" /* ADD */ ? Array.isArray(target) ? 'length' : "iterate" /* ITERATE */ : key; var idsArray = keyToComponentIdsMap[tempKey]; if (idsArray === void 0 || idsArray.length === 0) { return; } (_this$waitTriggerComp = this.waitTriggerComponentIds).push.apply(_this$waitTriggerComp, (0, _toConsumableArray2["default"])(idsArray)); } }, { key: "endBatch", value: function endBatch() { var isClearHistory = arguments.length > 0 && arguments[0] !== undefined ? arguments[0] : true; this.waitTriggerComponentIds = []; if (!_config.ctx.timeTravel.isActive || !isClearHistory) { return; } this.currentHistory = void 0; this.currentHistoryIdSet = void 0; } }, { key: "canUndo", value: function canUndo() { return this.cursor >= 0; } }, { key: "canRedo", value: function canRedo() { return this.cursor < this.transactionHistories.length - 1; } /** * @todo support multiple steps * revert to the previous history status */ }, { key: "undo", value: function undo() { var stepNum = arguments.length > 0 && arguments[0] !== undefined ? arguments[0] : 1; if (!this.canUndo()) { return; } var currentHistory = this.transactionHistories[this.cursor]; var original = function original() { currentHistory.historyKey.forEach(function (target) { var keyToDiffObj = currentHistory.history.get(target); if (keyToDiffObj) { var keys = Object.keys(keyToDiffObj); for (var i = 0; i < keys.length; i++) { var propKey = keys[i]; target[propKey] = keyToDiffObj[propKey].beforeUpdate; } } }); }; _domain.materialCallStack.push(_interfaces.EMaterialType.TIME_TRAVEL); _store.store.dispatch({ name: "$timeTravel_".concat((0, _uuid["default"])()), payload: [], original: original, isInner: true }); _domain.materialCallStack.pop(); this.cursor -= 1; } /** * @todo support multiple steps * apply the next history status */ }, { key: "redo", value: function redo() { var stepNum = arguments.length > 0 && arguments[0] !== undefined ? arguments[0] : 1; if (!this.canRedo()) { return; } this.cursor += 1; var currentHistory = this.transactionHistories[this.cursor]; var original = function original() { currentHistory.historyKey.forEach(function (target) { var keyToDiffObj = currentHistory.history.get(target); if (keyToDiffObj) { var keys = Object.keys(keyToDiffObj); for (var i = 0; i < keys.length; i++) { var propKey = keys[i]; target[propKey] = keyToDiffObj[propKey].didUpdate; } } }); }; _domain.materialCallStack.push(_interfaces.EMaterialType.TIME_TRAVEL); _store.store.dispatch({ name: "$timeTravel_".concat((0, _uuid["default"])()), payload: [], original: original, isInner: true }); _domain.materialCallStack.pop(); } }, { key: "save", value: function save() { if (this.cursor === this.transactionHistories.length - 1) { this.transactionHistories.push({ historyKey: this.currentHistoryIdSet, history: this.currentHistory }); this.cursor += 1; } else if (this.cursor < this.transactionHistories.length - 1) { this.transactionHistories = this.transactionHistories.slice(0, this.cursor + 1); this.transactionHistories.push({ historyKey: this.currentHistoryIdSet, history: this.currentHistory }); this.cursor += 1; } if (this.transactionHistories.length > _config.ctx.timeTravel.maxStepNumber) { this.transactionHistories.shift(); this.cursor -= 1; } } }]); return HistoryCollector; }(); var historyCollector = new HistoryCollector(); exports.historyCollector = historyCollector; var undo = function undo() { var stepNum = arguments.length > 0 && arguments[0] !== undefined ? arguments[0] : 1; historyCollector.undo(stepNum); }; exports.undo = undo; var redo = function redo() { var stepNum = arguments.length > 0 && arguments[0] !== undefined ? arguments[0] : 1; historyCollector.redo(stepNum); }; exports.redo = redo; var getTimeTravelStatus = function getTimeTravelStatus() { return { canUndo: historyCollector.canUndo(), canRedo: historyCollector.canRedo() }; }; exports.getTimeTravelStatus = getTimeTravelStatus;