Title: [205097] trunk
Revision
205097
Author
[email protected]
Date
2016-08-27 22:55:17 -0700 (Sat, 27 Aug 2016)

Log Message

URLParser should parse relative URLs
https://bugs.webkit.org/show_bug.cgi?id=161282

Patch by Alex Christensen <[email protected]> on 2016-08-27
Reviewed by Darin Adler.

Source/WebCore:

Partially covered by new API tests, but once the parser is complete enough we can
use the url web platform tests to more fully test this.  It's still a work in
progress only used by tests.

* platform/URLParser.cpp:
(WebCore::URLParser::urlLengthUntilPart):
(WebCore::URLParser::copyURLPartsUntil):
Added some helper functions to reduce redundant code.  When parsing relative URLs,
we often want to copy large parts of the base URL, but the stopping point differs.
(WebCore::URLParser::parse):
The parser now returns a URL instead of an Optional<URL> because a URL has a m_isValid which behaves like Optional.
* platform/URLParser.h:
(WebCore::URLParser::parse):

Source/WTF:

* wtf/text/StringView.h:
Use a std::reference_wrapper for the StringView& to make it reassignable so we can add an operator=.

Tools:

* TestWebKitAPI/Tests/WTF/StringView.cpp:
(TestWebKitAPI::TEST):
Added some tests for the new operator=.
Test saving iterators, restoring iterators, and even assigning iterators to new CodePoints objects.
Using the same iterator to iterate multiple objects is bad practice, but it's possible and now tested.
* TestWebKitAPI/Tests/WebCore/URLParser.cpp:
(TestWebKitAPI::checkURL):
(TestWebKitAPI::TEST_F):
(TestWebKitAPI::checkRelativeURL):
(TestWebKitAPI::checkURLDifferences):
(TestWebKitAPI::shouldFail):
Add some relative URL tests.

Modified Paths

Diff

Modified: trunk/Source/WTF/ChangeLog (205096 => 205097)


--- trunk/Source/WTF/ChangeLog	2016-08-28 05:29:05 UTC (rev 205096)
+++ trunk/Source/WTF/ChangeLog	2016-08-28 05:55:17 UTC (rev 205097)
@@ -1,3 +1,13 @@
+2016-08-27  Alex Christensen  <[email protected]>
+
+        URLParser should parse relative URLs
+        https://bugs.webkit.org/show_bug.cgi?id=161282
+
+        Reviewed by Darin Adler.
+
+        * wtf/text/StringView.h:
+        Use a std::reference_wrapper for the StringView& to make it reassignable so we can add an operator=.
+
 2016-08-26  JF Bastien  <[email protected]>
 
         bitwise_cast uses inactive member of union

Modified: trunk/Source/WTF/wtf/text/StringView.h (205096 => 205097)


--- trunk/Source/WTF/wtf/text/StringView.h	2016-08-28 05:29:05 UTC (rev 205096)
+++ trunk/Source/WTF/wtf/text/StringView.h	2016-08-28 05:55:17 UTC (rev 205097)
@@ -656,9 +656,10 @@
 
     bool operator==(const Iterator&) const;
     bool operator!=(const Iterator&) const;
+    Iterator& operator=(const Iterator&);
 
 private:
-    const StringView& m_stringView;
+    std::reference_wrapper<const StringView> m_stringView;
     Optional<unsigned> m_nextCodePointOffset;
     UChar32 m_codePoint;
 };
