Skip to content

Commit

Permalink
Merge pull request #32 from hapijs/31/circular_references
Browse files Browse the repository at this point in the history
account for circular references properly, closes #31
  • Loading branch information
geek committed Aug 28, 2014
2 parents 9bc7567 + c0d7343 commit 1554fcf
Show file tree
Hide file tree
Showing 2 changed files with 58 additions and 20 deletions.
59 changes: 39 additions & 20 deletions lib/utils.js
Original file line number Diff line number Diff line change
Expand Up @@ -20,7 +20,7 @@ exports.arrayToObject = function (source) {
};


exports.clone = function (source) {
exports.clone = function (source, refs) {

if (typeof source !== 'object' ||
source === null) {
Expand All @@ -32,14 +32,24 @@ exports.clone = function (source) {
return source.toString();
}

var obj = Array.isArray(source) ? [] : {};
refs = refs || [];

var lookup = refs.indexOf(source);
if (lookup !== -1) {
return refs[lookup];
}

var copy = Array.isArray(source) ? [] : source;

refs.push(source);

for (var i in source) {
if (source.hasOwnProperty(i)) {
obj[i] = exports.clone(source[i]);
copy[i] = exports.clone(source[i], refs);
}
}

return obj;
return copy;
};


Expand Down Expand Up @@ -108,32 +118,41 @@ exports.decode = function (str) {
};


exports.compact = function (obj) {
exports.compact = function (obj, refs) {

if (typeof obj !== 'object' ||
obj === null) {

if (typeof obj !== 'object' || obj === null) {
return obj;
}

var compacted = {};
refs = refs || [];
var lookup = refs.indexOf(obj);
if (lookup !== -1) {
return refs[lookup];
}

for (var key in obj) {
if (obj.hasOwnProperty(key)) {
if (Array.isArray(obj[key])) {
compacted[key] = [];
refs.push(obj);

for (var i = 0, l = obj[key].length; i < l; i++) {
if (typeof obj[key][i] !== 'undefined') {
compacted[key].push(obj[key][i]);
}
}
}
else {
compacted[key] = exports.compact(obj[key]);
if (Array.isArray(obj)) {
var compacted = [];

for (var i = 0, l = obj.length; i < l; ++i) {
if (typeof obj[i] !== 'undefined') {
compacted.push(obj[i]);
}
}

return compacted;
}

for (var key in obj) {
if (obj.hasOwnProperty(key)) {
obj[key] = exports.compact(obj[key], refs);
}
}

return compacted;
return obj;
};


Expand Down
19 changes: 19 additions & 0 deletions test/parse.js
Original file line number Diff line number Diff line change
Expand Up @@ -337,4 +337,23 @@ describe('#parse', function () {
expect(Qs.parse('roomInfoList[0].childrenAges[0]=15&roomInfoList[0].numberOfAdults=2')).to.deep.equal({ roomInfoList: [['15', '2']] });
done();
});

it('does not crash when parsing circular references', function (done) {

var a = {};
a.b = a;

var parsed;

expect(function () {

parsed = Qs.parse({ 'foo[bar]': 'baz', 'foo[baz]': a });
}).to.not.throw(Error);

expect(parsed).to.have.key('foo');
expect(parsed.foo).to.have.keys('bar', 'baz');
expect(parsed.foo.bar).to.equal('baz');
expect(parsed.foo.baz).to.deep.equal(a);
done();
});
});

0 comments on commit 1554fcf

Please sign in to comment.