auto merge of #1867 : saneyuki/servo/1828, r=pcwalton

Fix #1828
This commit is contained in:
bors-servo 2014-03-20 14:10:54 -04:00
commit 0265fb9784
6 changed files with 110 additions and 134 deletions

View file

@ -216,18 +216,17 @@ impl StyleSharingCandidate {
let mut style = Some(style);
let mut parent_style = Some(parent_style);
node.with_element(|element| {
if element.style_attribute().is_some() {
return None
}
let element = node.as_element();
if element.style_attribute().is_some() {
return None
}
Some(StyleSharingCandidate {
style: style.take_unwrap(),
parent_style: parent_style.take_unwrap(),
local_name: element.get_local_name().to_str(),
class: element.get_attr(&Null, "class")
.map(|string| string.to_str()),
})
Some(StyleSharingCandidate {
style: style.take_unwrap(),
parent_style: parent_style.take_unwrap(),
local_name: element.get_local_name().to_str(),
class: element.get_attr(&Null, "class")
.map(|string| string.to_str()),
})
}
@ -401,7 +400,7 @@ impl<'ln> PrivateMatchMethods for LayoutNode<'ln> {
}
// Check tag names, classes, etc.
if !self.with_element(|element| candidate.can_share_style_with(element)) {
if !candidate.can_share_style_with(&self.as_element()) {
return None
}
@ -419,9 +418,7 @@ impl<'ln> MatchMethods for LayoutNode<'ln> {
stylist: &Stylist,
applicable_declarations: &mut ApplicableDeclarations,
shareable: &mut bool) {
let style_attribute = self.with_element(|element| {
element.style_attribute().as_ref()
});
let style_attribute = self.as_element().style_attribute().as_ref();
applicable_declarations.normal_shareable =
stylist.push_applicable_declarations(self,
@ -448,9 +445,10 @@ impl<'ln> MatchMethods for LayoutNode<'ln> {
if !self.is_element() {
return CannotShare(false)
}
let ok = self.with_element(|element| {
let ok = {
let element = self.as_element();
element.style_attribute().is_none() && element.get_attr(&Null, "id").is_none()
});
};
if !ok {
return CannotShare(false)
}

View file

@ -132,12 +132,11 @@ impl ImageBoxInfo {
local_image_cache: MutexArc<LocalImageCache>)
-> ImageBoxInfo {
fn convert_length(node: &ThreadSafeLayoutNode, name: &str) -> Option<Au> {
node.with_element(|element| {
element.get_attr(&namespace::Null, name).and_then(|string| {
let n: Option<int> = FromStr::from_str(string);
n
}).and_then(|pixels| Some(Au::from_px(pixels)))
})
let element = node.as_element();
element.get_attr(&namespace::Null, name).and_then(|string| {
let n: Option<int> = FromStr::from_str(string);
n
}).and_then(|pixels| Some(Au::from_px(pixels)))
}
ImageBoxInfo {

View file

@ -851,8 +851,8 @@ trait ObjectElement {
impl<'ln> ObjectElement for ThreadSafeLayoutNode<'ln> {
fn get_type_and_data(&self) -> (Option<&'static str>, Option<&'static str>) {
(self.with_element(|e| { e.get_attr(&namespace::Null, "type") } ),
self.with_element(|e| { e.get_attr(&namespace::Null, "data") } ))
let elem = self.as_element();
(elem.get_attr(&namespace::Null, "type"), elem.get_attr(&namespace::Null, "data"))
}
fn has_object_data(&self) -> bool {

View file

@ -34,7 +34,7 @@
//! `html_element_in_html_document_for_layout()`.
use extra::url::Url;
use script::dom::bindings::codegen::InheritTypes::{ElementDerived, HTMLIFrameElementDerived};
use script::dom::bindings::codegen::InheritTypes::{HTMLIFrameElementDerived};
use script::dom::bindings::codegen::InheritTypes::{HTMLImageElementDerived, TextDerived};
use script::dom::bindings::js::JS;
use script::dom::element::{Element, HTMLAreaElementTypeId, HTMLAnchorElementTypeId};
@ -228,16 +228,13 @@ impl<'ln> TNode<LayoutElement<'ln>> for LayoutNode<'ln> {
/// If this is an element, accesses the element data. Fails if this is not an element node.
#[inline]
fn with_element<R>(&self, f: |&LayoutElement<'ln>| -> R) -> R {
fn as_element(&self) -> LayoutElement<'ln> {
unsafe {
if !self.node.is_element() {
fail!("not an element!")
}
let elem: JS<Element> = self.node.transmute_copy();
let element = elem.get();
f(&LayoutElement {
LayoutElement {
element: cast::transmute_region(element),
})
}
}
}
@ -250,23 +247,22 @@ impl<'ln> TNode<LayoutElement<'ln>> for LayoutNode<'ln> {
}
fn match_attr(&self, attr: &AttrSelector, test: |&str| -> bool) -> bool {
self.with_element(|element| {
let name = unsafe {
if element.element.html_element_in_html_document_for_layout() {
attr.lower_name.as_slice()
} else {
attr.name.as_slice()
}
};
match attr.namespace {
SpecificNamespace(ref ns) => {
element.get_attr(ns, name)
.map_or(false, |attr| test(attr))
},
// FIXME: https://github.com/mozilla/servo/issues/1558
AnyNamespace => false,
let element = self.as_element();
let name = unsafe {
if element.element.html_element_in_html_document_for_layout() {
attr.lower_name.as_slice()
} else {
attr.name.as_slice()
}
})
};
match attr.namespace {
SpecificNamespace(ref ns) => {
element.get_attr(ns, name)
.map_or(false, |attr| test(attr))
},
// FIXME: https://github.com/mozilla/servo/issues/1558
AnyNamespace => false,
}
}
}
@ -433,18 +429,15 @@ impl<'ln> ThreadSafeLayoutNode<'ln> {
/// If this is an element, accesses the element data. Fails if this is not an element node.
#[inline]
pub fn with_element<R>(&self, f: |&ThreadSafeLayoutElement| -> R) -> R {
pub fn as_element(&self) -> ThreadSafeLayoutElement {
unsafe {
if !self.node.is_element() {
fail!("not an element!")
}
let elem: JS<Element> = self.node.transmute_copy();
let element = elem.unsafe_get();
// FIXME(pcwalton): Workaround until Rust gets multiple lifetime parameters on
// implementations.
f(&ThreadSafeLayoutElement {
ThreadSafeLayoutElement {
element: cast::transmute::<*mut Element,&mut Element>(element),
})
}
}
}

View file

@ -15,10 +15,7 @@ pub trait TNode<E:TElement> : Clone {
fn next_sibling(&self) -> Option<Self>;
fn is_document(&self) -> bool;
fn is_element(&self) -> bool;
/// FIXME(pcwalton): This should not use the `with` pattern.
fn with_element<'a, R>(&self, f: |&E| -> R) -> R;
fn as_element(&self) -> E;
fn match_attr(&self, attr: &AttrSelector, test: |&str| -> bool) -> bool;
}

View file

@ -117,44 +117,43 @@ impl SelectorMap {
// At the end, we're going to sort the rules that we added, so remember where we began.
let init_len = matching_rules_list.len();
node.with_element(|element: &E| {
match element.get_attr(&namespace::Null, "id") {
Some(id) => {
let element = node.as_element();
match element.get_attr(&namespace::Null, "id") {
Some(id) => {
SelectorMap::get_matching_rules_from_hash(node,
&self.id_hash,
id,
matching_rules_list,
shareable)
}
None => {}
}
match element.get_attr(&namespace::Null, "class") {
Some(ref class_attr) => {
for class in class_attr.split(SELECTOR_WHITESPACE) {
SelectorMap::get_matching_rules_from_hash(node,
&self.id_hash,
id,
matching_rules_list,
shareable)
&self.class_hash,
class,
matching_rules_list,
shareable);
}
None => {}
}
None => {}
}
match element.get_attr(&namespace::Null, "class") {
Some(ref class_attr) => {
for class in class_attr.split(SELECTOR_WHITESPACE) {
SelectorMap::get_matching_rules_from_hash(node,
&self.class_hash,
class,
matching_rules_list,
shareable);
}
}
None => {}
}
// HTML elements in HTML documents must be matched case-insensitively.
// TODO(pradeep): Case-sensitivity depends on the document type.
SelectorMap::get_matching_rules_from_hash_ignoring_case(node,
&self.element_hash,
element.get_local_name(),
matching_rules_list,
shareable);
// HTML elements in HTML documents must be matched case-insensitively.
// TODO(pradeep): Case-sensitivity depends on the document type.
SelectorMap::get_matching_rules_from_hash_ignoring_case(node,
&self.element_hash,
element.get_local_name(),
matching_rules_list,
shareable);
SelectorMap::get_matching_rules(node,
self.universal_rules,
matching_rules_list,
shareable);
});
SelectorMap::get_matching_rules(node,
self.universal_rules,
matching_rules_list,
shareable);
// Sort only the rules we just added.
sort::quicksort(matching_rules_list.mut_slice_from(init_len));
@ -582,36 +581,32 @@ fn matches_simple_selector<E:TElement,
// TODO: case-sensitivity depends on the document type
// TODO: intern element names
LocalNameSelector(ref name) => {
element.with_element(|element: &E| {
element.get_local_name().eq_ignore_ascii_case(name.as_slice())
})
let element = element.as_element();
element.get_local_name().eq_ignore_ascii_case(name.as_slice())
}
NamespaceSelector(ref namespace) => {
*shareable = false;
element.with_element(|element: &E| {
element.get_namespace() == namespace
})
let element = element.as_element();
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;
element.with_element(|element: &E| {
element.get_attr(&namespace::Null, "id")
.map_or(false, |attr| {
attr == *id
})
let element = element.as_element();
element.get_attr(&namespace::Null, "id")
.map_or(false, |attr| {
attr == *id
})
}
// TODO: cache and intern class names on elements.
ClassSelector(ref class) => {
element.with_element(|element: &E| {
element.get_attr(&namespace::Null, "class")
.map_or(false, |attr| {
// TODO: case-sensitivity depends on the document type and quirks mode
attr.split(SELECTOR_WHITESPACE).any(|c| c == class.as_slice())
})
let element = element.as_element();
element.get_attr(&namespace::Null, "class")
.map_or(false, |attr| {
// TODO: case-sensitivity depends on the document type and quirks mode
attr.split(SELECTOR_WHITESPACE).any(|c| c == class.as_slice())
})
}
@ -663,34 +658,30 @@ fn matches_simple_selector<E:TElement,
AnyLink => {
*shareable = false;
element.with_element(|element: &E| {
element.get_link().is_some()
})
let element = element.as_element();
element.get_link().is_some()
}
Link => {
*shareable = false;
element.with_element(|element: &E| {
match element.get_link() {
Some(url) => !url_is_visited(url),
None => false,
}
})
let elem = element.as_element();
match elem.get_link() {
Some(url) => !url_is_visited(url),
None => false,
}
}
Visited => {
*shareable = false;
element.with_element(|element: &E| {
match element.get_link() {
Some(url) => url_is_visited(url),
None => false,
}
})
let elem = element.as_element();
match elem.get_link() {
Some(url) => url_is_visited(url),
None => false,
}
}
Hover => {
*shareable = false;
element.with_element(|element: &E| {
element.get_hover_state()
})
let elem = element.as_element();
elem.get_hover_state()
},
FirstChild => {
*shareable = false;
@ -791,14 +782,12 @@ fn matches_generic_nth_child<'a,
if node.is_element() {
if is_of_type {
element.with_element(|element: &E| {
node.with_element(|node: &E| {
if element.get_local_name() == node.get_local_name() &&
element.get_namespace() == node.get_namespace() {
index += 1;
}
})
})
let element = element.as_element();
let node = node.as_element();
if element.get_local_name() == node.get_local_name() &&
element.get_namespace() == node.get_namespace() {
index += 1;
}
} else {
index += 1;
}