Fix / complete validateDelta
This uncovered the fact that until now delta.range had not always been a Range object. This inconsistency has been resolved by my changes in mirror.js.
This commit is contained in:
parent
08edcdfc98
commit
ef0e8da522
2 changed files with 62 additions and 47 deletions
|
|
@ -33,59 +33,63 @@ define(function(require, exports, module) {
|
|||
|
||||
var Range = require("./range").Range;
|
||||
|
||||
function splitLine (lines, point) {
|
||||
var text = lines[point.row];
|
||||
lines[point.row] = text.slice(0, point.column);
|
||||
lines.splice(point.row + 1, 0, text.slice(point.column));
|
||||
function splitLine (docLines, position) {
|
||||
var text = docLines[position.row];
|
||||
docLines[position.row] = text.slice(0, position.column);
|
||||
docLines.splice(position.row + 1, 0, text.slice(position.column));
|
||||
}
|
||||
|
||||
function joinLineWithNext(lines, row) {
|
||||
lines[row] += lines[row + 1];
|
||||
lines.splice(row + 1, 1);
|
||||
function joinLineWithNext(docLines, row) {
|
||||
docLines[row] += docLines[row + 1];
|
||||
docLines.splice(row + 1, 1);
|
||||
}
|
||||
|
||||
function throwDeltaError(delta, errorText){
|
||||
errorText = 'Invalid Delta: ' + errorText;
|
||||
console.log(errorText, delta);
|
||||
throw errorText;
|
||||
console.log('Invalid Delta:', delta);
|
||||
throw 'Invalid Delta: ' + errorText;
|
||||
}
|
||||
|
||||
function validateDelta(lines, delta) {
|
||||
function positionInDocument(docLines, position)
|
||||
{
|
||||
return position.row >= 0 && position.row < docLines.length &&
|
||||
position.column >= 0 && position.column <= docLines[position.row].length;
|
||||
}
|
||||
|
||||
// Validate action.
|
||||
function validateDelta(docLines, delta) {
|
||||
|
||||
// Validate action string.
|
||||
if (delta.action != 'insert' && delta.action != 'remove')
|
||||
fnThrow('Delta action must be "insert" or "remove".');
|
||||
|
||||
// Validate lines.
|
||||
if (!delta.lines instanceof Array)
|
||||
fnThrow('Delta lines must be an array');
|
||||
throwDeltaError(delta, 'delta.action must be "insert" or "remove"');
|
||||
|
||||
// Validate lines type.
|
||||
if (!(delta.lines instanceof Array))
|
||||
throwDeltaError(delta, 'delta.lines must be an Array');
|
||||
|
||||
// Validate range type.
|
||||
if (!delta.range instanceof Range)
|
||||
fnThrow('Range object is not an instance of the Range class');
|
||||
|
||||
// Validate start point.
|
||||
if (!(delta.range instanceof Range))
|
||||
throwDeltaError(delta, 'delta.range must be an instance of the Range class');
|
||||
|
||||
// Validate that the start point is contained in the document.
|
||||
var start = delta.range.start;
|
||||
if (Math.min(Math.max(start.row, 0), lines.length - 1 ) != start.row ||
|
||||
Math.min(Math.max(start.column, 0), lines[start.row].length) != start.column)
|
||||
{
|
||||
fnThrow('Range start point not contained in document');
|
||||
}
|
||||
if (!positionInDocument(docLines, delta.range.start))
|
||||
throwDeltaError(delta, 'delta.range.start must be contained in document');
|
||||
|
||||
// Validate ending row offset.
|
||||
if (delta.lines.length - 1 != delta.range.end.row - delta.range.start.row)
|
||||
fnThrow('Range row offsets does not match delta lines');
|
||||
// Validate that the end point is contained in the document (remove deltas only).
|
||||
var end = delta.range.end;
|
||||
if (delta.action == 'remove' && !positionInDocument(docLines, end))
|
||||
throwDeltaError(delta, 'delta.range.end must contained in document for "remove" actions');
|
||||
|
||||
// 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.
|
||||
// Validate that the .range size matches the .lines size.
|
||||
var numRangeRows = end.row - start.row;
|
||||
var numRangeLastLineChars = (end.column - (numRangeRows == 0 ? start.column : 0));
|
||||
if (numRangeRows != delta.lines.length - 1 || delta.lines[numRangeRows].length != numRangeLastLineChars)
|
||||
throwDeltaError(delta, 'delta.range must match delta lines');
|
||||
}
|
||||
|
||||
exports.applyDelta = function(lines, delta) {
|
||||
exports.applyDelta = function(docLines, delta) {
|
||||
|
||||
// Validate delta.
|
||||
validateDelta(lines, delta);
|
||||
validateDelta(docLines, delta);
|
||||
|
||||
// Apply delta.
|
||||
if (delta.range.start.row == delta.range.end.row)
|
||||
|
|
@ -96,15 +100,15 @@ exports.applyDelta = function(lines, delta) {
|
|||
var row = delta.range.start.row;
|
||||
var startColumn = delta.range.start.column;
|
||||
var endColumn = delta.range.end.column;
|
||||
var line = lines[row];
|
||||
var line = docLines[row];
|
||||
switch (delta.action) {
|
||||
|
||||
case 'insert':
|
||||
lines[row] = line.substring(0, startColumn) + delta.lines[0] + line.substring(startColumn);
|
||||
docLines[row] = line.substring(0, startColumn) + delta.lines[0] + line.substring(startColumn);
|
||||
break;
|
||||
|
||||
case 'remove':
|
||||
lines[row] = line.substring(0, startColumn) + line.substring(endColumn);
|
||||
docLines[row] = line.substring(0, startColumn) + line.substring(endColumn);
|
||||
break;
|
||||
}
|
||||
} else {
|
||||
|
|
@ -113,20 +117,20 @@ exports.applyDelta = function(lines, delta) {
|
|||
switch (delta.action) {
|
||||
|
||||
case 'insert':
|
||||
splitLine(lines, delta.range.start);
|
||||
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);
|
||||
splitLine(docLines, delta.range.start);
|
||||
docLines.splice.apply(docLines, [delta.range.start.row + 1, 0].concat(delta.lines));
|
||||
joinLineWithNext(docLines, delta.range.start.row);
|
||||
joinLineWithNext(docLines, delta.range.end.row);
|
||||
break;
|
||||
|
||||
case 'remove':
|
||||
splitLine(lines, delta.range.end);
|
||||
splitLine(lines, delta.range.start);
|
||||
lines.splice(
|
||||
splitLine(docLines, delta.range.end);
|
||||
splitLine(docLines, delta.range.start);
|
||||
docLines.splice(
|
||||
delta.range.start.row + 1, // Where to start deleting
|
||||
delta.range.end.row - delta.range.start.row + 1 // Num lines to delete.
|
||||
);
|
||||
joinLineWithNext(lines, delta.range.start.row);
|
||||
joinLineWithNext(docLines, delta.range.start.row);
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -1,6 +1,7 @@
|
|||
define(function(require, exports, module) {
|
||||
"use strict";
|
||||
|
||||
var Range = require("../range").Range;
|
||||
var Document = require("../document").Document;
|
||||
var lang = require("../lib/lang");
|
||||
|
||||
|
|
@ -12,7 +13,17 @@ var Mirror = exports.Mirror = function(sender) {
|
|||
|
||||
var _self = this;
|
||||
sender.on("change", function(e) {
|
||||
doc.applyDeltas(e.data);
|
||||
|
||||
// Convert delta.range back into a Range instance since
|
||||
// window.onMessage loses non-primitive data. See http://jsfiddle.net/nqJfw/1/.
|
||||
var deltas = e.data;
|
||||
for (var i in deltas)
|
||||
{
|
||||
var delta = deltas[i];
|
||||
delta.range = Range.fromPoints(delta.range.start, delta.range.end);
|
||||
}
|
||||
|
||||
doc.applyDeltas(deltas);
|
||||
if (_self.$timeout)
|
||||
return deferredUpdate.schedule(_self.$timeout);
|
||||
_self.onUpdate();
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue