@@ -24,15 +24,12 @@ function encoderForArrayFormat(options) {
2424 }
2525
2626 if ( value === null ) {
27- return [
28- ...result , [ encode ( key , options ) , '[' , index , ']' ] . join ( '' ) ,
29- ] ;
27+ result . push ( [ encode ( key , options ) , '[' , index , ']' ] . join ( '' ) ) ;
28+ return result ;
3029 }
3130
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 ;
3633 } ;
3734 }
3835
@@ -47,16 +44,12 @@ function encoderForArrayFormat(options) {
4744 }
4845
4946 if ( value === null ) {
50- return [
51- ...result ,
52- [ encode ( key , options ) , '[]' ] . join ( '' ) ,
53- ] ;
47+ result . push ( [ encode ( key , options ) , '[]' ] . join ( '' ) ) ;
48+ return result ;
5449 }
5550
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 ;
6053 } ;
6154 }
6255
@@ -71,16 +64,12 @@ function encoderForArrayFormat(options) {
7164 }
7265
7366 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 ;
7869 }
7970
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 ;
8473 } ;
8574 }
8675
@@ -104,10 +93,12 @@ function encoderForArrayFormat(options) {
10493 value = value === null ? '' : value ;
10594
10695 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 ;
10898 }
10999
110- return [ [ result , encode ( value , options ) ] . join ( options . arrayFormatSeparator ) ] ;
100+ result . push ( encode ( value , options ) ) ;
101+ return result ;
111102 } ;
112103 }
113104
@@ -122,16 +113,12 @@ function encoderForArrayFormat(options) {
122113 }
123114
124115 if ( value === null ) {
125- return [
126- ...result ,
127- encode ( key , options ) ,
128- ] ;
116+ result . push ( encode ( key , options ) ) ;
117+ return result ;
129118 }
130119
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 ;
135122 } ;
136123 }
137124 }
@@ -175,7 +162,7 @@ function parserForArrayFormat(options) {
175162 return ;
176163 }
177164
178- accumulator [ key ] = [ ... accumulator [ key ] , value ] ;
165+ accumulator [ key ] . push ( value ) ;
179166 } ;
180167 }
181168
@@ -194,7 +181,7 @@ function parserForArrayFormat(options) {
194181 return ;
195182 }
196183
197- accumulator [ key ] = [ ... accumulator [ key ] , value ] ;
184+ accumulator [ key ] . push ( value ) ;
198185 } ;
199186 }
200187
@@ -226,7 +213,9 @@ function parserForArrayFormat(options) {
226213 return ;
227214 }
228215
229- accumulator [ key ] = [ ...accumulator [ key ] , ...arrayValue ] ;
216+ for ( const item of arrayValue ) {
217+ accumulator [ key ] . push ( item ) ;
218+ }
230219 } ;
231220 }
232221
@@ -237,7 +226,12 @@ function parserForArrayFormat(options) {
237226 return ;
238227 }
239228
240- accumulator [ key ] = [ ...[ accumulator [ key ] ] . flat ( ) , value ] ;
229+ if ( Array . isArray ( accumulator [ key ] ) ) {
230+ accumulator [ key ] . push ( value ) ;
231+ return ;
232+ }
233+
234+ accumulator [ key ] = [ accumulator [ key ] , value ] ;
241235 } ;
242236 }
243237 }
@@ -298,6 +292,12 @@ function getHash(url) {
298292 return hash ;
299293}
300294
295+ function getUrlWithoutQuery ( url ) {
296+ // Avoid `split('?')` so query-heavy URLs don't allocate large arrays.
297+ const queryStart = url . indexOf ( '?' ) ;
298+ return queryStart === - 1 ? url : url . slice ( 0 , queryStart ) ;
299+ }
300+
301301function parseValue ( value , options , type ) {
302302 if ( type === 'string' && typeof value === 'string' ) {
303303 return value ;
@@ -381,11 +381,21 @@ export function parse(query, options) {
381381 return returnValue ;
382382 }
383383
384- for ( const parameter of query . split ( '&' ) ) {
385- if ( parameter === '' ) {
384+ // Avoid `split('&')` so separator-heavy inputs don't allocate large arrays of empty strings.
385+ let parameterStart = 0 ;
386+
387+ for ( let index = 0 ; index <= query . length ; index ++ ) {
388+ if ( index < query . length && query [ index ] !== '&' ) {
386389 continue ;
387390 }
388391
392+ if ( index === parameterStart ) {
393+ parameterStart = index + 1 ;
394+ continue ;
395+ }
396+
397+ const parameter = query . slice ( parameterStart , index ) ;
398+ parameterStart = index + 1 ;
389399 const parameter_ = options . decode ? parameter . replaceAll ( '+' , ' ' ) : parameter ;
390400
391401 let [ key , value ] = splitOnFirst ( parameter_ , '=' ) ;
@@ -498,9 +508,9 @@ export function stringify(object, options) {
498508 ) . filter ( item => item !== undefined ) ;
499509 }
500510
501- return processedArray
502- . reduce ( formatter ( key ) , [ ] )
503- . join ( '&' ) ;
511+ const result = processedArray . reduce ( formatter ( key ) , [ ] ) ;
512+ const arrayFormatSeparator = [ 'comma' , 'separator' , 'bracket-separator' ] . includes ( options . arrayFormat ) ? options . arrayFormatSeparator : '&' ;
513+ return result . join ( arrayFormatSeparator ) ;
504514 }
505515
506516 return encode ( key , options ) + '=' + encode ( value , options ) ;
@@ -520,7 +530,7 @@ export function parseUrl(url, options) {
520530 }
521531
522532 return {
523- url : url_ ?. split ( '?' ) ?. [ 0 ] ?? '' ,
533+ url : getUrlWithoutQuery ( url_ ?? '' ) ,
524534 query : parse ( extract ( url ) , options ) ,
525535 ...( options && options . parseFragmentIdentifier && hash ? { fragmentIdentifier : decode ( hash , options ) } : { } ) ,
526536 } ;
@@ -534,7 +544,7 @@ export function stringifyUrl(object, options) {
534544 ...options ,
535545 } ;
536546
537- const url = removeHash ( object . url ) . split ( '?' ) [ 0 ] || '' ;
547+ const url = getUrlWithoutQuery ( removeHash ( object . url ) ) || '' ;
538548 const queryFromUrl = extract ( object . url ) ;
539549
540550 const query = {
@@ -572,7 +582,10 @@ export function pick(input, filter, options) {
572582}
573583
574584export function exclude ( input , filter , options ) {
575- const exclusionFilter = Array . isArray ( filter ) ? key => ! filter . includes ( key ) : ( key , value ) => ! filter ( key , value ) ;
585+ if ( Array . isArray ( filter ) ) {
586+ const filterSet = new Set ( filter ) ;
587+ return pick ( input , key => ! filterSet . has ( key ) , options ) ;
588+ }
576589
577- return pick ( input , exclusionFilter , options ) ;
590+ return pick ( input , ( key , value ) => ! filter ( key , value ) , options ) ;
578591}
0 commit comments