diff --git a/src/SpecHelper.js b/src/SpecHelper.js index 4097b7a7b9ca425d37f664e9d75c677952215e73..28abcf5bc385cc7e59e277679d546f51e52f174a 100644 --- a/src/SpecHelper.js +++ b/src/SpecHelper.js @@ -208,6 +208,7 @@ g.compareAllUsers = async(function * compareAllUsers (users) { yield* this.os.iterate(this, null, null, function * (o) { o = Y.utils.copyObject(o) delete o.origin + delete o.originOf db1.push(o) }) }) @@ -222,6 +223,7 @@ g.compareAllUsers = async(function * compareAllUsers (users) { yield* this.os.iterate(this, null, null, function * (o) { o = Y.utils.copyObject(o) delete o.origin + delete o.originOf expect(db1[count++]).toEqual(o) }) }) diff --git a/src/Struct.js b/src/Struct.js index 0ea0dd132a593c530ad6074b2f4120e0ebca1ac2..6638127817a24e68339dd736a706aa4ab2c0be33 100644 --- a/src/Struct.js +++ b/src/Struct.js @@ -126,6 +126,19 @@ module.exports = function (Y/* :any */) { execute: function *(op) { var i // loop counter var distanceToOrigin = i = yield* Struct.Insert.getDistanceToOrigin.call(this, op) // most cases: 0 (starts from 0) + + if (op.origin != null) { + // we save in origin that op originates in it + // we need that later when we eventually garbage collect origin (see transaction) + var origin = yield* this.getOperation(op.origin) + if (origin.originOf == null) { + origin.originOf = [] + } + origin.originOf.push(op.id) + yield* this.setOperation(origin) + } + + // now we begin to insert op in the list of insertions.. var o var parent var start diff --git a/src/Transaction.js b/src/Transaction.js index 45d2e8d6342ce90f6d65ce3f622eb115cf08d5c5..c1e1db14d7e8e66902fd99551b58c4795c76c96e 100644 --- a/src/Transaction.js +++ b/src/Transaction.js @@ -362,23 +362,31 @@ module.exports = function (Y/* :any */) { if (o.right != null) { var right = yield* this.getOperation(o.right) right.left = o.left - if (Y.utils.compareIds(right.origin, o.id)) { // rights origin is o + + if (Y.utils.compareIds(right.origin, id)) { // rights origin is o // find new origin of right ops // origin is the first left deleted operation var neworigin = o.left + var neworigin_ = null while (neworigin != null) { - var neworigin_ = yield* this.getOperation(neworigin) + neworigin_ = yield* this.getOperation(neworigin) if (neworigin_.deleted) { break } neworigin = neworigin_.left } + // reset origin of all right ops (except first right - duh!), + + /* ** The following code does not rely on the the originOf property ** + I recently added originOf to all Insert Operations (see Struct.Insert.execute), + which saves which operations originate in a Insert operation. + Garbage collecting without originOf is more memory efficient, but is nearly impossible for large texts, or lists! + But I keep this code for now + ``` // reset origin of right right.origin = neworigin - - // reset origin of all right ops (except first right - duh!), - // until you find origin pointer to the left of o + // search until you find origin pointer to the left of o if (right.right != null) { var i = yield* this.getOperation(right.right) var ids = [o.id, o.right] @@ -399,9 +407,41 @@ module.exports = function (Y/* :any */) { } } } - } /* otherwise, rights origin is to the left of o, - then there is no right op (from o), that origins in o */ - yield* this.setOperation(right) + ``` + */ + // ** Now the new implementation starts ** + // reset neworigin of all originOf[*] + for (var _i in o.originOf) { + var originsIn = yield* this.getOperation(o.originOf[_i]) + if (originsIn != null) { + originsIn.origin = neworigin + yield* this.setOperation(originsIn) + } + } + if (neworigin != null) { + if (neworigin_.originOf == null) { + neworigin_.originOf = o.originOf + } else { + neworigin_.originOf = o.originOf.concat(neworigin_.originOf) + } + yield* this.setOperation(neworigin_) + } + // we don't need to set right here, because + // right should be in o.originOf => it is set it the previous for loop + } else { + // we didn't need to reset the origin of right + // so we have to set right here + yield* this.setOperation(right) + } + // o may originate in another operation. + // Since o is deleted, we have to reset o.origin's `originOf` property + if (o.origin != null) { + var origin = yield* this.getOperation(o.origin) + origin.originOf = origin.originOf.filter(function (_id) { + return !Y.utils.compareIds(id, _id) + }) + yield* this.setOperation(origin) + } } if (o.parent != null) {