fixing types.
This commit is contained in:
parent
f862fae473
commit
9b45a78e58
@ -4,8 +4,22 @@ class AbstractTransaction { //eslint-disable-line no-unused-vars
|
|||||||
this.store = store;
|
this.store = store;
|
||||||
}
|
}
|
||||||
*getType (id) {
|
*getType (id) {
|
||||||
var op = yield* this.getOperation(id);
|
var sid = JSON.stringify(id);
|
||||||
return new Y[op.type].Create(op);
|
var t = this.store.initializedTypes[sid];
|
||||||
|
if (t == null) {
|
||||||
|
var op = yield* this.getOperation(id);
|
||||||
|
if (op != null) {
|
||||||
|
t = new Y[op.type].Create(op.id);
|
||||||
|
this.store.initializedTypes[sid] = t;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return t;
|
||||||
|
}
|
||||||
|
createType (model) {
|
||||||
|
var sid = JSON.stringify(model.id);
|
||||||
|
var t = new Y[model.type].Create(model.id);
|
||||||
|
this.store.initializedTypes[sid] = t;
|
||||||
|
return t;
|
||||||
}
|
}
|
||||||
// returns false if operation is not expected.
|
// returns false if operation is not expected.
|
||||||
*addOperation (op) {
|
*addOperation (op) {
|
||||||
@ -34,9 +48,6 @@ type Id = [string, number];
|
|||||||
class AbstractOperationStore { //eslint-disable-line no-unused-vars
|
class AbstractOperationStore { //eslint-disable-line no-unused-vars
|
||||||
constructor (y) {
|
constructor (y) {
|
||||||
this.y = y;
|
this.y = y;
|
||||||
this.parentListeners = {};
|
|
||||||
this.parentListenersRequestPending = false;
|
|
||||||
this.parentListenersActivated = {};
|
|
||||||
// E.g. this.listenersById[id] : Array<Listener>
|
// E.g. this.listenersById[id] : Array<Listener>
|
||||||
this.listenersById = {};
|
this.listenersById = {};
|
||||||
// Execute the next time a transaction is requested
|
// Execute the next time a transaction is requested
|
||||||
@ -53,6 +64,9 @@ class AbstractOperationStore { //eslint-disable-line no-unused-vars
|
|||||||
Always remember to first overwrite
|
Always remember to first overwrite
|
||||||
a property before you iterate over it!
|
a property before you iterate over it!
|
||||||
*/
|
*/
|
||||||
|
// TODO: Use ES7 Weak Maps. This way types that are no longer user,
|
||||||
|
// wont be kept in memory.
|
||||||
|
this.initializedTypes = {};
|
||||||
}
|
}
|
||||||
setUserId (userId) {
|
setUserId (userId) {
|
||||||
this.userId = userId;
|
this.userId = userId;
|
||||||
@ -142,32 +156,11 @@ class AbstractOperationStore { //eslint-disable-line no-unused-vars
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
// notify parent listeners, if possible
|
// notify parent, if it has been initialized as a custom type
|
||||||
var listeners = this.parentListeners[op.parent];
|
var t = this.initializedTypes[JSON.stringify(op.parent)];
|
||||||
if ( this.parentListenersRequestPending
|
if (t != null) {
|
||||||
|| ( listeners == null )
|
t._changed(op);
|
||||||
|| ( listeners.length === 0 )) {
|
|
||||||
return;
|
|
||||||
}
|
}
|
||||||
var al = this.parentListenersActivated[JSON.stringify(op.parent)];
|
|
||||||
if ( al == null ){
|
|
||||||
al = [];
|
|
||||||
this.parentListenersActivated[JSON.stringify(op.parent)] = al;
|
|
||||||
}
|
|
||||||
al.push(op);
|
|
||||||
|
|
||||||
this.parentListenersRequestPending = true;
|
|
||||||
var store = this;
|
|
||||||
this.requestTransaction(function*(){
|
|
||||||
store.parentListenersRequestPending = false;
|
|
||||||
var activatedOperations = store.parentListenersActivated;
|
|
||||||
store.parentListenersActivated = {};
|
|
||||||
for (var parentId in activatedOperations){
|
|
||||||
var parent = yield* this.getOperation(parentId);
|
|
||||||
Struct[parent.struct].notifyObservers(activatedOperations[parentId]);
|
|
||||||
}
|
|
||||||
});
|
|
||||||
|
|
||||||
}
|
}
|
||||||
removeParentListener (id, f) {
|
removeParentListener (id, f) {
|
||||||
var ls = this.parentListeners[id];
|
var ls = this.parentListeners[id];
|
||||||
|
@ -35,12 +35,10 @@ Y.Memory = (function(){ //eslint-disable-line no-unused-vars
|
|||||||
return op;
|
return op;
|
||||||
}
|
}
|
||||||
*getOperation (id) {
|
*getOperation (id) {
|
||||||
var op = this.os.find(id);
|
if (id == null) {
|
||||||
if (op == null) {
|
throw new Error("You must define id!");
|
||||||
throw new Error("Op does not exist..");
|
|
||||||
} else {
|
|
||||||
return op;
|
|
||||||
}
|
}
|
||||||
|
return this.os.find(id);
|
||||||
}
|
}
|
||||||
*removeOperation (id) {
|
*removeOperation (id) {
|
||||||
this.os.delete(id);
|
this.os.delete(id);
|
||||||
@ -123,13 +121,13 @@ Y.Memory = (function(){ //eslint-disable-line no-unused-vars
|
|||||||
}
|
}
|
||||||
requestTransaction (makeGen : Function) {
|
requestTransaction (makeGen : Function) {
|
||||||
var t = new Transaction(this);
|
var t = new Transaction(this);
|
||||||
var gen = makeGen.call(t, new Y.Map.Create(["_", 0]));
|
var gen = makeGen.call(t, t.getType(["_", 0]).next().value);
|
||||||
var res = gen.next();
|
var res = gen.next();
|
||||||
while(!res.done){
|
while(!res.done){
|
||||||
if (res.value === "transaction") {
|
if (res.value === "transaction") {
|
||||||
res = gen.next(t);
|
res = gen.next(t);
|
||||||
} else {
|
} else {
|
||||||
throw new Error("You may not yield this type. (Maybe you meant to use 'yield*'?)");
|
throw new Error("You must not yield this type. (Maybe you meant to use 'yield*'?)");
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -417,9 +417,12 @@ var Struct = {
|
|||||||
}
|
}
|
||||||
},
|
},
|
||||||
get: function* (op, name) {
|
get: function* (op, name) {
|
||||||
var res = yield* this.getOperation(op.map[name]);
|
var oid = op.map[name];
|
||||||
return (res == null || res.deleted) ? void 0 : (res.opContent == null
|
if (oid != null) {
|
||||||
? res.content : yield* this.getType(res.opContent));
|
var res = yield* this.getOperation(oid);
|
||||||
|
return (res == null || res.deleted) ? void 0 : (res.opContent == null
|
||||||
|
? res.content : yield* this.getType(res.opContent));
|
||||||
|
}
|
||||||
},
|
},
|
||||||
set: function* (op, name, value) {
|
set: function* (op, name, value) {
|
||||||
var right = op.map[name] || null;
|
var right = op.map[name] || null;
|
||||||
@ -429,19 +432,13 @@ var Struct = {
|
|||||||
parent: op.id,
|
parent: op.id,
|
||||||
parentSub: name
|
parentSub: name
|
||||||
};
|
};
|
||||||
var oid;
|
|
||||||
if ( value != null && value._model != null
|
if ( value != null && value._model != null
|
||||||
&& (oid = value._model.id) != null && oid.length === 2) {
|
&& value._model.length === 2) {
|
||||||
insert.opContent = oid;
|
insert.opContent = value._model;
|
||||||
} else {
|
} else {
|
||||||
insert.content = value;
|
insert.content = value;
|
||||||
}
|
}
|
||||||
yield* Struct.Insert.create.call(this, insert);
|
yield* Struct.Insert.create.call(this, insert);
|
||||||
if (right != null) {
|
|
||||||
yield* Struct.Delete.create.call(this, {
|
|
||||||
target: right
|
|
||||||
});
|
|
||||||
}
|
|
||||||
},
|
},
|
||||||
delete: function* (op, name) {
|
delete: function* (op, name) {
|
||||||
var v = op.map[name] || null;
|
var v = op.map[name] || null;
|
||||||
|
@ -8,11 +8,12 @@
|
|||||||
}
|
}
|
||||||
*val (pos) {
|
*val (pos) {
|
||||||
var t = yield "transaction";
|
var t = yield "transaction";
|
||||||
|
var model = yield* t.getOperation(this._model);
|
||||||
if (pos != null) {
|
if (pos != null) {
|
||||||
var o = yield* Y.Struct.List.ref.call(t, this._model, pos);
|
var o = yield* Y.Struct.List.ref.call(t, model, pos);
|
||||||
return o ? o.content : null;
|
return o ? o.content : null;
|
||||||
} else {
|
} else {
|
||||||
return yield* Y.Struct.List.map.call(t, this._model, function(c){return c; });
|
return yield* Y.Struct.List.map.call(t, model, function(c){return c; });
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
*insert (pos, contents) {
|
*insert (pos, contents) {
|
||||||
@ -23,21 +24,25 @@
|
|||||||
throw new Error("contents must be an Array of objects!");
|
throw new Error("contents must be an Array of objects!");
|
||||||
}
|
}
|
||||||
var t = yield "transaction";
|
var t = yield "transaction";
|
||||||
yield* Y.Struct.List.insert.call(t, this._model, pos, contents);
|
var model = yield* t.getOperation(this._model);
|
||||||
|
yield* Y.Struct.List.insert.call(t, model, pos, contents);
|
||||||
}
|
}
|
||||||
*delete (pos) {
|
*delete (pos) {
|
||||||
if (typeof pos !== "number") {
|
if (typeof pos !== "number") {
|
||||||
throw new Error("pos must be a number!");
|
throw new Error("pos must be a number!");
|
||||||
}
|
}
|
||||||
var t = yield "transaction";
|
var t = yield "transaction";
|
||||||
yield* Y.Struct.List.delete.call(t, this._model, pos);
|
var model = yield* t.getOperation(this._model);
|
||||||
|
yield* Y.Struct.List.delete.call(t, model, pos);
|
||||||
|
}
|
||||||
|
_changed () {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
Y.List = function* YList(){
|
Y.List = function* YList(){
|
||||||
var t = yield "transaction";
|
var t = yield "transaction";
|
||||||
var model = yield* Y.Struct.List.create.call(t, {type: "List"});
|
var model = yield* Y.Struct.List.create.call(t, {type: "List"});
|
||||||
return new List(model);
|
return t.createType(model);
|
||||||
};
|
};
|
||||||
Y.List.Create = List;
|
Y.List.Create = List;
|
||||||
})();
|
})();
|
||||||
|
@ -29,13 +29,15 @@
|
|||||||
var model = yield* t.getOperation(this._model);
|
var model = yield* t.getOperation(this._model);
|
||||||
yield* Y.Struct.Map.delete.call(t, model, key);
|
yield* Y.Struct.Map.delete.call(t, model, key);
|
||||||
}
|
}
|
||||||
|
_changed () {
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
Y.Map = function* YMap(){
|
Y.Map = function* YMap(){
|
||||||
var t = yield "transaction";
|
var t = yield "transaction";
|
||||||
if (this instanceof Y.AbstractOperationStore) {
|
if (this instanceof Y.AbstractOperationStore) {
|
||||||
var model = yield* Y.Struct.map.create.call(t, {type: "Map"});
|
var model = yield* Y.Struct.map.create.call(t, {type: "Map"});
|
||||||
return new Map(model);
|
return t.createType(model);
|
||||||
} else {
|
} else {
|
||||||
throw new Error("Don't use `new` to create this type!");
|
throw new Error("Don't use `new` to create this type!");
|
||||||
}
|
}
|
||||||
|
7
src/y.js
7
src/y.js
@ -8,11 +8,14 @@ class Y { //eslint-disable-line no-unused-vars
|
|||||||
this.connector = new Y[opts.connector.name](this, opts.connector);
|
this.connector = new Y[opts.connector.name](this, opts.connector);
|
||||||
this.db.requestTransaction(function*(){
|
this.db.requestTransaction(function*(){
|
||||||
// create initial Map type
|
// create initial Map type
|
||||||
yield* this.addOperation({
|
var model = {
|
||||||
id: ["_", 0],
|
id: ["_", 0],
|
||||||
struct: "Map",
|
struct: "Map",
|
||||||
|
type: "Map",
|
||||||
map: {}
|
map: {}
|
||||||
});
|
};
|
||||||
|
yield* this.addOperation(model);
|
||||||
|
this.createType(model);
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
transact (generator) {
|
transact (generator) {
|
||||||
|
@ -21,7 +21,6 @@ function getRandomNumber(n) {
|
|||||||
return Math.floor(Math.random() * n);
|
return Math.floor(Math.random() * n);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
var numberOfYMapTests = 30;
|
var numberOfYMapTests = 30;
|
||||||
|
|
||||||
function applyRandomTransactions (users, transactions, numberOfTransactions) {
|
function applyRandomTransactions (users, transactions, numberOfTransactions) {
|
||||||
@ -94,12 +93,30 @@ describe("Yjs", function(){
|
|||||||
});
|
});
|
||||||
|
|
||||||
describe("Basic tests", function(){
|
describe("Basic tests", function(){
|
||||||
it("There is an initial Map type", function(){
|
it("There is an initial Map type & it is created only once", function(){
|
||||||
var y = this.users[0];
|
var y = this.users[0];
|
||||||
|
var root1;
|
||||||
y.transact(function*(root){
|
y.transact(function*(root){
|
||||||
expect(root).not.toBeUndefined();
|
expect(root).not.toBeUndefined();
|
||||||
|
root1 = root;
|
||||||
|
});
|
||||||
|
y.transact(function*(root2){
|
||||||
|
expect(root1).toBe(root2);
|
||||||
});
|
});
|
||||||
});
|
});
|
||||||
|
it("Custom Types are created only once", function(){
|
||||||
|
var y = this.users[0];
|
||||||
|
var l1;
|
||||||
|
y.transact(function*(root){
|
||||||
|
var l = yield* Y.List();
|
||||||
|
yield* root.val("list", l);
|
||||||
|
l1 = l;
|
||||||
|
});
|
||||||
|
y.transact(function*(root){
|
||||||
|
expect(l1).toBe(yield* root.val("list"));
|
||||||
|
});
|
||||||
|
});
|
||||||
|
|
||||||
it("Basic get&set of Map property (converge via sync)", function(){
|
it("Basic get&set of Map property (converge via sync)", function(){
|
||||||
var y = this.users[0];
|
var y = this.users[0];
|
||||||
y.transact(function*(root){
|
y.transact(function*(root){
|
||||||
|
Loading…
x
Reference in New Issue
Block a user