Skip to content

Commit 90d9f2b

Browse files
committed
v6.2.4
1 parent ba24e74 commit 90d9f2b

File tree

4 files changed

+136
-42
lines changed

4 files changed

+136
-42
lines changed

CHANGELOG.md

Lines changed: 17 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,3 +1,20 @@
1+
## **6.2.4**
2+
- [Fix] `parse`: ignore `__proto__` keys (#428)
3+
- [Fix] `utils.merge`: avoid a crash with a null target and an array source
4+
- [Fix] `utils.merge`: avoid a crash with a null target and a truthy non-array source
5+
- [Fix] `utils`: `merge`: fix crash when `source` is a truthy primitive & no options are provided
6+
- [Fix] when `parseArrays` is false, properly handle keys ending in `[]`
7+
- [Robustness] `stringify`: avoid relying on a global `undefined` (#427)
8+
- [Refactor] use cached `Array.isArray`
9+
- [Docs] Clarify the need for "arrayLimit" option
10+
- [meta] fix README.md (#399)
11+
- [meta] Clean up license text so it’s properly detected as BSD-3-Clause
12+
- [meta] add FUNDING.yml
13+
- [actions] backport actions from main
14+
- [Tests] use `safer-buffer` instead of `Buffer` constructor
15+
- [Tests] remove nonexistent tape option
16+
- [Dev Deps] backport from main
17+
118
## **6.2.3**
219
- [Fix] follow `allowPrototypes` option during merge (#201, #200)
320
- [Fix] chmod a-x

component.json

Lines changed: 1 addition & 1 deletion
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.2.3",
5+
"version": "6.2.4",
66
"keywords": ["querystring", "query", "parser"],
77
"main": "lib/index.js",
88
"scripts": [

dist/qs.js

Lines changed: 117 additions & 40 deletions
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,4 @@
1-
(function(f){if(typeof exports==="object"&&typeof module!=="undefined"){module.exports=f()}else if(typeof define==="function"&&define.amd){define([],f)}else{var g;if(typeof window!=="undefined"){g=window}else if(typeof global!=="undefined"){g=global}else if(typeof self!=="undefined"){g=self}else{g=this}g.Qs = f()}})(function(){var define,module,exports;return (function e(t,n,r){function s(o,u){if(!n[o]){if(!t[o]){var a=typeof require=="function"&&require;if(!u&&a)return a(o,!0);if(i)return i(o,!0);var f=new Error("Cannot find module '"+o+"'");throw f.code="MODULE_NOT_FOUND",f}var l=n[o]={exports:{}};t[o][0].call(l.exports,function(e){var n=t[o][1][e];return s(n?n:e)},l,l.exports,e,t,n,r)}return n[o].exports}var i=typeof require=="function"&&require;for(var o=0;o<r.length;o++)s(r[o]);return s})({1:[function(require,module,exports){
1+
(function(f){if(typeof exports==="object"&&typeof module!=="undefined"){module.exports=f()}else if(typeof define==="function"&&define.amd){define([],f)}else{var g;if(typeof window!=="undefined"){g=window}else if(typeof global!=="undefined"){g=global}else if(typeof self!=="undefined"){g=self}else{g=this}g.Qs = f()}})(function(){var define,module,exports;return (function(){function r(e,n,t){function o(i,f){if(!n[i]){if(!e[i]){var c="function"==typeof require&&require;if(!f&&c)return c(i,!0);if(u)return u(i,!0);var a=new Error("Cannot find module '"+i+"'");throw a.code="MODULE_NOT_FOUND",a}var p=n[i]={exports:{}};e[i][0].call(p.exports,function(r){var n=e[i][1][r];return o(n||r)},p,p.exports,r,e,n,t)}return n[i].exports}for(var u="function"==typeof require&&require,i=0;i<t.length;i++)o(t[i]);return o}return r})()({1:[function(require,module,exports){
22
'use strict';
33

44
var Stringify = require('./stringify');
@@ -62,23 +62,25 @@ var parseObject = function parseObject(chain, val, options) {
6262
var root = chain.shift();
6363

6464
var obj;
65-
if (root === '[]') {
65+
if (root === '[]' && options.parseArrays) {
6666
obj = [];
6767
obj = obj.concat(parseObject(chain, val, options));
6868
} else {
6969
obj = options.plainObjects ? Object.create(null) : {};
7070
var cleanRoot = root.charAt(0) === '[' && root.charAt(root.length - 1) === ']' ? root.slice(1, -1) : root;
7171
var index = parseInt(cleanRoot, 10);
72-
if (
73-
!isNaN(index) &&
74-
root !== cleanRoot &&
75-
String(index) === cleanRoot &&
76-
index >= 0 &&
77-
(options.parseArrays && index <= options.arrayLimit)
72+
if (!options.parseArrays && cleanRoot === '') {
73+
obj = { 0: val };
74+
} else if (
75+
!isNaN(index)
76+
&& root !== cleanRoot
77+
&& String(index) === cleanRoot
78+
&& index >= 0
79+
&& (options.parseArrays && index <= options.arrayLimit)
7880
) {
7981
obj = [];
8082
obj[index] = parseObject(chain, val, options);
81-
} else {
83+
} else if (cleanRoot !== '__proto__') {
8284
obj[cleanRoot] = parseObject(chain, val, options);
8385
}
8486
}
@@ -108,8 +110,7 @@ var parseKeys = function parseKeys(givenKey, val, options) {
108110

109111
var keys = [];
110112
if (parent) {
111-
// If we aren't using plain objects, optionally prefix keys
112-
// that would overwrite object prototype properties
113+
// If we aren't using plain objects, optionally prefix keys that would overwrite object prototype properties
113114
if (!options.plainObjects && has.call(Object.prototype, parent)) {
114115
if (!options.allowPrototypes) {
115116
return;
@@ -203,7 +204,18 @@ var defaults = {
203204
encoder: Utils.encode
204205
};
205206

206-
var stringify = function stringify(object, prefix, generateArrayPrefix, strictNullHandling, skipNulls, encoder, filter, sort, allowDots) {
207+
var isArray = Array.isArray;
208+
var stringify = function stringify(
209+
object,
210+
prefix,
211+
generateArrayPrefix,
212+
strictNullHandling,
213+
skipNulls,
214+
encoder,
215+
filter,
216+
sort,
217+
allowDots
218+
) {
207219
var obj = object;
208220
if (typeof filter === 'function') {
209221
obj = filter(prefix, obj);
@@ -231,7 +243,7 @@ var stringify = function stringify(object, prefix, generateArrayPrefix, strictNu
231243
}
232244

233245
var objKeys;
234-
if (Array.isArray(filter)) {
246+
if (isArray(filter)) {
235247
objKeys = filter;
236248
} else {
237249
var keys = Object.keys(obj);
@@ -245,10 +257,30 @@ var stringify = function stringify(object, prefix, generateArrayPrefix, strictNu
245257
continue;
246258
}
247259

248-
if (Array.isArray(obj)) {
249-
values = values.concat(stringify(obj[key], generateArrayPrefix(prefix, key), generateArrayPrefix, strictNullHandling, skipNulls, encoder, filter, sort, allowDots));
260+
if (isArray(obj)) {
261+
values = values.concat(stringify(
262+
obj[key],
263+
generateArrayPrefix(prefix, key),
264+
generateArrayPrefix,
265+
strictNullHandling,
266+
skipNulls,
267+
encoder,
268+
filter,
269+
sort,
270+
allowDots
271+
));
250272
} else {
251-
values = values.concat(stringify(obj[key], prefix + (allowDots ? '.' + key : '[' + key + ']'), generateArrayPrefix, strictNullHandling, skipNulls, encoder, filter, sort, allowDots));
273+
values = values.concat(stringify(
274+
obj[key],
275+
prefix + (allowDots ? '.' + key : '[' + key + ']'),
276+
generateArrayPrefix,
277+
strictNullHandling,
278+
skipNulls,
279+
encoder,
280+
filter,
281+
sort,
282+
allowDots
283+
));
252284
}
253285
}
254286

@@ -262,21 +294,22 @@ module.exports = function (object, opts) {
262294
var strictNullHandling = typeof options.strictNullHandling === 'boolean' ? options.strictNullHandling : defaults.strictNullHandling;
263295
var skipNulls = typeof options.skipNulls === 'boolean' ? options.skipNulls : defaults.skipNulls;
264296
var encode = typeof options.encode === 'boolean' ? options.encode : defaults.encode;
265-
var encoder = encode ? (typeof options.encoder === 'function' ? options.encoder : defaults.encoder) : null;
297+
var encoder = encode ? typeof options.encoder === 'function' ? options.encoder : defaults.encoder : null;
266298
var sort = typeof options.sort === 'function' ? options.sort : null;
267299
var allowDots = typeof options.allowDots === 'undefined' ? false : options.allowDots;
268300
var objKeys;
269301
var filter;
270302

271-
if (options.encoder !== null && options.encoder !== undefined && typeof options.encoder !== 'function') {
303+
if (options.encoder !== null && typeof options.encoder !== 'undefined' && typeof options.encoder !== 'function') {
272304
throw new TypeError('Encoder has to be a function.');
273305
}
274306

275307
if (typeof options.filter === 'function') {
276308
filter = options.filter;
277309
obj = filter('', obj);
278-
} else if (Array.isArray(options.filter)) {
279-
objKeys = filter = options.filter;
310+
} else if (isArray(options.filter)) {
311+
objKeys = options.filter;
312+
filter = options.filter;
280313
}
281314

282315
var keys = [];
@@ -311,7 +344,17 @@ module.exports = function (object, opts) {
311344
continue;
312345
}
313346

314-
keys = keys.concat(stringify(obj[key], key, generateArrayPrefix, strictNullHandling, skipNulls, encoder, filter, sort, allowDots));
347+
keys = keys.concat(stringify(
348+
obj[key],
349+
key,
350+
generateArrayPrefix,
351+
strictNullHandling,
352+
skipNulls,
353+
encoder,
354+
filter,
355+
sort,
356+
allowDots
357+
));
315358
}
316359

317360
return keys.join(delimiter);
@@ -332,7 +375,20 @@ var hexTable = (function () {
332375
var has = Object.prototype.hasOwnProperty;
333376

334377
exports.arrayToObject = function (source, options) {
335-
var obj = options.plainObjects ? Object.create(null) : {};
378+
var obj = options && options.plainObjects ? Object.create(null) : {};
379+
for (var i = 0; i < source.length; ++i) {
380+
if (typeof source[i] !== 'undefined') {
381+
obj[i] = source[i];
382+
}
383+
}
384+
385+
return obj;
386+
};
387+
388+
var isArray = Array.isArray;
389+
390+
var arrayToObject = function arrayToObject(source, options) {
391+
var obj = options && options.plainObjects ? Object.create(null) : {};
336392
for (var i = 0; i < source.length; ++i) {
337393
if (typeof source[i] !== 'undefined') {
338394
obj[i] = source[i];
@@ -342,16 +398,17 @@ exports.arrayToObject = function (source, options) {
342398
return obj;
343399
};
344400

345-
exports.merge = function (target, source, options) {
401+
exports.merge = function merge(target, source, options) {
402+
/* eslint no-param-reassign: 0 */
346403
if (!source) {
347404
return target;
348405
}
349406

350407
if (typeof source !== 'object') {
351-
if (Array.isArray(target)) {
408+
if (isArray(target)) {
352409
target.push(source);
353-
} else if (typeof target === 'object') {
354-
if (options.plainObjects || options.allowPrototypes || !has.call(Object.prototype, source)) {
410+
} else if (target && typeof target === 'object') {
411+
if ((options && (options.plainObjects || options.allowPrototypes)) || !has.call(Object.prototype, source)) {
355412
target[source] = true;
356413
}
357414
} else {
@@ -361,20 +418,36 @@ exports.merge = function (target, source, options) {
361418
return target;
362419
}
363420

364-
if (typeof target !== 'object') {
421+
if (!target || typeof target !== 'object') {
365422
return [target].concat(source);
366423
}
367424

368425
var mergeTarget = target;
369-
if (Array.isArray(target) && !Array.isArray(source)) {
370-
mergeTarget = exports.arrayToObject(target, options);
426+
if (isArray(target) && !isArray(source)) {
427+
mergeTarget = arrayToObject(target, options);
428+
}
429+
430+
if (isArray(target) && isArray(source)) {
431+
source.forEach(function (item, i) {
432+
if (has.call(target, i)) {
433+
var targetItem = target[i];
434+
if (targetItem && typeof targetItem === 'object' && item && typeof item === 'object') {
435+
target[i] = merge(targetItem, item, options);
436+
} else {
437+
target.push(item);
438+
}
439+
} else {
440+
target[i] = item;
441+
}
442+
});
443+
return target;
371444
}
372445

373446
return Object.keys(source).reduce(function (acc, key) {
374447
var value = source[key];
375448

376449
if (has.call(acc, key)) {
377-
acc[key] = exports.merge(acc[key], value, options);
450+
acc[key] = merge(acc[key], value, options);
378451
} else {
379452
acc[key] = value;
380453
}
@@ -404,13 +477,13 @@ exports.encode = function (str) {
404477
var c = string.charCodeAt(i);
405478

406479
if (
407-
c === 0x2D || // -
408-
c === 0x2E || // .
409-
c === 0x5F || // _
410-
c === 0x7E || // ~
411-
(c >= 0x30 && c <= 0x39) || // 0-9
412-
(c >= 0x41 && c <= 0x5A) || // a-z
413-
(c >= 0x61 && c <= 0x7A) // A-Z
480+
c === 0x2D // -
481+
|| c === 0x2E // .
482+
|| c === 0x5F // _
483+
|| c === 0x7E // ~
484+
|| (c >= 0x30 && c <= 0x39) // 0-9
485+
|| (c >= 0x41 && c <= 0x5A) // a-z
486+
|| (c >= 0x61 && c <= 0x7A) // A-Z
414487
) {
415488
out += string.charAt(i);
416489
continue;
@@ -433,7 +506,11 @@ exports.encode = function (str) {
433506

434507
i += 1;
435508
c = 0x10000 + (((c & 0x3FF) << 10) | (string.charCodeAt(i) & 0x3FF));
436-
out += hexTable[0xF0 | (c >> 18)] + hexTable[0x80 | ((c >> 12) & 0x3F)] + hexTable[0x80 | ((c >> 6) & 0x3F)] + hexTable[0x80 | (c & 0x3F)];
509+
/* eslint operator-linebreak: [2, "before"] */
510+
out += hexTable[0xF0 | (c >> 18)]
511+
+ hexTable[0x80 | ((c >> 12) & 0x3F)]
512+
+ hexTable[0x80 | ((c >> 6) & 0x3F)]
513+
+ hexTable[0x80 | (c & 0x3F)];
437514
}
438515

439516
return out;
@@ -452,7 +529,7 @@ exports.compact = function (obj, references) {
452529

453530
refs.push(obj);
454531

455-
if (Array.isArray(obj)) {
532+
if (isArray(obj)) {
456533
var compacted = [];
457534

458535
for (var i = 0; i < obj.length; ++i) {
@@ -488,4 +565,4 @@ exports.isBuffer = function (obj) {
488565
};
489566

490567
},{}]},{},[1])(1)
491-
});
568+
});

package.json

Lines changed: 1 addition & 1 deletion
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.2.3",
5+
"version": "6.2.4",
66
"repository": {
77
"type": "git",
88
"url": "https://github.com/ljharb/qs.git"

0 commit comments

Comments
 (0)