UNPKG

@turbox3d/reactivity

Version:

Large-scale reactive state management library

306 lines 10.5 kB
import _classCallCheck from "@babel/runtime/helpers/esm/classCallCheck"; import _createClass from "@babel/runtime/helpers/esm/createClass"; import { fail, nextTick } from '@turbox3d/shared'; import { ctx } from '../const/config'; import { TimeTravel } from './time-travel'; import { actionTypeChain } from './store'; import { EDepState, ECollectType, ESpecialReservedKey } from '../const/enums'; import { Action } from './action'; import { rawCache } from './domain'; import { isDomain } from '../utils/common'; import { EEventName, emitter } from '../utils/event'; import { materialCallStack } from '../utils/materialCallStack'; var isInBlackList = function isInBlackList(propKey) { var blackList = { constructor: true, $$turboxProperties: true, context: true, currentTarget: true, originalArrayLength: true, reactorConfigMap: true, computedProperties: true, propertyGet: true, propertySet: true, proxyDeleteProperty: true, proxyOwnKeys: 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 reaction ids */ var DepCollector = /*#__PURE__*/function () { function DepCollector() { _classCallCheck(this, DepCollector); this.dependencyGraph = new Map(); this.reactionIdDeps = new Map(); this.reactionIdStack = []; } return _createClass(DepCollector, [{ key: "start", value: function start(id) { this.reactionIdStack.push(id); } }, { key: "collect", value: function collect(target, propertyKey) { if (isInBlackList(propertyKey)) { return; } var stackLength = this.reactionIdStack.length; if (stackLength === 0) { return; } var currentReactionId = this.reactionIdStack[stackLength - 1]; var depNodeAssembly = this.dependencyGraph.get(target); if (depNodeAssembly !== void 0) { var depNode = depNodeAssembly.get(propertyKey); if (depNode !== void 0) { depNode.add(currentReactionId); } else { depNodeAssembly.set(propertyKey, new Set([currentReactionId])); } } else { var map = new Map([[propertyKey, new Set([currentReactionId])]]); this.dependencyGraph.set(target, map); } var reactionDeps = this.reactionIdDeps.get(currentReactionId); if (reactionDeps !== void 0) { var depNodeStatusAssembly = reactionDeps.get(target); if (depNodeStatusAssembly !== void 0) { depNodeStatusAssembly.set(propertyKey, EDepState.LATEST); } else { reactionDeps.set(target, new Map([[propertyKey, EDepState.LATEST]])); } } else { this.reactionIdDeps.set(currentReactionId, new Map([[target, new Map([[propertyKey, EDepState.LATEST]])]])); } } }, { key: "end", value: function end() { var _this = this; var currentReactionId = this.reactionIdStack.pop(); if (!currentReactionId) { return; } var map = this.reactionIdDeps.get(currentReactionId); if (!map) { return; } map.forEach(function (depNode, target) { depNode.forEach(function (value, key) { // remove stale deps if (value === EDepState.OBSERVED) { var depNodeAssembly = _this.dependencyGraph.get(target); if (depNodeAssembly) { var idSet = depNodeAssembly.get(key); idSet && idSet["delete"](currentReactionId); depNode.set(key, EDepState.NOT_OBSERVED); } } // reset dep status if (value === EDepState.LATEST) { depNode.set(key, EDepState.OBSERVED); } }); }); } }, { key: "clear", value: function clear(id) { var _this2 = this; var map = this.reactionIdDeps.get(id); if (!map) { return; } map.forEach(function (depNode, target) { depNode.forEach(function (value, key) { var depNodeAssembly = _this2.dependencyGraph.get(target); if (depNodeAssembly) { var idSet = depNodeAssembly.get(key); idSet && idSet["delete"](id); } }); }); this.reactionIdDeps["delete"](id); } }, { key: "isObserved", value: function isObserved(targetKey, propKey) { var map = this.dependencyGraph.get(targetKey); return map !== void 0 && map.has(propKey) && (map.get(propKey) || new Set()).size > 0; } }]); }(); export var depCollector = new DepCollector(); var TriggerCollector = /*#__PURE__*/function () { function TriggerCollector() { _classCallCheck(this, TriggerCollector); this.waitTriggerIds = new Set(); } return _createClass(TriggerCollector, [{ key: "trigger", value: function trigger(target, key, payload) { var isNeedRecord = arguments.length > 3 && arguments[3] !== undefined ? arguments[3] : true; var devToolInfo = arguments.length > 4 ? arguments[4] : undefined; var _a, _b; var type = payload.type, beforeUpdate = payload.beforeUpdate, didUpdate = payload.didUpdate; if (ctx.devTool && devToolInfo) { try { var stringify = (_a = window && window.__TURBOX_DEVTOOL_GOLBAL_STRINGIFY__) !== null && _a !== void 0 ? _a : JSON.stringify; var event = { time: Date.now(), stackId: (_b = materialCallStack.currentStack) === null || _b === void 0 ? void 0 : _b.stackId, domain: devToolInfo.domain, keyPath: devToolInfo.keyPath, newValue: stringify(didUpdate), oldValue: stringify(beforeUpdate), type: type }; emitter.emit(EEventName.setProperty, event); console.log(event); } catch (e) { fail(e); } } var enhanceKey = type === ECollectType.ADD ? ESpecialReservedKey.ITERATE : key; this.collectComponentId(target, enhanceKey); if (!ctx.timeTravel.isActive || !TimeTravel.currentTimeTravel || !isNeedRecord || TimeTravel.processing || enhanceKey === ESpecialReservedKey.ITERATE || enhanceKey === ESpecialReservedKey.COMPUTED) { return; } if (Action.context) { this.recordDiff(target, enhanceKey, payload, Action.context.historyNode.history); return; } this.recordDiff(target, enhanceKey, payload, TimeTravel.currentTimeTravel.currentHistory); } }, { key: "endBatch", value: function endBatch() { var isClearHistory = arguments.length > 0 && arguments[0] !== undefined ? arguments[0] : true; var action = arguments.length > 1 ? arguments[1] : undefined; if (!action) { this.waitTriggerIds.clear(); } if (!ctx.timeTravel.isActive || !TimeTravel.currentTimeTravel || !isClearHistory) { return; } if (action) { action.historyNode.actionChain.length = 0; action.historyNode.history.clear(); nextTick(function () { var ctt = TimeTravel.currentTimeTravel; ctt && ctt.onChange(ctt.undoable, ctt.redoable, 'clear', action); }); return; } actionTypeChain.length = 0; TimeTravel.currentTimeTravel.currentHistory.clear(); } }, { key: "save", value: function save(action) { if (!ctx.timeTravel.isActive || !TimeTravel.currentTimeTravel || Action.context) { return; } var ctt = TimeTravel.currentTimeTravel; if (action) { this.saveHistory(ctt, action.historyNode.actionChain, action.historyNode.history, action); return; } this.saveHistory(ctt, actionTypeChain, ctt.currentHistory); } }, { key: "collectComponentId", value: function collectComponentId(target, enhanceKey) { var _this3 = this; var depNodeAssembly = depCollector.dependencyGraph.get(target); if (depNodeAssembly !== void 0) { var idSet = depNodeAssembly.get(enhanceKey); if (idSet !== void 0 && idSet.size > 0) { idSet.forEach(function (id) { return _this3.waitTriggerIds.add(id); }); } } } }, { key: "recordDiff", value: function recordDiff(target, enhanceKey, payload, history) { var type = payload.type, beforeUpdate = payload.beforeUpdate, didUpdate = payload.didUpdate; var proxyTarget; if (isDomain(target)) { proxyTarget = target; } else { proxyTarget = rawCache.get(target); } if (!proxyTarget) { return; } var keyToDiffChangeMap = history.get(proxyTarget); if (keyToDiffChangeMap !== void 0) { var diffInfo = keyToDiffChangeMap.get(enhanceKey); if (diffInfo !== void 0) { diffInfo.didUpdate = didUpdate; } else { keyToDiffChangeMap.set(enhanceKey, { type: type, beforeUpdate: beforeUpdate, didUpdate: didUpdate }); } } else { history.set(proxyTarget, new Map([[enhanceKey, { type: type, beforeUpdate: beforeUpdate, didUpdate: didUpdate }]])); } } }, { key: "saveHistory", value: function saveHistory(ctt, actionChain, history, action) { if (!history) { return; } if (history.size === 0) { return; } var clonedChain = ctx.timeTravel.keepActionChain ? actionChain.slice() : []; var clonedHistory = new Map(history); if (ctt.cursor === ctt.transactionHistories.length - 1) { ctt.transactionHistories.push({ actionChain: clonedChain, history: clonedHistory }); ctt.cursor += 1; } else if (ctt.cursor < ctt.transactionHistories.length - 1) { ctt.transactionHistories = ctt.transactionHistories.slice(0, ctt.cursor + 1); ctt.transactionHistories.push({ actionChain: clonedChain, history: clonedHistory }); ctt.cursor += 1; } if (ctt.transactionHistories.length > ctx.timeTravel.maxStepNumber) { ctt.transactionHistories.shift(); ctt.cursor -= 1; } nextTick(function () { ctt.onChange(ctt.undoable, ctt.redoable, 'save', action); }); } }]); }(); export var triggerCollector = new TriggerCollector();