mirror of
https://github.com/servo/servo.git
synced 2025-08-06 22:15:33 +01:00
Merge pull request #2927 from saneyuki/id_atom
Port `id` attribute to use atom.
This commit is contained in:
commit
43d176f653
6 changed files with 68 additions and 11 deletions
|
@ -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 {
|
||||||
|
|
|
@ -30,6 +30,7 @@ pub enum AttrValue {
|
||||||
StringAttrValue(DOMString),
|
StringAttrValue(DOMString),
|
||||||
TokenListAttrValue(DOMString, Vec<(uint, uint)>),
|
TokenListAttrValue(DOMString, Vec<(uint, uint)>),
|
||||||
UIntAttrValue(DOMString, u32),
|
UIntAttrValue(DOMString, u32),
|
||||||
|
AtomAttrValue(Atom),
|
||||||
}
|
}
|
||||||
|
|
||||||
impl AttrValue {
|
impl AttrValue {
|
||||||
|
@ -50,11 +51,17 @@ impl AttrValue {
|
||||||
UIntAttrValue(string, result)
|
UIntAttrValue(string, result)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
pub fn from_atomic(string: DOMString) -> AttrValue {
|
||||||
|
let value = Atom::from_slice(string.as_slice());
|
||||||
|
AtomAttrValue(value)
|
||||||
|
}
|
||||||
|
|
||||||
pub fn as_slice<'a>(&'a self) -> &'a str {
|
pub fn as_slice<'a>(&'a self) -> &'a str {
|
||||||
match *self {
|
match *self {
|
||||||
StringAttrValue(ref value) |
|
StringAttrValue(ref value) |
|
||||||
TokenListAttrValue(ref value, _) |
|
TokenListAttrValue(ref value, _) |
|
||||||
UIntAttrValue(ref value, _) => value.as_slice(),
|
UIntAttrValue(ref value, _) => value.as_slice(),
|
||||||
|
AtomAttrValue(ref value) => value.as_slice(),
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -160,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 {
|
||||||
|
@ -168,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,
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -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 {
|
||||||
|
@ -239,6 +254,8 @@ pub trait AttributeHandlers {
|
||||||
fn notify_attribute_changed(&self, local_name: DOMString);
|
fn notify_attribute_changed(&self, local_name: DOMString);
|
||||||
fn has_class(&self, name: &str) -> bool;
|
fn has_class(&self, name: &str) -> bool;
|
||||||
|
|
||||||
|
fn set_atomic_attribute(&self, name: &str, value: DOMString);
|
||||||
|
|
||||||
// http://www.whatwg.org/html/#reflecting-content-attributes-in-idl-attributes
|
// http://www.whatwg.org/html/#reflecting-content-attributes-in-idl-attributes
|
||||||
fn get_url_attribute(&self, name: &str) -> DOMString;
|
fn get_url_attribute(&self, name: &str) -> DOMString;
|
||||||
fn set_url_attribute(&self, name: &str, value: DOMString);
|
fn set_url_attribute(&self, name: &str, value: DOMString);
|
||||||
|
@ -362,6 +379,12 @@ impl<'a> AttributeHandlers for JSRef<'a, Element> {
|
||||||
classes.any(|class| name == class)
|
classes.any(|class| name == class)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
fn set_atomic_attribute(&self, name: &str, value: DOMString) {
|
||||||
|
assert!(name == name.to_ascii_lower().as_slice());
|
||||||
|
let value = AttrValue::from_atomic(value);
|
||||||
|
self.set_attribute(name, value);
|
||||||
|
}
|
||||||
|
|
||||||
fn get_url_attribute(&self, name: &str) -> DOMString {
|
fn get_url_attribute(&self, name: &str) -> DOMString {
|
||||||
// XXX Resolve URL.
|
// XXX Resolve URL.
|
||||||
self.get_string_attribute(name)
|
self.get_string_attribute(name)
|
||||||
|
@ -459,7 +482,7 @@ impl<'a> ElementMethods for JSRef<'a, Element> {
|
||||||
|
|
||||||
// http://dom.spec.whatwg.org/#dom-element-id
|
// http://dom.spec.whatwg.org/#dom-element-id
|
||||||
fn SetId(&self, id: DOMString) {
|
fn SetId(&self, id: DOMString) {
|
||||||
self.set_string_attribute("id", id);
|
self.set_atomic_attribute("id", id);
|
||||||
}
|
}
|
||||||
|
|
||||||
// http://dom.spec.whatwg.org/#dom-element-classname
|
// http://dom.spec.whatwg.org/#dom-element-classname
|
||||||
|
@ -824,6 +847,7 @@ impl<'a> VirtualMethods for JSRef<'a, Element> {
|
||||||
|
|
||||||
fn parse_plain_attribute(&self, name: &str, value: DOMString) -> AttrValue {
|
fn parse_plain_attribute(&self, name: &str, value: DOMString) -> AttrValue {
|
||||||
match name {
|
match name {
|
||||||
|
"id" => AttrValue::from_atomic(value),
|
||||||
"class" => AttrValue::from_tokenlist(value),
|
"class" => AttrValue::from_tokenlist(value),
|
||||||
_ => self.super_type().unwrap().parse_plain_attribute(name, value),
|
_ => self.super_type().unwrap().parse_plain_attribute(name, value),
|
||||||
}
|
}
|
||||||
|
@ -892,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"),
|
||||||
|
}
|
||||||
|
})
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -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>;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -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.
|
||||||
|
|
|
@ -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())),
|
||||||
|
|
Loading…
Add table
Add a link
Reference in a new issue