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"
|
||||||
@ -8,4 +8,5 @@ node_js:
|
|||||||
- "0.10"
|
- "0.10"
|
||||||
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