Skip to content

Commit f4cc58c

Browse files
Tony SpataroTony Spataro
Tony Spataro
and
Tony Spataro
authored
Allow early termination to limit execution time with degenerate cases (#365)
Co-authored-by: Tony Spataro <[email protected]>
1 parent fffd8a7 commit f4cc58c

File tree

4 files changed

+41
-3
lines changed

4 files changed

+41
-3
lines changed

Diff for: src/diff/base.js

+6-3
Original file line numberDiff line numberDiff line change
@@ -30,6 +30,10 @@ Diff.prototype = {
3030
let newLen = newString.length, oldLen = oldString.length;
3131
let editLength = 1;
3232
let maxEditLength = newLen + oldLen;
33+
if(options.maxEditLength) {
34+
maxEditLength = Math.min(maxEditLength, options.maxEditLength);
35+
}
36+
3337
let bestPath = [{ newPos: -1, components: [] }];
3438

3539
// Seed editLength = 0, i.e. the content starts with the same values
@@ -87,12 +91,11 @@ Diff.prototype = {
8791

8892
// Performs the length of edit iteration. Is a bit fugly as this has to support the
8993
// sync and async mode which is never fun. Loops over execEditLength until a value
90-
// is produced.
94+
// is produced, or until the edit length exceeds options.maxEditLength (if given),
95+
// in which case it will return undefined.
9196
if (callback) {
9297
(function exec() {
9398
setTimeout(function() {
94-
// This should not happen, but we want to be safe.
95-
/* istanbul ignore next */
9699
if (editLength > maxEditLength) {
97100
return callback();
98101
}

Diff for: src/patch/create.js

+4
Original file line numberDiff line numberDiff line change
@@ -9,6 +9,10 @@ export function structuredPatch(oldFileName, newFileName, oldStr, newStr, oldHea
99
}
1010

1111
const diff = diffLines(oldStr, newStr, options);
12+
if(!diff) {
13+
return;
14+
}
15+
1216
diff.push({value: '', lines: []}); // Append an empty value to make cleanup easier
1317

1418
function contextLines(lines) {

Diff for: test/diff/line.js

+18
Original file line numberDiff line numberDiff line change
@@ -46,6 +46,24 @@ describe('diff/line', function() {
4646
'');
4747
expect(convertChangesToXML(diffResult)).to.equal('<del>line\n\nold value \n\nline</del>');
4848
});
49+
50+
describe('given options.maxEditLength', function() {
51+
it('terminates early', function() {
52+
const diffResult = diffLines(
53+
'line\nold value\nline',
54+
'line\nnew value\nline', { maxEditLength: 1 });
55+
expect(diffResult).to.be.undefined;
56+
});
57+
it('terminates early - async', function(done) {
58+
function callback(diffResult) {
59+
expect(diffResult).to.be.undefined;
60+
done();
61+
}
62+
diffLines(
63+
'line\nold value\nline',
64+
'line\nnew value\nline', { callback, maxEditLength: 1 });
65+
});
66+
});
4967
});
5068

5169
// Trimmed Line Diff

Diff for: test/patch/create.js

+13
Original file line numberDiff line numberDiff line change
@@ -721,6 +721,19 @@ describe('patch/create', function() {
721721
}]
722722
});
723723
});
724+
725+
describe('given options.maxEditLength', function() {
726+
const options = { maxEditLength: 1 };
727+
728+
it('terminates early', function() {
729+
const res = structuredPatch(
730+
'oldfile', 'newfile',
731+
'line2\nline3\nline4\n', 'line2\nline3\nline5',
732+
'header1', 'header2', options
733+
);
734+
expect(res).to.be.undefined;
735+
});
736+
});
724737
});
725738

726739
describe('#formatPatch', function() {

0 commit comments

Comments
 (0)