@@ -723,18 +724,26 @@
 inline auto StringView::CodePoints::Iterator::operator++() -> Iterator&
 {
     ASSERT(m_nextCodePointOffset);
-    if (m_nextCodePointOffset.value() == m_stringView.length()) {
+    if (m_nextCodePointOffset.value() == m_stringView.get().length()) {
         m_nextCodePointOffset = Nullopt;
         return *this;
     }
-    if (m_stringView.is8Bit())
-        m_codePoint = m_stringView.characters8()[m_nextCodePointOffset.value()++];
+    if (m_stringView.get().is8Bit())
+        m_codePoint = m_stringView.get().characters8()[m_nextCodePointOffset.value()++];
     else
-        U16_NEXT(m_stringView.characters16(), m_nextCodePointOffset.value(), m_stringView.length(), m_codePoint);
-    ASSERT(m_nextCodePointOffset.value() <= m_stringView.length());
+        U16_NEXT(m_stringView.get().characters16(), m_nextCodePointOffset.value(), m_stringView.get().length(), m_codePoint);
+    ASSERT(m_nextCodePointOffset.value() <= m_stringView.get().length());
     return *this;
 }
 
+inline auto StringView::CodePoints::Iterator::operator=(const Iterator& other) -> Iterator&
+{
+    m_stringView = other.m_stringView;
+    m_nextCodePointOffset = other.m_nextCodePointOffset;
+    m_codePoint = other.m_codePoint;
+    return *this;
+}
+
 inline UChar32 StringView::CodePoints::Iterator::operator*() const
 {
     ASSERT(m_nextCodePointOffset);
@@ -743,7 +752,7 @@
 
 inline bool StringView::CodePoints::Iterator::operator==(const Iterator& other) const
 {
-    ASSERT(&m_stringView == &other.m_stringView);
+    ASSERT(&m_stringView.get() == &other.m_stringView.get());
     return m_nextCodePointOffset == other.m_nextCodePointOffset;
 }
 

Modified: trunk/Source/WebCore/ChangeLog (205096 => 205097)


--- trunk/Source/WebCore/ChangeLog	2016-08-28 05:29:05 UTC (rev 205096)
+++ trunk/Source/WebCore/ChangeLog	2016-08-28 05:55:17 UTC (rev 205097)
@@ -1,3 +1,24 @@
+2016-08-27  Alex Christensen  <[email protected]>
+
+        URLParser should parse relative URLs
+        https://bugs.webkit.org/show_bug.cgi?id=161282
+
+        Reviewed by Darin Adler.
+
+        Partially covered by new API tests, but once the parser is complete enough we can
+        use the url web platform tests to more fully test this.  It's still a work in
+        progress only used by tests.
+
+        * platform/URLParser.cpp:
+        (WebCore::URLParser::urlLengthUntilPart):
+        (WebCore::URLParser::copyURLPartsUntil):
+        Added some helper functions to reduce redundant code.  When parsing relative URLs,
+        we often want to copy large parts of the base URL, but the stopping point differs.
+        (WebCore::URLParser::parse):
+        The parser now returns a URL instead of an Optional<URL> because a URL has a m_isValid which behaves like Optional.
+        * platform/URLParser.h:
+        (WebCore::URLParser::parse):
+
 2016-08-27  Chris Dumez  <[email protected]>
 
         Update generated bindings to throw a SecurityError when denying cross-origin access to properties

Modified: trunk/Source/WebCore/platform/URLParser.cpp (205096 => 205097)


--- trunk/Source/WebCore/platform/URLParser.cpp	2016-08-28 05:29:05 UTC (rev 205096)
+++ trunk/Source/WebCore/platform/URLParser.cpp	2016-08-28 05:55:17 UTC (rev 205097)
@@ -48,8 +48,88 @@
         || scheme == "wss";
 }
 
-Optional<URL> URLParser::parse(const String& input, const URL& base, const TextEncoding&)
+enum class URLParser::URLPart {
+    SchemeEnd,
+    UserStart,
+    UserEnd,
+    PasswordEnd,
+    HostEnd,
+    PortEnd,
+    PathAfterLastSlash,
+    PathEnd,
+    QueryEnd,
+    FragmentEnd,
+};
+
+size_t URLParser::urlLengthUntilPart(const URL& url, URLPart part)
 {
+    switch (part) {
+    case URLPart::FragmentEnd:
+        return url.m_fragmentEnd;
+    case URLPart::QueryEnd:
+        return url.m_queryEnd;
+    case URLPart::PathEnd:
+        return url.m_pathEnd;
+    case URLPart::PathAfterLastSlash:
+        return url.m_pathAfterLastSlash;
+    case URLPart::PortEnd:
+        return url.m_portEnd;
+    case URLPart::HostEnd:
+        return url.m_hostEnd;
+    case URLPart::PasswordEnd:
+        return url.m_passwordEnd;
+    case URLPart::UserEnd:
+        return url.m_userEnd;
+    case URLPart::UserStart:
+        return url.m_userStart;
+    case URLPart::SchemeEnd:
+        return url.m_schemeEnd;
+    }
+    ASSERT_NOT_REACHED();
+    return 0;
+}
+    
+void URLParser::copyURLPartsUntil(const URL& base, URLPart part)
+{
+    m_buffer.clear();
+    m_buffer.append(base.m_string.substring(0, urlLengthUntilPart(base, part)));
+    switch (part) {
+    case URLPart::FragmentEnd:
+        m_url.m_fragmentEnd = base.m_fragmentEnd;
+        FALLTHROUGH;
+    case URLPart::QueryEnd:
+        m_url.m_queryEnd = base.m_queryEnd;
+        FALLTHROUGH;
+    case URLPart::PathEnd:
+        m_url.m_pathEnd = base.m_pathEnd;
+        FALLTHROUGH;
+    case URLPart::PathAfterLastSlash:
+        m_url.m_pathAfterLastSlash = base.m_pathAfterLastSlash;
+        FALLTHROUGH;
+    case URLPart::PortEnd:
+        m_url.m_portEnd = base.m_portEnd;
+        FALLTHROUGH;
+    case URLPart::HostEnd:
+        m_url.m_hostEnd = base.m_hostEnd;
+        FALLTHROUGH;
+    case URLPart::PasswordEnd:
+        m_url.m_passwordEnd = base.m_passwordEnd;
+        FALLTHROUGH;
+    case URLPart::UserEnd:
+        m_url.m_userEnd = base.m_userEnd;
+        FALLTHROUGH;
+    case URLPart::UserStart:
+        m_url.m_userStart = base.m_userStart;
+        FALLTHROUGH;
+    case URLPart::SchemeEnd:
+        m_url.m_isValid = base.m_isValid;
+        m_url.m_protocolIsInHTTPFamily = base.m_protocolIsInHTTPFamily;
+        m_url.m_schemeEnd = base.m_schemeEnd;
+    }
+}
+    
+URL URLParser::parse(const String& input, const URL& base, const TextEncoding&)
+{
     m_url = { };
     m_buffer.clear();
     m_authorityOrHostBuffer.clear();
@@ -98,10 +178,10 @@
             LOG_STATE("SchemeStart");
             if (isASCIIAlpha(*c)) {
                 m_buffer.append(toASCIILower(*c));
+                ++c;
                 state = State::Scheme;
             } else
                 state = State::NoScheme;
-            ++c;
             break;
         case State::Scheme:
             LOG_STATE("Scheme");
@@ -124,15 +204,20 @@
             } else {
                 m_buffer.clear();
                 state = State::NoScheme;
-                // FIXME: Find a way to start over here.
-                notImplemented();
-                continue;
+                c = codePoints.begin();
+                break;
             }
             ++c;
+            if (c == end) {
+                m_buffer.clear();
+                state = State::NoScheme;
+                c = codePoints.begin();
+            }
             break;
         case State::SchemeEndCheckForSlashes:
             LOG_STATE("SchemeEndCheckForSlashes");
             if (*c == '/') {
+                m_buffer.append('/');
                 state = State::PathOrAuthority;
                 ++c;
             } else
@@ -140,60 +225,101 @@
             break;
         case State::NoScheme:
             LOG_STATE("NoScheme");
-            notImplemented();
-            ++c;
+            if (base.isNull()) {
+                if (*c == '#') {
+                    copyURLPartsUntil(base, URLPart::QueryEnd);
+                    state = State::Fragment;
+                    ++c;
+                } else
+                    return { };
+            } else if (base.protocol() == "file")
+                state = State::File;
+            else
+                state = State::Relative;
             break;
         case State::SpecialRelativeOrAuthority:
             LOG_STATE("SpecialRelativeOrAuthority");
             if (*c == '/') {
+                m_buffer.append('/');
                 ++c;
+                while (c != end && isTabOrNewline(*c))
+                    ++c;
                 if (c == end)
-                    return Nullopt;
+                    return { };
                 if (*c == '/') {
+                    m_buffer.append('/');
                     state = State::SpecialAuthorityIgnoreSlashes;
                     ++c;
-                } else
-                    notImplemented();
+                }
             } else
                 state = State::Relative;
             break;
         case State::PathOrAuthority:
             LOG_STATE("PathOrAuthority");
