experimental approach works!

This commit is contained in:
Mark Nadal 2016-10-13 00:48:36 -07:00
parent da3e644c70
commit 53e171310d
2 changed files with 129 additions and 94 deletions

199
gun.js
View File

@ -372,14 +372,19 @@
} }
if(last){ if(last){
if(act.on.map){ if(act.on.map){
console.log(209, "TODO: BUG!!!! MARK COME BACK HERE!!!!!! Because input does not use emit [] syntax, the new event does not override the previous one thus infinite loop. You need a way of associating IDs on maps and then prevent [] syntax so it works no matter whate everywhere. Remember that their `gun` might be different each time!", last, act);
//console.debug.i=1;
Gun.obj.map(act.on.map, function(v,f){ // TODO: BUG! Gun is not available in this module. Gun.obj.map(act.on.map, function(v,f){ // TODO: BUG! Gun is not available in this module.
//emit(v[0], act, event, v[1]); // below enables more control //emit(v[0], act, event, v[1]); // below enables more control
emit(v[1], act, event, v[2]); //console.log("boooooooo", f,v);
emit(v, act, event);
//emit(v[1], act, event, v[2]);
}); });
} else { } else {
emit(last, act, event); emit(last, act, event);
} }
if(last !== act.on.last){ if(last !== act.on.last){
//console.log(">>>>>>>>>>>>>>>>>>>>>>>>>>", last, act.on.last);
event(act); event(act);
} }
} }
@ -393,16 +398,17 @@
} }
on.on('emit', function(ev){ on.on('emit', function(ev){
if(ev.on.map && ev.arg instanceof Array){ if(ev.on.map){
console.log("EMIT", ev);
var id = ev.arg.via.gun._.id + ev.arg.get;
/* /*
ev.id = ev.id || Gun.text.random(6); ev.id = ev.id || Gun.text.random(6);
ev.on.map[ev.id] = ev.arg; ev.on.map[ev.id] = ev.arg;
ev.proxy = ev.arg[1]; ev.proxy = ev.arg[1];
ev.arg = ev.arg[0]; ev.arg = ev.arg[0];
*/ // below gives more control. */ // below gives more control.
ev.on.map[ev.arg[0]] = ev.arg; ev.on.map[id] = ev.arg;
//ev.proxy = ev.arg[2]; //ev.proxy = ev.arg[2];
ev.arg = ev.arg[1];
} }
ev.on.last = ev.arg; ev.on.last = ev.arg;
}); });
@ -915,7 +921,6 @@
} }
function get(at, cat){ function get(at, cat){
var soul = at.get[_soul], node = cat.graph[soul], field = at.get[_field]; var soul = at.get[_soul], node = cat.graph[soul], field = at.get[_field];
console.debug(4, 'GET', soul, node, field);
if(node && (!field || obj_has(node, field))){ if(node && (!field || obj_has(node, field))){
if(field){ if(field){
node = Gun.obj.put({_: node._}, field, node[field]); node = Gun.obj.put({_: node._}, field, node[field]);
@ -937,7 +942,6 @@
if(cat.graph){ if(cat.graph){
Gun.obj.map(at.put, ham, {at: at, cat: cat}); // all unions must happen first, sadly. Gun.obj.map(at.put, ham, {at: at, cat: cat}); // all unions must happen first, sadly.
} }
console.debug(6, 'IN', at);
Gun.obj.map(at.put, map, {at: at, cat: cat}); Gun.obj.map(at.put, map, {at: at, cat: cat});
} }
function ham(data, key){ function ham(data, key){
@ -1350,38 +1354,50 @@
return gun; return gun;
} }
function output(at){ function output(at){
var cat = this, gun = cat.gun, root = gun.Back(-1), put, get, tmp; var cat = this, gun = cat.gun, root = gun.Back(-1), put, get, now, tmp;
if(!at.gun){ if(!at.gun){
at.gun = gun; at.gun = gun;
} }
if(get = at.get){ if(get = at.get){
if(!get[_soul]){ if(!get[_soul]){
console.debug(3, 'out', cat.get);
console.debug(2, 'out', cat.get);
if(obj_has(get, _field)){ if(obj_has(get, _field)){
get = get[_field]; get = get[_field];
if((cat.ask = cat.ask || {})[get || node_]){ return } var next = get? gun.get(get)._ : cat;
cat.ask._ = cat.ask._ || {}; if(0 >= next.ask){ return }
if(get){ cat.ask[get] = cat.ask._['.'] = 1 } next.ask = 1;
tmp = false; //console.debug.i=100;
cat.on('in', function(tac, ev){ cat.on('in', function(tac, ev){
tmp = true; //console.log("--------------------------", tac);
if(u !== tac.put){ console.debug(1, '!!!!!!!!', tac);
var val = tac.put, rel;
cat.FOOBAR = 'FOOBAR';
if(u === val){
at.gun.on('in', {
get: get,
gun: at.gun,
via: tac
});
return;
}
if(Gun.node.soul(val)){ return } // TODO: BUG! Should ask for the property!
if(rel = Gun.val.rel.is(val)){
at.gun.on('out', {
get: {'#': rel, '.': get},
'#': Gun.on.ask(ack, at.gun),
gun: at.gun
});
if(tmp = tac.gun._.put){ // TODO: CLEAN THIS UP! DO NOT DEPEND UPON IT!
//console.log("~~~~~~ END THIS MISERY ~~~~~~~", tac.get);
tac.put = tmp;
}
return;
}
input.call(cat, tac, ev); input.call(cat, tac, ev);
return; return;
} now = true;
// TODO: BUG! We want to query for it! So should still `input`. There should be no special case here. var val = tac.put, rel;
// Nots require some special treatment. if(rel = Gun.val.is(val)){
at.gun.on('in', { if(!rel.length){
get: get,
gun: at.gun,
via: tac
});
return;
var put = tac.put, rel = tac.put;
if(!(rel = (Gun.node.soul(put) || Gun.val.rel.is(put)))){
if(!get){ return }
// Nots require some special treatment.
at.gun.on('in', { at.gun.on('in', {
get: get, get: get,
gun: at.gun, gun: at.gun,
@ -1389,11 +1405,26 @@
}); });
return; return;
} }
ask(cat, rel); } else {
tmp = true; rel = Gun.node.soul(val);
}
if(!rel){
at.gun.on('in', {
get: get,
put: val[get],
gun: at.gun,
via: tac
});
return;
}
at.gun.on('out', {
get: {'#': rel, '.': get},
'#': Gun.on.ask(ack, at.gun),
gun: at.gun
});
}).off(); // TODO: BUG! This `.off()` is correct, but note that not doing it inside of the callback means that potentially inside of the callback will do/cause other work which might trigger the event listener synchronously before it can ever unsubscribe. The problem currently with having an unsubscribe inside is because there might be a `.map` that needs multiple things to be triggered. Although now that I have mentioned it the `ev.off()` inside for a map should only effect their own event, not the thing as a whole. Hmmm. }).off(); // TODO: BUG! This `.off()` is correct, but note that not doing it inside of the callback means that potentially inside of the callback will do/cause other work which might trigger the event listener synchronously before it can ever unsubscribe. The problem currently with having an unsubscribe inside is because there might be a `.map` that needs multiple things to be triggered. Although now that I have mentioned it the `ev.off()` inside for a map should only effect their own event, not the thing as a whole. Hmmm.
if(tmp){ return } console.log("????????????????????????????????????????????");
if(!cat.get){ return } if(now || !cat.get){ return }
if(root === cat.back){ if(root === cat.back){
if(get){ cat.ask[get] = -1 } if(get){ cat.ask[get] = -1 }
at.gun.on('out', { at.gun.on('out', {
@ -1410,10 +1441,10 @@
return; return;
} else { } else {
if(cat.ask){ return } if(cat.ask){ return }
cat.ask = {_:{'*':1}}; cat.ask = 1;
if(!cat.get){ return } if(!cat.get){ return }
if(root === cat.back){ if(root === cat.back){
cat.ask._['*'] = -1; cat.ask = -1;
gun.on('out', { gun.on('out', {
get: {'#': cat.get}, get: {'#': cat.get},
'#': Gun.on.ask(ack, gun), '#': Gun.on.ask(ack, gun),
@ -1434,7 +1465,7 @@
function input(at, ev){ function input(at, ev){
at = at._ || at; at = at._ || at;
var cat = this, gun = at.gun, coat = gun._, change = coat.change, tmp; var cat = this, gun = at.gun, coat = gun._, change = coat.change, tmp;
//coat.id = coat.id || Gun.text.random(5); // TODO: BUG! This allows for 1B item entropy in memory. In the future, people might want to expand this to be larger. coat.id = coat.id || Gun.text.random(5); // TODO: BUG! This allows for 1B item entropy in memory. In the future, people might want to expand this to be larger.
if(!coat.soul && !coat.field && coat.back._.soul){ // TODO: PERF! Any faster/simpler/easier way we could do this? if(!coat.soul && !coat.field && coat.back._.soul){ // TODO: PERF! Any faster/simpler/easier way we could do this?
coat.field = coat.get; coat.field = coat.get;
} }
@ -1442,83 +1473,70 @@
Gun.on.ack(tmp, at); Gun.on.ack(tmp, at);
if(at.err){ return } if(at.err){ return }
}; };
console.debug(11, 'in', cat.get, change, Gun.obj.copy(cat.ask), cat.next, cat.on('in').s.slice()); cat.FOOBAR&&at.put&&at.put.name==='Bob!'&&(console.debug.i=300);
console.debug(9, 'in', cat.get, change, Gun.obj.copy(cat.ask), cat.next, cat.on('in').s.slice()); cat.FOOBAR&&console.debug(2, 'in!');
console.debug(7, 'in', cat.get, change, Gun.obj.copy(cat.ask), cat.next, cat.on('in').s.slice()); //console.log("--- in ---", cat.FOOBAR, cat.get, change, cat.next, cat.proxy);
//console.debug(13, 'in', cat.get, change, cat.next, cat.on('in').s.slice());
if(value.call(cat, at, ev)){ if(value.call(cat, at, ev)){
return; return;
} }
obj_map(change, map, {at: at, cat: cat}); // Important because `values` sometimes `ask`s for things which changes what the `changes` are. obj_map(change, map, {at: at, cat: cat}); // Important because `values` sometimes `ask`s for things which changes what the `changes` are.
console.debug.i===14&&(console.debug.i=200);
} }
Gun.chain.get.input = input; Gun.chain.get.input = input;
function value(at, ev){ function value(at, ev){
var cat = this, gun = at.gun, put = at.put, coat = gun._, rel, tmp; var cat = this, gun = at.gun, put = at.put, coat = gun._, rel, tmp;
if(u === at.put){ if(u === put){
not(cat, at); not(cat, at);
return true; return true;
} }
if(!(rel = Gun.val.rel.is(put))){ if(!(rel = Gun.val.rel.is(put))){
if(cat.proxy){ if(cat.proxy && cat.proxy.at !== at){
if(cat.proxy.it === at){ //if(cat.proxy.at === at){ return } // TODO: BUG! It is unclear at this point whether at.put will ever be a primitive. We need to figure that out. Either way, even with a node it might be a different soul than before. If so, we need to emit undefined first to clear out children listeners.
if(!cat.proxy.rel){ return true }
//ev.stun();
console.debug(13, 'values', cat.get, put, Gun.obj.copy(cat.ask), Gun.obj.copy(coat.ask));
ask(cat, Gun.node.soul(put), cat);
console.debug(14, 'values', cat.get, put);
return true;
} // TODO: PERF! Anyway to simplify this?
if(cat.proxy.rel){ if(cat.proxy.rel){
cat.change = coat.change; cat.change = coat.change;
cat.put = coat.put; cat.put = coat.put;
} }
// TODO: BUG! This mutated `at` won't effect the original at that was sent via the poly-proxy approach. Meaning what is still cached in the poly-set is not this better/recent/fuller one. window.FOO = (window.FOO || 0) + 1;
console.debug(12, 'values', cat.get, put, cat.proxy, cat.on('in').s.slice()); if(window.FOO > 100){ return true }
cat.on('in', obj_to(at, cat.proxy.it = {get: cat.get || at.get})); console.log(3, 'values', cat.get, put, cat.proxy);
console.debug(15, 'values', cat.get, put, cat.proxy, cat.on('in').s.slice()); cat.on('in', cat.proxy.at = obj_to(at, {get: cat.get, via: at}));
} //cat.on('in', cat.proxy.at = obj_to(at, {get: cat.get, via: obj_to(at, {put: obj_put({}, cat.get||at.get, at.put)})}));
if(Gun.val.is(put)){
//ask(); // ask?
not(cat, at);
return true; return true;
} }
if(Gun.val.is(put)){
//not(cat, at);
return true;
}
/*
// iterables? // iterables?
if(!cat.proxy){ if(!cat.proxy){
ask(cat, rel || Gun.node.soul(put)); ask(cat, rel || Gun.node.soul(put));
} }
*/
return; return;
}; };
if(coat.proxy && rel === coat.proxy.rel){ if(coat !== cat){
coat.id = coat.id || Gun.text.random(6); if((cat.proxy = cat.proxy || {})[coat.id = coat.id || Gun.text.random(6)]){
ask(cat, rel, coat);
if(cat === coat){
ev.stun(); ev.stun();
cat.put = at.put = coat.proxy.ref._.put; return true;
// change?
} else
if(!cat.proxy || !cat.proxy[coat.id]){
(cat.proxy = cat.proxy || {})[coat.id] = coat;
cat.proxy.res = ev.stun(rel); // TODO: BUG! Race? Or this all goes to the same thing so it doesn't matter?
gun.on('in', input, cat); // TODO: BUG! PERF! MEMORY LEAK!
} }
return cat.put === coat.put? false : true; cat.proxy[coat.id] = coat;
}
if(cat !== coat){
coat.id = coat.id || Gun.text.random(6); // TODO: BUG! REPEATS ABOVE
if(!cat.proxy || !cat.proxy[coat.id]){ // TODO: BUG! REPEATS ABOVE
(cat.proxy = cat.proxy || {})[coat.id] = coat;
cat.proxy.res = ev.stun(rel);
gun.on('in', input, cat); gun.on('in', input, cat);
} }
if(coat.proxy){
if(rel === coat.proxy.rel){
ev.stun();
tmp = coat.proxy.ref._;
coat.change = tmp.change;
at.put = coat.put = tmp.put;
return true;
}
not(coat, at);
} }
//not(cat, at);
//coat.put = u; // this okay?
tmp = coat.proxy = {rel: rel, ref: coat.root.get(rel)}; tmp = coat.proxy = {rel: rel, ref: coat.root.get(rel)};
tmp.ev = ev; /*tmp.res = ev.stun(rel);*/ tmp.as = coat;
console.debug(10, 'values', cat.get, put, cat.proxy);
tmp.ref.on('in', input, coat); tmp.ref.on('in', input, coat);
// TODO: BUG, MAKE SURE NOT TO DO ASK IF ^ IS CACHED SINCE IT WILL ON ITS OWN END. if(coat.put !== put){ ev.stun() }
ask(cat, rel, coat);
if(put !== cat.put){ ev.stun() }
return true; return true;
} }
function value2(at, ev){ function value2(at, ev){
@ -1624,12 +1642,13 @@
var cat = this.cat, next = cat.next || {}, via = this.at, gun, at, tmp; var cat = this.cat, next = cat.next || {}, via = this.at, gun, at, tmp;
if(!(gun = next[key])){ return } if(!(gun = next[key])){ return }
at = gun._; at = gun._;
/*
if(tmp = Gun.val.rel.is(data)){ if(tmp = Gun.val.rel.is(data)){
if(at.link && tmp === at.link.rel){ if(at.link && tmp === at.link.rel){
return; return;
} }
} }
console.debug(8, '---->>', key, data); */
if(via.gun === cat.gun){ if(via.gun === cat.gun){
at.change = data; at.change = data;
at.put = data; at.put = data;
@ -1672,7 +1691,6 @@
}); });
} }
function not(cat, at){ function not(cat, at){
//if(u !== at.put){ return }
var ask = cat.ask, tmp = cat.proxy; var ask = cat.ask, tmp = cat.proxy;
cat.proxy = null; cat.proxy = null;
if(null === tmp){ return } if(null === tmp){ return }
@ -1745,7 +1763,6 @@
var opt = opt || {}, gun = opt.gun = this; var opt = opt || {}, gun = opt.gun = this;
if(opt.change){ opt.change = 1 } if(opt.change){ opt.change = 1 }
opt.any = cb; opt.any = cb;
console.debug(1, 'any', gun._.get);
return gun.on('in', any, opt).on('out', {get: opt}); return gun.on('in', any, opt).on('out', {get: opt});
} }
function any(at, ev){ var opt = this; function any(at, ev){ var opt = this;
@ -1754,12 +1771,10 @@
if((tmp = data) && tmp[Gun.val.rel._] && (tmp = Gun.val.rel.is(tmp))){ if((tmp = data) && tmp[Gun.val.rel._] && (tmp = Gun.val.rel.is(tmp))){
//console.log("ooooooooh jolllllly", data); //console.log("ooooooooh jolllllly", data);
if(null !== opt['.']){ if(null !== opt['.']){
if(Gun.val.rel.is(cat.put)){ if(!cat.ask){
if(cat.ask && cat.ask._ && 0 >= cat.ask._['*']){ return } // TODO: CLEAN UP!!! cat.root.get(tmp).val(function(){});
console.debug(12, 'ANY!', at, cat);
cat.root.get(tmp).any(function(err,d,k,a,e){e.off()});
return;
} }
return;
} }
at = obj_to(at, {put: data = cat.change = cat.put = cat.put || Gun.state.ify(Gun.node.ify({}, tmp))}); at = obj_to(at, {put: data = cat.change = cat.put = cat.put || Gun.state.ify(Gun.node.ify({}, tmp))});
} }
@ -2125,14 +2140,15 @@
} }
function map(at,ev){ function map(at,ev){
var cat = this, gun = at.gun || this.back, tac = gun._; var cat = this, gun = at.gun || this.back, tac = gun._;
obj_map(at.put, each, {gun:gun, cat: cat, id: tac.id||at.get}); obj_map(at.put, each, {gun:gun, cat: cat, id: tac.id||at.get, at: at});
} }
function each(v,f){ function each(v,f){
if(n_ === f){ return } if(n_ === f){ return }
var gun = this.gun, cat = this.cat, id = this.id; var gun = this.gun, cat = this.cat, id = this.id;
if(cat.list[id+f]){ return } if(cat.list[id+f]){ return }
// TODO: BUG! Ghosting! // TODO: BUG! Ghosting!
return cat.on('in', [id+f, {gun: (cat.list[id+f] = gun.path(f)), get: f, put: v}]); return cat.on('in', {gun: (cat.list[id+f] = gun.path(f)), get: f, put: v, via: this.at});
//return cat.on('in', [id+f, {gun: (cat.list[id+f] = gun.path(f)), get: f, put: v}]);
} }
var obj_map = Gun.obj.map, noop = function(){}, event = {stun: noop, off: noop}, n_ = Gun.node._; var obj_map = Gun.obj.map, noop = function(){}, event = {stun: noop, off: noop}, n_ = Gun.node._;
}()); }());
@ -2184,7 +2200,6 @@
if(!data){ return } // localStorage isn't trustworthy to say "not found". if(!data){ return } // localStorage isn't trustworthy to say "not found".
if(Gun.obj.has(lex, '.')){var tmp = data[lex['.']];data = {_: data._};if(u !== tmp){data[lex['.']] = tmp}} if(Gun.obj.has(lex, '.')){var tmp = data[lex['.']];data = {_: data._};if(u !== tmp){data[lex['.']] = tmp}}
//console.log('@@@@@@@@@@@@local get', data, at); //console.log('@@@@@@@@@@@@local get', data, at);
console.debug(5, 'get local', data);
gun.Back(-1).on('in', {'@': at['#'], put: Gun.graph.node(data)}); gun.Back(-1).on('in', {'@': at['#'], put: Gun.graph.node(data)});
//},100); //},100);
} }

View File

@ -1453,6 +1453,26 @@ describe('Gun', function(){
}); });
it.only('delete this', function(done){
var s = Gun.state.map();s.soul = 'u/m';
Gun.on('put', {gun: gun, put: Gun.graph.ify({
alice: {
age: 26,
name: "Alice",
boo: {a:1}
},
bob: {
age: 29,
name: "Bob!",
boo: {b:2}
}
}, s)});
//console.debug.i=1;console.log('------------------');
gun.get('u/m').map().path('name').on(function(v){
console.log("*************************** users...", v);
});
});
describe('plural chains', function(){ describe('plural chains', function(){
it("get before put in memory", function(done){ it("get before put in memory", function(done){