Skip to content

Commit 0d7ee19

Browse files
TimothyGuBridgeAR
authored andcommitted
url: reuse existing context in href setter
Correctness-wise, this removes side effects in the href setter if parsing fails. Style-wise, this allows removing the parse() wrapper function around C++ _parse(). Also fix an existing bug with whitespace trimming in C++ that was previously circumvented by additionally trimming the input in JavaScript. Fixes: #24345 Refs: #24218 (comment) PR-URL: #24495 Reviewed-By: Anna Henningsen <[email protected]> Reviewed-By: Joyee Cheung <[email protected]> Reviewed-By: Gus Caplan <[email protected]> Reviewed-By: Franziska Hinkelmann <[email protected]> Reviewed-By: Daijiro Wachi <[email protected]> Reviewed-By: Ruben Bridgewater <[email protected]> Reviewed-By: Colin Ihrig <[email protected]> Reviewed-By: James M Snell <[email protected]>
1 parent 0e88f44 commit 0d7ee19

File tree

3 files changed

+33
-21
lines changed

3 files changed

+33
-21
lines changed

‎lib/internal/url.js‎

Lines changed: 17 additions & 21 deletions
Original file line numberDiff line numberDiff line change
@@ -43,7 +43,7 @@ const{
4343
domainToUnicode: _domainToUnicode,
4444
encodeAuth,
4545
toUSVString: _toUSVString,
46-
parse: _parse,
46+
parse,
4747
setURLConstructor,
4848
URL_FLAGS_CANNOT_BE_BASE,
4949
URL_FLAGS_HAS_FRAGMENT,
@@ -243,14 +243,6 @@ function onParseError(flags, input){
243243
throwerror;
244244
}
245245

246-
// Reused by URL constructor and URL#href setter.
247-
functionparse(url,input,base){
248-
constbase_context=base ? base[context] : undefined;
249-
url[context]=newURLContext();
250-
_parse(input.trim(),-1,base_context,undefined,
251-
onParseComplete.bind(url),onParseError);
252-
}
253-
254246
functiononParseProtocolComplete(flags,protocol,username,password,
255247
host,port,path,query,fragment){
256248
constctx=this[context];
@@ -319,10 +311,13 @@ class URL{
319311
constructor(input,base){
320312
// toUSVString is not needed.
321313
input=`${input}`;
314+
letbase_context;
322315
if(base!==undefined){
323-
base=newURL(base);
316+
base_context=newURL(base)[context];
324317
}
325-
parse(this,input,base);
318+
this[context]=newURLContext();
319+
parse(input,-1,base_context,undefined,onParseComplete.bind(this),
320+
onParseError);
326321
}
327322

328323
get[special](){
@@ -445,7 +440,8 @@ Object.defineProperties(URL.prototype,{
445440
set(input){
446441
// toUSVString is not needed.
447442
input=`${input}`;
448-
parse(this,input);
443+
parse(input,-1,undefined,undefined,onParseComplete.bind(this),
444+
onParseError);
449445
}
450446
},
451447
origin: {// readonly
@@ -491,8 +487,8 @@ Object.defineProperties(URL.prototype,{
491487
(ctx.host===''||ctx.host===null)){
492488
return;
493489
}
494-
_parse(scheme,kSchemeStart,null,ctx,
495-
onParseProtocolComplete.bind(this));
490+
parse(scheme,kSchemeStart,null,ctx,
491+
onParseProtocolComplete.bind(this));
496492
}
497493
},
498494
username: {
@@ -555,7 +551,7 @@ Object.defineProperties(URL.prototype,{
555551
// Cannot set the host if cannot-be-base is set
556552
return;
557553
}
558-
_parse(host,kHost,null,ctx,onParseHostComplete.bind(this));
554+
parse(host,kHost,null,ctx,onParseHostComplete.bind(this));
559555
}
560556
},
561557
hostname: {
@@ -572,7 +568,7 @@ Object.defineProperties(URL.prototype,{
572568
// Cannot set the host if cannot-be-base is set
573569
return;
574570
}
575-
_parse(host,kHostname,null,ctx,onParseHostnameComplete.bind(this));
571+
parse(host,kHostname,null,ctx,onParseHostnameComplete.bind(this));
576572
}
577573
},
578574
port: {
@@ -592,7 +588,7 @@ Object.defineProperties(URL.prototype,{
592588
ctx.port=null;
593589
return;
594590
}
595-
_parse(port,kPort,null,ctx,onParsePortComplete.bind(this));
591+
parse(port,kPort,null,ctx,onParsePortComplete.bind(this));
596592
}
597593
},
598594
pathname: {
@@ -611,8 +607,8 @@ Object.defineProperties(URL.prototype,{
611607
path=`${path}`;
612608
if(this[cannotBeBase])
613609
return;
614-
_parse(path,kPathStart,null,this[context],
615-
onParsePathComplete.bind(this));
610+
parse(path,kPathStart,null,this[context],
611+
onParsePathComplete.bind(this));
616612
}
617613
},
618614
search: {
@@ -635,7 +631,7 @@ Object.defineProperties(URL.prototype,{
635631
ctx.query='';
636632
ctx.flags|=URL_FLAGS_HAS_QUERY;
637633
if(search){
638-
_parse(search,kQuery,null,ctx,onParseSearchComplete.bind(this));
634+
parse(search,kQuery,null,ctx,onParseSearchComplete.bind(this));
639635
}
640636
}
641637
initSearchParams(this[searchParams],search);
@@ -669,7 +665,7 @@ Object.defineProperties(URL.prototype,{
669665
if(hash[0]==='#')hash=hash.slice(1);
670666
ctx.fragment='';
671667
ctx.flags|=URL_FLAGS_HAS_FRAGMENT;
672-
_parse(hash,kFragment,null,ctx,onParseHashComplete.bind(this));
668+
parse(hash,kFragment,null,ctx,onParseHashComplete.bind(this));
673669
}
674670
},
675671
toJSON: {

‎src/node_url.cc‎

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1376,6 +1376,7 @@ void URL::Parse(const char* input,
13761376
else
13771377
break;
13781378
}
1379+
input = p;
13791380
len = end - p;
13801381
}
13811382

Lines changed: 15 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,15 @@
1+
'use strict';
2+
3+
// Tests below are not from WPT.
4+
constcommon=require('../common');
5+
constassert=require('assert');
6+
7+
constref=newURL('http://example.com/path');
8+
consturl=newURL('http://example.com/path');
9+
common.expectsError(()=>{
10+
url.href='';
11+
},{
12+
type: TypeError
13+
});
14+
15+
assert.deepStrictEqual(url,ref);

0 commit comments

Comments
(0)