query-string 9.3.1 → 9.5.1

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.
Files changed (3) hide show
  1. package/base.js +89 -49
  2. package/package.json +2 -2
  3. package/readme.md +3 -0
package/base.js CHANGED
@@ -24,15 +24,12 @@ function encoderForArrayFormat(options) {
24
24
  }
25
25
 
26
26
  if (value === null) {
27
- return [
28
- ...result, [encode(key, options), '[', index, ']'].join(''),
29
- ];
27
+ result.push([encode(key, options), '[', index, ']'].join(''));
28
+ return result;
30
29
  }
31
30
 
32
- return [
33
- ...result,
34
- [encode(key, options), '[', encode(index, options), ']=', encode(value, options)].join(''),
35
- ];
31
+ result.push([encode(key, options), '[', encode(index, options), ']=', encode(value, options)].join(''));
32
+ return result;
36
33
  };
37
34
  }
38
35
 
@@ -47,16 +44,12 @@ function encoderForArrayFormat(options) {
47
44
  }
48
45
 
49
46
  if (value === null) {
50
- return [
51
- ...result,
52
- [encode(key, options), '[]'].join(''),
53
- ];
47
+ result.push([encode(key, options), '[]'].join(''));
48
+ return result;
54
49
  }
55
50
 
56
- return [
57
- ...result,
58
- [encode(key, options), '[]=', encode(value, options)].join(''),
59
- ];
51
+ result.push([encode(key, options), '[]=', encode(value, options)].join(''));
52
+ return result;
60
53
  };
61
54
  }
62
55
 
@@ -71,16 +64,12 @@ function encoderForArrayFormat(options) {
71
64
  }
72
65
 
73
66
  if (value === null) {
74
- return [
75
- ...result,
76
- [encode(key, options), ':list='].join(''),
77
- ];
67
+ result.push([encode(key, options), ':list='].join(''));
68
+ return result;
78
69
  }
79
70
 
80
- return [
81
- ...result,
82
- [encode(key, options), ':list=', encode(value, options)].join(''),
83
- ];
71
+ result.push([encode(key, options), ':list=', encode(value, options)].join(''));
72
+ return result;
84
73
  };
85
74
  }
86
75
 
@@ -104,10 +93,12 @@ function encoderForArrayFormat(options) {
104
93
  value = value === null ? '' : value;
105
94
 
106
95
  if (result.length === 0) {
107
- return [[encode(key, options), keyValueSeparator, encode(value, options)].join('')];
96
+ result.push([encode(key, options), keyValueSeparator, encode(value, options)].join(''));
97
+ return result;
108
98
  }
109
99
 
110
- return [[result, encode(value, options)].join(options.arrayFormatSeparator)];
100
+ result.push(encode(value, options));
101
+ return result;
111
102
  };
112
103
  }
113
104
 
@@ -122,16 +113,12 @@ function encoderForArrayFormat(options) {
122
113
  }
123
114
 
124
115
  if (value === null) {
125
- return [
126
- ...result,
127
- encode(key, options),
128
- ];
116
+ result.push(encode(key, options));
117
+ return result;
129
118
  }
130
119
 
131
- return [
132
- ...result,
133
- [encode(key, options), '=', encode(value, options)].join(''),
134
- ];
120
+ result.push([encode(key, options), '=', encode(value, options)].join(''));
121
+ return result;
135
122
  };
136
123
  }
137
124
  }
@@ -175,7 +162,12 @@ function parserForArrayFormat(options) {
175
162
  return;
176
163
  }
177
164
 
178
- accumulator[key] = [...accumulator[key], value];
165
+ if (!Array.isArray(accumulator[key])) {
166
+ accumulator[key] = [accumulator[key], value];
167
+ return;
168
+ }
169
+
170
+ accumulator[key].push(value);
179
171
  };
180
172
  }
181
173
 
