array & type are observeable
This commit is contained in:
		
							parent
							
								
									9b3fe2f197
								
							
						
					
					
						commit
						60b75d1862
					
				@ -1,6 +1,6 @@
 | 
				
			|||||||
language: node_js
 | 
					language: node_js
 | 
				
			||||||
before_install:
 | 
					before_install:
 | 
				
			||||||
  - "npm install -g bower coffee-script"
 | 
					  - "npm install -g bower"
 | 
				
			||||||
  - "bower install"
 | 
					  - "bower install"
 | 
				
			||||||
node_js:
 | 
					node_js:
 | 
				
			||||||
  - "0.12"
 | 
					  - "0.12"
 | 
				
			||||||
@ -9,3 +9,4 @@ node_js:
 | 
				
			|||||||
branches:
 | 
					branches:
 | 
				
			||||||
  only:
 | 
					  only:
 | 
				
			||||||
    - master
 | 
					    - master
 | 
				
			||||||
 | 
					    - 0.6
 | 
				
			||||||
 | 
				
			|||||||
@ -11,6 +11,7 @@
 | 
				
			|||||||
      // Array of all the values
 | 
					      // Array of all the values
 | 
				
			||||||
      this.valArray = valArray;
 | 
					      this.valArray = valArray;
 | 
				
			||||||
      this.eventHandler = new EventHandler( ops =>{
 | 
					      this.eventHandler = new EventHandler( ops =>{
 | 
				
			||||||
 | 
					        var userEvents = [];
 | 
				
			||||||
        for (var i in ops) {
 | 
					        for (var i in ops) {
 | 
				
			||||||
          var op = ops[i];
 | 
					          var op = ops[i];
 | 
				
			||||||
          if (op.struct === "Insert") {
 | 
					          if (op.struct === "Insert") {
 | 
				
			||||||
@ -28,14 +29,27 @@
 | 
				
			|||||||
            }
 | 
					            }
 | 
				
			||||||
            this.idArray.splice(pos, 0, JSON.stringify(op.id));
 | 
					            this.idArray.splice(pos, 0, JSON.stringify(op.id));
 | 
				
			||||||
            this.valArray.splice(pos, 0, op.content);
 | 
					            this.valArray.splice(pos, 0, op.content);
 | 
				
			||||||
 | 
					            userEvents.push({
 | 
				
			||||||
 | 
					              type: "insert",
 | 
				
			||||||
 | 
					              object: this,
 | 
				
			||||||
 | 
					              index: pos,
 | 
				
			||||||
 | 
					              length: 1
 | 
				
			||||||
 | 
					            });
 | 
				
			||||||
          } else if (op.struct === "Delete") {
 | 
					          } else if (op.struct === "Delete") {
 | 
				
			||||||
            let pos = this.idArray.indexOf(JSON.stringify(op.target));
 | 
					            let pos = this.idArray.indexOf(JSON.stringify(op.target));
 | 
				
			||||||
            this.idArray.splice(pos, 1);
 | 
					            this.idArray.splice(pos, 1);
 | 
				
			||||||
            this.valArray.splice(pos, 1);
 | 
					            this.valArray.splice(pos, 1);
 | 
				
			||||||
 | 
					            userEvents.push({
 | 
				
			||||||
 | 
					              type: "delete",
 | 
				
			||||||
 | 
					              object: this,
 | 
				
			||||||
 | 
					              index: pos,
 | 
				
			||||||
 | 
					              length: 1
 | 
				
			||||||
 | 
					            });
 | 
				
			||||||
          } else {
 | 
					          } else {
 | 
				
			||||||
            throw new Error("Unexpected struct!");
 | 
					            throw new Error("Unexpected struct!");
 | 
				
			||||||
          }
 | 
					          }
 | 
				
			||||||
        }
 | 
					        }
 | 
				
			||||||
 | 
					        this.eventHandler.callUserEventListeners(userEvents);
 | 
				
			||||||
      });
 | 
					      });
 | 
				
			||||||
    }
 | 
					    }
 | 
				
			||||||
    get (pos) {
 | 
					    get (pos) {
 | 
				
			||||||
@ -121,6 +135,9 @@
 | 
				
			|||||||
        eventHandler.awaitedLastDeletes(dels.length, newLeft);
 | 
					        eventHandler.awaitedLastDeletes(dels.length, newLeft);
 | 
				
			||||||
      });
 | 
					      });
 | 
				
			||||||
    }
 | 
					    }
 | 
				
			||||||
 | 
					    observe (f) {
 | 
				
			||||||
 | 
					      this.eventHandler.addUserEventListener(f);
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
    *_changed (transaction, op) {
 | 
					    *_changed (transaction, op) {
 | 
				
			||||||
      if (op.struct === "Insert") {
 | 
					      if (op.struct === "Insert") {
 | 
				
			||||||
        var l = op.left;
 | 
					        var l = op.left;
 | 
				
			||||||
 | 
				
			|||||||
@ -89,6 +89,29 @@ describe("Array Type", function(){
 | 
				
			|||||||
        done();
 | 
					        done();
 | 
				
			||||||
      });
 | 
					      });
 | 
				
			||||||
    });
 | 
					    });
 | 
				
			||||||
 | 
					    it("throw insert & delete events", function(done){
 | 
				
			||||||
 | 
					      this.users[0].root.set("array", Y.Array).then(function(array){
 | 
				
			||||||
 | 
					        var event;
 | 
				
			||||||
 | 
					        array.observe(function(e){
 | 
				
			||||||
 | 
					          event = e;
 | 
				
			||||||
 | 
					        });
 | 
				
			||||||
 | 
					        array.insert(0, [0]);
 | 
				
			||||||
 | 
					        expect(event).toEqual([{
 | 
				
			||||||
 | 
					          type: "insert",
 | 
				
			||||||
 | 
					          object: array,
 | 
				
			||||||
 | 
					          index: 0,
 | 
				
			||||||
 | 
					          length: 1
 | 
				
			||||||
 | 
					        }]);
 | 
				
			||||||
 | 
					        array.delete(0);
 | 
				
			||||||
 | 
					        expect(event).toEqual([{
 | 
				
			||||||
 | 
					          type: "delete",
 | 
				
			||||||
 | 
					          object: array,
 | 
				
			||||||
 | 
					          index: 0,
 | 
				
			||||||
 | 
					          length: 1
 | 
				
			||||||
 | 
					        }]);
 | 
				
			||||||
 | 
					        done();
 | 
				
			||||||
 | 
					      });
 | 
				
			||||||
 | 
					    });
 | 
				
			||||||
  });
 | 
					  });
 | 
				
			||||||
  describe(`${numberOfYArrayTests} Random tests`, function(){
 | 
					  describe(`${numberOfYArrayTests} Random tests`, function(){
 | 
				
			||||||
    var randomArrayTransactions = [
 | 
					    var randomArrayTransactions = [
 | 
				
			||||||
 | 
				
			|||||||
@ -6,6 +6,7 @@ class EventHandler {
 | 
				
			|||||||
    this.waiting = [];
 | 
					    this.waiting = [];
 | 
				
			||||||
    this.awaiting = 0;
 | 
					    this.awaiting = 0;
 | 
				
			||||||
    this.onevent = onevent;
 | 
					    this.onevent = onevent;
 | 
				
			||||||
 | 
					    this.userEventListeners = [];
 | 
				
			||||||
  }
 | 
					  }
 | 
				
			||||||
  receivedOp (op) {
 | 
					  receivedOp (op) {
 | 
				
			||||||
    if (this.awaiting <= 0) {
 | 
					    if (this.awaiting <= 0) {
 | 
				
			||||||
@ -18,6 +19,26 @@ class EventHandler {
 | 
				
			|||||||
    this.awaiting++;
 | 
					    this.awaiting++;
 | 
				
			||||||
    this.onevent(ops);
 | 
					    this.onevent(ops);
 | 
				
			||||||
  }
 | 
					  }
 | 
				
			||||||
 | 
					  addUserEventListener (f) {
 | 
				
			||||||
 | 
					    this.userEventListeners.push(f);
 | 
				
			||||||
 | 
					  }
 | 
				
			||||||
 | 
					  removeUserEventListener (f) {
 | 
				
			||||||
 | 
					    this.userEventListeners = this.userEventListeners.filter(function(g){
 | 
				
			||||||
 | 
					      return f !== g;
 | 
				
			||||||
 | 
					    });
 | 
				
			||||||
 | 
					  }
 | 
				
			||||||
 | 
					  removeAllUserEventListeners () {
 | 
				
			||||||
 | 
					    this.userEventListeners = [];
 | 
				
			||||||
 | 
					  }
 | 
				
			||||||
 | 
					  callUserEventListeners (event) {
 | 
				
			||||||
 | 
					    for (var i in this.userEventListeners) {
 | 
				
			||||||
 | 
					      try {
 | 
				
			||||||
 | 
					        this.userEventListeners[i](event);
 | 
				
			||||||
 | 
					      } catch (e) {
 | 
				
			||||||
 | 
					        console.log("User events must not throw Errors!");//eslint-disable-line
 | 
				
			||||||
 | 
					      }
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					  }
 | 
				
			||||||
  awaitedLastInserts (n) {
 | 
					  awaitedLastInserts (n) {
 | 
				
			||||||
    var ops = this.waiting.splice(this.waiting.length - n);
 | 
					    var ops = this.waiting.splice(this.waiting.length - n);
 | 
				
			||||||
    for (var oid = 0; oid < ops.length; oid++) {
 | 
					    for (var oid = 0; oid < ops.length; oid++) {
 | 
				
			||||||
@ -56,7 +77,7 @@ class EventHandler {
 | 
				
			|||||||
  }
 | 
					  }
 | 
				
			||||||
  tryCallEvents () {
 | 
					  tryCallEvents () {
 | 
				
			||||||
    this.awaiting--;
 | 
					    this.awaiting--;
 | 
				
			||||||
    if (this.awaiting <= 0) {
 | 
					    if (this.awaiting <= 0 && this.waiting.length > 0) {
 | 
				
			||||||
      var events = this.waiting;
 | 
					      var events = this.waiting;
 | 
				
			||||||
      this.waiting = [];
 | 
					      this.waiting = [];
 | 
				
			||||||
      this.onevent(events);
 | 
					      this.onevent(events);
 | 
				
			||||||
@ -73,30 +94,69 @@ class EventHandler {
 | 
				
			|||||||
      this.contents = {};
 | 
					      this.contents = {};
 | 
				
			||||||
      this.opContents = {};
 | 
					      this.opContents = {};
 | 
				
			||||||
      this.eventHandler = new EventHandler( ops =>{
 | 
					      this.eventHandler = new EventHandler( ops =>{
 | 
				
			||||||
 | 
					        var userEvents = [];
 | 
				
			||||||
        for (var i in ops) {
 | 
					        for (var i in ops) {
 | 
				
			||||||
          var op = ops[i];
 | 
					          var op = ops[i];
 | 
				
			||||||
 | 
					          var oldValue;
 | 
				
			||||||
 | 
					          // key is the name to use to access (op)content
 | 
				
			||||||
 | 
					          var key = op.struct === "Delete" ? op.key : op.parentSub;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					          // compute oldValue
 | 
				
			||||||
 | 
					          if (this.opContents[key] != null) {
 | 
				
			||||||
 | 
					            let prevType = this.opContents[key];
 | 
				
			||||||
 | 
					            oldValue = () => { //eslint-disable-line
 | 
				
			||||||
 | 
					              let def = Promise.defer();
 | 
				
			||||||
 | 
					              this.os.requestTransaction(function*(){//eslint-disable-line
 | 
				
			||||||
 | 
					                def.resolve(yield* this.getType(prevType));
 | 
				
			||||||
 | 
					              });
 | 
				
			||||||
 | 
					              return def.promise;
 | 
				
			||||||
 | 
					            };
 | 
				
			||||||
 | 
					          } else {
 | 
				
			||||||
 | 
					            oldValue = this.contents[key];
 | 
				
			||||||
 | 
					          }
 | 
				
			||||||
 | 
					          // compute op event
 | 
				
			||||||
          if (op.struct === "Insert"){
 | 
					          if (op.struct === "Insert"){
 | 
				
			||||||
            if (op.left === null) {
 | 
					            if (op.left === null) {
 | 
				
			||||||
              if (op.opContent != null) {
 | 
					              if (op.opContent != null) {
 | 
				
			||||||
                this.opContents[op.parentSub] = op.opContent;
 | 
					 | 
				
			||||||
              } else {
 | 
					 | 
				
			||||||
                this.contents[op.parentSub] = op.content;
 | 
					 | 
				
			||||||
              }
 | 
					 | 
				
			||||||
              this.map[op.parentSub] = op.id;
 | 
					 | 
				
			||||||
            }
 | 
					 | 
				
			||||||
          } else if (op.struct === "Delete") {
 | 
					 | 
				
			||||||
            var key = op.key;
 | 
					 | 
				
			||||||
            if (compareIds(this.map[key], op.target)) {
 | 
					 | 
				
			||||||
              if (this.contents[key] != null) {
 | 
					 | 
				
			||||||
                delete this.contents[key];
 | 
					                delete this.contents[key];
 | 
				
			||||||
 | 
					                this.opContents[key] = op.opContent;
 | 
				
			||||||
              } else {
 | 
					              } else {
 | 
				
			||||||
                delete this.opContents[key];
 | 
					                delete this.opContents[key];
 | 
				
			||||||
 | 
					                this.contents[key] = op.content;
 | 
				
			||||||
              }
 | 
					              }
 | 
				
			||||||
 | 
					              this.map[key] = op.id;
 | 
				
			||||||
 | 
					              var insertEvent = {
 | 
				
			||||||
 | 
					                name: key,
 | 
				
			||||||
 | 
					                object: this
 | 
				
			||||||
 | 
					              };
 | 
				
			||||||
 | 
					              if (oldValue === undefined) {
 | 
				
			||||||
 | 
					                insertEvent.type = "add";
 | 
				
			||||||
 | 
					              } else {
 | 
				
			||||||
 | 
					                insertEvent.type = "update";
 | 
				
			||||||
 | 
					                insertEvent.oldValue = oldValue;
 | 
				
			||||||
 | 
					              }
 | 
				
			||||||
 | 
					              userEvents.push(insertEvent);
 | 
				
			||||||
 | 
					            }
 | 
				
			||||||
 | 
					          } else if (op.struct === "Delete") {
 | 
				
			||||||
 | 
					            if (compareIds(this.map[key], op.target)) {
 | 
				
			||||||
 | 
					              if (this.opContents[key] != null) {
 | 
				
			||||||
 | 
					                delete this.opContents[key];
 | 
				
			||||||
 | 
					              } else {
 | 
				
			||||||
 | 
					                delete this.contents[key];
 | 
				
			||||||
 | 
					              }
 | 
				
			||||||
 | 
					              var deleteEvent = {
 | 
				
			||||||
 | 
					                name: key,
 | 
				
			||||||
 | 
					                object: this,
 | 
				
			||||||
 | 
					                oldValue: oldValue,
 | 
				
			||||||
 | 
					                type: "delete"
 | 
				
			||||||
 | 
					              };
 | 
				
			||||||
 | 
					              userEvents.push(deleteEvent);
 | 
				
			||||||
            }
 | 
					            }
 | 
				
			||||||
          } else {
 | 
					          } else {
 | 
				
			||||||
            throw new Error("Unexpected Operation!");
 | 
					            throw new Error("Unexpected Operation!");
 | 
				
			||||||
          }
 | 
					          }
 | 
				
			||||||
        }
 | 
					        }
 | 
				
			||||||
 | 
					        this.eventHandler.callUserEventListeners(userEvents);
 | 
				
			||||||
      });
 | 
					      });
 | 
				
			||||||
    }
 | 
					    }
 | 
				
			||||||
    get (key) {
 | 
					    get (key) {
 | 
				
			||||||
@ -173,12 +233,9 @@ class EventHandler {
 | 
				
			|||||||
      }
 | 
					      }
 | 
				
			||||||
      return def.promise;
 | 
					      return def.promise;
 | 
				
			||||||
    }
 | 
					    }
 | 
				
			||||||
    /*
 | 
					    observe (f) {
 | 
				
			||||||
    *delete (key) {
 | 
					      this.eventHandler.addUserEventListener(f);
 | 
				
			||||||
      var t = yield "transaction";
 | 
					    }
 | 
				
			||||||
      var model = yield* t.getOperation(this._model);
 | 
					 | 
				
			||||||
      yield* Y.Struct.Map.delete.call(t, model, key);
 | 
					 | 
				
			||||||
    }*/
 | 
					 | 
				
			||||||
    *_changed (transaction, op) {
 | 
					    *_changed (transaction, op) {
 | 
				
			||||||
      if (op.struct === "Delete") {
 | 
					      if (op.struct === "Delete") {
 | 
				
			||||||
        op.key = (yield* transaction.getOperation(op.target)).parentSub;
 | 
					        op.key = (yield* transaction.getOperation(op.target)).parentSub;
 | 
				
			||||||
 | 
				
			|||||||
@ -136,6 +136,46 @@ describe("Map Type", function(){
 | 
				
			|||||||
        done();
 | 
					        done();
 | 
				
			||||||
      }, 50);
 | 
					      }, 50);
 | 
				
			||||||
    });
 | 
					    });
 | 
				
			||||||
 | 
					    it("throws add & update & delete events (with type and primitive content)", function(done){
 | 
				
			||||||
 | 
					      var y = this.users[0].root;
 | 
				
			||||||
 | 
					      var event;
 | 
				
			||||||
 | 
					      y.observe(function(e){
 | 
				
			||||||
 | 
					        event = e; // just put it on event, should be thrown synchronously anyway
 | 
				
			||||||
 | 
					      });
 | 
				
			||||||
 | 
					      y.set("stuff", 4);
 | 
				
			||||||
 | 
					      expect(event).toEqual([{
 | 
				
			||||||
 | 
					        type: "add",
 | 
				
			||||||
 | 
					        object: y,
 | 
				
			||||||
 | 
					        name: "stuff"
 | 
				
			||||||
 | 
					      }]);
 | 
				
			||||||
 | 
					      // update, oldValue is in contents
 | 
				
			||||||
 | 
					      y.set("stuff", Y.Array);
 | 
				
			||||||
 | 
					      expect(event).toEqual([{
 | 
				
			||||||
 | 
					        type: "update",
 | 
				
			||||||
 | 
					        object: y,
 | 
				
			||||||
 | 
					        name: "stuff",
 | 
				
			||||||
 | 
					        oldValue: 4
 | 
				
			||||||
 | 
					      }]);
 | 
				
			||||||
 | 
					      y.get("stuff").then(function(replacedArray){
 | 
				
			||||||
 | 
					        // update, oldValue is in opContents
 | 
				
			||||||
 | 
					        y.set("stuff", 5);
 | 
				
			||||||
 | 
					        var getYArray = event[0].oldValue;
 | 
				
			||||||
 | 
					        expect(typeof getYArray.constructor === "function").toBeTruthy();
 | 
				
			||||||
 | 
					        getYArray().then(function(array){
 | 
				
			||||||
 | 
					          expect(array).toEqual(replacedArray);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					          // delete
 | 
				
			||||||
 | 
					          y.delete("stuff");
 | 
				
			||||||
 | 
					          expect(event).toEqual([{
 | 
				
			||||||
 | 
					            type: "delete",
 | 
				
			||||||
 | 
					            name: "stuff",
 | 
				
			||||||
 | 
					            object: y,
 | 
				
			||||||
 | 
					            oldValue: 5
 | 
				
			||||||
 | 
					          }]);
 | 
				
			||||||
 | 
					          done();
 | 
				
			||||||
 | 
					        });
 | 
				
			||||||
 | 
					      });
 | 
				
			||||||
 | 
					    });
 | 
				
			||||||
  });
 | 
					  });
 | 
				
			||||||
  describe(`${numberOfYMapTests} Random tests`, function(){
 | 
					  describe(`${numberOfYMapTests} Random tests`, function(){
 | 
				
			||||||
    var randomMapTransactions = [
 | 
					    var randomMapTransactions = [
 | 
				
			||||||
 | 
				
			|||||||
		Loading…
	
	
			
			x
			
			
		
	
		Reference in New Issue
	
	Block a user