qs 6.5.2 → 6.5.4
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/.editorconfig +14 -1
- package/.eslintrc +21 -3
- package/.github/FUNDING.yml +12 -0
- package/.nycrc +13 -0
- package/CHANGELOG.md +31 -0
- package/LICENSE.md +29 -0
- package/README.md +62 -21
- package/bower.json +21 -0
- package/component.json +15 -0
- package/dist/qs.js +45 -35
- package/lib/formats.js +1 -1
- package/lib/parse.js +10 -9
- package/lib/stringify.js +21 -14
- package/lib/utils.js +13 -11
- package/package.json +18 -16
- package/test/parse.js +79 -4
- package/test/stringify.js +45 -0
- package/test/utils.js +31 -0
- package/.eslintignore +0 -1
- package/LICENSE +0 -28
- package/test/.eslintrc +0 -15
package/.editorconfig
CHANGED
|
@@ -7,11 +7,15 @@ end_of_line = lf
|
|
|
7
7
|
charset = utf-8
|
|
8
8
|
trim_trailing_whitespace = true
|
|
9
9
|
insert_final_newline = true
|
|
10
|
-
max_line_length =
|
|
10
|
+
max_line_length = 160
|
|
11
|
+
quote_type = single
|
|
11
12
|
|
|
12
13
|
[test/*]
|
|
13
14
|
max_line_length = off
|
|
14
15
|
|
|
16
|
+
[LICENSE.md]
|
|
17
|
+
indent_size = off
|
|
18
|
+
|
|
15
19
|
[*.md]
|
|
16
20
|
max_line_length = off
|
|
17
21
|
|
|
@@ -28,3 +32,12 @@ indent_size = 2
|
|
|
28
32
|
[LICENSE]
|
|
29
33
|
indent_size = 2
|
|
30
34
|
max_line_length = off
|
|
35
|
+
|
|
36
|
+
[coverage/**/*]
|
|
37
|
+
indent_size = off
|
|
38
|
+
indent_style = off
|
|
39
|
+
indent = off
|
|
40
|
+
max_line_length = off
|
|
41
|
+
|
|
42
|
+
[.nycrc]
|
|
43
|
+
indent_style = tab
|
package/.eslintrc
CHANGED
|
@@ -3,17 +3,35 @@
|
|
|
3
3
|
|
|
4
4
|
"extends": "@ljharb",
|
|
5
5
|
|
|
6
|
+
"ignorePatterns": [
|
|
7
|
+
"dist/",
|
|
8
|
+
],
|
|
9
|
+
|
|
6
10
|
"rules": {
|
|
7
11
|
"complexity": 0,
|
|
8
12
|
"consistent-return": 1,
|
|
9
|
-
|
|
13
|
+
"func-name-matching": 0,
|
|
10
14
|
"id-length": [2, { "min": 1, "max": 25, "properties": "never" }],
|
|
11
15
|
"indent": [2, 4],
|
|
16
|
+
"max-lines-per-function": 0,
|
|
12
17
|
"max-params": [2, 12],
|
|
13
18
|
"max-statements": [2, 45],
|
|
19
|
+
"multiline-comment-style": 0,
|
|
14
20
|
"no-continue": 1,
|
|
15
21
|
"no-magic-numbers": 0,
|
|
22
|
+
"no-param-reassign": 1,
|
|
16
23
|
"no-restricted-syntax": [2, "BreakStatement", "DebuggerStatement", "ForInStatement", "LabeledStatement", "WithStatement"],
|
|
17
|
-
|
|
18
|
-
|
|
24
|
+
},
|
|
25
|
+
|
|
26
|
+
"overrides": [
|
|
27
|
+
{
|
|
28
|
+
"files": "test/**",
|
|
29
|
+
"rules": {
|
|
30
|
+
"max-lines-per-function": 0,
|
|
31
|
+
"max-statements": 0,
|
|
32
|
+
"no-extend-native": 0,
|
|
33
|
+
"function-paren-newline": 0,
|
|
34
|
+
},
|
|
35
|
+
},
|
|
36
|
+
],
|
|
19
37
|
}
|
|
@@ -0,0 +1,12 @@
|
|
|
1
|
+
# These are supported funding model platforms
|
|
2
|
+
|
|
3
|
+
github: [ljharb]
|
|
4
|
+
patreon: # Replace with a single Patreon username
|
|
5
|
+
open_collective: # Replace with a single Open Collective username
|
|
6
|
+
ko_fi: # Replace with a single Ko-fi username
|
|
7
|
+
tidelift: npm/qs
|
|
8
|
+
community_bridge: # Replace with a single Community Bridge project-name e.g., cloud-foundry
|
|
9
|
+
liberapay: # Replace with a single Liberapay username
|
|
10
|
+
issuehunt: # Replace with a single IssueHunt username
|
|
11
|
+
otechie: # Replace with a single Otechie username
|
|
12
|
+
custom: # Replace with a single custom sponsorship URL
|
package/.nycrc
ADDED
package/CHANGELOG.md
CHANGED
|
@@ -1,3 +1,34 @@
|
|
|
1
|
+
## **6.5.4**
|
|
2
|
+
- [Robustness] avoid `.push`, use `void`
|
|
3
|
+
- [readme] clarify `parseArrays` and `arrayLimit` documentation (#543)
|
|
4
|
+
- [readme] document that `addQueryPrefix` does not add `?` to empty output (#418)
|
|
5
|
+
- [readme] replace runkit CI badge with shields.io check-runs badge
|
|
6
|
+
- [actions] fix rebase workflow permissions
|
|
7
|
+
|
|
8
|
+
## **6.5.3**
|
|
9
|
+
- [Fix] `parse`: ignore `__proto__` keys (#428)
|
|
10
|
+
- [Fix]` `utils.merge`: avoid a crash with a null target and a truthy non-array source
|
|
11
|
+
- [Fix] correctly parse nested arrays
|
|
12
|
+
- [Fix] `stringify`: fix a crash with `strictNullHandling` and a custom `filter`/`serializeDate` (#279)
|
|
13
|
+
- [Fix] `utils`: `merge`: fix crash when `source` is a truthy primitive & no options are provided
|
|
14
|
+
- [Fix] when `parseArrays` is false, properly handle keys ending in `[]`
|
|
15
|
+
- [Fix] fix for an impossible situation: when the formatter is called with a non-string value
|
|
16
|
+
- [Fix] `utils.merge`: avoid a crash with a null target and an array source
|
|
17
|
+
- [Refactor] `utils`: reduce observable [[Get]]s
|
|
18
|
+
- [Refactor] use cached `Array.isArray`
|
|
19
|
+
- [Refactor] `stringify`: Avoid arr = arr.concat(...), push to the existing instance (#269)
|
|
20
|
+
- [Refactor] `parse`: only need to reassign the var once
|
|
21
|
+
- [Robustness] `stringify`: avoid relying on a global `undefined` (#427)
|
|
22
|
+
- [readme] remove travis badge; add github actions/codecov badges; update URLs
|
|
23
|
+
- [Docs] Clean up license text so it’s properly detected as BSD-3-Clause
|
|
24
|
+
- [Docs] Clarify the need for "arrayLimit" option
|
|
25
|
+
- [meta] fix README.md (#399)
|
|
26
|
+
- [meta] add FUNDING.yml
|
|
27
|
+
- [actions] backport actions from main
|
|
28
|
+
- [Tests] always use `String(x)` over `x.toString()`
|
|
29
|
+
- [Tests] remove nonexistent tape option
|
|
30
|
+
- [Dev Deps] backport from main
|
|
31
|
+
|
|
1
32
|
## **6.5.2**
|
|
2
33
|
- [Fix] use `safer-buffer` instead of `Buffer` constructor
|
|
3
34
|
- [Refactor] utils: `module.exports` one thing, instead of mutating `exports` (#230)
|
package/LICENSE.md
ADDED
|
@@ -0,0 +1,29 @@
|
|
|
1
|
+
BSD 3-Clause License
|
|
2
|
+
|
|
3
|
+
Copyright (c) 2014, Nathan LaFreniere and other [contributors](https://github.com/ljharb/qs/graphs/contributors)
|
|
4
|
+
All rights reserved.
|
|
5
|
+
|
|
6
|
+
Redistribution and use in source and binary forms, with or without
|
|
7
|
+
modification, are permitted provided that the following conditions are met:
|
|
8
|
+
|
|
9
|
+
1. Redistributions of source code must retain the above copyright notice, this
|
|
10
|
+
list of conditions and the following disclaimer.
|
|
11
|
+
|
|
12
|
+
2. Redistributions in binary form must reproduce the above copyright notice,
|
|
13
|
+
this list of conditions and the following disclaimer in the documentation
|
|
14
|
+
and/or other materials provided with the distribution.
|
|
15
|
+
|
|
16
|
+
3. Neither the name of the copyright holder nor the names of its
|
|
17
|
+
contributors may be used to endorse or promote products derived from
|
|
18
|
+
this software without specific prior written permission.
|
|
19
|
+
|
|
20
|
+
THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
|
|
21
|
+
AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
|
|
22
|
+
IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
|
|
23
|
+
DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE
|
|
24
|
+
FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
|
|
25
|
+
DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
|
|
26
|
+
SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
|
|
27
|
+
CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
|
|
28
|
+
OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
|
|
29
|
+
OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
package/README.md
CHANGED
|
@@ -1,12 +1,13 @@
|
|
|
1
1
|
# qs <sup>[![Version Badge][2]][1]</sup>
|
|
2
2
|
|
|
3
|
-
[![
|
|
4
|
-
[![
|
|
5
|
-
[![
|
|
3
|
+
[![github actions][actions-image]][actions-url]
|
|
4
|
+
[![coverage][codecov-image]][codecov-url]
|
|
5
|
+
[![dependency status][deps-svg]][deps-url]
|
|
6
|
+
[![dev dependency status][dev-deps-svg]][dev-deps-url]
|
|
6
7
|
[![License][license-image]][license-url]
|
|
7
8
|
[![Downloads][downloads-image]][downloads-url]
|
|
8
9
|
|
|
9
|
-
[![npm badge][
|
|
10
|
+
[![npm badge][npm-badge-png]][package-url]
|
|
10
11
|
|
|
11
12
|
A querystring parsing and stringifying library with some added security.
|
|
12
13
|
|
|
@@ -181,8 +182,8 @@ var withIndexedEmptyString = qs.parse('a[0]=b&a[1]=&a[2]=c');
|
|
|
181
182
|
assert.deepEqual(withIndexedEmptyString, { a: ['b', '', 'c'] });
|
|
182
183
|
```
|
|
183
184
|
|
|
184
|
-
**qs** will also limit
|
|
185
|
-
instead be converted to an object with the index as the key
|
|
185
|
+
**qs** will also limit arrays to a maximum of `20` elements. Any array members with an index of `20` or greater will
|
|
186
|
+
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.
|
|
186
187
|
|
|
187
188
|
```javascript
|
|
188
189
|
var withMaxIndex = qs.parse('a[100]=b');
|
|
@@ -196,7 +197,7 @@ var withArrayLimit = qs.parse('a[1]=b', { arrayLimit: 0 });
|
|
|
196
197
|
assert.deepEqual(withArrayLimit, { a: { '1': 'b' } });
|
|
197
198
|
```
|
|
198
199
|
|
|
199
|
-
To
|
|
200
|
+
To prevent array syntax (`a[]`, `a[0]`) from being parsed as arrays, set `parseArrays` to `false`.
|
|
200
201
|
|
|
201
202
|
```javascript
|
|
202
203
|
var noParsingArrays = qs.parse('a[]=b', { parseArrays: false });
|
|
@@ -267,6 +268,30 @@ var decoded = qs.parse('x=z', { decoder: function (str) {
|
|
|
267
268
|
}})
|
|
268
269
|
```
|
|
269
270
|
|
|
271
|
+
You can encode keys and values using different logic by using the type argument provided to the encoder:
|
|
272
|
+
|
|
273
|
+
```javascript
|
|
274
|
+
var encoded = qs.stringify({ a: { b: 'c' } }, { encoder: function (str, defaultEncoder, charset, type) {
|
|
275
|
+
if (type === 'key') {
|
|
276
|
+
return // Encoded key
|
|
277
|
+
} else if (type === 'value') {
|
|
278
|
+
return // Encoded value
|
|
279
|
+
}
|
|
280
|
+
}})
|
|
281
|
+
```
|
|
282
|
+
|
|
283
|
+
The type argument is also provided to the decoder:
|
|
284
|
+
|
|
285
|
+
```javascript
|
|
286
|
+
var decoded = qs.parse('x=z', { decoder: function (str, defaultDecoder, charset, type) {
|
|
287
|
+
if (type === 'key') {
|
|
288
|
+
return // Decoded key
|
|
289
|
+
} else if (type === 'value') {
|
|
290
|
+
return // Decoded value
|
|
291
|
+
}
|
|
292
|
+
}})
|
|
293
|
+
```
|
|
294
|
+
|
|
270
295
|
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.
|
|
271
296
|
|
|
272
297
|
When arrays are stringified, by default they are given explicit indices:
|
|
@@ -336,6 +361,12 @@ The query string may optionally be prepended with a question mark:
|
|
|
336
361
|
assert.equal(qs.stringify({ a: 'b', c: 'd' }, { addQueryPrefix: true }), '?a=b&c=d');
|
|
337
362
|
```
|
|
338
363
|
|
|
364
|
+
Note that when the output is an empty string, the prefix will not be added:
|
|
365
|
+
|
|
366
|
+
```javascript
|
|
367
|
+
assert.equal(qs.stringify({}, { addQueryPrefix: true }), '');
|
|
368
|
+
```
|
|
369
|
+
|
|
339
370
|
The delimiter may be overridden with stringify as well:
|
|
340
371
|
|
|
341
372
|
```javascript
|
|
@@ -458,18 +489,28 @@ assert.equal(qs.stringify({ a: 'b c' }, { format : 'RFC3986' }), 'a=b%20c');
|
|
|
458
489
|
assert.equal(qs.stringify({ a: 'b c' }, { format : 'RFC1738' }), 'a=b+c');
|
|
459
490
|
```
|
|
460
491
|
|
|
461
|
-
|
|
462
|
-
|
|
463
|
-
[
|
|
464
|
-
|
|
465
|
-
|
|
466
|
-
|
|
467
|
-
|
|
468
|
-
|
|
469
|
-
[
|
|
470
|
-
|
|
471
|
-
[
|
|
472
|
-
[
|
|
492
|
+
## Security
|
|
493
|
+
|
|
494
|
+
Please email [@ljharb](https://github.com/ljharb) or see https://tidelift.com/security if you have a potential security vulnerability to report.
|
|
495
|
+
|
|
496
|
+
## qs for enterprise
|
|
497
|
+
|
|
498
|
+
Available as part of the Tidelift Subscription
|
|
499
|
+
|
|
500
|
+
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)
|
|
501
|
+
|
|
502
|
+
[package-url]: https://npmjs.org/package/qs
|
|
503
|
+
[npm-version-svg]: https://versionbadg.es/ljharb/qs.svg
|
|
504
|
+
[deps-svg]: https://david-dm.org/ljharb/qs.svg
|
|
505
|
+
[deps-url]: https://david-dm.org/ljharb/qs
|
|
506
|
+
[dev-deps-svg]: https://david-dm.org/ljharb/qs/dev-status.svg
|
|
507
|
+
[dev-deps-url]: https://david-dm.org/ljharb/qs#info=devDependencies
|
|
508
|
+
[npm-badge-png]: https://nodei.co/npm/qs.png?downloads=true&stars=true
|
|
509
|
+
[license-image]: https://img.shields.io/npm/l/qs.svg
|
|
473
510
|
[license-url]: LICENSE
|
|
474
|
-
[downloads-image]:
|
|
475
|
-
[downloads-url]:
|
|
511
|
+
[downloads-image]: https://img.shields.io/npm/dm/qs.svg
|
|
512
|
+
[downloads-url]: https://npm-stat.com/charts.html?package=qs
|
|
513
|
+
[codecov-image]: https://codecov.io/gh/ljharb/qs/branch/main/graphs/badge.svg
|
|
514
|
+
[codecov-url]: https://app.codecov.io/gh/ljharb/qs/
|
|
515
|
+
[actions-image]: https://img.shields.io/github/check-runs/ljharb/qs/main
|
|
516
|
+
[actions-url]: https://github.com/ljharb/qs/actions
|
package/bower.json
ADDED
|
@@ -0,0 +1,21 @@
|
|
|
1
|
+
{
|
|
2
|
+
"name": "qs",
|
|
3
|
+
"main": "dist/qs.js",
|
|
4
|
+
"homepage": "https://github.com/hapijs/qs",
|
|
5
|
+
"authors": [
|
|
6
|
+
"Nathan LaFreniere <quitlahok@gmail.com>"
|
|
7
|
+
],
|
|
8
|
+
"description": "A querystring parser that supports nesting and arrays, with a depth limit",
|
|
9
|
+
"keywords": [
|
|
10
|
+
"querystring",
|
|
11
|
+
"qs"
|
|
12
|
+
],
|
|
13
|
+
"license": "BSD-3-Clause",
|
|
14
|
+
"ignore": [
|
|
15
|
+
"**/.*",
|
|
16
|
+
"node_modules",
|
|
17
|
+
"bower_components",
|
|
18
|
+
"test",
|
|
19
|
+
"tests"
|
|
20
|
+
]
|
|
21
|
+
}
|
package/component.json
ADDED
|
@@ -0,0 +1,15 @@
|
|
|
1
|
+
{
|
|
2
|
+
"name": "qs",
|
|
3
|
+
"repository": "ljharb/qs",
|
|
4
|
+
"description": "query-string parser / stringifier with nesting support",
|
|
5
|
+
"version": "6.5.3",
|
|
6
|
+
"keywords": ["querystring", "query", "parser"],
|
|
7
|
+
"main": "lib/index.js",
|
|
8
|
+
"scripts": [
|
|
9
|
+
"lib/index.js",
|
|
10
|
+
"lib/parse.js",
|
|
11
|
+
"lib/stringify.js",
|
|
12
|
+
"lib/utils.js"
|
|
13
|
+
],
|
|
14
|
+
"license": "BSD-3-Clause"
|
|
15
|
+
}
|
package/dist/qs.js
CHANGED
|
@@ -11,7 +11,7 @@ module.exports = {
|
|
|
11
11
|
return replace.call(value, percentTwenties, '+');
|
|
12
12
|
},
|
|
13
13
|
RFC3986: function (value) {
|
|
14
|
-
return value;
|
|
14
|
+
return String(value);
|
|
15
15
|
}
|
|
16
16
|
},
|
|
17
17
|
RFC1738: 'RFC1738',
|
|
@@ -53,7 +53,7 @@ var defaults = {
|
|
|
53
53
|
var parseValues = function parseQueryStringValues(str, options) {
|
|
54
54
|
var obj = {};
|
|
55
55
|
var cleanStr = options.ignoreQueryPrefix ? str.replace(/^\?/, '') : str;
|
|
56
|
-
var limit = options.parameterLimit === Infinity ? undefined : options.parameterLimit;
|
|
56
|
+
var limit = options.parameterLimit === Infinity ? void undefined : options.parameterLimit;
|
|
57
57
|
var parts = cleanStr.split(options.delimiter, limit);
|
|
58
58
|
|
|
59
59
|
for (var i = 0; i < parts.length; ++i) {
|
|
@@ -87,14 +87,15 @@ var parseObject = function (chain, val, options) {
|
|
|
87
87
|
var obj;
|
|
88
88
|
var root = chain[i];
|
|
89
89
|
|
|
90
|
-
if (root === '[]') {
|
|
91
|
-
obj = [];
|
|
92
|
-
obj = obj.concat(leaf);
|
|
90
|
+
if (root === '[]' && options.parseArrays) {
|
|
91
|
+
obj = [].concat(leaf);
|
|
93
92
|
} else {
|
|
94
93
|
obj = options.plainObjects ? Object.create(null) : {};
|
|
95
94
|
var cleanRoot = root.charAt(0) === '[' && root.charAt(root.length - 1) === ']' ? root.slice(1, -1) : root;
|
|
96
95
|
var index = parseInt(cleanRoot, 10);
|
|
97
|
-
if (
|
|
96
|
+
if (!options.parseArrays && cleanRoot === '') {
|
|
97
|
+
obj = { 0: leaf };
|
|
98
|
+
} else if (
|
|
98
99
|
!isNaN(index)
|
|
99
100
|
&& root !== cleanRoot
|
|
100
101
|
&& String(index) === cleanRoot
|
|
@@ -103,7 +104,7 @@ var parseObject = function (chain, val, options) {
|
|
|
103
104
|
) {
|
|
104
105
|
obj = [];
|
|
105
106
|
obj[index] = leaf;
|
|
106
|
-
} else {
|
|
107
|
+
} else if (cleanRoot !== '__proto__') {
|
|
107
108
|
obj[cleanRoot] = leaf;
|
|
108
109
|
}
|
|
109
110
|
}
|
|
@@ -144,7 +145,7 @@ var parseKeys = function parseQueryStringKeys(givenKey, val, options) {
|
|
|
144
145
|
}
|
|
145
146
|
}
|
|
146
147
|
|
|
147
|
-
keys.
|
|
148
|
+
keys[keys.length] = parent;
|
|
148
149
|
}
|
|
149
150
|
|
|
150
151
|
// Loop through children appending to the array until we hit depth
|
|
@@ -157,13 +158,13 @@ var parseKeys = function parseQueryStringKeys(givenKey, val, options) {
|
|
|
157
158
|
return;
|
|
158
159
|
}
|
|
159
160
|
}
|
|
160
|
-
keys.
|
|
161
|
+
keys[keys.length] = segment[1];
|
|
161
162
|
}
|
|
162
163
|
|
|
163
164
|
// If there's a remainder, just add whatever is left
|
|
164
165
|
|
|
165
166
|
if (segment) {
|
|
166
|
-
keys.
|
|
167
|
+
keys[keys.length] = '[' + key.slice(segment.index + ']');
|
|
167
168
|
}
|
|
168
169
|
|
|
169
170
|
return parseObject(keys, val, options);
|
|
@@ -214,17 +215,23 @@ var utils = require('./utils');
|
|
|
214
215
|
var formats = require('./formats');
|
|
215
216
|
|
|
216
217
|
var arrayPrefixGenerators = {
|
|
217
|
-
brackets: function brackets(prefix) {
|
|
218
|
+
brackets: function brackets(prefix) {
|
|
218
219
|
return prefix + '[]';
|
|
219
220
|
},
|
|
220
|
-
indices: function indices(prefix, key) {
|
|
221
|
+
indices: function indices(prefix, key) {
|
|
221
222
|
return prefix + '[' + key + ']';
|
|
222
223
|
},
|
|
223
|
-
repeat: function repeat(prefix) {
|
|
224
|
+
repeat: function repeat(prefix) {
|
|
224
225
|
return prefix;
|
|
225
226
|
}
|
|
226
227
|
};
|
|
227
228
|
|
|
229
|
+
var isArray = Array.isArray;
|
|
230
|
+
var push = Array.prototype.push;
|
|
231
|
+
var pushToArray = function (arr, valueOrArray) {
|
|
232
|
+
push.apply(arr, isArray(valueOrArray) ? valueOrArray : [valueOrArray]);
|
|
233
|
+
};
|
|
234
|
+
|
|
228
235
|
var toISO = Date.prototype.toISOString;
|
|
229
236
|
|
|
230
237
|
var defaults = {
|
|
@@ -232,14 +239,14 @@ var defaults = {
|
|
|
232
239
|
encode: true,
|
|
233
240
|
encoder: utils.encode,
|
|
234
241
|
encodeValuesOnly: false,
|
|
235
|
-
serializeDate: function serializeDate(date) {
|
|
242
|
+
serializeDate: function serializeDate(date) {
|
|
236
243
|
return toISO.call(date);
|
|
237
244
|
},
|
|
238
245
|
skipNulls: false,
|
|
239
246
|
strictNullHandling: false
|
|
240
247
|
};
|
|
241
248
|
|
|
242
|
-
var stringify = function stringify(
|
|
249
|
+
var stringify = function stringify(
|
|
243
250
|
object,
|
|
244
251
|
prefix,
|
|
245
252
|
generateArrayPrefix,
|
|
@@ -258,7 +265,9 @@ var stringify = function stringify( // eslint-disable-line func-name-matching
|
|
|
258
265
|
obj = filter(prefix, obj);
|
|
259
266
|
} else if (obj instanceof Date) {
|
|
260
267
|
obj = serializeDate(obj);
|
|
261
|
-
}
|
|
268
|
+
}
|
|
269
|
+
|
|
270
|
+
if (obj === null) {
|
|
262
271
|
if (strictNullHandling) {
|
|
263
272
|
return encoder && !encodeValuesOnly ? encoder(prefix, defaults.encoder) : prefix;
|
|
264
273
|
}
|
|
@@ -281,7 +290,7 @@ var stringify = function stringify( // eslint-disable-line func-name-matching
|
|
|
281
290
|
}
|
|
282
291
|
|
|
283
292
|
var objKeys;
|
|
284
|
-
if (
|
|
293
|
+
if (isArray(filter)) {
|
|
285
294
|
objKeys = filter;
|
|
286
295
|
} else {
|
|
287
296
|
var keys = Object.keys(obj);
|
|
@@ -295,8 +304,8 @@ var stringify = function stringify( // eslint-disable-line func-name-matching
|
|
|
295
304
|
continue;
|
|
296
305
|
}
|
|
297
306
|
|
|
298
|
-
if (
|
|
299
|
-
values
|
|
307
|
+
if (isArray(obj)) {
|
|
308
|
+
pushToArray(values, stringify(
|
|
300
309
|
obj[key],
|
|
301
310
|
generateArrayPrefix(prefix, key),
|
|
302
311
|
generateArrayPrefix,
|
|
@@ -311,7 +320,7 @@ var stringify = function stringify( // eslint-disable-line func-name-matching
|
|
|
311
320
|
encodeValuesOnly
|
|
312
321
|
));
|
|
313
322
|
} else {
|
|
314
|
-
values
|
|
323
|
+
pushToArray(values, stringify(
|
|
315
324
|
obj[key],
|
|
316
325
|
prefix + (allowDots ? '.' + key : '[' + key + ']'),
|
|
317
326
|
generateArrayPrefix,
|
|
@@ -335,7 +344,7 @@ module.exports = function (object, opts) {
|
|
|
335
344
|
var obj = object;
|
|
336
345
|
var options = opts ? utils.assign({}, opts) : {};
|
|
337
346
|
|
|
338
|
-
if (options.encoder !== null && options.encoder !== undefined && typeof options.encoder !== 'function') {
|
|
347
|
+
if (options.encoder !== null && typeof options.encoder !== 'undefined' && typeof options.encoder !== 'function') {
|
|
339
348
|
throw new TypeError('Encoder has to be a function.');
|
|
340
349
|
}
|
|
341
350
|
|
|
@@ -360,7 +369,7 @@ module.exports = function (object, opts) {
|
|
|
360
369
|
if (typeof options.filter === 'function') {
|
|
361
370
|
filter = options.filter;
|
|
362
371
|
obj = filter('', obj);
|
|
363
|
-
} else if (
|
|
372
|
+
} else if (isArray(options.filter)) {
|
|
364
373
|
filter = options.filter;
|
|
365
374
|
objKeys = filter;
|
|
366
375
|
}
|
|
@@ -396,8 +405,7 @@ module.exports = function (object, opts) {
|
|
|
396
405
|
if (skipNulls && obj[key] === null) {
|
|
397
406
|
continue;
|
|
398
407
|
}
|
|
399
|
-
|
|
400
|
-
keys = keys.concat(stringify(
|
|
408
|
+
pushToArray(keys, stringify(
|
|
401
409
|
obj[key],
|
|
402
410
|
key,
|
|
403
411
|
generateArrayPrefix,
|
|
@@ -427,7 +435,7 @@ var has = Object.prototype.hasOwnProperty;
|
|
|
427
435
|
var hexTable = (function () {
|
|
428
436
|
var array = [];
|
|
429
437
|
for (var i = 0; i < 256; ++i) {
|
|
430
|
-
array.
|
|
438
|
+
array[array.length] = '%' + ((i < 16 ? '0' : '' + i.toString(16)).toUpperCase());
|
|
431
439
|
}
|
|
432
440
|
|
|
433
441
|
return array;
|
|
@@ -445,7 +453,7 @@ var compactQueue = function compactQueue(queue) {
|
|
|
445
453
|
|
|
446
454
|
for (var j = 0; j < obj.length; ++j) {
|
|
447
455
|
if (typeof obj[j] !== 'undefined') {
|
|
448
|
-
compacted.
|
|
456
|
+
compacted[compacted.length] = obj[j];
|
|
449
457
|
}
|
|
450
458
|
}
|
|
451
459
|
|
|
@@ -474,9 +482,9 @@ var merge = function merge(target, source, options) {
|
|
|
474
482
|
|
|
475
483
|
if (typeof source !== 'object') {
|
|
476
484
|
if (Array.isArray(target)) {
|
|
477
|
-
target.
|
|
478
|
-
} else if (typeof target === 'object') {
|
|
479
|
-
if (options.plainObjects || options.allowPrototypes || !has.call(Object.prototype, source)) {
|
|
485
|
+
target[target.length] = source;
|
|
486
|
+
} else if (target && typeof target === 'object') {
|
|
487
|
+
if ((options && (options.plainObjects || options.allowPrototypes)) || !has.call(Object.prototype, source)) {
|
|
480
488
|
target[source] = true;
|
|
481
489
|
}
|
|
482
490
|
} else {
|
|
@@ -486,7 +494,7 @@ var merge = function merge(target, source, options) {
|
|
|
486
494
|
return target;
|
|
487
495
|
}
|
|
488
496
|
|
|
489
|
-
if (typeof target !== 'object') {
|
|
497
|
+
if (!target || typeof target !== 'object') {
|
|
490
498
|
return [target].concat(source);
|
|
491
499
|
}
|
|
492
500
|
|
|
@@ -498,10 +506,11 @@ var merge = function merge(target, source, options) {
|
|
|
498
506
|
if (Array.isArray(target) && Array.isArray(source)) {
|
|
499
507
|
source.forEach(function (item, i) {
|
|
500
508
|
if (has.call(target, i)) {
|
|
501
|
-
|
|
502
|
-
|
|
509
|
+
var targetItem = target[i];
|
|
510
|
+
if (targetItem && typeof targetItem === 'object' && item && typeof item === 'object') {
|
|
511
|
+
target[i] = merge(targetItem, item, options);
|
|
503
512
|
} else {
|
|
504
|
-
target.
|
|
513
|
+
target[target.length] = item;
|
|
505
514
|
}
|
|
506
515
|
} else {
|
|
507
516
|
target[i] = item;
|
|
@@ -580,6 +589,7 @@ var encode = function encode(str) {
|
|
|
580
589
|
|
|
581
590
|
i += 1;
|
|
582
591
|
c = 0x10000 + (((c & 0x3FF) << 10) | (string.charCodeAt(i) & 0x3FF));
|
|
592
|
+
/* eslint operator-linebreak: [2, "before"] */
|
|
583
593
|
out += hexTable[0xF0 | (c >> 18)]
|
|
584
594
|
+ hexTable[0x80 | ((c >> 12) & 0x3F)]
|
|
585
595
|
+ hexTable[0x80 | ((c >> 6) & 0x3F)]
|
|
@@ -602,8 +612,8 @@ var compact = function compact(value) {
|
|
|
602
612
|
var key = keys[j];
|
|
603
613
|
var val = obj[key];
|
|
604
614
|
if (typeof val === 'object' && val !== null && refs.indexOf(val) === -1) {
|
|
605
|
-
queue.
|
|
606
|
-
refs.
|
|
615
|
+
queue[queue.length] = { obj: obj, prop: key };
|
|
616
|
+
refs[refs.length] = val;
|
|
607
617
|
}
|
|
608
618
|
}
|
|
609
619
|
}
|
package/lib/formats.js
CHANGED
package/lib/parse.js
CHANGED
|
@@ -19,7 +19,7 @@ var defaults = {
|
|
|
19
19
|
var parseValues = function parseQueryStringValues(str, options) {
|
|
20
20
|
var obj = {};
|
|
21
21
|
var cleanStr = options.ignoreQueryPrefix ? str.replace(/^\?/, '') : str;
|
|
22
|
-
var limit = options.parameterLimit === Infinity ? undefined : options.parameterLimit;
|
|
22
|
+
var limit = options.parameterLimit === Infinity ? void undefined : options.parameterLimit;
|
|
23
23
|
var parts = cleanStr.split(options.delimiter, limit);
|
|
24
24
|
|
|
25
25
|
for (var i = 0; i < parts.length; ++i) {
|
|
@@ -53,14 +53,15 @@ var parseObject = function (chain, val, options) {
|
|
|
53
53
|
var obj;
|
|
54
54
|
var root = chain[i];
|
|
55
55
|
|
|
56
|
-
if (root === '[]') {
|
|
57
|
-
obj = [];
|
|
58
|
-
obj = obj.concat(leaf);
|
|
56
|
+
if (root === '[]' && options.parseArrays) {
|
|
57
|
+
obj = [].concat(leaf);
|
|
59
58
|
} else {
|
|
60
59
|
obj = options.plainObjects ? Object.create(null) : {};
|
|
61
60
|
var cleanRoot = root.charAt(0) === '[' && root.charAt(root.length - 1) === ']' ? root.slice(1, -1) : root;
|
|
62
61
|
var index = parseInt(cleanRoot, 10);
|
|
63
|
-
if (
|
|
62
|
+
if (!options.parseArrays && cleanRoot === '') {
|
|
63
|
+
obj = { 0: leaf };
|
|
64
|
+
} else if (
|
|
64
65
|
!isNaN(index)
|
|
65
66
|
&& root !== cleanRoot
|
|
66
67
|
&& String(index) === cleanRoot
|
|
@@ -69,7 +70,7 @@ var parseObject = function (chain, val, options) {
|
|
|
69
70
|
) {
|
|
70
71
|
obj = [];
|
|
71
72
|
obj[index] = leaf;
|
|
72
|
-
} else {
|
|
73
|
+
} else if (cleanRoot !== '__proto__') {
|
|
73
74
|
obj[cleanRoot] = leaf;
|
|
74
75
|
}
|
|
75
76
|
}
|
|
@@ -110,7 +111,7 @@ var parseKeys = function parseQueryStringKeys(givenKey, val, options) {
|
|
|
110
111
|
}
|
|
111
112
|
}
|
|
112
113
|
|
|
113
|
-
keys.
|
|
114
|
+
keys[keys.length] = parent;
|
|
114
115
|
}
|
|
115
116
|
|
|
116
117
|
// Loop through children appending to the array until we hit depth
|
|
@@ -123,13 +124,13 @@ var parseKeys = function parseQueryStringKeys(givenKey, val, options) {
|
|
|
123
124
|
return;
|
|
124
125
|
}
|
|
125
126
|
}
|
|
126
|
-
keys.
|
|
127
|
+
keys[keys.length] = segment[1];
|
|
127
128
|
}
|
|
128
129
|
|
|
129
130
|
// If there's a remainder, just add whatever is left
|
|
130
131
|
|
|
131
132
|
if (segment) {
|
|
132
|
-
keys.
|
|
133
|
+
keys[keys.length] = '[' + key.slice(segment.index + ']');
|
|
133
134
|
}
|
|
134
135
|
|
|
135
136
|
return parseObject(keys, val, options);
|
package/lib/stringify.js
CHANGED
|
@@ -4,17 +4,23 @@ var utils = require('./utils');
|
|
|
4
4
|
var formats = require('./formats');
|
|
5
5
|
|
|
6
6
|
var arrayPrefixGenerators = {
|
|
7
|
-
brackets: function brackets(prefix) {
|
|
7
|
+
brackets: function brackets(prefix) {
|
|
8
8
|
return prefix + '[]';
|
|
9
9
|
},
|
|
10
|
-
indices: function indices(prefix, key) {
|
|
10
|
+
indices: function indices(prefix, key) {
|
|
11
11
|
return prefix + '[' + key + ']';
|
|
12
12
|
},
|
|
13
|
-
repeat: function repeat(prefix) {
|
|
13
|
+
repeat: function repeat(prefix) {
|
|
14
14
|
return prefix;
|
|
15
15
|
}
|
|
16
16
|
};
|
|
17
17
|
|
|
18
|
+
var isArray = Array.isArray;
|
|
19
|
+
var push = Array.prototype.push;
|
|
20
|
+
var pushToArray = function (arr, valueOrArray) {
|
|
21
|
+
push.apply(arr, isArray(valueOrArray) ? valueOrArray : [valueOrArray]);
|
|
22
|
+
};
|
|
23
|
+
|
|
18
24
|
var toISO = Date.prototype.toISOString;
|
|
19
25
|
|
|
20
26
|
var defaults = {
|
|
@@ -22,14 +28,14 @@ var defaults = {
|
|
|
22
28
|
encode: true,
|
|
23
29
|
encoder: utils.encode,
|
|
24
30
|
encodeValuesOnly: false,
|
|
25
|
-
serializeDate: function serializeDate(date) {
|
|
31
|
+
serializeDate: function serializeDate(date) {
|
|
26
32
|
return toISO.call(date);
|
|
27
33
|
},
|
|
28
34
|
skipNulls: false,
|
|
29
35
|
strictNullHandling: false
|
|
30
36
|
};
|
|
31
37
|
|
|
32
|
-
var stringify = function stringify(
|
|
38
|
+
var stringify = function stringify(
|
|
33
39
|
object,
|
|
34
40
|
prefix,
|
|
35
41
|
generateArrayPrefix,
|
|
@@ -48,7 +54,9 @@ var stringify = function stringify( // eslint-disable-line func-name-matching
|
|
|
48
54
|
obj = filter(prefix, obj);
|
|
49
55
|
} else if (obj instanceof Date) {
|
|
50
56
|
obj = serializeDate(obj);
|
|
51
|
-
}
|
|
57
|
+
}
|
|
58
|
+
|
|
59
|
+
if (obj === null) {
|
|
52
60
|
if (strictNullHandling) {
|
|
53
61
|
return encoder && !encodeValuesOnly ? encoder(prefix, defaults.encoder) : prefix;
|
|
54
62
|
}
|
|
@@ -71,7 +79,7 @@ var stringify = function stringify( // eslint-disable-line func-name-matching
|
|
|
71
79
|
}
|
|
72
80
|
|
|
73
81
|
var objKeys;
|
|
74
|
-
if (
|
|
82
|
+
if (isArray(filter)) {
|
|
75
83
|
objKeys = filter;
|
|
76
84
|
} else {
|
|
77
85
|
var keys = Object.keys(obj);
|
|
@@ -85,8 +93,8 @@ var stringify = function stringify( // eslint-disable-line func-name-matching
|
|
|
85
93
|
continue;
|
|
86
94
|
}
|
|
87
95
|
|
|
88
|
-
if (
|
|
89
|
-
values
|
|
96
|
+
if (isArray(obj)) {
|
|
97
|
+
pushToArray(values, stringify(
|
|
90
98
|
obj[key],
|
|
91
99
|
generateArrayPrefix(prefix, key),
|
|
92
100
|
generateArrayPrefix,
|
|
@@ -101,7 +109,7 @@ var stringify = function stringify( // eslint-disable-line func-name-matching
|
|
|
101
109
|
encodeValuesOnly
|
|
102
110
|
));
|
|
103
111
|
} else {
|
|
104
|
-
values
|
|
112
|
+
pushToArray(values, stringify(
|
|
105
113
|
obj[key],
|
|
106
114
|
prefix + (allowDots ? '.' + key : '[' + key + ']'),
|
|
107
115
|
generateArrayPrefix,
|
|
@@ -125,7 +133,7 @@ module.exports = function (object, opts) {
|
|
|
125
133
|
var obj = object;
|
|
126
134
|
var options = opts ? utils.assign({}, opts) : {};
|
|
127
135
|
|
|
128
|
-
if (options.encoder !== null && options.encoder !== undefined && typeof options.encoder !== 'function') {
|
|
136
|
+
if (options.encoder !== null && typeof options.encoder !== 'undefined' && typeof options.encoder !== 'function') {
|
|
129
137
|
throw new TypeError('Encoder has to be a function.');
|
|
130
138
|
}
|
|
131
139
|
|
|
@@ -150,7 +158,7 @@ module.exports = function (object, opts) {
|
|
|
150
158
|
if (typeof options.filter === 'function') {
|
|
151
159
|
filter = options.filter;
|
|
152
160
|
obj = filter('', obj);
|
|
153
|
-
} else if (
|
|
161
|
+
} else if (isArray(options.filter)) {
|
|
154
162
|
filter = options.filter;
|
|
155
163
|
objKeys = filter;
|
|
156
164
|
}
|
|
@@ -186,8 +194,7 @@ module.exports = function (object, opts) {
|
|
|
186
194
|
if (skipNulls && obj[key] === null) {
|
|
187
195
|
continue;
|
|
188
196
|
}
|
|
189
|
-
|
|
190
|
-
keys = keys.concat(stringify(
|
|
197
|
+
pushToArray(keys, stringify(
|
|
191
198
|
obj[key],
|
|
192
199
|
key,
|
|
193
200
|
generateArrayPrefix,
|
package/lib/utils.js
CHANGED
|
@@ -5,7 +5,7 @@ var has = Object.prototype.hasOwnProperty;
|
|
|
5
5
|
var hexTable = (function () {
|
|
6
6
|
var array = [];
|
|
7
7
|
for (var i = 0; i < 256; ++i) {
|
|
8
|
-
array.
|
|
8
|
+
array[array.length] = '%' + ((i < 16 ? '0' : '' + i.toString(16)).toUpperCase());
|
|
9
9
|
}
|
|
10
10
|
|
|
11
11
|
return array;
|
|
@@ -23,7 +23,7 @@ var compactQueue = function compactQueue(queue) {
|
|
|
23
23
|
|
|
24
24
|
for (var j = 0; j < obj.length; ++j) {
|
|
25
25
|
if (typeof obj[j] !== 'undefined') {
|
|
26
|
-
compacted.
|
|
26
|
+
compacted[compacted.length] = obj[j];
|
|
27
27
|
}
|
|
28
28
|
}
|
|
29
29
|
|
|
@@ -52,9 +52,9 @@ var merge = function merge(target, source, options) {
|
|
|
52
52
|
|
|
53
53
|
if (typeof source !== 'object') {
|
|
54
54
|
if (Array.isArray(target)) {
|
|
55
|
-
target.
|
|
56
|
-
} else if (typeof target === 'object') {
|
|
57
|
-
if (options.plainObjects || options.allowPrototypes || !has.call(Object.prototype, source)) {
|
|
55
|
+
target[target.length] = source;
|
|
56
|
+
} else if (target && typeof target === 'object') {
|
|
57
|
+
if ((options && (options.plainObjects || options.allowPrototypes)) || !has.call(Object.prototype, source)) {
|
|
58
58
|
target[source] = true;
|
|
59
59
|
}
|
|
60
60
|
} else {
|
|
@@ -64,7 +64,7 @@ var merge = function merge(target, source, options) {
|
|
|
64
64
|
return target;
|
|
65
65
|
}
|
|
66
66
|
|
|
67
|
-
if (typeof target !== 'object') {
|
|
67
|
+
if (!target || typeof target !== 'object') {
|
|
68
68
|
return [target].concat(source);
|
|
69
69
|
}
|
|
70
70
|
|
|
@@ -76,10 +76,11 @@ var merge = function merge(target, source, options) {
|
|
|
76
76
|
if (Array.isArray(target) && Array.isArray(source)) {
|
|
77
77
|
source.forEach(function (item, i) {
|
|
78
78
|
if (has.call(target, i)) {
|
|
79
|
-
|
|
80
|
-
|
|
79
|
+
var targetItem = target[i];
|
|
80
|
+
if (targetItem && typeof targetItem === 'object' && item && typeof item === 'object') {
|
|
81
|
+
target[i] = merge(targetItem, item, options);
|
|
81
82
|
} else {
|
|
82
|
-
target.
|
|
83
|
+
target[target.length] = item;
|
|
83
84
|
}
|
|
84
85
|
} else {
|
|
85
86
|
target[i] = item;
|
|
@@ -158,6 +159,7 @@ var encode = function encode(str) {
|
|
|
158
159
|
|
|
159
160
|
i += 1;
|
|
160
161
|
c = 0x10000 + (((c & 0x3FF) << 10) | (string.charCodeAt(i) & 0x3FF));
|
|
162
|
+
/* eslint operator-linebreak: [2, "before"] */
|
|
161
163
|
out += hexTable[0xF0 | (c >> 18)]
|
|
162
164
|
+ hexTable[0x80 | ((c >> 12) & 0x3F)]
|
|
163
165
|
+ hexTable[0x80 | ((c >> 6) & 0x3F)]
|
|
@@ -180,8 +182,8 @@ var compact = function compact(value) {
|
|
|
180
182
|
var key = keys[j];
|
|
181
183
|
var val = obj[key];
|
|
182
184
|
if (typeof val === 'object' && val !== null && refs.indexOf(val) === -1) {
|
|
183
|
-
queue.
|
|
184
|
-
refs.
|
|
185
|
+
queue[queue.length] = { obj: obj, prop: key };
|
|
186
|
+
refs[refs.length] = val;
|
|
185
187
|
}
|
|
186
188
|
}
|
|
187
189
|
}
|
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.5.
|
|
5
|
+
"version": "6.5.4",
|
|
6
6
|
"repository": {
|
|
7
7
|
"type": "git",
|
|
8
8
|
"url": "https://github.com/ljharb/qs.git"
|
|
@@ -22,30 +22,32 @@
|
|
|
22
22
|
"engines": {
|
|
23
23
|
"node": ">=0.6"
|
|
24
24
|
},
|
|
25
|
-
"dependencies": {},
|
|
26
25
|
"devDependencies": {
|
|
27
|
-
"@ljharb/eslint-config": "^
|
|
28
|
-
"
|
|
29
|
-
"
|
|
30
|
-
"
|
|
31
|
-
"eslint": "^
|
|
26
|
+
"@ljharb/eslint-config": "^20.1.0",
|
|
27
|
+
"aud": "^1.1.5",
|
|
28
|
+
"browserify": "^16.5.2",
|
|
29
|
+
"eclint": "^2.8.1",
|
|
30
|
+
"eslint": "^8.6.0",
|
|
32
31
|
"evalmd": "^0.0.17",
|
|
33
|
-
"iconv-lite": "^0.4.
|
|
32
|
+
"iconv-lite": "^0.4.24",
|
|
33
|
+
"in-publish": "^2.0.1",
|
|
34
34
|
"mkdirp": "^0.5.1",
|
|
35
|
+
"nyc": "^10.3.2",
|
|
35
36
|
"qs-iconv": "^1.0.4",
|
|
36
|
-
"safe-publish-latest": "^
|
|
37
|
+
"safe-publish-latest": "^2.0.0",
|
|
37
38
|
"safer-buffer": "^2.1.2",
|
|
38
|
-
"tape": "^4.
|
|
39
|
+
"tape": "^5.4.0"
|
|
39
40
|
},
|
|
40
41
|
"scripts": {
|
|
41
|
-
"
|
|
42
|
+
"prepublishOnly": "safe-publish-latest && npm run dist",
|
|
43
|
+
"prepublish": "not-in-publish || npm run prepublishOnly",
|
|
42
44
|
"pretest": "npm run --silent readme && npm run --silent lint",
|
|
43
|
-
"test": "npm run --silent
|
|
44
|
-
"tests-only": "
|
|
45
|
+
"test": "npm run --silent tests-only",
|
|
46
|
+
"tests-only": "nyc tape 'test/**/*.js'",
|
|
47
|
+
"posttest": "aud --production",
|
|
45
48
|
"readme": "evalmd README.md",
|
|
46
|
-
"
|
|
47
|
-
"lint": "eslint
|
|
48
|
-
"coverage": "covert test",
|
|
49
|
+
"postlint": "eclint check $(git ls-files | xargs find 2> /dev/null | grep -vE 'node_modules|\\.git')",
|
|
50
|
+
"lint": "eslint --ext=js,mjs .",
|
|
49
51
|
"dist": "mkdirp dist && browserify --standalone Qs lib/index.js > dist/qs.js"
|
|
50
52
|
},
|
|
51
53
|
"license": "BSD-3-Clause"
|
package/test/parse.js
CHANGED
|
@@ -237,6 +237,14 @@ test('parse()', function (t) {
|
|
|
237
237
|
st.end();
|
|
238
238
|
});
|
|
239
239
|
|
|
240
|
+
t.test('parses jquery-param strings', function (st) {
|
|
241
|
+
// readable = 'filter[0][]=int1&filter[0][]==&filter[0][]=77&filter[]=and&filter[2][]=int2&filter[2][]==&filter[2][]=8'
|
|
242
|
+
var encoded = 'filter%5B0%5D%5B%5D=int1&filter%5B0%5D%5B%5D=%3D&filter%5B0%5D%5B%5D=77&filter%5B%5D=and&filter%5B2%5D%5B%5D=int2&filter%5B2%5D%5B%5D=%3D&filter%5B2%5D%5B%5D=8';
|
|
243
|
+
var expected = { filter: [['int1', '=', '77'], 'and', ['int2', '=', '8']] };
|
|
244
|
+
st.deepEqual(qs.parse(encoded), expected);
|
|
245
|
+
st.end();
|
|
246
|
+
});
|
|
247
|
+
|
|
240
248
|
t.test('continues parsing when no parent is found', function (st) {
|
|
241
249
|
st.deepEqual(qs.parse('[]=&a=b'), { 0: '', a: 'b' });
|
|
242
250
|
st.deepEqual(qs.parse('[]&a=b', { strictNullHandling: true }), { 0: null, a: 'b' });
|
|
@@ -257,7 +265,7 @@ test('parse()', function (t) {
|
|
|
257
265
|
st.end();
|
|
258
266
|
});
|
|
259
267
|
|
|
260
|
-
t.test('should not throw when a native prototype has an enumerable property',
|
|
268
|
+
t.test('should not throw when a native prototype has an enumerable property', function (st) {
|
|
261
269
|
Object.prototype.crash = '';
|
|
262
270
|
Array.prototype.crash = '';
|
|
263
271
|
st.doesNotThrow(qs.parse.bind(null, 'a=b'));
|
|
@@ -302,7 +310,14 @@ test('parse()', function (t) {
|
|
|
302
310
|
});
|
|
303
311
|
|
|
304
312
|
t.test('allows disabling array parsing', function (st) {
|
|
305
|
-
|
|
313
|
+
var indices = qs.parse('a[0]=b&a[1]=c', { parseArrays: false });
|
|
314
|
+
st.deepEqual(indices, { a: { 0: 'b', 1: 'c' } });
|
|
315
|
+
st.equal(Array.isArray(indices.a), false, 'parseArrays:false, indices case is not an array');
|
|
316
|
+
|
|
317
|
+
var emptyBrackets = qs.parse('a[]=b', { parseArrays: false });
|
|
318
|
+
st.deepEqual(emptyBrackets, { a: { 0: 'b' } });
|
|
319
|
+
st.equal(Array.isArray(emptyBrackets.a), false, 'parseArrays:false, empty brackets case is not an array');
|
|
320
|
+
|
|
306
321
|
st.end();
|
|
307
322
|
});
|
|
308
323
|
|
|
@@ -508,13 +523,73 @@ test('parse()', function (t) {
|
|
|
508
523
|
|
|
509
524
|
st.deepEqual(
|
|
510
525
|
qs.parse('a[b]=c&a=toString', { plainObjects: true }),
|
|
511
|
-
{ a: { b: 'c', toString: true } },
|
|
526
|
+
{ __proto__: null, a: { __proto__: null, b: 'c', toString: true } },
|
|
512
527
|
'can overwrite prototype with plainObjects true'
|
|
513
528
|
);
|
|
514
529
|
|
|
515
530
|
st.end();
|
|
516
531
|
});
|
|
517
532
|
|
|
533
|
+
t.test('dunder proto is ignored', function (st) {
|
|
534
|
+
var payload = 'categories[__proto__]=login&categories[__proto__]&categories[length]=42';
|
|
535
|
+
var result = qs.parse(payload, { allowPrototypes: true });
|
|
536
|
+
|
|
537
|
+
st.deepEqual(
|
|
538
|
+
result,
|
|
539
|
+
{
|
|
540
|
+
categories: {
|
|
541
|
+
length: '42'
|
|
542
|
+
}
|
|
543
|
+
},
|
|
544
|
+
'silent [[Prototype]] payload'
|
|
545
|
+
);
|
|
546
|
+
|
|
547
|
+
var plainResult = qs.parse(payload, { allowPrototypes: true, plainObjects: true });
|
|
548
|
+
|
|
549
|
+
st.deepEqual(
|
|
550
|
+
plainResult,
|
|
551
|
+
{
|
|
552
|
+
__proto__: null,
|
|
553
|
+
categories: {
|
|
554
|
+
__proto__: null,
|
|
555
|
+
length: '42'
|
|
556
|
+
}
|
|
557
|
+
},
|
|
558
|
+
'silent [[Prototype]] payload: plain objects'
|
|
559
|
+
);
|
|
560
|
+
|
|
561
|
+
var query = qs.parse('categories[__proto__]=cats&categories[__proto__]=dogs&categories[some][json]=toInject', { allowPrototypes: true });
|
|
562
|
+
|
|
563
|
+
st.notOk(Array.isArray(query.categories), 'is not an array');
|
|
564
|
+
st.notOk(query.categories instanceof Array, 'is not instanceof an array');
|
|
565
|
+
st.deepEqual(query.categories, { some: { json: 'toInject' } });
|
|
566
|
+
st.equal(JSON.stringify(query.categories), '{"some":{"json":"toInject"}}', 'stringifies as a non-array');
|
|
567
|
+
|
|
568
|
+
st.deepEqual(
|
|
569
|
+
qs.parse('foo[__proto__][hidden]=value&foo[bar]=stuffs', { allowPrototypes: true }),
|
|
570
|
+
{
|
|
571
|
+
foo: {
|
|
572
|
+
bar: 'stuffs'
|
|
573
|
+
}
|
|
574
|
+
},
|
|
575
|
+
'hidden values'
|
|
576
|
+
);
|
|
577
|
+
|
|
578
|
+
st.deepEqual(
|
|
579
|
+
qs.parse('foo[__proto__][hidden]=value&foo[bar]=stuffs', { allowPrototypes: true, plainObjects: true }),
|
|
580
|
+
{
|
|
581
|
+
__proto__: null,
|
|
582
|
+
foo: {
|
|
583
|
+
__proto__: null,
|
|
584
|
+
bar: 'stuffs'
|
|
585
|
+
}
|
|
586
|
+
},
|
|
587
|
+
'hidden values: plain objects'
|
|
588
|
+
);
|
|
589
|
+
|
|
590
|
+
st.end();
|
|
591
|
+
});
|
|
592
|
+
|
|
518
593
|
t.test('can return null objects', { skip: !Object.create }, function (st) {
|
|
519
594
|
var expected = Object.create(null);
|
|
520
595
|
expected.a = Object.create(null);
|
|
@@ -540,7 +615,7 @@ test('parse()', function (t) {
|
|
|
540
615
|
result.push(parseInt(parts[1], 16));
|
|
541
616
|
parts = reg.exec(str);
|
|
542
617
|
}
|
|
543
|
-
return iconv.decode(SaferBuffer.from(result), 'shift_jis')
|
|
618
|
+
return String(iconv.decode(SaferBuffer.from(result), 'shift_jis'));
|
|
544
619
|
}
|
|
545
620
|
}), { 県: '大阪府' });
|
|
546
621
|
st.end();
|
package/test/stringify.js
CHANGED
|
@@ -19,6 +19,15 @@ test('stringify()', function (t) {
|
|
|
19
19
|
st.end();
|
|
20
20
|
});
|
|
21
21
|
|
|
22
|
+
t.test('stringifies falsy values', function (st) {
|
|
23
|
+
st.equal(qs.stringify(undefined), '');
|
|
24
|
+
st.equal(qs.stringify(null), '');
|
|
25
|
+
st.equal(qs.stringify(null, { strictNullHandling: true }), '');
|
|
26
|
+
st.equal(qs.stringify(false), '');
|
|
27
|
+
st.equal(qs.stringify(0), '');
|
|
28
|
+
st.end();
|
|
29
|
+
});
|
|
30
|
+
|
|
22
31
|
t.test('adds query prefix', function (st) {
|
|
23
32
|
st.equal(qs.stringify({ a: 'b' }, { addQueryPrefix: true }), '?a=b');
|
|
24
33
|
st.end();
|
|
@@ -29,6 +38,13 @@ test('stringify()', function (t) {
|
|
|
29
38
|
st.end();
|
|
30
39
|
});
|
|
31
40
|
|
|
41
|
+
t.test('stringifies nested falsy values', function (st) {
|
|
42
|
+
st.equal(qs.stringify({ a: { b: { c: null } } }), 'a%5Bb%5D%5Bc%5D=');
|
|
43
|
+
st.equal(qs.stringify({ a: { b: { c: null } } }, { strictNullHandling: true }), 'a%5Bb%5D%5Bc%5D');
|
|
44
|
+
st.equal(qs.stringify({ a: { b: { c: false } } }), 'a%5Bb%5D%5Bc%5D=false');
|
|
45
|
+
st.end();
|
|
46
|
+
});
|
|
47
|
+
|
|
32
48
|
t.test('stringifies a nested object', function (st) {
|
|
33
49
|
st.equal(qs.stringify({ a: { b: 'c' } }), 'a%5Bb%5D=c');
|
|
34
50
|
st.equal(qs.stringify({ a: { b: { c: { d: 'e' } } } }), 'a%5Bb%5D%5Bc%5D%5Bd%5D=e');
|
|
@@ -490,6 +506,12 @@ test('stringify()', function (t) {
|
|
|
490
506
|
return String.fromCharCode(buffer.readUInt8(0) + 97);
|
|
491
507
|
}
|
|
492
508
|
}), 'a=b');
|
|
509
|
+
|
|
510
|
+
st.equal(qs.stringify({ a: SaferBuffer.from('a b') }, {
|
|
511
|
+
encoder: function (buffer) {
|
|
512
|
+
return buffer;
|
|
513
|
+
}
|
|
514
|
+
}), 'a=a b');
|
|
493
515
|
st.end();
|
|
494
516
|
});
|
|
495
517
|
|
|
@@ -530,17 +552,20 @@ test('stringify()', function (t) {
|
|
|
530
552
|
t.test('RFC 1738 spaces serialization', function (st) {
|
|
531
553
|
st.equal(qs.stringify({ a: 'b c' }, { format: qs.formats.RFC1738 }), 'a=b+c');
|
|
532
554
|
st.equal(qs.stringify({ 'a b': 'c d' }, { format: qs.formats.RFC1738 }), 'a+b=c+d');
|
|
555
|
+
st.equal(qs.stringify({ 'a b': SaferBuffer.from('a b') }, { format: qs.formats.RFC1738 }), 'a+b=a+b');
|
|
533
556
|
st.end();
|
|
534
557
|
});
|
|
535
558
|
|
|
536
559
|
t.test('RFC 3986 spaces serialization', function (st) {
|
|
537
560
|
st.equal(qs.stringify({ a: 'b c' }, { format: qs.formats.RFC3986 }), 'a=b%20c');
|
|
538
561
|
st.equal(qs.stringify({ 'a b': 'c d' }, { format: qs.formats.RFC3986 }), 'a%20b=c%20d');
|
|
562
|
+
st.equal(qs.stringify({ 'a b': SaferBuffer.from('a b') }, { format: qs.formats.RFC3986 }), 'a%20b=a%20b');
|
|
539
563
|
st.end();
|
|
540
564
|
});
|
|
541
565
|
|
|
542
566
|
t.test('Backward compatibility to RFC 3986', function (st) {
|
|
543
567
|
st.equal(qs.stringify({ a: 'b c' }), 'a=b%20c');
|
|
568
|
+
st.equal(qs.stringify({ 'a b': SaferBuffer.from('a b') }), 'a%20b=a%20b');
|
|
544
569
|
st.end();
|
|
545
570
|
});
|
|
546
571
|
|
|
@@ -593,5 +618,25 @@ test('stringify()', function (t) {
|
|
|
593
618
|
st.end();
|
|
594
619
|
});
|
|
595
620
|
|
|
621
|
+
t.test('strictNullHandling works with custom filter', function (st) {
|
|
622
|
+
var filter = function (prefix, value) {
|
|
623
|
+
return value;
|
|
624
|
+
};
|
|
625
|
+
|
|
626
|
+
var options = { strictNullHandling: true, filter: filter };
|
|
627
|
+
st.equal(qs.stringify({ key: null }, options), 'key');
|
|
628
|
+
st.end();
|
|
629
|
+
});
|
|
630
|
+
|
|
631
|
+
t.test('strictNullHandling works with null serializeDate', function (st) {
|
|
632
|
+
var serializeDate = function () {
|
|
633
|
+
return null;
|
|
634
|
+
};
|
|
635
|
+
var options = { strictNullHandling: true, serializeDate: serializeDate };
|
|
636
|
+
var date = new Date();
|
|
637
|
+
st.equal(qs.stringify({ key: date }, options), 'key');
|
|
638
|
+
st.end();
|
|
639
|
+
});
|
|
640
|
+
|
|
596
641
|
t.end();
|
|
597
642
|
});
|
package/test/utils.js
CHANGED
|
@@ -4,6 +4,10 @@ var test = require('tape');
|
|
|
4
4
|
var utils = require('../lib/utils');
|
|
5
5
|
|
|
6
6
|
test('merge()', function (t) {
|
|
7
|
+
t.deepEqual(utils.merge(null, true), [null, true], 'merges true into null');
|
|
8
|
+
|
|
9
|
+
t.deepEqual(utils.merge(null, [42]), [null, 42], 'merges null into an array');
|
|
10
|
+
|
|
7
11
|
t.deepEqual(utils.merge({ a: 'b' }, { a: 'c' }), { a: ['b', 'c'] }, 'merges two objects with the same key');
|
|
8
12
|
|
|
9
13
|
var oneMerged = utils.merge({ foo: 'bar' }, { foo: { first: '123' } });
|
|
@@ -18,6 +22,33 @@ test('merge()', function (t) {
|
|
|
18
22
|
var nestedArrays = utils.merge({ foo: ['baz'] }, { foo: ['bar', 'xyzzy'] });
|
|
19
23
|
t.deepEqual(nestedArrays, { foo: ['baz', 'bar', 'xyzzy'] });
|
|
20
24
|
|
|
25
|
+
var noOptionsNonObjectSource = utils.merge({ foo: 'baz' }, 'bar');
|
|
26
|
+
t.deepEqual(noOptionsNonObjectSource, { foo: 'baz', bar: true });
|
|
27
|
+
|
|
28
|
+
t.test(
|
|
29
|
+
'avoids invoking array setters unnecessarily',
|
|
30
|
+
{ skip: typeof Object.defineProperty !== 'function' },
|
|
31
|
+
function (st) {
|
|
32
|
+
var setCount = 0;
|
|
33
|
+
var getCount = 0;
|
|
34
|
+
var observed = [];
|
|
35
|
+
Object.defineProperty(observed, 0, {
|
|
36
|
+
get: function () {
|
|
37
|
+
getCount += 1;
|
|
38
|
+
return { bar: 'baz' };
|
|
39
|
+
},
|
|
40
|
+
set: function () { setCount += 1; }
|
|
41
|
+
});
|
|
42
|
+
utils.merge(observed, [null]);
|
|
43
|
+
st.equal(setCount, 0);
|
|
44
|
+
st.equal(getCount, 1);
|
|
45
|
+
observed[0] = observed[0]; // eslint-disable-line no-self-assign
|
|
46
|
+
st.equal(setCount, 1);
|
|
47
|
+
st.equal(getCount, 2);
|
|
48
|
+
st.end();
|
|
49
|
+
}
|
|
50
|
+
);
|
|
51
|
+
|
|
21
52
|
t.end();
|
|
22
53
|
});
|
|
23
54
|
|
package/.eslintignore
DELETED
|
@@ -1 +0,0 @@
|
|
|
1
|
-
dist
|
package/LICENSE
DELETED
|
@@ -1,28 +0,0 @@
|
|
|
1
|
-
Copyright (c) 2014 Nathan LaFreniere and other contributors.
|
|
2
|
-
All rights reserved.
|
|
3
|
-
|
|
4
|
-
Redistribution and use in source and binary forms, with or without
|
|
5
|
-
modification, are permitted provided that the following conditions are met:
|
|
6
|
-
* Redistributions of source code must retain the above copyright
|
|
7
|
-
notice, this list of conditions and the following disclaimer.
|
|
8
|
-
* Redistributions in binary form must reproduce the above copyright
|
|
9
|
-
notice, this list of conditions and the following disclaimer in the
|
|
10
|
-
documentation and/or other materials provided with the distribution.
|
|
11
|
-
* The names of any contributors may not be used to endorse or promote
|
|
12
|
-
products derived from this software without specific prior written
|
|
13
|
-
permission.
|
|
14
|
-
|
|
15
|
-
THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
|
|
16
|
-
ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
|
|
17
|
-
WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
|
|
18
|
-
DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDERS AND CONTRIBUTORS BE LIABLE FOR ANY
|
|
19
|
-
DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
|
|
20
|
-
(INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
|
|
21
|
-
LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
|
|
22
|
-
ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
|
|
23
|
-
(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
|
|
24
|
-
SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
|
25
|
-
|
|
26
|
-
* * *
|
|
27
|
-
|
|
28
|
-
The complete list of contributors can be found at: https://github.com/hapijs/qs/graphs/contributors
|
package/test/.eslintrc
DELETED
|
@@ -1,15 +0,0 @@
|
|
|
1
|
-
{
|
|
2
|
-
"rules": {
|
|
3
|
-
"array-bracket-newline": 0,
|
|
4
|
-
"array-element-newline": 0,
|
|
5
|
-
"consistent-return": 2,
|
|
6
|
-
"max-lines": 0,
|
|
7
|
-
"max-nested-callbacks": [2, 3],
|
|
8
|
-
"max-statements": 0,
|
|
9
|
-
"no-buffer-constructor": 0,
|
|
10
|
-
"no-extend-native": 0,
|
|
11
|
-
"no-magic-numbers": 0,
|
|
12
|
-
"object-curly-newline": 0,
|
|
13
|
-
"sort-keys": 0
|
|
14
|
-
}
|
|
15
|
-
}
|