<!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>[206125] 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/206125">206125</a></dd>
<dt>Author</dt> <dd>achristensen@apple.com</dd>
<dt>Date</dt> <dd>2016-09-19 16:03:02 -0700 (Mon, 19 Sep 2016)</dd>
</dl>

<h3>Log Message</h3>
<pre>URLParser should parse serialized valid URLs faster than unknown input
https://bugs.webkit.org/show_bug.cgi?id=162228

Reviewed by Chris Dumez.

The URL constructor with ParsedURLStringTag is almost twice as fast as the other URL constructors.
Assuming there are no tabs or newlines, and assuming characters are already encoded decreases the URLParser
runtime by over 25% and adds infrastructure for more optimizations.

No new tests. No change in behaviour.

* platform/URL.cpp:
(WebCore::URL::URL):
* platform/URLParser.cpp:
(WebCore::utf8PercentEncode):
(WebCore::utf8PercentEncodeQuery):
(WebCore::URLParser::parse):
(WebCore::URLParser::parseSerializedURL):
(WebCore::incrementIterator):
(WebCore::URLParser::parseAuthority):
(WebCore::URLParser::parsePort):
(WebCore::URLParser::parseHost):
* platform/URLParser.h:
(WebCore::URLParser::parse): Deleted.</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>
</ul>

