This commit is contained in:
Mark Nadal 2015-01-24 19:00:37 -07:00
parent 8980f738c3
commit 7c4ad28b34
3 changed files with 69 additions and 75 deletions

93
gun.js
View File

@ -134,7 +134,7 @@
return {converge: true, incoming: true};
}
}
return {err: "you have not properly handled recursion through your data or filtered it as JSON"};
return {err: console.log("you have not properly handled recursion through your data or filtered it as JSON")};
}
var context = Gun.shot();
context.HAM = {};
@ -151,9 +151,9 @@
var serverState = Gun.time.is();
// add more checks?
var state = HAM(serverState, context.states.delta[field], context.states.current[field], deltaValue, current[field]);
//Gun.log("HAM:", field, deltaValue, context.states.delta[field], context.states.current[field], 'the', state, (context.states.delta[field] - serverState));
//console.log("HAM:", field, deltaValue, context.states.delta[field], context.states.current[field], 'the', state, (context.states.delta[field] - serverState));
if(state.err){
Gun.log(".!HYPOTHETICAL AMNESIA MACHINE ERR!.", state.err);
root.console.log(".!HYPOTHETICAL AMNESIA MACHINE ERR!.", state.err); // this error should never happen.
return;
}
if(state.state || state.quarantineState || state.current){
@ -188,15 +188,6 @@
}
return Gun.text.random(l, c);
}
Gun.log = function(a, b, c, d, e, f){
var gun = this;
if(!gun || !gun.__ || !gun.__.opt){
console.log(gun.__);
return console.log.apply(console, arguments);
}
if(!gun.__.opt.verbose){ return }
return console.log.apply(console, arguments);
}
}(Gun));
;(function(Chain){
Chain.opt = function(opt, stun){ // idempotently update or set options
@ -248,7 +239,7 @@
(gun._.keys = gun._.keys || {})[key] = cb.node? 1 : 0; // set a key marker on it
}
if(!opt.force && cb.node){ // if it was in cache, then...
Gun.log.call(gun, "load via gun");
console.log("load via gun");
gun._.node = cb.node; // assign it to this context
cb.call(gun, null, Gun.obj.copy(gun._.node)); // frozen copy
gun.shot('then').fire();
@ -272,7 +263,7 @@
gun.shot('then').fire();
}, opt);
} else {
Gun.log.call(gun, "Warning! You have no persistence layer to load from!");
cb.call(gun, {err: console.log("Warning! You have no persistence layer to load from!")});
}
});
gun.shot('done').fire(); // because we are loading, we always fire!
@ -300,7 +291,7 @@
return cb.call(gun, null);
});
} else {
Gun.log.call(gun, "Warning! You have no key hook!");
cb.call(gun, {err: console.log("Warning! You have no key hook!")});
}
});
return gun;
@ -397,14 +388,14 @@
val = partial;
} else
if(!Gun.obj.is(val)){
return cb.call(gun, {err: "No field exists to set the " + (typeof val) + " on."});
return cb.call(gun, {err: console.log("No field exists to set the " + (typeof val) + " on.")});
}
// TODO: should be able to handle val being a relation or a gun context or a gun promise.
// TODO: BUG: IF we are setting an object, doing a partial merge, and they are reusing a frozen copy, we need to do a DIFF to update the HAM! Or else we'll get "old" HAM.
val._ = Gun.ify.soul.call(gun, {}, gun._.node || val); // set their souls to be the same that way they will merge correctly for us during the union!
set = Gun.ify.call(gun, val, set);
cb.root = set.root;
if(set.err || !cb.root){ return cb.call(gun, set.err || {err: "No root object!"}) }
if(set.err || !cb.root){ return cb.call(gun, set.err || {err: console.log("No root object!")}) }
set = Gun.ify.state(set.nodes, Gun.time.is()); // set time state on nodes?
if(set.err){ return cb.call(gun, set.err) }
gun.union(set.nodes); // while this maybe should return a list of the nodes that were changed, we want to send the actual delta
@ -421,7 +412,7 @@
return cb.call(gun, null);
});
} else {
Gun.log.call(gun, "Warning! You have no persistence layer to save to!");
cb.call(gun, {err: console.log("Warning! You have no persistence layer to save to!")})
}
});
if(!gun.back){
@ -439,7 +430,7 @@
}).get(function(val){
if(error){ return cb.call(gun, error) } // which in case it is, allows us to fail fast.
var list = {}, soul = Gun.is.soul.on(val);
if(!soul){ return cb.call(gun, {err: "No soul!"}) }
if(!soul){ return cb.call(gun, {err: console.log("No soul!")}) }
list[soul] = val; // other wise, let's then
gun.set(list, cb); // merge with the graph node.
});
@ -472,20 +463,20 @@
cb = cb || function(){}
context.nodes = {};
if(!prime){
context.err = {err: "No data to merge!"};
context.err = {err: console.log("No data to merge!")};
} else
if(Gun.is.soul.on(prime)){
tmp[prime._[Gun._.soul]] = prime;
prime = tmp;
}
if(!gun || context.err){
cb(context.err = context.err || {err: "No gun instance!", corrupt: true}, context);
cb(context.err = context.err || {err: console.log("No gun instance!"), corrupt: true}, context);
return context;
}
if(!Gun.is.graph(prime, function(node, soul){
context.nodes[soul] = node;
})){
cb(context.err = context.err || {err: "Invalid graph!", corrupt: true}, context);
cb(context.err = context.err || {err: console.log("Invalid graph!"), corrupt: true}, context);
return context;
}
if(context.err){ return cb(context.err, context), context } // if any errors happened in the previous steps, then fail.
@ -769,7 +760,7 @@
}({}));
;(function(Serializer){
Gun.ify = function(data, bind){ // TODO: BUG: Modify lists to include HAM state
if(Gun.obj.map(bind, function(){ return true })){ return {err: "Bind must be an empty object."} }
if(Gun.obj.map(bind, function(){ return true })){ return {err: console.log("Bind must be an empty object.")} }
var gun = Gun.is(this)? this : {}
, context = {
nodes: {}
@ -786,16 +777,16 @@
} else
if(Gun.obj.is(data)){
var value = bind || {}, symbol = {}, seen
, err = {err: "Metadata does not support external or circular references at " + sub.path, meta: true};
, err = {err: console.log("Metadata does not support external or circular references at " + sub.path), meta: true};
context.root = context.root || value;
bind = null;
if(seen = ify.seen(context._seen, data)){
//Gun.log.call(gun, "seen in _", sub._, sub.path, data);
//console.log("seen in _", sub._, sub.path, data);
context.err = err;
return;
} else
if(seen = ify.seen(context.seen, data)){
//Gun.log.call(gun, "seen in data", sub._, sub.path, data);
//console.log("seen in data", sub._, sub.path, data);
if(sub._){
context.err = err;
return;
@ -803,7 +794,7 @@
symbol = Gun.ify.soul.call(gun, symbol, seen);
return symbol;
} else {
//Gun.log.call(gun, "seen nowhere", sub._, sub.path, data);
//console.log("seen nowhere", sub._, sub.path, data);
if(sub._){
context.seen.push({data: data, node: value});
} else {
@ -815,7 +806,7 @@
Gun.obj.map(data, function(val, field){
var subs = {path: sub.path + field + '.', _: sub._ || (field == Gun._.meta)? true : false };
val = ify(val, context, subs);
//Gun.log.call(gun, '>>>>', sub.path + field, 'is', val);
//console.log('>>>>', sub.path + field, 'is', val);
if(context.err){ return true }
if(nothing === val){ return }
// TODO: check field validity
@ -828,7 +819,7 @@
} else
if(Gun.list.is(data)){
var unique = {}, edges
, err = {err: "Arrays cause data corruption at " + sub.path, array: true}
, err = {err: console.log("Arrays cause data corruption at " + sub.path), array: true}
edges = Gun.list.map(data, function(val, i, map){
val = ify(val, context, sub);
if(context.err){ return true }
@ -849,7 +840,7 @@
if(context.err){ return }
return edges;
} else {
context.err = {err: "Data type not supported at " + sub.path, invalid: true};
context.err = {err: console.log("Data type not supported at " + sub.path), invalid: true};
}
}
ify.seen = function(seen, data){
@ -867,7 +858,7 @@
context.now = now = (now === 0)? now : now || Gun.time.is();
Gun.obj.map(context.nodes, function(node, soul){
if(!node || !soul || !node._ || !node._[Gun._.soul] || node._[Gun._.soul] !== soul){
return context.err = {err: "There is a corruption of nodes and or their souls", corrupt: true};
return context.err = {err: console.log("There is a corruption of nodes and or their souls"), corrupt: true};
}
var states = node._[Gun._.HAM] = node._[Gun._.HAM] || {};
Gun.obj.map(node, function(val, field){
@ -894,6 +885,9 @@
} else {
module.exports = Gun;
}
var root = this || {}; // safe for window, global, root, and 'use strict'.
root.console = root.console || {log: function(s){ return s }}; // safe for old browsers
var console = {log: Gun.log = function(s){return (Gun.log.verbose && root.console.log.apply(root.console, arguments)), s}};
}({}));
;(function(tab){
@ -915,10 +909,10 @@
} else {
opt.url.pathname = '/' + key;
}
Gun.log("gun load", key);
console.log("gun load", key);
Gun.obj.map(gun.__.opt.peers, function(peer, url){
request(url, null, function(err, reply){
//Gun.log('via', url, key, reply);
//console.log('via', url, key, reply);
if(err || !reply){ return } // handle reconnect?
if(reply.body && reply.body.err){
cb(reply.body.err);
@ -929,21 +923,20 @@
cb.peers = true;
});
if(!cb.peers){ // there are no peers! this is a local only instance
Gun.log.call(gun, "Warning! You have no peers to connect to!");
setTimeout(function(){cb({err: "No peers!"})},0);
setTimeout(function(){cb({err: console.log("Warning! You have no peers to connect to!")})},0);
}
}
tab.key = function(key, soul, cb){
var meta = {};
meta[Gun._.soul] = soul = Gun.text.is(soul)? soul : (soul||{})[Gun._.soul];
if(!soul){
return cb({err: "No soul!"});
return cb({err: console.log("No soul!")});
}
Gun.obj.map(gun.__.opt.peers, function(peer, url){
request(url, meta, function(err, reply){
//Gun.log("gun key done", soul, err, reply);
//console.log("gun key done", soul, err, reply);
if(err || !reply){
Gun.log.call(gun, err = err || "Error: Key failed to be made on " + url);
console.log(err = err || "Error: Key failed to be made on " + url);
// tab.key(key, soul, cb); // naive implementation of retry TODO: BUG: need backoff and anti-infinite-loop!
cb(err);
} else {
@ -956,10 +949,10 @@
cb = cb || function(){};
// TODO: batch and throttle later.
//tab.store.set(cb.id = 'send/' + Gun.text.random(), nodes);
//Gun.log("gun set start");
//console.log("gun set start");
Gun.obj.map(gun.__.opt.peers, function(peer, url){
request(url, nodes, function respond(err, reply, id){
//Gun.log("gun set done", err, reply, id);
//console.log("gun set done", err, reply, id);
return;
var body = reply && reply.body;
@ -967,14 +960,14 @@
Gun.obj.del(tab.set.defer, id); // handle err with a retry? Or make a system auto-do it?
if(!body){ return }
if(body.defer){
//Gun.log("deferring post", body.defer);
//console.log("deferring post", body.defer);
tab.set.defer[body.defer] = respond;
}
if(body.reply){
respond(null, {headers: reply.headers, body: body.reply });
}
if(body.refed){
Gun.log("-------post-reply-all--------->", 1 || reply, err);
console.log("-------post-reply-all--------->", 1 || reply, err);
Gun.obj.map(body.refed, function(r, id){
var cb;
if(cb = tab.set.defer[id]){
@ -1057,7 +1050,7 @@
}catch(e){ return }
if(!res){ return }
if(res.wsrid){ (r.ws.cbs[res.wsrid]||function(){})(null, res) }
//Gun.log("We have a pushed message!", res);
//console.log("We have a pushed message!", res);
if(res.body){ r.createServer(res, function(){}) } // emit extra events.
};
ws.onerror = function(e){ console.log(e); };
@ -1066,12 +1059,12 @@
r.ws.peers = {};
r.ws.cbs = {};
r.jsonp = function(opt, cb){
//Gun.log("jsonp send", opt);
//console.log("jsonp send", opt);
r.jsonp.ify(opt, function(url){
//Gun.log(url);
//console.log(url);
if(!url){ return }
r.jsonp.send(url, function(reply){
//Gun.log("jsonp reply", reply);
//console.log("jsonp reply", reply);
cb(null, reply);
r.jsonp.poll(opt, reply);
}, opt.jsonp);
@ -1095,15 +1088,15 @@
r.jsonp.poll = function(opt, res){
if(!opt || !opt.base || !res || !res.headers || !res.headers.poll){ return }
(r.jsonp.poll.s = r.jsonp.poll.s || {})[opt.base] = r.jsonp.poll.s[opt.base] || setTimeout(function(){ // TODO: Need to optimize for Chrome's 6 req limit?
//Gun.log("polling again");
//console.log("polling again");
var o = {base: opt.base, headers: {pull: 1}};
r.each(opt.headers, function(v,i){ o.headers[i] = v })
r.jsonp(o, function(err, reply){
delete r.jsonp.poll.s[opt.base];
//Gun.log(' ');
//console.log(' ');
while(reply.body && reply.body.length && reply.body.shift){ // we're assuming an array rather than chunk encoding. :(
var res = reply.body.shift();
//Gun.log("-- go go go", res);
//console.log("-- go go go", res);
if(res && res.body){ r.createServer(res, function(){}) } // emit extra events.
}
});
@ -1113,7 +1106,7 @@
var uri = encodeURIComponent, q = '?';
if(opt.url && opt.url.pathname){ q = opt.url.pathname + q; }
q = opt.base + q;
//Gun.log("what up doc?", opt);
//console.log("what up doc?", opt);
r.each((opt.url||{}).query, function(v, i){ q += uri(i) + '=' + uri(v) + '&' });
if(opt.headers){ q += uri('`') + '=' + uri(JSON.stringify(opt.headers)) + '&' }
if(r.jsonp.max < q.length){ return cb() }

View File

@ -1,2 +1,4 @@
console.log("MAKE SURE TO DELETE `data.json` BEFORE RUNNING TESTS!");
var expect = global.expect = require("./expect");
require('./common');
require('./common');

View File

@ -2,6 +2,29 @@ describe('Gun', function(){
var Gun = require('../gun')
, t = {};
describe('Utility', function(){
it('verbose console.log debugging', function(done) {
var gun = Gun();
var log = root.console.log, counter = 1;
root.console.log = function(a,b,c){
--counter;
//log(a,b,c);
}
Gun.log.verbose = true;
gun.set('bar', function(err, yay){ // intentionally trigger an error that will get logged.
expect(counter).to.be(0);
Gun.log.verbose = false;
gun.set('bar', function(err, yay){ // intentionally trigger an error that will get logged.
expect(counter).to.be(0);
root.console.log = log;
done();
});
});
});
describe('Type Check', function(){
it('binary', function(){
expect(Gun.bi.is(false)).to.be(true);
@ -319,30 +342,6 @@ describe('Gun', function(){
require('../lib/file');
var gun = Gun({file: 'data.json'});
it('verbose mode works properly', function(done) {
gun.load('hello/world').get(function() {
var counter = 2;
var originalLog = console.log;
/*
*console.log = function() {
* counter--;
*};
*/
Gun.log('this is a test');
gun.opt({verbose: true});
Gun.log('this is a test');
// Restore original console.log
console.log = originalLog;
expect(counter).to.be(1);
// Finish asynchronous mocha test
done();
});
});
it('set key get', function(done){
gun.set({hello: "world"}).key('hello/world').get(function(val){
expect(val.hello).to.be('world');