<!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>[206329] 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/206329">206329</a></dd>
<dt>Author</dt> <dd>achristensen@apple.com</dd>
<dt>Date</dt> <dd>2016-09-23 13:58:03 -0700 (Fri, 23 Sep 2016)</dd>
</dl>

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

Reviewed by Brady Eidson.

Source/WebCore:

Make the constructor take the parameters instead of URL::parse.
Now we don't need to copy the input string on failure.
Also, turn some static functions into methods so they will be able to access member variables.

Covered by existing and new API tests.

* platform/URL.cpp:
(WebCore::URL::URL):
(WebCore::URL::setProtocol):
(WebCore::URL::setHost):
(WebCore::URL::removePort):
(WebCore::URL::setPort):
(WebCore::URL::setHostAndPort):
(WebCore::URL::setUser):
(WebCore::URL::setPass):
(WebCore::URL::setFragmentIdentifier):
(WebCore::URL::removeFragmentIdentifier):
(WebCore::URL::setQuery):
(WebCore::URL::setPath):
* platform/URLParser.cpp:
(WebCore::URLParser::incrementIteratorSkippingTabAndNewLine):
(WebCore::URLParser::isWindowsDriveLetter):
(WebCore::URLParser::checkWindowsDriveLetter):
(WebCore::URLParser::shouldCopyFileURL):
(WebCore::URLParser::failure):
(WebCore::URLParser::URLParser):
(WebCore::URLParser::parse):
(WebCore::incrementIteratorSkippingTabAndNewLine): Deleted.
(WebCore::isWindowsDriveLetter): Deleted.
(WebCore::checkWindowsDriveLetter): Deleted.
(WebCore::shouldCopyFileURL): Deleted.
* platform/URLParser.h:
(WebCore::URLParser::URLParser):
(WebCore::URLParser::result):
(WebCore::URLParser::parse): Deleted.
* platform/cf/URLCF.cpp:
(WebCore::URL::URL):
Drive-by fix: Actually assign the URL to be the result of parsing.
* platform/mac/URLMac.mm:
(WebCore::URL::URL):

Tools:

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

