project/node_modules/zrender/lib/core/arrayDiff.js

146 lines
4.6 KiB
JavaScript
Raw Normal View History

2024-07-14 15:48:34 +08:00
function diff(oldArr, newArr, equals) {
if (!equals) {
equals = function (a, b) {
return a === b;
};
}
oldArr = oldArr.slice();
newArr = newArr.slice();
var newLen = newArr.length;
var oldLen = oldArr.length;
var editLength = 1;
var maxEditLength = newLen + oldLen;
var bestPath = [{ newPos: -1, components: [] }];
var oldPos = extractCommon(bestPath[0], newArr, oldArr, 0, equals);
if (!oldLen
|| !newLen
|| (bestPath[0].newPos + 1 >= newLen && oldPos + 1 >= oldLen)) {
var indices = [];
var allCleared = !newLen && oldLen > 0;
var allCreated = !oldLen && newLen > 0;
for (var i = 0; i < (allCleared ? oldArr : newArr).length; i++) {
indices.push(i);
}
return [{
indices: indices,
count: indices.length,
added: allCreated,
removed: allCleared
}];
}
function execEditLength() {
for (var diagonalPath = -1 * editLength; diagonalPath <= editLength; diagonalPath += 2) {
var basePath;
var addPath = bestPath[diagonalPath - 1];
var removePath = bestPath[diagonalPath + 1];
var oldPos = (removePath ? removePath.newPos : 0) - diagonalPath;
if (addPath) {
bestPath[diagonalPath - 1] = undefined;
}
var canAdd = addPath && addPath.newPos + 1 < newLen;
var canRemove = removePath && 0 <= oldPos && oldPos < oldLen;
if (!canAdd && !canRemove) {
bestPath[diagonalPath] = undefined;
continue;
}
if (!canAdd || (canRemove && addPath.newPos < removePath.newPos)) {
basePath = clonePath(removePath);
pushComponent(basePath.components, false, true);
}
else {
basePath = addPath;
basePath.newPos++;
pushComponent(basePath.components, true, false);
}
oldPos = extractCommon(basePath, newArr, oldArr, diagonalPath, equals);
if (basePath.newPos + 1 >= newLen && oldPos + 1 >= oldLen) {
return buildValues(basePath.components);
}
else {
bestPath[diagonalPath] = basePath;
}
}
editLength++;
}
while (editLength <= maxEditLength) {
var ret = execEditLength();
if (ret) {
return ret;
}
}
}
function extractCommon(basePath, newArr, oldArr, diagonalPath, equals) {
var newLen = newArr.length;
var oldLen = oldArr.length;
var newPos = basePath.newPos;
var oldPos = newPos - diagonalPath;
var commonCount = 0;
while (newPos + 1 < newLen && oldPos + 1 < oldLen && equals(newArr[newPos + 1], oldArr[oldPos + 1])) {
newPos++;
oldPos++;
commonCount++;
}
if (commonCount) {
basePath.components.push({
count: commonCount,
added: false,
removed: false,
indices: []
});
}
basePath.newPos = newPos;
return oldPos;
}
function pushComponent(components, added, removed) {
var last = components[components.length - 1];
if (last && last.added === added && last.removed === removed) {
components[components.length - 1] = {
count: last.count + 1,
added: added,
removed: removed,
indices: []
};
}
else {
components.push({
count: 1,
added: added,
removed: removed,
indices: []
});
}
}
function buildValues(components) {
var componentPos = 0;
var componentLen = components.length;
var newPos = 0;
var oldPos = 0;
for (; componentPos < componentLen; componentPos++) {
var component = components[componentPos];
if (!component.removed) {
var indices = [];
for (var i = newPos; i < newPos + component.count; i++) {
indices.push(i);
}
component.indices = indices;
newPos += component.count;
if (!component.added) {
oldPos += component.count;
}
}
else {
for (var i = oldPos; i < oldPos + component.count; i++) {
component.indices.push(i);
}
oldPos += component.count;
}
}
return components;
}
function clonePath(path) {
return { newPos: path.newPos, components: path.components.slice(0) };
}
export default function arrayDiff(oldArr, newArr, equal) {
return diff(oldArr, newArr, equal);
}