@@ -113,10 +113,10 @@ const slashedProtocol = new SafeSet([
113113 'wss:' ,
114114] ) ;
115115const {
116+ CHAR_LINE_FEED ,
117+ CHAR_CARRIAGE_RETURN ,
116118 CHAR_SPACE ,
117119 CHAR_TAB ,
118- CHAR_CARRIAGE_RETURN ,
119- CHAR_LINE_FEED ,
120120 CHAR_NO_BREAK_SPACE ,
121121 CHAR_ZERO_WIDTH_NOBREAK_SPACE ,
122122 CHAR_HASH ,
@@ -130,7 +130,6 @@ const {
130130 CHAR_QUESTION_MARK ,
131131 CHAR_DOUBLE_QUOTE ,
132132 CHAR_SINGLE_QUOTE ,
133- CHAR_PERCENT ,
134133 CHAR_SEMICOLON ,
135134 CHAR_BACKWARD_SLASH ,
136135 CHAR_CIRCUMFLEX_ACCENT ,
@@ -314,6 +313,7 @@ Url.prototype.parse = function parse(url, parseQueryString, slashesDenoteHost) {
314313 let hostEnd = - 1 ;
315314 let atSign = - 1 ;
316315 let nonHost = - 1 ;
316+ let invalid = - 1 ;
317317 for ( let i = 0 ; i < rest . length ; ++ i ) {
318318 switch ( rest . charCodeAt ( i ) ) {
319319 case CHAR_TAB :
@@ -324,35 +324,37 @@ Url.prototype.parse = function parse(url, parseQueryString, slashesDenoteHost) {
324324 i -= 1 ;
325325 break ;
326326 case CHAR_SPACE :
327- case CHAR_DOUBLE_QUOTE :
328- case CHAR_PERCENT :
329- case CHAR_SINGLE_QUOTE :
330- case CHAR_SEMICOLON :
331327 case CHAR_LEFT_ANGLE_BRACKET :
332328 case CHAR_RIGHT_ANGLE_BRACKET :
333- case CHAR_BACKWARD_SLASH :
334329 case CHAR_CIRCUMFLEX_ACCENT :
330+ case CHAR_VERTICAL_LINE :
331+ case CHAR_DOUBLE_QUOTE :
332+ case CHAR_SINGLE_QUOTE :
335333 case CHAR_GRAVE_ACCENT :
336334 case CHAR_LEFT_CURLY_BRACKET :
337- case CHAR_VERTICAL_LINE :
338335 case CHAR_RIGHT_CURLY_BRACKET :
339- // Characters that are never ever allowed in a hostname from RFC 2396
340- if ( nonHost === - 1 )
341- nonHost = i ;
336+ // Characters that are never ever allowed in a hostname from RFC 2396
337+ if ( invalid === - 1 ) {
338+ invalid = i ;
339+ }
342340 break ;
341+ case CHAR_SEMICOLON :
342+ case CHAR_BACKWARD_SLASH :
343343 case CHAR_HASH :
344344 case CHAR_FORWARD_SLASH :
345345 case CHAR_QUESTION_MARK :
346346 // Find the first instance of any host-ending characters
347- if ( nonHost === - 1 )
347+ if ( nonHost === - 1 ) {
348348 nonHost = i ;
349+ }
349350 hostEnd = i ;
350351 break ;
351352 case CHAR_AT :
352353 // At this point, either we have an explicit point where the
353354 // auth portion cannot go past, or the last @ char is the decider.
354355 atSign = i ;
355356 nonHost = - 1 ;
357+ invalid = - 1 ;
356358 break ;
357359 }
358360 if ( hostEnd !== - 1 )
@@ -364,9 +366,15 @@ Url.prototype.parse = function parse(url, parseQueryString, slashesDenoteHost) {
364366 start = atSign + 1 ;
365367 }
366368 if ( nonHost === - 1 ) {
369+ if ( invalid !== - 1 ) {
370+ throw new ERR_INVALID_URL ( url ) ;
371+ }
367372 this . host = rest . slice ( start ) ;
368373 rest = '' ;
369374 } else {
375+ if ( invalid > - 1 && invalid < nonHost ) {
376+ throw new ERR_INVALID_URL ( url ) ;
377+ }
370378 this . host = rest . slice ( start , nonHost ) ;
371379 rest = rest . slice ( nonHost ) ;
372380 }
@@ -509,13 +517,13 @@ Url.prototype.parse = function parse(url, parseQueryString, slashesDenoteHost) {
509517function getHostname ( self , rest , hostname , url ) {
510518 for ( let i = 0 ; i < hostname . length ; ++ i ) {
511519 const code = hostname . charCodeAt ( i ) ;
512- const isValid = ( code !== CHAR_FORWARD_SLASH &&
513- code !== CHAR_BACKWARD_SLASH &&
514- code !== CHAR_HASH &&
515- code !== CHAR_QUESTION_MARK &&
516- code ! == CHAR_COLON ) ;
520+ const isHostEnd = ( code === CHAR_FORWARD_SLASH ||
521+ code === CHAR_BACKWARD_SLASH ||
522+ code === CHAR_HASH ||
523+ code === CHAR_QUESTION_MARK ||
524+ code = == CHAR_COLON ) ;
517525
518- if ( ! isValid ) {
526+ if ( isHostEnd ) {
519527 // If leftover starts with :, then it represents an invalid port.
520528 if ( hostname . charCodeAt ( i ) === 58 ) {
521529 throw new ERR_INVALID_URL ( url ) ;
0 commit comments