query-string 9.3.1 → 9.4.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.
Files changed (3) hide show
  1. package/base.js +73 -46
  2. package/package.json +1 -1
  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,21 @@ export function parse(query, options) {
381
395
  return returnValue;
382
396
  }
383
397
 
384
- for (const parameter of query.split('&')) {
385
- if (parameter === '') {
398
+ // Avoid `split('&')` so separator-heavy inputs don't allocate large arrays of empty strings.
399
+ let parameterStart = 0;
400
+
401
+ for (let index = 0; index <= query.length; index++) {
402
+ if (index < query.length && query[index] !== '&') {
403
+ continue;
404
+ }
405
+
406
+ if (index === parameterStart) {
407
+ parameterStart = index + 1;
386
408
  continue;
387
409
  }
388
410
 
411
+ const parameter = query.slice(parameterStart, index);
412
+ parameterStart = index + 1;
389
413
  const parameter_ = options.decode ? parameter.replaceAll('+', ' ') : parameter;
390
414
 
391
415
  let [key, value] = splitOnFirst(parameter_, '=');
@@ -498,9 +522,9 @@ export function stringify(object, options) {
498
522
  ).filter(item => item !== undefined);
499
523
  }
500
524
 
501
- return processedArray
502
- .reduce(formatter(key), [])
503
- .join('&');
525
+ const result = processedArray.reduce(formatter(key), []);
526
+ const arrayFormatSeparator = ['comma', 'separator', 'bracket-separator'].includes(options.arrayFormat) ? options.arrayFormatSeparator : '&';
527
+ return result.join(arrayFormatSeparator);
504
528
  }
505
529
 
506
530
  return encode(key, options) + '=' + encode(value, options);
@@ -520,7 +544,7 @@ export function parseUrl(url, options) {
520
544
  }
521
545
 
522
546
  return {
523
- url: url_?.split('?')?.[0] ?? '',
547
+ url: getUrlWithoutQuery(url_ ?? ''),
524
548
  query: parse(extract(url), options),
525
549
  ...(options && options.parseFragmentIdentifier && hash ? {fragmentIdentifier: decode(hash, options)} : {}),
526
550
  };
@@ -534,7 +558,7 @@ export function stringifyUrl(object, options) {
534
558
  ...options,
535
559
  };
536
560
 
537
- const url = removeHash(object.url).split('?')[0] || '';
561
+ const url = getUrlWithoutQuery(removeHash(object.url)) || '';
538
562
  const queryFromUrl = extract(object.url);
539
563
 
540
564
  const query = {
@@ -572,7 +596,10 @@ export function pick(input, filter, options) {
572
596
  }
573
597
 
574
598
  export function exclude(input, filter, options) {
575
- const exclusionFilter = Array.isArray(filter) ? key => !filter.includes(key) : (key, value) => !filter(key, value);
599
+ if (Array.isArray(filter)) {
600
+ const filterSet = new Set(filter);
601
+ return pick(input, key => !filterSet.has(key), options);
602
+ }
576
603
 
577
- return pick(input, exclusionFilter, options);
604
+ return pick(input, (key, value) => !filter(key, value), options);
578
605
  }
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "query-string",
3
- "version": "9.3.1",
3
+ "version": "9.4.0",
4
4
  "description": "Parse and stringify URL query strings",
5
5
  "license": "MIT",
6
6
  "repository": "sindresorhus/query-string",
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