mirror of
https://github.com/servo/servo.git
synced 2025-08-05 21:50:18 +01:00
commit
0265fb9784
6 changed files with 110 additions and 134 deletions
|
@ -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)
|
||||
}
|
||||
|
|
|
@ -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 {
|
||||
|
|
|
@ -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 {
|
||||
|
|
|
@ -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),
|
||||
})
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
@ -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;
|
||||
}
|
||||
|
||||
|
|
|
@ -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;
|
||||
}
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue