diff --git a/scripts/get-latest-platform-tests.js b/scripts/get-latest-platform-tests.js index 9e6bf07..50e4b0e 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 = "1e1e80441b8d6a60f836de4005dba25698ecfe4a"; +const commitHash = "6e9508aab07d0c3e81e2ae60bac32290c02cd8f2"; 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 1998803..11d6909 100644 --- a/src/url-state-machine.js +++ b/src/url-state-machine.js @@ -309,14 +309,14 @@ function parseIPv6(input) { ++piecePtr; } - if (input[pointer] !== undefined) { - ++pointer; - } - if (dotsSeen === 3 && input[pointer] !== undefined) { return failure; } - ++dotsSeen; + + if (input[pointer] === p(".")) { + ++pointer; + ++dotsSeen; + } } } diff --git a/test.js b/test.js new file mode 100644 index 0000000..e4760e2 --- /dev/null +++ b/test.js @@ -0,0 +1,165 @@ +"use strict"; +const URL = require(".").URL; +const punycode = require("punycode"); +const failure = Symbol("failure"); + + +console.log(parseIPv6("::1.")); + +//console.log(new URL("http://[::1.]").href); + +function p(char) { + return char.codePointAt(0); +} + +function at(input, idx) { + const c = input[idx]; + return isNaN(c) ? undefined : String.fromCodePoint(c); +} + +function isASCIIDigit(c) { + return c >= 0x30 && c <= 0x39; +} + +function isASCIIAlpha(c) { + return (c >= 0x41 && c <= 0x5A) || (c >= 0x61 && c <= 0x7A); +} + +function isASCIIAlphanumeric(c) { + return isASCIIAlpha(c) || isASCIIDigit(c); +} + +function isASCIIHex(c) { + return isASCIIDigit(c) || (c >= 0x41 && c <= 0x46) || (c >= 0x61 && c <= 0x66); +} + + +function parseIPv6(input) { + const ip = [0, 0, 0, 0, 0, 0, 0, 0]; + let piecePtr = 0; + let compressPtr = null; + let pointer = 0; + + input = punycode.ucs2.decode(input); + + if (input[pointer] === p(":")) { + if (input[pointer + 1] !== p(":")) { + return failure; + } + + pointer += 2; + ++piecePtr; + compressPtr = piecePtr; + } + + let ipv4 = false; + Main: + while (pointer < input.length) { + if (piecePtr === 8) { + return failure; + } + + if (input[pointer] === p(":")) { + if (compressPtr !== null) { + return failure; + } + ++pointer; + ++piecePtr; + compressPtr = piecePtr; + continue; + } + + let value = 0; + let length = 0; + + while (length < 4 && isASCIIHex(input[pointer])) { + value = value * 0x10 + parseInt(at(input, pointer), 16); + ++pointer; + ++length; + } + + switch (at(input, pointer)) { + case ".": + if (length === 0) { + return failure; + } + pointer -= length; + ipv4 = true; + break Main; + case ":": + ++pointer; + if (input[pointer] === undefined) { + return failure; + } + break; + case undefined: + break; + default: + return failure; + } + + ip[piecePtr] = value; + ++piecePtr; + } + + if (ipv4 && piecePtr > 6) { + return failure; + } else if (input[pointer] !== undefined) { + let dotsSeen = 0; + + while (input[pointer] !== undefined) { + let value = null; + if (!isASCIIDigit(input[pointer])) { + return failure; + } + + while (isASCIIDigit(input[pointer])) { + const number = parseInt(at(input, pointer)); + if (value === null) { + value = number; + } else if (value === 0) { + return failure; + } else { + value = value * 10 + number; + } + ++pointer; + if (value > 255) { + return failure; + } + } + + if (dotsSeen < 3 && input[pointer] !== p(".")) { + return failure; + } + ip[piecePtr] = ip[piecePtr] * 0x100 + value; + if (dotsSeen === 1 || dotsSeen === 3) { + ++piecePtr; + } + + if (dotsSeen === 3 && input[pointer] !== undefined) { + return failure; + } + + if (input[pointer] === p(".")) { + ++pointer; + ++dotsSeen; + } + } + } + + if (compressPtr !== null) { + let swaps = piecePtr - compressPtr; + piecePtr = 7; + while (piecePtr !== 0 && swaps > 0) { + const temp = ip[compressPtr + swaps - 1]; // piece + ip[compressPtr + swaps - 1] = ip[piecePtr]; + ip[piecePtr] = temp; + --piecePtr; + --swaps; + } + } else if (piecePtr !== 8) { + return failure; + } + + return ip; +} \ No newline at end of file