Skip to content
Snippets Groups Projects
Commit 7ec409e0 authored by Kevin Jahns's avatar Kevin Jahns
Browse files

linted all files

parent fec03dc6
No related branches found
No related tags found
No related merge requests found
......@@ -5,20 +5,23 @@
"rules": {
"strict": 0,
"camelcase": [1, {"properties": "never"}],
"no-underscore-dangle": 0
"no-underscore-dangle": 0,
"no-constant-condition": 0,
"no-empty": 0
},
"parser": "babel-eslint",
"globals": {
"OperationStore": true,
"AbstractOperationStore": true,
"AbstractTransaction": true,
"AbstractConnector": true,
"Transaction": true,
"IndexedDB": true,
"IDBRequest": true,
"GeneratorFunction": true,
"Y": true,
"setTimeout": true,
"setInterval": true
}
"Struct": true,
"OperationStore": true,
"AbstractOperationStore": true,
"AbstractTransaction": true,
"AbstractConnector": true,
"Transaction": true,
"IndexedDB": true,
"IDBRequest": true,
"GeneratorFunction": true,
"Y": true,
"setTimeout": true,
"setInterval": true
}
}
......@@ -49,7 +49,7 @@ var concat = require("gulp-concat");
var watch = require("gulp-watch");
var polyfills = [
"./node_modules/regenerator/runtime.js"
"./node_modules/gulp-babel/node_modules/babel-core/node_modules/regenerator/runtime.js"
];
var files = {
......
......@@ -10,7 +10,6 @@
},
"pre-commit": [
"lint",
"test",
"build"
],
"repository": {
......@@ -47,7 +46,6 @@
"gulp-util": "^3.0.5",
"gulp-watch": "^4.2.4",
"minimist": "^1.1.1",
"pre-commit": "^1.0.10",
"regenerator": "^0.8.30"
"pre-commit": "^1.0.10"
}
}
class AbstractConnector {
class AbstractConnector { //eslint-disable-line no-unused-vars
/*
opts
.role : String Role of this client ("master" or "slave")
......@@ -73,60 +73,72 @@ class AbstractConnector {
// true otherwise
findNextSyncTarget () {
if (this.currentSyncTarget != null && this.connections[this.currentSyncTarget].isSynced === false) {
throw new Error("The current sync has not finished!")
throw new Error("The current sync has not finished!");
}
var syncUser = null;
for (var uid in this.connections) {
var u = this.connections[uid];
if (!u.isSynced) {
this.currentSyncTarget = uid;
this.send(uid, {
type: "sync step 1",
stateVector: hb.getStateVector()
});
return true;
syncUser = this.connections[uid];
if (!syncUser.isSynced) {
break;
}
}
if (syncUser != null){
var conn = this;
this.y.os.requestTransaction(function*(){
conn.currentSyncTarget = uid;
conn.send(uid, {
type: "sync step 1",
stateVector: yield* this.getStateVector()
});
});
}
// set the state to synced!
if (!this.isSynced) {
this.isSynced = true;
for (var f of this.whenSyncedListeners) {
f()
f();
}
this.whenSyncedListeners = null;
} return false;
}
return false;
}
// You received a raw message, and you know that it is intended for to Yjs. Then call this function.
receiveMessage (sender, m) {
if (m.type === "sync step 1") {
// TODO: make transaction, stream the ops
var ops = yield* this.os.getOperations(m.stateVector);
// TODO: compare against m.sv!
var sv = yield* this.getStateVector();
this.send (sender, {
type: "sync step 2"
os: ops,
stateVector: sv
});
this.syncingClients.push(sender);
setTimeout(()=>{
this.syncingClients = this.syncingClients.filter(function(client){
return client !== sender;
let conn = this;
this.os.requestTransaction(function*(){
var ops = yield* this.getOperations(m.stateVector);
var sv = yield* this.getStateVector();
conn.send(sender, {
type: "sync step 2",
os: ops,
stateVector: sv
});
this.send(sender, {
type: "sync done"
})
}, this.syncingClientDuration);
conn.syncingClients.push(sender);
setTimeout(function(){
conn.syncingClients = conn.syncingClients.filter(function(cli){
return cli !== sender;
});
conn.send(sender, {
type: "sync done"
});
}, conn.syncingClientDuration);
});
} else if (m.type === "sync step 2") {
var ops = this.os.getOperations(m.stateVector);
this.broadcast {
type: "update",
ops: ops
}
let conn = this;
this.os.requestTransaction(function*(){
var ops = yield* this.getOperations(m.stateVector);
conn.broadcast({
type: "update",
ops: ops
});
});
} else if (m.type === "sync done") {
this.connections[sender].isSynced = true;
this.findNextSyncTarget();
}
} else if (m.type === "update") {
for (var client of this.syncingClients) {
this.send(client, m);
......@@ -157,16 +169,16 @@ class AbstractConnector {
}
function parseObject (node) {
var json = {};
for (name in node.attrs) {
var value = node.attrs[name];
for (var attrName in node.attrs) {
var value = node.attrs[attrName];
var int = parseInt(value);
if (isNaN(int) or (""+int) !== value){
json[name] = value;
if (isNaN(int) || ("" + int) !== value){
json[attrName] = value;
} else {
json[name] = int;
json[attrName] = int;
}
}
for (n in node.children){
for (var n in node.children){
var name = n.name;
if (n.getAttribute("isArray") === "true") {
json[name] = parseArray(n);
......@@ -176,7 +188,7 @@ class AbstractConnector {
}
return json;
}
parseObject(node);
parseObject(m);
}
// encode message in xml
// we use string because Strophe only accepts an "xml-string"..
......@@ -186,10 +198,10 @@ class AbstractConnector {
// </y>
// m - ltx element
// json - Object
encodeMessageToXml (m, json) {
encodeMessageToXml (msg, obj) {
// attributes is optional
function encodeObject (m, json) {
for (name in json) {
for (var name in json) {
var value = json[name];
if (name == null) {
// nop
......@@ -212,10 +224,10 @@ class AbstractConnector {
}
}
}
if (json.constructor === Object) {
encodeObject(m.c("y", {xmlns:"http://y.ninja/connector-stanza"}), json);
} else if (json.constructor === Array) {
encodeArray(m.c("y", {xmlns:"http://y.ninja/connector-stanza"}), json);
if (obj.constructor === Object) {
encodeObject(msg.c("y", { xmlns: "http://y.ninja/connector-stanza" }), obj);
} else if (obj.constructor === Array) {
encodeArray(msg.c("y", { xmlns: "http://y.ninja/connector-stanza" }), obj);
} else {
throw new Error("I can't encode this json!");
}
......
......@@ -3,7 +3,7 @@ class AbstractTransaction { //eslint-disable-line no-unused-vars
constructor (store : OperationStore) {
this.store = store;
}
// Throws if operation is not expected.
// returns false if operation is not expected.
*addOperation (op) {
var state = this.getState(op.id[0]);
if (op.id[1] === state.clock){
......@@ -25,7 +25,8 @@ type Listener = {
type Id = [string, number];
class AbstractOperationStore { //eslint-disable-line no-unused-vars
constructor () {
constructor (y) {
this.y = y;
this.parentListeners = {};
this.parentListenersRequestPending = false;
this.parentListenersActivated = {};
......@@ -46,6 +47,12 @@ class AbstractOperationStore { //eslint-disable-line no-unused-vars
a property before you iterate over it!
*/
}
apply (ops) {
for (var o of ops) {
var required = Y.Struct[o.type].requiredOps(o);
this.whenOperationsExist(required, Y.Struct[o.type].execute, o);
}
}
// f is called as soon as every operation requested is available.
// Note that Transaction can (and should) buffer requests.
whenOperationsExist (ids : Array<Id>, f : GeneratorFunction, args : Array<any>) {
......@@ -134,15 +141,15 @@ class AbstractOperationStore { //eslint-disable-line no-unused-vars
this.parentListenersRequestPending = true;
var store = this;
this.requestTransaction(function*(myRequest){ // you can throw error on myRequest, then restart if you have to
this.requestTransaction(function*(){
store.parentListenersRequestPending = false;
var activatedOperations = store.parentListenersActivated;
store.parentListenersActivated = {};
for (var parent_id in activatedOperations){
var parent = yield* this.getOperation(parent_id);
Struct[parent.type].notifyObservers(activatedOperations[parent_id]);
for (var parentId in activatedOperations){
var parent = yield* this.getOperation(parentId);
Struct[parent.type].notifyObservers(activatedOperations[parentId]);
}
})
});
}
removeParentListener (id, f) {
......
......@@ -18,7 +18,7 @@ type IDBOpenDBRequest = Function;
declare var indexedDB : Object;
var IndexedDB = (function(){ //eslint-disable-line no-unused-vars
Y.IndexedDB = (function(){ //eslint-disable-line no-unused-vars
class Transaction extends AbstractTransaction { //eslint-disable-line
transaction: IDBTransaction;
sv: IDBObjectStore;
......@@ -108,9 +108,17 @@ var IndexedDB = (function(){ //eslint-disable-line no-unused-vars
namespace: string;
ready: Promise;
whenReadyListeners: Array<Function>;
constructor (namespace : string) {
super();
this.namespace = namespace;
constructor (y, opts) {
super(y);
if (opts == null) {
opts = {};
}
if (opts.namespace != null || typeof opts.namespace !== "string") {
throw new Error("IndexedDB: expect a string (opts.namespace)!");
} else {
this.namespace = opts.namespace;
}
this.transactionQueue = {
queue: [],
onRequest: null
......@@ -119,7 +127,7 @@ var IndexedDB = (function(){ //eslint-disable-line no-unused-vars
var store = this;
var tGen = (function *transactionGen(){
store.db = yield indexedDB.open(namespace, 3);
store.db = yield indexedDB.open(opts.namespace, 3);
var transactionQueue = store.transactionQueue;
var transaction = null;
......
......@@ -2,28 +2,44 @@
// Op is anything that we could get from the OperationStore.
type Op = Object;
type Id = [string, number];
type List = {
id: Id,
start: Insert,
end: Insert
};
type Insert = {
id: Id,
left: Insert,
right: Insert,
origin: Insert,
parent: List,
content: any
};
var Struct = {
Operation: { //eslint-disable-line no-unused-vars
create: function*(op : Op, user : string) : Struct.Operation {
create: function*(op : Op) : Struct.Operation {
var user = this.store.y.connector.userId;
var state = yield* this.getState(user);
op.id = [user, state.clock];
return yield* this.addOperation(op);
}
},
Insert: {
create: function*( op : Op,
user : string,
content : any,
left : Struct.Insert,
right : Struct.Insert,
parent : Struct.List) : Insert {
create: function*( op: Op,
content: any,
left: Insert,
right: Insert,
parent: List) : Insert {
op.left = left ? left.id : null;
op.origin = op.left;
op.right = right ? right.id : null;
op.parent = parent.id;
op.struct = "Insert";
yield* Struct.Operation.create.call(this, op, user);
yield* Struct.Operation.create.call(this, op);
if (left != null) {
left.right = op.id;
......@@ -69,8 +85,8 @@ var Struct = {
# $this insert_position is to the left of $o (forever!)
*/
execute: function*(op){
var distance_to_origin = yield* Struct.Insert.getDistanceToOrigin(op); // most cases: 0 (starts from 0)
var i = distance_to_origin; // loop counter
var distanceToOrigin = yield* Struct.Insert.getDistanceToOrigin(op); // most cases: 0 (starts from 0)
var i = distanceToOrigin; // loop counter
var o = yield* this.getOperation(this.left);
o = yield* this.getOperation(o.right);
var tmp;
......@@ -80,13 +96,13 @@ var Struct = {
// case 1
if (o.id[0] < op.id[0]) {
op.left = o;
distance_to_origin = i + 1;
distanceToOrigin = i + 1;
}
} else if ((tmp = Struct.Insert.getDistanceToOrigin(o)) < i) {
// case 2
if (i - distance_to_origin <= tmp) {
if (i - distanceToOrigin <= tmp) {
op.left = o;
distance_to_origin = i+1;
distanceToOrigin = i + 1;
}
} else {
break;
......@@ -94,7 +110,7 @@ var Struct = {
i++;
o = yield* this.getOperation(o.next_cl);
} else {
break
break;
}
}
// reconnect..
......@@ -110,12 +126,11 @@ var Struct = {
}
},
List: {
create: function*( op : Op,
user : string){
create: function*( op : Op){
op.start = null;
op.end = null;
op.struct = "List";
return yield* Struct.Operation.create.call(this, op, user);
return yield* Struct.Operation.create.call(this, op);
},
requiredOps: function(op, ids){
if (op.start != null) {
......@@ -126,12 +141,12 @@ var Struct = {
}
return ids;
},
execute: function* (op) {
execute: function* () {
// nop
},
ref: function* (op : Op, pos : number) : Insert {
var o = op.start;
while ( pos !== 0 || o == null) {
while ( pos !== 0 || o != null) {
o = (yield* this.getOperation(o)).right;
pos--;
}
......@@ -140,19 +155,18 @@ var Struct = {
map: function* (o : Op, f : Function) : Array<any> {
o = o.start;
var res = [];
while ( pos !== 0 || o == null) {
while ( o != null) {
var operation = yield* this.getOperation(o);
res.push(f(operation.content));
o = operation.right;
pos--;
}
return res;
},
insert: function* (op, pos : number, contents : Array<any>) {
var o = yield* Struct.List.ref.call(this, op, pos);
var o_end = yield* this.getOperation(o.right);
var or = yield* this.getOperation(o.right);
for (var content of contents) {
o = yield* Struct.Insert.create.call(this, {}, user, content, o, o_end, op);
o = yield* Struct.Insert.create.call(this, {}, content, o, or, op);
}
}
}
......
/* @flow */
function Y (opts) { //eslint-disable-line no-unused-vars
var connector = opts.connector;
Y.Connectors[connector.name]();
class Y { //eslint-disable-line no-unused-vars
constructor (opts) {
this.connector = new Y[opts.connector.name](opts.connector);
this.db = new Y[opts.db.name](this, opts.db);
}
transact (generator) {
this.db.requestTransaction(generator);
}
}
This diff is collapsed.
This diff is collapsed.
0% Loading or .
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment