瀏覽代碼

LibURL: Do not treat port of 0 as a null port in Origin

It is not treated as the same thing in the specification, or by us in
other places too. This fixes 8 more origin related URL tests on WPT.
Shannon Booth 10 月之前
父節點
當前提交
088b659abd

+ 1 - 0
Tests/LibWeb/Text/expected/URL/url-origin-for-port-number-of-zero.txt

@@ -0,0 +1 @@
+http://f:0

+ 7 - 0
Tests/LibWeb/Text/input/URL/url-origin-for-port-number-of-zero.html

@@ -0,0 +1,7 @@
+<a id="a" href='http://f:0/c'>
+<script src="../include.js"></script>
+<script>
+    test(() => {
+        println(document.getElementById("a").origin);
+    })
+</script>

+ 1 - 1
Userland/Libraries/LibIPC/Decoder.cpp

@@ -102,7 +102,7 @@ ErrorOr<URL::Origin> decode(Decoder& decoder)
 {
     auto scheme = TRY(decoder.decode<ByteString>());
     auto host = TRY(decoder.decode<URL::Host>());
-    u16 port = TRY(decoder.decode<u16>());
+    auto port = TRY(decoder.decode<Optional<u16>>());
 
     return URL::Origin { move(scheme), move(host), port };
 }

+ 11 - 6
Userland/Libraries/LibURL/Origin.cpp

@@ -27,9 +27,9 @@ ByteString Origin::serialize() const
     result.append(Parser::serialize_host(host()).release_value_but_fixme_should_propagate_errors().to_byte_string());
 
     // 5. If origin's port is non-null, append a U+003A COLON character (:), and origin's port, serialized, to result.
-    if (port() != 0) {
+    if (port().has_value()) {
         result.append(':');
-        result.append(ByteString::number(port()));
+        result.append(ByteString::number(*port()));
     }
     // 6. Return result
     return result.to_byte_string();
@@ -41,10 +41,15 @@ namespace AK {
 
 unsigned Traits<URL::Origin>::hash(URL::Origin const& origin)
 {
-    auto hash_without_host = pair_int_hash(origin.scheme().hash(), origin.port());
-    if (origin.host().has<Empty>())
-        return hash_without_host;
-    return pair_int_hash(hash_without_host, URL::Parser::serialize_host(origin.host()).release_value_but_fixme_should_propagate_errors().hash());
+    unsigned hash = origin.scheme().hash();
+
+    if (origin.port().has_value())
+        hash = pair_int_hash(hash, *origin.port());
+
+    if (!origin.host().has<Empty>())
+        hash = pair_int_hash(hash, URL::Parser::serialize_host(origin.host()).release_value_but_fixme_should_propagate_errors().hash());
+
+    return hash;
 }
 
 } // namespace AK

+ 4 - 4
Userland/Libraries/LibURL/Origin.h

@@ -15,7 +15,7 @@ namespace URL {
 class Origin {
 public:
     Origin() = default;
-    Origin(Optional<ByteString> const& scheme, Host const& host, u16 port)
+    Origin(Optional<ByteString> const& scheme, Host const& host, Optional<u16> port)
         : m_scheme(scheme)
         , m_host(host)
         , m_port(port)
@@ -23,14 +23,14 @@ public:
     }
 
     // https://html.spec.whatwg.org/multipage/origin.html#concept-origin-opaque
-    bool is_opaque() const { return !m_scheme.has_value() && m_host.has<Empty>() && m_port == 0; }
+    bool is_opaque() const { return !m_scheme.has_value() && m_host.has<Empty>() && !m_port.has_value(); }
 
     StringView scheme() const
     {
         return m_scheme.map([](auto& str) { return str.view(); }).value_or(StringView {});
     }
     Host const& host() const { return m_host; }
-    u16 port() const { return m_port; }
+    Optional<u16> port() const { return m_port; }
 
     // https://html.spec.whatwg.org/multipage/origin.html#same-origin
     bool is_same_origin(Origin const& other) const
@@ -91,7 +91,7 @@ public:
 private:
     Optional<ByteString> m_scheme;
     Host m_host;
-    u16 m_port { 0 };
+    Optional<u16> m_port;
 };
 
 }

+ 2 - 2
Userland/Libraries/LibURL/URL.cpp

@@ -386,7 +386,7 @@ Origin URL::origin() const
     // -> "wss"
     if (scheme().is_one_of("ftp"sv, "http"sv, "https"sv, "ws"sv, "wss"sv)) {
         // Return the tuple origin (url’s scheme, url’s host, url’s port, null).
-        return Origin(scheme().to_byte_string(), host(), port().value_or(0));
+        return Origin(scheme().to_byte_string(), host(), port());
     }
 
     // -> "file"
@@ -394,7 +394,7 @@ Origin URL::origin() const
     if (scheme() == "file"sv || scheme() == "resource"sv) {
         // Unfortunate as it is, this is left as an exercise to the reader. When in doubt, return a new opaque origin.
         // Note: We must return an origin with the `file://' protocol for `file://' iframes to work from `file://' pages.
-        return Origin(scheme().to_byte_string(), String {}, 0);
+        return Origin(scheme().to_byte_string(), String {}, {});
     }
 
     // -> Otherwise