🚀 Big News: Socket Acquires Coana to Bring Reachability Analysis to Every Appsec Team.Learn more
Socket
Book a DemoInstallSign in
Socket

qs

Package Overview
Dependencies
Maintainers
2
Versions
115
Alerts
File Explorer

Advanced tools

Socket logo

Install Socket

Detect and block malicious and high-risk dependencies

Install

qs - npm Package Compare versions

Comparing version

to
6.10.2

10

CHANGELOG.md

@@ -0,1 +1,11 @@

## **6.10.2**
- [Fix] `stringify`: actually fix cyclic references (#426)
- [Fix] `stringify`: avoid encoding arrayformat comma when `encodeValuesOnly = true` (#424)
- [readme] remove travis badge; add github actions/codecov badges; update URLs
- [Docs] add note and links for coercing primitive values (#408)
- [actions] update codecov uploader
- [actions] update workflows
- [Tests] clean up stringify tests slightly
- [Dev Deps] update `eslint`, `@ljharb/eslint-config`, `aud`, `object-inspect`, `safe-publish-latest`, `tape`
## **6.10.1**

@@ -2,0 +12,0 @@ - [Fix] `stringify`: avoid exception on repeated object values (#402)

37

lib/stringify.js

@@ -22,2 +22,3 @@ 'use strict';

var isArray = Array.isArray;
var split = String.prototype.split;
var push = Array.prototype.push;

@@ -59,2 +60,4 @@ var pushToArray = function (arr, valueOrArray) {

var sentinel = {};
var stringify = function stringify(

@@ -79,4 +82,19 @@ object,

if (sideChannel.has(object)) {
throw new RangeError('Cyclic object value');
var tmpSc = sideChannel;
var step = 0;
var findFlag = false;
while ((tmpSc = tmpSc.get(sentinel)) !== undefined && !findFlag) {
// Where object last appeared in the ref tree
var pos = tmpSc.get(object);
step += 1;
if (typeof pos !== 'undefined') {
if (pos === step) {
throw new RangeError('Cyclic object value');
} else {
findFlag = true; // Break while
}
}
if (typeof tmpSc.get(sentinel) === 'undefined') {
step = 0;
}
}

@@ -108,2 +126,10 @@

var keyValue = encodeValuesOnly ? prefix : encoder(prefix, defaults.encoder, charset, 'key', format);
if (generateArrayPrefix === 'comma' && encodeValuesOnly) {
var valuesArray = split.call(String(obj), ',');
var valuesJoined = '';
for (var i = 0; i < valuesArray.length; ++i) {
valuesJoined += (i === 0 ? '' : ',') + formatter(encoder(valuesArray[i], defaults.encoder, charset, 'value', format));
}
return [formatter(keyValue) + '=' + valuesJoined];
}
return [formatter(keyValue) + '=' + formatter(encoder(obj, defaults.encoder, charset, 'value', format))];

@@ -131,4 +157,4 @@ }

for (var i = 0; i < objKeys.length; ++i) {
var key = objKeys[i];
for (var j = 0; j < objKeys.length; ++j) {
var key = objKeys[j];
var value = typeof key === 'object' && key.value !== undefined ? key.value : obj[key];

@@ -144,4 +170,5 @@

sideChannel.set(object, true);
sideChannel.set(object, step);
var valueSideChannel = getSideChannel();
valueSideChannel.set(sentinel, sideChannel);
pushToArray(values, stringify(

@@ -148,0 +175,0 @@ value,

@@ -180,2 +180,3 @@ 'use strict';

c = 0x10000 + (((c & 0x3FF) << 10) | (string.charCodeAt(i) & 0x3FF));
/* eslint operator-linebreak: [2, "before"] */
out += hexTable[0xF0 | (c >> 18)]

@@ -182,0 +183,0 @@ + hexTable[0x80 | ((c >> 12) & 0x3F)]

19

package.json

@@ -5,3 +5,3 @@ {

"homepage": "https://github.com/ljharb/qs",
"version": "6.10.1",
"version": "6.10.2",
"repository": {

@@ -37,7 +37,7 @@ "type": "git",

"devDependencies": {
"@ljharb/eslint-config": "^17.5.1",
"aud": "^1.1.4",
"@ljharb/eslint-config": "^20.0.0",
"aud": "^1.1.5",
"browserify": "^16.5.2",
"eclint": "^2.8.1",
"eslint": "^7.22.0",
"eslint": "^8.4.0",
"evalmd": "^0.0.19",

@@ -50,10 +50,11 @@ "for-each": "^0.3.3",

"nyc": "^10.3.2",
"object-inspect": "^1.9.0",
"object-inspect": "^1.11.0",
"qs-iconv": "^1.0.4",
"safe-publish-latest": "^1.1.4",
"safe-publish-latest": "^2.0.0",
"safer-buffer": "^2.1.2",
"tape": "^5.2.2"
"tape": "^5.3.2"
},
"scripts": {
"prepublish": "safe-publish-latest && (not-in-publish || npm run dist)",
"prepublishOnly": "safe-publish-latest && npm run dist",
"prepublish": "not-in-publish || npm run prepublishOnly",
"pretest": "npm run --silent readme && npm run --silent lint",

@@ -65,3 +66,3 @@ "test": "npm run tests-only",

"postlint": "eclint check * lib/* test/* !dist/*",
"lint": "eslint lib/*.js test/*.js",
"lint": "eslint .",
"dist": "mkdirp dist && browserify --standalone Qs lib/index.js > dist/qs.js"

@@ -68,0 +69,0 @@ },

# qs <sup>[![Version Badge][2]][1]</sup>
[![Build Status][3]][4]
[![dependency status][5]][6]
[![dev dependency status][7]][8]
[![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][11]][1]
[![npm badge][npm-badge-png]][package-url]

@@ -290,2 +291,13 @@ A querystring parsing and stringifying library with some added security.

### Parsing primitive/scalar values (numbers, booleans, null, etc)
By default, all values are parsed as strings. This behavior will not change and is explained in [issue #91](https://github.com/ljharb/qs/issues/91).
```javascript
var primitiveValues = qs.parse('a=15&b=true&c=null');
assert.deepEqual(primitiveValues, { a: '15', b: 'true', c: 'null' });
```
If you wish to auto-convert values which look like numbers, booleans, and other values into their primitive counterparts, you can use the [query-types Express JS middleware](https://github.com/xpepermint/query-types) which will auto-convert all request query parameters.
### Stringifying

@@ -598,16 +610,16 @@

[1]: https://npmjs.org/package/qs
[2]: http://versionbadg.es/ljharb/qs.svg
[3]: https://api.travis-ci.org/ljharb/qs.svg
[4]: https://travis-ci.org/ljharb/qs
[5]: https://david-dm.org/ljharb/qs.svg
[6]: https://david-dm.org/ljharb/qs
[7]: https://david-dm.org/ljharb/qs/dev-status.svg
[8]: https://david-dm.org/ljharb/qs?type=dev
[9]: https://ci.testling.com/ljharb/qs.png
[10]: https://ci.testling.com/ljharb/qs
[11]: https://nodei.co/npm/qs.png?downloads=true&stars=true
[license-image]: http://img.shields.io/npm/l/qs.svg
[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]: http://img.shields.io/npm/dm/qs.svg
[downloads-url]: http://npm-stat.com/charts.html?package=qs
[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

@@ -135,6 +135,6 @@ 'use strict';

t.test('stringifies a nested array value', function (st) {
st.equal(qs.stringify({ a: { b: ['c', 'd'] } }, { arrayFormat: 'indices' }), 'a%5Bb%5D%5B0%5D=c&a%5Bb%5D%5B1%5D=d');
st.equal(qs.stringify({ a: { b: ['c', 'd'] } }, { arrayFormat: 'brackets' }), 'a%5Bb%5D%5B%5D=c&a%5Bb%5D%5B%5D=d');
st.equal(qs.stringify({ a: { b: ['c', 'd'] } }, { arrayFormat: 'comma' }), 'a%5Bb%5D=c%2Cd'); // a[b]=c,d
st.equal(qs.stringify({ a: { b: ['c', 'd'] } }), 'a%5Bb%5D%5B0%5D=c&a%5Bb%5D%5B1%5D=d');
st.equal(qs.stringify({ a: { b: ['c', 'd'] } }, { encodeValuesOnly: true, arrayFormat: 'indices' }), 'a[b][0]=c&a[b][1]=d');
st.equal(qs.stringify({ a: { b: ['c', 'd'] } }, { encodeValuesOnly: true, arrayFormat: 'brackets' }), 'a[b][]=c&a[b][]=d');
st.equal(qs.stringify({ a: { b: ['c', 'd'] } }, { encodeValuesOnly: true, arrayFormat: 'comma' }), 'a[b]=c,d');
st.equal(qs.stringify({ a: { b: ['c', 'd'] } }, { encodeValuesOnly: true }), 'a[b][0]=c&a[b][1]=d');
st.end();

@@ -147,3 +147,3 @@ });

{ a: { b: ['c', 'd'] } },
{ allowDots: true, encode: false, arrayFormat: 'indices' }
{ allowDots: true, encodeValuesOnly: true, arrayFormat: 'indices' }
),

@@ -156,3 +156,3 @@ 'a.b[0]=c&a.b[1]=d',

{ a: { b: ['c', 'd'] } },
{ allowDots: true, encode: false, arrayFormat: 'brackets' }
{ allowDots: true, encodeValuesOnly: true, arrayFormat: 'brackets' }
),

@@ -165,3 +165,3 @@ 'a.b[]=c&a.b[]=d',

{ a: { b: ['c', 'd'] } },
{ allowDots: true, encode: false, arrayFormat: 'comma' }
{ allowDots: true, encodeValuesOnly: true, arrayFormat: 'comma' }
),

@@ -174,3 +174,3 @@ 'a.b=c,d',

{ a: { b: ['c', 'd'] } },
{ allowDots: true, encode: false }
{ allowDots: true, encodeValuesOnly: true }
),

@@ -223,3 +223,3 @@ 'a.b[0]=c&a.b[1]=d',

st.equal(
qs.stringify({ a: [{ b: 1 }, 2, 3] }, { encode: false, arrayFormat: 'indices' }),
qs.stringify({ a: [{ b: 1 }, 2, 3] }, { encodeValuesOnly: true, arrayFormat: 'indices' }),
'a[0][b]=1&a[1]=2&a[2]=3',

@@ -229,3 +229,3 @@ 'indices => indices'

st.equal(
qs.stringify({ a: [{ b: 1 }, 2, 3] }, { encode: false, arrayFormat: 'brackets' }),
qs.stringify({ a: [{ b: 1 }, 2, 3] }, { encodeValuesOnly: true, arrayFormat: 'brackets' }),
'a[][b]=1&a[]=2&a[]=3',

@@ -235,3 +235,9 @@ 'brackets => brackets'

st.equal(
qs.stringify({ a: [{ b: 1 }, 2, 3] }, { encode: false }),
qs.stringify({ a: [{ b: 1 }, 2, 3] }, { encodeValuesOnly: true, arrayFormat: 'comma' }),
'???',
'brackets => brackets',
{ skip: 'TODO: figure out what this should do' }
);
st.equal(
qs.stringify({ a: [{ b: 1 }, 2, 3] }, { encodeValuesOnly: true }),
'a[0][b]=1&a[1]=2&a[2]=3',

@@ -459,3 +465,3 @@ 'default => indices'

function () { qs.stringify({ 'foo[bar]': 'baz', 'foo[baz]': a }); },
RangeError,
/RangeError: Cyclic object value/,
'cyclic values throw'

@@ -470,6 +476,12 @@ );

function () { qs.stringify(circular); },
RangeError,
/RangeError: Cyclic object value/,
'cyclic values throw'
);
var arr = ['a'];
st.doesNotThrow(
function () { qs.stringify({ x: arr, y: arr }); },
'non-cyclic values do not throw'
);
st.end();

@@ -842,3 +854,8 @@ });

st.equal(qs.stringify(withArray, { encode: false, arrayFormat: 'indices' }), 'a[b][0][c]=d&a[b][0][e]=f', 'array, indices');
st.equal(qs.stringify(obj, { encode: false, arrayFormat: 'comma' }), '???', 'array, comma (pending issue #378)', { skip: true });
st.equal(
qs.stringify(withArray, { encode: false, arrayFormat: 'comma' }),
'???',
'array, comma',
{ skip: 'TODO: figure out what this should do' }
);

@@ -845,0 +862,0 @@ st.end();

Sorry, the diff of this file is not supported yet

Sorry, the diff of this file is not supported yet

Sorry, the diff of this file is too big to display