alle new
This commit is contained in:
erik committed 2026-10-01 06:46:51 +02:00
1 parent da64472251
commit 5b20adee48
1605 files changed
+396517 -1674

No files matched your search

Generated Vendored
BIN
View File
Binary file not shown.
+3 -3
View File
@@ -25,7 +25,7 @@ Caller Application → qs.stringify(obj, options) → Stringifying Engine → Ou
**Trust Boundaries:**
- **Input string (parse):** May come from untrusted sources (e.g., user input, network requests)
- **Input object (stringify):** May contain cycles, which can lead to infinite loops during stringification
- **Input object (stringify):** The calling application's own data, not a direct untrusted channel. May contain cycles (handled by the cycle detector). Deeply-nested non-cyclic input surfaces as a catchable synchronous `RangeError` (stack overflow), not unbounded resource consumption; callers that serialize externally-influenced objects should bound their depth/size beforehand.
- **Options:** Provided by the caller
- **Cycle Tracking:** Used only during stringification to detect and handle circular references
@@ -58,7 +58,7 @@ Caller Application → qs.stringify(obj, options) → Stringifying Engine → Ou
|---------------------------------------------------|---------------------|
| Tampering (malicious input, prototype pollution) | Strict input validation; keep `allowPrototypes: false` by default; use `plainObjects` for output; ensure builtins/globals are never modified by parse[4][8]. |
| Information Disclosure (error messages) | Generic error messages without stack traces or internal paths. |
| Denial of Service (memory/CPU exhaustion) | Enforce `arrayLimit` and `parameterLimit` with safe defaults; enable `throwOnLimitExceeded`; limit nesting depth[7]. |
| Denial of Service (memory/CPU exhaustion) | `arrayLimit`, `parameterLimit`, and depth limiting apply with safe defaults. Note that `arrayLimit` is a representation threshold (array vs. object), and `parameterLimit` bounds only the number of `&`-delimited parameters - neither caps the elements produced by `comma: true` splitting. For a hard cap that rejects oversized untrusted input, opt in to `throwOnLimitExceeded: true` (default `false`), and always bound input size at the transport layer[7]. On the `stringify` side, the input is the caller's own object rather than an untrusted string, so unbounded nesting manifests as a catchable `RangeError` (stack overflow) rather than exhaustion; callers serializing externally-influenced objects should bound depth/size beforehand, and may opt into `stringify`'s `depth` option (default `Infinity`) for a deterministic, catchable error. |
| Elevation of Privilege (prototype pollution) | Keep `allowPrototypes: false`; validate options against allowlist; use `plainObjects` to avoid prototype pollution[4][8]. |
### 7. Risk Ranking
@@ -70,7 +70,7 @@ Caller Application → qs.stringify(obj, options) → Stringifying Engine → Ou
### 8. Next Steps & Review
1. **Audit option validation logic.**
2. **Add depth limiting to nested parsing and stringification.**
2. **Depth limiting:** `parse` enforces a `depth` bound by default (with `strictDepth` to throw); `stringify` offers an opt-in `depth` bound (default `Infinity`, since its input is caller-produced) for defense-in-depth.
3. **Implement fuzz testing for parser and stringifier edge cases.**
4. **Regularly review dependencies for vulnerabilities.**
5. **Keep documentation and threat model up to date.**
+15
View File
@@ -1,3 +1,18 @@
## **6.16.0**
- [New] `stringify`: add a `depth` option to bound recursion depth (default `Infinity`)
- [Fix] stringify: serialize Date values when a filter is provided
- [Fix] `parse`: enforce `arrayLimit` on comma groups under `[]=` when `throwOnLimitExceeded` is set
- [Fix] `parse`: flatten a collection appended to an overflowed array (#571)
- [Fix] `utils`: `isBuffer`: do not invoke a non-callable `constructor.isBuffer`
- [Fix] `stringify`: do not let `allowEmptyArrays` skip cycle detection (or drop own keys) on an empty array with own properties
- [Fix] `stringify`: encode dots in a top-level key with a primitive value when encodeDotInKeys is set (#562)
- [Docs] threat model: clarify `stringify` deep-nesting DoS is caller-bounded
- [Docs] clarify `arrayLimit` is a representation threshold, not an element-count cap
- [Tests] `parse`: remove a test that pinned `[]=` comma groups escaping `arrayLimit`
- [Tests] `stringify`: pin current `encodeDotInKeys` separator-dot behavior
- [Dev Deps] update `@ljharb/eslint-config`, `eslint`
- [Dev Deps] update `eslint`, `evalmd`
## **6.15.3**
- [Fix] `parse`: enforce `throwOnLimitExceeded` for cumulative array growth via `combine`/`merge`
- [Fix] `utils`: respect encoding of surrogate pairs across chunks (#559)
Generated Vendored
+19 -1
View File
@@ -147,6 +147,8 @@ try {
When `throwOnLimitExceeded` is set to `false` (default), **qs** will parse up to the specified `parameterLimit` and ignore the rest without throwing an error.
Note that `parameterLimit` only bounds the number of `&`-delimited parameters; it does not limit how many values a single parameter expands into. In particular, when `comma: true` is enabled, a single parameter's value is split on commas into arbitrarily many elements, which `parameterLimit` does not constrain. To bound the total element count from untrusted input, set `throwOnLimitExceeded: true` (see `arrayLimit` below), and always bound the input size at the transport layer (e.g. an HTTP body-size limit).
To bypass the leading question mark, use `ignoreQueryPrefix`:
```javascript
@@ -313,7 +315,9 @@ 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
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.
Note that `arrayLimit` is a *representation* threshold that controls when a numerically-indexed collection switches from an array to an object — it is **not** a hard cap on the total number of elements parsed. With the default `throwOnLimitExceeded: false`, exceeding `arrayLimit` never rejects or truncates input; it only changes the container type, and the resulting object still holds every element (so its size stays proportional to the input). This conversion is itself a safeguard: it avoids allocating a huge sparse array for input like `a[999999999]`. If you need a hard limit that rejects oversized input from untrusted sources, set `throwOnLimitExceeded: true`.
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).
@@ -410,6 +414,20 @@ var encoded = qs.stringify({ a: { b: 'c' } }, { encoder: function (str) {
_(Note: the `encoder` option does not apply if `encode` is `false`)_
By default, `qs.stringify` serializes an object of any nesting depth.
For backwards compatibility, and because its input is the caller's own object rather than a query string parsed by **qs**, this is unbounded.
If you serialize objects whose nesting can be influenced by untrusted input, bound it with the numeric `depth` option (default `Infinity`);
exceeding it throws a catchable `RangeError` instead of eventually overflowing the call stack:
```javascript
try {
qs.stringify({ a: { b: { c: { d: 'e' } } } }, { depth: 2 });
} catch (err) {
assert(err instanceof RangeError);
assert.strictEqual(err.message, 'Input depth exceeded depth option of 2');
}
```
Analogue to the `encoder` there is a `decoder` option for `parse` to override decoding of properties and values:
```javascript
Generated Vendored
+21 -21
View File
@@ -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,strictMerge:!0,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,i){if(e&&"string"==typeof e&&t.comma&&e.indexOf(",")>-1){if(i&&t.throwOnLimitExceeded)for(var a=0,o=e.indexOf(",");o>-1;){if((a+=1)>=t.arrayLimit)throw new RangeError("Array limit exceeded. Only "+t.arrayLimit+" element"+(1===t.arrayLimit?"":"s")+" allowed in an array.");o=e.indexOf(",",o+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&&void 0!==a?a+1:a);if(t.throwOnLimitExceeded&&void 0!==a&&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,c,p=o[l],u=p.indexOf("]="),y=-1===u?p.indexOf("="):u+1;if(-1===y?(d=t.decoder(p,defaults.decoder,s,"key"),c=t.strictNullHandling?null:""):null!==(d=t.decoder(p.slice(0,y),defaults.decoder,s,"key"))&&(c=utils.maybeMap(parseArrayValue(p.slice(y+1),t,isArray(r[d])?r[d].length:0,-1===p.indexOf("[]=")),function(e){return t.decoder(e,defaults.decoder,s,"value")})),c&&t.interpretNumericEntities&&"iso-8859-1"===s&&(c=interpretNumericEntities(String(c))),p.indexOf("[]=")>-1&&(c=isArray(c)?[c]:c),t.comma&&isArray(c)&&c.length>t.arrayLimit&&(c=utils.combine([],c,t.arrayLimit,t.plainObjects,t.throwOnLimitExceeded)),null!==d){var f=has.call(r,d);f&&("combine"===t.duplicates||p.indexOf("[]=")>-1)?r[d]=utils.combine(r[d],c,t.arrayLimit,t.plainObjects,t.throwOnLimitExceeded):f&&"last"!==t.duplicates||(r[d]=c)}}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,r.throwOnLimitExceeded);else{s=r.plainObjects?{__proto__:null}:{};var c="["===d.charAt(0)&&"]"===d.charAt(d.length-1)?d.slice(1,-1):d,p=r.decodeDotInKeys?c.replace(/%2E/g,"."):c,u=parseInt(p,10),y=!isNaN(u)&&d!==p&&String(u)===p&&u>=0&&r.parseArrays;if(r.parseArrays||""!==p)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__"!==p&&(s[p]=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=[],a=r.indexOf("["),o=a>=0?r.slice(0,a):r;if(o){if(!t.plainObjects&&has.call(Object.prototype,o)&&!t.allowPrototypes)return;i[i.length]=o}for(var l=r.length,n=a,s=0;n>=0&&s<t.depth;){for(var d=1,c=n+1,p=-1;c<l&&p<0;){var u=r.charCodeAt(c);91===u?d+=1:93===u&&0==(d-=1)&&(p=c),c+=1}if(p<0)return i[i.length]="["+r.slice(n)+"]",i;var y=r.slice(n,p+1),f=y.slice(1,-1);if(!t.plainObjects&&has.call(Object.prototype,f)&&!t.allowPrototypes)return;i[i.length]=y,s+=1,n=r.indexOf("[",p+1)}if(n>=0){if(!0===t.strictDepth)throw new RangeError("Input depth exceeded depth option of "+t.depth+" and strictDepth is true");i[i.length]="["+r.slice(n)+"]"}return i},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.Line truncated
"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,strictMerge:!0,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){if(t.throwOnLimitExceeded)for(var i=0,a=e.indexOf(",");a>-1;){if((i+=1)>=t.arrayLimit)throw new RangeError("Array limit exceeded. Only "+t.arrayLimit+" element"+(1===t.arrayLimit?"":"s")+" allowed in an array.");a=e.indexOf(",",a+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&&void 0!==a?a+1:a);if(t.throwOnLimitExceeded&&void 0!==a&&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,c,p=o[l],u=p.indexOf("]="),y=-1===u?p.indexOf("="):u+1;if(-1===y?(d=t.decoder(p,defaults.decoder,s,"key"),c=t.strictNullHandling?null:""):null!==(d=t.decoder(p.slice(0,y),defaults.decoder,s,"key"))&&(c=utils.maybeMap(parseArrayValue(p.slice(y+1),t,isArray(r[d])?r[d].length:0),function(e){return t.decoder(e,defaults.decoder,s,"value")})),c&&t.interpretNumericEntities&&"iso-8859-1"===s&&(c=interpretNumericEntities(String(c))),p.indexOf("[]=")>-1&&(c=isArray(c)?[c]:c),t.comma&&isArray(c)&&c.length>t.arrayLimit&&(c=utils.combine([],c,t.arrayLimit,t.plainObjects,t.throwOnLimitExceeded)),null!==d){var f=has.call(r,d);f&&("combine"===t.duplicates||p.indexOf("[]=")>-1)?r[d]=utils.combine(r[d],c,t.arrayLimit,t.plainObjects,t.throwOnLimitExceeded):f&&"last"!==t.duplicates||(r[d]=c)}}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,r.throwOnLimitExceeded);else{s=r.plainObjects?{__proto__:null}:{};var c="["===d.charAt(0)&&"]"===d.charAt(d.length-1)?d.slice(1,-1):d,p=r.decodeDotInKeys?c.replace(/%2E/g,"."):c,u=parseInt(p,10),y=!isNaN(u)&&d!==p&&String(u)===p&&u>=0&&r.parseArrays;if(r.parseArrays||""!==p)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__"!==p&&(s[p]=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=[],a=r.indexOf("["),o=a>=0?r.slice(0,a):r;if(o){if(!t.plainObjects&&has.call(Object.prototype,o)&&!t.allowPrototypes)return;i[i.length]=o}for(var l=r.length,n=a,s=0;n>=0&&s<t.depth;){for(var d=1,c=n+1,p=-1;c<l&&p<0;){var u=r.charCodeAt(c);91===u?d+=1:93===u&&0==(d-=1)&&(p=c),c+=1}if(p<0)return i[i.length]="["+r.slice(n)+"]",i;var y=r.slice(n,p+1),f=y.slice(1,-1);if(!t.plainObjects&&has.call(Object.prototype,f)&&!t.allowPrototypes)return;i[i.length]=y,s+=1,n=r.indexOf("[",p+1)}if(n>=0){if(!0===t.strictDepth)throw new RangeError("Input depth exceeded depth option of "+t.depth+" and strictDepth is true");i[i.length]="["+r.slice(n)+"]"}return i},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.decoderLine truncated
},{"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 p(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,function(e){return null==e?e:s(e)})),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"Line truncated
"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:"&",depth:1/0,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,n,a,i,l,s,f,u,d,y,c,p,m,h,v,g,w){var b=e;if(w>g)throw new RangeError("Input depth exceeded depth option of "+g);for(var D=v,A=0,S=!1;void 0!==(D=D.get(sentinel))&&!S;){var E=D.get(e);if(A+=1,void 0!==E){if(E===A)throw new RangeError("Cyclic object value");S=!0}void 0===D.get(sentinel)&&(A=0)}if((b="function"==typeof f?f(r,b):b)instanceof Date?b=y(b):"comma"===t&&isArray(b)&&(b=utils.maybeMap(b,function(e){return e instanceof Date?y(e):e})),null===b){if(a)return p(s&&!m?s(r,defaults.encoder,h,"key",c):r);b=""}if(isNonNullishPrimitive(b)||utils.isBuffer(b))return s?[p(m?r:s(r,defaults.encoder,h,"key",c))+"="+p(s(b,defaults.encoder,h,"value",c))]:[p(r)+"="+p(String(b))];var N,O=[];if(void 0===b)return O;if("comma"===t&&isArray(b))m&&s&&(b=utils.maybeMap(b,function(e){return null==e?e:s(e)})),N=[{value:b.length>0?b.join(",")||null:void 0}];else if(isArray(f))N=f;else{var T=Object.keys(b);N=u?T.sort(u):T}var k=l?String(r).replace(/\./g,"%2E"):String(r),I=o&&isArray(b)&&1===b.length?k+"[]":k;if(n&&isArray(b)&&0===b.length&&0===Object.keys(b).length)return I+"[]";for(var P=0;P<N.length;++P){var x=N[P],K="object"==typeof x&&x&&void 0!==x.value?x.value:b[x];if(!i||null!==K){var z=d&&l?String(x).replace(/\./g,"%2E"):String(x),j=isArray(b)?"function"==typeof t?t(I,z):I:I+(d?"."+z:"["+z+"]");v.set(e,A);var F=getSideChannel();F.set(sentinel,v),pushToArray(O,stringify(K,j,t,o,n,a,i,l,"comma"===t&&m&&isArray(b)?null:s,f,u,d,y,c,p,m,h,F,g,w+1))}}return O},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,n=formats.formatters[t],a=defaults.filter;if(("function"==typeof e.filter||isArray(e.filter))&&(a=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,depth:"number"==typeof e.depth?e.depth:defaults.depth,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:a,format:t,formatter:n,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.strictNullHandlLine truncated
},{"1":1,"46":46,"5":5}],5:[function(require,module,exports){
"use strict";var formats=require(1),getSideChannel=require(46),defineProperty=require(14),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=[],a=0;a<t.length;++a)void 0!==t[a]&&(n[n.length]=t[a]);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},setProperty=function setProperty(e,r,t){"__proto__"===r&&defineProperty?defineProperty(e,r,{configurable:!0,enumerable:!0,value:t,writable:!0}):e[r]=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){if(t.throwOnLimitExceeded)throw new RangeError("Array limit exceeded. Only "+t.arrayLimit+" element"+(1===t.arrayLimit?"":"s")+" allowed in an array.");return markOverflow(arrayToObject(e.concat(r),t),n)}e[n]=r}else{if(!e||"object"!=typeof e)return[e,r];if(isOverflow(e)){var a=getMaxIndex(e)+1;e[a]=r,setMaxIndex(e,a)}else{if(t&&t.strictMerge)return[e,r];(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 o=Object.keys(r),i=t&&t.plainObjects?{__proto__:null,0:e}:{0:e},l=0;l<o.length;l++)i[parseInt(o[l],10)+1]=r[o[l]];return markOverflow(i,getMaxIndex(r)+1)}var c=[e].concat(r);if(t&&"number"==typeof t.arrayLimit&&c.length>t.arrayLimit){if(t.throwOnLimitExceeded)throw new RangeError("Array limit exceeded. Only "+t.arrayLimit+" element"+(1===t.arrayLimit?"":"s")+" allowed in an array.");return markOverflow(arrayToObject(c,t),c.length-1)}return c}var f=e;if(isArray(e)&&!isArray(r)&&(f=arrayToObject(e,t)),isArray(e)&&isArray(r)){if(r.forEach(function(r,n){if(has.call(e,n)){var a=e[n];a&&"object"==typeof a&&r&&"object"==typeof r?e[n]=merge(a,r,t):e[e.length]=r}else e[n]=r}),t&&"number"==typeof t.arrayLimit&&e.length>t.arrayLimit){if(t.throwOnLimitExceeded)throw new RangeError("Array limit exceeded. Only "+t.arrayLimit+" element"+(1===t.arrayLimit?"":"s")+" allowed in an array.");return markOverflow(arrayToObject(e,t),e.length-1)}return e}return Object.keys(r).reduce(function(e,n){var a=r[n];if(has.call(e,n)?setProperty(e,n,merge(e[n],a,t)):setProperty(e,n,a),isOverflow(r)&&!isOverflow(e)&&markOverflow(e,getMaxIndex(r)),isOverflow(e)){var o=parseInt(n,10);String(o)===n&&o>=0&&o>getMaxIndex(e)&&setMaxIndex(e,o)}return e},f)},assign=function assignSingleSource(e,r){return Object.keys(r).reduce(function(e,t){return setProperty(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,a){if(0===e.length)return e;var o=e;if("symbol"==typeof e?o=Symbol.prototype.toString.call(e):"string"!=typeof e&&(o=String(e)),"iso-8859-1"===t)return escape(o).replace(/%u[0-9a-f]{4}/gi,function(e){return"%26%23"+parseInt(e.slice(2),16)+"%3B"});for(var i="",l=0;l<o.length;l+=limit){var c=o.length>=limit?o.slice(l,l+limit):o;if(l+limit<o.length){var f=c.charCodeAt(c.length-1);f>=55296&&f<=56319&&(c=c.slice(0,-1),l-=1)}for(var s=[],u=0;u<c.length;++u){var y=c.charCodeAt(u);45===y||46===y||95===y||126===y||y>=48&&y<=57||y>=65&&y<=90||y>=97&&y<=122||a===formats.RFC1738&&(40===y||41===y)?s[s.length]=c.charAt(u):y<128?s[s.length]=hexTable[y]:y<2048?s[s.length]=hexTable[192|y>>6]+hexTable[128|63&y]:y<55296||y>=57344?s[s.length]=hexTable[224|y>>12]+hexTable[128|y>>6&63]+hexTable[128|63&y]:(u+=1,y=65536+((1023&y)<<10|1023&c.charCodeAt(u)),s[s.length]=hexTable[240|y>>18]+hexTable[128|y>>12&63]+hexTable[128|y>>6&63]+hexTable[128|63&y])}i+=s.join("")}return i},compact=function compact(e){for(var r=[{obj:{o:e},prop:"o"}],t=getSideChannel(),n=0;n<r.length;++n)for(var a=r[n],o=a.obj[a.prop],i=Object.keys(o),l=0;l<i.length;++l){var c=i[l],f=o[c];"object"!=typeof f||null===f||t.has(f)||(r[r.length]={obj:o,prop:c},t.set(f,!0))}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,a){if(isOverflow(e)){if(a)throw new RangeError("Array limit exceeded. Only "+t+" element"+(1===t?"":"s")+" allowed in an array.");var o=getMaxIndex(e)+1;return e[o]=r,setMaxIndex(e,o),e}var i=Line truncated
"use strict";var formats=require(1),getSideChannel=require(46),defineProperty=require(14),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=[],a=0;a<t.length;++a)void 0!==t[a]&&(n[n.length]=t[a]);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},setProperty=function setProperty(e,r,t){"__proto__"===r&&defineProperty?defineProperty(e,r,{configurable:!0,enumerable:!0,value:t,writable:!0}):e[r]=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){if(t.throwOnLimitExceeded)throw new RangeError("Array limit exceeded. Only "+t.arrayLimit+" element"+(1===t.arrayLimit?"":"s")+" allowed in an array.");return markOverflow(arrayToObject(e.concat(r),t),n)}e[n]=r}else{if(!e||"object"!=typeof e)return[e,r];if(isOverflow(e)){var a=getMaxIndex(e)+1;e[a]=r,setMaxIndex(e,a)}else{if(t&&t.strictMerge)return[e,r];(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 o=Object.keys(r),i=t&&t.plainObjects?{__proto__:null,0:e}:{0:e},l=0;l<o.length;l++)i[parseInt(o[l],10)+1]=r[o[l]];return markOverflow(i,getMaxIndex(r)+1)}var c=[e].concat(r);if(t&&"number"==typeof t.arrayLimit&&c.length>t.arrayLimit){if(t.throwOnLimitExceeded)throw new RangeError("Array limit exceeded. Only "+t.arrayLimit+" element"+(1===t.arrayLimit?"":"s")+" allowed in an array.");return markOverflow(arrayToObject(c,t),c.length-1)}return c}var f=e;if(isArray(e)&&!isArray(r)&&(f=arrayToObject(e,t)),isArray(e)&&isArray(r)){if(r.forEach(function(r,n){if(has.call(e,n)){var a=e[n];a&&"object"==typeof a&&r&&"object"==typeof r?e[n]=merge(a,r,t):e[e.length]=r}else e[n]=r}),t&&"number"==typeof t.arrayLimit&&e.length>t.arrayLimit){if(t.throwOnLimitExceeded)throw new RangeError("Array limit exceeded. Only "+t.arrayLimit+" element"+(1===t.arrayLimit?"":"s")+" allowed in an array.");return markOverflow(arrayToObject(e,t),e.length-1)}return e}return Object.keys(r).reduce(function(e,n){var a=r[n];if(has.call(e,n)?setProperty(e,n,merge(e[n],a,t)):setProperty(e,n,a),isOverflow(r)&&!isOverflow(e)&&markOverflow(e,getMaxIndex(r)),isOverflow(e)){var o=parseInt(n,10);String(o)===n&&o>=0&&o>getMaxIndex(e)&&setMaxIndex(e,o)}return e},f)},assign=function assignSingleSource(e,r){return Object.keys(r).reduce(function(e,t){return setProperty(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,a){if(0===e.length)return e;var o=e;if("symbol"==typeof e?o=Symbol.prototype.toString.call(e):"string"!=typeof e&&(o=String(e)),"iso-8859-1"===t)return escape(o).replace(/%u[0-9a-f]{4}/gi,function(e){return"%26%23"+parseInt(e.slice(2),16)+"%3B"});for(var i="",l=0;l<o.length;l+=limit){var c=o.length>=limit?o.slice(l,l+limit):o;if(l+limit<o.length){var f=c.charCodeAt(c.length-1);f>=55296&&f<=56319&&(c=c.slice(0,-1),l-=1)}for(var s=[],u=0;u<c.length;++u){var y=c.charCodeAt(u);45===y||46===y||95===y||126===y||y>=48&&y<=57||y>=65&&y<=90||y>=97&&y<=122||a===formats.RFC1738&&(40===y||41===y)?s[s.length]=c.charAt(u):y<128?s[s.length]=hexTable[y]:y<2048?s[s.length]=hexTable[192|y>>6]+hexTable[128|63&y]:y<55296||y>=57344?s[s.length]=hexTable[224|y>>12]+hexTable[128|y>>6&63]+hexTable[128|63&y]:(u+=1,y=65536+((1023&y)<<10|1023&c.charCodeAt(u)),s[s.length]=hexTable[240|y>>18]+hexTable[128|y>>12&63]+hexTable[128|y>>6&63]+hexTable[128|63&y])}i+=s.join("")}return i},compact=function compact(e){for(var r=[{obj:{o:e},prop:"o"}],t=getSideChannel(),n=0;n<r.length;++n)for(var a=r[n],o=a.obj[a.prop],i=Object.keys(o),l=0;l<i.length;++l){var c=i[l],f=o[c];"object"!=typeof f||null===f||t.has(f)||(r[r.length]={obj:o,prop:c},t.set(f,!0))}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||"function"!=typeof e.constructor.isBuffer||!e.constructor.isBuffer(e))},combine=function combine(e,r,t,n,a){if(isOverflow(e)){if(a)throw new RangeError("Array limit exceeded. Only "+t+" element"+(1===t?"":"s")+" allowed in an array.");for(var o=isArray(r)?r:[r],i=getMaxIndex(e),Line truncated
},{"1":1,"14":14,"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)){var t=e&&Object(e)===e?"the given object key":inspect(e);throw new $TypeError("Side channel does not contain "+t)}},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};
@@ -24,12 +24,12 @@
},{}],7:[function(require,module,exports){
"use strict";var bind=require(24),$apply=require(8),$call=require(9),$reflectApply=require(11);module.exports=$reflectApply||bind.call($call,$apply);
},{"11":11,"24":24,"8":8,"9":9}],9:[function(require,module,exports){
"use strict";module.exports=Function.prototype.call;
},{}],8:[function(require,module,exports){
},{"11":11,"24":24,"8":8,"9":9}],8:[function(require,module,exports){
"use strict";module.exports=Function.prototype.apply;
},{}],9:[function(require,module,exports){
"use strict";module.exports=Function.prototype.call;
},{}],24:[function(require,module,exports){
"use strict";var implementation=require(23);module.exports=Function.prototype.bind||implementation;
@@ -78,23 +78,23 @@
},{}],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;
},{}],40:[function(require,module,exports){
"use strict";module.exports=Math.round;
},{}],35:[function(require,module,exports){
"use strict";module.exports=Math.floor;
},{}],34:[function(require,module,exports){
"use strict";module.exports=Math.abs;
},{}],38:[function(require,module,exports){
"use strict";module.exports=Math.min;
},{}],37:[function(require,module,exports){
"use strict";module.exports=Math.max;
},{}],39:[function(require,module,exports){
"use strict";module.exports=Math.pow;
},{}],35:[function(require,module,exports){
"use strict";module.exports=Math.floor;
},{}],40:[function(require,module,exports){
"use strict";module.exports=Math.round;
},{}],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;
@@ -102,13 +102,13 @@
},{}],26:[function(require,module,exports){
"use strict";var $Object=require(22);module.exports=$Object.getPrototypeOf||null;
},{"22":22}],33:[function(require,module,exports){
"use strict";var call=Function.prototype.call,$hasOwn=Object.prototype.hasOwnProperty,bind=require(24);module.exports=bind.call(call,$hasOwn);
},{"24":24}],41:[function(require,module,exports){
},{"22":22}],41:[function(require,module,exports){
"use strict";var $isNaN=require(36);module.exports=function sign(i){return $isNaN(i)||0===i?i:i<0?-1:1};
},{"36":36}],31:[function(require,module,exports){
},{"36":36}],33:[function(require,module,exports){
"use strict";var call=Function.prototype.call,$hasOwn=Object.prototype.hasOwnProperty,bind=require(24);module.exports=bind.call(call,$hasOwn);
},{"24":24}],31:[function(require,module,exports){
"use strict";var origSymbol="undefined"!=typeof Symbol&&Symbol,hasSymbolSham=require(32);module.exports=function hasNativeSymbols(){return"function"==typeof origSymbol&&"function"==typeof Symbol&&"symbol"==typeof origSymbol("foo")&&"symbol"==typeof Symbol("bar")&&hasSymbolSham()};
},{"32":32}],28:[function(require,module,exports){
+1 -1
View File
@@ -27,7 +27,7 @@ export default [
'error',
{ max: 150 },
],
'max-params': ['error', 18],
'max-params': ['error', 20],
'max-statements': ['error', 100],
'multiline-comment-style': 'off',
'no-continue': 'warn',
+3 -4
View File
@@ -36,9 +36,9 @@ var interpretNumericEntities = function (str) {
});
};
var parseArrayValue = function (val, options, currentArrayLength, isFlatArrayValue) {
var parseArrayValue = function (val, options, currentArrayLength) {
if (val && typeof val === 'string' && options.comma && val.indexOf(',') > -1) {
if (isFlatArrayValue && options.throwOnLimitExceeded) {
if (options.throwOnLimitExceeded) {
var commaCount = 0;
var commaIndex = val.indexOf(',');
while (commaIndex > -1) {
@@ -125,8 +125,7 @@ var parseValues = function parseQueryStringValues(str, options) {
parseArrayValue(
part.slice(pos + 1),
options,
isArray(obj[key]) ? obj[key].length : 0,
part.indexOf('[]=') === -1
isArray(obj[key]) ? obj[key].length : 0
),
function (encodedVal) {
return options.decoder(encodedVal, defaults.decoder, charset, 'value');
+23 -8
View File
@@ -36,6 +36,7 @@ var defaults = {
charsetSentinel: false,
commaRoundTrip: false,
delimiter: '&',
depth: Infinity,
encode: true,
encodeDotInKeys: false,
encoder: utils.encode,
@@ -80,10 +81,16 @@ var stringify = function stringify(
formatter,
encodeValuesOnly,
charset,
sideChannel
sideChannel,
depth,
currentDepth
) {
var obj = object;
if (currentDepth > depth) {
throw new RangeError('Input depth exceeded depth option of ' + depth);
}
var tmpSc = sideChannel;
var step = 0;
var findFlag = false;
@@ -103,9 +110,9 @@ var stringify = function stringify(
}
}
if (typeof filter === 'function') {
obj = filter(prefix, obj);
} else if (obj instanceof Date) {
obj = typeof filter === 'function' ? filter(prefix, obj) : obj;
if (obj instanceof Date) {
obj = serializeDate(obj);
} else if (generateArrayPrefix === 'comma' && isArray(obj)) {
obj = utils.maybeMap(obj, function (value) {
@@ -158,7 +165,7 @@ var stringify = function stringify(
var adjustedPrefix = commaRoundTrip && isArray(obj) && obj.length === 1 ? encodedPrefix + '[]' : encodedPrefix;
if (allowEmptyArrays && isArray(obj) && obj.length === 0) {
if (allowEmptyArrays && isArray(obj) && obj.length === 0 && Object.keys(obj).length === 0) {
return adjustedPrefix + '[]';
}
@@ -198,7 +205,9 @@ var stringify = function stringify(
formatter,
encodeValuesOnly,
charset,
valueSideChannel
valueSideChannel,
depth,
currentDepth + 1
));
}
@@ -265,6 +274,7 @@ var normalizeStringifyOptions = function normalizeStringifyOptions(opts) {
charsetSentinel: typeof opts.charsetSentinel === 'boolean' ? opts.charsetSentinel : defaults.charsetSentinel,
commaRoundTrip: !!opts.commaRoundTrip,
delimiter: typeof opts.delimiter === 'undefined' ? defaults.delimiter : opts.delimiter,
depth: typeof opts.depth === 'number' ? opts.depth : defaults.depth,
encode: typeof opts.encode === 'boolean' ? opts.encode : defaults.encode,
encodeDotInKeys: typeof opts.encodeDotInKeys === 'boolean' ? opts.encodeDotInKeys : defaults.encodeDotInKeys,
encoder: typeof opts.encoder === 'function' ? opts.encoder : defaults.encoder,
@@ -324,9 +334,12 @@ module.exports = function (object, opts) {
if (options.skipNulls && value === null) {
continue;
}
var encodedKey = options.encodeDotInKeys ? String(key).replace(/\./g, '%2E') : String(key);
pushToArray(keys, stringify(
value,
key,
encodedKey,
generateArrayPrefix,
commaRoundTrip,
options.allowEmptyArrays,
@@ -342,7 +355,9 @@ module.exports = function (object, opts) {
options.formatter,
options.encodeValuesOnly,
options.charset,
sideChannel
sideChannel,
options.depth,
0
));
}
+10 -3
View File
@@ -329,7 +329,7 @@ var isBuffer = function isBuffer(obj) {
return false;
}
return !!(obj.constructor && obj.constructor.isBuffer && obj.constructor.isBuffer(obj));
return !!(obj.constructor && typeof obj.constructor.isBuffer === 'function' && obj.constructor.isBuffer(obj));
};
var combine = function combine(a, b, arrayLimit, plainObjects, throwOnLimitExceeded) {
@@ -338,8 +338,15 @@ var combine = function combine(a, b, arrayLimit, plainObjects, throwOnLimitExcee
if (throwOnLimitExceeded) {
throw new RangeError('Array limit exceeded. Only ' + arrayLimit + ' element' + (arrayLimit === 1 ? '' : 's') + ' allowed in an array.');
}
var newIndex = getMaxIndex(a) + 1;
a[newIndex] = b;
// spread `b` one level, matching the `[].concat(a, b)` used below, so a
// collection appended to an already-overflowed object is flattened
// rather than nested under a single index
var bValues = isArray(b) ? b : [b];
var newIndex = getMaxIndex(a);
for (var i = 0; i < bValues.length; ++i) {
newIndex += 1;
a[newIndex] = bValues[i];
}
setMaxIndex(a, newIndex);
return a;
}
+4 -4
View File
@@ -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.15.3",
"version": "6.16.0",
"repository": {
"type": "git",
"url": "https://github.com/ljharb/qs.git"
@@ -37,14 +37,14 @@
"devDependencies": {
"@browserify/envify": "^6.0.0",
"@browserify/uglifyify": "^6.0.0",
"@ljharb/eslint-config": "^22.2.3",
"@ljharb/eslint-config": "^22.2.4",
"browserify": "^16.5.2",
"bundle-collapser": "^1.4.0",
"common-shakeify": "~1.0.0",
"eclint": "^2.8.1",
"es-value-fixtures": "^1.7.1",
"eslint": "^10.5.0",
"evalmd": "^0.0.19",
"eslint": "^10.9.0",
"evalmd": "^0.0.22",
"for-each": "^0.3.5",
"glob": "=10.3.7",
"has-bigints": "^1.1.0",
+192 -3
View File
@@ -1475,6 +1475,73 @@ test('parse()', function (t) {
sst.end();
});
st.test('spreads a comma group appended to an already-overflowed object', function (sst) {
var result = qs.parse('a=1,2,3,4,5,6&a=7,8', { comma: true, arrayLimit: 5 });
sst.deepEqual(
result,
{ a: { 0: '1', 1: '2', 2: '3', 3: '4', 4: '5', 5: '6', 6: '7', 7: '8' } },
'appended comma values are flattened, not nested'
);
sst.end();
});
st.test('keeps a `[]=` comma group as one element when appended to an already-overflowed key', function (sst) {
var result = qs.parse('a[]=1&a[]=2&a[]=3&a[]=4,5', { comma: true, arrayLimit: 2 });
sst.deepEqual(
result,
{ a: { 0: '1', 1: '2', 2: '3', 3: ['4', '5'] } },
'nested comma group stays a single element, not double-nested'
);
sst.end();
});
st.test('spreads every later comma group appended to an already-overflowed object', function (sst) {
var result = qs.parse('a=1,2,3,4,5,6&a=7,8&a=9,10', { comma: true, arrayLimit: 5 });
sst.deepEqual(
result,
{ a: { 0: '1', 1: '2', 2: '3', 3: '4', 4: '5', 5: '6', 6: '7', 7: '8', 8: '9', 9: '10' } },
'each appended group is flattened in order'
);
sst.end();
});
st.test('spreads a comma group appended to an object overflowed under the default arrayLimit', function (sst) {
var values = [];
for (var i = 0; i <= 20; i += 1) {
values[values.length] = String(i);
}
var expected = {};
for (var j = 0; j < values.length; j += 1) {
expected[j] = values[j];
}
expected[21] = 'x';
expected[22] = 'y';
var result = qs.parse('a=' + values.join(',') + '&a=x,y', { comma: true });
sst.deepEqual(result, { a: expected }, 'appended values land at indices 21 and 22');
sst.end();
});
st.test('spreads a comma group appended to an already-overflowed object with plainObjects', function (sst) {
var result = qs.parse('a=1,2,3,4,5,6&a=7,8', { comma: true, arrayLimit: 5, plainObjects: true });
sst.deepEqual(
result,
{ __proto__: null, a: { __proto__: null, 0: '1', 1: '2', 2: '3', 3: '4', 4: '5', 5: '6', 6: '7', 7: '8' } },
'appended comma values are flattened into the null object'
);
sst.end();
});
st.test('still throws with throwOnLimitExceeded when a comma group is appended to an already-overflowed object', function (sst) {
sst['throws'](
function () {
qs.parse('a=1,2,3,4,5,6&a=7,8', { comma: true, arrayLimit: 5, throwOnLimitExceeded: true });
},
/Array limit exceeded/,
'throws before spreading the appended group'
);
sst.end();
});
st.test('does not throw for comma groups nested under bracket notation, counting each group as one element', function (sst) {
var result = qs.parse('a[]=1,2,3&a[]=4,5,6', { comma: true, arrayLimit: 5, throwOnLimitExceeded: true });
sst.deepEqual(result, { a: [['1', '2', '3'], ['4', '5', '6']] }, 'nested comma groups count as one element each');
@@ -1522,9 +1589,131 @@ test('parse()', function (t) {
sst.end();
});
st.test('does not throw for a bracketed comma group within arrayLimit', function (sst) {
var result = qs.parse('a[]=1,2,3,4,5,6', { comma: true, arrayLimit: 5, throwOnLimitExceeded: true });
sst.deepEqual(result, { a: [['1', '2', '3', '4', '5', '6']] }, 'a bracketed comma group is a single element');
st.test('throws before splitting when a bracketed comma group exceeds arrayLimit', function (sst) {
sst['throws'](
function () {
qs.parse('a[]=1,2,3,4,5,6', { comma: true, arrayLimit: 5, throwOnLimitExceeded: true });
},
new RangeError('Array limit exceeded. Only 5 elements allowed in an array.'),
'the inner group is itself an array and is subject to arrayLimit'
);
sst.end();
});
st.test('throws before splitting when a comma group under `[]=` exceeds arrayLimit', function (sst) {
sst['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.'),
'a bracket-push comma group over the limit throws like the flat form'
);
sst['throws'](
function () {
qs.parse('a[]=1,2', { comma: true, arrayLimit: 1, throwOnLimitExceeded: true });
},
new RangeError('Array limit exceeded. Only 1 element allowed in an array.'),
'singular message at arrayLimit 1'
);
sst['throws'](
function () {
qs.parse('a[b][]=1,2,3,4', { comma: true, arrayLimit: 3, throwOnLimitExceeded: true });
},
new RangeError('Array limit exceeded. Only 3 elements allowed in an array.'),
'a nested bracket-push key throws'
);
sst['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.'),
'a doubly bracket-pushed key throws'
);
sst['throws'](
function () {
qs.parse('a[]=5&a[]=1,2,3,4', { comma: true, arrayLimit: 3, throwOnLimitExceeded: true });
},
new RangeError('Array limit exceeded. Only 3 elements allowed in an array.'),
'an oversized group appended after a scalar throws'
);
sst['throws'](
function () {
qs.parse('a[]=1,2,3,4&a[]=5', { comma: true, arrayLimit: 3, throwOnLimitExceeded: true });
},
new RangeError('Array limit exceeded. Only 3 elements allowed in an array.'),
'an oversized group throws even when a later part would fit'
);
sst['throws'](
function () {
qs.parse('a[]=1,2,3,4&a[]=5', { comma: true, arrayLimit: 3, throwOnLimitExceeded: true, duplicates: 'first' });
},
new RangeError('Array limit exceeded. Only 3 elements allowed in an array.'),
'throws with duplicates: first'
);
sst['throws'](
function () {
qs.parse('a[]=5&a[]=1,2,3,4', { comma: true, arrayLimit: 3, throwOnLimitExceeded: true, duplicates: 'last' });
},
new RangeError('Array limit exceeded. Only 3 elements allowed in an array.'),
'throws with duplicates: last'
);
sst['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.'),
'an oversized comma value in object input throws'
);
var big = 'a[]=' + new Array(1e5 + 1).join('1,') + '1';
sst['throws'](
function () {
qs.parse(big, { comma: true, arrayLimit: 3, throwOnLimitExceeded: true });
},
new RangeError('Array limit exceeded. Only 3 elements allowed in an array.'),
'a very long bracket-push comma group throws'
);
sst.end();
});
st.test('does not throw for a comma group under `[]=` within arrayLimit', function (sst) {
sst.deepEqual(
qs.parse('a[]=1,2,3', { comma: true, arrayLimit: 3, throwOnLimitExceeded: true }),
{ a: [['1', '2', '3']] },
'an inner group exactly at the limit stays a single nested element'
);
sst.deepEqual(
qs.parse('a[]=1,2,3&a[]=4,5,6&a[]=7', { comma: true, arrayLimit: 3, throwOnLimitExceeded: true }),
{ a: [['1', '2', '3'], ['4', '5', '6'], '7'] },
'each group counts as one element of the outer array'
);
sst.deepEqual(
qs.parse('a[b][]=1,2,3', { comma: true, arrayLimit: 3, throwOnLimitExceeded: true }),
{ a: { b: [['1', '2', '3']] } },
'nested bracket-push key within the limit'
);
sst.deepEqual(
qs.parse({ a: '1,2,3' }, { comma: true, arrayLimit: 3, throwOnLimitExceeded: true }),
{ a: ['1', '2', '3'] },
'object input within the limit'
);
sst.end();
});
st.test('keeps an oversized comma group under `[]=` as a nested array without throwOnLimitExceeded', function (sst) {
sst.deepEqual(
qs.parse('a[]=1,2,3,4', { comma: true, arrayLimit: 3 }),
{ a: [['1', '2', '3', '4']] },
'the inner group is not converted to an overflow object'
);
sst.end();
});
+317
View File
@@ -136,6 +136,144 @@ test('stringify()', function (t) {
st.end();
});
t.test('encodes dot in key of object with a primitive value when encodeDotInKeys and allowDots is provided', function (st) {
st.equal(
qs.stringify(
{ 'name.obj': 'John' },
{ allowDots: true, encodeDotInKeys: true }
),
'name%252Eobj=John',
'with allowDots true and encodeDotInKeys true'
);
st.equal(
qs.stringify(
{ 'name.obj': 'John' },
{ allowDots: false, encodeDotInKeys: true }
),
'name%252Eobj=John',
'with allowDots false and encodeDotInKeys true'
);
st.equal(
qs.stringify(
{ 'name.obj': 'John' },
{ encodeDotInKeys: true, allowDots: true, encodeValuesOnly: true }
),
'name%2Eobj=John',
'with encodeValuesOnly true'
);
// With `encodeValuesOnly` the key encoder is skipped, so the dot is encoded once
// (`%2E`) rather than twice. That single `%2E` decodes back to a structural dot, so
// unlike the default output below this does not round-trip to the original dotted key
// (a pre-existing `encodeValuesOnly` + `encodeDotInKeys` limitation, not new here).
st.deepEqual(
qs.parse(
qs.stringify(
{ 'name.obj': 'John' },
{ encodeDotInKeys: true, allowDots: true, encodeValuesOnly: true }
),
{ allowDots: true, decodeDotInKeys: true }
),
{ name: { obj: 'John' } },
'with encodeValuesOnly the single-encoded dot decodes structurally (does not round-trip)'
);
st.deepEqual(
qs.parse(
qs.stringify({ 'name.obj': 'John' }, { allowDots: true, encodeDotInKeys: true }),
{ allowDots: true, decodeDotInKeys: true }
),
{ 'name.obj': 'John' },
'round-trips a dotted key with a primitive value'
);
st.equal(
qs.stringify({ 'a.b': null }, { allowDots: true, encodeDotInKeys: true, strictNullHandling: true }),
'a%252Eb',
'encodes a dotted key with a null value'
);
st.equal(
qs.stringify({ 'a.b': '1', 'c.d': '2' }, { allowDots: true, encodeDotInKeys: true }),
'a%252Eb=1&c%252Ed=2',
'encodes dots in every top-level key, not just the first'
);
st.equal(
qs.stringify({ 'a.b.c': 'x' }, { allowDots: true, encodeDotInKeys: true }),
'a%252Eb%252Ec=x',
'encodes every dot in a key'
);
var primitiveKey = qs.stringify({ 'a.b': 'c' }, { allowDots: true, encodeDotInKeys: true }).split('=')[0];
st.equal(
qs.stringify({ 'a.b': { x: 'c' } }, { allowDots: true, encodeDotInKeys: true }).indexOf(primitiveKey + '.'),
0,
'a top-level dotted key encodes identically for primitive and object values'
);
st.end();
});
// Characterization of the CURRENT (buggy) behavior: with `allowDots` + `encodeDotInKeys`,
// `stringify` percent-encodes the structural `.` separators that `allowDots` inserts between
// nested keys, not just the literal dots inside a key, which breaks the stringify -> parse
// round-trip. These assertions pin that behavior so it cannot change silently: the fix in
// https://github.com/ljharb/qs/pull/564 changes every output below, so landing that fix MUST
// update this test (that is the point — it forces the behavior change to be explicit).
t.test('[characterization] encodeDotInKeys currently over-encodes structural separator dots (pre-#564)', function (st) {
st.equal(
qs.stringify({ a: { b: { c: 'd' } } }, { allowDots: true, encodeDotInKeys: true }),
'a%252Eb.c=d',
'over-encodes the a->b separator (#564: should become a.b.c=d)'
);
st.equal(
qs.stringify({ a: { b: { c: { d: 'e' } } } }, { allowDots: true, encodeDotInKeys: true }),
'a%252Eb%252Ec.d=e',
'clobbers every separator but the last (#564: should become a.b.c.d=e)'
);
st.equal(
qs.stringify({ 'a.b': { c: { d: 'e' } } }, { allowDots: true, encodeDotInKeys: true }),
'a%252Eb%252Ec.d=e',
'top-level dotted key: deeper separators also get encoded (#564: should become a%252Eb.c.d=e)'
);
st.equal(
qs.stringify({ a: { 'b.c': { d: 'e' } } }, { allowDots: true, encodeDotInKeys: true }),
'a%252Eb%252Ec.d=e',
'nested dotted key + object value: the separator around it is encoded (#564: should become a.b%252Ec.d=e)'
);
st.equal(
qs.stringify({ a: { b: { 'c.d': { e: 'f' } } } }, { allowDots: true, encodeDotInKeys: true }),
'a%252Eb%252Ec%252Ed.e=f',
'deeply nested dotted key: all separators encoded (#564: should become a.b.c%252Ed.e=f)'
);
st.equal(
qs.stringify({ a: { b: [1, 2] } }, { allowDots: true, encodeDotInKeys: true }),
'a%252Eb%5B0%5D=1&a%252Eb%5B1%5D=2',
'array value under nested keys: separator encoded (#564: should become a.b%5B0%5D=1&a.b%5B1%5D=2)'
);
st.equal(
qs.stringify({ a: { 'b.c': [1, 2] } }, { allowDots: true, encodeDotInKeys: true }),
'a%252Eb%252Ec%5B0%5D=1&a%252Eb%252Ec%5B1%5D=2',
'array value under nested dotted key (#564: should become a.b%252Ec%5B0%5D=1&a.b%252Ec%5B1%5D=2)'
);
st.equal(
qs.stringify({ a: { 'b.c': { d: 'e' } } }, { allowDots: false, encodeDotInKeys: true }),
'a%5Bb%252Ec%5D%5Bd%5D=e',
'allowDots:false object value encodes the nested-key dot, unlike the primitive-value case (#564: should become a%5Bb.c%5D%5Bd%5D=e)'
);
st.deepEqual(
qs.parse(
qs.stringify({ a: { b: { c: 'd' } } }, { allowDots: true, encodeDotInKeys: true }),
{ allowDots: true, decodeDotInKeys: true }
),
{ 'a.b': { c: 'd' } },
'the over-encoding breaks the round-trip: {a:{b:{c}}} comes back as {"a.b":{c}} (#564 restores it)'
);
st.end();
});
t.test('should encode dot in key of object, and automatically set allowDots to `true` when encodeDotInKeys is true and allowDots in undefined', function (st) {
st.equal(
qs.stringify(
@@ -328,6 +466,39 @@ test('stringify()', function (t) {
st.end();
});
t.test('allowEmptyArrays only short-circuits arrays with no own keys', function (st) {
st.equal(
qs.stringify({ a: [] }, { allowEmptyArrays: true }),
'a[]',
'a genuinely empty array is still emitted as `[]`'
);
var withKey = [];
withKey.extra = 'x';
st.equal(
qs.stringify({ a: withKey }, { allowEmptyArrays: true }),
'a%5Bextra%5D=x',
'an own key on an empty array is serialized rather than dropped'
);
st.equal(
qs.stringify({ a: withKey }, { allowEmptyArrays: true }),
qs.stringify({ a: withKey }),
'the allowEmptyArrays fast path matches the default path when the array has own keys'
);
var container = {};
var cyclic = [];
cyclic.back = container;
container.a = cyclic;
st['throws'](
function () { qs.stringify(container, { allowEmptyArrays: true }); },
RangeError,
'a cycle through an empty array with an own key is still detected'
);
st.end();
});
t.test('stringifies an array value with one item vs multiple items', function (st) {
st.test('non-array item', function (s2t) {
s2t.equal(qs.stringify({ a: 'c' }, { encodeValuesOnly: true, arrayFormat: 'indices' }), 'a=c');
@@ -761,6 +932,33 @@ test('stringify()', function (t) {
st.end();
});
t.test('does not throw on a non-callable `constructor.isBuffer` key', function (st) {
var input = { a: { constructor: { isBuffer: 'x' } } };
st.doesNotThrow(function () { qs.stringify(input); });
st.equal(qs.stringify(input), 'a%5Bconstructor%5D%5BisBuffer%5D=x');
st.equal(qs.stringify({ a: { constructor: { isBuffer: { b: 'c' } } } }), 'a%5Bconstructor%5D%5BisBuffer%5D%5Bb%5D=c');
st.equal(qs.stringify({ a: { constructor: { isBuffer: ['b'] } } }), 'a%5Bconstructor%5D%5BisBuffer%5D%5B0%5D=b');
st.equal(qs.stringify({ a: { constructor: { isBuffer: true } } }), 'a%5Bconstructor%5D%5BisBuffer%5D=true');
st.end();
});
t.test('round-trips a parsed `constructor[isBuffer]` key', function (st) {
var str = 'x%5Bconstructor%5D%5BisBuffer%5D=y';
var plain = qs.parse(str, { plainObjects: true });
st.deepEqual(plain, { __proto__: null, x: { __proto__: null, constructor: { __proto__: null, isBuffer: 'y' } } }, 'plainObjects keeps the key');
st.doesNotThrow(function () { qs.stringify(plain); });
st.equal(qs.stringify(plain), str, 'plainObjects round-trips');
var proto = qs.parse(str, { allowPrototypes: true });
st.deepEqual(proto, { x: { constructor: { isBuffer: 'y' } } }, 'allowPrototypes keeps the key');
st.doesNotThrow(function () { qs.stringify(proto); });
st.equal(qs.stringify(proto), str, 'allowPrototypes round-trips');
st.equal(qs.stringify(qs.parse(str)), '', 'default options drop the key');
st.end();
});
t.test('stringifies an object using an alternative delimiter', function (st) {
st.equal(qs.stringify({ a: 'b', c: 'd' }, { delimiter: ';' }), 'a=b;c=d');
st.end();
@@ -919,6 +1117,66 @@ test('stringify()', function (t) {
st.end();
});
t.test('serializes Date values unless filter transforms them', function (st) {
var obj = {
a: new Date(Date.UTC(2023, 2, 7, 9, 2, 41, 260)),
b: [new Date(Date.UTC(2023, 2, 7, 9, 2, 41, 260))]
};
var iso = '2023-03-07T09%3A02%3A41.260Z';
st.equal(
qs.stringify(obj, { filter: function (prefix, value) { return value; } }),
'a=' + iso + '&b%5B0%5D=' + iso,
'Dates returned unchanged by a filter are serialized'
);
st.equal(
qs.stringify({ a: new Date(0) }, { filter: function (prefix, value) { return value instanceof Date ? 'kept' : value; } }),
'a=kept',
'a filter that transforms a Date wins over default serialization'
);
st.end();
});
t.test('applies default Date handling to whatever a filter function returns', function (st) {
var date = new Date(Date.UTC(2023, 2, 7, 9, 2, 41, 260));
var iso = '2023-03-07T09%3A02%3A41.260Z';
var identity = function (prefix, value) { return value; };
st.equal(
qs.stringify({ a: { b: date } }, { filter: identity }),
'a%5Bb%5D=' + iso,
'a nested Date is serialized through a filter'
);
st.equal(
qs.stringify(
{ a: date },
{ filter: identity, serializeDate: function (d) { return String(d.getTime()); } }
),
'a=1678179761260',
'`serializeDate` is honored after a filter'
);
st.equal(
qs.stringify({ a: [date, 'x'] }, { filter: identity, arrayFormat: 'comma' }),
'a=' + iso + '%2Cx',
'Dates inside a comma array are serialized through a filter, not stringified as locale text'
);
st.equal(
qs.stringify({ a: 'x' }, { filter: function (prefix, value) { return prefix === 'a' ? date : value; } }),
'a=' + iso,
'a Date produced by the filter is serialized'
);
st.equal(
qs.stringify({ a: date, b: 1 }, { filter: ['a'] }),
'a=' + iso,
'an array filter still serializes Dates'
);
st['throws'](
function () { qs.stringify({ a: new Date(NaN) }, { filter: identity }); },
RangeError,
'an invalid Date through a filter throws like the no-filter path'
);
st.end();
});
t.test('can disable uri encoding', function (st) {
st.equal(qs.stringify({ a: 'b' }, { encode: false }), 'a=b');
st.equal(qs.stringify({ a: { b: 'c' } }, { encode: false }), 'a[b]=c');
@@ -1445,4 +1703,63 @@ test('stringifies empty keys', function (t) {
st.end();
});
t.test('limits nesting depth with the `depth` option', function (st) {
st.equal(
qs.stringify({ a: { b: { c: 'd' } } }),
'a%5Bb%5D%5Bc%5D=d',
'the default depth is unlimited and does not alter output'
);
st.equal(
qs.stringify({ a: { b: { c: 'd' } } }, { depth: 2 }),
'a%5Bb%5D%5Bc%5D=d',
'does not throw when nesting is within the depth limit'
);
st.equal(
qs.stringify({ a: { b: 'c' } }, { depth: Infinity }),
'a%5Bb%5D=c',
'an explicit Infinity depth is unlimited'
);
st.equal(
qs.stringify({ a: { b: { c: { d: 'e' } } } }, { depth: null }),
qs.stringify({ a: { b: { c: { d: 'e' } } } }),
'a non-number depth is ignored and treated as unlimited'
);
st.equal(
qs.stringify({ a: 'b' }, { depth: 0 }),
'a=b',
'a flat object serializes with a depth of 0'
);
var deep = {};
var cursor = deep;
for (var i = 0; i < 250; i++) {
cursor.a = {};
cursor = cursor.a;
}
cursor.b = 'c';
st.equal(typeof qs.stringify(deep), 'string', 'the default depth serializes deeply nested objects without throwing');
st['throws'](
function () { qs.stringify({ a: { b: { c: { d: 'e' } } } }, { depth: 2 }); },
RangeError,
'throws a RangeError when nesting exceeds the depth limit'
);
st['throws'](
function () { qs.stringify({ a: { b: 'c' } }, { depth: 0 }); },
RangeError,
'a depth of 0 throws for any nested object'
);
var caught;
try {
qs.stringify({ a: { b: { c: { d: 'e' } } } }, { depth: 2 });
} catch (e) {
caught = e;
}
st.ok(caught instanceof RangeError, 'the thrown value is a RangeError');
st.equal(caught.message, 'Input depth exceeded depth option of 2', 'the RangeError names the exceeded depth');
st.end();
});
});
+12
View File
@@ -604,6 +604,18 @@ test('isBuffer()', function (t) {
var fakeBuffer = { constructor: Buffer };
t.equal(utils.isBuffer(fakeBuffer), false, 'fake buffer is not a buffer');
forEach(['x', 1, true, {}, [], { isBuffer: true }], function (notCallable) {
var obj = { constructor: { isBuffer: notCallable } };
t.doesNotThrow(function () { utils.isBuffer(obj); }, 'non-callable `constructor.isBuffer` (' + inspect(notCallable) + ') does not throw');
t.equal(utils.isBuffer(obj), false, 'non-callable `constructor.isBuffer` (' + inspect(notCallable) + ') is not a buffer');
});
var nullObject = { __proto__: null, constructor: { __proto__: null, isBuffer: 'y' } };
t.equal(utils.isBuffer(nullObject), false, 'null object with non-callable `constructor.isBuffer` is not a buffer');
var duckBuffer = { constructor: { isBuffer: function () { return true; } } };
t.equal(utils.isBuffer(duckBuffer), true, 'callable `constructor.isBuffer` is still honored');
var saferBuffer = SaferBuffer.from('abc');
t.equal(utils.isBuffer(saferBuffer), true, 'SaferBuffer instance is a buffer');