<!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>[206337] trunk/Source/WebCore</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/206337">206337</a></dd>
<dt>Author</dt> <dd>achristensen@apple.com</dd>
<dt>Date</dt> <dd>2016-09-23 16:40:46 -0700 (Fri, 23 Sep 2016)</dd>
</dl>

<h3>Log Message</h3>
<pre>Refactor URLParser
https://bugs.webkit.org/show_bug.cgi?id=162518

Reviewed by Brady Eidson.

Use a helper function to determine the currentPosition instead of always determining position based on the
size of the buffer.  Soon there will be nothing in the buffer in the common case where there are no syntax errors.
Also make more static functions into methods.  Give IPv6Addresses and IPv4Addresses names.  Start adding syntaxError stubs.

No change in behavior.  Covered by API tests.

* platform/URLParser.cpp:
(WebCore::URLParser::incrementIteratorSkippingTabAndNewLine):
(WebCore::URLParser::isWindowsDriveLetter):
(WebCore::URLParser::appendToASCIIBuffer):
(WebCore::URLParser::syntaxError):
(WebCore::URLParser::currentPosition):
(WebCore::URLParser::URLParser):
(WebCore::URLParser::parse):
(WebCore::URLParser::parseAuthority):
(WebCore::URLParser::appendNumberToASCIIBuffer):
(WebCore::URLParser::serializeIPv4):
(WebCore::URLParser::serializeIPv6Piece):
(WebCore::URLParser::serializeIPv6):
(WebCore::URLParser::parseIPv4Host):
(WebCore::URLParser::parseIPv6Host):
(WebCore::URLParser::parsePort):
(WebCore::URLParser::parseHostAndPort):
(WebCore::append): Deleted.
(WebCore::serializeIPv4): Deleted.
(WebCore::serializeIPv6Piece): Deleted.
(WebCore::serializeIPv6): Deleted.
(WebCore::parseIPv4Host): Deleted.
(WebCore::parseIPv6Host): Deleted.
* platform/URLParser.h:</pre>

<h3>Modified Paths</h3>
<ul>
<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="#trunkSourceWebCoreplatformURLParserh">trunk/Source/WebCore/platform/URLParser.h</a></li>
</ul>

