qs 6.9.7 → 6.9.9
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 +11 -11
- package/lib/parse.js +4 -4
- package/lib/utils.js +7 -7
- package/package.json +12 -3
- package/test/parse.js +9 -0
- package/test/stringify.js +6 -0
package/CHANGELOG.md
CHANGED
|
@@ -1,3 +1,15 @@
|
|
|
1
|
+
## **6.9.9**
|
|
2
|
+
- [Fix] fix regressions from robustness refactor
|
|
3
|
+
- [meta] add `npmignore` to autogenerate an npmignore file
|
|
4
|
+
- [actions] update reusable workflows
|
|
5
|
+
|
|
6
|
+
## **6.9.8**
|
|
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.9.7**
|
|
2
14
|
- [Fix] `parse`: ignore `__proto__` keys (#428)
|
|
3
15
|
- [Fix] `stringify`: avoid encoding arrayformat comma when `encodeValuesOnly = true` (#424)
|
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 });
|
|
@@ -437,6 +437,12 @@ The query string may optionally be prepended with a question mark:
|
|
|
437
437
|
assert.equal(qs.stringify({ a: 'b', c: 'd' }, { addQueryPrefix: true }), '?a=b&c=d');
|
|
438
438
|
```
|
|
439
439
|
|
|
440
|
+
Note that when the output is an empty string, the prefix will not be added:
|
|
441
|
+
|
|
442
|
+
```javascript
|
|
443
|
+
assert.equal(qs.stringify({}, { addQueryPrefix: true }), '');
|
|
444
|
+
```
|
|
445
|
+
|
|
440
446
|
The delimiter may be overridden with stringify as well:
|
|
441
447
|
|
|
442
448
|
```javascript
|
|
@@ -612,5 +618,5 @@ The maintainers of qs and thousands of other packages are working with Tidelift
|
|
|
612
618
|
[downloads-url]: https://npm-stat.com/charts.html?package=qs
|
|
613
619
|
[codecov-image]: https://codecov.io/gh/ljharb/qs/branch/main/graphs/badge.svg
|
|
614
620
|
[codecov-url]: https://app.codecov.io/gh/ljharb/qs/
|
|
615
|
-
[actions-image]: https://img.shields.io/
|
|
621
|
+
[actions-image]: https://img.shields.io/github/check-runs/ljharb/qs/main
|
|
616
622
|
[actions-url]: https://github.com/ljharb/qs/actions
|
package/dist/qs.js
CHANGED
|
@@ -89,7 +89,7 @@ var charsetSentinel = 'utf8=%E2%9C%93'; // encodeURIComponent('✓')
|
|
|
89
89
|
var parseValues = function parseQueryStringValues(str, options) {
|
|
90
90
|
var obj = {};
|
|
91
91
|
var cleanStr = options.ignoreQueryPrefix ? str.replace(/^\?/, '') : str;
|
|
92
|
-
var limit = options.parameterLimit === Infinity ? undefined : options.parameterLimit;
|
|
92
|
+
var limit = options.parameterLimit === Infinity ? void undefined : options.parameterLimit;
|
|
93
93
|
var parts = cleanStr.split(options.delimiter, limit);
|
|
94
94
|
var skipIndex = -1; // Keep track of where the utf8 sentinel was found
|
|
95
95
|
var i;
|
|
@@ -214,7 +214,7 @@ var parseKeys = function parseQueryStringKeys(givenKey, val, options, valuesPars
|
|
|
214
214
|
}
|
|
215
215
|
}
|
|
216
216
|
|
|
217
|
-
keys.
|
|
217
|
+
keys[keys.length] = parent;
|
|
218
218
|
}
|
|
219
219
|
|
|
220
220
|
// Loop through children appending to the array until we hit depth
|
|
@@ -227,13 +227,13 @@ var parseKeys = function parseQueryStringKeys(givenKey, val, options, valuesPars
|
|
|
227
227
|
return;
|
|
228
228
|
}
|
|
229
229
|
}
|
|
230
|
-
keys.
|
|
230
|
+
keys[keys.length] = segment[1];
|
|
231
231
|
}
|
|
232
232
|
|
|
233
233
|
// If there's a remainder, just add whatever is left
|
|
234
234
|
|
|
235
235
|
if (segment) {
|
|
236
|
-
keys.
|
|
236
|
+
keys[keys.length] = '[' + key.slice(segment.index) + ']';
|
|
237
237
|
}
|
|
238
238
|
|
|
239
239
|
return parseObject(keys, val, options, valuesParsed);
|
|
@@ -595,7 +595,7 @@ var isArray = Array.isArray;
|
|
|
595
595
|
var hexTable = (function () {
|
|
596
596
|
var array = [];
|
|
597
597
|
for (var i = 0; i < 256; ++i) {
|
|
598
|
-
array.
|
|
598
|
+
array[array.length] = '%' + ((i < 16 ? '0' : '') + i.toString(16)).toUpperCase();
|
|
599
599
|
}
|
|
600
600
|
|
|
601
601
|
return array;
|
|
@@ -611,7 +611,7 @@ var compactQueue = function compactQueue(queue) {
|
|
|
611
611
|
|
|
612
612
|
for (var j = 0; j < obj.length; ++j) {
|
|
613
613
|
if (typeof obj[j] !== 'undefined') {
|
|
614
|
-
compacted.
|
|
614
|
+
compacted[compacted.length] = obj[j];
|
|
615
615
|
}
|
|
616
616
|
}
|
|
617
617
|
|
|
@@ -639,7 +639,7 @@ var merge = function merge(target, source, options) {
|
|
|
639
639
|
|
|
640
640
|
if (typeof source !== 'object') {
|
|
641
641
|
if (isArray(target)) {
|
|
642
|
-
target.
|
|
642
|
+
target[target.length] = source;
|
|
643
643
|
} else if (target && typeof target === 'object') {
|
|
644
644
|
if ((options && (options.plainObjects || options.allowPrototypes)) || !has.call(Object.prototype, source)) {
|
|
645
645
|
target[source] = true;
|
|
@@ -667,7 +667,7 @@ var merge = function merge(target, source, options) {
|
|
|
667
667
|
if (targetItem && typeof targetItem === 'object' && item && typeof item === 'object') {
|
|
668
668
|
target[i] = merge(targetItem, item, options);
|
|
669
669
|
} else {
|
|
670
|
-
target.
|
|
670
|
+
target[target.length] = item;
|
|
671
671
|
}
|
|
672
672
|
} else {
|
|
673
673
|
target[i] = item;
|
|
@@ -787,8 +787,8 @@ var compact = function compact(value) {
|
|
|
787
787
|
var key = keys[j];
|
|
788
788
|
var val = obj[key];
|
|
789
789
|
if (typeof val === 'object' && val !== null && refs.indexOf(val) === -1) {
|
|
790
|
-
queue.
|
|
791
|
-
refs.
|
|
790
|
+
queue[queue.length] = { obj: obj, prop: key };
|
|
791
|
+
refs[refs.length] = val;
|
|
792
792
|
}
|
|
793
793
|
}
|
|
794
794
|
}
|
|
@@ -818,7 +818,7 @@ var maybeMap = function maybeMap(val, fn) {
|
|
|
818
818
|
if (isArray(val)) {
|
|
819
819
|
var mapped = [];
|
|
820
820
|
for (var i = 0; i < val.length; i += 1) {
|
|
821
|
-
mapped.
|
|
821
|
+
mapped[mapped.length] = fn(val[i]);
|
|
822
822
|
}
|
|
823
823
|
return mapped;
|
|
824
824
|
}
|
package/lib/parse.js
CHANGED
|
@@ -50,7 +50,7 @@ var charsetSentinel = 'utf8=%E2%9C%93'; // encodeURIComponent('✓')
|
|
|
50
50
|
var parseValues = function parseQueryStringValues(str, options) {
|
|
51
51
|
var obj = {};
|
|
52
52
|
var cleanStr = options.ignoreQueryPrefix ? str.replace(/^\?/, '') : str;
|
|
53
|
-
var limit = options.parameterLimit === Infinity ? undefined : options.parameterLimit;
|
|
53
|
+
var limit = options.parameterLimit === Infinity ? void undefined : options.parameterLimit;
|
|
54
54
|
var parts = cleanStr.split(options.delimiter, limit);
|
|
55
55
|
var skipIndex = -1; // Keep track of where the utf8 sentinel was found
|
|
56
56
|
var i;
|
|
@@ -175,7 +175,7 @@ var parseKeys = function parseQueryStringKeys(givenKey, val, options, valuesPars
|
|
|
175
175
|
}
|
|
176
176
|
}
|
|
177
177
|
|
|
178
|
-
keys.
|
|
178
|
+
keys[keys.length] = parent;
|
|
179
179
|
}
|
|
180
180
|
|
|
181
181
|
// Loop through children appending to the array until we hit depth
|
|
@@ -188,13 +188,13 @@ var parseKeys = function parseQueryStringKeys(givenKey, val, options, valuesPars
|
|
|
188
188
|
return;
|
|
189
189
|
}
|
|
190
190
|
}
|
|
191
|
-
keys.
|
|
191
|
+
keys[keys.length] = segment[1];
|
|
192
192
|
}
|
|
193
193
|
|
|
194
194
|
// If there's a remainder, just add whatever is left
|
|
195
195
|
|
|
196
196
|
if (segment) {
|
|
197
|
-
keys.
|
|
197
|
+
keys[keys.length] = '[' + key.slice(segment.index) + ']';
|
|
198
198
|
}
|
|
199
199
|
|
|
200
200
|
return parseObject(keys, val, options, valuesParsed);
|
package/lib/utils.js
CHANGED
|
@@ -8,7 +8,7 @@ var isArray = Array.isArray;
|
|
|
8
8
|
var hexTable = (function () {
|
|
9
9
|
var array = [];
|
|
10
10
|
for (var i = 0; i < 256; ++i) {
|
|
11
|
-
array.
|
|
11
|
+
array[array.length] = '%' + ((i < 16 ? '0' : '') + i.toString(16)).toUpperCase();
|
|
12
12
|
}
|
|
13
13
|
|
|
14
14
|
return array;
|
|
@@ -24,7 +24,7 @@ var compactQueue = function compactQueue(queue) {
|
|
|
24
24
|
|
|
25
25
|
for (var j = 0; j < obj.length; ++j) {
|
|
26
26
|
if (typeof obj[j] !== 'undefined') {
|
|
27
|
-
compacted.
|
|
27
|
+
compacted[compacted.length] = obj[j];
|
|
28
28
|
}
|
|
29
29
|
}
|
|
30
30
|
|
|
@@ -52,7 +52,7 @@ var merge = function merge(target, source, options) {
|
|
|
52
52
|
|
|
53
53
|
if (typeof source !== 'object') {
|
|
54
54
|
if (isArray(target)) {
|
|
55
|
-
target.
|
|
55
|
+
target[target.length] = source;
|
|
56
56
|
} else if (target && typeof target === 'object') {
|
|
57
57
|
if ((options && (options.plainObjects || options.allowPrototypes)) || !has.call(Object.prototype, source)) {
|
|
58
58
|
target[source] = true;
|
|
@@ -80,7 +80,7 @@ var merge = function merge(target, source, options) {
|
|
|
80
80
|
if (targetItem && typeof targetItem === 'object' && item && typeof item === 'object') {
|
|
81
81
|
target[i] = merge(targetItem, item, options);
|
|
82
82
|
} else {
|
|
83
|
-
target.
|
|
83
|
+
target[target.length] = item;
|
|
84
84
|
}
|
|
85
85
|
} else {
|
|
86
86
|
target[i] = item;
|
|
@@ -200,8 +200,8 @@ var compact = function compact(value) {
|
|
|
200
200
|
var key = keys[j];
|
|
201
201
|
var val = obj[key];
|
|
202
202
|
if (typeof val === 'object' && val !== null && refs.indexOf(val) === -1) {
|
|
203
|
-
queue.
|
|
204
|
-
refs.
|
|
203
|
+
queue[queue.length] = { obj: obj, prop: key };
|
|
204
|
+
refs[refs.length] = val;
|
|
205
205
|
}
|
|
206
206
|
}
|
|
207
207
|
}
|
|
@@ -231,7 +231,7 @@ var maybeMap = function maybeMap(val, fn) {
|
|
|
231
231
|
if (isArray(val)) {
|
|
232
232
|
var mapped = [];
|
|
233
233
|
for (var i = 0; i < val.length; i += 1) {
|
|
234
|
-
mapped.
|
|
234
|
+
mapped[mapped.length] = fn(val[i]);
|
|
235
235
|
}
|
|
236
236
|
return mapped;
|
|
237
237
|
}
|
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.9.
|
|
5
|
+
"version": "6.9.9",
|
|
6
6
|
"repository": {
|
|
7
7
|
"type": "git",
|
|
8
8
|
"url": "https://github.com/ljharb/qs.git"
|
|
@@ -46,10 +46,11 @@
|
|
|
46
46
|
"qs-iconv": "^1.0.4",
|
|
47
47
|
"safe-publish-latest": "^2.0.0",
|
|
48
48
|
"safer-buffer": "^2.1.2",
|
|
49
|
-
"tape": "^5.4.0"
|
|
49
|
+
"tape": "^5.4.0",
|
|
50
|
+
"npmignore": "^0.3.1"
|
|
50
51
|
},
|
|
51
52
|
"scripts": {
|
|
52
|
-
"prepublishOnly": "safe-publish-latest && npm run dist",
|
|
53
|
+
"prepublishOnly": "safe-publish-latest && npmignore --auto --commentLines=autogenerated && npm run dist",
|
|
53
54
|
"prepublish": "not-in-publish || npm run prepublishOnly",
|
|
54
55
|
"pretest": "npm run --silent readme && npm run --silent lint",
|
|
55
56
|
"test": "npm run tests-only",
|
|
@@ -66,5 +67,13 @@
|
|
|
66
67
|
"iconv-lite",
|
|
67
68
|
"mkdirp"
|
|
68
69
|
]
|
|
70
|
+
},
|
|
71
|
+
"publishConfig": {
|
|
72
|
+
"ignore": [
|
|
73
|
+
"!dist/*",
|
|
74
|
+
"bower.json",
|
|
75
|
+
"component.json",
|
|
76
|
+
".github/workflows"
|
|
77
|
+
]
|
|
69
78
|
}
|
|
70
79
|
}
|
package/test/parse.js
CHANGED
|
@@ -84,6 +84,15 @@ test('parse()', function (t) {
|
|
|
84
84
|
st.end();
|
|
85
85
|
});
|
|
86
86
|
|
|
87
|
+
t.test('correctly computes the remainder when depth is exceeded', function (st) {
|
|
88
|
+
st.deepEqual(
|
|
89
|
+
qs.parse('a[b][c][d][e]=f', { depth: 2 }),
|
|
90
|
+
{ a: { b: { c: { '[d][e]': 'f' } } } },
|
|
91
|
+
'the remainder is "[d][e]", not the full original key'
|
|
92
|
+
);
|
|
93
|
+
st.end();
|
|
94
|
+
});
|
|
95
|
+
|
|
87
96
|
t.test('uses original key when depth = 0', function (st) {
|
|
88
97
|
st.deepEqual(qs.parse('a[0]=b&a[1]=c', { depth: 0 }), { 'a[0]': 'b', 'a[1]': 'c' });
|
|
89
98
|
st.deepEqual(qs.parse('a[0][0]=b&a[0][1]=c&a[1]=d&e=2', { depth: 0 }), { 'a[0][0]': 'b', 'a[0][1]': 'c', 'a[1]': 'd', e: '2' });
|
package/test/stringify.js
CHANGED
|
@@ -21,6 +21,12 @@ test('stringify()', function (t) {
|
|
|
21
21
|
st.end();
|
|
22
22
|
});
|
|
23
23
|
|
|
24
|
+
t.test('correctly encodes low-byte characters', function (st) {
|
|
25
|
+
st.equal(qs.stringify({ a: String.fromCharCode(1) }), 'a=%01', 'encodes 0x01');
|
|
26
|
+
st.equal(qs.stringify({ a: String.fromCharCode(15) }), 'a=%0F', 'encodes 0x0F');
|
|
27
|
+
st.end();
|
|
28
|
+
});
|
|
29
|
+
|
|
24
30
|
t.test('stringifies falsy values', function (st) {
|
|
25
31
|
st.equal(qs.stringify(undefined), '');
|
|
26
32
|
st.equal(qs.stringify(null), '');
|