@@ -194,7 +186,12 @@ function parserForArrayFormat(options) {
194
186
  return;
195
187
  }
196
188
 
197
- accumulator[key] = [...accumulator[key], value];
189
+ if (!Array.isArray(accumulator[key])) {
190
+ accumulator[key] = [accumulator[key], value];
191
+ return;
192
+ }
193
+
194
+ accumulator[key].push(value);
198
195
  };
199
196
  }
200
197
 
@@ -226,7 +223,13 @@ function parserForArrayFormat(options) {
226
223
  return;
227
224
  }
228
225
 
229
- accumulator[key] = [...accumulator[key], ...arrayValue];
226
+ if (!Array.isArray(accumulator[key])) {
227
+ accumulator[key] = [accumulator[key]];
228
+ }
229
+
230
+ for (const item of arrayValue) {
231
+ accumulator[key].push(item);
232
+ }
230
233
  };
231
234
  }
232
235
 
@@ -237,7 +240,12 @@ function parserForArrayFormat(options) {
237
240
  return;
238
241
  }
239
242
 
240
- accumulator[key] = [...[accumulator[key]].flat(), value];
243
+ if (Array.isArray(accumulator[key])) {
244
+ accumulator[key].push(value);
245
+ return;
246
+ }
247
+
248
+ accumulator[key] = [accumulator[key], value];
241
249
  };
242
250
  }
243
251
  }
@@ -298,6 +306,12 @@ function getHash(url) {
298
306
  return hash;
299
307
  }
300
308
 