</div>
<div id="patch">
<h3>Diff</h3>
<a id="trunkSourceWebCoreChangeLog"></a>
<div class="modfile"><h4>Modified: trunk/Source/WebCore/ChangeLog (206124 => 206125)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/Source/WebCore/ChangeLog        2016-09-19 23:02:39 UTC (rev 206124)
+++ trunk/Source/WebCore/ChangeLog        2016-09-19 23:03:02 UTC (rev 206125)
</span><span class="lines">@@ -1,3 +1,30 @@
</span><ins>+2016-09-19  Alex Christensen  &lt;achristensen@webkit.org&gt;
+
+        URLParser should parse serialized valid URLs faster than unknown input
+        https://bugs.webkit.org/show_bug.cgi?id=162228
+
+        Reviewed by Chris Dumez.
+
+        The URL constructor with ParsedURLStringTag is almost twice as fast as the other URL constructors.
+        Assuming there are no tabs or newlines, and assuming characters are already encoded decreases the URLParser
+        runtime by over 25% and adds infrastructure for more optimizations.
+
+        No new tests. No change in behaviour.
+
+        * platform/URL.cpp:
+        (WebCore::URL::URL):
+        * platform/URLParser.cpp:
+        (WebCore::utf8PercentEncode):
+        (WebCore::utf8PercentEncodeQuery):
+        (WebCore::URLParser::parse):
+        (WebCore::URLParser::parseSerializedURL):
+        (WebCore::incrementIterator):
+        (WebCore::URLParser::parseAuthority):
+        (WebCore::URLParser::parsePort):
+        (WebCore::URLParser::parseHost):
+        * platform/URLParser.h:
+        (WebCore::URLParser::parse): Deleted.
+
</ins><span class="cx"> 2016-09-19  Daniel Bates  &lt;dabates@apple.com&gt;
</span><span class="cx"> 
</span><span class="cx">         Cleanup: Remove an extraneous copy of SecurityOrigin
</span></span></pre></div>
<a id="trunkSourceWebCoreplatformURLcpp"></a>
<div class="modfile"><h4>Modified: trunk/Source/WebCore/platform/URL.cpp (206124 => 206125)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/Source/WebCore/platform/URL.cpp        2016-09-19 23:02:39 UTC (rev 206124)
+++ trunk/Source/WebCore/platform/URL.cpp        2016-09-19 23:03:02 UTC (rev 206125)
</span><span class="lines">@@ -442,9 +442,8 @@
</span><span class="cx"> {
</span><span class="cx">     if (URLParser::enabled()) {
</span><span class="cx">         URLParser parser;
</span><del>-        *this = parser.parse(url);
-        ASSERT((url.isEmpty() &amp;&amp; m_string.isEmpty()) || url == m_string); // FIXME: Investigate parsing non-null empty ParsedURLStrings.
-    } else {
</del><ins>+        *this = parser.parseSerializedURL(url);
+    } else
</ins><span class="cx">         parse(url);
</span><span class="cx"> #if OS(WINDOWS)
</span><span class="cx">         // FIXME(148598): Work around Windows local file handling bug in CFNetwork
</span><span class="lines">@@ -452,7 +451,6 @@
</span><span class="cx"> #else
</span><span class="cx">         ASSERT(url == m_string);
</span><span class="cx"> #endif
</span><del>-    }
</del><span class="cx"> }
</span><span class="cx"> 
</span><span class="cx"> URL::URL(const URL&amp; base, const String&amp; relative)
</span></span></pre></div>
<a id="trunkSourceWebCoreplatformURLParsercpp"></a>
<div class="modfile"><h4>Modified: trunk/Source/WebCore/platform/URLParser.cpp (206124 => 206125)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/Source/WebCore/platform/URLParser.cpp        2016-09-19 23:02:39 UTC (rev 206124)
+++ trunk/Source/WebCore/platform/URLParser.cpp        2016-09-19 23:03:02 UTC (rev 206125)
</span><span class="lines">@@ -435,36 +435,50 @@
</span><span class="cx">     buffer.append(lowerNibbleToASCIIHexDigit(byte));
</span><span class="cx"> }
</span><span class="cx"> 
</span><ins>+template&lt;bool serialized&gt;
</ins><span class="cx"> inline static void utf8PercentEncode(UChar32 codePoint, Vector&lt;LChar&gt;&amp; destination, bool(*isInCodeSet)(UChar32))
</span><span class="cx"> {
</span><del>-    if (isInCodeSet(codePoint)) {
-        uint8_t buffer[U8_MAX_LENGTH];
-        int32_t offset = 0;
-        UBool error = false;
-        U8_APPEND(buffer, offset, U8_MAX_LENGTH, codePoint, error);
-        // FIXME: Check error.
-        for (int32_t i = 0; i &lt; offset; ++i)
-            percentEncode(buffer[i], destination);
</del><ins>+    if (serialized) {
+        ASSERT_WITH_SECURITY_IMPLICATION(isASCII(codePoint));
+        ASSERT_WITH_SECURITY_IMPLICATION(!isInCodeSet(codePoint));
+        destination.append(codePoint);
</ins><span class="cx">     } else {
</span><del>-        ASSERT_WITH_MESSAGE(isASCII(codePoint), &quot;isInCodeSet should always return true for non-ASCII characters&quot;);
-        destination.append(codePoint);
</del><ins>+        if (isInCodeSet(codePoint)) {
+            uint8_t buffer[U8_MAX_LENGTH];
+            int32_t offset = 0;
+            UBool error = false;
+            U8_APPEND(buffer, offset, U8_MAX_LENGTH, codePoint, error);
+            // FIXME: Check error.
+            for (int32_t i = 0; i &lt; offset; ++i)
+                percentEncode(buffer[i], destination);
+        } else {
+            ASSERT_WITH_MESSAGE(isASCII(codePoint), &quot;isInCodeSet should always return true for non-ASCII characters&quot;);
+            destination.append(codePoint);
+        }
</ins><span class="cx">     }
</span><span class="cx"> }
</span><span class="cx"> 
</span><ins>+template&lt;bool serialized&gt;
</ins><span class="cx"> inline static void utf8PercentEncodeQuery(UChar32 codePoint, Vector&lt;LChar&gt;&amp; destination)
</span><span class="cx"> {
</span><del>-    uint8_t buffer[U8_MAX_LENGTH];
-    int32_t offset = 0;
-    UBool error = false;
-    U8_APPEND(buffer, offset, U8_MAX_LENGTH, codePoint, error);
-    ASSERT_WITH_SECURITY_IMPLICATION(offset &lt;= static_cast&lt;int32_t&gt;(sizeof(buffer)));
-    // FIXME: Check error.
-    for (int32_t i = 0; i &lt; offset; ++i) {
-        auto byte = buffer[i];
-        if (shouldPercentEncodeQueryByte(byte))
-            percentEncode(byte, destination);
-        else
-            destination.append(byte);
</del><ins>+    if (serialized) {
+        ASSERT_WITH_SECURITY_IMPLICATION(isASCII(codePoint));
+        ASSERT_WITH_SECURITY_IMPLICATION(!shouldPercentEncodeQueryByte(codePoint));
+        destination.append(codePoint);
+    } else {
+        uint8_t buffer[U8_MAX_LENGTH];
+        int32_t offset = 0;
+        UBool error = false;
+        U8_APPEND(buffer, offset, U8_MAX_LENGTH, codePoint, error);
+        ASSERT_WITH_SECURITY_IMPLICATION(offset &lt;= static_cast&lt;int32_t&gt;(sizeof(buffer)));
+        // FIXME: Check error.
+        for (int32_t i = 0; i &lt; offset; ++i) {
+            auto byte = buffer[i];
+            if (shouldPercentEncodeQueryByte(byte))
+                percentEncode(byte, destination);
+            else
+                destination.append(byte);
+        }
</ins><span class="cx">     }
</span><span class="cx"> }
</span><span class="cx">     
</span><span class="lines">@@ -863,12 +877,29 @@
</span><span class="cx"> 
</span><span class="cx"> URL URLParser::parse(const String&amp; input, const URL&amp; base, const TextEncoding&amp; encoding)
</span><span class="cx"> {
</span><ins>+    const bool serialized = false;
</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>+        return parse&lt;serialized&gt;(input.characters8(), input.length(), base, encoding);
+    return parse&lt;serialized&gt;(input.characters16(), input.length(), base, encoding);
</ins><span class="cx"> }
</span><span class="cx"> 
</span><del>-template&lt;typename CharacterType&gt;
</del><ins>+URL URLParser::parseSerializedURL(const String&amp; input)
+{
+    const bool serialized = true;
+    if (input.is8Bit())
+        return parse&lt;serialized&gt;(input.characters8(), input.length(), { }, UTF8Encoding());
+    return parse&lt;serialized&gt;(input.characters16(), input.length(), { }, UTF8Encoding());
+}
+
+template&lt;bool serialized, typename CharacterType&gt;
+void incrementIteratorSkippingTabAndNewLine(CodePointIterator&lt;CharacterType&gt;&amp; iterator)
+{
+    ++iterator;
+    while (!serialized &amp;&amp; !iterator.atEnd() &amp;&amp; isTabOrNewline(*iterator))
+        ++iterator;
+}
+    
+template&lt;bool serialized, typename CharacterType&gt;
</ins><span class="cx"> URL URLParser::parse(const CharacterType* input, const unsigned length, const URL&amp; base, const TextEncoding&amp; encoding)
</span><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="lines">@@ -916,7 +947,7 @@
</span><span class="cx"> 
</span><span class="cx">     State state = State::SchemeStart;
</span><span class="cx">     while (!c.atEnd()) {
</span><del>-        if (isTabOrNewline(*c)) {
</del><ins>+        if (!serialized &amp;&amp; isTabOrNewline(*c)) {
</ins><span class="cx">             ++c;
</span><span class="cx">             continue;
</span><span class="cx">         }
</span><span class="lines">@@ -960,9 +991,7 @@
</span><span class="cx">                     m_url.m_hostEnd = m_url.m_userStart;
</span><span class="cx">                     m_url.m_portEnd = m_url.m_userStart;
</span><span class="cx">                     auto maybeSlash = c;
</span><del>-                    ++maybeSlash;
-                    while (!maybeSlash.atEnd() &amp;&amp; isTabOrNewline(*maybeSlash))
-                        ++maybeSlash;
</del><ins>+                    incrementIteratorSkippingTabAndNewLine&lt;serialized&gt;(maybeSlash);
</ins><span class="cx">                     if (!maybeSlash.atEnd() &amp;&amp; *maybeSlash == '/') {
</span><span class="cx">                         m_asciiBuffer.append('/');
</span><span class="cx">                         m_url.m_pathAfterLastSlash = m_url.m_userStart + 1;
</span><span class="lines">@@ -983,9 +1012,7 @@
</span><span class="cx">                 c = beginAfterControlAndSpace;
</span><span class="cx">                 break;
</span><span class="cx">             }
</span><del>-            ++c;
-            while (!c.atEnd() &amp;&amp; isTabOrNewline(*c))
-                ++c;
</del><ins>+            incrementIteratorSkippingTabAndNewLine&lt;serialized&gt;(c);
</ins><span class="cx">             if (c.atEnd()) {
</span><span class="cx">                 m_asciiBuffer.clear();
</span><span class="cx">                 state = State::NoScheme;
</span><span class="lines">@@ -1015,9 +1042,7 @@
</span><span class="cx">             LOG_STATE(&quot;SpecialRelativeOrAuthority&quot;);
</span><span class="cx">             if (*c == '/') {
</span><span class="cx">                 m_asciiBuffer.append('/');
</span><del>-                ++c;
-                while (!c.atEnd() &amp;&amp; isTabOrNewline(*c))
-                    ++c;
</del><ins>+                incrementIteratorSkippingTabAndNewLine&lt;serialized&gt;(c);
</ins><span class="cx">                 if (c.atEnd())
</span><span class="cx">                     return failure(input, length);
</span><span class="cx">                 if (*c == '/') {
</span><span class="lines">@@ -1083,9 +1108,7 @@
</span><span class="cx">             LOG_STATE(&quot;SpecialAuthoritySlashes&quot;);
</span><span class="cx">             m_asciiBuffer.append(&quot;//&quot;, 2);
</span><span class="cx">             if (*c == '/' || *c == '\\') {
</span><del>-                ++c;
-                while (!c.atEnd() &amp;&amp; isTabOrNewline(*c))
-                    ++c;
</del><ins>+                incrementIteratorSkippingTabAndNewLine&lt;serialized&gt;(c);
</ins><span class="cx">                 if (!c.atEnd() &amp;&amp; (*c == '/' || *c == '\\'))
</span><span class="cx">                     ++c;
</span><span class="cx">             }
</span><span class="lines">@@ -1105,10 +1128,8 @@
</span><span class="cx">             LOG_STATE(&quot;AuthorityOrHost&quot;);
</span><span class="cx">             {
</span><span class="cx">                 if (*c == '@') {
</span><del>-                    parseAuthority(CodePointIterator&lt;CharacterType&gt;(authorityOrHostBegin, c));
-                    ++c;
-                    while (!c.atEnd() &amp;&amp; isTabOrNewline(*c))
-                        ++c;
</del><ins>+                    parseAuthority&lt;serialized&gt;(CodePointIterator&lt;CharacterType&gt;(authorityOrHostBegin, c));
+                    incrementIteratorSkippingTabAndNewLine&lt;serialized&gt;(c);
</ins><span class="cx">                     authorityOrHostBegin = c;
</span><span class="cx">                     state = State::Host;
</span><span class="cx">                     m_hostHasPercentOrNonASCII = false;
</span><span class="lines">@@ -1118,7 +1139,7 @@
</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 (!parseHost(CodePointIterator&lt;CharacterType&gt;(authorityOrHostBegin, c)))
</del><ins>+                    if (!parseHost&lt;serialized&gt;(CodePointIterator&lt;CharacterType&gt;(authorityOrHostBegin, c)))
</ins><span class="cx">                         return failure(input, length);
</span><span class="cx">                     if (!isSlash) {
</span><span class="cx">                         m_asciiBuffer.append('/');
</span><span class="lines">@@ -1135,7 +1156,7 @@
</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 (!parseHost(CodePointIterator&lt;CharacterType&gt;(authorityOrHostBegin, c)))
</del><ins>+                if (!parseHost&lt;serialized&gt;(CodePointIterator&lt;CharacterType&gt;(authorityOrHostBegin, c)))
</ins><span class="cx">                     return failure(input, length);
</span><span class="cx">                 state = State::Path;
</span><span class="cx">                 break;
</span><span class="lines">@@ -1265,7 +1286,7 @@
</span><span class="cx">                     state = State::Path;
</span><span class="cx">                     break;
</span><span class="cx">                 }
</span><del>-                if (!parseHost(CodePointIterator&lt;CharacterType&gt;(authorityOrHostBegin, c)))
</del><ins>+                if (!parseHost&lt;serialized&gt;(CodePointIterator&lt;CharacterType&gt;(authorityOrHostBegin, c)))
</ins><span class="cx">                     return failure(input, length);
</span><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="lines">@@ -1327,7 +1348,7 @@
</span><span class="cx">                 ++c;
</span><span class="cx">                 break;
</span><span class="cx">             }
</span><del>-            utf8PercentEncode(*c, m_asciiBuffer, isInDefaultEncodeSet);
</del><ins>+            utf8PercentEncode&lt;serialized&gt;(*c, m_asciiBuffer, isInDefaultEncodeSet);
</ins><span class="cx">             ++c;
</span><span class="cx">             break;
</span><span class="cx">         case State::CannotBeABaseURLPath:
</span><span class="lines">@@ -1340,7 +1361,7 @@
</span><span class="cx">                 m_url.m_queryEnd = m_url.m_pathEnd;
</span><span class="cx">                 state = State::Fragment;
</span><span class="cx">             } else {
</span><del>-                utf8PercentEncode(*c, m_asciiBuffer, isInSimpleEncodeSet);
</del><ins>+                utf8PercentEncode&lt;serialized&gt;(*c, m_asciiBuffer, isInSimpleEncodeSet);
</ins><span class="cx">                 ++c;
</span><span class="cx">             }
</span><span class="cx">             break;
</span><span class="lines">@@ -1354,7 +1375,7 @@
</span><span class="cx">                 break;
</span><span class="cx">             }
</span><span class="cx">             if (isUTF8Encoding)
</span><del>-                utf8PercentEncodeQuery(*c, m_asciiBuffer);
</del><ins>+                utf8PercentEncodeQuery&lt;serialized&gt;(*c, m_asciiBuffer);
</ins><span class="cx">             else
</span><span class="cx">                 queryBuffer.append(*c);
</span><span class="cx">             ++c;
</span><span class="lines">@@ -1430,7 +1451,7 @@
</span><span class="cx">     case State::Host:
</span><span class="cx">         if (state == State::Host)
</span><span class="cx">             LOG_FINAL_STATE(&quot;Host&quot;);
</span><del>-        if (!parseHost(authorityOrHostBegin))
</del><ins>+        if (!parseHost&lt;serialized&gt;(authorityOrHostBegin))
</ins><span class="cx">             return failure(input, length);
</span><span class="cx">         m_asciiBuffer.append('/');
</span><span class="cx">         m_url.m_pathEnd = m_url.m_portEnd + 1;
</span><span class="lines">@@ -1484,7 +1505,7 @@
</span><span class="cx">             break;
</span><span class="cx">         }
</span><span class="cx"> 
</span><del>-        if (!parseHost(CodePointIterator&lt;CharacterType&gt;(authorityOrHostBegin, c)))
</del><ins>+        if (!parseHost&lt;serialized&gt;(CodePointIterator&lt;CharacterType&gt;(authorityOrHostBegin, c)))
</ins><span class="cx">             return failure(input, length);
</span><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="lines">@@ -1542,7 +1563,7 @@
</span><span class="cx">     return m_url;
</span><span class="cx"> }
</span><span class="cx"> 
</span><del>-template&lt;typename CharacterType&gt;
</del><ins>+template&lt;bool serialized, typename CharacterType&gt;
</ins><span class="cx"> void URLParser::parseAuthority(CodePointIterator&lt;CharacterType&gt; iterator)
</span><span class="cx"> {
</span><span class="cx">     if (iterator.atEnd()) {
</span><span class="lines">@@ -1563,10 +1584,10 @@
</span><span class="cx">             m_asciiBuffer.append(':');
</span><span class="cx">             break;
</span><span class="cx">         }
</span><del>-        utf8PercentEncode(*iterator, m_asciiBuffer, isInUserInfoEncodeSet);
</del><ins>+        utf8PercentEncode&lt;serialized&gt;(*iterator, m_asciiBuffer, isInUserInfoEncodeSet);
</ins><span class="cx">     }
</span><span class="cx">     for (; !iterator.atEnd(); ++iterator)
</span><del>-        utf8PercentEncode(*iterator, m_asciiBuffer, isInUserInfoEncodeSet);
</del><ins>+        utf8PercentEncode&lt;serialized&gt;(*iterator, m_asciiBuffer, isInUserInfoEncodeSet);
</ins><span class="cx">     m_url.m_passwordEnd = m_asciiBuffer.size();
</span><span class="cx">     if (!m_url.m_userEnd)
</span><span class="cx">         m_url.m_userEnd = m_url.m_passwordEnd;
</span><span class="lines">@@ -1929,7 +1950,7 @@
</span><span class="cx">     return false;
</span><span class="cx"> }
</span><span class="cx"> 
</span><del>-template&lt;typename CharacterType&gt;
</del><ins>+template&lt;bool serialized, typename CharacterType&gt;
</ins><span class="cx"> bool URLParser::parsePort(CodePointIterator&lt;CharacterType&gt;&amp; iterator)
</span><span class="cx"> {
</span><span class="cx">     uint32_t port = 0;
</span><span class="lines">@@ -1939,7 +1960,7 @@
</span><span class="cx">     }
</span><span class="cx">     m_asciiBuffer.append(':');
</span><span class="cx">     for (; !iterator.atEnd(); ++iterator) {
</span><del>-        if (isTabOrNewline(*iterator))
</del><ins>+        if (!serialized &amp;&amp; isTabOrNewline(*iterator))
</ins><span class="cx">             continue;
</span><span class="cx">         if (isASCIIDigit(*iterator)) {
</span><span class="cx">             port = port * 10 + *iterator - '0';
</span><span class="lines">@@ -1959,7 +1980,7 @@
</span><span class="cx">     return true;
</span><span class="cx"> }
</span><span class="cx"> 
</span><del>-template&lt;typename CharacterType&gt;
</del><ins>+template&lt;bool serialized, typename CharacterType&gt;
</ins><span class="cx"> bool URLParser::parseHost(CodePointIterator&lt;CharacterType&gt; iterator)
</span><span class="cx"> {
</span><span class="cx">     if (iterator.atEnd())
</span><span class="lines">@@ -1976,7 +1997,7 @@
</span><span class="cx">                 ++ipv6End;
</span><span class="cx">                 if (!ipv6End.atEnd() &amp;&amp; *ipv6End == ':') {
</span><span class="cx">                     ++ipv6End;
</span><del>-                    return parsePort(ipv6End);
</del><ins>+                    return parsePort&lt;serialized&gt;(ipv6End);
</ins><span class="cx">                 }
</span><span class="cx">                 m_url.m_portEnd = m_asciiBuffer.size();
</span><span class="cx">                 return true;
</span><span class="lines">@@ -1988,7 +2009,7 @@
</span><span class="cx">     if (!m_hostHasPercentOrNonASCII) {
</span><span class="cx">         auto hostIterator = iterator;
</span><span class="cx">         for (; !iterator.atEnd(); ++iterator) {
</span><del>-            if (isTabOrNewline(*iterator))
</del><ins>+            if (!serialized &amp;&amp; isTabOrNewline(*iterator))
</ins><span class="cx">                 continue;
</span><span class="cx">             if (*iterator == ':')
</span><span class="cx">                 break;
</span><span class="lines">@@ -2003,19 +2024,17 @@
</span><span class="cx">                 return true;
</span><span class="cx">             }
</span><span class="cx">             ++iterator;
</span><del>-            return parsePort(iterator);
</del><ins>+            return parsePort&lt;serialized&gt;(iterator);
</ins><span class="cx">         }
</span><span class="cx">         for (; hostIterator != iterator; ++hostIterator) {
</span><del>-            if (!isTabOrNewline(*hostIterator))
</del><ins>+            if (serialized || !isTabOrNewline(*hostIterator))
</ins><span class="cx">                 m_asciiBuffer.append(toASCIILower(*hostIterator));
</span><span class="cx">         }
</span><span class="cx">         m_url.m_hostEnd = m_asciiBuffer.size();
</span><span class="cx">         if (!hostIterator.atEnd()) {
</span><span class="cx">             ASSERT(*hostIterator == ':');
</span><del>-            ++hostIterator;
-            while (!hostIterator.atEnd() &amp;&amp; isTabOrNewline(*hostIterator))
-                ++hostIterator;
-            return parsePort(hostIterator);
</del><ins>+            incrementIteratorSkippingTabAndNewLine&lt;serialized&gt;(hostIterator);
+            return parsePort&lt;serialized&gt;(hostIterator);
</ins><span class="cx">         }
</span><span class="cx">         m_url.m_portEnd = m_asciiBuffer.size();
</span><span class="cx">         return true;
</span><span class="lines">@@ -2024,7 +2043,7 @@
</span><span class="cx">     // FIXME: We probably don't need to make so many buffers and String copies.
</span><span class="cx">     StringBuilder utf8Encoded;
</span><span class="cx">     for (; !iterator.atEnd(); ++iterator) {
</span><del>-        if (isTabOrNewline(*iterator))
</del><ins>+        if (!serialized &amp;&amp; isTabOrNewline(*iterator))
</ins><span class="cx">             continue;
</span><span class="cx">         if (*iterator == ':')
</span><span class="cx">             break;
</span><span class="lines">@@ -2055,7 +2074,7 @@
</span><span class="cx">             return true;
</span><span class="cx">         }
</span><span class="cx">         ++iterator;
</span><del>-        return parsePort(iterator);
</del><ins>+        return parsePort&lt;serialized&gt;(iterator);
</ins><span class="cx">     }
</span><span class="cx"> 
</span><span class="cx">     m_asciiBuffer.append(asciiDomainCharacters, asciiDomainValue.length());
</span><span class="lines">@@ -2062,10 +2081,8 @@
</span><span class="cx">     m_url.m_hostEnd = m_asciiBuffer.size();
</span><span class="cx">     if (!iterator.atEnd()) {
</span><span class="cx">         ASSERT(*iterator == ':');
</span><del>-        ++iterator;
-        while (!iterator.atEnd() &amp;&amp; isTabOrNewline(*iterator))
-            ++iterator;
-        return parsePort(iterator);
</del><ins>+        incrementIteratorSkippingTabAndNewLine&lt;serialized&gt;(iterator);
+        return parsePort&lt;serialized&gt;(iterator);
</ins><span class="cx">     }
</span><span class="cx">     m_url.m_portEnd = m_asciiBuffer.size();
</span><span class="cx">     return true;
</span></span></pre></div>
<a id="trunkSourceWebCoreplatformURLParserh"></a>
<div class="modfile"><h4>Modified: trunk/Source/WebCore/platform/URLParser.h (206124 => 206125)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/Source/WebCore/platform/URLParser.h        2016-09-19 23:02:39 UTC (rev 206124)
+++ trunk/Source/WebCore/platform/URLParser.h        2016-09-19 23:03:02 UTC (rev 206125)
</span><span class="lines">@@ -37,6 +37,7 @@
</span><span class="cx"> class URLParser {
</span><span class="cx"> public:
</span><span class="cx">     WEBCORE_EXPORT URL parse(const String&amp;, const URL&amp; = { }, const TextEncoding&amp; = UTF8Encoding());
</span><ins>+    WEBCORE_EXPORT URL parseSerializedURL(const String&amp;);
</ins><span class="cx">     WEBCORE_EXPORT static bool allValuesEqual(const URL&amp;, const URL&amp;);
</span><span class="cx"> 
</span><span class="cx">     WEBCORE_EXPORT static bool enabled();
</span><span class="lines">@@ -53,10 +54,10 @@
</span><span class="cx">     bool m_urlIsSpecial { false };
</span><span class="cx">     bool m_hostHasPercentOrNonASCII { false };
</span><span class="cx"> 
</span><del>-    template&lt;typename CharacterType&gt; URL parse(const CharacterType*, const unsigned length, const URL&amp;, const TextEncoding&amp;);
-    template&lt;typename CharacterType&gt; void parseAuthority(CodePointIterator&lt;CharacterType&gt;);
-    template&lt;typename CharacterType&gt; bool parseHost(CodePointIterator&lt;CharacterType&gt;);
-    template&lt;typename CharacterType&gt; bool parsePort(CodePointIterator&lt;CharacterType&gt;&amp;);
</del><ins>+    template&lt;bool serialized, typename CharacterType&gt; URL parse(const CharacterType*, const unsigned length, const URL&amp;, const TextEncoding&amp;);
+    template&lt;bool serialized, typename CharacterType&gt; void parseAuthority(CodePointIterator&lt;CharacterType&gt;);
+    template&lt;bool serialized, typename CharacterType&gt; bool parseHost(CodePointIterator&lt;CharacterType&gt;);
+    template&lt;bool serialized, typename CharacterType&gt; bool parsePort(CodePointIterator&lt;CharacterType&gt;&amp;);
</ins><span class="cx">     template&lt;typename CharacterType&gt; URL failure(const CharacterType*, unsigned length);
</span><span class="cx"> 
</span><span class="cx">     enum class URLPart;
</span></span></pre>
</div>
</div>

</body>
</html>