qs 6.10.1 → 6.10.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/.editorconfig +1 -0
- package/.eslintrc +0 -1
- package/CHANGELOG.md +10 -0
- package/README.md +30 -18
- package/dist/qs.js +124 -26
- package/lib/stringify.js +32 -5
- package/lib/utils.js +1 -0
- package/package.json +10 -9
- package/test/stringify.js +31 -14
package/.editorconfig
CHANGED
package/.eslintrc
CHANGED
package/CHANGELOG.md
CHANGED
|
@@ -1,3 +1,13 @@
|
|
|
1
|
+
## **6.10.2**
|
|
2
|
+
- [Fix] `stringify`: actually fix cyclic references (#426)
|
|
3
|
+
- [Fix] `stringify`: avoid encoding arrayformat comma when `encodeValuesOnly = true` (#424)
|
|
4
|
+
- [readme] remove travis badge; add github actions/codecov badges; update URLs
|
|
5
|
+
- [Docs] add note and links for coercing primitive values (#408)
|
|
6
|
+
- [actions] update codecov uploader
|
|
7
|
+
- [actions] update workflows
|
|
8
|
+
- [Tests] clean up stringify tests slightly
|
|
9
|
+
- [Dev Deps] update `eslint`, `@ljharb/eslint-config`, `aud`, `object-inspect`, `safe-publish-latest`, `tape`
|
|
10
|
+
|
|
1
11
|
## **6.10.1**
|
|
2
12
|
- [Fix] `stringify`: avoid exception on repeated object values (#402)
|
|
3
13
|
|
package/README.md
CHANGED
|
@@ -1,12 +1,13 @@
|
|
|
1
1
|
# qs <sup>[![Version Badge][2]][1]</sup>
|
|
2
2
|
|
|
3
|
-
[![
|
|
4
|
-
[![
|
|
5
|
-
[![
|
|
3
|
+
[![github actions][actions-image]][actions-url]
|
|
4
|
+
[![coverage][codecov-image]][codecov-url]
|
|
5
|
+
[![dependency status][deps-svg]][deps-url]
|
|
6
|
+
[![dev dependency status][dev-deps-svg]][dev-deps-url]
|
|
6
7
|
[![License][license-image]][license-url]
|
|
7
8
|
[![Downloads][downloads-image]][downloads-url]
|
|
8
9
|
|
|
9
|
-
[![npm badge][
|
|
10
|
+
[![npm badge][npm-badge-png]][package-url]
|
|
10
11
|
|
|
11
12
|
A querystring parsing and stringifying library with some added security.
|
|
12
13
|
|
|
@@ -287,6 +288,17 @@ assert.deepEqual(arraysOfObjects, { a: ['b', 'c'] })
|
|
|
287
288
|
```
|
|
288
289
|
(_this cannot convert nested objects, such as `a={b:1},{c:d}`_)
|
|
289
290
|
|
|
291
|
+
### Parsing primitive/scalar values (numbers, booleans, null, etc)
|
|
292
|
+
|
|
293
|
+
By default, all values are parsed as strings. This behavior will not change and is explained in [issue #91](https://github.com/ljharb/qs/issues/91).
|
|
294
|
+
|
|
295
|
+
```javascript
|
|
296
|
+
var primitiveValues = qs.parse('a=15&b=true&c=null');
|
|
297
|
+
assert.deepEqual(primitiveValues, { a: '15', b: 'true', c: 'null' });
|
|
298
|
+
```
|
|
299
|
+
|
|
300
|
+
If you wish to auto-convert values which look like numbers, booleans, and other values into their primitive counterparts, you can use the [query-types Express JS middleware](https://github.com/xpepermint/query-types) which will auto-convert all request query parameters.
|
|
301
|
+
|
|
290
302
|
### Stringifying
|
|
291
303
|
|
|
292
304
|
[](#preventEval)
|
|
@@ -594,18 +606,18 @@ Available as part of the Tidelift Subscription
|
|
|
594
606
|
|
|
595
607
|
The maintainers of qs and thousands of other packages are working with Tidelift to deliver commercial support and maintenance for the open source dependencies you use to build your applications. Save time, reduce risk, and improve code health, while paying the maintainers of the exact dependencies you use. [Learn more.](https://tidelift.com/subscription/pkg/npm-qs?utm_source=npm-qs&utm_medium=referral&utm_campaign=enterprise&utm_term=repo)
|
|
596
608
|
|
|
597
|
-
[
|
|
598
|
-
[
|
|
599
|
-
[
|
|
600
|
-
[
|
|
601
|
-
[
|
|
602
|
-
[
|
|
603
|
-
[
|
|
604
|
-
[
|
|
605
|
-
[9]: https://ci.testling.com/ljharb/qs.png
|
|
606
|
-
[10]: https://ci.testling.com/ljharb/qs
|
|
607
|
-
[11]: https://nodei.co/npm/qs.png?downloads=true&stars=true
|
|
608
|
-
[license-image]: http://img.shields.io/npm/l/qs.svg
|
|
609
|
+
[package-url]: https://npmjs.org/package/qs
|
|
610
|
+
[npm-version-svg]: https://versionbadg.es/ljharb/qs.svg
|
|
611
|
+
[deps-svg]: https://david-dm.org/ljharb/qs.svg
|
|
612
|
+
[deps-url]: https://david-dm.org/ljharb/qs
|
|
613
|
+
[dev-deps-svg]: https://david-dm.org/ljharb/qs/dev-status.svg
|
|
614
|
+
[dev-deps-url]: https://david-dm.org/ljharb/qs#info=devDependencies
|
|
615
|
+
[npm-badge-png]: https://nodei.co/npm/qs.png?downloads=true&stars=true
|
|
616
|
+
[license-image]: https://img.shields.io/npm/l/qs.svg
|
|
609
617
|
[license-url]: LICENSE
|
|
610
|
-
[downloads-image]:
|
|
611
|
-
[downloads-url]:
|
|
618
|
+
[downloads-image]: https://img.shields.io/npm/dm/qs.svg
|
|
619
|
+
[downloads-url]: https://npm-stat.com/charts.html?package=qs
|
|
620
|
+
[codecov-image]: https://codecov.io/gh/ljharb/qs/branch/main/graphs/badge.svg
|
|
621
|
+
[codecov-url]: https://app.codecov.io/gh/ljharb/qs/
|
|
622
|
+
[actions-image]: https://img.shields.io/endpoint?url=https://github-actions-badge-u3jn4tfpocch.runkit.sh/ljharb/qs
|
|
623
|
+
[actions-url]: https://github.com/ljharb/qs/actions
|
package/dist/qs.js
CHANGED
|
@@ -323,6 +323,7 @@ var arrayPrefixGenerators = {
|
|
|
323
323
|
};
|
|
324
324
|
|
|
325
325
|
var isArray = Array.isArray;
|
|
326
|
+
var split = String.prototype.split;
|
|
326
327
|
var push = Array.prototype.push;
|
|
327
328
|
var pushToArray = function (arr, valueOrArray) {
|
|
328
329
|
push.apply(arr, isArray(valueOrArray) ? valueOrArray : [valueOrArray]);
|
|
@@ -359,6 +360,8 @@ var isNonNullishPrimitive = function isNonNullishPrimitive(v) {
|
|
|
359
360
|
|| typeof v === 'bigint';
|
|
360
361
|
};
|
|
361
362
|
|
|
363
|
+
var sentinel = {};
|
|
364
|
+
|
|
362
365
|
var stringify = function stringify(
|
|
363
366
|
object,
|
|
364
367
|
prefix,
|
|
@@ -378,8 +381,23 @@ var stringify = function stringify(
|
|
|
378
381
|
) {
|
|
379
382
|
var obj = object;
|
|
380
383
|
|
|
381
|
-
|
|
382
|
-
|
|
384
|
+
var tmpSc = sideChannel;
|
|
385
|
+
var step = 0;
|
|
386
|
+
var findFlag = false;
|
|
387
|
+
while ((tmpSc = tmpSc.get(sentinel)) !== undefined && !findFlag) {
|
|
388
|
+
// Where object last appeared in the ref tree
|
|
389
|
+
var pos = tmpSc.get(object);
|
|
390
|
+
step += 1;
|
|
391
|
+
if (typeof pos !== 'undefined') {
|
|
392
|
+
if (pos === step) {
|
|
393
|
+
throw new RangeError('Cyclic object value');
|
|
394
|
+
} else {
|
|
395
|
+
findFlag = true; // Break while
|
|
396
|
+
}
|
|
397
|
+
}
|
|
398
|
+
if (typeof tmpSc.get(sentinel) === 'undefined') {
|
|
399
|
+
step = 0;
|
|
400
|
+
}
|
|
383
401
|
}
|
|
384
402
|
|
|
385
403
|
if (typeof filter === 'function') {
|
|
@@ -406,6 +424,14 @@ var stringify = function stringify(
|
|
|
406
424
|
if (isNonNullishPrimitive(obj) || utils.isBuffer(obj)) {
|
|
407
425
|
if (encoder) {
|
|
408
426
|
var keyValue = encodeValuesOnly ? prefix : encoder(prefix, defaults.encoder, charset, 'key', format);
|
|
427
|
+
if (generateArrayPrefix === 'comma' && encodeValuesOnly) {
|
|
428
|
+
var valuesArray = split.call(String(obj), ',');
|
|
429
|
+
var valuesJoined = '';
|
|
430
|
+
for (var i = 0; i < valuesArray.length; ++i) {
|
|
431
|
+
valuesJoined += (i === 0 ? '' : ',') + formatter(encoder(valuesArray[i], defaults.encoder, charset, 'value', format));
|
|
432
|
+
}
|
|
433
|
+
return [formatter(keyValue) + '=' + valuesJoined];
|
|
434
|
+
}
|
|
409
435
|
return [formatter(keyValue) + '=' + formatter(encoder(obj, defaults.encoder, charset, 'value', format))];
|
|
410
436
|
}
|
|
411
437
|
return [formatter(prefix) + '=' + formatter(String(obj))];
|
|
@@ -428,8 +454,8 @@ var stringify = function stringify(
|
|
|
428
454
|
objKeys = sort ? keys.sort(sort) : keys;
|
|
429
455
|
}
|
|
430
456
|
|
|
431
|
-
for (var
|
|
432
|
-
var key = objKeys[
|
|
457
|
+
for (var j = 0; j < objKeys.length; ++j) {
|
|
458
|
+
var key = objKeys[j];
|
|
433
459
|
var value = typeof key === 'object' && key.value !== undefined ? key.value : obj[key];
|
|
434
460
|
|
|
435
461
|
if (skipNulls && value === null) {
|
|
@@ -440,7 +466,9 @@ var stringify = function stringify(
|
|
|
440
466
|
? typeof generateArrayPrefix === 'function' ? generateArrayPrefix(prefix, key) : prefix
|
|
441
467
|
: prefix + (allowDots ? '.' + key : '[' + key + ']');
|
|
442
468
|
|
|
443
|
-
sideChannel.set(object,
|
|
469
|
+
sideChannel.set(object, step);
|
|
470
|
+
var valueSideChannel = getSideChannel();
|
|
471
|
+
valueSideChannel.set(sentinel, sideChannel);
|
|
444
472
|
pushToArray(values, stringify(
|
|
445
473
|
value,
|
|
446
474
|
keyPrefix,
|
|
@@ -456,7 +484,7 @@ var stringify = function stringify(
|
|
|
456
484
|
formatter,
|
|
457
485
|
encodeValuesOnly,
|
|
458
486
|
charset,
|
|
459
|
-
|
|
487
|
+
valueSideChannel
|
|
460
488
|
));
|
|
461
489
|
}
|
|
462
490
|
|
|
@@ -772,6 +800,7 @@ var encode = function encode(str, defaultEncoder, charset, kind, format) {
|
|
|
772
800
|
|
|
773
801
|
i += 1;
|
|
774
802
|
c = 0x10000 + (((c & 0x3FF) << 10) | (string.charCodeAt(i) & 0x3FF));
|
|
803
|
+
/* eslint operator-linebreak: [2, "before"] */
|
|
775
804
|
out += hexTable[0xF0 | (c >> 18)]
|
|
776
805
|
+ hexTable[0x80 | ((c >> 12) & 0x3F)]
|
|
777
806
|
+ hexTable[0x80 | ((c >> 6) & 0x3F)]
|
|
@@ -1385,17 +1414,29 @@ var hasWeakMap = typeof WeakMap === 'function' && WeakMap.prototype;
|
|
|
1385
1414
|
var weakMapHas = hasWeakMap ? WeakMap.prototype.has : null;
|
|
1386
1415
|
var hasWeakSet = typeof WeakSet === 'function' && WeakSet.prototype;
|
|
1387
1416
|
var weakSetHas = hasWeakSet ? WeakSet.prototype.has : null;
|
|
1417
|
+
var hasWeakRef = typeof WeakRef === 'function' && WeakRef.prototype;
|
|
1418
|
+
var weakRefDeref = hasWeakRef ? WeakRef.prototype.deref : null;
|
|
1388
1419
|
var booleanValueOf = Boolean.prototype.valueOf;
|
|
1389
1420
|
var objectToString = Object.prototype.toString;
|
|
1390
1421
|
var functionToString = Function.prototype.toString;
|
|
1391
1422
|
var match = String.prototype.match;
|
|
1392
1423
|
var bigIntValueOf = typeof BigInt === 'function' ? BigInt.prototype.valueOf : null;
|
|
1393
1424
|
var gOPS = Object.getOwnPropertySymbols;
|
|
1394
|
-
var symToString = typeof Symbol === 'function' ? Symbol.prototype.toString : null;
|
|
1425
|
+
var symToString = typeof Symbol === 'function' && typeof Symbol.iterator === 'symbol' ? Symbol.prototype.toString : null;
|
|
1426
|
+
var hasShammedSymbols = typeof Symbol === 'function' && typeof Symbol.iterator === 'object';
|
|
1395
1427
|
var isEnumerable = Object.prototype.propertyIsEnumerable;
|
|
1396
1428
|
|
|
1429
|
+
var gPO = (typeof Reflect === 'function' ? Reflect.getPrototypeOf : Object.getPrototypeOf) || (
|
|
1430
|
+
[].__proto__ === Array.prototype // eslint-disable-line no-proto
|
|
1431
|
+
? function (O) {
|
|
1432
|
+
return O.__proto__; // eslint-disable-line no-proto
|
|
1433
|
+
}
|
|
1434
|
+
: null
|
|
1435
|
+
);
|
|
1436
|
+
|
|
1397
1437
|
var inspectCustom = require('./util.inspect').custom;
|
|
1398
1438
|
var inspectSymbol = inspectCustom && isSymbol(inspectCustom) ? inspectCustom : null;
|
|
1439
|
+
var toStringTag = typeof Symbol === 'function' && typeof Symbol.toStringTag !== 'undefined' ? Symbol.toStringTag : null;
|
|
1399
1440
|
|
|
1400
1441
|
module.exports = function inspect_(obj, options, depth, seen) {
|
|
1401
1442
|
var opts = options || {};
|
|
@@ -1412,8 +1453,8 @@ module.exports = function inspect_(obj, options, depth, seen) {
|
|
|
1412
1453
|
throw new TypeError('option "maxStringLength", if provided, must be a positive integer, Infinity, or `null`');
|
|
1413
1454
|
}
|
|
1414
1455
|
var customInspect = has(opts, 'customInspect') ? opts.customInspect : true;
|
|
1415
|
-
if (typeof customInspect !== 'boolean') {
|
|
1416
|
-
throw new TypeError('option "customInspect", if provided, must be `true` or `
|
|
1456
|
+
if (typeof customInspect !== 'boolean' && customInspect !== 'symbol') {
|
|
1457
|
+
throw new TypeError('option "customInspect", if provided, must be `true`, `false`, or `\'symbol\'`');
|
|
1417
1458
|
}
|
|
1418
1459
|
|
|
1419
1460
|
if (
|
|
@@ -1485,8 +1526,8 @@ module.exports = function inspect_(obj, options, depth, seen) {
|
|
|
1485
1526
|
return '[Function' + (name ? ': ' + name : ' (anonymous)') + ']' + (keys.length > 0 ? ' { ' + keys.join(', ') + ' }' : '');
|
|
1486
1527
|
}
|
|
1487
1528
|
if (isSymbol(obj)) {
|
|
1488
|
-
var symString = symToString.call(obj);
|
|
1489
|
-
return typeof obj === 'object' ? markBoxed(symString) : symString;
|
|
1529
|
+
var symString = hasShammedSymbols ? String(obj).replace(/^(Symbol\(.*\))_[^)]*$/, '$1') : symToString.call(obj);
|
|
1530
|
+
return typeof obj === 'object' && !hasShammedSymbols ? markBoxed(symString) : symString;
|
|
1490
1531
|
}
|
|
1491
1532
|
if (isElement(obj)) {
|
|
1492
1533
|
var s = '<' + String(obj.nodeName).toLowerCase();
|
|
@@ -1515,7 +1556,7 @@ module.exports = function inspect_(obj, options, depth, seen) {
|
|
|
1515
1556
|
if (typeof obj === 'object' && customInspect) {
|
|
1516
1557
|
if (inspectSymbol && typeof obj[inspectSymbol] === 'function') {
|
|
1517
1558
|
return obj[inspectSymbol]();
|
|
1518
|
-
} else if (typeof obj.inspect === 'function') {
|
|
1559
|
+
} else if (customInspect !== 'symbol' && typeof obj.inspect === 'function') {
|
|
1519
1560
|
return obj.inspect();
|
|
1520
1561
|
}
|
|
1521
1562
|
}
|
|
@@ -1539,6 +1580,9 @@ module.exports = function inspect_(obj, options, depth, seen) {
|
|
|
1539
1580
|
if (isWeakSet(obj)) {
|
|
1540
1581
|
return weakCollectionOf('WeakSet');
|
|
1541
1582
|
}
|
|
1583
|
+
if (isWeakRef(obj)) {
|
|
1584
|
+
return weakCollectionOf('WeakRef');
|
|
1585
|
+
}
|
|
1542
1586
|
if (isNumber(obj)) {
|
|
1543
1587
|
return markBoxed(inspect(Number(obj)));
|
|
1544
1588
|
}
|
|
@@ -1553,11 +1597,16 @@ module.exports = function inspect_(obj, options, depth, seen) {
|
|
|
1553
1597
|
}
|
|
1554
1598
|
if (!isDate(obj) && !isRegExp(obj)) {
|
|
1555
1599
|
var ys = arrObjKeys(obj, inspect);
|
|
1556
|
-
|
|
1600
|
+
var isPlainObject = gPO ? gPO(obj) === Object.prototype : obj instanceof Object || obj.constructor === Object;
|
|
1601
|
+
var protoTag = obj instanceof Object ? '' : 'null prototype';
|
|
1602
|
+
var stringTag = !isPlainObject && toStringTag && Object(obj) === obj && toStringTag in obj ? toStr(obj).slice(8, -1) : protoTag ? 'Object' : '';
|
|
1603
|
+
var constructorTag = isPlainObject || typeof obj.constructor !== 'function' ? '' : obj.constructor.name ? obj.constructor.name + ' ' : '';
|
|
1604
|
+
var tag = constructorTag + (stringTag || protoTag ? '[' + [].concat(stringTag || [], protoTag || []).join(': ') + '] ' : '');
|
|
1605
|
+
if (ys.length === 0) { return tag + '{}'; }
|
|
1557
1606
|
if (indent) {
|
|
1558
|
-
return '{' + indentedJoin(ys, indent) + '}';
|
|
1607
|
+
return tag + '{' + indentedJoin(ys, indent) + '}';
|
|
1559
1608
|
}
|
|
1560
|
-
return '{ ' + ys.join(', ') + ' }';
|
|
1609
|
+
return tag + '{ ' + ys.join(', ') + ' }';
|
|
1561
1610
|
}
|
|
1562
1611
|
return String(obj);
|
|
1563
1612
|
};
|
|
@@ -1571,15 +1620,42 @@ function quote(s) {
|
|
|
1571
1620
|
return String(s).replace(/"/g, '"');
|
|
1572
1621
|
}
|
|
1573
1622
|
|
|
1574
|
-
function isArray(obj) { return toStr(obj) === '[object Array]'; }
|
|
1575
|
-
function isDate(obj) { return toStr(obj) === '[object Date]'; }
|
|
1576
|
-
function isRegExp(obj) { return toStr(obj) === '[object RegExp]'; }
|
|
1577
|
-
function isError(obj) { return toStr(obj) === '[object Error]'; }
|
|
1578
|
-
function
|
|
1579
|
-
function
|
|
1580
|
-
function
|
|
1581
|
-
|
|
1582
|
-
|
|
1623
|
+
function isArray(obj) { return toStr(obj) === '[object Array]' && (!toStringTag || !(typeof obj === 'object' && toStringTag in obj)); }
|
|
1624
|
+
function isDate(obj) { return toStr(obj) === '[object Date]' && (!toStringTag || !(typeof obj === 'object' && toStringTag in obj)); }
|
|
1625
|
+
function isRegExp(obj) { return toStr(obj) === '[object RegExp]' && (!toStringTag || !(typeof obj === 'object' && toStringTag in obj)); }
|
|
1626
|
+
function isError(obj) { return toStr(obj) === '[object Error]' && (!toStringTag || !(typeof obj === 'object' && toStringTag in obj)); }
|
|
1627
|
+
function isString(obj) { return toStr(obj) === '[object String]' && (!toStringTag || !(typeof obj === 'object' && toStringTag in obj)); }
|
|
1628
|
+
function isNumber(obj) { return toStr(obj) === '[object Number]' && (!toStringTag || !(typeof obj === 'object' && toStringTag in obj)); }
|
|
1629
|
+
function isBoolean(obj) { return toStr(obj) === '[object Boolean]' && (!toStringTag || !(typeof obj === 'object' && toStringTag in obj)); }
|
|
1630
|
+
|
|
1631
|
+
// Symbol and BigInt do have Symbol.toStringTag by spec, so that can't be used to eliminate false positives
|
|
1632
|
+
function isSymbol(obj) {
|
|
1633
|
+
if (hasShammedSymbols) {
|
|
1634
|
+
return obj && typeof obj === 'object' && obj instanceof Symbol;
|
|
1635
|
+
}
|
|
1636
|
+
if (typeof obj === 'symbol') {
|
|
1637
|
+
return true;
|
|
1638
|
+
}
|
|
1639
|
+
if (!obj || typeof obj !== 'object' || !symToString) {
|
|
1640
|
+
return false;
|
|
1641
|
+
}
|
|
1642
|
+
try {
|
|
1643
|
+
symToString.call(obj);
|
|
1644
|
+
return true;
|
|
1645
|
+
} catch (e) {}
|
|
1646
|
+
return false;
|
|
1647
|
+
}
|
|
1648
|
+
|
|
1649
|
+
function isBigInt(obj) {
|
|
1650
|
+
if (!obj || typeof obj !== 'object' || !bigIntValueOf) {
|
|
1651
|
+
return false;
|
|
1652
|
+
}
|
|
1653
|
+
try {
|
|
1654
|
+
bigIntValueOf.call(obj);
|
|
1655
|
+
return true;
|
|
1656
|
+
} catch (e) {}
|
|
1657
|
+
return false;
|
|
1658
|
+
}
|
|
1583
1659
|
|
|
1584
1660
|
var hasOwn = Object.prototype.hasOwnProperty || function (key) { return key in this; };
|
|
1585
1661
|
function has(obj, key) {
|
|
@@ -1637,6 +1713,17 @@ function isWeakMap(x) {
|
|
|
1637
1713
|
return false;
|
|
1638
1714
|
}
|
|
1639
1715
|
|
|
1716
|
+
function isWeakRef(x) {
|
|
1717
|
+
if (!weakRefDeref || !x || typeof x !== 'object') {
|
|
1718
|
+
return false;
|
|
1719
|
+
}
|
|
1720
|
+
try {
|
|
1721
|
+
weakRefDeref.call(x);
|
|
1722
|
+
return true;
|
|
1723
|
+
} catch (e) {}
|
|
1724
|
+
return false;
|
|
1725
|
+
}
|
|
1726
|
+
|
|
1640
1727
|
function isSet(x) {
|
|
1641
1728
|
if (!setSize || !x || typeof x !== 'object') {
|
|
1642
1729
|
return false;
|
|
@@ -1753,17 +1840,28 @@ function arrObjKeys(obj, inspect) {
|
|
|
1753
1840
|
xs[i] = has(obj, i) ? inspect(obj[i], obj) : '';
|
|
1754
1841
|
}
|
|
1755
1842
|
}
|
|
1843
|
+
var syms = typeof gOPS === 'function' ? gOPS(obj) : [];
|
|
1844
|
+
var symMap;
|
|
1845
|
+
if (hasShammedSymbols) {
|
|
1846
|
+
symMap = {};
|
|
1847
|
+
for (var k = 0; k < syms.length; k++) {
|
|
1848
|
+
symMap['$' + syms[k]] = syms[k];
|
|
1849
|
+
}
|
|
1850
|
+
}
|
|
1851
|
+
|
|
1756
1852
|
for (var key in obj) { // eslint-disable-line no-restricted-syntax
|
|
1757
1853
|
if (!has(obj, key)) { continue; } // eslint-disable-line no-restricted-syntax, no-continue
|
|
1758
1854
|
if (isArr && String(Number(key)) === key && key < obj.length) { continue; } // eslint-disable-line no-restricted-syntax, no-continue
|
|
1759
|
-
if (
|
|
1855
|
+
if (hasShammedSymbols && symMap['$' + key] instanceof Symbol) {
|
|
1856
|
+
// this is to prevent shammed Symbols, which are stored as strings, from being included in the string key section
|
|
1857
|
+
continue; // eslint-disable-line no-restricted-syntax, no-continue
|
|
1858
|
+
} else if ((/[^\w$]/).test(key)) {
|
|
1760
1859
|
xs.push(inspect(key, obj) + ': ' + inspect(obj[key], obj));
|
|
1761
1860
|
} else {
|
|
1762
1861
|
xs.push(key + ': ' + inspect(obj[key], obj));
|
|
1763
1862
|
}
|
|
1764
1863
|
}
|
|
1765
1864
|
if (typeof gOPS === 'function') {
|
|
1766
|
-
var syms = gOPS(obj);
|
|
1767
1865
|
for (var j = 0; j < syms.length; j++) {
|
|
1768
1866
|
if (isEnumerable.call(obj, syms[j])) {
|
|
1769
1867
|
xs.push('[' + inspect(syms[j]) + ']: ' + inspect(obj[syms[j]], obj));
|
package/lib/stringify.js
CHANGED
|
@@ -19,6 +19,7 @@ var arrayPrefixGenerators = {
|
|
|
19
19
|
};
|
|
20
20
|
|
|
21
21
|
var isArray = Array.isArray;
|
|
22
|
+
var split = String.prototype.split;
|
|
22
23
|
var push = Array.prototype.push;
|
|
23
24
|
var pushToArray = function (arr, valueOrArray) {
|
|
24
25
|
push.apply(arr, isArray(valueOrArray) ? valueOrArray : [valueOrArray]);
|
|
@@ -55,6 +56,8 @@ var isNonNullishPrimitive = function isNonNullishPrimitive(v) {
|
|
|
55
56
|
|| typeof v === 'bigint';
|
|
56
57
|
};
|
|
57
58
|
|
|
59
|
+
var sentinel = {};
|
|
60
|
+
|
|
58
61
|
var stringify = function stringify(
|
|
59
62
|
object,
|
|
60
63
|
prefix,
|
|
@@ -74,8 +77,23 @@ var stringify = function stringify(
|
|
|
74
77
|
) {
|
|
75
78
|
var obj = object;
|
|
76
79
|
|
|
77
|
-
|
|
78
|
-
|
|
80
|
+
var tmpSc = sideChannel;
|
|
81
|
+
var step = 0;
|
|
82
|
+
var findFlag = false;
|
|
83
|
+
while ((tmpSc = tmpSc.get(sentinel)) !== undefined && !findFlag) {
|
|
84
|
+
// Where object last appeared in the ref tree
|
|
85
|
+
var pos = tmpSc.get(object);
|
|
86
|
+
step += 1;
|
|
87
|
+
if (typeof pos !== 'undefined') {
|
|
88
|
+
if (pos === step) {
|
|
89
|
+
throw new RangeError('Cyclic object value');
|
|
90
|
+
} else {
|
|
91
|
+
findFlag = true; // Break while
|
|
92
|
+
}
|
|
93
|
+
}
|
|
94
|
+
if (typeof tmpSc.get(sentinel) === 'undefined') {
|
|
95
|
+
step = 0;
|
|
96
|
+
}
|
|
79
97
|
}
|
|
80
98
|
|
|
81
99
|
if (typeof filter === 'function') {
|
|
@@ -102,6 +120,14 @@ var stringify = function stringify(
|
|
|
102
120
|
if (isNonNullishPrimitive(obj) || utils.isBuffer(obj)) {
|
|
103
121
|
if (encoder) {
|
|
104
122
|
var keyValue = encodeValuesOnly ? prefix : encoder(prefix, defaults.encoder, charset, 'key', format);
|
|
123
|
+
if (generateArrayPrefix === 'comma' && encodeValuesOnly) {
|
|
124
|
+
var valuesArray = split.call(String(obj), ',');
|
|
125
|
+
var valuesJoined = '';
|
|
126
|
+
for (var i = 0; i < valuesArray.length; ++i) {
|
|
127
|
+
valuesJoined += (i === 0 ? '' : ',') + formatter(encoder(valuesArray[i], defaults.encoder, charset, 'value', format));
|
|
128
|
+
}
|
|
129
|
+
return [formatter(keyValue) + '=' + valuesJoined];
|
|
130
|
+
}
|
|
105
131
|
return [formatter(keyValue) + '=' + formatter(encoder(obj, defaults.encoder, charset, 'value', format))];
|
|
106
132
|
}
|
|
107
133
|
return [formatter(prefix) + '=' + formatter(String(obj))];
|
|
@@ -124,8 +150,8 @@ var stringify = function stringify(
|
|
|
124
150
|
objKeys = sort ? keys.sort(sort) : keys;
|
|
125
151
|
}
|
|
126
152
|
|
|
127
|
-
for (var
|
|
128
|
-
var key = objKeys[
|
|
153
|
+
for (var j = 0; j < objKeys.length; ++j) {
|
|
154
|
+
var key = objKeys[j];
|
|
129
155
|
var value = typeof key === 'object' && key.value !== undefined ? key.value : obj[key];
|
|
130
156
|
|
|
131
157
|
if (skipNulls && value === null) {
|
|
@@ -136,8 +162,9 @@ var stringify = function stringify(
|
|
|
136
162
|
? typeof generateArrayPrefix === 'function' ? generateArrayPrefix(prefix, key) : prefix
|
|
137
163
|
: prefix + (allowDots ? '.' + key : '[' + key + ']');
|
|
138
164
|
|
|
139
|
-
sideChannel.set(object,
|
|
165
|
+
sideChannel.set(object, step);
|
|
140
166
|
var valueSideChannel = getSideChannel();
|
|
167
|
+
valueSideChannel.set(sentinel, sideChannel);
|
|
141
168
|
pushToArray(values, stringify(
|
|
142
169
|
value,
|
|
143
170
|
keyPrefix,
|
package/lib/utils.js
CHANGED
|
@@ -177,6 +177,7 @@ var encode = function encode(str, defaultEncoder, charset, kind, format) {
|
|
|
177
177
|
|
|
178
178
|
i += 1;
|
|
179
179
|
c = 0x10000 + (((c & 0x3FF) << 10) | (string.charCodeAt(i) & 0x3FF));
|
|
180
|
+
/* eslint operator-linebreak: [2, "before"] */
|
|
180
181
|
out += hexTable[0xF0 | (c >> 18)]
|
|
181
182
|
+ hexTable[0x80 | ((c >> 12) & 0x3F)]
|
|
182
183
|
+ hexTable[0x80 | ((c >> 6) & 0x3F)]
|
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.10.
|
|
5
|
+
"version": "6.10.2",
|
|
6
6
|
"repository": {
|
|
7
7
|
"type": "git",
|
|
8
8
|
"url": "https://github.com/ljharb/qs.git"
|
|
@@ -33,11 +33,11 @@
|
|
|
33
33
|
"side-channel": "^1.0.4"
|
|
34
34
|
},
|
|
35
35
|
"devDependencies": {
|
|
36
|
-
"@ljharb/eslint-config": "^
|
|
37
|
-
"aud": "^1.1.
|
|
36
|
+
"@ljharb/eslint-config": "^20.0.0",
|
|
37
|
+
"aud": "^1.1.5",
|
|
38
38
|
"browserify": "^16.5.2",
|
|
39
39
|
"eclint": "^2.8.1",
|
|
40
|
-
"eslint": "^
|
|
40
|
+
"eslint": "^8.4.0",
|
|
41
41
|
"evalmd": "^0.0.19",
|
|
42
42
|
"for-each": "^0.3.3",
|
|
43
43
|
"has-symbols": "^1.0.2",
|
|
@@ -45,21 +45,22 @@
|
|
|
45
45
|
"in-publish": "^2.0.1",
|
|
46
46
|
"mkdirp": "^0.5.5",
|
|
47
47
|
"nyc": "^10.3.2",
|
|
48
|
-
"object-inspect": "^1.
|
|
48
|
+
"object-inspect": "^1.11.0",
|
|
49
49
|
"qs-iconv": "^1.0.4",
|
|
50
|
-
"safe-publish-latest": "^
|
|
50
|
+
"safe-publish-latest": "^2.0.0",
|
|
51
51
|
"safer-buffer": "^2.1.2",
|
|
52
|
-
"tape": "^5.
|
|
52
|
+
"tape": "^5.3.2"
|
|
53
53
|
},
|
|
54
54
|
"scripts": {
|
|
55
|
-
"
|
|
55
|
+
"prepublishOnly": "safe-publish-latest && npm run dist",
|
|
56
|
+
"prepublish": "not-in-publish || npm run prepublishOnly",
|
|
56
57
|
"pretest": "npm run --silent readme && npm run --silent lint",
|
|
57
58
|
"test": "npm run tests-only",
|
|
58
59
|
"tests-only": "nyc tape 'test/**/*.js'",
|
|
59
60
|
"posttest": "aud --production",
|
|
60
61
|
"readme": "evalmd README.md",
|
|
61
62
|
"postlint": "eclint check * lib/* test/* !dist/*",
|
|
62
|
-
"lint": "eslint
|
|
63
|
+
"lint": "eslint .",
|
|
63
64
|
"dist": "mkdirp dist && browserify --standalone Qs lib/index.js > dist/qs.js"
|
|
64
65
|
},
|
|
65
66
|
"license": "BSD-3-Clause",
|
package/test/stringify.js
CHANGED
|
@@ -132,10 +132,10 @@ test('stringify()', function (t) {
|
|
|
132
132
|
});
|
|
133
133
|
|
|
134
134
|
t.test('stringifies a nested array value', function (st) {
|
|
135
|
-
st.equal(qs.stringify({ a: { b: ['c', 'd'] } }, { arrayFormat: 'indices' }), 'a
|
|
136
|
-
st.equal(qs.stringify({ a: { b: ['c', 'd'] } }, { arrayFormat: 'brackets' }), 'a
|
|
137
|
-
st.equal(qs.stringify({ a: { b: ['c', 'd'] } }, { arrayFormat: 'comma' }), 'a
|
|
138
|
-
st.equal(qs.stringify({ a: { b: ['c', 'd'] } }), 'a
|
|
135
|
+
st.equal(qs.stringify({ a: { b: ['c', 'd'] } }, { encodeValuesOnly: true, arrayFormat: 'indices' }), 'a[b][0]=c&a[b][1]=d');
|
|
136
|
+
st.equal(qs.stringify({ a: { b: ['c', 'd'] } }, { encodeValuesOnly: true, arrayFormat: 'brackets' }), 'a[b][]=c&a[b][]=d');
|
|
137
|
+
st.equal(qs.stringify({ a: { b: ['c', 'd'] } }, { encodeValuesOnly: true, arrayFormat: 'comma' }), 'a[b]=c,d');
|
|
138
|
+
st.equal(qs.stringify({ a: { b: ['c', 'd'] } }, { encodeValuesOnly: true }), 'a[b][0]=c&a[b][1]=d');
|
|
139
139
|
st.end();
|
|
140
140
|
});
|
|
141
141
|
|
|
@@ -143,7 +143,7 @@ test('stringify()', function (t) {
|
|
|
143
143
|
st.equal(
|
|
144
144
|
qs.stringify(
|
|
145
145
|
{ a: { b: ['c', 'd'] } },
|
|
146
|
-
{ allowDots: true,
|
|
146
|
+
{ allowDots: true, encodeValuesOnly: true, arrayFormat: 'indices' }
|
|
147
147
|
),
|
|
148
148
|
'a.b[0]=c&a.b[1]=d',
|
|
149
149
|
'indices: stringifies with dots + indices'
|
|
@@ -151,7 +151,7 @@ test('stringify()', function (t) {
|
|
|
151
151
|
st.equal(
|
|
152
152
|
qs.stringify(
|
|
153
153
|
{ a: { b: ['c', 'd'] } },
|
|
154
|
-
{ allowDots: true,
|
|
154
|
+
{ allowDots: true, encodeValuesOnly: true, arrayFormat: 'brackets' }
|
|
155
155
|
),
|
|
156
156
|
'a.b[]=c&a.b[]=d',
|
|
157
157
|
'brackets: stringifies with dots + brackets'
|
|
@@ -159,7 +159,7 @@ test('stringify()', function (t) {
|
|
|
159
159
|
st.equal(
|
|
160
160
|
qs.stringify(
|
|
161
161
|
{ a: { b: ['c', 'd'] } },
|
|
162
|
-
{ allowDots: true,
|
|
162
|
+
{ allowDots: true, encodeValuesOnly: true, arrayFormat: 'comma' }
|
|
163
163
|
),
|
|
164
164
|
'a.b=c,d',
|
|
165
165
|
'comma: stringifies with dots + comma'
|
|
@@ -167,7 +167,7 @@ test('stringify()', function (t) {
|
|
|
167
167
|
st.equal(
|
|
168
168
|
qs.stringify(
|
|
169
169
|
{ a: { b: ['c', 'd'] } },
|
|
170
|
-
{ allowDots: true,
|
|
170
|
+
{ allowDots: true, encodeValuesOnly: true }
|
|
171
171
|
),
|
|
172
172
|
'a.b[0]=c&a.b[1]=d',
|
|
173
173
|
'default: stringifies with dots + indices'
|
|
@@ -215,17 +215,23 @@ test('stringify()', function (t) {
|
|
|
215
215
|
|
|
216
216
|
t.test('stringifies an array with mixed objects and primitives', function (st) {
|
|
217
217
|
st.equal(
|
|
218
|
-
qs.stringify({ a: [{ b: 1 }, 2, 3] }, {
|
|
218
|
+
qs.stringify({ a: [{ b: 1 }, 2, 3] }, { encodeValuesOnly: true, arrayFormat: 'indices' }),
|
|
219
219
|
'a[0][b]=1&a[1]=2&a[2]=3',
|
|
220
220
|
'indices => indices'
|
|
221
221
|
);
|
|
222
222
|
st.equal(
|
|
223
|
-
qs.stringify({ a: [{ b: 1 }, 2, 3] }, {
|
|
223
|
+
qs.stringify({ a: [{ b: 1 }, 2, 3] }, { encodeValuesOnly: true, arrayFormat: 'brackets' }),
|
|
224
224
|
'a[][b]=1&a[]=2&a[]=3',
|
|
225
225
|
'brackets => brackets'
|
|
226
226
|
);
|
|
227
227
|
st.equal(
|
|
228
|
-
qs.stringify({ a: [{ b: 1 }, 2, 3] }, {
|
|
228
|
+
qs.stringify({ a: [{ b: 1 }, 2, 3] }, { encodeValuesOnly: true, arrayFormat: 'comma' }),
|
|
229
|
+
'???',
|
|
230
|
+
'brackets => brackets',
|
|
231
|
+
{ skip: 'TODO: figure out what this should do' }
|
|
232
|
+
);
|
|
233
|
+
st.equal(
|
|
234
|
+
qs.stringify({ a: [{ b: 1 }, 2, 3] }, { encodeValuesOnly: true }),
|
|
229
235
|
'a[0][b]=1&a[1]=2&a[2]=3',
|
|
230
236
|
'default => indices'
|
|
231
237
|
);
|
|
@@ -448,7 +454,7 @@ test('stringify()', function (t) {
|
|
|
448
454
|
|
|
449
455
|
st['throws'](
|
|
450
456
|
function () { qs.stringify({ 'foo[bar]': 'baz', 'foo[baz]': a }); },
|
|
451
|
-
RangeError
|
|
457
|
+
/RangeError: Cyclic object value/,
|
|
452
458
|
'cyclic values throw'
|
|
453
459
|
);
|
|
454
460
|
|
|
@@ -458,10 +464,16 @@ test('stringify()', function (t) {
|
|
|
458
464
|
circular.a = circular;
|
|
459
465
|
st['throws'](
|
|
460
466
|
function () { qs.stringify(circular); },
|
|
461
|
-
RangeError
|
|
467
|
+
/RangeError: Cyclic object value/,
|
|
462
468
|
'cyclic values throw'
|
|
463
469
|
);
|
|
464
470
|
|
|
471
|
+
var arr = ['a'];
|
|
472
|
+
st.doesNotThrow(
|
|
473
|
+
function () { qs.stringify({ x: arr, y: arr }); },
|
|
474
|
+
'non-cyclic values do not throw'
|
|
475
|
+
);
|
|
476
|
+
|
|
465
477
|
st.end();
|
|
466
478
|
});
|
|
467
479
|
|
|
@@ -829,7 +841,12 @@ test('stringify()', function (t) {
|
|
|
829
841
|
st.equal(qs.stringify(withArray, { encode: false }), 'a[b][0][c]=d&a[b][0][e]=f', 'array, no arrayFormat');
|
|
830
842
|
st.equal(qs.stringify(withArray, { encode: false, arrayFormat: 'bracket' }), 'a[b][0][c]=d&a[b][0][e]=f', 'array, bracket');
|
|
831
843
|
st.equal(qs.stringify(withArray, { encode: false, arrayFormat: 'indices' }), 'a[b][0][c]=d&a[b][0][e]=f', 'array, indices');
|
|
832
|
-
st.equal(
|
|
844
|
+
st.equal(
|
|
845
|
+
qs.stringify(withArray, { encode: false, arrayFormat: 'comma' }),
|
|
846
|
+
'???',
|
|
847
|
+
'array, comma',
|
|
848
|
+
{ skip: 'TODO: figure out what this should do' }
|
|
849
|
+
);
|
|
833
850
|
|
|
834
851
|
st.end();
|
|
835
852
|
});
|