<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.1//EN"
"http://www.w3.org/TR/xhtml11/DTD/xhtml11.dtd">
<html xmlns="http://www.w3.org/1999/xhtml">
<head><meta http-equiv="content-type" content="text/html; charset=utf-8" />
<title>[205273] trunk</title>
</head>
<body>

<style type="text/css"><!--
#msg dl.meta { border: 1px #006 solid; background: #369; padding: 6px; color: #fff; }
#msg dl.meta dt { float: left; width: 6em; font-weight: bold; }
#msg dt:after { content:':';}
#msg dl, #msg dt, #msg ul, #msg li, #header, #footer, #logmsg { font-family: verdana,arial,helvetica,sans-serif; font-size: 10pt;  }
#msg dl a { font-weight: bold}
#msg dl a:link    { color:#fc3; }
#msg dl a:active  { color:#ff0; }
#msg dl a:visited { color:#cc6; }
h3 { font-family: verdana,arial,helvetica,sans-serif; font-size: 10pt; font-weight: bold; }
#msg pre { overflow: auto; background: #ffc; border: 1px #fa0 solid; padding: 6px; }
#logmsg { background: #ffc; border: 1px #fa0 solid; padding: 1em 1em 0 1em; }
#logmsg p, #logmsg pre, #logmsg blockquote { margin: 0 0 1em 0; }
#logmsg p, #logmsg li, #logmsg dt, #logmsg dd { line-height: 14pt; }
#logmsg h1, #logmsg h2, #logmsg h3, #logmsg h4, #logmsg h5, #logmsg h6 { margin: .5em 0; }
#logmsg h1:first-child, #logmsg h2:first-child, #logmsg h3:first-child, #logmsg h4:first-child, #logmsg h5:first-child, #logmsg h6:first-child { margin-top: 0; }
#logmsg ul, #logmsg ol { padding: 0; list-style-position: inside; margin: 0 0 0 1em; }
#logmsg ul { text-indent: -1em; padding-left: 1em; }#logmsg ol { text-indent: -1.5em; padding-left: 1.5em; }
#logmsg > ul, #logmsg > ol { margin: 0 0 1em 0; }
#logmsg pre { background: #eee; padding: 1em; }
#logmsg blockquote { border: 1px solid #fa0; border-left-width: 10px; padding: 1em 1em 0 1em; background: white;}
#logmsg dl { margin: 0; }
#logmsg dt { font-weight: bold; }
#logmsg dd { margin: 0; padding: 0 0 0.5em 0; }
#logmsg dd:before { content:'\00bb';}
#logmsg table { border-spacing: 0px; border-collapse: collapse; border-top: 4px solid #fa0; border-bottom: 1px solid #fa0; background: #fff; }
#logmsg table th { text-align: left; font-weight: normal; padding: 0.2em 0.5em; border-top: 1px dotted #fa0; }
#logmsg table td { text-align: right; border-top: 1px dotted #fa0; padding: 0.2em 0.5em; }
#logmsg table thead th { text-align: center; border-bottom: 1px solid #fa0; }
#logmsg table th.Corner { text-align: left; }
#logmsg hr { border: none 0; border-top: 2px dashed #fa0; height: 1px; }
#header, #footer { color: #fff; background: #636; border: 1px #300 solid; padding: 6px; }
#patch { width: 100%; }
#patch h4 {font-family: verdana,arial,helvetica,sans-serif;font-size:10pt;padding:8px;background:#369;color:#fff;margin:0;}
#patch .propset h4, #patch .binary h4 {margin:0;}
#patch pre {padding:0;line-height:1.2em;margin:0;}
#patch .diff {width:100%;background:#eee;padding: 0 0 10px 0;overflow:auto;}
#patch .propset .diff, #patch .binary .diff  {padding:10px 0;}
#patch span {display:block;padding:0 10px;}
#patch .modfile, #patch .addfile, #patch .delfile, #patch .propset, #patch .binary, #patch .copfile {border:1px solid #ccc;margin:10px 0;}
#patch ins {background:#dfd;text-decoration:none;display:block;padding:0 10px;}
#patch del {background:#fdd;text-decoration:none;display:block;padding:0 10px;}
#patch .lines, .info {color:#888;background:#fff;}
--></style>
<div id="msg">
<dl class="meta">
<dt>Revision</dt> <dd><a href="http://trac.webkit.org/projects/webkit/changeset/205273">205273</a></dd>
<dt>Author</dt> <dd>achristensen@apple.com</dd>
<dt>Date</dt> <dd>2016-08-31 17:23:47 -0700 (Wed, 31 Aug 2016)</dd>
</dl>

