Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
8 changes: 6 additions & 2 deletions Source/WTF/wtf/URL.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -133,9 +133,13 @@ bool URL::protocolIsSecure() const
unsigned URL::pathStart() const
{
unsigned start = m_hostEnd + m_portLength;
// URLParser::addNonSpecialDotSlash inserts "/." before a path that starts with "//" in a URL
// without a host, so that the path is not parsed back as an authority. It is not part of the
// path. "/." followed by anything else is the path's first segment (e.g. "foo:/.well-known"):
// the parser removes single-dot segments, so a real segment is never just ".".
if (start == m_schemeEnd + 1U
&& start + 1 < m_string.length()
&& m_string[start] == '/' && m_string[start + 1] == '.')
&& start + 2 < m_string.length()
&& m_string[start] == '/' && m_string[start + 1] == '.' && m_string[start + 2] == '/')
start += 2;
return start;
}
Expand Down
76 changes: 76 additions & 0 deletions Tools/TestWebKitAPI/Tests/WTF/URL.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -120,6 +120,82 @@ TEST_F(WTF_URL, URLProtocolHostAndPort)

url = createURL("asdf:///a/b/c"_s);
EXPECT_EQ(String("asdf://"_s), url.protocolHostAndPort());

url = createURL("asdf:/a/b/c"_s);
EXPECT_EQ(String("asdf:"_s), url.protocolHostAndPort());

url = createURL("asdf:/.a/b/c"_s);
EXPECT_EQ(String("asdf:"_s), url.protocolHostAndPort());
}

// A URL without a host whose path starts with "//" is serialized with "/." in front of the path so that it does not
// parse back as an authority. That prefix is not part of the path; a first segment that starts with "." is.
TEST_F(WTF_URL, PathStartingWithDotWithoutHost)
{
auto url = createURL("asdf:/.a/b"_s);
EXPECT_TRUE(url.isValid());
EXPECT_TRUE(url.hasPath());
EXPECT_EQ(String("asdf:/.a/b"_s), url.string());
EXPECT_EQ(String("/.a/b"_s), url.path().toString());
EXPECT_EQ(String("b"_s), url.lastPathComponent().toString());

url = createURL("asdf:/.a"_s);
EXPECT_EQ(String("/.a"_s), url.path().toString());
EXPECT_EQ(String(".a"_s), url.lastPathComponent().toString());

url = createURL("asdf:/..a"_s);
EXPECT_EQ(String("/..a"_s), url.path().toString());
EXPECT_EQ(String("..a"_s), url.lastPathComponent().toString());

url = createURL("asdf:/.well-known/x?q#f"_s);
EXPECT_EQ(String("/.well-known/x"_s), url.path().toString());
EXPECT_EQ(String("x"_s), url.lastPathComponent().toString());

url = createURL("asdf:/.//b"_s);
EXPECT_EQ(String("asdf:/.//b"_s), url.string());
EXPECT_EQ(String("//b"_s), url.path().toString());
EXPECT_EQ(String("b"_s), url.lastPathComponent().toString());

url = createURL("asdf:/.//.a"_s);
EXPECT_EQ(String("//.a"_s), url.path().toString());
EXPECT_EQ(String(".a"_s), url.lastPathComponent().toString());

url = createURL("asdf://host/.a"_s);
EXPECT_EQ(String("/.a"_s), url.path().toString());

url = createURL("asdf:///.a"_s);
EXPECT_EQ(String("/.a"_s), url.path().toString());

url = createURL("asdf:/x"_s);
url.setPath("/.a/b"_s);
EXPECT_EQ(String("asdf:/.a/b"_s), url.string());
EXPECT_EQ(String("/.a/b"_s), url.path().toString());

url = createURL("asdf:/.a"_s);
url.setPath("/b"_s);
EXPECT_EQ(String("asdf:/b"_s), url.string());
EXPECT_EQ(String("/b"_s), url.path().toString());

url = createURL("asdf:/.a"_s);
url.setPath("//b"_s);
EXPECT_EQ(String("asdf:/.//b"_s), url.string());
EXPECT_EQ(String("//b"_s), url.path().toString());

url = createURL("asdf:/.//b"_s);
url.setPath("/.c"_s);
EXPECT_EQ(String("asdf:/.c"_s), url.string());
EXPECT_EQ(String("/.c"_s), url.path().toString());

url = createURL("asdf:/.a"_s);
url.setHostAndPort("host:1"_s);
EXPECT_TRUE(url.isValid());
EXPECT_EQ(String("asdf://host:1/.a"_s), url.string());
EXPECT_EQ(String("/.a"_s), url.path().toString());

url = createURL("asdf:/.//b"_s);
url.setHostAndPort("host:1"_s);
EXPECT_EQ(String("asdf://host:1//b"_s), url.string());
EXPECT_EQ(String("//b"_s), url.path().toString());
}

