зеркало из https://github.com/mozilla/gecko-dev.git
servo: Merge #3623 - script: Use atom comparison in more places, especially for attributes (from pcwalton:use-atoms-2); r=jdm
75% improvement in style recalc for Guardians of the Galaxy. Source-Repo: https://github.com/servo/servo Source-Revision: 8077edc0622b04aeb26d42ced86ea285c9cac0e7
This commit is contained in:
Родитель
ee7c17eaa4
Коммит
7495bb838a
|
@ -226,7 +226,7 @@ impl<'a> FlowConstructor<'a> {
|
|||
//FIXME: would it make more sense to use HTMLInputElement::input_type instead of the raw
|
||||
// value? definitely for string comparisons.
|
||||
let elem = node.as_element();
|
||||
let data = match elem.get_attr(&ns!(""), "type") {
|
||||
let data = match elem.get_attr(&ns!(""), &atom!("type")) {
|
||||
Some("checkbox") | Some("radio") => None,
|
||||
Some("button") | Some("submit") | Some("reset") =>
|
||||
Some(node.get_input_value().len() as u32),
|
||||
|
@ -1158,7 +1158,7 @@ trait ObjectElement<'a> {
|
|||
impl<'ln> ObjectElement<'ln> for ThreadSafeLayoutNode<'ln> {
|
||||
fn get_type_and_data(&self) -> (Option<&'ln str>, Option<&'ln str>) {
|
||||
let elem = self.as_element();
|
||||
(elem.get_attr(&ns!(""), "type"), elem.get_attr(&ns!(""), "data"))
|
||||
(elem.get_attr(&ns!(""), &atom!("type")), elem.get_attr(&ns!(""), &atom!("data")))
|
||||
}
|
||||
|
||||
fn has_object_data(&self) -> bool {
|
||||
|
|
|
@ -15,7 +15,6 @@ use script::dom::node::{TextNodeTypeId};
|
|||
use servo_util::bloom::BloomFilter;
|
||||
use servo_util::cache::{Cache, LRUCache, SimpleHashCache};
|
||||
use servo_util::smallvec::{SmallVec, SmallVec16};
|
||||
use servo_util::str::DOMString;
|
||||
use std::mem;
|
||||
use std::hash::{Hash, sip};
|
||||
use std::slice::Items;
|
||||
|
@ -165,7 +164,8 @@ pub struct StyleSharingCandidate {
|
|||
pub style: Arc<ComputedValues>,
|
||||
pub parent_style: Arc<ComputedValues>,
|
||||
pub local_name: Atom,
|
||||
pub class: Option<DOMString>,
|
||||
// FIXME(pcwalton): Should be a list of atoms instead.
|
||||
pub class: Option<String>,
|
||||
}
|
||||
|
||||
impl PartialEq for StyleSharingCandidate {
|
||||
|
@ -222,7 +222,7 @@ impl StyleSharingCandidate {
|
|||
style: style,
|
||||
parent_style: parent_style,
|
||||
local_name: element.get_local_name().clone(),
|
||||
class: element.get_attr(&ns!(""), "class")
|
||||
class: element.get_attr(&ns!(""), &atom!("class"))
|
||||
.map(|string| string.to_string()),
|
||||
})
|
||||
}
|
||||
|
@ -231,10 +231,12 @@ impl StyleSharingCandidate {
|
|||
if *element.get_local_name() != self.local_name {
|
||||
return false
|
||||
}
|
||||
match (&self.class, element.get_attr(&ns!(""), "class")) {
|
||||
|
||||
// FIXME(pcwalton): Use `each_class` here instead of slow string comparison.
|
||||
match (&self.class, element.get_attr(&ns!(""), &atom!("class"))) {
|
||||
(&None, Some(_)) | (&Some(_), None) => return false,
|
||||
(&Some(ref this_class), Some(element_class))
|
||||
if element_class != this_class.as_slice() => {
|
||||
(&Some(ref this_class), Some(element_class)) if
|
||||
element_class != this_class.as_slice() => {
|
||||
return false
|
||||
}
|
||||
(&Some(_), Some(_)) | (&None, None) => {}
|
||||
|
@ -457,7 +459,8 @@ impl<'ln> MatchMethods for LayoutNode<'ln> {
|
|||
}
|
||||
let ok = {
|
||||
let element = self.as_element();
|
||||
element.style_attribute().is_none() && element.get_attr(&ns!(""), "id").is_none()
|
||||
element.style_attribute().is_none() &&
|
||||
element.get_attr(&ns!(""), &atom!("id")).is_none()
|
||||
};
|
||||
if !ok {
|
||||
return CannotShare(false)
|
||||
|
|
|
@ -48,6 +48,7 @@ use std::cmp::{max, min};
|
|||
use std::fmt;
|
||||
use std::from_str::FromStr;
|
||||
use std::num::Zero;
|
||||
use string_cache::Atom;
|
||||
use style::{ComputedValues, TElement, TNode, cascade_anonymous, RGBA};
|
||||
use style::computed_values::{LengthOrPercentage, LengthOrPercentageOrAuto};
|
||||
use style::computed_values::{LengthOrPercentageOrNone};
|
||||
|
@ -220,7 +221,7 @@ impl ImageFragmentInfo {
|
|||
image_url: Url,
|
||||
local_image_cache: Arc<Mutex<LocalImageCache<UntrustedNodeAddress>>>)
|
||||
-> ImageFragmentInfo {
|
||||
fn convert_length(node: &ThreadSafeLayoutNode, name: &str) -> Option<Au> {
|
||||
fn convert_length(node: &ThreadSafeLayoutNode, name: &Atom) -> Option<Au> {
|
||||
let element = node.as_element();
|
||||
element.get_attr(&ns!(""), name).and_then(|string| {
|
||||
let n: Option<int> = FromStr::from_str(string);
|
||||
|
@ -229,8 +230,8 @@ impl ImageFragmentInfo {
|
|||
}
|
||||
|
||||
let is_vertical = node.style().writing_mode.is_vertical();
|
||||
let dom_width = convert_length(node, "width");
|
||||
let dom_height = convert_length(node, "height");
|
||||
let dom_width = convert_length(node, &atom!("width"));
|
||||
let dom_height = convert_length(node, &atom!("height"));
|
||||
|
||||
let opaque_node: OpaqueNode = OpaqueNodeMethods::from_thread_safe_layout_node(node);
|
||||
let untrusted_node: UntrustedNodeAddress = opaque_node.to_untrusted_node_address();
|
||||
|
@ -412,7 +413,7 @@ impl TableColumnFragmentInfo {
|
|||
pub fn new(node: &ThreadSafeLayoutNode) -> TableColumnFragmentInfo {
|
||||
let span = {
|
||||
let element = node.as_element();
|
||||
element.get_attr(&ns!(""), "span").and_then(|string| {
|
||||
element.get_attr(&ns!(""), &atom!("span")).and_then(|string| {
|
||||
let n: Option<int> = FromStr::from_str(string);
|
||||
n
|
||||
})
|
||||
|
|
|
@ -28,9 +28,10 @@ extern crate "net" as servo_net;
|
|||
extern crate "msg" as servo_msg;
|
||||
#[phase(plugin, link)]
|
||||
extern crate "util" as servo_util;
|
||||
extern crate string_cache;
|
||||
|
||||
#[phase(plugin)]
|
||||
extern crate string_cache_macros;
|
||||
extern crate string_cache;
|
||||
|
||||
extern crate collections;
|
||||
extern crate encoding;
|
||||
|
|
|
@ -317,15 +317,14 @@ impl<'ln> TNode<'ln, LayoutElement<'ln>> for LayoutNode<'ln> {
|
|||
fn match_attr(self, attr: &AttrSelector, test: |&str| -> bool) -> bool {
|
||||
assert!(self.is_element())
|
||||
let name = if self.is_html_element_in_html_document() {
|
||||
attr.lower_name.as_slice()
|
||||
&attr.lower_name
|
||||
} else {
|
||||
attr.name.as_slice()
|
||||
&attr.name
|
||||
};
|
||||
match attr.namespace {
|
||||
SpecificNamespace(ref ns) => {
|
||||
let element = self.as_element();
|
||||
element.get_attr(ns, name)
|
||||
.map_or(false, |attr| test(attr))
|
||||
element.get_attr(ns, name).map_or(false, |attr| test(attr))
|
||||
},
|
||||
AnyNamespace => {
|
||||
let element = self.as_element();
|
||||
|
@ -445,13 +444,15 @@ impl<'le> TElement<'le> for LayoutElement<'le> {
|
|||
}
|
||||
|
||||
#[inline]
|
||||
fn get_attr(self, namespace: &Namespace, name: &str) -> Option<&'le str> {
|
||||
fn get_attr(self, namespace: &Namespace, name: &Atom) -> Option<&'le str> {
|
||||
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_attrs(self, name: &Atom) -> Vec<&'le str> {
|
||||
unsafe {
|
||||
self.element.get_attr_vals_for_layout(name)
|
||||
}
|
||||
}
|
||||
|
||||
fn get_link(self) -> Option<&'le str> {
|
||||
|
@ -462,7 +463,9 @@ impl<'le> TElement<'le> for LayoutElement<'le> {
|
|||
ElementNodeTypeId(HTMLAnchorElementTypeId) |
|
||||
ElementNodeTypeId(HTMLAreaElementTypeId) |
|
||||
ElementNodeTypeId(HTMLLinkElementTypeId) => {
|
||||
unsafe { self.element.get_attr_val_for_layout(&ns!(""), "href") }
|
||||
unsafe {
|
||||
self.element.get_attr_val_for_layout(&ns!(""), &atom!("href"))
|
||||
}
|
||||
}
|
||||
_ => None,
|
||||
}
|
||||
|
@ -476,7 +479,9 @@ impl<'le> TElement<'le> for LayoutElement<'le> {
|
|||
|
||||
#[inline]
|
||||
fn get_id(self) -> Option<Atom> {
|
||||
unsafe { self.element.get_attr_atom_for_layout(&ns!(""), "id") }
|
||||
unsafe {
|
||||
self.element.get_attr_atom_for_layout(&ns!(""), &atom!("id"))
|
||||
}
|
||||
}
|
||||
|
||||
fn get_disabled_state(self) -> bool {
|
||||
|
@ -491,7 +496,7 @@ impl<'le> TElement<'le> for LayoutElement<'le> {
|
|||
}
|
||||
}
|
||||
|
||||
fn has_class(self, name: &str) -> bool {
|
||||
fn has_class(self, name: &Atom) -> bool {
|
||||
unsafe {
|
||||
self.element.has_class_for_layout(name)
|
||||
}
|
||||
|
@ -502,8 +507,8 @@ impl<'le> TElement<'le> for LayoutElement<'le> {
|
|||
unsafe {
|
||||
match self.element.get_classes_for_layout() {
|
||||
None => {}
|
||||
Some(mut classes) => {
|
||||
for class in classes {
|
||||
Some(ref classes) => {
|
||||
for class in classes.iter() {
|
||||
callback(class)
|
||||
}
|
||||
}
|
||||
|
@ -867,8 +872,10 @@ pub struct ThreadSafeLayoutElement<'le> {
|
|||
|
||||
impl<'le> ThreadSafeLayoutElement<'le> {
|
||||
#[inline]
|
||||
pub fn get_attr(&self, namespace: &Namespace, name: &str) -> Option<&'le str> {
|
||||
unsafe { self.element.get_attr_val_for_layout(namespace, name) }
|
||||
pub fn get_attr(&self, namespace: &Namespace, name: &Atom) -> Option<&'le str> {
|
||||
unsafe {
|
||||
self.element.get_attr_val_for_layout(namespace, name)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
@ -17,7 +17,6 @@ use devtools_traits::AttrInfo;
|
|||
use servo_util::str::{DOMString, split_html_space_chars};
|
||||
use std::cell::{Ref, RefCell};
|
||||
use std::mem;
|
||||
use std::slice::Items;
|
||||
use string_cache::{Atom, Namespace};
|
||||
|
||||
pub enum AttrSettingType {
|
||||
|
@ -51,9 +50,9 @@ impl AttrValue {
|
|||
AtomAttrValue(value)
|
||||
}
|
||||
|
||||
pub fn tokens<'a>(&'a self) -> Option<Items<'a, Atom>> {
|
||||
pub fn tokens<'a>(&'a self) -> Option<&'a [Atom]> {
|
||||
match *self {
|
||||
TokenListAttrValue(_, ref tokens) => Some(tokens.iter()),
|
||||
TokenListAttrValue(_, ref tokens) => Some(tokens.as_slice()),
|
||||
_ => None
|
||||
}
|
||||
}
|
||||
|
@ -215,17 +214,19 @@ impl<'a> AttrHelpers<'a> for JSRef<'a, Attr> {
|
|||
pub trait AttrHelpersForLayout {
|
||||
unsafe fn value_ref_forever(&self) -> &'static str;
|
||||
unsafe fn value_atom_forever(&self) -> Option<Atom>;
|
||||
unsafe fn value_tokens_forever(&self) -> Option<Items<Atom>>;
|
||||
unsafe fn value_tokens_forever(&self) -> Option<&'static [Atom]>;
|
||||
unsafe fn local_name_atom_forever(&self) -> Atom;
|
||||
}
|
||||
|
||||
impl AttrHelpersForLayout for Attr {
|
||||
#[inline]
|
||||
unsafe fn value_ref_forever(&self) -> &'static str {
|
||||
// cast to point to T in RefCell<T> directly
|
||||
let value = mem::transmute::<&RefCell<AttrValue>, &AttrValue>(&self.value);
|
||||
value.as_slice()
|
||||
}
|
||||
|
||||
#[inline]
|
||||
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);
|
||||
|
@ -235,15 +236,17 @@ impl AttrHelpersForLayout for Attr {
|
|||
}
|
||||
}
|
||||
|
||||
unsafe fn value_tokens_forever(&self) -> Option<Items<Atom>> {
|
||||
#[inline]
|
||||
unsafe fn value_tokens_forever(&self) -> Option<&'static [Atom]> {
|
||||
// cast to point to T in RefCell<T> directly
|
||||
let value = mem::transmute::<&RefCell<AttrValue>, &AttrValue>(&self.value);
|
||||
match *value {
|
||||
TokenListAttrValue(_, ref tokens) => Some(tokens.iter()),
|
||||
TokenListAttrValue(_, ref tokens) => Some(tokens.as_slice()),
|
||||
_ => None,
|
||||
}
|
||||
}
|
||||
|
||||
#[inline]
|
||||
unsafe fn local_name_atom_forever(&self) -> Atom {
|
||||
self.local_name.clone()
|
||||
}
|
||||
|
|
|
@ -5451,6 +5451,7 @@ class GlobalGenRoots():
|
|||
for protoName in descriptor.prototypeChain[1:-1]:
|
||||
protoDescriptor = config.getDescriptor(protoName)
|
||||
delegate = string.Template('''impl ${selfName} for ${baseName} {
|
||||
#[inline]
|
||||
fn ${fname}(&self) -> bool {
|
||||
self.${parentName}().${fname}()
|
||||
}
|
||||
|
|
|
@ -123,7 +123,8 @@ impl CollectionFilter for EmbedsFilter {
|
|||
struct LinksFilter;
|
||||
impl CollectionFilter for LinksFilter {
|
||||
fn filter(&self, elem: JSRef<Element>, _root: JSRef<Node>) -> bool {
|
||||
(elem.is_htmlanchorelement() || elem.is_htmlareaelement()) && elem.has_attribute("href")
|
||||
(elem.is_htmlanchorelement() || elem.is_htmlareaelement()) &&
|
||||
elem.has_attribute(&atom!("href"))
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -147,7 +148,7 @@ impl CollectionFilter for ScriptsFilter {
|
|||
struct AnchorsFilter;
|
||||
impl CollectionFilter for AnchorsFilter {
|
||||
fn filter(&self, elem: JSRef<Element>, _root: JSRef<Node>) -> bool {
|
||||
elem.is_htmlanchorelement() && elem.has_attribute("href")
|
||||
elem.is_htmlanchorelement() && elem.has_attribute(&atom!("href"))
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -278,7 +279,7 @@ impl<'a> DocumentHelpers<'a> for JSRef<'a, Document> {
|
|||
self.GetElementById(fragid.clone()).or_else(|| {
|
||||
let check_anchor = |&node: &JSRef<HTMLAnchorElement>| {
|
||||
let elem: JSRef<Element> = ElementCast::from_ref(node);
|
||||
elem.get_attribute(ns!(""), "name").root().map_or(false, |attr| {
|
||||
elem.get_attribute(ns!(""), &atom!("name")).root().map_or(false, |attr| {
|
||||
attr.value().as_slice() == fragid.as_slice()
|
||||
})
|
||||
};
|
||||
|
@ -785,7 +786,7 @@ impl<'a> DocumentMethods for JSRef<'a, Document> {
|
|||
}
|
||||
|
||||
let element: JSRef<Element> = ElementCast::to_ref(node).unwrap();
|
||||
element.get_attribute(ns!(""), "name").root().map_or(false, |attr| {
|
||||
element.get_attribute(ns!(""), &atom!("name")).root().map_or(false, |attr| {
|
||||
attr.value().as_slice() == name.as_slice()
|
||||
})
|
||||
})
|
||||
|
|
|
@ -21,12 +21,11 @@ use string_cache::Atom;
|
|||
pub struct DOMTokenList {
|
||||
reflector_: Reflector,
|
||||
element: JS<Element>,
|
||||
local_name: &'static str,
|
||||
local_name: Atom,
|
||||
}
|
||||
|
||||
impl DOMTokenList {
|
||||
fn new_inherited(element: JSRef<Element>,
|
||||
local_name: &'static str) -> DOMTokenList {
|
||||
pub fn new_inherited(element: JSRef<Element>, local_name: Atom) -> DOMTokenList {
|
||||
DOMTokenList {
|
||||
reflector_: Reflector::new(),
|
||||
element: JS::from_rooted(element),
|
||||
|
@ -34,11 +33,11 @@ impl DOMTokenList {
|
|||
}
|
||||
}
|
||||
|
||||
pub fn new(element: JSRef<Element>,
|
||||
local_name: &'static str) -> Temporary<DOMTokenList> {
|
||||
pub fn new(element: JSRef<Element>, local_name: &Atom) -> Temporary<DOMTokenList> {
|
||||
let window = window_from_node(element).root();
|
||||
reflect_dom_object(box DOMTokenList::new_inherited(element, local_name),
|
||||
&Window(*window), DOMTokenListBinding::Wrap)
|
||||
reflect_dom_object(box DOMTokenList::new_inherited(element, local_name.clone()),
|
||||
&Window(*window),
|
||||
DOMTokenListBinding::Wrap)
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -56,7 +55,7 @@ trait PrivateDOMTokenListHelpers {
|
|||
impl<'a> PrivateDOMTokenListHelpers for JSRef<'a, DOMTokenList> {
|
||||
fn attribute(self) -> Option<Temporary<Attr>> {
|
||||
let element = self.element.root();
|
||||
element.get_attribute(ns!(""), self.local_name)
|
||||
element.get_attribute(ns!(""), &self.local_name)
|
||||
}
|
||||
|
||||
fn check_token_exceptions<'a>(self, token: &'a str) -> Fallible<&'a str> {
|
||||
|
@ -79,8 +78,8 @@ impl<'a> DOMTokenListMethods for JSRef<'a, DOMTokenList> {
|
|||
|
||||
// http://dom.spec.whatwg.org/#dom-domtokenlist-item
|
||||
fn Item(self, index: u32) -> Option<DOMString> {
|
||||
self.attribute().root().and_then(|attr| attr.value().tokens().and_then(|mut tokens| {
|
||||
tokens.idx(index as uint).map(|token| token.as_slice().to_string())
|
||||
self.attribute().root().and_then(|attr| attr.value().tokens().and_then(|tokens| {
|
||||
tokens.get(index as uint).map(|token| token.as_slice().to_string())
|
||||
}))
|
||||
}
|
||||
|
||||
|
@ -93,9 +92,9 @@ impl<'a> DOMTokenListMethods for JSRef<'a, DOMTokenList> {
|
|||
// 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| {
|
||||
self.attribute().root().and_then(|attr| attr.value().tokens().map(|tokens| {
|
||||
let atom = Atom::from_slice(slice);
|
||||
tokens.any(|token| *token == atom)
|
||||
tokens.iter().any(|token| *token == atom)
|
||||
})).unwrap_or(false)
|
||||
})
|
||||
}
|
||||
|
|
|
@ -38,7 +38,6 @@ use std::ascii::StrAsciiExt;
|
|||
use std::cell::{Ref, RefMut, RefCell};
|
||||
use std::default::Default;
|
||||
use std::mem;
|
||||
use std::slice::Items;
|
||||
use string_cache::{Atom, Namespace};
|
||||
use url::UrlParser;
|
||||
|
||||
|
@ -57,6 +56,7 @@ pub struct Element {
|
|||
}
|
||||
|
||||
impl ElementDerived for EventTarget {
|
||||
#[inline]
|
||||
fn is_element(&self) -> bool {
|
||||
match *self.type_id() {
|
||||
NodeTargetTypeId(ElementNodeTypeId(_)) => true,
|
||||
|
@ -205,24 +205,25 @@ 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;
|
||||
unsafe fn get_classes_for_layout<'a>(&'a self) -> Option<Items<'a,Atom>>;
|
||||
unsafe fn get_attr_val_for_layout<'a>(&'a self, namespace: &Namespace, name: &Atom)
|
||||
-> Option<&'a str>;
|
||||
unsafe fn get_attr_vals_for_layout<'a>(&'a self, name: &Atom) -> Vec<&'a str>;
|
||||
unsafe fn get_attr_atom_for_layout(&self, namespace: &Namespace, name: &Atom) -> Option<Atom>;
|
||||
unsafe fn has_class_for_layout(&self, name: &Atom) -> bool;
|
||||
unsafe fn get_classes_for_layout(&self) -> Option<&'static [Atom]>;
|
||||
}
|
||||
|
||||
impl RawLayoutElementHelpers for Element {
|
||||
#[inline]
|
||||
#[allow(unrooted_must_root)]
|
||||
unsafe fn get_attr_val_for_layout<'a>(&'a self, namespace: &Namespace, name: &str)
|
||||
unsafe fn get_attr_val_for_layout<'a>(&'a self, namespace: &Namespace, name: &Atom)
|
||||
-> Option<&'a str> {
|
||||
// cast to point to T in RefCell<T> directly
|
||||
let attrs: *const Vec<JS<Attr>> = mem::transmute(&self.attrs);
|
||||
(*attrs).iter().find(|attr: & &JS<Attr>| {
|
||||
let attr = attr.unsafe_get();
|
||||
name == (*attr).local_name_atom_forever().as_slice() &&
|
||||
*(*attr).namespace() == *namespace
|
||||
*name == (*attr).local_name_atom_forever() &&
|
||||
(*attr).namespace() == namespace
|
||||
}).map(|attr| {
|
||||
let attr = attr.unsafe_get();
|
||||
(*attr).value_ref_forever()
|
||||
|
@ -231,12 +232,12 @@ impl RawLayoutElementHelpers for Element {
|
|||
|
||||
#[inline]
|
||||
#[allow(unrooted_must_root)]
|
||||
unsafe fn get_attr_vals_for_layout<'a>(&'a self, name: &str) -> Vec<&'a str> {
|
||||
unsafe fn get_attr_vals_for_layout<'a>(&'a self, name: &Atom) -> 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() {
|
||||
if *name == (*attr).local_name_atom_forever() {
|
||||
Some((*attr).value_ref_forever())
|
||||
} else {
|
||||
None
|
||||
|
@ -246,14 +247,14 @@ impl RawLayoutElementHelpers for Element {
|
|||
|
||||
#[inline]
|
||||
#[allow(unrooted_must_root)]
|
||||
unsafe fn get_attr_atom_for_layout(&self, namespace: &Namespace, name: &str)
|
||||
unsafe fn get_attr_atom_for_layout(&self, namespace: &Namespace, name: &Atom)
|
||||
-> Option<Atom> {
|
||||
// cast to point to T in RefCell<T> directly
|
||||
let attrs: *const Vec<JS<Attr>> = mem::transmute(&self.attrs);
|
||||
(*attrs).iter().find(|attr: & &JS<Attr>| {
|
||||
let attr = attr.unsafe_get();
|
||||
name == (*attr).local_name_atom_forever().as_slice() &&
|
||||
*(*attr).namespace() == *namespace
|
||||
*name == (*attr).local_name_atom_forever() &&
|
||||
(*attr).namespace() == namespace
|
||||
}).and_then(|attr| {
|
||||
let attr = attr.unsafe_get();
|
||||
(*attr).value_atom_forever()
|
||||
|
@ -262,24 +263,26 @@ impl RawLayoutElementHelpers for Element {
|
|||
|
||||
#[inline]
|
||||
#[allow(unrooted_must_root)]
|
||||
unsafe fn has_class_for_layout(&self, name: &str) -> bool {
|
||||
unsafe fn has_class_for_layout(&self, name: &Atom) -> bool {
|
||||
let attrs: *const Vec<JS<Attr>> = mem::transmute(&self.attrs);
|
||||
(*attrs).iter().find(|attr: & &JS<Attr>| {
|
||||
let attr = attr.unsafe_get();
|
||||
(*attr).local_name_atom_forever().as_slice() == "class"
|
||||
(*attr).local_name_atom_forever() == atom!("class")
|
||||
}).map_or(false, |attr| {
|
||||
let attr = attr.unsafe_get();
|
||||
(*attr).value_tokens_forever().map(|mut tokens| { tokens.any(|atom| atom.as_slice() == name) })
|
||||
(*attr).value_tokens_forever().map(|tokens| {
|
||||
tokens.iter().any(|atom| atom == name)
|
||||
})
|
||||
}.take().unwrap())
|
||||
}
|
||||
|
||||
#[inline]
|
||||
#[allow(unrooted_must_root)]
|
||||
unsafe fn get_classes_for_layout<'a>(&'a self) -> Option<Items<'a,Atom>> {
|
||||
unsafe fn get_classes_for_layout(&self) -> Option<&'static [Atom]> {
|
||||
let attrs: *const Vec<JS<Attr>> = mem::transmute(&self.attrs);
|
||||
(*attrs).iter().find(|attr: & &JS<Attr>| {
|
||||
let attr = attr.unsafe_get();
|
||||
(*attr).local_name_atom_forever().as_slice() == "class"
|
||||
(*attr).local_name_atom_forever() == atom!("class")
|
||||
}).and_then(|attr| {
|
||||
let attr = attr.unsafe_get();
|
||||
(*attr).value_tokens_forever()
|
||||
|
@ -293,6 +296,7 @@ pub trait LayoutElementHelpers {
|
|||
|
||||
impl LayoutElementHelpers for JS<Element> {
|
||||
#[allow(unrooted_must_root)]
|
||||
#[inline]
|
||||
unsafe fn html_element_in_html_document_for_layout(&self) -> bool {
|
||||
if (*self.unsafe_get()).namespace != ns!(HTML) {
|
||||
return false
|
||||
|
@ -355,14 +359,16 @@ impl<'a> ElementHelpers<'a> for JSRef<'a, Element> {
|
|||
pub trait AttributeHandlers {
|
||||
/// Returns the attribute with given namespace and case-sensitive local
|
||||
/// name, if any.
|
||||
fn get_attribute(self, namespace: Namespace, local_name: &str)
|
||||
fn get_attribute(self, namespace: Namespace, local_name: &Atom)
|
||||
-> Option<Temporary<Attr>>;
|
||||
fn get_attributes(self, local_name: &str)
|
||||
fn get_attributes(self, local_name: &Atom)
|
||||
-> Vec<Temporary<Attr>>;
|
||||
fn set_attribute_from_parser(self, local_name: Atom,
|
||||
value: DOMString, namespace: Namespace,
|
||||
fn set_attribute_from_parser(self,
|
||||
local_name: Atom,
|
||||
value: DOMString,
|
||||
namespace: Namespace,
|
||||
prefix: Option<DOMString>);
|
||||
fn set_attribute(self, name: &str, value: AttrValue);
|
||||
fn set_attribute(self, name: &Atom, value: AttrValue);
|
||||
fn do_set_attribute(self, local_name: Atom, value: AttrValue,
|
||||
name: Atom, namespace: Namespace,
|
||||
prefix: Option<DOMString>, cb: |JSRef<Attr>| -> bool);
|
||||
|
@ -371,34 +377,33 @@ pub trait AttributeHandlers {
|
|||
|
||||
fn remove_attribute(self, namespace: Namespace, name: &str);
|
||||
fn notify_attribute_changed(self, local_name: &Atom);
|
||||
fn has_class(&self, name: &str) -> bool;
|
||||
fn has_class(&self, name: &Atom) -> bool;
|
||||
fn notify_attribute_removed(self);
|
||||
|
||||
fn set_atomic_attribute(self, name: &str, value: DOMString);
|
||||
fn set_atomic_attribute(self, name: &Atom, value: DOMString);
|
||||
|
||||
// http://www.whatwg.org/html/#reflecting-content-attributes-in-idl-attributes
|
||||
fn has_attribute(self, name: &str) -> bool;
|
||||
fn set_bool_attribute(self, name: &str, value: bool);
|
||||
fn get_url_attribute(self, name: &str) -> DOMString;
|
||||
fn set_url_attribute(self, name: &str, value: DOMString);
|
||||
fn get_string_attribute(self, name: &str) -> DOMString;
|
||||
fn set_string_attribute(self, name: &str, value: DOMString);
|
||||
fn set_tokenlist_attribute(self, name: &str, value: DOMString);
|
||||
fn get_uint_attribute(self, name: &str) -> u32;
|
||||
fn set_uint_attribute(self, name: &str, value: u32);
|
||||
fn has_attribute(self, name: &Atom) -> bool;
|
||||
fn set_bool_attribute(self, name: &Atom, value: bool);
|
||||
fn get_url_attribute(self, name: &Atom) -> DOMString;
|
||||
fn set_url_attribute(self, name: &Atom, value: DOMString);
|
||||
fn get_string_attribute(self, name: &Atom) -> DOMString;
|
||||
fn set_string_attribute(self, name: &Atom, value: DOMString);
|
||||
fn set_tokenlist_attribute(self, name: &Atom, value: DOMString);
|
||||
fn get_uint_attribute(self, name: &Atom) -> u32;
|
||||
fn set_uint_attribute(self, name: &Atom, value: u32);
|
||||
}
|
||||
|
||||
impl<'a> AttributeHandlers for JSRef<'a, Element> {
|
||||
fn get_attribute(self, namespace: Namespace, local_name: &str) -> Option<Temporary<Attr>> {
|
||||
fn get_attribute(self, namespace: Namespace, local_name: &Atom) -> 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);
|
||||
fn get_attributes(self, local_name: &Atom) -> Vec<Temporary<Attr>> {
|
||||
self.attrs.borrow().iter().map(|attr| attr.root()).filter_map(|attr| {
|
||||
if *attr.local_name() == local_name {
|
||||
if *attr.local_name() == *local_name {
|
||||
Some(Temporary::from_rooted(*attr))
|
||||
} else {
|
||||
None
|
||||
|
@ -406,8 +411,10 @@ impl<'a> AttributeHandlers for JSRef<'a, Element> {
|
|||
}).collect()
|
||||
}
|
||||
|
||||
fn set_attribute_from_parser(self, local_name: Atom,
|
||||
value: DOMString, namespace: Namespace,
|
||||
fn set_attribute_from_parser(self,
|
||||
local_name: Atom,
|
||||
value: DOMString,
|
||||
namespace: Namespace,
|
||||
prefix: Option<DOMString>) {
|
||||
let name = match prefix {
|
||||
None => local_name.clone(),
|
||||
|
@ -420,16 +427,15 @@ impl<'a> AttributeHandlers for JSRef<'a, Element> {
|
|||
self.do_set_attribute(local_name, value, name, namespace, prefix, |_| false)
|
||||
}
|
||||
|
||||
fn set_attribute(self, name: &str, value: AttrValue) {
|
||||
assert!(name == name.to_ascii_lower().as_slice());
|
||||
assert!(!name.contains(":"));
|
||||
fn set_attribute(self, name: &Atom, value: AttrValue) {
|
||||
assert!(name.as_slice() == name.as_slice().to_ascii_lower().as_slice());
|
||||
assert!(!name.as_slice().contains(":"));
|
||||
|
||||
let node: JSRef<Node> = NodeCast::from_ref(self);
|
||||
node.wait_until_safe_to_modify_dom();
|
||||
|
||||
let name = Atom::from_slice(name);
|
||||
self.do_set_attribute(name.clone(), value, name.clone(),
|
||||
ns!(""), None, |attr| *attr.local_name() == name);
|
||||
ns!(""), None, |attr| *attr.local_name() == *name);
|
||||
}
|
||||
|
||||
fn do_set_attribute(self, local_name: Atom, value: AttrValue,
|
||||
|
@ -507,41 +513,40 @@ impl<'a> AttributeHandlers for JSRef<'a, Element> {
|
|||
}
|
||||
}
|
||||
|
||||
fn has_class(&self, name: &str) -> bool {
|
||||
self.get_attribute(ns!(""), "class").root().map(|attr| {
|
||||
attr.value().tokens().map(|mut tokens| {
|
||||
tokens.any(|atom| atom.as_slice() == name)
|
||||
fn has_class(&self, name: &Atom) -> bool {
|
||||
self.get_attribute(ns!(""), &atom!("class")).root().map(|attr| {
|
||||
attr.value().tokens().map(|tokens| {
|
||||
tokens.iter().any(|atom| atom == name)
|
||||
}).unwrap_or(false)
|
||||
}).unwrap_or(false)
|
||||
}
|
||||
|
||||
fn set_atomic_attribute(self, name: &str, value: DOMString) {
|
||||
assert!(name == name.to_ascii_lower().as_slice());
|
||||
fn set_atomic_attribute(self, name: &Atom, value: DOMString) {
|
||||
assert!(name.as_slice().eq_ignore_ascii_case(name.as_slice()));
|
||||
let value = AttrValue::from_atomic(value);
|
||||
self.set_attribute(name, value);
|
||||
}
|
||||
|
||||
fn has_attribute(self, name: &str) -> bool {
|
||||
let name = match self.html_element_in_html_document() {
|
||||
true => Atom::from_slice(name.to_ascii_lower().as_slice()),
|
||||
false => Atom::from_slice(name)
|
||||
};
|
||||
fn has_attribute(self, name: &Atom) -> bool {
|
||||
assert!(name.as_slice().chars().all(|ch| {
|
||||
!ch.is_ascii() || ch.to_ascii().to_lowercase() == ch.to_ascii()
|
||||
}));
|
||||
self.attrs.borrow().iter().map(|attr| attr.root()).any(|attr| {
|
||||
*attr.local_name() == name && *attr.namespace() == ns!("")
|
||||
*attr.local_name() == *name && *attr.namespace() == ns!("")
|
||||
})
|
||||
}
|
||||
|
||||
fn set_bool_attribute(self, name: &str, value: bool) {
|
||||
fn set_bool_attribute(self, name: &Atom, value: bool) {
|
||||
if self.has_attribute(name) == value { return; }
|
||||
if value {
|
||||
self.set_string_attribute(name, String::new());
|
||||
} else {
|
||||
self.remove_attribute(ns!(""), name);
|
||||
self.remove_attribute(ns!(""), name.as_slice());
|
||||
}
|
||||
}
|
||||
|
||||
fn get_url_attribute(self, name: &str) -> DOMString {
|
||||
assert!(name == name.to_ascii_lower().as_slice());
|
||||
fn get_url_attribute(self, name: &Atom) -> DOMString {
|
||||
assert!(name.as_slice() == name.as_slice().to_ascii_lower().as_slice());
|
||||
if !self.has_attribute(name) {
|
||||
return "".to_string();
|
||||
}
|
||||
|
@ -555,29 +560,30 @@ impl<'a> AttributeHandlers for JSRef<'a, Element> {
|
|||
Err(_) => "".to_string()
|
||||
}
|
||||
}
|
||||
fn set_url_attribute(self, name: &str, value: DOMString) {
|
||||
fn set_url_attribute(self, name: &Atom, value: DOMString) {
|
||||
self.set_string_attribute(name, value);
|
||||
}
|
||||
|
||||
fn get_string_attribute(self, name: &str) -> DOMString {
|
||||
assert!(name == name.to_ascii_lower().as_slice());
|
||||
fn get_string_attribute(self, name: &Atom) -> DOMString {
|
||||
match self.get_attribute(ns!(""), name) {
|
||||
Some(x) => x.root().Value(),
|
||||
None => "".to_string()
|
||||
}
|
||||
}
|
||||
fn set_string_attribute(self, name: &str, value: DOMString) {
|
||||
assert!(name == name.to_ascii_lower().as_slice());
|
||||
fn set_string_attribute(self, name: &Atom, value: DOMString) {
|
||||
assert!(name.as_slice() == name.as_slice().to_ascii_lower().as_slice());
|
||||
self.set_attribute(name, StringAttrValue(value));
|
||||
}
|
||||
|
||||
fn set_tokenlist_attribute(self, name: &str, value: DOMString) {
|
||||
assert!(name == name.to_ascii_lower().as_slice());
|
||||
fn set_tokenlist_attribute(self, name: &Atom, value: DOMString) {
|
||||
assert!(name.as_slice() == name.as_slice().to_ascii_lower().as_slice());
|
||||
self.set_attribute(name, AttrValue::from_tokenlist(value));
|
||||
}
|
||||
|
||||
fn get_uint_attribute(self, name: &str) -> u32 {
|
||||
assert!(name == name.to_ascii_lower().as_slice());
|
||||
fn get_uint_attribute(self, name: &Atom) -> u32 {
|
||||
assert!(name.as_slice().chars().all(|ch| {
|
||||
!ch.is_ascii() || ch.to_ascii().to_lowercase() == ch.to_ascii()
|
||||
}));
|
||||
let attribute = self.get_attribute(ns!(""), name).root();
|
||||
match attribute {
|
||||
Some(attribute) => {
|
||||
|
@ -589,8 +595,8 @@ impl<'a> AttributeHandlers for JSRef<'a, Element> {
|
|||
None => 0,
|
||||
}
|
||||
}
|
||||
fn set_uint_attribute(self, name: &str, value: u32) {
|
||||
assert!(name == name.to_ascii_lower().as_slice());
|
||||
fn set_uint_attribute(self, name: &Atom, value: u32) {
|
||||
assert!(name.as_slice() == name.as_slice().to_ascii_lower().as_slice());
|
||||
self.set_attribute(name, UIntAttrValue(value.to_string(), value));
|
||||
}
|
||||
}
|
||||
|
@ -628,28 +634,28 @@ impl<'a> ElementMethods for JSRef<'a, Element> {
|
|||
|
||||
// http://dom.spec.whatwg.org/#dom-element-id
|
||||
fn Id(self) -> DOMString {
|
||||
self.get_string_attribute("id")
|
||||
self.get_string_attribute(&atom!("id"))
|
||||
}
|
||||
|
||||
// http://dom.spec.whatwg.org/#dom-element-id
|
||||
fn SetId(self, id: DOMString) {
|
||||
self.set_atomic_attribute("id", id);
|
||||
self.set_atomic_attribute(&atom!("id"), id);
|
||||
}
|
||||
|
||||
// http://dom.spec.whatwg.org/#dom-element-classname
|
||||
fn ClassName(self) -> DOMString {
|
||||
self.get_string_attribute("class")
|
||||
self.get_string_attribute(&atom!("class"))
|
||||
}
|
||||
|
||||
// http://dom.spec.whatwg.org/#dom-element-classname
|
||||
fn SetClassName(self, class: DOMString) {
|
||||
self.set_tokenlist_attribute("class", class);
|
||||
self.set_tokenlist_attribute(&atom!("class"), class);
|
||||
}
|
||||
|
||||
// http://dom.spec.whatwg.org/#dom-element-classlist
|
||||
fn ClassList(self) -> Temporary<DOMTokenList> {
|
||||
if self.class_list.get().is_none() {
|
||||
let class_list = DOMTokenList::new(self, "class");
|
||||
let class_list = DOMTokenList::new(self, &atom!("class"));
|
||||
self.class_list.assign(Some(class_list));
|
||||
}
|
||||
self.class_list.get().unwrap()
|
||||
|
@ -676,7 +682,7 @@ impl<'a> ElementMethods for JSRef<'a, Element> {
|
|||
} else {
|
||||
name
|
||||
};
|
||||
self.get_attribute(ns!(""), name.as_slice()).root()
|
||||
self.get_attribute(ns!(""), &Atom::from_slice(name.as_slice())).root()
|
||||
.map(|s| s.Value())
|
||||
}
|
||||
|
||||
|
@ -685,7 +691,7 @@ impl<'a> ElementMethods for JSRef<'a, Element> {
|
|||
namespace: Option<DOMString>,
|
||||
local_name: DOMString) -> Option<DOMString> {
|
||||
let namespace = namespace::from_domstring(namespace);
|
||||
self.get_attribute(namespace, local_name.as_slice()).root()
|
||||
self.get_attribute(namespace, &Atom::from_slice(local_name.as_slice())).root()
|
||||
.map(|attr| attr.Value())
|
||||
}
|
||||
|
||||
|
@ -808,9 +814,17 @@ impl<'a> ElementMethods for JSRef<'a, Element> {
|
|||
}
|
||||
|
||||
// http://dom.spec.whatwg.org/#dom-element-hasattribute
|
||||
fn HasAttribute(self,
|
||||
name: DOMString) -> bool {
|
||||
self.has_attribute(name.as_slice())
|
||||
fn HasAttribute(self, name: DOMString) -> bool {
|
||||
// Step 1.
|
||||
if self.html_element_in_html_document() {
|
||||
// TODO(pcwalton): Small string optimization here.
|
||||
return self.has_attribute(&Atom::from_slice(name.as_slice()
|
||||
.to_ascii_lower()
|
||||
.as_slice()))
|
||||
}
|
||||
|
||||
// Step 2.
|
||||
self.has_attribute(&Atom::from_slice(name.as_slice()))
|
||||
}
|
||||
|
||||
// http://dom.spec.whatwg.org/#dom-element-hasattributens
|
||||
|
@ -997,7 +1011,7 @@ impl<'a> VirtualMethods for JSRef<'a, Element> {
|
|||
|
||||
if !tree_in_doc { return; }
|
||||
|
||||
match self.get_attribute(ns!(""), "id").root() {
|
||||
match self.get_attribute(ns!(""), &atom!("id")).root() {
|
||||
Some(attr) => {
|
||||
let doc = document_from_node(*self).root();
|
||||
let value = attr.Value();
|
||||
|
@ -1018,7 +1032,7 @@ impl<'a> VirtualMethods for JSRef<'a, Element> {
|
|||
|
||||
if !tree_in_doc { return; }
|
||||
|
||||
match self.get_attribute(ns!(""), "id").root() {
|
||||
match self.get_attribute(ns!(""), &atom!("id")).root() {
|
||||
Some(attr) => {
|
||||
let doc = document_from_node(*self).root();
|
||||
let value = attr.Value();
|
||||
|
@ -1033,12 +1047,12 @@ impl<'a> VirtualMethods for JSRef<'a, Element> {
|
|||
}
|
||||
|
||||
impl<'a> style::TElement<'a> for JSRef<'a, Element> {
|
||||
fn get_attr(self, namespace: &Namespace, attr: &str) -> Option<&'a str> {
|
||||
fn get_attr(self, namespace: &Namespace, attr: &Atom) -> Option<&'a str> {
|
||||
self.get_attribute(namespace.clone(), attr).root().map(|attr| {
|
||||
unsafe { mem::transmute(attr.value().as_slice()) }
|
||||
})
|
||||
}
|
||||
fn get_attrs(self, attr: &str) -> Vec<&'a str> {
|
||||
fn get_attrs(self, attr: &Atom) -> Vec<&'a str> {
|
||||
self.get_attributes(attr).iter().map(|attr| attr.root()).map(|attr| {
|
||||
unsafe { mem::transmute(attr.value().as_slice()) }
|
||||
}).collect()
|
||||
|
@ -1051,7 +1065,7 @@ impl<'a> style::TElement<'a> for JSRef<'a, Element> {
|
|||
// selector-link
|
||||
ElementNodeTypeId(HTMLAnchorElementTypeId) |
|
||||
ElementNodeTypeId(HTMLAreaElementTypeId) |
|
||||
ElementNodeTypeId(HTMLLinkElementTypeId) => self.get_attr(&ns!(""), "href"),
|
||||
ElementNodeTypeId(HTMLLinkElementTypeId) => self.get_attr(&ns!(""), &atom!("href")),
|
||||
_ => None,
|
||||
}
|
||||
}
|
||||
|
@ -1078,7 +1092,7 @@ impl<'a> style::TElement<'a> for JSRef<'a, Element> {
|
|||
node.get_hover_state()
|
||||
}
|
||||
fn get_id(self) -> Option<Atom> {
|
||||
self.get_attribute(ns!(""), "id").map(|attr| {
|
||||
self.get_attribute(ns!(""), &atom!("id")).map(|attr| {
|
||||
let attr = attr.root();
|
||||
match *attr.value() {
|
||||
AtomAttrValue(ref val) => val.clone(),
|
||||
|
@ -1094,23 +1108,23 @@ impl<'a> style::TElement<'a> for JSRef<'a, Element> {
|
|||
let node: JSRef<Node> = NodeCast::from_ref(self);
|
||||
node.get_enabled_state()
|
||||
}
|
||||
fn has_class(self, name: &str) -> bool {
|
||||
fn has_class(self, name: &Atom) -> bool {
|
||||
// FIXME(zwarich): Remove this when UFCS lands and there is a better way
|
||||
// of disambiguating methods.
|
||||
fn has_class<T: AttributeHandlers>(this: T, name: &str) -> bool {
|
||||
fn has_class<T: AttributeHandlers>(this: T, name: &Atom) -> bool {
|
||||
this.has_class(name)
|
||||
}
|
||||
|
||||
has_class(self, name)
|
||||
}
|
||||
fn each_class(self, callback: |&Atom|) {
|
||||
match self.get_attribute(ns!(""), "class").root() {
|
||||
match self.get_attribute(ns!(""), &atom!("class")).root() {
|
||||
None => {}
|
||||
Some(attr) => {
|
||||
match attr.deref().value().tokens() {
|
||||
Some(ref attr) => {
|
||||
match attr.value().tokens() {
|
||||
None => {}
|
||||
Some(mut tokens) => {
|
||||
for token in tokens {
|
||||
Some(tokens) => {
|
||||
for token in tokens.iter() {
|
||||
callback(token)
|
||||
}
|
||||
}
|
||||
|
|
|
@ -56,7 +56,7 @@ impl<'a> PrivateHTMLAnchorElementHelpers for JSRef<'a, HTMLAnchorElement> {
|
|||
fn handle_event_impl(self, event: JSRef<Event>) {
|
||||
if "click" == event.Type().as_slice() && !event.DefaultPrevented() {
|
||||
let element: JSRef<Element> = ElementCast::from_ref(self);
|
||||
let attr = element.get_attribute(ns!(""), "href").root();
|
||||
let attr = element.get_attribute(ns!(""), &atom!("href")).root();
|
||||
match attr {
|
||||
Some(ref href) => {
|
||||
let value = href.Value();
|
||||
|
|
|
@ -62,7 +62,7 @@ impl<'a> HTMLButtonElementMethods for JSRef<'a, HTMLButtonElement> {
|
|||
// https://html.spec.whatwg.org/multipage/forms.html#dom-button-type
|
||||
fn Type(self) -> DOMString {
|
||||
let elem: JSRef<Element> = ElementCast::from_ref(self);
|
||||
let ty = elem.get_string_attribute("type").into_ascii_lower();
|
||||
let ty = elem.get_string_attribute(&atom!("type")).into_ascii_lower();
|
||||
// https://html.spec.whatwg.org/multipage/forms.html#attr-button-type
|
||||
match ty.as_slice() {
|
||||
"reset" | "button" | "menu" => ty,
|
||||
|
|
|
@ -68,7 +68,7 @@ impl<'a> HTMLCanvasElementMethods for JSRef<'a, HTMLCanvasElement> {
|
|||
|
||||
fn SetWidth(self, width: u32) {
|
||||
let elem: JSRef<Element> = ElementCast::from_ref(self);
|
||||
elem.set_uint_attribute("width", width)
|
||||
elem.set_uint_attribute(&atom!("width"), width)
|
||||
}
|
||||
|
||||
fn Height(self) -> u32 {
|
||||
|
@ -77,7 +77,7 @@ impl<'a> HTMLCanvasElementMethods for JSRef<'a, HTMLCanvasElement> {
|
|||
|
||||
fn SetHeight(self, height: u32) {
|
||||
let elem: JSRef<Element> = ElementCast::from_ref(self);
|
||||
elem.set_uint_attribute("height", height)
|
||||
elem.set_uint_attribute(&atom!("height"), height)
|
||||
}
|
||||
|
||||
fn GetContext(self, id: DOMString) -> Option<Temporary<CanvasRenderingContext2D>> {
|
||||
|
|
|
@ -139,15 +139,17 @@ impl HTMLCollection {
|
|||
-> Temporary<HTMLCollection> {
|
||||
#[jstraceable]
|
||||
struct ClassNameFilter {
|
||||
classes: Vec<DOMString>
|
||||
classes: Vec<Atom>
|
||||
}
|
||||
impl CollectionFilter for ClassNameFilter {
|
||||
fn filter(&self, elem: JSRef<Element>, _root: JSRef<Node>) -> bool {
|
||||
self.classes.iter().all(|class| elem.has_class(class.as_slice()))
|
||||
self.classes.iter().all(|class| elem.has_class(class))
|
||||
}
|
||||
}
|
||||
let filter = ClassNameFilter {
|
||||
classes: split_html_space_chars(classes.as_slice()).map(|class| class.to_string()).collect()
|
||||
classes: split_html_space_chars(classes.as_slice()).map(|class| {
|
||||
Atom::from_slice(class)
|
||||
}).collect()
|
||||
};
|
||||
HTMLCollection::create(window, root, box filter)
|
||||
}
|
||||
|
@ -216,8 +218,8 @@ impl<'a> HTMLCollectionMethods for JSRef<'a, HTMLCollection> {
|
|||
Static(ref elems) => elems.iter()
|
||||
.map(|elem| elem.root())
|
||||
.find(|elem| {
|
||||
elem.get_string_attribute("name") == key ||
|
||||
elem.get_string_attribute("id") == key })
|
||||
elem.get_string_attribute(&atom!("name")) == key ||
|
||||
elem.get_string_attribute(&atom!("id")) == key })
|
||||
.map(|maybe_elem| Temporary::from_rooted(*maybe_elem)),
|
||||
Live(ref root, ref filter) => {
|
||||
let root = root.root();
|
||||
|
@ -230,8 +232,8 @@ impl<'a> HTMLCollectionMethods for JSRef<'a, HTMLCollection> {
|
|||
}
|
||||
})
|
||||
.find(|elem| {
|
||||
elem.get_string_attribute("name") == key ||
|
||||
elem.get_string_attribute("id") == key })
|
||||
elem.get_string_attribute(&atom!("name")) == key ||
|
||||
elem.get_string_attribute(&atom!("id")) == key })
|
||||
.map(|maybe_elem| Temporary::from_rooted(maybe_elem))
|
||||
}
|
||||
}
|
||||
|
|
|
@ -28,6 +28,7 @@ use std::ascii::OwnedStrAsciiExt;
|
|||
use std::str::StrSlice;
|
||||
use url::UrlParser;
|
||||
use url::form_urlencoded::serialize;
|
||||
use string_cache::Atom;
|
||||
|
||||
#[jstraceable]
|
||||
#[must_root]
|
||||
|
@ -349,14 +350,24 @@ impl<'a> FormSubmitter<'a> {
|
|||
fn action(&self) -> DOMString {
|
||||
match *self {
|
||||
FormElement(form) => form.Action(),
|
||||
InputElement(input_element) => input_element.get_form_attribute("formaction", |i| i.FormAction(), |f| f.Action())
|
||||
InputElement(input_element) => {
|
||||
// FIXME(pcwalton): Make this a static atom.
|
||||
input_element.get_form_attribute(&Atom::from_slice("formaction"),
|
||||
|i| i.FormAction(),
|
||||
|f| f.Action())
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
fn enctype(&self) -> FormEncType {
|
||||
let attr = match *self {
|
||||
FormElement(form) => form.Enctype(),
|
||||
InputElement(input_element) => input_element.get_form_attribute("formenctype", |i| i.FormEnctype(), |f| f.Enctype())
|
||||
InputElement(input_element) => {
|
||||
// FIXME(pcwalton): Make this a static atom.
|
||||
input_element.get_form_attribute(&Atom::from_slice("formenctype"),
|
||||
|i| i.FormEnctype(),
|
||||
|f| f.Enctype())
|
||||
}
|
||||
};
|
||||
match attr.as_slice() {
|
||||
"multipart/form-data" => FormDataEncoded,
|
||||
|
@ -370,7 +381,12 @@ impl<'a> FormSubmitter<'a> {
|
|||
fn method(&self) -> FormMethod {
|
||||
let attr = match *self {
|
||||
FormElement(form) => form.Method(),
|
||||
InputElement(input_element) => input_element.get_form_attribute("formmethod", |i| i.FormMethod(), |f| f.Method())
|
||||
InputElement(input_element) => {
|
||||
// FIXME(pcwalton): Make this a static atom.
|
||||
input_element.get_form_attribute(&Atom::from_slice("formmethod"),
|
||||
|i| i.FormMethod(),
|
||||
|f| f.Method())
|
||||
}
|
||||
};
|
||||
match attr.as_slice() {
|
||||
"dialog" => FormDialog,
|
||||
|
@ -382,14 +398,20 @@ impl<'a> FormSubmitter<'a> {
|
|||
fn target(&self) -> DOMString {
|
||||
match *self {
|
||||
FormElement(form) => form.Target(),
|
||||
InputElement(input_element) => input_element.get_form_attribute("formtarget", |i| i.FormTarget(), |f| f.Target())
|
||||
InputElement(input_element) => {
|
||||
// FIXME(pcwalton): Make this a static atom.
|
||||
input_element.get_form_attribute(&Atom::from_slice("formtarget"),
|
||||
|i| i.FormTarget(),
|
||||
|f| f.Target())
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
pub trait FormOwner<'a> : Copy {
|
||||
fn form_owner(self) -> Option<Temporary<HTMLFormElement>>;
|
||||
fn get_form_attribute(self, attr: &str,
|
||||
fn get_form_attribute(self,
|
||||
attr: &Atom,
|
||||
input: |Self| -> DOMString,
|
||||
owner: |JSRef<HTMLFormElement>| -> DOMString) -> DOMString {
|
||||
if self.to_element().has_attribute(attr) {
|
||||
|
|
|
@ -87,7 +87,7 @@ impl<'a> HTMLIFrameElementHelpers for JSRef<'a, HTMLIFrameElement> {
|
|||
|
||||
fn get_url(self) -> Option<Url> {
|
||||
let element: JSRef<Element> = ElementCast::from_ref(self);
|
||||
element.get_attribute(ns!(""), "src").root().and_then(|src| {
|
||||
element.get_attribute(ns!(""), &atom!("src")).root().and_then(|src| {
|
||||
let url = src.value();
|
||||
if url.as_slice().is_empty() {
|
||||
None
|
||||
|
@ -150,22 +150,22 @@ impl HTMLIFrameElement {
|
|||
impl<'a> HTMLIFrameElementMethods for JSRef<'a, HTMLIFrameElement> {
|
||||
fn Src(self) -> DOMString {
|
||||
let element: JSRef<Element> = ElementCast::from_ref(self);
|
||||
element.get_string_attribute("src")
|
||||
element.get_string_attribute(&atom!("src"))
|
||||
}
|
||||
|
||||
fn SetSrc(self, src: DOMString) {
|
||||
let element: JSRef<Element> = ElementCast::from_ref(self);
|
||||
element.set_url_attribute("src", src)
|
||||
element.set_url_attribute(&atom!("src"), src)
|
||||
}
|
||||
|
||||
fn Sandbox(self) -> DOMString {
|
||||
let element: JSRef<Element> = ElementCast::from_ref(self);
|
||||
element.get_string_attribute("sandbox")
|
||||
element.get_string_attribute(&atom!("sandbox"))
|
||||
}
|
||||
|
||||
fn SetSandbox(self, sandbox: DOMString) {
|
||||
let element: JSRef<Element> = ElementCast::from_ref(self);
|
||||
element.set_string_attribute("sandbox", sandbox);
|
||||
element.set_string_attribute(&atom!("sandbox"), sandbox);
|
||||
}
|
||||
|
||||
fn GetContentWindow(self) -> Option<Temporary<Window>> {
|
||||
|
|
|
@ -113,7 +113,7 @@ impl<'a> HTMLImageElementMethods for JSRef<'a, HTMLImageElement> {
|
|||
|
||||
fn SetIsMap(self, is_map: bool) {
|
||||
let element: JSRef<Element> = ElementCast::from_ref(self);
|
||||
element.set_string_attribute("ismap", is_map.to_string())
|
||||
element.set_string_attribute(&atom!("ismap"), is_map.to_string())
|
||||
}
|
||||
|
||||
fn Width(self) -> u32 {
|
||||
|
@ -124,7 +124,7 @@ impl<'a> HTMLImageElementMethods for JSRef<'a, HTMLImageElement> {
|
|||
|
||||
fn SetWidth(self, width: u32) {
|
||||
let elem: JSRef<Element> = ElementCast::from_ref(self);
|
||||
elem.set_uint_attribute("width", width)
|
||||
elem.set_uint_attribute(&atom!("width"), width)
|
||||
}
|
||||
|
||||
fn Height(self) -> u32 {
|
||||
|
@ -135,7 +135,7 @@ impl<'a> HTMLImageElementMethods for JSRef<'a, HTMLImageElement> {
|
|||
|
||||
fn SetHeight(self, height: u32) {
|
||||
let elem: JSRef<Element> = ElementCast::from_ref(self);
|
||||
elem.set_uint_attribute("height", height)
|
||||
elem.set_uint_attribute(&atom!("height"), height)
|
||||
}
|
||||
|
||||
make_getter!(Name)
|
||||
|
@ -188,7 +188,7 @@ impl<'a> VirtualMethods for JSRef<'a, HTMLImageElement> {
|
|||
_ => (),
|
||||
}
|
||||
|
||||
if "src" == name.as_slice() {
|
||||
if atom!("src") == *name {
|
||||
self.update_image(None);
|
||||
}
|
||||
}
|
||||
|
|
|
@ -232,7 +232,7 @@ impl<'a> HTMLInputElementHelpers for JSRef<'a, HTMLInputElement> {
|
|||
fn get_radio_group(self) -> Option<String> {
|
||||
//TODO: determine form owner
|
||||
let elem: JSRef<Element> = ElementCast::from_ref(self);
|
||||
elem.get_attribute(ns!(""), "name")
|
||||
elem.get_attribute(ns!(""), &atom!("name"))
|
||||
.root()
|
||||
.map(|name| name.Value())
|
||||
}
|
||||
|
@ -409,7 +409,7 @@ impl<'a> FormOwner<'a> for JSRef<'a, HTMLInputElement> {
|
|||
fn form_owner(self) -> Option<Temporary<HTMLFormElement>> {
|
||||
// https://html.spec.whatwg.org/multipage/forms.html#reset-the-form-owner
|
||||
let elem: JSRef<Element> = ElementCast::from_ref(self);
|
||||
let owner = elem.get_string_attribute("form");
|
||||
let owner = elem.get_string_attribute(&atom!("form"));
|
||||
if !owner.is_empty() {
|
||||
let doc = document_from_node(self).root();
|
||||
let owner = doc.GetElementById(owner).root();
|
||||
|
|
|
@ -48,7 +48,7 @@ impl HTMLLinkElement {
|
|||
}
|
||||
}
|
||||
|
||||
fn get_attr(element: JSRef<Element>, name: &str) -> Option<String> {
|
||||
fn get_attr(element: JSRef<Element>, name: &Atom) -> Option<String> {
|
||||
let elem = element.get_attribute(ns!(""), name).root();
|
||||
elem.map(|e| e.value().as_slice().to_string())
|
||||
}
|
||||
|
@ -76,7 +76,7 @@ impl<'a> VirtualMethods for JSRef<'a, HTMLLinkElement> {
|
|||
}
|
||||
|
||||
let element: JSRef<Element> = ElementCast::from_ref(*self);
|
||||
let rel = get_attr(element, "rel");
|
||||
let rel = get_attr(element, &atom!("rel"));
|
||||
|
||||
match (rel, name.as_slice()) {
|
||||
(ref rel, "href") => {
|
||||
|
@ -97,8 +97,8 @@ impl<'a> VirtualMethods for JSRef<'a, HTMLLinkElement> {
|
|||
if tree_in_doc {
|
||||
let element: JSRef<Element> = ElementCast::from_ref(*self);
|
||||
|
||||
let rel = get_attr(element, "rel");
|
||||
let href = get_attr(element, "href");
|
||||
let rel = get_attr(element, &atom!("rel"));
|
||||
let href = get_attr(element, &atom!("href"));
|
||||
|
||||
match (rel, href) {
|
||||
(ref rel, Some(ref href)) if is_stylesheet(rel) => {
|
||||
|
|
|
@ -63,8 +63,8 @@ impl<'a> ProcessDataURL for JSRef<'a, HTMLObjectElement> {
|
|||
let elem: JSRef<Element> = ElementCast::from_ref(*self);
|
||||
|
||||
// TODO: support other values
|
||||
match (elem.get_attribute(ns!(""), "type").map(|x| x.root().Value()),
|
||||
elem.get_attribute(ns!(""), "data").map(|x| x.root().Value())) {
|
||||
match (elem.get_attribute(ns!(""), &atom!("type")).map(|x| x.root().Value()),
|
||||
elem.get_attribute(ns!(""), &atom!("data")).map(|x| x.root().Value())) {
|
||||
(None, Some(uri)) => {
|
||||
if is_image_data(uri.as_slice()) {
|
||||
let data_url = Url::parse(uri.as_slice()).unwrap();
|
||||
|
|
|
@ -74,7 +74,7 @@ impl<'a> HTMLOptionElementMethods for JSRef<'a, HTMLOptionElement> {
|
|||
// http://www.whatwg.org/html/#dom-option-disabled
|
||||
fn SetDisabled(self, disabled: bool) {
|
||||
let elem: JSRef<Element> = ElementCast::from_ref(self);
|
||||
elem.set_bool_attribute("disabled", disabled)
|
||||
elem.set_bool_attribute(&atom!("disabled"), disabled)
|
||||
}
|
||||
|
||||
// http://www.whatwg.org/html/#dom-option-text
|
||||
|
|
|
@ -75,7 +75,7 @@ static SCRIPT_JS_MIMES: StaticStringVec = &[
|
|||
impl<'a> HTMLScriptElementHelpers for JSRef<'a, HTMLScriptElement> {
|
||||
fn is_javascript(self) -> bool {
|
||||
let element: JSRef<Element> = ElementCast::from_ref(self);
|
||||
match element.get_attribute(ns!(""), "type").root().map(|s| s.Value()) {
|
||||
match element.get_attribute(ns!(""), &atom!("type")).root().map(|s| s.Value()) {
|
||||
Some(ref s) if s.is_empty() => {
|
||||
// type attr exists, but empty means js
|
||||
debug!("script type empty, inferring js");
|
||||
|
@ -87,7 +87,9 @@ impl<'a> HTMLScriptElementHelpers for JSRef<'a, HTMLScriptElement> {
|
|||
},
|
||||
None => {
|
||||
debug!("no script type");
|
||||
match element.get_attribute(ns!(""), "language").root().map(|s| s.Value()) {
|
||||
match element.get_attribute(ns!(""), &atom!("language"))
|
||||
.root()
|
||||
.map(|s| s.Value()) {
|
||||
Some(ref s) if s.is_empty() => {
|
||||
debug!("script language empty, inferring js");
|
||||
true
|
||||
|
@ -109,7 +111,7 @@ impl<'a> HTMLScriptElementHelpers for JSRef<'a, HTMLScriptElement> {
|
|||
impl<'a> HTMLScriptElementMethods for JSRef<'a, HTMLScriptElement> {
|
||||
fn Src(self) -> DOMString {
|
||||
let element: JSRef<Element> = ElementCast::from_ref(self);
|
||||
element.get_url_attribute("src")
|
||||
element.get_url_attribute(&atom!("src"))
|
||||
}
|
||||
|
||||
// http://www.whatwg.org/html/#dom-script-text
|
||||
|
|
|
@ -67,7 +67,7 @@ impl<'a> HTMLSelectElementMethods for JSRef<'a, HTMLSelectElement> {
|
|||
// https://html.spec.whatwg.org/multipage/forms.html#dom-select-type
|
||||
fn Type(self) -> DOMString {
|
||||
let elem: JSRef<Element> = ElementCast::from_ref(self);
|
||||
if elem.has_attribute("multiple") {
|
||||
if elem.has_attribute(&atom!("multiple")) {
|
||||
"select-multiple".to_string()
|
||||
} else {
|
||||
"select-one".to_string()
|
||||
|
|
|
@ -11,7 +11,7 @@ macro_rules! make_getter(
|
|||
#[allow(unused_imports)]
|
||||
use std::ascii::StrAsciiExt;
|
||||
let element: JSRef<Element> = ElementCast::from_ref(self);
|
||||
element.get_string_attribute($htmlname)
|
||||
element.get_string_attribute(&Atom::from_slice($htmlname.to_ascii_lower().as_slice()))
|
||||
}
|
||||
);
|
||||
($attr:ident) => {
|
||||
|
@ -28,7 +28,8 @@ macro_rules! make_bool_getter(
|
|||
#[allow(unused_imports)]
|
||||
use std::ascii::StrAsciiExt;
|
||||
let element: JSRef<Element> = ElementCast::from_ref(self);
|
||||
element.has_attribute($htmlname)
|
||||
// FIXME(pcwalton): Do this at compile time, not runtime.
|
||||
element.has_attribute(&Atom::from_slice($htmlname))
|
||||
}
|
||||
);
|
||||
($attr:ident) => {
|
||||
|
@ -45,7 +46,8 @@ macro_rules! make_uint_getter(
|
|||
#[allow(unused_imports)]
|
||||
use std::ascii::StrAsciiExt;
|
||||
let element: JSRef<Element> = ElementCast::from_ref(self);
|
||||
element.get_uint_attribute($htmlname)
|
||||
// FIXME(pcwalton): Do this at compile time, not runtime.
|
||||
element.get_uint_attribute(&Atom::from_slice($htmlname))
|
||||
}
|
||||
);
|
||||
($attr:ident) => {
|
||||
|
@ -62,10 +64,12 @@ macro_rules! make_url_getter(
|
|||
#[allow(unused_imports)]
|
||||
use std::ascii::StrAsciiExt;
|
||||
let element: JSRef<Element> = ElementCast::from_ref(self);
|
||||
element.get_url_attribute($htmlname)
|
||||
// FIXME(pcwalton): Do this at compile time, not runtime.
|
||||
element.get_url_attribute(&Atom::from_slice($htmlname))
|
||||
}
|
||||
);
|
||||
($attr:ident) => {
|
||||
// FIXME(pcwalton): Do this at compile time, not runtime.
|
||||
make_url_getter!($attr, stringify!($attr).to_ascii_lower().as_slice())
|
||||
}
|
||||
)
|
||||
|
@ -79,7 +83,7 @@ macro_rules! make_url_or_base_getter(
|
|||
#[allow(unused_imports)]
|
||||
use std::ascii::StrAsciiExt;
|
||||
let element: JSRef<Element> = ElementCast::from_ref(self);
|
||||
let url = element.get_url_attribute($htmlname);
|
||||
let url = element.get_url_attribute(&Atom::from_slice($htmlname));
|
||||
match url.as_slice() {
|
||||
"" => {
|
||||
let window = window_from_node(self).root();
|
||||
|
@ -103,7 +107,8 @@ macro_rules! make_enumerated_getter(
|
|||
#[allow(unused_imports)]
|
||||
use std::ascii::StrAsciiExt;
|
||||
let element: JSRef<Element> = ElementCast::from_ref(self);
|
||||
let val = element.get_string_attribute($htmlname).into_ascii_lower();
|
||||
let val = element.get_string_attribute(&Atom::from_slice($htmlname))
|
||||
.into_ascii_lower();
|
||||
// https://html.spec.whatwg.org/multipage/forms.html#attr-fs-method
|
||||
match val.as_slice() {
|
||||
$($choices)|+ => val,
|
||||
|
@ -125,7 +130,8 @@ macro_rules! make_setter(
|
|||
use dom::element::{Element, AttributeHandlers};
|
||||
use dom::bindings::codegen::InheritTypes::ElementCast;
|
||||
let element: JSRef<Element> = ElementCast::from_ref(self);
|
||||
element.set_string_attribute($htmlname, value)
|
||||
// FIXME(pcwalton): Do this at compile time, not at runtime.
|
||||
element.set_string_attribute(&Atom::from_slice($htmlname), value)
|
||||
}
|
||||
);
|
||||
)
|
||||
|
@ -137,7 +143,8 @@ macro_rules! make_bool_setter(
|
|||
use dom::element::{Element, AttributeHandlers};
|
||||
use dom::bindings::codegen::InheritTypes::ElementCast;
|
||||
let element: JSRef<Element> = ElementCast::from_ref(self);
|
||||
element.set_bool_attribute($htmlname, value)
|
||||
// FIXME(pcwalton): Do this at compile time, not at runtime.
|
||||
element.set_bool_attribute(&Atom::from_slice($htmlname), value)
|
||||
}
|
||||
);
|
||||
)
|
||||
|
@ -149,7 +156,8 @@ macro_rules! make_uint_setter(
|
|||
use dom::element::{Element, AttributeHandlers};
|
||||
use dom::bindings::codegen::InheritTypes::ElementCast;
|
||||
let element: JSRef<Element> = ElementCast::from_ref(self);
|
||||
element.set_uint_attribute($htmlname, value)
|
||||
// FIXME(pcwalton): Do this at compile time, not at runtime.
|
||||
element.set_uint_attribute(&Atom::from_slice($htmlname), value)
|
||||
}
|
||||
);
|
||||
)
|
||||
|
|
|
@ -919,16 +919,19 @@ pub trait RawLayoutNodeHelpers {
|
|||
}
|
||||
|
||||
impl RawLayoutNodeHelpers for Node {
|
||||
#[inline]
|
||||
unsafe fn get_hover_state_for_layout(&self) -> bool {
|
||||
(*self.unsafe_get_flags()).contains(InHoverState)
|
||||
}
|
||||
#[inline]
|
||||
unsafe fn get_disabled_state_for_layout(&self) -> bool {
|
||||
(*self.unsafe_get_flags()).contains(InDisabledState)
|
||||
}
|
||||
#[inline]
|
||||
unsafe fn get_enabled_state_for_layout(&self) -> bool {
|
||||
(*self.unsafe_get_flags()).contains(InEnabledState)
|
||||
}
|
||||
|
||||
#[inline]
|
||||
fn type_id_for_layout(&self) -> NodeTypeId {
|
||||
self.type_id
|
||||
}
|
||||
|
@ -1581,6 +1584,7 @@ impl Node {
|
|||
}
|
||||
}
|
||||
|
||||
#[inline]
|
||||
pub unsafe fn unsafe_get_flags(&self) -> *const NodeFlags {
|
||||
mem::transmute(&self.flags)
|
||||
}
|
||||
|
@ -2221,9 +2225,9 @@ impl<'a> style::TNode<'a, JSRef<'a, Element>> for JSRef<'a, Node> {
|
|||
fn match_attr(self, attr: &style::AttrSelector, test: |&str| -> bool) -> bool {
|
||||
let name = {
|
||||
if self.is_html_element_in_html_document() {
|
||||
attr.lower_name.as_slice()
|
||||
&attr.lower_name
|
||||
} else {
|
||||
attr.name.as_slice()
|
||||
&attr.name
|
||||
}
|
||||
};
|
||||
match attr.namespace {
|
||||
|
@ -2294,7 +2298,7 @@ impl<'a> DisabledStateHelpers for JSRef<'a, Node> {
|
|||
|
||||
fn check_disabled_attribute(self) {
|
||||
let elem: JSRef<'a, Element> = ElementCast::to_ref(self).unwrap();
|
||||
let has_disabled_attrib = elem.has_attribute("disabled");
|
||||
let has_disabled_attrib = elem.has_attribute(&atom!("disabled"));
|
||||
self.set_disabled_state(has_disabled_attrib);
|
||||
self.set_enabled_state(!has_disabled_attrib);
|
||||
}
|
||||
|
|
|
@ -481,7 +481,7 @@ pub fn parse_html(page: &Page,
|
|||
};
|
||||
|
||||
let script_element: JSRef<Element> = ElementCast::from_ref(script);
|
||||
match script_element.get_attribute(ns!(""), "src").root() {
|
||||
match script_element.get_attribute(ns!(""), &atom!("src")).root() {
|
||||
Some(src) => {
|
||||
debug!("found script: {:s}", src.Value());
|
||||
let mut url_parser = UrlParser::new();
|
||||
|
|
|
@ -35,3 +35,4 @@ git = "https://github.com/servo/string-cache"
|
|||
|
||||
[dependencies.string_cache_macros]
|
||||
git = "https://github.com/servo/string-cache"
|
||||
|
||||
|
|
|
@ -11,6 +11,7 @@
|
|||
|
||||
#![feature(phase)]
|
||||
#[phase(plugin, link)] extern crate log;
|
||||
#[phase(plugin)] extern crate string_cache_macros;
|
||||
|
||||
extern crate debug;
|
||||
extern crate collections;
|
||||
|
|
|
@ -8,7 +8,6 @@
|
|||
use selectors::AttrSelector;
|
||||
use string_cache::{Atom, Namespace};
|
||||
|
||||
|
||||
pub trait TNode<'a, E: TElement<'a>> : Clone + Copy {
|
||||
fn parent_node(self) -> Option<Self>;
|
||||
fn first_child(self) -> Option<Self>;
|
||||
|
@ -28,8 +27,8 @@ 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_attr(self, namespace: &Namespace, attr: &Atom) -> Option<&'a str>;
|
||||
fn get_attrs(self, attr: &Atom) -> Vec<&'a str>;
|
||||
fn get_link(self) -> Option<&'a str>;
|
||||
fn get_local_name(self) -> &'a Atom;
|
||||
fn get_namespace(self) -> &'a Namespace;
|
||||
|
@ -37,6 +36,13 @@ pub trait TElement<'a> : Copy {
|
|||
fn get_id(self) -> Option<Atom>;
|
||||
fn get_disabled_state(self) -> bool;
|
||||
fn get_enabled_state(self) -> bool;
|
||||
fn has_class(self, name: &str) -> bool;
|
||||
fn has_class(self, name: &Atom) -> bool;
|
||||
|
||||
// Ordinarily I wouldn't use callbacks like this, but the alternative is
|
||||
// really messy, since there is a `JSRef` and a `RefCell` involved. Maybe
|
||||
// in the future when we have associated types and/or a more convenient
|
||||
// JS GC story... --pcwalton
|
||||
fn each_class(self, callback: |&Atom|);
|
||||
}
|
||||
|
||||
|
||||
|
|
|
@ -108,20 +108,14 @@ impl SelectorMap {
|
|||
None => {}
|
||||
}
|
||||
|
||||
match element.get_attr(&ns!(""), "class") {
|
||||
Some(ref class_attr) => {
|
||||
// FIXME: Store classes pre-split as atoms to make the loop below faster.
|
||||
for class in class_attr.split(SELECTOR_WHITESPACE) {
|
||||
element.each_class(|class| {
|
||||
SelectorMap::get_matching_rules_from_hash(node,
|
||||
parent_bf,
|
||||
&self.class_hash,
|
||||
&Atom::from_slice(class),
|
||||
class,
|
||||
matching_rules_list,
|
||||
shareable);
|
||||
}
|
||||
}
|
||||
None => {}
|
||||
}
|
||||
});
|
||||
|
||||
let local_name_hash = if node.is_html_element_in_html_document() {
|
||||
&self.lower_local_name_hash
|
||||
|
@ -699,12 +693,12 @@ fn matches_compound_selector_internal<'a,
|
|||
/// will almost certainly break as nodes will start mistakenly sharing styles. (See the code in
|
||||
/// `main/css/matching.rs`.)
|
||||
#[inline]
|
||||
pub fn matches_simple_selector<'a, E:TElement<'a>,
|
||||
N:TNode<'a, E>>(
|
||||
pub fn matches_simple_selector<'a,E,N>(
|
||||
selector: &SimpleSelector,
|
||||
element: &N,
|
||||
shareable: &mut bool)
|
||||
-> bool {
|
||||
-> bool
|
||||
where E:TElement<'a>, N:TNode<'a,E> {
|
||||
match *selector {
|
||||
LocalNameSelector(LocalName { ref name, ref lower_name }) => {
|
||||
let name = if element.is_html_element_in_html_document() { lower_name } else { name };
|
||||
|
@ -718,7 +712,6 @@ pub fn matches_simple_selector<'a, E:TElement<'a>,
|
|||
element.get_namespace() == namespace
|
||||
}
|
||||
// TODO: case-sensitivity depends on the document type and quirks mode
|
||||
// TODO: cache and intern IDs on elements.
|
||||
IDSelector(ref id) => {
|
||||
*shareable = false;
|
||||
let element = element.as_element();
|
||||
|
@ -726,10 +719,9 @@ pub fn matches_simple_selector<'a, E:TElement<'a>,
|
|||
attr == *id
|
||||
})
|
||||
}
|
||||
// TODO: cache and intern class names on elements.
|
||||
ClassSelector(ref class) => {
|
||||
let element = element.as_element();
|
||||
element.has_class(class.as_slice())
|
||||
element.has_class(class)
|
||||
}
|
||||
|
||||
AttrExists(ref attr) => {
|
||||
|
@ -876,6 +868,7 @@ pub fn matches_simple_selector<'a, E:TElement<'a>,
|
|||
}
|
||||
}
|
||||
|
||||
#[inline]
|
||||
fn url_is_visited(_url: &str) -> bool {
|
||||
// FIXME: implement this.
|
||||
// This function will probably need to take a "session"
|
||||
|
@ -884,15 +877,14 @@ fn url_is_visited(_url: &str) -> bool {
|
|||
}
|
||||
|
||||
#[inline]
|
||||
fn matches_generic_nth_child<'a,
|
||||
E:TElement<'a>,
|
||||
N:TNode<'a, E>>(
|
||||
fn matches_generic_nth_child<'a,E,N>(
|
||||
element: &N,
|
||||
a: i32,
|
||||
b: i32,
|
||||
is_of_type: bool,
|
||||
is_from_end: bool)
|
||||
-> bool {
|
||||
-> bool
|
||||
where E: TElement<'a>, N: TNode<'a,E> {
|
||||
let mut node = element.clone();
|
||||
// fail if we can't find a parent or if the node is the root element
|
||||
// of the document (Cf. Selectors Level 3)
|
||||
|
|
|
@ -106,8 +106,8 @@ pub struct LocalName {
|
|||
|
||||
#[deriving(Eq, PartialEq, Clone, Hash)]
|
||||
pub struct AttrSelector {
|
||||
pub name: String,
|
||||
pub lower_name: String,
|
||||
pub name: Atom,
|
||||
pub lower_name: Atom,
|
||||
pub namespace: NamespaceConstraint,
|
||||
}
|
||||
|
||||
|
@ -448,8 +448,8 @@ fn parse_attribute_selector(content: Vec<ComponentValue>, namespaces: &Namespace
|
|||
Some((_, None)) => fail!("Implementation error, this should not happen."),
|
||||
Some((namespace, Some(local_name))) => AttrSelector {
|
||||
namespace: namespace,
|
||||
lower_name: local_name.as_slice().to_ascii_lower(),
|
||||
name: local_name,
|
||||
lower_name: Atom::from_slice(local_name.as_slice().to_ascii_lower().as_slice()),
|
||||
name: Atom::from_slice(local_name.as_slice()),
|
||||
},
|
||||
};
|
||||
skip_whitespace(iter);
|
||||
|
@ -675,8 +675,8 @@ mod tests {
|
|||
assert!(parse_ns("[Foo]", &namespaces) == Ok(vec!(Selector {
|
||||
compound_selectors: Arc::new(CompoundSelector {
|
||||
simple_selectors: vec!(AttrExists(AttrSelector {
|
||||
name: String::from_str("Foo"),
|
||||
lower_name: String::from_str("foo"),
|
||||
name: Atom::from_slice("Foo"),
|
||||
lower_name: Atom::from_slice("foo"),
|
||||
namespace: SpecificNamespace(ns!("")),
|
||||
})),
|
||||
next: None,
|
||||
|
@ -690,8 +690,8 @@ mod tests {
|
|||
assert!(parse_ns("[Foo]", &namespaces) == Ok(vec!(Selector {
|
||||
compound_selectors: Arc::new(CompoundSelector {
|
||||
simple_selectors: vec!(AttrExists(AttrSelector {
|
||||
name: String::from_str("Foo"),
|
||||
lower_name: String::from_str("foo"),
|
||||
name: Atom::from_slice("Foo"),
|
||||
lower_name: Atom::from_slice("foo"),
|
||||
namespace: SpecificNamespace(ns!("")),
|
||||
})),
|
||||
next: None,
|
||||
|
|
Загрузка…
Ссылка в новой задаче