a clean link and map

This commit is contained in:
Mark Nadal 2018-06-18 21:33:05 -07:00
parent 9291434ed7
commit 944194b299
13 changed files with 378 additions and 346 deletions

View File

@ -169,7 +169,7 @@
Gun.node.is(at.put.users, function(val, key){
Gun.SEA.verify(val, false, function(val){
//Gun.SEA.read(val, false, function(val){
if('~@'+key === Gun.val.rel.is(val)){ return }
if('~@'+key === Gun.val.link.is(val)){ return }
no = true;
})
if(no){ return no }

145
gun.js
View File

@ -22,7 +22,7 @@
// Generic javascript utilities.
var Type = {};
//Type.fns = Type.fn = {is: function(fn){ return (!!fn && fn instanceof Function) }}
Type.fns = Type.fn = {is: function(fn){ return (!!fn && 'function' == typeof fn) }}
Type.fn = {is: function(fn){ return (!!fn && 'function' == typeof fn) }}
Type.bi = {is: function(b){ return (b instanceof Boolean || typeof b == 'boolean') }}
Type.num = {is: function(n){ return !list_is(n) && ((n - parseFloat(n) + 1) >= 0 || Infinity === n || -Infinity === n) }}
Type.text = {is: function(t){ return (typeof t == 'string') }}
@ -266,7 +266,7 @@
}
return Val.rel.is(v) || false; // is the value a soul relation? Then it is valid and return it. If not, everything else remaining is an invalid data type. Custom extensions can be built on top of these primitives to support other types.
}
Val.rel = {_: '#'};
Val.link = Val.rel = {_: '#'};
;(function(){
Val.rel.is = function(v){ // this defines whether an object is a soul relation or not, they look like this: {'#': 'UUID'}
if(v && v[rel_] && !v._ && obj_is(v)){ // must be an object.
@ -289,7 +289,7 @@
}());
Val.rel.ify = function(t){ return obj_put({}, rel_, t) } // convert a soul into a relation and return it.
Type.obj.has._ = '.';
var rel_ = Val.rel._, u;
var rel_ = Val.link._, u;
var bi_is = Type.bi.is;
var num_is = Type.num.is;
var text_is = Type.text.is;
@ -309,7 +309,7 @@
n._[soul_] = o.soul || n._[soul_] || text_random(); // put the soul on it.
return n;
}
Node.soul._ = Val.rel._;
Node.soul._ = Val.link._;
;(function(){
Node.is = function(n, cb, as){ var s; // checks to see if an object is a valid node.
if(!obj_is(n)){ return false } // must be an object.
@ -685,7 +685,7 @@
var gun = at.gun.opt(at.opt);
if(!at.once){
at.on('in', root, at);
at.on('out', root, obj_to(at, {out: root}));
at.on('out', root, {at: at, out: root});
Gun.on('create', at);
at.on('create', at);
}
@ -694,11 +694,11 @@
}
function root(msg){
//console.log("add to.next(at)"); // TODO: MISSING FEATURE!!!
var ev = this, at = ev.as, gun = at.gun, dup, tmp;
var ev = this, as = ev.as, at = as.at || as, gun = at.gun, dup, tmp;
//if(!msg.gun){ msg.gun = at.gun }
if(!(tmp = msg['#'])){ tmp = msg['#'] = text_rand(9) }
if((dup = at.dup).check(tmp)){
if(at.out === msg.out){
if(as.out === msg.out){
msg.out = u;
ev.to.next(msg);
}
@ -717,7 +717,7 @@
}
}
ev.to.next(msg);
if(!at.out){
if(!as.out){
msg.out = root;
at.on('out', msg);
}
@ -726,14 +726,11 @@
;(function(){
Gun.on.put = function(msg, gun){
var at = gun._, ctx = {gun: gun, graph: at.graph, put: {}, map: {}, souls: {}, machine: Gun.state(), ack: msg['@']};
var at = gun._, ctx = {gun: gun, graph: at.graph, put: {}, map: {}, souls: {}, machine: Gun.state(), ack: msg['@'], cat: at, stop: {}};
if(!Gun.graph.is(msg.put, null, verify, ctx)){ ctx.err = "Error: Invalid graph!" }
if(ctx.err){ return at.on('in', {'@': msg['#'], err: Gun.log(ctx.err) }) }
obj_map(ctx.put, merge, ctx);
if(!ctx.async){
at.stop = {}; // temporary fix till a better solution?
obj_map(ctx.map, map, ctx)
}
if(!ctx.async){ obj_map(ctx.map, map, ctx) }
if(u !== ctx.defer){
setTimeout(function(){
Gun.on.put(msg, gun);
@ -776,16 +773,15 @@
obj_map(node, each, as);
if(!ctx.async){ return }
if(!ctx.and){
// If it is async, we only need to setup on listener per context (ctx)
// If it is async, we only need to setup one listener per context (ctx)
cat.on('node', function(m){
this.to.next(m); // make sure to call other context's listeners.
if(m !== ctx.map[m.get]){ return } // filter out events not from this context!
ctx.souls[m.get] = false; // set our many-async flag
obj_map(m.put, aeach, m); // merge into view
obj_map(m.put, patch, m); // merge into view
if(obj_map(ctx.souls, function(v){ if(v){ return v } })){ return } // if flag still outstanding, keep waiting.
if(ctx.c){ return } ctx.c = 1; // failsafe for only being called once per context.
this.off();
cat.stop = {}; // temporary fix till a better solution?
obj_map(ctx.map, map, ctx); // all done, trigger chains.
});
}
@ -798,14 +794,16 @@
if(ctx.async){ return }
at.put = Gun.state.to(node, key, at.put);
}
function aeach(val, key){
function patch(val, key){
var msg = this, node = msg.put, at = (msg.gun._);
at.put = Gun.state.to(node, key, at.put);
}
function map(msg, soul){
if(!msg.gun){ return }
//console.log('map ->', soul, msg.put);
this.cat.stop = this.stop; // temporary fix till a better solution?
//console.log("MAP |||-->", soul);
(msg.gun._).on('in', msg);
this.cat.stop = null; // temporary fix till a better solution?
}
Gun.on.get = function(msg, gun){
@ -861,7 +859,7 @@
var list_is = Gun.list.is;
var text = Gun.text, text_is = text.is, text_rand = text.random;
var obj = Gun.obj, obj_is = obj.is, obj_has = obj.has, obj_to = obj.to, obj_map = obj.map, obj_copy = obj.copy;
var state_lex = Gun.state.lex, _soul = Gun.val.rel._, _has = '.', node_ = Gun.node._, rel_is = Gun.val.rel.is;
var state_lex = Gun.state.lex, _soul = Gun.val.rel._, _has = '.', node_ = Gun.node._, rel_is = Gun.val.link.is;
var empty = {}, u;
console.debug = function(i, s){ return (console.debug.i && i === console.debug.i && console.debug.i++) && (console.log.apply(console, arguments) || s) };
@ -983,9 +981,7 @@
root.ask(ack, msg);
return root.on('in', msg);
}
if(root.now){
root.now[at.id] = root.now[at.id] || true;
}
if(root.now){ root.now[at.id] = root.now[at.id] || true; at.pass = {} }
if(get['.']){
if(at.get){
msg = {get: {'.': at.get}, gun: at.gun};
@ -1007,7 +1003,7 @@
}
function input(msg){
var ev = this, cat = this.as, gun = msg.gun, at = gun._, change = msg.put, rel, tmp;
var ev = this, cat = ev.as, gun = msg.gun, at = (gun||empty)._ || empty, change = msg.put, rel, tmp;
if(cat.get && msg.get !== cat.get){
msg = obj_to(msg, {get: cat.get});
}
@ -1036,10 +1032,10 @@
if(cat.soul){
ev.to.next(msg);
echo(cat, msg, ev);
obj_map(change, map, {at: msg, cat: cat});
if(cat.next){ obj_map(change, map, {msg: msg, cat: cat}) }
return;
}
if(!(rel = Gun.val.rel.is(change))){
if(!(rel = Gun.val.link.is(change))){
if(Gun.val.is(change)){
if(cat.has || cat.soul){
not(cat, msg);
@ -1062,11 +1058,10 @@
ev.to.next(msg);
echo(cat, msg, ev);
relate(cat, msg, at, rel);
obj_map(change, map, {at: msg, cat: cat});
if(cat.next){ obj_map(change, map, {msg: msg, cat: cat}) }
return;
}
relate(cat, msg, at, rel);
ev.to.next(msg);
echo(cat, msg, ev);
}
@ -1080,31 +1075,43 @@
relate(from, msg, from, rel);
}
if(from === at){ return }
if(!from.gun){ from = {} }
(from.echo || (from.echo = {}))[at.id] = at;
if(at.has && !(at.map||empty)[from.id]){ // if we haven't seen this before.
not(at, msg);
}
tmp = (at.map || (at.map = {}))[from.id] = at.map[from.id] || {at: from};
var now = at.root.now;
//now = now || at.root.stop;
if(rel === tmp.rel){
tmp = from.id? ((at.map || (at.map = {}))[from.id] = at.map[from.id] || {at: from}) : {};
//console.log("!!!", at.id, at.get, at.ask, rel, tmp, 'pass?', at.pass, tmp.pass);
if(rel === tmp.link){
if(!(tmp.pass || at.pass)){
return;
}
/*if(from.ack){ return } //return; // if at.has
// NOW is a hack to get synchronous replies to correctly call.
// and STOP is a hack to get async behavior to correctly call.
// neither of these are ideal, need to be fixed without hacks,
// but for now, this works for current tests. :/
if(!now){
return;
/*var stop = at.root.stop;
var stop = at.root.stop;
if(!stop){ return }
if(stop[at.id] === rel){ return }
stop[at.id] = rel;*/
stop[at.id] = rel;
} else {
// move back to here to get rid of bugs
if(u === now[at.id]){ return }
if((now._ || (now._ = {}))[at.id] === rel){ return }
now._[at.id] = rel;
}
//return; // delete this*/
}
ask(at, tmp.rel = rel);
if(at.pass){
Gun.obj.map(at.map, function(tmp){ tmp.pass = true })
obj_del(at, 'pass');
}
if(tmp.pass){ obj_del(tmp, 'pass') }
if(at.has){ at.link = rel }
ask(at, tmp.link = rel);
}
function echo(at, msg, ev){
if(!at.echo){ return } // || node_ === at.get ?
@ -1115,7 +1122,7 @@
to.on('in', this);
}
function map(data, key){ // Map over only the changes on every update.
var cat = this.cat, next = cat.next || empty, via = this.at, chain, at, tmp;
var cat = this.cat, next = cat.next || empty, via = this.msg, chain, at, tmp;
if(node_ === key && !next[key]){ return }
if(!(at = next[key])){
return;
@ -1128,9 +1135,8 @@
at.put = data;
}
chain = at.gun;
} else {
chain = via.gun.get(key);
}
} else
if(via.gun){ chain = via.gun.get(key) }
at.on('in', {
put: data,
get: key,
@ -1142,10 +1148,12 @@
if(!(at.has || at.soul)){ return }
var tmp = at.map, root = at.root;
at.map = null;
if(!root.now || !root.now[at.id]){
if(at.has){ at.link = null }
//if(!root.now || !root.now[at.id]){
if(!at.pass){
if((!msg['@']) && null === tmp){ return }
}
if(u === tmp && Gun.val.rel.is(at.put)){ return } // TODO: Bug? Threw second condition in for a particular test, not sure if a counter example is tested though.
if(u === tmp && Gun.val.link.is(at.put)){ return } // This prevents the very first call of a thing from triggering a "clean up" call. // TODO: link.is(at.put) || !val.is(at.put) ?
obj_map(tmp, function(proxy){
if(!(proxy = proxy.at)){ return }
obj_del(proxy.echo, at.id);
@ -1169,10 +1177,7 @@
if(!at.ask){ return } // TODO: PERFORMANCE? More elegant way?
}
obj_map(at.ask || at.next, function(neat, key){
//(tmp.gun.get(key)._).on('out', {get: {'#': soul, '.': key}});
//tmp.on('out', {get: {'#': soul, '.': key}});
neat.on('out', {get: {'#': soul, '.': key}});
//at.on('out', {get: {'#': soul, '.': key}});
});
Gun.obj.del(at, 'ask'); // TODO: PERFORMANCE? More elegant way?
}
@ -1191,7 +1196,7 @@
return;
}
if(node_ == get['.']){ // is this a security concern?
at.on('in', {get: at.get, put: tmp[at.get], gun: at.gun, '@': msg['@']});
at.on('in', {get: at.get, put: Gun.val.link.ify(get['#']), gun: at.gun, '@': msg['@']});
return;
}
//if(/*!msg.gun &&*/ !get['.'] && get['#']){ at.ack = (at.ack + 1) || 1 }
@ -1265,15 +1270,16 @@
return at;
}
function use(msg){
var ev = this, as = ev.as, gun = msg.gun, at = gun._, root = at.root, data = msg.put, tmp;
if((tmp = root.now) && ev !== tmp[as.now]){
var ev = this, as = ev.as, gun = msg.gun, at = (gun||{})._ || {}, root = at.root, data = msg.put, tmp;
if(root && (tmp = root.stop)){ if(tmp[at.id]){ return } tmp[at.id] = msg.root; } // temporary fix till a better solution?
if(root && (tmp = root.now) && ev !== tmp[as.now]){
return ev.to.next(msg);
}
if(u === data){
data = at.put;
}
if((tmp = data) && tmp[rel._] && (tmp = rel.is(tmp))){
tmp = (at.root.gun.get(tmp)._);
if((tmp = data) && tmp[rel._] && (tmp = rel.is(tmp)) && root){
tmp = (root.gun.get(tmp)._);
if(u !== tmp.put){
msg = obj_to(msg, {put: tmp.put});
}
@ -1392,7 +1398,6 @@
// neither of these are ideal, need to be fixed without hacks,
// but for now, this works for current tests. :/
var tmp = cat.root.now; obj.del(cat.root, 'now'); cat.root.PUT = true;
var tmp2 = cat.root.stop;
(as.ref._).now = true;
(as.ref._).on('out', {
gun: as.ref, put: as.out = as.env.graph, opt: as.opt, '#': ask
@ -1400,7 +1405,6 @@
obj.del((as.ref._), 'now');
obj.del((cat.root), 'PUT');
cat.root.now = tmp;
cat.root.stop = tmp2;
}, as);
if(as.res){ as.res() }
} function no(v,k){ if(v){ return true } }
@ -1553,31 +1557,31 @@
return gun;
}
function ok(at, ev){ var opt = this;
var gun = at.gun, cat = gun._, data = cat.put || at.put, tmp = opt.last, id = cat.id+at.get, tmp;
function ok(msg, ev){ var opt = this;
var gun = msg.gun, at = (gun||{})._ || {}, data = at.put || msg.put, tmp = opt.last, id = (at.id||'')+msg.get, tmp;
if(u === data){
return;
}
if(data && data[rel._] && (tmp = rel.is(data))){
tmp = (cat.root.gun.get(tmp)._);
if(data && data[rel._] && (tmp = rel.is(data)) && at.root){
tmp = (at.root.gun.get(tmp)._);
if(u === tmp.put){
return;
}
data = tmp.put;
}
if(opt.change){ // TODO: BUG? Move above the undef checks?
data = at.put;
data = msg.put;
}
// DEDUPLICATE // TODO: NEEDS WORK! BAD PROTOTYPE
if(tmp.put === data && tmp.get === id && !Gun.node.soul(data)){ return }
tmp.put = data;
tmp.get = id;
// DEDUPLICATE // TODO: NEEDS WORK! BAD PROTOTYPE
cat.last = data;
at.last = data;
if(opt.as){
opt.ok.call(opt.as, at, ev);
opt.ok.call(opt.as, msg, ev);
} else {
opt.ok.call(gun, data, at.get, at, ev);
opt.ok.call(gun, data, msg.get, msg, ev);
}
}
@ -1600,7 +1604,7 @@
} else {
Gun.log.once("valonce", "Chainable val is experimental, its behavior and API may change moving forward. Please play with it and report bugs and ideas on how to improve it.");
var chain = gun.chain();
chain._.val = gun.once(function(){
chain._.nix = gun.once(function(){
chain._.on('in', gun._);
});
return chain;
@ -1662,8 +1666,8 @@
}
if(tmp = at.map){
obj_map(tmp, function(at){
if(at.rel){
cat.root.gun.get(at.rel).off();
if(at.link){
cat.root.gun.get(at.link).off();
}
});
}
@ -1685,10 +1689,9 @@
Gun.chain.map = function(cb, opt, t){
var gun = this, cat = gun._, chain;
if(!cb){
if(chain = cat.fields){ return chain }
chain = cat.fields = gun.chain();
chain._.val = gun.back('val');
chain._.MAPOF = cat.soul;
if(chain = cat.each){ return chain }
chain = cat.each = gun.chain();
chain._.nix = gun.back('nix');
gun.on('in', map, chain._);
return chain;
}
@ -1697,17 +1700,17 @@
gun.map().on(function(data, key, at, ev){
var next = (cb||noop).call(this, data, key, at, ev);
if(u === next){ return }
if(Gun.is(next)){
if(data === next || Gun.is(next)){
chain._.on('in', next._);
return;
}
chain._.on('in', {get: key, put: next, gun: chain});
chain._.on('in', {get: key, put: next});
});
return chain;
}
function map(msg){
if(!msg.put || Gun.val.is(msg.put)){ return }
if(this.as.val){ this.off() } // TODO: Ugly hack!
if(this.as.nix){ this.off() } // TODO: Ugly hack!
obj_map(msg.put, each, {at: this.as, msg: msg});
this.to.next(msg);
}
@ -1850,7 +1853,7 @@
root.on('get', function(msg){
this.to.next(msg);
var lex = msg.get, soul, data, u;
//setTimeout(function(){
function to(){
if(!lex || !(soul = lex['#'])){ return }
//if(0 >= msg.cap){ return }
var has = lex['.'];
@ -1861,8 +1864,10 @@
if(!data && !Gun.obj.empty(opt.peers)){ // if data not found, don't ack if there are peers.
return; // Hmm, what if we have peers but we are disconnected?
}
//console.log("lS get", id, data);
root.on('in', {'@': msg['#'], put: Gun.graph.node(data), how: 'lS', lS: msg.I});
//},1);
};
Gun.debug? setTimeout(to,1) : to();
});
var map = function(val, key, node, soul){

View File

@ -39,7 +39,7 @@ Gun.chain.open = function(cb, opt, at){
}
var tmp = this, id;
Gun.obj.map(data, function(val, key){
if(!(id = Gun.val.rel.is(val))){
if(!(id = Gun.val.link.is(val))){
(at || opt.doc)[key] = val;
return;
}

View File

@ -277,7 +277,7 @@ function Radisk(opt){
}
return t + '"' + d + s;
} else
if(d && d['#'] && (tmp = Gun.val.rel.is(d))){
if(d && d['#'] && (tmp = Gun.val.link.is(d))){
return t + '#' + tmp + t;
} else
if(Gun.num.is(d)){
@ -317,7 +317,7 @@ function Radisk(opt){
return d;
} else
if('#' === p){
return Gun.val.rel.ify(d);
return Gun.val.link.ify(d);
} else
if('+' === p){
if(0 === d.length){

View File

@ -21,7 +21,7 @@ if(typeof window === "undefined"){ //Not in the browser, Include from node
cb && cb({err: "Only root level node references supported currently, hopefully will change this in the future."});
return gun;
}
data = Gun.val.rel.ify(data);
data = Gun.val.link.ify(data);
}
opt = (cb === a)? b : a;
opt = Gun.text.is(opt)? {key: opt} : opt || {};

View File

@ -4,7 +4,7 @@ if(typeof window !== "undefined"){
var Gun = require('gun/gun');
}
const rel_ = Gun.val.rel._; // '#'
const rel_ = Gun.val.link._; // '#'
const node_ = Gun.node._; // '_'
Gun.chain.unset = function(node){

View File

@ -1,6 +1,6 @@
{
"name": "gun",
"version": "0.9.9991",
"version": "0.9.9992",
"description": "A realtime, decentralized, offline-first, graph data synchronization engine.",
"main": "index.js",
"browser": "gun.min.js",

12
sea.js
View File

@ -1164,7 +1164,7 @@
gunRoot.get(tmp).put(user)
}catch(e){console.log(e)}
// next up, we want to associate the alias with the public key. So we add it to the alias list.
gunRoot.get('~@'+username).put(Gun.obj.put({}, tmp, Gun.val.rel.ify(tmp)))
gunRoot.get('~@'+username).put(Gun.obj.put({}, tmp, Gun.val.link.ify(tmp)))
// callback that the user has been created. (Note: ok = 0 because we didn't wait for disk to ack)
setTimeout(() => { cat.ing = false; resolve({ ok: 0, pub: pairs.pub}) }, 10) // TODO: BUG! If `.auth` happens synchronously after `create` finishes, auth won't work. This setTimeout is a temporary hack until we can properly fix it.
} catch (e) {
@ -1496,12 +1496,12 @@
};
each.alias = function(val, key, node, soul){ // Example: {_:#~@, ~@alice: {#~@alice}}
if(!val){ return each.end({err: "Data must exist!"}) } // data MUST exist
if('~@'+key === Gun.val.rel.is(val)){ return check['alias'+key] = 0 } // in fact, it must be EXACTLY equal to itself
if('~@'+key === Gun.val.link.is(val)){ return check['alias'+key] = 0 } // in fact, it must be EXACTLY equal to itself
each.end({err: "Mismatching alias."}); // if it isn't, reject.
};
each.pubs = function(val, key, node, soul){ // Example: {_:#~@alice, ~asdf: {#~asdf}}
if(!val){ return each.end({err: "Alias must exist!"}) } // data MUST exist
if(key === Gun.val.rel.is(val)){ return check['pubs'+soul+key] = 0 } // and the ID must be EXACTLY equal to its property
if(key === Gun.val.link.is(val)){ return check['pubs'+soul+key] = 0 } // and the ID must be EXACTLY equal to its property
each.end({err: "Alias must match!"}); // that way nobody can tamper with the list of public keys.
};
each.pub = function(val, key, node, soul, pub, user){ // Example: {_:#~asdf, hello:SEA{'world',fdsa}}
@ -1514,7 +1514,7 @@
//var id = Gun.text.random(3);
SEA.sign(val, user.sea, function(data){ var rel;
if(u === data){ return each.end({err: SEA.err || 'Pub signature fail.'}) }
if(rel = Gun.val.rel.is(val)){
if(rel = Gun.val.link.is(val)){
(at.sea.own[rel] = at.sea.own[rel] || {})[pub] = true;
}
node[key] = data;
@ -1528,7 +1528,7 @@
if(u === data){ // make sure the signature matches the account it claims to be on.
return each.end({err: "Unverified data."}); // reject any updates that are signed with a mismatched account.
}
if((rel = Gun.val.rel.is(data)) && pub === relpub(rel)){
if((rel = Gun.val.link.is(data)) && pub === relpub(rel)){
(at.sea.own[rel] = at.sea.own[rel] || {})[pub] = true;
}
check['user'+soul+key] = 0;
@ -1550,7 +1550,7 @@
check['any'+soul+key] = 1;
SEA.verify(val, pub = tmp, function(data){ var rel;
if(!data){ return each.end({err: "Mismatched owner on '" + key + "'."}) }
if((rel = Gun.val.rel.is(data)) && pub === relpub(rel)){
if((rel = Gun.val.link.is(data)) && pub === relpub(rel)){
(at.sea.own[rel] = at.sea.own[rel] || {})[pub] = true;
}
check['any'+soul+key] = 0;

View File

@ -1,170 +1,35 @@
var root;
(function(env){
root = env.window? env.window : global;
env.window && root.localStorage && root.localStorage.clear();
try{ require('fs').unlinkSync('data.json') }catch(e){}
//root.Gun = root.Gun || require('../gun');
if(root.Gun){
root.Gun = root.Gun;
} else {
root.Gun = require('../gun');
Gun.serve = require('../lib/serve');
//require('./s3');
//require('./uws');
//require('./wsp/server');
require('../lib/file');
}
}(this));
//Gun.log.squelch = true;
var gleak = {globals: {}, check: function(){ // via tobyho
var leaked = []
for (var key in gleak.globe){ if (!(key in gleak.globals)){ leaked.push(key)} }
if (leaked.length > 0){ console.log("GLOBAL LEAK!", leaked); return leaked }
}};
(function(env){
for (var key in (gleak.globe = env)){ gleak.globals[key] = true }
}(this));
describe('Performance', function(){ return; // performance tests
var console = root.console || {log: function(){}};
function perf(fn, i){
i = i || 1000;
while(--i){
fn(i);
}
}
perf.now = this.performance? function(){ return performance.now() } : function(){ return Gun.time.now()/1000 };
(function(){
var t1 = perf.now();
var obj = {1: 'a', 2: 'b', 3: 'c', 4: 'd', 5: 'e', 6: 'f', 7: 'g', 8: 'h', 9: 'i'};
Object.keys && perf(function(){
var l = Object.keys(obj), ll = l.length, i = 0, s = '';
for(; i < ll; i++){
var v = l[i];
s += v;
}
});
console.log('map: native', (t1 = (perf.now() - t1)/1000) + 's');
var t2 = perf.now();
var obj = {1: 'a', 2: 'b', 3: 'c', 4: 'd', 5: 'e', 6: 'f', 7: 'g', 8: 'h', 9: 'i'};
perf(function(){
var s = '';
Gun.obj.map(obj, function(v){
s += v;
})
});
console.log('map: gun', (t2 = (perf.now() - t2)/1000) + 's', (t2 / t1).toFixed(1)+'x', 'slower.');
}());
(function(){
if(!Gun.store){
var tab = Gun().tab;
if(!tab){ return }
Gun.store = tab.store;
}
root.localStorage && root.localStorage.clear();
var it = 1000;
var t1 = perf.now();
perf(function(i){
var obj = {'i': i, 'v': Gun.text.random(100)};
Gun.store.put('test/native/' + i, obj);
}, it);
console.log('store: native', (t1 = (perf.now() - t1)/1000) + 's');
root.localStorage && root.localStorage.clear();
var gun = Gun({wire: {get:function(l,cb){cb()},put:function(g,cb){
Gun.is.graph(g, function(node, soul){
Gun.store.put(soul, node);
});
cb(null);
}}});
var t2 = perf.now();
perf(function(i){
var obj = {'i': i, 'v': Gun.text.random(100)};
gun.put(obj);
}, it);
console.log('store: gun', (t2 = (perf.now() - t2)/1000) + 's', (t2 / t1).toFixed(1)+'x', 'slower.');
root.localStorage && root.localStorage.clear();
}());
(function(){ // setTimeout
if(!Gun.store){
var tab = Gun().tab;
if(!tab){ return }
Gun.store = tab.store;
}
root.localStorage && root.localStorage.clear();
var t1 = perf.now();
i = i || 1000;
while(--i){
var obj = {'i': i, 'v': Gun.text.random(100)};
Gun.store.put('test/native/' + i, obj);
}
console.log('store: native', (t1 = (perf.now() - t1)/1000) + 's');
root.localStorage && root.localStorage.clear();
var gun = Gun({wire: {get:function(l,cb){cb()},put:function(g,cb){
Gun.is.graph(g, function(node, soul){
Gun.store.put(soul, node);
});
cb(null);
}}});
var t2 = perf.now();
perf(function(i){
var obj = {'i': i, 'v': Gun.text.random(100)};
gun.put(obj);
}, it);
console.log('store: gun', (t2 = (perf.now() - t2)/1000) + 's', (t2 / t1).toFixed(1)+'x', 'slower.');
root.localStorage && root.localStorage.clear();
}());
(function(){
var t1 = perf.now();
var on = Gun.on.create(), c = 0, o = [];
perf(function(i){
o.push(function(n){
c += 1;
});
var ii = 0, l = o.length;
for(; ii < l; ii++){
o[ii](i);
}
});
console.log('on: native', (t1 = (perf.now() - t1)/1000) + 's');
var on = Gun.on.create(), c = 0;
var t2 = perf.now();
perf(function(i){
on('change').event(function(n){
c += 1;
});
on('change').emit(i);
});
console.log('on: gun', (t2 = (perf.now() - t2)/1000) + 's', (t2 / t1).toFixed(1)+'x', 'slower.');
}());return;
(function(){ // always do this last!
var t1 = perf.now();
perf(function(i){
setTimeout(function(){
if(i === 1){
cb1();
}
},0);
}); var cb1 = function(){
console.log('setTimeout: native', (t1 = (perf.now() - t1)/1000) + 's', (t1 / t2).toFixed(1)+'x', 'slower.');
}
var t2 = perf.now();
perf(function(i){
setImmediate(function(){
if(i === 1){
cb2();
}
});
}); var cb2 = function(){
console.log('setImmediate: gun', (t2 = (perf.now() - t2)/1000) + 's', (t2 / t1).toFixed(1)+'x', 'slower.');
}
}());
});
describe('Gun', function(){
var root;
(function(){
var env;
if(typeof global !== 'undefined'){ env = global }
if(typeof window !== 'undefined'){ env = window }
root = env.window? env.window : global;
env.window && root.localStorage && root.localStorage.clear();
try{ require('fs').unlinkSync('data.json') }catch(e){}
//root.Gun = root.Gun || require('../gun');
if(root.Gun){
root.Gun = root.Gun;
} else {
root.Gun = require('../gun');
Gun.serve = require('../lib/serve');
//require('./s3');
//require('./uws');
//require('./wsp/server');
require('../lib/file');
}
}(this));
//Gun.log.squelch = true;
var gleak = {globals: {}, check: function(){ // via tobyho
var leaked = []
for (var key in gleak.globe){ if (!(key in gleak.globals)){ leaked.push(key)} }
if (leaked.length > 0){ console.log("GLOBAL LEAK!", leaked); return leaked }
}};
(function(env){
for (var key in (gleak.globe = env)){ gleak.globals[key] = true }
}(this));
var t = {};
describe('Utility', function(){
@ -278,20 +143,20 @@ describe('Gun', function(){
this.document && expect(Gun.obj.is(document.createElement('div'))).to.be(false);
expect(Gun.obj.is(new (function Class(){ this.x = 1; this.y = 2 })())).to.be(true);
});
it('fns',function(){
expect(Gun.fns.is(function(){})).to.be(true);
expect(Gun.fns.is(u)).to.be(false);
expect(Gun.fns.is(null)).to.be(false);
expect(Gun.fns.is('')).to.be(false);
expect(Gun.fns.is('a')).to.be(false);
expect(Gun.fns.is(0)).to.be(false);
expect(Gun.fns.is(1)).to.be(false);
expect(Gun.fns.is([])).to.be(false);
expect(Gun.fns.is([1])).to.be(false);
expect(Gun.fns.is({})).to.be(false);
expect(Gun.fns.is({a:1})).to.be(false);
expect(Gun.fns.is(false)).to.be(false);
expect(Gun.fns.is(true)).to.be(false);
it('fn',function(){
expect(Gun.fn.is(function(){})).to.be(true);
expect(Gun.fn.is(u)).to.be(false);
expect(Gun.fn.is(null)).to.be(false);
expect(Gun.fn.is('')).to.be(false);
expect(Gun.fn.is('a')).to.be(false);
expect(Gun.fn.is(0)).to.be(false);
expect(Gun.fn.is(1)).to.be(false);
expect(Gun.fn.is([])).to.be(false);
expect(Gun.fn.is([1])).to.be(false);
expect(Gun.fn.is({})).to.be(false);
expect(Gun.fn.is({a:1})).to.be(false);
expect(Gun.fn.is(false)).to.be(false);
expect(Gun.fn.is(true)).to.be(false);
});
it('time',function(){
t.ts = Gun.time.is();
@ -402,7 +267,7 @@ describe('Gun', function(){
setTimeout(this.add(function(){
this.done(null, num * num);
}, key), parseInt((""+Math.random()).substring(2,5)));
}, Gun.fns.sum(function(err, val){
}, Gun.fn.sum(function(err, val){
expect(val.a).to.eql(4);
expect(val.b).to.eql(4);
expect(val.c).to.eql(9);
@ -780,24 +645,24 @@ describe('Gun', function(){
expect(Gun.val.is({a:1})).to.be(false);
expect(Gun.val.is(function(){})).to.be(false);
});
it('is rel',function(){
expect(Gun.val.rel.is({'#':'somesoulidhere'})).to.be('somesoulidhere');
expect(Gun.val.rel.is({'#':'somethingelsehere'})).to.be('somethingelsehere');
expect(Gun.val.rel.is({'#':'somesoulidhere', and: 'nope'})).to.be(false);
expect(Gun.val.rel.is({or: 'nope', '#':'somesoulidhere'})).to.be(false);
expect(Gun.val.rel.is(false)).to.be(false);
expect(Gun.val.rel.is(true)).to.be(false);
expect(Gun.val.rel.is('')).to.be(false);
expect(Gun.val.rel.is('a')).to.be(false);
expect(Gun.val.rel.is(0)).to.be(false);
expect(Gun.val.rel.is(1)).to.be(false);
expect(Gun.val.rel.is(Infinity)).to.be(false); // boohoo :(
expect(Gun.val.rel.is(NaN)).to.be(false);
expect(Gun.val.rel.is([])).to.be(false);
expect(Gun.val.rel.is([1])).to.be(false);
expect(Gun.val.rel.is({})).to.be(false);
expect(Gun.val.rel.is({a:1})).to.be(false);
expect(Gun.val.rel.is(function(){})).to.be(false);
it('is link',function(){
expect(Gun.val.link.is({'#':'somesoulidhere'})).to.be('somesoulidhere');
expect(Gun.val.link.is({'#':'somethingelsehere'})).to.be('somethingelsehere');
expect(Gun.val.link.is({'#':'somesoulidhere', and: 'nope'})).to.be(false);
expect(Gun.val.link.is({or: 'nope', '#':'somesoulidhere'})).to.be(false);
expect(Gun.val.link.is(false)).to.be(false);
expect(Gun.val.link.is(true)).to.be(false);
expect(Gun.val.link.is('')).to.be(false);
expect(Gun.val.link.is('a')).to.be(false);
expect(Gun.val.link.is(0)).to.be(false);
expect(Gun.val.link.is(1)).to.be(false);
expect(Gun.val.link.is(Infinity)).to.be(false); // boohoo :(
expect(Gun.val.link.is(NaN)).to.be(false);
expect(Gun.val.link.is([])).to.be(false);
expect(Gun.val.link.is([1])).to.be(false);
expect(Gun.val.link.is({})).to.be(false);
expect(Gun.val.link.is({a:1})).to.be(false);
expect(Gun.val.link.is(function(){})).to.be(false);
});
it.skip('is lex',function(){
expect(Gun.is.lex({'#': 'soul'})).to.eql({soul: 'soul'});
@ -1021,11 +886,11 @@ describe('Gun', function(){
var data = {users: {1: {where: {lat: Math.random(), lng: Math.random(), i: 1}}}};
Gun.ify(data, function(err, ctx){
var soul, node;
expect(soul = Gun.val.rel.is(ctx.root.users)).to.be.ok();
expect(soul = Gun.val.link.is(ctx.root.users)).to.be.ok();
node = ctx.graph[soul];
expect(soul = Gun.val.rel.is(node[1])).to.be.ok();
expect(soul = Gun.val.link.is(node[1])).to.be.ok();
node = ctx.graph[soul];
expect(soul = Gun.val.rel.is(node.where)).to.be.ok();
expect(soul = Gun.val.link.is(node.where)).to.be.ok();
node = ctx.graph[soul];
expect(node.lat).to.be.ok();
expect(node.lng).to.be.ok();
@ -1538,11 +1403,11 @@ describe('Gun', function(){
done.to = setTimeout(function(){
expect(check.alice.age).to.be(26);
expect(check.alice.name).to.be('Alice');
expect(Gun.val.rel.is(check.alice.pet)).to.be.ok();
expect(Gun.val.link.is(check.alice.pet)).to.be.ok();
//expect(count.alice).to.be(1);
expect(check.bob.age).to.be(29);
expect(check.bob.name).to.be('Bob!');
expect(Gun.val.rel.is(check.bob.pet)).to.be.ok();
expect(Gun.val.link.is(check.bob.pet)).to.be.ok();
//expect(count.bob).to.be(1);
done();
},10);
@ -1756,9 +1621,9 @@ describe('Gun', function(){
gun.get('u/m/mutate/n/u').map().on(function(v,f){
check[v.name] = f;
count[v.name] = (count[v.name] || 0) + 1;
//console.log("*****************", f,v);
if(check.Alice && check.Bob && check['Alice Zzxyz']){
clearTimeout(done.to);
//console.log("****", f, v)
done.to = setTimeout(function(){
expect(done.last).to.be.ok();
//expect(check['Alice Aabca']).to.not.be.ok();
@ -2187,10 +2052,10 @@ describe('Gun', function(){
done.to = setTimeout(function(){
expect(check.alice.name).to.be('alice');
expect(check.alice.age).to.be(24);
expect(Gun.val.rel.is(check.alice.spouse)).to.be.ok();
expect(Gun.val.link.is(check.alice.spouse)).to.be.ok();
expect(check.bob.name).to.be('bob');
expect(check.bob.age).to.be(26);
expect(Gun.val.rel.is(check.bob.spouse)).to.be.ok();
expect(Gun.val.link.is(check.bob.spouse)).to.be.ok();
expect(check.GUN.name).to.be('GUN');
expect(check.ACME.name).to.be('ACME');
expect(check.ACME.corp).to.be('C');
@ -2274,10 +2139,10 @@ describe('Gun', function(){
done.to = setTimeout(function(){
expect(check.alice.name).to.be('alice');
expect(check.alice.age).to.be(24);
expect(Gun.val.rel.is(check.alice.spouse)).to.be.ok();
expect(Gun.val.link.is(check.alice.spouse)).to.be.ok();
expect(check.bob.name).to.be('bob');
expect(check.bob.age).to.be(26);
expect(Gun.val.rel.is(check.bob.spouse)).to.be.ok();
expect(Gun.val.link.is(check.bob.spouse)).to.be.ok();
expect(check.GUN.name).to.be('GUN');
expect(check.ACME.name).to.be('ACME');
expect(check.ACME.corp).to.be('C');
@ -2970,7 +2835,7 @@ describe('Gun', function(){
//console.log("*****************", data);
expect(data.age).to.be(29);
expect(data.name).to.be("Bob!");
expect(Gun.val.rel.is(data.pet)).to.ok();
expect(Gun.val.link.is(data.pet)).to.ok();
done();
//},300);
});
@ -3146,11 +3011,12 @@ describe('Gun', function(){
//console.log("***", at.put);
done.alias = done.alias || at.put.mark;
//!console.debug.i&&(console.debug.i=1)&&console.log("---------------------");
}).get('mark').get(function(at){
}).get('mark').on(function(data){
//console.log("************", at.put);//return;
setTimeout(function(){
done.mark = done.mark || at.put.pub;
expect(Gun.val.rel.is(done.mark)).to.be('pub');
clearTimeout(done.to);
done.to = setTimeout(function(){
done.mark = done.mark || data.pub;
expect(Gun.val.link.is(done.mark)).to.be('pub');
expect(done.app).to.be.ok();
expect(done.pub).to.be.ok();
expect(done.alias).to.be.ok();
@ -3498,9 +3364,10 @@ describe('Gun', function(){
list.set(gun.get('dave').put({name: 'dave', age: 25}));
var check = {};
list.val().map().on(function(data, key){
list.once().map().on(function(data, key){
check[key] = data;
clearTimeout(done.to);
//console.log("*****", key, data);
done.to = setTimeout(function(){
if(check.alice && check.bob && check.carl && check.dave && done.last){
expect(check.alice.age).to.be(27);
@ -4157,7 +4024,7 @@ describe('Gun', function(){
done.e = 2;
return;
}
expect(Gun.val.rel.is(data.bob)).to.be.ok();
expect(Gun.val.link.is(data.bob)).to.be.ok();
done.e = 1;
});
});
@ -4194,7 +4061,7 @@ describe('Gun', function(){
}, s)});
gun.get('only/p/soul').path('bob').any(function(err, data){
//console.log("*********", err, data);
expect(Gun.val.rel.is(data)).to.be.ok();
expect(Gun.val.link.is(data)).to.be.ok();
//expect(Gun.obj.empty(data, '_')).to.be.ok();
done();
}, {'.': null});
@ -4216,7 +4083,7 @@ describe('Gun', function(){
if(done.c){
expect(data.age).to.be(30);
expect(data.name).to.be('Bob!');
expect(Gun.val.rel.is(data.pet)).to.be.ok();
expect(Gun.val.link.is(data.pet)).to.be.ok();
expect(done.c).to.be(1);
done();
done.c = 2;
@ -4224,7 +4091,7 @@ describe('Gun', function(){
}
expect(data.age).to.be(29);
expect(data.name).to.be('Bob!');
expect(Gun.val.rel.is(data.pet)).to.be.ok();
expect(Gun.val.link.is(data.pet)).to.be.ok();
done.c=1;
});
setTimeout(function(){
@ -4248,13 +4115,13 @@ describe('Gun', function(){
if(done.c){
expect(data.age).to.be(30);
expect(data.name).to.be('Bob!');
expect(Gun.val.rel.is(data.pet)).to.be.ok();
expect(Gun.val.link.is(data.pet)).to.be.ok();
done();
return;
}
expect(data.age).to.be(29);
expect(data.name).to.be('Bob!');
expect(Gun.val.rel.is(data.pet)).to.be.ok();
expect(Gun.val.link.is(data.pet)).to.be.ok();
done.c=1;
});
setTimeout(function(){
@ -4287,7 +4154,7 @@ describe('Gun', function(){
}
expect(data.age).to.be(29);
expect(data.name).to.be('Bob!');
expect(Gun.val.rel.is(data.pet)).to.be.ok();
expect(Gun.val.link.is(data.pet)).to.be.ok();
});
setTimeout(function(){
gun.get('change/pointer/to/prime').path('bob').put(3);
@ -4362,7 +4229,7 @@ describe('Gun', function(){
expect(done.soul = Gun.node.soul(data)).to.be('dafssfad');
expect(data.age).to.be(29);
expect(data.name).to.be('Bob!');
expect(Gun.val.rel.is(data.pet)).to.be.ok();
expect(Gun.val.link.is(data.pet)).to.be.ok();
});
return;
setTimeout(function(){
@ -4437,7 +4304,7 @@ describe('Gun', function(){
get.put({foo: 'bar'});
get.any(function(err,data){
//console.log("data", data);
expect(Gun.val.rel.is(data.all)).to.be.ok();
expect(Gun.val.link.is(data.all)).to.be.ok();
expect(data.foo).to.be('bar');
});
});
@ -4642,7 +4509,7 @@ describe('Gun', function(){
kn = Gun.obj.copy(kn);
delete kn._;
expect(Gun.obj.empty(kn, '##')).to.be.ok();
kn = gun.back(-1)._.graph[Gun.val.rel.is(kn['##'])];
kn = gun.back(-1)._.graph[Gun.val.link.is(kn['##'])];
Gun.node.is(kn, function(node, s){
var n = gun.back(-1)._.graph[s];
if(Gun.obj.has(n, '##')){
@ -4842,12 +4709,12 @@ describe('Gun', function(){
var root = gun.back(-1)._.graph[soul];
expect(root.hello).to.be('key');
expect(root.yay).to.not.be.ok();
expect(Gun.val.rel.is(root.hi)).to.be.ok();
expect(Gun.val.rel.is(root.hi)).to.not.be(soul);
var node = gun.back(-1)._.graph[Gun.val.rel.is(root.hi)];
expect(Gun.val.link.is(root.hi)).to.be.ok();
expect(Gun.val.link.is(root.hi)).to.not.be(soul);
var node = gun.back(-1)._.graph[Gun.val.link.is(root.hi)];
expect(node.yay).to.be('value');
if(done.sub){ expect(done.sub).to.be(Gun.val.rel.is(root.hi)) }
else { done.sub = Gun.val.rel.is(root.hi) }
if(done.sub){ expect(done.sub).to.be(Gun.val.link.is(root.hi)) }
else { done.sub = Gun.val.link.is(root.hi) }
done.w = 1; if(done.r){ done(); done.c = 1 };
}).on(function(node, field){
if(done.c){ return }
@ -4984,7 +4851,7 @@ describe('Gun', function(){
get.val(function(data){ // TODO: API CHANGE! Empty objects should react.
//console.log("...1", data);
expect(Gun.obj.empty(data, '_')).to.be.ok(); // API CHANGED,
//expect(Gun.val.rel.is(data.very)).to.be.ok();
//expect(Gun.val.link.is(data.very)).to.be.ok();
});//, {wait: 10000});
setTimeout(function(){
var put = get.put({
@ -4998,12 +4865,12 @@ describe('Gun', function(){
});
get.val(function(data){
//console.log("...2", data);
expect(Gun.val.rel.is(data.very)).to.be.ok();
expect(Gun.val.link.is(data.very)).to.be.ok();
});
setTimeout(function(){
put.val(function(data){
//console.log("...3", data);
expect(Gun.val.rel.is(data.very)).to.be.ok();
expect(Gun.val.link.is(data.very)).to.be.ok();
done.val = true;
});
var p = put.path('very');
@ -5012,7 +4879,7 @@ describe('Gun', function(){
p.val(function(data){
//console.log("...4", data);
expect(data.we).to.be('have gone!');
expect(Gun.val.rel.is(data.deep)).to.be.ok();
expect(Gun.val.link.is(data.deep)).to.be.ok();
});
p.put('EXPLODE');
setTimeout(function(){
@ -5104,7 +4971,7 @@ describe('Gun', function(){
var g = gun.get('hello/key', function(err, node){
if(done.soul){ return }
expect(err).to.not.be.ok();
expect(done.ref = Gun.val.rel.is(node.hi)).to.be.ok();
expect(done.ref = Gun.val.link.is(node.hi)).to.be.ok();
done.soul = Gun.node.soul(node);
});
g.path('hi').put({happy: "faces"}, function(err, ok){
@ -5138,7 +5005,7 @@ describe('Gun', function(){
gun.get('hello/key', function(err, node){
if(done.soul){ return }
expect(err).to.not.be.ok();
expect(done.ref = Gun.val.rel.is(node.hi)).to.be.ok();
expect(done.ref = Gun.val.link.is(node.hi)).to.be.ok();
done.soul = Gun.node.soul(node);
}).path('hi').put('crushed', function(err, ok){
if(done.c){ return }
@ -5472,12 +5339,12 @@ describe('Gun', function(){
expect(err).to.not.be.ok();
}).val(function(val){
setTimeout(function(){ // TODO: Is this cheating? I don't think so cause we are using things outside of the API!
var a = gun.back(-1)._.graph[Gun.val.rel.is(val.a)];
var b = gun.back(-1)._.graph[Gun.val.rel.is(val.b)];
expect(Gun.val.rel.is(val.a)).to.be(Gun.node.soul(a));
expect(Gun.val.rel.is(val.b)).to.be(Gun.node.soul(b));
expect(Gun.val.rel.is(a.kid)).to.be(Gun.node.soul(b));
expect(Gun.val.rel.is(b.parent)).to.be(Gun.node.soul(a));
var a = gun.back(-1)._.graph[Gun.val.link.is(val.a)];
var b = gun.back(-1)._.graph[Gun.val.link.is(val.b)];
expect(Gun.val.link.is(val.a)).to.be(Gun.node.soul(a));
expect(Gun.val.link.is(val.b)).to.be(Gun.node.soul(b));
expect(Gun.val.link.is(a.kid)).to.be(Gun.node.soul(b));
expect(Gun.val.link.is(b.parent)).to.be(Gun.node.soul(a));
done();
},10);
});
@ -5579,8 +5446,8 @@ describe('Gun', function(){
}).val(function(val){
expect(val.age).to.be(23);
expect(val.name).to.be("Mark Nadal");
expect(Gun.val.rel.is(val.wife)).to.be.ok();
expect(Gun.val.rel.is(val.pet)).to.be.ok();
expect(Gun.val.link.is(val.wife)).to.be.ok();
expect(Gun.val.link.is(val.pet)).to.be.ok();
}).path('wife.pet.name').val(function(val){
//console.debug(1, "*****************", val);
expect(val).to.be('Hobbes');
@ -5589,7 +5456,7 @@ describe('Gun', function(){
expect(val.name).to.be("Amber Nadal");
expect(val.phd).to.be.ok();
expect(val.age).to.be(23);
expect(Gun.val.rel.is(val.pet)).to.be.ok();
expect(Gun.val.link.is(val.pet)).to.be.ok();
done();
});
});
@ -5686,7 +5553,7 @@ describe('Gun', function(){
foo.put({bar: {zoo: 'who'}}).val(function(obj, field){
//console.log("terribly terrilby unpleasant", field, obj);
expect(obj.foo).to.be('bar');
expect(Gun.val.rel.is(obj.bar)).to.ok();
expect(Gun.val.link.is(obj.bar)).to.ok();
done(); //setTimeout(function(){ done() },1);
});
});
@ -5718,8 +5585,8 @@ describe('Gun', function(){
expect(obj.another).to.be('node');
// double .vals here also RELATED to the #"context no double emit" but because of a faulty .not or .init system.
bar.val(function(node){
expect(Gun.val.rel.is(node.combo)).to.be.ok();
expect(Gun.val.rel.is(node.combo)).to.be(Gun.node.soul(obj));
expect(Gun.val.link.is(node.combo)).to.be.ok();
expect(Gun.val.link.is(node.combo)).to.be(Gun.node.soul(obj));
done(); //setTimeout(function(){ done() },1);
});
});
@ -6253,7 +6120,7 @@ describe('Gun', function(){
users.path(Gun.text.random()).put('sam');
setTimeout(function(){
users.val(function(v){
expect(Gun.val.rel.is(v)).to.not.be.ok();
expect(Gun.val.link.is(v)).to.not.be.ok();
expect(Object.keys(v).length).to.be(3);
done();
});
@ -7343,11 +7210,11 @@ describe('Gun', function(){
//console.log("chain.put PUT <----", ify.graph, '\n');
if(err || ify.err){ return cb.call(gun, err || ify.err) }
if(err = Gun.union(gun, ify.graph).err){ return cb.call(gun, err) }
if($.from = Gun.val.rel.is(ify.root[$.field])){ $.soul = $.from; $.field = null }
if($.from = Gun.val.link.is(ify.root[$.field])){ $.soul = $.from; $.field = null }
Gun.obj.map(ify.graph, function(node, soul){ Gun.union(gun, Gun.union.pseudo(soul)) });
gun._.at('soul').emit({soul: $.soul, field: $.field, key: $.key, PUT: 'SOUL', WAS: 'ON'}); // WAS ON
//return cb(null, true);
if(Gun.fns.is(ctx.hook = gun.__.opt.hooks.put)){
if(Gun.fn.is(ctx.hook = gun.__.opt.hooks.put)){
ctx.hook(ify.graph, function(err, data){ // now iterate through those nodes to a persistence layer and get a callback once all are saved
if(err){ return cb.call(gun, err) }
return cb.call(gun, null, data);
@ -7506,11 +7373,11 @@ describe('Gun', function(){
expect(done.c++).to.be(0);
}).val(function(p){
done.p = Gun.node.soul(p);
done.m = Gun.val.rel.is(p[0]);
expect(Gun.val.rel.is(p[0])).to.be.ok();
expect(Gun.val.rel.is(p[1])).to.be.ok();
expect(Gun.val.rel.is(p[2])).to.be.ok();
expect(Gun.val.rel.is(p[3])).to.be.ok();
done.m = Gun.val.link.is(p[0]);
expect(Gun.val.link.is(p[0])).to.be.ok();
expect(Gun.val.link.is(p[1])).to.be.ok();
expect(Gun.val.link.is(p[2])).to.be.ok();
expect(Gun.val.link.is(p[3])).to.be.ok();
})
var players = [], me;
@ -8023,19 +7890,19 @@ describe('Gun', function(){
test.val(function(node,b){
delete node._;
expect(Gun.obj.empty(node, 'try')).to.be.ok();
node = Gun.obj.copy(gun.__.graph[Gun.val.rel.is(node.try)]);
node = Gun.obj.copy(gun.__.graph[Gun.val.link.is(node.try)]);
delete node._;
expect(Gun.obj.empty(node, 'this')).to.be.ok();
node = Gun.obj.copy(gun.__.graph[Gun.val.rel.is(node.this)]);
node = Gun.obj.copy(gun.__.graph[Gun.val.link.is(node.this)]);
delete node._;
expect(Gun.obj.empty(node, 'at')).to.be.ok();
node = Gun.obj.copy(gun.__.graph[Gun.val.rel.is(node.at)]);
node = Gun.obj.copy(gun.__.graph[Gun.val.link.is(node.at)]);
delete node._;
expect(Gun.obj.empty(node, 'lvl4')).to.be.ok();
node = Gun.obj.copy(gun.__.graph[Gun.val.rel.is(node.lvl4)]);
node = Gun.obj.copy(gun.__.graph[Gun.val.link.is(node.lvl4)]);
delete node._;
expect(Gun.obj.empty(node, 'msg')).to.be.ok();

View File

@ -18,6 +18,28 @@
<script></script>
<script src="../gun.js"></script>
<script src="./common.js"></script>
<script>mocha.run()</script>
<script>
if(location.search){
Gun.debug = true;
}
mocha.run(function(a,b,c){
return;
var yes = confirm("REFRESH BROWSER FOR ASYNC TESTS?");
if(yes){
if(location.search){
location.search = '';
} else {
location.search = '?async';
}
return;
}
/*console.log("???????????", a);
//if(a !== 0){ return }
document.getElementById('mocha-stats').id = 'mocha-stats2';
document.getElementById('mocha-report').style.display = 'none';
document.getElementById('mocha-report').id = 'mocha-report2';
Gun.debug = false;
mocha.run();*/
})</script>
</body>
</html>

138
test/old/performance.js Normal file
View File

@ -0,0 +1,138 @@
describe('Performance', function(){ return; // performance tests
var console = root.console || {log: function(){}};
function perf(fn, i){
i = i || 1000;
while(--i){
fn(i);
}
}
perf.now = this.performance? function(){ return performance.now() } : function(){ return Gun.time.now()/1000 };
(function(){
var t1 = perf.now();
var obj = {1: 'a', 2: 'b', 3: 'c', 4: 'd', 5: 'e', 6: 'f', 7: 'g', 8: 'h', 9: 'i'};
Object.keys && perf(function(){
var l = Object.keys(obj), ll = l.length, i = 0, s = '';
for(; i < ll; i++){
var v = l[i];
s += v;
}
});
console.log('map: native', (t1 = (perf.now() - t1)/1000) + 's');
var t2 = perf.now();
var obj = {1: 'a', 2: 'b', 3: 'c', 4: 'd', 5: 'e', 6: 'f', 7: 'g', 8: 'h', 9: 'i'};
perf(function(){
var s = '';
Gun.obj.map(obj, function(v){
s += v;
})
});
console.log('map: gun', (t2 = (perf.now() - t2)/1000) + 's', (t2 / t1).toFixed(1)+'x', 'slower.');
}());
(function(){
if(!Gun.store){
var tab = Gun().tab;
if(!tab){ return }
Gun.store = tab.store;
}
root.localStorage && root.localStorage.clear();
var it = 1000;
var t1 = perf.now();
perf(function(i){
var obj = {'i': i, 'v': Gun.text.random(100)};
Gun.store.put('test/native/' + i, obj);
}, it);
console.log('store: native', (t1 = (perf.now() - t1)/1000) + 's');
root.localStorage && root.localStorage.clear();
var gun = Gun({wire: {get:function(l,cb){cb()},put:function(g,cb){
Gun.is.graph(g, function(node, soul){
Gun.store.put(soul, node);
});
cb(null);
}}});
var t2 = perf.now();
perf(function(i){
var obj = {'i': i, 'v': Gun.text.random(100)};
gun.put(obj);
}, it);
console.log('store: gun', (t2 = (perf.now() - t2)/1000) + 's', (t2 / t1).toFixed(1)+'x', 'slower.');
root.localStorage && root.localStorage.clear();
}());
(function(){ // setTimeout
if(!Gun.store){
var tab = Gun().tab;
if(!tab){ return }
Gun.store = tab.store;
}
root.localStorage && root.localStorage.clear();
var t1 = perf.now();
i = i || 1000;
while(--i){
var obj = {'i': i, 'v': Gun.text.random(100)};
Gun.store.put('test/native/' + i, obj);
}
console.log('store: native', (t1 = (perf.now() - t1)/1000) + 's');
root.localStorage && root.localStorage.clear();
var gun = Gun({wire: {get:function(l,cb){cb()},put:function(g,cb){
Gun.is.graph(g, function(node, soul){
Gun.store.put(soul, node);
});
cb(null);
}}});
var t2 = perf.now();
perf(function(i){
var obj = {'i': i, 'v': Gun.text.random(100)};
gun.put(obj);
}, it);
console.log('store: gun', (t2 = (perf.now() - t2)/1000) + 's', (t2 / t1).toFixed(1)+'x', 'slower.');
root.localStorage && root.localStorage.clear();
}());
(function(){
var t1 = perf.now();
var on = Gun.on.create(), c = 0, o = [];
perf(function(i){
o.push(function(n){
c += 1;
});
var ii = 0, l = o.length;
for(; ii < l; ii++){
o[ii](i);
}
});
console.log('on: native', (t1 = (perf.now() - t1)/1000) + 's');
var on = Gun.on.create(), c = 0;
var t2 = perf.now();
perf(function(i){
on('change').event(function(n){
c += 1;
});
on('change').emit(i);
});
console.log('on: gun', (t2 = (perf.now() - t2)/1000) + 's', (t2 / t1).toFixed(1)+'x', 'slower.');
}());return;
(function(){ // always do this last!
var t1 = perf.now();
perf(function(i){
setTimeout(function(){
if(i === 1){
cb1();
}
},0);
}); var cb1 = function(){
console.log('setTimeout: native', (t1 = (perf.now() - t1)/1000) + 's', (t1 / t2).toFixed(1)+'x', 'slower.');
}
var t2 = perf.now();
perf(function(i){
setImmediate(function(){
if(i === 1){
cb2();
}
});
}); var cb2 = function(){
console.log('setImmediate: gun', (t2 = (perf.now() - t2)/1000) + 's', (t2 / t1).toFixed(1)+'x', 'slower.');
}
}());
});

View File

@ -172,7 +172,7 @@ describe("Stress test GUN with SEA users causing PANIC!", function(){
var no;
Gun.node.is(at.put.users, function(val, key){
Gun.SEA.read(val, false, function(val){
if('alias/'+key === Gun.val.rel.is(val)){ return }
if('alias/'+key === Gun.val.link.is(val)){ return }
no = true;
})
if(no){ return no }

View File

@ -15,7 +15,7 @@
var no;
Gun.node.is(at.put.users, function(val, key){
Gun.SEA.read(val, false, function(val){
if('alias/'+key === Gun.val.rel.is(val)){ return }
if('alias/'+key === Gun.val.link.is(val)){ return }
no = true;
})
if(no){ return no }