TEST_F(WTF_URL, URLDataURIStringSharing)
Expand Down
17 changes: 17 additions & 0 deletions Tools/TestWebKitAPI/Tests/WTF/URLParser.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -235,6 +235,23 @@ TEST_F(WTF_URLParser, Idempotence)
checkURL("v:/.//.."_s, { "v"_s, ""_s, ""_s, ""_s, 0, "/"_s, ""_s, ""_s, "v:/"_s });
checkURL("w:/.//..//"_s, { "w"_s, ""_s, ""_s, ""_s, 0, "//"_s, ""_s, ""_s, "w:/.//"_s });
checkURL("x:/.//../a"_s, { "x"_s, ""_s, ""_s, ""_s, 0, "/a"_s, ""_s, ""_s, "x:/a"_s });
// "/." is only a serialization artifact in front of a path starting with "//". A first path segment that
// merely starts with "." is part of the path.
checkURL("y:/.a"_s, { "y"_s, ""_s, ""_s, ""_s, 0, "/.a"_s, ""_s, ""_s, "y:/.a"_s });
checkURL("z:/.a/b"_s, { "z"_s, ""_s, ""_s, ""_s, 0, "/.a/b"_s, ""_s, ""_s, "z:/.a/b"_s });
checkURL("aa:/..a"_s, { "aa"_s, ""_s, ""_s, ""_s, 0, "/..a"_s, ""_s, ""_s, "aa:/..a"_s });
checkURL("ab:/.a?q#f"_s, { "ab"_s, ""_s, ""_s, ""_s, 0, "/.a"_s, "q"_s, "f"_s, "ab:/.a?q#f"_s });
checkURL("ac:/.a//b"_s, { "ac"_s, ""_s, ""_s, ""_s, 0, "/.a//b"_s, ""_s, ""_s, "ac:/.a//b"_s });
checkURL("ad:/.%2Fa"_s, { "ad"_s, ""_s, ""_s, ""_s, 0, "/.%2Fa"_s, ""_s, ""_s, "ad:/.%2Fa"_s });
checkURL("ae:/.//.a"_s, { "ae"_s, ""_s, ""_s, ""_s, 0, "//.a"_s, ""_s, ""_s, "ae:/.//.a"_s });
checkURL("af:/./.a"_s, { "af"_s, ""_s, ""_s, ""_s, 0, "/.a"_s, ""_s, ""_s, "af:/.a"_s });
checkURL("ag:/.well-known/x"_s, { "ag"_s, ""_s, ""_s, ""_s, 0, "/.well-known/x"_s, ""_s, ""_s, "ag:/.well-known/x"_s });
checkURL("ah://host/.a"_s, { "ah"_s, ""_s, ""_s, "host"_s, 0, "/.a"_s, ""_s, ""_s, "ah://host/.a"_s });
checkURL("ai:///.a"_s, { "ai"_s, ""_s, ""_s, ""_s, 0, "/.a"_s, ""_s, ""_s, "ai:///.a"_s });
checkRelativeURL("x"_s, "aj:/.a/b"_s, { "aj"_s, ""_s, ""_s, ""_s, 0, "/.a/x"_s, ""_s, ""_s, "aj:/.a/x"_s });
checkRelativeURL("../y"_s, "ak:/.a/b/c"_s, { "ak"_s, ""_s, ""_s, ""_s, 0, "/.a/y"_s, ""_s, ""_s, "ak:/.a/y"_s });
checkRelativeURL("/.a"_s, "al:/.//b"_s, { "al"_s, ""_s, ""_s, ""_s, 0, "/.a"_s, ""_s, ""_s, "al:/.a"_s });
checkRelativeURL("//b"_s, "am:/.a"_s, { "am"_s, ""_s, ""_s, "b"_s, 0, ""_s, ""_s, ""_s, "am://b"_s });
checkURL("http://host/./"_s, { "http"_s, ""_s, ""_s, "host"_s, 0, "/"_s, ""_s, ""_s, "http://host/"_s });
checkURL("http://host/../"_s, { "http"_s, ""_s, ""_s, "host"_s, 0, "/"_s, ""_s, ""_s, "http://host/"_s });
checkURL("http://host/.../"_s, { "http"_s, ""_s, ""_s, "host"_s, 0, "/.../"_s, ""_s, ""_s, "http://host/.../"_s });
Expand Down
Loading