From 8bb003e311e921017646e4e645f5c0eea392d2c0 Mon Sep 17 00:00:00 2001 From: Mark Nadal Date: Mon, 14 Nov 2016 16:34:28 -0800 Subject: [PATCH] getting back from Italy... --- gun.js | 102 ++++++++++----- test/common.js | 329 ++++++++++++++++++++++++++++++++++++++++++++++--- 2 files changed, 383 insertions(+), 48 deletions(-) diff --git a/gun.js b/gun.js index a6d9e805..6dae5d28 100644 --- a/gun.js +++ b/gun.js @@ -372,8 +372,6 @@ } if(last){ 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. //emit(v[0], act, event, v[1]); // below enables more control //console.log("boooooooo", f,v); @@ -399,7 +397,6 @@ on.on('emit', function(ev){ 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); @@ -1362,15 +1359,16 @@ if(!get[_soul]){ if(obj_has(get, _field)){ get = get[_field]; - var next = get? gun.get(get)._ : cat; + var next = get? gun.get(get, null, {path: true})._ : cat; if(0 >= next.ask){ return } - next.ask = 1; + //next.ask = 1; + //console.log("<<<<< out", cat.get, at.get, next.ask, next.get, next); //console.debug.i=100; cat.on('in', function(tac, ev){ - //console.log("--------------------------", tac); - console.debug(1, '!!!!!!!!', tac); + //console.log("--------------------------", tac.get, get, tac.put); + now = true; + //next.ask = -1; var val = tac.put, rel; - cat.FOOBAR = 'FOOBAR'; if(u === val){ at.gun.on('in', { get: get, @@ -1380,6 +1378,7 @@ return; } if(Gun.node.soul(val)){ return } // TODO: BUG! Should ask for the property! + // TODO: BUG!!!! ^^^^ We might have loaded 1 property on this node and thus have the node but not other properties yet. if(rel = Gun.val.rel.is(val)){ at.gun.on('out', { get: {'#': rel, '.': get}, @@ -1394,6 +1393,9 @@ } input.call(cat, tac, ev); return; + return; + return; + return; now = true; var val = tac.put, rel; if(rel = Gun.val.is(val)){ @@ -1423,10 +1425,10 @@ 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. - console.log("????????????????????????????????????????????"); if(now || !cat.get){ return } if(root === cat.back){ - if(get){ cat.ask[get] = -1 } + at.gun._.ask = -1; + //if(get){ cat.ask[get] = -1 } at.gun.on('out', { get: {'#': cat.get, '.': get}, '#': Gun.on.ask(ack, at.gun), @@ -1473,20 +1475,17 @@ Gun.on.ack(tmp, at); if(at.err){ return } }; - cat.FOOBAR&&at.put&&at.put.name==='Bob!'&&(console.debug.i=300); - cat.FOOBAR&&console.debug(2, 'in!'); - //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()); + //console.log('>>>>>>>>>>>>>>>>>>>in', cat.get, cat.next); if(value.call(cat, at, ev)){ return; } 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; function value(at, ev){ var cat = this, gun = at.gun, put = at.put, coat = gun._, rel, tmp; if(u === put){ + console.log("oye!", cat); not(cat, at); return true; } @@ -1497,15 +1496,13 @@ cat.change = coat.change; cat.put = coat.put; } - window.FOO = (window.FOO || 0) + 1; - if(window.FOO > 100){ return true } - console.log(3, 'values', cat.get, put, cat.proxy); 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)})})); return true; } if(Gun.val.is(put)){ - //not(cat, at); + console.log("hi", cat.get, put, coat, cat); + not(coat, at); + not(cat, at); return true; } /* @@ -1517,12 +1514,13 @@ return; }; if(coat !== cat){ - if((cat.proxy = cat.proxy || {})[coat.id = coat.id || Gun.text.random(6)]){ - ev.stun(); - return true; + if(console.debug(2, '????', cat.get, rel, cat, coat.id, cat.proxy, coat.proxy && coat.proxy.rel === rel)){}// debugger } + if(!(cat.proxy = cat.proxy || {})[coat.id = coat.id || Gun.text.random(6)]){ + cat.proxy[coat.id] = coat; + gun.on('in', input, cat); + } else { + ask(cat, rel); } - cat.proxy[coat.id] = coat; - gun.on('in', input, cat); } if(coat.proxy){ if(rel === coat.proxy.rel){ @@ -1532,11 +1530,19 @@ at.put = coat.put = tmp.put; return true; } + console.debug(1, "?????????", cat.get, rel); not(coat, at); + not(cat, at); } tmp = coat.proxy = {rel: rel, ref: coat.root.get(rel)}; - tmp.ref.on('in', input, coat); - if(coat.put !== put){ ev.stun() } + tmp.sub = tmp.ref._.on('in', input, coat); + ask(cat, rel); + /* + if(cat.ask && u === coat.put){ + console.log("<<>>>>>>", cat.get, cat.ask, coat.put); + cat.root.get(rel).any(function(err,d,f,a,e){console.log("???", d, e);e.off()}); + }*/ + if(coat.put && coat.put !== put){ ev.stun() } return true; } function value2(at, ev){ @@ -1659,6 +1665,7 @@ via: via }); } else { + //console.log("---->>", key, data); gun.on('in', { put: data, get: key, @@ -1700,6 +1707,21 @@ } tmp.off = true; } + if(cat.ask){ cat.ask = 1 } + obj_map(cat.next, function(gun, key){ + var at = gun._; + if(obj_has(at,'put')){ + at.put = at.change = u; + } + gun.on('in', { + get: key, + put: u, + gun: gun, + via: at + }) + }) + // TODO: BUG! Need to fix/update. + return; obj_map(ask, function(state, key){ if(key === node_){ if(state['*']){ @@ -1720,7 +1742,29 @@ }); }); } - function ask(cat, soul, at){ + function ask(cat, soul){ + var tmp; + if(cat.ask){ + if(0 >= cat.ask){ return } + tmp = cat.root.get(soul); + tmp.on('out', { + get: {'#': soul}, + gun: tmp, + '#': Gun.on.ask(ack, tmp) + }); + return; + } + if(0 === cat.ask){ return } + obj_map(cat.next, function(gun, key){ + console.log("ask next", cat.get, key, gun._.ask); + gun.on('out', { + get: {'#': soul, '.': key}, + gun: gun, + '#': Gun.on.ask(ack, gun) + }); + }); + } + function ask2(cat, soul, at){ if(at && !at.ask){ at.ask = {} } // TODO: BUG! Second time through? Or first time through and *? var ask = cat.ask, coat = at || cat, proxy = coat.ask || ask, lex, tmp; if(!ask || !soul || !ask._){ return } @@ -1766,11 +1810,13 @@ return gun.on('in', any, opt).on('out', {get: opt}); } function any(at, ev){ var opt = this; + console.debug.i&&console.log("any!", at); if(!at.gun){ console.log("Error: %%%%%%% No gun context! %%%%%%%") } var gun = at.gun, cat = gun._, data = at.put, tmp; if((tmp = data) && tmp[Gun.val.rel._] && (tmp = Gun.val.rel.is(tmp))){ //console.log("ooooooooh jolllllly", data); if(null !== opt['.']){ + console.log("any soul ask", at.get, at.put, cat.ask); if(!cat.ask){ cat.root.get(tmp).val(function(){}); } diff --git a/test/common.js b/test/common.js index 9d7b85b5..0115a79a 100644 --- a/test/common.js +++ b/test/common.js @@ -1453,28 +1453,317 @@ 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(){ + it('uncached synchronous map on', 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", + pet: {a:1, name: "Fluffy"} + }, + bob: { + age: 29, + name: "Bob!", + pet: {b:2, name: "Frisky"} + } + }, s)}); + var check = {}; + gun.get('u/m').map().on(function(v,f){ + check[f] = v; + if(check.alice && check.bob){ + 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(check.bob.age).to.be(29); + expect(check.bob.name).to.be('Bob!'); + expect(Gun.val.rel.is(check.bob.pet)).to.be.ok(); + done(); + } + }); + }); + + it('uncached synchronous map path on', function(done){ + var s = Gun.state.map();s.soul = 'u/m/p'; + Gun.on('put', {gun: gun, put: Gun.graph.ify({ + alice: { + age: 26, + name: "alice", + pet: {a:1, name: "Fluffy"} + }, + bob: { + age: 29, + name: "bob", + pet: {b:2, name: "Frisky"} + } + }, s)}); + var check = {}; + gun.get('u/m/p').map().path('name').on(function(v,f){ + check[v] = f; + if(check.alice && check.bob){ + expect(check.alice).to.be('name'); + expect(check.bob).to.be('name'); + done(); + } + }); + }); + + it('uncached synchronous map path on node', function(done){ + var s = Gun.state.map();s.soul = 'u/m/p/n'; + Gun.on('put', {gun: gun, put: Gun.graph.ify({ + alice: { + age: 26, + name: "alice", + pet: {a:1, name: "Fluffy"} + }, + bob: { + age: 29, + name: "bob", + pet: {b:2, name: "Frisky"} + } + }, s)}); + var check = {}; + gun.get('u/m/p/n').map().path('pet').on(function(v,f){ + check[v.name] = v; + if(check.Fluffy && check.Frisky){ + expect(check.Fluffy.a).to.be(1); + expect(check.Frisky.b).to.be(2); + done(); + } + }); + }); + + it('uncached synchronous map path on node path', function(done){ + var gun = Gun(); + var s = Gun.state.map();s.soul = 'u/m/p/n/p'; + Gun.on('put', {gun: gun, put: Gun.graph.ify({ + alice: { + age: 26, + name: "alice", + pet: {a:1, name: "Fluffy"} + }, + bob: { + age: 29, + name: "bob", + pet: {b:2, name: "Frisky"} + } + }, s)}); + var check = {}; + gun.get('u/m/p/n/p').map().path('pet').path('name').on(function(v,f){ + check[v] = f; + if(check.Fluffy && check.Frisky){ + expect(check.Fluffy).to.be('name'); + expect(check.Frisky).to.be('name'); + Gun.obj.map(gun._.graph, function(n,s){ + if('u/m/p/n/p' === s){ return } + var a = Gun.obj.map(n, function(v,f,t){t(v)}); + expect(a.length).to.be(2); + }); + done(); + } + }); + }); + + it('uncached synchronous map on mutate', function(done){ + var s = Gun.state.map();s.soul = 'u/m/mutate'; + Gun.on('put', {gun: gun, put: Gun.graph.ify({ + alice: { + age: 26, + name: "Alice", + pet: {a:1, name: "Fluffy"} + }, + bob: { + age: 29, + name: "Bob", + pet: {b:2, name: "Frisky"} + } + }, s)}); + var check = {}; + gun.get('u/m/mutate').map().path('name').any(function(e,v,f){ + check[v] = f; + if(check.Alice && check.Bob && check['undefined']){ + done(); + } + }); + setTimeout(function(){ + gun.get('u/m/mutate').path('alice').put(7); + }, 300); + }); + + it('uncached synchronous map on mutate node', function(done){ + var s = Gun.state.map();s.soul = 'u/m/mutate/n'; + Gun.on('put', {gun: gun, put: Gun.graph.ify({ + alice: {_:{'#':'umaliceo'}, + age: 26, + name: "Alice", + pet: {a:1, name: "Fluffy"} + }, + bob: { + age: 29, + name: "Bob", + pet: {b:2, name: "Frisky"} + } + }, s)}); + var check = {}; + gun.get('u/m/mutate/n').map().path('name').on(function(v,f){ + check[v] = f; + if(check.Alice && check.Bob && check['Alice Zzxyz']){ + setTimeout(function(){ + expect(done.last).to.be.ok(); + expect(check['Alice Aabca']).to.not.be.ok(); + done(); + },100); + } + }); + setTimeout(function(){ + gun.get('u/m/mutate/n').path('alice').put({ + _:{'#':'u/m/m/n/soul'}, + name: 'Alice Zzxyz' + }); + setTimeout(function(){ + gun.get('umaliceo').put({ + name: 'Alice Aabca' + }); + done.last = true; + }, 10); + }, 300); + }); + + it('uncached synchronous map on mutate node uncached', function(done){ + var s = Gun.state.map();s.soul = 'u/m/mutate/n/u'; + Gun.on('put', {gun: gun, put: Gun.graph.ify({ + alice: {_:{'#':'umaliceo1'}, + age: 26, + name: "Alice", + pet: {a:1, name: "Fluffy"} + }, + bob: { + age: 29, + name: "Bob", + pet: {b:2, name: "Frisky"} + } + }, s)}); + var check = {}; + gun.get('u/m/mutate/n/u').map().on(function(v,f){ + check[v.name] = f; + if(check.Alice && check.Bob && check['Alice Zzxyz']){ + setTimeout(function(){ + expect(done.last).to.be.ok(); + expect(check['Alice Aabca']).to.not.be.ok(); + done(); + },100); + } + }); + setTimeout(function(){ + var s = Gun.state.map();s.soul = 'u/m/m/n/u/soul'; + Gun.on('put', {gun: gun, put: Gun.graph.ify({ + name: 'Alice Zzxyz' + }, s)}); + gun.get('u/m/mutate/n/u').put({ + alice: {'#':'u/m/m/n/u/soul'}, + }); + setTimeout(function(){ + gun.get('umaliceo1').put({ + name: 'Alice Aabca' + }); + done.last = true; + }, 10); + }, 300); + }); + + it('uncached synchronous map on path mutate node uncached', function(done){ + var s = Gun.state.map();s.soul = 'u/m/p/mutate/n/u'; + Gun.on('put', {gun: gun, put: Gun.graph.ify({ + alice: {_:{'#':'umaliceo2'}, + age: 26, + name: "Alice", + pet: {a:1, name: "Fluffy"} + }, + bob: { + age: 29, + name: "Bob", + pet: {b:2, name: "Frisky"} + } + }, s)}); + var check = {}; + gun.get('u/m/p/mutate/n/u').map().path('name').on(function(v,f){ + check[v] = f; + if(check.Alice && check.Bob && check['Alice Zzxyz']){ + setTimeout(function(){ + var a = Gun.obj.map(gun._.graph['u/m/p/m/n/u/soul'], function(v,f,t){t(v)}); + expect(a.length).to.be(2); + expect(done.last).to.be.ok(); + expect(check['Alice Aabca']).to.not.be.ok(); + done(); + },100); + } + }); + setTimeout(function(){ + var s = Gun.state.map();s.soul = 'u/m/p/m/n/u/soul'; + Gun.on('put', {gun: gun, put: Gun.graph.ify({ + name: 'Alice Zzxyz', age: 34 + }, s)}); + gun.get('u/m/p/mutate/n/u').put({ + alice: {'#':'u/m/p/m/n/u/soul'}, + }); + setTimeout(function(){ + gun.get('umaliceo2').put({ + name: 'Alice Aabca' + }); + done.last = true; + }, 10); + }, 300); + }); + + it.only('uncached synchronous map on path node mutate node uncached', function(done){ + var s = Gun.state.map();s.soul = 'u/m/p/n/mutate/n/u'; + Gun.on('put', {gun: gun, put: Gun.graph.ify({ + alice: {_:{'#':'umaliceo3'}, + age: 26, + name: "Alice", + pet: {_:{'#':'sflufso'},a:1, name: "Fluffy"} + }, + bob: { + age: 29, + name: "Bob", + pet: {b:2, name: "Frisky"} + } + }, s)}); + var check = {}; + (window.FOO = gun.get('u/m/p/n/mutate/n/u').map().path('pet')).on(function(v,f){ + check[v.name] = f; + console.log("************", f,v);return; + if(check.Fluffy && check.Frisky && check.Fuzzball){ + setTimeout(function(){ + //var a = Gun.obj.map(gun._.graph['u/m/p/n/m/n/u/soul'], function(v,f,t){t(v)}); + //expect(a.length).to.be(2); + expect(done.last).to.be.ok(); + expect(check['Fluffs']).to.not.be.ok(); + done(); + },100); + } + }); + //gun.get('u/m/p/n/m/n/u/soul').path('alice').path('pet').on(function(v){console.log("?????????????????????????????????????????", v)}) + setTimeout(function(){ + var s = Gun.state.map();s.soul = 'alice/fuzz/soul'; + Gun.on('put', {gun: gun, put: Gun.graph.ify({ + name: 'Alice Zzxyz', age: 34, + pet: {c:3, name: "Fuzzball"} + }, s)}); + console.debug.i=1;console.log("-----------------------------"); + gun.get('u/m/p/n/mutate/n/u').put({ + alice: {'#':'alice/fuzz/soul'}, + }); + setTimeout(function(){ + gun.get('sflufso').put({ + name: 'Fluffs' + }); + done.last = true; + }, 10); + }, 300); + }); + return; it("get before put in memory", function(done){ var gun = Gun(); var check = {};