This commit is contained in:
Mark Nadal 2018-03-25 05:19:49 -07:00
parent ae6f136ab2
commit 6464247d9c
18 changed files with 177 additions and 158 deletions

95
gun.js
View File

@ -677,7 +677,7 @@
;(function(){ ;(function(){
Gun.create = function(at){ Gun.create = function(at){
at.root = at.root || at.gun; at.root = at.root || at;
at.graph = at.graph || {}; at.graph = at.graph || {};
at.on = at.on || Gun.on; at.on = at.on || Gun.on;
at.ask = at.ask || Gun.ask; at.ask = at.ask || Gun.ask;
@ -882,10 +882,10 @@
Gun.chain.back = function(n, opt){ var tmp; Gun.chain.back = function(n, opt){ var tmp;
n = n || 1; n = n || 1;
if(-1 === n || Infinity === n){ if(-1 === n || Infinity === n){
return this._.root; return this._.root.gun;
} else } else
if(1 === n){ if(1 === n){
return this._.back || this; return (this._.back || this._).gun;
} }
var gun = this, at = gun._; var gun = this, at = gun._;
if(typeof n === 'string'){ if(typeof n === 'string'){
@ -900,19 +900,18 @@
return opt? gun : tmp; return opt? gun : tmp;
} else } else
if((tmp = at.back)){ if((tmp = at.back)){
return tmp.back(n, opt); return tmp.gun.back(n, opt);
} }
return; return;
} }
if(n instanceof Function){ if(n instanceof Function){
var yes, tmp = {back: gun}; var yes, tmp = {back: at};
while((tmp = tmp.back) while((tmp = tmp.back)
&& (tmp = tmp._)
&& !(yes = n(tmp, opt))){} && !(yes = n(tmp, opt))){}
return yes; return yes;
} }
if(Gun.num.is(n)){ if(Gun.num.is(n)){
return at.back.back(n - 1); return (at.back || at).gun.back(n - 1);
} }
return this; return this;
} }
@ -927,8 +926,8 @@
Gun.chain.chain = function(){ Gun.chain.chain = function(){
var at = this._, chain = new this.constructor(this), cat = chain._, root; var at = this._, chain = new this.constructor(this), cat = chain._, root;
cat.root = root = at.root; cat.root = root = at.root;
cat.id = ++root._.once; cat.id = ++root.once;
cat.back = this; cat.back = this._;
cat.on = Gun.on; cat.on = Gun.on;
cat.on('in', input, cat); // For 'in' if I add my own listeners to each then I MUST do it before in gets called. If I listen globally for all incoming data instead though, regardless of individual listeners, I can transform the data there and then as well. cat.on('in', input, cat); // For 'in' if I add my own listeners to each then I MUST do it before in gets called. If I listen globally for all incoming data instead though, regardless of individual listeners, I can transform the data there and then as well.
cat.on('out', output, cat); // However for output, there isn't really the global option. I must listen by adding my own listener individually BEFORE this one is ever called. cat.on('out', output, cat); // However for output, there isn't really the global option. I must listen by adding my own listener individually BEFORE this one is ever called.
@ -936,7 +935,7 @@
} }
function output(msg){ function output(msg){
var put, get, at = this.as, back = at.back._, root = at.root._; var put, get, at = this.as, back = at.back, root = at.root;
if(!msg.gun){ msg.gun = at.gun } if(!msg.gun){ msg.gun = at.gun }
this.to.next(msg); this.to.next(msg);
if(get = msg.get){ if(get = msg.get){
@ -974,7 +973,7 @@
if(get['.']){ if(get['.']){
if(at.get){ if(at.get){
msg = {get: {'.': at.get}, gun: at.gun}; msg = {get: {'.': at.get}, gun: at.gun};
(back.ask || (back.ask = {}))[at.get] = msg.gun; // TODO: PERFORMANCE? More elegant way? (back.ask || (back.ask = {}))[at.get] = msg.gun._; // TODO: PERFORMANCE? More elegant way?
return back.on('out', msg); return back.on('out', msg);
} }
msg = {get: {}, gun: at.gun}; msg = {get: {}, gun: at.gun};
@ -984,7 +983,7 @@
if(at.get){ if(at.get){
msg.gun = at.gun; msg.gun = at.gun;
get['.'] = at.get; get['.'] = at.get;
(back.ask || (back.ask = {}))[at.get] = msg.gun; // TODO: PERFORMANCE? More elegant way? (back.ask || (back.ask = {}))[at.get] = msg.gun._; // TODO: PERFORMANCE? More elegant way?
return back.on('out', msg); return back.on('out', msg);
} }
} }
@ -1042,7 +1041,7 @@
cat.put = at.put; cat.put = at.put;
}; };
if((rel = Gun.node.soul(change)) && at.has){ if((rel = Gun.node.soul(change)) && at.has){
at.put = (cat.root.get(rel)._).put; at.put = (cat.root.gun.get(rel)._).put;
} }
ev.to.next(msg); ev.to.next(msg);
echo(cat, msg, ev); echo(cat, msg, ev);
@ -1057,7 +1056,7 @@
function relate(at, msg, from, rel){ function relate(at, msg, from, rel){
if(!rel || node_ === at.get){ return } if(!rel || node_ === at.get){ return }
var tmp = (at.root.get(rel)._); var tmp = (at.root.gun.get(rel)._);
if(at.has){ if(at.has){
from = tmp; from = tmp;
} else } else
@ -1070,8 +1069,8 @@
not(at, msg); not(at, msg);
} }
tmp = (at.map || (at.map = {}))[from.id] = at.map[from.id] || {at: from}; tmp = (at.map || (at.map = {}))[from.id] = at.map[from.id] || {at: from};
var now = at.root._.now; var now = at.root.now;
//now = now || at.root._.stop; //now = now || at.root.stop;
if(rel === tmp.rel){ if(rel === tmp.rel){
// NOW is a hack to get synchronous replies to correctly call. // NOW is a hack to get synchronous replies to correctly call.
// and STOP is a hack to get async behavior to correctly call. // and STOP is a hack to get async behavior to correctly call.
@ -1079,7 +1078,7 @@
// but for now, this works for current tests. :/ // but for now, this works for current tests. :/
if(!now){ if(!now){
return; return;
/*var stop = at.root._.stop; /*var stop = at.root.stop;
if(!stop){ return } if(!stop){ return }
if(stop[at.id] === rel){ return } if(stop[at.id] === rel){ return }
stop[at.id] = rel;*/ stop[at.id] = rel;*/
@ -1105,7 +1104,7 @@
if(!(at = next[key])){ if(!(at = next[key])){
return; return;
} }
//if(data && data[_soul] && (tmp = Gun.val.rel.is(data)) && (tmp = (cat.root.get(tmp)._)) && obj_has(tmp, 'put')){ //if(data && data[_soul] && (tmp = Gun.val.rel.is(data)) && (tmp = (cat.root.gun.get(tmp)._)) && obj_has(tmp, 'put')){
// data = tmp.put; // data = tmp.put;
//} //}
if(at.has){ if(at.has){
@ -1125,7 +1124,7 @@
} }
function not(at, msg){ function not(at, msg){
if(!(at.has || at.soul)){ return } if(!(at.has || at.soul)){ return }
var tmp = at.map, root = at.root._; var tmp = at.map, root = at.root;
at.map = null; at.map = null;
if(!root.now || !root.now[at.id]){ if(!root.now || !root.now[at.id]){
if((!msg['@']) && null === tmp){ return } if((!msg['@']) && null === tmp){ return }
@ -1148,7 +1147,7 @@
}); });
} }
function ask(at, soul){ function ask(at, soul){
var tmp = (at.root.get(soul)._); var tmp = (at.root.gun.get(soul)._);
if(at.ack){ if(at.ack){
tmp.on('out', {get: {'#': soul}}); tmp.on('out', {get: {'#': soul}});
if(!at.ask){ return } // TODO: PERFORMANCE? More elegant way? if(!at.ask){ return } // TODO: PERFORMANCE? More elegant way?
@ -1181,9 +1180,9 @@
} }
//if(/*!msg.gun &&*/ !get['.'] && get['#']){ at.ack = (at.ack + 1) || 1 } //if(/*!msg.gun &&*/ !get['.'] && get['#']){ at.ack = (at.ack + 1) || 1 }
//msg = obj_to(msg); //msg = obj_to(msg);
msg.gun = at.root; msg.gun = at.root.gun;
//Gun.on('put', at); //Gun.on('put', at);
Gun.on.put(msg, at.root); Gun.on.put(msg, at.root.gun);
} }
var empty = {}, u; var empty = {}, u;
var obj = Gun.obj, obj_has = obj.has, obj_put = obj.put, obj_del = obj.del, obj_to = obj.to, obj_map = obj.map; var obj = Gun.obj, obj_has = obj.has, obj_put = obj.put, obj_del = obj.del, obj_to = obj.to, obj_map = obj.map;
@ -1205,7 +1204,7 @@
} else } else
if(key instanceof Function){ if(key instanceof Function){
gun = this; gun = this;
var at = gun._, root = at.root._, tmp = root.now, ev; var at = gun._, root = at.root, tmp = root.now, ev;
as = cb || {}; as = cb || {};
as.use = key; as.use = key;
as.out = as.out || {}; as.out = as.out || {};
@ -1235,7 +1234,7 @@
var cat = back._, next = cat.next, gun = back.chain(), at = gun._; var cat = back._, next = cat.next, gun = back.chain(), at = gun._;
if(!next){ next = cat.next = {} } if(!next){ next = cat.next = {} }
next[at.get = key] = at; next[at.get = key] = at;
if(back === cat.root){ if(back === cat.root.gun){
at.soul = key; at.soul = key;
} else } else
if(cat.soul || cat.has){ if(cat.soul || cat.has){
@ -1247,7 +1246,7 @@
return at; return at;
} }
function use(msg){ function use(msg){
var ev = this, as = ev.as, gun = msg.gun, at = gun._, root = at.root._, data = msg.put, tmp; 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]){ if((tmp = root.now) && ev !== tmp[as.now]){
return ev.to.next(msg); return ev.to.next(msg);
} }
@ -1255,7 +1254,7 @@
data = at.put; data = at.put;
} }
if((tmp = data) && tmp[rel._] && (tmp = rel.is(tmp))){ if((tmp = data) && tmp[rel._] && (tmp = rel.is(tmp))){
tmp = (at.root.get(tmp)._); tmp = (at.root.gun.get(tmp)._);
if(u !== tmp.put){ if(u !== tmp.put){
msg = obj_to(msg, {put: tmp.put}); msg = obj_to(msg, {put: tmp.put});
} }
@ -1275,7 +1274,7 @@
// #soul.has=value>state // #soul.has=value>state
// ~who#where.where=what>when@was // ~who#where.where=what>when@was
// TODO: BUG! Put probably cannot handle plural chains! // TODO: BUG! Put probably cannot handle plural chains!
var gun = this, at = (gun._), root = at.root, tmp; var gun = this, at = (gun._), root = at.root.gun, tmp;
as = as || {}; as = as || {};
as.data = data; as.data = data;
as.gun = as.gun || gun; as.gun = as.gun || gun;
@ -1308,14 +1307,14 @@
} }
if(Gun.is(data)){ if(Gun.is(data)){
data.get('_').get(function(at, ev, tmp){ ev.off(); data.get('_').get(function(at, ev, tmp){ ev.off();
if(!(tmp = at.gun) || !(tmp = tmp._.back) || !tmp._.soul){ if(!(tmp = at.gun) || !(tmp = tmp._.back) || !tmp.soul){
return Gun.log("The reference you are saving is a", typeof at.put, '"'+ as.put +'", not a node (object)!'); return Gun.log("The reference you are saving is a", typeof at.put, '"'+ as.put +'", not a node (object)!');
} }
gun.put(Gun.val.rel.ify(tmp._.soul), cb, as); gun.put(Gun.val.rel.ify(tmp.soul), cb, as);
}); });
return gun; return gun;
} }
as.ref = as.ref || (root === (tmp = at.back))? gun : tmp; as.ref = as.ref || (root._ === (tmp = at.back))? gun : tmp.gun;
if(as.ref._.soul && Gun.val.is(as.data) && at.get){ if(as.ref._.soul && Gun.val.is(as.data) && at.get){
as.data = obj_put({}, at.get, as.data); as.data = obj_put({}, at.get, as.data);
as.ref.put(as.data, as.soul, as); as.ref.put(as.data, as.soul, as);
@ -1372,16 +1371,16 @@
// and STOP is a hack to get async behavior 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, // neither of these are ideal, need to be fixed without hacks,
// but for now, this works for current tests. :/ // but for now, this works for current tests. :/
var tmp = cat.root._.now; obj.del(cat.root._, 'now'); cat.root._.PUT = true; var tmp = cat.root.now; obj.del(cat.root, 'now'); cat.root.PUT = true;
var tmp2 = cat.root._.stop; var tmp2 = cat.root.stop;
(as.ref._).now = true; (as.ref._).now = true;
(as.ref._).on('out', { (as.ref._).on('out', {
gun: as.ref, put: as.out = as.env.graph, opt: as.opt, '#': ask gun: as.ref, put: as.out = as.env.graph, opt: as.opt, '#': ask
}); });
obj.del((as.ref._), 'now'); obj.del((as.ref._), 'now');
obj.del((cat.root._), 'PUT'); obj.del((cat.root), 'PUT');
cat.root._.now = tmp; cat.root.now = tmp;
cat.root._.stop = tmp2; cat.root.stop = tmp2;
}, as); }, as);
if(as.res){ as.res() } if(as.res){ as.res() }
} function no(v,k){ if(v){ return true } } } function no(v,k){ if(v){ return true } }
@ -1422,7 +1421,7 @@
var at = msg.gun._, at_ = at; var at = msg.gun._, at_ = at;
var _id = (msg.put||empty)['#']; var _id = (msg.put||empty)['#'];
ev.off(); ev.off();
at = (msg.gun._.back._); // go up 1! at = (msg.gun._.back); // go up 1!
var id = id || Gun.node.soul(cat.obj) || Gun.node.soul(at.put) || Gun.val.rel.is(at.put) || _id || at_._id || (as.gun.back('opt.uuid') || Gun.text.random)(); // TODO: BUG!? Do we really want the soul of the object given to us? Could that be dangerous? var id = id || Gun.node.soul(cat.obj) || Gun.node.soul(at.put) || Gun.val.rel.is(at.put) || _id || at_._id || (as.gun.back('opt.uuid') || Gun.text.random)(); // TODO: BUG!? Do we really want the soul of the object given to us? Could that be dangerous?
if(!id){ // polyfill async uuid for SEA if(!id){ // polyfill async uuid for SEA
at.gun.back('opt.uuid')(function(err, id){ // TODO: improve perf without anonymous callback at.gun.back('opt.uuid')(function(err, id){ // TODO: improve perf without anonymous callback
@ -1448,7 +1447,7 @@
console.log("Please report this as an issue! Put.any.err"); console.log("Please report this as an issue! Put.any.err");
return; return;
} }
var cat = (at.gun._.back._), data = cat.put, opt = as.opt||{}, root, tmp; var cat = (at.gun._.back), data = cat.put, opt = as.opt||{}, root, tmp;
if((tmp = as.ref) && tmp._.now){ return } if((tmp = as.ref) && tmp._.now){ return }
ev.off(); ev.off();
if(as.ref !== as.gun){ if(as.ref !== as.gun){
@ -1469,19 +1468,19 @@
}); });
} }
tmp = tmp || cat.get; tmp = tmp || cat.get;
cat = (cat.root.get(tmp)._); cat = (cat.root.gun.get(tmp)._);
as.not = as.soul = tmp; as.not = as.soul = tmp;
data = as.data; data = as.data;
} }
if(!as.not && !(as.soul = Gun.node.soul(data))){ if(!as.not && !(as.soul = Gun.node.soul(data))){
if(as.path && obj_is(as.data)){ // Apparently necessary if(as.path && obj_is(as.data)){ // Apparently necessary
as.soul = (opt.uuid || cat.root._.opt.uuid || Gun.text.random)(); as.soul = (opt.uuid || cat.root.opt.uuid || Gun.text.random)();
} else { } else {
//as.data = obj_put({}, as.gun._.get, as.data); //as.data = obj_put({}, as.gun._.get, as.data);
if(node_ == at.get){ if(node_ == at.get){
as.soul = (at.put||empty)['#'] || at._id; as.soul = (at.put||empty)['#'] || at._id;
} }
as.soul = as.soul || at.soul || cat.soul || (opt.uuid || cat.root._.opt.uuid || Gun.text.random)(); as.soul = as.soul || at.soul || cat.soul || (opt.uuid || cat.root.opt.uuid || Gun.text.random)();
} }
if(!as.soul){ // polyfill async uuid for SEA if(!as.soul){ // polyfill async uuid for SEA
as.ref.back('opt.uuid')(function(err, soul){ // TODO: improve perf without anonymous callback as.ref.back('opt.uuid')(function(err, soul){ // TODO: improve perf without anonymous callback
@ -1539,7 +1538,7 @@
return; return;
} }
if(data && data[rel._] && (tmp = rel.is(data))){ if(data && data[rel._] && (tmp = rel.is(data))){
tmp = (cat.root.get(tmp)._); tmp = (cat.root.gun.get(tmp)._);
if(u === tmp.put){ if(u === tmp.put){
return; return;
} }
@ -1596,7 +1595,7 @@
//if(coat.soul && !(0 < coat.ack)){ return } //if(coat.soul && !(0 < coat.ack)){ return }
if(tmp = Gun.node.soul(data) || rel.is(data)){ if(tmp = Gun.node.soul(data) || rel.is(data)){
//if(data && data[rel._] && (tmp = rel.is(data))){ //if(data && data[rel._] && (tmp = rel.is(data))){
tmp = (cat.root.get(tmp)._); tmp = (cat.root.gun.get(tmp)._);
if(u === tmp.put){//} || !(0 < tmp.ack)){ if(u === tmp.put){//} || !(0 < tmp.ack)){
return; return;
} }
@ -1622,7 +1621,7 @@
Gun.chain.off = function(){ Gun.chain.off = function(){
// make off more aggressive. Warning, it might backfire! // make off more aggressive. Warning, it might backfire!
var gun = this, at = gun._, tmp; var gun = this, at = gun._, tmp;
var back = at.back || {}, cat = back._; var cat = at.back;
if(!cat){ return } if(!cat){ return }
if(tmp = cat.next){ if(tmp = cat.next){
if(tmp[at.get]){ if(tmp[at.get]){
@ -1638,12 +1637,12 @@
obj_del(tmp, at.get); obj_del(tmp, at.get);
} }
if(tmp = at.soul){ if(tmp = at.soul){
obj_del(cat.root._.graph, tmp); obj_del(cat.root.graph, tmp);
} }
if(tmp = at.map){ if(tmp = at.map){
obj_map(tmp, function(at){ obj_map(tmp, function(at){
if(at.rel){ if(at.rel){
cat.root.get(at.rel).off(); cat.root.gun.get(at.rel).off();
} }
}); });
} }
@ -1707,9 +1706,9 @@
opt = opt || {}; opt.item = opt.item || item; opt = opt || {}; opt.item = opt.item || item;
if(soul = Gun.node.soul(item)){ return gun.set(gun.back(-1).get(soul), cb, opt) } if(soul = Gun.node.soul(item)){ return gun.set(gun.back(-1).get(soul), cb, opt) }
if(!Gun.is(item)){ if(!Gun.is(item)){
var id = gun._.root._.opt.uuid(); var id = gun._.root.opt.uuid();
if(id && Gun.obj.is(item)){ if(id && Gun.obj.is(item)){
return gun.set(gun._.root.put(item, id), cb, opt); return gun.set(gun._.root.gun.put(item, id), cb, opt);
} }
return gun.get(id || (Gun.state.lex() + Gun.text.random(12))).put(item, cb, opt); return gun.get(id || (Gun.state.lex() + Gun.text.random(12))).put(item, cb, opt);
} }
@ -1717,7 +1716,7 @@
if(!at.gun || !at.gun._.back){ return } if(!at.gun || !at.gun._.back){ return }
ev.off(); ev.off();
var soul = (at.put||{})['#']; var soul = (at.put||{})['#'];
at = (at.gun._.back._); at = (at.gun._.back);
var put = {}, node = at.put; var put = {}, node = at.put;
soul = at.soul || Gun.node.soul(node) || soul; soul = at.soul || Gun.node.soul(node) || soul;
if(!soul){ return cb.call(gun, {err: Gun.log('Only a node can be linked! Not "' + node + '"!')}) } if(!soul){ return cb.call(gun, {err: Gun.log('Only a node can be linked! Not "' + node + '"!')}) }

2
gun.min.js vendored

File diff suppressed because one or more lines are too long

View File

@ -1,4 +1,4 @@
var Gun = Gun || require('gun'); var Gun = Gun || require('../gun');
Gun.on('opt', function(ctx){ Gun.on('opt', function(ctx){
this.to.next(ctx); this.to.next(ctx);

22
lib/forget.js Normal file
View File

@ -0,0 +1,22 @@
;(function(){
var Gun = (this||{}).Gun || require('../gun');
Gun.on('opt', function(ctx){
once(ctx);
this.to.next(ctx);
});
function once(ctx){
if(ctx.once){ return }
var forget = ctx.opt.forget = ctx.opt.forget || {};
ctx.on('put', function(msg){
Gun.graph.is(msg.put, function(node, soul){
if(!Gun.obj.has(forget, soul)){ return }
delete msg.put[soul];
});
this.to.next(msg);
});
}
}());

View File

@ -23,7 +23,7 @@ Gun.chain.set = function(val, cb, opt){
cb = cb || function(){}; cb = cb || function(){};
opt = opt || {}; opt = opt || {};
if(!gun.back){ gun = gun.put({}) } if(!gun._.back){ gun = gun.put({}) }
gun = gun.not(function(next, key){ gun = gun.not(function(next, key){
return key? this.put({}).key(key) : this.put({}); return key? this.put({}).key(key) : this.put({});
}); });

View File

@ -13,7 +13,7 @@ require('./client.js');
Gun.on('opt', function (at) { Gun.on('opt', function (at) {
this.to.next(at); this.to.next(at);
var gun = at.gun, opt = at.opt; var gun = at.gun, opt = at.opt;
gun.__ = at.root._; gun.__ = at.root;
gun.__.opt.ws = opt.ws = gun.__.opt.ws || opt.ws || {}; gun.__.opt.ws = opt.ws = gun.__.opt.ws || opt.ws || {};
gun.__.opt.ws.path = gun.__.opt.ws.path || '/gun'; gun.__.opt.ws.path = gun.__.opt.ws.path || '/gun';
@ -181,7 +181,7 @@ Gun.on('opt', function (at) {
headers: { 'Content-Type': tran.json }, headers: { 'Content-Type': tran.json },
}; };
var graph = gun.Back(Infinity)._.graph; var graph = gun.back(Infinity)._.graph;
var node = graph[lex['#']]; var node = graph[lex['#']];
var result = Gun.graph.ify(node); var result = Gun.graph.ify(node);

View File

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

View File

@ -131,7 +131,7 @@ function Mesh(ctx){
if(put){ (msg = Type.obj.to(msg)).put = _ } if(put){ (msg = Type.obj.to(msg)).put = _ }
} }
var i = 0, to = []; Type.obj.map(ctx.opt.peers, function(p){ var i = 0, to = []; Type.obj.map(ctx.opt.peers, function(p){
to.push[p.url || p.id]; if(++i > 9){ return true } // limit server, fast fix, improve later! to.push(p.url || p.id); if(++i > 9){ return true } // limit server, fast fix, improve later!
}); msg['><'] = to.join(); }); msg['><'] = to.join();
var raw = $(msg); var raw = $(msg);
if(u !== put){ if(u !== put){

View File

@ -3,10 +3,10 @@ var Gun = require('./root');
Gun.chain.back = function(n, opt){ var tmp; Gun.chain.back = function(n, opt){ var tmp;
n = n || 1; n = n || 1;
if(-1 === n || Infinity === n){ if(-1 === n || Infinity === n){
return this._.root; return this._.root.gun;
} else } else
if(1 === n){ if(1 === n){
return this._.back || this; return (this._.back || this._).gun;
} }
var gun = this, at = gun._; var gun = this, at = gun._;
if(typeof n === 'string'){ if(typeof n === 'string'){
@ -21,19 +21,18 @@ Gun.chain.back = function(n, opt){ var tmp;
return opt? gun : tmp; return opt? gun : tmp;
} else } else
if((tmp = at.back)){ if((tmp = at.back)){
return tmp.back(n, opt); return tmp.gun.back(n, opt);
} }
return; return;
} }
if(n instanceof Function){ if(n instanceof Function){
var yes, tmp = {back: gun}; var yes, tmp = {back: at};
while((tmp = tmp.back) while((tmp = tmp.back)
&& (tmp = tmp._)
&& !(yes = n(tmp, opt))){} && !(yes = n(tmp, opt))){}
return yes; return yes;
} }
if(Gun.num.is(n)){ if(Gun.num.is(n)){
return at.back.back(n - 1); return (at.back || at).gun.back(n - 1);
} }
return this; return this;
} }

View File

@ -6,8 +6,8 @@ var Gun = require('./root');
Gun.chain.chain = function(){ Gun.chain.chain = function(){
var at = this._, chain = new this.constructor(this), cat = chain._, root; var at = this._, chain = new this.constructor(this), cat = chain._, root;
cat.root = root = at.root; cat.root = root = at.root;
cat.id = ++root._.once; cat.id = ++root.once;
cat.back = this; cat.back = this._;
cat.on = Gun.on; cat.on = Gun.on;
cat.on('in', input, cat); // For 'in' if I add my own listeners to each then I MUST do it before in gets called. If I listen globally for all incoming data instead though, regardless of individual listeners, I can transform the data there and then as well. cat.on('in', input, cat); // For 'in' if I add my own listeners to each then I MUST do it before in gets called. If I listen globally for all incoming data instead though, regardless of individual listeners, I can transform the data there and then as well.
cat.on('out', output, cat); // However for output, there isn't really the global option. I must listen by adding my own listener individually BEFORE this one is ever called. cat.on('out', output, cat); // However for output, there isn't really the global option. I must listen by adding my own listener individually BEFORE this one is ever called.
@ -15,7 +15,7 @@ Gun.chain.chain = function(){
} }
function output(msg){ function output(msg){
var put, get, at = this.as, back = at.back._, root = at.root._; var put, get, at = this.as, back = at.back, root = at.root;
if(!msg.gun){ msg.gun = at.gun } if(!msg.gun){ msg.gun = at.gun }
this.to.next(msg); this.to.next(msg);
if(get = msg.get){ if(get = msg.get){
@ -53,7 +53,7 @@ function output(msg){
if(get['.']){ if(get['.']){
if(at.get){ if(at.get){
msg = {get: {'.': at.get}, gun: at.gun}; msg = {get: {'.': at.get}, gun: at.gun};
(back.ask || (back.ask = {}))[at.get] = msg.gun; // TODO: PERFORMANCE? More elegant way? (back.ask || (back.ask = {}))[at.get] = msg.gun._; // TODO: PERFORMANCE? More elegant way?
return back.on('out', msg); return back.on('out', msg);
} }
msg = {get: {}, gun: at.gun}; msg = {get: {}, gun: at.gun};
@ -63,7 +63,7 @@ function output(msg){
if(at.get){ if(at.get){
msg.gun = at.gun; msg.gun = at.gun;
get['.'] = at.get; get['.'] = at.get;
(back.ask || (back.ask = {}))[at.get] = msg.gun; // TODO: PERFORMANCE? More elegant way? (back.ask || (back.ask = {}))[at.get] = msg.gun._; // TODO: PERFORMANCE? More elegant way?
return back.on('out', msg); return back.on('out', msg);
} }
} }
@ -121,7 +121,7 @@ function input(msg){
cat.put = at.put; cat.put = at.put;
}; };
if((rel = Gun.node.soul(change)) && at.has){ if((rel = Gun.node.soul(change)) && at.has){
at.put = (cat.root.get(rel)._).put; at.put = (cat.root.gun.get(rel)._).put;
} }
ev.to.next(msg); ev.to.next(msg);
echo(cat, msg, ev); echo(cat, msg, ev);
@ -136,7 +136,7 @@ function input(msg){
function relate(at, msg, from, rel){ function relate(at, msg, from, rel){
if(!rel || node_ === at.get){ return } if(!rel || node_ === at.get){ return }
var tmp = (at.root.get(rel)._); var tmp = (at.root.gun.get(rel)._);
if(at.has){ if(at.has){
from = tmp; from = tmp;
} else } else
@ -149,8 +149,8 @@ function relate(at, msg, from, rel){
not(at, msg); not(at, msg);
} }
tmp = (at.map || (at.map = {}))[from.id] = at.map[from.id] || {at: from}; tmp = (at.map || (at.map = {}))[from.id] = at.map[from.id] || {at: from};
var now = at.root._.now; var now = at.root.now;
//now = now || at.root._.stop; //now = now || at.root.stop;
if(rel === tmp.rel){ if(rel === tmp.rel){
// NOW is a hack to get synchronous replies to correctly call. // NOW is a hack to get synchronous replies to correctly call.
// and STOP is a hack to get async behavior to correctly call. // and STOP is a hack to get async behavior to correctly call.
@ -158,7 +158,7 @@ function relate(at, msg, from, rel){
// but for now, this works for current tests. :/ // but for now, this works for current tests. :/
if(!now){ if(!now){
return; return;
/*var stop = at.root._.stop; /*var stop = at.root.stop;
if(!stop){ return } if(!stop){ return }
if(stop[at.id] === rel){ return } if(stop[at.id] === rel){ return }
stop[at.id] = rel;*/ stop[at.id] = rel;*/
@ -179,20 +179,19 @@ function reverb(to){
to.on('in', this); to.on('in', this);
} }
function map(data, key){ // Map over only the changes on every update. function map(data, key){ // Map over only the changes on every update.
var cat = this.cat, next = cat.next || empty, via = this.at, gun, chain, at, tmp; var cat = this.cat, next = cat.next || empty, via = this.at, chain, at, tmp;
if(node_ === key && !next[key]){ return } if(node_ === key && !next[key]){ return }
if(!(gun = next[key])){ if(!(at = next[key])){
return; return;
} }
at = (gun._); //if(data && data[_soul] && (tmp = Gun.val.rel.is(data)) && (tmp = (cat.root.gun.get(tmp)._)) && obj_has(tmp, 'put')){
//if(data && data[_soul] && (tmp = Gun.val.rel.is(data)) && (tmp = (cat.root.get(tmp)._)) && obj_has(tmp, 'put')){
// data = tmp.put; // data = tmp.put;
//} //}
if(at.has){ if(at.has){
if(!(data && data[_soul] && Gun.val.rel.is(data) === Gun.node.soul(at.put))){ if(!(data && data[_soul] && Gun.val.rel.is(data) === Gun.node.soul(at.put))){
at.put = data; at.put = data;
} }
chain = gun; chain = at.gun;
} else { } else {
chain = via.gun.get(key); chain = via.gun.get(key);
} }
@ -205,7 +204,7 @@ function map(data, key){ // Map over only the changes on every update.
} }
function not(at, msg){ function not(at, msg){
if(!(at.has || at.soul)){ return } if(!(at.has || at.soul)){ return }
var tmp = at.map, root = at.root._; var tmp = at.map, root = at.root;
at.map = null; at.map = null;
if(!root.now || !root.now[at.id]){ if(!root.now || !root.now[at.id]){
if((!msg['@']) && null === tmp){ return } if((!msg['@']) && null === tmp){ return }
@ -215,29 +214,28 @@ function not(at, msg){
if(!(proxy = proxy.at)){ return } if(!(proxy = proxy.at)){ return }
obj_del(proxy.echo, at.id); obj_del(proxy.echo, at.id);
}); });
obj_map(at.next, function(gun, key){ obj_map(at.next, function(neat, key){
var coat = (gun._); neat.put = u;
coat.put = u; if(neat.ack){
if(coat.ack){ neat.ack = -1;
coat.ack = -1;
} }
coat.on('in', { neat.on('in', {
get: key, get: key,
gun: gun, gun: neat.gun,
put: u put: u
}); });
}); });
} }
function ask(at, soul){ function ask(at, soul){
var tmp = (at.root.get(soul)._); var tmp = (at.root.gun.get(soul)._);
if(at.ack){ if(at.ack){
tmp.on('out', {get: {'#': soul}}); tmp.on('out', {get: {'#': soul}});
if(!at.ask){ return } // TODO: PERFORMANCE? More elegant way? if(!at.ask){ return } // TODO: PERFORMANCE? More elegant way?
} }
obj_map(at.ask || at.next, function(gun, key){ obj_map(at.ask || at.next, function(neat, key){
//(tmp.gun.get(key)._).on('out', {get: {'#': soul, '.': key}}); //(tmp.gun.get(key)._).on('out', {get: {'#': soul, '.': key}});
//tmp.on('out', {get: {'#': soul, '.': key}}); //tmp.on('out', {get: {'#': soul, '.': key}});
(gun._).on('out', {get: {'#': soul, '.': key}}); neat.on('out', {get: {'#': soul, '.': key}});
//at.on('out', {get: {'#': soul, '.': key}}); //at.on('out', {get: {'#': soul, '.': key}});
}); });
Gun.obj.del(at, 'ask'); // TODO: PERFORMANCE? More elegant way? Gun.obj.del(at, 'ask'); // TODO: PERFORMANCE? More elegant way?
@ -262,9 +260,9 @@ function ack(msg, ev){
} }
//if(/*!msg.gun &&*/ !get['.'] && get['#']){ at.ack = (at.ack + 1) || 1 } //if(/*!msg.gun &&*/ !get['.'] && get['#']){ at.ack = (at.ack + 1) || 1 }
//msg = obj_to(msg); //msg = obj_to(msg);
msg.gun = at.root; msg.gun = at.root.gun;
//Gun.on('put', at); //Gun.on('put', at);
Gun.on.put(msg, at.root); Gun.on.put(msg, at.root.gun);
} }
var empty = {}, u; var empty = {}, u;
var obj = Gun.obj, obj_has = obj.has, obj_put = obj.put, obj_del = obj.del, obj_to = obj.to, obj_map = obj.map; var obj = Gun.obj, obj_has = obj.has, obj_put = obj.put, obj_del = obj.del, obj_to = obj.to, obj_map = obj.map;

View File

@ -1,15 +1,18 @@
var Gun = require('./root'); var Gun = require('./root');
Gun.chain.get = function(key, cb, as){ Gun.chain.get = function(key, cb, as){
var gun;
if(typeof key === 'string'){ if(typeof key === 'string'){
var gun, back = this, cat = back._; var back = this, cat = back._;
var next = cat.next || empty, tmp; var next = cat.next || empty, tmp;
if(!(gun = next[key])){ if(!(gun = next[key])){
gun = cache(key, back); gun = cache(key, back);
} }
gun = gun.gun;
} else } else
if(key instanceof Function){ if(key instanceof Function){
var gun = this, at = gun._, root = at.root._, tmp = root.now, ev; gun = this;
var at = gun._, root = at.root, tmp = root.now, ev;
as = cb || {}; as = cb || {};
as.use = key; as.use = key;
as.out = as.out || {}; as.out = as.out || {};
@ -38,8 +41,8 @@ Gun.chain.get = function(key, cb, as){
function cache(key, back){ function cache(key, back){
var cat = back._, next = cat.next, gun = back.chain(), at = gun._; var cat = back._, next = cat.next, gun = back.chain(), at = gun._;
if(!next){ next = cat.next = {} } if(!next){ next = cat.next = {} }
next[at.get = key] = gun; next[at.get = key] = at;
if(cat.root === back){ if(back === cat.root.gun){
at.soul = key; at.soul = key;
} else } else
if(cat.soul || cat.has){ if(cat.soul || cat.has){
@ -48,10 +51,10 @@ function cache(key, back){
//at.put = cat.put[key]; //at.put = cat.put[key];
//} //}
} }
return gun; return at;
} }
function use(msg){ function use(msg){
var ev = this, as = ev.as, gun = msg.gun, at = gun._, root = at.root._, data = msg.put, tmp; 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]){ if((tmp = root.now) && ev !== tmp[as.now]){
return ev.to.next(msg); return ev.to.next(msg);
} }
@ -59,7 +62,7 @@ function use(msg){
data = at.put; data = at.put;
} }
if((tmp = data) && tmp[rel._] && (tmp = rel.is(tmp))){ if((tmp = data) && tmp[rel._] && (tmp = rel.is(tmp))){
tmp = (at.root.get(tmp)._); tmp = (at.root.gun.get(tmp)._);
if(u !== tmp.put){ if(u !== tmp.put){
msg = obj_to(msg, {put: tmp.put}); msg = obj_to(msg, {put: tmp.put});
} }

View File

@ -30,7 +30,7 @@ function ok(at, ev){ var opt = this;
return; return;
} }
if(data && data[rel._] && (tmp = rel.is(data))){ if(data && data[rel._] && (tmp = rel.is(data))){
tmp = (cat.root.get(tmp)._); tmp = (cat.root.gun.get(tmp)._);
if(u === tmp.put){ if(u === tmp.put){
return; return;
} }
@ -87,7 +87,7 @@ function val(msg, ev, to){
//if(coat.soul && !(0 < coat.ack)){ return } //if(coat.soul && !(0 < coat.ack)){ return }
if(tmp = Gun.node.soul(data) || rel.is(data)){ if(tmp = Gun.node.soul(data) || rel.is(data)){
//if(data && data[rel._] && (tmp = rel.is(data))){ //if(data && data[rel._] && (tmp = rel.is(data))){
tmp = (cat.root.get(tmp)._); tmp = (cat.root.gun.get(tmp)._);
if(u === tmp.put){//} || !(0 < tmp.ack)){ if(u === tmp.put){//} || !(0 < tmp.ack)){
return; return;
} }
@ -113,7 +113,7 @@ function val(msg, ev, to){
Gun.chain.off = function(){ Gun.chain.off = function(){
// make off more aggressive. Warning, it might backfire! // make off more aggressive. Warning, it might backfire!
var gun = this, at = gun._, tmp; var gun = this, at = gun._, tmp;
var back = at.back || {}, cat = back._; var cat = at.back;
if(!cat){ return } if(!cat){ return }
if(tmp = cat.next){ if(tmp = cat.next){
if(tmp[at.get]){ if(tmp[at.get]){
@ -129,18 +129,18 @@ Gun.chain.off = function(){
obj_del(tmp, at.get); obj_del(tmp, at.get);
} }
if(tmp = at.soul){ if(tmp = at.soul){
obj_del(cat.root._.graph, tmp); obj_del(cat.root.graph, tmp);
} }
if(tmp = at.map){ if(tmp = at.map){
obj_map(tmp, function(at){ obj_map(tmp, function(at){
if(at.rel){ if(at.rel){
cat.root.get(at.rel).off(); cat.root.gun.get(at.rel).off();
} }
}); });
} }
if(tmp = at.next){ if(tmp = at.next){
obj_map(tmp, function(ref){ obj_map(tmp, function(neat){
ref.off(); neat.gun.off();
}); });
} }
at.on('off', {}); at.on('off', {});

View File

@ -4,7 +4,7 @@ Gun.chain.put = function(data, cb, as){
// #soul.has=value>state // #soul.has=value>state
// ~who#where.where=what>when@was // ~who#where.where=what>when@was
// TODO: BUG! Put probably cannot handle plural chains! // TODO: BUG! Put probably cannot handle plural chains!
var gun = this, at = (gun._), root = at.root, tmp; var gun = this, at = (gun._), root = at.root.gun, tmp;
as = as || {}; as = as || {};
as.data = data; as.data = data;
as.gun = as.gun || gun; as.gun = as.gun || gun;
@ -37,14 +37,14 @@ Gun.chain.put = function(data, cb, as){
} }
if(Gun.is(data)){ if(Gun.is(data)){
data.get('_').get(function(at, ev, tmp){ ev.off(); data.get('_').get(function(at, ev, tmp){ ev.off();
if(!(tmp = at.gun) || !(tmp = tmp._.back) || !tmp._.soul){ if(!(tmp = at.gun) || !(tmp = tmp._.back) || !tmp.soul){
return Gun.log("The reference you are saving is a", typeof at.put, '"'+ as.put +'", not a node (object)!'); return Gun.log("The reference you are saving is a", typeof at.put, '"'+ as.put +'", not a node (object)!');
} }
gun.put(Gun.val.rel.ify(tmp._.soul), cb, as); gun.put(Gun.val.rel.ify(tmp.soul), cb, as);
}); });
return gun; return gun;
} }
as.ref = as.ref || (root === (tmp = at.back))? gun : tmp; as.ref = as.ref || (root._ === (tmp = at.back))? gun : tmp.gun;
if(as.ref._.soul && Gun.val.is(as.data) && at.get){ if(as.ref._.soul && Gun.val.is(as.data) && at.get){
as.data = obj_put({}, at.get, as.data); as.data = obj_put({}, at.get, as.data);
as.ref.put(as.data, as.soul, as); as.ref.put(as.data, as.soul, as);
@ -101,16 +101,16 @@ function batch(){ var as = this;
// and STOP is a hack to get async behavior 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, // neither of these are ideal, need to be fixed without hacks,
// but for now, this works for current tests. :/ // but for now, this works for current tests. :/
var tmp = cat.root._.now; obj.del(cat.root._, 'now'); cat.root._.PUT = true; var tmp = cat.root.now; obj.del(cat.root, 'now'); cat.root.PUT = true;
var tmp2 = cat.root._.stop; var tmp2 = cat.root.stop;
(as.ref._).now = true; (as.ref._).now = true;
(as.ref._).on('out', { (as.ref._).on('out', {
gun: as.ref, put: as.out = as.env.graph, opt: as.opt, '#': ask gun: as.ref, put: as.out = as.env.graph, opt: as.opt, '#': ask
}); });
obj.del((as.ref._), 'now'); obj.del((as.ref._), 'now');
obj.del((cat.root._), 'PUT'); obj.del((cat.root), 'PUT');
cat.root._.now = tmp; cat.root.now = tmp;
cat.root._.stop = tmp2; cat.root.stop = tmp2;
}, as); }, as);
if(as.res){ as.res() } if(as.res){ as.res() }
} function no(v,k){ if(v){ return true } } } function no(v,k){ if(v){ return true } }
@ -151,7 +151,7 @@ function soul(msg, ev){ var as = this.as, cat = as.at; as = as.as;
var at = msg.gun._, at_ = at; var at = msg.gun._, at_ = at;
var _id = (msg.put||empty)['#']; var _id = (msg.put||empty)['#'];
ev.off(); ev.off();
at = (msg.gun._.back._); // go up 1! at = (msg.gun._.back); // go up 1!
var id = id || Gun.node.soul(cat.obj) || Gun.node.soul(at.put) || Gun.val.rel.is(at.put) || _id || at_._id || (as.gun.back('opt.uuid') || Gun.text.random)(); // TODO: BUG!? Do we really want the soul of the object given to us? Could that be dangerous? var id = id || Gun.node.soul(cat.obj) || Gun.node.soul(at.put) || Gun.val.rel.is(at.put) || _id || at_._id || (as.gun.back('opt.uuid') || Gun.text.random)(); // TODO: BUG!? Do we really want the soul of the object given to us? Could that be dangerous?
if(!id){ // polyfill async uuid for SEA if(!id){ // polyfill async uuid for SEA
at.gun.back('opt.uuid')(function(err, id){ // TODO: improve perf without anonymous callback at.gun.back('opt.uuid')(function(err, id){ // TODO: improve perf without anonymous callback
@ -177,7 +177,7 @@ function any(at, ev){
console.log("Please report this as an issue! Put.any.err"); console.log("Please report this as an issue! Put.any.err");
return; return;
} }
var cat = (at.gun._.back._), data = cat.put, opt = as.opt||{}, root, tmp; var cat = (at.gun._.back), data = cat.put, opt = as.opt||{}, root, tmp;
if((tmp = as.ref) && tmp._.now){ return } if((tmp = as.ref) && tmp._.now){ return }
ev.off(); ev.off();
if(as.ref !== as.gun){ if(as.ref !== as.gun){
@ -198,19 +198,19 @@ function any(at, ev){
}); });
} }
tmp = tmp || cat.get; tmp = tmp || cat.get;
cat = (cat.root.get(tmp)._); cat = (cat.root.gun.get(tmp)._);
as.not = as.soul = tmp; as.not = as.soul = tmp;
data = as.data; data = as.data;
} }
if(!as.not && !(as.soul = Gun.node.soul(data))){ if(!as.not && !(as.soul = Gun.node.soul(data))){
if(as.path && obj_is(as.data)){ // Apparently necessary if(as.path && obj_is(as.data)){ // Apparently necessary
as.soul = (opt.uuid || cat.root._.opt.uuid || Gun.text.random)(); as.soul = (opt.uuid || cat.root.opt.uuid || Gun.text.random)();
} else { } else {
//as.data = obj_put({}, as.gun._.get, as.data); //as.data = obj_put({}, as.gun._.get, as.data);
if(node_ == at.get){ if(node_ == at.get){
as.soul = (at.put||empty)['#'] || at._id; as.soul = (at.put||empty)['#'] || at._id;
} }
as.soul = as.soul || at.soul || cat.soul || (opt.uuid || cat.root._.opt.uuid || Gun.text.random)(); as.soul = as.soul || at.soul || cat.soul || (opt.uuid || cat.root.opt.uuid || Gun.text.random)();
} }
if(!as.soul){ // polyfill async uuid for SEA if(!as.soul){ // polyfill async uuid for SEA
as.ref.back('opt.uuid')(function(err, soul){ // TODO: improve perf without anonymous callback as.ref.back('opt.uuid')(function(err, soul){ // TODO: improve perf without anonymous callback

View File

@ -26,7 +26,7 @@ Gun.dup = require('./dup');
;(function(){ ;(function(){
Gun.create = function(at){ Gun.create = function(at){
at.root = at.root || at.gun; at.root = at.root || at;
at.graph = at.graph || {}; at.graph = at.graph || {};
at.on = at.on || Gun.on; at.on = at.on || Gun.on;
at.ask = at.ask || Gun.ask; at.ask = at.ask || Gun.ask;
@ -103,7 +103,7 @@ Gun.dup = require('./dup');
var msg = ctx.map[soul] = { var msg = ctx.map[soul] = {
put: node, put: node,
get: soul, get: soul,
gun: at gun: at.gun
}, as = {ctx: ctx, msg: msg}; }, as = {ctx: ctx, msg: msg};
ctx.async = !!cat.tag.node; ctx.async = !!cat.tag.node;
if(ctx.ack){ msg['@'] = ctx.ack } if(ctx.ack){ msg['@'] = ctx.ack }
@ -144,7 +144,7 @@ Gun.dup = require('./dup');
Gun.on.get = function(msg, gun){ Gun.on.get = function(msg, gun){
var root = gun._, soul = msg.get[_soul], node = root.graph[soul], has = msg.get[_has], tmp; var root = gun._, soul = msg.get[_soul], node = root.graph[soul], has = msg.get[_has], tmp;
var next = root.next || (root.next = {}), at = ((next[soul] || empty)._); var next = root.next || (root.next = {}), at = next[soul];
if(!node || !at){ return root.on('get', msg) } if(!node || !at){ return root.on('get', msg) }
if(has){ if(has){
if(!obj_has(node, has)){ return root.on('get', msg) } if(!obj_has(node, has)){ return root.on('get', msg) }

View File

@ -6,9 +6,9 @@ Gun.chain.set = function(item, cb, opt){
opt = opt || {}; opt.item = opt.item || item; opt = opt || {}; opt.item = opt.item || item;
if(soul = Gun.node.soul(item)){ return gun.set(gun.back(-1).get(soul), cb, opt) } if(soul = Gun.node.soul(item)){ return gun.set(gun.back(-1).get(soul), cb, opt) }
if(!Gun.is(item)){ if(!Gun.is(item)){
var id = gun._.root._.opt.uuid(); var id = gun._.root.opt.uuid();
if(id && Gun.obj.is(item)){ if(id && Gun.obj.is(item)){
return gun.set(gun._.root.put(item, id), cb, opt); return gun.set(gun._.root.gun.put(item, id), cb, opt);
} }
return gun.get(id || (Gun.state.lex() + Gun.text.random(12))).put(item, cb, opt); return gun.get(id || (Gun.state.lex() + Gun.text.random(12))).put(item, cb, opt);
} }
@ -16,7 +16,7 @@ Gun.chain.set = function(item, cb, opt){
if(!at.gun || !at.gun._.back){ return } if(!at.gun || !at.gun._.back){ return }
ev.off(); ev.off();
var soul = (at.put||{})['#']; var soul = (at.put||{})['#'];
at = (at.gun._.back._); at = (at.gun._.back);
var put = {}, node = at.put; var put = {}, node = at.put;
soul = at.soul || Gun.node.soul(node) || soul; soul = at.soul || Gun.node.soul(node) || soul;
if(!soul){ return cb.call(gun, {err: Gun.log('Only a node can be linked! Not "' + node + '"!')}) } if(!soul){ return cb.call(gun, {err: Gun.log('Only a node can be linked! Not "' + node + '"!')}) }

View File

@ -3136,7 +3136,6 @@ describe('Gun', function(){
//return; //return;
setTimeout(function(){ setTimeout(function(){
gun.get(function(at){ gun.get(function(at){
//console.log('*', at.put);
done.app = done.app || at.put.alias; done.app = done.app || at.put.alias;
}); });
gun.back(-1).get('pub').get(function(at){ gun.back(-1).get('pub').get(function(at){
@ -3611,7 +3610,7 @@ describe('Gun', function(){
}); });
gun.get('ds/safe').val(function(data){ gun.get('ds/safe').val(function(data){
expect(gun._.root._.graph['ds/safe'].b).to.not.be.ok(); expect(gun.back(-1)._.graph['ds/safe'].b).to.not.be.ok();
if(done.c){ return } done.c = 1; if(done.c){ return } done.c = 1;
done(); done();
}); });
@ -3695,7 +3694,7 @@ describe('Gun', function(){
}); });
it('users map map who said map on', function(done){ it('users map map who said map on', function(done){
this.timeout(1000 * 60 * 5); this.timeout(1000 * 9);
var gun = Gun(); var gun = Gun();
gun.get('users').put({ gun.get('users').put({
@ -4607,7 +4606,7 @@ describe('Gun', function(){
gun.get('hello/earth').key('hello/galaxy', function(err, ok){ gun.get('hello/earth').key('hello/galaxy', function(err, ok){
expect(err).to.not.be.ok(); expect(err).to.not.be.ok();
}); });
var node = gun.Back(-1)._.graph['hello/earth'] || {}; // TODO: IS THIS CORRECT? var node = gun.back(-1)._.graph['hello/earth'] || {}; // TODO: IS THIS CORRECT?
expect(node['hello/galaxy']).to.not.be.ok(); expect(node['hello/galaxy']).to.not.be.ok();
gun.get('hello/earth', function(err, pseudo){ gun.get('hello/earth', function(err, pseudo){
expect(pseudo.hello).to.be('world'); expect(pseudo.hello).to.be('world');
@ -4615,7 +4614,7 @@ describe('Gun', function(){
expect(pseudo.place).to.be('asia'); expect(pseudo.place).to.be('asia');
expect(pseudo.north).to.not.be.ok(); expect(pseudo.north).to.not.be.ok();
}); });
var galaxy = gun.Back(-1)._.graph['hello/galaxy'] || {}; // TODO: IS THIS CORRECT? var galaxy = gun.back(-1)._.graph['hello/galaxy'] || {}; // TODO: IS THIS CORRECT?
expect(galaxy['hello/earth']).to.not.be.ok(); expect(galaxy['hello/earth']).to.not.be.ok();
gun.get('hello/galaxy', function(err, pseudo){ gun.get('hello/galaxy', function(err, pseudo){
if(done.c || !pseudo.hello || !pseudo.south || !pseudo.place || !pseudo.continent || !pseudo.north){ return } if(done.c || !pseudo.hello || !pseudo.south || !pseudo.place || !pseudo.continent || !pseudo.north){ return }
@ -4635,9 +4634,9 @@ describe('Gun', function(){
kn = Gun.obj.copy(kn); kn = Gun.obj.copy(kn);
delete kn._; delete kn._;
expect(Gun.obj.empty(kn, '##')).to.be.ok(); 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.rel.is(kn['##'])];
Gun.node.is(kn, function(node, s){ Gun.node.is(kn, function(node, s){
var n = gun.Back(-1)._.graph[s]; var n = gun.back(-1)._.graph[s];
if(Gun.obj.has(n, '##')){ if(Gun.obj.has(n, '##')){
soulnode(gun, n, r); soulnode(gun, n, r);
return; return;
@ -4655,11 +4654,11 @@ describe('Gun', function(){
done.soul = Gun.node.soul(node); done.soul = Gun.node.soul(node);
}).put({hi: 'you'}, function(err, ok){ }).put({hi: 'you'}, function(err, ok){
expect(err).to.not.be.ok(); expect(err).to.not.be.ok();
var keynode = gun.Back(-1)._.graph[done.soul], soul; var keynode = gun.back(-1)._.graph[done.soul], soul;
expect(keynode.hi).to.not.be.ok(); expect(keynode.hi).to.not.be.ok();
var c = soulnode(gun, keynode), soul = c[0]; var c = soulnode(gun, keynode), soul = c[0];
expect(c.length).to.be(1); expect(c.length).to.be(1);
var node = gun.Back(-1)._.graph[soul]; var node = gun.back(-1)._.graph[soul];
expect(node.hello).to.be('key'); expect(node.hello).to.be('key');
expect(node.hi).to.be('you'); expect(node.hi).to.be('you');
}).on(function(node){ }).on(function(node){
@ -4713,10 +4712,10 @@ describe('Gun', function(){
}).put({hi: 'overwritten'}, function(err, ok){ }).put({hi: 'overwritten'}, function(err, ok){
if(done.c){ return } if(done.c){ return }
expect(err).to.not.be.ok(); expect(err).to.not.be.ok();
var keynode = gun.Back(-1)._.graph[done.soul], soul; var keynode = gun.back(-1)._.graph[done.soul], soul;
var c = soulnode(gun, keynode), soul = c[0]; var c = soulnode(gun, keynode), soul = c[0];
expect(c.length).to.be(1); expect(c.length).to.be(1);
var node = gun.Back(-1)._.graph[soul]; var node = gun.back(-1)._.graph[soul];
expect(node.hello).to.be('key'); expect(node.hello).to.be('key');
expect(node.hi).to.be('overwritten'); expect(node.hi).to.be('overwritten');
done.w = 1; if(done.r){ done(); done.c = 1 }; done.w = 1; if(done.r){ done(); done.c = 1 };
@ -4804,10 +4803,10 @@ describe('Gun', function(){
}).path('hi').put('again', function(err, ok){ }).path('hi').put('again', function(err, ok){
if(done.c){ return } if(done.c){ return }
expect(err).to.not.be.ok(); expect(err).to.not.be.ok();
var keynode = gun.Back(-1)._.graph[done.soul], soul; var keynode = gun.back(-1)._.graph[done.soul], soul;
var c = soulnode(gun, keynode), soul = c[0]; var c = soulnode(gun, keynode), soul = c[0];
expect(c.length).to.be(1); expect(c.length).to.be(1);
var node = gun.Back(-1)._.graph[done.sub = soul]; var node = gun.back(-1)._.graph[done.sub = soul];
expect(node.hello).to.be('key'); expect(node.hello).to.be('key');
expect(node.hi).to.be('again'); expect(node.hi).to.be('again');
done.w = 1; if(done.r){ done(); done.c = 1 }; done.w = 1; if(done.r){ done(); done.c = 1 };
@ -4829,15 +4828,15 @@ describe('Gun', function(){
}).path('hi').put({yay: "value"}, function(err, ok){ }).path('hi').put({yay: "value"}, function(err, ok){
if(done.c){ return } if(done.c){ return }
expect(err).to.not.be.ok(); expect(err).to.not.be.ok();
var keynode = gun.Back(-1)._.graph[done.soul], soul; var keynode = gun.back(-1)._.graph[done.soul], soul;
var c = soulnode(gun, keynode), soul = c[0]; var c = soulnode(gun, keynode), soul = c[0];
expect(c.length).to.be(1); expect(c.length).to.be(1);
var root = gun.Back(-1)._.graph[soul]; var root = gun.back(-1)._.graph[soul];
expect(root.hello).to.be('key'); expect(root.hello).to.be('key');
expect(root.yay).to.not.be.ok(); 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.be.ok();
expect(Gun.val.rel.is(root.hi)).to.not.be(soul); expect(Gun.val.rel.is(root.hi)).to.not.be(soul);
var node = gun.Back(-1)._.graph[Gun.val.rel.is(root.hi)]; var node = gun.back(-1)._.graph[Gun.val.rel.is(root.hi)];
expect(node.yay).to.be('value'); expect(node.yay).to.be('value');
if(done.sub){ expect(done.sub).to.be(Gun.val.rel.is(root.hi)) } if(done.sub){ expect(done.sub).to.be(Gun.val.rel.is(root.hi)) }
else { done.sub = Gun.val.rel.is(root.hi) } else { done.sub = Gun.val.rel.is(root.hi) }
@ -5103,11 +5102,11 @@ describe('Gun', function(){
g.path('hi').put({happy: "faces"}, function(err, ok){ g.path('hi').put({happy: "faces"}, function(err, ok){
if(done.c){ return } if(done.c){ return }
expect(err).to.not.be.ok(); expect(err).to.not.be.ok();
var keynode = gun.Back(-1)._.graph[done.soul], soul; var keynode = gun.back(-1)._.graph[done.soul], soul;
var c = soulnode(gun, keynode), soul = c[0]; var c = soulnode(gun, keynode), soul = c[0];
expect(c.length).to.be(1); expect(c.length).to.be(1);
var root = gun.Back(-1)._.graph[soul]; var root = gun.back(-1)._.graph[soul];
var sub = gun.Back(-1)._.graph[done.ref]; var sub = gun.back(-1)._.graph[done.ref];
expect(root.hello).to.be('key'); expect(root.hello).to.be('key');
expect(root.yay).to.not.be.ok(); expect(root.yay).to.not.be.ok();
expect(Gun.node.soul(sub)).to.be(done.ref); expect(Gun.node.soul(sub)).to.be(done.ref);
@ -5136,11 +5135,11 @@ describe('Gun', function(){
}).path('hi').put('crushed', function(err, ok){ }).path('hi').put('crushed', function(err, ok){
if(done.c){ return } if(done.c){ return }
expect(err).to.not.be.ok(); expect(err).to.not.be.ok();
var keynode = gun.Back(-1)._.graph[done.soul], soul; var keynode = gun.back(-1)._.graph[done.soul], soul;
var c = soulnode(gun, keynode), soul = c[0]; var c = soulnode(gun, keynode), soul = c[0];
expect(c.length).to.be(1); expect(c.length).to.be(1);
var root = gun.Back(-1)._.graph[soul]; var root = gun.back(-1)._.graph[soul];
var sub = gun.Back(-1)._.graph[done.ref]; var sub = gun.back(-1)._.graph[done.ref];
expect(root.hello).to.be('key'); expect(root.hello).to.be('key');
expect(root.yay).to.not.be.ok(); expect(root.yay).to.not.be.ok();
expect(Gun.node.soul(sub)).to.be(done.ref); expect(Gun.node.soul(sub)).to.be(done.ref);
@ -5465,8 +5464,8 @@ describe('Gun', function(){
expect(err).to.not.be.ok(); expect(err).to.not.be.ok();
}).val(function(val){ }).val(function(val){
setTimeout(function(){ // TODO: Is this cheating? I don't think so cause we are using things outside of the API! 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 a = gun.back(-1)._.graph[Gun.val.rel.is(val.a)];
var b = gun.Back(-1)._.graph[Gun.val.rel.is(val.b)]; 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.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(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(a.kid)).to.be(Gun.node.soul(b));
@ -5577,7 +5576,7 @@ describe('Gun', function(){
}).path('wife.pet.name').val(function(val){ }).path('wife.pet.name').val(function(val){
//console.debug(1, "*****************", val); //console.debug(1, "*****************", val);
expect(val).to.be('Hobbes'); expect(val).to.be('Hobbes');
}).back.path('pet.master').val(function(val){ }).back().path('pet.master').val(function(val){
//console.log("*****************", val); //console.log("*****************", val);
expect(val.name).to.be("Amber Nadal"); expect(val.name).to.be("Amber Nadal");
expect(val.phd).to.be.ok(); expect(val.phd).to.be.ok();
@ -5750,7 +5749,7 @@ describe('Gun', function(){
//expect(a['_']['key']).to.be.ok(); //expect(a['_']['key']).to.be.ok();
gun.get('user/beth').put({friend: a}, function(err, ok){ // b - friend_of -> a gun.get('user/beth').put({friend: a}, function(err, ok){ // b - friend_of -> a
expect(err).to.not.be.ok(); expect(err).to.not.be.ok();
var keynode = gun.Back(-1)._.graph['user/alfred']; var keynode = gun.back(-1)._.graph['user/alfred'];
var c = soulnode(gun, keynode), soul = c[0]; var c = soulnode(gun, keynode), soul = c[0];
expect(c.length).to.be(1); expect(c.length).to.be(1);
}); });
@ -5796,7 +5795,7 @@ describe('Gun', function(){
var gun = Gun(); var gun = Gun();
gun.key('me', function(err, ok){ gun.key('me', function(err, ok){
expect(err).to.not.be.ok(); expect(err).to.not.be.ok();
var keynode = gun.Back(-1)._.graph['me']; var keynode = gun.back(-1)._.graph['me'];
var c = soulnode(gun, keynode), soul = c[0]; var c = soulnode(gun, keynode), soul = c[0];
expect(c.length).to.be(1); expect(c.length).to.be(1);
@ -6984,7 +6983,7 @@ describe('Gun', function(){
passengers.map().path('direction.lol').val(function(val){ passengers.map().path('direction.lol').val(function(val){
this.path('just').val(function(val){ this.path('just').val(function(val){
expect(val).to.be('kidding'); expect(val).to.be('kidding');
}).back.path('dude').val(function(val){ }).back().path('dude').val(function(val){
expect(val).to.be('!'); expect(val).to.be('!');
done(); done();
}); });
@ -7125,7 +7124,7 @@ describe('Gun', function(){
gun gun
.path('history') .path('history')
.put(null) .put(null)
.back .back()
.path('taken') .path('taken')
.put(false) .put(false)
@ -7322,7 +7321,7 @@ describe('Gun', function(){
cb(at, at.soul); cb(at, at.soul);
//first = performance.now() - start;(first > .05) && console.log('here'); //first = performance.now() - start;(first > .05) && console.log('here');
}; };
($.empty && !$.field)? path() : chain.back.path(at.path || [], path, {once: true, end: true}); // TODO: clean this up. ($.empty && !$.field)? path() : chain.back().path(at.path || [], path, {once: true, end: true}); // TODO: clean this up.
} }
//var diff1 = (first - start), diff2 = (second - first), diff3 = (third - second); //var diff1 = (first - start), diff2 = (second - first), diff3 = (third - second);
//(diff1 || diff2 || diff3) && console.log(diff1, ' ', diff2, ' ', diff3); //(diff1 || diff2 || diff3) && console.log(diff1, ' ', diff2, ' ', diff3);
@ -7785,9 +7784,9 @@ describe('Gun', function(){
users.set(carl); users.set(carl);
users.set(dave); users.set(dave);
alice.path('friends').set(bob).back.set(carl); alice.path('friends').set(bob).back().set(carl);
bob.path('friends').set(alice); bob.path('friends').set(alice);
dave.path('friends').set(alice).back.set(carl); dave.path('friends').set(alice).back().set(carl);
var team = gun.get('team/lions').put({name: "Lions"}); var team = gun.get('team/lions').put({name: "Lions"});
team.path('members').set(alice); team.path('members').set(alice);

View File

@ -1,7 +1,6 @@
<script src="../examples/jquery.js"></script> <script src="../examples/jquery.js"></script>
<script src="../gun.js"></script> <script src="../gun.js"></script>
<script src="../lib/open.js"></script> <script src="../lib/open.js"></script>
<script src="../lib/erase.js"></script>
<script> <script>
var gun = Gun('http://localhost:8080/gun'); var gun = Gun('http://localhost:8080/gun');
</script> </script>

View File

@ -3,8 +3,8 @@ var config = {
port: 8080, port: 8080,
servers: 2, servers: 2,
browsers: 2, browsers: 2,
each: 10000, each: 12000,
burst: 100, burst: 1000,
wait: 1, wait: 1,
route: { route: {
'/': __dirname + '/index.html', '/': __dirname + '/index.html',