diff options
-rw-r--r-- | src/components/script/dom/domtokenlist.rs | 23 | ||||
-rw-r--r-- | src/components/script/dom/webidls/DOMTokenList.webidl | 5 | ||||
-rw-r--r-- | src/test/content/test_domtokenlist.html | 45 | ||||
-rw-r--r-- | src/test/wpt/metadata/dom/interfaces.html.ini | 9 | ||||
-rw-r--r-- | src/test/wpt/metadata/dom/nodes/Element-classlist.html.ini | 39 |
5 files changed, 71 insertions, 50 deletions
diff --git a/src/components/script/dom/domtokenlist.rs b/src/components/script/dom/domtokenlist.rs index cf44d5f7abc..3d252d36731 100644 --- a/src/components/script/dom/domtokenlist.rs +++ b/src/components/script/dom/domtokenlist.rs @@ -5,14 +5,16 @@ use dom::attr::{Attr, TokenListAttrValue}; use dom::bindings::codegen::Bindings::DOMTokenListBinding; use dom::bindings::codegen::Bindings::DOMTokenListBinding::DOMTokenListMethods; +use dom::bindings::error::{Fallible, InvalidCharacter, Syntax}; use dom::bindings::global::Window; use dom::bindings::js::{JS, JSRef, Temporary, OptionalRootable}; use dom::bindings::utils::{Reflector, Reflectable, reflect_dom_object}; use dom::element::{Element, AttributeHandlers}; use dom::node::window_from_node; +use servo_util::atom::Atom; use servo_util::namespace::Null; -use servo_util::str::DOMString; +use servo_util::str::{DOMString, HTML_SPACE_CHARACTERS}; #[deriving(Encodable)] pub struct DOMTokenList { @@ -47,6 +49,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>; } impl<'a> PrivateDOMTokenListHelpers for JSRef<'a, DOMTokenList> { @@ -54,6 +57,14 @@ impl<'a> PrivateDOMTokenListHelpers for JSRef<'a, DOMTokenList> { let element = self.element.root(); element.deref().get_attribute(Null, self.local_name) } + + fn check_token_exceptions<'a>(&self, token: &'a str) -> Fallible<&'a str> { + match token { + "" => Err(Syntax), + token if token.find(HTML_SPACE_CHARACTERS).is_some() => Err(InvalidCharacter), + token => Ok(token) + } + } } // http://dom.spec.whatwg.org/#domtokenlist @@ -92,4 +103,14 @@ impl<'a> DOMTokenListMethods for JSRef<'a, DOMTokenList> { *found = item.is_some(); item } + + // 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.attribute().root().and_then(|attr| attr.value().tokens().map(|mut tokens| { + let atom = Atom::from_slice(slice); + tokens.any(|token| *token == atom) + })).unwrap_or(false) + }) + } } diff --git a/src/components/script/dom/webidls/DOMTokenList.webidl b/src/components/script/dom/webidls/DOMTokenList.webidl index 650d8abf6c6..bc32f4bf256 100644 --- a/src/components/script/dom/webidls/DOMTokenList.webidl +++ b/src/components/script/dom/webidls/DOMTokenList.webidl @@ -7,7 +7,10 @@ interface DOMTokenList { readonly attribute unsigned long length; getter DOMString? item(unsigned long index); - //boolean contains(DOMString token); + + [Throws] + boolean contains(DOMString token); + //void add(DOMString... tokens); //void remove(DOMString... tokens); //boolean toggle(DOMString token, optional boolean force); diff --git a/src/test/content/test_domtokenlist.html b/src/test/content/test_domtokenlist.html new file mode 100644 index 00000000000..bc32777ec0e --- /dev/null +++ b/src/test/content/test_domtokenlist.html @@ -0,0 +1,45 @@ +<!DOCTYPE html> +<html> + <head> + <script src="harness.js"></script> + <script> + var div = document.createElement("div"); + var classList = div.classList; + + is(classList.length, 0); + is(classList.item(0), null); + should_throw(function () { + classList.contains(""); + }); + should_throw(function () { + classList.contains(" "); + }); + + var list = ["foo", " foo", "foo ", " foo ", " foo "]; + for(var i = 0; i < list.length; i++) { + div.className = list[i]; + is(div.className, list[i]); + is(classList.length, 1); + is(classList.item(0), "foo"); + is(classList.item(1), null); + is(classList.contains("foo"), true); + is(classList.contains("bar"), false); + } + + list = ["foo bar", " foo bar", " foo bar ", " foo bar "]; + for(var i = 0; i < list.length; i++) { + div.className = list[i]; + is(div.className, list[i]); + is(classList.length, 2); + is(classList.item(0), "foo"); + is(classList.item(1), "bar"); + is(classList.item(2), null); + is(classList.contains("foo"), true); + is(classList.contains("bar"), true); + is(classList.contains("baz"), false); + } + + finish(); + </script> + </head> +</html> diff --git a/src/test/wpt/metadata/dom/interfaces.html.ini b/src/test/wpt/metadata/dom/interfaces.html.ini index f534ec23922..53d11f5d15f 100644 --- a/src/test/wpt/metadata/dom/interfaces.html.ini +++ b/src/test/wpt/metadata/dom/interfaces.html.ini @@ -1017,9 +1017,6 @@ [TreeWalker interface: document.createTreeWalker(document.body, NodeFilter.SHOW_ALL, null, false) must inherit property "nextNode" with the proper type (10)] expected: FAIL - [DOMTokenList interface: operation contains(DOMString)] - expected: FAIL - [DOMTokenList interface: operation add(DOMString)] expected: FAIL @@ -1029,12 +1026,6 @@ [DOMTokenList interface: operation toggle(DOMString,boolean)] expected: FAIL - [DOMTokenList interface: document.body.classList must inherit property "contains" with the proper type (2)] - expected: FAIL - - [DOMTokenList interface: calling contains(DOMString) on document.body.classList with too few arguments must throw TypeError] - expected: FAIL - [DOMTokenList interface: document.body.classList must inherit property "add" with the proper type (3)] expected: FAIL diff --git a/src/test/wpt/metadata/dom/nodes/Element-classlist.html.ini b/src/test/wpt/metadata/dom/nodes/Element-classlist.html.ini index 61f7cd11fbf..b1c1947cac2 100644 --- a/src/test/wpt/metadata/dom/nodes/Element-classlist.html.ini +++ b/src/test/wpt/metadata/dom/nodes/Element-classlist.html.ini @@ -6,24 +6,9 @@ [classList must be correct for an element that has classes] expected: FAIL - [classList.length must be 0 for an element that has no classes] - expected: FAIL - - [classList must not contain an undefined class] - expected: FAIL - - [classList.item() must return null for out-of-range index] - expected: FAIL - - [classList[index\] must be undefined for out-of-range index] - expected: FAIL - [empty classList should return the empty string since the ordered set parser skip the whitespaces] expected: FAIL - [.contains(empty_string) must throw a SYNTAX_ERR] - expected: FAIL - [.add(empty_string) must throw a SYNTAX_ERR] expected: FAIL @@ -33,9 +18,6 @@ [.toggle(empty_string) must throw a SYNTAX_ERR] expected: FAIL - [.contains(string_with_spaces) must throw an INVALID_CHARACTER_ERR] - expected: FAIL - [.add(string_with_spaces) must throw an INVALID_CHARACTER_ERR] expected: FAIL @@ -48,36 +30,18 @@ [computed style must update when setting .className] expected: FAIL - [classList.contains must update when .className is changed] - expected: FAIL - - [classList.contains must be case sensitive] - expected: FAIL - - [classList.contains must not match when punctuation characters are added] - expected: FAIL - [classList.add must not cause the CSS selector to stop matching] expected: FAIL - [classList.add must not remove existing classes] - expected: FAIL - [classList.contains case sensitivity must match a case-specific string] expected: FAIL [classList.length must correctly reflect the number of tokens] expected: FAIL - [classList.item(0) must return the first token] - expected: FAIL - [classList.item must return case-sensitive strings and preserve token order] expected: FAIL - [classList[0\] must return the first token] - expected: FAIL - [classList[index\] must return case-sensitive strings and preserve token order] expected: FAIL @@ -153,6 +117,3 @@ [classList.add should treat \\f as a space] expected: FAIL - [classList.length must be read-only] - expected: FAIL - |