react-diff-viewer icon indicating copy to clipboard operation
react-diff-viewer copied to clipboard

big data cause Page jammed

Open vincent-tian opened this issue 3 years ago • 8 comments

use react-diff-viewer data size :1m

vincent-tian avatar Jan 10 '22 13:01 vincent-tian

1.open node_modules/react-diff-viewer/lib/compute-lines.js 2.find the function computeLineInformation 3. replace my functionvar computeLineInformation = function (oldString, newString, disableWordDiff, compareMethod, linesOffset) { if (disableWordDiff === void 0) { disableWordDiff = false; } if (compareMethod === void 0) { compareMethod = DiffMethod.CHARS; } if (linesOffset === void 0) { linesOffset = 0; } var diffArray = [] var type = 3 var num = 100 if (oldString.length > 1000 || newString.length > 1000) { type = 1 } if (type == 1) { var oldarr = getArr(oldString, { newlineIsToken: true, ignoreWhitespace: false, ignoreCase: false, }) var newarr = getArr(newString, { newlineIsToken: true, ignoreWhitespace: false, ignoreCase: false, }) var oa = oldarr.splice(0, num) var na = newarr.splice(0, num) while (oa.length > 0 || na.length > 0) { var o = oa.join('') var n = na.join('') diffArray = diffArray.concat(diff.diffLines(o, n, { newlineIsToken: true, ignoreWhitespace: false, ignoreCase: false, })); oa = oldarr.splice(0, num) na = newarr.splice(0, num) } } else if (type == 2) { var oldarr = oldString.split('\n') var newarr = newString.split('\n') var oa = oldarr.splice(0, num) var na = newarr.splice(0, num) while (oa.length > 0 || na.length > 0) { var o = '' var n = '' for (var i = 0; i < oa.length; i++) { o += '\n' + oa[i] } for (var i = 0; i < na.length; i++) { n += '\n' + na[i] } diffArray = diffArray.concat(diff.diffLines(o, n, { newlineIsToken: true, ignoreWhitespace: false, ignoreCase: false, })); oa = oldarr.splice(0, num) na = newarr.splice(0, num) } } else { diffArray = diffArray.concat(diff.diffLines(oldString, newString, { newlineIsToken: true, ignoreWhitespace: false, ignoreCase: false, })); } var rightLineNumber = linesOffset; var leftLineNumber = linesOffset; var lineInformation = []; var counter = 0; var diffLines = []; var ignoreDiffIndexes = []; var getLineInformation = function (value, diffIndex, added, removed, evaluateOnlyFirstLine) { var lines = constructLines(value); return lines .map(function (line, lineIndex) { var left = {}; var right = {}; if (ignoreDiffIndexes.includes(diffIndex + "-" + lineIndex) || (evaluateOnlyFirstLine && lineIndex !== 0)) { return undefined; } if (added || removed) { if (!diffLines.includes(counter)) { diffLines.push(counter); } if (removed) { leftLineNumber += 1; left.lineNumber = leftLineNumber; left.type = DiffType.REMOVED; left.value = line || ' '; // When the current line is of type REMOVED, check the next item in // the diff array whether it is of type ADDED. If true, the current // diff will be marked as both REMOVED and ADDED. Meaning, the // current line is a modification. var nextDiff = diffArray[diffIndex + 1]; if (nextDiff && nextDiff.added) { var nextDiffLines = constructLines(nextDiff.value)[lineIndex]; if (nextDiffLines) { var _a = getLineInformation(nextDiff.value, diffIndex, true, false, true)[0].right, rightValue = _a.value, lineNumber = _a.lineNumber, type = _a.type; // When identified as modification, push the next diff to ignore // list as the next value will be added in this line computation as // right and left values. ignoreDiffIndexes.push(diffIndex + 1 + "-" + lineIndex); right.lineNumber = lineNumber; right.type = type; // Do word level diff and assign the corresponding values to the // left and right diff information object. if (disableWordDiff) { right.value = rightValue; } else { var computedDiff = computeDiff(line, rightValue, compareMethod); right.value = computedDiff.right; left.value = computedDiff.left; } } } } else { rightLineNumber += 1; right.lineNumber = rightLineNumber; right.type = DiffType.ADDED; right.value = line; } } else { leftLineNumber += 1; rightLineNumber += 1; left.lineNumber = leftLineNumber; left.type = DiffType.DEFAULT; left.value = line; right.lineNumber = rightLineNumber; right.type = DiffType.DEFAULT; right.value = line; } counter += 1; return { right: right, left: left }; }) .filter(Boolean); }; diffArray.forEach(function (_a, index) { var added = _a.added, removed = _a.removed, value = _a.value; lineInformation = __spread(lineInformation, getLineInformation(value, index, added, removed)); }); return { lineInformation: lineInformation, diffLines: diffLines, }; }; 4. if it dosent work, make sure the node_modules cache is cleaned

LeePiaPia avatar Feb 18 '22 08:02 LeePiaPia

var newarr = getArr(newString, { newlineIsToken: true, ignoreWhitespace: false, ignoreCase: false, }) var oa = oldarr.splice(0, num)

I tried replace code, but can't find the getArr() function, where is it defined

Monster12138 avatar Mar 02 '22 07:03 Monster12138

var newarr = getArr(newString, { newlineIsToken: true, ignoreWhitespace: false, ignoreCase: false, }) var oa = oldarr.splice(0, num)

I tried replace code, but can't find the getArr() function, where is it defined

var getArr = (value, options) => { let retLines = [], linesAndNewlines = value.split(/(\n|\r\n)/);

// Ignore the final empty token that occurs if the string ends with a new line
if (!linesAndNewlines[linesAndNewlines.length - 1]) {
    linesAndNewlines.pop();
}

// Merge the content and line separators into single tokens
for (let i = 0; i < linesAndNewlines.length; i++) {
    let line = linesAndNewlines[i];

    if (i % 2 && !options.newlineIsToken) {
        retLines[retLines.length - 1] += line;
    } else {
        if (options.ignoreWhitespace) {
            line = line.trim();
        }
        retLines.push(line);
    }
}

return retLines;

}

var spliceArray = function (arr, num) { var len = arr.length var n = num var lineNum = len % n === 0 ? len / n : Math.floor((len / n) + 1); var result = [] for (var i = 0; i < lineNum; i++) { var temp = arr.slice(i * n, i * n + n); result.push(temp); } return result }

LeePiaPia avatar Mar 03 '22 07:03 LeePiaPia

var newarr = getArr(newString, { newlineIsToken: true, ignoreWhitespace: false, ignoreCase: false, }) var oa = oldarr.splice(0, num)

I tried replace code, but can't find the getArr() function, where is it defined

Has your problem been solved?

lucyfeifei avatar Mar 09 '22 10:03 lucyfeifei

Will this be fixed in a future release? The above changes did work.

tylersiemers avatar Apr 04 '22 17:04 tylersiemers

Any update on getting this issue fixed in the repo? We are trying to diff large files but not files I would consider too big (ie ~2000 lines of code) and it is causing the browser to hang in most cases

TristanSpeakEasy avatar Sep 05 '22 15:09 TristanSpeakEasy

@praneshr I have created a PR to fix this issue https://github.com/praneshr/react-diff-viewer/pull/172

@LeePiaPia would be great to get a review as it was based on your provided code (with some cleanup)

TristanSpeakEasy avatar Sep 30 '22 10:09 TristanSpeakEasy

This code should not be used. It is faster, but it is incorrect.

Because the new approach is "chunking" the diff processing into sets of 100 it gives incorrect results on inputs over 100 lines long. For example, you can use the following inputs to simulate a pair of input files 302 lines long where the only difference is that a single line has been removed from the new value.

const range = (start, end) => [...Array(end).keys()].slice(start, end);
const oldValue = `{\n${range(0, 300).join('\n')}\n}`;
const newValue = `{\n${[...range(0, 50), ...range(51, 300)].join('\n')}\n}`;

When I try this in the original version of the code it works fine, and reports only the line containing "50" as removed and no other changes. When I try it with the suggested change above it correctly reports the line containing "50" as removed on the left, but then reports the lines containing "99", "149", "199", "249", and "299" as removed on the left and added on the right.

This problem will become worse the larger the difference in line counts between the files. Once you get past 100 lines difference on a given side, every line will be reported as a difference even when all the lines exist with no changes elsewhere in each file.

Note: I did this testing with the cleaned up version in the linked PR.

erothmayer avatar Oct 23 '22 14:10 erothmayer