UNPKG

@dark-engine/core

Version:

The lightweight and powerful UI rendering engine without dependencies and written in TypeScript (Browser, Node.js, Android, iOS, Windows, Linux, macOS)

143 lines (142 loc) 4.37 kB
'use strict'; Object.defineProperty(exports, '__esModule', { value: true }); exports.Reconciler = void 0; const utils_1 = require('../utils'); const constants_1 = require('../constants'); const view_1 = require('../view'); class Reconciler { store; constructor(store = {}) { this.store = store; } get(id) { return this.store[id]; } reset() { this.store = {}; } fork() { return new Reconciler({ ...this.store }); } reconcile(fiber, alt, $scope) { const { id, inst } = fiber; const areSameTypes = (0, view_1.detectAreSameInstanceTypes)(alt.inst, inst); const nextChildren = inst.children; if (!areSameTypes) { $scope.addDeletion(alt); } else if ((0, view_1.hasChildrenProp)(alt.inst) && nextChildren) { const { prevKeys, nextKeys, prevKeysMap, nextKeysMap, keyedFibersMap } = extractKeys(alt.child, nextChildren); const flush = nextKeys.length === 0; let size = Math.max(prevKeys.length, nextKeys.length); let p = 0; let n = 0; this.createStore(id, keyedFibersMap); for (let i = 0; i < size; i++) { const nextKey = nextKeys[i - n] ?? null; const prevKey = prevKeys[i - p] ?? null; const prevKeyFiber = keyedFibersMap[prevKey] || null; if (nextKey !== prevKey) { if (nextKey !== null && !prevKeysMap[nextKey]) { if (prevKey !== null && !nextKeysMap[prevKey]) { this.replace(id, nextKey); $scope.addDeletion(prevKeyFiber); } else { this.insert(id, nextKey); p++; size++; } } else if (!nextKeysMap[prevKey]) { this.remove(id, prevKey); $scope.addDeletion(prevKeyFiber); flush && (prevKeyFiber.mask |= constants_1.FLUSH_MASK); n++; size++; } else if (nextKeysMap[prevKey] && nextKeysMap[nextKey]) { this.move(id, nextKey); } } else if (nextKey !== null) { this.stable(id, nextKey); } } } } createStore(id, map) { this.store[id] = { map, replace: null, insert: null, remove: null, move: null, stable: null, }; } replace(id, nextKey) { !this.store[id].replace && (this.store[id].replace = {}); this.store[id].replace[nextKey] = true; } insert(id, nextKey) { !this.store[id].insert && (this.store[id].insert = {}); this.store[id].insert[nextKey] = true; } remove(id, prevKey) { !this.store[id].remove && (this.store[id].remove = {}); this.store[id].remove[prevKey] = true; } move(id, nextKey) { !this.store[id].move && (this.store[id].move = {}); this.store[id].move[nextKey] = true; } stable(id, nextKey) { !this.store[id].stable && (this.store[id].stable = {}); this.store[id].stable[nextKey] = true; } } exports.Reconciler = Reconciler; function extractKeys(alt, children) { let nextFiber = alt; let idx = 0; const prevKeys = []; const nextKeys = []; const prevKeysMap = {}; const nextKeysMap = {}; const keyedFibersMap = {}; const usedKeysMap = {}; while (nextFiber || idx < children.length) { if (nextFiber) { const key = (0, view_1.getElementKey)(nextFiber.inst); const prevKey = (0, utils_1.detectIsEmpty)(key) ? (0, utils_1.createIndexKey)(idx) : key; if (!prevKeysMap[prevKey]) { prevKeysMap[prevKey] = true; prevKeys.push(prevKey); } keyedFibersMap[prevKey] = nextFiber; } if (idx < children.length) { const inst = children[idx]; const key = (0, view_1.getElementKey)(inst); const nextKey = (0, utils_1.detectIsEmpty)(key) ? (0, utils_1.createIndexKey)(idx) : key; if (process.env.NODE_ENV !== 'production') { if (usedKeysMap[nextKey]) { (0, utils_1.logError)((0, utils_1.formatErrorMsg)(`The key of node [${nextKey}] already has been used!`), [ inst, ]); } } if (!nextKeysMap[nextKey]) { nextKeysMap[nextKey] = true; nextKeys.push(nextKey); } usedKeysMap[nextKey] = true; } nextFiber = nextFiber ? nextFiber.next : null; idx++; } return { prevKeys, nextKeys, prevKeysMap, nextKeysMap, keyedFibersMap, }; } //# sourceMappingURL=reconciler.js.map