</div>
<div id="patch">
<h3>Diff</h3>
<a id="trunkSourceWebCoreChangeLog"></a>
<div class="modfile"><h4>Modified: trunk/Source/WebCore/ChangeLog (206336 => 206337)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/Source/WebCore/ChangeLog        2016-09-23 23:26:01 UTC (rev 206336)
+++ trunk/Source/WebCore/ChangeLog        2016-09-23 23:40:46 UTC (rev 206337)
</span><span class="lines">@@ -1,6 +1,44 @@
</span><span class="cx"> 2016-09-23  Alex Christensen  &lt;achristensen@webkit.org&gt;
</span><span class="cx"> 
</span><span class="cx">         Refactor URLParser
</span><ins>+        https://bugs.webkit.org/show_bug.cgi?id=162518
+
+        Reviewed by Brady Eidson.
+
+        Use a helper function to determine the currentPosition instead of always determining position based on the
+        size of the buffer.  Soon there will be nothing in the buffer in the common case where there are no syntax errors.
+        Also make more static functions into methods.  Give IPv6Addresses and IPv4Addresses names.  Start adding syntaxError stubs.
+
+        No change in behavior.  Covered by API tests.
+
+        * platform/URLParser.cpp:
+        (WebCore::URLParser::incrementIteratorSkippingTabAndNewLine):
+        (WebCore::URLParser::isWindowsDriveLetter):
+        (WebCore::URLParser::appendToASCIIBuffer):
+        (WebCore::URLParser::syntaxError):
+        (WebCore::URLParser::currentPosition):
+        (WebCore::URLParser::URLParser):
+        (WebCore::URLParser::parse):
+        (WebCore::URLParser::parseAuthority):
+        (WebCore::URLParser::appendNumberToASCIIBuffer):
+        (WebCore::URLParser::serializeIPv4):
+        (WebCore::URLParser::serializeIPv6Piece):
+        (WebCore::URLParser::serializeIPv6):
+        (WebCore::URLParser::parseIPv4Host):
+        (WebCore::URLParser::parseIPv6Host):
+        (WebCore::URLParser::parsePort):
+        (WebCore::URLParser::parseHostAndPort):
+        (WebCore::append): Deleted.
+        (WebCore::serializeIPv4): Deleted.
+        (WebCore::serializeIPv6Piece): Deleted.
+        (WebCore::serializeIPv6): Deleted.
+        (WebCore::parseIPv4Host): Deleted.
+        (WebCore::parseIPv6Host): Deleted.
+        * platform/URLParser.h:
+
+2016-09-23  Alex Christensen  &lt;achristensen@webkit.org&gt;
+
+        Refactor URLParser
</ins><span class="cx">         https://bugs.webkit.org/show_bug.cgi?id=162516
</span><span class="cx"> 
</span><span class="cx">         Reviewed by Brady Eidson.
</span></span></pre></div>
<a id="trunkSourceWebCoreplatformURLParsercpp"></a>
<div class="modfile"><h4>Modified: trunk/Source/WebCore/platform/URLParser.cpp (206336 => 206337)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/Source/WebCore/platform/URLParser.cpp        2016-09-23 23:26:01 UTC (rev 206336)
+++ trunk/Source/WebCore/platform/URLParser.cpp        2016-09-23 23:40:46 UTC (rev 206337)
</span><span class="lines">@@ -413,8 +413,10 @@
</span><span class="cx"> void URLParser::incrementIteratorSkippingTabAndNewLine(CodePointIterator&lt;CharacterType&gt;&amp; iterator)
</span><span class="cx"> {
</span><span class="cx">     ++iterator;
</span><del>-    while (!iterator.atEnd() &amp;&amp; isTabOrNewline(*iterator))
</del><ins>+    while (!iterator.atEnd() &amp;&amp; isTabOrNewline(*iterator)) {
+        syntaxError(iterator);
</ins><span class="cx">         ++iterator;
</span><ins>+    }
</ins><span class="cx"> }
</span><span class="cx"> 
</span><span class="cx"> template&lt;typename CharacterType&gt;
</span><span class="lines">@@ -427,8 +429,10 @@
</span><span class="cx">         return false;
</span><span class="cx">     if (*iterator == ':')
</span><span class="cx">         return true;
</span><del>-    if (*iterator == '|')
</del><ins>+    if (*iterator == '|') {
+        syntaxError(iterator);
</ins><span class="cx">         return true;
</span><ins>+    }
</ins><span class="cx">     return false;
</span><span class="cx"> }
</span><span class="cx"> 
</span><span class="lines">@@ -443,13 +447,15 @@
</span><span class="cx"> {
</span><span class="cx">     ASSERT(m_unicodeFragmentBuffer.isEmpty());
</span><span class="cx">     ASSERT(isASCII(codePoint));
</span><del>-    m_asciiBuffer.append(codePoint);
</del><ins>+    if (m_seenSyntaxError)
+        m_asciiBuffer.append(codePoint);
</ins><span class="cx"> }
</span><span class="cx"> 
</span><span class="cx"> void URLParser::appendToASCIIBuffer(const char* characters, size_t length)
</span><span class="cx"> {
</span><span class="cx">     ASSERT(m_unicodeFragmentBuffer.isEmpty());
</span><del>-    m_asciiBuffer.append(characters, length);
</del><ins>+    if (m_seenSyntaxError)
+        m_asciiBuffer.append(characters, length);
</ins><span class="cx"> }
</span><span class="cx"> 
</span><span class="cx"> template&lt;typename CharacterType&gt;
</span><span class="lines">@@ -926,6 +932,12 @@
</span><span class="cx">     m_asciiBuffer.resize(m_url.m_pathAfterLastSlash);
</span><span class="cx"> }
</span><span class="cx"> 
</span><ins>+template&lt;typename CharacterType&gt;
+void URLParser::syntaxError(const CodePointIterator&lt;CharacterType&gt;&amp;)
+{
+    // FIXME: Implement.
+}
+
</ins><span class="cx"> void URLParser::failure()
</span><span class="cx"> {
</span><span class="cx">     m_url.invalidate();
</span><span class="lines">@@ -932,6 +944,15 @@
</span><span class="cx">     m_url.m_string = m_inputString;
</span><span class="cx"> }
</span><span class="cx"> 
</span><ins>+template&lt;typename CharacterType&gt;
+size_t URLParser::currentPosition(const CodePointIterator&lt;CharacterType&gt;&amp; iterator)
+{
+    if (m_seenSyntaxError)
+        return m_asciiBuffer.size();
+    
+    return iterator.codeUnitsSince(reinterpret_cast&lt;const CharacterType*&gt;(m_inputBegin));
+}
+
</ins><span class="cx"> URLParser::URLParser(const String&amp; input, const URL&amp; base, const TextEncoding&amp; encoding)
</span><span class="cx">     : m_inputString(input)
</span><span class="cx"> {
</span><span class="lines">@@ -938,10 +959,13 @@
</span><span class="cx">     if (input.isNull())
</span><span class="cx">         return;
</span><span class="cx"> 
</span><del>-    if (input.is8Bit())
</del><ins>+    if (input.is8Bit()) {
+        m_inputBegin = input.characters8();
</ins><span class="cx">         parse(input.characters8(), input.length(), base, encoding);
</span><del>-    else
</del><ins>+    } else {
+        m_inputBegin = input.characters16();
</ins><span class="cx">         parse(input.characters16(), input.length(), base, encoding);
</span><ins>+    }
</ins><span class="cx"> }
</span><span class="cx"> 
</span><span class="cx"> template&lt;typename CharacterType&gt;
</span><span class="lines">@@ -987,12 +1011,13 @@
</span><span class="cx">         Fragment,
</span><span class="cx">     };
</span><span class="cx"> 
</span><del>-#define LOG_STATE(x) LOG(URLParser, &quot;State %s, code point %c, asciiBuffer size %zu&quot;, x, *c, m_asciiBuffer.size())
</del><ins>+#define LOG_STATE(x) LOG(URLParser, &quot;State %s, code point %c, asciiBuffer size %zu&quot;, x, *c, currentPosition(c))
</ins><span class="cx"> #define LOG_FINAL_STATE(x) LOG(URLParser, &quot;Final State: %s&quot;, x)
</span><span class="cx"> 
</span><span class="cx">     State state = State::SchemeStart;
</span><span class="cx">     while (!c.atEnd()) {
</span><span class="cx">         if (isTabOrNewline(*c)) {
</span><ins>+            syntaxError(c);
</ins><span class="cx">             ++c;
</span><span class="cx">             continue;
</span><span class="cx">         }
</span><span class="lines">@@ -1001,7 +1026,7 @@
</span><span class="cx">         case State::SchemeStart:
</span><span class="cx">             LOG_STATE(&quot;SchemeStart&quot;);
</span><span class="cx">             if (isASCIIAlpha(*c)) {
</span><del>-                m_asciiBuffer.uncheckedAppend(toASCIILower(*c));
</del><ins>+                appendToASCIIBuffer(toASCIILower(*c));
</ins><span class="cx">                 incrementIteratorSkippingTabAndNewLine(c);
</span><span class="cx">                 if (c.atEnd()) {
</span><span class="cx">                     m_asciiBuffer.clear();
</span><span class="lines">@@ -1017,7 +1042,7 @@
</span><span class="cx">             if (isValidSchemeCharacter(*c))
</span><span class="cx">                 appendToASCIIBuffer(toASCIILower(*c));
</span><span class="cx">             else if (*c == ':') {
</span><del>-                m_url.m_schemeEnd = m_asciiBuffer.size();
</del><ins>+                m_url.m_schemeEnd = currentPosition(c);
</ins><span class="cx">                 StringView urlScheme = StringView(m_asciiBuffer.data(), m_url.m_schemeEnd);
</span><span class="cx">                 m_url.m_protocolIsInHTTPFamily = urlScheme == &quot;http&quot; || urlScheme == &quot;https&quot;;
</span><span class="cx">                 if (urlScheme == &quot;file&quot;) {
</span><span class="lines">@@ -1030,7 +1055,7 @@
</span><span class="cx">                 appendToASCIIBuffer(':');
</span><span class="cx">                 if (isSpecialScheme(urlScheme)) {
</span><span class="cx">                     m_urlIsSpecial = true;
</span><del>-                    if (base.protocolIs(m_asciiBuffer.data(), m_asciiBuffer.size() - 1))
</del><ins>+                    if (base.protocolIs(m_asciiBuffer.data(), currentPosition(c) - 1))
</ins><span class="cx">                         state = State::SpecialRelativeOrAuthority;
</span><span class="cx">                     else
</span><span class="cx">                         state = State::SpecialAuthoritySlashes;
</span><span class="lines">@@ -1039,12 +1064,12 @@
</span><span class="cx">                     incrementIteratorSkippingTabAndNewLine(maybeSlash);
</span><span class="cx">                     if (!maybeSlash.atEnd() &amp;&amp; *maybeSlash == '/') {
</span><span class="cx">                         appendToASCIIBuffer('/');
</span><del>-                        m_url.m_userStart = m_asciiBuffer.size();
</del><ins>+                        m_url.m_userStart = currentPosition(c);
</ins><span class="cx">                         state = State::PathOrAuthority;
</span><span class="cx">                         c = maybeSlash;
</span><span class="cx">                         ASSERT(*c == '/');
</span><span class="cx">                     } else {
</span><del>-                        m_url.m_userStart = m_asciiBuffer.size();
</del><ins>+                        m_url.m_userStart = currentPosition(c);
</ins><span class="cx">                         m_url.m_userEnd = m_url.m_userStart;
</span><span class="cx">                         m_url.m_passwordEnd = m_url.m_userStart;
</span><span class="cx">                         m_url.m_hostEnd = m_url.m_userStart;
</span><span class="lines">@@ -1112,13 +1137,13 @@
</span><span class="cx">             LOG_STATE(&quot;PathOrAuthority&quot;);
</span><span class="cx">             if (*c == '/') {
</span><span class="cx">                 appendToASCIIBuffer('/');
</span><del>-                m_url.m_userStart = m_asciiBuffer.size();
</del><ins>+                m_url.m_userStart = currentPosition(c);
</ins><span class="cx">                 state = State::AuthorityOrHost;
</span><span class="cx">                 ++c;
</span><span class="cx">                 authorityOrHostBegin = c;
</span><span class="cx">             } else {
</span><span class="cx">                 ASSERT(m_asciiBuffer.last() == '/');
</span><del>-                m_url.m_userStart = m_asciiBuffer.size() - 1;
</del><ins>+                m_url.m_userStart = currentPosition(c) - 1;
</ins><span class="cx">                 m_url.m_userEnd = m_url.m_userStart;
</span><span class="cx">                 m_url.m_passwordEnd = m_url.m_userStart;
</span><span class="cx">                 m_url.m_hostEnd = m_url.m_userStart;
</span><span class="lines">@@ -1183,7 +1208,7 @@
</span><span class="cx">                 appendToASCIIBuffer('/');
</span><span class="cx">                 ++c;
</span><span class="cx">             }
</span><del>-            m_url.m_userStart = m_asciiBuffer.size();
</del><ins>+            m_url.m_userStart = currentPosition(c);
</ins><span class="cx">             state = State::AuthorityOrHost;
</span><span class="cx">             authorityOrHostBegin = c;
</span><span class="cx">             break;
</span><span class="lines">@@ -1208,7 +1233,7 @@
</span><span class="cx">                 }
</span><span class="cx">                 bool isSlash = *c == '/' || (m_urlIsSpecial &amp;&amp; *c == '\\');
</span><span class="cx">                 if (isSlash || *c == '?' || *c == '#') {
</span><del>-                    m_url.m_userEnd = m_asciiBuffer.size();
</del><ins>+                    m_url.m_userEnd = currentPosition(c);
</ins><span class="cx">                     m_url.m_passwordEnd = m_url.m_userEnd;
</span><span class="cx">                     if (!parseHostAndPort(CodePointIterator&lt;CharacterType&gt;(authorityOrHostBegin, c))) {
</span><span class="cx">                         failure();
</span><span class="lines">@@ -1216,7 +1241,7 @@
</span><span class="cx">                     }
</span><span class="cx">                     if (!isSlash) {
</span><span class="cx">                         appendToASCIIBuffer('/');
</span><del>-                        m_url.m_pathAfterLastSlash = m_asciiBuffer.size();
</del><ins>+                        m_url.m_pathAfterLastSlash = currentPosition(c);
</ins><span class="cx">                     }
</span><span class="cx">                     state = State::Path;
</span><span class="cx">                     break;
</span><span class="lines">@@ -1253,7 +1278,7 @@
</span><span class="cx">                 if (base.isValid() &amp;&amp; base.protocolIs(&quot;file&quot;))
</span><span class="cx">                     copyURLPartsUntil(base, URLPart::PathEnd);
</span><span class="cx">                 appendToASCIIBuffer(&quot;///?&quot;, 4);
</span><del>-                m_url.m_userStart = m_asciiBuffer.size() - 2;
</del><ins>+                m_url.m_userStart = currentPosition(c) - 2;
</ins><span class="cx">                 m_url.m_userEnd = m_url.m_userStart;
</span><span class="cx">                 m_url.m_passwordEnd = m_url.m_userStart;
</span><span class="cx">                 m_url.m_hostEnd = m_url.m_userStart;
</span><span class="lines">@@ -1267,7 +1292,7 @@
</span><span class="cx">                 if (base.isValid() &amp;&amp; base.protocolIs(&quot;file&quot;))
</span><span class="cx">                     copyURLPartsUntil(base, URLPart::QueryEnd);
</span><span class="cx">                 appendToASCIIBuffer(&quot;///#&quot;, 4);
</span><del>-                m_url.m_userStart = m_asciiBuffer.size() - 2;
</del><ins>+                m_url.m_userStart = currentPosition(c) - 2;
</ins><span class="cx">                 m_url.m_userEnd = m_url.m_userStart;
</span><span class="cx">                 m_url.m_passwordEnd = m_url.m_userStart;
</span><span class="cx">                 m_url.m_hostEnd = m_url.m_userStart;
</span><span class="lines">@@ -1283,7 +1308,7 @@
</span><span class="cx">                     copyURLPartsUntil(base, URLPart::PathAfterLastSlash);
</span><span class="cx">                 else {
</span><span class="cx">                     appendToASCIIBuffer(&quot;///&quot;, 3);
</span><del>-                    m_url.m_userStart = m_asciiBuffer.size() - 1;
</del><ins>+                    m_url.m_userStart = currentPosition(c) - 1;
</ins><span class="cx">                     m_url.m_userEnd = m_url.m_userStart;
</span><span class="cx">                     m_url.m_passwordEnd = m_url.m_userStart;
</span><span class="cx">                     m_url.m_hostEnd = m_url.m_userStart;
</span><span class="lines">@@ -1300,7 +1325,7 @@
</span><span class="cx">             if (*c == '/' || *c == '\\') {
</span><span class="cx">                 ++c;
</span><span class="cx">                 appendToASCIIBuffer('/');
</span><del>-                m_url.m_userStart = m_asciiBuffer.size();
</del><ins>+                m_url.m_userStart = currentPosition(c);
</ins><span class="cx">                 m_url.m_userEnd = m_url.m_userStart;
</span><span class="cx">                 m_url.m_passwordEnd = m_url.m_userStart;
</span><span class="cx">                 m_url.m_hostEnd = m_url.m_userStart;
</span><span class="lines">@@ -1323,7 +1348,7 @@
</span><span class="cx">                 }
</span><span class="cx">             }
</span><span class="cx">             appendToASCIIBuffer(&quot;//&quot;, 2);
</span><del>-            m_url.m_userStart = m_asciiBuffer.size() - 1;
</del><ins>+            m_url.m_userStart = currentPosition(c) - 1;
</ins><span class="cx">             m_url.m_userEnd = m_url.m_userStart;
</span><span class="cx">             m_url.m_passwordEnd = m_url.m_userStart;
</span><span class="cx">             m_url.m_hostEnd = m_url.m_userStart;
</span><span class="lines">@@ -1340,10 +1365,10 @@
</span><span class="cx">                     break;
</span><span class="cx">                 }
</span><span class="cx">                 if (authorityOrHostBegin == c) {
</span><del>-                    ASSERT(m_asciiBuffer[m_asciiBuffer.size() - 1] == '/');
</del><ins>+                    ASSERT(m_asciiBuffer[currentPosition(c) - 1] == '/');
</ins><span class="cx">                     if (*c == '?') {
</span><span class="cx">                         appendToASCIIBuffer(&quot;/?&quot;, 2);
</span><del>-                        m_url.m_pathAfterLastSlash = m_asciiBuffer.size() - 1;
</del><ins>+                        m_url.m_pathAfterLastSlash = currentPosition(c) - 1;
</ins><span class="cx">                         m_url.m_pathEnd = m_url.m_pathAfterLastSlash;
</span><span class="cx">                         state = State::Query;
</span><span class="cx">                         ++c;
</span><span class="lines">@@ -1351,7 +1376,7 @@
</span><span class="cx">                     }
</span><span class="cx">                     if (*c == '#') {
</span><span class="cx">                         appendToASCIIBuffer(&quot;/#&quot;, 2);
</span><del>-                        m_url.m_pathAfterLastSlash = m_asciiBuffer.size() - 1;
</del><ins>+                        m_url.m_pathAfterLastSlash = currentPosition(c) - 1;
</ins><span class="cx">                         m_url.m_pathEnd = m_url.m_pathAfterLastSlash;
</span><span class="cx">                         m_url.m_queryEnd = m_url.m_pathAfterLastSlash;
</span><span class="cx">                         state = State::Fragment;
</span><span class="lines">@@ -1366,9 +1391,9 @@
</span><span class="cx">                     return;
</span><span class="cx">                 }
</span><span class="cx">                 
</span><del>-                if (StringView(m_asciiBuffer.data() + m_url.m_passwordEnd, m_asciiBuffer.size() - m_url.m_passwordEnd) == &quot;localhost&quot;)  {
</del><ins>+                if (StringView(m_asciiBuffer.data() + m_url.m_passwordEnd, currentPosition(c) - m_url.m_passwordEnd) == &quot;localhost&quot;)  {
</ins><span class="cx">                     m_asciiBuffer.shrink(m_url.m_passwordEnd);
</span><del>-                    m_url.m_hostEnd = m_asciiBuffer.size();
</del><ins>+                    m_url.m_hostEnd = currentPosition(c);
</ins><span class="cx">                     m_url.m_portEnd = m_url.m_hostEnd;
</span><span class="cx">                 }
</span><span class="cx">                 
</span><span class="lines">@@ -1389,28 +1414,28 @@
</span><span class="cx">             LOG_STATE(&quot;Path&quot;);
</span><span class="cx">             if (*c == '/' || (m_urlIsSpecial &amp;&amp; *c == '\\')) {
</span><span class="cx">                 appendToASCIIBuffer('/');
</span><del>-                m_url.m_pathAfterLastSlash = m_asciiBuffer.size();
</del><ins>+                m_url.m_pathAfterLastSlash = currentPosition(c);
</ins><span class="cx">                 ++c;
</span><span class="cx">                 break;
</span><span class="cx">             }
</span><del>-            if (m_asciiBuffer.size() &amp;&amp; m_asciiBuffer[m_asciiBuffer.size() - 1] == '/') {
</del><ins>+            if (currentPosition(c) &amp;&amp; m_asciiBuffer[currentPosition(c) - 1] == '/') {
</ins><span class="cx">                 if (isDoubleDotPathSegment(c)) {
</span><span class="cx">                     consumeDoubleDotPathSegment(c);
</span><span class="cx">                     popPath();
</span><span class="cx">                     break;
</span><span class="cx">                 }
</span><del>-                if (m_asciiBuffer[m_asciiBuffer.size() - 1] == '/' &amp;&amp; isSingleDotPathSegment(c)) {
</del><ins>+                if (m_asciiBuffer[currentPosition(c) - 1] == '/' &amp;&amp; isSingleDotPathSegment(c)) {
</ins><span class="cx">                     consumeSingleDotPathSegment(c);
</span><span class="cx">                     break;
</span><span class="cx">                 }
</span><span class="cx">             }
</span><span class="cx">             if (*c == '?') {
</span><del>-                m_url.m_pathEnd = m_asciiBuffer.size();
</del><ins>+                m_url.m_pathEnd = currentPosition(c);
</ins><span class="cx">                 state = State::Query;
</span><span class="cx">                 break;
</span><span class="cx">             }
</span><span class="cx">             if (*c == '#') {
</span><del>-                m_url.m_pathEnd = m_asciiBuffer.size();
</del><ins>+                m_url.m_pathEnd = currentPosition(c);
</ins><span class="cx">                 m_url.m_queryEnd = m_url.m_pathEnd;
</span><span class="cx">                 state = State::Fragment;
</span><span class="cx">                 break;
</span><span class="lines">@@ -1431,15 +1456,15 @@
</span><span class="cx">         case State::CannotBeABaseURLPath:
</span><span class="cx">             LOG_STATE(&quot;CannotBeABaseURLPath&quot;);
</span><span class="cx">             if (*c == '?') {
</span><del>-                m_url.m_pathEnd = m_asciiBuffer.size();
</del><ins>+                m_url.m_pathEnd = currentPosition(c);
</ins><span class="cx">                 state = State::Query;
</span><span class="cx">             } else if (*c == '#') {
</span><del>-                m_url.m_pathEnd = m_asciiBuffer.size();
</del><ins>+                m_url.m_pathEnd = currentPosition(c);
</ins><span class="cx">                 m_url.m_queryEnd = m_url.m_pathEnd;
</span><span class="cx">                 state = State::Fragment;
</span><span class="cx">             } else if (*c == '/') {
</span><span class="cx">                 appendToASCIIBuffer('/');
</span><del>-                m_url.m_pathAfterLastSlash = m_asciiBuffer.size();
</del><ins>+                m_url.m_pathAfterLastSlash = currentPosition(c);
</ins><span class="cx">                 ++c;
</span><span class="cx">             } else {
</span><span class="cx">                 utf8PercentEncode&lt;isInSimpleEncodeSet&gt;(*c);
</span><span class="lines">@@ -1451,7 +1476,7 @@
</span><span class="cx">             if (*c == '#') {
</span><span class="cx">                 if (!isUTF8Encoding)
</span><span class="cx">                     encodeQuery(queryBuffer, encoding);
</span><del>-                m_url.m_queryEnd = m_asciiBuffer.size();
</del><ins>+                m_url.m_queryEnd = currentPosition(c);
</ins><span class="cx">                 state = State::Fragment;
</span><span class="cx">                 break;
</span><span class="cx">             }
</span><span class="lines">@@ -1475,7 +1500,7 @@
</span><span class="cx">     switch (state) {
</span><span class="cx">     case State::SchemeStart:
</span><span class="cx">         LOG_FINAL_STATE(&quot;SchemeStart&quot;);
</span><del>-        if (!m_asciiBuffer.size() &amp;&amp; base.isValid()) {
</del><ins>+        if (!currentPosition(c) &amp;&amp; base.isValid()) {
</ins><span class="cx">             m_url = base;
</span><span class="cx">             return;
</span><span class="cx">         }
</span><span class="lines">@@ -1496,7 +1521,7 @@
</span><span class="cx">     case State::PathOrAuthority:
</span><span class="cx">         LOG_FINAL_STATE(&quot;PathOrAuthority&quot;);
</span><span class="cx">         ASSERT(m_url.m_userStart);
</span><del>-        ASSERT(m_url.m_userStart == m_asciiBuffer.size());
</del><ins>+        ASSERT(m_url.m_userStart == currentPosition(c));
</ins><span class="cx">         ASSERT(m_asciiBuffer.last() == '/');
</span><span class="cx">         m_url.m_userStart--;
</span><span class="cx">         m_url.m_userEnd = m_url.m_userStart;
</span><span class="lines">@@ -1523,7 +1548,7 @@
</span><span class="cx">         break;
</span><span class="cx">     case State::SpecialAuthoritySlashes:
</span><span class="cx">         LOG_FINAL_STATE(&quot;SpecialAuthoritySlashes&quot;);
</span><del>-        m_url.m_userStart = m_asciiBuffer.size();
</del><ins>+        m_url.m_userStart = currentPosition(c);
</ins><span class="cx">         m_url.m_userEnd = m_url.m_userStart;
</span><span class="cx">         m_url.m_passwordEnd = m_url.m_userStart;
</span><span class="cx">         m_url.m_hostEnd = m_url.m_userStart;
</span><span class="lines">@@ -1540,7 +1565,7 @@
</span><span class="cx">         break;
</span><span class="cx">     case State::AuthorityOrHost:
</span><span class="cx">         LOG_FINAL_STATE(&quot;AuthorityOrHost&quot;);
</span><del>-        m_url.m_userEnd = m_asciiBuffer.size();
</del><ins>+        m_url.m_userEnd = currentPosition(c);
</ins><span class="cx">         m_url.m_passwordEnd = m_url.m_userEnd;
</span><span class="cx">         if (authorityOrHostBegin.atEnd()) {
</span><span class="cx">             m_url.m_hostEnd = m_url.m_userEnd;
</span><span class="lines">@@ -1574,7 +1599,7 @@
</span><span class="cx">             appendToASCIIBuffer(':');
</span><span class="cx">         }
</span><span class="cx">         appendToASCIIBuffer(&quot;///&quot;, 3);
</span><del>-        m_url.m_userStart = m_asciiBuffer.size() - 1;
</del><ins>+        m_url.m_userStart = currentPosition(c) - 1;
</ins><span class="cx">         m_url.m_userEnd = m_url.m_userStart;
</span><span class="cx">         m_url.m_passwordEnd = m_url.m_userStart;
</span><span class="cx">         m_url.m_hostEnd = m_url.m_userStart;
</span><span class="lines">@@ -1587,7 +1612,7 @@
</span><span class="cx">     case State::FileSlash:
</span><span class="cx">         LOG_FINAL_STATE(&quot;FileSlash&quot;);
</span><span class="cx">         appendToASCIIBuffer(&quot;//&quot;, 2);
</span><del>-        m_url.m_userStart = m_asciiBuffer.size() - 1;
</del><ins>+        m_url.m_userStart = currentPosition(c) - 1;
</ins><span class="cx">         m_url.m_userEnd = m_url.m_userStart;
</span><span class="cx">         m_url.m_passwordEnd = m_url.m_userStart;
</span><span class="cx">         m_url.m_hostEnd = m_url.m_userStart;
</span><span class="lines">@@ -1601,7 +1626,7 @@
</span><span class="cx">         LOG_FINAL_STATE(&quot;FileHost&quot;);
</span><span class="cx">         if (authorityOrHostBegin == c) {
</span><span class="cx">             appendToASCIIBuffer('/');
</span><del>-            m_url.m_userStart = m_asciiBuffer.size() - 1;
</del><ins>+            m_url.m_userStart = currentPosition(c) - 1;
</ins><span class="cx">             m_url.m_userEnd = m_url.m_userStart;
</span><span class="cx">             m_url.m_passwordEnd = m_url.m_userStart;
</span><span class="cx">             m_url.m_hostEnd = m_url.m_userStart;
</span><span class="lines">@@ -1618,9 +1643,9 @@
</span><span class="cx">             return;
</span><span class="cx">         }
</span><span class="cx"> 
</span><del>-        if (StringView(m_asciiBuffer.data() + m_url.m_passwordEnd, m_asciiBuffer.size() - m_url.m_passwordEnd) == &quot;localhost&quot;)  {
</del><ins>+        if (StringView(m_asciiBuffer.data() + m_url.m_passwordEnd, currentPosition(c) - m_url.m_passwordEnd) == &quot;localhost&quot;)  {
</ins><span class="cx">             m_asciiBuffer.shrink(m_url.m_passwordEnd);
</span><del>-            m_url.m_hostEnd = m_asciiBuffer.size();
</del><ins>+            m_url.m_hostEnd = currentPosition(c);
</ins><span class="cx">             m_url.m_portEnd = m_url.m_hostEnd;
</span><span class="cx">         }
</span><span class="cx">         appendToASCIIBuffer('/');
</span><span class="lines">@@ -1634,13 +1659,13 @@
</span><span class="cx">         RELEASE_ASSERT_NOT_REACHED();
</span><span class="cx">     case State::Path:
</span><span class="cx">         LOG_FINAL_STATE(&quot;Path&quot;);
</span><del>-        m_url.m_pathEnd = m_asciiBuffer.size();
</del><ins>+        m_url.m_pathEnd = currentPosition(c);
</ins><span class="cx">         m_url.m_queryEnd = m_url.m_pathEnd;
</span><span class="cx">         m_url.m_fragmentEnd = m_url.m_pathEnd;
</span><span class="cx">         break;
</span><span class="cx">     case State::CannotBeABaseURLPath:
</span><span class="cx">         LOG_FINAL_STATE(&quot;CannotBeABaseURLPath&quot;);
</span><del>-        m_url.m_pathEnd = m_asciiBuffer.size();
</del><ins>+        m_url.m_pathEnd = currentPosition(c);
</ins><span class="cx">         m_url.m_queryEnd = m_url.m_pathEnd;
</span><span class="cx">         m_url.m_fragmentEnd = m_url.m_pathEnd;
</span><span class="cx">         break;
</span><span class="lines">@@ -1648,20 +1673,24 @@
</span><span class="cx">         LOG_FINAL_STATE(&quot;Query&quot;);
</span><span class="cx">         if (!isUTF8Encoding)
</span><span class="cx">             encodeQuery(queryBuffer, encoding);
</span><del>-        m_url.m_queryEnd = m_asciiBuffer.size();
</del><ins>+        m_url.m_queryEnd = currentPosition(c);
</ins><span class="cx">         m_url.m_fragmentEnd = m_url.m_queryEnd;
</span><span class="cx">         break;
</span><span class="cx">     case State::Fragment:
</span><span class="cx">         LOG_FINAL_STATE(&quot;Fragment&quot;);
</span><del>-        m_url.m_fragmentEnd = m_asciiBuffer.size() + m_unicodeFragmentBuffer.size();
</del><ins>+        m_url.m_fragmentEnd = currentPosition(c) + m_unicodeFragmentBuffer.size();
</ins><span class="cx">         break;
</span><span class="cx">     }
</span><span class="cx"> 
</span><del>-    if (m_unicodeFragmentBuffer.isEmpty())
</del><ins>+    if (!m_seenSyntaxError) {
+        m_url.m_string = m_inputString;
+        ASSERT(m_asciiBuffer.isEmpty());
+        ASSERT(m_unicodeFragmentBuffer.isEmpty());
+    } else if (m_unicodeFragmentBuffer.isEmpty())
</ins><span class="cx">         m_url.m_string = String::adopt(WTFMove(m_asciiBuffer));
</span><span class="cx">     else {
</span><span class="cx">         Vector&lt;UChar&gt; buffer;
</span><del>-        buffer.reserveInitialCapacity(m_asciiBuffer.size() + m_unicodeFragmentBuffer.size());
</del><ins>+        buffer.reserveInitialCapacity(currentPosition(c) + m_unicodeFragmentBuffer.size());
</ins><span class="cx">         buffer.appendVector(m_asciiBuffer);
</span><span class="cx">         buffer.appendVector(m_unicodeFragmentBuffer);
</span><span class="cx">         m_url.m_string = String::adopt(WTFMove(buffer));
</span><span class="lines">@@ -1675,7 +1704,7 @@
</span><span class="cx"> void URLParser::parseAuthority(CodePointIterator&lt;CharacterType&gt; iterator)
</span><span class="cx"> {
</span><span class="cx">     if (iterator.atEnd()) {
</span><del>-        m_url.m_userEnd = m_asciiBuffer.size();
</del><ins>+        m_url.m_userEnd = currentPosition(iterator);
</ins><span class="cx">         m_url.m_passwordEnd = m_url.m_userEnd;
</span><span class="cx">         return;
</span><span class="cx">     }
</span><span class="lines">@@ -1682,7 +1711,7 @@
</span><span class="cx">     for (; !iterator.atEnd(); ++iterator) {
</span><span class="cx">         if (*iterator == ':') {
</span><span class="cx">             ++iterator;
</span><del>-            m_url.m_userEnd = m_asciiBuffer.size();
</del><ins>+            m_url.m_userEnd = currentPosition(iterator);
</ins><span class="cx">             if (iterator.atEnd()) {
</span><span class="cx">                 m_url.m_passwordEnd = m_url.m_userEnd;
</span><span class="cx">                 if (m_url.m_userEnd &gt; m_url.m_userStart)
</span><span class="lines">@@ -1696,7 +1725,7 @@
</span><span class="cx">     }
</span><span class="cx">     for (; !iterator.atEnd(); ++iterator)
</span><span class="cx">         utf8PercentEncode&lt;isInUserInfoEncodeSet&gt;(*iterator);
</span><del>-    m_url.m_passwordEnd = m_asciiBuffer.size();
</del><ins>+    m_url.m_passwordEnd = currentPosition(iterator);
</ins><span class="cx">     if (!m_url.m_userEnd)
</span><span class="cx">         m_url.m_userEnd = m_url.m_passwordEnd;
</span><span class="cx">     appendToASCIIBuffer('@');
</span><span class="lines">@@ -1703,7 +1732,7 @@
</span><span class="cx"> }
</span><span class="cx"> 
</span><span class="cx"> template&lt;typename UnsignedIntegerType&gt;
</span><del>-void append(Vector&lt;LChar&gt;&amp; destination, UnsignedIntegerType number)
</del><ins>+void URLParser::appendNumberToASCIIBuffer(UnsignedIntegerType number)
</ins><span class="cx"> {
</span><span class="cx">     LChar buf[sizeof(UnsignedIntegerType) * 3 + 1];
</span><span class="cx">     LChar* end = buf + WTF_ARRAY_LENGTH(buf);
</span><span class="lines">@@ -1712,18 +1741,18 @@
</span><span class="cx">         *--p = (number % 10) + '0';
</span><span class="cx">         number /= 10;
</span><span class="cx">     } while (number);
</span><del>-    destination.append(p, end - p);
</del><ins>+    appendToASCIIBuffer(p, end - p);
</ins><span class="cx"> }
</span><span class="cx"> 
</span><del>-inline static void serializeIPv4(uint32_t address, Vector&lt;LChar&gt;&amp; buffer)
</del><ins>+void URLParser::serializeIPv4(IPv4Address address)
</ins><span class="cx"> {
</span><del>-    append&lt;uint8_t&gt;(buffer, address &gt;&gt; 24);
-    buffer.append('.');
-    append&lt;uint8_t&gt;(buffer, address &gt;&gt; 16);
-    buffer.append('.');
-    append&lt;uint8_t&gt;(buffer, address &gt;&gt; 8);
-    buffer.append('.');
-    append&lt;uint8_t&gt;(buffer, address);
</del><ins>+    appendNumberToASCIIBuffer&lt;uint8_t&gt;(address &gt;&gt; 24);
+    appendToASCIIBuffer('.');
+    appendNumberToASCIIBuffer&lt;uint8_t&gt;(address &gt;&gt; 16);
+    appendToASCIIBuffer('.');
+    appendNumberToASCIIBuffer&lt;uint8_t&gt;(address &gt;&gt; 8);
+    appendToASCIIBuffer('.');
+    appendNumberToASCIIBuffer&lt;uint8_t&gt;(address);
</ins><span class="cx"> }
</span><span class="cx">     
</span><span class="cx"> inline static size_t zeroSequenceLength(const std::array&lt;uint16_t, 8&gt;&amp; address, size_t begin)
</span><span class="lines">@@ -1752,46 +1781,46 @@
</span><span class="cx">     }
</span><span class="cx">     return longest;
</span><span class="cx"> }
</span><del>-    
-inline static void serializeIPv6Piece(uint16_t piece, Vector&lt;LChar&gt;&amp; buffer)
</del><ins>+
+void URLParser::serializeIPv6Piece(uint16_t piece)
</ins><span class="cx"> {
</span><span class="cx">     bool printed = false;
</span><span class="cx">     if (auto nibble0 = piece &gt;&gt; 12) {
</span><del>-        buffer.append(lowerNibbleToLowercaseASCIIHexDigit(nibble0));
</del><ins>+        appendToASCIIBuffer(lowerNibbleToLowercaseASCIIHexDigit(nibble0));
</ins><span class="cx">         printed = true;
</span><span class="cx">     }
</span><span class="cx">     auto nibble1 = piece &gt;&gt; 8 &amp; 0xF;
</span><span class="cx">     if (printed || nibble1) {
</span><del>-        buffer.append(lowerNibbleToLowercaseASCIIHexDigit(nibble1));
</del><ins>+        appendToASCIIBuffer(lowerNibbleToLowercaseASCIIHexDigit(nibble1));
</ins><span class="cx">         printed = true;
</span><span class="cx">     }
</span><span class="cx">     auto nibble2 = piece &gt;&gt; 4 &amp; 0xF;
</span><span class="cx">     if (printed || nibble2)
</span><del>-        buffer.append(lowerNibbleToLowercaseASCIIHexDigit(nibble2));
-    buffer.append(lowerNibbleToLowercaseASCIIHexDigit(piece &amp; 0xF));
</del><ins>+        appendToASCIIBuffer(lowerNibbleToLowercaseASCIIHexDigit(nibble2));
+    appendToASCIIBuffer(lowerNibbleToLowercaseASCIIHexDigit(piece &amp; 0xF));
</ins><span class="cx"> }
</span><span class="cx"> 
</span><del>-inline static void serializeIPv6(std::array&lt;uint16_t, 8&gt; address, Vector&lt;LChar&gt;&amp; buffer)
</del><ins>+void URLParser::serializeIPv6(URLParser::IPv6Address address)
</ins><span class="cx"> {
</span><del>-    buffer.append('[');
</del><ins>+    appendToASCIIBuffer('[');
</ins><span class="cx">     auto compressPointer = findLongestZeroSequence(address);
</span><span class="cx">     for (size_t piece = 0; piece &lt; 8; piece++) {
</span><span class="cx">         if (compressPointer &amp;&amp; compressPointer.value() == piece) {
</span><span class="cx">             ASSERT(!address[piece]);
</span><span class="cx">             if (piece)
</span><del>-                buffer.append(':');
</del><ins>+                appendToASCIIBuffer(':');
</ins><span class="cx">             else
</span><del>-                buffer.append(&quot;::&quot;, 2);
</del><ins>+                appendToASCIIBuffer(&quot;::&quot;, 2);
</ins><span class="cx">             while (piece &lt; 8 &amp;&amp; !address[piece])
</span><span class="cx">                 piece++;
</span><span class="cx">             if (piece == 8)
</span><span class="cx">                 break;
</span><span class="cx">         }
</span><del>-        serializeIPv6Piece(address[piece], buffer);
</del><ins>+        serializeIPv6Piece(address[piece]);
</ins><span class="cx">         if (piece &lt; 7)
</span><del>-            buffer.append(':');
</del><ins>+            appendToASCIIBuffer(':');
</ins><span class="cx">     }
</span><del>-    buffer.append(']');
</del><ins>+    appendToASCIIBuffer(']');
</ins><span class="cx"> }
</span><span class="cx"> 
</span><span class="cx"> template&lt;typename CharacterType&gt;
</span><span class="lines">@@ -1863,7 +1892,7 @@
</span><span class="cx"> }
</span><span class="cx"> 
</span><span class="cx"> template&lt;typename CharacterType&gt;
</span><del>-inline static Optional&lt;uint32_t&gt; parseIPv4Host(CodePointIterator&lt;CharacterType&gt; iterator)
</del><ins>+Optional&lt;URLParser::IPv4Address&gt; URLParser::parseIPv4Host(CodePointIterator&lt;CharacterType&gt; iterator)
</ins><span class="cx"> {
</span><span class="cx">     Vector&lt;uint32_t, 4&gt; items;
</span><span class="cx">     items.reserveInitialCapacity(4);
</span><span class="lines">@@ -1889,7 +1918,7 @@
</span><span class="cx">         if (item &gt; 255)
</span><span class="cx">             return Nullopt;
</span><span class="cx">     }
</span><del>-    uint32_t ipv4 = items.takeLast();
</del><ins>+    IPv4Address ipv4 = items.takeLast();
</ins><span class="cx">     for (size_t counter = 0; counter &lt; items.size(); ++counter)
</span><span class="cx">         ipv4 += items[counter] * pow256(3 - counter);
</span><span class="cx">     return ipv4;
</span><span class="lines">@@ -1896,12 +1925,12 @@
</span><span class="cx"> }
</span><span class="cx">     
</span><span class="cx"> template&lt;typename CharacterType&gt;
</span><del>-inline static Optional&lt;std::array&lt;uint16_t, 8&gt;&gt; parseIPv6Host(CodePointIterator&lt;CharacterType&gt; c)
</del><ins>+Optional&lt;URLParser::IPv6Address&gt; URLParser::parseIPv6Host(CodePointIterator&lt;CharacterType&gt; c)
</ins><span class="cx"> {
</span><span class="cx">     if (c.atEnd())
</span><span class="cx">         return Nullopt;
</span><span class="cx"> 
</span><del>-    std::array&lt;uint16_t, 8&gt; address = {{0, 0, 0, 0, 0, 0, 0, 0}};
</del><ins>+    IPv6Address address = {{0, 0, 0, 0, 0, 0, 0, 0}};
</ins><span class="cx">     size_t piecePointer = 0;
</span><span class="cx">     Optional&lt;size_t&gt; compressPointer;
</span><span class="cx"> 
</span><span class="lines">@@ -2078,7 +2107,7 @@
</span><span class="cx"> {
</span><span class="cx">     uint32_t port = 0;
</span><span class="cx">     if (iterator.atEnd()) {
</span><del>-        m_url.m_portEnd = m_asciiBuffer.size();
</del><ins>+        m_url.m_portEnd = currentPosition(iterator);
</ins><span class="cx">         return true;
</span><span class="cx">     }
</span><span class="cx">     appendToASCIIBuffer(':');
</span><span class="lines">@@ -2095,11 +2124,13 @@
</span><span class="cx"> 
</span><span class="cx">     if (isDefaultPort(StringView(m_asciiBuffer.data(), m_url.m_schemeEnd), port)) {
</span><span class="cx">         ASSERT(m_asciiBuffer.last() == ':');
</span><del>-        m_asciiBuffer.shrink(m_asciiBuffer.size() - 1);
-    } else
-        append&lt;uint16_t&gt;(m_asciiBuffer, static_cast&lt;uint16_t&gt;(port));
</del><ins>+        m_asciiBuffer.shrink(currentPosition(iterator) - 1);
+    } else {
+        ASSERT(port &lt;= std::numeric_limits&lt;uint16_t&gt;::max());
+        appendNumberToASCIIBuffer&lt;uint16_t&gt;(static_cast&lt;uint16_t&gt;(port));
+    }
</ins><span class="cx"> 
</span><del>-    m_url.m_portEnd = m_asciiBuffer.size();
</del><ins>+    m_url.m_portEnd = currentPosition(iterator);
</ins><span class="cx">     return true;
</span><span class="cx"> }
</span><span class="cx"> 
</span><span class="lines">@@ -2114,8 +2145,8 @@
</span><span class="cx">         while (!ipv6End.atEnd() &amp;&amp; *ipv6End != ']')
</span><span class="cx">             ++ipv6End;
</span><span class="cx">         if (auto address = parseIPv6Host(CodePointIterator&lt;CharacterType&gt;(iterator, ipv6End))) {
</span><del>-            serializeIPv6(address.value(), m_asciiBuffer);
-            m_url.m_hostEnd = m_asciiBuffer.size();
</del><ins>+            serializeIPv6(address.value());
+            m_url.m_hostEnd = currentPosition(iterator);
</ins><span class="cx">             if (!ipv6End.atEnd()) {
</span><span class="cx">                 ++ipv6End;
</span><span class="cx">                 if (!ipv6End.atEnd() &amp;&amp; *ipv6End == ':') {
</span><span class="lines">@@ -2122,7 +2153,7 @@
</span><span class="cx">                     ++ipv6End;
</span><span class="cx">                     return parsePort(ipv6End);
</span><span class="cx">                 }
</span><del>-                m_url.m_portEnd = m_asciiBuffer.size();
</del><ins>+                m_url.m_portEnd = currentPosition(iterator);
</ins><span class="cx">                 return true;
</span><span class="cx">             }
</span><span class="cx">             return true;
</span><span class="lines">@@ -2140,10 +2171,10 @@
</span><span class="cx">                 return false;
</span><span class="cx">         }
</span><span class="cx">         if (auto address = parseIPv4Host(CodePointIterator&lt;CharacterType&gt;(hostIterator, iterator))) {
</span><del>-            serializeIPv4(address.value(), m_asciiBuffer);
-            m_url.m_hostEnd = m_asciiBuffer.size();
</del><ins>+            serializeIPv4(address.value());
+            m_url.m_hostEnd = currentPosition(iterator);
</ins><span class="cx">             if (iterator.atEnd()) {
</span><del>-                m_url.m_portEnd = m_asciiBuffer.size();
</del><ins>+                m_url.m_portEnd = currentPosition(iterator);
</ins><span class="cx">                 return true;
</span><span class="cx">             }
</span><span class="cx">             ++iterator;
</span><span class="lines">@@ -2153,13 +2184,13 @@
</span><span class="cx">             if (!isTabOrNewline(*hostIterator))
</span><span class="cx">                 appendToASCIIBuffer(toASCIILower(*hostIterator));
</span><span class="cx">         }
</span><del>-        m_url.m_hostEnd = m_asciiBuffer.size();
</del><ins>+        m_url.m_hostEnd = currentPosition(iterator);
</ins><span class="cx">         if (!hostIterator.atEnd()) {
</span><span class="cx">             ASSERT(*hostIterator == ':');
</span><span class="cx">             incrementIteratorSkippingTabAndNewLine(hostIterator);
</span><span class="cx">             return parsePort(hostIterator);
</span><span class="cx">         }
</span><del>-        m_url.m_portEnd = m_asciiBuffer.size();
</del><ins>+        m_url.m_portEnd = currentPosition(iterator);
</ins><span class="cx">         return true;
</span><span class="cx">     }
</span><span class="cx">     
</span><span class="lines">@@ -2186,10 +2217,10 @@
</span><span class="cx">     const LChar* asciiDomainCharacters = asciiDomainValue.data();
</span><span class="cx"> 
</span><span class="cx">     if (auto address = parseIPv4Host(CodePointIterator&lt;LChar&gt;(asciiDomainValue.begin(), asciiDomainValue.end()))) {
</span><del>-        serializeIPv4(address.value(), m_asciiBuffer);
-        m_url.m_hostEnd = m_asciiBuffer.size();
</del><ins>+        serializeIPv4(address.value());
+        m_url.m_hostEnd = currentPosition(iterator);
</ins><span class="cx">         if (iterator.atEnd()) {
</span><del>-            m_url.m_portEnd = m_asciiBuffer.size();
</del><ins>+            m_url.m_portEnd = currentPosition(iterator);
</ins><span class="cx">             return true;
</span><span class="cx">         }
</span><span class="cx">         ++iterator;
</span><span class="lines">@@ -2197,13 +2228,13 @@
</span><span class="cx">     }
</span><span class="cx"> 
</span><span class="cx">     appendToASCIIBuffer(asciiDomainCharacters, asciiDomainValue.size());
</span><del>-    m_url.m_hostEnd = m_asciiBuffer.size();
</del><ins>+    m_url.m_hostEnd = currentPosition(iterator);
</ins><span class="cx">     if (!iterator.atEnd()) {
</span><span class="cx">         ASSERT(*iterator == ':');
</span><span class="cx">         incrementIteratorSkippingTabAndNewLine(iterator);
</span><span class="cx">         return parsePort(iterator);
</span><span class="cx">     }
</span><del>-    m_url.m_portEnd = m_asciiBuffer.size();
</del><ins>+    m_url.m_portEnd = currentPosition(iterator);
</ins><span class="cx">     return true;
</span><span class="cx"> }
</span><span class="cx"> 
</span></span></pre></div>
<a id="trunkSourceWebCoreplatformURLParserh"></a>
<div class="modfile"><h4>Modified: trunk/Source/WebCore/platform/URLParser.h (206336 => 206337)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/Source/WebCore/platform/URLParser.h        2016-09-23 23:26:01 UTC (rev 206336)
+++ trunk/Source/WebCore/platform/URLParser.h        2016-09-23 23:40:46 UTC (rev 206337)
</span><span class="lines">@@ -56,7 +56,11 @@
</span><span class="cx">     bool m_urlIsSpecial { false };
</span><span class="cx">     bool m_hostHasPercentOrNonASCII { false };
</span><span class="cx">     String m_inputString;
</span><ins>+    const void* m_inputBegin { nullptr };
</ins><span class="cx"> 
</span><ins>+    // FIXME: This should start out as false and only change to true when we see a syntax error once syntax error handling is implemented.
+    bool m_seenSyntaxError { true };
+
</ins><span class="cx">     template&lt;typename CharacterType&gt; void parse(const CharacterType*, const unsigned length, const URL&amp;, const TextEncoding&amp;);
</span><span class="cx">     template&lt;typename CharacterType&gt; void parseAuthority(CodePointIterator&lt;CharacterType&gt;);
</span><span class="cx">     template&lt;typename CharacterType&gt; bool parseHostAndPort(CodePointIterator&lt;CharacterType&gt;);
</span><span class="lines">@@ -68,6 +72,8 @@
</span><span class="cx">     template&lt;typename CharacterType&gt; bool isWindowsDriveLetter(CodePointIterator&lt;CharacterType&gt;);
</span><span class="cx">     template&lt;typename CharacterType&gt; bool shouldCopyFileURL(CodePointIterator&lt;CharacterType&gt;);
</span><span class="cx">     template&lt;typename CharacterType&gt; void checkWindowsDriveLetter(CodePointIterator&lt;CharacterType&gt;&amp;);
</span><ins>+    template&lt;typename CharacterType&gt; size_t currentPosition(const CodePointIterator&lt;CharacterType&gt;&amp;);
+    template&lt;typename UnsignedIntegerType&gt; void appendNumberToASCIIBuffer(UnsignedIntegerType);
</ins><span class="cx">     template&lt;bool(*isInCodeSet)(UChar32)&gt; void utf8PercentEncode(UChar32);
</span><span class="cx">     void utf8QueryEncode(UChar32);
</span><span class="cx">     void percentEncodeByte(uint8_t);
</span><span class="lines">@@ -77,6 +83,14 @@
</span><span class="cx">     void encodeQuery(const Vector&lt;UChar&gt;&amp; source, const TextEncoding&amp;);
</span><span class="cx">     void copyASCIIStringUntil(const String&amp;, size_t lengthIf8Bit, size_t lengthIf16Bit);
</span><span class="cx"> 
</span><ins>+    using IPv4Address = uint32_t;
+    void serializeIPv4(IPv4Address);
+    template&lt;typename CharacterType&gt; Optional&lt;IPv4Address&gt; parseIPv4Host(CodePointIterator&lt;CharacterType&gt;);
+    using IPv6Address = std::array&lt;uint16_t, 8&gt;;
+    template&lt;typename CharacterType&gt; Optional&lt;IPv6Address&gt; parseIPv6Host(CodePointIterator&lt;CharacterType&gt;);
+    void serializeIPv6Piece(uint16_t piece);
+    void serializeIPv6(URLParser::IPv6Address);
+
</ins><span class="cx">     enum class URLPart;
</span><span class="cx">     void copyURLPartsUntil(const URL&amp; base, URLPart);
</span><span class="cx">     static size_t urlLengthUntilPart(const URL&amp;, URLPart);
</span></span></pre>
</div>
</div>

</body>
</html>