Speed up single-line deltas
2e6f12725b slowed down the application of
deltas that only affect a single line. The slow-down, though trivial for
a single line, is significant for operations than separately modify
thousands of rows (such as indenting a large document).
This commit speeds up single-line deltas by avoiding unnecessary calls
to splitLine() and joinLineWithNext().
This commit is contained in:
parent
810e196cc6
commit
612478e39f
1 changed files with 47 additions and 23 deletions
|
|
@ -261,9 +261,13 @@ var Document = function(textOrLines) {
|
||||||
throw errorText;
|
throw errorText;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Validate action.
|
||||||
|
if (delta.action != 'insert' && delta.action != 'delete')
|
||||||
|
fnThrow('Delta action must be "insert" or "delete".');
|
||||||
|
|
||||||
// Validate lines.
|
// Validate lines.
|
||||||
if (!delta.lines instanceof Array)
|
if (!delta.lines instanceof Array)
|
||||||
fnThrow('Delta object lines must be an array');
|
fnThrow('Delta lines must be an array');
|
||||||
|
|
||||||
// Validate range type.
|
// Validate range type.
|
||||||
if (!delta.range instanceof Range)
|
if (!delta.range instanceof Range)
|
||||||
|
|
@ -567,30 +571,50 @@ var Document = function(textOrLines) {
|
||||||
this.$validateDelta(delta);
|
this.$validateDelta(delta);
|
||||||
|
|
||||||
// Apply delta.
|
// Apply delta.
|
||||||
switch (delta.action)
|
if (delta.range.start.row == delta.range.end.row)
|
||||||
{
|
{
|
||||||
case 'insert':
|
// Apply single-line delta.
|
||||||
splitLine(this.$lines, delta.range.start);
|
// Note: The multi-line code below correctly handle single-line
|
||||||
for (var i = 0; i < delta.lines.length; i++) {
|
// deltas too, but we need to short-circuit for speed.
|
||||||
var row = delta.range.start.row + 1 + i;
|
var row = delta.range.start.row;
|
||||||
this.$lines.splice(row, 0, delta.lines[i]);
|
var startColumn = delta.range.start.column;
|
||||||
}
|
var endColumn = delta.range.end.column;
|
||||||
joinLineWithNext(this.$lines, delta.range.start.row);
|
var line = this.$lines[row];
|
||||||
joinLineWithNext(this.$lines, delta.range.end.row);
|
switch (delta.action) {
|
||||||
break;
|
|
||||||
|
|
||||||
case 'delete':
|
case 'insert':
|
||||||
splitLine(this.$lines, delta.range.end);
|
this.$lines[row] = line.substring(0, startColumn) + delta.lines[0] + line.substring(startColumn);
|
||||||
splitLine(this.$lines, delta.range.start);
|
break;
|
||||||
this.$lines.splice(
|
|
||||||
delta.range.start.row + 1, // Where to start deleting
|
|
||||||
delta.range.end.row - delta.range.start.row + 1 // Num lines to delete.
|
|
||||||
);
|
|
||||||
joinLineWithNext(this.$lines, delta.range.start.row);
|
|
||||||
break;
|
|
||||||
|
|
||||||
default:
|
case 'delete':
|
||||||
throw 'Invalid delta type: ' + delta.action
|
this.$lines[row] = line.substring(0, startColumn) + line.substring(endColumn);
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
|
||||||
|
// Apply multi-line delta.
|
||||||
|
switch (delta.action) {
|
||||||
|
|
||||||
|
case 'insert':
|
||||||
|
splitLine(this.$lines, delta.range.start);
|
||||||
|
for (var i = 0; i < delta.lines.length; i++) {
|
||||||
|
var row = delta.range.start.row + 1 + i;
|
||||||
|
this.$lines.splice(row, 0, delta.lines[i]);
|
||||||
|
}
|
||||||
|
joinLineWithNext(this.$lines, delta.range.start.row);
|
||||||
|
joinLineWithNext(this.$lines, delta.range.end.row);
|
||||||
|
break;
|
||||||
|
|
||||||
|
case 'delete':
|
||||||
|
splitLine(this.$lines, delta.range.end);
|
||||||
|
splitLine(this.$lines, delta.range.start);
|
||||||
|
this.$lines.splice(
|
||||||
|
delta.range.start.row + 1, // Where to start deleting
|
||||||
|
delta.range.end.row - delta.range.start.row + 1 // Num lines to delete.
|
||||||
|
);
|
||||||
|
joinLineWithNext(this.$lines, delta.range.start.row);
|
||||||
|
break;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
this._emit("change", { data: delta });
|
this._emit("change", { data: delta });
|
||||||
|
|
|
||||||
Loading…
Add table
Add a link
Reference in a new issue