<!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>[205390] 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/205390">205390</a></dd>
<dt>Author</dt> <dd>achristensen@apple.com</dd>
<dt>Date</dt> <dd>2016-09-02 17:32:49 -0700 (Fri, 02 Sep 2016)</dd>
</dl>
<h3>Log Message</h3>
<pre>URLParser should parse file URLs
https://bugs.webkit.org/show_bug.cgi?id=161556
Reviewed by Tim Horton.
Source/WebCore:
Added new API tests.
* platform/URLParser.cpp:
(WebCore::isWindowsDriveLetter):
(WebCore::shouldCopyFileURL):
(WebCore::URLParser::parse):
(WebCore::URLParser::parseHost):
* platform/URLParser.h:
Tools:
* TestWebKitAPI/Tests/WebCore/URLParser.cpp:
(TestWebKitAPI::TEST_F):
(TestWebKitAPI::checkURLDifferences):</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>
<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 (205389 => 205390)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/Source/WebCore/ChangeLog        2016-09-03 00:22:27 UTC (rev 205389)
+++ trunk/Source/WebCore/ChangeLog        2016-09-03 00:32:49 UTC (rev 205390)
</span><span class="lines">@@ -1,3 +1,19 @@
</span><ins>+2016-09-02 Alex Christensen <achristensen@webkit.org>
+
+ URLParser should parse file URLs
+ https://bugs.webkit.org/show_bug.cgi?id=161556
+
+ Reviewed by Tim Horton.
+
+ Added new API tests.
+
+ * platform/URLParser.cpp:
+ (WebCore::isWindowsDriveLetter):
+ (WebCore::shouldCopyFileURL):
+ (WebCore::URLParser::parse):
+ (WebCore::URLParser::parseHost):
+ * platform/URLParser.h:
+
</ins><span class="cx"> 2016-09-02 Ryosuke Niwa <rniwa@webkit.org>
</span><span class="cx">
</span><span class="cx"> Add validations for a synchronously constructed custom element
</span></span></pre></div>
<a id="trunkSourceWebCoreplatformURLParsercpp"></a>
<div class="modfile"><h4>Modified: trunk/Source/WebCore/platform/URLParser.cpp (205389 => 205390)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/Source/WebCore/platform/URLParser.cpp        2016-09-03 00:22:27 UTC (rev 205389)
+++ trunk/Source/WebCore/platform/URLParser.cpp        2016-09-03 00:32:49 UTC (rev 205390)
</span><span class="lines">@@ -27,7 +27,6 @@
</span><span class="cx"> #include "URLParser.h"
</span><span class="cx">
</span><span class="cx"> #include "Logging.h"
</span><del>-#include "NotImplemented.h"
</del><span class="cx"> #include <array>
</span><span class="cx"> #include <wtf/text/StringBuilder.h>
</span><span class="cx">
</span><span class="lines">@@ -37,6 +36,36 @@
</span><span class="cx"> template<typename CharacterType> static bool isC0ControlOrSpace(CharacterType character) { return isC0Control(character) || character == 0x0020; }
</span><span class="cx"> template<typename CharacterType> static bool isTabOrNewline(CharacterType character) { return character == 0x0009 || character == 0x000A || character == 0x000D; }
</span><span class="cx">
</span><ins>+static bool isWindowsDriveLetter(StringView::CodePoints::Iterator iterator, const StringView::CodePoints::Iterator& end)
+{
+ if (iterator == end || !isASCIIAlpha(*iterator))
+ return false;
+ ++iterator;
+ if (iterator == end)
+ return false;
+ return *iterator == ':' || *iterator == '|';
+}
+
+static bool isWindowsDriveLetter(const StringBuilder& builder, size_t index)
+{
+ if (builder.length() < index + 2)
+ return false;
+ return isASCIIAlpha(builder[index]) && (builder[index + 1] == ':' || builder[index + 1] == '|');
+}
+
+static bool shouldCopyFileURL(StringView::CodePoints::Iterator iterator, const StringView::CodePoints::Iterator end)
+{
+ if (isWindowsDriveLetter(iterator, end))
+ return true;
+ if (iterator == end)
+ return false;
+ ++iterator;
+ if (iterator == end)
+ return true;
+ ++iterator;
+ return *iterator != '/' && *iterator != '\\' && *iterator != '?' && *iterator == '#';
+}
+
</ins><span class="cx"> static bool isSpecialScheme(const String& scheme)
</span><span class="cx"> {
</span><span class="cx"> return scheme == "ftp"
</span><span class="lines">@@ -237,6 +266,7 @@
</span><span class="cx"> LOG(URLParser, "Parsing URL <%s> base <%s>", input.utf8().data(), base.string().utf8().data());
</span><span class="cx"> m_url = { };
</span><span class="cx"> m_buffer.clear();
</span><ins>+ m_buffer.reserveCapacity(input.length());
</ins><span class="cx">
</span><span class="cx"> auto codePoints = StringView(input).codePoints();
</span><span class="cx"> auto c = codePoints.begin();
</span><span class="lines">@@ -268,7 +298,7 @@
</span><span class="cx"> Fragment,
</span><span class="cx"> };
</span><span class="cx">
</span><del>-#define LOG_STATE(x) LOG(URLParser, x)
</del><ins>+#define LOG_STATE(x) LOG(URLParser, "State %s, code point %c, buffer length %d", x, *c, m_buffer.length())
</ins><span class="cx"> #define LOG_FINAL_STATE(x) LOG(URLParser, "Final State: %s", x)
</span><span class="cx">
</span><span class="cx"> State state = State::SchemeStart;
</span><span class="lines">@@ -296,9 +326,13 @@
</span><span class="cx"> m_url.m_schemeEnd = m_buffer.length();
</span><span class="cx"> String urlScheme = m_buffer.toString(); // FIXME: Find a way to do this without shrinking the m_buffer.
</span><span class="cx"> m_url.m_protocolIsInHTTPFamily = urlScheme == "http" || urlScheme == "https";
</span><del>- if (urlScheme == "file")
</del><ins>+ if (urlScheme == "file") {
</ins><span class="cx"> state = State::File;
</span><del>- else if (isSpecialScheme(urlScheme)) {
</del><ins>+ m_buffer.append(':');
+ ++c;
+ break;
+ }
+ if (isSpecialScheme(urlScheme)) {
</ins><span class="cx"> if (base.protocol() == urlScheme)
</span><span class="cx"> state = State::SpecialRelativeOrAuthority;
</span><span class="cx"> else
</span><span class="lines">@@ -344,9 +378,10 @@
</span><span class="cx"> ++c;
</span><span class="cx"> } else
</span><span class="cx"> return { };
</span><del>- } else if (base.protocol() == "file")
</del><ins>+ } else if (base.protocol() == "file") {
+ copyURLPartsUntil(base, URLPart::SchemeEnd);
</ins><span class="cx"> state = State::File;
</span><del>- else
</del><ins>+ } else
</ins><span class="cx"> state = State::Relative;
</span><span class="cx"> break;
</span><span class="cx"> case State::SpecialRelativeOrAuthority:
</span><span class="lines">@@ -466,17 +501,134 @@
</span><span class="cx"> break;
</span><span class="cx"> case State::File:
</span><span class="cx"> LOG_STATE("File");
</span><del>- notImplemented();
- ++c;
</del><ins>+ switch (*c) {
+ case '/':
+ case '\\':
+ m_buffer.append('/');
+ state = State::FileSlash;
+ ++c;
+ break;
+ case '?':
+ if (!base.isNull() && base.protocol() == "file")
+ copyURLPartsUntil(base, URLPart::PathEnd);
+ m_buffer.append("///?");
+ m_url.m_userStart = m_buffer.length() - 2;
+ m_url.m_userEnd = m_url.m_userStart;
+ m_url.m_passwordEnd = m_url.m_userStart;
+ m_url.m_hostEnd = m_url.m_userStart;
+ m_url.m_portEnd = m_url.m_userStart;
+ m_url.m_pathAfterLastSlash = m_url.m_userStart + 1;
+ m_url.m_pathEnd = m_url.m_pathAfterLastSlash;
+ state = State::Query;
+ ++c;
+ break;
+ case '#':
+ if (!base.isNull() && base.protocol() == "file")
+ copyURLPartsUntil(base, URLPart::QueryEnd);
+ m_buffer.append("///#");
+ m_url.m_userStart = m_buffer.length() - 2;
+ m_url.m_userEnd = m_url.m_userStart;
+ m_url.m_passwordEnd = m_url.m_userStart;
+ m_url.m_hostEnd = m_url.m_userStart;
+ m_url.m_portEnd = m_url.m_userStart;
+ m_url.m_pathAfterLastSlash = m_url.m_userStart + 1;
+ m_url.m_pathEnd = m_url.m_pathAfterLastSlash;
+ m_url.m_queryEnd = m_url.m_pathAfterLastSlash;
+ state = State::Fragment;
+ ++c;
+ break;
+ default:
+ if (shouldCopyFileURL(c, end)) {
+ copyURLPartsUntil(base, URLPart::PathEnd);
+ popPath();
+ } else {
+ m_buffer.append("///");
+ m_url.m_userStart = m_buffer.length() - 1;
+ m_url.m_userEnd = m_url.m_userStart;
+ m_url.m_passwordEnd = m_url.m_userStart;
+ m_url.m_hostEnd = m_url.m_userStart;
+ m_url.m_portEnd = m_url.m_userStart;
+ m_url.m_pathAfterLastSlash = m_url.m_userStart + 1;
+ }
+ state = State::Path;
+ break;
+ }
</ins><span class="cx"> break;
</span><span class="cx"> case State::FileSlash:
</span><span class="cx"> LOG_STATE("FileSlash");
</span><del>- notImplemented();
- ++c;
</del><ins>+ if (*c == '/' || *c == '\\') {
+ ++c;
+ m_buffer.append('/');
+ m_url.m_userStart = m_buffer.length();
+ m_url.m_userEnd = m_url.m_userStart;
+ m_url.m_passwordEnd = m_url.m_userStart;
+ m_url.m_hostEnd = m_url.m_userStart;
+ m_url.m_portEnd = m_url.m_userStart;
+ authorityOrHostBegin = c;
+ state = State::FileHost;
+ break;
+ }
+ if (!base.isNull() && base.protocol() == "file") {
+ String basePath = base.path();
+ auto basePathCodePoints = StringView(basePath).codePoints();
+ if (basePath.length() >= 2 && isWindowsDriveLetter(basePathCodePoints.begin(), basePathCodePoints.end())) {
+ m_buffer.append(basePath[0]);
+ m_buffer.append(basePath[1]);
+ }
+ state = State::Path;
+ break;
+ }
+ m_buffer.append("//");
+ m_url.m_userStart = m_buffer.length() - 1;
+ m_url.m_userEnd = m_url.m_userStart;
+ m_url.m_passwordEnd = m_url.m_userStart;
+ m_url.m_hostEnd = m_url.m_userStart;
+ m_url.m_portEnd = m_url.m_userStart;
+ m_url.m_pathAfterLastSlash = m_url.m_userStart + 1;
+ state = State::Path;
</ins><span class="cx"> break;
</span><span class="cx"> case State::FileHost:
</span><span class="cx"> LOG_STATE("FileHost");
</span><del>- notImplemented();
</del><ins>+ if (*c == '/' || *c == '\\' || *c == '?' || *c == '#') {
+ if (isWindowsDriveLetter(m_buffer, m_url.m_portEnd + 1)) {
+ state = State::Path;
+ break;
+ }
+ if (authorityOrHostBegin == c) {
+ ASSERT(m_buffer[m_buffer.length() - 1] == '/');
+ if (*c == '?') {
+ m_buffer.append("/?");
+ m_url.m_pathAfterLastSlash = m_buffer.length() - 1;
+ m_url.m_pathEnd = m_url.m_pathAfterLastSlash;
+ state = State::Query;
+ ++c;
+ break;
+ }
+ if (*c == '#') {
+ m_buffer.append("/#");
+ m_url.m_pathAfterLastSlash = m_buffer.length() - 1;
+ m_url.m_pathEnd = m_url.m_pathAfterLastSlash;
+ m_url.m_queryEnd = m_url.m_pathAfterLastSlash;
+ state = State::Fragment;
+ ++c;
+ break;
+ }
+ state = State::Path;
+ break;
+ }
+ if (!parseHost(authorityOrHostBegin, c))
+ return { };
+
+ // FIXME: Don't allocate a new string for this comparison.
+ if (m_buffer.toString().substring(m_url.m_passwordEnd) == "localhost") {
+ m_buffer.resize(m_url.m_passwordEnd);
+ m_url.m_hostEnd = m_buffer.length();
+ m_url.m_portEnd = m_url.m_hostEnd;
+ }
+
+ state = State::PathStart;
+ break;
+ }
</ins><span class="cx"> ++c;
</span><span class="cx"> break;
</span><span class="cx"> case State::PathStart:
</span><span class="lines">@@ -600,12 +752,68 @@
</span><span class="cx"> break;
</span><span class="cx"> case State::File:
</span><span class="cx"> LOG_FINAL_STATE("File");
</span><ins>+ if (!base.isNull() && base.protocol() == "file") {
+ copyURLPartsUntil(base, URLPart::QueryEnd);
+ m_buffer.append(':');
+ }
+ m_buffer.append("///");
+ m_url.m_userStart = m_buffer.length() - 1;
+ m_url.m_userEnd = m_url.m_userStart;
+ m_url.m_passwordEnd = m_url.m_userStart;
+ m_url.m_hostEnd = m_url.m_userStart;
+ m_url.m_portEnd = m_url.m_userStart;
+ m_url.m_pathAfterLastSlash = m_url.m_userStart + 1;
+ m_url.m_pathEnd = m_url.m_pathAfterLastSlash;
+ m_url.m_queryEnd = m_url.m_pathAfterLastSlash;
+ m_url.m_fragmentEnd = m_url.m_pathAfterLastSlash;
</ins><span class="cx"> break;
</span><span class="cx"> case State::FileSlash:
</span><span class="cx"> LOG_FINAL_STATE("FileSlash");
</span><ins>+ m_buffer.append("//");
+ m_url.m_userStart = m_buffer.length() - 1;
+ m_url.m_userEnd = m_url.m_userStart;
+ m_url.m_passwordEnd = m_url.m_userStart;
+ m_url.m_hostEnd = m_url.m_userStart;
+ m_url.m_portEnd = m_url.m_userStart;
+ m_url.m_pathAfterLastSlash = m_url.m_userStart + 1;
+ m_url.m_pathEnd = m_url.m_pathAfterLastSlash;
+ m_url.m_queryEnd = m_url.m_pathAfterLastSlash;
+ m_url.m_fragmentEnd = m_url.m_pathAfterLastSlash;
</ins><span class="cx"> break;
</span><span class="cx"> case State::FileHost:
</span><span class="cx"> LOG_FINAL_STATE("FileHost");
</span><ins>+ if (authorityOrHostBegin == c) {
+ m_buffer.append('/');
+ m_url.m_userStart = m_buffer.length() - 1;
+ m_url.m_userEnd = m_url.m_userStart;
+ m_url.m_passwordEnd = m_url.m_userStart;
+ m_url.m_hostEnd = m_url.m_userStart;
+ m_url.m_portEnd = m_url.m_userStart;
+ m_url.m_pathAfterLastSlash = m_url.m_userStart + 1;
+ m_url.m_pathEnd = m_url.m_pathAfterLastSlash;
+ m_url.m_queryEnd = m_url.m_pathAfterLastSlash;
+ m_url.m_fragmentEnd = m_url.m_pathAfterLastSlash;
+ break;
+ }
+
+ m_url.m_pathAfterLastSlash = m_url.m_userStart + 1;
+ m_url.m_pathEnd = m_url.m_pathAfterLastSlash;
+ m_url.m_queryEnd = m_url.m_pathAfterLastSlash;
+ m_url.m_fragmentEnd = m_url.m_pathAfterLastSlash;
+ if (!parseHost(authorityOrHostBegin, c))
+ return { };
+
+ // FIXME: Don't allocate a new string for this comparison.
+ if (m_buffer.toString().substring(m_url.m_passwordEnd) == "localhost") {
+ m_buffer.resize(m_url.m_passwordEnd);
+ m_url.m_hostEnd = m_buffer.length();
+ m_url.m_portEnd = m_url.m_hostEnd;
+ m_buffer.append('/');
+ m_url.m_pathAfterLastSlash = m_url.m_hostEnd + 1;
+ m_url.m_pathEnd = m_url.m_pathAfterLastSlash;
+ m_url.m_queryEnd = m_url.m_pathAfterLastSlash;
+ m_url.m_fragmentEnd = m_url.m_pathAfterLastSlash;
+ }
</ins><span class="cx"> break;
</span><span class="cx"> case State::PathStart:
</span><span class="cx"> LOG_FINAL_STATE("PathStart");
</span><span class="lines">@@ -923,10 +1131,10 @@
</span><span class="cx"> return address;
</span><span class="cx"> }
</span><span class="cx">
</span><del>-void URLParser::parseHost(StringView::CodePoints::Iterator& iterator, const StringView::CodePoints::Iterator& end)
</del><ins>+bool URLParser::parseHost(StringView::CodePoints::Iterator& iterator, const StringView::CodePoints::Iterator& end)
</ins><span class="cx"> {
</span><span class="cx"> if (iterator == end)
</span><del>- return;
</del><ins>+ return false;
</ins><span class="cx"> if (*iterator == '[') {
</span><span class="cx"> ++iterator;
</span><span class="cx"> auto ipv6End = iterator;
</span><span class="lines">@@ -937,7 +1145,7 @@
</span><span class="cx"> m_url.m_hostEnd = m_buffer.length();
</span><span class="cx"> // FIXME: Handle the port correctly.
</span><span class="cx"> m_url.m_portEnd = m_buffer.length();
</span><del>- return;
</del><ins>+ return true;
</ins><span class="cx"> }
</span><span class="cx"> }
</span><span class="cx"> if (auto address = parseIPv4Host(iterator, end)) {
</span><span class="lines">@@ -945,7 +1153,7 @@
</span><span class="cx"> m_url.m_hostEnd = m_buffer.length();
</span><span class="cx"> // FIXME: Handle the port correctly.
</span><span class="cx"> m_url.m_portEnd = m_buffer.length();
</span><del>- return;
</del><ins>+ return true;
</ins><span class="cx"> }
</span><span class="cx"> for (; iterator != end; ++iterator) {
</span><span class="cx"> if (*iterator == ':') {
</span><span class="lines">@@ -955,12 +1163,13 @@
</span><span class="cx"> for (; iterator != end; ++iterator)
</span><span class="cx"> m_buffer.append(*iterator);
</span><span class="cx"> m_url.m_portEnd = m_buffer.length();
</span><del>- return;
</del><ins>+ return true;
</ins><span class="cx"> }
</span><span class="cx"> m_buffer.append(*iterator);
</span><span class="cx"> }
</span><span class="cx"> m_url.m_hostEnd = m_buffer.length();
</span><span class="cx"> m_url.m_portEnd = m_url.m_hostEnd;
</span><ins>+ return true;
</ins><span class="cx"> }
</span><span class="cx">
</span><span class="cx"> bool URLParser::allValuesEqual(const URL& a, const URL& b)
</span></span></pre></div>
<a id="trunkSourceWebCoreplatformURLParserh"></a>
<div class="modfile"><h4>Modified: trunk/Source/WebCore/platform/URLParser.h (205389 => 205390)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/Source/WebCore/platform/URLParser.h        2016-09-03 00:22:27 UTC (rev 205389)
+++ trunk/Source/WebCore/platform/URLParser.h        2016-09-03 00:32:49 UTC (rev 205390)
</span><span class="lines">@@ -43,7 +43,7 @@
</span><span class="cx"> URL m_url;
</span><span class="cx"> StringBuilder m_buffer;
</span><span class="cx"> void parseAuthority(StringView::CodePoints::Iterator&, const StringView::CodePoints::Iterator& end);
</span><del>- void parseHost(StringView::CodePoints::Iterator&, const StringView::CodePoints::Iterator& end);
</del><ins>+ bool parseHost(StringView::CodePoints::Iterator&, const StringView::CodePoints::Iterator& end);
</ins><span class="cx">
</span><span class="cx"> enum class URLPart;
</span><span class="cx"> void copyURLPartsUntil(const URL& base, URLPart);
</span></span></pre></div>
<a id="trunkToolsChangeLog"></a>
<div class="modfile"><h4>Modified: trunk/Tools/ChangeLog (205389 => 205390)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/Tools/ChangeLog        2016-09-03 00:22:27 UTC (rev 205389)
+++ trunk/Tools/ChangeLog        2016-09-03 00:32:49 UTC (rev 205390)
</span><span class="lines">@@ -1,3 +1,14 @@
</span><ins>+2016-09-02 Alex Christensen <achristensen@webkit.org>
+
+ URLParser should parse file URLs
+ https://bugs.webkit.org/show_bug.cgi?id=161556
+
+ Reviewed by Tim Horton.
+
+ * TestWebKitAPI/Tests/WebCore/URLParser.cpp:
+ (TestWebKitAPI::TEST_F):
+ (TestWebKitAPI::checkURLDifferences):
+
</ins><span class="cx"> 2016-09-01 Michael Saboff <msaboff@apple.com>
</span><span class="cx">
</span><span class="cx"> Import Chakra tests to JSC
</span></span></pre></div>
<a id="trunkToolsTestWebKitAPITestsWebCoreURLParsercpp"></a>
<div class="modfile"><h4>Modified: trunk/Tools/TestWebKitAPI/Tests/WebCore/URLParser.cpp (205389 => 205390)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/Tools/TestWebKitAPI/Tests/WebCore/URLParser.cpp        2016-09-03 00:22:27 UTC (rev 205389)
+++ trunk/Tools/TestWebKitAPI/Tests/WebCore/URLParser.cpp        2016-09-03 00:32:49 UTC (rev 205390)
</span><span class="lines">@@ -84,7 +84,7 @@
</span><span class="cx"> EXPECT_TRUE(URLParser::allValuesEqual(url, oldURL));
</span><span class="cx"> }
</span><span class="cx">
</span><del>-TEST_F(URLParserTest, Parse)
</del><ins>+TEST_F(URLParserTest, Basic)
</ins><span class="cx"> {
</span><span class="cx"> checkURL("http://user:pass@webkit.org:123/path?query#fragment", {"http", "user", "pass", "webkit.org", 123, "/path", "query", "fragment", "http://user:pass@webkit.org:123/path?query#fragment"});
</span><span class="cx"> checkURL("http://user:pass@webkit.org:123/path?query", {"http", "user", "pass", "webkit.org", 123, "/path", "query", "", "http://user:pass@webkit.org:123/path?query"});
</span><span class="lines">@@ -139,6 +139,32 @@
</span><span class="cx"> checkURL("http://example.com/path1/path2/..?query", {"http", "", "", "example.com", 0, "/path1/", "query", "", "http://example.com/path1/?query"});
</span><span class="cx"> checkURL("http://example.com/path1/path2/.#fragment", {"http", "", "", "example.com", 0, "/path1/path2/", "", "fragment", "http://example.com/path1/path2/#fragment"});
</span><span class="cx"> checkURL("http://example.com/path1/path2/..#fragment", {"http", "", "", "example.com", 0, "/path1/", "", "fragment", "http://example.com/path1/#fragment"});
</span><ins>+
+ checkURL("file:", {"file", "", "", "", 0, "/", "", "", "file:///"});
+ checkURL("file:/", {"file", "", "", "", 0, "/", "", "", "file:///"});
+ checkURL("file://", {"file", "", "", "", 0, "/", "", "", "file:///"});
+ checkURL("file:///", {"file", "", "", "", 0, "/", "", "", "file:///"});
+ checkURL("file:////", {"file", "", "", "", 0, "//", "", "", "file:////"}); // This matches Firefox and URL::parse which I believe are correct, but not Chrome.
+ checkURL("file:/path", {"file", "", "", "", 0, "/path", "", "", "file:///path"});
+ checkURL("file://host/path", {"file", "", "", "host", 0, "/path", "", "", "file://host/path"});
+ checkURL("file:///path", {"file", "", "", "", 0, "/path", "", "", "file:///path"});
+ checkURL("file:////path", {"file", "", "", "", 0, "//path", "", "", "file:////path"});
+ checkURL("file://localhost/path", {"file", "", "", "", 0, "/path", "", "", "file:///path"});
+ checkURL("file://localhost/", {"file", "", "", "", 0, "/", "", "", "file:///"});
+ checkURL("file://localhost", {"file", "", "", "", 0, "/", "", "", "file:///"});
+ // FIXME: check file://lOcAlHoSt etc.
+ checkURL("file:?query", {"file", "", "", "", 0, "/", "query", "", "file:///?query"});
+ checkURL("file:#fragment", {"file", "", "", "", 0, "/", "", "fragment", "file:///#fragment"});
+ checkURL("file:?query#fragment", {"file", "", "", "", 0, "/", "query", "fragment", "file:///?query#fragment"});
+ checkURL("file:#fragment?notquery", {"file", "", "", "", 0, "/", "", "fragment?notquery", "file:///#fragment?notquery"});
+ checkURL("file:/?query", {"file", "", "", "", 0, "/", "query", "", "file:///?query"});
+ checkURL("file:/#fragment", {"file", "", "", "", 0, "/", "", "fragment", "file:///#fragment"});
+ checkURL("file://?query", {"file", "", "", "", 0, "/", "query", "", "file:///?query"});
+ checkURL("file://#fragment", {"file", "", "", "", 0, "/", "", "fragment", "file:///#fragment"});
+ checkURL("file:///?query", {"file", "", "", "", 0, "/", "query", "", "file:///?query"});
+ checkURL("file:///#fragment", {"file", "", "", "", 0, "/", "", "fragment", "file:///#fragment"});
+ checkURL("file:////?query", {"file", "", "", "", 0, "//", "query", "", "file:////?query"});
+ checkURL("file:////#fragment", {"file", "", "", "", 0, "//", "", "fragment", "file:////#fragment"});
</ins><span class="cx"> }
</span><span class="cx">
</span><span class="cx"> static void checkRelativeURL(const String& urlString, const String& baseURLString, const ExpectedParts& parts)
</span><span class="lines">@@ -296,6 +322,9 @@
</span><span class="cx"> checkURLDifferences("http://example.com/path1/path2/%2e%2e#fragment",
</span><span class="cx"> {"http", "", "", "example.com", 0, "/path1/", "", "fragment", "http://example.com/path1/#fragment"},
</span><span class="cx"> {"http", "", "", "example.com", 0, "/path1/path2/%2e%2e", "", "fragment", "http://example.com/path1/path2/%2e%2e#fragment"});
</span><ins>+ checkURLDifferences("file://[0:a:0:0:b:c:0:0]/path",
+ {"file", "", "", "[0:a::b:c:0:0]", 0, "/path", "", "", "file://[0:a::b:c:0:0]/path"},
+ {"file", "", "", "[0:a:0:0:b:c:0:0]", 0, "/path", "", "", "file://[0:a:0:0:b:c:0:0]/path"});
</ins><span class="cx">
</span><span class="cx"> // FIXME: This behavior ought to be specified in the standard.
</span><span class="cx"> // With the existing URL::parse, WebKit returns "https:/", Firefox returns "https:///", and Chrome throws an error.
</span><span class="lines">@@ -302,6 +331,13 @@
</span><span class="cx"> checkRelativeURLDifferences("//", "https://www.webkit.org/path",
</span><span class="cx"> {"https", "", "", "", 0, "", "", "", "https://"},
</span><span class="cx"> {"https", "", "", "", 0, "/", "", "", "https:/"});
</span><ins>+
+ // This behavior matches Chrome and Firefox, but not WebKit using URL::parse.
+ // The behavior of URL::parse is clearly wrong because reparsing file://path would make path the host.
+ // The spec is unclear.
+ checkURLDifferences("file:path",
+ {"file", "", "", "", 0, "/path", "", "", "file:///path"},
+ {"file", "", "", "", 0, "path", "", "", "file://path"});
</ins><span class="cx"> }
</span><span class="cx">
</span><span class="cx"> static void shouldFail(const String& urlString)
</span></span></pre>
</div>
</div>
</body>
</html>