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