UNPKG

@tacky/store

Version:

State management framework based on react

382 lines (327 loc) 11.1 kB
import _toConsumableArray from "@babel/runtime/helpers/esm/toConsumableArray"; import _defineProperty from "@babel/runtime/helpers/esm/defineProperty"; import _classCallCheck from "@babel/runtime/helpers/esm/classCallCheck"; import _createClass from "@babel/runtime/helpers/esm/createClass"; import { includes } from '../utils/common'; import { ctx } from '../const/config'; import { store } from './store'; import generateUUID from '../utils/uuid'; import { materialCallStack } from './domain'; import { EMaterialType } from '../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() { _classCallCheck(this, DepCollector); this.dependencyMap = new WeakMap(); /** * Using a small amount of memory to improve execute performance */ this.reverseDependencyMap = new WeakMap(); this.componentIdStack = []; } _createClass(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 (!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 (!includes(idsArray, currentComponentId)) idsArray.push(currentComponentId); } else { keyToComponentIdsMap[propKey] = [currentComponentId]; } } else { this.dependencyMap.set(targetKey, _defineProperty({}, 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; }(); export var depCollector = new DepCollector(); export var 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 || (EOperationTypes = {})); /** * collect prop diff history record */ var HistoryCollector = /*#__PURE__*/function () { function HistoryCollector() { _classCallCheck(this, HistoryCollector); this.transactionHistories = []; this.waitTriggerComponentIds = []; this.cursor = -1; } _createClass(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 (!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, _defineProperty({}, 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, _toConsumableArray(idsArray)); } }, { key: "endBatch", value: function endBatch() { var isClearHistory = arguments.length > 0 && arguments[0] !== undefined ? arguments[0] : true; this.waitTriggerComponentIds = []; if (!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; } } }); }; materialCallStack.push(EMaterialType.TIME_TRAVEL); store.dispatch({ name: "$timeTravel_".concat(generateUUID()), payload: [], original: original, isInner: true }); 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; } } }); }; materialCallStack.push(EMaterialType.TIME_TRAVEL); store.dispatch({ name: "$timeTravel_".concat(generateUUID()), payload: [], original: original, isInner: true }); 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 > ctx.timeTravel.maxStepNumber) { this.transactionHistories.shift(); this.cursor -= 1; } } }]); return HistoryCollector; }(); export var historyCollector = new HistoryCollector(); export var undo = function undo() { var stepNum = arguments.length > 0 && arguments[0] !== undefined ? arguments[0] : 1; historyCollector.undo(stepNum); }; export var redo = function redo() { var stepNum = arguments.length > 0 && arguments[0] !== undefined ? arguments[0] : 1; historyCollector.redo(stepNum); }; export var getTimeTravelStatus = function getTimeTravelStatus() { return { canUndo: historyCollector.canUndo(), canRedo: historyCollector.canRedo() }; };