fix infinite loop when inserting more than 0xF000 lines at once
This commit is contained in:
parent
a4532dd8b9
commit
27264bb9d9
2 changed files with 43 additions and 12 deletions
|
|
@ -575,14 +575,14 @@ var Document = function(textOrLines) {
|
||||||
return;
|
return;
|
||||||
|
|
||||||
if (isInsert && delta.lines.length > 0xF000)
|
if (isInsert && delta.lines.length > 0xF000)
|
||||||
this.$splitAndapplyLargeDelta(delta);
|
this.$splitAndapplyLargeDelta(delta, 0xF000);
|
||||||
|
|
||||||
// Apply.
|
// Apply.
|
||||||
applyDelta(this.$lines, delta, doNotValidate);
|
applyDelta(this.$lines, delta, doNotValidate);
|
||||||
this._signal("change", delta);
|
this._signal("change", delta);
|
||||||
};
|
};
|
||||||
|
|
||||||
this.$splitAndapplyLargeDelta = function(delta) {
|
this.$splitAndapplyLargeDelta = function(delta, MAX) {
|
||||||
// Split large insert deltas. This is necessary because:
|
// Split large insert deltas. This is necessary because:
|
||||||
// 1. We need to support splicing delta lines into the document via $lines.splice.apply(...)
|
// 1. We need to support splicing delta lines into the document via $lines.splice.apply(...)
|
||||||
// 2. fn.apply() doesn't work for a large number of params. The smallest threshold is on safari 0xFFFF.
|
// 2. fn.apply() doesn't work for a large number of params. The smallest threshold is on safari 0xFFFF.
|
||||||
|
|
@ -592,18 +592,30 @@ var Document = function(textOrLines) {
|
||||||
// delta handling is too slow. If we make delete delta handling faster we can split all large deltas
|
// delta handling is too slow. If we make delete delta handling faster we can split all large deltas
|
||||||
// as shown in https://gist.github.com/aldendaniels/8367109#file-document-snippet-js
|
// as shown in https://gist.github.com/aldendaniels/8367109#file-document-snippet-js
|
||||||
// If we do this, update validateDelta() to limit the number of lines in a delete delta.
|
// If we do this, update validateDelta() to limit the number of lines in a delete delta.
|
||||||
while (delta.lines.length > 0xF000) {
|
var lines = delta.lines;
|
||||||
// Get split deltas.
|
var l = lines.length;
|
||||||
var lines = delta.lines.splice(0, 0xF000);
|
var row = delta.start.row;
|
||||||
lines.push("");
|
var column = delta.start.column;
|
||||||
var start = delta.start;
|
var from = 0, to = 0;
|
||||||
|
do {
|
||||||
|
from = to;
|
||||||
|
to += MAX - 1;
|
||||||
|
var chunk = lines.slice(from, to);
|
||||||
|
if (to > l) {
|
||||||
|
// Update remaining delta.
|
||||||
|
delta.lines = chunk;
|
||||||
|
delta.start.row = row + from;
|
||||||
|
delta.start.column = column;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
chunk.push("");
|
||||||
this.applyDelta({
|
this.applyDelta({
|
||||||
start: this.pos(start.row, start.column),
|
start: this.pos(row + from, column),
|
||||||
end: this.pos(start.row += 0xF000, start.column = 0), // Updates remaining delta.
|
end: this.pos(row + to, column = 0),
|
||||||
action: delta.action,
|
action: delta.action,
|
||||||
lines: lines
|
lines: chunk
|
||||||
}, true);
|
}, true);
|
||||||
}
|
} while(true);
|
||||||
};
|
};
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
|
@ -615,7 +627,7 @@ var Document = function(textOrLines) {
|
||||||
this.applyDelta({
|
this.applyDelta({
|
||||||
start: range.start,
|
start: range.start,
|
||||||
end: range.end,
|
end: range.end,
|
||||||
action: delta.action == "insert" ? "remove" : "insert",
|
action: (delta.action == "insert" ? "remove" : "insert"),
|
||||||
lines: delta.lines.slice()
|
lines: delta.lines.slice()
|
||||||
});
|
});
|
||||||
};
|
};
|
||||||
|
|
|
||||||
|
|
@ -296,6 +296,25 @@ module.exports = {
|
||||||
"test: empty document has to contain one line": function() {
|
"test: empty document has to contain one line": function() {
|
||||||
var doc = new Document("");
|
var doc = new Document("");
|
||||||
assert.equal(doc.$lines.length, 1);
|
assert.equal(doc.$lines.length, 1);
|
||||||
|
},
|
||||||
|
|
||||||
|
"test: inserting huge delta": function() {
|
||||||
|
var doc = new Document("");
|
||||||
|
var val = "";
|
||||||
|
var MAX = 0xF000;
|
||||||
|
for (var i = 0; i < 10 * MAX; i++) {
|
||||||
|
val += i + "\n"
|
||||||
|
}
|
||||||
|
doc.setValue(val);
|
||||||
|
assert.equal(doc.getValue(), val);
|
||||||
|
|
||||||
|
for (var i = 3 * MAX + 2; i >= 3 * MAX - 2; i--) {
|
||||||
|
val = doc.getLines(0, i).join("\n");
|
||||||
|
doc.setValue("\nab");
|
||||||
|
assert.equal(doc.getValue(), "\nab");
|
||||||
|
doc.insert({row: 1, column: 1}, val);
|
||||||
|
assert.equal(doc.getValue(), "\na" + val + "b");
|
||||||
|
}
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
|
||||||
Loading…
Add table
Add a link
Reference in a new issue