Don't error when rewinding and insert op which is beyond the length of the document.

ShareJS will accept an op where p > content.length when applied,
and it applies as though p == content.length. However, the op is
passed to us with the original p > content.length. Detect if that
is the case with this op, and shift p back appropriately to match
ShareJS if so.
This commit is contained in:
James Allen 2015-09-25 13:44:44 +01:00
parent 92e0b0f04c
commit 23dfe68cb8
2 changed files with 23 additions and 3 deletions

View file

@ -5,6 +5,8 @@ ConsistencyError = (message) ->
return error
ConsistencyError.prototype.__proto__ = Error.prototype
logger = require "logger-sharelatex"
module.exports = DiffGenerator =
ConsistencyError: ConsistencyError
@ -15,13 +17,24 @@ module.exports = DiffGenerator =
rewindOp: (content, op) ->
if op.i?
textToBeRemoved = content.slice(op.p, op.p + op.i.length)
# ShareJS will accept an op where p > content.length when applied,
# and it applies as though p == content.length. However, the op is
# passed to us with the original p > content.length. Detect if that
# is the case with this op, and shift p back appropriately to match
# ShareJS if so.
p = op.p
max_p = content.length - op.i.length
if p > max_p
logger.warn {max_p, p}, "truncating position to content length"
p = max_p
textToBeRemoved = content.slice(p, p + op.i.length)
if op.i != textToBeRemoved
throw new ConsistencyError(
"Inserted content, '#{op.i}', does not match text to be removed, '#{textToBeRemoved}'"
)
return content.slice(0, op.p) + content.slice(op.p + op.i.length)
return content.slice(0, p) + content.slice(p + op.i.length)
else if op.d?
return content.slice(0, op.p) + op.d + content.slice(op.p)

View file

@ -7,7 +7,8 @@ SandboxedModule = require('sandboxed-module')
describe "DiffGenerator", ->
beforeEach ->
@DiffGenerator = SandboxedModule.require modulePath
@DiffGenerator = SandboxedModule.require modulePath, requires:
"logger-sharelatex": { warn: sinon.stub() }
@ts = Date.now()
@user_id = "mock-user-id"
@user_id_2 = "mock-user-id-2"
@ -34,6 +35,12 @@ describe "DiffGenerator", ->
expect( () =>
@DiffGenerator.rewindOp content, { p: 6, i: "foo" }
).to.throw(@DiffGenerator.ConsistencyError)
describe "with an update which is beyond the length of the content", ->
it "should undo the insert as if it were at the end of the content", ->
content = "foobar"
rewoundContent = @DiffGenerator.rewindOp content, { p: 4, i: "bar" }
rewoundContent.should.equal "foo"
describe "rewindUpdate", ->
it "should rewind ops in reverse", ->