qs 6.9.7 → 6.9.9

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