qs 6.14.1 → 6.15.0
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 +1 -1
- package/CHANGELOG.md +176 -1
- package/README.md +29 -4
- package/dist/qs.js +15 -15
- package/lib/parse.js +24 -11
- package/lib/utils.js +30 -8
- package/package.json +1 -1
- package/test/parse.js +185 -13
- package/test/utils.js +43 -20
package/.editorconfig
CHANGED
package/CHANGELOG.md
CHANGED
|
@@ -1,5 +1,22 @@
|
|
|
1
|
+
## **6.15.0**
|
|
2
|
+
- [New] `parse`: add `strictMerge` option to wrap object/primitive conflicts in an array (#425, #122)
|
|
3
|
+
- [Fix] `duplicates` option should not apply to bracket notation keys (#514)
|
|
4
|
+
|
|
5
|
+
## **6.14.2**
|
|
6
|
+
- [Fix] `parse`: mark overflow objects for indexed notation exceeding `arrayLimit` (#546)
|
|
7
|
+
- [Fix] `arrayLimit` means max count, not max index, in `combine`/`merge`/`parseArrayValue`
|
|
8
|
+
- [Fix] `parse`: throw on `arrayLimit` exceeded with indexed notation when `throwOnLimitExceeded` is true (#529)
|
|
9
|
+
- [Fix] `parse`: enforce `arrayLimit` on `comma`-parsed values
|
|
10
|
+
- [Fix] `parse`: fix error message to reflect arrayLimit as max index; remove extraneous comments (#545)
|
|
11
|
+
- [Robustness] avoid `.push`, use `void`
|
|
12
|
+
- [readme] document that `addQueryPrefix` does not add `?` to empty output (#418)
|
|
13
|
+
- [readme] clarify `parseArrays` and `arrayLimit` documentation (#543)
|
|
14
|
+
- [readme] replace runkit CI badge with shields.io check-runs badge
|
|
15
|
+
- [meta] fix changelog typo (`arrayLength` → `arrayLimit`)
|
|
16
|
+
- [actions] fix rebase workflow permissions
|
|
17
|
+
|
|
1
18
|
## **6.14.1**
|
|
2
|
-
- [Fix] ensure
|
|
19
|
+
- [Fix] ensure `arrayLimit` applies to `[]` notation as well
|
|
3
20
|
- [Fix] `parse`: when a custom decoder returns `null` for a key, ignore that key
|
|
4
21
|
- [Refactor] `parse`: extract key segment splitting helper
|
|
5
22
|
- [meta] add threat model
|
|
@@ -17,6 +34,17 @@
|
|
|
17
34
|
- [Dev Deps] update `es-value-fixtures`, `has-bigints`, `has-proto`, `has-symbols`
|
|
18
35
|
- [Tests] increase coverage
|
|
19
36
|
|
|
37
|
+
## **6.13.3**
|
|
38
|
+
[Fix] fix regressions from robustness refactor
|
|
39
|
+
[actions] update reusable workflows
|
|
40
|
+
|
|
41
|
+
## **6.13.2**
|
|
42
|
+
- [Robustness] avoid `.push`, use `void`
|
|
43
|
+
- [readme] clarify `parseArrays` and `arrayLimit` documentation (#543)
|
|
44
|
+
- [readme] document that `addQueryPrefix` does not add `?` to empty output (#418)
|
|
45
|
+
- [readme] replace runkit CI badge with shields.io check-runs badge
|
|
46
|
+
- [actions] fix rebase workflow permissions
|
|
47
|
+
|
|
20
48
|
## **6.13.1**
|
|
21
49
|
- [Fix] `stringify`: avoid a crash when a `filter` key is `null`
|
|
22
50
|
- [Fix] `utils.merge`: functions should not be stringified into keys
|
|
@@ -33,6 +61,17 @@
|
|
|
33
61
|
- [New] `parse`: add `strictDepth` option (#511)
|
|
34
62
|
- [Tests] use `npm audit` instead of `aud`
|
|
35
63
|
|
|
64
|
+
## **6.12.5**
|
|
65
|
+
- [Fix] fix regressions from robustness refactor
|
|
66
|
+
- [actions] update reusable workflows
|
|
67
|
+
|
|
68
|
+
## **6.12.4**
|
|
69
|
+
- [Robustness] avoid `.push`, use `void`
|
|
70
|
+
- [readme] clarify `parseArrays` and `arrayLimit` documentation (#543)
|
|
71
|
+
- [readme] document that `addQueryPrefix` does not add `?` to empty output (#418)
|
|
72
|
+
- [readme] replace runkit CI badge with shields.io check-runs badge
|
|
73
|
+
- [actions] fix rebase workflow permissions
|
|
74
|
+
|
|
36
75
|
## **6.12.3**
|
|
37
76
|
- [Fix] `parse`: properly account for `strictNullHandling` when `allowEmptyArrays`
|
|
38
77
|
- [meta] fix changelog indentation
|
|
@@ -70,6 +109,17 @@
|
|
|
70
109
|
- [Dev Deps] pin `glob`, since v10.3.8+ requires a broken `jackspeak`
|
|
71
110
|
- [Dev Deps] pin `jackspeak` since 2.1.2+ depends on npm aliases, which kill the install process in npm < 6
|
|
72
111
|
|
|
112
|
+
## **6.11.4**
|
|
113
|
+
- [Fix] fix regressions from robustness refactor
|
|
114
|
+
- [actions] update reusable workflows
|
|
115
|
+
|
|
116
|
+
## **6.11.3**
|
|
117
|
+
- [Robustness] avoid `.push`, use `void`
|
|
118
|
+
- [readme] clarify `parseArrays` and `arrayLimit` documentation (#543)
|
|
119
|
+
- [readme] document that `addQueryPrefix` does not add `?` to empty output (#418)
|
|
120
|
+
- [readme] replace runkit CI badge with shields.io check-runs badge
|
|
121
|
+
- [actions] fix rebase workflow permissions
|
|
122
|
+
|
|
73
123
|
## **6.11.2**
|
|
74
124
|
- [Fix] `parse`: Fix parsing when the global Object prototype is frozen (#473)
|
|
75
125
|
- [Tests] add passing test cases with empty keys (#473)
|
|
@@ -87,6 +137,17 @@
|
|
|
87
137
|
- [New] [Fix] `stringify`: revert 0e903c0; add `commaRoundTrip` option (#442)
|
|
88
138
|
- [readme] fix version badge
|
|
89
139
|
|
|
140
|
+
## **6.10.7**
|
|
141
|
+
- [Fix] fix regressions from robustness refactor
|
|
142
|
+
- [actions] update reusable workflows
|
|
143
|
+
|
|
144
|
+
## **6.10.6**
|
|
145
|
+
- [Robustness] avoid `.push`, use `void`
|
|
146
|
+
- [readme] clarify `parseArrays` and `arrayLimit` documentation (#543)
|
|
147
|
+
- [readme] document that `addQueryPrefix` does not add `?` to empty output (#418)
|
|
148
|
+
- [readme] replace runkit CI badge with shields.io check-runs badge
|
|
149
|
+
- [actions] fix rebase workflow permissions
|
|
150
|
+
|
|
90
151
|
## **6.10.5**
|
|
91
152
|
- [Fix] `stringify`: with `arrayFormat: comma`, properly include an explicit `[]` on a single-item array (#434)
|
|
92
153
|
|
|
@@ -124,6 +185,18 @@
|
|
|
124
185
|
- [Tests] use `ljharb/actions/node/install` instead of `ljharb/actions/node/run`
|
|
125
186
|
- [Tests] Revert "[meta] ignore eclint transitive audit warning"
|
|
126
187
|
|
|
188
|
+
## **6.9.9**
|
|
189
|
+
- [Fix] fix regressions from robustness refactor
|
|
190
|
+
- [meta] add `npmignore` to autogenerate an npmignore file
|
|
191
|
+
- [actions] update reusable workflows
|
|
192
|
+
|
|
193
|
+
## **6.9.8**
|
|
194
|
+
- [Robustness] avoid `.push`, use `void`
|
|
195
|
+
- [readme] clarify `parseArrays` and `arrayLimit` documentation (#543)
|
|
196
|
+
- [readme] document that `addQueryPrefix` does not add `?` to empty output (#418)
|
|
197
|
+
- [readme] replace runkit CI badge with shields.io check-runs badge
|
|
198
|
+
- [actions] fix rebase workflow permissions
|
|
199
|
+
|
|
127
200
|
## **6.9.7**
|
|
128
201
|
- [Fix] `parse`: ignore `__proto__` keys (#428)
|
|
129
202
|
- [Fix] `stringify`: avoid encoding arrayformat comma when `encodeValuesOnly = true` (#424)
|
|
@@ -184,6 +257,18 @@
|
|
|
184
257
|
- [Tests] up to `node` `v12.10`, `v11.15`, `v10.16`, `v8.16`
|
|
185
258
|
- [Tests] `Buffer.from` in node v5.0-v5.9 and v4.0-v4.4 requires a TypedArray
|
|
186
259
|
|
|
260
|
+
## **6.8.5**
|
|
261
|
+
- [Fix] fix regressions from robustness refactor
|
|
262
|
+
- [meta] add `npmignore` to autogenerate an npmignore file
|
|
263
|
+
- [actions] update reusable workflows
|
|
264
|
+
|
|
265
|
+
## **6.8.4**
|
|
266
|
+
- [Robustness] avoid `.push`, use `void`
|
|
267
|
+
- [readme] clarify `parseArrays` and `arrayLimit` documentation (#543)
|
|
268
|
+
- [readme] document that `addQueryPrefix` does not add `?` to empty output (#418)
|
|
269
|
+
- [readme] replace runkit CI badge with shields.io check-runs badge
|
|
270
|
+
- [actions] fix rebase workflow permissions
|
|
271
|
+
|
|
187
272
|
## **6.8.3**
|
|
188
273
|
- [Fix] `parse`: ignore `__proto__` keys (#428)
|
|
189
274
|
- [Robustness] `stringify`: avoid relying on a global `undefined` (#427)
|
|
@@ -228,6 +313,18 @@
|
|
|
228
313
|
- [meta] add FUNDING.yml
|
|
229
314
|
- [meta] Clean up license text so it’s properly detected as BSD-3-Clause
|
|
230
315
|
|
|
316
|
+
## **6.7.5**
|
|
317
|
+
- [Fix] fix regressions from robustness refactor
|
|
318
|
+
- [meta] add `npmignore` to autogenerate an npmignore file
|
|
319
|
+
- [actions] update reusable workflows
|
|
320
|
+
|
|
321
|
+
## **6.7.4**
|
|
322
|
+
- [Robustness] avoid `.push`, use `void`
|
|
323
|
+
- [readme] clarify `parseArrays` and `arrayLimit` documentation (#543)
|
|
324
|
+
- [readme] document that `addQueryPrefix` does not add `?` to empty output (#418)
|
|
325
|
+
- [readme] replace runkit CI badge with shields.io check-runs badge
|
|
326
|
+
- [actions] fix rebase workflow permissions
|
|
327
|
+
|
|
231
328
|
## **6.7.3**
|
|
232
329
|
- [Fix] `parse`: ignore `__proto__` keys (#428)
|
|
233
330
|
- [Fix] `stringify`: avoid encoding arrayformat comma when `encodeValuesOnly = true` (#424)
|
|
@@ -279,6 +376,18 @@
|
|
|
279
376
|
- [Tests] fix Buffer tests to work in node < 4.5 and node < 5.10
|
|
280
377
|
- [Tests] temporarily allow coverage to fail
|
|
281
378
|
|
|
379
|
+
## **6.6.3**
|
|
380
|
+
- [Fix] fix regressions from robustness refactor
|
|
381
|
+
- [meta] add `npmignore` to autogenerate an npmignore file
|
|
382
|
+
- [actions] update reusable workflows
|
|
383
|
+
|
|
384
|
+
## **6.6.2**
|
|
385
|
+
- [Robustness] avoid `.push`, use `void`
|
|
386
|
+
- [readme] clarify `parseArrays` and `arrayLimit` documentation (#543)
|
|
387
|
+
- [readme] document that `addQueryPrefix` does not add `?` to empty output (#418)
|
|
388
|
+
- [readme] replace runkit CI badge with shields.io check-runs badge
|
|
389
|
+
- [actions] fix rebase workflow permissions
|
|
390
|
+
|
|
282
391
|
## **6.6.1**
|
|
283
392
|
- [Fix] `parse`: ignore `__proto__` keys (#428)
|
|
284
393
|
- [Fix] fix for an impossible situation: when the formatter is called with a non-string value
|
|
@@ -321,6 +430,18 @@
|
|
|
321
430
|
- [Dev Deps] update `browserify`, `eslint`, `@ljharb/eslint-config`, `iconv-lite`, `safe-publish-latest`, `tape`
|
|
322
431
|
- [Tests] up to `node` `v10.10`, `v9.11`, `v8.12`, `v6.14`, `v4.9`; pin included builds to LTS
|
|
323
432
|
|
|
433
|
+
## **6.5.5**
|
|
434
|
+
- [Fix] fix regressions from robustness refactor
|
|
435
|
+
- [meta] add `npmignore` to autogenerate an npmignore file
|
|
436
|
+
- [actions] update reusable workflows
|
|
437
|
+
|
|
438
|
+
## **6.5.4**
|
|
439
|
+
- [Robustness] avoid `.push`, use `void`
|
|
440
|
+
- [readme] clarify `parseArrays` and `arrayLimit` documentation (#543)
|
|
441
|
+
- [readme] document that `addQueryPrefix` does not add `?` to empty output (#418)
|
|
442
|
+
- [readme] replace runkit CI badge with shields.io check-runs badge
|
|
443
|
+
- [actions] fix rebase workflow permissions
|
|
444
|
+
|
|
324
445
|
## **6.5.3**
|
|
325
446
|
- [Fix] `parse`: ignore `__proto__` keys (#428)
|
|
326
447
|
- [Fix] `utils.merge`: avoid a crash with a null target and a truthy non-array source
|
|
@@ -371,6 +492,18 @@
|
|
|
371
492
|
- [Tests] up to `node` `v8.1`, `v7.10`, `v6.11`; npm v4.6 breaks on node < v1; npm v5+ breaks on node < v4
|
|
372
493
|
- [Tests] add `editorconfig-tools`
|
|
373
494
|
|
|
495
|
+
## **6.4.3**
|
|
496
|
+
- [Fix] fix regressions from robustness refactor
|
|
497
|
+
- [meta] add `npmignore` to autogenerate an npmignore file
|
|
498
|
+
- [actions] update reusable workflows
|
|
499
|
+
|
|
500
|
+
## **6.4.2**
|
|
501
|
+
- [Robustness] avoid `.push`, use `void`
|
|
502
|
+
- [readme] clarify `parseArrays` and `arrayLimit` documentation (#543)
|
|
503
|
+
- [readme] replace runkit CI badge with shields.io check-runs badge
|
|
504
|
+
- [readme] replace travis CI badge with shields.io check-runs badge
|
|
505
|
+
- [actions] fix rebase workflow permissions
|
|
506
|
+
|
|
374
507
|
## **6.4.1**
|
|
375
508
|
- [Fix] `parse`: ignore `__proto__` keys (#428)
|
|
376
509
|
- [Fix] fix for an impossible situation: when the formatter is called with a non-string value
|
|
@@ -401,6 +534,17 @@
|
|
|
401
534
|
- [Tests] up to `node` `v7.7`, `v6.10`,` v4.8`; disable osx builds since they block linux builds
|
|
402
535
|
- [eslint] reduce warnings
|
|
403
536
|
|
|
537
|
+
## **6.3.5**
|
|
538
|
+
- [Fix] fix regressions from robustness refactor
|
|
539
|
+
- [meta] add `npmignore` to autogenerate an npmignore file
|
|
540
|
+
- [actions] update reusable workflows
|
|
541
|
+
|
|
542
|
+
## **6.3.4**
|
|
543
|
+
- [Robustness] avoid `.push`, use `void`
|
|
544
|
+
- [readme] clarify `parseArrays` and `arrayLimit` documentation (#543)
|
|
545
|
+
- [readme] replace travis CI badge with shields.io check-runs badge
|
|
546
|
+
- [actions] fix rebase workflow permissions
|
|
547
|
+
|
|
404
548
|
## **6.3.3**
|
|
405
549
|
- [Fix] `parse`: ignore `__proto__` keys (#428)
|
|
406
550
|
- [Fix] fix for an impossible situation: when the formatter is called with a non-string value
|
|
@@ -454,6 +598,17 @@
|
|
|
454
598
|
- [Tests] skip Object.create tests when null objects are not available
|
|
455
599
|
- [Tests] Turn on eslint for test files (#175)
|
|
456
600
|
|
|
601
|
+
## **6.2.6**
|
|
602
|
+
- [Fix] fix regression from robustness refactor
|
|
603
|
+
- [meta] add `npmignore` to autogenerate an npmignore file
|
|
604
|
+
- [actions] update reusable workflows
|
|
605
|
+
|
|
606
|
+
## **6.2.5**
|
|
607
|
+
- [Robustness] avoid `.push`, use `void`
|
|
608
|
+
- [readme] clarify `parseArrays` and `arrayLimit` documentation (#543)
|
|
609
|
+
- [readme] replace travis CI badge with shields.io check-runs badge
|
|
610
|
+
- [actions] fix rebase workflow permissions
|
|
611
|
+
|
|
457
612
|
## **6.2.4**
|
|
458
613
|
- [Fix] `parse`: ignore `__proto__` keys (#428)
|
|
459
614
|
- [Fix] `utils.merge`: avoid a crash with a null target and an array source
|
|
@@ -492,6 +647,16 @@
|
|
|
492
647
|
- [New] add "encoder" and "decoder" options, for custom param encoding/decoding (#160)
|
|
493
648
|
- [Fix] fix compacting of nested sparse arrays (#150)
|
|
494
649
|
|
|
650
|
+
## **6.1.4**
|
|
651
|
+
- [Fix] fix regression from robustness refactor
|
|
652
|
+
- [meta] add `npmignore` to autogenerate an npmignore file
|
|
653
|
+
- [actions] update reusable workflows
|
|
654
|
+
|
|
655
|
+
## **6.1.3**
|
|
656
|
+
- [Robustness] avoid `.push`, use `void`
|
|
657
|
+
- [readme] clarify `parseArrays` and `arrayLimit` documentation (#543)
|
|
658
|
+
- [readme] replace travis CI badge with shields.io check-runs badge
|
|
659
|
+
|
|
495
660
|
## **6.1.2**
|
|
496
661
|
- [Fix] follow `allowPrototypes` option during merge (#201, #200)
|
|
497
662
|
- [Fix] chmod a-x
|
|
@@ -506,6 +671,16 @@
|
|
|
506
671
|
- [Fix] "sort" option should work at a depth of 3 or more (#151)
|
|
507
672
|
- [Fix] Restore `dist` directory; will be removed in v7 (#148)
|
|
508
673
|
|
|
674
|
+
## **6.0.6**
|
|
675
|
+
- [Fix] fix regression from robustness refactor
|
|
676
|
+
- [meta] add `npmignore` to autogenerate an npmignore file
|
|
677
|
+
- [actions] update reusable workflows
|
|
678
|
+
|
|
679
|
+
## **6.0.5**
|
|
680
|
+
- [Robustness] avoid `.push`, use `void`
|
|
681
|
+
- [readme] clarify `parseArrays` and `arrayLimit` documentation (#543)
|
|
682
|
+
- [readme] replace travis CI badge with shields.io check-runs badge
|
|
683
|
+
|
|
509
684
|
## **6.0.4**
|
|
510
685
|
- [Fix] follow `allowPrototypes` option during merge (#201, #200)
|
|
511
686
|
- [Fix] chmod a-x
|
package/README.md
CHANGED
|
@@ -197,6 +197,11 @@ assert.deepEqual(qs.parse('foo=bar&foo=baz', { duplicates: 'first' }), { foo: 'b
|
|
|
197
197
|
assert.deepEqual(qs.parse('foo=bar&foo=baz', { duplicates: 'last' }), { foo: 'baz' });
|
|
198
198
|
```
|
|
199
199
|
|
|
200
|
+
Note that keys with bracket notation (`[]`) always combine into arrays, regardless of the `duplicates` setting:
|
|
201
|
+
```javascript
|
|
202
|
+
assert.deepEqual(qs.parse('a=1&a=2&b[]=1&b[]=2', { duplicates: 'last' }), { a: '2', b: ['1', '2'] });
|
|
203
|
+
```
|
|
204
|
+
|
|
200
205
|
If you have to deal with legacy browsers or services, there's also support for decoding percent-encoded octets as iso-8859-1:
|
|
201
206
|
|
|
202
207
|
```javascript
|
|
@@ -282,8 +287,8 @@ var withIndexedEmptyString = qs.parse('a[0]=b&a[1]=&a[2]=c');
|
|
|
282
287
|
assert.deepEqual(withIndexedEmptyString, { a: ['b', '', 'c'] });
|
|
283
288
|
```
|
|
284
289
|
|
|
285
|
-
**qs** will also limit
|
|
286
|
-
Any array members with an index of
|
|
290
|
+
**qs** will also limit arrays to a maximum of `20` elements.
|
|
291
|
+
Any array members with an index of `20` or greater will instead be converted to an object with the index as the key.
|
|
287
292
|
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.
|
|
288
293
|
|
|
289
294
|
```javascript
|
|
@@ -310,7 +315,8 @@ try {
|
|
|
310
315
|
|
|
311
316
|
When `throwOnLimitExceeded` is set to `false` (default), **qs** will parse up to the specified `arrayLimit` and if the limit is exceeded, the array will instead be converted to an object with the index as the key
|
|
312
317
|
|
|
313
|
-
To
|
|
318
|
+
To prevent array syntax (`a[]`, `a[0]`) from being parsed as arrays, set `parseArrays` to `false`.
|
|
319
|
+
Note that duplicate keys (e.g. `a=b&a=c`) may still produce arrays when `duplicates` is `'combine'` (the default).
|
|
314
320
|
|
|
315
321
|
```javascript
|
|
316
322
|
var noParsingArrays = qs.parse('a[]=b', { parseArrays: false });
|
|
@@ -324,6 +330,19 @@ var mixedNotation = qs.parse('a[0]=b&a[b]=c');
|
|
|
324
330
|
assert.deepEqual(mixedNotation, { a: { '0': 'b', b: 'c' } });
|
|
325
331
|
```
|
|
326
332
|
|
|
333
|
+
When a key appears as both a plain value and an object, **qs** will by default wrap the conflicting values in an array (`strictMerge` defaults to `true`):
|
|
334
|
+
|
|
335
|
+
```javascript
|
|
336
|
+
assert.deepEqual(qs.parse('a[b]=c&a=d'), { a: [{ b: 'c' }, 'd'] });
|
|
337
|
+
assert.deepEqual(qs.parse('a=d&a[b]=c'), { a: ['d', { b: 'c' }] });
|
|
338
|
+
```
|
|
339
|
+
|
|
340
|
+
To restore the legacy behavior (where the primitive is used as a key with value `true`), set `strictMerge` to `false`:
|
|
341
|
+
|
|
342
|
+
```javascript
|
|
343
|
+
assert.deepEqual(qs.parse('a[b]=c&a=d', { strictMerge: false }), { a: { b: 'c', d: true } });
|
|
344
|
+
```
|
|
345
|
+
|
|
327
346
|
You can also create arrays of objects:
|
|
328
347
|
|
|
329
348
|
```javascript
|
|
@@ -512,6 +531,12 @@ The query string may optionally be prepended with a question mark:
|
|
|
512
531
|
assert.equal(qs.stringify({ a: 'b', c: 'd' }, { addQueryPrefix: true }), '?a=b&c=d');
|
|
513
532
|
```
|
|
514
533
|
|
|
534
|
+
Note that when the output is an empty string, the prefix will not be added:
|
|
535
|
+
|
|
536
|
+
```javascript
|
|
537
|
+
assert.equal(qs.stringify({}, { addQueryPrefix: true }), '');
|
|
538
|
+
```
|
|
539
|
+
|
|
515
540
|
The delimiter may be overridden with stringify as well:
|
|
516
541
|
|
|
517
542
|
```javascript
|
|
@@ -723,7 +748,7 @@ Save time, reduce risk, and improve code health, while paying the maintainers of
|
|
|
723
748
|
[downloads-url]: https://npm-stat.com/charts.html?package=qs
|
|
724
749
|
[codecov-image]: https://codecov.io/gh/ljharb/qs/branch/main/graphs/badge.svg
|
|
725
750
|
[codecov-url]: https://app.codecov.io/gh/ljharb/qs/
|
|
726
|
-
[actions-image]: https://img.shields.io/
|
|
751
|
+
[actions-image]: https://img.shields.io/github/check-runs/ljharb/qs/main
|
|
727
752
|
[actions-url]: https://github.com/ljharb/qs/actions
|
|
728
753
|
|
|
729
754
|
## Acknowledgements
|
package/dist/qs.js
CHANGED
|
@@ -5,13 +5,13 @@
|
|
|
5
5
|
"use strict";var stringify=require(4),parse=require(3),formats=require(1);module.exports={formats:formats,parse:parse,stringify:stringify};
|
|
6
6
|
|
|
7
7
|
},{"1":1,"3":3,"4":4}],3:[function(require,module,exports){
|
|
8
|
-
"use strict";var utils=require(5),has=Object.prototype.hasOwnProperty,isArray=Array.isArray,defaults={allowDots:!1,allowEmptyArrays:!1,allowPrototypes:!1,allowSparse:!1,arrayLimit:20,charset:"utf-8",charsetSentinel:!1,comma:!1,decodeDotInKeys:!1,decoder:utils.decode,delimiter:"&",depth:5,duplicates:"combine",ignoreQueryPrefix:!1,interpretNumericEntities:!1,parameterLimit:1e3,parseArrays:!0,plainObjects:!1,strictDepth:!1,strictNullHandling:!1,throwOnLimitExceeded:!1},interpretNumericEntities=function(e){return e.replace(/&#(\d+);/g,function(e,t){return String.fromCharCode(parseInt(t,10))})},parseArrayValue=function(e,t,r){if(e&&"string"==typeof e&&t.comma&&e.indexOf(",")>-1)return e.split(",");if(t.throwOnLimitExceeded&&r>=t.arrayLimit)throw new RangeError("Array limit exceeded. Only "+t.arrayLimit+" element"+(1===t.arrayLimit?"":"s")+" allowed in an array.");return e},isoSentinel="utf8=%26%2310003%3B",charsetSentinel="utf8=%E2%9C%93",parseValues=function parseQueryStringValues(e,t){var r={__proto__:null},i=t.ignoreQueryPrefix?e.replace(/^\?/,""):e;i=i.replace(/%5B/gi,"[").replace(/%5D/gi,"]");var a=t.parameterLimit===1/0?void 0:t.parameterLimit,o=i.split(t.delimiter,t.throwOnLimitExceeded?a+1:a);if(t.throwOnLimitExceeded&&o.length>a)throw new RangeError("Parameter limit exceeded. Only "+a+" parameter"+(1===a?"":"s")+" allowed.");var l,n=-1,s=t.charset;if(t.charsetSentinel)for(l=0;l<o.length;++l)0===o[l].indexOf("utf8=")&&(o[l]===charsetSentinel?s="utf-8":o[l]===isoSentinel&&(s="iso-8859-1"),n=l,l=o.length);for(l=0;l<o.length;++l)if(l!==n){var
|
|
8
|
+
"use strict";var utils=require(5),has=Object.prototype.hasOwnProperty,isArray=Array.isArray,defaults={allowDots:!1,allowEmptyArrays:!1,allowPrototypes:!1,allowSparse:!1,arrayLimit:20,charset:"utf-8",charsetSentinel:!1,comma:!1,decodeDotInKeys:!1,decoder:utils.decode,delimiter:"&",depth:5,duplicates:"combine",ignoreQueryPrefix:!1,interpretNumericEntities:!1,parameterLimit:1e3,parseArrays:!0,plainObjects:!1,strictDepth:!1,strictMerge:!0,strictNullHandling:!1,throwOnLimitExceeded:!1},interpretNumericEntities=function(e){return e.replace(/&#(\d+);/g,function(e,t){return String.fromCharCode(parseInt(t,10))})},parseArrayValue=function(e,t,r){if(e&&"string"==typeof e&&t.comma&&e.indexOf(",")>-1)return e.split(",");if(t.throwOnLimitExceeded&&r>=t.arrayLimit)throw new RangeError("Array limit exceeded. Only "+t.arrayLimit+" element"+(1===t.arrayLimit?"":"s")+" allowed in an array.");return e},isoSentinel="utf8=%26%2310003%3B",charsetSentinel="utf8=%E2%9C%93",parseValues=function parseQueryStringValues(e,t){var r={__proto__:null},i=t.ignoreQueryPrefix?e.replace(/^\?/,""):e;i=i.replace(/%5B/gi,"[").replace(/%5D/gi,"]");var a=t.parameterLimit===1/0?void 0:t.parameterLimit,o=i.split(t.delimiter,t.throwOnLimitExceeded?a+1:a);if(t.throwOnLimitExceeded&&o.length>a)throw new RangeError("Parameter limit exceeded. Only "+a+" parameter"+(1===a?"":"s")+" allowed.");var l,n=-1,s=t.charset;if(t.charsetSentinel)for(l=0;l<o.length;++l)0===o[l].indexOf("utf8=")&&(o[l]===charsetSentinel?s="utf-8":o[l]===isoSentinel&&(s="iso-8859-1"),n=l,l=o.length);for(l=0;l<o.length;++l)if(l!==n){var d,c,p=o[l],u=p.indexOf("]="),y=-1===u?p.indexOf("="):u+1;if(-1===y?(d=t.decoder(p,defaults.decoder,s,"key"),c=t.strictNullHandling?null:""):null!==(d=t.decoder(p.slice(0,y),defaults.decoder,s,"key"))&&(c=utils.maybeMap(parseArrayValue(p.slice(y+1),t,isArray(r[d])?r[d].length:0),function(e){return t.decoder(e,defaults.decoder,s,"value")})),c&&t.interpretNumericEntities&&"iso-8859-1"===s&&(c=interpretNumericEntities(String(c))),p.indexOf("[]=")>-1&&(c=isArray(c)?[c]:c),t.comma&&isArray(c)&&c.length>t.arrayLimit){if(t.throwOnLimitExceeded)throw new RangeError("Array limit exceeded. Only "+t.arrayLimit+" element"+(1===t.arrayLimit?"":"s")+" allowed in an array.");c=utils.combine([],c,t.arrayLimit,t.plainObjects)}if(null!==d){var f=has.call(r,d);f&&("combine"===t.duplicates||p.indexOf("[]=")>-1)?r[d]=utils.combine(r[d],c,t.arrayLimit,t.plainObjects):f&&"last"!==t.duplicates||(r[d]=c)}}return r},parseObject=function(e,t,r,i){var a=0;if(e.length>0&&"[]"===e[e.length-1]){var o=e.slice(0,-1).join("");a=Array.isArray(t)&&t[o]?t[o].length:0}for(var l=i?t:parseArrayValue(t,r,a),n=e.length-1;n>=0;--n){var s,d=e[n];if("[]"===d&&r.parseArrays)s=utils.isOverflow(l)?l:r.allowEmptyArrays&&(""===l||r.strictNullHandling&&null===l)?[]:utils.combine([],l,r.arrayLimit,r.plainObjects);else{s=r.plainObjects?{__proto__:null}:{};var c="["===d.charAt(0)&&"]"===d.charAt(d.length-1)?d.slice(1,-1):d,p=r.decodeDotInKeys?c.replace(/%2E/g,"."):c,u=parseInt(p,10),y=!isNaN(u)&&d!==p&&String(u)===p&&u>=0&&r.parseArrays;if(r.parseArrays||""!==p)if(y&&u<r.arrayLimit)(s=[])[u]=l;else{if(y&&r.throwOnLimitExceeded)throw new RangeError("Array limit exceeded. Only "+r.arrayLimit+" element"+(1===r.arrayLimit?"":"s")+" allowed in an array.");y?(s[u]=l,utils.markOverflow(s,u)):"__proto__"!==p&&(s[p]=l)}else s={0:l}}l=s}return l},splitKeyIntoSegments=function splitKeyIntoSegments(e,t){var r=t.allowDots?e.replace(/\.([^.[]+)/g,"[$1]"):e;if(t.depth<=0){if(!t.plainObjects&&has.call(Object.prototype,r)&&!t.allowPrototypes)return;return[r]}var i=/(\[[^[\]]*])/g,a=/(\[[^[\]]*])/.exec(r),o=a?r.slice(0,a.index):r,l=[];if(o){if(!t.plainObjects&&has.call(Object.prototype,o)&&!t.allowPrototypes)return;l[l.length]=o}for(var n=0;null!==(a=i.exec(r))&&n<t.depth;){n+=1;var s=a[1].slice(1,-1);if(!t.plainObjects&&has.call(Object.prototype,s)&&!t.allowPrototypes)return;l[l.length]=a[1]}if(a){if(!0===t.strictDepth)throw new RangeError("Input depth exceeded depth option of "+t.depth+" and strictDepth is true");l[l.length]="["+r.slice(a.index)+"]"}return l},parseKeys=function parseQueryStringKeys(e,t,r,i){if(e){var a=splitKeyIntoSegments(e,r);if(a)return parseObject(a,t,r,i)}},normalizeParseOptions=function normalizeParseOptions(e){if(!e)return defaults;if(void 0!==e.allowEmptyArrays&&"boolean"!=typeof e.allowEmptyArrays)throw new TypeError("`allowEmptyArrays` option can only be `true` or `false`, when provided");if(void 0!==e.decodeDotInKeys&&"boolean"!=typeof e.decodeDotInKeys)throw new TypeError("`decodeDotInKeys` option can only be `true` or `false`, when provided");if(null!==e.decoder&&void 0!==e.decoder&&"function"!=typeof e.decoder)throw new TypeError("Decoder has to be a function.");if(void 0!==e.charset&&"utf-8"!==e.charset&&"iso-8859-1"!==e.charset)throw new TypeError("The charset option must be either utf-8, iso-8859-1, or undefined");if(void 0!==e.throwOnLimitExceeded&&"boolean"!=typeof e.throwOnLimitExceeded)throw new TypeError("`throwOnLimitExceeded` option must be a boolean");var t=void 0===e.charset?defaults.charset:e.charset,r=void 0===e.duplicates?defaults.duplicates:e.duplicates;if("combine"!==r&&"first"!==r&&"last"!==r)throw new TypeError("The duplicates option must be either combine, first, or last");return{allowDots:void 0===e.allowDots?!0===e.decodeDotInKeys||defaults.allowDots:!!e.allowDots,allowEmptyArrays:"boolean"==typeof e.allowEmptyArrays?!!e.allowEmptyArrays:defaults.allowEmptyArrays,allowPrototypes:"boolean"==typeof e.allowPrototypes?e.allowPrototypes:defaults.allowPrototypes,allowSparse:"boolean"==typeof e.allowSparse?e.allowSparse:defaults.allowSparse,arrayLimit:"number"==typeof e.arrayLimit?e.arrayLimit:defaults.arrayLimit,charset:t,charsetSentinel:"boolean"==typeof e.charsetSentinel?e.charsetSentinel:defaults.charsetSentinel,comma:"boolean"==typeof e.comma?e.comma:defaults.comma,decodeDotInKeys:"boolean"==typeof e.decodeDotInKeys?e.decodeDotInKeys:defaults.decodeDotInKeys,decoder:"function"==typeof e.decoder?e.decoder:defaults.decoder,delimiter:"string"==typeof e.delimiter||utils.isRegExp(e.delimiter)?e.delimiter:defaults.delimiter,depth:"number"==typeof e.depth||!1===e.depth?+e.depth:defaults.depth,duplicates:r,ignoreQueryPrefix:!0===e.ignoreQueryPrefix,interpretNumericEntities:"boolean"==typeof e.interpretNumericEntities?e.interpretNumericEntities:defaults.interpretNumericEntities,parameterLimit:"number"==typeof e.parameterLimit?e.parameterLimit:defaults.parameterLimit,parseArrays:!1!==e.parseArrays,plainObjects:"boolean"==typeof e.plainObjects?e.plainObjects:defaults.plainObjects,strictDepth:"boolean"==typeof e.strictDepth?!!e.strictDepth:defaults.strictDepth,strictMerge:"boolean"==typeof e.strictMerge?!!e.strictMerge:defaults.strictMerge,strictNullHandling:"boolean"==typeof e.strictNullHandling?e.strictNullHandling:defaults.strictNullHandling,throwOnLimitExceeded:"boolean"==typeof e.throwOnLimitExceeded&&e.throwOnLimitExceeded}};module.exports=function(e,t){var r=normalizeParseOptions(t);if(""===e||null==e)return r.plainObjects?{__proto__:null}:{};for(var i="string"==typeof e?parseValues(e,r):e,a=r.plainObjects?{__proto__:null}:{},o=Object.keys(i),l=0;l<o.length;++l){var n=o[l],s=parseKeys(n,i[n],r,"string"==typeof e);a=utils.merge(a,s,r)}return!0===r.allowSparse?a:utils.compact(a)};
|
|
9
9
|
|
|
10
10
|
},{"5":5}],4:[function(require,module,exports){
|
|
11
11
|
"use strict";var getSideChannel=require(46),utils=require(5),formats=require(1),has=Object.prototype.hasOwnProperty,arrayPrefixGenerators={brackets:function brackets(e){return e+"[]"},comma:"comma",indices:function indices(e,r){return e+"["+r+"]"},repeat:function repeat(e){return e}},isArray=Array.isArray,push=Array.prototype.push,pushToArray=function(e,r){push.apply(e,isArray(r)?r:[r])},toISO=Date.prototype.toISOString,defaultFormat=formats.default,defaults={addQueryPrefix:!1,allowDots:!1,allowEmptyArrays:!1,arrayFormat:"indices",charset:"utf-8",charsetSentinel:!1,commaRoundTrip:!1,delimiter:"&",encode:!0,encodeDotInKeys:!1,encoder:utils.encode,encodeValuesOnly:!1,filter:void 0,format:defaultFormat,formatter:formats.formatters[defaultFormat],indices:!1,serializeDate:function serializeDate(e){return toISO.call(e)},skipNulls:!1,strictNullHandling:!1},isNonNullishPrimitive=function isNonNullishPrimitive(e){return"string"==typeof e||"number"==typeof e||"boolean"==typeof e||"symbol"==typeof e||"bigint"==typeof e},sentinel={},stringify=function stringify(e,r,t,o,a,n,i,l,s,f,u,d,y,c,p,m,h,v){for(var g=e,w=v,b=0,A=!1;void 0!==(w=w.get(sentinel))&&!A;){var D=w.get(e);if(b+=1,void 0!==D){if(D===b)throw new RangeError("Cyclic object value");A=!0}void 0===w.get(sentinel)&&(b=0)}if("function"==typeof f?g=f(r,g):g instanceof Date?g=y(g):"comma"===t&&isArray(g)&&(g=utils.maybeMap(g,function(e){return e instanceof Date?y(e):e})),null===g){if(n)return s&&!m?s(r,defaults.encoder,h,"key",c):r;g=""}if(isNonNullishPrimitive(g)||utils.isBuffer(g))return s?[p(m?r:s(r,defaults.encoder,h,"key",c))+"="+p(s(g,defaults.encoder,h,"value",c))]:[p(r)+"="+p(String(g))];var S,E=[];if(void 0===g)return E;if("comma"===t&&isArray(g))m&&s&&(g=utils.maybeMap(g,s)),S=[{value:g.length>0?g.join(",")||null:void 0}];else if(isArray(f))S=f;else{var N=Object.keys(g);S=u?N.sort(u):N}var T=l?String(r).replace(/\./g,"%2E"):String(r),O=o&&isArray(g)&&1===g.length?T+"[]":T;if(a&&isArray(g)&&0===g.length)return O+"[]";for(var k=0;k<S.length;++k){var I=S[k],P="object"==typeof I&&I&&void 0!==I.value?I.value:g[I];if(!i||null!==P){var x=d&&l?String(I).replace(/\./g,"%2E"):String(I),z=isArray(g)?"function"==typeof t?t(O,x):O:O+(d?"."+x:"["+x+"]");v.set(e,b);var K=getSideChannel();K.set(sentinel,v),pushToArray(E,stringify(P,z,t,o,a,n,i,l,"comma"===t&&m&&isArray(g)?null:s,f,u,d,y,c,p,m,h,K))}}return E},normalizeStringifyOptions=function normalizeStringifyOptions(e){if(!e)return defaults;if(void 0!==e.allowEmptyArrays&&"boolean"!=typeof e.allowEmptyArrays)throw new TypeError("`allowEmptyArrays` option can only be `true` or `false`, when provided");if(void 0!==e.encodeDotInKeys&&"boolean"!=typeof e.encodeDotInKeys)throw new TypeError("`encodeDotInKeys` option can only be `true` or `false`, when provided");if(null!==e.encoder&&void 0!==e.encoder&&"function"!=typeof e.encoder)throw new TypeError("Encoder has to be a function.");var r=e.charset||defaults.charset;if(void 0!==e.charset&&"utf-8"!==e.charset&&"iso-8859-1"!==e.charset)throw new TypeError("The charset option must be either utf-8, iso-8859-1, or undefined");var t=formats.default;if(void 0!==e.format){if(!has.call(formats.formatters,e.format))throw new TypeError("Unknown format option provided.");t=e.format}var o,a=formats.formatters[t],n=defaults.filter;if(("function"==typeof e.filter||isArray(e.filter))&&(n=e.filter),o=e.arrayFormat in arrayPrefixGenerators?e.arrayFormat:"indices"in e?e.indices?"indices":"repeat":defaults.arrayFormat,"commaRoundTrip"in e&&"boolean"!=typeof e.commaRoundTrip)throw new TypeError("`commaRoundTrip` must be a boolean, or absent");var i=void 0===e.allowDots?!0===e.encodeDotInKeys||defaults.allowDots:!!e.allowDots;return{addQueryPrefix:"boolean"==typeof e.addQueryPrefix?e.addQueryPrefix:defaults.addQueryPrefix,allowDots:i,allowEmptyArrays:"boolean"==typeof e.allowEmptyArrays?!!e.allowEmptyArrays:defaults.allowEmptyArrays,arrayFormat:o,charset:r,charsetSentinel:"boolean"==typeof e.charsetSentinel?e.charsetSentinel:defaults.charsetSentinel,commaRoundTrip:!!e.commaRoundTrip,delimiter:void 0===e.delimiter?defaults.delimiter:e.delimiter,encode:"boolean"==typeof e.encode?e.encode:defaults.encode,encodeDotInKeys:"boolean"==typeof e.encodeDotInKeys?e.encodeDotInKeys:defaults.encodeDotInKeys,encoder:"function"==typeof e.encoder?e.encoder:defaults.encoder,encodeValuesOnly:"boolean"==typeof e.encodeValuesOnly?e.encodeValuesOnly:defaults.encodeValuesOnly,filter:n,format:t,formatter:a,serializeDate:"function"==typeof e.serializeDate?e.serializeDate:defaults.serializeDate,skipNulls:"boolean"==typeof e.skipNulls?e.skipNulls:defaults.skipNulls,sort:"function"==typeof e.sort?e.sort:null,strictNullHandling:"boolean"==typeof e.strictNullHandling?e.strictNullHandling:defaults.strictNullHandling}};module.exports=function(e,r){var t,o=e,a=normalizeStringifyOptions(r);"function"==typeof a.filter?o=(0,a.filter)("",o):isArray(a.filter)&&(t=a.filter);var n=[];if("object"!=typeof o||null===o)return"";var i=arrayPrefixGenerators[a.arrayFormat],l="comma"===i&&a.commaRoundTrip;t||(t=Object.keys(o)),a.sort&&t.sort(a.sort);for(var s=getSideChannel(),f=0;f<t.length;++f){var u=t[f],d=o[u];a.skipNulls&&null===d||pushToArray(n,stringify(d,u,i,l,a.allowEmptyArrays,a.strictNullHandling,a.skipNulls,a.encodeDotInKeys,a.encode?a.encoder:null,a.filter,a.sort,a.allowDots,a.serializeDate,a.format,a.formatter,a.encodeValuesOnly,a.charset,s))}var y=n.join(a.delimiter),c=!0===a.addQueryPrefix?"?":"";return a.charsetSentinel&&("iso-8859-1"===a.charset?c+="utf8=%26%2310003%3B&":c+="utf8=%E2%9C%93&"),y.length>0?c+y:""};
|
|
12
12
|
|
|
13
13
|
},{"1":1,"46":46,"5":5}],5:[function(require,module,exports){
|
|
14
|
-
"use strict";var formats=require(1),getSideChannel=require(46),has=Object.prototype.hasOwnProperty,isArray=Array.isArray,overflowChannel=getSideChannel(),markOverflow=function markOverflow(e,r){return overflowChannel.set(e,r),e},isOverflow=function isOverflow(e){return overflowChannel.has(e)},getMaxIndex=function getMaxIndex(e){return overflowChannel.get(e)},setMaxIndex=function setMaxIndex(e,r){overflowChannel.set(e,r)},hexTable=function(){for(var e=[],r=0;r<256;++r)e.
|
|
14
|
+
"use strict";var formats=require(1),getSideChannel=require(46),has=Object.prototype.hasOwnProperty,isArray=Array.isArray,overflowChannel=getSideChannel(),markOverflow=function markOverflow(e,r){return overflowChannel.set(e,r),e},isOverflow=function isOverflow(e){return overflowChannel.has(e)},getMaxIndex=function getMaxIndex(e){return overflowChannel.get(e)},setMaxIndex=function setMaxIndex(e,r){overflowChannel.set(e,r)},hexTable=function(){for(var e=[],r=0;r<256;++r)e[e.length]="%"+((r<16?"0":"")+r.toString(16)).toUpperCase();return e}(),compactQueue=function compactQueue(e){for(;e.length>1;){var r=e.pop(),t=r.obj[r.prop];if(isArray(t)){for(var n=[],o=0;o<t.length;++o)void 0!==t[o]&&(n[n.length]=t[o]);r.obj[r.prop]=n}}},arrayToObject=function arrayToObject(e,r){for(var t=r&&r.plainObjects?{__proto__:null}:{},n=0;n<e.length;++n)void 0!==e[n]&&(t[n]=e[n]);return t},merge=function merge(e,r,t){if(!r)return e;if("object"!=typeof r&&"function"!=typeof r){if(isArray(e)){var n=e.length;if(t&&"number"==typeof t.arrayLimit&&n>t.arrayLimit)return markOverflow(arrayToObject(e.concat(r),t),n);e[n]=r}else{if(!e||"object"!=typeof e)return[e,r];if(isOverflow(e)){var o=getMaxIndex(e)+1;e[o]=r,setMaxIndex(e,o)}else{if(t&&t.strictMerge)return[e,r];(t&&(t.plainObjects||t.allowPrototypes)||!has.call(Object.prototype,r))&&(e[r]=!0)}}return e}if(!e||"object"!=typeof e){if(isOverflow(r)){for(var a=Object.keys(r),i=t&&t.plainObjects?{__proto__:null,0:e}:{0:e},c=0;c<a.length;c++)i[parseInt(a[c],10)+1]=r[a[c]];return markOverflow(i,getMaxIndex(r)+1)}var l=[e].concat(r);return t&&"number"==typeof t.arrayLimit&&l.length>t.arrayLimit?markOverflow(arrayToObject(l,t),l.length-1):l}var f=e;return isArray(e)&&!isArray(r)&&(f=arrayToObject(e,t)),isArray(e)&&isArray(r)?(r.forEach(function(r,n){if(has.call(e,n)){var o=e[n];o&&"object"==typeof o&&r&&"object"==typeof r?e[n]=merge(o,r,t):e[e.length]=r}else e[n]=r}),e):Object.keys(r).reduce(function(e,n){var o=r[n];if(has.call(e,n)?e[n]=merge(e[n],o,t):e[n]=o,isOverflow(r)&&!isOverflow(e)&&markOverflow(e,getMaxIndex(r)),isOverflow(e)){var a=parseInt(n,10);String(a)===n&&a>=0&&a>getMaxIndex(e)&&setMaxIndex(e,a)}return e},f)},assign=function assignSingleSource(e,r){return Object.keys(r).reduce(function(e,t){return e[t]=r[t],e},e)},decode=function(e,r,t){var n=e.replace(/\+/g," ");if("iso-8859-1"===t)return n.replace(/%[0-9a-f]{2}/gi,unescape);try{return decodeURIComponent(n)}catch(e){return n}},limit=1024,encode=function encode(e,r,t,n,o){if(0===e.length)return e;var a=e;if("symbol"==typeof e?a=Symbol.prototype.toString.call(e):"string"!=typeof e&&(a=String(e)),"iso-8859-1"===t)return escape(a).replace(/%u[0-9a-f]{4}/gi,function(e){return"%26%23"+parseInt(e.slice(2),16)+"%3B"});for(var i="",c=0;c<a.length;c+=limit){for(var l=a.length>=limit?a.slice(c,c+limit):a,f=[],s=0;s<l.length;++s){var u=l.charCodeAt(s);45===u||46===u||95===u||126===u||u>=48&&u<=57||u>=65&&u<=90||u>=97&&u<=122||o===formats.RFC1738&&(40===u||41===u)?f[f.length]=l.charAt(s):u<128?f[f.length]=hexTable[u]:u<2048?f[f.length]=hexTable[192|u>>6]+hexTable[128|63&u]:u<55296||u>=57344?f[f.length]=hexTable[224|u>>12]+hexTable[128|u>>6&63]+hexTable[128|63&u]:(s+=1,u=65536+((1023&u)<<10|1023&l.charCodeAt(s)),f[f.length]=hexTable[240|u>>18]+hexTable[128|u>>12&63]+hexTable[128|u>>6&63]+hexTable[128|63&u])}i+=f.join("")}return i},compact=function compact(e){for(var r=[{obj:{o:e},prop:"o"}],t=[],n=0;n<r.length;++n)for(var o=r[n],a=o.obj[o.prop],i=Object.keys(a),c=0;c<i.length;++c){var l=i[c],f=a[l];"object"==typeof f&&null!==f&&-1===t.indexOf(f)&&(r[r.length]={obj:a,prop:l},t[t.length]=f)}return compactQueue(r),e},isRegExp=function isRegExp(e){return"[object RegExp]"===Object.prototype.toString.call(e)},isBuffer=function isBuffer(e){return!(!e||"object"!=typeof e||!(e.constructor&&e.constructor.isBuffer&&e.constructor.isBuffer(e)))},combine=function combine(e,r,t,n){if(isOverflow(e)){var o=getMaxIndex(e)+1;return e[o]=r,setMaxIndex(e,o),e}var a=[].concat(e,r);return a.length>t?markOverflow(arrayToObject(a,{plainObjects:n}),a.length-1):a},maybeMap=function maybeMap(e,r){if(isArray(e)){for(var t=[],n=0;n<e.length;n+=1)t[t.length]=r(e[n]);return t}return r(e)};module.exports={/* common-shake removed: arrayToObject:arrayToObject *//* common-shake removed: assign:assign */combine:combine,compact:compact,decode:decode,encode:encode,isBuffer:isBuffer,isOverflow:isOverflow,isRegExp:isRegExp,markOverflow:markOverflow,maybeMap:maybeMap,merge:merge};
|
|
15
15
|
|
|
16
16
|
},{"1":1,"46":46}],46:[function(require,module,exports){
|
|
17
17
|
"use strict";var $TypeError=require(20),inspect=require(42),getSideChannelList=require(43),getSideChannelMap=require(44),getSideChannelWeakMap=require(45),makeChannel=getSideChannelWeakMap||getSideChannelMap||getSideChannelList;module.exports=function getSideChannel(){var e,n={assert:function(e){if(!n.has(e))throw new $TypeError("Side channel does not contain "+inspect(e))},delete:function(n){return!!e&&e.delete(n)},get:function(n){return e&&e.get(n)},has:function(n){return!!e&&e.has(n)},set:function(n,t){e||(e=makeChannel()),e.set(n,t)}};return n};
|
|
@@ -81,20 +81,20 @@
|
|
|
81
81
|
},{}],35:[function(require,module,exports){
|
|
82
82
|
"use strict";module.exports=Math.floor;
|
|
83
83
|
|
|
84
|
-
},{}],
|
|
85
|
-
"use strict";module.exports=Math.
|
|
84
|
+
},{}],34:[function(require,module,exports){
|
|
85
|
+
"use strict";module.exports=Math.abs;
|
|
86
86
|
|
|
87
|
-
},{}],
|
|
88
|
-
"use strict";module.exports=Math.
|
|
87
|
+
},{}],39:[function(require,module,exports){
|
|
88
|
+
"use strict";module.exports=Math.pow;
|
|
89
89
|
|
|
90
90
|
},{}],38:[function(require,module,exports){
|
|
91
91
|
"use strict";module.exports=Math.min;
|
|
92
92
|
|
|
93
|
-
},{}],
|
|
94
|
-
"use strict";module.exports=Math.
|
|
93
|
+
},{}],40:[function(require,module,exports){
|
|
94
|
+
"use strict";module.exports=Math.round;
|
|
95
95
|
|
|
96
|
-
},{}],
|
|
97
|
-
"use strict";module.exports=Math.
|
|
96
|
+
},{}],37:[function(require,module,exports){
|
|
97
|
+
"use strict";module.exports=Math.max;
|
|
98
98
|
|
|
99
99
|
},{}],27:[function(require,module,exports){
|
|
100
100
|
"use strict";module.exports="undefined"!=typeof Reflect&&Reflect.getPrototypeOf||null;
|
|
@@ -102,16 +102,16 @@
|
|
|
102
102
|
},{}],26:[function(require,module,exports){
|
|
103
103
|
"use strict";var $Object=require(22);module.exports=$Object.getPrototypeOf||null;
|
|
104
104
|
|
|
105
|
-
},{"22":22}],
|
|
106
|
-
"use strict";var call=Function.prototype.call,$hasOwn=Object.prototype.hasOwnProperty,bind=require(24);module.exports=bind.call(call,$hasOwn);
|
|
107
|
-
|
|
108
|
-
},{"24":24}],41:[function(require,module,exports){
|
|
105
|
+
},{"22":22}],41:[function(require,module,exports){
|
|
109
106
|
"use strict";var $isNaN=require(36);module.exports=function sign(i){return $isNaN(i)||0===i?i:i<0?-1:1};
|
|
110
107
|
|
|
111
108
|
},{"36":36}],31:[function(require,module,exports){
|
|
112
109
|
"use strict";var origSymbol="undefined"!=typeof Symbol&&Symbol,hasSymbolSham=require(32);module.exports=function hasNativeSymbols(){return"function"==typeof origSymbol&&"function"==typeof Symbol&&"symbol"==typeof origSymbol("foo")&&"symbol"==typeof Symbol("bar")&&hasSymbolSham()};
|
|
113
110
|
|
|
114
|
-
},{"32":32}],
|
|
111
|
+
},{"32":32}],33:[function(require,module,exports){
|
|
112
|
+
"use strict";var call=Function.prototype.call,$hasOwn=Object.prototype.hasOwnProperty,bind=require(24);module.exports=bind.call(call,$hasOwn);
|
|
113
|
+
|
|
114
|
+
},{"24":24}],28:[function(require,module,exports){
|
|
115
115
|
"use strict";var reflectGetProto=require(27),originalGetProto=require(26),getDunderProto=require(13);module.exports=reflectGetProto?function getProto(t){return reflectGetProto(t)}:originalGetProto?function getProto(t){if(!t||"object"!=typeof t&&"function"!=typeof t)throw new TypeError("getProto: not an object");return originalGetProto(t)}:getDunderProto?function getProto(t){return getDunderProto(t)}:null;
|
|
116
116
|
|
|
117
117
|
},{"13":13,"26":26,"27":27}],29:[function(require,module,exports){
|
package/lib/parse.js
CHANGED
|
@@ -25,6 +25,7 @@ var defaults = {
|
|
|
25
25
|
parseArrays: true,
|
|
26
26
|
plainObjects: false,
|
|
27
27
|
strictDepth: false,
|
|
28
|
+
strictMerge: true,
|
|
28
29
|
strictNullHandling: false,
|
|
29
30
|
throwOnLimitExceeded: false
|
|
30
31
|
};
|
|
@@ -63,7 +64,7 @@ var parseValues = function parseQueryStringValues(str, options) {
|
|
|
63
64
|
var cleanStr = options.ignoreQueryPrefix ? str.replace(/^\?/, '') : str;
|
|
64
65
|
cleanStr = cleanStr.replace(/%5B/gi, '[').replace(/%5D/gi, ']');
|
|
65
66
|
|
|
66
|
-
var limit = options.parameterLimit === Infinity ? undefined : options.parameterLimit;
|
|
67
|
+
var limit = options.parameterLimit === Infinity ? void undefined : options.parameterLimit;
|
|
67
68
|
var parts = cleanStr.split(
|
|
68
69
|
options.delimiter,
|
|
69
70
|
options.throwOnLimitExceeded ? limit + 1 : limit
|
|
@@ -130,9 +131,16 @@ var parseValues = function parseQueryStringValues(str, options) {
|
|
|
130
131
|
val = isArray(val) ? [val] : val;
|
|
131
132
|
}
|
|
132
133
|
|
|
134
|
+
if (options.comma && isArray(val) && val.length > options.arrayLimit) {
|
|
135
|
+
if (options.throwOnLimitExceeded) {
|
|
136
|
+
throw new RangeError('Array limit exceeded. Only ' + options.arrayLimit + ' element' + (options.arrayLimit === 1 ? '' : 's') + ' allowed in an array.');
|
|
137
|
+
}
|
|
138
|
+
val = utils.combine([], val, options.arrayLimit, options.plainObjects);
|
|
139
|
+
}
|
|
140
|
+
|
|
133
141
|
if (key !== null) {
|
|
134
142
|
var existing = has.call(obj, key);
|
|
135
|
-
if (existing && options.duplicates === 'combine') {
|
|
143
|
+
if (existing && (options.duplicates === 'combine' || part.indexOf('[]=') > -1)) {
|
|
136
144
|
obj[key] = utils.combine(
|
|
137
145
|
obj[key],
|
|
138
146
|
val,
|
|
@@ -180,17 +188,21 @@ var parseObject = function (chain, val, options, valuesParsed) {
|
|
|
180
188
|
var cleanRoot = root.charAt(0) === '[' && root.charAt(root.length - 1) === ']' ? root.slice(1, -1) : root;
|
|
181
189
|
var decodedRoot = options.decodeDotInKeys ? cleanRoot.replace(/%2E/g, '.') : cleanRoot;
|
|
182
190
|
var index = parseInt(decodedRoot, 10);
|
|
183
|
-
|
|
184
|
-
obj = { 0: leaf };
|
|
185
|
-
} else if (
|
|
186
|
-
!isNaN(index)
|
|
191
|
+
var isValidArrayIndex = !isNaN(index)
|
|
187
192
|
&& root !== decodedRoot
|
|
188
193
|
&& String(index) === decodedRoot
|
|
189
194
|
&& index >= 0
|
|
190
|
-
&&
|
|
191
|
-
) {
|
|
195
|
+
&& options.parseArrays;
|
|
196
|
+
if (!options.parseArrays && decodedRoot === '') {
|
|
197
|
+
obj = { 0: leaf };
|
|
198
|
+
} else if (isValidArrayIndex && index < options.arrayLimit) {
|
|
192
199
|
obj = [];
|
|
193
200
|
obj[index] = leaf;
|
|
201
|
+
} else if (isValidArrayIndex && options.throwOnLimitExceeded) {
|
|
202
|
+
throw new RangeError('Array limit exceeded. Only ' + options.arrayLimit + ' element' + (options.arrayLimit === 1 ? '' : 's') + ' allowed in an array.');
|
|
203
|
+
} else if (isValidArrayIndex) {
|
|
204
|
+
obj[index] = leaf;
|
|
205
|
+
utils.markOverflow(obj, index);
|
|
194
206
|
} else if (decodedRoot !== '__proto__') {
|
|
195
207
|
obj[decodedRoot] = leaf;
|
|
196
208
|
}
|
|
@@ -230,7 +242,7 @@ var splitKeyIntoSegments = function splitKeyIntoSegments(givenKey, options) {
|
|
|
230
242
|
}
|
|
231
243
|
}
|
|
232
244
|
|
|
233
|
-
keys.
|
|
245
|
+
keys[keys.length] = parent;
|
|
234
246
|
}
|
|
235
247
|
|
|
236
248
|
var i = 0;
|
|
@@ -244,7 +256,7 @@ var splitKeyIntoSegments = function splitKeyIntoSegments(givenKey, options) {
|
|
|
244
256
|
}
|
|
245
257
|
}
|
|
246
258
|
|
|
247
|
-
keys.
|
|
259
|
+
keys[keys.length] = segment[1];
|
|
248
260
|
}
|
|
249
261
|
|
|
250
262
|
if (segment) {
|
|
@@ -252,7 +264,7 @@ var splitKeyIntoSegments = function splitKeyIntoSegments(givenKey, options) {
|
|
|
252
264
|
throw new RangeError('Input depth exceeded depth option of ' + options.depth + ' and strictDepth is true');
|
|
253
265
|
}
|
|
254
266
|
|
|
255
|
-
keys.
|
|
267
|
+
keys[keys.length] = '[' + key.slice(segment.index) + ']';
|
|
256
268
|
}
|
|
257
269
|
|
|
258
270
|
return keys;
|
|
@@ -328,6 +340,7 @@ var normalizeParseOptions = function normalizeParseOptions(opts) {
|
|
|
328
340
|
parseArrays: opts.parseArrays !== false,
|
|
329
341
|
plainObjects: typeof opts.plainObjects === 'boolean' ? opts.plainObjects : defaults.plainObjects,
|
|
330
342
|
strictDepth: typeof opts.strictDepth === 'boolean' ? !!opts.strictDepth : defaults.strictDepth,
|
|
343
|
+
strictMerge: typeof opts.strictMerge === 'boolean' ? !!opts.strictMerge : defaults.strictMerge,
|
|
331
344
|
strictNullHandling: typeof opts.strictNullHandling === 'boolean' ? opts.strictNullHandling : defaults.strictNullHandling,
|
|
332
345
|
throwOnLimitExceeded: typeof opts.throwOnLimitExceeded === 'boolean' ? opts.throwOnLimitExceeded : false
|
|
333
346
|
};
|
package/lib/utils.js
CHANGED
|
@@ -30,7 +30,7 @@ var setMaxIndex = function setMaxIndex(obj, maxIndex) {
|
|
|
30
30
|
var hexTable = (function () {
|
|
31
31
|
var array = [];
|
|
32
32
|
for (var i = 0; i < 256; ++i) {
|
|
33
|
-
array.
|
|
33
|
+
array[array.length] = '%' + ((i < 16 ? '0' : '') + i.toString(16)).toUpperCase();
|
|
34
34
|
}
|
|
35
35
|
|
|
36
36
|
return array;
|
|
@@ -46,7 +46,7 @@ var compactQueue = function compactQueue(queue) {
|
|
|
46
46
|
|
|
47
47
|
for (var j = 0; j < obj.length; ++j) {
|
|
48
48
|
if (typeof obj[j] !== 'undefined') {
|
|
49
|
-
compacted.
|
|
49
|
+
compacted[compacted.length] = obj[j];
|
|
50
50
|
}
|
|
51
51
|
}
|
|
52
52
|
|
|
@@ -74,13 +74,19 @@ var merge = function merge(target, source, options) {
|
|
|
74
74
|
|
|
75
75
|
if (typeof source !== 'object' && typeof source !== 'function') {
|
|
76
76
|
if (isArray(target)) {
|
|
77
|
-
target.
|
|
77
|
+
var nextIndex = target.length;
|
|
78
|
+
if (options && typeof options.arrayLimit === 'number' && nextIndex > options.arrayLimit) {
|
|
79
|
+
return markOverflow(arrayToObject(target.concat(source), options), nextIndex);
|
|
80
|
+
}
|
|
81
|
+
target[nextIndex] = source;
|
|
78
82
|
} else if (target && typeof target === 'object') {
|
|
79
83
|
if (isOverflow(target)) {
|
|
80
84
|
// Add at next numeric index for overflow objects
|
|
81
85
|
var newIndex = getMaxIndex(target) + 1;
|
|
82
86
|
target[newIndex] = source;
|
|
83
87
|
setMaxIndex(target, newIndex);
|
|
88
|
+
} else if (options && options.strictMerge) {
|
|
89
|
+
return [target, source];
|
|
84
90
|
} else if (
|
|
85
91
|
(options && (options.plainObjects || options.allowPrototypes))
|
|
86
92
|
|| !has.call(Object.prototype, source)
|
|
@@ -107,7 +113,11 @@ var merge = function merge(target, source, options) {
|
|
|
107
113
|
}
|
|
108
114
|
return markOverflow(result, getMaxIndex(source) + 1);
|
|
109
115
|
}
|
|
110
|
-
|
|
116
|
+
var combined = [target].concat(source);
|
|
117
|
+
if (options && typeof options.arrayLimit === 'number' && combined.length > options.arrayLimit) {
|
|
118
|
+
return markOverflow(arrayToObject(combined, options), combined.length - 1);
|
|
119
|
+
}
|
|
120
|
+
return combined;
|
|
111
121
|
}
|
|
112
122
|
|
|
113
123
|
var mergeTarget = target;
|
|
@@ -122,7 +132,7 @@ var merge = function merge(target, source, options) {
|
|
|
122
132
|
if (targetItem && typeof targetItem === 'object' && item && typeof item === 'object') {
|
|
123
133
|
target[i] = merge(targetItem, item, options);
|
|
124
134
|
} else {
|
|
125
|
-
target.
|
|
135
|
+
target[target.length] = item;
|
|
126
136
|
}
|
|
127
137
|
} else {
|
|
128
138
|
target[i] = item;
|
|
@@ -139,6 +149,17 @@ var merge = function merge(target, source, options) {
|
|
|
139
149
|
} else {
|
|
140
150
|
acc[key] = value;
|
|
141
151
|
}
|
|
152
|
+
|
|
153
|
+
if (isOverflow(source) && !isOverflow(acc)) {
|
|
154
|
+
markOverflow(acc, getMaxIndex(source));
|
|
155
|
+
}
|
|
156
|
+
if (isOverflow(acc)) {
|
|
157
|
+
var keyNum = parseInt(key, 10);
|
|
158
|
+
if (String(keyNum) === key && keyNum >= 0 && keyNum > getMaxIndex(acc)) {
|
|
159
|
+
setMaxIndex(acc, keyNum);
|
|
160
|
+
}
|
|
161
|
+
}
|
|
162
|
+
|
|
142
163
|
return acc;
|
|
143
164
|
}, mergeTarget);
|
|
144
165
|
};
|
|
@@ -255,8 +276,8 @@ var compact = function compact(value) {
|
|
|
255
276
|
var key = keys[j];
|
|
256
277
|
var val = obj[key];
|
|
257
278
|
if (typeof val === 'object' && val !== null && refs.indexOf(val) === -1) {
|
|
258
|
-
queue.
|
|
259
|
-
refs.
|
|
279
|
+
queue[queue.length] = { obj: obj, prop: key };
|
|
280
|
+
refs[refs.length] = val;
|
|
260
281
|
}
|
|
261
282
|
}
|
|
262
283
|
}
|
|
@@ -298,7 +319,7 @@ var maybeMap = function maybeMap(val, fn) {
|
|
|
298
319
|
if (isArray(val)) {
|
|
299
320
|
var mapped = [];
|
|
300
321
|
for (var i = 0; i < val.length; i += 1) {
|
|
301
|
-
mapped.
|
|
322
|
+
mapped[mapped.length] = fn(val[i]);
|
|
302
323
|
}
|
|
303
324
|
return mapped;
|
|
304
325
|
}
|
|
@@ -315,6 +336,7 @@ module.exports = {
|
|
|
315
336
|
isBuffer: isBuffer,
|
|
316
337
|
isOverflow: isOverflow,
|
|
317
338
|
isRegExp: isRegExp,
|
|
339
|
+
markOverflow: markOverflow,
|
|
318
340
|
maybeMap: maybeMap,
|
|
319
341
|
merge: merge
|
|
320
342
|
};
|
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
|
+
"version": "6.15.0",
|
|
6
6
|
"repository": {
|
|
7
7
|
"type": "git",
|
|
8
8
|
"url": "https://github.com/ljharb/qs.git"
|
package/test/parse.js
CHANGED
|
@@ -261,11 +261,11 @@ test('parse()', function (t) {
|
|
|
261
261
|
});
|
|
262
262
|
|
|
263
263
|
t.test('limits specific array indices to arrayLimit', function (st) {
|
|
264
|
-
st.deepEqual(qs.parse('a[
|
|
265
|
-
st.deepEqual(qs.parse('a[
|
|
264
|
+
st.deepEqual(qs.parse('a[19]=a', { arrayLimit: 20 }), { a: ['a'] });
|
|
265
|
+
st.deepEqual(qs.parse('a[20]=a', { arrayLimit: 20 }), { a: { 20: 'a' } });
|
|
266
266
|
|
|
267
|
-
st.deepEqual(qs.parse('a[
|
|
268
|
-
st.deepEqual(qs.parse('a[
|
|
267
|
+
st.deepEqual(qs.parse('a[19]=a'), { a: ['a'] });
|
|
268
|
+
st.deepEqual(qs.parse('a[20]=a'), { a: { 20: 'a' } });
|
|
269
269
|
st.end();
|
|
270
270
|
});
|
|
271
271
|
|
|
@@ -483,7 +483,7 @@ test('parse()', function (t) {
|
|
|
483
483
|
|
|
484
484
|
t.test('allows overriding array limit', function (st) {
|
|
485
485
|
st.deepEqual(qs.parse('a[0]=b', { arrayLimit: -1 }), { a: { 0: 'b' } });
|
|
486
|
-
st.deepEqual(qs.parse('a[0]=b', { arrayLimit: 0 }), { a:
|
|
486
|
+
st.deepEqual(qs.parse('a[0]=b', { arrayLimit: 0 }), { a: { 0: 'b' } });
|
|
487
487
|
|
|
488
488
|
st.deepEqual(qs.parse('a[-1]=b', { arrayLimit: -1 }), { a: { '-1': 'b' } });
|
|
489
489
|
st.deepEqual(qs.parse('a[-1]=b', { arrayLimit: 0 }), { a: { '-1': 'b' } });
|
|
@@ -784,25 +784,25 @@ test('parse()', function (t) {
|
|
|
784
784
|
|
|
785
785
|
t.test('add keys to objects', function (st) {
|
|
786
786
|
st.deepEqual(
|
|
787
|
-
qs.parse('a[b]=c&a=d'),
|
|
787
|
+
qs.parse('a[b]=c&a=d', { strictMerge: false }),
|
|
788
788
|
{ a: { b: 'c', d: true } },
|
|
789
789
|
'can add keys to objects'
|
|
790
790
|
);
|
|
791
791
|
|
|
792
792
|
st.deepEqual(
|
|
793
|
-
qs.parse('a[b]=c&a=toString'),
|
|
793
|
+
qs.parse('a[b]=c&a=toString', { strictMerge: false }),
|
|
794
794
|
{ a: { b: 'c' } },
|
|
795
795
|
'can not overwrite prototype'
|
|
796
796
|
);
|
|
797
797
|
|
|
798
798
|
st.deepEqual(
|
|
799
|
-
qs.parse('a[b]=c&a=toString', { allowPrototypes: true }),
|
|
799
|
+
qs.parse('a[b]=c&a=toString', { strictMerge: false, allowPrototypes: true }),
|
|
800
800
|
{ a: { b: 'c', toString: true } },
|
|
801
801
|
'can overwrite prototype with allowPrototypes true'
|
|
802
802
|
);
|
|
803
803
|
|
|
804
804
|
st.deepEqual(
|
|
805
|
-
qs.parse('a[b]=c&a=toString', { plainObjects: true }),
|
|
805
|
+
qs.parse('a[b]=c&a=toString', { strictMerge: false, plainObjects: true }),
|
|
806
806
|
{ __proto__: null, a: { __proto__: null, b: 'c', toString: true } },
|
|
807
807
|
'can overwrite prototype with plainObjects true'
|
|
808
808
|
);
|
|
@@ -810,6 +810,34 @@ test('parse()', function (t) {
|
|
|
810
810
|
st.end();
|
|
811
811
|
});
|
|
812
812
|
|
|
813
|
+
t.test('strictMerge wraps object and primitive into an array', function (st) {
|
|
814
|
+
st.deepEqual(
|
|
815
|
+
qs.parse('a[b]=c&a=d'),
|
|
816
|
+
{ a: [{ b: 'c' }, 'd'] },
|
|
817
|
+
'object then primitive produces array'
|
|
818
|
+
);
|
|
819
|
+
|
|
820
|
+
st.deepEqual(
|
|
821
|
+
qs.parse('a=d&a[b]=c'),
|
|
822
|
+
{ a: ['d', { b: 'c' }] },
|
|
823
|
+
'primitive then object produces array'
|
|
824
|
+
);
|
|
825
|
+
|
|
826
|
+
st.deepEqual(
|
|
827
|
+
qs.parse('a[b]=c&a=toString'),
|
|
828
|
+
{ a: [{ b: 'c' }, 'toString'] },
|
|
829
|
+
'prototype-colliding value is preserved in array'
|
|
830
|
+
);
|
|
831
|
+
|
|
832
|
+
st.deepEqual(
|
|
833
|
+
qs.parse('a[b]=c&a=toString', { plainObjects: true }),
|
|
834
|
+
{ __proto__: null, a: [{ __proto__: null, b: 'c' }, 'toString'] },
|
|
835
|
+
'plainObjects preserved in array wrapping'
|
|
836
|
+
);
|
|
837
|
+
|
|
838
|
+
st.end();
|
|
839
|
+
});
|
|
840
|
+
|
|
813
841
|
t.test('dunder proto is ignored', function (st) {
|
|
814
842
|
var payload = 'categories[__proto__]=login&categories[__proto__]&categories[length]=42';
|
|
815
843
|
var result = qs.parse(payload, { allowPrototypes: true });
|
|
@@ -1118,6 +1146,7 @@ test('parse()', function (t) {
|
|
|
1118
1146
|
});
|
|
1119
1147
|
|
|
1120
1148
|
st.test('throws error when array limit exceeded', function (sst) {
|
|
1149
|
+
// 4 elements exceeds limit of 3
|
|
1121
1150
|
sst['throws'](
|
|
1122
1151
|
function () {
|
|
1123
1152
|
qs.parse('a[]=1&a[]=2&a[]=3&a[]=4', { arrayLimit: 3, throwOnLimitExceeded: true });
|
|
@@ -1128,6 +1157,14 @@ test('parse()', function (t) {
|
|
|
1128
1157
|
sst.end();
|
|
1129
1158
|
});
|
|
1130
1159
|
|
|
1160
|
+
st.test('does not throw when at limit', function (sst) {
|
|
1161
|
+
// 3 elements = limit of 3, should not throw
|
|
1162
|
+
var result = qs.parse('a[]=1&a[]=2&a[]=3', { arrayLimit: 3, throwOnLimitExceeded: true });
|
|
1163
|
+
sst.ok(Array.isArray(result.a), 'result is an array');
|
|
1164
|
+
sst.deepEqual(result.a, ['1', '2', '3'], 'all values present');
|
|
1165
|
+
sst.end();
|
|
1166
|
+
});
|
|
1167
|
+
|
|
1131
1168
|
st.test('converts array to object if length is greater than limit', function (sst) {
|
|
1132
1169
|
var result = qs.parse('a[1]=1&a[2]=2&a[3]=3&a[4]=4&a[5]=5&a[6]=6', { arrayLimit: 5 });
|
|
1133
1170
|
|
|
@@ -1135,6 +1172,40 @@ test('parse()', function (t) {
|
|
|
1135
1172
|
sst.end();
|
|
1136
1173
|
});
|
|
1137
1174
|
|
|
1175
|
+
st.test('throws error when indexed notation exceeds arrayLimit with throwOnLimitExceeded', function (sst) {
|
|
1176
|
+
sst['throws'](
|
|
1177
|
+
function () {
|
|
1178
|
+
qs.parse('a[1001]=b', { arrayLimit: 1000, throwOnLimitExceeded: true });
|
|
1179
|
+
},
|
|
1180
|
+
new RangeError('Array limit exceeded. Only 1000 elements allowed in an array.'),
|
|
1181
|
+
'throws error for a single index exceeding arrayLimit'
|
|
1182
|
+
);
|
|
1183
|
+
|
|
1184
|
+
sst['throws'](
|
|
1185
|
+
function () {
|
|
1186
|
+
qs.parse('a[0]=1&a[1]=2&a[2]=3&a[10]=4', { arrayLimit: 6, throwOnLimitExceeded: true, allowSparse: true });
|
|
1187
|
+
},
|
|
1188
|
+
new RangeError('Array limit exceeded. Only 6 elements allowed in an array.'),
|
|
1189
|
+
'throws error when a sparse index exceeds arrayLimit'
|
|
1190
|
+
);
|
|
1191
|
+
|
|
1192
|
+
sst.end();
|
|
1193
|
+
});
|
|
1194
|
+
|
|
1195
|
+
st.test('does not throw for indexed notation within arrayLimit with throwOnLimitExceeded', function (sst) {
|
|
1196
|
+
var result = qs.parse('a[4]=b', { arrayLimit: 5, throwOnLimitExceeded: true, allowSparse: true });
|
|
1197
|
+
sst.ok(Array.isArray(result.a), 'result is an array');
|
|
1198
|
+
sst.equal(result.a.length, 5, 'array has correct length');
|
|
1199
|
+
sst.equal(result.a[4], 'b', 'value at index 4 is correct');
|
|
1200
|
+
sst.end();
|
|
1201
|
+
});
|
|
1202
|
+
|
|
1203
|
+
st.test('silently converts to object for indexed notation exceeding arrayLimit without throwOnLimitExceeded', function (sst) {
|
|
1204
|
+
var result = qs.parse('a[1001]=b', { arrayLimit: 1000 });
|
|
1205
|
+
sst.deepEqual(result, { a: { 1001: 'b' } }, 'converts to object without throwing');
|
|
1206
|
+
sst.end();
|
|
1207
|
+
});
|
|
1208
|
+
|
|
1138
1209
|
st.end();
|
|
1139
1210
|
});
|
|
1140
1211
|
|
|
@@ -1186,6 +1257,34 @@ test('`duplicates` option', function (t) {
|
|
|
1186
1257
|
'duplicates: last'
|
|
1187
1258
|
);
|
|
1188
1259
|
|
|
1260
|
+
t.test('bracket notation always combines regardless of duplicates', function (st) {
|
|
1261
|
+
st.deepEqual(
|
|
1262
|
+
qs.parse('a=1&a=2&b[]=1&b[]=2', { duplicates: 'last' }),
|
|
1263
|
+
{ a: '2', b: ['1', '2'] },
|
|
1264
|
+
'duplicates last: unbracketed takes last, bracketed combines'
|
|
1265
|
+
);
|
|
1266
|
+
|
|
1267
|
+
st.deepEqual(
|
|
1268
|
+
qs.parse('b[]=1&b[]=2', { duplicates: 'last' }),
|
|
1269
|
+
{ b: ['1', '2'] },
|
|
1270
|
+
'duplicates last: bracketed always combines'
|
|
1271
|
+
);
|
|
1272
|
+
|
|
1273
|
+
st.deepEqual(
|
|
1274
|
+
qs.parse('b[]=1&b[]=2', { duplicates: 'first' }),
|
|
1275
|
+
{ b: ['1', '2'] },
|
|
1276
|
+
'duplicates first: bracketed always combines'
|
|
1277
|
+
);
|
|
1278
|
+
|
|
1279
|
+
st.deepEqual(
|
|
1280
|
+
qs.parse('a=1&a=2&b[]=1&b[]=2', { duplicates: 'first' }),
|
|
1281
|
+
{ a: '1', b: ['1', '2'] },
|
|
1282
|
+
'duplicates first: unbracketed takes first, bracketed combines'
|
|
1283
|
+
);
|
|
1284
|
+
|
|
1285
|
+
st.end();
|
|
1286
|
+
});
|
|
1287
|
+
|
|
1189
1288
|
t.end();
|
|
1190
1289
|
});
|
|
1191
1290
|
|
|
@@ -1304,24 +1403,72 @@ test('DOS', function (t) {
|
|
|
1304
1403
|
});
|
|
1305
1404
|
|
|
1306
1405
|
test('arrayLimit boundary conditions', function (t) {
|
|
1406
|
+
// arrayLimit is the max number of elements allowed in an array
|
|
1307
1407
|
t.test('exactly at the limit stays as array', function (st) {
|
|
1408
|
+
// 3 elements = limit of 3
|
|
1308
1409
|
var result = qs.parse('a[]=1&a[]=2&a[]=3', { arrayLimit: 3 });
|
|
1309
|
-
st.ok(Array.isArray(result.a), 'result is an array when
|
|
1410
|
+
st.ok(Array.isArray(result.a), 'result is an array when count equals limit');
|
|
1310
1411
|
st.deepEqual(result.a, ['1', '2', '3'], 'all values present');
|
|
1311
1412
|
st.end();
|
|
1312
1413
|
});
|
|
1313
1414
|
|
|
1314
1415
|
t.test('one over the limit converts to object', function (st) {
|
|
1416
|
+
// 4 elements exceeds limit of 3
|
|
1315
1417
|
var result = qs.parse('a[]=1&a[]=2&a[]=3&a[]=4', { arrayLimit: 3 });
|
|
1316
1418
|
st.notOk(Array.isArray(result.a), 'result is not an array when over limit');
|
|
1317
1419
|
st.deepEqual(result.a, { 0: '1', 1: '2', 2: '3', 3: '4' }, 'all values preserved as object');
|
|
1318
1420
|
st.end();
|
|
1319
1421
|
});
|
|
1320
1422
|
|
|
1321
|
-
t.test('arrayLimit 1 with
|
|
1423
|
+
t.test('arrayLimit 1 with one value', function (st) {
|
|
1424
|
+
// 1 element = limit of 1
|
|
1425
|
+
var result = qs.parse('a[]=1', { arrayLimit: 1 });
|
|
1426
|
+
st.ok(Array.isArray(result.a), 'result is an array when count equals limit');
|
|
1427
|
+
st.deepEqual(result.a, ['1'], 'value preserved as array');
|
|
1428
|
+
st.end();
|
|
1429
|
+
});
|
|
1430
|
+
|
|
1431
|
+
t.test('arrayLimit 1 with two values converts to object', function (st) {
|
|
1432
|
+
// 2 elements exceeds limit of 1
|
|
1322
1433
|
var result = qs.parse('a[]=1&a[]=2', { arrayLimit: 1 });
|
|
1323
1434
|
st.notOk(Array.isArray(result.a), 'result is not an array');
|
|
1324
|
-
st.deepEqual(result.a, { 0: '1', 1: '2' }, '
|
|
1435
|
+
st.deepEqual(result.a, { 0: '1', 1: '2' }, 'all values preserved as object');
|
|
1436
|
+
st.end();
|
|
1437
|
+
});
|
|
1438
|
+
|
|
1439
|
+
t.end();
|
|
1440
|
+
});
|
|
1441
|
+
|
|
1442
|
+
test('comma + arrayLimit', function (t) {
|
|
1443
|
+
t.test('comma-separated values within arrayLimit stay as array', function (st) {
|
|
1444
|
+
var result = qs.parse('a=1,2,3', { comma: true, arrayLimit: 5 });
|
|
1445
|
+
st.ok(Array.isArray(result.a), 'result is an array');
|
|
1446
|
+
st.deepEqual(result.a, ['1', '2', '3'], 'all values present');
|
|
1447
|
+
st.end();
|
|
1448
|
+
});
|
|
1449
|
+
|
|
1450
|
+
t.test('comma-separated values exceeding arrayLimit convert to object', function (st) {
|
|
1451
|
+
var result = qs.parse('a=1,2,3,4', { comma: true, arrayLimit: 3 });
|
|
1452
|
+
st.notOk(Array.isArray(result.a), 'result is not an array when over limit');
|
|
1453
|
+
st.deepEqual(result.a, { 0: '1', 1: '2', 2: '3', 3: '4' }, 'all values preserved as object');
|
|
1454
|
+
st.end();
|
|
1455
|
+
});
|
|
1456
|
+
|
|
1457
|
+
t.test('comma-separated values exceeding arrayLimit with throwOnLimitExceeded throws', function (st) {
|
|
1458
|
+
st['throws'](
|
|
1459
|
+
function () {
|
|
1460
|
+
qs.parse('a=1,2,3,4', { comma: true, arrayLimit: 3, throwOnLimitExceeded: true });
|
|
1461
|
+
},
|
|
1462
|
+
new RangeError('Array limit exceeded. Only 3 elements allowed in an array.'),
|
|
1463
|
+
'throws error when comma-split exceeds array limit'
|
|
1464
|
+
);
|
|
1465
|
+
st.end();
|
|
1466
|
+
});
|
|
1467
|
+
|
|
1468
|
+
t.test('comma-separated values at exactly arrayLimit stay as array', function (st) {
|
|
1469
|
+
var result = qs.parse('a=1,2,3', { comma: true, arrayLimit: 3 });
|
|
1470
|
+
st.ok(Array.isArray(result.a), 'result is an array when exactly at limit');
|
|
1471
|
+
st.deepEqual(result.a, ['1', '2', '3'], 'all values present');
|
|
1325
1472
|
st.end();
|
|
1326
1473
|
});
|
|
1327
1474
|
|
|
@@ -1384,13 +1531,38 @@ test('mixed array and object notation', function (t) {
|
|
|
1384
1531
|
});
|
|
1385
1532
|
|
|
1386
1533
|
t.test('multiple plain values exceeding limit', function (st) {
|
|
1534
|
+
// 3 elements (indices 0-2), max index 2 > limit 1
|
|
1387
1535
|
st.deepEqual(
|
|
1388
|
-
qs.parse('a=b&a=c&a=d', { arrayLimit:
|
|
1536
|
+
qs.parse('a=b&a=c&a=d', { arrayLimit: 1 }),
|
|
1389
1537
|
{ a: { 0: 'b', 1: 'c', 2: 'd' } },
|
|
1390
1538
|
'duplicate plain keys convert to object when exceeding limit'
|
|
1391
1539
|
);
|
|
1392
1540
|
st.end();
|
|
1393
1541
|
});
|
|
1394
1542
|
|
|
1543
|
+
t.test('mixed notation produces consistent results when arrayLimit is exceeded', function (st) {
|
|
1544
|
+
var expected = { a: { 0: 'b', 1: 'c', 2: 'd' } };
|
|
1545
|
+
|
|
1546
|
+
st.deepEqual(
|
|
1547
|
+
qs.parse('a[]=b&a[1]=c&a=d', { arrayLimit: -1 }),
|
|
1548
|
+
expected,
|
|
1549
|
+
'arrayLimit -1'
|
|
1550
|
+
);
|
|
1551
|
+
|
|
1552
|
+
st.deepEqual(
|
|
1553
|
+
qs.parse('a[]=b&a[1]=c&a=d', { arrayLimit: 0 }),
|
|
1554
|
+
expected,
|
|
1555
|
+
'arrayLimit 0'
|
|
1556
|
+
);
|
|
1557
|
+
|
|
1558
|
+
st.deepEqual(
|
|
1559
|
+
qs.parse('a[]=b&a[1]=c&a=d', { arrayLimit: 1 }),
|
|
1560
|
+
expected,
|
|
1561
|
+
'arrayLimit 1'
|
|
1562
|
+
);
|
|
1563
|
+
|
|
1564
|
+
st.end();
|
|
1565
|
+
});
|
|
1566
|
+
|
|
1395
1567
|
t.end();
|
|
1396
1568
|
});
|
package/test/utils.js
CHANGED
|
@@ -69,12 +69,14 @@ test('merge()', function (t) {
|
|
|
69
69
|
);
|
|
70
70
|
|
|
71
71
|
t.test('with overflow objects (from arrayLimit)', function (st) {
|
|
72
|
+
// arrayLimit is max index, so with limit 0, max index 0 is allowed (1 element)
|
|
73
|
+
// To create overflow, need 2+ elements with limit 0, or 3+ with limit 1, etc.
|
|
72
74
|
st.test('merges primitive into overflow object at next index', function (s2t) {
|
|
73
|
-
// Create an overflow object via combine
|
|
74
|
-
var overflow = utils.combine(['a'
|
|
75
|
+
// Create an overflow object via combine: 3 elements (indices 0-2) with limit 0
|
|
76
|
+
var overflow = utils.combine(['a', 'b'], 'c', 0, false);
|
|
75
77
|
s2t.ok(utils.isOverflow(overflow), 'overflow object is marked');
|
|
76
|
-
var merged = utils.merge(overflow, '
|
|
77
|
-
s2t.deepEqual(merged, { 0: 'a', 1: 'b', 2: 'c' }, 'adds primitive at next numeric index');
|
|
78
|
+
var merged = utils.merge(overflow, 'd');
|
|
79
|
+
s2t.deepEqual(merged, { 0: 'a', 1: 'b', 2: 'c', 3: 'd' }, 'adds primitive at next numeric index');
|
|
78
80
|
s2t.end();
|
|
79
81
|
});
|
|
80
82
|
|
|
@@ -93,22 +95,29 @@ test('merge()', function (t) {
|
|
|
93
95
|
s2t.end();
|
|
94
96
|
});
|
|
95
97
|
|
|
98
|
+
st.test('with strictMerge, wraps object and primitive in array', function (s2t) {
|
|
99
|
+
var obj = { foo: 'bar' };
|
|
100
|
+
var merged = utils.merge(obj, 'baz', { strictMerge: true });
|
|
101
|
+
s2t.deepEqual(merged, [{ foo: 'bar' }, 'baz'], 'wraps in array with strictMerge');
|
|
102
|
+
s2t.end();
|
|
103
|
+
});
|
|
104
|
+
|
|
96
105
|
st.test('merges overflow object into primitive', function (s2t) {
|
|
97
|
-
// Create an overflow object via combine
|
|
98
|
-
var overflow = utils.combine([], 'b', 0, false);
|
|
106
|
+
// Create an overflow object via combine: 2 elements (indices 0-1) with limit 0
|
|
107
|
+
var overflow = utils.combine(['a'], 'b', 0, false);
|
|
99
108
|
s2t.ok(utils.isOverflow(overflow), 'overflow object is marked');
|
|
100
|
-
var merged = utils.merge('
|
|
109
|
+
var merged = utils.merge('c', overflow);
|
|
101
110
|
s2t.ok(utils.isOverflow(merged), 'result is also marked as overflow');
|
|
102
|
-
s2t.deepEqual(merged, { 0: '
|
|
111
|
+
s2t.deepEqual(merged, { 0: 'c', 1: 'a', 2: 'b' }, 'creates object with primitive at 0, source values shifted');
|
|
103
112
|
s2t.end();
|
|
104
113
|
});
|
|
105
114
|
|
|
106
115
|
st.test('merges overflow object with multiple values into primitive', function (s2t) {
|
|
107
|
-
// Create an overflow object via combine
|
|
108
|
-
var overflow = utils.combine(['b'
|
|
116
|
+
// Create an overflow object via combine: 3 elements (indices 0-2) with limit 0
|
|
117
|
+
var overflow = utils.combine(['b', 'c'], 'd', 0, false);
|
|
109
118
|
s2t.ok(utils.isOverflow(overflow), 'overflow object is marked');
|
|
110
119
|
var merged = utils.merge('a', overflow);
|
|
111
|
-
s2t.deepEqual(merged, { 0: 'a', 1: 'b', 2: 'c' }, 'shifts all source indices by 1');
|
|
120
|
+
s2t.deepEqual(merged, { 0: 'a', 1: 'b', 2: 'c', 3: 'd' }, 'shifts all source indices by 1');
|
|
112
121
|
s2t.end();
|
|
113
122
|
});
|
|
114
123
|
|
|
@@ -196,7 +205,7 @@ test('combine()', function (t) {
|
|
|
196
205
|
|
|
197
206
|
st.test('exactly at the limit stays as array', function (s2t) {
|
|
198
207
|
var combined = utils.combine(['a', 'b'], 'c', 3, false);
|
|
199
|
-
s2t.deepEqual(combined, ['a', 'b', 'c'], 'stays as array when
|
|
208
|
+
s2t.deepEqual(combined, ['a', 'b', 'c'], 'stays as array when count equals limit');
|
|
200
209
|
s2t.ok(Array.isArray(combined), 'result is an array');
|
|
201
210
|
s2t.end();
|
|
202
211
|
});
|
|
@@ -208,16 +217,30 @@ test('combine()', function (t) {
|
|
|
208
217
|
s2t.end();
|
|
209
218
|
});
|
|
210
219
|
|
|
211
|
-
st.test('with arrayLimit
|
|
220
|
+
st.test('with arrayLimit 1', function (s2t) {
|
|
221
|
+
var combined = utils.combine([], 'a', 1, false);
|
|
222
|
+
s2t.deepEqual(combined, ['a'], 'stays as array when count equals limit');
|
|
223
|
+
s2t.ok(Array.isArray(combined), 'result is an array');
|
|
224
|
+
s2t.end();
|
|
225
|
+
});
|
|
226
|
+
|
|
227
|
+
st.test('with arrayLimit 0 converts single element to object', function (s2t) {
|
|
212
228
|
var combined = utils.combine([], 'a', 0, false);
|
|
213
|
-
s2t.deepEqual(combined, { 0: 'a' }, 'converts
|
|
229
|
+
s2t.deepEqual(combined, { 0: 'a' }, 'converts to object when count exceeds limit');
|
|
230
|
+
s2t.notOk(Array.isArray(combined), 'result is not an array');
|
|
231
|
+
s2t.end();
|
|
232
|
+
});
|
|
233
|
+
|
|
234
|
+
st.test('with arrayLimit 0 and two elements converts to object', function (s2t) {
|
|
235
|
+
var combined = utils.combine(['a'], 'b', 0, false);
|
|
236
|
+
s2t.deepEqual(combined, { 0: 'a', 1: 'b' }, 'converts to object when count exceeds limit');
|
|
214
237
|
s2t.notOk(Array.isArray(combined), 'result is not an array');
|
|
215
238
|
s2t.end();
|
|
216
239
|
});
|
|
217
240
|
|
|
218
241
|
st.test('with plainObjects option', function (s2t) {
|
|
219
|
-
var combined = utils.combine(['a'
|
|
220
|
-
var expected = { __proto__: null, 0: 'a', 1: 'b' };
|
|
242
|
+
var combined = utils.combine(['a', 'b'], 'c', 1, true);
|
|
243
|
+
var expected = { __proto__: null, 0: 'a', 1: 'b', 2: 'c' };
|
|
221
244
|
s2t.deepEqual(combined, expected, 'converts to object with null prototype');
|
|
222
245
|
s2t.equal(Object.getPrototypeOf(combined), null, 'result has null prototype when plainObjects is true');
|
|
223
246
|
s2t.end();
|
|
@@ -228,13 +251,13 @@ test('combine()', function (t) {
|
|
|
228
251
|
|
|
229
252
|
t.test('with existing overflow object', function (st) {
|
|
230
253
|
st.test('adds to existing overflow object at next index', function (s2t) {
|
|
231
|
-
// Create overflow object first via combine
|
|
232
|
-
var overflow = utils.combine(['a'
|
|
254
|
+
// Create overflow object first via combine: 3 elements (indices 0-2) with limit 0
|
|
255
|
+
var overflow = utils.combine(['a', 'b'], 'c', 0, false);
|
|
233
256
|
s2t.ok(utils.isOverflow(overflow), 'initial object is marked as overflow');
|
|
234
257
|
|
|
235
|
-
var combined = utils.combine(overflow, '
|
|
258
|
+
var combined = utils.combine(overflow, 'd', 10, false);
|
|
236
259
|
s2t.equal(combined, overflow, 'returns the same object (mutated)');
|
|
237
|
-
s2t.deepEqual(combined, { 0: 'a', 1: 'b', 2: 'c' }, 'adds value at next numeric index');
|
|
260
|
+
s2t.deepEqual(combined, { 0: 'a', 1: 'b', 2: 'c', 3: 'd' }, 'adds value at next numeric index');
|
|
238
261
|
s2t.end();
|
|
239
262
|
});
|
|
240
263
|
|