Skip to content

Commit

Permalink
url: more closely align url.parse() with WHATWHG
Browse files Browse the repository at this point in the history
There are still lots of ways they are different, but this aligns
url.parse() a bit more closely with WHATWHG URL.
  • Loading branch information
Trott committed Mar 4, 2022
1 parent 29bb2bb commit 4604a3e
Show file tree
Hide file tree
Showing 2 changed files with 86 additions and 13 deletions.
39 changes: 26 additions & 13 deletions lib/url.js
Original file line number Diff line number Diff line change
Expand Up @@ -299,18 +299,27 @@ Url.prototype.parse = function parse(url, parseQueryString, slashesDenoteHost) {
// resolution will treat //foo/bar as host=foo,path=bar because that's
// how the browser resolves relative URLs. http:@example.com is treated
// the same as http://example.com.
let slashes;
let at;
let removedCharsCount = 0;
let isExtraSlashForFileSchemes = false;
if (slashesDenoteHost || proto || hostPattern.test(rest)) {
slashes = rest.charCodeAt(0) === CHAR_FORWARD_SLASH &&
rest.charCodeAt(1) === CHAR_FORWARD_SLASH;
at = rest.charCodeAt(0) === CHAR_AT;
if (rest.charCodeAt(0) === CHAR_FORWARD_SLASH && rest.charCodeAt(1) === CHAR_FORWARD_SLASH) {
this.slashes = true;
}
if (!(proto && hostlessProtocol.has(lowerProto))) {
if (slashes) {
rest = rest.slice(2);
this.slashes = true;
} else if (at) {
rest = rest.slice(1);
}

if (slashedProtocol.has(lowerProto)) {
let newRest = rest.replace(/^[/\\]*@?/, '');
removedCharsCount = rest.length - newRest.length;
if (lowerProto === 'file' || lowerProto === 'file:') {
if (rest[removedCharsCount - 1] === '/') {
newRest = '/' + rest;
isExtraSlashForFileSchemes = true;
}
}
rest = newRest;
}
}
}
Expand Down Expand Up @@ -510,6 +519,12 @@ Url.prototype.parse = function parse(url, parseQueryString, slashesDenoteHost) {
this.path = p + s;
}

// Remove extra `/` previously inserted for file: URLs.
if (isExtraSlashForFileSchemes) {
this.path = this.path.slice(1);
this.pathname = this.pathname.slice(1);
}

// Finally, reconstruct the href based on what has been validated.
this.href = this.format();
return this;
Expand Down Expand Up @@ -763,13 +778,11 @@ Url.prototype.resolveObject = function resolveObject(relative) {

if (relative.protocol && relative.protocol !== result.protocol) {
// If it's a known url protocol, then changing
// the protocol does weird things
// first, if it's not file:, then we MUST have a host,
// the protocol does weird things.
// If it's not file:, then we MUST have a host,
// and if there was a path
// to begin with, then we MUST have a path.
// if it is file:, then the host is dropped,
// because that's known to be hostless.
// anything else is assumed to be absolute.
// Anything else is assumed to be absolute.
if (!slashedProtocol.has(relative.protocol)) {
const keys = ObjectKeys(relative);
for (let v = 0; v < keys.length; v++) {
Expand Down
60 changes: 60 additions & 0 deletions test/parallel/test-url-parse-format.js
Original file line number Diff line number Diff line change
Expand Up @@ -992,6 +992,66 @@ const parseTests = {
path: '/',
href: 'http://localhost/',
},

'http:example.com': {
protocol: 'http:',
slashes: null,
auth: null,
host: 'example.com',
port: null,
hostname: 'example.com',
hash: null,
search: null,
query: null,
pathname: '/',
path: '/',
href: 'http://example.com/',
},

'http:/example.com': {
protocol: 'http:',
slashes: null,
auth: null,
host: 'example.com',
port: null,
hostname: 'example.com',
hash: null,
search: null,
query: null,
pathname: '/',
path: '/',
href: 'http://example.com/',
},

'http:\\example.com': {
protocol: 'http:',
slashes: null,
auth: null,
host: 'example.com',
port: null,
hostname: 'example.com',
hash: null,
search: null,
query: null,
pathname: '/',
path: '/',
href: 'http://example.com/',
},

'http://////////example.com': {
protocol: 'http:',
slashes: true,
auth: null,
host: 'example.com',
port: null,
hostname: 'example.com',
hash: null,
search: null,
query: null,
pathname: '/',
path: '/',
href: 'http://example.com/',
},
};

for (const u in parseTests) {
Expand Down

0 comments on commit 4604a3e

Please sign in to comment.