UNPKG

@turbox3d/reactivity

Version:

Large-scale reactive state management library

310 lines (309 loc) 11.6 kB
"use strict"; var _interopRequireDefault = require("@babel/runtime/helpers/interopRequireDefault"); Object.defineProperty(exports, "__esModule", { value: true }); exports.actionTypeChain = void 0; exports.createStore = createStore; exports.store = exports.registerExternalBatchUpdate = void 0; var _toConsumableArray2 = _interopRequireDefault(require("@babel/runtime/helpers/toConsumableArray")); var _shared = require("@turbox3d/shared"); var _collector = require("./collector"); var _enums = require("../const/enums"); var _reactive = require("./reactive"); var _config = require("../const/config"); var _event2 = require("../utils/event"); var _materialCallStack = require("../utils/materialCallStack"); var _timeTravel = require("./time-travel"); var store; var actionTypeChain = exports.actionTypeChain = []; var batchedUpdates = []; var registerExternalBatchUpdate = exports.registerExternalBatchUpdate = function registerExternalBatchUpdate(obj) { batchedUpdates.push(obj); }; function createStore(enhancer) { if (enhancer !== void 0) { exports.store = store = enhancer(createStore); return store; } var componentUUIDToListeners = new WeakMap(); function subscribe(listener, uuid, idCustomType) { var isSubscribed = true; var obj = componentUUIDToListeners.get(uuid); if (obj === void 0 || obj.listeners === void 0) { componentUUIDToListeners.set(uuid, { idCustomType: idCustomType, listeners: [listener] }); } else if (!(0, _shared.includes)(obj.listeners, listener)) { componentUUIDToListeners.set(uuid, { idCustomType: idCustomType, listeners: obj.listeners.concat(listener) }); } return function unsubscribe() { if (!isSubscribed) { return; } isSubscribed = false; if (componentUUIDToListeners.has(uuid)) { componentUUIDToListeners["delete"](uuid); } }; } var dirtyJob; var mutationDepth = 0; var called = false; var flushChange = function flushChange(ids, useExternalBatchUpdate, isInner) { if (!ids.length || _config.ctx.disableReactive) { return; } var pendingObjs = []; for (var index = 0; index < ids.length; index++) { var cid = ids[index]; var obj = componentUUIDToListeners.get(cid); if (obj) { pendingObjs.push(obj); } } var flush = function flush(idCustomType) { return function () { for (var _index = 0; _index < pendingObjs.length; _index++) { var _obj = pendingObjs[_index]; if (_obj.idCustomType === idCustomType) { var listeners = _obj.listeners; for (var j = 0; j < listeners.length; j++) { var listener = listeners[j]; listener(isInner); } } } }; }; if (useExternalBatchUpdate) { batchedUpdates.forEach(function (obj) { var batchUpdate = obj.handler; batchUpdate(flush(obj.idCustomType), function () { // finish batchUpdate _config.ctx.batchUpdateOnFinish && _config.ctx.batchUpdateOnFinish(); }); }); } else { // reverse flush()(); } }; var keepAliveComputed = function keepAliveComputed(isInner) { var computedReactionIds = (0, _toConsumableArray2["default"])(_collector.triggerCollector.waitTriggerIds.values()).filter(function (id) { return id instanceof _reactive.Reaction && !id.lazy && id.computed; }); if (!computedReactionIds.length) { return; } if (_config.ctx.devTool) { console.log('keepAlive computed', computedReactionIds); } flushChange(computedReactionIds, false, isInner); // clean wait queue keep alive (0, _shared.batchRemoveFromSet)(_collector.triggerCollector.waitTriggerIds, computedReactionIds); }; var immediatelyReactive = function immediatelyReactive(isInner) { var immediatelyReactionIds = (0, _toConsumableArray2["default"])(_collector.triggerCollector.waitTriggerIds.values()).filter(function (id) { return id instanceof _reactive.Reaction && !id.computed && id.immediately; }); if (!immediatelyReactionIds.length) { return; } // clean wait queue (0, _shared.batchRemoveFromSet)(_collector.triggerCollector.waitTriggerIds, immediatelyReactionIds); if (_config.ctx.devTool) { console.log('immediately reactive', immediatelyReactionIds); } flushChange(immediatelyReactionIds, false, isInner); }; var nextTickQueue = []; var nextTickCaller = function nextTickCaller() { if (called) { return; } called = true; var func = function func() { (0, _shared.nextTick)(function () { if (mutationDepth > 0) { called = false; nextTickQueue.shift(); return; } if (nextTickQueue.length === 0) { return; } dirtyJob && dirtyJob(); }); }; nextTickQueue.push(func); func(); }; var clean = function clean() { var needClearHistory = arguments.length > 0 && arguments[0] !== undefined ? arguments[0] : true; called = false; dirtyJob = void 0; nextTickQueue.shift(); actionTypeChain.length = 0; needClearHistory && _collector.triggerCollector.endBatch(); }; function dispatch(dispatchedAction) { var _a, _b, _c, _d; var payload = dispatchedAction.payload, type = dispatchedAction.type, original = dispatchedAction.original, immediately = dispatchedAction.immediately, _dispatchedAction$isI = dispatchedAction.isInner, isInner = _dispatchedAction$isI === void 0 ? false : _dispatchedAction$isI, domain = dispatchedAction.domain, name = dispatchedAction.name, _dispatchedAction$for = dispatchedAction.forceSaveHistory, forceSaveHistory = _dispatchedAction$for === void 0 ? false : _dispatchedAction$for, _dispatchedAction$isN = dispatchedAction.isNeedRecord, isNeedRecord = _dispatchedAction$isN === void 0 ? true : _dispatchedAction$isN; if (isInner) { _timeTravel.TimeTravel.processing = true; } var syncStackId = _materialCallStack.materialCallStack.push({ type: type, method: name, domain: domain === null || domain === void 0 ? void 0 : domain.constructor.name }); if (!isInner && type !== _enums.EMaterialType.MUTATION && type !== _enums.EMaterialType.UPDATE) { return; } var callback = function callback() { var ids = (0, _toConsumableArray2["default"])(_collector.triggerCollector.waitTriggerIds.values()); if (!ids.length && !forceSaveHistory) { clean(false); return; } if (!isInner && isNeedRecord) { _collector.triggerCollector.save(); } var computedReactionIds = ids.filter(function (id) { return id instanceof _reactive.Reaction && id.lazy && id.computed; }); // do lazy computed reaction first,PS:maybe add new trigger ids if (_config.ctx.devTool) { console.log('lazy computed', computedReactionIds); } flushChange(computedReactionIds, false, isInner); var lazyReactiveIds = (0, _toConsumableArray2["default"])(_collector.triggerCollector.waitTriggerIds.values()).filter(function (id) { return id instanceof _reactive.Reaction && !id.computed && !id.immediately; }); var restIds = (0, _toConsumableArray2["default"])(_collector.triggerCollector.waitTriggerIds.values()).filter(function (id) { return !(id instanceof _reactive.Reaction); }); clean(); // do lazy reactive if (_config.ctx.devTool) { console.log('lazy reactive', lazyReactiveIds); } flushChange(lazyReactiveIds, false, isInner); // do Reactive/ReactReactive/CustomReactive if (_config.ctx.devTool) { console.log('custom view Reactive', restIds); } flushChange(restIds, true, isInner); }; mutationDepth += 1; if (isInner || immediately && _collector.triggerCollector.waitTriggerIds.size > 0) { // flush previous job dirtyJob && dirtyJob(); } if (dirtyJob === void 0) { dirtyJob = callback; } var result; if (_config.ctx.devTool) { var event = { domain: (_a = domain === null || domain === void 0 ? void 0 : domain.constructor.name) !== null && _a !== void 0 ? _a : 'UNKNOWN', method: name, args: payload, state: domain === null || domain === void 0 ? void 0 : domain.$$turboxProperties, time: Date.now(), stackId: (_b = _materialCallStack.materialCallStack.currentStack) === null || _b === void 0 ? void 0 : _b.stackId }; _event2.emitter.emit(_event2.EEventName.beforeStoreChange, event); } try { result = original.apply(void 0, (0, _toConsumableArray2["default"])(payload)); } catch (error) { return error; } if (_config.ctx.devTool) { var _event = { domain: (_c = domain === null || domain === void 0 ? void 0 : domain.constructor.name) !== null && _c !== void 0 ? _c : 'UNKNOWN', method: name, args: payload, state: domain === null || domain === void 0 ? void 0 : domain.$$turboxProperties, async: false, time: Date.now(), stackId: (_d = _materialCallStack.materialCallStack.currentStack) === null || _d === void 0 ? void 0 : _d.stackId }; _event2.emitter.emit(_event2.EEventName.afterStoreChange, _event); } if ((0, _shared.isPromise)(result)) { _materialCallStack.materialCallStack.pop(syncStackId); return new Promise(function (resolve, reject) { var asyncStackId; Promise.resolve().then(function () { asyncStackId = _materialCallStack.materialCallStack.push({ type: type, method: name, domain: domain === null || domain === void 0 ? void 0 : domain.constructor.name, syncStackId: syncStackId }); }); result.then(function (res) { var _a, _b; if (_config.ctx.devTool) { _event2.emitter.emit(_event2.EEventName.asyncAfterStoreChange, { domain: (_a = domain === null || domain === void 0 ? void 0 : domain.constructor.name) !== null && _a !== void 0 ? _a : 'UNKNOWN', method: name, args: payload, state: domain === null || domain === void 0 ? void 0 : domain.$$turboxProperties, async: true, time: Date.now(), stackId: (_b = _materialCallStack.materialCallStack.currentStack) === null || _b === void 0 ? void 0 : _b.stackId }); } keepAliveComputed(isInner); immediatelyReactive(isInner); mutationDepth -= 1; if (immediately) { // immediately execute dirtyJob && dirtyJob(); } else { nextTickCaller(); } _materialCallStack.materialCallStack.pop(asyncStackId); resolve(res); })["catch"](function (error) { reject(error); }); }); } keepAliveComputed(isInner); immediatelyReactive(isInner); mutationDepth -= 1; if (isInner || immediately) { // immediately execute dirtyJob && dirtyJob(); _timeTravel.TimeTravel.processing = false; } else { nextTickCaller(); } _materialCallStack.materialCallStack.pop(syncStackId); return result; } return { dispatch: dispatch, subscribe: subscribe }; }