diff options
author | bors-servo <metajack+bors@gmail.com> | 2014-12-26 13:18:45 -0700 |
---|---|---|
committer | bors-servo <metajack+bors@gmail.com> | 2014-12-26 13:18:45 -0700 |
commit | 3af73e9962fe810de0c556693ec2eb0559b06a67 (patch) | |
tree | 3a6220ae9a6c05c5b43bdf5fc6f822e597e39d7a /components/script | |
parent | 0e6304dcf7fd6712f4455151b55a361de857359d (diff) | |
parent | 3624673d2faf7a36face3321af70fc55117a24a7 (diff) | |
download | servo-3af73e9962fe810de0c556693ec2eb0559b06a67.tar.gz servo-3af73e9962fe810de0c556693ec2eb0559b06a67.zip |
auto merge of #4353 : brunoabinader/servo/domtokenlist, r=Ms2ger
Specs:
https://dom.spec.whatwg.org/#dom-domtokenlist-add
https://dom.spec.whatwg.org/#dom-domtokenlist-remove
https://dom.spec.whatwg.org/#dom-domtokenlist-toggle
https://dom.spec.whatwg.org/#concept-dtl-update
https://dom.spec.whatwg.org/#concept-ordered-set-serializer
Closes #3138.
Diffstat (limited to 'components/script')
-rw-r--r-- | components/script/dom/attr.rs | 18 | ||||
-rw-r--r-- | components/script/dom/domtokenlist.rs | 75 | ||||
-rw-r--r-- | components/script/dom/element.rs | 20 | ||||
-rw-r--r-- | components/script/dom/htmlanchorelement.rs | 2 | ||||
-rw-r--r-- | components/script/dom/htmlareaelement.rs | 2 | ||||
-rw-r--r-- | components/script/dom/htmllinkelement.rs | 2 | ||||
-rw-r--r-- | components/script/dom/webidls/DOMTokenList.webidl | 9 |
7 files changed, 106 insertions, 22 deletions
diff --git a/components/script/dom/attr.rs b/components/script/dom/attr.rs index d1b288bd7ad..014fa5f5357 100644 --- a/components/script/dom/attr.rs +++ b/components/script/dom/attr.rs @@ -37,9 +37,21 @@ pub enum AttrValue { } impl AttrValue { - pub fn from_tokenlist(tokens: DOMString) -> AttrValue { - let atoms = split_html_space_chars(tokens.as_slice()) - .map(|token| Atom::from_slice(token)).collect(); + pub fn from_serialized_tokenlist(tokens: DOMString) -> AttrValue { + let mut atoms: Vec<Atom> = vec!(); + for token in split_html_space_chars(tokens.as_slice()).map(|slice| Atom::from_slice(slice)) { + if !atoms.iter().any(|atom| *atom == token) { + atoms.push(token); + } + } + AttrValue::TokenList(tokens, atoms) + } + + pub fn from_atomic_tokens(atoms: Vec<Atom>) -> AttrValue { + let tokens = { + let slices: Vec<&str> = atoms.iter().map(|atom| atom.as_slice()).collect(); + slices.connect("\x20") + }; AttrValue::TokenList(tokens, atoms) } diff --git a/components/script/dom/domtokenlist.rs b/components/script/dom/domtokenlist.rs index 6ba0307b14e..fc1ed509568 100644 --- a/components/script/dom/domtokenlist.rs +++ b/components/script/dom/domtokenlist.rs @@ -5,7 +5,7 @@ use dom::attr::{Attr, AttrHelpers}; use dom::bindings::codegen::Bindings::DOMTokenListBinding; use dom::bindings::codegen::Bindings::DOMTokenListBinding::DOMTokenListMethods; -use dom::bindings::error::Fallible; +use dom::bindings::error::{ErrorResult, Fallible}; use dom::bindings::error::Error::{InvalidCharacter, Syntax}; use dom::bindings::global::GlobalRef; use dom::bindings::js::{JS, JSRef, Temporary, OptionalRootable}; @@ -48,7 +48,7 @@ impl Reflectable for DOMTokenList { trait PrivateDOMTokenListHelpers { fn attribute(self) -> Option<Temporary<Attr>>; - fn check_token_exceptions<'a>(self, token: &'a str) -> Fallible<&'a str>; + fn check_token_exceptions<'a>(self, token: &'a str) -> Fallible<Atom>; } impl<'a> PrivateDOMTokenListHelpers for JSRef<'a, DOMTokenList> { @@ -57,11 +57,11 @@ impl<'a> PrivateDOMTokenListHelpers for JSRef<'a, DOMTokenList> { element.get_attribute(ns!(""), &self.local_name) } - fn check_token_exceptions<'a>(self, token: &'a str) -> Fallible<&'a str> { + fn check_token_exceptions<'a>(self, token: &'a str) -> Fallible<Atom> { match token { "" => Err(Syntax), - token if token.find(HTML_SPACE_CHARACTERS).is_some() => Err(InvalidCharacter), - token => Ok(token) + slice if slice.find(HTML_SPACE_CHARACTERS).is_some() => Err(InvalidCharacter), + slice => Ok(Atom::from_slice(slice)) } } } @@ -90,14 +90,67 @@ impl<'a> DOMTokenListMethods for JSRef<'a, DOMTokenList> { // http://dom.spec.whatwg.org/#dom-domtokenlist-contains fn Contains(self, token: DOMString) -> Fallible<bool> { - self.check_token_exceptions(token.as_slice()).map(|slice| { + self.check_token_exceptions(token.as_slice()).map(|token| { self.attribute().root().map(|attr| { - let value = attr.value(); - let tokens = value.tokens() - .expect("Should have parsed this attribute"); - let atom = Atom::from_slice(slice); - tokens.iter().any(|token| *token == atom) + attr.value() + .tokens() + .expect("Should have parsed this attribute") + .iter() + .any(|atom| *atom == token) }).unwrap_or(false) }) } + + // https://dom.spec.whatwg.org/#dom-domtokenlist-add + fn Add(self, tokens: Vec<DOMString>) -> ErrorResult { + let element = self.element.root(); + let mut atoms = element.get_tokenlist_attribute(&self.local_name); + for token in tokens.iter() { + let token = try!(self.check_token_exceptions(token.as_slice())); + if !atoms.iter().any(|atom| *atom == token) { + atoms.push(token); + } + } + element.set_atomic_tokenlist_attribute(&self.local_name, atoms); + Ok(()) + } + + // https://dom.spec.whatwg.org/#dom-domtokenlist-remove + fn Remove(self, tokens: Vec<DOMString>) -> ErrorResult { + let element = self.element.root(); + let mut atoms = element.get_tokenlist_attribute(&self.local_name); + for token in tokens.iter() { + let token = try!(self.check_token_exceptions(token.as_slice())); + atoms.iter().position(|atom| *atom == token).and_then(|index| { + atoms.remove(index) + }); + } + element.set_atomic_tokenlist_attribute(&self.local_name, atoms); + Ok(()) + } + + // https://dom.spec.whatwg.org/#dom-domtokenlist-toggle + fn Toggle(self, token: DOMString, force: Option<bool>) -> Fallible<bool> { + let element = self.element.root(); + let mut atoms = element.get_tokenlist_attribute(&self.local_name); + let token = try!(self.check_token_exceptions(token.as_slice())); + match atoms.iter().position(|atom| *atom == token) { + Some(index) => match force { + Some(true) => Ok(true), + _ => { + atoms.remove(index); + element.set_atomic_tokenlist_attribute(&self.local_name, atoms); + Ok(false) + } + }, + None => match force { + Some(false) => Ok(false), + _ => { + atoms.push(token); + element.set_atomic_tokenlist_attribute(&self.local_name, atoms); + Ok(true) + } + } + } + } } diff --git a/components/script/dom/element.rs b/components/script/dom/element.rs index 52a16fc6ea4..60c12399160 100644 --- a/components/script/dom/element.rs +++ b/components/script/dom/element.rs @@ -655,7 +655,9 @@ pub trait AttributeHandlers { fn set_url_attribute(self, name: &Atom, value: DOMString); fn get_string_attribute(self, name: &Atom) -> DOMString; fn set_string_attribute(self, name: &Atom, value: DOMString); + fn get_tokenlist_attribute(self, name: &Atom) -> Vec<Atom>; fn set_tokenlist_attribute(self, name: &Atom, value: DOMString); + fn set_atomic_tokenlist_attribute(self, name: &Atom, tokens: Vec<Atom>); fn get_uint_attribute(self, name: &Atom) -> u32; fn set_uint_attribute(self, name: &Atom, value: u32); } @@ -846,9 +848,23 @@ impl<'a> AttributeHandlers for JSRef<'a, Element> { self.set_attribute(name, AttrValue::String(value)); } + fn get_tokenlist_attribute(self, name: &Atom) -> Vec<Atom> { + self.get_attribute(ns!(""), name).root().map(|attr| { + attr.value() + .tokens() + .expect("Expected a TokenListAttrValue") + .to_vec() + }).unwrap_or(vec!()) + } + fn set_tokenlist_attribute(self, name: &Atom, value: DOMString) { assert!(name.as_slice() == name.as_slice().to_ascii_lower().as_slice()); - self.set_attribute(name, AttrValue::from_tokenlist(value)); + self.set_attribute(name, AttrValue::from_serialized_tokenlist(value)); + } + + fn set_atomic_tokenlist_attribute(self, name: &Atom, tokens: Vec<Atom>) { + assert!(name.as_slice() == name.as_slice().to_ascii_lower().as_slice()); + self.set_attribute(name, AttrValue::from_atomic_tokens(tokens)); } fn get_uint_attribute(self, name: &Atom) -> u32 { @@ -1290,7 +1306,7 @@ impl<'a> VirtualMethods for JSRef<'a, Element> { fn parse_plain_attribute(&self, name: &Atom, value: DOMString) -> AttrValue { match name { &atom!("id") => AttrValue::from_atomic(value), - &atom!("class") => AttrValue::from_tokenlist(value), + &atom!("class") => AttrValue::from_serialized_tokenlist(value), _ => self.super_type().unwrap().parse_plain_attribute(name, value), } } diff --git a/components/script/dom/htmlanchorelement.rs b/components/script/dom/htmlanchorelement.rs index 10d574672a3..c4e9558c359 100644 --- a/components/script/dom/htmlanchorelement.rs +++ b/components/script/dom/htmlanchorelement.rs @@ -93,7 +93,7 @@ impl<'a> VirtualMethods for JSRef<'a, HTMLAnchorElement> { fn parse_plain_attribute(&self, name: &Atom, value: DOMString) -> AttrValue { match name { - &atom!("rel") => AttrValue::from_tokenlist(value), + &atom!("rel") => AttrValue::from_serialized_tokenlist(value), _ => self.super_type().unwrap().parse_plain_attribute(name, value), } } diff --git a/components/script/dom/htmlareaelement.rs b/components/script/dom/htmlareaelement.rs index 1ede87d380d..4871f35dc2d 100644 --- a/components/script/dom/htmlareaelement.rs +++ b/components/script/dom/htmlareaelement.rs @@ -58,7 +58,7 @@ impl<'a> VirtualMethods for JSRef<'a, HTMLAreaElement> { fn parse_plain_attribute(&self, name: &Atom, value: DOMString) -> AttrValue { match name { - &atom!("rel") => AttrValue::from_tokenlist(value), + &atom!("rel") => AttrValue::from_serialized_tokenlist(value), _ => self.super_type().unwrap().parse_plain_attribute(name, value), } } diff --git a/components/script/dom/htmllinkelement.rs b/components/script/dom/htmllinkelement.rs index f84314b7008..1105d60c6c6 100644 --- a/components/script/dom/htmllinkelement.rs +++ b/components/script/dom/htmllinkelement.rs @@ -94,7 +94,7 @@ impl<'a> VirtualMethods for JSRef<'a, HTMLLinkElement> { fn parse_plain_attribute(&self, name: &Atom, value: DOMString) -> AttrValue { match name { - &atom!("rel") => AttrValue::from_tokenlist(value), + &atom!("rel") => AttrValue::from_serialized_tokenlist(value), _ => self.super_type().unwrap().parse_plain_attribute(name, value), } } diff --git a/components/script/dom/webidls/DOMTokenList.webidl b/components/script/dom/webidls/DOMTokenList.webidl index bc32f4bf256..4cdcea84255 100644 --- a/components/script/dom/webidls/DOMTokenList.webidl +++ b/components/script/dom/webidls/DOMTokenList.webidl @@ -10,9 +10,12 @@ interface DOMTokenList { [Throws] boolean contains(DOMString token); + [Throws] + void add(DOMString... tokens); + [Throws] + void remove(DOMString... tokens); + [Throws] + boolean toggle(DOMString token, optional boolean force); - //void add(DOMString... tokens); - //void remove(DOMString... tokens); - //boolean toggle(DOMString token, optional boolean force); //stringifier; }; |