mirror of
https://github.com/servo/servo.git
synced 2025-06-06 16:45:39 +00:00
Implement DOMTokenList.supports API
This commit is contained in:
parent
3f7697690a
commit
2a4dd894de
20 changed files with 147 additions and 72 deletions
|
@ -20,21 +20,35 @@ pub struct DOMTokenList {
|
|||
reflector_: Reflector,
|
||||
element: Dom<Element>,
|
||||
local_name: LocalName,
|
||||
supported_tokens: Option<Vec<Atom>>,
|
||||
}
|
||||
|
||||
impl DOMTokenList {
|
||||
pub fn new_inherited(element: &Element, local_name: LocalName) -> DOMTokenList {
|
||||
pub fn new_inherited(
|
||||
element: &Element,
|
||||
local_name: LocalName,
|
||||
supported_tokens: Option<Vec<Atom>>,
|
||||
) -> 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<DOMTokenList> {
|
||||
pub fn new(
|
||||
element: &Element,
|
||||
local_name: &LocalName,
|
||||
supported_tokens: Option<Vec<Atom>>,
|
||||
) -> DomRoot<DOMTokenList> {
|
||||
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<bool> {
|
||||
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<bool> {
|
||||
self.validation_steps(&token)
|
||||
}
|
||||
|
||||
// check-tidy: no specs after this line
|
||||
fn IndexedGetter(&self, index: u32) -> Option<DOMString> {
|
||||
self.Item(index)
|
||||
|
|
|
@ -1953,7 +1953,7 @@ impl ElementMethods for Element {
|
|||
// https://dom.spec.whatwg.org/#dom-element-classlist
|
||||
fn ClassList(&self) -> DomRoot<DOMTokenList> {
|
||||
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
|
||||
|
|
|
@ -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<DOMTokenList> {
|
||||
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
|
||||
|
|
|
@ -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::<Element>()
|
||||
.set_tokenlist_attribute(&local_name!("rel"), rel);
|
||||
}
|
||||
|
||||
// https://html.spec.whatwg.org/multipage/#dom-area-rellist
|
||||
fn RelList(&self) -> DomRoot<DOMTokenList> {
|
||||
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"),
|
||||
]),
|
||||
)
|
||||
})
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
@ -450,8 +450,17 @@ impl HTMLFormElementMethods for HTMLFormElement {
|
|||
|
||||
// https://html.spec.whatwg.org/multipage/#dom-a-rellist
|
||||
fn RelList(&self) -> DomRoot<DOMTokenList> {
|
||||
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
|
||||
|
|
|
@ -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<DOMTokenList> {
|
||||
self.sandbox
|
||||
.or_init(|| DOMTokenList::new(self.upcast::<Element>(), &local_name!("sandbox")))
|
||||
self.sandbox.or_init(|| {
|
||||
DOMTokenList::new(
|
||||
self.upcast::<Element>(),
|
||||
&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
|
||||
|
|
|
@ -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<DOMTokenList> {
|
||||
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
|
||||
|
|
|
@ -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;
|
||||
|
|
|
@ -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
|
||||
};
|
||||
|
|
|
@ -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
|
||||
|
||||
|
|
|
@ -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
|
||||
|
||||
|
|
|
@ -8,7 +8,3 @@
|
|||
|
||||
[<link rel='prefetch' href='https://web-platform.test:8443/...'>]
|
||||
expected: TIMEOUT
|
||||
|
||||
[Browser supports prefetch.]
|
||||
expected: FAIL
|
||||
|
||||
|
|
|
@ -24,9 +24,6 @@
|
|||
[<link rel='preload' as='track' href='https://web-platform.test:8443/...'>]
|
||||
expected: TIMEOUT
|
||||
|
||||
[Browser supports preload.]
|
||||
expected: FAIL
|
||||
|
||||
[<link rel='preload' as='fetch' href='https://www.not-web-platform.test:8443/...'>]
|
||||
expected: TIMEOUT
|
||||
|
||||
|
|
|
@ -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
|
||||
|
||||
|
|
|
@ -9,3 +9,12 @@
|
|||
[Https downgrade embed]
|
||||
expected: TIMEOUT
|
||||
|
||||
[Https downgrade preload]
|
||||
expected: TIMEOUT
|
||||
|
||||
[Https downgrade stylesheet]
|
||||
expected: NOTRUN
|
||||
|
||||
[Https downgrade track]
|
||||
expected: NOTRUN
|
||||
|
||||
|
|
|
@ -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
|
||||
|
||||
|
|
|
@ -1,4 +0,0 @@
|
|||
[link-rel-manifest.html]
|
||||
[link element supports a rel value of "manifest".]
|
||||
expected: FAIL
|
||||
|
|
@ -1,5 +0,0 @@
|
|||
[link-rellist.html]
|
||||
type: testharness
|
||||
[link.relList: non-string contains]
|
||||
expected: FAIL
|
||||
|
|
@ -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
|
||||
|
||||
|
|
|
@ -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 <a>]
|
||||
expected: FAIL
|
||||
|
||||
[Make sure that relList based feature detection is working for <form>]
|
||||
expected: FAIL
|
||||
|
||||
[Make sure that relList based feature detection is working for <area>]
|
||||
expected: FAIL
|
||||
|
||||
[Make sure that relList based feature detection is working for <link>]
|
||||
expected: FAIL
|
||||
|
Loading…
Add table
Add a link
Reference in a new issue