-            notImplemented();
-            ++c;
+            if (*c == '/') {
+                state = State::AuthorityOrHost;
+                ++c;
+            } else
+                state = State::Path;
             break;
         case State::Relative:
             LOG_STATE("Relative");
-            notImplemented();
-            ++c;
+            switch (*c) {
+            case '/':
+            case '\\':
+                state = State::RelativeSlash;
+                ++c;
+                break;
+            case '?':
+                copyURLPartsUntil(base, URLPart::PathEnd);
+                state = State::Query;
+                ++c;
+                break;
+            case '#':
+                copyURLPartsUntil(base, URLPart::QueryEnd);
+                state = State::Fragment;
+                ++c;
+                break;
+            default:
+                copyURLPartsUntil(base, URLPart::PathAfterLastSlash);
+                state = State::Path;
+                break;
+            }
             break;
         case State::RelativeSlash:
             LOG_STATE("RelativeSlash");
-            notImplemented();
-            ++c;
+            if (*c == '/' || *c == '\\') {
+                ++c;
+                state = State::SpecialAuthorityIgnoreSlashes;
+            } else {
+                copyURLPartsUntil(base, URLPart::PortEnd);
+                m_buffer.append('/');
+                m_url.m_pathAfterLastSlash = base.m_portEnd + 1;
+                state = State::Path;
+            }
             break;
         case State::SpecialAuthoritySlashes:
             LOG_STATE("SpecialAuthoritySlashes");
             if (*c == '/') {
                 ++c;
+                while (c != end && isTabOrNewline(*c))
+                    ++c;
                 if (c == end)
-                    return Nullopt;
+                    return { };
                 m_buffer.append('/');
                 if (*c == '/') {
                     m_buffer.append('/');
-                    state = State::SpecialAuthorityIgnoreSlashes;
                     ++c;
-                    break;
                 }
-                notImplemented();
-            } else
-                notImplemented();
-            ++c;
+            }
+            state = State::SpecialAuthorityIgnoreSlashes;
             break;
         case State::SpecialAuthorityIgnoreSlashes:
             LOG_STATE("SpecialAuthorityIgnoreSlashes");
