Comparing version 6.4.0 to 6.4.1
@@ -0,1 +1,22 @@ | ||
## **6.4.1** | ||
- [Fix] `parse`: ignore `__proto__` keys (#428) | ||
- [Fix] fix for an impossible situation: when the formatter is called with a non-string value | ||
- [Fix] use `safer-buffer` instead of `Buffer` constructor | ||
- [Fix] `utils.merge`: avoid a crash with a null target and an array source | ||
- [Fix]` `utils.merge`: avoid a crash with a null target and a truthy non-array source | ||
- [Fix] `stringify`: fix a crash with `strictNullHandling` and a custom `filter`/`serializeDate` (#279) | ||
- [Fix] `utils`: `merge`: fix crash when `source` is a truthy primitive & no options are provided | ||
- [Fix] when `parseArrays` is false, properly handle keys ending in `[]` | ||
- [Robustness] `stringify`: avoid relying on a global `undefined` (#427) | ||
- [Refactor] use cached `Array.isArray` | ||
- [Refactor] `stringify`: Avoid arr = arr.concat(...), push to the existing instance (#269) | ||
- [readme] remove travis badge; add github actions/codecov badges; update URLs | ||
- [Docs] Clarify the need for "arrayLimit" option | ||
- [meta] fix README.md (#399) | ||
- [meta] Clean up license text so it’s properly detected as BSD-3-Clause | ||
- [meta] add FUNDING.yml | ||
- [actions] backport actions from main | ||
- [Tests] remove nonexistent tape option | ||
- [Dev Deps] backport from main | ||
## **6.4.0** | ||
@@ -2,0 +23,0 @@ - [New] `qs.stringify`: add `encodeValuesOnly` option |
@@ -1,2 +0,2 @@ | ||
(function(f){if(typeof exports==="object"&&typeof module!=="undefined"){module.exports=f()}else if(typeof define==="function"&&define.amd){define([],f)}else{var g;if(typeof window!=="undefined"){g=window}else if(typeof global!=="undefined"){g=global}else if(typeof self!=="undefined"){g=self}else{g=this}g.Qs = f()}})(function(){var define,module,exports;return (function e(t,n,r){function s(o,u){if(!n[o]){if(!t[o]){var a=typeof require=="function"&&require;if(!u&&a)return a(o,!0);if(i)return i(o,!0);var f=new Error("Cannot find module '"+o+"'");throw f.code="MODULE_NOT_FOUND",f}var l=n[o]={exports:{}};t[o][0].call(l.exports,function(e){var n=t[o][1][e];return s(n?n:e)},l,l.exports,e,t,n,r)}return n[o].exports}var i=typeof require=="function"&&require;for(var o=0;o<r.length;o++)s(r[o]);return s})({1:[function(require,module,exports){ | ||
(function(f){if(typeof exports==="object"&&typeof module!=="undefined"){module.exports=f()}else if(typeof define==="function"&&define.amd){define([],f)}else{var g;if(typeof window!=="undefined"){g=window}else if(typeof global!=="undefined"){g=global}else if(typeof self!=="undefined"){g=self}else{g=this}g.Qs = f()}})(function(){var define,module,exports;return (function(){function r(e,n,t){function o(i,f){if(!n[i]){if(!e[i]){var c="function"==typeof require&&require;if(!f&&c)return c(i,!0);if(u)return u(i,!0);var a=new Error("Cannot find module '"+i+"'");throw a.code="MODULE_NOT_FOUND",a}var p=n[i]={exports:{}};e[i][0].call(p.exports,function(r){var n=e[i][1][r];return o(n||r)},p,p.exports,r,e,n,t)}return n[i].exports}for(var u="function"==typeof require&&require,i=0;i<t.length;i++)o(t[i]);return o}return r})()({1:[function(require,module,exports){ | ||
'use strict'; | ||
@@ -14,3 +14,3 @@ | ||
RFC3986: function (value) { | ||
return value; | ||
return String(value); | ||
} | ||
@@ -88,3 +88,3 @@ }, | ||
var obj; | ||
if (root === '[]') { | ||
if (root === '[]' && options.parseArrays) { | ||
obj = []; | ||
@@ -96,12 +96,14 @@ obj = obj.concat(parseObject(chain, val, options)); | ||
var index = parseInt(cleanRoot, 10); | ||
if ( | ||
!isNaN(index) && | ||
root !== cleanRoot && | ||
String(index) === cleanRoot && | ||
index >= 0 && | ||
(options.parseArrays && index <= options.arrayLimit) | ||
if (!options.parseArrays && cleanRoot === '') { | ||
obj = { 0: val }; | ||
} else if ( | ||
!isNaN(index) | ||
&& root !== cleanRoot | ||
&& String(index) === cleanRoot | ||
&& index >= 0 | ||
&& (options.parseArrays && index <= options.arrayLimit) | ||
) { | ||
obj = []; | ||
obj[index] = parseObject(chain, val, options); | ||
} else { | ||
} else if (cleanRoot !== '__proto__') { | ||
obj[cleanRoot] = parseObject(chain, val, options); | ||
@@ -136,4 +138,3 @@ } | ||
if (parent) { | ||
// If we aren't using plain objects, optionally prefix keys | ||
// that would overwrite object prototype properties | ||
// If we aren't using plain objects, optionally prefix keys that would overwrite object prototype properties | ||
if (!options.plainObjects && has.call(Object.prototype, parent)) { | ||
@@ -214,9 +215,9 @@ if (!options.allowPrototypes) { | ||
var arrayPrefixGenerators = { | ||
brackets: function brackets(prefix) { // eslint-disable-line func-name-matching | ||
brackets: function brackets(prefix) { | ||
return prefix + '[]'; | ||
}, | ||
indices: function indices(prefix, key) { // eslint-disable-line func-name-matching | ||
indices: function indices(prefix, key) { | ||
return prefix + '[' + key + ']'; | ||
}, | ||
repeat: function repeat(prefix) { // eslint-disable-line func-name-matching | ||
repeat: function repeat(prefix) { | ||
return prefix; | ||
@@ -226,2 +227,8 @@ } | ||
var isArray = Array.isArray; | ||
var push = Array.prototype.push; | ||
var pushToArray = function (arr, valueOrArray) { | ||
push.apply(arr, isArray(valueOrArray) ? valueOrArray : [valueOrArray]); | ||
}; | ||
var toISO = Date.prototype.toISOString; | ||
@@ -234,3 +241,3 @@ | ||
encodeValuesOnly: false, | ||
serializeDate: function serializeDate(date) { // eslint-disable-line func-name-matching | ||
serializeDate: function serializeDate(date) { | ||
return toISO.call(date); | ||
@@ -242,3 +249,3 @@ }, | ||
var stringify = function stringify( // eslint-disable-line func-name-matching | ||
var stringify = function stringify( | ||
object, | ||
@@ -262,3 +269,5 @@ prefix, | ||
obj = serializeDate(obj); | ||
} else if (obj === null) { | ||
} | ||
if (obj === null) { | ||
if (strictNullHandling) { | ||
@@ -286,3 +295,3 @@ return encoder && !encodeValuesOnly ? encoder(prefix) : prefix; | ||
var objKeys; | ||
if (Array.isArray(filter)) { | ||
if (isArray(filter)) { | ||
objKeys = filter; | ||
@@ -301,4 +310,4 @@ } else { | ||
if (Array.isArray(obj)) { | ||
values = values.concat(stringify( | ||
if (isArray(obj)) { | ||
pushToArray(values, stringify( | ||
obj[key], | ||
@@ -318,3 +327,3 @@ generateArrayPrefix(prefix, key), | ||
} else { | ||
values = values.concat(stringify( | ||
pushToArray(values, stringify( | ||
obj[key], | ||
@@ -343,3 +352,3 @@ prefix + (allowDots ? '.' + key : '[' + key + ']'), | ||
if (options.encoder !== null && options.encoder !== undefined && typeof options.encoder !== 'function') { | ||
if (options.encoder !== null && typeof options.encoder !== 'undefined' && typeof options.encoder !== 'function') { | ||
throw new TypeError('Encoder has to be a function.'); | ||
@@ -358,3 +367,3 @@ } | ||
if (typeof options.format === 'undefined') { | ||
options.format = formats.default; | ||
options.format = formats['default']; | ||
} else if (!Object.prototype.hasOwnProperty.call(formats.formatters, options.format)) { | ||
@@ -370,3 +379,3 @@ throw new TypeError('Unknown format option provided.'); | ||
obj = filter('', obj); | ||
} else if (Array.isArray(options.filter)) { | ||
} else if (isArray(options.filter)) { | ||
filter = options.filter; | ||
@@ -407,4 +416,3 @@ objKeys = filter; | ||
} | ||
keys = keys.concat(stringify( | ||
pushToArray(keys, stringify( | ||
obj[key], | ||
@@ -461,4 +469,4 @@ key, | ||
target.push(source); | ||
} else if (typeof target === 'object') { | ||
if (options.plainObjects || options.allowPrototypes || !has.call(Object.prototype, source)) { | ||
} else if (target && typeof target === 'object') { | ||
if ((options && (options.plainObjects || options.allowPrototypes)) || !has.call(Object.prototype, source)) { | ||
target[source] = true; | ||
@@ -473,3 +481,3 @@ } | ||
if (typeof target !== 'object') { | ||
if (!target || typeof target !== 'object') { | ||
return [target].concat(source); | ||
@@ -532,9 +540,9 @@ } | ||
if ( | ||
c === 0x2D || // - | ||
c === 0x2E || // . | ||
c === 0x5F || // _ | ||
c === 0x7E || // ~ | ||
(c >= 0x30 && c <= 0x39) || // 0-9 | ||
(c >= 0x41 && c <= 0x5A) || // a-z | ||
(c >= 0x61 && c <= 0x7A) // A-Z | ||
c === 0x2D // - | ||
|| c === 0x2E // . | ||
|| c === 0x5F // _ | ||
|| c === 0x7E // ~ | ||
|| (c >= 0x30 && c <= 0x39) // 0-9 | ||
|| (c >= 0x41 && c <= 0x5A) // a-z | ||
|| (c >= 0x61 && c <= 0x7A) // A-Z | ||
) { | ||
@@ -562,3 +570,7 @@ out += string.charAt(i); | ||
c = 0x10000 + (((c & 0x3FF) << 10) | (string.charCodeAt(i) & 0x3FF)); | ||
out += hexTable[0xF0 | (c >> 18)] + hexTable[0x80 | ((c >> 12) & 0x3F)] + hexTable[0x80 | ((c >> 6) & 0x3F)] + hexTable[0x80 | (c & 0x3F)]; // eslint-disable-line max-len | ||
/* eslint operator-linebreak: [2, "before"] */ | ||
out += hexTable[0xF0 | (c >> 18)] | ||
+ hexTable[0x80 | ((c >> 12) & 0x3F)] | ||
+ hexTable[0x80 | ((c >> 6) & 0x3F)] | ||
+ hexTable[0x80 | (c & 0x3F)]; | ||
} | ||
@@ -617,2 +629,2 @@ | ||
},{}]},{},[2])(2) | ||
}); | ||
}); |
@@ -13,3 +13,3 @@ 'use strict'; | ||
RFC3986: function (value) { | ||
return value; | ||
return String(value); | ||
} | ||
@@ -16,0 +16,0 @@ }, |
@@ -53,3 +53,3 @@ 'use strict'; | ||
var obj; | ||
if (root === '[]') { | ||
if (root === '[]' && options.parseArrays) { | ||
obj = []; | ||
@@ -61,12 +61,14 @@ obj = obj.concat(parseObject(chain, val, options)); | ||
var index = parseInt(cleanRoot, 10); | ||
if ( | ||
!isNaN(index) && | ||
root !== cleanRoot && | ||
String(index) === cleanRoot && | ||
index >= 0 && | ||
(options.parseArrays && index <= options.arrayLimit) | ||
if (!options.parseArrays && cleanRoot === '') { | ||
obj = { 0: val }; | ||
} else if ( | ||
!isNaN(index) | ||
&& root !== cleanRoot | ||
&& String(index) === cleanRoot | ||
&& index >= 0 | ||
&& (options.parseArrays && index <= options.arrayLimit) | ||
) { | ||
obj = []; | ||
obj[index] = parseObject(chain, val, options); | ||
} else { | ||
} else if (cleanRoot !== '__proto__') { | ||
obj[cleanRoot] = parseObject(chain, val, options); | ||
@@ -101,4 +103,3 @@ } | ||
if (parent) { | ||
// If we aren't using plain objects, optionally prefix keys | ||
// that would overwrite object prototype properties | ||
// If we aren't using plain objects, optionally prefix keys that would overwrite object prototype properties | ||
if (!options.plainObjects && has.call(Object.prototype, parent)) { | ||
@@ -105,0 +106,0 @@ if (!options.allowPrototypes) { |
@@ -7,9 +7,9 @@ 'use strict'; | ||
var arrayPrefixGenerators = { | ||
brackets: function brackets(prefix) { // eslint-disable-line func-name-matching | ||
brackets: function brackets(prefix) { | ||
return prefix + '[]'; | ||
}, | ||
indices: function indices(prefix, key) { // eslint-disable-line func-name-matching | ||
indices: function indices(prefix, key) { | ||
return prefix + '[' + key + ']'; | ||
}, | ||
repeat: function repeat(prefix) { // eslint-disable-line func-name-matching | ||
repeat: function repeat(prefix) { | ||
return prefix; | ||
@@ -19,2 +19,8 @@ } | ||
var isArray = Array.isArray; | ||
var push = Array.prototype.push; | ||
var pushToArray = function (arr, valueOrArray) { | ||
push.apply(arr, isArray(valueOrArray) ? valueOrArray : [valueOrArray]); | ||
}; | ||
var toISO = Date.prototype.toISOString; | ||
@@ -27,3 +33,3 @@ | ||
encodeValuesOnly: false, | ||
serializeDate: function serializeDate(date) { // eslint-disable-line func-name-matching | ||
serializeDate: function serializeDate(date) { | ||
return toISO.call(date); | ||
@@ -35,3 +41,3 @@ }, | ||
var stringify = function stringify( // eslint-disable-line func-name-matching | ||
var stringify = function stringify( | ||
object, | ||
@@ -55,3 +61,5 @@ prefix, | ||
obj = serializeDate(obj); | ||
} else if (obj === null) { | ||
} | ||
if (obj === null) { | ||
if (strictNullHandling) { | ||
@@ -79,3 +87,3 @@ return encoder && !encodeValuesOnly ? encoder(prefix) : prefix; | ||
var objKeys; | ||
if (Array.isArray(filter)) { | ||
if (isArray(filter)) { | ||
objKeys = filter; | ||
@@ -94,4 +102,4 @@ } else { | ||
if (Array.isArray(obj)) { | ||
values = values.concat(stringify( | ||
if (isArray(obj)) { | ||
pushToArray(values, stringify( | ||
obj[key], | ||
@@ -111,3 +119,3 @@ generateArrayPrefix(prefix, key), | ||
} else { | ||
values = values.concat(stringify( | ||
pushToArray(values, stringify( | ||
obj[key], | ||
@@ -136,3 +144,3 @@ prefix + (allowDots ? '.' + key : '[' + key + ']'), | ||
if (options.encoder !== null && options.encoder !== undefined && typeof options.encoder !== 'function') { | ||
if (options.encoder !== null && typeof options.encoder !== 'undefined' && typeof options.encoder !== 'function') { | ||
throw new TypeError('Encoder has to be a function.'); | ||
@@ -151,3 +159,3 @@ } | ||
if (typeof options.format === 'undefined') { | ||
options.format = formats.default; | ||
options.format = formats['default']; | ||
} else if (!Object.prototype.hasOwnProperty.call(formats.formatters, options.format)) { | ||
@@ -163,3 +171,3 @@ throw new TypeError('Unknown format option provided.'); | ||
obj = filter('', obj); | ||
} else if (Array.isArray(options.filter)) { | ||
} else if (isArray(options.filter)) { | ||
filter = options.filter; | ||
@@ -200,4 +208,3 @@ objKeys = filter; | ||
} | ||
keys = keys.concat(stringify( | ||
pushToArray(keys, stringify( | ||
obj[key], | ||
@@ -204,0 +211,0 @@ key, |
@@ -33,4 +33,4 @@ 'use strict'; | ||
target.push(source); | ||
} else if (typeof target === 'object') { | ||
if (options.plainObjects || options.allowPrototypes || !has.call(Object.prototype, source)) { | ||
} else if (target && typeof target === 'object') { | ||
if ((options && (options.plainObjects || options.allowPrototypes)) || !has.call(Object.prototype, source)) { | ||
target[source] = true; | ||
@@ -45,3 +45,3 @@ } | ||
if (typeof target !== 'object') { | ||
if (!target || typeof target !== 'object') { | ||
return [target].concat(source); | ||
@@ -104,9 +104,9 @@ } | ||
if ( | ||
c === 0x2D || // - | ||
c === 0x2E || // . | ||
c === 0x5F || // _ | ||
c === 0x7E || // ~ | ||
(c >= 0x30 && c <= 0x39) || // 0-9 | ||
(c >= 0x41 && c <= 0x5A) || // a-z | ||
(c >= 0x61 && c <= 0x7A) // A-Z | ||
c === 0x2D // - | ||
|| c === 0x2E // . | ||
|| c === 0x5F // _ | ||
|| c === 0x7E // ~ | ||
|| (c >= 0x30 && c <= 0x39) // 0-9 | ||
|| (c >= 0x41 && c <= 0x5A) // a-z | ||
|| (c >= 0x61 && c <= 0x7A) // A-Z | ||
) { | ||
@@ -134,3 +134,7 @@ out += string.charAt(i); | ||
c = 0x10000 + (((c & 0x3FF) << 10) | (string.charCodeAt(i) & 0x3FF)); | ||
out += hexTable[0xF0 | (c >> 18)] + hexTable[0x80 | ((c >> 12) & 0x3F)] + hexTable[0x80 | ((c >> 6) & 0x3F)] + hexTable[0x80 | (c & 0x3F)]; // eslint-disable-line max-len | ||
/* eslint operator-linebreak: [2, "before"] */ | ||
out += hexTable[0xF0 | (c >> 18)] | ||
+ hexTable[0x80 | ((c >> 12) & 0x3F)] | ||
+ hexTable[0x80 | ((c >> 6) & 0x3F)] | ||
+ hexTable[0x80 | (c & 0x3F)]; | ||
} | ||
@@ -137,0 +141,0 @@ |
100
package.json
{ | ||
"name": "qs", | ||
"description": "A querystring parser that supports nesting and arrays, with a depth limit", | ||
"homepage": "https://github.com/ljharb/qs", | ||
"version": "6.4.0", | ||
"repository": { | ||
"type": "git", | ||
"url": "https://github.com/ljharb/qs.git" | ||
}, | ||
"main": "lib/index.js", | ||
"contributors": [ | ||
{ | ||
"name": "Jordan Harband", | ||
"email": "ljharb@gmail.com", | ||
"url": "http://ljharb.codes" | ||
} | ||
], | ||
"keywords": [ | ||
"querystring", | ||
"qs" | ||
], | ||
"engines": { | ||
"node": ">=0.6" | ||
}, | ||
"dependencies": {}, | ||
"devDependencies": { | ||
"@ljharb/eslint-config": "^11.0.0", | ||
"browserify": "^14.1.0", | ||
"covert": "^1.1.0", | ||
"eslint": "^3.17.0", | ||
"evalmd": "^0.0.17", | ||
"iconv-lite": "^0.4.15", | ||
"mkdirp": "^0.5.1", | ||
"parallelshell": "^2.0.0", | ||
"qs-iconv": "^1.0.4", | ||
"safe-publish-latest": "^1.1.1", | ||
"tape": "^4.6.3" | ||
}, | ||
"scripts": { | ||
"prepublish": "safe-publish-latest && npm run dist", | ||
"pretest": "npm run --silent readme && npm run --silent lint", | ||
"test": "npm run --silent coverage", | ||
"tests-only": "node test", | ||
"readme": "evalmd README.md", | ||
"lint": "eslint lib/*.js test/*.js", | ||
"coverage": "covert test", | ||
"dist": "mkdirp dist && browserify --standalone Qs lib/index.js > dist/qs.js" | ||
}, | ||
"license": "BSD-3-Clause" | ||
"name": "qs", | ||
"description": "A querystring parser that supports nesting and arrays, with a depth limit", | ||
"homepage": "https://github.com/ljharb/qs", | ||
"version": "6.4.1", | ||
"repository": { | ||
"type": "git", | ||
"url": "https://github.com/ljharb/qs.git" | ||
}, | ||
"main": "lib/index.js", | ||
"contributors": [ | ||
{ | ||
"name": "Jordan Harband", | ||
"email": "ljharb@gmail.com", | ||
"url": "http://ljharb.codes" | ||
} | ||
], | ||
"keywords": [ | ||
"querystring", | ||
"qs" | ||
], | ||
"engines": { | ||
"node": ">=0.6" | ||
}, | ||
"devDependencies": { | ||
"@ljharb/eslint-config": "^20.1.0", | ||
"aud": "^1.1.5", | ||
"browserify": "^16.5.2", | ||
"eclint": "^2.8.1", | ||
"eslint": "^8.6.0", | ||
"evalmd": "^0.0.17", | ||
"iconv-lite": "^0.4.24", | ||
"in-publish": "^2.0.1", | ||
"mkdirp": "^0.5.1", | ||
"nyc": "^10.3.2", | ||
"qs-iconv": "^1.0.4", | ||
"safe-publish-latest": "^2.0.0", | ||
"safer-buffer": "^2.1.2", | ||
"tape": "^5.4.0" | ||
}, | ||
"scripts": { | ||
"prepublishOnly": "safe-publish-latest && npm run dist", | ||
"prepublish": "not-in-publish || npm run prepublishOnly", | ||
"pretest": "npm run --silent readme && npm run --silent lint", | ||
"test": "npm run --silent tests-only", | ||
"tests-only": "nyc tape 'test/**/*.js'", | ||
"posttest": "aud --production", | ||
"readme": "evalmd README.md", | ||
"postlint": "eclint check $(git ls-files | xargs find 2> /dev/null | grep -vE 'node_modules|\\.git')", | ||
"lint": "eslint --ext=js,mjs .", | ||
"dist": "mkdirp dist && browserify --standalone Qs lib/index.js > dist/qs.js" | ||
}, | ||
"license": "BSD-3-Clause" | ||
} |
@@ -1,3 +0,12 @@ | ||
# qs | ||
# qs <sup>[![Version Badge][2]][1]</sup> | ||
[![github actions][actions-image]][actions-url] | ||
[![coverage][codecov-image]][codecov-url] | ||
[![dependency status][deps-svg]][deps-url] | ||
[![dev dependency status][dev-deps-svg]][dev-deps-url] | ||
[![License][license-image]][license-url] | ||
[![Downloads][downloads-image]][downloads-url] | ||
[![npm badge][npm-badge-png]][package-url] | ||
A querystring parsing and stringifying library with some added security. | ||
@@ -172,3 +181,3 @@ | ||
**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: | ||
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. | ||
@@ -258,2 +267,26 @@ ```javascript | ||
You can encode keys and values using different logic by using the type argument provided to the encoder: | ||
```javascript | ||
var encoded = qs.stringify({ a: { b: 'c' } }, { encoder: function (str, defaultEncoder, charset, type) { | ||
if (type === 'key') { | ||
return // Encoded key | ||
} else if (type === 'value') { | ||
return // Encoded value | ||
} | ||
}}) | ||
``` | ||
The type argument is also provided to the decoder: | ||
```javascript | ||
var decoded = qs.parse('x=z', { decoder: function (str, defaultDecoder, charset, type) { | ||
if (type === 'key') { | ||
return // Decoded key | ||
} else if (type === 'value') { | ||
return // Decoded value | ||
} | ||
}}) | ||
``` | ||
Examples beyond this point will be shown as though the output is not URI encoded for clarity. Please note that the return values in these cases *will* be URI encoded during real usage. | ||
@@ -443,1 +476,27 @@ | ||
``` | ||
## Security | ||
Please email [@ljharb](https://github.com/ljharb) or see https://tidelift.com/security if you have a potential security vulnerability to report. | ||
## qs for enterprise | ||
Available as part of the Tidelift Subscription | ||
The maintainers of qs and thousands of other packages are working with Tidelift to deliver commercial support and maintenance for the open source dependencies you use to build your applications. Save time, reduce risk, and improve code health, while paying the maintainers of the exact dependencies you use. [Learn more.](https://tidelift.com/subscription/pkg/npm-qs?utm_source=npm-qs&utm_medium=referral&utm_campaign=enterprise&utm_term=repo) | ||
[package-url]: https://npmjs.org/package/qs | ||
[npm-version-svg]: https://versionbadg.es/ljharb/qs.svg | ||
[deps-svg]: https://david-dm.org/ljharb/qs.svg | ||
[deps-url]: https://david-dm.org/ljharb/qs | ||
[dev-deps-svg]: https://david-dm.org/ljharb/qs/dev-status.svg | ||
[dev-deps-url]: https://david-dm.org/ljharb/qs#info=devDependencies | ||
[npm-badge-png]: https://nodei.co/npm/qs.png?downloads=true&stars=true | ||
[license-image]: https://img.shields.io/npm/l/qs.svg | ||
[license-url]: LICENSE | ||
[downloads-image]: https://img.shields.io/npm/dm/qs.svg | ||
[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-url]: https://github.com/ljharb/qs/actions |
@@ -6,2 +6,3 @@ 'use strict'; | ||
var iconv = require('iconv-lite'); | ||
var SaferBuffer = require('safer-buffer').Buffer; | ||
@@ -234,3 +235,3 @@ test('parse()', function (t) { | ||
t.test('parses buffers correctly', function (st) { | ||
var b = new Buffer('test'); | ||
var b = SaferBuffer.from('test'); | ||
st.deepEqual(qs.parse({ a: b }), { a: b }); | ||
@@ -260,3 +261,3 @@ st.end(); | ||
t.test('should not throw when a native prototype has an enumerable property', { parallel: false }, function (st) { | ||
t.test('should not throw when a native prototype has an enumerable property', function (st) { | ||
Object.prototype.crash = ''; | ||
@@ -306,3 +307,10 @@ Array.prototype.crash = ''; | ||
t.test('allows disabling array parsing', function (st) { | ||
st.deepEqual(qs.parse('a[0]=b&a[1]=c', { parseArrays: false }), { a: { 0: 'b', 1: 'c' } }); | ||
var indices = qs.parse('a[0]=b&a[1]=c', { parseArrays: false }); | ||
st.deepEqual(indices, { a: { 0: 'b', 1: 'c' } }); | ||
st.equal(Array.isArray(indices.a), false, 'parseArrays:false, indices case is not an array'); | ||
var emptyBrackets = qs.parse('a[]=b', { parseArrays: false }); | ||
st.deepEqual(emptyBrackets, { a: { 0: 'b' } }); | ||
st.equal(Array.isArray(emptyBrackets.a), false, 'parseArrays:false, empty brackets case is not an array'); | ||
st.end(); | ||
@@ -479,3 +487,3 @@ }); | ||
qs.parse('a[b]=c&a=toString', { plainObjects: true }), | ||
{ a: { b: 'c', toString: true } }, | ||
{ __proto__: null, a: { __proto__: null, b: 'c', toString: true } }, | ||
'can overwrite prototype with plainObjects true' | ||
@@ -487,2 +495,62 @@ ); | ||
t.test('dunder proto is ignored', function (st) { | ||
var payload = 'categories[__proto__]=login&categories[__proto__]&categories[length]=42'; | ||
var result = qs.parse(payload, { allowPrototypes: true }); | ||
st.deepEqual( | ||
result, | ||
{ | ||
categories: { | ||
length: '42' | ||
} | ||
}, | ||
'silent [[Prototype]] payload' | ||
); | ||
var plainResult = qs.parse(payload, { allowPrototypes: true, plainObjects: true }); | ||
st.deepEqual( | ||
plainResult, | ||
{ | ||
__proto__: null, | ||
categories: { | ||
__proto__: null, | ||
length: '42' | ||
} | ||
}, | ||
'silent [[Prototype]] payload: plain objects' | ||
); | ||
var query = qs.parse('categories[__proto__]=cats&categories[__proto__]=dogs&categories[some][json]=toInject', { allowPrototypes: true }); | ||
st.notOk(Array.isArray(query.categories), 'is not an array'); | ||
st.notOk(query.categories instanceof Array, 'is not instanceof an array'); | ||
st.deepEqual(query.categories, { some: { json: 'toInject' } }); | ||
st.equal(JSON.stringify(query.categories), '{"some":{"json":"toInject"}}', 'stringifies as a non-array'); | ||
st.deepEqual( | ||
qs.parse('foo[__proto__][hidden]=value&foo[bar]=stuffs', { allowPrototypes: true }), | ||
{ | ||
foo: { | ||
bar: 'stuffs' | ||
} | ||
}, | ||
'hidden values' | ||
); | ||
st.deepEqual( | ||
qs.parse('foo[__proto__][hidden]=value&foo[bar]=stuffs', { allowPrototypes: true, plainObjects: true }), | ||
{ | ||
__proto__: null, | ||
foo: { | ||
__proto__: null, | ||
bar: 'stuffs' | ||
} | ||
}, | ||
'hidden values: plain objects' | ||
); | ||
st.end(); | ||
}); | ||
t.test('can return null objects', { skip: !Object.create }, function (st) { | ||
@@ -513,3 +581,3 @@ var expected = Object.create(null); | ||
} | ||
return iconv.decode(new Buffer(result), 'shift_jis').toString(); | ||
return iconv.decode(SaferBuffer.from(result), 'shift_jis').toString(); | ||
} | ||
@@ -521,3 +589,3 @@ }), { 県: '大阪府' }); | ||
t.test('throws error with wrong decoder', function (st) { | ||
st.throws(function () { | ||
st['throws'](function () { | ||
qs.parse({}, { decoder: 'string' }); | ||
@@ -524,0 +592,0 @@ }, new TypeError('Decoder has to be a function.')); |
@@ -6,2 +6,3 @@ 'use strict'; | ||
var iconv = require('iconv-lite'); | ||
var SaferBuffer = require('safer-buffer').Buffer; | ||
@@ -329,4 +330,4 @@ test('stringify()', function (t) { | ||
t.test('stringifies buffer values', function (st) { | ||
st.equal(qs.stringify({ a: new Buffer('test') }), 'a=test'); | ||
st.equal(qs.stringify({ a: { b: new Buffer('test') } }), 'a%5Bb%5D=test'); | ||
st.equal(qs.stringify({ a: SaferBuffer.from('test') }), 'a=test'); | ||
st.equal(qs.stringify({ a: { b: SaferBuffer.from('test') } }), 'a%5Bb%5D=test'); | ||
st.end(); | ||
@@ -458,3 +459,3 @@ }); | ||
t.test('throws error with wrong encoder', function (st) { | ||
st.throws(function () { | ||
st['throws'](function () { | ||
qs.stringify({}, { encoder: 'string' }); | ||
@@ -466,3 +467,3 @@ }, new TypeError('Encoder has to be a function.')); | ||
t.test('can use custom encoder for a buffer object', { skip: typeof Buffer === 'undefined' }, function (st) { | ||
st.equal(qs.stringify({ a: new Buffer([1]) }, { | ||
st.equal(qs.stringify({ a: SaferBuffer.from([1]) }, { | ||
encoder: function (buffer) { | ||
@@ -475,2 +476,8 @@ if (typeof buffer === 'string') { | ||
}), 'a=b'); | ||
st.equal(qs.stringify({ a: SaferBuffer.from('a b') }, { | ||
encoder: function (buffer) { | ||
return buffer; | ||
} | ||
}), 'a=a b'); | ||
st.end(); | ||
@@ -491,3 +498,3 @@ }); | ||
}; | ||
st.throws(function () { | ||
st['throws'](function () { | ||
mutatedDate.toISOString(); | ||
@@ -517,2 +524,3 @@ }, SyntaxError); | ||
st.equal(qs.stringify({ 'a b': 'c d' }, { format: qs.formats.RFC1738 }), 'a+b=c+d'); | ||
st.equal(qs.stringify({ 'a b': SaferBuffer.from('a b') }, { format: qs.formats.RFC1738 }), 'a+b=a+b'); | ||
st.end(); | ||
@@ -524,2 +532,3 @@ }); | ||
st.equal(qs.stringify({ 'a b': 'c d' }, { format: qs.formats.RFC3986 }), 'a%20b=c%20d'); | ||
st.equal(qs.stringify({ 'a b': SaferBuffer.from('a b') }, { format: qs.formats.RFC3986 }), 'a%20b=a%20b'); | ||
st.end(); | ||
@@ -530,2 +539,3 @@ }); | ||
st.equal(qs.stringify({ a: 'b c' }), 'a=b%20c'); | ||
st.equal(qs.stringify({ 'a b': SaferBuffer.from('a b') }), 'a%20b=a%20b'); | ||
st.end(); | ||
@@ -537,3 +547,3 @@ }); | ||
function (format) { | ||
st.throws( | ||
st['throws']( | ||
function () { | ||
@@ -577,2 +587,23 @@ qs.stringify({ a: 'b c' }, { format: format }); | ||
t.test('strictNullHandling works with custom filter', function (st) { | ||
var filter = function (prefix, value) { | ||
return value; | ||
}; | ||
var options = { strictNullHandling: true, filter: filter }; | ||
st.equal(qs.stringify({ key: null }, options), 'key'); | ||
st.end(); | ||
}); | ||
t.test('strictNullHandling works with null serializeDate', function (st) { | ||
var serializeDate = function () { | ||
return null; | ||
}; | ||
var options = { strictNullHandling: true, serializeDate: serializeDate }; | ||
var date = new Date(); | ||
st.equal(qs.stringify({ key: date }, options), 'key'); | ||
st.end(); | ||
}); | ||
t.end(); | ||
}); |
@@ -7,2 +7,6 @@ 'use strict'; | ||
test('merge()', function (t) { | ||
t.deepEqual(utils.merge(null, true), [null, true], 'merges true into null'); | ||
t.deepEqual(utils.merge(null, [42]), [null, 42], 'merges null into an array'); | ||
t.deepEqual(utils.merge({ a: 'b' }, { a: 'c' }), { a: ['b', 'c'] }, 'merges two objects with the same key'); | ||
@@ -22,3 +26,6 @@ | ||
var noOptionsNonObjectSource = utils.merge({ foo: 'baz' }, 'bar'); | ||
t.deepEqual(noOptionsNonObjectSource, { foo: 'baz', bar: true }); | ||
t.end(); | ||
}); |
Sorry, the diff of this file is not supported yet
License Policy Violation
LicenseThis package is not allowed per your license policy. Review the package's license to ensure compliance.
Found 1 instance in 1 package
License Policy Violation
LicenseThis package is not allowed per your license policy. Review the package's license to ensure compliance.
Found 1 instance in 1 package
115464
20
2083
500
14