qs 6.6.1 → 6.6.3
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/CHANGELOG.md +12 -0
- package/README.md +9 -3
- package/dist/qs.js +10 -10
- package/lib/parse.js +4 -4
- package/lib/utils.js +6 -6
- package/package.json +13 -4
- package/test/parse.js +9 -0
- package/test/stringify.js +6 -0
package/CHANGELOG.md
CHANGED
|
@@ -1,3 +1,15 @@
|
|
|
1
|
+
## **6.6.3**
|
|
2
|
+
- [Fix] fix regressions from robustness refactor
|
|
3
|
+
- [meta] add `npmignore` to autogenerate an npmignore file
|
|
4
|
+
- [actions] update reusable workflows
|
|
5
|
+
|
|
6
|
+
## **6.6.2**
|
|
7
|
+
- [Robustness] avoid `.push`, use `void`
|
|
8
|
+
- [readme] clarify `parseArrays` and `arrayLimit` documentation (#543)
|
|
9
|
+
- [readme] document that `addQueryPrefix` does not add `?` to empty output (#418)
|
|
10
|
+
- [readme] replace runkit CI badge with shields.io check-runs badge
|
|
11
|
+
- [actions] fix rebase workflow permissions
|
|
12
|
+
|
|
1
13
|
## **6.6.1**
|
|
2
14
|
- [Fix] `parse`: ignore `__proto__` keys (#428)
|
|
3
15
|
- [Fix] fix for an impossible situation: when the formatter is called with a non-string value
|
package/README.md
CHANGED
|
@@ -238,7 +238,7 @@ var withIndexedEmptyString = qs.parse('a[0]=b&a[1]=&a[2]=c');
|
|
|
238
238
|
assert.deepEqual(withIndexedEmptyString, { a: ['b', '', 'c'] });
|
|
239
239
|
```
|
|
240
240
|
|
|
241
|
-
**qs** will also limit
|
|
241
|
+
**qs** will also limit arrays to a maximum of `20` elements. Any array members with an index of `20` or greater will
|
|
242
242
|
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.
|
|
243
243
|
|
|
244
244
|
```javascript
|
|
@@ -253,7 +253,7 @@ var withArrayLimit = qs.parse('a[1]=b', { arrayLimit: 0 });
|
|
|
253
253
|
assert.deepEqual(withArrayLimit, { a: { '1': 'b' } });
|
|
254
254
|
```
|
|
255
255
|
|
|
256
|
-
To
|
|
256
|
+
To prevent array syntax (`a[]`, `a[0]`) from being parsed as arrays, set `parseArrays` to `false`.
|
|
257
257
|
|
|
258
258
|
```javascript
|
|
259
259
|
var noParsingArrays = qs.parse('a[]=b', { parseArrays: false });
|
|
@@ -417,6 +417,12 @@ The query string may optionally be prepended with a question mark:
|
|
|
417
417
|
assert.equal(qs.stringify({ a: 'b', c: 'd' }, { addQueryPrefix: true }), '?a=b&c=d');
|
|
418
418
|
```
|
|
419
419
|
|
|
420
|
+
Note that when the output is an empty string, the prefix will not be added:
|
|
421
|
+
|
|
422
|
+
```javascript
|
|
423
|
+
assert.equal(qs.stringify({}, { addQueryPrefix: true }), '');
|
|
424
|
+
```
|
|
425
|
+
|
|
420
426
|
The delimiter may be overridden with stringify as well:
|
|
421
427
|
|
|
422
428
|
```javascript
|
|
@@ -592,5 +598,5 @@ The maintainers of qs and thousands of other packages are working with Tidelift
|
|
|
592
598
|
[downloads-url]: https://npm-stat.com/charts.html?package=qs
|
|
593
599
|
[codecov-image]: https://codecov.io/gh/ljharb/qs/branch/main/graphs/badge.svg
|
|
594
600
|
[codecov-url]: https://app.codecov.io/gh/ljharb/qs/
|
|
595
|
-
[actions-image]: https://img.shields.io/
|
|
601
|
+
[actions-image]: https://img.shields.io/github/check-runs/ljharb/qs/main
|
|
596
602
|
[actions-url]: https://github.com/ljharb/qs/actions
|
package/dist/qs.js
CHANGED
|
@@ -82,7 +82,7 @@ var charsetSentinel = 'utf8=%E2%9C%93'; // encodeURIComponent('✓')
|
|
|
82
82
|
var parseValues = function parseQueryStringValues(str, options) {
|
|
83
83
|
var obj = {};
|
|
84
84
|
var cleanStr = options.ignoreQueryPrefix ? str.replace(/^\?/, '') : str;
|
|
85
|
-
var limit = options.parameterLimit === Infinity ? undefined : options.parameterLimit;
|
|
85
|
+
var limit = options.parameterLimit === Infinity ? void undefined : options.parameterLimit;
|
|
86
86
|
var parts = cleanStr.split(options.delimiter, limit);
|
|
87
87
|
var skipIndex = -1; // Keep track of where the utf8 sentinel was found
|
|
88
88
|
var i;
|
|
@@ -197,7 +197,7 @@ var parseKeys = function parseQueryStringKeys(givenKey, val, options) {
|
|
|
197
197
|
}
|
|
198
198
|
}
|
|
199
199
|
|
|
200
|
-
keys.
|
|
200
|
+
keys[keys.length] = parent;
|
|
201
201
|
}
|
|
202
202
|
|
|
203
203
|
// Loop through children appending to the array until we hit depth
|
|
@@ -210,13 +210,13 @@ var parseKeys = function parseQueryStringKeys(givenKey, val, options) {
|
|
|
210
210
|
return;
|
|
211
211
|
}
|
|
212
212
|
}
|
|
213
|
-
keys.
|
|
213
|
+
keys[keys.length] = segment[1];
|
|
214
214
|
}
|
|
215
215
|
|
|
216
216
|
// If there's a remainder, just add whatever is left
|
|
217
217
|
|
|
218
218
|
if (segment) {
|
|
219
|
-
keys.
|
|
219
|
+
keys[keys.length] = '[' + key.slice(segment.index) + ']';
|
|
220
220
|
}
|
|
221
221
|
|
|
222
222
|
return parseObject(keys, val, options);
|
|
@@ -555,7 +555,7 @@ var isArray = Array.isArray;
|
|
|
555
555
|
var hexTable = (function () {
|
|
556
556
|
var array = [];
|
|
557
557
|
for (var i = 0; i < 256; ++i) {
|
|
558
|
-
array.
|
|
558
|
+
array[array.length] = '%' + ((i < 16 ? '0' : '') + i.toString(16)).toUpperCase();
|
|
559
559
|
}
|
|
560
560
|
|
|
561
561
|
return array;
|
|
@@ -571,7 +571,7 @@ var compactQueue = function compactQueue(queue) {
|
|
|
571
571
|
|
|
572
572
|
for (var j = 0; j < obj.length; ++j) {
|
|
573
573
|
if (typeof obj[j] !== 'undefined') {
|
|
574
|
-
compacted.
|
|
574
|
+
compacted[compacted.length] = obj[j];
|
|
575
575
|
}
|
|
576
576
|
}
|
|
577
577
|
|
|
@@ -598,7 +598,7 @@ var merge = function merge(target, source, options) {
|
|
|
598
598
|
|
|
599
599
|
if (typeof source !== 'object') {
|
|
600
600
|
if (isArray(target)) {
|
|
601
|
-
target.
|
|
601
|
+
target[target.length] = source;
|
|
602
602
|
} else if (target && typeof target === 'object') {
|
|
603
603
|
if ((options && (options.plainObjects || options.allowPrototypes)) || !has.call(Object.prototype, source)) {
|
|
604
604
|
target[source] = true;
|
|
@@ -626,7 +626,7 @@ var merge = function merge(target, source, options) {
|
|
|
626
626
|
if (targetItem && typeof targetItem === 'object' && item && typeof item === 'object') {
|
|
627
627
|
target[i] = merge(targetItem, item, options);
|
|
628
628
|
} else {
|
|
629
|
-
target.
|
|
629
|
+
target[target.length] = item;
|
|
630
630
|
}
|
|
631
631
|
} else {
|
|
632
632
|
target[i] = item;
|
|
@@ -739,8 +739,8 @@ var compact = function compact(value) {
|
|
|
739
739
|
var key = keys[j];
|
|
740
740
|
var val = obj[key];
|
|
741
741
|
if (typeof val === 'object' && val !== null && refs.indexOf(val) === -1) {
|
|
742
|
-
queue.
|
|
743
|
-
refs.
|
|
742
|
+
queue[queue.length] = { obj: obj, prop: key };
|
|
743
|
+
refs[refs.length] = val;
|
|
744
744
|
}
|
|
745
745
|
}
|
|
746
746
|
}
|
package/lib/parse.js
CHANGED
|
@@ -40,7 +40,7 @@ var charsetSentinel = 'utf8=%E2%9C%93'; // encodeURIComponent('✓')
|
|
|
40
40
|
var parseValues = function parseQueryStringValues(str, options) {
|
|
41
41
|
var obj = {};
|
|
42
42
|
var cleanStr = options.ignoreQueryPrefix ? str.replace(/^\?/, '') : str;
|
|
43
|
-
var limit = options.parameterLimit === Infinity ? undefined : options.parameterLimit;
|
|
43
|
+
var limit = options.parameterLimit === Infinity ? void undefined : options.parameterLimit;
|
|
44
44
|
var parts = cleanStr.split(options.delimiter, limit);
|
|
45
45
|
var skipIndex = -1; // Keep track of where the utf8 sentinel was found
|
|
46
46
|
var i;
|
|
@@ -155,7 +155,7 @@ var parseKeys = function parseQueryStringKeys(givenKey, val, options) {
|
|
|
155
155
|
}
|
|
156
156
|
}
|
|
157
157
|
|
|
158
|
-
keys.
|
|
158
|
+
keys[keys.length] = parent;
|
|
159
159
|
}
|
|
160
160
|
|
|
161
161
|
// Loop through children appending to the array until we hit depth
|
|
@@ -168,13 +168,13 @@ var parseKeys = function parseQueryStringKeys(givenKey, val, options) {
|
|
|
168
168
|
return;
|
|
169
169
|
}
|
|
170
170
|
}
|
|
171
|
-
keys.
|
|
171
|
+
keys[keys.length] = segment[1];
|
|
172
172
|
}
|
|
173
173
|
|
|
174
174
|
// If there's a remainder, just add whatever is left
|
|
175
175
|
|
|
176
176
|
if (segment) {
|
|
177
|
-
keys.
|
|
177
|
+
keys[keys.length] = '[' + key.slice(segment.index) + ']';
|
|
178
178
|
}
|
|
179
179
|
|
|
180
180
|
return parseObject(keys, val, options);
|
package/lib/utils.js
CHANGED
|
@@ -6,7 +6,7 @@ var isArray = Array.isArray;
|
|
|
6
6
|
var hexTable = (function () {
|
|
7
7
|
var array = [];
|
|
8
8
|
for (var i = 0; i < 256; ++i) {
|
|
9
|
-
array.
|
|
9
|
+
array[array.length] = '%' + ((i < 16 ? '0' : '') + i.toString(16)).toUpperCase();
|
|
10
10
|
}
|
|
11
11
|
|
|
12
12
|
return array;
|
|
@@ -22,7 +22,7 @@ var compactQueue = function compactQueue(queue) {
|
|
|
22
22
|
|
|
23
23
|
for (var j = 0; j < obj.length; ++j) {
|
|
24
24
|
if (typeof obj[j] !== 'undefined') {
|
|
25
|
-
compacted.
|
|
25
|
+
compacted[compacted.length] = obj[j];
|
|
26
26
|
}
|
|
27
27
|
}
|
|
28
28
|
|
|
@@ -49,7 +49,7 @@ var merge = function merge(target, source, options) {
|
|
|
49
49
|
|
|
50
50
|
if (typeof source !== 'object') {
|
|
51
51
|
if (isArray(target)) {
|
|
52
|
-
target.
|
|
52
|
+
target[target.length] = source;
|
|
53
53
|
} else if (target && typeof target === 'object') {
|
|
54
54
|
if ((options && (options.plainObjects || options.allowPrototypes)) || !has.call(Object.prototype, source)) {
|
|
55
55
|
target[source] = true;
|
|
@@ -77,7 +77,7 @@ var merge = function merge(target, source, options) {
|
|
|
77
77
|
if (targetItem && typeof targetItem === 'object' && item && typeof item === 'object') {
|
|
78
78
|
target[i] = merge(targetItem, item, options);
|
|
79
79
|
} else {
|
|
80
|
-
target.
|
|
80
|
+
target[target.length] = item;
|
|
81
81
|
}
|
|
82
82
|
} else {
|
|
83
83
|
target[i] = item;
|
|
@@ -190,8 +190,8 @@ var compact = function compact(value) {
|
|
|
190
190
|
var key = keys[j];
|
|
191
191
|
var val = obj[key];
|
|
192
192
|
if (typeof val === 'object' && val !== null && refs.indexOf(val) === -1) {
|
|
193
|
-
queue.
|
|
194
|
-
refs.
|
|
193
|
+
queue[queue.length] = { obj: obj, prop: key };
|
|
194
|
+
refs[refs.length] = val;
|
|
195
195
|
}
|
|
196
196
|
}
|
|
197
197
|
}
|
package/package.json
CHANGED
|
@@ -2,7 +2,7 @@
|
|
|
2
2
|
"name": "qs",
|
|
3
3
|
"description": "A querystring parser that supports nesting and arrays, with a depth limit",
|
|
4
4
|
"homepage": "https://github.com/ljharb/qs",
|
|
5
|
-
"version": "6.6.
|
|
5
|
+
"version": "6.6.3",
|
|
6
6
|
"repository": {
|
|
7
7
|
"type": "git",
|
|
8
8
|
"url": "https://github.com/ljharb/qs.git"
|
|
@@ -38,10 +38,11 @@
|
|
|
38
38
|
"qs-iconv": "^1.0.4",
|
|
39
39
|
"safe-publish-latest": "^2.0.0",
|
|
40
40
|
"safer-buffer": "^2.1.2",
|
|
41
|
-
"tape": "^4.14.0"
|
|
41
|
+
"tape": "^4.14.0",
|
|
42
|
+
"npmignore": "^0.3.1"
|
|
42
43
|
},
|
|
43
44
|
"scripts": {
|
|
44
|
-
"prepublishOnly": "safe-publish-latest && npm run dist",
|
|
45
|
+
"prepublishOnly": "safe-publish-latest && npmignore --auto --commentLines=autogenerated && npm run dist",
|
|
45
46
|
"prepublish": "not-in-publish || npm run prepublishOnly",
|
|
46
47
|
"pretest": "npm run --silent readme && npm run --silent lint",
|
|
47
48
|
"test": "npm run --silent tests-only",
|
|
@@ -52,5 +53,13 @@
|
|
|
52
53
|
"lint": "eslint --ext=js,mjs .",
|
|
53
54
|
"dist": "mkdirp dist && browserify --standalone Qs lib/index.js > dist/qs.js"
|
|
54
55
|
},
|
|
55
|
-
"license": "BSD-3-Clause"
|
|
56
|
+
"license": "BSD-3-Clause",
|
|
57
|
+
"publishConfig": {
|
|
58
|
+
"ignore": [
|
|
59
|
+
"!dist/*",
|
|
60
|
+
"bower.json",
|
|
61
|
+
"component.json",
|
|
62
|
+
".github/workflows"
|
|
63
|
+
]
|
|
64
|
+
}
|
|
56
65
|
}
|
package/test/parse.js
CHANGED
|
@@ -52,6 +52,15 @@ test('parse()', function (t) {
|
|
|
52
52
|
st.end();
|
|
53
53
|
});
|
|
54
54
|
|
|
55
|
+
t.test('correctly computes the remainder when depth is exceeded', function (st) {
|
|
56
|
+
st.deepEqual(
|
|
57
|
+
qs.parse('a[b][c][d][e]=f', { depth: 2 }),
|
|
58
|
+
{ a: { b: { c: { '[d][e]': 'f' } } } },
|
|
59
|
+
'the remainder is "[d][e]", not the full original key'
|
|
60
|
+
);
|
|
61
|
+
st.end();
|
|
62
|
+
});
|
|
63
|
+
|
|
55
64
|
t.deepEqual(qs.parse('a=b&a=c'), { a: ['b', 'c'] }, 'parses a simple array');
|
|
56
65
|
|
|
57
66
|
t.test('parses an explicit array', function (st) {
|
package/test/stringify.js
CHANGED
|
@@ -19,6 +19,12 @@ test('stringify()', function (t) {
|
|
|
19
19
|
st.end();
|
|
20
20
|
});
|
|
21
21
|
|
|
22
|
+
t.test('correctly encodes low-byte characters', function (st) {
|
|
23
|
+
st.equal(qs.stringify({ a: String.fromCharCode(1) }), 'a=%01', 'encodes 0x01');
|
|
24
|
+
st.equal(qs.stringify({ a: String.fromCharCode(15) }), 'a=%0F', 'encodes 0x0F');
|
|
25
|
+
st.end();
|
|
26
|
+
});
|
|
27
|
+
|
|
22
28
|
t.test('stringifies falsy values', function (st) {
|
|
23
29
|
st.equal(qs.stringify(undefined), '');
|
|
24
30
|
st.equal(qs.stringify(null), '');
|