diff --git a/lib/utils.js b/lib/utils.js index 0d410c6a..b2143323 100755 --- a/lib/utils.js +++ b/lib/utils.js @@ -31,7 +31,9 @@ exports.merge = function (target, source, options) { if (Array.isArray(target)) { target.push(source); } else if (typeof target === 'object') { - target[source] = true; + if (options.plainObjects || options.allowPrototypes || !has.call(Object.prototype, source)) { + target[source] = true; + } } else { return [target, source]; } diff --git a/test/parse.js b/test/parse.js index 84e06b61..2e1116ec 100755 --- a/test/parse.js +++ b/test/parse.js @@ -152,8 +152,6 @@ test('parse()', function (t) { st.end(); }); - t.deepEqual(qs.parse('a[b]=c&a=d'), { a: { b: 'c', d: true } }, 'can add keys to objects'); - t.test('correctly prunes undefined values when converting an array to an object', function (st) { st.deepEqual(qs.parse('a[2]=b&a[99999999]=c'), { a: { 2: 'b', 99999999: 'c' } }); st.end(); @@ -444,6 +442,44 @@ test('parse()', function (t) { st.end(); }); + t.test('params starting with a starting bracket', function (st) { + st.deepEqual(qs.parse('[=toString'), {}); + st.end(); + }); + + t.test('params starting with a starting bracket', function (st) { + st.deepEqual(qs.parse('[=toString'), {}); + st.end(); + }); + + t.test('add keys to objects', function (st) { + st.deepEqual( + qs.parse('a[b]=c&a=d'), + { a: { b: 'c', d: true } }, + 'can add keys to objects' + ); + + st.deepEqual( + qs.parse('a[b]=c&a=toString'), + { a: { b: 'c' } }, + 'can not overwrite prototype' + ); + + st.deepEqual( + qs.parse('a[b]=c&a=toString', { allowPrototypes: true }), + { a: { b: 'c', toString: true } }, + 'can overwrite prototype with allowPrototypes true' + ); + + st.deepEqual( + qs.parse('a[b]=c&a=toString', { plainObjects: true }), + { a: { b: 'c', toString: true } }, + 'can overwrite prototype with plainObjects true' + ); + + st.end(); + }); + t.test('can return null objects', { skip: !Object.create }, function (st) { var expected = Object.create(null); expected.a = Object.create(null);