From 3709e381ea85d2fa4a4845775be88228af5f67e3 Mon Sep 17 00:00:00 2001 From: Domenic Denicola Date: Tue, 24 Jan 2017 14:41:18 -0500 Subject: [PATCH] Spec update: add opaque hosts Follows https://github.com/whatwg/url/pull/185. --- scripts/get-latest-platform-tests.js | 2 +- src/url-state-machine.js | 35 ++++++++++++++++++++++++---- 2 files changed, 32 insertions(+), 5 deletions(-) diff --git a/scripts/get-latest-platform-tests.js b/scripts/get-latest-platform-tests.js index 63b12c1..20b5190 100644 --- a/scripts/get-latest-platform-tests.js +++ b/scripts/get-latest-platform-tests.js @@ -14,7 +14,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 = "165824d1b5eae50004050c77ccbe243990b620fc"; +const commitHash = "eb26d340eb22a83cefe644a7ebe810e06682e326"; 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 4534bd6..ac7b46f 100644 --- a/src/url-state-machine.js +++ b/src/url-state-machine.js @@ -52,6 +52,10 @@ function isDoubleDot(buffer) { return buffer === ".." || buffer === "%2e." || buffer === ".%2e" || buffer === "%2e%2e"; } +function containsForbiddenHostCodePoint(string) { + return string.search(/\u0000|\u0009|\u000A|\u000D|\u0020|#|%|\/|:|\?|@|\[|\\|\]/) !== -1; +} + function isSpecialScheme(scheme) { return specialSchemes[scheme] !== undefined; } @@ -382,7 +386,7 @@ function parseHost(input, isUnicode) { return failure; } - if (asciiDomain.search(/\u0000|\u0009|\u000A|\u000D|\u0020|#|%|\/|:|\?|@|\[|\\|\]/) !== -1) { + if (containsForbiddenHostCodePoint(asciiDomain)) { return failure; } @@ -394,6 +398,23 @@ function parseHost(input, isUnicode) { return isUnicode ? tr46.toUnicode(asciiDomain, false).domain : asciiDomain; } +function parseURLHost(input, isSpecialArg) { + if (isSpecialArg) { + return parseHost(input); + } + + if (containsForbiddenHostCodePoint(input)) { + return failure; + } + + 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 @@ -748,6 +769,10 @@ URLStateMachine.prototype["parse authority"] = function parseAuthority(c, cStr) this.buffer = ""; } else if (isNaN(c) || c === p("/") || c === p("?") || c === p("#") || (isSpecial(this.url) && c === p("\\"))) { + if (this.atFlag && this.buffer === "") { + this.parseError = true; + return failure; + } this.pointer -= countSymbols(this.buffer) + 1; this.buffer = ""; this.state = "host"; @@ -761,11 +786,12 @@ 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 === "") { + if (this.buffer === "") { + this.parseError = true; return failure; } - const host = parseHost(this.buffer); + const host = parseURLHost(this.buffer, isSpecial(this.url)); if (host === failure) { return failure; } @@ -780,10 +806,11 @@ URLStateMachine.prototype["parse host"] = function parseHostName(c, cStr) { (isSpecial(this.url) && c === p("\\"))) { --this.pointer; if (isSpecial(this.url) && this.buffer === "") { + this.parseError = true; return failure; } - const host = parseHost(this.buffer); + const host = parseURLHost(this.buffer, isSpecial(this.url)); if (host === failure) { return failure; }