mirror of
https://github.com/amark/gun.git
synced 2025-07-03 11:22:32 +00:00
Before adding queue to on
This commit is contained in:
parent
ac761bf674
commit
752fe41a19
159
gun.js
159
gun.js
@ -176,7 +176,8 @@
|
|||||||
function noop(){};
|
function noop(){};
|
||||||
function Event(tag, arg, at, as, skip){
|
function Event(tag, arg, at, as, skip){
|
||||||
var ctx = this, ons = ctx.ons || (ctx.ons = {}), on = ons[tag] || (ons[tag] = {s: []}), act, mem;
|
var ctx = this, ons = ctx.ons || (ctx.ons = {}), on = ons[tag] || (ons[tag] = {s: []}), act, mem;
|
||||||
/*if(!arg && 1 === arguments.length){
|
//typeof console !== 'undefined' && console.debug(102, 'on', tag, arg, 'ons', ctx, ons);
|
||||||
|
/*if(!arg && 1 === arguments.length){ // Performance drops significantly even though `arguments.length` should be okay to use.
|
||||||
return on.s;
|
return on.s;
|
||||||
}*/
|
}*/
|
||||||
if(arg instanceof Function){
|
if(arg instanceof Function){
|
||||||
@ -188,7 +189,7 @@
|
|||||||
return;
|
return;
|
||||||
}*/
|
}*/
|
||||||
}
|
}
|
||||||
return;
|
return act;
|
||||||
}
|
}
|
||||||
if(emit){ emit(tag, arg, on, ctx) }
|
if(emit){ emit(tag, arg, on, ctx) }
|
||||||
on.arg = arg;
|
on.arg = arg;
|
||||||
@ -226,9 +227,9 @@
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
on.s = still;
|
on.s = still;
|
||||||
if(0 === still.length){
|
//if(0 === still.length){ // TODO: BUG! If we clean up the events themselves when no longer needed by deleting this code, it causes some tests to fail.
|
||||||
delete ons[tag];
|
// delete ons[tag];
|
||||||
}
|
//}
|
||||||
}
|
}
|
||||||
if(!gap && at && at instanceof Function){
|
if(!gap && at && at instanceof Function){
|
||||||
at.call(as, arg);
|
at.call(as, arg);
|
||||||
@ -237,7 +238,9 @@
|
|||||||
}
|
}
|
||||||
exports.on = Event;
|
exports.on = Event;
|
||||||
}(Util, function add(tag, act, on, ctx){ // Gun specific extensions
|
}(Util, function add(tag, act, on, ctx){ // Gun specific extensions
|
||||||
var mem = on.mem, at;
|
var mem = on.mem;
|
||||||
|
typeof console !== 'undefined' && console.debug(9, 'ON', tag, mem);
|
||||||
|
typeof console !== 'undefined' && console.debug(10, 'SO! The problem is that subsequent event listeners trigger lazy again, but the should queue for the results of the one already trying to finish or else you will get wrong results.');
|
||||||
if(mem){
|
if(mem){
|
||||||
if(mem instanceof Array){
|
if(mem instanceof Array){
|
||||||
act.fn.apply(act.at, mem.concat(act));
|
act.fn.apply(act.at, mem.concat(act));
|
||||||
@ -246,11 +249,10 @@
|
|||||||
}
|
}
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
at = act.at? act.at.gun? act.at : ctx : ctx;
|
if(!ctx.lazy){ return }
|
||||||
if(!at.lex || !at.lex.soul){ return } // TODO: What about lex cursors?
|
var at = act.at? act.at.gun? act.at : ctx : ctx;
|
||||||
console.debug(16, 'on', tag, mem);
|
if(!at.gun){ return }
|
||||||
console.debug(3, 'on', tag, mem);
|
ctx.lazy(at, tag);
|
||||||
Gun.get(at);
|
|
||||||
//if(on.mem){ add(tag, act, on, ctx) } // for synchronous async actions.
|
//if(on.mem){ add(tag, act, on, ctx) } // for synchronous async actions.
|
||||||
}, function(tag, arg, on, at){
|
}, function(tag, arg, on, at){
|
||||||
on.mem = arg;
|
on.mem = arg;
|
||||||
@ -606,8 +608,7 @@
|
|||||||
is_graph(at.graph, map, null, at);
|
is_graph(at.graph, map, null, at);
|
||||||
});
|
});
|
||||||
function map(node, soul){
|
function map(node, soul){
|
||||||
console.debug(12, 'put to get', soul);
|
//Gun.get.got.call(this, null, node);
|
||||||
console.debug(9, 'put to get', soul);
|
|
||||||
Gun.get.got.call(this.gun.__.gun.get(soul)._, null, node);
|
Gun.get.got.call(this.gun.__.gun.get(soul)._, null, node);
|
||||||
}
|
}
|
||||||
}());
|
}());
|
||||||
@ -626,20 +627,21 @@
|
|||||||
stream: cb
|
stream: cb
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
console.debug(4, 'GET', at);
|
console.debug(5, 'GET', at.lex);
|
||||||
Gun.on('get', at); // TODO: What is the cleanest way to reply if there is no responses, without assuming drivers do reply or not?
|
Gun.on('get', at); // TODO: What is the cleanest way to reply if there is no responses, without assuming drivers do reply or not?
|
||||||
return at.gun;
|
return at.gun;
|
||||||
}
|
}
|
||||||
Gun.get.got = got;
|
Gun.get.got = got;
|
||||||
function got(err, node){
|
function got(err, node){ var at = this;
|
||||||
if(err){ Gun.log(err) }
|
if(err){ Gun.log(err) }
|
||||||
console.debug(105, 'GOT', err, node);
|
if(!at.stream){ var soul;
|
||||||
console.debug(5, 'GOT', err, node);
|
if(!node && !at.lex.soul){ return }
|
||||||
Gun.on('stream', Gun.obj.to(this, {err: err, change: node}), stream);
|
at = at.gun.__.gun.get(is_node_soul(node) || at.lex.soul)._;
|
||||||
|
}
|
||||||
|
Gun.on('stream', Gun.obj.to(at, {err: err, change: node}), stream);
|
||||||
}
|
}
|
||||||
function stream(at){
|
function stream(at){
|
||||||
if(!at.stream){ console.log("WARNING! No at.get", at); }
|
if(!at.stream){ console.log("WARNING! No at.stream", at); }
|
||||||
console.debug(6, 'STREAM', at);
|
|
||||||
at.stream(at.err, at.change);
|
at.stream(at.err, at.change);
|
||||||
}
|
}
|
||||||
}());
|
}());
|
||||||
@ -649,6 +651,7 @@
|
|||||||
if(opt.force){ return }
|
if(opt.force){ return }
|
||||||
var lex = at.lex, gun = at.gun, graph = gun.__.graph, node = graph[lex.soul];
|
var lex = at.lex, gun = at.gun, graph = gun.__.graph, node = graph[lex.soul];
|
||||||
if(opt.memory || node){ return at.cb(null, node), ev.stun() }
|
if(opt.memory || node){ return at.cb(null, node), ev.stun() }
|
||||||
|
console.debug(6, 'not in memory');
|
||||||
});
|
});
|
||||||
|
|
||||||
Gun.on('stream', function(at, ev){ var node;
|
Gun.on('stream', function(at, ev){ var node;
|
||||||
@ -667,8 +670,8 @@
|
|||||||
if(get && get[soul] && !get[soul]._.node){
|
if(get && get[soul] && !get[soul]._.node){
|
||||||
get[soul]._.node = __.graph[soul];
|
get[soul]._.node = __.graph[soul];
|
||||||
}
|
}
|
||||||
});
|
});*/
|
||||||
*/
|
|
||||||
Gun.on('stream', function(at){
|
Gun.on('stream', function(at){
|
||||||
var lex = at.lex, soul = lex.soul, field = lex.field;
|
var lex = at.lex, soul = lex.soul, field = lex.field;
|
||||||
var gun = at.gun, graph = gun.__.graph, node = graph[soul], u;
|
var gun = at.gun, graph = gun.__.graph, node = graph[soul], u;
|
||||||
@ -840,12 +843,13 @@
|
|||||||
put.any = cb;
|
put.any = cb;
|
||||||
put.data = data;
|
put.data = data;
|
||||||
put.state = (opt.state || opts.state)();
|
put.state = (opt.state || opts.state)();
|
||||||
|
console.debug(3, 'put put', data);
|
||||||
at.on('chain', link, at); // TODO: ONE?
|
at.on('chain', link, at); // TODO: ONE?
|
||||||
return gun;
|
return gun;
|
||||||
};
|
};
|
||||||
function link(cat, ev){ ev.off(); // TODO: BUG!
|
function link(cat, ev){ ev.off(); // TODO: BUG!
|
||||||
|
console.log(8, 'putting', cat);
|
||||||
var at = this, put = at.put, data, cb;
|
var at = this, put = at.put, data, cb;
|
||||||
console.debug(7, 'putting', at, cat.gun === at.gun, cat);
|
|
||||||
if(cat.err){ return }
|
if(cat.err){ return }
|
||||||
if(!cat.node && (put.opt.init || cat.gun.__.opt.init)){ return }
|
if(!cat.node && (put.opt.init || cat.gun.__.opt.init)){ return }
|
||||||
// TODO: BUG! `at` doesn't have correct backwards data!
|
// TODO: BUG! `at` doesn't have correct backwards data!
|
||||||
@ -858,9 +862,9 @@
|
|||||||
ev.stun();
|
ev.stun();
|
||||||
//put.resume = ev.stun(put.resume);
|
//put.resume = ev.stun(put.resume);
|
||||||
Gun.ify(data, end, {
|
Gun.ify(data, end, {
|
||||||
node: function(env, cb){ var eat = env.at;
|
node: function(env, cb){ var eat = env.at, tmp;
|
||||||
if(1 === eat.path.length && cat.node){
|
if(1 === eat.path.length && cat.node){
|
||||||
eat.soul = is_rel(cat.node[eat.path[0]]); // TODO: BUG! Need to handle paths that aren't loaded yet.
|
eat.soul = (tmp = is_rel(at.value))? tmp : is_rel(cat.node[eat.path[0]]); // TODO: BUG! Need to handle paths that aren't loaded yet.
|
||||||
}
|
}
|
||||||
cb(env, eat);
|
cb(env, eat);
|
||||||
}, value: function(env){ var eat = env.at;
|
}, value: function(env){ var eat = env.at;
|
||||||
@ -892,11 +896,9 @@
|
|||||||
Gun.on('normalize', Gun.obj.to(at, {err: err, graph: env.graph, env: env}), wire);
|
Gun.on('normalize', Gun.obj.to(at, {err: err, graph: env.graph, env: env}), wire);
|
||||||
}
|
}
|
||||||
function wire(at){
|
function wire(at){
|
||||||
console.debug(8, 'pat', at);
|
|
||||||
Gun.put(Gun.obj.to(at, {cb: ack}));
|
Gun.put(Gun.obj.to(at, {cb: ack}));
|
||||||
}
|
}
|
||||||
function ack(err, ok){ var at = this, cb;
|
function ack(err, ok){ var at = this, cb;
|
||||||
console.debug(14, 'ack', err, ok);
|
|
||||||
if((cb = at.put.any) && cb instanceof Function){
|
if((cb = at.put.any) && cb instanceof Function){
|
||||||
cb.call(at.gun, err, ok);
|
cb.call(at.gun, err, ok);
|
||||||
}
|
}
|
||||||
@ -925,16 +927,23 @@
|
|||||||
}
|
}
|
||||||
Gun.on('chain', function(cat, e){
|
Gun.on('chain', function(cat, e){
|
||||||
if(!is_node_soul(cat.node, 'key')){ return }
|
if(!is_node_soul(cat.node, 'key')){ return }
|
||||||
var resume = e.stun(1), node = cat.node, pseudo = cat.gun._.pseudo || (cat.gun._.pseudo = cat.gun._.node = is_node_ify({}, is_node_soul(node)));
|
var resume = e.stun(1), node = cat.change, field = cat.lex.field, pseudo = cat.gun._.pseudo || (cat.gun._.pseudo = cat.gun._.node = is_node_ify({}, is_node_soul(cat.node)));
|
||||||
pseudo._.key = 'pseudo';
|
pseudo._.key = 'pseudo';
|
||||||
cat.seen = cat.seen || {}; // TODO: There is a better way.
|
cat.seen = cat.seen || {}; // TODO: There is a better way.
|
||||||
|
'hello/world' === is_node_soul(node) && console.log("scan", node);
|
||||||
is_node(node, function(n, f){ // TODO: PERF! BAD! Filter out items we've already seen.
|
is_node(node, function(n, f){ // TODO: PERF! BAD! Filter out items we've already seen.
|
||||||
if(cat.seen[f]){ return } cat.seen[f] = true; // TODO: There is a better way.
|
if(cat.seen[f]){ return } cat.seen[f] = true; // TODO: There is a better way.
|
||||||
cat.gun.get(Gun.obj.to(cat.lex, {soul: f}), on);
|
//cat.gun.__.gun.get(Gun.obj.to(cat.lex, {soul: f}), on);
|
||||||
function on(err, node){
|
if(field){
|
||||||
|
cat.gun.__.gun.get(f).path(field, on);
|
||||||
|
} else {
|
||||||
|
cat.gun.__.gun.get(f, on);
|
||||||
|
}
|
||||||
|
function on(err, node, field, at){
|
||||||
if(!node){ return }
|
if(!node){ return }
|
||||||
HAM_node(pseudo, node);
|
HAM_node(pseudo, node);
|
||||||
cat.node = pseudo;
|
cat.node = pseudo;
|
||||||
|
cat.change = at.change;
|
||||||
resume();
|
resume();
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
@ -966,17 +975,10 @@
|
|||||||
if(!opt || !opt.path){ var back = this.__.gun; } // TODO: CHANGING API! Remove this line!
|
if(!opt || !opt.path){ var back = this.__.gun; } // TODO: CHANGING API! Remove this line!
|
||||||
var gun, back = back || this;
|
var gun, back = back || this;
|
||||||
var get = back._.get || (back._.get = {}), tmp;
|
var get = back._.get || (back._.get = {}), tmp;
|
||||||
|
console.debug(2, 'get', lex);
|
||||||
if(typeof lex === 'string'){
|
if(typeof lex === 'string'){
|
||||||
if(!(gun = get[lex])){
|
if(!(gun = get[lex])){
|
||||||
gun = cache(get, lex, back);
|
gun = cache(get, lex, back);
|
||||||
console.debug(15, 'get', lex, get, 'and the', gun);
|
|
||||||
console.debug(2, 'get', lex);
|
|
||||||
if((tmp = gun._.lex).field){
|
|
||||||
/*if(!back._.ons.chain || !back._.ons.chain.s.length){ // TODO: CLEAN UP! // TODO: ONE?
|
|
||||||
back._.on('chain', link, gun._);
|
|
||||||
}*/
|
|
||||||
back._.on('field:' + tmp.field, field, gun._); // TODO: ONE?
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
} else
|
} else
|
||||||
if(!lex && 0 != lex){ // TODO: BUG!?
|
if(!lex && 0 != lex){ // TODO: BUG!?
|
||||||
@ -990,7 +992,7 @@
|
|||||||
if(tmp = lex.soul){
|
if(tmp = lex.soul){
|
||||||
if(lex.field){
|
if(lex.field){
|
||||||
gun = back.chain();
|
gun = back.chain();
|
||||||
gun._.stream = cb;
|
//gun._.stream = cb;
|
||||||
gun._.lex = lex;
|
gun._.lex = lex;
|
||||||
Gun.get(gun._);
|
Gun.get(gun._);
|
||||||
return gun;
|
return gun;
|
||||||
@ -1000,59 +1002,82 @@
|
|||||||
}
|
}
|
||||||
} else
|
} else
|
||||||
if(tmp = lex[_soul]){
|
if(tmp = lex[_soul]){
|
||||||
if(lex[_field]){
|
|
||||||
return back.get({soul: tmp, field: lex[_field]}, cb, opt);
|
|
||||||
}
|
|
||||||
if(!(gun = get[tmp])){
|
if(!(gun = get[tmp])){
|
||||||
gun = cache(get, tmp, back);
|
gun = cache(get, tmp, back);
|
||||||
}
|
}
|
||||||
|
if(tmp = lex[_field]){
|
||||||
|
return gun.path(tmp, cb, opt);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
console.debug(7, 'get', lex);
|
||||||
if(cb && cb instanceof Function){
|
if(cb && cb instanceof Function){
|
||||||
gun._.on('any', pop(cb), gun); // TODO: Perf! Batch! // TODO: API CHANGE? Having to use pop is annoying. Should we support NodeJS style callbacks anymore?
|
//gun._.on('any', pop(cb), gun); // TODO: Perf! Batch! // TODO: API CHANGE? Having to use pop is annoying. Should we support NodeJS style callbacks anymore?
|
||||||
|
console.debug(8, 'getting');
|
||||||
|
gun._.on('any', cb, gun); // TODO: Perf! Batch! // TODO: API CHANGE? Having to use pop is annoying. Should we support NodeJS style callbacks anymore?
|
||||||
}
|
}
|
||||||
return gun;
|
return gun;
|
||||||
}
|
}
|
||||||
function cache(get, key, back){
|
function cache(get, key, back){
|
||||||
var gun = get[key] = back.chain(), at = gun._;
|
var gun = get[key] = back.chain(), at = gun._;
|
||||||
at.stream = stream;
|
at.lazy = lazy;
|
||||||
if(!back.back){
|
if(!back.back){
|
||||||
|
at.stream = stream;
|
||||||
at.lex.soul = key;
|
at.lex.soul = key;
|
||||||
} else {
|
} else {
|
||||||
var lex = at.lex, flex = back._.lex;
|
var lex = at.lex, cat = back._, flex = cat.lex;
|
||||||
lex.field = key;
|
lex.field = key;
|
||||||
if(!flex.field && flex.soul){
|
if(!flex.field && flex.soul){
|
||||||
lex.soul = flex.soul;
|
lex.soul = flex.soul;
|
||||||
}
|
}
|
||||||
|
back._.on('field:' + key, field, at);
|
||||||
}
|
}
|
||||||
return gun;
|
return gun;
|
||||||
}
|
}
|
||||||
function stream(err, node){
|
function lazy(at){ var cat = this;
|
||||||
console.debug(10, 'stream', err, node);
|
if(at.path && at.path.wait){ return } // means we're being lazy again.
|
||||||
Gun.on('chain', this);
|
console.debug(4, 'lazy', at);
|
||||||
//Gun.on('chain', this, link, this);
|
var lex = at.lex;
|
||||||
}
|
if(!lex.soul){
|
||||||
Gun.on('chain', link);
|
if(!(lex.soul = is_rel(cat.value))){
|
||||||
function link(cat, ev){ var at = cat.gun._, u;
|
return; // TODO: BUG! Handle async case.
|
||||||
var err = cat.err, node = cat.node, cex = cat.lex, lex = at.lex, field = lex.field, rel, val;
|
|
||||||
console.debug(13, 'link', at, cat);
|
|
||||||
console.debug(11, 'link', at, cat);
|
|
||||||
if(lex !== cex && lex.field && cex.field){
|
|
||||||
if(obj_has(node, cex.field) && (rel = is_rel(val = node[cex.field]))){
|
|
||||||
return Gun.get(Gun.obj.to(at, {lex: {soul: rel, field: lex.field}}));
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
console.debug(17, 'link', at, cat);
|
Gun.get(at);
|
||||||
at.on('any', [err, (field && node)? node[field] : node, field, cat]); // TODO: Revisit!
|
};
|
||||||
|
function stream(err, node){
|
||||||
|
//Gun.on('chain', this);
|
||||||
|
Gun.on('chain', this, link, this);
|
||||||
|
}
|
||||||
|
//Gun.on('chain', link);
|
||||||
|
function link(cat, ev){ var at = this, u;
|
||||||
|
//at.value = cat.value = cat.node;
|
||||||
|
var err = cat.err, node = cat.node, cex = cat.lex, lex = at.lex, field = lex.field, rel, val;
|
||||||
|
if(at.path && is_node_soul(node) === at.path.rel){ field = u }
|
||||||
|
at.on('any', [err, (field && node)? node[field] : node, lex.field, cat]) // TODO: Revisit!
|
||||||
if(err){ at.on('err', err) }
|
if(err){ at.on('err', err) }
|
||||||
if(node){ at.on('ok', [(field && node)? node[field] : node, field, cat]) } // TODO: Revisit!
|
if(node){ at.on('ok', [(field && node)? node[field] : node, lex.field, cat]) } // TODO: Revisit!
|
||||||
is_node(at.change, map, {cat: cat, at: at});
|
|
||||||
at.on('chain', cat);
|
at.on('chain', cat);
|
||||||
|
if(at.path && field){ return }
|
||||||
|
is_node(cat.change, map, {cat: cat, at: at}) || obj_map(at.get, map, {cat: cat, at: at}); // TODO: Cleaner way? Necessary to pass error/nots down the chain for implicit puts.
|
||||||
}
|
}
|
||||||
function map(val, field){
|
function map(val, field){
|
||||||
this.cat.on('field:' + field, this.cat);
|
this.at.on('field:' + field, this.cat);
|
||||||
}
|
}
|
||||||
function field(cat, ev){ var at = this;
|
function field(cat, ev){ var at = this;
|
||||||
at.on('chain', Gun.obj.to(at, {err: cat.err, change: cat.change}));
|
var node = cat.node, lex, field, rel;
|
||||||
|
if(!at.path){ at.path = {} }
|
||||||
|
if(!node){ return link.call(at, cat, ev) } // TODO: Errors and nots?
|
||||||
|
(lex = at.lex).soul = is_node_soul(node);
|
||||||
|
if(at.value === node[field = lex.field] && obj_has(at, 'value')){ return }
|
||||||
|
if(at.path.ev){ at.path.ev.off() }
|
||||||
|
at.value = node[field];
|
||||||
|
if(rel = at.path.rel = is_rel(at.value)){
|
||||||
|
at.path.wait = true;
|
||||||
|
at.path.ev = at.gun.__.gun.get(rel)._.on('chain', link, at);
|
||||||
|
at.path.wait = false;
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
link.call(at, cat, ev);
|
||||||
}
|
}
|
||||||
}());
|
}());
|
||||||
Gun.chain.path = function(field, cb, opt){
|
Gun.chain.path = function(field, cb, opt){
|
||||||
@ -1160,10 +1185,12 @@
|
|||||||
;(function(){
|
;(function(){
|
||||||
function get(err, data, at){
|
function get(err, data, at){
|
||||||
if(!data && !Gun.obj.empty(at.opt.peers)){ return } // let the peers handle no data.
|
if(!data && !Gun.obj.empty(at.opt.peers)){ return } // let the peers handle no data.
|
||||||
|
console.log("ouch");
|
||||||
at.cb(err, data); // node
|
at.cb(err, data); // node
|
||||||
}
|
}
|
||||||
Gun.on('get', function(at){
|
Gun.on('get', function(at){
|
||||||
var opt = at.opt, lex = at.lex;
|
var opt = at.opt, lex = at.lex;
|
||||||
|
console.debug(7, 'get ASYNC');
|
||||||
Tab.store.get((opt.prefix || '') + lex.soul, get, at);
|
Tab.store.get((opt.prefix || '') + lex.soul, get, at);
|
||||||
});
|
});
|
||||||
}());
|
}());
|
||||||
@ -1303,10 +1330,10 @@
|
|||||||
;(function(exports){ var u;
|
;(function(exports){ var u;
|
||||||
function s(){}
|
function s(){}
|
||||||
s.put = function(key, val, cb){ try{ store.setItem(key, Gun.text.ify(val));if(cb)cb(null) }catch(e){if(cb)cb(e)} }
|
s.put = function(key, val, cb){ try{ store.setItem(key, Gun.text.ify(val));if(cb)cb(null) }catch(e){if(cb)cb(e)} }
|
||||||
s.get = function(key, cb, t){ //setTimeout(function(){
|
s.get = function(key, cb, t){ setTimeout(function(){
|
||||||
try{ cb(null, Gun.obj.ify(store.getItem(key) || null), t);
|
try{ cb(null, Gun.obj.ify(store.getItem(key) || null), t);
|
||||||
}catch(e){ cb(e,u,t)}
|
}catch(e){ cb(e,u,t)}
|
||||||
}//,1) }
|
},1) }
|
||||||
s.del = function(key){ return store.removeItem(key) }
|
s.del = function(key){ return store.removeItem(key) }
|
||||||
var store = window.localStorage || {setItem: function(){}, removeItem: function(){}, getItem: function(){}};
|
var store = window.localStorage || {setItem: function(){}, removeItem: function(){}, getItem: function(){}};
|
||||||
exports.store = s;
|
exports.store = s;
|
||||||
|
@ -49,7 +49,7 @@
|
|||||||
},
|
},
|
||||||
"devDependencies": {
|
"devDependencies": {
|
||||||
"mocha": "~>1.9.0",
|
"mocha": "~>1.9.0",
|
||||||
"panic-server": "~>0.2.4",
|
"panic-server": "~>0.3.0",
|
||||||
"selenium-webdriver": "~>2.53.2"
|
"selenium-webdriver": "~>2.53.2"
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -1352,9 +1352,11 @@ describe('Gun', function(){
|
|||||||
});
|
});
|
||||||
});
|
});
|
||||||
|
|
||||||
it('put node with soul get soul', function(done){
|
it.only('put node with soul get soul', function(done){
|
||||||
|
Gun.log.debug=1;console.log("--------------------------");
|
||||||
gun.put({_: {'#': 'foo'}, hello: 'world'})
|
gun.put({_: {'#': 'foo'}, hello: 'world'})
|
||||||
.get({'#': 'foo'}, function(err, node){
|
.get({'#': 'foo'}, function(err, node){
|
||||||
|
console.log("huh?", err, node);
|
||||||
expect(err).to.not.be.ok();
|
expect(err).to.not.be.ok();
|
||||||
expect(Gun.is.node.soul(node)).to.be('foo');
|
expect(Gun.is.node.soul(node)).to.be('foo');
|
||||||
expect(node.hello).to.be('world');
|
expect(node.hello).to.be('world');
|
||||||
@ -1583,15 +1585,14 @@ describe('Gun', function(){
|
|||||||
|
|
||||||
it('put node path path', function(done){
|
it('put node path path', function(done){
|
||||||
var gun = Gun();
|
var gun = Gun();
|
||||||
Gun.log.debug=1;console.log("----------------------------------");
|
var g = gun.put({hello: {little: 'world'}}).path('hello').path('little', function(err, val, field){
|
||||||
gun.put({hello: {little: 'world'}}).path('hello').path('little', function(err, val, field){
|
|
||||||
if(done.end){ return } // it is okay for path's callback to be called multiple times.
|
if(done.end){ return } // it is okay for path's callback to be called multiple times.
|
||||||
expect(err).to.not.be.ok();
|
expect(err).to.not.be.ok();
|
||||||
expect(field).to.be('little');
|
expect(field).to.be('little');
|
||||||
expect(val).to.be('world');
|
expect(val).to.be('world');
|
||||||
done(); done.end = true;
|
done(); done.end = true;
|
||||||
});
|
});
|
||||||
});return;
|
});
|
||||||
|
|
||||||
it('put node path rel', function(done){
|
it('put node path rel', function(done){
|
||||||
gun.put({foo: {bar: 'lol'}}).path('foo', function(err, val, field){
|
gun.put({foo: {bar: 'lol'}}).path('foo', function(err, val, field){
|
||||||
@ -1617,8 +1618,9 @@ describe('Gun', function(){
|
|||||||
var gun = Gun();
|
var gun = Gun();
|
||||||
gun.put({_:{'#': 'soul/field'}, hi: 'lol', foo: 'bar'});//.key('key/field');
|
gun.put({_:{'#': 'soul/field'}, hi: 'lol', foo: 'bar'});//.key('key/field');
|
||||||
gun.get({'#': 'soul/field', '.': 'hi'}, function(err, val){
|
gun.get({'#': 'soul/field', '.': 'hi'}, function(err, val){
|
||||||
expect(val.hi).to.be('lol');
|
//expect(val.hi).to.be('lol'); // TODO: REVISE API?
|
||||||
expect(Gun.obj.has(val,'foo')).to.not.be.ok();
|
expect(val).to.be('lol');
|
||||||
|
//expect(Gun.obj.has(val,'foo')).to.not.be.ok();
|
||||||
done();
|
done();
|
||||||
})
|
})
|
||||||
});
|
});
|
||||||
@ -1767,7 +1769,7 @@ describe('Gun', function(){
|
|||||||
expect(val).to.be('are');
|
expect(val).to.be('are');
|
||||||
expect(field).to.be('you');
|
expect(field).to.be('you');
|
||||||
done();
|
done();
|
||||||
})
|
});
|
||||||
});
|
});
|
||||||
|
|
||||||
it('get node path put object merge isolated', function(done){
|
it('get node path put object merge isolated', function(done){
|
||||||
@ -1778,6 +1780,8 @@ describe('Gun', function(){
|
|||||||
var puthi = get.put({hi: 'you'});
|
var puthi = get.put({hi: 'you'});
|
||||||
puthi.on(function(node){
|
puthi.on(function(node){
|
||||||
if(done.hi){ return }
|
if(done.hi){ return }
|
||||||
|
//console.log(1, node);
|
||||||
|
expect(node.hello).to.be('key');
|
||||||
expect(node.hi).to.be('you');
|
expect(node.hi).to.be('you');
|
||||||
done.hi = 1;
|
done.hi = 1;
|
||||||
});
|
});
|
||||||
@ -1787,8 +1791,11 @@ describe('Gun', function(){
|
|||||||
path2._.id = 'path2';
|
path2._.id = 'path2';
|
||||||
var putyay = path2.put({yay: "value"});
|
var putyay = path2.put({yay: "value"});
|
||||||
putyay.on(function(node, field){
|
putyay.on(function(node, field){
|
||||||
|
if(done.yay){ return }
|
||||||
|
//console.log(2, field, node);
|
||||||
expect(field).to.be('hi');
|
expect(field).to.be('hi');
|
||||||
expect(node.yay).to.be('value');
|
expect(node.yay).to.be('value');
|
||||||
|
done.yay = true;
|
||||||
});
|
});
|
||||||
setTimeout(function(){
|
setTimeout(function(){
|
||||||
var get3 = gun.get('hello/key/iso');
|
var get3 = gun.get('hello/key/iso');
|
||||||
@ -1796,9 +1803,10 @@ describe('Gun', function(){
|
|||||||
path3._.id = 'path3';
|
path3._.id = 'path3';
|
||||||
var puthappy = path3.put({happy: "faces"});
|
var puthappy = path3.put({happy: "faces"});
|
||||||
puthappy.on(function(node, field){
|
puthappy.on(function(node, field){
|
||||||
|
//console.log(3, field, node);
|
||||||
expect(field).to.be('hi');
|
expect(field).to.be('hi');
|
||||||
expect(node.yay).to.be('value');
|
|
||||||
expect(node.happy).to.be('faces');
|
expect(node.happy).to.be('faces');
|
||||||
|
expect(node.yay).to.be('value');
|
||||||
setTimeout(function(){
|
setTimeout(function(){
|
||||||
done();
|
done();
|
||||||
},200);
|
},200);
|
||||||
@ -1931,6 +1939,7 @@ describe('Gun', function(){
|
|||||||
});
|
});
|
||||||
|
|
||||||
it('get put path', function(done){
|
it('get put path', function(done){
|
||||||
|
Gun.log.debug=1;console.log("-------------------------");
|
||||||
gun.get('hello/world').put({hello: 'Mark'}).path('hello').val(function(val, field){
|
gun.get('hello/world').put({hello: 'Mark'}).path('hello').val(function(val, field){
|
||||||
console.log("WAT?", field, val);
|
console.log("WAT?", field, val);
|
||||||
expect(val).to.be('Mark');
|
expect(val).to.be('Mark');
|
||||||
|
@ -1,3 +1,5 @@
|
|||||||
|
require('./holy/grail');
|
||||||
|
|
||||||
describe('PANIC!', function(){
|
describe('PANIC!', function(){
|
||||||
this.timeout(1000 * 100);
|
this.timeout(1000 * 100);
|
||||||
|
|
||||||
@ -35,7 +37,7 @@ describe('PANIC!', function(){
|
|||||||
function min(n, done, list){
|
function min(n, done, list){
|
||||||
list = list || clients;
|
list = list || clients;
|
||||||
function ready() {
|
function ready() {
|
||||||
if (list.len() >= n) {
|
if (list.length >= n) {
|
||||||
done();
|
done();
|
||||||
list.removeListener('add', ready);
|
list.removeListener('add', ready);
|
||||||
return true;
|
return true;
|
||||||
@ -46,7 +48,7 @@ describe('PANIC!', function(){
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
function gunify(ctx, done){
|
function gunify(done, ctx){
|
||||||
var s = document.createElement('script');
|
var s = document.createElement('script');
|
||||||
s.src = 'gun.js';
|
s.src = 'gun.js';
|
||||||
s.onload = done;
|
s.onload = done;
|
||||||
@ -69,7 +71,7 @@ describe('PANIC!', function(){
|
|||||||
var sync = gun.get('sync');
|
var sync = gun.get('sync');
|
||||||
sync.put({hello: 'world'})
|
sync.put({hello: 'world'})
|
||||||
}).then(function(){
|
}).then(function(){
|
||||||
return bob.run(function(ctx, done){
|
return bob.run(function(done, ctx){
|
||||||
var sync = gun.get('sync');
|
var sync = gun.get('sync');
|
||||||
sync.on(function(val){
|
sync.on(function(val){
|
||||||
if(val.hello === 'world'){
|
if(val.hello === 'world'){
|
177
test/holy/grail.js
Normal file
177
test/holy/grail.js
Normal file
@ -0,0 +1,177 @@
|
|||||||
|
/*
|
||||||
|
This file should be one
|
||||||
|
folder deeper than every
|
||||||
|
other file. It requires
|
||||||
|
mocha to run.
|
||||||
|
*/
|
||||||
|
var panic = require('panic-server');
|
||||||
|
var spawn = require('child_process').spawn;
|
||||||
|
var path = require('path');
|
||||||
|
var http = require('http');
|
||||||
|
var fs = require('fs');
|
||||||
|
var ports = require('./ports');
|
||||||
|
|
||||||
|
var wd = require('selenium-webdriver');
|
||||||
|
|
||||||
|
function open(url) {
|
||||||
|
var driver = new wd.Builder()
|
||||||
|
.forBrowser('firefox')
|
||||||
|
.build();
|
||||||
|
|
||||||
|
driver.get(url);
|
||||||
|
|
||||||
|
return driver;
|
||||||
|
}
|
||||||
|
|
||||||
|
open('http://localhost:' + ports.panic + '/index.html');
|
||||||
|
open('http://localhost:' + ports.panic + '/index.html');
|
||||||
|
|
||||||
|
var staticServer = new http.Server(function (req, res) {
|
||||||
|
if (req.url === '/') {
|
||||||
|
req.url = '/index.html';
|
||||||
|
}
|
||||||
|
var file = path.join(__dirname, req.url);
|
||||||
|
try {
|
||||||
|
var page = fs.readFileSync(file, 'utf8');
|
||||||
|
res.end(page);
|
||||||
|
} catch (e) {
|
||||||
|
// don't care
|
||||||
|
}
|
||||||
|
});
|
||||||
|
|
||||||
|
var server = panic.clients.filter('Node.js').pluck(1);
|
||||||
|
var browsers = panic.clients.excluding(server);
|
||||||
|
|
||||||
|
var alice = browsers.pluck(1);
|
||||||
|
var bob = browsers.excluding(alice).pluck(1);
|
||||||
|
|
||||||
|
var serverPath = path.join(__dirname, 'gun-server.js');
|
||||||
|
|
||||||
|
// start the server on :8080
|
||||||
|
spawn('node', [serverPath]);
|
||||||
|
|
||||||
|
function waitFor (num, list) {
|
||||||
|
return new Promise(function (res) {
|
||||||
|
|
||||||
|
function ready() {
|
||||||
|
if (list.length < num) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
res();
|
||||||
|
list.removeListener('add', ready);
|
||||||
|
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (!ready()) {
|
||||||
|
list.on('add', ready);
|
||||||
|
}
|
||||||
|
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
before(function () {
|
||||||
|
|
||||||
|
this.timeout(1500000);
|
||||||
|
|
||||||
|
// start the panic server
|
||||||
|
panic.server(staticServer).listen(ports.panic);
|
||||||
|
|
||||||
|
return waitFor(2, browsers)
|
||||||
|
.then(function () {
|
||||||
|
return waitFor(1, server);
|
||||||
|
});
|
||||||
|
});
|
||||||
|
|
||||||
|
var scope = {
|
||||||
|
uniqueKey: Math.random().toString(16).slice(2),
|
||||||
|
file: path.join(process.cwd(), 'delete-me.json'),
|
||||||
|
'@scope': true
|
||||||
|
}
|
||||||
|
|
||||||
|
describe('The holy grail', function () {
|
||||||
|
|
||||||
|
it('should allow full recovery', function () {
|
||||||
|
this.timeout(1500000);
|
||||||
|
|
||||||
|
return browsers.run(function () {
|
||||||
|
localStorage.clear();
|
||||||
|
})
|
||||||
|
.then(function () {
|
||||||
|
return browsers.run(function () {
|
||||||
|
window.ref = gun.get(uniqueKey).put({
|
||||||
|
text: 'ignore'
|
||||||
|
});
|
||||||
|
}, scope)
|
||||||
|
})
|
||||||
|
.then(function () {
|
||||||
|
return alice.run(function (done) {
|
||||||
|
// alice saves some data
|
||||||
|
//ref.path('text').put('Initial text', done); // TODO: USE THIS LINE INSTEAD!
|
||||||
|
ref.path('text').put('Initial text');
|
||||||
|
setTimeout(done, 50);
|
||||||
|
});
|
||||||
|
})
|
||||||
|
.then(function () {
|
||||||
|
return bob.run(function (done) {
|
||||||
|
var ctx = this;
|
||||||
|
ref.path('text').on(function (data) {
|
||||||
|
if (data === 'ignore') {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
// bob sees alice's data
|
||||||
|
if (data !== 'Initial text') {
|
||||||
|
ctx.fail('Wrong data showed up: ' + JSON.stringify(data));
|
||||||
|
}
|
||||||
|
done();
|
||||||
|
});
|
||||||
|
});
|
||||||
|
})
|
||||||
|
.then(function () {
|
||||||
|
return server.run(function () {
|
||||||
|
var fs = require('fs');
|
||||||
|
|
||||||
|
// destroy the data
|
||||||
|
fs.unlinkSync(file);
|
||||||
|
|
||||||
|
// crash the server
|
||||||
|
process.exit(0);
|
||||||
|
}, scope);
|
||||||
|
})
|
||||||
|
.then(function () {
|
||||||
|
return alice.run(function (done) {
|
||||||
|
ref.path('text').put('A conflicting update');
|
||||||
|
setTimeout(done, 50);
|
||||||
|
});
|
||||||
|
})
|
||||||
|
.then(function () {
|
||||||
|
return bob.run(function () {
|
||||||
|
ref.path('text').put('B conflicting update');
|
||||||
|
});
|
||||||
|
})
|
||||||
|
.then(function () {
|
||||||
|
spawn('node', [serverPath]);
|
||||||
|
return waitFor(1, server);
|
||||||
|
})
|
||||||
|
.then(function () {
|
||||||
|
return browsers.run(function (done) {
|
||||||
|
var ctx = this;
|
||||||
|
ref.path('text').on(function (value) {
|
||||||
|
if (value === 'B conflicting update') {
|
||||||
|
done();
|
||||||
|
}
|
||||||
|
});
|
||||||
|
});
|
||||||
|
});
|
||||||
|
});
|
||||||
|
});
|
||||||
|
|
||||||
|
|
||||||
|
after(function () {
|
||||||
|
if (server.length) {
|
||||||
|
return server.run(function () {
|
||||||
|
process.exit(0);
|
||||||
|
});
|
||||||
|
}
|
||||||
|
});
|
16
test/holy/gun-server.js
Normal file
16
test/holy/gun-server.js
Normal file
@ -0,0 +1,16 @@
|
|||||||
|
var panic = require('panic-client');
|
||||||
|
var ports = require('./ports');
|
||||||
|
var Gun = require('gun');
|
||||||
|
var gun = new Gun({
|
||||||
|
file: 'delete-me.json'
|
||||||
|
});
|
||||||
|
|
||||||
|
var http = require('http');
|
||||||
|
|
||||||
|
var server = new http.Server(gun.wsp.server);
|
||||||
|
|
||||||
|
gun.wsp(server);
|
||||||
|
|
||||||
|
server.listen(ports.gun);
|
||||||
|
|
||||||
|
panic.server('http://localhost:' + ports.panic);
|
27
test/holy/index.html
Normal file
27
test/holy/index.html
Normal file
@ -0,0 +1,27 @@
|
|||||||
|
|
||||||
|
<!DOCTYPE html>
|
||||||
|
<html lang="en">
|
||||||
|
<head>
|
||||||
|
<meta charset="UTF-8">
|
||||||
|
<title>Holy grail demo</title>
|
||||||
|
</head>
|
||||||
|
<body>
|
||||||
|
<script src='panic.js'></script>
|
||||||
|
<script src='http://localhost:8080/gun.js'></script>
|
||||||
|
|
||||||
|
<script>
|
||||||
|
(function () {
|
||||||
|
var req = new XMLHttpRequest();
|
||||||
|
req.overrideMimeType('application/json');
|
||||||
|
req.open('GET', 'ports.json');
|
||||||
|
req.addEventListener('load', function () {
|
||||||
|
var ports = JSON.parse(req.responseText);
|
||||||
|
var server = 'http://localhost:' + ports.gun + '/gun';
|
||||||
|
window.gun = new Gun(server);
|
||||||
|
panic.server('http://localhost:' + ports.panic);
|
||||||
|
});
|
||||||
|
req.send();
|
||||||
|
}());
|
||||||
|
</script>
|
||||||
|
</body>
|
||||||
|
</html>
|
4
test/holy/ports.json
Normal file
4
test/holy/ports.json
Normal file
@ -0,0 +1,4 @@
|
|||||||
|
{
|
||||||
|
"panic": 3000,
|
||||||
|
"gun": 8080
|
||||||
|
}
|
@ -1978,11 +1978,13 @@
|
|||||||
var hewo = {hello: "world"};
|
var hewo = {hello: "world"};
|
||||||
window.puti = window.puti || 0;
|
window.puti = window.puti || 0;
|
||||||
window.geti = window.geti || 0;
|
window.geti = window.geti || 0;
|
||||||
|
/*
|
||||||
localStorage.clear();
|
localStorage.clear();
|
||||||
gun.get('users').put({1: {where: {lat: Math.random(), lng: Math.random(), i: 1}}});
|
gun.get('users').put({1: {where: {lat: Math.random(), lng: Math.random(), i: 1}}});
|
||||||
//var ok = function(a,b){ console.log('wat', a,b) }
|
//var ok = function(a,b){ console.log('wat', a,b) }
|
||||||
//Gun.log.debug=1;console.log("------------------");
|
//Gun.log.debug=1;console.log("------------------");
|
||||||
var val = gun.get('users').path(1).path('where').val(ok);
|
var val = gun.get('users').path(1).path('where').val(ok);
|
||||||
|
*/
|
||||||
});
|
});
|
||||||
//localStorage.clear();
|
//localStorage.clear();
|
||||||
/*
|
/*
|
||||||
|
@ -27,7 +27,7 @@
|
|||||||
<button id="abort">Abort</button>
|
<button id="abort">Abort</button>
|
||||||
<button id="share">Share</button>
|
<button id="share">Share</button>
|
||||||
<a id="share-result"></a>
|
<a id="share-result"></a>
|
||||||
<script src="./mocha/json2.js"></script>
|
<script src="../json2.js"></script>
|
||||||
<script src="https://code.jquery.com/jquery-1.12.4.min.js"></script>
|
<script src="https://code.jquery.com/jquery-1.12.4.min.js"></script>
|
||||||
<script src="benchmark.js"></script>
|
<script src="benchmark.js"></script>
|
||||||
<script src="ptsd.js"></script>
|
<script src="ptsd.js"></script>
|
||||||
|
Loading…
x
Reference in New Issue
Block a user