diff options
author | Tim Taubert <tim@timtaubert.de> | 2014-10-06 16:02:19 +0200 |
---|---|---|
committer | Tim Taubert <tim@timtaubert.de> | 2014-10-08 11:01:31 +0200 |
commit | b9e23563bb9940ece621d3f6a969a5e08e1bd82b (patch) | |
tree | 981ee905456f2cb51975f6955ae75344569ec8fc | |
parent | 070b6046aa9a7869e2ca53f69d7a349afbec09c4 (diff) | |
download | servo-b9e23563bb9940ece621d3f6a969a5e08e1bd82b.tar.gz servo-b9e23563bb9940ece621d3f6a969a5e08e1bd82b.zip |
Support [*|attr], attribute selectors in any namespace (fixes #1558)
-rw-r--r-- | components/layout/wrapper.rs | 11 | ||||
-rw-r--r-- | components/script/dom/element.rs | 39 | ||||
-rw-r--r-- | components/script/dom/node.rs | 10 | ||||
-rw-r--r-- | components/style/node.rs | 1 | ||||
-rw-r--r-- | tests/ref/attr_exists_selector.html | 4 | ||||
-rw-r--r-- | tests/ref/attr_exists_selector_ref.html | 1 | ||||
-rw-r--r-- | tests/ref/noteq_attr_exists_selector.html | 1 |
7 files changed, 57 insertions, 10 deletions
diff --git a/components/layout/wrapper.rs b/components/layout/wrapper.rs index 40a77935129..c9f9df91bec 100644 --- a/components/layout/wrapper.rs +++ b/components/layout/wrapper.rs @@ -310,8 +310,10 @@ impl<'ln> TNode<'ln, LayoutElement<'ln>> for LayoutNode<'ln> { element.get_attr(ns, name) .map_or(false, |attr| test(attr)) }, - // FIXME: https://github.com/mozilla/servo/issues/1558 - AnyNamespace => false, + AnyNamespace => { + let element = self.as_element(); + element.get_attrs(name).iter().any(|attr| test(*attr)) + } } } @@ -414,6 +416,11 @@ impl<'le> TElement<'le> for LayoutElement<'le> { unsafe { self.element.get_attr_val_for_layout(namespace, name) } } + #[inline] + fn get_attrs(self, name: &str) -> Vec<&'le str> { + unsafe { self.element.get_attr_vals_for_layout(name) } + } + fn get_link(self) -> Option<&'le str> { // FIXME: This is HTML only. match self.element.node.type_id_for_layout() { diff --git a/components/script/dom/element.rs b/components/script/dom/element.rs index a3960116ab2..681951136a0 100644 --- a/components/script/dom/element.rs +++ b/components/script/dom/element.rs @@ -170,6 +170,7 @@ impl Element { pub trait RawLayoutElementHelpers { unsafe fn get_attr_val_for_layout<'a>(&'a self, namespace: &Namespace, name: &str) -> Option<&'a str>; + unsafe fn get_attr_vals_for_layout<'a>(&'a self, name: &str) -> Vec<&'a str>; unsafe fn get_attr_atom_for_layout(&self, namespace: &Namespace, name: &str) -> Option<Atom>; unsafe fn has_class_for_layout(&self, name: &str) -> bool; } @@ -193,6 +194,21 @@ impl RawLayoutElementHelpers for Element { #[inline] #[allow(unrooted_must_root)] + unsafe fn get_attr_vals_for_layout<'a>(&'a self, name: &str) -> Vec<&'a str> { + // cast to point to T in RefCell<T> directly + let attrs: *const Vec<JS<Attr>> = mem::transmute(&self.attrs); + (*attrs).iter().filter_map(|attr: &JS<Attr>| { + let attr = attr.unsafe_get(); + if name == (*attr).local_name_atom_forever().as_slice() { + Some((*attr).value_ref_forever()) + } else { + None + } + }).collect() + } + + #[inline] + #[allow(unrooted_must_root)] unsafe fn get_attr_atom_for_layout(&self, namespace: &Namespace, name: &str) -> Option<Atom> { // cast to point to T in RefCell<T> directly @@ -291,6 +307,8 @@ pub trait AttributeHandlers { /// name, if any. fn get_attribute(self, namespace: Namespace, local_name: &str) -> Option<Temporary<Attr>>; + fn get_attributes(self, local_name: &str) + -> Vec<Temporary<Attr>>; fn set_attribute_from_parser(self, local_name: Atom, value: DOMString, namespace: Namespace, prefix: Option<DOMString>); @@ -321,10 +339,20 @@ pub trait AttributeHandlers { impl<'a> AttributeHandlers for JSRef<'a, Element> { fn get_attribute(self, namespace: Namespace, local_name: &str) -> Option<Temporary<Attr>> { + self.get_attributes(local_name).iter().map(|attr| attr.root()) + .find(|attr| attr.namespace == namespace) + .map(|x| Temporary::from_rooted(*x)) + } + + fn get_attributes(self, local_name: &str) -> Vec<Temporary<Attr>> { let local_name = Atom::from_slice(local_name); - self.attrs.borrow().iter().map(|attr| attr.root()).find(|attr| { - *attr.local_name() == local_name && attr.namespace == namespace - }).map(|x| Temporary::from_rooted(*x)) + self.attrs.borrow().iter().map(|attr| attr.root()).filter_map(|attr| { + if *attr.local_name() == local_name { + Some(Temporary::from_rooted(*attr)) + } else { + None + } + }).collect() } fn set_attribute_from_parser(self, local_name: Atom, @@ -947,6 +975,11 @@ impl<'a> style::TElement<'a> for JSRef<'a, Element> { unsafe { mem::transmute(attr.deref().value().as_slice()) } }) } + fn get_attrs(self, attr: &str) -> Vec<&'a str> { + self.get_attributes(attr).iter().map(|attr| attr.root()).map(|attr| { + unsafe { mem::transmute(attr.deref().value().as_slice()) } + }).collect() + } fn get_link(self) -> Option<&'a str> { // FIXME: This is HTML only. let node: JSRef<Node> = NodeCast::from_ref(self); diff --git a/components/script/dom/node.rs b/components/script/dom/node.rs index b8319bd0da4..fdee69fbf3e 100644 --- a/components/script/dom/node.rs +++ b/components/script/dom/node.rs @@ -5,7 +5,6 @@ //! The core DOM types. Defines the basic DOM hierarchy as well as all the HTML elements. use dom::attr::{Attr, AttrHelpers}; -use dom::bindings::codegen::Bindings::AttrBinding::AttrMethods; use dom::bindings::codegen::Bindings::CharacterDataBinding::CharacterDataMethods; use dom::bindings::codegen::Bindings::DocumentBinding::DocumentMethods; use dom::bindings::codegen::Bindings::ElementBinding::ElementMethods; @@ -2115,10 +2114,13 @@ impl<'a> style::TNode<'a, JSRef<'a, Element>> for JSRef<'a, Node> { match attr.namespace { style::SpecificNamespace(ref ns) => { self.as_element().get_attribute(ns.clone(), name).root() - .map_or(false, |attr| test(attr.deref().Value().as_slice())) + .map_or(false, |attr| test(attr.deref().value().as_slice())) }, - // FIXME: https://github.com/mozilla/servo/issues/1558 - style::AnyNamespace => false, + style::AnyNamespace => { + self.as_element().get_attributes(name).iter() + .map(|attr| attr.root()) + .any(|attr| test(attr.deref().value().as_slice())) + } } } diff --git a/components/style/node.rs b/components/style/node.rs index 75d098563c2..450e6655e35 100644 --- a/components/style/node.rs +++ b/components/style/node.rs @@ -23,6 +23,7 @@ pub trait TNode<'a, E: TElement<'a>> : Clone + Copy { pub trait TElement<'a> : Copy { fn get_attr(self, namespace: &Namespace, attr: &str) -> Option<&'a str>; + fn get_attrs(self, attr: &str) -> Vec<&'a str>; fn get_link(self) -> Option<&'a str>; fn get_local_name(self) -> &'a Atom; fn get_namespace(self) -> &'a Namespace; diff --git a/tests/ref/attr_exists_selector.html b/tests/ref/attr_exists_selector.html index 6d8f01e16aa..43ad48bb62a 100644 --- a/tests/ref/attr_exists_selector.html +++ b/tests/ref/attr_exists_selector.html @@ -1,13 +1,15 @@ <!DOCTYPE html> <html> <head> - <title>Attribute exists selector: [foo]</title> + <title>Attribute exists selector: [foo] and [*|foo]</title> <style> p[data-green] { color: green } + p[*|data-red] { color: red } </style> </head> <body> <p data-green="">This text should be green.</p> + <p data-red="">This text should be red.</p> <p>This text should be black.</p> </body> </html> diff --git a/tests/ref/attr_exists_selector_ref.html b/tests/ref/attr_exists_selector_ref.html index 522883d8ed4..ba75fc54945 100644 --- a/tests/ref/attr_exists_selector_ref.html +++ b/tests/ref/attr_exists_selector_ref.html @@ -5,6 +5,7 @@ </head> <body> <p style="color: green">This text should be green.</p> + <p style="color: red">This text should be red.</p> <p>This text should be black.</p> </body> </html> diff --git a/tests/ref/noteq_attr_exists_selector.html b/tests/ref/noteq_attr_exists_selector.html index 58bce6d5d39..c335c166985 100644 --- a/tests/ref/noteq_attr_exists_selector.html +++ b/tests/ref/noteq_attr_exists_selector.html @@ -5,6 +5,7 @@ </head> <body> <p>This text should be green.</p> + <p>This text should be red.</p> <p>This text should be black.</p> </body> </html> |