From 752fe41a19bc3b3a1cf31b443c146b39f2b6d1bb Mon Sep 17 00:00:00 2001 From: Mark Nadal Date: Wed, 8 Jun 2016 15:07:04 -0700 Subject: [PATCH] Before adding queue to on --- gun.js | 159 ++++++++++++++++------------ package.json | 2 +- test/common.js | 25 +++-- test/{e2e.js => distributed.js} | 8 +- test/holy/grail.js | 177 ++++++++++++++++++++++++++++++++ test/holy/gun-server.js | 16 +++ test/holy/index.html | 27 +++++ test/holy/ports.json | 4 + test/ptsd/perf.js | 2 + test/ptsd/ptsd.html | 2 +- 10 files changed, 343 insertions(+), 79 deletions(-) rename test/{e2e.js => distributed.js} (93%) create mode 100644 test/holy/grail.js create mode 100644 test/holy/gun-server.js create mode 100644 test/holy/index.html create mode 100644 test/holy/ports.json diff --git a/gun.js b/gun.js index 59b5726f..e838ba9c 100644 --- a/gun.js +++ b/gun.js @@ -176,7 +176,8 @@ function noop(){}; function Event(tag, arg, at, as, skip){ var ctx = this, ons = ctx.ons || (ctx.ons = {}), on = ons[tag] || (ons[tag] = {s: []}), act, mem; - /*if(!arg && 1 === arguments.length){ + //typeof console !== 'undefined' && console.debug(102, 'on', tag, arg, 'ons', ctx, ons); + /*if(!arg && 1 === arguments.length){ // Performance drops significantly even though `arguments.length` should be okay to use. return on.s; }*/ if(arg instanceof Function){ @@ -188,7 +189,7 @@ return; }*/ } - return; + return act; } if(emit){ emit(tag, arg, on, ctx) } on.arg = arg; @@ -226,9 +227,9 @@ } } on.s = still; - if(0 === still.length){ - delete ons[tag]; - } + //if(0 === still.length){ // TODO: BUG! If we clean up the events themselves when no longer needed by deleting this code, it causes some tests to fail. + // delete ons[tag]; + //} } if(!gap && at && at instanceof Function){ at.call(as, arg); @@ -237,7 +238,9 @@ } exports.on = Event; }(Util, function add(tag, act, on, ctx){ // Gun specific extensions - var mem = on.mem, at; + var mem = on.mem; + typeof console !== 'undefined' && console.debug(9, 'ON', tag, mem); + typeof console !== 'undefined' && console.debug(10, 'SO! The problem is that subsequent event listeners trigger lazy again, but the should queue for the results of the one already trying to finish or else you will get wrong results.'); if(mem){ if(mem instanceof Array){ act.fn.apply(act.at, mem.concat(act)); @@ -246,11 +249,10 @@ } return; } - at = act.at? act.at.gun? act.at : ctx : ctx; - if(!at.lex || !at.lex.soul){ return } // TODO: What about lex cursors? - console.debug(16, 'on', tag, mem); - console.debug(3, 'on', tag, mem); - Gun.get(at); + if(!ctx.lazy){ return } + var at = act.at? act.at.gun? act.at : ctx : ctx; + if(!at.gun){ return } + ctx.lazy(at, tag); //if(on.mem){ add(tag, act, on, ctx) } // for synchronous async actions. }, function(tag, arg, on, at){ on.mem = arg; @@ -606,8 +608,7 @@ is_graph(at.graph, map, null, at); }); function map(node, soul){ - console.debug(12, 'put to get', soul); - console.debug(9, 'put to get', soul); + //Gun.get.got.call(this, null, node); Gun.get.got.call(this.gun.__.gun.get(soul)._, null, node); } }()); @@ -626,20 +627,21 @@ stream: cb } } - console.debug(4, 'GET', at); + console.debug(5, 'GET', at.lex); Gun.on('get', at); // TODO: What is the cleanest way to reply if there is no responses, without assuming drivers do reply or not? return at.gun; } Gun.get.got = got; - function got(err, node){ + function got(err, node){ var at = this; if(err){ Gun.log(err) } - console.debug(105, 'GOT', err, node); - console.debug(5, 'GOT', err, node); - Gun.on('stream', Gun.obj.to(this, {err: err, change: node}), stream); + if(!at.stream){ var soul; + if(!node && !at.lex.soul){ return } + at = at.gun.__.gun.get(is_node_soul(node) || at.lex.soul)._; + } + Gun.on('stream', Gun.obj.to(at, {err: err, change: node}), stream); } function stream(at){ - if(!at.stream){ console.log("WARNING! No at.get", at); } - console.debug(6, 'STREAM', at); + if(!at.stream){ console.log("WARNING! No at.stream", at); } at.stream(at.err, at.change); } }()); @@ -649,6 +651,7 @@ if(opt.force){ return } var lex = at.lex, gun = at.gun, graph = gun.__.graph, node = graph[lex.soul]; if(opt.memory || node){ return at.cb(null, node), ev.stun() } + console.debug(6, 'not in memory'); }); Gun.on('stream', function(at, ev){ var node; @@ -667,8 +670,8 @@ if(get && get[soul] && !get[soul]._.node){ get[soul]._.node = __.graph[soul]; } - }); - */ + });*/ + Gun.on('stream', function(at){ var lex = at.lex, soul = lex.soul, field = lex.field; var gun = at.gun, graph = gun.__.graph, node = graph[soul], u; @@ -840,12 +843,13 @@ put.any = cb; put.data = data; put.state = (opt.state || opts.state)(); + console.debug(3, 'put put', data); at.on('chain', link, at); // TODO: ONE? return gun; }; function link(cat, ev){ ev.off(); // TODO: BUG! + console.log(8, 'putting', cat); var at = this, put = at.put, data, cb; - console.debug(7, 'putting', at, cat.gun === at.gun, cat); if(cat.err){ return } if(!cat.node && (put.opt.init || cat.gun.__.opt.init)){ return } // TODO: BUG! `at` doesn't have correct backwards data! @@ -858,9 +862,9 @@ ev.stun(); //put.resume = ev.stun(put.resume); Gun.ify(data, end, { - node: function(env, cb){ var eat = env.at; + node: function(env, cb){ var eat = env.at, tmp; if(1 === eat.path.length && cat.node){ - eat.soul = is_rel(cat.node[eat.path[0]]); // TODO: BUG! Need to handle paths that aren't loaded yet. + eat.soul = (tmp = is_rel(at.value))? tmp : is_rel(cat.node[eat.path[0]]); // TODO: BUG! Need to handle paths that aren't loaded yet. } cb(env, eat); }, value: function(env){ var eat = env.at; @@ -892,11 +896,9 @@ Gun.on('normalize', Gun.obj.to(at, {err: err, graph: env.graph, env: env}), wire); } function wire(at){ - console.debug(8, 'pat', at); Gun.put(Gun.obj.to(at, {cb: ack})); } function ack(err, ok){ var at = this, cb; - console.debug(14, 'ack', err, ok); if((cb = at.put.any) && cb instanceof Function){ cb.call(at.gun, err, ok); } @@ -925,16 +927,23 @@ } Gun.on('chain', function(cat, e){ if(!is_node_soul(cat.node, 'key')){ return } - var resume = e.stun(1), node = cat.node, pseudo = cat.gun._.pseudo || (cat.gun._.pseudo = cat.gun._.node = is_node_ify({}, is_node_soul(node))); + var resume = e.stun(1), node = cat.change, field = cat.lex.field, pseudo = cat.gun._.pseudo || (cat.gun._.pseudo = cat.gun._.node = is_node_ify({}, is_node_soul(cat.node))); pseudo._.key = 'pseudo'; cat.seen = cat.seen || {}; // TODO: There is a better way. + 'hello/world' === is_node_soul(node) && console.log("scan", node); is_node(node, function(n, f){ // TODO: PERF! BAD! Filter out items we've already seen. if(cat.seen[f]){ return } cat.seen[f] = true; // TODO: There is a better way. - cat.gun.get(Gun.obj.to(cat.lex, {soul: f}), on); - function on(err, node){ + //cat.gun.__.gun.get(Gun.obj.to(cat.lex, {soul: f}), on); + if(field){ + cat.gun.__.gun.get(f).path(field, on); + } else { + cat.gun.__.gun.get(f, on); + } + function on(err, node, field, at){ if(!node){ return } HAM_node(pseudo, node); cat.node = pseudo; + cat.change = at.change; resume(); } }); @@ -966,17 +975,10 @@ if(!opt || !opt.path){ var back = this.__.gun; } // TODO: CHANGING API! Remove this line! var gun, back = back || this; var get = back._.get || (back._.get = {}), tmp; + console.debug(2, 'get', lex); if(typeof lex === 'string'){ if(!(gun = get[lex])){ gun = cache(get, lex, back); - console.debug(15, 'get', lex, get, 'and the', gun); - console.debug(2, 'get', lex); - if((tmp = gun._.lex).field){ - /*if(!back._.ons.chain || !back._.ons.chain.s.length){ // TODO: CLEAN UP! // TODO: ONE? - back._.on('chain', link, gun._); - }*/ - back._.on('field:' + tmp.field, field, gun._); // TODO: ONE? - } } } else if(!lex && 0 != lex){ // TODO: BUG!? @@ -990,7 +992,7 @@ if(tmp = lex.soul){ if(lex.field){ gun = back.chain(); - gun._.stream = cb; + //gun._.stream = cb; gun._.lex = lex; Gun.get(gun._); return gun; @@ -1000,59 +1002,82 @@ } } else if(tmp = lex[_soul]){ - if(lex[_field]){ - return back.get({soul: tmp, field: lex[_field]}, cb, opt); - } if(!(gun = get[tmp])){ gun = cache(get, tmp, back); } + if(tmp = lex[_field]){ + return gun.path(tmp, cb, opt); + } } + console.debug(7, 'get', lex); if(cb && cb instanceof Function){ - gun._.on('any', pop(cb), gun); // TODO: Perf! Batch! // TODO: API CHANGE? Having to use pop is annoying. Should we support NodeJS style callbacks anymore? + //gun._.on('any', pop(cb), gun); // TODO: Perf! Batch! // TODO: API CHANGE? Having to use pop is annoying. Should we support NodeJS style callbacks anymore? + console.debug(8, 'getting'); + gun._.on('any', cb, gun); // TODO: Perf! Batch! // TODO: API CHANGE? Having to use pop is annoying. Should we support NodeJS style callbacks anymore? } return gun; } function cache(get, key, back){ var gun = get[key] = back.chain(), at = gun._; - at.stream = stream; + at.lazy = lazy; if(!back.back){ + at.stream = stream; at.lex.soul = key; } else { - var lex = at.lex, flex = back._.lex; + var lex = at.lex, cat = back._, flex = cat.lex; lex.field = key; if(!flex.field && flex.soul){ lex.soul = flex.soul; } + back._.on('field:' + key, field, at); } return gun; } - function stream(err, node){ - console.debug(10, 'stream', err, node); - Gun.on('chain', this); - //Gun.on('chain', this, link, this); - } - Gun.on('chain', link); - function link(cat, ev){ var at = cat.gun._, u; - var err = cat.err, node = cat.node, cex = cat.lex, lex = at.lex, field = lex.field, rel, val; - console.debug(13, 'link', at, cat); - console.debug(11, 'link', at, cat); - if(lex !== cex && lex.field && cex.field){ - if(obj_has(node, cex.field) && (rel = is_rel(val = node[cex.field]))){ - return Gun.get(Gun.obj.to(at, {lex: {soul: rel, field: lex.field}})); + function lazy(at){ var cat = this; + if(at.path && at.path.wait){ return } // means we're being lazy again. + console.debug(4, 'lazy', at); + var lex = at.lex; + if(!lex.soul){ + if(!(lex.soul = is_rel(cat.value))){ + return; // TODO: BUG! Handle async case. } } - console.debug(17, 'link', at, cat); - at.on('any', [err, (field && node)? node[field] : node, field, cat]); // TODO: Revisit! + Gun.get(at); + }; + function stream(err, node){ + //Gun.on('chain', this); + Gun.on('chain', this, link, this); + } + //Gun.on('chain', link); + function link(cat, ev){ var at = this, u; + //at.value = cat.value = cat.node; + var err = cat.err, node = cat.node, cex = cat.lex, lex = at.lex, field = lex.field, rel, val; + if(at.path && is_node_soul(node) === at.path.rel){ field = u } + at.on('any', [err, (field && node)? node[field] : node, lex.field, cat]) // TODO: Revisit! if(err){ at.on('err', err) } - if(node){ at.on('ok', [(field && node)? node[field] : node, field, cat]) } // TODO: Revisit! - is_node(at.change, map, {cat: cat, at: at}); + if(node){ at.on('ok', [(field && node)? node[field] : node, lex.field, cat]) } // TODO: Revisit! at.on('chain', cat); + if(at.path && field){ return } + is_node(cat.change, map, {cat: cat, at: at}) || obj_map(at.get, map, {cat: cat, at: at}); // TODO: Cleaner way? Necessary to pass error/nots down the chain for implicit puts. } function map(val, field){ - this.cat.on('field:' + field, this.cat); + this.at.on('field:' + field, this.cat); } function field(cat, ev){ var at = this; - at.on('chain', Gun.obj.to(at, {err: cat.err, change: cat.change})); + var node = cat.node, lex, field, rel; + if(!at.path){ at.path = {} } + if(!node){ return link.call(at, cat, ev) } // TODO: Errors and nots? + (lex = at.lex).soul = is_node_soul(node); + if(at.value === node[field = lex.field] && obj_has(at, 'value')){ return } + if(at.path.ev){ at.path.ev.off() } + at.value = node[field]; + if(rel = at.path.rel = is_rel(at.value)){ + at.path.wait = true; + at.path.ev = at.gun.__.gun.get(rel)._.on('chain', link, at); + at.path.wait = false; + return; + } + link.call(at, cat, ev); } }()); Gun.chain.path = function(field, cb, opt){ @@ -1160,10 +1185,12 @@ ;(function(){ function get(err, data, at){ if(!data && !Gun.obj.empty(at.opt.peers)){ return } // let the peers handle no data. + console.log("ouch"); at.cb(err, data); // node } Gun.on('get', function(at){ var opt = at.opt, lex = at.lex; + console.debug(7, 'get ASYNC'); Tab.store.get((opt.prefix || '') + lex.soul, get, at); }); }()); @@ -1303,10 +1330,10 @@ ;(function(exports){ var u; function s(){} s.put = function(key, val, cb){ try{ store.setItem(key, Gun.text.ify(val));if(cb)cb(null) }catch(e){if(cb)cb(e)} } - s.get = function(key, cb, t){ //setTimeout(function(){ + s.get = function(key, cb, t){ setTimeout(function(){ try{ cb(null, Gun.obj.ify(store.getItem(key) || null), t); }catch(e){ cb(e,u,t)} - }//,1) } + },1) } s.del = function(key){ return store.removeItem(key) } var store = window.localStorage || {setItem: function(){}, removeItem: function(){}, getItem: function(){}}; exports.store = s; diff --git a/package.json b/package.json index bc69e016..6047760c 100644 --- a/package.json +++ b/package.json @@ -49,7 +49,7 @@ }, "devDependencies": { "mocha": "~>1.9.0", - "panic-server": "~>0.2.4", + "panic-server": "~>0.3.0", "selenium-webdriver": "~>2.53.2" } } diff --git a/test/common.js b/test/common.js index 362710a4..d74a2e10 100644 --- a/test/common.js +++ b/test/common.js @@ -1352,9 +1352,11 @@ describe('Gun', function(){ }); }); - it('put node with soul get soul', function(done){ + it.only('put node with soul get soul', function(done){ + Gun.log.debug=1;console.log("--------------------------"); gun.put({_: {'#': 'foo'}, hello: 'world'}) .get({'#': 'foo'}, function(err, node){ + console.log("huh?", err, node); expect(err).to.not.be.ok(); expect(Gun.is.node.soul(node)).to.be('foo'); expect(node.hello).to.be('world'); @@ -1583,15 +1585,14 @@ describe('Gun', function(){ it('put node path path', function(done){ var gun = Gun(); - Gun.log.debug=1;console.log("----------------------------------"); - gun.put({hello: {little: 'world'}}).path('hello').path('little', function(err, val, field){ + var g = gun.put({hello: {little: 'world'}}).path('hello').path('little', function(err, val, field){ if(done.end){ return } // it is okay for path's callback to be called multiple times. expect(err).to.not.be.ok(); expect(field).to.be('little'); expect(val).to.be('world'); done(); done.end = true; }); - });return; + }); it('put node path rel', function(done){ gun.put({foo: {bar: 'lol'}}).path('foo', function(err, val, field){ @@ -1617,8 +1618,9 @@ describe('Gun', function(){ var gun = Gun(); gun.put({_:{'#': 'soul/field'}, hi: 'lol', foo: 'bar'});//.key('key/field'); gun.get({'#': 'soul/field', '.': 'hi'}, function(err, val){ - expect(val.hi).to.be('lol'); - expect(Gun.obj.has(val,'foo')).to.not.be.ok(); + //expect(val.hi).to.be('lol'); // TODO: REVISE API? + expect(val).to.be('lol'); + //expect(Gun.obj.has(val,'foo')).to.not.be.ok(); done(); }) }); @@ -1767,7 +1769,7 @@ describe('Gun', function(){ expect(val).to.be('are'); expect(field).to.be('you'); done(); - }) + }); }); it('get node path put object merge isolated', function(done){ @@ -1778,6 +1780,8 @@ describe('Gun', function(){ var puthi = get.put({hi: 'you'}); puthi.on(function(node){ if(done.hi){ return } + //console.log(1, node); + expect(node.hello).to.be('key'); expect(node.hi).to.be('you'); done.hi = 1; }); @@ -1787,8 +1791,11 @@ describe('Gun', function(){ path2._.id = 'path2'; var putyay = path2.put({yay: "value"}); putyay.on(function(node, field){ + if(done.yay){ return } + //console.log(2, field, node); expect(field).to.be('hi'); expect(node.yay).to.be('value'); + done.yay = true; }); setTimeout(function(){ var get3 = gun.get('hello/key/iso'); @@ -1796,9 +1803,10 @@ describe('Gun', function(){ path3._.id = 'path3'; var puthappy = path3.put({happy: "faces"}); puthappy.on(function(node, field){ + //console.log(3, field, node); expect(field).to.be('hi'); - expect(node.yay).to.be('value'); expect(node.happy).to.be('faces'); + expect(node.yay).to.be('value'); setTimeout(function(){ done(); },200); @@ -1931,6 +1939,7 @@ describe('Gun', function(){ }); it('get put path', function(done){ + Gun.log.debug=1;console.log("-------------------------"); gun.get('hello/world').put({hello: 'Mark'}).path('hello').val(function(val, field){ console.log("WAT?", field, val); expect(val).to.be('Mark'); diff --git a/test/e2e.js b/test/distributed.js similarity index 93% rename from test/e2e.js rename to test/distributed.js index f264f37d..a62a876c 100644 --- a/test/e2e.js +++ b/test/distributed.js @@ -1,3 +1,5 @@ +require('./holy/grail'); + describe('PANIC!', function(){ this.timeout(1000 * 100); @@ -35,7 +37,7 @@ describe('PANIC!', function(){ function min(n, done, list){ list = list || clients; function ready() { - if (list.len() >= n) { + if (list.length >= n) { done(); list.removeListener('add', ready); return true; @@ -46,7 +48,7 @@ describe('PANIC!', function(){ } } - function gunify(ctx, done){ + function gunify(done, ctx){ var s = document.createElement('script'); s.src = 'gun.js'; s.onload = done; @@ -69,7 +71,7 @@ describe('PANIC!', function(){ var sync = gun.get('sync'); sync.put({hello: 'world'}) }).then(function(){ - return bob.run(function(ctx, done){ + return bob.run(function(done, ctx){ var sync = gun.get('sync'); sync.on(function(val){ if(val.hello === 'world'){ diff --git a/test/holy/grail.js b/test/holy/grail.js new file mode 100644 index 00000000..eb49f46f --- /dev/null +++ b/test/holy/grail.js @@ -0,0 +1,177 @@ +/* + This file should be one + folder deeper than every + other file. It requires + mocha to run. +*/ +var panic = require('panic-server'); +var spawn = require('child_process').spawn; +var path = require('path'); +var http = require('http'); +var fs = require('fs'); +var ports = require('./ports'); + +var wd = require('selenium-webdriver'); + +function open(url) { + var driver = new wd.Builder() + .forBrowser('firefox') + .build(); + + driver.get(url); + + return driver; +} + +open('http://localhost:' + ports.panic + '/index.html'); +open('http://localhost:' + ports.panic + '/index.html'); + +var staticServer = new http.Server(function (req, res) { + if (req.url === '/') { + req.url = '/index.html'; + } + var file = path.join(__dirname, req.url); + try { + var page = fs.readFileSync(file, 'utf8'); + res.end(page); + } catch (e) { + // don't care + } +}); + +var server = panic.clients.filter('Node.js').pluck(1); +var browsers = panic.clients.excluding(server); + +var alice = browsers.pluck(1); +var bob = browsers.excluding(alice).pluck(1); + +var serverPath = path.join(__dirname, 'gun-server.js'); + +// start the server on :8080 +spawn('node', [serverPath]); + +function waitFor (num, list) { + return new Promise(function (res) { + + function ready() { + if (list.length < num) { + return; + } + + res(); + list.removeListener('add', ready); + + return true; + } + + if (!ready()) { + list.on('add', ready); + } + + }); +} + +before(function () { + + this.timeout(1500000); + + // start the panic server + panic.server(staticServer).listen(ports.panic); + + return waitFor(2, browsers) + .then(function () { + return waitFor(1, server); + }); +}); + +var scope = { + uniqueKey: Math.random().toString(16).slice(2), + file: path.join(process.cwd(), 'delete-me.json'), + '@scope': true +} + +describe('The holy grail', function () { + + it('should allow full recovery', function () { + this.timeout(1500000); + + return browsers.run(function () { + localStorage.clear(); + }) + .then(function () { + return browsers.run(function () { + window.ref = gun.get(uniqueKey).put({ + text: 'ignore' + }); + }, scope) + }) + .then(function () { + return alice.run(function (done) { + // alice saves some data + //ref.path('text').put('Initial text', done); // TODO: USE THIS LINE INSTEAD! + ref.path('text').put('Initial text'); + setTimeout(done, 50); + }); + }) + .then(function () { + return bob.run(function (done) { + var ctx = this; + ref.path('text').on(function (data) { + if (data === 'ignore') { + return; + } + // bob sees alice's data + if (data !== 'Initial text') { + ctx.fail('Wrong data showed up: ' + JSON.stringify(data)); + } + done(); + }); + }); + }) + .then(function () { + return server.run(function () { + var fs = require('fs'); + + // destroy the data + fs.unlinkSync(file); + + // crash the server + process.exit(0); + }, scope); + }) + .then(function () { + return alice.run(function (done) { + ref.path('text').put('A conflicting update'); + setTimeout(done, 50); + }); + }) + .then(function () { + return bob.run(function () { + ref.path('text').put('B conflicting update'); + }); + }) + .then(function () { + spawn('node', [serverPath]); + return waitFor(1, server); + }) + .then(function () { + return browsers.run(function (done) { + var ctx = this; + ref.path('text').on(function (value) { + if (value === 'B conflicting update') { + done(); + } + }); + }); + }); + }); +}); + + +after(function () { + if (server.length) { + return server.run(function () { + process.exit(0); + }); + } +}); \ No newline at end of file diff --git a/test/holy/gun-server.js b/test/holy/gun-server.js new file mode 100644 index 00000000..c5191916 --- /dev/null +++ b/test/holy/gun-server.js @@ -0,0 +1,16 @@ +var panic = require('panic-client'); +var ports = require('./ports'); +var Gun = require('gun'); +var gun = new Gun({ + file: 'delete-me.json' +}); + +var http = require('http'); + +var server = new http.Server(gun.wsp.server); + +gun.wsp(server); + +server.listen(ports.gun); + +panic.server('http://localhost:' + ports.panic); \ No newline at end of file diff --git a/test/holy/index.html b/test/holy/index.html new file mode 100644 index 00000000..5a8a87bb --- /dev/null +++ b/test/holy/index.html @@ -0,0 +1,27 @@ + + + + + + Holy grail demo + + + + + + + + \ No newline at end of file diff --git a/test/holy/ports.json b/test/holy/ports.json new file mode 100644 index 00000000..1e36ca3f --- /dev/null +++ b/test/holy/ports.json @@ -0,0 +1,4 @@ +{ + "panic": 3000, + "gun": 8080 +} \ No newline at end of file diff --git a/test/ptsd/perf.js b/test/ptsd/perf.js index 46529b35..ab0fb1a8 100644 --- a/test/ptsd/perf.js +++ b/test/ptsd/perf.js @@ -1978,11 +1978,13 @@ var hewo = {hello: "world"}; window.puti = window.puti || 0; window.geti = window.geti || 0; + /* localStorage.clear(); gun.get('users').put({1: {where: {lat: Math.random(), lng: Math.random(), i: 1}}}); //var ok = function(a,b){ console.log('wat', a,b) } //Gun.log.debug=1;console.log("------------------"); var val = gun.get('users').path(1).path('where').val(ok); + */ }); //localStorage.clear(); /* diff --git a/test/ptsd/ptsd.html b/test/ptsd/ptsd.html index 33df212e..affadedc 100644 --- a/test/ptsd/ptsd.html +++ b/test/ptsd/ptsd.html @@ -27,7 +27,7 @@ - +