Use atom to match id selector.

This commit is contained in:
Tetsuharu OHZEKI 2014-07-26 04:33:54 +09:00
parent f2db7faf19
commit 794ce9cd4d
6 changed files with 51 additions and 10 deletions

View file

@ -393,6 +393,11 @@ impl<'le> TElement for LayoutElement<'le> {
self.element.node.get_hover_state_for_layout() self.element.node.get_hover_state_for_layout()
} }
} }
#[inline]
fn get_id(&self) -> Option<Atom> {
unsafe { self.element.get_attr_atom_for_layout(&namespace::Null, "id") }
}
} }
fn get_content(content_list: &content::T) -> String { fn get_content(content_list: &content::T) -> String {

View file

@ -167,6 +167,7 @@ impl<'a> AttrMethods for JSRef<'a, Attr> {
pub trait AttrHelpersForLayout { pub trait AttrHelpersForLayout {
unsafe fn value_ref_forever(&self) -> &'static str; unsafe fn value_ref_forever(&self) -> &'static str;
unsafe fn value_atom_forever(&self) -> Option<Atom>;
} }
impl AttrHelpersForLayout for Attr { impl AttrHelpersForLayout for Attr {
@ -175,4 +176,13 @@ impl AttrHelpersForLayout for Attr {
let value = mem::transmute::<&RefCell<AttrValue>, &AttrValue>(self.value.deref()); let value = mem::transmute::<&RefCell<AttrValue>, &AttrValue>(self.value.deref());
value.as_slice() value.as_slice()
} }
unsafe fn value_atom_forever(&self) -> Option<Atom> {
// cast to point to T in RefCell<T> directly
let value = mem::transmute::<&RefCell<AttrValue>, &AttrValue>(self.value.deref());
match *value {
AtomAttrValue(ref val) => Some(val.clone()),
_ => None,
}
}
} }

View file

@ -6,7 +6,7 @@
use cssparser::tokenize; use cssparser::tokenize;
use dom::attr::{Attr, ReplacedAttr, FirstSetAttr, AttrHelpersForLayout}; use dom::attr::{Attr, ReplacedAttr, FirstSetAttr, AttrHelpersForLayout};
use dom::attr::{AttrValue, StringAttrValue, UIntAttrValue}; use dom::attr::{AttrValue, StringAttrValue, UIntAttrValue, AtomAttrValue};
use dom::attrlist::AttrList; use dom::attrlist::AttrList;
use dom::bindings::codegen::Bindings::AttrBinding::AttrMethods; use dom::bindings::codegen::Bindings::AttrBinding::AttrMethods;
use dom::bindings::codegen::Bindings::ElementBinding; use dom::bindings::codegen::Bindings::ElementBinding;
@ -168,6 +168,7 @@ impl Element {
pub trait RawLayoutElementHelpers { pub trait RawLayoutElementHelpers {
unsafe fn get_attr_val_for_layout(&self, namespace: &Namespace, name: &str) -> Option<&'static str>; unsafe fn get_attr_val_for_layout(&self, namespace: &Namespace, name: &str) -> Option<&'static str>;
unsafe fn get_attr_atom_for_layout(&self, namespace: &Namespace, name: &str) -> Option<Atom>;
} }
impl RawLayoutElementHelpers for Element { impl RawLayoutElementHelpers for Element {
@ -184,6 +185,20 @@ impl RawLayoutElementHelpers for Element {
(*attr).value_ref_forever() (*attr).value_ref_forever()
}) })
} }
#[inline]
unsafe fn get_attr_atom_for_layout(&self, namespace: &Namespace, name: &str)
-> Option<Atom> {
// cast to point to T in RefCell<T> directly
let attrs: *Vec<JS<Attr>> = mem::transmute(&self.attrs);
(*attrs).iter().find(|attr: & &JS<Attr>| {
let attr = attr.unsafe_get();
name == (*attr).local_name.as_slice() && (*attr).namespace == *namespace
}).and_then(|attr| {
let attr = attr.unsafe_get();
(*attr).value_atom_forever()
})
}
} }
pub trait LayoutElementHelpers { pub trait LayoutElementHelpers {
@ -901,4 +916,13 @@ impl<'a> style::TElement for JSRef<'a, Element> {
let node: &JSRef<Node> = NodeCast::from_ref(self); let node: &JSRef<Node> = NodeCast::from_ref(self);
node.get_hover_state() node.get_hover_state()
} }
fn get_id<'a>(&self) -> Option<Atom> {
self.get_attribute(namespace::Null, "id").map(|attr| {
let attr = attr.root();
match *attr.value() {
AtomAttrValue(ref val) => val.clone(),
_ => fail!("`id` attribute should be AtomAttrValue"),
}
})
}
} }

View file

