Conversation
Bumps [qs](https://github.com/ljharb/qs) from 6.14.1 to 6.14.2. - [Changelog](https://github.com/ljharb/qs/blob/main/CHANGELOG.md) - [Commits](ljharb/qs@v6.14.1...v6.14.2) --- updated-dependencies: - dependency-name: qs dependency-version: 6.14.2 dependency-type: indirect ... Signed-off-by: dependabot[bot] <support@github.com>
|
[puLL-Merge] - ljharb/qs@v6.14.1..v6.14.2 Diffdiff --git .editorconfig .editorconfig
index 6adecfbf..dd5a8d84 100644
--- .editorconfig
+++ .editorconfig
@@ -7,7 +7,7 @@ end_of_line = lf
charset = utf-8
trim_trailing_whitespace = true
insert_final_newline = true
-max_line_length = 160
+max_line_length = 180
quote_type = single
[test/*]
diff --git .github/workflows/rebase.yml .github/workflows/rebase.yml
index a7740531..1c4b85b7 100644
--- .github/workflows/rebase.yml
+++ .github/workflows/rebase.yml
@@ -3,7 +3,8 @@ name: Automatic Rebase
on: [pull_request_target]
permissions:
- contents: read
+ contents: write # for ljharb/rebase to push code to rebase
+ pull-requests: read # for ljharb/rebase to get info about PR
jobs:
_:
diff --git CHANGELOG.md CHANGELOG.md
index 35828d51..0d304ea4 100644
--- CHANGELOG.md
+++ CHANGELOG.md
@@ -1,5 +1,18 @@
+## **6.14.2**
+- [Fix] `parse`: mark overflow objects for indexed notation exceeding `arrayLimit` (#546)
+- [Fix] `arrayLimit` means max count, not max index, in `combine`/`merge`/`parseArrayValue`
+- [Fix] `parse`: throw on `arrayLimit` exceeded with indexed notation when `throwOnLimitExceeded` is true (#529)
+- [Fix] `parse`: enforce `arrayLimit` on `comma`-parsed values
+- [Fix] `parse`: fix error message to reflect arrayLimit as max index; remove extraneous comments (#545)
+- [Robustness] avoid `.push`, use `void`
+- [readme] document that `addQueryPrefix` does not add `?` to empty output (#418)
+- [readme] clarify `parseArrays` and `arrayLimit` documentation (#543)
+- [readme] replace runkit CI badge with shields.io check-runs badge
+- [meta] fix changelog typo (`arrayLength` → `arrayLimit`)
+- [actions] fix rebase workflow permissions
+
## **6.14.1**
-- [Fix] ensure arrayLength applies to `[]` notation as well
+- [Fix] ensure `arrayLimit` applies to `[]` notation as well
- [Fix] `parse`: when a custom decoder returns `null` for a key, ignore that key
- [Refactor] `parse`: extract key segment splitting helper
- [meta] add threat model
diff --git README.md README.md
index 22c411df..5c377393 100644
--- README.md
+++ README.md
@@ -282,8 +282,8 @@ var withIndexedEmptyString = qs.parse('a[0]=b&a[1]=&a[2]=c');
assert.deepEqual(withIndexedEmptyString, { a: ['b', '', 'c'] });
```
-**qs** will also limit specifying indices in an array to a maximum index of `20`.
-Any array members with an index of greater than `20` will instead be converted to an object with the index as the key.
+**qs** will also limit arrays to a maximum of `20` elements.
+Any array members with an index of `20` or greater will instead be converted to an object with the index as the key.
This is needed to handle cases when someone sent, for example, `a[999999999]` and it will take significant time to iterate over this huge array.
```javascript
@@ -310,7 +310,8 @@ try {
When `throwOnLimitExceeded` is set to `false` (default), **qs** will parse up to the specified `arrayLimit` and if the limit is exceeded, the array will instead be converted to an object with the index as the key
-To disable array parsing entirely, set `parseArrays` to `false`.
+To prevent array syntax (`a[]`, `a[0]`) from being parsed as arrays, set `parseArrays` to `false`.
+Note that duplicate keys (e.g. `a=b&a=c`) may still produce arrays when `duplicates` is `'combine'` (the default).
```javascript
var noParsingArrays = qs.parse('a[]=b', { parseArrays: false });
@@ -512,6 +513,12 @@ The query string may optionally be prepended with a question mark:
assert.equal(qs.stringify({ a: 'b', c: 'd' }, { addQueryPrefix: true }), '?a=b&c=d');
```
+Note that when the output is an empty string, the prefix will not be added:
+
+```javascript
+assert.equal(qs.stringify({}, { addQueryPrefix: true }), '');
+```
+
The delimiter may be overridden with stringify as well:
```javascript
@@ -723,7 +730,7 @@ Save time, reduce risk, and improve code health, while paying the maintainers of
[downloads-url]: https://npm-stat.com/charts.html?package=qs
[codecov-image]: https://codecov.io/gh/ljharb/qs/branch/main/graphs/badge.svg
[codecov-url]: https://app.codecov.io/gh/ljharb/qs/
-[actions-image]: https://img.shields.io/endpoint?url=https://github-actions-badge-u3jn4tfpocch.runkit.sh/ljharb/qs
+[actions-image]: https://img.shields.io/github/check-runs/ljharb/qs/main
[actions-url]: https://github.com/ljharb/qs/actions
## Acknowledgements
diff --git dist/qs.js dist/qs.js
index ffb80a24..46568ae4 100644
--- dist/qs.js
+++ dist/qs.js
@@ -5,13 +5,13 @@
"use strict";var stringify=require(4),parse=require(3),formats=require(1);module.exports={formats:formats,parse:parse,stringify:stringify};
},{"1":1,"3":3,"4":4}],3:[function(require,module,exports){
-"use strict";var utils=require(5),has=Object.prototype.hasOwnProperty,isArray=Array.isArray,defaults={allowDots:!1,allowEmptyArrays:!1,allowPrototypes:!1,allowSparse:!1,arrayLimit:20,charset:"utf-8",charsetSentinel:!1,comma:!1,decodeDotInKeys:!1,decoder:utils.decode,delimiter:"&",depth:5,duplicates:"combine",ignoreQueryPrefix:!1,interpretNumericEntities:!1,parameterLimit:1e3,parseArrays:!0,plainObjects:!1,strictDepth:!1,strictNullHandling:!1,throwOnLimitExceeded:!1},interpretNumericEntities=function(e){return e.replace(/&#(\d+);/g,function(e,t){return String.fromCharCode(parseInt(t,10))})},parseArrayValue=function(e,t,r){if(e&&"string"==typeof e&&t.comma&&e.indexOf(",")>-1)return e.split(",");if(t.throwOnLimitExceeded&&r>=t.arrayLimit)throw new RangeError("Array limit exceeded. Only "+t.arrayLimit+" element"+(1===t.arrayLimit?"":"s")+" allowed in an array.");return e},isoSentinel="utf8=%26%2310003%3B",charsetSentinel="utf8=%E2%9C%93",parseValues=function parseQueryStringValues(e,t){var r={__proto__:null},i=t.ignoreQueryPrefix?e.replace(/^\?/,""):e;i=i.replace(/%5B/gi,"[").replace(/%5D/gi,"]");var a=t.parameterLimit===1/0?void 0:t.parameterLimit,o=i.split(t.delimiter,t.throwOnLimitExceeded?a+1:a);if(t.throwOnLimitExceeded&&o.length>a)throw new RangeError("Parameter limit exceeded. Only "+a+" parameter"+(1===a?"":"s")+" allowed.");var l,n=-1,s=t.charset;if(t.charsetSentinel)for(l=0;l<o.length;++l)0===o[l].indexOf("utf8=")&&(o[l]===charsetSentinel?s="utf-8":o[l]===isoSentinel&&(s="iso-8859-1"),n=l,l=o.length);for(l=0;l<o.length;++l)if(l!==n){var p,d,c=o[l],u=c.indexOf("]="),y=-1===u?c.indexOf("="):u+1;if(-1===y?(p=t.decoder(c,defaults.decoder,s,"key"),d=t.strictNullHandling?null:""):null!==(p=t.decoder(c.slice(0,y),defaults.decoder,s,"key"))&&(d=utils.maybeMap(parseArrayValue(c.slice(y+1),t,isArray(r[p])?r[p].length:0),function(e){return t.decoder(e,defaults.decoder,s,"value")})),d&&t.interpretNumericEntities&&"iso-8859-1"===s&&(d=interpretNumericEntities(String(d))),c.indexOf("[]=")>-1&&(d=isArray(d)?[d]:d),null!==p){var f=has.call(r,p);f&&"combine"===t.duplicates?r[p]=utils.combine(r[p],d,t.arrayLimit,t.plainObjects):f&&"last"!==t.duplicates||(r[p]=d)}}return r},parseObject=function(e,t,r,i){var a=0;if(e.length>0&&"[]"===e[e.length-1]){var o=e.slice(0,-1).join("");a=Array.isArray(t)&&t[o]?t[o].length:0}for(var l=i?t:parseArrayValue(t,r,a),n=e.length-1;n>=0;--n){var s,p=e[n];if("[]"===p&&r.parseArrays)s=utils.isOverflow(l)?l:r.allowEmptyArrays&&(""===l||r.strictNullHandling&&null===l)?[]:utils.combine([],l,r.arrayLimit,r.plainObjects);else{s=r.plainObjects?{__proto__:null}:{};var d="["===p.charAt(0)&&"]"===p.charAt(p.length-1)?p.slice(1,-1):p,c=r.decodeDotInKeys?d.replace(/%2E/g,"."):d,u=parseInt(c,10);r.parseArrays||""!==c?!isNaN(u)&&p!==c&&String(u)===c&&u>=0&&r.parseArrays&&u<=r.arrayLimit?(s=[])[u]=l:"__proto__"!==c&&(s[c]=l):s={0:l}}l=s}return l},splitKeyIntoSegments=function splitKeyIntoSegments(e,t){var r=t.allowDots?e.replace(/\.([^.[]+)/g,"[$1]"):e;if(t.depth<=0){if(!t.plainObjects&&has.call(Object.prototype,r)&&!t.allowPrototypes)return;return[r]}var i=/(\[[^[\]]*])/g,a=/(\[[^[\]]*])/.exec(r),o=a?r.slice(0,a.index):r,l=[];if(o){if(!t.plainObjects&&has.call(Object.prototype,o)&&!t.allowPrototypes)return;l.push(o)}for(var n=0;null!==(a=i.exec(r))&&n<t.depth;){n+=1;var s=a[1].slice(1,-1);if(!t.plainObjects&&has.call(Object.prototype,s)&&!t.allowPrototypes)return;l.push(a[1])}if(a){if(!0===t.strictDepth)throw new RangeError("Input depth exceeded depth option of "+t.depth+" and strictDepth is true");l.push("["+r.slice(a.index)+"]")}return l},parseKeys=function parseQueryStringKeys(e,t,r,i){if(e){var a=splitKeyIntoSegments(e,r);if(a)return parseObject(a,t,r,i)}},normalizeParseOptions=function normalizeParseOptions(e){if(!e)return defaults;if(void 0!==e.allowEmptyArrays&&"boolean"!=typeof e.allowEmptyArrays)throw new TypeError("`allowEmptyArrays` option can only be `true` or `false`, when provided");if(void 0!==e.decodeDotInKeys&&"boolean"!=typeof e.decodeDotInKeys)throw new TypeError("`decodeDotInKeys` option can only be `true` or `false`, when provided");if(null!==e.decoder&&void 0!==e.decoder&&"function"!=typeof e.decoder)throw new TypeError("Decoder has to be a function.");if(void 0!==e.charset&&"utf-8"!==e.charset&&"iso-8859-1"!==e.charset)throw new TypeError("The charset option must be either utf-8, iso-8859-1, or undefined");if(void 0!==e.throwOnLimitExceeded&&"boolean"!=typeof e.throwOnLimitExceeded)throw new TypeError("`throwOnLimitExceeded` option must be a boolean");var t=void 0===e.charset?defaults.charset:e.charset,r=void 0===e.duplicates?defaults.duplicates:e.duplicates;if("combine"!==r&&"first"!==r&&"last"!==r)throw new TypeError("The duplicates option must be either combine, first, or last");return{allowDots:void 0===e.allowDots?!0===e.decodeDotInKeys||defaults.allowDots:!!e.allowDots,allowEmptyArrays:"boolean"==typeof e.allowEmptyArrays?!!e.allowEmptyArrays:defaults.allowEmptyArrays,allowPrototypes:"boolean"==typeof e.allowPrototypes?e.allowPrototypes:defaults.allowPrototypes,allowSparse:"boolean"==typeof e.allowSparse?e.allowSparse:defaults.allowSparse,arrayLimit:"number"==typeof e.arrayLimit?e.arrayLimit:defaults.arrayLimit,charset:t,charsetSentinel:"boolean"==typeof e.charsetSentinel?e.charsetSentinel:defaults.charsetSentinel,comma:"boolean"==typeof e.comma?e.comma:defaults.comma,decodeDotInKeys:"boolean"==typeof e.decodeDotInKeys?e.decodeDotInKeys:defaults.decodeDotInKeys,decoder:"function"==typeof e.decoder?e.decoder:defaults.decoder,delimiter:"string"==typeof e.delimiter||utils.isRegExp(e.delimiter)?e.delimiter:defaults.delimiter,depth:"number"==typeof e.depth||!1===e.depth?+e.depth:defaults.depth,duplicates:r,ignoreQueryPrefix:!0===e.ignoreQueryPrefix,interpretNumericEntities:"boolean"==typeof e.interpretNumericEntities?e.interpretNumericEntities:defaults.interpretNumericEntities,parameterLimit:"number"==typeof e.parameterLimit?e.parameterLimit:defaults.parameterLimit,parseArrays:!1!==e.parseArrays,plainObjects:"boolean"==typeof e.plainObjects?e.plainObjects:defaults.plainObjects,strictDepth:"boolean"==typeof e.strictDepth?!!e.strictDepth:defaults.strictDepth,strictNullHandling:"boolean"==typeof e.strictNullHandling?e.strictNullHandling:defaults.strictNullHandling,throwOnLimitExceeded:"boolean"==typeof e.throwOnLimitExceeded&&e.throwOnLimitExceeded}};module.exports=function(e,t){var r=normalizeParseOptions(t);if(""===e||null==e)return r.plainObjects?{__proto__:null}:{};for(var i="string"==typeof e?parseValues(e,r):e,a=r.plainObjects?{__proto__:null}:{},o=Object.keys(i),l=0;l<o.length;++l){var n=o[l],s=parseKeys(n,i[n],r,"string"==typeof e);a=utils.merge(a,s,r)}return!0===r.allowSparse?a:utils.compact(a)};
+"use strict";var utils=require(5),has=Object.prototype.hasOwnProperty,isArray=Array.isArray,defaults={allowDots:!1,allowEmptyArrays:!1,allowPrototypes:!1,allowSparse:!1,arrayLimit:20,charset:"utf-8",charsetSentinel:!1,comma:!1,decodeDotInKeys:!1,decoder:utils.decode,delimiter:"&",depth:5,duplicates:"combine",ignoreQueryPrefix:!1,interpretNumericEntities:!1,parameterLimit:1e3,parseArrays:!0,plainObjects:!1,strictDepth:!1,strictNullHandling:!1,throwOnLimitExceeded:!1},interpretNumericEntities=function(e){return e.replace(/&#(\d+);/g,function(e,t){return String.fromCharCode(parseInt(t,10))})},parseArrayValue=function(e,t,r){if(e&&"string"==typeof e&&t.comma&&e.indexOf(",")>-1)return e.split(",");if(t.throwOnLimitExceeded&&r>=t.arrayLimit)throw new RangeError("Array limit exceeded. Only "+t.arrayLimit+" element"+(1===t.arrayLimit?"":"s")+" allowed in an array.");return e},isoSentinel="utf8=%26%2310003%3B",charsetSentinel="utf8=%E2%9C%93",parseValues=function parseQueryStringValues(e,t){var r={__proto__:null},i=t.ignoreQueryPrefix?e.replace(/^\?/,""):e;i=i.replace(/%5B/gi,"[").replace(/%5D/gi,"]");var a=t.parameterLimit===1/0?void 0:t.parameterLimit,o=i.split(t.delimiter,t.throwOnLimitExceeded?a+1:a);if(t.throwOnLimitExceeded&&o.length>a)throw new RangeError("Parameter limit exceeded. Only "+a+" parameter"+(1===a?"":"s")+" allowed.");var l,n=-1,s=t.charset;if(t.charsetSentinel)for(l=0;l<o.length;++l)0===o[l].indexOf("utf8=")&&(o[l]===charsetSentinel?s="utf-8":o[l]===isoSentinel&&(s="iso-8859-1"),n=l,l=o.length);for(l=0;l<o.length;++l)if(l!==n){var d,p,c=o[l],u=c.indexOf("]="),y=-1===u?c.indexOf("="):u+1;if(-1===y?(d=t.decoder(c,defaults.decoder,s,"key"),p=t.strictNullHandling?null:""):null!==(d=t.decoder(c.slice(0,y),defaults.decoder,s,"key"))&&(p=utils.maybeMap(parseArrayValue(c.slice(y+1),t,isArray(r[d])?r[d].length:0),function(e){return t.decoder(e,defaults.decoder,s,"value")})),p&&t.interpretNumericEntities&&"iso-8859-1"===s&&(p=interpretNumericEntities(String(p))),c.indexOf("[]=")>-1&&(p=isArray(p)?[p]:p),t.comma&&isArray(p)&&p.length>t.arrayLimit){if(t.throwOnLimitExceeded)throw new RangeError("Array limit exceeded. Only "+t.arrayLimit+" element"+(1===t.arrayLimit?"":"s")+" allowed in an array.");p=utils.combine([],p,t.arrayLimit,t.plainObjects)}if(null!==d){var f=has.call(r,d);f&&"combine"===t.duplicates?r[d]=utils.combine(r[d],p,t.arrayLimit,t.plainObjects):f&&"last"!==t.duplicates||(r[d]=p)}}return r},parseObject=function(e,t,r,i){var a=0;if(e.length>0&&"[]"===e[e.length-1]){var o=e.slice(0,-1).join("");a=Array.isArray(t)&&t[o]?t[o].length:0}for(var l=i?t:parseArrayValue(t,r,a),n=e.length-1;n>=0;--n){var s,d=e[n];if("[]"===d&&r.parseArrays)s=utils.isOverflow(l)?l:r.allowEmptyArrays&&(""===l||r.strictNullHandling&&null===l)?[]:utils.combine([],l,r.arrayLimit,r.plainObjects);else{s=r.plainObjects?{__proto__:null}:{};var p="["===d.charAt(0)&&"]"===d.charAt(d.length-1)?d.slice(1,-1):d,c=r.decodeDotInKeys?p.replace(/%2E/g,"."):p,u=parseInt(c,10),y=!isNaN(u)&&d!==c&&String(u)===c&&u>=0&&r.parseArrays;if(r.parseArrays||""!==c)if(y&&u<r.arrayLimit)(s=[])[u]=l;else{if(y&&r.throwOnLimitExceeded)throw new RangeError("Array limit exceeded. Only "+r.arrayLimit+" element"+(1===r.arrayLimit?"":"s")+" allowed in an array.");y?(s[u]=l,utils.markOverflow(s,u)):"__proto__"!==c&&(s[c]=l)}else s={0:l}}l=s}return l},splitKeyIntoSegments=function splitKeyIntoSegments(e,t){var r=t.allowDots?e.replace(/\.([^.[]+)/g,"[$1]"):e;if(t.depth<=0){if(!t.plainObjects&&has.call(Object.prototype,r)&&!t.allowPrototypes)return;return[r]}var i=/(\[[^[\]]*])/g,a=/(\[[^[\]]*])/.exec(r),o=a?r.slice(0,a.index):r,l=[];if(o){if(!t.plainObjects&&has.call(Object.prototype,o)&&!t.allowPrototypes)return;l[l.length]=o}for(var n=0;null!==(a=i.exec(r))&&n<t.depth;){n+=1;var s=a[1].slice(1,-1);if(!t.plainObjects&&has.call(Object.prototype,s)&&!t.allowPrototypes)return;l[l.length]=a[1]}if(a){if(!0===t.strictDepth)throw new RangeError("Input depth exceeded depth option of "+t.depth+" and strictDepth is true");l[l.length]="["+r.slice(a.index)+"]"}return l},parseKeys=function parseQueryStringKeys(e,t,r,i){if(e){var a=splitKeyIntoSegments(e,r);if(a)return parseObject(a,t,r,i)}},normalizeParseOptions=function normalizeParseOptions(e){if(!e)return defaults;if(void 0!==e.allowEmptyArrays&&"boolean"!=typeof e.allowEmptyArrays)throw new TypeError("`allowEmptyArrays` option can only be `true` or `false`, when provided");if(void 0!==e.decodeDotInKeys&&"boolean"!=typeof e.decodeDotInKeys)throw new TypeError("`decodeDotInKeys` option can only be `true` or `false`, when provided");if(null!==e.decoder&&void 0!==e.decoder&&"function"!=typeof e.decoder)throw new TypeError("Decoder has to be a function.");if(void 0!==e.charset&&"utf-8"!==e.charset&&"iso-8859-1"!==e.charset)throw new TypeError("The charset option must be either utf-8, iso-8859-1, or undefined");if(void 0!==e.throwOnLimitExceeded&&"boolean"!=typeof e.throwOnLimitExceeded)throw new TypeError("`throwOnLimitExceeded` option must be a boolean");var t=void 0===e.charset?defaults.charset:e.charset,r=void 0===e.duplicates?defaults.duplicates:e.duplicates;if("combine"!==r&&"first"!==r&&"last"!==r)throw new TypeError("The duplicates option must be either combine, first, or last");return{allowDots:void 0===e.allowDots?!0===e.decodeDotInKeys||defaults.allowDots:!!e.allowDots,allowEmptyArrays:"boolean"==typeof e.allowEmptyArrays?!!e.allowEmptyArrays:defaults.allowEmptyArrays,allowPrototypes:"boolean"==typeof e.allowPrototypes?e.allowPrototypes:defaults.allowPrototypes,allowSparse:"boolean"==typeof e.allowSparse?e.allowSparse:defaults.allowSparse,arrayLimit:"number"==typeof e.arrayLimit?e.arrayLimit:defaults.arrayLimit,charset:t,charsetSentinel:"boolean"==typeof e.charsetSentinel?e.charsetSentinel:defaults.charsetSentinel,comma:"boolean"==typeof e.comma?e.comma:defaults.comma,decodeDotInKeys:"boolean"==typeof e.decodeDotInKeys?e.decodeDotInKeys:defaults.decodeDotInKeys,decoder:"function"==typeof e.decoder?e.decoder:defaults.decoder,delimiter:"string"==typeof e.delimiter||utils.isRegExp(e.delimiter)?e.delimiter:defaults.delimiter,depth:"number"==typeof e.depth||!1===e.depth?+e.depth:defaults.depth,duplicates:r,ignoreQueryPrefix:!0===e.ignoreQueryPrefix,interpretNumericEntities:"boolean"==typeof e.interpretNumericEntities?e.interpretNumericEntities:defaults.interpretNumericEntities,parameterLimit:"number"==typeof e.parameterLimit?e.parameterLimit:defaults.parameterLimit,parseArrays:!1!==e.parseArrays,plainObjects:"boolean"==typeof e.plainObjects?e.plainObjects:defaults.plainObjects,strictDepth:"boolean"==typeof e.strictDepth?!!e.strictDepth:defaults.strictDepth,strictNullHandling:"boolean"==typeof e.strictNullHandling?e.strictNullHandling:defaults.strictNullHandling,throwOnLimitExceeded:"boolean"==typeof e.throwOnLimitExceeded&&e.throwOnLimitExceeded}};module.exports=function(e,t){var r=normalizeParseOptions(t);if(""===e||null==e)return r.plainObjects?{__proto__:null}:{};for(var i="string"==typeof e?parseValues(e,r):e,a=r.plainObjects?{__proto__:null}:{},o=Object.keys(i),l=0;l<o.length;++l){var n=o[l],s=parseKeys(n,i[n],r,"string"==typeof e);a=utils.merge(a,s,r)}return!0===r.allowSparse?a:utils.compact(a)};
},{"5":5}],4:[function(require,module,exports){
"use strict";var getSideChannel=require(46),utils=require(5),formats=require(1),has=Object.prototype.hasOwnProperty,arrayPrefixGenerators={brackets:function brackets(e){return e+"[]"},comma:"comma",indices:function indices(e,r){return e+"["+r+"]"},repeat:function repeat(e){return e}},isArray=Array.isArray,push=Array.prototype.push,pushToArray=function(e,r){push.apply(e,isArray(r)?r:[r])},toISO=Date.prototype.toISOString,defaultFormat=formats.default,defaults={addQueryPrefix:!1,allowDots:!1,allowEmptyArrays:!1,arrayFormat:"indices",charset:"utf-8",charsetSentinel:!1,commaRoundTrip:!1,delimiter:"&",encode:!0,encodeDotInKeys:!1,encoder:utils.encode,encodeValuesOnly:!1,filter:void 0,format:defaultFormat,formatter:formats.formatters[defaultFormat],indices:!1,serializeDate:function serializeDate(e){return toISO.call(e)},skipNulls:!1,strictNullHandling:!1},isNonNullishPrimitive=function isNonNullishPrimitive(e){return"string"==typeof e||"number"==typeof e||"boolean"==typeof e||"symbol"==typeof e||"bigint"==typeof e},sentinel={},stringify=function stringify(e,r,t,o,a,n,i,l,s,f,u,d,y,c,p,m,h,v){for(var g=e,w=v,b=0,A=!1;void 0!==(w=w.get(sentinel))&&!A;){var D=w.get(e);if(b+=1,void 0!==D){if(D===b)throw new RangeError("Cyclic object value");A=!0}void 0===w.get(sentinel)&&(b=0)}if("function"==typeof f?g=f(r,g):g instanceof Date?g=y(g):"comma"===t&&isArray(g)&&(g=utils.maybeMap(g,function(e){return e instanceof Date?y(e):e})),null===g){if(n)return s&&!m?s(r,defaults.encoder,h,"key",c):r;g=""}if(isNonNullishPrimitive(g)||utils.isBuffer(g))return s?[p(m?r:s(r,defaults.encoder,h,"key",c))+"="+p(s(g,defaults.encoder,h,"value",c))]:[p(r)+"="+p(String(g))];var S,E=[];if(void 0===g)return E;if("comma"===t&&isArray(g))m&&s&&(g=utils.maybeMap(g,s)),S=[{value:g.length>0?g.join(",")||null:void 0}];else if(isArray(f))S=f;else{var N=Object.keys(g);S=u?N.sort(u):N}var T=l?String(r).replace(/\./g,"%2E"):String(r),O=o&&isArray(g)&&1===g.length?T+"[]":T;if(a&&isArray(g)&&0===g.length)return O+"[]";for(var k=0;k<S.length;++k){var I=S[k],P="object"==typeof I&&I&&void 0!==I.value?I.value:g[I];if(!i||null!==P){var x=d&&l?String(I).replace(/\./g,"%2E"):String(I),z=isArray(g)?"function"==typeof t?t(O,x):O:O+(d?"."+x:"["+x+"]");v.set(e,b);var K=getSideChannel();K.set(sentinel,v),pushToArray(E,stringify(P,z,t,o,a,n,i,l,"comma"===t&&m&&isArray(g)?null:s,f,u,d,y,c,p,m,h,K))}}return E},normalizeStringifyOptions=function normalizeStringifyOptions(e){if(!e)return defaults;if(void 0!==e.allowEmptyArrays&&"boolean"!=typeof e.allowEmptyArrays)throw new TypeError("`allowEmptyArrays` option can only be `true` or `false`, when provided");if(void 0!==e.encodeDotInKeys&&"boolean"!=typeof e.encodeDotInKeys)throw new TypeError("`encodeDotInKeys` option can only be `true` or `false`, when provided");if(null!==e.encoder&&void 0!==e.encoder&&"function"!=typeof e.encoder)throw new TypeError("Encoder has to be a function.");var r=e.charset||defaults.charset;if(void 0!==e.charset&&"utf-8"!==e.charset&&"iso-8859-1"!==e.charset)throw new TypeError("The charset option must be either utf-8, iso-8859-1, or undefined");var t=formats.default;if(void 0!==e.format){if(!has.call(formats.formatters,e.format))throw new TypeError("Unknown format option provided.");t=e.format}var o,a=formats.formatters[t],n=defaults.filter;if(("function"==typeof e.filter||isArray(e.filter))&&(n=e.filter),o=e.arrayFormat in arrayPrefixGenerators?e.arrayFormat:"indices"in e?e.indices?"indices":"repeat":defaults.arrayFormat,"commaRoundTrip"in e&&"boolean"!=typeof e.commaRoundTrip)throw new TypeError("`commaRoundTrip` must be a boolean, or absent");var i=void 0===e.allowDots?!0===e.encodeDotInKeys||defaults.allowDots:!!e.allowDots;return{addQueryPrefix:"boolean"==typeof e.addQueryPrefix?e.addQueryPrefix:defaults.addQueryPrefix,allowDots:i,allowEmptyArrays:"boolean"==typeof e.allowEmptyArrays?!!e.allowEmptyArrays:defaults.allowEmptyArrays,arrayFormat:o,charset:r,charsetSentinel:"boolean"==typeof e.charsetSentinel?e.charsetSentinel:defaults.charsetSentinel,commaRoundTrip:!!e.commaRoundTrip,delimiter:void 0===e.delimiter?defaults.delimiter:e.delimiter,encode:"boolean"==typeof e.encode?e.encode:defaults.encode,encodeDotInKeys:"boolean"==typeof e.encodeDotInKeys?e.encodeDotInKeys:defaults.encodeDotInKeys,encoder:"function"==typeof e.encoder?e.encoder:defaults.encoder,encodeValuesOnly:"boolean"==typeof e.encodeValuesOnly?e.encodeValuesOnly:defaults.encodeValuesOnly,filter:n,format:t,formatter:a,serializeDate:"function"==typeof e.serializeDate?e.serializeDate:defaults.serializeDate,skipNulls:"boolean"==typeof e.skipNulls?e.skipNulls:defaults.skipNulls,sort:"function"==typeof e.sort?e.sort:null,strictNullHandling:"boolean"==typeof e.strictNullHandling?e.strictNullHandling:defaults.strictNullHandling}};module.exports=function(e,r){var t,o=e,a=normalizeStringifyOptions(r);"function"==typeof a.filter?o=(0,a.filter)("",o):isArray(a.filter)&&(t=a.filter);var n=[];if("object"!=typeof o||null===o)return"";var i=arrayPrefixGenerators[a.arrayFormat],l="comma"===i&&a.commaRoundTrip;t||(t=Object.keys(o)),a.sort&&t.sort(a.sort);for(var s=getSideChannel(),f=0;f<t.length;++f){var u=t[f],d=o[u];a.skipNulls&&null===d||pushToArray(n,stringify(d,u,i,l,a.allowEmptyArrays,a.strictNullHandling,a.skipNulls,a.encodeDotInKeys,a.encode?a.encoder:null,a.filter,a.sort,a.allowDots,a.serializeDate,a.format,a.formatter,a.encodeValuesOnly,a.charset,s))}var y=n.join(a.delimiter),c=!0===a.addQueryPrefix?"?":"";return a.charsetSentinel&&("iso-8859-1"===a.charset?c+="utf8=%26%2310003%3B&":c+="utf8=%E2%9C%93&"),y.length>0?c+y:""};
},{"1":1,"46":46,"5":5}],5:[function(require,module,exports){
-"use strict";var formats=require(1),getSideChannel=require(46),has=Object.prototype.hasOwnProperty,isArray=Array.isArray,overflowChannel=getSideChannel(),markOverflow=function markOverflow(e,r){return overflowChannel.set(e,r),e},isOverflow=function isOverflow(e){return overflowChannel.has(e)},getMaxIndex=function getMaxIndex(e){return overflowChannel.get(e)},setMaxIndex=function setMaxIndex(e,r){overflowChannel.set(e,r)},hexTable=function(){for(var e=[],r=0;r<256;++r)e.push("%"+((r<16?"0":"")+r.toString(16)).toUpperCase());return e}(),compactQueue=function compactQueue(e){for(;e.length>1;){var r=e.pop(),t=r.obj[r.prop];if(isArray(t)){for(var o=[],n=0;n<t.length;++n)void 0!==t[n]&&o.push(t[n]);r.obj[r.prop]=o}}},arrayToObject=function arrayToObject(e,r){for(var t=r&&r.plainObjects?{__proto__:null}:{},o=0;o<e.length;++o)void 0!==e[o]&&(t[o]=e[o]);return t},merge=function merge(e,r,t){if(!r)return e;if("object"!=typeof r&&"function"!=typeof r){if(isArray(e))e.push(r);else{if(!e||"object"!=typeof e)return[e,r];if(isOverflow(e)){var o=getMaxIndex(e)+1;e[o]=r,setMaxIndex(e,o)}else(t&&(t.plainObjects||t.allowPrototypes)||!has.call(Object.prototype,r))&&(e[r]=!0)}return e}if(!e||"object"!=typeof e){if(isOverflow(r)){for(var n=Object.keys(r),a=t&&t.plainObjects?{__proto__:null,0:e}:{0:e},c=0;c<n.length;c++)a[parseInt(n[c],10)+1]=r[n[c]];return markOverflow(a,getMaxIndex(r)+1)}return[e].concat(r)}var i=e;return isArray(e)&&!isArray(r)&&(i=arrayToObject(e,t)),isArray(e)&&isArray(r)?(r.forEach(function(r,o){if(has.call(e,o)){var n=e[o];n&&"object"==typeof n&&r&&"object"==typeof r?e[o]=merge(n,r,t):e.push(r)}else e[o]=r}),e):Object.keys(r).reduce(function(e,o){var n=r[o];return has.call(e,o)?e[o]=merge(e[o],n,t):e[o]=n,e},i)},assign=function assignSingleSource(e,r){return Object.keys(r).reduce(function(e,t){return e[t]=r[t],e},e)},decode=function(e,r,t){var o=e.replace(/\+/g," ");if("iso-8859-1"===t)return o.replace(/%[0-9a-f]{2}/gi,unescape);try{return decodeURIComponent(o)}catch(e){return o}},limit=1024,encode=function encode(e,r,t,o,n){if(0===e.length)return e;var a=e;if("symbol"==typeof e?a=Symbol.prototype.toString.call(e):"string"!=typeof e&&(a=String(e)),"iso-8859-1"===t)return escape(a).replace(/%u[0-9a-f]{4}/gi,function(e){return"%26%23"+parseInt(e.slice(2),16)+"%3B"});for(var c="",i=0;i<a.length;i+=limit){for(var l=a.length>=limit?a.slice(i,i+limit):a,f=[],s=0;s<l.length;++s){var u=l.charCodeAt(s);45===u||46===u||95===u||126===u||u>=48&&u<=57||u>=65&&u<=90||u>=97&&u<=122||n===formats.RFC1738&&(40===u||41===u)?f[f.length]=l.charAt(s):u<128?f[f.length]=hexTable[u]:u<2048?f[f.length]=hexTable[192|u>>6]+hexTable[128|63&u]:u<55296||u>=57344?f[f.length]=hexTable[224|u>>12]+hexTable[128|u>>6&63]+hexTable[128|63&u]:(s+=1,u=65536+((1023&u)<<10|1023&l.charCodeAt(s)),f[f.length]=hexTable[240|u>>18]+hexTable[128|u>>12&63]+hexTable[128|u>>6&63]+hexTable[128|63&u])}c+=f.join("")}return c},compact=function compact(e){for(var r=[{obj:{o:e},prop:"o"}],t=[],o=0;o<r.length;++o)for(var n=r[o],a=n.obj[n.prop],c=Object.keys(a),i=0;i<c.length;++i){var l=c[i],f=a[l];"object"==typeof f&&null!==f&&-1===t.indexOf(f)&&(r.push({obj:a,prop:l}),t.push(f))}return compactQueue(r),e},isRegExp=function isRegExp(e){return"[object RegExp]"===Object.prototype.toString.call(e)},isBuffer=function isBuffer(e){return!(!e||"object"!=typeof e||!(e.constructor&&e.constructor.isBuffer&&e.constructor.isBuffer(e)))},combine=function combine(e,r,t,o){if(isOverflow(e)){var n=getMaxIndex(e)+1;return e[n]=r,setMaxIndex(e,n),e}var a=[].concat(e,r);return a.length>t?markOverflow(arrayToObject(a,{plainObjects:o}),a.length-1):a},maybeMap=function maybeMap(e,r){if(isArray(e)){for(var t=[],o=0;o<e.length;o+=1)t.push(r(e[o]));return t}return r(e)};module.exports={/* common-shake removed: arrayToObject:arrayToObject *//* common-shake removed: assign:assign */combine:combine,compact:compact,decode:decode,encode:encode,isBuffer:isBuffer,isOverflow:isOverflow,isRegExp:isRegExp,maybeMap:maybeMap,merge:merge};
+"use strict";var formats=require(1),getSideChannel=require(46),has=Object.prototype.hasOwnProperty,isArray=Array.isArray,overflowChannel=getSideChannel(),markOverflow=function markOverflow(e,r){return overflowChannel.set(e,r),e},isOverflow=function isOverflow(e){return overflowChannel.has(e)},getMaxIndex=function getMaxIndex(e){return overflowChannel.get(e)},setMaxIndex=function setMaxIndex(e,r){overflowChannel.set(e,r)},hexTable=function(){for(var e=[],r=0;r<256;++r)e[e.length]="%"+((r<16?"0":"")+r.toString(16)).toUpperCase();return e}(),compactQueue=function compactQueue(e){for(;e.length>1;){var r=e.pop(),t=r.obj[r.prop];if(isArray(t)){for(var n=[],o=0;o<t.length;++o)void 0!==t[o]&&(n[n.length]=t[o]);r.obj[r.prop]=n}}},arrayToObject=function arrayToObject(e,r){for(var t=r&&r.plainObjects?{__proto__:null}:{},n=0;n<e.length;++n)void 0!==e[n]&&(t[n]=e[n]);return t},merge=function merge(e,r,t){if(!r)return e;if("object"!=typeof r&&"function"!=typeof r){if(isArray(e)){var n=e.length;if(t&&"number"==typeof t.arrayLimit&&n>t.arrayLimit)return markOverflow(arrayToObject(e.concat(r),t),n);e[n]=r}else{if(!e||"object"!=typeof e)return[e,r];if(isOverflow(e)){var o=getMaxIndex(e)+1;e[o]=r,setMaxIndex(e,o)}else(t&&(t.plainObjects||t.allowPrototypes)||!has.call(Object.prototype,r))&&(e[r]=!0)}return e}if(!e||"object"!=typeof e){if(isOverflow(r)){for(var a=Object.keys(r),i=t&&t.plainObjects?{__proto__:null,0:e}:{0:e},c=0;c<a.length;c++)i[parseInt(a[c],10)+1]=r[a[c]];return markOverflow(i,getMaxIndex(r)+1)}var l=[e].concat(r);return t&&"number"==typeof t.arrayLimit&&l.length>t.arrayLimit?markOverflow(arrayToObject(l,t),l.length-1):l}var f=e;return isArray(e)&&!isArray(r)&&(f=arrayToObject(e,t)),isArray(e)&&isArray(r)?(r.forEach(function(r,n){if(has.call(e,n)){var o=e[n];o&&"object"==typeof o&&r&&"object"==typeof r?e[n]=merge(o,r,t):e[e.length]=r}else e[n]=r}),e):Object.keys(r).reduce(function(e,n){var o=r[n];if(has.call(e,n)?e[n]=merge(e[n],o,t):e[n]=o,isOverflow(r)&&!isOverflow(e)&&markOverflow(e,getMaxIndex(r)),isOverflow(e)){var a=parseInt(n,10);String(a)===n&&a>=0&&a>getMaxIndex(e)&&setMaxIndex(e,a)}return e},f)},assign=function assignSingleSource(e,r){return Object.keys(r).reduce(function(e,t){return e[t]=r[t],e},e)},decode=function(e,r,t){var n=e.replace(/\+/g," ");if("iso-8859-1"===t)return n.replace(/%[0-9a-f]{2}/gi,unescape);try{return decodeURIComponent(n)}catch(e){return n}},limit=1024,encode=function encode(e,r,t,n,o){if(0===e.length)return e;var a=e;if("symbol"==typeof e?a=Symbol.prototype.toString.call(e):"string"!=typeof e&&(a=String(e)),"iso-8859-1"===t)return escape(a).replace(/%u[0-9a-f]{4}/gi,function(e){return"%26%23"+parseInt(e.slice(2),16)+"%3B"});for(var i="",c=0;c<a.length;c+=limit){for(var l=a.length>=limit?a.slice(c,c+limit):a,f=[],s=0;s<l.length;++s){var u=l.charCodeAt(s);45===u||46===u||95===u||126===u||u>=48&&u<=57||u>=65&&u<=90||u>=97&&u<=122||o===formats.RFC1738&&(40===u||41===u)?f[f.length]=l.charAt(s):u<128?f[f.length]=hexTable[u]:u<2048?f[f.length]=hexTable[192|u>>6]+hexTable[128|63&u]:u<55296||u>=57344?f[f.length]=hexTable[224|u>>12]+hexTable[128|u>>6&63]+hexTable[128|63&u]:(s+=1,u=65536+((1023&u)<<10|1023&l.charCodeAt(s)),f[f.length]=hexTable[240|u>>18]+hexTable[128|u>>12&63]+hexTable[128|u>>6&63]+hexTable[128|63&u])}i+=f.join("")}return i},compact=function compact(e){for(var r=[{obj:{o:e},prop:"o"}],t=[],n=0;n<r.length;++n)for(var o=r[n],a=o.obj[o.prop],i=Object.keys(a),c=0;c<i.length;++c){var l=i[c],f=a[l];"object"==typeof f&&null!==f&&-1===t.indexOf(f)&&(r[r.length]={obj:a,prop:l},t[t.length]=f)}return compactQueue(r),e},isRegExp=function isRegExp(e){return"[object RegExp]"===Object.prototype.toString.call(e)},isBuffer=function isBuffer(e){return!(!e||"object"!=typeof e||!(e.constructor&&e.constructor.isBuffer&&e.constructor.isBuffer(e)))},combine=function combine(e,r,t,n){if(isOverflow(e)){var o=getMaxIndex(e)+1;return e[o]=r,setMaxIndex(e,o),e}var a=[].concat(e,r);return a.length>t?markOverflow(arrayToObject(a,{plainObjects:n}),a.length-1):a},maybeMap=function maybeMap(e,r){if(isArray(e)){for(var t=[],n=0;n<e.length;n+=1)t[t.length]=r(e[n]);return t}return r(e)};module.exports={/* common-shake removed: arrayToObject:arrayToObject *//* common-shake removed: assign:assign */combine:combine,compact:compact,decode:decode,encode:encode,isBuffer:isBuffer,isOverflow:isOverflow,isRegExp:isRegExp,markOverflow:markOverflow,maybeMap:maybeMap,merge:merge};
},{"1":1,"46":46}],46:[function(require,module,exports){
"use strict";var $TypeError=require(20),inspect=require(42),getSideChannelList=require(43),getSideChannelMap=require(44),getSideChannelWeakMap=require(45),makeChannel=getSideChannelWeakMap||getSideChannelMap||getSideChannelList;module.exports=function getSideChannel(){var e,n={assert:function(e){if(!n.has(e))throw new $TypeError("Side channel does not contain "+inspect(e))},delete:function(n){return!!e&&e.delete(n)},get:function(n){return e&&e.get(n)},has:function(n){return!!e&&e.has(n)},set:function(n,t){e||(e=makeChannel()),e.set(n,t)}};return n};
@@ -78,24 +78,24 @@
},{}],23:[function(require,module,exports){
"use strict";var ERROR_MESSAGE="Function.prototype.bind called on incompatible ",toStr=Object.prototype.toString,max=Math.max,funcType="[object Function]",concatty=function concatty(t,n){for(var r=[],o=0;o<t.length;o+=1)r[o]=t[o];for(var e=0;e<n.length;e+=1)r[e+t.length]=n[e];return r},slicy=function slicy(t,n){for(var r=[],o=n||0,e=0;o<t.length;o+=1,e+=1)r[e]=t[o];return r},joiny=function(t,n){for(var r="",o=0;o<t.length;o+=1)r+=t[o],o+1<t.length&&(r+=n);return r};module.exports=function bind(t){var n=this;if("function"!=typeof n||toStr.apply(n)!==funcType)throw new TypeError(ERROR_MESSAGE+n);for(var r,o=slicy(arguments,1),e=max(0,n.length-o.length),i=[],c=0;c<e;c++)i[c]="$"+c;if(r=Function("binder","return function ("+joiny(i,",")+"){ return binder.apply(this,arguments); }")(function(){if(this instanceof r){var e=n.apply(this,concatty(o,arguments));return Object(e)===e?e:this}return n.apply(t,concatty(o,arguments))}),n.prototype){var p=function Empty(){};p.prototype=n.prototype,r.prototype=new p,p.prototype=null}return r};
-},{}],37:[function(require,module,exports){
-"use strict";module.exports=Math.max;
-
-},{}],38:[function(require,module,exports){
-"use strict";module.exports=Math.min;
+},{}],34:[function(require,module,exports){
+"use strict";module.exports=Math.abs;
},{}],39:[function(require,module,exports){
"use strict";module.exports=Math.pow;
-},{}],34:[function(require,module,exports){
-"use strict";module.exports=Math.abs;
-
},{}],40:[function(require,module,exports){
"use strict";module.exports=Math.round;
+},{}],37:[function(require,module,exports){
+"use strict";module.exports=Math.max;
+
},{}],35:[function(require,module,exports){
"use strict";module.exports=Math.floor;
+},{}],38:[function(require,module,exports){
+"use strict";module.exports=Math.min;
+
},{}],27:[function(require,module,exports){
"use strict";module.exports="undefined"!=typeof Reflect&&Reflect.getPrototypeOf||null;
diff --git lib/parse.js lib/parse.js
index 621c41e8..2aa1c485 100644
--- lib/parse.js
+++ lib/parse.js
@@ -63,7 +63,7 @@ var parseValues = function parseQueryStringValues(str, options) {
var cleanStr = options.ignoreQueryPrefix ? str.replace(/^\?/, '') : str;
cleanStr = cleanStr.replace(/%5B/gi, '[').replace(/%5D/gi, ']');
- var limit = options.parameterLimit === Infinity ? undefined : options.parameterLimit;
+ var limit = options.parameterLimit === Infinity ? void undefined : options.parameterLimit;
var parts = cleanStr.split(
options.delimiter,
options.throwOnLimitExceeded ? limit + 1 : limit
@@ -130,6 +130,13 @@ var parseValues = function parseQueryStringValues(str, options) {
val = isArray(val) ? [val] : val;
}
+ if (options.comma && isArray(val) && val.length > options.arrayLimit) {
+ if (options.throwOnLimitExceeded) {
+ throw new RangeError('Array limit exceeded. Only ' + options.arrayLimit + ' element' + (options.arrayLimit === 1 ? '' : 's') + ' allowed in an array.');
+ }
+ val = utils.combine([], val, options.arrayLimit, options.plainObjects);
+ }
+
if (key !== null) {
var existing = has.call(obj, key);
if (existing && options.duplicates === 'combine') {
@@ -180,17 +187,21 @@ var parseObject = function (chain, val, options, valuesParsed) {
var cleanRoot = root.charAt(0) === '[' && root.charAt(root.length - 1) === ']' ? root.slice(1, -1) : root;
var decodedRoot = options.decodeDotInKeys ? cleanRoot.replace(/%2E/g, '.') : cleanRoot;
var index = parseInt(decodedRoot, 10);
- if (!options.parseArrays && decodedRoot === '') {
- obj = { 0: leaf };
- } else if (
- !isNaN(index)
+ var isValidArrayIndex = !isNaN(index)
&& root !== decodedRoot
&& String(index) === decodedRoot
&& index >= 0
- && (options.parseArrays && index <= options.arrayLimit)
- ) {
+ && options.parseArrays;
+ if (!options.parseArrays && decodedRoot === '') {
+ obj = { 0: leaf };
+ } else if (isValidArrayIndex && index < options.arrayLimit) {
obj = [];
obj[index] = leaf;
+ } else if (isValidArrayIndex && options.throwOnLimitExceeded) {
+ throw new RangeError('Array limit exceeded. Only ' + options.arrayLimit + ' element' + (options.arrayLimit === 1 ? '' : 's') + ' allowed in an array.');
+ } else if (isValidArrayIndex) {
+ obj[index] = leaf;
+ utils.markOverflow(obj, index);
} else if (decodedRoot !== '__proto__') {
obj[decodedRoot] = leaf;
}
@@ -230,7 +241,7 @@ var splitKeyIntoSegments = function splitKeyIntoSegments(givenKey, options) {
}
}
- keys.push(parent);
+ keys[keys.length] = parent;
}
var i = 0;
@@ -244,7 +255,7 @@ var splitKeyIntoSegments = function splitKeyIntoSegments(givenKey, options) {
}
}
- keys.push(segment[1]);
+ keys[keys.length] = segment[1];
}
if (segment) {
@@ -252,7 +263,7 @@ var splitKeyIntoSegments = function splitKeyIntoSegments(givenKey, options) {
throw new RangeError('Input depth exceeded depth option of ' + options.depth + ' and strictDepth is true');
}
- keys.push('[' + key.slice(segment.index) + ']');
+ keys[keys.length] = '[' + key.slice(segment.index) + ']';
}
return keys;
diff --git lib/utils.js lib/utils.js
index 91f555e4..8e10e394 100644
--- lib/utils.js
+++ lib/utils.js
@@ -30,7 +30,7 @@ var setMaxIndex = function setMaxIndex(obj, maxIndex) {
var hexTable = (function () {
var array = [];
for (var i = 0; i < 256; ++i) {
- array.push('%' + ((i < 16 ? '0' : '') + i.toString(16)).toUpperCase());
+ array[array.length] = '%' + ((i < 16 ? '0' : '') + i.toString(16)).toUpperCase();
}
return array;
@@ -46,7 +46,7 @@ var compactQueue = function compactQueue(queue) {
for (var j = 0; j < obj.length; ++j) {
if (typeof obj[j] !== 'undefined') {
- compacted.push(obj[j]);
+ compacted[compacted.length] = obj[j];
}
}
@@ -74,7 +74,11 @@ var merge = function merge(target, source, options) {
if (typeof source !== 'object' && typeof source !== 'function') {
if (isArray(target)) {
- target.push(source);
+ var nextIndex = target.length;
+ if (options && typeof options.arrayLimit === 'number' && nextIndex > options.arrayLimit) {
+ return markOverflow(arrayToObject(target.concat(source), options), nextIndex);
+ }
+ target[nextIndex] = source;
} else if (target && typeof target === 'object') {
if (isOverflow(target)) {
// Add at next numeric index for overflow objects
@@ -107,7 +111,11 @@ var merge = function merge(target, source, options) {
}
return markOverflow(result, getMaxIndex(source) + 1);
}
- return [target].concat(source);
+ var combined = [target].concat(source);
+ if (options && typeof options.arrayLimit === 'number' && combined.length > options.arrayLimit) {
+ return markOverflow(arrayToObject(combined, options), combined.length - 1);
+ }
+ return combined;
}
var mergeTarget = target;
@@ -122,7 +130,7 @@ var merge = function merge(target, source, options) {
if (targetItem && typeof targetItem === 'object' && item && typeof item === 'object') {
target[i] = merge(targetItem, item, options);
} else {
- target.push(item);
+ target[target.length] = item;
}
} else {
target[i] = item;
@@ -139,6 +147,17 @@ var merge = function merge(target, source, options) {
} else {
acc[key] = value;
}
+
+ if (isOverflow(source) && !isOverflow(acc)) {
+ markOverflow(acc, getMaxIndex(source));
+ }
+ if (isOverflow(acc)) {
+ var keyNum = parseInt(key, 10);
+ if (String(keyNum) === key && keyNum >= 0 && keyNum > getMaxIndex(acc)) {
+ setMaxIndex(acc, keyNum);
+ }
+ }
+
return acc;
}, mergeTarget);
};
@@ -255,8 +274,8 @@ var compact = function compact(value) {
var key = keys[j];
var val = obj[key];
if (typeof val === 'object' && val !== null && refs.indexOf(val) === -1) {
- queue.push({ obj: obj, prop: key });
- refs.push(val);
+ queue[queue.length] = { obj: obj, prop: key };
+ refs[refs.length] = val;
}
}
}
@@ -298,7 +317,7 @@ var maybeMap = function maybeMap(val, fn) {
if (isArray(val)) {
var mapped = [];
for (var i = 0; i < val.length; i += 1) {
- mapped.push(fn(val[i]));
+ mapped[mapped.length] = fn(val[i]);
}
return mapped;
}
@@ -315,6 +334,7 @@ module.exports = {
isBuffer: isBuffer,
isOverflow: isOverflow,
isRegExp: isRegExp,
+ markOverflow: markOverflow,
maybeMap: maybeMap,
merge: merge
};
diff --git package.json package.json
index e4875e4a..cb5cfbe0 100644
--- package.json
+++ package.json
@@ -2,7 +2,7 @@
"name": "qs",
"description": "A querystring parser that supports nesting and arrays, with a depth limit",
"homepage": "https://github.com/ljharb/qs",
- "version": "6.14.1",
+ "version": "6.14.2",
"repository": {
"type": "git",
"url": "https://github.com/ljharb/qs.git"
diff --git test/parse.js test/parse.js
index 7b353ffc..6234fefa 100644
--- test/parse.js
+++ test/parse.js
@@ -261,11 +261,11 @@ test('parse()', function (t) {
});
t.test('limits specific array indices to arrayLimit', function (st) {
- st.deepEqual(qs.parse('a[20]=a', { arrayLimit: 20 }), { a: ['a'] });
- st.deepEqual(qs.parse('a[21]=a', { arrayLimit: 20 }), { a: { 21: 'a' } });
+ st.deepEqual(qs.parse('a[19]=a', { arrayLimit: 20 }), { a: ['a'] });
+ st.deepEqual(qs.parse('a[20]=a', { arrayLimit: 20 }), { a: { 20: 'a' } });
- st.deepEqual(qs.parse('a[20]=a'), { a: ['a'] });
- st.deepEqual(qs.parse('a[21]=a'), { a: { 21: 'a' } });
+ st.deepEqual(qs.parse('a[19]=a'), { a: ['a'] });
+ st.deepEqual(qs.parse('a[20]=a'), { a: { 20: 'a' } });
st.end();
});
@@ -483,7 +483,7 @@ test('parse()', function (t) {
t.test('allows overriding array limit', function (st) {
st.deepEqual(qs.parse('a[0]=b', { arrayLimit: -1 }), { a: { 0: 'b' } });
- st.deepEqual(qs.parse('a[0]=b', { arrayLimit: 0 }), { a: ['b'] });
+ st.deepEqual(qs.parse('a[0]=b', { arrayLimit: 0 }), { a: { 0: 'b' } });
st.deepEqual(qs.parse('a[-1]=b', { arrayLimit: -1 }), { a: { '-1': 'b' } });
st.deepEqual(qs.parse('a[-1]=b', { arrayLimit: 0 }), { a: { '-1': 'b' } });
@@ -1118,6 +1118,7 @@ test('parse()', function (t) {
});
st.test('throws error when array limit exceeded', function (sst) {
+ // 4 elements exceeds limit of 3
sst['throws'](
function () {
qs.parse('a[]=1&a[]=2&a[]=3&a[]=4', { arrayLimit: 3, throwOnLimitExceeded: true });
@@ -1128,6 +1129,14 @@ test('parse()', function (t) {
sst.end();
});
+ st.test('does not throw when at limit', function (sst) {
+ // 3 elements = limit of 3, should not throw
+ var result = qs.parse('a[]=1&a[]=2&a[]=3', { arrayLimit: 3, throwOnLimitExceeded: true });
+ sst.ok(Array.isArray(result.a), 'result is an array');
+ sst.deepEqual(result.a, ['1', '2', '3'], 'all values present');
+ sst.end();
+ });
+
st.test('converts array to object if length is greater than limit', function (sst) {
var result = qs.parse('a[1]=1&a[2]=2&a[3]=3&a[4]=4&a[5]=5&a[6]=6', { arrayLimit: 5 });
@@ -1135,6 +1144,40 @@ test('parse()', function (t) {
sst.end();
});
+ st.test('throws error when indexed notation exceeds arrayLimit with throwOnLimitExceeded', function (sst) {
+ sst['throws'](
+ function () {
+ qs.parse('a[1001]=b', { arrayLimit: 1000, throwOnLimitExceeded: true });
+ },
+ new RangeError('Array limit exceeded. Only 1000 elements allowed in an array.'),
+ 'throws error for a single index exceeding arrayLimit'
+ );
+
+ sst['throws'](
+ function () {
+ qs.parse('a[0]=1&a[1]=2&a[2]=3&a[10]=4', { arrayLimit: 6, throwOnLimitExceeded: true, allowSparse: true });
+ },
+ new RangeError('Array limit exceeded. Only 6 elements allowed in an array.'),
+ 'throws error when a sparse index exceeds arrayLimit'
+ );
+
+ sst.end();
+ });
+
+ st.test('does not throw for indexed notation within arrayLimit with throwOnLimitExceeded', function (sst) {
+ var result = qs.parse('a[4]=b', { arrayLimit: 5, throwOnLimitExceeded: true, allowSparse: true });
+ sst.ok(Array.isArray(result.a), 'result is an array');
+ sst.equal(result.a.length, 5, 'array has correct length');
+ sst.equal(result.a[4], 'b', 'value at index 4 is correct');
+ sst.end();
+ });
+
+ st.test('silently converts to object for indexed notation exceeding arrayLimit without throwOnLimitExceeded', function (sst) {
+ var result = qs.parse('a[1001]=b', { arrayLimit: 1000 });
+ sst.deepEqual(result, { a: { 1001: 'b' } }, 'converts to object without throwing');
+ sst.end();
+ });
+
st.end();
});
@@ -1304,24 +1347,72 @@ test('DOS', function (t) {
});
test('arrayLimit boundary conditions', function (t) {
+ // arrayLimit is the max number of elements allowed in an array
t.test('exactly at the limit stays as array', function (st) {
+ // 3 elements = limit of 3
var result = qs.parse('a[]=1&a[]=2&a[]=3', { arrayLimit: 3 });
- st.ok(Array.isArray(result.a), 'result is an array when exactly at limit');
+ st.ok(Array.isArray(result.a), 'result is an array when count equals limit');
st.deepEqual(result.a, ['1', '2', '3'], 'all values present');
st.end();
});
t.test('one over the limit converts to object', function (st) {
+ // 4 elements exceeds limit of 3
var result = qs.parse('a[]=1&a[]=2&a[]=3&a[]=4', { arrayLimit: 3 });
st.notOk(Array.isArray(result.a), 'result is not an array when over limit');
st.deepEqual(result.a, { 0: '1', 1: '2', 2: '3', 3: '4' }, 'all values preserved as object');
st.end();
});
- t.test('arrayLimit 1 with two values', function (st) {
+ t.test('arrayLimit 1 with one value', function (st) {
+ // 1 element = limit of 1
+ var result = qs.parse('a[]=1', { arrayLimit: 1 });
+ st.ok(Array.isArray(result.a), 'result is an array when count equals limit');
+ st.deepEqual(result.a, ['1'], 'value preserved as array');
+ st.end();
+ });
+
+ t.test('arrayLimit 1 with two values converts to object', function (st) {
+ // 2 elements exceeds limit of 1
var result = qs.parse('a[]=1&a[]=2', { arrayLimit: 1 });
st.notOk(Array.isArray(result.a), 'result is not an array');
- st.deepEqual(result.a, { 0: '1', 1: '2' }, 'both values preserved');
+ st.deepEqual(result.a, { 0: '1', 1: '2' }, 'all values preserved as object');
+ st.end();
+ });
+
+ t.end();
+});
+
+test('comma + arrayLimit', function (t) {
+ t.test('comma-separated values within arrayLimit stay as array', function (st) {
+ var result = qs.parse('a=1,2,3', { comma: true, arrayLimit: 5 });
+ st.ok(Array.isArray(result.a), 'result is an array');
+ st.deepEqual(result.a, ['1', '2', '3'], 'all values present');
+ st.end();
+ });
+
+ t.test('comma-separated values exceeding arrayLimit convert to object', function (st) {
+ var result = qs.parse('a=1,2,3,4', { comma: true, arrayLimit: 3 });
+ st.notOk(Array.isArray(result.a), 'result is not an array when over limit');
+ st.deepEqual(result.a, { 0: '1', 1: '2', 2: '3', 3: '4' }, 'all values preserved as object');
+ st.end();
+ });
+
+ t.test('comma-separated values exceeding arrayLimit with throwOnLimitExceeded throws', function (st) {
+ st['throws'](
+ function () {
+ qs.parse('a=1,2,3,4', { comma: true, arrayLimit: 3, throwOnLimitExceeded: true });
+ },
+ new RangeError('Array limit exceeded. Only 3 elements allowed in an array.'),
+ 'throws error when comma-split exceeds array limit'
+ );
+ st.end();
+ });
+
+ t.test('comma-separated values at exactly arrayLimit stay as array', function (st) {
+ var result = qs.parse('a=1,2,3', { comma: true, arrayLimit: 3 });
+ st.ok(Array.isArray(result.a), 'result is an array when exactly at limit');
+ st.deepEqual(result.a, ['1', '2', '3'], 'all values present');
st.end();
});
@@ -1384,13 +1475,38 @@ test('mixed array and object notation', function (t) {
});
t.test('multiple plain values exceeding limit', function (st) {
+ // 3 elements (indices 0-2), max index 2 > limit 1
st.deepEqual(
- qs.parse('a=b&a=c&a=d', { arrayLimit: 2 }),
+ qs.parse('a=b&a=c&a=d', { arrayLimit: 1 }),
{ a: { 0: 'b', 1: 'c', 2: 'd' } },
'duplicate plain keys convert to object when exceeding limit'
);
st.end();
});
+ t.test('mixed notation produces consistent results when arrayLimit is exceeded', function (st) {
+ var expected = { a: { 0: 'b', 1: 'c', 2: 'd' } };
+
+ st.deepEqual(
+ qs.parse('a[]=b&a[1]=c&a=d', { arrayLimit: -1 }),
+ expected,
+ 'arrayLimit -1'
+ );
+
+ st.deepEqual(
+ qs.parse('a[]=b&a[1]=c&a=d', { arrayLimit: 0 }),
+ expected,
+ 'arrayLimit 0'
+ );
+
+ st.deepEqual(
+ qs.parse('a[]=b&a[1]=c&a=d', { arrayLimit: 1 }),
+ expected,
+ 'arrayLimit 1'
+ );
+
+ st.end();
+ });
+
t.end();
});
diff --git test/utils.js test/utils.js
index defb7f26..65baea72 100644
--- test/utils.js
+++ test/utils.js
@@ -69,12 +69,14 @@ test('merge()', function (t) {
);
t.test('with overflow objects (from arrayLimit)', function (st) {
+ // arrayLimit is max index, so with limit 0, max index 0 is allowed (1 element)
+ // To create overflow, need 2+ elements with limit 0, or 3+ with limit 1, etc.
st.test('merges primitive into overflow object at next index', function (s2t) {
- // Create an overflow object via combine
- var overflow = utils.combine(['a'], 'b', 1, false);
+ // Create an overflow object via combine: 3 elements (indices 0-2) with limit 0
+ var overflow = utils.combine(['a', 'b'], 'c', 0, false);
s2t.ok(utils.isOverflow(overflow), 'overflow object is marked');
- var merged = utils.merge(overflow, 'c');
- s2t.deepEqual(merged, { 0: 'a', 1: 'b', 2: 'c' }, 'adds primitive at next numeric index');
+ var merged = utils.merge(overflow, 'd');
+ s2t.deepEqual(merged, { 0: 'a', 1: 'b', 2: 'c', 3: 'd' }, 'adds primitive at next numeric index');
s2t.end();
});
@@ -94,21 +96,21 @@ test('merge()', function (t) {
});
st.test('merges overflow object into primitive', function (s2t) {
- // Create an overflow object via combine
- var overflow = utils.combine([], 'b', 0, false);
+ // Create an overflow object via combine: 2 elements (indices 0-1) with limit 0
+ var overflow = utils.combine(['a'], 'b', 0, false);
s2t.ok(utils.isOverflow(overflow), 'overflow object is marked');
- var merged = utils.merge('a', overflow);
+ var merged = utils.merge('c', overflow);
s2t.ok(utils.isOverflow(merged), 'result is also marked as overflow');
- s2t.deepEqual(merged, { 0: 'a', 1: 'b' }, 'creates object with primitive at 0, source values shifted');
+ s2t.deepEqual(merged, { 0: 'c', 1: 'a', 2: 'b' }, 'creates object with primitive at 0, source values shifted');
s2t.end();
});
st.test('merges overflow object with multiple values into primitive', function (s2t) {
- // Create an overflow object via combine
- var overflow = utils.combine(['b'], 'c', 1, false);
+ // Create an overflow object via combine: 3 elements (indices 0-2) with limit 0
+ var overflow = utils.combine(['b', 'c'], 'd', 0, false);
s2t.ok(utils.isOverflow(overflow), 'overflow object is marked');
var merged = utils.merge('a', overflow);
- s2t.deepEqual(merged, { 0: 'a', 1: 'b', 2: 'c' }, 'shifts all source indices by 1');
+ s2t.deepEqual(merged, { 0: 'a', 1: 'b', 2: 'c', 3: 'd' }, 'shifts all source indices by 1');
s2t.end();
});
@@ -196,7 +198,7 @@ test('combine()', function (t) {
st.test('exactly at the limit stays as array', function (s2t) {
var combined = utils.combine(['a', 'b'], 'c', 3, false);
- s2t.deepEqual(combined, ['a', 'b', 'c'], 'stays as array when exactly at limit');
+ s2t.deepEqual(combined, ['a', 'b', 'c'], 'stays as array when count equals limit');
s2t.ok(Array.isArray(combined), 'result is an array');
s2t.end();
});
@@ -208,16 +210,30 @@ test('combine()', function (t) {
s2t.end();
});
- st.test('with arrayLimit 0', function (s2t) {
+ st.test('with arrayLimit 1', function (s2t) {
+ var combined = utils.combine([], 'a', 1, false);
+ s2t.deepEqual(combined, ['a'], 'stays as array when count equals limit');
+ s2t.ok(Array.isArray(combined), 'result is an array');
+ s2t.end();
+ });
+
+ st.test('with arrayLimit 0 converts single element to object', function (s2t) {
var combined = utils.combine([], 'a', 0, false);
- s2t.deepEqual(combined, { 0: 'a' }, 'converts single element to object with arrayLimit 0');
+ s2t.deepEqual(combined, { 0: 'a' }, 'converts to object when count exceeds limit');
+ s2t.notOk(Array.isArray(combined), 'result is not an array');
+ s2t.end();
+ });
+
+ st.test('with arrayLimit 0 and two elements converts to object', function (s2t) {
+ var combined = utils.combine(['a'], 'b', 0, false);
+ s2t.deepEqual(combined, { 0: 'a', 1: 'b' }, 'converts to object when count exceeds limit');
s2t.notOk(Array.isArray(combined), 'result is not an array');
s2t.end();
});
st.test('with plainObjects option', function (s2t) {
- var combined = utils.combine(['a'], 'b', 1, true);
- var expected = { __proto__: null, 0: 'a', 1: 'b' };
+ var combined = utils.combine(['a', 'b'], 'c', 1, true);
+ var expected = { __proto__: null, 0: 'a', 1: 'b', 2: 'c' };
s2t.deepEqual(combined, expected, 'converts to object with null prototype');
s2t.equal(Object.getPrototypeOf(combined), null, 'result has null prototype when plainObjects is true');
s2t.end();
@@ -228,13 +244,13 @@ test('combine()', function (t) {
t.test('with existing overflow object', function (st) {
st.test('adds to existing overflow object at next index', function (s2t) {
- // Create overflow object first via combine
- var overflow = utils.combine(['a'], 'b', 1, false);
+ // Create overflow object first via combine: 3 elements (indices 0-2) with limit 0
+ var overflow = utils.combine(['a', 'b'], 'c', 0, false);
s2t.ok(utils.isOverflow(overflow), 'initial object is marked as overflow');
- var combined = utils.combine(overflow, 'c', 10, false);
+ var combined = utils.combine(overflow, 'd', 10, false);
s2t.equal(combined, overflow, 'returns the same object (mutated)');
- s2t.deepEqual(combined, { 0: 'a', 1: 'b', 2: 'c' }, 'adds value at next numeric index');
+ s2t.deepEqual(combined, { 0: 'a', 1: 'b', 2: 'c', 3: 'd' }, 'adds value at next numeric index');
s2t.end();
});
DescriptionThis pull request makes changes across various files to enhance the
Possible IssuesNo apparent major issues, the code changes seem to address limit handling, documentation, and test coverage thoroughly. However, increasing Security Hotspots
Privacy HotspotsNone identified. ChangesChanges
The provided code changes make the |
Bumps qs from 6.14.1 to 6.14.2.
Changelog
Sourced from qs's changelog.
Commits
bdcf0c7v6.14.2294db90[readme] document thataddQueryPrefixdoes not add?to empty output5c308e5[readme] clarifyparseArraysandarrayLimitdocumentation6addf8c[Fix]parse: mark overflow objects for indexed notation exceedingarrayLimitcfc108f[Fix]arrayLimitmeans max count, not max index, incombine/merge/`pars...febb644[Fix]parse: throw onarrayLimitexceeded with indexed notation when `thr...f6a7abf[Fix]parse: enforcearrayLimitoncomma-parsed valuesfbc5206[Fix]parse: fix error message to reflect arrayLimit as max index; remove e...1b9a8b4[actions] fix rebase workflow permissions2a35775[meta] fix changelog typo (arrayLength→arrayLimit)Dependabot will resolve any conflicts with this PR as long as you don't alter it yourself. You can also trigger a rebase manually by commenting
@dependabot rebase.Dependabot commands and options
You can trigger Dependabot actions by commenting on this PR:
@dependabot rebasewill rebase this PR@dependabot recreatewill recreate this PR, overwriting any edits that have been made to it@dependabot show <dependency name> ignore conditionswill show all of the ignore conditions of the specified dependency@dependabot ignore this major versionwill close this PR and stop Dependabot creating any more for this major version (unless you reopen the PR or upgrade to it yourself)@dependabot ignore this minor versionwill close this PR and stop Dependabot creating any more for this minor version (unless you reopen the PR or upgrade to it yourself)@dependabot ignore this dependencywill close this PR and stop Dependabot creating any more for this dependency (unless you reopen the PR or upgrade to it yourself)You can disable automated security fix PRs for this repo from the Security Alerts page.