-            if (*c == '/' || *c == '\\')
+            if (*c == '/' || *c == '\\') {
+                m_buffer.append('/');
                 ++c;
+            }
             m_url.m_userStart = m_buffer.length();
             state = State::AuthorityOrHost;
             break;
@@ -203,6 +329,8 @@
                 authorityEndReached();
                 state = State::Host;
             } else if (*c == '/' || *c == '?' || *c == '#') {
+                m_url.m_userEnd = m_buffer.length();
+                m_url.m_passwordEnd = m_url.m_userEnd;
                 hostEndReached();
                 state = State::Path;
                 break;
@@ -215,7 +343,7 @@
             if (*c == '/' || *c == '?' || *c == '#') {
                 hostEndReached();
                 state = State::Path;
-                continue;
+                break;
             }
             m_authorityOrHostBuffer.append(*c);
             ++c;
@@ -237,8 +365,10 @@
             break;
         case State::PathStart:
             LOG_STATE("PathStart");
+            if (*c != '/' && *c != '\\')
+                ++c;
             state = State::Path;
-            continue;
+            break;
         case State::Path:
             LOG_STATE("Path");
             if (*c == '/') {
@@ -245,12 +375,16 @@
                 m_buffer.append('/');
                 m_url.m_pathAfterLastSlash = m_buffer.length();
                 ++c;
+                while (c != end && isTabOrNewline(*c))
+                    ++c;
                 if (c == end)
                     break;
                 if (*c == '.') {
                     ++c;
+                    while (c != end && isTabOrNewline(*c))
+                        ++c;
                     if (c == end)
-                        return Nullopt;
+                        return { };
                     if (*c == '.')
                         notImplemented();
                     notImplemented();
@@ -258,11 +392,11 @@
             } else if (*c == '?') {
                 m_url.m_pathEnd = m_buffer.length();
                 state = State::Query;
-                continue;
+                break;
             } else if (*c == '#') {
                 m_url.m_pathEnd = m_buffer.length();
                 state = State::Fragment;
-                continue;
+                break;
             }
             // FIXME: Percent encode c
             m_buffer.append(*c);
@@ -278,7 +412,7 @@
             if (*c == '#') {
                 m_url.m_queryEnd = m_buffer.length();
                 state = State::Fragment;
-                continue;
+                break;
             }
             m_buffer.append(*c);
             ++c;
@@ -294,8 +428,8 @@
     switch (state) {
     case State::SchemeStart:
         LOG_FINAL_STATE("SchemeStart");
-        return Nullopt;
-        break;
+        ASSERT_NOT_REACHED();
+        return { };
     case State::Scheme:
         LOG_FINAL_STATE("Scheme");
         break;
@@ -313,6 +447,7 @@
         break;
     case State::Relative:
         LOG_FINAL_STATE("Relative");
+        copyURLPartsUntil(base, URLPart::FragmentEnd);
         break;
     case State::RelativeSlash:
         LOG_FINAL_STATE("RelativeSlash");

Modified: trunk/Source/WebCore/platform/URLParser.h (205096 => 205097)


--- trunk/Source/WebCore/platform/URLParser.h	2016-08-28 05:29:05 UTC (rev 205096)
+++ trunk/Source/WebCore/platform/URLParser.h	2016-08-28 05:55:17 UTC (rev 205097)
@@ -31,17 +31,21 @@
 #include <wtf/text/StringBuilder.h>
 
 namespace WebCore {
-    
+
 class URLParser {
 public:
-    WEBCORE_EXPORT Optional<URL> parse(const String&, const URL& = { }, const TextEncoding& = UTF8Encoding());
+    WEBCORE_EXPORT URL parse(const String&, const URL& = { }, const TextEncoding& = UTF8Encoding());
     WEBCORE_EXPORT static bool allValuesEqual(const URL&, const URL&);
 private:
     URL m_url;
     StringBuilder m_buffer;
-    StringBuilder m_authorityOrHostBuffer;
+    StringBuilder m_authorityOrHostBuffer; // FIXME: Save the iterator at the end of the scheme instead of using a second buffer.
     void authorityEndReached();
     void hostEndReached();
+
+    enum class URLPart;
+    void copyURLPartsUntil(const URL& base, URLPart);
+    static size_t urlLengthUntilPart(const URL&, URLPart);
 };
 
 }

Modified: trunk/Tools/ChangeLog (205096 => 205097)


--- trunk/Tools/ChangeLog	2016-08-28 05:29:05 UTC (rev 205096)
+++ trunk/Tools/ChangeLog	2016-08-28 05:55:17 UTC (rev 205097)
@@ -1,3 +1,23 @@
+2016-08-27  Alex Christensen  <[email protected]>
+
+        URLParser should parse relative URLs
+        https://bugs.webkit.org/show_bug.cgi?id=161282
+
+        Reviewed by Darin Adler.
+
+        * TestWebKitAPI/Tests/WTF/StringView.cpp:
+        (TestWebKitAPI::TEST):
+        Added some tests for the new operator=.
+        Test saving iterators, restoring iterators, and even assigning iterators to new CodePoints objects.
+        Using the same iterator to iterate multiple objects is bad practice, but it's possible and now tested.
+        * TestWebKitAPI/Tests/WebCore/URLParser.cpp:
+        (TestWebKitAPI::checkURL):
+        (TestWebKitAPI::TEST_F):
+        (TestWebKitAPI::checkRelativeURL):
+        (TestWebKitAPI::checkURLDifferences):
+        (TestWebKitAPI::shouldFail):
+        Add some relative URL tests.
+
 2016-08-27  Jonathan Bedard  <[email protected]>
 
         WTR needs an implementation of setAutomaticLinkDetectionEnabled

Modified: trunk/Tools/TestWebKitAPI/Tests/WTF/StringView.cpp (205096 => 205097)


--- trunk/Tools/TestWebKitAPI/Tests/WTF/StringView.cpp	2016-08-28 05:29:05 UTC (rev 205096)
+++ trunk/Tools/TestWebKitAPI/Tests/WTF/StringView.cpp	2016-08-28 05:55:17 UTC (rev 205097)
@@ -129,6 +129,19 @@
     ++codePointsIterator;
     ++codePointsIterator;
     EXPECT_EQ(*codePointsIterator, 'l');
+    auto savedIterator = codePointsIterator;
+    codePointsIterator = codePoints.begin();
+    EXPECT_EQ(*codePointsIterator, 'h');
+    codePointsIterator = savedIterator;
+    EXPECT_EQ(*codePointsIterator, 'l');
+    String webkit("webkit");
+    auto webkitCodePoints = StringView(webkit).codePoints();
+    codePointsIterator = webkitCodePoints.begin();
+    ++codePointsIterator;
+    ++codePointsIterator;
+    EXPECT_EQ(*codePointsIterator, 'b');
+    while (codePointsIterator != webkitCodePoints.end())
+        ++codePointsIterator;
 
     EXPECT_TRUE(compareLoopIterations(heloView.codePoints(), {'h', 'e', 'l', 'o'}));
     EXPECT_TRUE(compareLoopIterations(heloView.codeUnits(), {'h', 'e', 'l', 'o'}));

Modified: trunk/Tools/TestWebKitAPI/Tests/WebCore/URLParser.cpp (205096 => 205097)


--- trunk/Tools/TestWebKitAPI/Tests/WebCore/URLParser.cpp	2016-08-28 05:29:05 UTC (rev 205096)
+++ trunk/Tools/TestWebKitAPI/Tests/WebCore/URLParser.cpp	2016-08-28 05:55:17 UTC (rev 205097)
@@ -55,15 +55,15 @@
 {
     URLParser parser;
     auto url = ""
-    EXPECT_TRUE(eq(parts.protocol, url->protocol()));
-    EXPECT_TRUE(eq(parts.user, url->user()));
-    EXPECT_TRUE(eq(parts.password, url->pass()));
-    EXPECT_TRUE(eq(parts.host, url->host()));
-    EXPECT_EQ(parts.port, url->port());
-    EXPECT_TRUE(eq(parts.path, url->path()));
-    EXPECT_TRUE(eq(parts.query, url->query()));
-    EXPECT_TRUE(eq(parts.fragment, url->fragmentIdentifier()));
-    EXPECT_TRUE(eq(parts.string, url->string()));
+    EXPECT_TRUE(eq(parts.protocol, url.protocol()));
+    EXPECT_TRUE(eq(parts.user, url.user()));
+    EXPECT_TRUE(eq(parts.password, url.pass()));
+    EXPECT_TRUE(eq(parts.host, url.host()));
+    EXPECT_EQ(parts.port, url.port());
+    EXPECT_TRUE(eq(parts.path, url.path()));
+    EXPECT_TRUE(eq(parts.query, url.query()));
+    EXPECT_TRUE(eq(parts.fragment, url.fragmentIdentifier()));
+    EXPECT_TRUE(eq(parts.string, url.string()));
     
     auto oldURL = URL(URL(), urlString);
     EXPECT_TRUE(eq(parts.protocol, oldURL.protocol()));
@@ -76,7 +76,7 @@
     EXPECT_TRUE(eq(parts.fragment, oldURL.fragmentIdentifier()));
     EXPECT_TRUE(eq(parts.string, oldURL.string()));
     
-    EXPECT_TRUE(URLParser::allValuesEqual(url.value(), oldURL));
+    EXPECT_TRUE(URLParser::allValuesEqual(url, oldURL));
 }
 
 TEST_F(URLParserTest, Parse)
@@ -89,21 +89,62 @@
     checkURL("http://user:[email protected]", {"http", "user", "pass", "webkit.org", 0, "/", "", "", "http://user:[email protected]/"});
     checkURL("http://webkit.org", {"http", "", "", "webkit.org", 0, "/", "", "", "http://webkit.org/"});
     checkURL("http://127.0.0.1", {"http", "", "", "127.0.0.1", 0, "/", "", "", "http://127.0.0.1/"});
+    checkURL("http://webkit.org/", {"http", "", "", "webkit.org", 0, "/", "", "", "http://webkit.org/"});
+    checkURL("http://webkit.org/path1/path2/index.html", {"http", "", "", "webkit.org", 0, "/path1/path2/index.html", "", "", "http://webkit.org/path1/path2/index.html"});
+
 }
 
+static void checkRelativeURL(const String& urlString, const String& baseURLString, const ExpectedParts& parts)
+{
+    URLParser baseParser;
+    auto base = baseParser.parse(baseURLString);
+
+    URLParser parser;
+    auto url = "" base);
+    EXPECT_TRUE(eq(parts.protocol, url.protocol()));
+    EXPECT_TRUE(eq(parts.user, url.user()));
+    EXPECT_TRUE(eq(parts.password, url.pass()));
+    EXPECT_TRUE(eq(parts.host, url.host()));
+    EXPECT_EQ(parts.port, url.port());
+    EXPECT_TRUE(eq(parts.path, url.path()));
+    EXPECT_TRUE(eq(parts.query, url.query()));
+    EXPECT_TRUE(eq(parts.fragment, url.fragmentIdentifier()));
+    EXPECT_TRUE(eq(parts.string, url.string()));
+
+    auto oldURL = URL(URL(URL(), baseURLString), urlString);
+    EXPECT_TRUE(eq(parts.protocol, oldURL.protocol()));
+    EXPECT_TRUE(eq(parts.user, oldURL.user()));
+    EXPECT_TRUE(eq(parts.password, oldURL.pass()));
+    EXPECT_TRUE(eq(parts.host, oldURL.host()));
+    EXPECT_EQ(parts.port, oldURL.port());
+    EXPECT_TRUE(eq(parts.path, oldURL.path()));
+    EXPECT_TRUE(eq(parts.query, oldURL.query()));
+    EXPECT_TRUE(eq(parts.fragment, oldURL.fragmentIdentifier()));
+    EXPECT_TRUE(eq(parts.string, oldURL.string()));
+
+    EXPECT_TRUE(URLParser::allValuesEqual(url, oldURL));
+}
+
+TEST_F(URLParserTest, ParseRelative)
+{
+    checkRelativeURL("/index.html", "http://webkit.org/path1/path2/", {"http", "", "", "webkit.org", 0, "/index.html", "", "", "http://webkit.org/index.html"});
+    checkRelativeURL("http://whatwg.org/index.html", "http://webkit.org/path1/path2/", {"http", "", "", "whatwg.org", 0, "/index.html", "", "", "http://whatwg.org/index.html"});
+    checkRelativeURL("index.html", "http://webkit.org/path1/path2/page.html?query#fragment", {"http", "", "", "webkit.org", 0, "/path1/path2/index.html", "", "", "http://webkit.org/path1/path2/index.html"});
+}
+
 static void checkURLDifferences(const String& urlString, const ExpectedParts& partsNew, const ExpectedParts& partsOld)
 {
     URLParser parser;
     auto url = ""
-    EXPECT_TRUE(eq(partsNew.protocol, url->protocol()));
-    EXPECT_TRUE(eq(partsNew.user, url->user()));
-    EXPECT_TRUE(eq(partsNew.password, url->pass()));
-    EXPECT_TRUE(eq(partsNew.host, url->host()));
-    EXPECT_EQ(partsNew.port, url->port());
-    EXPECT_TRUE(eq(partsNew.path, url->path()));
-    EXPECT_TRUE(eq(partsNew.query, url->query()));
-    EXPECT_TRUE(eq(partsNew.fragment, url->fragmentIdentifier()));
-    EXPECT_TRUE(eq(partsNew.string, url->string()));
+    EXPECT_TRUE(eq(partsNew.protocol, url.protocol()));
+    EXPECT_TRUE(eq(partsNew.user, url.user()));
+    EXPECT_TRUE(eq(partsNew.password, url.pass()));
+    EXPECT_TRUE(eq(partsNew.host, url.host()));
+    EXPECT_EQ(partsNew.port, url.port());
+    EXPECT_TRUE(eq(partsNew.path, url.path()));
+    EXPECT_TRUE(eq(partsNew.query, url.query()));
+    EXPECT_TRUE(eq(partsNew.fragment, url.fragmentIdentifier()));
+    EXPECT_TRUE(eq(partsNew.string, url.string()));
     
     auto oldURL = URL(URL(), urlString);
     EXPECT_TRUE(eq(partsOld.protocol, oldURL.protocol()));
@@ -116,7 +157,7 @@
     EXPECT_TRUE(eq(partsOld.fragment, oldURL.fragmentIdentifier()));
     EXPECT_TRUE(eq(partsOld.string, oldURL.string()));
     
-    EXPECT_FALSE(URLParser::allValuesEqual(url.value(), oldURL));
+    EXPECT_FALSE(URLParser::allValuesEqual(url, oldURL));
 }
 
 TEST_F(URLParserTest, ParserDifferences)
@@ -133,7 +174,7 @@
 {
     URLParser parser;
     auto invalidURL = parser.parse(urlString);
-    EXPECT_TRUE(invalidURL == Nullopt);
+    EXPECT_TRUE(URLParser::allValuesEqual(invalidURL, { }));
 }
     
 TEST_F(URLParserTest, ParserFailures)
_______________________________________________
webkit-changes mailing list
[email protected]
https://lists.webkit.org/mailman/listinfo/webkit-changes

Reply via email to