From 2a4dd894deb33bfe7c0d788afc9cc8c40c55ef48 Mon Sep 17 00:00:00 2001 From: Vincent Ricard Date: Sun, 20 Sep 2020 23:05:41 +0200 Subject: [PATCH] Implement DOMTokenList.supports API --- components/script/dom/domtokenlist.rs | 44 +++++++++++++++++-- components/script/dom/element.rs | 2 +- components/script/dom/htmlanchorelement.rs | 14 +++++- components/script/dom/htmlareaelement.rs | 23 +++++++++- components/script/dom/htmlformelement.rs | 13 +++++- components/script/dom/htmliframeelement.rs | 17 ++++++- components/script/dom/htmllinkelement.rs | 26 ++++++++++- .../script/dom/webidls/DOMTokenList.webidl | 2 + .../script/dom/webidls/HTMLAreaElement.webidl | 4 +- .../reactions/HTMLAreaElement.html.ini | 6 --- .../wpt/metadata/dom/idlharness.window.js.ini | 9 ---- .../metadata/prefetch.https.sub.html.ini | 4 -- .../fetch/metadata/preload.https.sub.html.ini | 3 -- .../redirect-http-upgrade.sub.html.ini | 9 ++++ .../redirect-https-downgrade.sub.html.ini | 9 ++++ .../html/dom/idlharness.https.html.ini | 6 --- .../link-rel-manifest.html.ini | 4 -- .../the-link-element/link-rellist.html.ini | 5 --- .../sandbox-ascii-case-insensitive.html.ini | 3 -- .../rellist-feature-detection.html.ini | 16 ------- 20 files changed, 147 insertions(+), 72 deletions(-) delete mode 100644 tests/wpt/metadata/html/links/manifest/link-relationship/link-rel-manifest.html.ini delete mode 100644 tests/wpt/metadata/html/semantics/document-metadata/the-link-element/link-rellist.html.ini delete mode 100644 tests/wpt/metadata/html/semantics/rellist-feature-detection.html.ini diff --git a/components/script/dom/domtokenlist.rs b/components/script/dom/domtokenlist.rs index 5c25409971c..70b306d223b 100644 --- a/components/script/dom/domtokenlist.rs +++ b/components/script/dom/domtokenlist.rs @@ -20,21 +20,35 @@ pub struct DOMTokenList { reflector_: Reflector, element: Dom, local_name: LocalName, + supported_tokens: Option>, } impl DOMTokenList { - pub fn new_inherited(element: &Element, local_name: LocalName) -> DOMTokenList { + pub fn new_inherited( + element: &Element, + local_name: LocalName, + supported_tokens: Option>, + ) -> DOMTokenList { DOMTokenList { reflector_: Reflector::new(), element: Dom::from_ref(element), local_name: local_name, + supported_tokens: supported_tokens, } } - pub fn new(element: &Element, local_name: &LocalName) -> DomRoot { + pub fn new( + element: &Element, + local_name: &LocalName, + supported_tokens: Option>, + ) -> DomRoot { let window = window_from_node(element); reflect_dom_object( - Box::new(DOMTokenList::new_inherited(element, local_name.clone())), + Box::new(DOMTokenList::new_inherited( + element, + local_name.clone(), + supported_tokens, + )), &*window, ) } @@ -61,6 +75,25 @@ impl DOMTokenList { self.element .set_atomic_tokenlist_attribute(&self.local_name, atoms) } + + // https://dom.spec.whatwg.org/#concept-domtokenlist-validation + fn validation_steps(&self, token: &str) -> Fallible { + match &self.supported_tokens { + None => Err(Error::Type( + "This attribute has no supported tokens".to_owned(), + )), + Some(supported_tokens) => { + let token = Atom::from(token).to_ascii_lowercase(); + if supported_tokens + .iter() + .any(|supported_token| *supported_token == token) + { + return Ok(true); + } + Ok(false) + }, + } + } } // https://dom.spec.whatwg.org/#domtokenlist @@ -197,6 +230,11 @@ impl DOMTokenListMethods for DOMTokenList { Ok(result) } + // https://dom.spec.whatwg.org/#dom-domtokenlist-supports + fn Supports(&self, token: DOMString) -> Fallible { + self.validation_steps(&token) + } + // check-tidy: no specs after this line fn IndexedGetter(&self, index: u32) -> Option { self.Item(index) diff --git a/components/script/dom/element.rs b/components/script/dom/element.rs index e7316ecfeb9..19dbb0b526e 100644 --- a/components/script/dom/element.rs +++ b/components/script/dom/element.rs @@ -1953,7 +1953,7 @@ impl ElementMethods for Element { // https://dom.spec.whatwg.org/#dom-element-classlist fn ClassList(&self) -> DomRoot { self.class_list - .or_init(|| DOMTokenList::new(self, &local_name!("class"))) + .or_init(|| DOMTokenList::new(self, &local_name!("class"), None)) } // https://dom.spec.whatwg.org/#dom-element-attributes diff --git a/components/script/dom/htmlanchorelement.rs b/components/script/dom/htmlanchorelement.rs index e6a89b7e746..be246203121 100644 --- a/components/script/dom/htmlanchorelement.rs +++ b/components/script/dom/htmlanchorelement.rs @@ -32,6 +32,7 @@ use html5ever::{LocalName, Prefix}; use net_traits::request::Referrer; use num_traits::ToPrimitive; use script_traits::{HistoryEntryReplacement, LoadData, LoadOrigin}; +use servo_atoms::Atom; use servo_url::ServoUrl; use std::default::Default; use style::attr::AttrValue; @@ -138,8 +139,17 @@ impl HTMLAnchorElementMethods for HTMLAnchorElement { // https://html.spec.whatwg.org/multipage/#dom-a-rellist fn RelList(&self) -> DomRoot { - self.rel_list - .or_init(|| DOMTokenList::new(self.upcast(), &local_name!("rel"))) + self.rel_list.or_init(|| { + DOMTokenList::new( + self.upcast(), + &local_name!("rel"), + Some(vec![ + Atom::from("noopener"), + Atom::from("noreferrer"), + Atom::from("opener"), + ]), + ) + }) } // https://html.spec.whatwg.org/multipage/#dom-a-coords diff --git a/components/script/dom/htmlareaelement.rs b/components/script/dom/htmlareaelement.rs index 1f25510b819..ef85bb8791e 100644 --- a/components/script/dom/htmlareaelement.rs +++ b/components/script/dom/htmlareaelement.rs @@ -19,6 +19,7 @@ use crate::dom::virtualmethods::VirtualMethods; use dom_struct::dom_struct; use euclid::default::Point2D; use html5ever::{LocalName, Prefix}; +use servo_atoms::Atom; use std::default::Default; use std::f32; use std::str; @@ -303,10 +304,28 @@ impl HTMLAreaElementMethods for HTMLAreaElement { // https://html.spec.whatwg.org/multipage/#attr-hyperlink-target make_setter!(SetTarget, "target"); + // https://html.spec.whatwg.org/multipage/#dom-a-rel + make_getter!(Rel, "rel"); + + // https://html.spec.whatwg.org/multipage/#dom-a-rel + fn SetRel(&self, rel: DOMString) { + self.upcast::() + .set_tokenlist_attribute(&local_name!("rel"), rel); + } + // https://html.spec.whatwg.org/multipage/#dom-area-rellist fn RelList(&self) -> DomRoot { - self.rel_list - .or_init(|| DOMTokenList::new(self.upcast(), &local_name!("rel"))) + self.rel_list.or_init(|| { + DOMTokenList::new( + self.upcast(), + &local_name!("rel"), + Some(vec![ + Atom::from("noopener"), + Atom::from("noreferrer"), + Atom::from("opener"), + ]), + ) + }) } } diff --git a/components/script/dom/htmlformelement.rs b/components/script/dom/htmlformelement.rs index af2ee5e5d15..54c9d710dd3 100644 --- a/components/script/dom/htmlformelement.rs +++ b/components/script/dom/htmlformelement.rs @@ -450,8 +450,17 @@ impl HTMLFormElementMethods for HTMLFormElement { // https://html.spec.whatwg.org/multipage/#dom-a-rellist fn RelList(&self) -> DomRoot { - self.rel_list - .or_init(|| DOMTokenList::new(self.upcast(), &local_name!("rel"))) + self.rel_list.or_init(|| { + DOMTokenList::new( + self.upcast(), + &local_name!("rel"), + Some(vec![ + Atom::from("noopener"), + Atom::from("noreferrer"), + Atom::from("opener"), + ]), + ) + }) } // https://html.spec.whatwg.org/multipage/#the-form-element:supported-property-names diff --git a/components/script/dom/htmliframeelement.rs b/components/script/dom/htmliframeelement.rs index 60c3e93ece8..345e815ee50 100644 --- a/components/script/dom/htmliframeelement.rs +++ b/components/script/dom/htmliframeelement.rs @@ -38,6 +38,7 @@ use script_traits::{ LoadOrigin, UpdatePipelineIdReason, WindowSizeData, }; use script_traits::{NewLayoutInfo, ScriptMsg}; +use servo_atoms::Atom; use servo_url::ServoUrl; use std::cell::Cell; use style::attr::{AttrValue, LengthOrPercentageOrAuto}; @@ -530,8 +531,20 @@ impl HTMLIFrameElementMethods for HTMLIFrameElement { // https://html.spec.whatwg.org/multipage/#dom-iframe-sandbox fn Sandbox(&self) -> DomRoot { - self.sandbox - .or_init(|| DOMTokenList::new(self.upcast::(), &local_name!("sandbox"))) + self.sandbox.or_init(|| { + DOMTokenList::new( + self.upcast::(), + &local_name!("sandbox"), + Some(vec![ + Atom::from("allow-same-origin"), + Atom::from("allow-forms"), + Atom::from("allow-pointer-lock"), + Atom::from("allow-popups"), + Atom::from("allow-scripts"), + Atom::from("allow-top-navigation"), + ]), + ) + }) } // https://html.spec.whatwg.org/multipage/#dom-iframe-contentwindow diff --git a/components/script/dom/htmllinkelement.rs b/components/script/dom/htmllinkelement.rs index 167420be382..93879fb60b7 100644 --- a/components/script/dom/htmllinkelement.rs +++ b/components/script/dom/htmllinkelement.rs @@ -30,6 +30,7 @@ use embedder_traits::EmbedderMsg; use html5ever::{LocalName, Prefix}; use net_traits::ReferrerPolicy; use servo_arc::Arc; +use servo_atoms::Atom; use std::borrow::ToOwned; use std::cell::Cell; use std::default::Default; @@ -428,8 +429,29 @@ impl HTMLLinkElementMethods for HTMLLinkElement { // https://html.spec.whatwg.org/multipage/#dom-link-rellist fn RelList(&self) -> DomRoot { - self.rel_list - .or_init(|| DOMTokenList::new(self.upcast(), &local_name!("rel"))) + self.rel_list.or_init(|| { + DOMTokenList::new( + self.upcast(), + &local_name!("rel"), + Some(vec![ + Atom::from("alternate"), + Atom::from("apple-touch-icon"), + Atom::from("apple-touch-icon-precomposed"), + Atom::from("canonical"), + Atom::from("dns-prefetch"), + Atom::from("icon"), + Atom::from("import"), + Atom::from("manifest"), + Atom::from("modulepreload"), + Atom::from("next"), + Atom::from("preconnect"), + Atom::from("prefetch"), + Atom::from("preload"), + Atom::from("prerender"), + Atom::from("stylesheet"), + ]), + ) + }) } // https://html.spec.whatwg.org/multipage/#dom-link-charset diff --git a/components/script/dom/webidls/DOMTokenList.webidl b/components/script/dom/webidls/DOMTokenList.webidl index b2d604ee2a9..b67dbb1a1dc 100644 --- a/components/script/dom/webidls/DOMTokenList.webidl +++ b/components/script/dom/webidls/DOMTokenList.webidl @@ -20,6 +20,8 @@ interface DOMTokenList { boolean toggle(DOMString token, optional boolean force); [CEReactions, Throws] boolean replace(DOMString token, DOMString newToken); + [Pure, Throws] + boolean supports(DOMString token); [CEReactions, Pure] stringifier attribute DOMString value; diff --git a/components/script/dom/webidls/HTMLAreaElement.webidl b/components/script/dom/webidls/HTMLAreaElement.webidl index f6c47e1b171..74c281e93c5 100644 --- a/components/script/dom/webidls/HTMLAreaElement.webidl +++ b/components/script/dom/webidls/HTMLAreaElement.webidl @@ -19,8 +19,8 @@ interface HTMLAreaElement : HTMLElement { // attribute DOMString download; // [CEReactions] // attribute USVString ping; - // [CEReactions] - // attribute DOMString rel; + [CEReactions] + attribute DOMString rel; [SameObject, PutForwards=value] readonly attribute DOMTokenList relList; // hreflang and type are not reflected }; diff --git a/tests/wpt/metadata/custom-elements/reactions/HTMLAreaElement.html.ini b/tests/wpt/metadata/custom-elements/reactions/HTMLAreaElement.html.ini index 6f1efd09327..1e92b595991 100644 --- a/tests/wpt/metadata/custom-elements/reactions/HTMLAreaElement.html.ini +++ b/tests/wpt/metadata/custom-elements/reactions/HTMLAreaElement.html.ini @@ -17,12 +17,6 @@ [alt on HTMLAreaElement must enqueue an attributeChanged reaction when adding a new attribute] expected: FAIL - [rel on HTMLAreaElement must enqueue an attributeChanged reaction when replacing an existing attribute] - expected: FAIL - - [rel on HTMLAreaElement must enqueue an attributeChanged reaction when adding a new attribute] - expected: FAIL - [ping on HTMLAreaElement must enqueue an attributeChanged reaction when replacing an existing attribute] expected: FAIL diff --git a/tests/wpt/metadata/dom/idlharness.window.js.ini b/tests/wpt/metadata/dom/idlharness.window.js.ini index 6e73346c87f..f841c6763a7 100644 --- a/tests/wpt/metadata/dom/idlharness.window.js.ini +++ b/tests/wpt/metadata/dom/idlharness.window.js.ini @@ -68,9 +68,6 @@ [Event interface: new CustomEvent("foo") must inherit property "composed" with the proper type] expected: FAIL - [DOMTokenList interface: document.body.classList must inherit property "supports(DOMString)" with the proper type] - expected: FAIL - [StaticRange interface: existence and properties of interface prototype object's "constructor" property] expected: FAIL @@ -179,9 +176,6 @@ [AbstractRange interface: existence and properties of interface prototype object's "constructor" property] expected: FAIL - [DOMTokenList interface: operation supports(DOMString)] - expected: FAIL - [EventTarget interface: calling dispatchEvent(Event) on new AbortController().signal with too few arguments must throw TypeError] expected: FAIL @@ -212,9 +206,6 @@ [Event interface: document.createEvent("Event") must inherit property "composedPath()" with the proper type] expected: FAIL - [DOMTokenList interface: calling supports(DOMString) on document.body.classList with too few arguments must throw TypeError] - expected: FAIL - [StaticRange interface object length] expected: FAIL diff --git a/tests/wpt/metadata/fetch/metadata/prefetch.https.sub.html.ini b/tests/wpt/metadata/fetch/metadata/prefetch.https.sub.html.ini index 21a8f5be01c..460d5ac99ae 100644 --- a/tests/wpt/metadata/fetch/metadata/prefetch.https.sub.html.ini +++ b/tests/wpt/metadata/fetch/metadata/prefetch.https.sub.html.ini @@ -8,7 +8,3 @@ [] expected: TIMEOUT - - [Browser supports prefetch.] - expected: FAIL - diff --git a/tests/wpt/metadata/fetch/metadata/preload.https.sub.html.ini b/tests/wpt/metadata/fetch/metadata/preload.https.sub.html.ini index 053f4a8f1c1..22fcc1d0610 100644 --- a/tests/wpt/metadata/fetch/metadata/preload.https.sub.html.ini +++ b/tests/wpt/metadata/fetch/metadata/preload.https.sub.html.ini @@ -24,9 +24,6 @@ [] expected: TIMEOUT - [Browser supports preload.] - expected: FAIL - [] expected: TIMEOUT diff --git a/tests/wpt/metadata/fetch/metadata/redirect/redirect-http-upgrade.sub.html.ini b/tests/wpt/metadata/fetch/metadata/redirect/redirect-http-upgrade.sub.html.ini index 1148df03997..f9bd431b18f 100644 --- a/tests/wpt/metadata/fetch/metadata/redirect/redirect-http-upgrade.sub.html.ini +++ b/tests/wpt/metadata/fetch/metadata/redirect/redirect-http-upgrade.sub.html.ini @@ -36,3 +36,12 @@ [Http upgrade fetch() api] expected: NOTRUN + [Http upgrade preload] + expected: TIMEOUT + + [Http upgrade stylesheet] + expected: NOTRUN + + [Http upgrade track] + expected: NOTRUN + diff --git a/tests/wpt/metadata/fetch/metadata/redirect/redirect-https-downgrade.sub.html.ini b/tests/wpt/metadata/fetch/metadata/redirect/redirect-https-downgrade.sub.html.ini index 537cc49f30c..26473651cb9 100644 --- a/tests/wpt/metadata/fetch/metadata/redirect/redirect-https-downgrade.sub.html.ini +++ b/tests/wpt/metadata/fetch/metadata/redirect/redirect-https-downgrade.sub.html.ini @@ -9,3 +9,12 @@ [Https downgrade embed] expected: TIMEOUT + [Https downgrade preload] + expected: TIMEOUT + + [Https downgrade stylesheet] + expected: NOTRUN + + [Https downgrade track] + expected: NOTRUN + diff --git a/tests/wpt/metadata/html/dom/idlharness.https.html.ini b/tests/wpt/metadata/html/dom/idlharness.https.html.ini index 33bbf1cddd9..7cd29f953f7 100644 --- a/tests/wpt/metadata/html/dom/idlharness.https.html.ini +++ b/tests/wpt/metadata/html/dom/idlharness.https.html.ini @@ -2550,9 +2550,6 @@ [HTMLMeterElement interface: attribute optimum] expected: FAIL - [HTMLAreaElement interface: document.createElement("area") must inherit property "rel" with the proper type] - expected: FAIL - [HTMLInputElement interface: createInput("password") must inherit property "useMap" with the proper type] expected: FAIL @@ -2646,9 +2643,6 @@ [HTMLFrameElement interface: attribute frameBorder] expected: FAIL - [HTMLAreaElement interface: attribute rel] - expected: FAIL - [HTMLImageElement interface: new Image() must inherit property "decode()" with the proper type] expected: FAIL diff --git a/tests/wpt/metadata/html/links/manifest/link-relationship/link-rel-manifest.html.ini b/tests/wpt/metadata/html/links/manifest/link-relationship/link-rel-manifest.html.ini deleted file mode 100644 index 95fd7732d02..00000000000 --- a/tests/wpt/metadata/html/links/manifest/link-relationship/link-rel-manifest.html.ini +++ /dev/null @@ -1,4 +0,0 @@ -[link-rel-manifest.html] - [link element supports a rel value of "manifest".] - expected: FAIL - diff --git a/tests/wpt/metadata/html/semantics/document-metadata/the-link-element/link-rellist.html.ini b/tests/wpt/metadata/html/semantics/document-metadata/the-link-element/link-rellist.html.ini deleted file mode 100644 index 677f02231de..00000000000 --- a/tests/wpt/metadata/html/semantics/document-metadata/the-link-element/link-rellist.html.ini +++ /dev/null @@ -1,5 +0,0 @@ -[link-rellist.html] - type: testharness - [link.relList: non-string contains] - expected: FAIL - diff --git a/tests/wpt/metadata/html/semantics/embedded-content/the-iframe-element/sandbox-ascii-case-insensitive.html.ini b/tests/wpt/metadata/html/semantics/embedded-content/the-iframe-element/sandbox-ascii-case-insensitive.html.ini index 12469241f2f..fd395f385b6 100644 --- a/tests/wpt/metadata/html/semantics/embedded-content/the-iframe-element/sandbox-ascii-case-insensitive.html.ini +++ b/tests/wpt/metadata/html/semantics/embedded-content/the-iframe-element/sandbox-ascii-case-insensitive.html.ini @@ -1,7 +1,4 @@ [sandbox-ascii-case-insensitive.html] - [iframe 'sandbox' ASCII case insensitive, allow-same-orİgin] - expected: FAIL - [iframe 'sandbox' ASCII case insensitive, allow-ſcripts] expected: FAIL diff --git a/tests/wpt/metadata/html/semantics/rellist-feature-detection.html.ini b/tests/wpt/metadata/html/semantics/rellist-feature-detection.html.ini deleted file mode 100644 index d64c90f3857..00000000000 --- a/tests/wpt/metadata/html/semantics/rellist-feature-detection.html.ini +++ /dev/null @@ -1,16 +0,0 @@ -[rellist-feature-detection.html] - [Make sure that relList based feature detection is working] - expected: FAIL - - [Make sure that relList based feature detection is working for ] - expected: FAIL - - [Make sure that relList based feature detection is working for
] - expected: FAIL - - [Make sure that relList based feature detection is working for ] - expected: FAIL - - [Make sure that relList based feature detection is working for ] - expected: FAIL -