aboutsummaryrefslogtreecommitdiffstats
path: root/components/script
diff options
context:
space:
mode:
authorbors-servo <metajack+bors@gmail.com>2014-12-26 13:18:45 -0700
committerbors-servo <metajack+bors@gmail.com>2014-12-26 13:18:45 -0700
commit3af73e9962fe810de0c556693ec2eb0559b06a67 (patch)
tree3a6220ae9a6c05c5b43bdf5fc6f822e597e39d7a /components/script
parent0e6304dcf7fd6712f4455151b55a361de857359d (diff)
parent3624673d2faf7a36face3321af70fc55117a24a7 (diff)
downloadservo-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.rs18
-rw-r--r--components/script/dom/domtokenlist.rs75
-rw-r--r--components/script/dom/element.rs20
-rw-r--r--components/script/dom/htmlanchorelement.rs2
-rw-r--r--components/script/dom/htmlareaelement.rs2
-rw-r--r--components/script/dom/htmllinkelement.rs2
-rw-r--r--components/script/dom/webidls/DOMTokenList.webidl9
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;
};