@ -26,5 +26,6 @@ pub trait TElement {
fn get_local_name<'a>(&'a self) -> &'a Atom; fn get_local_name<'a>(&'a self) -> &'a Atom;
fn get_namespace<'a>(&'a self) -> &'a Namespace; fn get_namespace<'a>(&'a self) -> &'a Namespace;
fn get_hover_state(&self) -> bool; fn get_hover_state(&self) -> bool;
fn get_id(&self) -> Option<Atom>;
} }

View file

@ -267,7 +267,7 @@ impl SelectorMap {
match *ss { match *ss {
// TODO(pradeep): Implement case-sensitivity based on the document type and quirks // TODO(pradeep): Implement case-sensitivity based on the document type and quirks
// mode. // mode.
IDSelector(ref id) => return Some(id.clone()), IDSelector(ref id) => return Some(id.as_slice().clone().to_string()),
_ => {} _ => {}
} }
} }
@ -691,9 +691,8 @@ fn matches_simple_selector<E:TElement,
IDSelector(ref id) => { IDSelector(ref id) => {
*shareable = false; *shareable = false;
let element = element.as_element(); let element = element.as_element();
element.get_attr(&namespace::Null, "id") element.get_id().map_or(false, |attr| {
.map_or(false, |attr| { attr == *id
attr == id.as_slice()
}) })
} }
// TODO: cache and intern class names on elements. // TODO: cache and intern class names on elements.

View file

@ -10,6 +10,7 @@ use sync::Arc;
use cssparser::ast::*; use cssparser::ast::*;
use cssparser::parse_nth; use cssparser::parse_nth;
use servo_util::atom::Atom;
use servo_util::namespace::Namespace; use servo_util::namespace::Namespace;
use servo_util::namespace; use servo_util::namespace;
@ -56,7 +57,7 @@ pub enum Combinator {
#[deriving(PartialEq, Clone)] #[deriving(PartialEq, Clone)]
pub enum SimpleSelector { pub enum SimpleSelector {
IDSelector(String), IDSelector(Atom),
ClassSelector(String), ClassSelector(String),
LocalNameSelector(String), LocalNameSelector(String),
NamespaceSelector(Namespace), NamespaceSelector(Namespace),
@ -306,7 +307,7 @@ fn parse_one_simple_selector(iter: &mut Iter, namespaces: &NamespaceMap, inside_
-> SimpleSelectorParseResult { -> SimpleSelectorParseResult {
match iter.peek() { match iter.peek() {
Some(&IDHash(_)) => match iter.next() { Some(&IDHash(_)) => match iter.next() {
Some(IDHash(id)) => SimpleSelectorResult(IDSelector(id)), Some(IDHash(id)) => SimpleSelectorResult(IDSelector(Atom::from_slice(id.as_slice()))),
_ => fail!("Implementation error, this should not happen."), _ => fail!("Implementation error, this should not happen."),
}, },
Some(&Delim('.')) => { Some(&Delim('.')) => {
@ -572,6 +573,7 @@ fn skip_whitespace(iter: &mut Iter) -> bool {
mod tests { mod tests {
use sync::Arc; use sync::Arc;
use cssparser; use cssparser;
use servo_util::atom::Atom;
use servo_util::namespace; use servo_util::namespace;
use namespaces::NamespaceMap; use namespaces::NamespaceMap;
use super::*; use super::*;
@ -611,7 +613,7 @@ mod tests {
}))) })))
assert!(parse("#bar") == Some(vec!(Selector{ assert!(parse("#bar") == Some(vec!(Selector{
compound_selectors: Arc::new(CompoundSelector { compound_selectors: Arc::new(CompoundSelector {
simple_selectors: vec!(IDSelector("bar".to_string())), simple_selectors: vec!(IDSelector(Atom::from_slice("bar"))),
next: None, next: None,
}), }),
pseudo_element: None, pseudo_element: None,
@ -621,7 +623,7 @@ mod tests {
compound_selectors: Arc::new(CompoundSelector { compound_selectors: Arc::new(CompoundSelector {
simple_selectors: vec!(LocalNameSelector("e".to_string()), simple_selectors: vec!(LocalNameSelector("e".to_string()),
ClassSelector("foo".to_string()), ClassSelector("foo".to_string()),
IDSelector("bar".to_string())), IDSelector(Atom::from_slice("bar"))),
next: None, next: None,
}), }),
pseudo_element: None, pseudo_element: None,
@ -629,7 +631,7 @@ mod tests {
}))) })))
assert!(parse("e.foo #bar") == Some(vec!(Selector{ assert!(parse("e.foo #bar") == Some(vec!(Selector{
compound_selectors: Arc::new(CompoundSelector { compound_selectors: Arc::new(CompoundSelector {
simple_selectors: vec!(IDSelector("bar".to_string())), simple_selectors: vec!(IDSelector(Atom::from_slice("bar"))),
next: Some((box CompoundSelector { next: Some((box CompoundSelector {
simple_selectors: vec!(LocalNameSelector("e".to_string()), simple_selectors: vec!(LocalNameSelector("e".to_string()),
ClassSelector("foo".to_string())), ClassSelector("foo".to_string())),