diff --git a/src/Connector.js b/src/Connector.js index b42f1123..832f580a 100644 --- a/src/Connector.js +++ b/src/Connector.js @@ -112,6 +112,13 @@ class AbstractConnector { //eslint-disable-line no-unused-vars } return false; } + send (uid, message) { + if (this.debug) { + console.log(`me -> ${uid}: ${message.type}`);//eslint-disable-line + console.dir(m); //eslint-disable-line + } + super(uid, message); + } // You received a raw message, and you know that it is intended for to Yjs. Then call this function. receiveMessage (sender, m){ if (sender === this.userId) { diff --git a/src/Connectors/Test.js b/src/Connectors/Test.js index ae7fde3f..5a41348e 100644 --- a/src/Connectors/Test.js +++ b/src/Connectors/Test.js @@ -37,6 +37,7 @@ function flushOne(){ return false; } } + // setInterval(flushOne, 10); var userIdCounter = 0; @@ -64,6 +65,13 @@ class Test extends AbstractConnector { disconnect () { globalRoom.removeUser(this.userId); } + flush() { + var buff = globalRoom.buffers[this.userId]; + while (buff.length > 0) { + var m = buff.shift(); + this.receiveMessage(m[0], m[1]); + } + } flushAll () { var c = true; while (c) { diff --git a/src/OperationStore.js b/src/OperationStore.js index 151fe9de..421d94ed 100644 --- a/src/OperationStore.js +++ b/src/OperationStore.js @@ -174,6 +174,9 @@ class AbstractOperationStore { //eslint-disable-line no-unused-vars yield* this.store.operationAdded(this, op); // find next operation to execute op = this.store.waitingOperations.find([op.id[0], state.clock]); + if (op != null) { + this.store.waitingOperations.delete([op.id[0], state.clock]); + } } else { if (op.id[1] > state.clock) { // has to be executed at some point later diff --git a/src/OperationStores/Memory.js b/src/OperationStores/Memory.js index 61bfb521..2038848a 100644 --- a/src/OperationStores/Memory.js +++ b/src/OperationStores/Memory.js @@ -120,17 +120,31 @@ Y.Memory = (function(){ //eslint-disable-line no-unused-vars super(y); this.os = new RBTree(); this.ss = {}; + this.waitingTransactions = []; + this.transactionInProgress = false; } - requestTransaction (makeGen : Function) { - var t = new Transaction(this); - var gen = makeGen.call(t); - var res = gen.next(); - while(!res.done){ - if (res.value === "transaction") { - res = gen.next(t); - } else { - throw new Error("You must not yield this type. (Maybe you meant to use 'yield*'?)"); - } + requestTransaction (_makeGen : Function) { + if (!this.transactionInProgress) { + this.transactionInProgress = true; + window.setTimeout(() => { + var makeGen = _makeGen; + while (makeGen != null) { + var t = new Transaction(this); + var gen = makeGen.call(t); + var res = gen.next(); + while(!res.done){ + if (res.value === "transaction") { + res = gen.next(t); + } else { + throw new Error("You must not yield this type. (Maybe you meant to use 'yield*'?)"); + } + } + makeGen = this.waitingTransactions.shift(); + } + this.transactionInProgress = false; + }, 0); + } else { + this.waitingTransactions.push(_makeGen); } } *removeDatabase () { diff --git a/src/Struct.js b/src/Struct.js index 04a5ca6b..37884537 100644 --- a/src/Struct.js +++ b/src/Struct.js @@ -95,9 +95,9 @@ var Struct = { if(op.right != null){ ids.push(op.right); } - if(op.right == null && op.left == null) { - ids.push(op.parent); - } + //if(op.right == null && op.left == null) {} + ids.push(op.parent); + if (op.opContent != null) { ids.push(op.opContent); } @@ -276,7 +276,7 @@ var Struct = { map: function* (o : Op, f : Function) : Array { o = o.start; var res = []; - while ( o != null) { + while ( o !== null) { var operation = yield* this.getOperation(o); if (!operation.deleted) { res.push(f(operation)); diff --git a/src/Types/Array.js b/src/Types/Array.js index 418c3104..3c58e73a 100644 --- a/src/Types/Array.js +++ b/src/Types/Array.js @@ -123,6 +123,9 @@ if (pos + length > this.idArray.length || pos < 0 || length < 0) { throw new Error("The deletion range exceeds the range of the array!"); } + if (length === 0) { + return; + } var eventHandler = this.eventHandler; var newLeft = pos > 0 ? JSON.parse(this.idArray[pos - 1]) : null; var dels = []; diff --git a/src/Types/TextBind.spec.js b/src/Types/TextBind.spec.js new file mode 100644 index 00000000..0937de25 --- /dev/null +++ b/src/Types/TextBind.spec.js @@ -0,0 +1,50 @@ +/* @flow */ +/*eslint-env browser,jasmine */ + +describe("TextBind Type", function(){ + jasmine.DEFAULT_TIMEOUT_INTERVAL = 5000; + beforeEach(function(done){ + createUsers(this, 5, done); + }); + + describe("debug tests", function(){ + it("#1", function(done){ + var y = this.users[0].root; + var y2 = this.users[1].root; + var y3 = this.users[2].root; + var c1 = this.users[0].connector; + var c2 = this.users[1].connector; + var c3 = this.users[2].connector; + function flushOneAndTwo(){ + c1.flush(); + c2.flush(); + } + var u1, u2; + y.set("text", Y.TextBind); + flushOneAndTwo(); + y.get("text").then(function(array) { + u1 = array; + flushOneAndTwo(); + return y2.get("text"); + }).then(function(array){ + u2 = array; + u1.insert(0, "a"); + flushOneAndTwo(); + u2.insert(1, "b"); + flushOneAndTwo(); + u1.insert(2, "c"); + flushOneAndTwo(); + u2.insert(3, "d"); + y3.observe(function(events){ + for (var event of events) { + if (event.name === "text") { + y3.get("text"); + } + } + }); + c3.flush(); + done(); + }); + }); + }); +});