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;
|
var Range = require("./range").Range;
|
||||||
|
|
||||||
function splitLine (lines, point) {
|
function splitLine (docLines, position) {
|
||||||
var text = lines[point.row];
|
var text = docLines[position.row];
|
||||||
lines[point.row] = text.slice(0, point.column);
|
docLines[position.row] = text.slice(0, position.column);
|
||||||
lines.splice(point.row + 1, 0, text.slice(point.column));
|
docLines.splice(position.row + 1, 0, text.slice(position.column));
|
||||||
}
|
}
|
||||||
|
|
||||||
function joinLineWithNext(lines, row) {
|
function joinLineWithNext(docLines, row) {
|
||||||
lines[row] += lines[row + 1];
|
docLines[row] += docLines[row + 1];
|
||||||
lines.splice(row + 1, 1);
|
docLines.splice(row + 1, 1);
|
||||||
}
|
}
|
||||||
|
|
||||||
function throwDeltaError(delta, errorText){
|
function throwDeltaError(delta, errorText){
|
||||||
errorText = 'Invalid Delta: ' + errorText;
|
console.log('Invalid Delta:', delta);
|
||||||
console.log(errorText, delta);
|
throw 'Invalid Delta: ' + errorText;
|
||||||
throw 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')
|
if (delta.action != 'insert' && delta.action != 'remove')
|
||||||
fnThrow('Delta action must be "insert" or "remove".');
|
throwDeltaError(delta, 'delta.action must be "insert" or "remove"');
|
||||||
|
|
||||||
// Validate lines.
|
// Validate lines type.
|
||||||
if (!delta.lines instanceof Array)
|
if (!(delta.lines instanceof Array))
|
||||||
fnThrow('Delta lines must be an array');
|
throwDeltaError(delta, 'delta.lines must be an Array');
|
||||||
|
|
||||||
// Validate range type.
|
// Validate range type.
|
||||||
if (!delta.range instanceof Range)
|
if (!(delta.range instanceof Range))
|
||||||
fnThrow('Range object is not an instance of the Range class');
|
throwDeltaError(delta, 'delta.range must be an instance of the Range class');
|
||||||
|
|
||||||
// Validate start point.
|
// Validate that the start point is contained in the document.
|
||||||
var start = delta.range.start;
|
var start = delta.range.start;
|
||||||
if (Math.min(Math.max(start.row, 0), lines.length - 1 ) != start.row ||
|
if (!positionInDocument(docLines, delta.range.start))
|
||||||
Math.min(Math.max(start.column, 0), lines[start.row].length) != start.column)
|
throwDeltaError(delta, 'delta.range.start must be contained in document');
|
||||||
{
|
|
||||||
fnThrow('Range start point not contained in document');
|
// 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');
|
||||||
|
|
||||||
|
// 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');
|
||||||
}
|
}
|
||||||
|
|
||||||
// Validate ending row offset.
|
exports.applyDelta = function(docLines, delta) {
|
||||||
if (delta.lines.length - 1 != delta.range.end.row - delta.range.start.row)
|
|
||||||
fnThrow('Range row offsets does not match delta lines');
|
|
||||||
|
|
||||||
// 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.
|
// Validate delta.
|
||||||
validateDelta(lines, delta);
|
validateDelta(docLines, delta);
|
||||||
|
|
||||||
// Apply delta.
|
// Apply delta.
|
||||||
if (delta.range.start.row == delta.range.end.row)
|
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 row = delta.range.start.row;
|
||||||
var startColumn = delta.range.start.column;
|
var startColumn = delta.range.start.column;
|
||||||
var endColumn = delta.range.end.column;
|
var endColumn = delta.range.end.column;
|
||||||
var line = lines[row];
|
var line = docLines[row];
|
||||||
switch (delta.action) {
|
switch (delta.action) {
|
||||||
|
|
||||||
case 'insert':
|
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;
|
break;
|
||||||
|
|
||||||
case 'remove':
|
case 'remove':
|
||||||
lines[row] = line.substring(0, startColumn) + line.substring(endColumn);
|
docLines[row] = line.substring(0, startColumn) + line.substring(endColumn);
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
|
|
@ -113,20 +117,20 @@ exports.applyDelta = function(lines, delta) {
|
||||||
switch (delta.action) {
|
switch (delta.action) {
|
||||||
|
|
||||||
case 'insert':
|
case 'insert':
|
||||||
splitLine(lines, delta.range.start);
|
splitLine(docLines, delta.range.start);
|
||||||
lines.splice.apply(lines, [delta.range.start.row + 1, 0].concat(delta.lines));
|
docLines.splice.apply(docLines, [delta.range.start.row + 1, 0].concat(delta.lines));
|
||||||
joinLineWithNext(lines, delta.range.start.row);
|
joinLineWithNext(docLines, delta.range.start.row);
|
||||||
joinLineWithNext(lines, delta.range.end.row);
|
joinLineWithNext(docLines, delta.range.end.row);
|
||||||
break;
|
break;
|
||||||
|
|
||||||
case 'remove':
|
case 'remove':
|
||||||
splitLine(lines, delta.range.end);
|
splitLine(docLines, delta.range.end);
|
||||||
splitLine(lines, delta.range.start);
|
splitLine(docLines, delta.range.start);
|
||||||
lines.splice(
|
docLines.splice(
|
||||||
delta.range.start.row + 1, // Where to start deleting
|
delta.range.start.row + 1, // Where to start deleting
|
||||||
delta.range.end.row - delta.range.start.row + 1 // Num lines to delete.
|
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;
|
break;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -1,6 +1,7 @@
|
||||||
define(function(require, exports, module) {
|
define(function(require, exports, module) {
|
||||||
"use strict";
|
"use strict";
|
||||||
|
|
||||||
|
var Range = require("../range").Range;
|
||||||
var Document = require("../document").Document;
|
var Document = require("../document").Document;
|
||||||
var lang = require("../lib/lang");
|
var lang = require("../lib/lang");
|
||||||
|
|
||||||
|
|
@ -12,7 +13,17 @@ var Mirror = exports.Mirror = function(sender) {
|
||||||
|
|
||||||
var _self = this;
|
var _self = this;
|
||||||
sender.on("change", function(e) {
|
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)
|
if (_self.$timeout)
|
||||||
return deferredUpdate.schedule(_self.$timeout);
|
return deferredUpdate.schedule(_self.$timeout);
|
||||||
_self.onUpdate();
|
_self.onUpdate();
|
||||||
|
|
|
||||||
Loading…
Add table
Add a link
Reference in a new issue