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