diff --git a/README.md b/README.md index b7cc7b6..e6a6bd5 100644 --- a/README.md +++ b/README.md @@ -23,7 +23,8 @@ The following methods are exported for use by places like jsdom that need to imp - [Serialize an integer](https://url.spec.whatwg.org/#serialize-an-integer): `serializeInteger(number)` - [Origin](https://url.spec.whatwg.org/#concept-url-origin) [Unicode serializer](https://html.spec.whatwg.org/multipage/browsers.html#unicode-serialisation-of-an-origin): `serializeURLToUnicodeOrigin(urlRecord)` - [Set the username](https://url.spec.whatwg.org/#set-the-username): `setTheUsername(urlRecord, usernameString)` -- [Set the password](https://url.spec.whatwg.org/#set-the-password): `setThePassword(urlRecord, passwordString)`. +- [Set the password](https://url.spec.whatwg.org/#set-the-password): `setThePassword(urlRecord, passwordString)` +- [Is special](https://url.spec.whatwg.org/#is-special): `isSpecial(urlRecord)` The `stateOverride` parameter is one of the following strings: diff --git a/lib/URL-impl.js b/lib/URL-impl.js index 44f6671..83982a5 100644 --- a/lib/URL-impl.js +++ b/lib/URL-impl.js @@ -140,6 +140,10 @@ exports.implementation = class URLImpl { return this._url.path[0]; } + if (!usm.isSpecial(this._url) && this._url.path.length === 0) { + return ""; + } + return "/" + this._url.path.join("/"); } diff --git a/scripts/get-latest-platform-tests.js b/scripts/get-latest-platform-tests.js index f564c50..e9d640b 100644 --- a/scripts/get-latest-platform-tests.js +++ b/scripts/get-latest-platform-tests.js @@ -15,7 +15,7 @@ const request = require("request"); // 1. Go to https://github.com/w3c/web-platform-tests/tree/master/url // 2. Press "y" on your keyboard to get a permalink // 3. Copy the commit hash -const commitHash = "5be497b5f5a7036e26dc14739aa8d42f643cf94f"; +const commitHash = "2c87b7d14b07b9383b837278e475d202969f6b64"; const sourceURL = `https://raw.githubusercontent.com/w3c/web-platform-tests/${commitHash}/url/urltestdata.json`; const setterSourceURL = `https://raw.githubusercontent.com/w3c/web-platform-tests/${commitHash}/url/setters_tests.json`; diff --git a/src/url-state-machine.js b/src/url-state-machine.js index 972f5fa..275d776 100644 --- a/src/url-state-machine.js +++ b/src/url-state-machine.js @@ -390,6 +390,23 @@ function parseHost(input, isUnicode) { return isUnicode ? tr46.toUnicode(asciiDomain, false).domain : asciiDomain; } +function parseURLHost(input, isSpecial) { + if (isSpecial) { + if (input === "") { + return failure; + } + + return parseHost(input); + } + + let output = ""; + const decoded = punycode.ucs2.decode(input); + for (let i = 0; i < decoded.length; ++i) { + output += encodeChar(decoded[i], isSimpleEncode); + } + return output; +} + function findLongestZeroSequence(arr) { let maxIdx = null; let maxLen = 1; // only find elements > 1 @@ -750,11 +767,7 @@ URLStateMachine.prototype["parse authority"] = function parseAuthority(c, cStr) URLStateMachine.prototype["parse hostname"] = URLStateMachine.prototype["parse host"] = function parseHostName(c, cStr) { if (c === p(":") && !this.arrFlag) { - if (isSpecial(this.url) && this.buffer === "") { - return failure; - } - - const host = parseHost(this.buffer); + const host = parseURLHost(this.buffer, isSpecial(this.url)); if (host === failure) { return failure; } @@ -768,11 +781,8 @@ URLStateMachine.prototype["parse host"] = function parseHostName(c, cStr) { } else if (isNaN(c) || c === p("/") || c === p("?") || c === p("#") || (isSpecial(this.url) && c === p("\\"))) { --this.pointer; - if (isSpecial(this.url) && this.buffer === "") { - return failure; - } - const host = parseHost(this.buffer); + const host = parseURLHost(this.buffer, isSpecial(this.url)); if (host === failure) { return failure; } @@ -1078,7 +1088,13 @@ function serializeURL(url, excludeFragment) { if (url.username !== "" || url.password !== null) { output += "@"; } - output += serializeHost(url.host); + + if (isSpecial(url)) { + output += serializeHost(url.host); + } else { + output += url.host; + } + if (url.port !== null) { output += ":" + url.port; } @@ -1089,6 +1105,9 @@ function serializeURL(url, excludeFragment) { if (url.cannotBeABaseURL) { output += url.path[0]; } else { + if (!isSpecial(url) && url.path.length === 0) { + return output; + } output += "/" + url.path.join("/"); } @@ -1196,3 +1215,5 @@ module.exports.parseURL = function (input, options) { // We don't handle blobs, so this just delegates: return module.exports.basicURLParse(input, { baseURL: options.baseURL, encodingOverride: options.encodingOverride }); }; + +module.exports.isSpecial = isSpecial;