<h3>Modified Paths</h3>
<ul>
<li><a href="#trunkSourceWebCoreChangeLog">trunk/Source/WebCore/ChangeLog</a></li>
<li><a href="#trunkSourceWebCoreplatformURLcpp">trunk/Source/WebCore/platform/URL.cpp</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>
<li><a href="#trunkSourceWebCoreplatformcfURLCFcpp">trunk/Source/WebCore/platform/cf/URLCF.cpp</a></li>
<li><a href="#trunkSourceWebCoreplatformmacURLMacmm">trunk/Source/WebCore/platform/mac/URLMac.mm</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="trunkSourceWebCoreChangeLog"></a>
<div class="modfile"><h4>Modified: trunk/Source/WebCore/ChangeLog (206328 => 206329)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/Source/WebCore/ChangeLog        2016-09-23 20:33:53 UTC (rev 206328)
+++ trunk/Source/WebCore/ChangeLog        2016-09-23 20:58:03 UTC (rev 206329)
</span><span class="lines">@@ -1,5 +1,53 @@
</span><span class="cx"> 2016-09-23  Alex Christensen  &lt;achristensen@webkit.org&gt;
</span><span class="cx"> 
</span><ins>+        Refactor URLParser
+        https://bugs.webkit.org/show_bug.cgi?id=162511
+
+        Reviewed by Brady Eidson.
+
+        Make the constructor take the parameters instead of URL::parse.
+        Now we don't need to copy the input string on failure.
+        Also, turn some static functions into methods so they will be able to access member variables.
+
+        Covered by existing and new API tests.
+
+        * platform/URL.cpp:
+        (WebCore::URL::URL):
+        (WebCore::URL::setProtocol):
+        (WebCore::URL::setHost):
+        (WebCore::URL::removePort):
+        (WebCore::URL::setPort):
+        (WebCore::URL::setHostAndPort):
+        (WebCore::URL::setUser):
+        (WebCore::URL::setPass):
+        (WebCore::URL::setFragmentIdentifier):
+        (WebCore::URL::removeFragmentIdentifier):
+        (WebCore::URL::setQuery):
+        (WebCore::URL::setPath):
+        * platform/URLParser.cpp:
+        (WebCore::URLParser::incrementIteratorSkippingTabAndNewLine):
+        (WebCore::URLParser::isWindowsDriveLetter):
+        (WebCore::URLParser::checkWindowsDriveLetter):
+        (WebCore::URLParser::shouldCopyFileURL):
+        (WebCore::URLParser::failure):
+        (WebCore::URLParser::URLParser):
+        (WebCore::URLParser::parse):
+        (WebCore::incrementIteratorSkippingTabAndNewLine): Deleted.
+        (WebCore::isWindowsDriveLetter): Deleted.
+        (WebCore::checkWindowsDriveLetter): Deleted.
+        (WebCore::shouldCopyFileURL): Deleted.
+        * platform/URLParser.h:
+        (WebCore::URLParser::URLParser):
+        (WebCore::URLParser::result):
+        (WebCore::URLParser::parse): Deleted.
+        * platform/cf/URLCF.cpp:
+        (WebCore::URL::URL):
+        Drive-by fix: Actually assign the URL to be the result of parsing.
+        * platform/mac/URLMac.mm:
+        (WebCore::URL::URL):
+
+2016-09-23  Alex Christensen  &lt;achristensen@webkit.org&gt;
+
</ins><span class="cx">         Remove URLParser serialized template
</span><span class="cx">         https://bugs.webkit.org/show_bug.cgi?id=162501
</span><span class="cx"> 
</span></span></pre></div>
<a id="trunkSourceWebCoreplatformURLcpp"></a>
<div class="modfile"><h4>Modified: trunk/Source/WebCore/platform/URL.cpp (206328 => 206329)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/Source/WebCore/platform/URL.cpp        2016-09-23 20:33:53 UTC (rev 206328)
+++ trunk/Source/WebCore/platform/URL.cpp        2016-09-23 20:58:03 UTC (rev 206329)
</span><span class="lines">@@ -441,8 +441,8 @@
</span><span class="cx"> URL::URL(ParsedURLStringTag, const String&amp; url)
</span><span class="cx"> {
</span><span class="cx">     if (URLParser::enabled()) {
</span><del>-        URLParser parser;
-        *this = parser.parse(url);
</del><ins>+        URLParser parser(url);
+        *this = parser.result();
</ins><span class="cx">     } else
</span><span class="cx">         parse(url);
</span><span class="cx"> #if OS(WINDOWS)
</span><span class="lines">@@ -456,8 +456,8 @@
</span><span class="cx"> URL::URL(const URL&amp; base, const String&amp; relative)
</span><span class="cx"> {
</span><span class="cx">     if (URLParser::enabled()) {
</span><del>-        URLParser parser;
-        *this = parser.parse(relative, base);
</del><ins>+        URLParser parser(relative, base);
+        *this = parser.result();
</ins><span class="cx">     } else
</span><span class="cx">         init(base, relative, UTF8Encoding());
</span><span class="cx"> }
</span><span class="lines">@@ -465,8 +465,8 @@
</span><span class="cx"> URL::URL(const URL&amp; base, const String&amp; relative, const TextEncoding&amp; encoding)
</span><span class="cx"> {
</span><span class="cx">     if (URLParser::enabled()) {
</span><del>-        URLParser parser;
-        *this = parser.parse(relative, base, encoding);
</del><ins>+        URLParser parser(relative, base, encoding);
+        *this = parser.result();
</ins><span class="cx">     } else {
</span><span class="cx">         // For UTF-{7,16,32}, we want to use UTF-8 for the query part as
</span><span class="cx">         // we do when submitting a form. A form with GET method
</span><span class="lines">@@ -865,8 +865,8 @@
</span><span class="cx"> 
</span><span class="cx">     if (!m_isValid) {
</span><span class="cx">         if (URLParser::enabled()) {
</span><del>-            URLParser parser;
-            *this = parser.parse(makeString(newProtocol, &quot;:&quot;, m_string));
</del><ins>+            URLParser parser(makeString(newProtocol, &quot;:&quot;, m_string));
+            *this = parser.result();
</ins><span class="cx">         } else
</span><span class="cx">             parse(newProtocol + ':' + m_string);
</span><span class="cx">         return true;
</span><span class="lines">@@ -873,8 +873,8 @@
</span><span class="cx">     }
</span><span class="cx"> 
</span><span class="cx">     if (URLParser::enabled()) {
</span><del>-        URLParser parser;
-        *this = parser.parse(makeString(newProtocol, m_string.substring(m_schemeEnd)));
</del><ins>+        URLParser parser(makeString(newProtocol, m_string.substring(m_schemeEnd)));
+        *this = parser.result();
</ins><span class="cx">     } else
</span><span class="cx">         parse(newProtocol + m_string.substring(m_schemeEnd));
</span><span class="cx"> 
</span><span class="lines">@@ -945,8 +945,8 @@
</span><span class="cx">     builder.append(m_string.substring(m_hostEnd));
</span><span class="cx">     
</span><span class="cx">     if (URLParser::enabled()) {
</span><del>-        URLParser parser;
-        *this = parser.parse(builder.toString());
</del><ins>+        URLParser parser(builder.toString());
+        *this = parser.result();
</ins><span class="cx">     } else
</span><span class="cx">         parse(builder.toString());
</span><span class="cx"> }
</span><span class="lines">@@ -956,8 +956,8 @@
</span><span class="cx">     if (m_hostEnd == m_portEnd)
</span><span class="cx">         return;
</span><span class="cx">     if (URLParser::enabled()) {
</span><del>-        URLParser parser;
-        *this = parser.parse(m_string.left(m_hostEnd) + m_string.substring(m_portEnd));
</del><ins>+        URLParser parser(m_string.left(m_hostEnd) + m_string.substring(m_portEnd));
+        *this = parser.result();
</ins><span class="cx">     } else
</span><span class="cx">         parse(m_string.left(m_hostEnd) + m_string.substring(m_portEnd));
</span><span class="cx"> }
</span><span class="lines">@@ -971,8 +971,8 @@
</span><span class="cx">     unsigned portStart = (colonNeeded ? m_hostEnd : m_hostEnd + 1);
</span><span class="cx"> 
</span><span class="cx">     if (URLParser::enabled()) {
</span><del>-        URLParser parser;
-        *this = parser.parse(makeString(m_string.left(portStart), (colonNeeded ? &quot;:&quot; : &quot;&quot;), String::number(i), m_string.substring(m_portEnd)));
</del><ins>+        URLParser parser(makeString(m_string.left(portStart), (colonNeeded ? &quot;:&quot; : &quot;&quot;), String::number(i), m_string.substring(m_portEnd)));
+        *this = parser.result();
</ins><span class="cx">     } else
</span><span class="cx">         parse(m_string.left(portStart) + (colonNeeded ? &quot;:&quot; : &quot;&quot;) + String::number(i) + m_string.substring(m_portEnd));
</span><span class="cx"> }
</span><span class="lines">@@ -1016,8 +1016,8 @@
</span><span class="cx">     builder.append(m_string.substring(m_portEnd));
</span><span class="cx"> 
</span><span class="cx">     if (URLParser::enabled()) {
</span><del>-        URLParser parser;
-        *this = parser.parse(builder.toString());
</del><ins>+        URLParser parser(builder.toString());
+        *this = parser.result();
</ins><span class="cx">     } else
</span><span class="cx">         parse(builder.toString());
</span><span class="cx"> }
</span><span class="lines">@@ -1039,8 +1039,8 @@
</span><span class="cx">         if (end == m_hostEnd || (end == m_passwordEnd &amp;&amp; m_string[end] != '@'))
</span><span class="cx">             u.append('@');
</span><span class="cx">         if (URLParser::enabled()) {
</span><del>-            URLParser parser;
-            *this = parser.parse(makeString(m_string.left(m_userStart), u, m_string.substring(end)));
</del><ins>+            URLParser parser(makeString(m_string.left(m_userStart), u, m_string.substring(end)));
+            *this = parser.result();
</ins><span class="cx">         } else
</span><span class="cx">             parse(m_string.left(m_userStart) + u + m_string.substring(end));
</span><span class="cx">     } else {
</span><span class="lines">@@ -1050,8 +1050,8 @@
</span><span class="cx">         // We don't want to parse in the extremely common case where we are not going to make a change.
</span><span class="cx">         if (m_userStart != end) {
</span><span class="cx">             if (URLParser::enabled()) {
</span><del>-                URLParser parser;
-                *this = parser.parse(makeString(m_string.left(m_userStart), m_string.substring(end)));
</del><ins>+                URLParser parser(makeString(m_string.left(m_userStart), m_string.substring(end)));
+                *this = parser.result();
</ins><span class="cx">             } else
</span><span class="cx">                 parse(m_string.left(m_userStart) + m_string.substring(end));
</span><span class="cx">         }
</span><span class="lines">@@ -1072,8 +1072,8 @@
</span><span class="cx">         if (end != m_hostEnd &amp;&amp; m_string[end] == '@')
</span><span class="cx">             end += 1;
</span><span class="cx">         if (URLParser::enabled()) {
</span><del>-            URLParser parser;
-            *this = parser.parse(makeString(m_string.left(m_userEnd), p, m_string.substring(end)));
</del><ins>+            URLParser parser(makeString(m_string.left(m_userEnd), p, m_string.substring(end)));
+            *this = parser.result();
</ins><span class="cx">         } else
</span><span class="cx">             parse(m_string.left(m_userEnd) + p + m_string.substring(end));
</span><span class="cx">     } else {
</span><span class="lines">@@ -1083,8 +1083,8 @@
</span><span class="cx">         // We don't want to parse in the extremely common case where we are not going to make a change.
</span><span class="cx">         if (m_userEnd != end) {
</span><span class="cx">             if (URLParser::enabled()) {
</span><del>-                URLParser parser;
-                *this = parser.parse(makeString(m_string.left(m_userEnd), m_string.substring(end)));
</del><ins>+                URLParser parser(makeString(m_string.left(m_userEnd), m_string.substring(end)));
+                *this = parser.result();
</ins><span class="cx">             } else
</span><span class="cx">                 parse(m_string.left(m_userEnd) + m_string.substring(end));
</span><span class="cx">         }
</span><span class="lines">@@ -1098,8 +1098,8 @@
</span><span class="cx"> 
</span><span class="cx">     // FIXME: Non-ASCII characters must be encoded and escaped to match parse() expectations.
</span><span class="cx">     if (URLParser::enabled()) {
</span><del>-        URLParser parser;
-        *this = parser.parse(makeString(m_string.left(m_queryEnd), &quot;#&quot;, s));
</del><ins>+        URLParser parser(makeString(m_string.left(m_queryEnd), &quot;#&quot;, s));
+        *this = parser.result();
</ins><span class="cx">     } else
</span><span class="cx">         parse(m_string.left(m_queryEnd) + &quot;#&quot; + s);
</span><span class="cx"> }
</span><span class="lines">@@ -1110,8 +1110,8 @@
</span><span class="cx">         return;
</span><span class="cx">     if (URLParser::enabled()) {
</span><span class="cx">         // FIXME: We shouldn't need to parse here.
</span><del>-        URLParser parser;
-        *this = parser.parse(m_string.left(m_queryEnd));
</del><ins>+        URLParser parser(m_string.left(m_queryEnd));
+        *this = parser.result();
</ins><span class="cx">     } else
</span><span class="cx">         parse(m_string.left(m_queryEnd));
</span><span class="cx"> }
</span><span class="lines">@@ -1127,14 +1127,14 @@
</span><span class="cx">     // https://webkit.org/b/161176
</span><span class="cx">     if ((query.isEmpty() || query[0] != '?') &amp;&amp; !query.isNull()) {
</span><span class="cx">         if (URLParser::enabled()) {
</span><del>-            URLParser parser;
-            *this = parser.parse(makeString(m_string.left(m_pathEnd), &quot;?&quot;, query, m_string.substring(m_queryEnd)));
</del><ins>+            URLParser parser(makeString(m_string.left(m_pathEnd), &quot;?&quot;, query, m_string.substring(m_queryEnd)));
+            *this = parser.result();
</ins><span class="cx">         } else
</span><span class="cx">             parse(m_string.left(m_pathEnd) + &quot;?&quot; + query + m_string.substring(m_queryEnd));
</span><span class="cx">     } else {
</span><span class="cx">         if (URLParser::enabled()) {
</span><del>-            URLParser parser;
-            *this = parser.parse(makeString(m_string.left(m_pathEnd), query, m_string.substring(m_queryEnd)));
</del><ins>+            URLParser parser(makeString(m_string.left(m_pathEnd), query, m_string.substring(m_queryEnd)));
+            *this = parser.result();
</ins><span class="cx">         } else
</span><span class="cx">             parse(m_string.left(m_pathEnd) + query + m_string.substring(m_queryEnd));
</span><span class="cx">     }
</span><span class="lines">@@ -1153,8 +1153,8 @@
</span><span class="cx">         path = &quot;/&quot; + path;
</span><span class="cx"> 
</span><span class="cx">     if (URLParser::enabled()) {
</span><del>-        URLParser parser;
-        *this = parser.parse(makeString(m_string.left(m_portEnd), encodeWithURLEscapeSequences(path), m_string.substring(m_pathEnd)));
</del><ins>+        URLParser parser(makeString(m_string.left(m_portEnd), encodeWithURLEscapeSequences(path), m_string.substring(m_pathEnd)));
+        *this = parser.result();
</ins><span class="cx">     } else
</span><span class="cx">         parse(m_string.left(m_portEnd) + encodeWithURLEscapeSequences(path) + m_string.substring(m_pathEnd));
</span><span class="cx"> }
</span></span></pre></div>
<a id="trunkSourceWebCoreplatformURLParsercpp"></a>
<div class="modfile"><h4>Modified: trunk/Source/WebCore/platform/URLParser.cpp (206328 => 206329)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/Source/WebCore/platform/URLParser.cpp        2016-09-23 20:33:53 UTC (rev 206328)
+++ trunk/Source/WebCore/platform/URLParser.cpp        2016-09-23 20:58:03 UTC (rev 206329)
</span><span class="lines">@@ -404,7 +404,7 @@
</span><span class="cx"> static bool shouldPercentEncodeQueryByte(uint8_t byte) { return characterClassTable[byte] &amp; QueryPercent; }
</span><span class="cx"> 
</span><span class="cx"> template&lt;typename CharacterType&gt;
</span><del>-void incrementIteratorSkippingTabAndNewLine(CodePointIterator&lt;CharacterType&gt;&amp; iterator)
</del><ins>+void URLParser::incrementIteratorSkippingTabAndNewLine(CodePointIterator&lt;CharacterType&gt;&amp; iterator)
</ins><span class="cx"> {
</span><span class="cx">     ++iterator;
</span><span class="cx">     while (!iterator.atEnd() &amp;&amp; isTabOrNewline(*iterator))
</span><span class="lines">@@ -412,7 +412,7 @@
</span><span class="cx"> }
</span><span class="cx"> 
</span><span class="cx"> template&lt;typename CharacterType&gt;
</span><del>-inline static bool isWindowsDriveLetter(CodePointIterator&lt;CharacterType&gt; iterator)
</del><ins>+bool URLParser::isWindowsDriveLetter(CodePointIterator&lt;CharacterType&gt; iterator)
</ins><span class="cx"> {
</span><span class="cx">     if (iterator.atEnd() || !isASCIIAlpha(*iterator))
</span><span class="cx">         return false;
</span><span class="lines">@@ -430,7 +430,7 @@
</span><span class="cx"> }
</span><span class="cx"> 
</span><span class="cx"> template&lt;typename CharacterType&gt;
</span><del>-inline static void checkWindowsDriveLetter(CodePointIterator&lt;CharacterType&gt;&amp; iterator, Vector&lt;LChar&gt;&amp; asciiBuffer)
</del><ins>+void URLParser::checkWindowsDriveLetter(CodePointIterator&lt;CharacterType&gt;&amp; iterator, Vector&lt;LChar&gt;&amp; asciiBuffer)
</ins><span class="cx"> {
</span><span class="cx">     if (isWindowsDriveLetter(iterator)) {
</span><span class="cx">         asciiBuffer.reserveCapacity(asciiBuffer.size() + 2);
</span><span class="lines">@@ -444,7 +444,7 @@
</span><span class="cx"> }
</span><span class="cx"> 
</span><span class="cx"> template&lt;typename CharacterType&gt;
</span><del>-inline static bool shouldCopyFileURL(CodePointIterator&lt;CharacterType&gt; iterator)
</del><ins>+bool URLParser::shouldCopyFileURL(CodePointIterator&lt;CharacterType&gt; iterator)
</ins><span class="cx"> {
</span><span class="cx">     if (!isWindowsDriveLetter(iterator))
</span><span class="cx">         return true;
</span><span class="lines">@@ -896,36 +896,25 @@
</span><span class="cx">     m_asciiBuffer.resize(m_url.m_pathAfterLastSlash);
</span><span class="cx"> }
</span><span class="cx"> 
</span><del>-template&lt;typename CharacterType&gt;
-URL URLParser::failure(const CharacterType* input, unsigned length)
</del><ins>+void URLParser::failure()
</ins><span class="cx"> {
</span><del>-    URL url;
-    url.m_isValid = false;
-    url.m_protocolIsInHTTPFamily = false;
-    url.m_cannotBeABaseURL = false;
-    url.m_schemeEnd = 0;
-    url.m_userStart = 0;
-    url.m_userEnd = 0;
-    url.m_passwordEnd = 0;
-    url.m_hostEnd = 0;
-    url.m_portEnd = 0;
-    url.m_pathAfterLastSlash = 0;
-    url.m_pathEnd = 0;
-    url.m_queryEnd = 0;
-    url.m_fragmentEnd = 0;
-    url.m_string = String(input, length);
-    return url;
</del><ins>+    m_url.invalidate();
+    m_url.m_string = m_inputString;
</ins><span class="cx"> }
</span><span class="cx"> 
</span><del>-URL URLParser::parse(const String&amp; input, const URL&amp; base, const TextEncoding&amp; encoding)
</del><ins>+URLParser::URLParser(const String&amp; input, const URL&amp; base, const TextEncoding&amp; encoding)
+    : m_inputString(input)
</ins><span class="cx"> {
</span><ins>+    if (input.isNull())
+        return;
</ins><span class="cx">     if (input.is8Bit())
</span><del>-        return parse(input.characters8(), input.length(), base, encoding);
-    return parse(input.characters16(), input.length(), base, encoding);
</del><ins>+        parse(input.characters8(), input.length(), base, encoding);
+    else
+        parse(input.characters16(), input.length(), base, encoding);
</ins><span class="cx"> }
</span><span class="cx"> 
</span><span class="cx"> template&lt;typename CharacterType&gt;
</span><del>-URL URLParser::parse(const CharacterType* input, const unsigned length, const URL&amp; base, const TextEncoding&amp; encoding)
</del><ins>+void URLParser::parse(const CharacterType* input, const unsigned length, const URL&amp; base, const TextEncoding&amp; encoding)
</ins><span class="cx"> {
</span><span class="cx">     LOG(URLParser, &quot;Parsing URL &lt;%s&gt; base &lt;%s&gt;&quot;, String(input, length).utf8().data(), base.string().utf8().data());
</span><span class="cx">     m_url = { };
</span><span class="lines">@@ -1051,8 +1040,10 @@
</span><span class="cx">             break;
</span><span class="cx">         case State::NoScheme:
</span><span class="cx">             LOG_STATE(&quot;NoScheme&quot;);
</span><del>-            if (!base.isValid() || (base.m_cannotBeABaseURL &amp;&amp; *c != '#'))
-                return failure(input, length);
</del><ins>+            if (!base.isValid() || (base.m_cannotBeABaseURL &amp;&amp; *c != '#')) {
+                failure();
+                return;
+            }
</ins><span class="cx">             if (base.m_cannotBeABaseURL &amp;&amp; *c == '#') {
</span><span class="cx">                 copyURLPartsUntil(base, URLPart::QueryEnd);
</span><span class="cx">                 state = State::Fragment;
</span><span class="lines">@@ -1073,8 +1064,10 @@
</span><span class="cx">             if (*c == '/') {
</span><span class="cx">                 m_asciiBuffer.append('/');
</span><span class="cx">                 incrementIteratorSkippingTabAndNewLine(c);
</span><del>-                if (c.atEnd())
-                    return failure(input, length);
</del><ins>+                if (c.atEnd()) {
+                    failure();
+                    return;
+                }
</ins><span class="cx">                 if (*c == '/') {
</span><span class="cx">                     m_asciiBuffer.append('/');
</span><span class="cx">                     state = State::SpecialAuthorityIgnoreSlashes;
</span><span class="lines">@@ -1186,8 +1179,10 @@
</span><span class="cx">                 if (isSlash || *c == '?' || *c == '#') {
</span><span class="cx">                     m_url.m_userEnd = m_asciiBuffer.size();
</span><span class="cx">                     m_url.m_passwordEnd = m_url.m_userEnd;
</span><del>-                    if (!parseHostAndPort(CodePointIterator&lt;CharacterType&gt;(authorityOrHostBegin, c)))
-                        return failure(input, length);
</del><ins>+                    if (!parseHostAndPort(CodePointIterator&lt;CharacterType&gt;(authorityOrHostBegin, c))) {
+                        failure();
+                        return;
+                    }
</ins><span class="cx">                     if (!isSlash) {
</span><span class="cx">                         m_asciiBuffer.append('/');
</span><span class="cx">                         m_url.m_pathAfterLastSlash = m_asciiBuffer.size();
</span><span class="lines">@@ -1203,8 +1198,10 @@
</span><span class="cx">         case State::Host:
</span><span class="cx">             LOG_STATE(&quot;Host&quot;);
</span><span class="cx">             if (*c == '/' || *c == '?' || *c == '#') {
</span><del>-                if (!parseHostAndPort(CodePointIterator&lt;CharacterType&gt;(authorityOrHostBegin, c)))
-                    return failure(input, length);
</del><ins>+                if (!parseHostAndPort(CodePointIterator&lt;CharacterType&gt;(authorityOrHostBegin, c))) {
+                    failure();
+                    return;
+                }
</ins><span class="cx">                 state = State::Path;
</span><span class="cx">                 break;
</span><span class="cx">             }
</span><span class="lines">@@ -1307,7 +1304,7 @@
</span><span class="cx">         case State::FileHost:
</span><span class="cx">             LOG_STATE(&quot;FileHost&quot;);
</span><span class="cx">             if (isSlashQuestionOrHash(*c)) {
</span><del>-                if (isWindowsDriveLetter(m_asciiBuffer, m_url.m_portEnd + 1)) {
</del><ins>+                if (WebCore::isWindowsDriveLetter(m_asciiBuffer, m_url.m_portEnd + 1)) {
</ins><span class="cx">                     state = State::Path;
</span><span class="cx">                     break;
</span><span class="cx">                 }
</span><span class="lines">@@ -1333,8 +1330,10 @@
</span><span class="cx">                     state = State::Path;
</span><span class="cx">                     break;
</span><span class="cx">                 }
</span><del>-                if (!parseHostAndPort(CodePointIterator&lt;CharacterType&gt;(authorityOrHostBegin, c)))
-                    return failure(input, length);
</del><ins>+                if (!parseHostAndPort(CodePointIterator&lt;CharacterType&gt;(authorityOrHostBegin, c))) {
+                    failure();
+                    return;
+                }
</ins><span class="cx">                 
</span><span class="cx">                 if (StringView(m_asciiBuffer.data() + m_url.m_passwordEnd, m_asciiBuffer.size() - m_url.m_passwordEnd) == &quot;localhost&quot;)  {
</span><span class="cx">                     m_asciiBuffer.shrink(m_url.m_passwordEnd);
</span><span class="lines">@@ -1445,12 +1444,16 @@
</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())
-            return base;
-        return failure(input, length);
</del><ins>+        if (!m_asciiBuffer.size() &amp;&amp; base.isValid()) {
+            m_url = base;
+            return;
+        }
+        failure();
+        return;
</ins><span class="cx">     case State::Scheme:
</span><span class="cx">         LOG_FINAL_STATE(&quot;Scheme&quot;);
</span><del>-        return failure(input, length);
</del><ins>+        failure();
+        return;
</ins><span class="cx">     case State::NoScheme:
</span><span class="cx">         LOG_FINAL_STATE(&quot;NoScheme&quot;);
</span><span class="cx">         RELEASE_ASSERT_NOT_REACHED();
</span><span class="lines">@@ -1501,7 +1504,8 @@
</span><span class="cx">         break;
</span><span class="cx">     case State::SpecialAuthorityIgnoreSlashes:
</span><span class="cx">         LOG_FINAL_STATE(&quot;SpecialAuthorityIgnoreSlashes&quot;);
</span><del>-        return failure(input, length);
</del><ins>+        failure();
+        return;
</ins><span class="cx">         break;
</span><span class="cx">     case State::AuthorityOrHost:
</span><span class="cx">         LOG_FINAL_STATE(&quot;AuthorityOrHost&quot;);
</span><span class="lines">@@ -1510,8 +1514,10 @@
</span><span class="cx">         if (authorityOrHostBegin.atEnd()) {
</span><span class="cx">             m_url.m_hostEnd = m_url.m_userEnd;
</span><span class="cx">             m_url.m_portEnd = m_url.m_userEnd;
</span><del>-        } else if (!parseHostAndPort(authorityOrHostBegin))
-            return failure(input, length);
</del><ins>+        } else if (!parseHostAndPort(authorityOrHostBegin)) {
+            failure();
+            return;
+        }
</ins><span class="cx">         m_asciiBuffer.append('/');
</span><span class="cx">         m_url.m_pathEnd = m_url.m_portEnd + 1;
</span><span class="cx">         m_url.m_pathAfterLastSlash = m_url.m_pathEnd;
</span><span class="lines">@@ -1520,8 +1526,10 @@
</span><span class="cx">         break;
</span><span class="cx">     case State::Host:
</span><span class="cx">         LOG_FINAL_STATE(&quot;Host&quot;);
</span><del>-        if (!parseHostAndPort(authorityOrHostBegin))
-            return failure(input, length);
</del><ins>+        if (!parseHostAndPort(authorityOrHostBegin)) {
+            failure();
+            return;
+        }
</ins><span class="cx">         m_asciiBuffer.append('/');
</span><span class="cx">         m_url.m_pathEnd = m_url.m_portEnd + 1;
</span><span class="cx">         m_url.m_pathAfterLastSlash = m_url.m_pathEnd;
</span><span class="lines">@@ -1574,8 +1582,10 @@
</span><span class="cx">             break;
</span><span class="cx">         }
</span><span class="cx"> 
</span><del>-        if (!parseHostAndPort(CodePointIterator&lt;CharacterType&gt;(authorityOrHostBegin, c)))
-            return failure(input, length);
</del><ins>+        if (!parseHostAndPort(CodePointIterator&lt;CharacterType&gt;(authorityOrHostBegin, c))) {
+            failure();
+            return;
+        }
</ins><span class="cx"> 
</span><span class="cx">         if (StringView(m_asciiBuffer.data() + m_url.m_passwordEnd, m_asciiBuffer.size() - m_url.m_passwordEnd) == &quot;localhost&quot;)  {
</span><span class="cx">             m_asciiBuffer.shrink(m_url.m_passwordEnd);
</span><span class="lines">@@ -1628,7 +1638,6 @@
</span><span class="cx">     m_url.m_isValid = true;
</span><span class="cx">     LOG(URLParser, &quot;Parsed URL &lt;%s&gt;&quot;, m_url.m_string.utf8().data());
</span><span class="cx">     ASSERT(internalValuesConsistent(m_url));
</span><del>-    return m_url;
</del><span class="cx"> }
</span><span class="cx"> 
</span><span class="cx"> template&lt;typename CharacterType&gt;
</span></span></pre></div>
<a id="trunkSourceWebCoreplatformURLParserh"></a>
<div class="modfile"><h4>Modified: trunk/Source/WebCore/platform/URLParser.h (206328 => 206329)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/Source/WebCore/platform/URLParser.h        2016-09-23 20:33:53 UTC (rev 206328)
+++ trunk/Source/WebCore/platform/URLParser.h        2016-09-23 20:58:03 UTC (rev 206329)
</span><span class="lines">@@ -36,7 +36,8 @@
</span><span class="cx"> 
</span><span class="cx"> class URLParser {
</span><span class="cx"> public:
</span><del>-    WEBCORE_EXPORT URL parse(const String&amp;, const URL&amp; = { }, const TextEncoding&amp; = UTF8Encoding());
</del><ins>+    WEBCORE_EXPORT URLParser(const String&amp;, const URL&amp; = { }, const TextEncoding&amp; = UTF8Encoding());
+    URL result() { return m_url; }
</ins><span class="cx"> 
</span><span class="cx">     WEBCORE_EXPORT static bool allValuesEqual(const URL&amp;, const URL&amp;);
</span><span class="cx">     WEBCORE_EXPORT static bool internalValuesConsistent(const URL&amp;);
</span><span class="lines">@@ -54,13 +55,20 @@
</span><span class="cx">     Vector&lt;UChar&gt; m_unicodeFragmentBuffer;
</span><span class="cx">     bool m_urlIsSpecial { false };
</span><span class="cx">     bool m_hostHasPercentOrNonASCII { false };
</span><ins>+    String m_inputString;
</ins><span class="cx"> 
</span><del>-    template&lt;typename CharacterType&gt; URL parse(const CharacterType*, const unsigned length, const URL&amp;, const TextEncoding&amp;);
</del><ins>+    template&lt;typename CharacterType&gt; void parse(const CharacterType*, const unsigned length, const URL&amp;, const TextEncoding&amp;);
</ins><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="cx">     template&lt;typename CharacterType&gt; bool parsePort(CodePointIterator&lt;CharacterType&gt;&amp;);
</span><del>-    template&lt;typename CharacterType&gt; URL failure(const CharacterType*, unsigned length);
</del><span class="cx"> 
</span><ins>+    void failure();
+    template&lt;typename CharacterType&gt; void incrementIteratorSkippingTabAndNewLine(CodePointIterator&lt;CharacterType&gt;&amp;);
+    template&lt;typename CharacterType&gt; void syntaxError(const CodePointIterator&lt;CharacterType&gt;&amp;);
+    template&lt;typename CharacterType&gt; bool isWindowsDriveLetter(CodePointIterator&lt;CharacterType&gt;);
+    template&lt;typename CharacterType&gt; bool shouldCopyFileURL(CodePointIterator&lt;CharacterType&gt;);
+    template&lt;typename CharacterType&gt; void checkWindowsDriveLetter(CodePointIterator&lt;CharacterType&gt;&amp;, Vector&lt;LChar&gt;&amp; asciiBuffer);
+
</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>
<a id="trunkSourceWebCoreplatformcfURLCFcpp"></a>
<div class="modfile"><h4>Modified: trunk/Source/WebCore/platform/cf/URLCF.cpp (206328 => 206329)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/Source/WebCore/platform/cf/URLCF.cpp        2016-09-23 20:33:53 UTC (rev 206328)
+++ trunk/Source/WebCore/platform/cf/URLCF.cpp        2016-09-23 20:58:03 UTC (rev 206329)
</span><span class="lines">@@ -48,8 +48,8 @@
</span><span class="cx">     CString urlBytes;
</span><span class="cx">     getURLBytes(url, urlBytes);
</span><span class="cx">     if (URLParser::enabled()) {
</span><del>-        URLParser parser;
-        parser.parse(urlBytes.data());
</del><ins>+        URLParser parser(urlBytes.data());
+        *this = parser.result();
</ins><span class="cx">     } else
</span><span class="cx">         parse(urlBytes.data());
</span><span class="cx"> }
</span></span></pre></div>
<a id="trunkSourceWebCoreplatformmacURLMacmm"></a>
<div class="modfile"><h4>Modified: trunk/Source/WebCore/platform/mac/URLMac.mm (206328 => 206329)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/Source/WebCore/platform/mac/URLMac.mm        2016-09-23 20:33:53 UTC (rev 206328)
+++ trunk/Source/WebCore/platform/mac/URLMac.mm        2016-09-23 20:58:03 UTC (rev 206329)
</span><span class="lines">@@ -44,8 +44,8 @@
</span><span class="cx">     CString urlBytes;
</span><span class="cx">     getURLBytes(reinterpret_cast&lt;CFURLRef&gt;(url), urlBytes);
</span><span class="cx">     if (URLParser::enabled()) {
</span><del>-        URLParser parser;
-        *this = parser.parse(urlBytes.data());
</del><ins>+        URLParser parser(urlBytes.data());
+        *this = parser.result();
</ins><span class="cx">     } else
</span><span class="cx">         parse(urlBytes.data());
</span><span class="cx"> }
</span></span></pre></div>
<a id="trunkToolsChangeLog"></a>
<div class="modfile"><h4>Modified: trunk/Tools/ChangeLog (206328 => 206329)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/Tools/ChangeLog        2016-09-23 20:33:53 UTC (rev 206328)
+++ trunk/Tools/ChangeLog        2016-09-23 20:58:03 UTC (rev 206329)
</span><span class="lines">@@ -1,3 +1,14 @@
</span><ins>+2016-09-23  Alex Christensen  &lt;achristensen@webkit.org&gt;
+
+        Refactor URLParser
+        https://bugs.webkit.org/show_bug.cgi?id=162511
+
+        Reviewed by Brady Eidson.
+
+        * TestWebKitAPI/Tests/WebCore/URLParser.cpp:
+        (TestWebKitAPI::TEST_F):
+        (TestWebKitAPI::checkURL):
+
</ins><span class="cx"> 2016-09-23  Alexey Proskuryakov  &lt;ap@apple.com&gt;
</span><span class="cx"> 
</span><span class="cx">         iOS playback user action tests fail on some machines
</span></span></pre></div>
<a id="trunkToolsTestWebKitAPITestsWebCoreURLParsercpp"></a>
<div class="modfile"><h4>Modified: trunk/Tools/TestWebKitAPI/Tests/WebCore/URLParser.cpp (206328 => 206329)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/Tools/TestWebKitAPI/Tests/WebCore/URLParser.cpp        2016-09-23 20:33:53 UTC (rev 206328)
+++ trunk/Tools/TestWebKitAPI/Tests/WebCore/URLParser.cpp        2016-09-23 20:58:03 UTC (rev 206329)
</span><span class="lines">@@ -670,6 +670,9 @@
</span><span class="cx">     checkURLDifferences(&quot;http://host/`&quot;,
</span><span class="cx">         {&quot;http&quot;, &quot;&quot;, &quot;&quot;, &quot;host&quot;, 0, &quot;/%60&quot;, &quot;&quot;, &quot;&quot;, &quot;http://host/%60&quot;},
</span><span class="cx">         {&quot;http&quot;, &quot;&quot;, &quot;&quot;, &quot;host&quot;, 0, &quot;/`&quot;, &quot;&quot;, &quot;&quot;, &quot;http://host/`&quot;});
</span><ins>+    checkURLDifferences(wideString(L&quot;http://host/path#šŸ’©\tšŸ’©&quot;),
+        {&quot;http&quot;, &quot;&quot;, &quot;&quot;, &quot;host&quot;, 0, &quot;/path&quot;, &quot;&quot;, wideString(L&quot;šŸ’©šŸ’©&quot;), wideString(L&quot;http://host/path#šŸ’©šŸ’©&quot;)},
+        {&quot;http&quot;, &quot;&quot;, &quot;&quot;, &quot;host&quot;, 0, &quot;/path&quot;, &quot;&quot;, &quot;%F0%9F%92%A9%F0%9F%92%A9&quot;, &quot;http://host/path#%F0%9F%92%A9%F0%9F%92%A9&quot;});
</ins><span class="cx"> }
</span><span class="cx">     
</span><span class="cx"> static void shouldFail(const String&amp; urlString)
</span><span class="lines">@@ -687,6 +690,7 @@
</span><span class="cx">     shouldFail(&quot;    &quot;);
</span><span class="cx">     shouldFail(&quot;  \a  &quot;);
</span><span class="cx">     shouldFail(&quot;&quot;);
</span><ins>+    shouldFail(String());
</ins><span class="cx">     shouldFail(&quot;http://127.0.0.1:abc&quot;);
</span><span class="cx">     shouldFail(&quot;http://host:abc&quot;);
</span><span class="cx">     shouldFail(&quot;http://a:@&quot;, &quot;about:blank&quot;);
</span><span class="lines">@@ -758,8 +762,8 @@
</span><span class="cx"> 
</span><span class="cx"> static void checkURL(const String&amp; urlString, const TextEncoding&amp; encoding, const ExpectedParts&amp; parts)
</span><span class="cx"> {
</span><del>-    URLParser parser;
-    auto url = parser.parse(urlString, { }, encoding);
</del><ins>+    URLParser parser(urlString, { }, encoding);
+    auto url = parser.result();
</ins><span class="cx">     EXPECT_TRUE(eq(parts.protocol, url.protocol()));
</span><span class="cx">     EXPECT_TRUE(eq(parts.user, url.user()));
</span><span class="cx">     EXPECT_TRUE(eq(parts.password, url.pass()));
</span></span></pre>
</div>
</div>

</body>
</html>