From 08edcdfc988fe8eacc40af4da464fb8ebde8c61c Mon Sep 17 00:00:00 2001 From: aldendaniels Date: Fri, 10 Jan 2014 22:49:17 -0600 Subject: [PATCH] Stop doing a line-by-line splicing in applyDelta Also brings back the functionality where large deltas are split into smaller deltas so that .splice.apply() calls will work. --- lib/ace/apply_delta.js | 7 ++----- lib/ace/document.js | 30 +++++++++++++++++++++++++++++- 2 files changed, 31 insertions(+), 6 deletions(-) diff --git a/lib/ace/apply_delta.js b/lib/ace/apply_delta.js index 142d5e1c..380c3289 100644 --- a/lib/ace/apply_delta.js +++ b/lib/ace/apply_delta.js @@ -79,9 +79,9 @@ function validateDelta(lines, delta) { // TODO: // - Validate that the ending column offset matches the lines. // - Validate the deleted lines match the lines in the document. + // - Vaiidate that an insert delta does not contain more than 65001 entries. } - exports.applyDelta = function(lines, delta) { // Validate delta. @@ -114,10 +114,7 @@ exports.applyDelta = function(lines, delta) { case 'insert': splitLine(lines, delta.range.start); - for (var i = 0; i < delta.lines.length; i++) { - var row = delta.range.start.row + 1 + i; - lines.splice(row, 0, delta.lines[i]); - } + lines.splice.apply(lines, [delta.range.start.row + 1, 0].concat(delta.lines)); joinLineWithNext(lines, delta.range.start.row); joinLineWithNext(lines, delta.range.end.row); break; diff --git a/lib/ace/document.js b/lib/ace/document.js index 6968e8f0..cefaa136 100644 --- a/lib/ace/document.js +++ b/lib/ace/document.js @@ -568,8 +568,36 @@ var Document = function(textOrLines) { * @param {Object} delta A delta object (can include 'insert' and 'remove' actions) **/ this.applyDelta = function(delta) { + + // Split large insert deltas. This is necessary because: + // 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 mallest threshold is on safari 0xFFFF. + // + // To Do: Ideally we'd be consistent and also split 'delete' deltas. We don't do this now, because delete + // 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 + // If we do this, update validateDelta() to limit the number of lines in a delete delta. + var bIsInsert = delta.action == 'insert'; + while (bIsInsert && delta.lines.length > 65001) + { + // Get split deltas. + var lines = delta.lines.splice(0, 65000); + lines.push(''); + this.applyDelta({ + action: delta.action, + lines: lines, + range: new Range(delta.range.start.row, delta.range.start.column, + delta.range.start.row + 65000, 0) + }); + + // Update remaining delta. + delta.range.start.row += 65000; + delta.range.start.column = 0; + } + + // Apply. applyDelta(this.$lines, delta); - this._emit("change", { data: delta }); + this._emit("change", { data: delta }); }; /**