@@ -100,6 +100,7 @@ const FORWARD_SLASH = /\//g;
100100
101101const context = Symbol ( 'context' ) ;
102102const searchParams = Symbol ( 'query' ) ;
103+ const kDirty = Symbol ( 'dirty' ) ;
103104
104105const updateActions = {
105106 kProtocol : 0 ,
@@ -224,11 +225,12 @@ class URLSearchParams {
224225 } else {
225226 // USVString
226227 init = toUSVString ( init ) ;
227- initSearchParams ( this , init ) ;
228+ this [ searchParams ] = init ? parseParams ( init ) : [ ] ;
228229 }
229230
230231 // "associated url object"
231232 this [ context ] = null ;
233+ this [ kDirty ] = false ;
232234 }
233235
234236 [ inspect . custom ] ( recurseTimes , ctx ) {
@@ -545,6 +547,7 @@ class URL {
545547 input = `${ input } ` ;
546548 this [ context ] = new URLContext ( ) ;
547549 this . #onParseComplete = FunctionPrototypeBind ( this . #onParseComplete, this ) ;
550+ this . #onSearchUpdate = FunctionPrototypeBind ( this . #onSearchUpdate, this ) ;
548551
549552 if ( base !== undefined ) {
550553 base = `${ base } ` ;
@@ -604,11 +607,34 @@ class URL {
604607 ctx . password = password ;
605608 ctx . port = port ;
606609 ctx . hash = hash ;
607- if ( ! this [ searchParams ] ) { // Invoked from URL constructor
608- this [ searchParams ] = new URLSearchParams ( ) ;
610+ if ( this [ searchParams ] ) {
611+ // Update `kDirty` property to recalculate searchParams on access.
612+ // This is done to reduce the overhead of initializing the URL.
613+ this [ searchParams ] [ kDirty ] = true ;
614+ }
615+ } ;
616+
617+ #onSearchUpdate = ( href , origin , protocol , hostname , pathname ,
618+ search , username , password , port , hash ) => {
619+ const ctx = this [ context ] ;
620+ ctx . href = href ;
621+ ctx . origin = origin ;
622+ ctx . protocol = protocol ;
623+ ctx . hostname = hostname ;
624+ ctx . pathname = pathname ;
625+ ctx . search = search ;
626+ ctx . username = username ;
627+ ctx . password = password ;
628+ ctx . port = port ;
629+ ctx . hash = hash ;
630+
631+ if ( this [ searchParams ] == null ) {
632+ this [ searchParams ] = new URLSearchParams ( this [ context ] . search ) ;
609633 this [ searchParams ] [ context ] = this ;
634+ } else {
635+ this [ searchParams ] [ searchParams ] = this [ context ] . search ? parseParams ( this [ context ] . search ) : [ ] ;
636+ this [ searchParams ] [ kDirty ] = false ;
610637 }
611- initSearchParams ( this [ searchParams ] , ctx . search ) ;
612638 } ;
613639
614640 toString ( ) {
@@ -729,18 +755,25 @@ class URL {
729755 return this [ context ] . search ;
730756 }
731757
732- set search ( search ) {
758+ set search ( value ) {
733759 if ( ! isURLThis ( this ) )
734760 throw new ERR_INVALID_THIS ( 'URL' ) ;
735- search = toUSVString ( search ) ;
736- updateUrl ( this [ context ] . href , updateActions . kSearch , search , this . #onParseComplete) ;
737- initSearchParams ( this [ searchParams ] , this [ context ] . search ) ;
761+ updateUrl ( this [ context ] . href , updateActions . kSearch , toUSVString ( value ) , this . #onSearchUpdate) ;
738762 }
739763
740764 // readonly
741765 get searchParams ( ) {
742766 if ( ! isURLThis ( this ) )
743767 throw new ERR_INVALID_THIS ( 'URL' ) ;
768+ // Create URLSearchParams on demand to greatly improve the URL performance.
769+ if ( this [ searchParams ] == null ) {
770+ this [ searchParams ] = new URLSearchParams ( this [ context ] . search ) ;
771+ this [ searchParams ] [ context ] = this ;
772+ } else if ( this [ searchParams ] [ kDirty ] ) {
773+ const updated = this [ context ] . search ;
774+ this [ searchParams ] [ searchParams ] = updated ? parseParams ( updated ) : [ ] ;
775+ this [ searchParams ] [ kDirty ] = false ;
776+ }
744777 return this [ searchParams ] ;
745778 }
746779
@@ -815,14 +848,6 @@ ObjectDefineProperties(URL, {
815848 revokeObjectURL : kEnumerableProperty ,
816849} ) ;
817850
818- function initSearchParams ( url , init ) {
819- if ( ! init ) {
820- url [ searchParams ] = [ ] ;
821- return ;
822- }
823- url [ searchParams ] = parseParams ( init ) ;
824- }
825-
826851// application/x-www-form-urlencoded parser
827852// Ref: https://url.spec.whatwg.org/#concept-urlencoded-parser
828853function parseParams ( qs ) {
0 commit comments