From fafc2d269b01921bc4f649ee2524c0fe4a329199 Mon Sep 17 00:00:00 2001 From: Wes Roberts Date: Mon, 4 Dec 2017 22:23:12 -0500 Subject: [PATCH] [Fix] correctly parse nested arrays Fixes #212. --- lib/utils.js | 2 +- test/parse.js | 8 ++++++++ test/utils.js | 24 ++++++++++++++++++++++++ 3 files changed, 33 insertions(+), 1 deletion(-) diff --git a/lib/utils.js b/lib/utils.js index 6d5f440b..5958edc8 100644 --- a/lib/utils.js +++ b/lib/utils.js @@ -76,7 +76,7 @@ var merge = function merge(target, source, options) { if (Array.isArray(target) && Array.isArray(source)) { source.forEach(function (item, i) { if (has.call(target, i)) { - if (target[i] && typeof target[i] === 'object') { + if (target[i] && typeof target[i] === 'object' && item && typeof item === 'object') { target[i] = merge(target[i], item, options); } else { target.push(item); diff --git a/test/parse.js b/test/parse.js index 74056e37..01a8ff47 100644 --- a/test/parse.js +++ b/test/parse.js @@ -237,6 +237,14 @@ test('parse()', function (t) { st.end(); }); + t.test('parses jquery-param strings', function (st) { + // readable = 'filter[0][]=int1&filter[0][]==&filter[0][]=77&filter[]=and&filter[2][]=int2&filter[2][]==&filter[2][]=8' + var encoded = 'filter%5B0%5D%5B%5D=int1&filter%5B0%5D%5B%5D=%3D&filter%5B0%5D%5B%5D=77&filter%5B%5D=and&filter%5B2%5D%5B%5D=int2&filter%5B2%5D%5B%5D=%3D&filter%5B2%5D%5B%5D=8'; + var expected = { filter: [['int1', '=', '77'], 'and', ['int2', '=', '8']] }; + st.deepEqual(qs.parse(encoded), expected); + st.end(); + }); + t.test('continues parsing when no parent is found', function (st) { st.deepEqual(qs.parse('[]=&a=b'), { 0: '', a: 'b' }); st.deepEqual(qs.parse('[]&a=b', { strictNullHandling: true }), { 0: null, a: 'b' }); diff --git a/test/utils.js b/test/utils.js index 5c6056f2..f255de3f 100644 --- a/test/utils.js +++ b/test/utils.js @@ -21,6 +21,30 @@ test('merge()', function (t) { var noOptionsNonObjectSource = utils.merge({ foo: 'baz' }, 'bar'); t.deepEqual(noOptionsNonObjectSource, { foo: 'baz', bar: true }); + t.test( + 'avoids invoking array setters unnecessarily', + { skip: typeof Object.defineProperty !== 'function' }, + function (st) { + var setCount = 0; + var getCount = 0; + var observed = []; + Object.defineProperty(observed, 0, { + get: function () { + getCount += 1; + return { bar: 'baz' }; + }, + set: function () { setCount += 1; } + }); + utils.merge(observed, [null]); + st.equal(setCount, 0); + st.equal(getCount, 2); + observed[0] = observed[0]; // eslint-disable-line no-self-assign + st.equal(setCount, 1); + st.equal(getCount, 3); + st.end(); + } + ); + t.end(); });