mirror of
https://github.com/amark/gun.git
synced 2025-03-30 15:08:33 +00:00
fix Jesse's synchronous Trace bug
This commit is contained in:
parent
7dee2d8b92
commit
272935630b
@ -4,4 +4,7 @@ node_js:
|
||||
- 0.8
|
||||
- 0.10
|
||||
- 0.11
|
||||
- 0.12
|
||||
- 0.12
|
||||
- 4.0
|
||||
- 4.2
|
||||
- 5.0
|
48
gun.js
48
gun.js
@ -478,7 +478,6 @@
|
||||
opt = opt || {};
|
||||
if(!Gun.text.is(path = Gun.text.is(path)? path || null : Gun.num.is(path)? (path + '') : Gun.list.is(path)? path.join('.') : path)){ return cb.call(gun, {err: Gun.log("Invalid path '" + path + "'!")}), gun }
|
||||
if(!gun.back._.at){ return cb.call(gun, {err: Gun.log("No context!")}), gun }
|
||||
|
||||
gun.back.on(function($, node){
|
||||
if(!(node = node || gun.__.graph[$.soul])){ return }
|
||||
var chain = this || gun, src = opt.src || gun;
|
||||
@ -500,11 +499,11 @@
|
||||
if(soul){
|
||||
return gun.get(val, function(err, data){
|
||||
if(err){ return cb.call(chain, err) }
|
||||
}).path(ctx.path, cb, {src: src, step: {soul: $.soul, field: field}});
|
||||
}).path(ctx.path, cb, {src: src, step: {soul: $.soul, field: field}, path: path});
|
||||
}
|
||||
cb.call(chain, null, val, field);
|
||||
return src._.at('soul').emit({soul: $.soul, field: field, gun: chain, PATH: 'SOUL'});
|
||||
}, {raw: true, once: true});
|
||||
}, {raw: true});
|
||||
|
||||
return gun;
|
||||
}
|
||||
@ -520,29 +519,38 @@
|
||||
opt = opt || {};
|
||||
|
||||
gun.on(function($, delta, on){
|
||||
var node = gun.__.graph[$.soul], hash = $.soul + ($.field || '');
|
||||
if(!$.soul || !node || ctx[hash + '.end']){ return }
|
||||
var node = gun.__.graph[$.soul];
|
||||
if(ctx[$.soul + '.end']){ return ctx[$.soul + '.end'](node, $) }
|
||||
//(on = on || {off:function(){}}).off();
|
||||
ctx[hash + '.end'] = function(data){
|
||||
if(data && $.soul != Gun.is.soul.on(data)){ return }
|
||||
var node = gun.__.graph[$.soul] || node; //on = (this || {off:function(){}}); // TODO: BUG? is var node = thing || node safe in old IE?
|
||||
if($.key){
|
||||
ctx[$.soul + '.end'] = function(data, $$){
|
||||
$$ = $$ || $;
|
||||
var soul, field;
|
||||
if(!$$.field && $$.from){ // if the current node is a child of the parent that we were subscribing to a field on.
|
||||
soul = $$.from;
|
||||
field = $$.at;
|
||||
} else {
|
||||
soul = $$.soul;
|
||||
field = $$.field || '';
|
||||
}
|
||||
var hash = soul + field;
|
||||
var node = gun.__.graph[$$.soul] || data || node; //on = (this || {off:function(){}}); // TODO: BUG? is var node = thing || node safe in old IE?
|
||||
if($$.key){
|
||||
// TODO: BUG! Shouldn't `.val` pseudo union check that each node in the key graph is ended? Current thought: Not necessarily! Since `.val` is first come first serve until we provide configurable end options.
|
||||
node = Gun.union.pseudo($.key, gun.__.key.s[$.key]) || node;
|
||||
}
|
||||
if($.field){
|
||||
if(!Gun.obj.has(node, $.field) || ctx[hash] || Gun.is.soul(node[$.field])){ return }
|
||||
if($$.field){
|
||||
if(!Gun.obj.has(node, $$.field) || ctx[hash] || Gun.is.soul(node[$$.field])){ return }
|
||||
ctx[hash] = true; //on.off(); // TODO: Fix the bug with at for this to be on.
|
||||
return cb.call($.gun || gun, node[$.field], $.field || $.at);
|
||||
return cb.call($$.gun || gun, node[$$.field], $$.field);
|
||||
}
|
||||
if(!gun.__.meta($.soul).end || (ctx[$.soul] || ($.key && ctx[$.key]))){ return } // TODO: Add opt to change number of terminations.
|
||||
ctx[$.soul] = ctx[$.key] = true; //on.off(); // TODO: Fix the bug with at for this to be on.
|
||||
cb.call($.gun || gun, Gun.obj.copy(node), $.field || $.at);
|
||||
if(!gun.__.meta($$.soul).end || (ctx[hash] || ($$.key && ctx[$$.key]))){ return } // TODO: Add opt to change number of terminations.
|
||||
ctx[hash] = ctx[$$.soul] = ctx[$$.key] = true; //on.off(); // TODO: Fix the bug with at for this to be on.
|
||||
cb.call($$.gun || gun, Gun.obj.copy(node), field);
|
||||
}
|
||||
if(gun.__.meta($.soul).end){
|
||||
if(!$.field || Gun.obj.has(node, $.field)){ return ctx[hash + '.end']() }
|
||||
if(!$.field || Gun.obj.has(node, $.field)){ return ctx[$.soul + '.end'](node, $) }
|
||||
}
|
||||
gun.__.on($.soul + '.end').event(ctx[hash + '.end']);
|
||||
gun.__.on($.soul + '.end').event(ctx[$.soul + '.end']);
|
||||
}, {raw: true});
|
||||
|
||||
return gun;
|
||||
@ -604,9 +612,13 @@
|
||||
}
|
||||
if(gun.back.not){ gun.back.not(call, {raw: true}) }
|
||||
|
||||
gun.back._.at('soul').event(function($){ // TODO: maybe once per soul?
|
||||
gun.back._.at('soul').event(function($){
|
||||
var chain = $.gun || gun;
|
||||
var ctx = {}, obj = val, $ = Gun.obj.copy($);
|
||||
var hash = $.field? $.soul + $.field : ($.from? $.from + ($.at || '') : $.soul);
|
||||
//var hash = $.from? ($.from + ($.at || '')) : ($.soul + ($.field || ''));
|
||||
if(call[hash]){ return }
|
||||
call[hash] = true;
|
||||
console.log("chain.put", val, '\n');
|
||||
if(Gun.is.value(obj)){
|
||||
if($.from && $.at){
|
||||
|
@ -1,6 +1,6 @@
|
||||
{
|
||||
"name": "gun",
|
||||
"version": "0.2.4",
|
||||
"version": "0.2.5",
|
||||
"description": "Graph engine",
|
||||
"main": "index.js",
|
||||
"scripts": {
|
||||
@ -12,6 +12,8 @@
|
||||
"url": "git+https://github.com/amark/gun.git"
|
||||
},
|
||||
"keywords": [
|
||||
"gun",
|
||||
"gunDB",
|
||||
"graph",
|
||||
"document",
|
||||
"key",
|
||||
@ -23,9 +25,9 @@
|
||||
"realtime",
|
||||
"decentralized",
|
||||
"peer-to-peer",
|
||||
"distributed",
|
||||
"P2P",
|
||||
"OSS",
|
||||
"distributed",
|
||||
"embedded",
|
||||
"localstorage",
|
||||
"S3"
|
||||
@ -48,4 +50,4 @@
|
||||
"devDependencies": {
|
||||
"mocha": "~>1.9.0"
|
||||
}
|
||||
}
|
||||
}
|
131
test/common.js
131
test/common.js
@ -1005,9 +1005,10 @@ describe('Gun', function(){
|
||||
|
||||
it('get node path', function(done){
|
||||
gun.get('hello/key').path('hi', function(err, val){
|
||||
if(done.end){ return } // it is okay for path's callback to be called multiple times.
|
||||
expect(err).to.not.be.ok();
|
||||
expect(val).to.be('overwritten');
|
||||
done();
|
||||
done(); done.end = true;
|
||||
});
|
||||
});
|
||||
|
||||
@ -1215,6 +1216,20 @@ describe('Gun', function(){
|
||||
});
|
||||
});
|
||||
|
||||
it('Gun get put null', function(done){ // flip flop bug
|
||||
var gun = Gun();
|
||||
gun.put({last: {some: 'object'}}).path('last').val(function(val, field){
|
||||
done.some = true;
|
||||
//console.log("*******************************", field, val);
|
||||
expect(val.some).to.be('object');
|
||||
}).put(null).val(function(val, field){
|
||||
//console.log("***************null****************", field, val);
|
||||
expect(val).to.be(null);
|
||||
expect(done.some).to.be.ok();
|
||||
done();
|
||||
});
|
||||
});
|
||||
|
||||
it('var put key path', function(done){ // contexts should be able to be saved to a variable
|
||||
var foo = gun.put({foo: 'bar'}).key('foo/bar');
|
||||
foo.path('hello.world.nowhere'); // this should become a sub-context, that doesn't alter the original
|
||||
@ -1430,7 +1445,7 @@ describe('Gun', function(){
|
||||
gun.put({gender:'f', age:22, name:'beth' }).key('user/beth');
|
||||
gun.get('user/alfred').val(function(a){
|
||||
gun.get('user/beth').path('friend').put(a); // b - friend_of -> a
|
||||
gun.get('user/beth').val(function(b){ // TODO: We should have b.friend by now!
|
||||
gun.get('user/beth').val(function(b){
|
||||
gun.get('user/alfred').path('friend').put(b).val(function(beth){ // a - friend_of -> b
|
||||
gun.get('user/beth').path('cat').put({name: "fluffy", age: 3, coat: "tabby"}).val(function(cat){
|
||||
|
||||
@ -1584,7 +1599,7 @@ describe('Gun', function(){
|
||||
var gun = Gun();
|
||||
gun.get('set').set().set().val(function(val){
|
||||
done.c += 1;
|
||||
expect(Gun.obj.empty(val, '_')).to.be.ok();
|
||||
expect(Gun.obj.empty(val, Gun._.meta)).to.be.ok();
|
||||
setTimeout(function(){
|
||||
expect(done.c).to.be(1);
|
||||
done()
|
||||
@ -1592,11 +1607,11 @@ describe('Gun', function(){
|
||||
});
|
||||
});
|
||||
|
||||
it('set multiple', function(done){
|
||||
it('set multiple', function(done){ // kinda related to flip flop?
|
||||
var gun = Gun().get('sets').set(), i = 0;
|
||||
gun.val(function(val){
|
||||
expect(done.soul = Gun.is.soul.on(val)).to.be.ok();
|
||||
expect(Gun.obj.empty(val, '_')).to.be.ok();
|
||||
expect(Gun.obj.empty(val, Gun._.meta)).to.be.ok();
|
||||
});
|
||||
|
||||
gun.set(1).set(2).set(3).set(4); // if you set an object you'd have to do a `.back`
|
||||
@ -1662,7 +1677,7 @@ describe('Gun', function(){
|
||||
gun.put({b: 2, z: 0}).key('pseudon');
|
||||
|
||||
gun.get('pseudon').on(function(val){
|
||||
if(done.val){ return } // TODO: Maybe prevent repeat ons where there is no diff?
|
||||
if(done.val){ return } // TODO: Maybe prevent repeat ons where there is no diff? (may not happen to after 1.0.0)
|
||||
done.val = val;
|
||||
expect(val.a).to.be(1);
|
||||
expect(val.b).to.be(2);
|
||||
@ -1851,6 +1866,32 @@ describe('Gun', function(){
|
||||
})
|
||||
});
|
||||
|
||||
/* // TODO: BUG! BAD! THIS IS AN ACTIVE BUG THAT NEEDS TO BE FIXED!!!!
|
||||
it('gun get put, sub path put, original val', function(done){ // bug from Jesse working on Trace
|
||||
var gun = Gun().get('players');
|
||||
|
||||
gun.put({
|
||||
taken: true,
|
||||
history: {0: {}, 1: {}}
|
||||
});
|
||||
|
||||
gun
|
||||
.path('history')
|
||||
.put(null)
|
||||
.back
|
||||
.path('taken')
|
||||
.put(false)
|
||||
|
||||
// TODO: BUG! There is a variation of this, where we just do `.val` rather than `gun.val` and `.val` by itself (chained off of the sub-paths) doesn't even get called. :(
|
||||
gun.val(function(players){ // this val is subscribed to the original put and therefore does not get any of the sub-path listeners, therefore it gets called EARLY with the original/old data rather than waiting for the sub-path data to "finish" and then get called.
|
||||
console.log("LOOK HERE!!!!", players);
|
||||
expect(players.taken).to.be(false);
|
||||
expect(players.history).to.be(null);
|
||||
done();
|
||||
});
|
||||
|
||||
});
|
||||
*/
|
||||
it("gun get empty set, path not -> this put", function(done){ // Issue #99 #101, bug in survey and trace game.
|
||||
var test = {c: 0}, u;
|
||||
var gun = Gun();
|
||||
@ -1919,10 +1960,11 @@ describe('Gun', function(){
|
||||
var game = gun.put({board: null, teamA: null, teamB: null, turn: null}).key('the/game');
|
||||
game.path('board').on(function(board, field){
|
||||
expect(field).to.be('board');
|
||||
if(done.c == 1){
|
||||
if(done.c === 1){
|
||||
expect(board).to.not.be.ok();
|
||||
}
|
||||
if(done.c === 2){
|
||||
if(!board[11] || !board[22] || !board[33]){ return }
|
||||
done.c++;
|
||||
delete board._;
|
||||
expect(board).to.be.eql({11: ' ', 22: ' ', 33: 'A'});
|
||||
@ -1935,7 +1977,66 @@ describe('Gun', function(){
|
||||
},100);
|
||||
});
|
||||
|
||||
it("gun get path empty val", function(done){
|
||||
it("get set put map -> put, foreach gun path map", function(done){ // replicate Jesse's Trace game bug
|
||||
done.c = 0;
|
||||
gun = Gun()
|
||||
.get('players').set()
|
||||
.put({
|
||||
0: {
|
||||
num: 0
|
||||
},
|
||||
1: {
|
||||
num: 1
|
||||
},
|
||||
2: {
|
||||
num: 2
|
||||
},
|
||||
3: {
|
||||
num: 3
|
||||
}
|
||||
}, function(err,ok){
|
||||
expect(done.c++).to.be(0);
|
||||
}).val(function(p){
|
||||
done.p = Gun.is.soul.on(p);
|
||||
done.m = Gun.is.soul(p[0]);
|
||||
expect(Gun.is.soul(p[0])).to.be.ok();
|
||||
expect(Gun.is.soul(p[1])).to.be.ok();
|
||||
expect(Gun.is.soul(p[2])).to.be.ok();
|
||||
expect(Gun.is.soul(p[3])).to.be.ok();
|
||||
})
|
||||
|
||||
var players = [], me;
|
||||
gun.map(function (player, number) {
|
||||
players[number] = player;
|
||||
players[number].history = [];
|
||||
if (!player.taken && !me) {
|
||||
this.put({
|
||||
taken: true,
|
||||
history: {
|
||||
0: {x: 1, y: 2}
|
||||
}
|
||||
}, function(err,ok){});
|
||||
me = number;
|
||||
}
|
||||
});
|
||||
|
||||
([0, 1, 2, 3]).forEach(function (player, number) {
|
||||
gun
|
||||
.path(number + '.history')
|
||||
.map(function (entry, logNum) {
|
||||
done.c++;
|
||||
players[number].history[logNum] = entry;
|
||||
expect(entry.x).to.be(1);
|
||||
expect(entry.y).to.be(2);
|
||||
setTimeout(function(){
|
||||
expect(done.c).to.be(2);
|
||||
done();
|
||||
},100);
|
||||
});
|
||||
});
|
||||
});
|
||||
|
||||
it("gun get path empty val", function(done){ // flip flop bug
|
||||
done.c = 0;
|
||||
var u;
|
||||
var gun = Gun();
|
||||
@ -1959,17 +2060,17 @@ describe('Gun', function(){
|
||||
done.c = 0;
|
||||
var u;
|
||||
var gun = Gun();
|
||||
var game = gun.get('game2/players').set();
|
||||
var game = gun.get('game2/players').set();
|
||||
var me = game.path('player2').on(function(val){
|
||||
if(!done.c){ done.fail = true }
|
||||
expect(done.fail).to.not.be.ok();
|
||||
expect(val).to.not.be(u);
|
||||
if(done.done || !val.x || !val.y){ return } // it is okay if ON gets called many times, this protects against that.
|
||||
// TODO: although it would be nice if we could minimize the amount of duplications. (may not happen to after 1.0.0)
|
||||
expect(val.x).to.be(1);
|
||||
expect(val.y).to.be(1);
|
||||
expect(done.fail).to.not.be.ok();
|
||||
if(done.c > 1){ return } // it is okay if ON gets called many times, this protects against that.
|
||||
// although it would be nice if we could minimize the amount of duplications.
|
||||
done.done = true;
|
||||
done();
|
||||
done.c++;
|
||||
});
|
||||
setTimeout(function(){
|
||||
done.c++;
|
||||
@ -1998,12 +2099,12 @@ describe('Gun', function(){
|
||||
done();
|
||||
})
|
||||
});
|
||||
});
|
||||
});
|
||||
|
||||
describe('Streams', function(){
|
||||
var gun = Gun(), g = function(){
|
||||
return Gun({hooks: {get: ctx.get}});
|
||||
}, ctx = {gen: 9, extra: 45, network: 2};
|
||||
}, ctx = {gen: 9, extra: 100, network: 2};
|
||||
|
||||
it('prep hook', function(done){
|
||||
this.timeout(ctx.gen * ctx.extra);
|
||||
|
@ -1,10 +1,10 @@
|
||||
WIRE PROTOCOL
|
||||
|
||||
save/set/create/put/post/delete/update/change/mutate
|
||||
put/save/set/create/post/delete/update/change/mutate
|
||||
|
||||
get/open/load/call/location/address
|
||||
|
||||
name/reference/key/index/point
|
||||
key/name/reference/index/point
|
||||
|
||||
|
||||
/gun {data: 'yay', #: "soul"}
|
||||
@ -37,7 +37,7 @@ Query formats are allowed as:
|
||||
Ex. "/users/?*=/&*>=a&*<=c" asks the peer to return users that start and end between 'a' and 'c',
|
||||
thus {"users/alice": {"#": "DSAF"}, "users/bob": {"#": "DAFS"}, "user/carl": {"#": "SAFD"}}
|
||||
# = ASDF
|
||||
pound means the peer should reply with the node that has this exact soul. There should be no key prefixed path on this type of request. A special case of "#=*" indicates to literally dump the entire graph, as is, to the client. Lexical carets are okay.
|
||||
pound means the peer should reply with a graph node that has this exact soul. There should be no key prefixed path on this type of request. A special case of "#=*" indicates to literally dump the entire graph, as is, to the client. Lexical carets are okay.
|
||||
% = 30
|
||||
percent means byte constraint requested by the peer asking for data.
|
||||
> = 1426007247399
|
||||
|
Loading…
x
Reference in New Issue
Block a user