mirror of
https://github.com/mozilla/gecko-dev.git
synced 2024-10-20 16:55:40 +00:00
servo: Merge #3584 - Support [*|attr], attribute selectors in any namespace (fixes #1558) (from ttaubert:issue/1558-attr-ns-selectors); r=Manishearth
This implements basic support for attribute selectors with namespace prefixes. I would have added a more sophisticated test covering various selectors but it seems that we don't have an XML parser yet and thus no XHTML support? r? @SimonSapin Source-Repo: https://github.com/servo/servo Source-Revision: f49c730720a51d14dacefe9815faf50216b36b91
This commit is contained in:
parent
4418d703bc
commit
17eeb55b66
@ -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() {
|
||||
|
@ -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;
|
||||
}
|
||||
@ -191,6 +192,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)
|
||||
@ -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);
|
||||
|
@ -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()))
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -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;
|
||||
|
Loading…
Reference in New Issue
Block a user