@@ -15,7 +15,12 @@ import type {
1515import { type ResponsePromise } from '../types/ResponsePromise.js' ;
1616import type { StandardSchemaV1 } from '../types/standard-schema.js' ;
1717import { streamRequest , streamResponse } from '../utils/body.js' ;
18- import { cloneShallow , mergeHeaders , mergeHooks } from '../utils/merge.js' ;
18+ import {
19+ cloneShallow ,
20+ mergeHeaders ,
21+ mergeHooks ,
22+ deletedParametersSymbol ,
23+ } from '../utils/merge.js' ;
1924import { normalizeRequestMethod , normalizeRetryOptions } from '../utils/normalize.js' ;
2025import timeout from '../utils/timeout.js' ;
2126import delay from '../utils/delay.js' ;
@@ -375,13 +380,40 @@ export class Ky {
375380 this . request = new globalThis . Request ( this . #input, this . #options) ;
376381
377382 if ( hasSearchParameters ( this . #options. searchParams ) ) {
378- // eslint-disable-next-line unicorn/prevent-abbreviations
379- const textSearchParams = typeof this . #options. searchParams === 'string'
380- ? this . #options. searchParams . replace ( / ^ \? / , '' )
381- : new URLSearchParams ( Ky . #normalizeSearchParams( this . #options. searchParams ) as unknown as SearchParamsInit ) . toString ( ) ;
382- // eslint-disable-next-line unicorn/prevent-abbreviations
383- const searchParams = '?' + textSearchParams ;
384- const url = this . request . url . replace ( / (?: \? .* ?) ? (? = # | $ ) / , searchParams ) ;
383+ const url = new URL ( this . request . url ) ;
384+
385+ if ( typeof this . #options. searchParams === 'string' ) {
386+ const stringSearchParameters = this . #options. searchParams . replace ( / ^ \? / , '' ) ;
387+ if ( stringSearchParameters !== '' ) {
388+ url . search = url . search ? `${ url . search } &${ stringSearchParameters } ` : `?${ stringSearchParameters } ` ;
389+ }
390+ } else {
391+ const optionsSearchParameters = new URLSearchParams ( Ky . #normalizeSearchParams( this . #options. searchParams ) as unknown as SearchParamsInit ) ;
392+
393+ for ( const [ key , value ] of optionsSearchParameters . entries ( ) ) {
394+ url . searchParams . append ( key , value ) ;
395+ }
396+ }
397+
398+ if (
399+ this . #options. searchParams
400+ && typeof this . #options. searchParams === 'object'
401+ && ! Array . isArray ( this . #options. searchParams )
402+ && ! ( this . #options. searchParams instanceof URLSearchParams )
403+ ) {
404+ for ( const [ key , value ] of Object . entries ( this . #options. searchParams ) ) {
405+ if ( value === undefined ) {
406+ url . searchParams . delete ( key ) ;
407+ }
408+ }
409+ }
410+
411+ const deleted = ( this . #options. searchParams as any ) ?. [ deletedParametersSymbol ] as Set < string > | undefined ;
412+ if ( deleted ) {
413+ for ( const key of deleted ) {
414+ url . searchParams . delete ( key ) ;
415+ }
416+ }
385417
386418 // Recreate request with the updated URL. We already have all options in this.#options, including duplex.
387419 this . request = new globalThis . Request ( url , this . #options as RequestInit ) ;
0 commit comments