mirror of
https://github.com/zebrajr/node.git
synced 2026-01-15 12:15:26 +00:00
assert: make myers_diff function more performant
PR-URL: https://github.com/nodejs/node/pull/56303 Refs: https://github.com/nodejs/node/pull/54862 Reviewed-By: Antoine du Hamel <duhamelantoine1995@gmail.com> Reviewed-By: Xuguang Mei <meixuguang@gmail.com> Reviewed-By: Ruben Bridgewater <ruben@bridgewater.de> Reviewed-By: Pietro Marchini <pietro.marchini94@gmail.com> Reviewed-By: James M Snell <jasnell@gmail.com>
This commit is contained in:
@@ -1,10 +1,9 @@
|
||||
'use strict';
|
||||
|
||||
const {
|
||||
Array,
|
||||
ArrayPrototypeFill,
|
||||
ArrayPrototypePush,
|
||||
ArrayPrototypeSlice,
|
||||
Int32Array,
|
||||
StringPrototypeEndsWith,
|
||||
} = primordials;
|
||||
|
||||
@@ -26,7 +25,7 @@ function myersDiff(actual, expected, checkCommaDisparity = false) {
|
||||
const actualLength = actual.length;
|
||||
const expectedLength = expected.length;
|
||||
const max = actualLength + expectedLength;
|
||||
const v = ArrayPrototypeFill(Array(2 * max + 1), 0);
|
||||
const v = new Int32Array(2 * max + 1);
|
||||
|
||||
const trace = [];
|
||||
|
||||
@@ -35,22 +34,24 @@ function myersDiff(actual, expected, checkCommaDisparity = false) {
|
||||
ArrayPrototypePush(trace, newTrace);
|
||||
|
||||
for (let diagonalIndex = -diffLevel; diagonalIndex <= diffLevel; diagonalIndex += 2) {
|
||||
let x;
|
||||
if (diagonalIndex === -diffLevel ||
|
||||
(diagonalIndex !== diffLevel && v[diagonalIndex - 1 + max] < v[diagonalIndex + 1 + max])) {
|
||||
x = v[diagonalIndex + 1 + max];
|
||||
} else {
|
||||
x = v[diagonalIndex - 1 + max] + 1;
|
||||
}
|
||||
|
||||
const offset = diagonalIndex + max;
|
||||
const previousOffset = v[offset - 1];
|
||||
const nextOffset = v[offset + 1];
|
||||
let x = diagonalIndex === -diffLevel || (diagonalIndex !== diffLevel && previousOffset < nextOffset) ?
|
||||
nextOffset :
|
||||
previousOffset + 1;
|
||||
let y = x - diagonalIndex;
|
||||
|
||||
while (x < actualLength && y < expectedLength && areLinesEqual(actual[x], expected[y], checkCommaDisparity)) {
|
||||
while (
|
||||
x < actualLength &&
|
||||
y < expectedLength &&
|
||||
areLinesEqual(actual[x], expected[y], checkCommaDisparity)
|
||||
) {
|
||||
x++;
|
||||
y++;
|
||||
}
|
||||
|
||||
v[diagonalIndex + max] = x;
|
||||
v[offset] = x;
|
||||
|
||||
if (x >= actualLength && y >= expectedLength) {
|
||||
return backtrack(trace, actual, expected, checkCommaDisparity);
|
||||
@@ -71,10 +72,13 @@ function backtrack(trace, actual, expected, checkCommaDisparity) {
|
||||
for (let diffLevel = trace.length - 1; diffLevel >= 0; diffLevel--) {
|
||||
const v = trace[diffLevel];
|
||||
const diagonalIndex = x - y;
|
||||
let prevDiagonalIndex;
|
||||
const offset = diagonalIndex + max;
|
||||
|
||||
if (diagonalIndex === -diffLevel ||
|
||||
(diagonalIndex !== diffLevel && v[diagonalIndex - 1 + max] < v[diagonalIndex + 1 + max])) {
|
||||
let prevDiagonalIndex;
|
||||
if (
|
||||
diagonalIndex === -diffLevel ||
|
||||
(diagonalIndex !== diffLevel && v[offset - 1] < v[offset + 1])
|
||||
) {
|
||||
prevDiagonalIndex = diagonalIndex + 1;
|
||||
} else {
|
||||
prevDiagonalIndex = diagonalIndex - 1;
|
||||
@@ -84,8 +88,11 @@ function backtrack(trace, actual, expected, checkCommaDisparity) {
|
||||
const prevY = prevX - prevDiagonalIndex;
|
||||
|
||||
while (x > prevX && y > prevY) {
|
||||
const value = !checkCommaDisparity ||
|
||||
StringPrototypeEndsWith(actual[x - 1], ',') ? actual[x - 1] : expected[y - 1];
|
||||
const actualItem = actual[x - 1];
|
||||
const value =
|
||||
!checkCommaDisparity || StringPrototypeEndsWith(actualItem, ',') ?
|
||||
actualItem :
|
||||
expected[y - 1];
|
||||
ArrayPrototypePush(result, { __proto__: null, type: 'nop', value });
|
||||
x--;
|
||||
y--;
|
||||
@@ -110,13 +117,15 @@ function printSimpleMyersDiff(diff) {
|
||||
|
||||
for (let diffIdx = diff.length - 1; diffIdx >= 0; diffIdx--) {
|
||||
const { type, value } = diff[diffIdx];
|
||||
let color = colors.white;
|
||||
|
||||
if (type === 'insert') {
|
||||
message += `${colors.green}${value}${colors.white}`;
|
||||
color = colors.green;
|
||||
} else if (type === 'delete') {
|
||||
message += `${colors.red}${value}${colors.white}`;
|
||||
} else {
|
||||
message += `${colors.white}${value}${colors.white}`;
|
||||
color = colors.red;
|
||||
}
|
||||
|
||||
message += `${color}${value}${colors.white}`;
|
||||
}
|
||||
|
||||
return `\n${message}`;
|
||||
@@ -129,17 +138,16 @@ function printMyersDiff(diff, operator) {
|
||||
|
||||
for (let diffIdx = diff.length - 1; diffIdx >= 0; diffIdx--) {
|
||||
const { type, value } = diff[diffIdx];
|
||||
const previousType = (diffIdx < (diff.length - 1)) ? diff[diffIdx + 1].type : null;
|
||||
const typeChanged = previousType && (type !== previousType);
|
||||
const previousType = diffIdx < diff.length - 1 ? diff[diffIdx + 1].type : null;
|
||||
|
||||
if (typeChanged && previousType === 'nop') {
|
||||
// Avoid grouping if only one line would have been grouped otherwise
|
||||
// Avoid grouping if only one line would have been grouped otherwise
|
||||
if (previousType === 'nop' && type !== previousType) {
|
||||
if (nopCount === kNopLinesToCollapse + 1) {
|
||||
message += `${colors.white} ${diff[diffIdx + 1].value}\n`;
|
||||
} else if (nopCount === kNopLinesToCollapse + 2) {
|
||||
message += `${colors.white} ${diff[diffIdx + 2].value}\n`;
|
||||
message += `${colors.white} ${diff[diffIdx + 1].value}\n`;
|
||||
} if (nopCount >= (kNopLinesToCollapse + 3)) {
|
||||
} else if (nopCount >= kNopLinesToCollapse + 3) {
|
||||
message += `${colors.blue}...${colors.white}\n`;
|
||||
message += `${colors.white} ${diff[diffIdx + 1].value}\n`;
|
||||
skipped = true;
|
||||
|
||||
Reference in New Issue
Block a user