diff --git a/lib/handlers.js b/lib/handlers.js index c00e6b0..57c7991 100755 --- a/lib/handlers.js +++ b/lib/handlers.js @@ -192,7 +192,8 @@ function traverser(recurse) { var results = []; - var descend = function(value, path) { + var descend = function(value, path, seen) { + seen = (seen || []).slice() if (is_array(value)) { value.forEach(function(element, index) { @@ -204,10 +205,15 @@ function traverser(recurse) { value.forEach(function(element, index) { if (results.length >= count) { return } if (recurse) { - descend(element, path.concat(index)); + descend(element, path.concat(index), seen); } }); } else if (is_object(value)) { + if (seen.indexOf(value) === -1) { + seen.push(value); + } else { + return; + } this.keys(value).forEach(function(k) { if (results.length >= count) { return } if (passable(k, value[k], ref)) { @@ -217,7 +223,7 @@ function traverser(recurse) { this.keys(value).forEach(function(k) { if (results.length >= count) { return } if (recurse) { - descend(value[k], path.concat(k)); + descend(value[k], path.concat(k), seen); } }); } diff --git a/test/query.js b/test/query.js index 6a2a184..0543668 100644 --- a/test/query.js +++ b/test/query.js @@ -355,5 +355,19 @@ suite('query', function() { assert.deepEqual(jp.query({a: 1, b: 2, c: null}, '$..["a","b","c","d"]'), [1, 2, null]); }); + test('circular reference', function() { + var obj = { foo: 'bar' }; + obj.circularReference = obj; + var results = jp.query(obj, '$..*'); + assert.deepEqual(results, ['bar', obj]); + + var obj = {}; + var o = { foo: 'bar' } + obj.foo = o; + obj.bar = o; + var results = jp.query(obj, '$..*'); + assert.deepEqual(results, [o, o, 'bar', 'bar']); + }); + });