qs 6.11.0 → 6.11.2
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/.eslintrc +1 -1
- package/CHANGELOG.md +18 -5
- package/README.md +38 -0
- package/dist/qs.js +65 -32
- package/lib/parse.js +2 -1
- package/lib/stringify.js +4 -10
- package/package.json +8 -5
- package/test/empty-keys-cases.js +37 -0
- package/test/parse.js +45 -2
- package/test/stringify.js +63 -0
package/.eslintrc
CHANGED
package/CHANGELOG.md
CHANGED
|
@@ -1,4 +1,17 @@
|
|
|
1
|
-
## **6.11.
|
|
1
|
+
## **6.11.2**
|
|
2
|
+
- [Fix] `parse`: Fix parsing when the global Object prototype is frozen (#473)
|
|
3
|
+
- [Tests] add passing test cases with empty keys (#473)
|
|
4
|
+
|
|
5
|
+
## **6.11.1**
|
|
6
|
+
- [Fix] `stringify`: encode comma values more consistently (#463)
|
|
7
|
+
- [readme] add usage of `filter` option for injecting custom serialization, i.e. of custom types (#447)
|
|
8
|
+
- [meta] remove extraneous code backticks (#457)
|
|
9
|
+
- [meta] fix changelog markdown
|
|
10
|
+
- [actions] update checkout action
|
|
11
|
+
- [actions] restrict action permissions
|
|
12
|
+
- [Dev Deps] update `@ljharb/eslint-config`, `aud`, `object-inspect`, `tape`
|
|
13
|
+
|
|
14
|
+
## **6.11.0**
|
|
2
15
|
- [New] [Fix] `stringify`: revert 0e903c0; add `commaRoundTrip` option (#442)
|
|
3
16
|
- [readme] fix version badge
|
|
4
17
|
|
|
@@ -238,7 +251,7 @@
|
|
|
238
251
|
|
|
239
252
|
## **6.5.3**
|
|
240
253
|
- [Fix] `parse`: ignore `__proto__` keys (#428)
|
|
241
|
-
- [Fix]
|
|
254
|
+
- [Fix] `utils.merge`: avoid a crash with a null target and a truthy non-array source
|
|
242
255
|
- [Fix] correctly parse nested arrays
|
|
243
256
|
- [Fix] `stringify`: fix a crash with `strictNullHandling` and a custom `filter`/`serializeDate` (#279)
|
|
244
257
|
- [Fix] `utils`: `merge`: fix crash when `source` is a truthy primitive & no options are provided
|
|
@@ -291,7 +304,7 @@
|
|
|
291
304
|
- [Fix] fix for an impossible situation: when the formatter is called with a non-string value
|
|
292
305
|
- [Fix] use `safer-buffer` instead of `Buffer` constructor
|
|
293
306
|
- [Fix] `utils.merge`: avoid a crash with a null target and an array source
|
|
294
|
-
- [Fix]
|
|
307
|
+
- [Fix] `utils.merge`: avoid a crash with a null target and a truthy non-array source
|
|
295
308
|
- [Fix] `stringify`: fix a crash with `strictNullHandling` and a custom `filter`/`serializeDate` (#279)
|
|
296
309
|
- [Fix] `utils`: `merge`: fix crash when `source` is a truthy primitive & no options are provided
|
|
297
310
|
- [Fix] when `parseArrays` is false, properly handle keys ending in `[]`
|
|
@@ -320,7 +333,7 @@
|
|
|
320
333
|
- [Fix] `parse`: ignore `__proto__` keys (#428)
|
|
321
334
|
- [Fix] fix for an impossible situation: when the formatter is called with a non-string value
|
|
322
335
|
- [Fix] `utils.merge`: avoid a crash with a null target and an array source
|
|
323
|
-
- [Fix]
|
|
336
|
+
- [Fix] `utils.merge`: avoid a crash with a null target and a truthy non-array source
|
|
324
337
|
- [Fix] `stringify`: fix a crash with `strictNullHandling` and a custom `filter`/`serializeDate` (#279)
|
|
325
338
|
- [Fix] `utils`: `merge`: fix crash when `source` is a truthy primitive & no options are provided
|
|
326
339
|
- [Fix] when `parseArrays` is false, properly handle keys ending in `[]`
|
|
@@ -407,7 +420,7 @@
|
|
|
407
420
|
- [New] add "encoder" and "decoder" options, for custom param encoding/decoding (#160)
|
|
408
421
|
- [Fix] fix compacting of nested sparse arrays (#150)
|
|
409
422
|
|
|
410
|
-
## **6.1.2
|
|
423
|
+
## **6.1.2**
|
|
411
424
|
- [Fix] follow `allowPrototypes` option during merge (#201, #200)
|
|
412
425
|
- [Fix] chmod a-x
|
|
413
426
|
- [Fix] support keys starting with brackets (#202, #200)
|
package/README.md
CHANGED
|
@@ -498,6 +498,44 @@ qs.stringify({ a: ['b', 'c', 'd'], e: 'f' }, { filter: ['a', 0, 2] });
|
|
|
498
498
|
// 'a[0]=b&a[2]=d'
|
|
499
499
|
```
|
|
500
500
|
|
|
501
|
+
You could also use `filter` to inject custom serialization for user defined types. Consider you're working with
|
|
502
|
+
some api that expects query strings of the format for ranges:
|
|
503
|
+
|
|
504
|
+
```
|
|
505
|
+
https://domain.com/endpoint?range=30...70
|
|
506
|
+
```
|
|
507
|
+
|
|
508
|
+
For which you model as:
|
|
509
|
+
|
|
510
|
+
```javascript
|
|
511
|
+
class Range {
|
|
512
|
+
constructor(from, to) {
|
|
513
|
+
this.from = from;
|
|
514
|
+
this.to = to;
|
|
515
|
+
}
|
|
516
|
+
}
|
|
517
|
+
```
|
|
518
|
+
|
|
519
|
+
You could _inject_ a custom serializer to handle values of this type:
|
|
520
|
+
|
|
521
|
+
```javascript
|
|
522
|
+
qs.stringify(
|
|
523
|
+
{
|
|
524
|
+
range: new Range(30, 70),
|
|
525
|
+
},
|
|
526
|
+
{
|
|
527
|
+
filter: (prefix, value) => {
|
|
528
|
+
if (value instanceof Range) {
|
|
529
|
+
return `${value.from}...${value.to}`;
|
|
530
|
+
}
|
|
531
|
+
// serialize the usual way
|
|
532
|
+
return value;
|
|
533
|
+
},
|
|
534
|
+
}
|
|
535
|
+
);
|
|
536
|
+
// range=30...70
|
|
537
|
+
```
|
|
538
|
+
|
|
501
539
|
### Handling of `null` values
|
|
502
540
|
|
|
503
541
|
By default, `null` values are treated like empty strings:
|
package/dist/qs.js
CHANGED
|
@@ -88,7 +88,8 @@ var isoSentinel = 'utf8=%26%2310003%3B'; // encodeURIComponent('✓')
|
|
|
88
88
|
var charsetSentinel = 'utf8=%E2%9C%93'; // encodeURIComponent('✓')
|
|
89
89
|
|
|
90
90
|
var parseValues = function parseQueryStringValues(str, options) {
|
|
91
|
-
var obj = {};
|
|
91
|
+
var obj = { __proto__: null };
|
|
92
|
+
|
|
92
93
|
var cleanStr = options.ignoreQueryPrefix ? str.replace(/^\?/, '') : str;
|
|
93
94
|
var limit = options.parameterLimit === Infinity ? undefined : options.parameterLimit;
|
|
94
95
|
var parts = cleanStr.split(options.delimiter, limit);
|
|
@@ -323,7 +324,6 @@ var arrayPrefixGenerators = {
|
|
|
323
324
|
};
|
|
324
325
|
|
|
325
326
|
var isArray = Array.isArray;
|
|
326
|
-
var split = String.prototype.split;
|
|
327
327
|
var push = Array.prototype.push;
|
|
328
328
|
var pushToArray = function (arr, valueOrArray) {
|
|
329
329
|
push.apply(arr, isArray(valueOrArray) ? valueOrArray : [valueOrArray]);
|
|
@@ -425,14 +425,6 @@ var stringify = function stringify(
|
|
|
425
425
|
if (isNonNullishPrimitive(obj) || utils.isBuffer(obj)) {
|
|
426
426
|
if (encoder) {
|
|
427
427
|
var keyValue = encodeValuesOnly ? prefix : encoder(prefix, defaults.encoder, charset, 'key', format);
|
|
428
|
-
if (generateArrayPrefix === 'comma' && encodeValuesOnly) {
|
|
429
|
-
var valuesArray = split.call(String(obj), ',');
|
|
430
|
-
var valuesJoined = '';
|
|
431
|
-
for (var i = 0; i < valuesArray.length; ++i) {
|
|
432
|
-
valuesJoined += (i === 0 ? '' : ',') + formatter(encoder(valuesArray[i], defaults.encoder, charset, 'value', format));
|
|
433
|
-
}
|
|
434
|
-
return [formatter(keyValue) + (commaRoundTrip && isArray(obj) && valuesArray.length === 1 ? '[]' : '') + '=' + valuesJoined];
|
|
435
|
-
}
|
|
436
428
|
return [formatter(keyValue) + '=' + formatter(encoder(obj, defaults.encoder, charset, 'value', format))];
|
|
437
429
|
}
|
|
438
430
|
return [formatter(prefix) + '=' + formatter(String(obj))];
|
|
@@ -447,6 +439,9 @@ var stringify = function stringify(
|
|
|
447
439
|
var objKeys;
|
|
448
440
|
if (generateArrayPrefix === 'comma' && isArray(obj)) {
|
|
449
441
|
// we need to join elements in
|
|
442
|
+
if (encodeValuesOnly && encoder) {
|
|
443
|
+
obj = utils.maybeMap(obj, encoder);
|
|
444
|
+
}
|
|
450
445
|
objKeys = [{ value: obj.length > 0 ? obj.join(',') || null : void undefined }];
|
|
451
446
|
} else if (isArray(filter)) {
|
|
452
447
|
objKeys = filter;
|
|
@@ -479,7 +474,7 @@ var stringify = function stringify(
|
|
|
479
474
|
commaRoundTrip,
|
|
480
475
|
strictNullHandling,
|
|
481
476
|
skipNulls,
|
|
482
|
-
encoder,
|
|
477
|
+
generateArrayPrefix === 'comma' && encodeValuesOnly && isArray(obj) ? null : encoder,
|
|
483
478
|
filter,
|
|
484
479
|
sort,
|
|
485
480
|
allowDots,
|
|
@@ -629,7 +624,7 @@ module.exports = function (object, opts) {
|
|
|
629
624
|
return joined.length > 0 ? prefix + joined : '';
|
|
630
625
|
};
|
|
631
626
|
|
|
632
|
-
},{"./formats":1,"./utils":5,"side-channel":
|
|
627
|
+
},{"./formats":1,"./utils":5,"side-channel":17}],5:[function(require,module,exports){
|
|
633
628
|
'use strict';
|
|
634
629
|
|
|
635
630
|
var formats = require('./formats');
|
|
@@ -1058,18 +1053,23 @@ var ThrowTypeError = $gOPD
|
|
|
1058
1053
|
: throwTypeError;
|
|
1059
1054
|
|
|
1060
1055
|
var hasSymbols = require('has-symbols')();
|
|
1056
|
+
var hasProto = require('has-proto')();
|
|
1061
1057
|
|
|
1062
|
-
var getProto = Object.getPrototypeOf ||
|
|
1058
|
+
var getProto = Object.getPrototypeOf || (
|
|
1059
|
+
hasProto
|
|
1060
|
+
? function (x) { return x.__proto__; } // eslint-disable-line no-proto
|
|
1061
|
+
: null
|
|
1062
|
+
);
|
|
1063
1063
|
|
|
1064
1064
|
var needsEval = {};
|
|
1065
1065
|
|
|
1066
|
-
var TypedArray = typeof Uint8Array === 'undefined' ? undefined : getProto(Uint8Array);
|
|
1066
|
+
var TypedArray = typeof Uint8Array === 'undefined' || !getProto ? undefined : getProto(Uint8Array);
|
|
1067
1067
|
|
|
1068
1068
|
var INTRINSICS = {
|
|
1069
1069
|
'%AggregateError%': typeof AggregateError === 'undefined' ? undefined : AggregateError,
|
|
1070
1070
|
'%Array%': Array,
|
|
1071
1071
|
'%ArrayBuffer%': typeof ArrayBuffer === 'undefined' ? undefined : ArrayBuffer,
|
|
1072
|
-
'%ArrayIteratorPrototype%': hasSymbols ? getProto([][Symbol.iterator]()) : undefined,
|
|
1072
|
+
'%ArrayIteratorPrototype%': hasSymbols && getProto ? getProto([][Symbol.iterator]()) : undefined,
|
|
1073
1073
|
'%AsyncFromSyncIteratorPrototype%': undefined,
|
|
1074
1074
|
'%AsyncFunction%': needsEval,
|
|
1075
1075
|
'%AsyncGenerator%': needsEval,
|
|
@@ -1077,6 +1077,8 @@ var INTRINSICS = {
|
|
|
1077
1077
|
'%AsyncIteratorPrototype%': needsEval,
|
|
1078
1078
|
'%Atomics%': typeof Atomics === 'undefined' ? undefined : Atomics,
|
|
1079
1079
|
'%BigInt%': typeof BigInt === 'undefined' ? undefined : BigInt,
|
|
1080
|
+
'%BigInt64Array%': typeof BigInt64Array === 'undefined' ? undefined : BigInt64Array,
|
|
1081
|
+
'%BigUint64Array%': typeof BigUint64Array === 'undefined' ? undefined : BigUint64Array,
|
|
1080
1082
|
'%Boolean%': Boolean,
|
|
1081
1083
|
'%DataView%': typeof DataView === 'undefined' ? undefined : DataView,
|
|
1082
1084
|
'%Date%': Date,
|
|
@@ -1097,10 +1099,10 @@ var INTRINSICS = {
|
|
|
1097
1099
|
'%Int32Array%': typeof Int32Array === 'undefined' ? undefined : Int32Array,
|
|
1098
1100
|
'%isFinite%': isFinite,
|
|
1099
1101
|
'%isNaN%': isNaN,
|
|
1100
|
-
'%IteratorPrototype%': hasSymbols ? getProto(getProto([][Symbol.iterator]())) : undefined,
|
|
1102
|
+
'%IteratorPrototype%': hasSymbols && getProto ? getProto(getProto([][Symbol.iterator]())) : undefined,
|
|
1101
1103
|
'%JSON%': typeof JSON === 'object' ? JSON : undefined,
|
|
1102
1104
|
'%Map%': typeof Map === 'undefined' ? undefined : Map,
|
|
1103
|
-
'%MapIteratorPrototype%': typeof Map === 'undefined' || !hasSymbols ? undefined : getProto(new Map()[Symbol.iterator]()),
|
|
1105
|
+
'%MapIteratorPrototype%': typeof Map === 'undefined' || !hasSymbols || !getProto ? undefined : getProto(new Map()[Symbol.iterator]()),
|
|
1104
1106
|
'%Math%': Math,
|
|
1105
1107
|
'%Number%': Number,
|
|
1106
1108
|
'%Object%': Object,
|
|
@@ -1113,10 +1115,10 @@ var INTRINSICS = {
|
|
|
1113
1115
|
'%Reflect%': typeof Reflect === 'undefined' ? undefined : Reflect,
|
|
1114
1116
|
'%RegExp%': RegExp,
|
|
1115
1117
|
'%Set%': typeof Set === 'undefined' ? undefined : Set,
|
|
1116
|
-
'%SetIteratorPrototype%': typeof Set === 'undefined' || !hasSymbols ? undefined : getProto(new Set()[Symbol.iterator]()),
|
|
1118
|
+
'%SetIteratorPrototype%': typeof Set === 'undefined' || !hasSymbols || !getProto ? undefined : getProto(new Set()[Symbol.iterator]()),
|
|
1117
1119
|
'%SharedArrayBuffer%': typeof SharedArrayBuffer === 'undefined' ? undefined : SharedArrayBuffer,
|
|
1118
1120
|
'%String%': String,
|
|
1119
|
-
'%StringIteratorPrototype%': hasSymbols ? getProto(''[Symbol.iterator]()) : undefined,
|
|
1121
|
+
'%StringIteratorPrototype%': hasSymbols && getProto ? getProto(''[Symbol.iterator]()) : undefined,
|
|
1120
1122
|
'%Symbol%': hasSymbols ? Symbol : undefined,
|
|
1121
1123
|
'%SyntaxError%': $SyntaxError,
|
|
1122
1124
|
'%ThrowTypeError%': ThrowTypeError,
|
|
@@ -1132,6 +1134,16 @@ var INTRINSICS = {
|
|
|
1132
1134
|
'%WeakSet%': typeof WeakSet === 'undefined' ? undefined : WeakSet
|
|
1133
1135
|
};
|
|
1134
1136
|
|
|
1137
|
+
if (getProto) {
|
|
1138
|
+
try {
|
|
1139
|
+
null.error; // eslint-disable-line no-unused-expressions
|
|
1140
|
+
} catch (e) {
|
|
1141
|
+
// https://github.com/tc39/proposal-shadowrealm/pull/384#issuecomment-1364264229
|
|
1142
|
+
var errorProto = getProto(getProto(e));
|
|
1143
|
+
INTRINSICS['%Error.prototype%'] = errorProto;
|
|
1144
|
+
}
|
|
1145
|
+
}
|
|
1146
|
+
|
|
1135
1147
|
var doEval = function doEval(name) {
|
|
1136
1148
|
var value;
|
|
1137
1149
|
if (name === '%AsyncFunction%') {
|
|
@@ -1147,7 +1159,7 @@ var doEval = function doEval(name) {
|
|
|
1147
1159
|
}
|
|
1148
1160
|
} else if (name === '%AsyncIteratorPrototype%') {
|
|
1149
1161
|
var gen = doEval('%AsyncGenerator%');
|
|
1150
|
-
if (gen) {
|
|
1162
|
+
if (gen && getProto) {
|
|
1151
1163
|
value = getProto(gen.prototype);
|
|
1152
1164
|
}
|
|
1153
1165
|
}
|
|
@@ -1217,6 +1229,7 @@ var $concat = bind.call(Function.call, Array.prototype.concat);
|
|
|
1217
1229
|
var $spliceApply = bind.call(Function.apply, Array.prototype.splice);
|
|
1218
1230
|
var $replace = bind.call(Function.call, String.prototype.replace);
|
|
1219
1231
|
var $strSlice = bind.call(Function.call, String.prototype.slice);
|
|
1232
|
+
var $exec = bind.call(Function.call, RegExp.prototype.exec);
|
|
1220
1233
|
|
|
1221
1234
|
/* adapted from https://github.com/lodash/lodash/blob/4.17.15/dist/lodash.js#L6735-L6744 */
|
|
1222
1235
|
var rePropName = /[^%.[\]]+|\[(?:(-?\d+(?:\.\d+)?)|(["'])((?:(?!\2)[^\\]|\\.)*?)\2)\]|(?=(?:\.|\[\])(?:\.|\[\]|%$))/g;
|
|
@@ -1272,6 +1285,9 @@ module.exports = function GetIntrinsic(name, allowMissing) {
|
|
|
1272
1285
|
throw new $TypeError('"allowMissing" argument must be a boolean');
|
|
1273
1286
|
}
|
|
1274
1287
|
|
|
1288
|
+
if ($exec(/^%?[^%]*%?$/, name) === null) {
|
|
1289
|
+
throw new $SyntaxError('`%` may not be present anywhere but at the beginning and end of the intrinsic name');
|
|
1290
|
+
}
|
|
1275
1291
|
var parts = stringToPath(name);
|
|
1276
1292
|
var intrinsicBaseName = parts.length > 0 ? parts[0] : '';
|
|
1277
1293
|
|
|
@@ -1344,7 +1360,20 @@ module.exports = function GetIntrinsic(name, allowMissing) {
|
|
|
1344
1360
|
return value;
|
|
1345
1361
|
};
|
|
1346
1362
|
|
|
1347
|
-
},{"function-bind":10,"has":
|
|
1363
|
+
},{"function-bind":10,"has":15,"has-proto":12,"has-symbols":13}],12:[function(require,module,exports){
|
|
1364
|
+
'use strict';
|
|
1365
|
+
|
|
1366
|
+
var test = {
|
|
1367
|
+
foo: {}
|
|
1368
|
+
};
|
|
1369
|
+
|
|
1370
|
+
var $Object = Object;
|
|
1371
|
+
|
|
1372
|
+
module.exports = function hasProto() {
|
|
1373
|
+
return { __proto__: test }.foo === test.foo && !({ __proto__: null } instanceof $Object);
|
|
1374
|
+
};
|
|
1375
|
+
|
|
1376
|
+
},{}],13:[function(require,module,exports){
|
|
1348
1377
|
'use strict';
|
|
1349
1378
|
|
|
1350
1379
|
var origSymbol = typeof Symbol !== 'undefined' && Symbol;
|
|
@@ -1359,7 +1388,7 @@ module.exports = function hasNativeSymbols() {
|
|
|
1359
1388
|
return hasSymbolSham();
|
|
1360
1389
|
};
|
|
1361
1390
|
|
|
1362
|
-
},{"./shams":
|
|
1391
|
+
},{"./shams":14}],14:[function(require,module,exports){
|
|
1363
1392
|
'use strict';
|
|
1364
1393
|
|
|
1365
1394
|
/* eslint complexity: [2, 18], max-statements: [2, 33] */
|
|
@@ -1403,14 +1432,14 @@ module.exports = function hasSymbols() {
|
|
|
1403
1432
|
return true;
|
|
1404
1433
|
};
|
|
1405
1434
|
|
|
1406
|
-
},{}],
|
|
1435
|
+
},{}],15:[function(require,module,exports){
|
|
1407
1436
|
'use strict';
|
|
1408
1437
|
|
|
1409
1438
|
var bind = require('function-bind');
|
|
1410
1439
|
|
|
1411
1440
|
module.exports = bind.call(Function.call, Object.prototype.hasOwnProperty);
|
|
1412
1441
|
|
|
1413
|
-
},{"function-bind":10}],
|
|
1442
|
+
},{"function-bind":10}],16:[function(require,module,exports){
|
|
1414
1443
|
var hasMap = typeof Map === 'function' && Map.prototype;
|
|
1415
1444
|
var mapSizeDescriptor = Object.getOwnPropertyDescriptor && hasMap ? Object.getOwnPropertyDescriptor(Map.prototype, 'size') : null;
|
|
1416
1445
|
var mapSize = hasMap && mapSizeDescriptor && typeof mapSizeDescriptor.get === 'function' ? mapSizeDescriptor.get : null;
|
|
@@ -1615,16 +1644,20 @@ module.exports = function inspect_(obj, options, depth, seen) {
|
|
|
1615
1644
|
}
|
|
1616
1645
|
if (isMap(obj)) {
|
|
1617
1646
|
var mapParts = [];
|
|
1618
|
-
|
|
1619
|
-
|
|
1620
|
-
|
|
1647
|
+
if (mapForEach) {
|
|
1648
|
+
mapForEach.call(obj, function (value, key) {
|
|
1649
|
+
mapParts.push(inspect(key, obj, true) + ' => ' + inspect(value, obj));
|
|
1650
|
+
});
|
|
1651
|
+
}
|
|
1621
1652
|
return collectionOf('Map', mapSize.call(obj), mapParts, indent);
|
|
1622
1653
|
}
|
|
1623
1654
|
if (isSet(obj)) {
|
|
1624
1655
|
var setParts = [];
|
|
1625
|
-
|
|
1626
|
-
|
|
1627
|
-
|
|
1656
|
+
if (setForEach) {
|
|
1657
|
+
setForEach.call(obj, function (value) {
|
|
1658
|
+
setParts.push(inspect(value, obj));
|
|
1659
|
+
});
|
|
1660
|
+
}
|
|
1628
1661
|
return collectionOf('Set', setSize.call(obj), setParts, indent);
|
|
1629
1662
|
}
|
|
1630
1663
|
if (isWeakMap(obj)) {
|
|
@@ -1924,7 +1957,7 @@ function arrObjKeys(obj, inspect) {
|
|
|
1924
1957
|
return xs;
|
|
1925
1958
|
}
|
|
1926
1959
|
|
|
1927
|
-
},{"./util.inspect":6}],
|
|
1960
|
+
},{"./util.inspect":6}],17:[function(require,module,exports){
|
|
1928
1961
|
'use strict';
|
|
1929
1962
|
|
|
1930
1963
|
var GetIntrinsic = require('get-intrinsic');
|
|
@@ -2050,5 +2083,5 @@ module.exports = function getSideChannel() {
|
|
|
2050
2083
|
return channel;
|
|
2051
2084
|
};
|
|
2052
2085
|
|
|
2053
|
-
},{"call-bind/callBound":7,"get-intrinsic":11,"object-inspect":
|
|
2086
|
+
},{"call-bind/callBound":7,"get-intrinsic":11,"object-inspect":16}]},{},[2])(2)
|
|
2054
2087
|
});
|
package/lib/parse.js
CHANGED
|
@@ -49,7 +49,8 @@ var isoSentinel = 'utf8=%26%2310003%3B'; // encodeURIComponent('✓')
|
|
|
49
49
|
var charsetSentinel = 'utf8=%E2%9C%93'; // encodeURIComponent('✓')
|
|
50
50
|
|
|
51
51
|
var parseValues = function parseQueryStringValues(str, options) {
|
|
52
|
-
var obj = {};
|
|
52
|
+
var obj = { __proto__: null };
|
|
53
|
+
|
|
53
54
|
var cleanStr = options.ignoreQueryPrefix ? str.replace(/^\?/, '') : str;
|
|
54
55
|
var limit = options.parameterLimit === Infinity ? undefined : options.parameterLimit;
|
|
55
56
|
var parts = cleanStr.split(options.delimiter, limit);
|
package/lib/stringify.js
CHANGED
|
@@ -19,7 +19,6 @@ var arrayPrefixGenerators = {
|
|
|
19
19
|
};
|
|
20
20
|
|
|
21
21
|
var isArray = Array.isArray;
|
|
22
|
-
var split = String.prototype.split;
|
|
23
22
|
var push = Array.prototype.push;
|
|
24
23
|
var pushToArray = function (arr, valueOrArray) {
|
|
25
24
|
push.apply(arr, isArray(valueOrArray) ? valueOrArray : [valueOrArray]);
|
|
@@ -121,14 +120,6 @@ var stringify = function stringify(
|
|
|
121
120
|
if (isNonNullishPrimitive(obj) || utils.isBuffer(obj)) {
|
|
122
121
|
if (encoder) {
|
|
123
122
|
var keyValue = encodeValuesOnly ? prefix : encoder(prefix, defaults.encoder, charset, 'key', format);
|
|
124
|
-
if (generateArrayPrefix === 'comma' && encodeValuesOnly) {
|
|
125
|
-
var valuesArray = split.call(String(obj), ',');
|
|
126
|
-
var valuesJoined = '';
|
|
127
|
-
for (var i = 0; i < valuesArray.length; ++i) {
|
|
128
|
-
valuesJoined += (i === 0 ? '' : ',') + formatter(encoder(valuesArray[i], defaults.encoder, charset, 'value', format));
|
|
129
|
-
}
|
|
130
|
-
return [formatter(keyValue) + (commaRoundTrip && isArray(obj) && valuesArray.length === 1 ? '[]' : '') + '=' + valuesJoined];
|
|
131
|
-
}
|
|
132
123
|
return [formatter(keyValue) + '=' + formatter(encoder(obj, defaults.encoder, charset, 'value', format))];
|
|
133
124
|
}
|
|
134
125
|
return [formatter(prefix) + '=' + formatter(String(obj))];
|
|
@@ -143,6 +134,9 @@ var stringify = function stringify(
|
|
|
143
134
|
var objKeys;
|
|
144
135
|
if (generateArrayPrefix === 'comma' && isArray(obj)) {
|
|
145
136
|
// we need to join elements in
|
|
137
|
+
if (encodeValuesOnly && encoder) {
|
|
138
|
+
obj = utils.maybeMap(obj, encoder);
|
|
139
|
+
}
|
|
146
140
|
objKeys = [{ value: obj.length > 0 ? obj.join(',') || null : void undefined }];
|
|
147
141
|
} else if (isArray(filter)) {
|
|
148
142
|
objKeys = filter;
|
|
@@ -175,7 +169,7 @@ var stringify = function stringify(
|
|
|
175
169
|
commaRoundTrip,
|
|
176
170
|
strictNullHandling,
|
|
177
171
|
skipNulls,
|
|
178
|
-
encoder,
|
|
172
|
+
generateArrayPrefix === 'comma' && encodeValuesOnly && isArray(obj) ? null : encoder,
|
|
179
173
|
filter,
|
|
180
174
|
sort,
|
|
181
175
|
allowDots,
|
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.11.
|
|
5
|
+
"version": "6.11.2",
|
|
6
6
|
"repository": {
|
|
7
7
|
"type": "git",
|
|
8
8
|
"url": "https://github.com/ljharb/qs.git"
|
|
@@ -33,24 +33,27 @@
|
|
|
33
33
|
"side-channel": "^1.0.4"
|
|
34
34
|
},
|
|
35
35
|
"devDependencies": {
|
|
36
|
-
"@ljharb/eslint-config": "^21.0.
|
|
37
|
-
"aud": "^2.0.
|
|
36
|
+
"@ljharb/eslint-config": "^21.0.1",
|
|
37
|
+
"aud": "^2.0.2",
|
|
38
38
|
"browserify": "^16.5.2",
|
|
39
39
|
"eclint": "^2.8.1",
|
|
40
40
|
"eslint": "=8.8.0",
|
|
41
41
|
"evalmd": "^0.0.19",
|
|
42
42
|
"for-each": "^0.3.3",
|
|
43
|
+
"has-override-mistake": "^1.0.0",
|
|
44
|
+
"has-property-descriptors": "^1.0.0",
|
|
43
45
|
"has-symbols": "^1.0.3",
|
|
44
46
|
"iconv-lite": "^0.5.1",
|
|
45
47
|
"in-publish": "^2.0.1",
|
|
46
48
|
"mkdirp": "^0.5.5",
|
|
49
|
+
"mock-property": "^1.0.0",
|
|
47
50
|
"npmignore": "^0.3.0",
|
|
48
51
|
"nyc": "^10.3.2",
|
|
49
|
-
"object-inspect": "^1.12.
|
|
52
|
+
"object-inspect": "^1.12.3",
|
|
50
53
|
"qs-iconv": "^1.0.4",
|
|
51
54
|
"safe-publish-latest": "^2.0.0",
|
|
52
55
|
"safer-buffer": "^2.1.2",
|
|
53
|
-
"tape": "^5.
|
|
56
|
+
"tape": "^5.6.3"
|
|
54
57
|
},
|
|
55
58
|
"scripts": {
|
|
56
59
|
"prepack": "npmignore --auto --commentLines=autogenerated",
|
|
@@ -0,0 +1,37 @@
|
|
|
1
|
+
'use strict';
|
|
2
|
+
|
|
3
|
+
module.exports = {
|
|
4
|
+
emptyTestCases: [
|
|
5
|
+
{ input: '&', withEmptyKeys: {}, stringifyOutput: '', noEmptyKeys: {} },
|
|
6
|
+
{ input: '&&', withEmptyKeys: {}, stringifyOutput: '', noEmptyKeys: {} },
|
|
7
|
+
{ input: '&=', withEmptyKeys: { '': '' }, stringifyOutput: '=', noEmptyKeys: {} },
|
|
8
|
+
{ input: '&=&', withEmptyKeys: { '': '' }, stringifyOutput: '=', noEmptyKeys: {} },
|
|
9
|
+
{ input: '&=&=', withEmptyKeys: { '': ['', ''] }, stringifyOutput: '[0]=&[1]=', noEmptyKeys: {} },
|
|
10
|
+
{ input: '&=&=&', withEmptyKeys: { '': ['', ''] }, stringifyOutput: '[0]=&[1]=', noEmptyKeys: {} },
|
|
11
|
+
|
|
12
|
+
{ input: '=', withEmptyKeys: { '': '' }, noEmptyKeys: {}, stringifyOutput: '=' },
|
|
13
|
+
{ input: '=&', withEmptyKeys: { '': '' }, stringifyOutput: '=', noEmptyKeys: {} },
|
|
14
|
+
{ input: '=&&&', withEmptyKeys: { '': '' }, stringifyOutput: '=', noEmptyKeys: {} },
|
|
15
|
+
{ input: '=&=&=&', withEmptyKeys: { '': ['', '', ''] }, stringifyOutput: '[0]=&[1]=&[2]=', noEmptyKeys: {} },
|
|
16
|
+
{ input: '=&a[]=b&a[1]=c', withEmptyKeys: { '': '', a: ['b', 'c'] }, stringifyOutput: '=&a[0]=b&a[1]=c', noEmptyKeys: { a: ['b', 'c'] } },
|
|
17
|
+
{ input: '=a', withEmptyKeys: { '': 'a' }, noEmptyKeys: {}, stringifyOutput: '=a' },
|
|
18
|
+
{ input: '=a', withEmptyKeys: { '': 'a' }, noEmptyKeys: {}, stringifyOutput: '=a' },
|
|
19
|
+
{ input: 'a==a', withEmptyKeys: { a: '=a' }, noEmptyKeys: { a: '=a' }, stringifyOutput: 'a==a' },
|
|
20
|
+
|
|
21
|
+
{ input: '=&a[]=b', withEmptyKeys: { '': '', a: ['b'] }, stringifyOutput: '=&a[0]=b', noEmptyKeys: { a: ['b'] } },
|
|
22
|
+
{ input: '=&a[]=b&a[]=c&a[2]=d', withEmptyKeys: { '': '', a: ['b', 'c', 'd'] }, stringifyOutput: '=&a[0]=b&a[1]=c&a[2]=d', noEmptyKeys: { a: ['b', 'c', 'd'] } },
|
|
23
|
+
{ input: '=a&=b', withEmptyKeys: { '': ['a', 'b'] }, stringifyOutput: '[0]=a&[1]=b', noEmptyKeys: {} },
|
|
24
|
+
{ input: '=a&foo=b', withEmptyKeys: { '': 'a', foo: 'b' }, noEmptyKeys: { foo: 'b' }, stringifyOutput: '=a&foo=b' },
|
|
25
|
+
|
|
26
|
+
{ input: 'a[]=b&a=c&=', withEmptyKeys: { '': '', a: ['b', 'c'] }, stringifyOutput: '=&a[0]=b&a[1]=c', noEmptyKeys: { a: ['b', 'c'] } },
|
|
27
|
+
{ input: 'a[]=b&a=c&=', withEmptyKeys: { '': '', a: ['b', 'c'] }, stringifyOutput: '=&a[0]=b&a[1]=c', noEmptyKeys: { a: ['b', 'c'] } },
|
|
28
|
+
{ input: 'a[0]=b&a=c&=', withEmptyKeys: { '': '', a: ['b', 'c'] }, stringifyOutput: '=&a[0]=b&a[1]=c', noEmptyKeys: { a: ['b', 'c'] } },
|
|
29
|
+
{ input: 'a=b&a[]=c&=', withEmptyKeys: { '': '', a: ['b', 'c'] }, stringifyOutput: '=&a[0]=b&a[1]=c', noEmptyKeys: { a: ['b', 'c'] } },
|
|
30
|
+
{ input: 'a=b&a[0]=c&=', withEmptyKeys: { '': '', a: ['b', 'c'] }, stringifyOutput: '=&a[0]=b&a[1]=c', noEmptyKeys: { a: ['b', 'c'] } },
|
|
31
|
+
|
|
32
|
+
{ input: '[]=a&[]=b& []=1', withEmptyKeys: { '': ['a', 'b'], ' ': ['1'] }, stringifyOutput: '[0]=a&[1]=b& [0]=1', noEmptyKeys: { 0: 'a', 1: 'b', ' ': ['1'] } },
|
|
33
|
+
{ input: '[0]=a&[1]=b&a[0]=1&a[1]=2', withEmptyKeys: { '': ['a', 'b'], a: ['1', '2'] }, noEmptyKeys: { 0: 'a', 1: 'b', a: ['1', '2'] }, stringifyOutput: '[0]=a&[1]=b&a[0]=1&a[1]=2' },
|
|
34
|
+
{ input: '[deep]=a&[deep]=2', withEmptyKeys: { '': { deep: ['a', '2'] } }, stringifyOutput: '[deep][0]=a&[deep][1]=2', noEmptyKeys: { deep: ['a', '2'] } },
|
|
35
|
+
{ input: '%5B0%5D=a&%5B1%5D=b', withEmptyKeys: { '': ['a', 'b'] }, stringifyOutput: '[0]=a&[1]=b', noEmptyKeys: { 0: 'a', 1: 'b' } }
|
|
36
|
+
]
|
|
37
|
+
};
|
package/test/parse.js
CHANGED
|
@@ -1,10 +1,15 @@
|
|
|
1
1
|
'use strict';
|
|
2
2
|
|
|
3
3
|
var test = require('tape');
|
|
4
|
-
var
|
|
5
|
-
var utils = require('../lib/utils');
|
|
4
|
+
var hasPropertyDescriptors = require('has-property-descriptors')();
|
|
6
5
|
var iconv = require('iconv-lite');
|
|
6
|
+
var mockProperty = require('mock-property');
|
|
7
|
+
var hasOverrideMistake = require('has-override-mistake')();
|
|
7
8
|
var SaferBuffer = require('safer-buffer').Buffer;
|
|
9
|
+
var emptyTestCases = require('./empty-keys-cases').emptyTestCases;
|
|
10
|
+
|
|
11
|
+
var qs = require('../');
|
|
12
|
+
var utils = require('../lib/utils');
|
|
8
13
|
|
|
9
14
|
test('parse()', function (t) {
|
|
10
15
|
t.test('parses a simple string', function (st) {
|
|
@@ -601,6 +606,34 @@ test('parse()', function (t) {
|
|
|
601
606
|
st.end();
|
|
602
607
|
});
|
|
603
608
|
|
|
609
|
+
t.test('does not crash when the global Object prototype is frozen', { skip: !hasPropertyDescriptors || !hasOverrideMistake }, function (st) {
|
|
610
|
+
// We can't actually freeze the global Object prototype as that will interfere with other tests, and once an object is frozen, it
|
|
611
|
+
// can't be unfrozen. Instead, we add a new non-writable property to simulate this.
|
|
612
|
+
st.teardown(mockProperty(Object.prototype, 'frozenProp', { value: 'foo', nonWritable: true, nonEnumerable: true }));
|
|
613
|
+
|
|
614
|
+
st['throws'](
|
|
615
|
+
function () {
|
|
616
|
+
var obj = {};
|
|
617
|
+
obj.frozenProp = 'bar';
|
|
618
|
+
},
|
|
619
|
+
// node < 6 has a different error message
|
|
620
|
+
/^TypeError: Cannot assign to read only property 'frozenProp' of (?:object '#<Object>'|#<Object>)/,
|
|
621
|
+
'regular assignment of an inherited non-writable property throws'
|
|
622
|
+
);
|
|
623
|
+
|
|
624
|
+
var parsed;
|
|
625
|
+
st.doesNotThrow(
|
|
626
|
+
function () {
|
|
627
|
+
parsed = qs.parse('frozenProp', { allowPrototypes: false });
|
|
628
|
+
},
|
|
629
|
+
'parsing a nonwritable Object.prototype property does not throw'
|
|
630
|
+
);
|
|
631
|
+
|
|
632
|
+
st.deepEqual(parsed, {}, 'bare "frozenProp" results in {}');
|
|
633
|
+
|
|
634
|
+
st.end();
|
|
635
|
+
});
|
|
636
|
+
|
|
604
637
|
t.test('params starting with a closing bracket', function (st) {
|
|
605
638
|
st.deepEqual(qs.parse(']=toString'), { ']': 'toString' });
|
|
606
639
|
st.deepEqual(qs.parse(']]=toString'), { ']]': 'toString' });
|
|
@@ -853,3 +886,13 @@ test('parse()', function (t) {
|
|
|
853
886
|
|
|
854
887
|
t.end();
|
|
855
888
|
});
|
|
889
|
+
|
|
890
|
+
test('parses empty keys', function (t) {
|
|
891
|
+
emptyTestCases.forEach(function (testCase) {
|
|
892
|
+
t.test('skips empty string key with ' + testCase.input, function (st) {
|
|
893
|
+
st.deepEqual(qs.parse(testCase.input), testCase.noEmptyKeys);
|
|
894
|
+
|
|
895
|
+
st.end();
|
|
896
|
+
});
|
|
897
|
+
});
|
|
898
|
+
});
|
package/test/stringify.js
CHANGED
|
@@ -6,6 +6,7 @@ var utils = require('../lib/utils');
|
|
|
6
6
|
var iconv = require('iconv-lite');
|
|
7
7
|
var SaferBuffer = require('safer-buffer').Buffer;
|
|
8
8
|
var hasSymbols = require('has-symbols');
|
|
9
|
+
var emptyTestCases = require('./empty-keys-cases').emptyTestCases;
|
|
9
10
|
var hasBigInt = typeof BigInt === 'function';
|
|
10
11
|
|
|
11
12
|
test('stringify()', function (t) {
|
|
@@ -160,6 +161,13 @@ test('stringify()', function (t) {
|
|
|
160
161
|
s2t.end();
|
|
161
162
|
});
|
|
162
163
|
|
|
164
|
+
st.test('array with multiple items with a comma inside', function (s2t) {
|
|
165
|
+
s2t.equal(qs.stringify({ a: ['c,d', 'e'] }, { encodeValuesOnly: true, arrayFormat: 'comma' }), 'a=c%2Cd,e');
|
|
166
|
+
s2t.equal(qs.stringify({ a: ['c,d', 'e'] }, { arrayFormat: 'comma' }), 'a=c%2Cd%2Ce');
|
|
167
|
+
|
|
168
|
+
s2t.end();
|
|
169
|
+
});
|
|
170
|
+
|
|
163
171
|
st.end();
|
|
164
172
|
});
|
|
165
173
|
|
|
@@ -171,6 +179,44 @@ test('stringify()', function (t) {
|
|
|
171
179
|
st.end();
|
|
172
180
|
});
|
|
173
181
|
|
|
182
|
+
t.test('stringifies comma and empty array values', function (st) {
|
|
183
|
+
st.equal(qs.stringify({ a: [',', '', 'c,d%'] }, { encode: false, arrayFormat: 'indices' }), 'a[0]=,&a[1]=&a[2]=c,d%');
|
|
184
|
+
st.equal(qs.stringify({ a: [',', '', 'c,d%'] }, { encode: false, arrayFormat: 'brackets' }), 'a[]=,&a[]=&a[]=c,d%');
|
|
185
|
+
st.equal(qs.stringify({ a: [',', '', 'c,d%'] }, { encode: false, arrayFormat: 'comma' }), 'a=,,,c,d%');
|
|
186
|
+
st.equal(qs.stringify({ a: [',', '', 'c,d%'] }, { encode: false, arrayFormat: 'repeat' }), 'a=,&a=&a=c,d%');
|
|
187
|
+
|
|
188
|
+
st.equal(qs.stringify({ a: [',', '', 'c,d%'] }, { encode: true, encodeValuesOnly: true, arrayFormat: 'indices' }), 'a[0]=%2C&a[1]=&a[2]=c%2Cd%25');
|
|
189
|
+
st.equal(qs.stringify({ a: [',', '', 'c,d%'] }, { encode: true, encodeValuesOnly: true, arrayFormat: 'brackets' }), 'a[]=%2C&a[]=&a[]=c%2Cd%25');
|
|
190
|
+
st.equal(qs.stringify({ a: [',', '', 'c,d%'] }, { encode: true, encodeValuesOnly: true, arrayFormat: 'comma' }), 'a=%2C,,c%2Cd%25');
|
|
191
|
+
st.equal(qs.stringify({ a: [',', '', 'c,d%'] }, { encode: true, encodeValuesOnly: true, arrayFormat: 'repeat' }), 'a=%2C&a=&a=c%2Cd%25');
|
|
192
|
+
|
|
193
|
+
st.equal(qs.stringify({ a: [',', '', 'c,d%'] }, { encode: true, encodeValuesOnly: false, arrayFormat: 'indices' }), 'a%5B0%5D=%2C&a%5B1%5D=&a%5B2%5D=c%2Cd%25');
|
|
194
|
+
st.equal(qs.stringify({ a: [',', '', 'c,d%'] }, { encode: true, encodeValuesOnly: false, arrayFormat: 'brackets' }), 'a%5B%5D=%2C&a%5B%5D=&a%5B%5D=c%2Cd%25');
|
|
195
|
+
st.equal(qs.stringify({ a: [',', '', 'c,d%'] }, { encode: true, encodeValuesOnly: false, arrayFormat: 'comma' }), 'a=%2C%2C%2Cc%2Cd%25');
|
|
196
|
+
st.equal(qs.stringify({ a: [',', '', 'c,d%'] }, { encode: true, encodeValuesOnly: false, arrayFormat: 'repeat' }), 'a=%2C&a=&a=c%2Cd%25');
|
|
197
|
+
|
|
198
|
+
st.end();
|
|
199
|
+
});
|
|
200
|
+
|
|
201
|
+
t.test('stringifies comma and empty non-array values', function (st) {
|
|
202
|
+
st.equal(qs.stringify({ a: ',', b: '', c: 'c,d%' }, { encode: false, arrayFormat: 'indices' }), 'a=,&b=&c=c,d%');
|
|
203
|
+
st.equal(qs.stringify({ a: ',', b: '', c: 'c,d%' }, { encode: false, arrayFormat: 'brackets' }), 'a=,&b=&c=c,d%');
|
|
204
|
+
st.equal(qs.stringify({ a: ',', b: '', c: 'c,d%' }, { encode: false, arrayFormat: 'comma' }), 'a=,&b=&c=c,d%');
|
|
205
|
+
st.equal(qs.stringify({ a: ',', b: '', c: 'c,d%' }, { encode: false, arrayFormat: 'repeat' }), 'a=,&b=&c=c,d%');
|
|
206
|
+
|
|
207
|
+
st.equal(qs.stringify({ a: ',', b: '', c: 'c,d%' }, { encode: true, encodeValuesOnly: true, arrayFormat: 'indices' }), 'a=%2C&b=&c=c%2Cd%25');
|
|
208
|
+
st.equal(qs.stringify({ a: ',', b: '', c: 'c,d%' }, { encode: true, encodeValuesOnly: true, arrayFormat: 'brackets' }), 'a=%2C&b=&c=c%2Cd%25');
|
|
209
|
+
st.equal(qs.stringify({ a: ',', b: '', c: 'c,d%' }, { encode: true, encodeValuesOnly: true, arrayFormat: 'comma' }), 'a=%2C&b=&c=c%2Cd%25');
|
|
210
|
+
st.equal(qs.stringify({ a: ',', b: '', c: 'c,d%' }, { encode: true, encodeValuesOnly: true, arrayFormat: 'repeat' }), 'a=%2C&b=&c=c%2Cd%25');
|
|
211
|
+
|
|
212
|
+
st.equal(qs.stringify({ a: ',', b: '', c: 'c,d%' }, { encode: true, encodeValuesOnly: false, arrayFormat: 'indices' }), 'a=%2C&b=&c=c%2Cd%25');
|
|
213
|
+
st.equal(qs.stringify({ a: ',', b: '', c: 'c,d%' }, { encode: true, encodeValuesOnly: false, arrayFormat: 'brackets' }), 'a=%2C&b=&c=c%2Cd%25');
|
|
214
|
+
st.equal(qs.stringify({ a: ',', b: '', c: 'c,d%' }, { encode: true, encodeValuesOnly: false, arrayFormat: 'comma' }), 'a=%2C&b=&c=c%2Cd%25');
|
|
215
|
+
st.equal(qs.stringify({ a: ',', b: '', c: 'c,d%' }, { encode: true, encodeValuesOnly: false, arrayFormat: 'repeat' }), 'a=%2C&b=&c=c%2Cd%25');
|
|
216
|
+
|
|
217
|
+
st.end();
|
|
218
|
+
});
|
|
219
|
+
|
|
174
220
|
t.test('stringifies a nested array value with dots notation', function (st) {
|
|
175
221
|
st.equal(
|
|
176
222
|
qs.stringify(
|
|
@@ -907,3 +953,20 @@ test('stringify()', function (t) {
|
|
|
907
953
|
|
|
908
954
|
t.end();
|
|
909
955
|
});
|
|
956
|
+
|
|
957
|
+
test('stringifies empty keys', function (t) {
|
|
958
|
+
emptyTestCases.forEach(function (testCase) {
|
|
959
|
+
t.test('stringifies an object with empty string key with ' + testCase.input, function (st) {
|
|
960
|
+
st.deepEqual(qs.stringify(testCase.withEmptyKeys, { encode: false }), testCase.stringifyOutput);
|
|
961
|
+
|
|
962
|
+
st.end();
|
|
963
|
+
});
|
|
964
|
+
});
|
|
965
|
+
|
|
966
|
+
t.test('edge case with object/arrays', function (st) {
|
|
967
|
+
st.deepEqual(qs.stringify({ '': { '': [2, 3] } }, { encode: false }), '[][0]=2&[][1]=3');
|
|
968
|
+
st.deepEqual(qs.stringify({ '': { '': [2, 3], a: 2 } }, { encode: false }), '[][0]=2&[][1]=3&[a]=2');
|
|
969
|
+
|
|
970
|
+
st.end();
|
|
971
|
+
});
|
|
972
|
+
});
|