Skip to content

Commit 298bfa5

Browse files
committed
v6.5.3
1 parent ed0f5dc commit 298bfa5

File tree

4 files changed

+62
-28
lines changed

4 files changed

+62
-28
lines changed

CHANGELOG.md

+24
Original file line numberDiff line numberDiff line change
@@ -1,3 +1,27 @@
1+
## **6.5.3**
2+
- [Fix] `parse`: ignore `__proto__` keys (#428)
3+
- [Fix]` `utils.merge`: avoid a crash with a null target and a truthy non-array source
4+
- [Fix] correctly parse nested arrays
5+
- [Fix] `stringify`: fix a crash with `strictNullHandling` and a custom `filter`/`serializeDate` (#279)
6+
- [Fix] `utils`: `merge`: fix crash when `source` is a truthy primitive & no options are provided
7+
- [Fix] when `parseArrays` is false, properly handle keys ending in `[]`
8+
- [Fix] fix for an impossible situation: when the formatter is called with a non-string value
9+
- [Fix] `utils.merge`: avoid a crash with a null target and an array source
10+
- [Refactor] `utils`: reduce observable [[Get]]s
11+
- [Refactor] use cached `Array.isArray`
12+
- [Refactor] `stringify`: Avoid arr = arr.concat(...), push to the existing instance (#269)
13+
- [Refactor] `parse`: only need to reassign the var once
14+
- [Robustness] `stringify`: avoid relying on a global `undefined` (#427)
15+
- [readme] remove travis badge; add github actions/codecov badges; update URLs
16+
- [Docs] Clean up license text so it’s properly detected as BSD-3-Clause
17+
- [Docs] Clarify the need for "arrayLimit" option
18+
- [meta] fix README.md (#399)
19+
- [meta] add FUNDING.yml
20+
- [actions] backport actions from main
21+
- [Tests] always use `String(x)` over `x.toString()`
22+
- [Tests] remove nonexistent tape option
23+
- [Dev Deps] backport from main
24+
125
## **6.5.2**
226
- [Fix] use `safer-buffer` instead of `Buffer` constructor
327
- [Refactor] utils: `module.exports` one thing, instead of mutating `exports` (#230)

component.json

+2-2
Original file line numberDiff line numberDiff line change
@@ -1,8 +1,8 @@
11
{
22
"name": "qs",
3-
"repository": "hapijs/qs",
3+
"repository": "ljharb/qs",
44
"description": "query-string parser / stringifier with nesting support",
5-
"version": "6.5.0",
5+
"version": "6.5.3",
66
"keywords": ["querystring", "query", "parser"],
77
"main": "lib/index.js",
88
"scripts": [

dist/qs.js

+35-25
Original file line numberDiff line numberDiff line change
@@ -11,7 +11,7 @@ module.exports = {
1111
return replace.call(value, percentTwenties, '+');
1212
},
1313
RFC3986: function (value) {
14-
return value;
14+
return String(value);
1515
}
1616
},
1717
RFC1738: 'RFC1738',
@@ -87,14 +87,15 @@ var parseObject = function (chain, val, options) {
8787
var obj;
8888
var root = chain[i];
8989

90-
if (root === '[]') {
91-
obj = [];
92-
obj = obj.concat(leaf);
90+
if (root === '[]' && options.parseArrays) {
91+
obj = [].concat(leaf);
9392
} else {
9493
obj = options.plainObjects ? Object.create(null) : {};
9594
var cleanRoot = root.charAt(0) === '[' && root.charAt(root.length - 1) === ']' ? root.slice(1, -1) : root;
9695
var index = parseInt(cleanRoot, 10);
97-
if (
96+
if (!options.parseArrays && cleanRoot === '') {
97+
obj = { 0: leaf };
98+
} else if (
9899
!isNaN(index)
99100
&& root !== cleanRoot
100101
&& String(index) === cleanRoot
@@ -103,7 +104,7 @@ var parseObject = function (chain, val, options) {
103104
) {
104105
obj = [];
105106
obj[index] = leaf;
106-
} else {
107+
} else if (cleanRoot !== '__proto__') {
107108
obj[cleanRoot] = leaf;
108109
}
109110
}
@@ -214,32 +215,38 @@ var utils = require('./utils');
214215
var formats = require('./formats');
215216

216217
var arrayPrefixGenerators = {
217-
brackets: function brackets(prefix) { // eslint-disable-line func-name-matching
218+
brackets: function brackets(prefix) {
218219
return prefix + '[]';
219220
},
220-
indices: function indices(prefix, key) { // eslint-disable-line func-name-matching
221+
indices: function indices(prefix, key) {
221222
return prefix + '[' + key + ']';
222223
},
223-
repeat: function repeat(prefix) { // eslint-disable-line func-name-matching
224+
repeat: function repeat(prefix) {
224225
return prefix;
225226
}
226227
};
227228

229+
var isArray = Array.isArray;
230+
var push = Array.prototype.push;
231+
var pushToArray = function (arr, valueOrArray) {
232+
push.apply(arr, isArray(valueOrArray) ? valueOrArray : [valueOrArray]);
233+
};
234+
228235
var toISO = Date.prototype.toISOString;
229236

230237
var defaults = {
231238
delimiter: '&',
232239
encode: true,
233240
encoder: utils.encode,
234241
encodeValuesOnly: false,
235-
serializeDate: function serializeDate(date) { // eslint-disable-line func-name-matching
242+
serializeDate: function serializeDate(date) {
236243
return toISO.call(date);
237244
},
238245
skipNulls: false,
239246
strictNullHandling: false
240247
};
241248

242-
var stringify = function stringify( // eslint-disable-line func-name-matching
249+
var stringify = function stringify(
243250
object,
244251
prefix,
245252
generateArrayPrefix,
@@ -258,7 +265,9 @@ var stringify = function stringify( // eslint-disable-line func-name-matching
258265
obj = filter(prefix, obj);
259266
} else if (obj instanceof Date) {
260267
obj = serializeDate(obj);
261-
} else if (obj === null) {
268+
}
269+
270+
if (obj === null) {
262271
if (strictNullHandling) {
263272
return encoder && !encodeValuesOnly ? encoder(prefix, defaults.encoder) : prefix;
264273
}
@@ -281,7 +290,7 @@ var stringify = function stringify( // eslint-disable-line func-name-matching
281290
}
282291

283292
var objKeys;
284-
if (Array.isArray(filter)) {
293+
if (isArray(filter)) {
285294
objKeys = filter;
286295
} else {
287296
var keys = Object.keys(obj);
@@ -295,8 +304,8 @@ var stringify = function stringify( // eslint-disable-line func-name-matching
295304
continue;
296305
}
297306

298-
if (Array.isArray(obj)) {
299-
values = values.concat(stringify(
307+
if (isArray(obj)) {
308+
pushToArray(values, stringify(
300309
obj[key],
301310
generateArrayPrefix(prefix, key),
302311
generateArrayPrefix,
@@ -311,7 +320,7 @@ var stringify = function stringify( // eslint-disable-line func-name-matching
311320
encodeValuesOnly
312321
));
313322
} else {
314-
values = values.concat(stringify(
323+
pushToArray(values, stringify(
315324
obj[key],
316325
prefix + (allowDots ? '.' + key : '[' + key + ']'),
317326
generateArrayPrefix,
@@ -335,7 +344,7 @@ module.exports = function (object, opts) {
335344
var obj = object;
336345
var options = opts ? utils.assign({}, opts) : {};
337346

338-
if (options.encoder !== null && options.encoder !== undefined && typeof options.encoder !== 'function') {
347+
if (options.encoder !== null && typeof options.encoder !== 'undefined' && typeof options.encoder !== 'function') {
339348
throw new TypeError('Encoder has to be a function.');
340349
}
341350

@@ -360,7 +369,7 @@ module.exports = function (object, opts) {
360369
if (typeof options.filter === 'function') {
361370
filter = options.filter;
362371
obj = filter('', obj);
363-
} else if (Array.isArray(options.filter)) {
372+
} else if (isArray(options.filter)) {
364373
filter = options.filter;
365374
objKeys = filter;
366375
}
@@ -396,8 +405,7 @@ module.exports = function (object, opts) {
396405
if (skipNulls && obj[key] === null) {
397406
continue;
398407
}
399-
400-
keys = keys.concat(stringify(
408+
pushToArray(keys, stringify(
401409
obj[key],
402410
key,
403411
generateArrayPrefix,
@@ -475,8 +483,8 @@ var merge = function merge(target, source, options) {
475483
if (typeof source !== 'object') {
476484
if (Array.isArray(target)) {
477485
target.push(source);
478-
} else if (typeof target === 'object') {
479-
if (options.plainObjects || options.allowPrototypes || !has.call(Object.prototype, source)) {
486+
} else if (target && typeof target === 'object') {
487+
if ((options && (options.plainObjects || options.allowPrototypes)) || !has.call(Object.prototype, source)) {
480488
target[source] = true;
481489
}
482490
} else {
@@ -486,7 +494,7 @@ var merge = function merge(target, source, options) {
486494
return target;
487495
}
488496

489-
if (typeof target !== 'object') {
497+
if (!target || typeof target !== 'object') {
490498
return [target].concat(source);
491499
}
492500

@@ -498,8 +506,9 @@ var merge = function merge(target, source, options) {
498506
if (Array.isArray(target) && Array.isArray(source)) {
499507
source.forEach(function (item, i) {
500508
if (has.call(target, i)) {
501-
if (target[i] && typeof target[i] === 'object') {
502-
target[i] = merge(target[i], item, options);
509+
var targetItem = target[i];
510+
if (targetItem && typeof targetItem === 'object' && item && typeof item === 'object') {
511+
target[i] = merge(targetItem, item, options);
503512
} else {
504513
target.push(item);
505514
}
@@ -580,6 +589,7 @@ var encode = function encode(str) {
580589

581590
i += 1;
582591
c = 0x10000 + (((c & 0x3FF) << 10) | (string.charCodeAt(i) & 0x3FF));
592+
/* eslint operator-linebreak: [2, "before"] */
583593
out += hexTable[0xF0 | (c >> 18)]
584594
+ hexTable[0x80 | ((c >> 12) & 0x3F)]
585595
+ hexTable[0x80 | ((c >> 6) & 0x3F)]

package.json

+1-1
Original file line numberDiff line numberDiff line change
@@ -2,7 +2,7 @@
22
"name": "qs",
33
"description": "A querystring parser that supports nesting and arrays, with a depth limit",
44
"homepage": "https://github.com/ljharb/qs",
5-
"version": "6.5.2",
5+
"version": "6.5.3",
66
"repository": {
77
"type": "git",
88
"url": "https://github.com/ljharb/qs.git"

0 commit comments

Comments
 (0)