@@ -27,6 +27,9 @@ const {
2727 ObjectAssign,
2828 ObjectKeys,
2929 StringPrototypeCharCodeAt,
30+ StringPrototypeIndexOf,
31+ StringPrototypeReplaceAll,
32+ StringPrototypeSlice,
3033 decodeURIComponent,
3134} = primordials ;
3235
@@ -637,6 +640,10 @@ Url.prototype.format = function format() {
637640 }
638641
639642 let protocol = this . protocol || '' ;
643+ if ( protocol && StringPrototypeCharCodeAt ( protocol , protocol . length - 1 ) !== 58 /* : */ ) {
644+ protocol += ':' ;
645+ }
646+
640647 let pathname = this . pathname || '' ;
641648 let hash = this . hash || '' ;
642649 let host = '' ;
@@ -646,7 +653,7 @@ Url.prototype.format = function format() {
646653 host = auth + this . host ;
647654 } else if ( this . hostname ) {
648655 host = auth + (
649- this . hostname . includes ( ':' ) && ! isIpv6Hostname ( this . hostname ) ?
656+ StringPrototypeIndexOf ( this . hostname , ':' ) !== - 1 && ! isIpv6Hostname ( this . hostname ) ?
650657 '[' + this . hostname + ']' :
651658 this . hostname
652659 ) ;
@@ -658,59 +665,55 @@ Url.prototype.format = function format() {
658665 if ( this . query !== null && typeof this . query === 'object' ) {
659666 query = querystring . stringify ( this . query ) ;
660667 }
661-
662668 let search = this . search || ( query && ( '?' + query ) ) || '' ;
663669
664- if ( protocol && protocol . charCodeAt ( protocol . length - 1 ) !== 58 /* : */ )
665- protocol += ':' ;
666-
667- let newPathname = '' ;
668- let lastPos = 0 ;
669- for ( let i = 0 ; i < pathname . length ; ++ i ) {
670- switch ( pathname . charCodeAt ( i ) ) {
671- case CHAR_HASH :
672- if ( i - lastPos > 0 )
673- newPathname += pathname . slice ( lastPos , i ) ;
674- newPathname += '%23' ;
675- lastPos = i + 1 ;
676- break ;
677- case CHAR_QUESTION_MARK :
678- if ( i - lastPos > 0 )
679- newPathname += pathname . slice ( lastPos , i ) ;
680- newPathname += '%3F' ;
670+ if ( StringPrototypeIndexOf ( pathname , '#' ) !== - 1 || StringPrototypeIndexOf ( pathname , '?' ) !== - 1 ) {
671+ let newPathname = '' ;
672+ let lastPos = 0 ;
673+ const len = pathname . length ;
674+ for ( let i = 0 ; i < len ; i ++ ) {
675+ const code = StringPrototypeCharCodeAt ( pathname , i ) ;
676+ if ( code === CHAR_HASH || code === CHAR_QUESTION_MARK ) {
677+ if ( i > lastPos ) {
678+ newPathname += StringPrototypeSlice ( pathname , lastPos , i ) ;
679+ }
680+ newPathname += ( code === CHAR_HASH ? '%23' : '%3F' ) ;
681681 lastPos = i + 1 ;
682- break ;
682+ }
683683 }
684- }
685- if ( lastPos > 0 ) {
686- if ( lastPos !== pathname . length )
687- pathname = newPathname + pathname . slice ( lastPos ) ;
688- else
689- pathname = newPathname ;
684+ if ( lastPos < len ) {
685+ newPathname += StringPrototypeSlice ( pathname , lastPos ) ;
686+ }
687+ pathname = newPathname ;
690688 }
691689
692690 // Only the slashedProtocols get the //. Not mailto:, xmpp:, etc.
693691 // unless they had them to begin with.
694692 if ( this . slashes || slashedProtocol . has ( protocol ) ) {
695693 if ( this . slashes || host ) {
696- if ( pathname && pathname . charCodeAt ( 0 ) !== CHAR_FORWARD_SLASH )
694+ if ( pathname && StringPrototypeCharCodeAt ( pathname , 0 ) !== CHAR_FORWARD_SLASH )
697695 pathname = '/' + pathname ;
698696 host = '//' + host ;
699697 } else if ( protocol . length >= 4 &&
700- protocol . charCodeAt ( 0 ) === 102 /* f */ &&
701- protocol . charCodeAt ( 1 ) === 105 /* i */ &&
702- protocol . charCodeAt ( 2 ) === 108 /* l */ &&
703- protocol . charCodeAt ( 3 ) === 101 /* e */ ) {
698+ StringPrototypeCharCodeAt ( protocol , 0 ) === 102 /* f */ &&
699+ StringPrototypeCharCodeAt ( protocol , 1 ) === 105 /* i */ &&
700+ StringPrototypeCharCodeAt ( protocol , 2 ) === 108 /* l */ &&
701+ StringPrototypeCharCodeAt ( protocol , 3 ) === 101 /* e */ ) {
704702 host = '//' ;
705703 }
706704 }
707705
708- search = search . replaceAll ( '#' , '%23' ) ;
706+ // Escape '#' in search.
707+ if ( StringPrototypeIndexOf ( search , '#' ) !== - 1 ) {
708+ search = StringPrototypeReplaceAll ( search , '#' , '%23' ) ;
709+ }
709710
710- if ( hash && hash . charCodeAt ( 0 ) !== CHAR_HASH )
711+ if ( hash && StringPrototypeCharCodeAt ( hash , 0 ) !== CHAR_HASH ) {
711712 hash = '#' + hash ;
712- if ( search && search . charCodeAt ( 0 ) !== CHAR_QUESTION_MARK )
713+ }
714+ if ( search && StringPrototypeCharCodeAt ( search , 0 ) !== CHAR_QUESTION_MARK ) {
713715 search = '?' + search ;
716+ }
714717
715718 return protocol + host + pathname + search + hash ;
716719} ;
0 commit comments