linted all files

This commit is contained in:
Kevin Jahns 2015-06-27 19:01:15 +02:00
parent fec03dc6e1
commit 7ec409e09f
10 changed files with 151 additions and 104 deletions

View File

@ -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
}
}

View File

@ -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 = {

View File

@ -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"
}
}

View File

@ -1,5 +1,5 @@
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!");
}

View File

@ -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) {

View File

@ -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;

View File

@ -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);
}
}
}

View File

@ -1,6 +1,11 @@
/* @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);
}
}

2
y.js

File diff suppressed because one or more lines are too long

File diff suppressed because one or more lines are too long