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:
aldendaniels 2014-01-01 14:45:54 -06:00
commit 612478e39f

View file

@ -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 'insert':
this.$lines[row] = line.substring(0, startColumn) + delta.lines[0] + line.substring(startColumn);
break;
case 'delete':
this.$lines[row] = line.substring(0, startColumn) + line.substring(endColumn);
break;
}
} else {
case 'delete': // Apply multi-line delta.
splitLine(this.$lines, delta.range.end); switch (delta.action) {
splitLine(this.$lines, delta.range.start);
this.$lines.splice( case 'insert':
delta.range.start.row + 1, // Where to start deleting splitLine(this.$lines, delta.range.start);
delta.range.end.row - delta.range.start.row + 1 // Num lines to delete. for (var i = 0; i < delta.lines.length; i++) {
); var row = delta.range.start.row + 1 + i;
joinLineWithNext(this.$lines, delta.range.start.row); this.$lines.splice(row, 0, delta.lines[i]);
break; }
joinLineWithNext(this.$lines, delta.range.start.row);
default: joinLineWithNext(this.$lines, delta.range.end.row);
throw 'Invalid delta type: ' + delta.action 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 });