<h3>Log Message</h3>
<pre>Implement IPv6 parsing in URLParser
https://bugs.webkit.org/show_bug.cgi?id=161390

Reviewed by Darin Adler.

Source/WebCore:

Covered by new API tests.

* platform/URLParser.cpp:
(WebCore::zeroSequenceLength):
(WebCore::findLongestZeroSequence):
(WebCore::nibbleToHex):
(WebCore::serializeIPv6Piece):
(WebCore::serializeIPv6):
(WebCore::parseIPv6Host):
(WebCore::URLParser::hostEndReached):

Source/WTF:

* wtf/ASCIICType.h:
(WTF::lowerNibbleToLowercaseASCIIHexDigit):
(WTF::upperNibbleToLowercaseASCIIHexDigit):

Tools:

* TestWebKitAPI/Tests/WebCore/URLParser.cpp:
(TestWebKitAPI::TEST_F):
(TestWebKitAPI::checkURLDifferences):</pre>

<h3>Modified Paths</h3>
<ul>
<li><a href="#trunkSourceWTFChangeLog">trunk/Source/WTF/ChangeLog</a></li>
<li><a href="#trunkSourceWTFwtfASCIICTypeh">trunk/Source/WTF/wtf/ASCIICType.h</a></li>
<li><a href="#trunkSourceWebCoreChangeLog">trunk/Source/WebCore/ChangeLog</a></li>
<li><a href="#trunkSourceWebCoreplatformURLParsercpp">trunk/Source/WebCore/platform/URLParser.cpp</a></li>
<li><a href="#trunkToolsChangeLog">trunk/Tools/ChangeLog</a></li>
<li><a href="#trunkToolsTestWebKitAPITestsWebCoreURLParsercpp">trunk/Tools/TestWebKitAPI/Tests/WebCore/URLParser.cpp</a></li>
</ul>