309
+ function getUrlWithoutQuery(url) {
310
+ // Avoid `split('?')` so query-heavy URLs don't allocate large arrays.
311
+ const queryStart = url.indexOf('?');
312
+ return queryStart === -1 ? url : url.slice(0, queryStart);
313
+ }
314
+
301
315
  function parseValue(value, options, type) {
302
316
  if (type === 'string' && typeof value === 'string') {
303
317
  return value;
@@ -381,11 +395,27 @@ export function parse(query, options) {
381
395
  return returnValue;
382
396
  }
383
397
 
384
- for (const parameter of query.split('&')) {
385
- if (parameter === '') {
398
+ if (/^&+$/.test(query)) {
399
+ return returnValue;
400
+ }
401
+
402
+ let parameterStart = 0;
403
+ let firstSeparator = query.indexOf('&');
404
+ if (firstSeparator === -1) {
405
+ firstSeparator = query.length;
406
+ }
407
+
408
+ for (let index = firstSeparator; index <= query.length; index++) {
409
+ if (index < query.length && query[index] !== '&') {
386
410
  continue;
387
411
  }
388
412
 
413
+ if (index === parameterStart) {
414
+ parameterStart = index + 1;
415
+ continue;
416
+ }
417
+
418
+ const parameter = query.slice(parameterStart, index);
389
419
  const parameter_ = options.decode ? parameter.replaceAll('+', ' ') : parameter;
390
420
 
391
421
  let [key, value] = splitOnFirst(parameter_, '=');
@@ -398,6 +428,8 @@ export function parse(query, options) {
398
428
  // http://w3.org/TR/2012/WD-url-20120524/#collect-url-parameters
399
429
  value = value === undefined ? null : (['comma', 'separator', 'bracket-separator'].includes(options.arrayFormat) ? value : decode(value, options));
400
430
  formatter(decode(key, options), value, returnValue);
431
+
432
+ parameterStart = index + 1;
401
433
  }
402
434
 
403
435
  for (const [key, value] of Object.entries(returnValue)) {
@@ -498,9 +530,9 @@ export function stringify(object, options) {
498
530
  ).filter(item => item !== undefined);
499
531
  }
500
532
 
501
- return processedArray
502
- .reduce(formatter(key), [])
503
- .join('&');
533
+ const result = processedArray.reduce(formatter(key), []);
534
+ const arrayFormatSeparator = ['comma', 'separator', 'bracket-separator'].includes(options.arrayFormat) ? options.arrayFormatSeparator : '&';
535
+ return result.join(arrayFormatSeparator);
504
536
  }
505
537
 
506
538
  return encode(key, options) + '=' + encode(value, options);
@@ -520,7 +552,7 @@ export function parseUrl(url, options) {
520
552
  }
521
553
 
522
554
  return {
523
- url: url_?.split('?')?.[0] ?? '',
555
+ url: getUrlWithoutQuery(url_ ?? ''),
524
556
  query: parse(extract(url), options),
525
557
  ...(options && options.parseFragmentIdentifier && hash ? {fragmentIdentifier: decode(hash, options)} : {}),
526
558
  };
@@ -534,7 +566,7 @@ export function stringifyUrl(object, options) {
534
566
  ...options,
535
567
  };
536
568
 
537
- const url = removeHash(object.url).split('?')[0] || '';
569
+ const url = getUrlWithoutQuery(removeHash(object.url)) || '';
538
570
  const queryFromUrl = extract(object.url);
539
571
 
540
572
  const query = {
@@ -547,9 +579,14 @@ export function stringifyUrl(object, options) {
547
579
 
548
580
  let hash = getHash(object.url);
549
581
  if (typeof object.fragmentIdentifier === 'string') {
550
- const urlObjectForFragmentEncode = new URL(url);
551
- urlObjectForFragmentEncode.hash = object.fragmentIdentifier;
552
- hash = options[encodeFragmentIdentifier] ? urlObjectForFragmentEncode.hash : `#${object.fragmentIdentifier}`;
582
+ hash = `#${object.fragmentIdentifier}`;
583
+
584
+ if (options[encodeFragmentIdentifier]) {
585
+ // Percent-encode the fragment with a throwaway URL. The fragment percent-encode set does not depend on the scheme, so the caller's URL is deliberately not parsed here; it may not even be parseable.
586
+ const throwawayUrl = new URL('https://query-string.invalid');
587
+ throwawayUrl.hash = hash;
588
+ hash = throwawayUrl.hash;
589
+ }
553
590
  }
554
591
 
555
592
  return `${url}${queryString}${hash}`;
@@ -572,7 +609,10 @@ export function pick(input, filter, options) {
572
609
  }
573
610
 
574
611
  export function exclude(input, filter, options) {
575
- const exclusionFilter = Array.isArray(filter) ? key => !filter.includes(key) : (key, value) => !filter(key, value);
612
+ if (Array.isArray(filter)) {
613
+ const filterSet = new Set(filter);
614
+ return pick(input, key => !filterSet.has(key), options);
615
+ }
576
616
 
577
- return pick(input, exclusionFilter, options);
617
+ return pick(input, (key, value) => !filter(key, value), options);
578
618
  }
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "query-string",
3
- "version": "9.3.1",
3
+ "version": "9.5.1",
4
4
  "description": "Parse and stringify URL query strings",
5
5
  "license": "MIT",
6
6
  "repository": "sindresorhus/query-string",
@@ -46,7 +46,7 @@
46
46
  "filter"
47
47
  ],
48
48
  "dependencies": {
49
- "decode-uri-component": "^0.4.1",
49
+ "decode-uri-component": "^0.5.0",
50
50
  "filter-obj": "^5.1.0",
51
51
  "split-on-first": "^3.0.0"
52
52
  },
package/readme.md CHANGED
@@ -13,6 +13,9 @@ npm install query-string
13
13
 
14
14
  For browser usage, this package targets the latest version of Chrome, Firefox, and Safari.
15
15
 
16
+ > [!TIP]
17
+ > Consider using [`URLSearchParams`](https://developer.mozilla.org/en-US/docs/Web/API/URLSearchParams) for simple use cases. It's a native browser API that handles basic query string operations.
18
+
16
19
  ## Usage
17
20
 
18
21
  ```js