Skip to content

Commit dfc8017

Browse files
TimothyGuevanlucas
authored andcommitted
url: improve WHATWG URL inspection
PR-URL: #12507 Reviewed-By: James M Snell <[email protected]>
1 parent b2a9e60 commit dfc8017

File tree

2 files changed

+103
-89
lines changed

2 files changed

+103
-89
lines changed

‎lib/internal/url.js‎

Lines changed: 54 additions & 24 deletions
Original file line numberDiff line numberDiff line change
@@ -184,6 +184,17 @@ function onParseHashComplete(flags, protocol, username, password,
184184
}
185185
}
186186

187+
functiongetEligibleConstructor(obj){
188+
while(obj!==null){
189+
if(Object.prototype.hasOwnProperty.call(obj,'constructor')&&
190+
typeofobj.constructor==='function'){
191+
returnobj.constructor;
192+
}
193+
obj=Object.getPrototypeOf(obj);
194+
}
195+
returnnull;
196+
}
197+
187198
classURL{
188199
constructor(input,base){
189200
// toUSVString is not needed.
@@ -204,33 +215,43 @@ class URL{
204215
}
205216

206217
[util.inspect.custom](depth,opts){
218+
if(this==null||
219+
Object.getPrototypeOf(this[context])!==URLContext.prototype){
220+
thrownewTypeError('Value of `this` is not a URL');
221+
}
222+
207223
constctx=this[context];
208-
varret='URL{\n';
209-
ret+=` href: ${this.href}\n`;
210-
if(ctx.scheme!==undefined)
211-
ret+=` protocol: ${this.protocol}\n`;
212-
if(ctx.username!==undefined)
213-
ret+=` username: ${this.username}\n`;
214-
if(ctx.password!==undefined){
215-
constpwd=opts.showHidden ? ctx.password : '--------';
216-
ret+=` password: ${pwd}\n`;
217-
}
218-
if(ctx.host!==undefined)
219-
ret+=` hostname: ${this.hostname}\n`;
220-
if(ctx.port!==undefined)
221-
ret+=` port: ${this.port}\n`;
222-
if(ctx.path!==undefined)
223-
ret+=` pathname: ${this.pathname}\n`;
224-
if(ctx.query!==undefined)
225-
ret+=` search: ${this.search}\n`;
226-
if(ctx.fragment!==undefined)
227-
ret+=` hash: ${this.hash}\n`;
224+
225+
if(typeofdepth==='number'&&depth<0)
226+
returnopts.stylize('[Object]','special');
227+
228+
constctor=getEligibleConstructor(this);
229+
230+
constobj=Object.create({
231+
constructor: ctor===null ? URL : ctor
232+
});
233+
234+
obj.href=this.href;
235+
obj.origin=this.origin;
236+
obj.protocol=this.protocol;
237+
obj.username=this.username;
238+
obj.password=(opts.showHidden||ctx.password==null) ?
239+
this.password : '--------';
240+
obj.host=this.host;
241+
obj.hostname=this.hostname;
242+
obj.port=this.port;
243+
obj.pathname=this.pathname;
244+
obj.search=this.search;
245+
obj.searchParams=this.searchParams;
246+
obj.hash=this.hash;
247+
228248
if(opts.showHidden){
229-
ret+=` cannot-be-base: ${this[cannotBeBase]}\n`;
230-
ret+=` special: ${this[special]}\n`;
249+
obj.cannotBeBase=this[cannotBeBase];
250+
obj.special=this[special];
251+
obj[context]=this[context];
231252
}
232-
ret+='}';
233-
returnret;
253+
254+
returnutil.inspect(obj,opts);
234255
}
235256
}
236257

@@ -858,6 +879,9 @@ class URLSearchParams{
858879
thrownewTypeError('Value of `this` is not a URLSearchParams');
859880
}
860881

882+
if(typeofrecurseTimes==='number'&&recurseTimes<0)
883+
returnctx.stylize('[Object]','special');
884+
861885
constseparator=', ';
862886
constinnerOpts=Object.assign({},ctx);
863887
if(recurseTimes!==null){
@@ -1211,6 +1235,12 @@ defineIDLClass(URLSearchParamsIteratorPrototype, 'URLSearchParamsIterator',{
12111235
};
12121236
},
12131237
[util.inspect.custom](recurseTimes,ctx){
1238+
if(this==null||this[context]==null||this[context].target==null)
1239+
thrownewTypeError('Value of `this` is not a URLSearchParamsIterator');
1240+
1241+
if(typeofrecurseTimes==='number'&&recurseTimes<0)
1242+
returnctx.stylize('[Object]','special');
1243+
12141244
constinnerOpts=Object.assign({},ctx);
12151245
if(recurseTimes!==null){
12161246
innerOpts.depth=recurseTimes-1;

‎test/parallel/test-whatwg-url-inspect.js‎

Lines changed: 49 additions & 65 deletions
Original file line numberDiff line numberDiff line change
@@ -3,7 +3,6 @@
33
constcommon=require('../common');
44
constutil=require('util');
55
constURL=require('url').URL;
6-
constpath=require('path');
76
constassert=require('assert');
87

98
if(!common.hasIntl){
@@ -13,71 +12,56 @@ if (!common.hasIntl){
1312
}
1413

1514
// Tests below are not from WPT.
16-
consttests=require(path.join(common.fixturesDir,'url-tests'));
17-
constadditional_tests=require(
18-
path.join(common.fixturesDir,'url-tests-additional'));
15+
consturl=newURL('https://username:[email protected]:8080/path/name/?que=ry#hash');
1916

20-
constallTests=additional_tests.slice();
21-
for(consttestoftests){
22-
if(test.failure||typeoftest==='string')continue;
23-
allTests.push(test);
24-
}
25-
26-
for(consttestofallTests){
27-
consturl=test.url ? newURL(test.url) : newURL(test.input,test.base);
28-
29-
for(constshowHiddenof[true,false]){
30-
constres=util.inspect(url,{
31-
showHidden
32-
});
33-
34-
constlines=res.split('\n');
17+
assert.strictEqual(
18+
util.inspect(url),
19+
`URL{
20+
href: 'https://username:[email protected]:8080/path/name/?que=ry#hash',
21+
origin: 'https://host.name:8080',
22+
protocol: 'https:',
23+
username: 'username',
24+
password: '--------',
25+
host: 'host.name:8080',
26+
hostname: 'host.name',
27+
port: '8080',
28+
pathname: '/path/name/',
29+
search: '?que=ry',
30+
searchParams: URLSearchParams{'que' => 'ry' },
31+
hash: '#hash' }`);
3532

36-
constfirstLine=lines[0];
37-
assert.strictEqual(firstLine,'URL{');
33+
assert.strictEqual(
34+
util.inspect(url,{showHidden: true}),
35+
`URL{
36+
href: 'https://username:[email protected]:8080/path/name/?que=ry#hash',
37+
origin: 'https://host.name:8080',
38+
protocol: 'https:',
39+
username: 'username',
40+
password: 'password',
41+
host: 'host.name:8080',
42+
hostname: 'host.name',
43+
port: '8080',
44+
pathname: '/path/name/',
45+
search: '?que=ry',
46+
searchParams: URLSearchParams{'que' => 'ry'},
47+
hash: '#hash',
48+
cannotBeBase: false,
49+
special: true,
50+
[Symbol(context)]:\x20
51+
URLContext{
52+
flags: 2032,
53+
scheme: 'https:',
54+
username: 'username',
55+
password: 'password',
56+
host: 'host.name',
57+
port: 8080,
58+
path: [ 'path', 'name', '', [length]: 3 ],
59+
query: 'que=ry',
60+
fragment: 'hash'} }`);
3861

39-
constlastLine=lines[lines.length-1];
40-
assert.strictEqual(lastLine,'}');
62+
assert.strictEqual(
63+
util.inspect({a: url},{depth: 0}),
64+
'{a: [Object] }');
4165

42-
constinnerLines=lines.slice(1,lines.length-1);
43-
constkeys=newSet();
44-
for(constlineofinnerLines){
45-
consti=line.indexOf(': ');
46-
constk=line.slice(0,i).trim();
47-
constv=line.slice(i+2);
48-
assert.strictEqual(keys.has(k),false,'duplicate key found: '+k);
49-
keys.add(k);
50-
51-
consthidden=newSet([
52-
'password',
53-
'cannot-be-base',
54-
'special'
55-
]);
56-
if(showHidden){
57-
if(!hidden.has(k)){
58-
assert.strictEqual(v,url[k],k);
59-
continue;
60-
}
61-
62-
if(k==='password'){
63-
assert.strictEqual(v,url[k],k);
64-
}
65-
if(k==='cannot-be-base'){
66-
assert.ok(v.match(/^true$|^false$/),k+' is Boolean');
67-
}
68-
if(k==='special'){
69-
assert.ok(v.match(/^true$|^false$/),k+' is Boolean');
70-
}
71-
continue;
72-
}
73-
74-
// showHidden is false
75-
if(k==='password'){
76-
assert.strictEqual(v,'--------',k);
77-
continue;
78-
}
79-
assert.strictEqual(hidden.has(k),false,'no hidden keys: '+k);
80-
assert.strictEqual(v,url[k],k);
81-
}
82-
}
83-
}
66+
classMyURLextendsURL{}
67+
assert(util.inspect(newMyURL(url.href)).startsWith('MyURL{'));

0 commit comments

Comments
(0)