Skip to content

Commit 486aa46

Browse files
committed
v6.4.1
1 parent 727ef5d commit 486aa46

File tree

4 files changed

+63
-32
lines changed

4 files changed

+63
-32
lines changed

CHANGELOG.md

+21
Original file line numberDiff line numberDiff line change
@@ -1,3 +1,24 @@
1+
## **6.4.1**
2+
- [Fix] `parse`: ignore `__proto__` keys (#428)
3+
- [Fix] fix for an impossible situation: when the formatter is called with a non-string value
4+
- [Fix] use `safer-buffer` instead of `Buffer` constructor
5+
- [Fix] `utils.merge`: avoid a crash with a null target and an array source
6+
- [Fix]` `utils.merge`: avoid a crash with a null target and a truthy non-array source
7+
- [Fix] `stringify`: fix a crash with `strictNullHandling` and a custom `filter`/`serializeDate` (#279)
8+
- [Fix] `utils`: `merge`: fix crash when `source` is a truthy primitive & no options are provided
9+
- [Fix] when `parseArrays` is false, properly handle keys ending in `[]`
10+
- [Robustness] `stringify`: avoid relying on a global `undefined` (#427)
11+
- [Refactor] use cached `Array.isArray`
12+
- [Refactor] `stringify`: Avoid arr = arr.concat(...), push to the existing instance (#269)
13+
- [readme] remove travis badge; add github actions/codecov badges; update URLs
14+
- [Docs] Clarify the need for "arrayLimit" option
15+
- [meta] fix README.md (#399)
16+
- [meta] Clean up license text so it’s properly detected as BSD-3-Clause
17+
- [meta] add FUNDING.yml
18+
- [actions] backport actions from main
19+
- [Tests] remove nonexistent tape option
20+
- [Dev Deps] backport from main
21+
122
## **6.4.0**
223
- [New] `qs.stringify`: add `encodeValuesOnly` option
324
- [Fix] follow `allowPrototypes` option during merge (#201, #201)

component.json

+1-1
Original file line numberDiff line numberDiff line change
@@ -2,7 +2,7 @@
22
"name": "qs",
33
"repository": "hapijs/qs",
44
"description": "query-string parser / stringifier with nesting support",
5-
"version": "6.4.0",
5+
"version": "6.4.1",
66
"keywords": ["querystring", "query", "parser"],
77
"main": "lib/index.js",
88
"scripts": [

dist/qs.js

+40-30
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',
@@ -102,7 +102,7 @@ var parseObject = function parseObjectRecursive(chain, val, options) {
102102
) {
103103
obj = [];
104104
obj[index] = parseObject(chain, val, options);
105-
} else {
105+
} else if (cleanRoot !== '__proto__') {
106106
obj[cleanRoot] = parseObject(chain, val, options);
107107
}
108108
}
@@ -132,8 +132,7 @@ var parseKeys = function parseQueryStringKeys(givenKey, val, options) {
132132

133133
var keys = [];
134134
if (parent) {
135-
// If we aren't using plain objects, optionally prefix keys
136-
// that would overwrite object prototype properties
135+
// If we aren't using plain objects, optionally prefix keys that would overwrite object prototype properties
137136
if (!options.plainObjects && has.call(Object.prototype, parent)) {
138137
if (!options.allowPrototypes) {
139138
return;
@@ -209,32 +208,38 @@ var utils = require('./utils');
209208
var formats = require('./formats');
210209

211210
var arrayPrefixGenerators = {
212-
brackets: function brackets(prefix) { // eslint-disable-line func-name-matching
211+
brackets: function brackets(prefix) {
213212
return prefix + '[]';
214213
},
215-
indices: function indices(prefix, key) { // eslint-disable-line func-name-matching
214+
indices: function indices(prefix, key) {
216215
return prefix + '[' + key + ']';
217216
},
218-
repeat: function repeat(prefix) { // eslint-disable-line func-name-matching
217+
repeat: function repeat(prefix) {
219218
return prefix;
220219
}
221220
};
222221

222+
var isArray = Array.isArray;
223+
var push = Array.prototype.push;
224+
var pushToArray = function (arr, valueOrArray) {
225+
push.apply(arr, isArray(valueOrArray) ? valueOrArray : [valueOrArray]);
226+
};
227+
223228
var toISO = Date.prototype.toISOString;
224229

225230
var defaults = {
226231
delimiter: '&',
227232
encode: true,
228233
encoder: utils.encode,
229234
encodeValuesOnly: false,
230-
serializeDate: function serializeDate(date) { // eslint-disable-line func-name-matching
235+
serializeDate: function serializeDate(date) {
231236
return toISO.call(date);
232237
},
233238
skipNulls: false,
234239
strictNullHandling: false
235240
};
236241

237-
var stringify = function stringify( // eslint-disable-line func-name-matching
242+
var stringify = function stringify(
238243
object,
239244
prefix,
240245
generateArrayPrefix,
@@ -253,7 +258,9 @@ var stringify = function stringify( // eslint-disable-line func-name-matching
253258
obj = filter(prefix, obj);
254259
} else if (obj instanceof Date) {
255260
obj = serializeDate(obj);
256-
} else if (obj === null) {
261+
}
262+
263+
if (obj === null) {
257264
if (strictNullHandling) {
258265
return encoder && !encodeValuesOnly ? encoder(prefix) : prefix;
259266
}
@@ -276,7 +283,7 @@ var stringify = function stringify( // eslint-disable-line func-name-matching
276283
}
277284

278285
var objKeys;
279-
if (Array.isArray(filter)) {
286+
if (isArray(filter)) {
280287
objKeys = filter;
281288
} else {
282289
var keys = Object.keys(obj);
@@ -290,8 +297,8 @@ var stringify = function stringify( // eslint-disable-line func-name-matching
290297
continue;
291298
}
292299

293-
if (Array.isArray(obj)) {
294-
values = values.concat(stringify(
300+
if (isArray(obj)) {
301+
pushToArray(values, stringify(
295302
obj[key],
296303
generateArrayPrefix(prefix, key),
297304
generateArrayPrefix,
@@ -306,7 +313,7 @@ var stringify = function stringify( // eslint-disable-line func-name-matching
306313
encodeValuesOnly
307314
));
308315
} else {
309-
values = values.concat(stringify(
316+
pushToArray(values, stringify(
310317
obj[key],
311318
prefix + (allowDots ? '.' + key : '[' + key + ']'),
312319
generateArrayPrefix,
@@ -330,7 +337,7 @@ module.exports = function (object, opts) {
330337
var obj = object;
331338
var options = opts || {};
332339

333-
if (options.encoder !== null && options.encoder !== undefined && typeof options.encoder !== 'function') {
340+
if (options.encoder !== null && typeof options.encoder !== 'undefined' && typeof options.encoder !== 'function') {
334341
throw new TypeError('Encoder has to be a function.');
335342
}
336343

@@ -344,7 +351,7 @@ module.exports = function (object, opts) {
344351
var serializeDate = typeof options.serializeDate === 'function' ? options.serializeDate : defaults.serializeDate;
345352
var encodeValuesOnly = typeof options.encodeValuesOnly === 'boolean' ? options.encodeValuesOnly : defaults.encodeValuesOnly;
346353
if (typeof options.format === 'undefined') {
347-
options.format = formats.default;
354+
options.format = formats['default'];
348355
} else if (!Object.prototype.hasOwnProperty.call(formats.formatters, options.format)) {
349356
throw new TypeError('Unknown format option provided.');
350357
}
@@ -355,7 +362,7 @@ module.exports = function (object, opts) {
355362
if (typeof options.filter === 'function') {
356363
filter = options.filter;
357364
obj = filter('', obj);
358-
} else if (Array.isArray(options.filter)) {
365+
} else if (isArray(options.filter)) {
359366
filter = options.filter;
360367
objKeys = filter;
361368
}
@@ -391,8 +398,7 @@ module.exports = function (object, opts) {
391398
if (skipNulls && obj[key] === null) {
392399
continue;
393400
}
394-
395-
keys = keys.concat(stringify(
401+
pushToArray(keys, stringify(
396402
obj[key],
397403
key,
398404
generateArrayPrefix,
@@ -444,8 +450,8 @@ exports.merge = function (target, source, options) {
444450
if (typeof source !== 'object') {
445451
if (Array.isArray(target)) {
446452
target.push(source);
447-
} else if (typeof target === 'object') {
448-
if (options.plainObjects || options.allowPrototypes || !has.call(Object.prototype, source)) {
453+
} else if (target && typeof target === 'object') {
454+
if ((options && (options.plainObjects || options.allowPrototypes)) || !has.call(Object.prototype, source)) {
449455
target[source] = true;
450456
}
451457
} else {
@@ -455,7 +461,7 @@ exports.merge = function (target, source, options) {
455461
return target;
456462
}
457463

458-
if (typeof target !== 'object') {
464+
if (!target || typeof target !== 'object') {
459465
return [target].concat(source);
460466
}
461467

@@ -513,13 +519,13 @@ exports.encode = function (str) {
513519
var c = string.charCodeAt(i);
514520

515521
if (
516-
c === 0x2D || // -
517-
c === 0x2E || // .
518-
c === 0x5F || // _
519-
c === 0x7E || // ~
520-
(c >= 0x30 && c <= 0x39) || // 0-9
521-
(c >= 0x41 && c <= 0x5A) || // a-z
522-
(c >= 0x61 && c <= 0x7A) // A-Z
522+
c === 0x2D // -
523+
|| c === 0x2E // .
524+
|| c === 0x5F // _
525+
|| c === 0x7E // ~
526+
|| (c >= 0x30 && c <= 0x39) // 0-9
527+
|| (c >= 0x41 && c <= 0x5A) // a-z
528+
|| (c >= 0x61 && c <= 0x7A) // A-Z
523529
) {
524530
out += string.charAt(i);
525531
continue;
@@ -542,7 +548,11 @@ exports.encode = function (str) {
542548

543549
i += 1;
544550
c = 0x10000 + (((c & 0x3FF) << 10) | (string.charCodeAt(i) & 0x3FF));
545-
out += hexTable[0xF0 | (c >> 18)] + hexTable[0x80 | ((c >> 12) & 0x3F)] + hexTable[0x80 | ((c >> 6) & 0x3F)] + hexTable[0x80 | (c & 0x3F)]; // eslint-disable-line max-len
551+
/* eslint operator-linebreak: [2, "before"] */
552+
out += hexTable[0xF0 | (c >> 18)]
553+
+ hexTable[0x80 | ((c >> 12) & 0x3F)]
554+
+ hexTable[0x80 | ((c >> 6) & 0x3F)]
555+
+ hexTable[0x80 | (c & 0x3F)];
546556
}
547557

548558
return out;

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.4.0",
5+
"version": "6.4.1",
66
"repository": {
77
"type": "git",
88
"url": "https://github.com/ljharb/qs.git"

0 commit comments

Comments
 (0)