script: Do not include fragments when comparing URLs in CookieStore (#38876)

Fixes a check for empty options in `getAll(options)` and makes url
comparison with exclude fragments set to true.

Testing: New passing WPT tests
Part of #37674

---------

Signed-off-by: Sebastian C <sebsebmc@gmail.com>
This commit is contained in:
Sebastian C 2025-08-27 18:41:11 -05:00 committed by GitHub
parent 84f478a47a
commit e5c83ec419
No known key found for this signature in database
GPG key ID: B5690EEEBB952194
14 changed files with 46 additions and 66 deletions

View file

@ -259,12 +259,12 @@ impl CookieStoreMethods<crate::DomTypeHolder> for CookieStore {
// 6.1. Let parsed be the result of parsing options["url"] with settingss API base URL.
let parsed_url = ServoUrl::parse_with_base(Some(&global.api_base_url()), get_url);
// 6.2. If thiss relevant global object is a Window object and parsed does not equal url,
// 6.2. If thiss relevant global object is a Window object and parsed does not equal url with exclude fragments set to true,
// then return a promise rejected with a TypeError.
if let Some(_window) = DomRoot::downcast::<Window>(self.global()) {
if parsed_url
.as_ref()
.is_ok_and(|parsed| parsed.as_url() != creation_url.as_url())
.is_ok_and(|parsed| !parsed.is_equal_excluding_fragments(creation_url))
{
p.reject_error(
Error::Type("URL does not match context".to_string()),
@ -354,7 +354,7 @@ impl CookieStoreMethods<crate::DomTypeHolder> for CookieStore {
// 2. Let origin be settingss origin.
let origin = global.origin();
// 7. Let p be a new promise.
// 6. Let p be a new promise.
let p = Promise::new(&global, can_gc);
// 3. If origin is an opaque origin, then return a promise rejected with a "SecurityError" DOMException.
@ -366,26 +366,19 @@ impl CookieStoreMethods<crate::DomTypeHolder> for CookieStore {
// 4. Let url be settingss creation URL.
let creation_url = global.creation_url();
// 5. If options is empty, then return a promise rejected with a TypeError.
// "is empty" is not strictly defined anywhere in the spec but the only value we require here is "url"
if options.url.is_none() && options.name.is_none() {
p.reject_error(Error::Type("Options cannot be empty".to_string()), can_gc);
return p;
}
let mut final_url = creation_url.clone();
// 6. If options["url"] is present, then run these steps:
// 5. If options["url"] is present, then run these steps:
if let Some(get_url) = &options.url {
// 6.1. Let parsed be the result of parsing options["url"] with settingss API base URL.
// 5.1. Let parsed be the result of parsing options["url"] with settingss API base URL.
let parsed_url = ServoUrl::parse_with_base(Some(&global.api_base_url()), get_url);
// 6.2. If thiss relevant global object is a Window object and parsed does not equal url,
// If thiss relevant global object is a Window object and parsed does not equal url with exclude fragments set to true,
// then return a promise rejected with a TypeError.
if let Some(_window) = DomRoot::downcast::<Window>(self.global()) {
if parsed_url
.as_ref()
.is_ok_and(|parsed| parsed.as_url() != creation_url.as_url())
.is_ok_and(|parsed| !parsed.is_equal_excluding_fragments(creation_url))
{
p.reject_error(
Error::Type("URL does not match context".to_string()),
@ -395,7 +388,7 @@ impl CookieStoreMethods<crate::DomTypeHolder> for CookieStore {
}
}
// 6.3. If parseds origin and urls origin are not the same origin,
// 5.3. If parseds origin and urls origin are not the same origin,
// then return a promise rejected with a TypeError.
if parsed_url
.as_ref()
@ -405,13 +398,13 @@ impl CookieStoreMethods<crate::DomTypeHolder> for CookieStore {
return p;
}
// 6.4. Set url to parsed.
// 5.4. Set url to parsed.
if let Ok(url) = parsed_url {
final_url = url;
}
}
// 6. Run the following steps in parallel:
// 7. Run the following steps in parallel:
let res =
self.global()
.resource_threads()

View file

@ -117,6 +117,13 @@ impl ServoUrl {
scheme == "wss"
}
/// <https://url.spec.whatwg.org/#url-equivalence>
/// In the future this may be removed if the helper is added upstream in rust-url
/// see <https://github.com/servo/rust-url/issues/1063> for details
pub fn is_equal_excluding_fragments(&self, other: &ServoUrl) -> bool {
self.0[..Position::AfterQuery] == other.0[..Position::AfterQuery]
}
pub fn as_str(&self) -> &str {
self.0.as_str()
}

View file

@ -1,18 +1,19 @@
[change_eventhandler_for_document_cookie.https.window.html]
expected: TIMEOUT
[document.cookie set/overwrite/delete observed by CookieStore]
expected: FAIL
expected: TIMEOUT
[document.cookie set already-expired cookie should not be observed by CookieStore]
expected: FAIL
expected: NOTRUN
[document.cookie duplicate cookie should not be observed by CookieStore]
expected: FAIL
expected: NOTRUN
[CookieStore set/overwrite/delete observed by document.cookie]
expected: FAIL
expected: NOTRUN
[CookieStore agrees with document.cookie on encoding non-ASCII cookies]
expected: FAIL
expected: NOTRUN
[document.cookie agrees with CookieStore on encoding non-ASCII cookies]
expected: FAIL
expected: NOTRUN

View file

@ -1,21 +1,22 @@
[change_eventhandler_for_http_cookie_and_set_cookie_headers.https.window.html]
expected: TIMEOUT
[HTTP set/overwrite/delete observed in CookieStore]
expected: FAIL
expected: TIMEOUT
[HTTP set already-expired cookie should not be observed by CookieStore]
expected: FAIL
expected: NOTRUN
[HTTP duplicate cookie should not be observed by CookieStore]
expected: FAIL
expected: NOTRUN
[CookieStore agreed with HTTP headers agree on encoding non-ASCII cookies]
expected: FAIL
expected: NOTRUN
[CookieStore set/overwrite/delete observed in HTTP headers]
expected: FAIL
expected: NOTRUN
[HTTP headers agreed with CookieStore on encoding non-ASCII cookies]
expected: FAIL
expected: NOTRUN
[Binary HTTP set/overwrite/delete observed in CookieStore]
expected: FAIL
expected: NOTRUN

View file

@ -1,6 +1,7 @@
[change_eventhandler_for_no_change.https.window.html]
expected: TIMEOUT
[CookieStore duplicate cookie should not be observed]
expected: FAIL
expected: TIMEOUT
[CookieStore duplicate partitioned cookie should not be observed]
expected: FAIL
expected: NOTRUN

View file

@ -1,3 +1,4 @@
[change_eventhandler_for_no_name_and_no_value.https.window.html]
expected: TIMEOUT
[Verify behavior of no-name and no-value cookies.]
expected: FAIL
expected: TIMEOUT

View file

@ -1,3 +1,4 @@
[change_eventhandler_for_no_name_equals_in_value.https.window.html]
expected: TIMEOUT
[Verify that attempting to set a cookie with no name and with '=' in the value does not work.]
expected: FAIL
expected: TIMEOUT

View file

@ -1,3 +1,4 @@
[change_eventhandler_for_no_name_multiple_values.https.window.html]
expected: TIMEOUT
[Verify behavior of multiple no-name cookies]
expected: FAIL
expected: TIMEOUT

View file

@ -2,17 +2,5 @@
expected: ERROR
[cookieStore_getAll_arguments.https.any.html]
[cookieStore.getAll with no arguments]
expected: FAIL
[cookieStore.getAll with empty options]
expected: FAIL
[cookieStore.getAll with absolute url with fragment in options]
expected: FAIL
[cookieStore.getAll with absolute different url in options]
expected: FAIL
[cookieStore.getAll with whitespace]
expected: FAIL

View file

@ -1,7 +1,4 @@
[cookieStore_getAll_multiple.https.any.html]
[cookieStore.getAll returns multiple cookies written by cookieStore.set]
expected: FAIL
[cookieStore_getAll_multiple.https.any.serviceworker.html]
expected: ERROR

View file

@ -1,3 +0,0 @@
[cookieStore_getAll_set_creation_url.https.any.html]
[cookieStore.set and cookieStore.getAll use the creation url]
expected: FAIL

View file

@ -2,11 +2,5 @@
expected: ERROR
[cookieStore_get_arguments.https.any.html]
[cookieStore.get with absolute url with fragment in options]
expected: FAIL
[cookieStore.get with absolute different url in options]
expected: FAIL
[cookieStore.get with whitespace]
expected: FAIL

View file

@ -1,7 +1,4 @@
[cookieStore_opaque_origin.https.html]
expected: TIMEOUT
[cookieStore in non-sandboxed iframe should not throw]
expected: FAIL
[cookieStore in sandboxed iframe should throw SecurityError]
expected: TIMEOUT

View file

@ -1,12 +1,13 @@
[httponly_cookies.https.window.html]
expected: TIMEOUT
[HttpOnly cookies are not observed]
expected: FAIL
expected: TIMEOUT
[HttpOnly cookies can not be set by document.cookie]
expected: FAIL
expected: NOTRUN
[HttpOnly cookies can not be set by CookieStore]
expected: FAIL
expected: NOTRUN
[HttpOnly cookies are not deleted/overwritten]
expected: FAIL
expected: NOTRUN