Skip to content

Commit

Permalink
assert: make myers_diff function more performant
Browse files Browse the repository at this point in the history
  • Loading branch information
puskin94 committed Dec 18, 2024
1 parent 0d00511 commit a00f603
Showing 1 changed file with 31 additions and 26 deletions.
57 changes: 31 additions & 26 deletions lib/internal/assert/myers_diff.js
Original file line number Diff line number Diff line change
@@ -1,10 +1,9 @@
'use strict';

const {
Array,
ArrayPrototypeFill,
ArrayPrototypePush,
ArrayPrototypeSlice,
Int32Array,
StringPrototypeEndsWith,
} = primordials;

Expand All @@ -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 = [];

Expand All @@ -35,22 +34,29 @@ function myersDiff(actual, expected, checkCommaDisparity = false) {
ArrayPrototypePush(trace, newTrace);

for (let diagonalIndex = -diffLevel; diagonalIndex <= diffLevel; diagonalIndex += 2) {
const offset = diagonalIndex + max;
let x;
if (diagonalIndex === -diffLevel ||
(diagonalIndex !== diffLevel && v[diagonalIndex - 1 + max] < v[diagonalIndex + 1 + max])) {
x = v[diagonalIndex + 1 + max];
if (
diagonalIndex === -diffLevel ||
(diagonalIndex !== diffLevel && v[offset - 1] < v[offset + 1])
) {
x = v[offset + 1];
} else {
x = v[diagonalIndex - 1 + max] + 1;
x = v[offset - 1] + 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);
Expand All @@ -71,10 +77,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;
Expand All @@ -84,8 +93,10 @@ 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 value =
!checkCommaDisparity || StringPrototypeEndsWith(actual[x - 1], ',') ?
actual[x - 1] :
expected[y - 1];
ArrayPrototypePush(result, { __proto__: null, type: 'nop', value });
x--;
y--;
Expand All @@ -110,13 +121,8 @@ function printSimpleMyersDiff(diff) {

for (let diffIdx = diff.length - 1; diffIdx >= 0; diffIdx--) {
const { type, value } = diff[diffIdx];
if (type === 'insert') {
message += `${colors.green}${value}${colors.white}`;
} else if (type === 'delete') {
message += `${colors.red}${value}${colors.white}`;
} else {
message += `${colors.white}${value}${colors.white}`;
}
const color = type === 'insert' ? colors.green : type === 'delete' ? colors.red : colors.white;
message += `${color}${value}${colors.white}`;
}

return `\n${message}`;
Expand All @@ -129,17 +135,16 @@ function printMyersDiff(diff, simple = false) {

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;
Expand Down

0 comments on commit a00f603

Please sign in to comment.