</div>
<div id="patch">
<h3>Diff</h3>
<a id="trunkSourceWTFChangeLog"></a>
<div class="modfile"><h4>Modified: trunk/Source/WTF/ChangeLog (205272 => 205273)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/Source/WTF/ChangeLog        2016-09-01 00:17:00 UTC (rev 205272)
+++ trunk/Source/WTF/ChangeLog        2016-09-01 00:23:47 UTC (rev 205273)
</span><span class="lines">@@ -1,3 +1,14 @@
</span><ins>+2016-08-31  Alex Christensen  &lt;achristensen@webkit.org&gt;
+
+        Implement IPv6 parsing in URLParser
+        https://bugs.webkit.org/show_bug.cgi?id=161390
+
+        Reviewed by Darin Adler.
+
+        * wtf/ASCIICType.h:
+        (WTF::lowerNibbleToLowercaseASCIIHexDigit):
+        (WTF::upperNibbleToLowercaseASCIIHexDigit):
+
</ins><span class="cx"> 2016-08-30  Brady Eidson  &lt;beidson@apple.com&gt;
</span><span class="cx"> 
</span><span class="cx">         GameController.framework backend for gamepad API.
</span></span></pre></div>
<a id="trunkSourceWTFwtfASCIICTypeh"></a>
<div class="modfile"><h4>Modified: trunk/Source/WTF/wtf/ASCIICType.h (205272 => 205273)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/Source/WTF/wtf/ASCIICType.h        2016-09-01 00:17:00 UTC (rev 205272)
+++ trunk/Source/WTF/wtf/ASCIICType.h        2016-09-01 00:23:47 UTC (rev 205273)
</span><span class="lines">@@ -187,6 +187,18 @@
</span><span class="cx">     return nibble + (nibble &lt; 10 ? '0' : 'A' - 10);
</span><span class="cx"> }
</span><span class="cx"> 
</span><ins>+inline char lowerNibbleToLowercaseASCIIHexDigit(uint8_t value)
+{
+    uint8_t nibble = value &amp; 0xF;
+    return nibble + (nibble &lt; 10 ? '0' : 'a' - 10);
+}
+
+inline char upperNibbleToLowercaseASCIIHexDigit(uint8_t value)
+{
+    uint8_t nibble = value &gt;&gt; 4;
+    return nibble + (nibble &lt; 10 ? '0' : 'a' - 10);
+}
+
</ins><span class="cx"> template&lt;typename CharacterType&gt; inline bool isASCIIAlphaCaselessEqual(CharacterType inputCharacter, char expectedASCIILowercaseLetter)
</span><span class="cx"> {
</span><span class="cx">     // Name of this argument says this must be a lowercase letter, but it can actually be:
</span><span class="lines">@@ -219,10 +231,12 @@
</span><span class="cx"> using WTF::isASCIISpace;
</span><span class="cx"> using WTF::isASCIIUpper;
</span><span class="cx"> using WTF::lowerNibbleToASCIIHexDigit;
</span><ins>+using WTF::lowerNibbleToLowercaseASCIIHexDigit;
</ins><span class="cx"> using WTF::toASCIIHexValue;
</span><span class="cx"> using WTF::toASCIILower;
</span><span class="cx"> using WTF::toASCIILowerUnchecked;
</span><span class="cx"> using WTF::toASCIIUpper;
</span><span class="cx"> using WTF::upperNibbleToASCIIHexDigit;
</span><ins>+using WTF::upperNibbleToLowercaseASCIIHexDigit;
</ins><span class="cx"> 
</span><span class="cx"> #endif
</span></span></pre></div>
<a id="trunkSourceWebCoreChangeLog"></a>
<div class="modfile"><h4>Modified: trunk/Source/WebCore/ChangeLog (205272 => 205273)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/Source/WebCore/ChangeLog        2016-09-01 00:17:00 UTC (rev 205272)
+++ trunk/Source/WebCore/ChangeLog        2016-09-01 00:23:47 UTC (rev 205273)
</span><span class="lines">@@ -1,3 +1,21 @@
</span><ins>+2016-08-31  Alex Christensen  &lt;achristensen@webkit.org&gt;
+
+        Implement IPv6 parsing in URLParser
+        https://bugs.webkit.org/show_bug.cgi?id=161390
+
+        Reviewed by Darin Adler.
+
+        Covered by new API tests.
+
+        * platform/URLParser.cpp:
+        (WebCore::zeroSequenceLength):
+        (WebCore::findLongestZeroSequence):
+        (WebCore::nibbleToHex):
+        (WebCore::serializeIPv6Piece):
+        (WebCore::serializeIPv6):
+        (WebCore::parseIPv6Host):
+        (WebCore::URLParser::hostEndReached):
+
</ins><span class="cx"> 2016-08-31  Ricky Mondello  &lt;rmondello@apple.com&gt;
</span><span class="cx"> 
</span><span class="cx">         Break pluginReplacementEnabled into youTubeFlashPluginReplacementEnabled and quickTimePluginReplacementEnabled
</span></span></pre></div>
<a id="trunkSourceWebCoreplatformURLParsercpp"></a>
<div class="modfile"><h4>Modified: trunk/Source/WebCore/platform/URLParser.cpp (205272 => 205273)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/Source/WebCore/platform/URLParser.cpp        2016-09-01 00:17:00 UTC (rev 205272)
+++ trunk/Source/WebCore/platform/URLParser.cpp        2016-09-01 00:23:47 UTC (rev 205273)
</span><span class="lines">@@ -563,6 +563,74 @@
</span><span class="cx">     buffer.appendNumber(address &amp; 0xFF);
</span><span class="cx"> }
</span><span class="cx">     
</span><ins>+static size_t zeroSequenceLength(const std::array&lt;uint16_t, 8&gt;&amp; address, size_t begin)
+{
+    size_t end = begin;
+    for (; end &lt; 8; end++) {
+        if (address[end])
+            break;
+    }
+    return end - begin;
+}
+
+static Optional&lt;size_t&gt; findLongestZeroSequence(const std::array&lt;uint16_t, 8&gt;&amp; address)
+{
+    Optional&lt;size_t&gt; longest;
+    size_t longestLength = 0;
+    for (size_t i = 0; i &lt; 8; i++) {
+        size_t length = zeroSequenceLength(address, i);
+        if (length) {
+            if (length &gt; 1 &amp;&amp; (!longest || longestLength &lt; length)) {
+                longest = i;
+                longestLength = length;
+            }
+            i += length;
+        }
+    }
+    return longest;
+}
+    
+static void serializeIPv6Piece(uint16_t piece, StringBuilder&amp; buffer)
+{
+    bool printed = false;
+    if (auto nibble0 = piece &gt;&gt; 12) {
+        buffer.append(lowerNibbleToLowercaseASCIIHexDigit(nibble0));
+        printed = true;
+    }
+    auto nibble1 = piece &gt;&gt; 8 &amp; 0xF;
+    if (printed || nibble1) {
+        buffer.append(lowerNibbleToLowercaseASCIIHexDigit(nibble1));
+        printed = true;
+    }
+    auto nibble2 = piece &gt;&gt; 4 &amp; 0xF;
+    if (printed || nibble2)
+        buffer.append(lowerNibbleToLowercaseASCIIHexDigit(nibble2));
+    buffer.append(lowerNibbleToLowercaseASCIIHexDigit(piece &amp; 0xF));
+}
+
+static void serializeIPv6(std::array&lt;uint16_t, 8&gt; address, StringBuilder&amp; buffer)
+{
+    buffer.append('[');
+    auto compressPointer = findLongestZeroSequence(address);
+    for (size_t piece = 0; piece &lt; 8; piece++) {
+        if (compressPointer &amp;&amp; compressPointer.value() == piece) {
+            ASSERT(!address[piece]);
+            if (piece)
+                buffer.append(':');
+            else
+                buffer.append(&quot;::&quot;);
+            while (!address[piece])
+                piece++;
+            if (piece == 8)
+                break;
+        }
+        serializeIPv6Piece(address[piece], buffer);
+        if (piece &lt; 7)
+            buffer.append(':');
+    }
+    buffer.append(']');
+}
+
</ins><span class="cx"> static Optional&lt;uint32_t&gt; parseIPv4Number(StringView::CodePoints::Iterator&amp; iterator, const StringView::CodePoints::Iterator&amp; end)
</span><span class="cx"> {
</span><span class="cx">     // FIXME: Check for overflow.
</span><span class="lines">@@ -660,10 +728,96 @@
</span><span class="cx">     return ipv4;
</span><span class="cx"> }
</span><span class="cx"> 
</span><del>-static Optional&lt;std::array&lt;uint16_t, 8&gt;&gt; parseIPv6Host(StringView::CodePoints::Iterator, StringView::CodePoints::Iterator)
</del><ins>+static Optional&lt;std::array&lt;uint16_t, 8&gt;&gt; parseIPv6Host(StringView::CodePoints::Iterator c, StringView::CodePoints::Iterator end)
</ins><span class="cx"> {
</span><del>-    notImplemented();
-    return Nullopt;
</del><ins>+    if (c == end)
+        return Nullopt;
+
+    std::array&lt;uint16_t, 8&gt; address = {{0, 0, 0, 0, 0, 0, 0, 0}};
+    size_t piecePointer = 0;
+    Optional&lt;size_t&gt; compressPointer;
+
+    if (*c == ':') {
+        ++c;
+        if (c == end)
+            return Nullopt;
+        if (*c != ':')
+            return Nullopt;
+        ++c;
+        ++piecePointer;
+        compressPointer = piecePointer;
+    }
+    
+    while (c != end) {
+        if (piecePointer == 8)
+            return Nullopt;
+        if (*c == ':') {
+            if (compressPointer)
+                return Nullopt;
+            ++c;
+            ++piecePointer;
+            compressPointer = piecePointer;
+            continue;
+        }
+        uint16_t value = 0;
+        for (size_t length = 0; length &lt; 4; length++) {
+            if (c == end)
+                break;
+            if (!isASCIIHexDigit(*c))
+                break;
+            value = value * 0x10 + toASCIIHexValue(*c);
+            ++c;
+        }
+        address[piecePointer++] = value;
+        if (c == end)
+            break;
+        if (*c != ':')
+            return Nullopt;
+        ++c;
+    }
+    
+    if (c != end) {
+        if (piecePointer &gt; 6)
+            return Nullopt;
+        size_t dotsSeen = 0;
+        while (c != end) {
+            Optional&lt;uint16_t&gt; value;
+            if (!isASCIIDigit(*c))
+                return Nullopt;
+            while (isASCIIDigit(*c)) {
+                auto number = *c - '0';
+                if (!value)
+                    value = number;
+                else if (!value.value())
+                    return Nullopt;
+                else
+                    value = value.value() * 10 + number;
+                ++c;
+                if (c == end)
+                    return Nullopt;
+                if (value.value() &gt; 255)
+                    return Nullopt;
+            }
+            if (dotsSeen &lt; 3 &amp;&amp; *c != '.')
+                return Nullopt;
+            address[piecePointer] = address[piecePointer] * 0x100 + value.valueOr(0);
+            if (dotsSeen == 1 || dotsSeen == 3)
+                piecePointer++;
+            if (c != end)
+                ++c;
+            if (dotsSeen == 3 &amp;&amp; c != end)
+                return Nullopt;
+            dotsSeen++;
+        }
+    }
+    if (compressPointer) {
+        size_t swaps = piecePointer - compressPointer.value();
+        piecePointer = 7;
+        while (swaps)
+            std::swap(address[piecePointer--], address[compressPointer.value() + swaps-- - 1]);
+    } else if (piecePointer != 8)
+        return Nullopt;
+    return address;
</ins><span class="cx"> }
</span><span class="cx"> 
</span><span class="cx"> void URLParser::hostEndReached()
</span><span class="lines">@@ -675,8 +829,16 @@
</span><span class="cx">         return;
</span><span class="cx">     if (*iterator == '[') {
</span><span class="cx">         ++iterator;
</span><del>-        parseIPv6Host(iterator, end);
-        return;
</del><ins>+        auto ipv6End = iterator;
+        while (ipv6End != end &amp;&amp; *ipv6End != ']')
+            ++ipv6End;
+        if (auto address = parseIPv6Host(iterator, ipv6End)) {
+            serializeIPv6(address.value(), m_buffer);
+            m_url.m_hostEnd = m_buffer.length();
+            // FIXME: Handle the port correctly.
+            m_url.m_portEnd = m_buffer.length();            
+            return;
+        }
</ins><span class="cx">     }
</span><span class="cx">     if (auto address = parseIPv4Host(iterator, end)) {
</span><span class="cx">         serializeIPv4(address.value(), m_buffer);
</span></span></pre></div>
<a id="trunkToolsChangeLog"></a>
<div class="modfile"><h4>Modified: trunk/Tools/ChangeLog (205272 => 205273)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/Tools/ChangeLog        2016-09-01 00:17:00 UTC (rev 205272)
+++ trunk/Tools/ChangeLog        2016-09-01 00:23:47 UTC (rev 205273)
</span><span class="lines">@@ -1,3 +1,14 @@
</span><ins>+2016-08-31  Alex Christensen  &lt;achristensen@webkit.org&gt;
+
+        Implement IPv6 parsing in URLParser
+        https://bugs.webkit.org/show_bug.cgi?id=161390
+
+        Reviewed by Darin Adler.
+
+        * TestWebKitAPI/Tests/WebCore/URLParser.cpp:
+        (TestWebKitAPI::TEST_F):
+        (TestWebKitAPI::checkURLDifferences):
+
</ins><span class="cx"> 2016-08-31  Brady Eidson  &lt;beidson@apple.com&gt;
</span><span class="cx"> 
</span><span class="cx">         WK2 Gamepad provider on iOS.
</span></span></pre></div>
<a id="trunkToolsTestWebKitAPITestsWebCoreURLParsercpp"></a>
<div class="modfile"><h4>Modified: trunk/Tools/TestWebKitAPI/Tests/WebCore/URLParser.cpp (205272 => 205273)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/Tools/TestWebKitAPI/Tests/WebCore/URLParser.cpp        2016-09-01 00:17:00 UTC (rev 205272)
+++ trunk/Tools/TestWebKitAPI/Tests/WebCore/URLParser.cpp        2016-09-01 00:23:47 UTC (rev 205273)
</span><span class="lines">@@ -50,7 +50,12 @@
</span><span class="cx">     String string;
</span><span class="cx"> };
</span><span class="cx"> 
</span><del>-static bool eq(const String&amp; s1, const String&amp; s2) { return s1.utf8() == s2.utf8(); }
</del><ins>+static bool eq(const String&amp; s1, const String&amp; s2)
+{
+    EXPECT_STREQ(s1.utf8().data(), s2.utf8().data());
+    return s1.utf8() == s2.utf8();
+}
+
</ins><span class="cx"> static void checkURL(const String&amp; urlString, const ExpectedParts&amp; parts)
</span><span class="cx"> {
</span><span class="cx">     URLParser parser;
</span><span class="lines">@@ -94,6 +99,9 @@
</span><span class="cx">     checkURL(&quot;about:blank&quot;, {&quot;about&quot;, &quot;&quot;, &quot;&quot;, &quot;&quot;, 0, &quot;blank&quot;, &quot;&quot;, &quot;&quot;, &quot;about:blank&quot;});
</span><span class="cx">     checkURL(&quot;about:blank?query&quot;, {&quot;about&quot;, &quot;&quot;, &quot;&quot;, &quot;&quot;, 0, &quot;blank&quot;, &quot;query&quot;, &quot;&quot;, &quot;about:blank?query&quot;});
</span><span class="cx">     checkURL(&quot;about:blank#fragment&quot;, {&quot;about&quot;, &quot;&quot;, &quot;&quot;, &quot;&quot;, 0, &quot;blank&quot;, &quot;&quot;, &quot;fragment&quot;, &quot;about:blank#fragment&quot;});
</span><ins>+    checkURL(&quot;http://[0:f::f:f:0:0]&quot;, {&quot;http&quot;, &quot;&quot;, &quot;&quot;, &quot;[0:f::f:f:0:0]&quot;, 0, &quot;/&quot;, &quot;&quot;, &quot;&quot;, &quot;http://[0:f::f:f:0:0]/&quot;});
+    checkURL(&quot;http://[0:f:0:0:f::]&quot;, {&quot;http&quot;, &quot;&quot;, &quot;&quot;, &quot;[0:f:0:0:f::]&quot;, 0, &quot;/&quot;, &quot;&quot;, &quot;&quot;, &quot;http://[0:f:0:0:f::]/&quot;});
+    checkURL(&quot;http://[::f:0:0:f:0:0]&quot;, {&quot;http&quot;, &quot;&quot;, &quot;&quot;, &quot;[::f:0:0:f:0:0]&quot;, 0, &quot;/&quot;, &quot;&quot;, &quot;&quot;, &quot;http://[::f:0:0:f:0:0]/&quot;});
</ins><span class="cx"> }
</span><span class="cx"> 
</span><span class="cx"> static void checkRelativeURL(const String&amp; urlString, const String&amp; baseURLString, const ExpectedParts&amp; parts)
</span><span class="lines">@@ -202,6 +210,18 @@
</span><span class="cx">     checkURLDifferences(&quot;http://011.11.0X11.0x011&quot;,
</span><span class="cx">         {&quot;http&quot;, &quot;&quot;, &quot;&quot;, &quot;9.11.17.17&quot;, 0, &quot;/&quot;, &quot;&quot;, &quot;&quot;, &quot;http://9.11.17.17/&quot;},
</span><span class="cx">         {&quot;http&quot;, &quot;&quot;, &quot;&quot;, &quot;011.11.0x11.0x011&quot;, 0, &quot;/&quot;, &quot;&quot;, &quot;&quot;, &quot;http://011.11.0x11.0x011/&quot;});
</span><ins>+    checkURLDifferences(&quot;http://[1234:0078:90AB:CdEf:0123:0007:89AB:0000]&quot;,
+        {&quot;http&quot;, &quot;&quot;, &quot;&quot;, &quot;[1234:78:90ab:cdef:123:7:89ab:0]&quot;, 0, &quot;/&quot;, &quot;&quot;, &quot;&quot;, &quot;http://[1234:78:90ab:cdef:123:7:89ab:0]/&quot;},
+        {&quot;http&quot;, &quot;&quot;, &quot;&quot;, &quot;[1234:0078:90ab:cdef:0123:0007:89ab:0000]&quot;, 0, &quot;/&quot;, &quot;&quot;, &quot;&quot;, &quot;http://[1234:0078:90ab:cdef:0123:0007:89ab:0000]/&quot;});
+    checkURLDifferences(&quot;http://[0:f:0:0:f:f:0:0]&quot;,
+        {&quot;http&quot;, &quot;&quot;, &quot;&quot;, &quot;[0:f::f:f:0:0]&quot;, 0, &quot;/&quot;, &quot;&quot;, &quot;&quot;, &quot;http://[0:f::f:f:0:0]/&quot;},
+        {&quot;http&quot;, &quot;&quot;, &quot;&quot;, &quot;[0:f:0:0:f:f:0:0]&quot;, 0, &quot;/&quot;, &quot;&quot;, &quot;&quot;, &quot;http://[0:f:0:0:f:f:0:0]/&quot;});
+    checkURLDifferences(&quot;http://[0:f:0:0:f:0:0:0]&quot;,
+        {&quot;http&quot;, &quot;&quot;, &quot;&quot;, &quot;[0:f:0:0:f::]&quot;, 0, &quot;/&quot;, &quot;&quot;, &quot;&quot;, &quot;http://[0:f:0:0:f::]/&quot;},
+        {&quot;http&quot;, &quot;&quot;, &quot;&quot;, &quot;[0:f:0:0:f:0:0:0]&quot;, 0, &quot;/&quot;, &quot;&quot;, &quot;&quot;, &quot;http://[0:f:0:0:f:0:0:0]/&quot;});
+    checkURLDifferences(&quot;http://[0:0:f:0:0:f:0:0]&quot;,
+        {&quot;http&quot;, &quot;&quot;, &quot;&quot;, &quot;[::f:0:0:f:0:0]&quot;, 0, &quot;/&quot;, &quot;&quot;, &quot;&quot;, &quot;http://[::f:0:0:f:0:0]/&quot;},
+        {&quot;http&quot;, &quot;&quot;, &quot;&quot;, &quot;[0:0:f:0:0:f:0:0]&quot;, 0, &quot;/&quot;, &quot;&quot;, &quot;&quot;, &quot;http://[0:0:f:0:0:f:0:0]/&quot;});
</ins><span class="cx"> 
</span><span class="cx">     // FIXME: This behavior ought to be specified in the standard.
</span><span class="cx">     // With the existing URL::parse, WebKit returns &quot;https:/&quot;, Firefox returns &quot;https:///&quot;, and Chrome throws an error.
</span></span></pre>
</div>
</div>

</body>
</html>