Bug 1365471: Check bool flags before going through FFI in a variety of situations. r=bz

MozReview-Commit-ID: E6mitc11tYa
Signed-off-by: Emilio Cobos Álvarez <emilio@crisal.io>
This commit is contained in:
Emilio Cobos Álvarez 2017-05-17 16:00:31 +02:00
parent 8375319928
commit b420b80073
No known key found for this signature in database
GPG key ID: 056B727BB9C1027C

View file

@ -46,7 +46,7 @@ use gecko_bindings::bindings::Gecko_MatchStringArgPseudo;
use gecko_bindings::bindings::Gecko_UpdateAnimations; use gecko_bindings::bindings::Gecko_UpdateAnimations;
use gecko_bindings::structs; use gecko_bindings::structs;
use gecko_bindings::structs::{RawGeckoElement, RawGeckoNode}; use gecko_bindings::structs::{RawGeckoElement, RawGeckoNode};
use gecko_bindings::structs::{nsIAtom, nsIContent, nsStyleContext}; use gecko_bindings::structs::{nsIAtom, nsIContent, nsINode_BooleanFlag, nsStyleContext};
use gecko_bindings::structs::ELEMENT_HANDLED_SNAPSHOT; use gecko_bindings::structs::ELEMENT_HANDLED_SNAPSHOT;
use gecko_bindings::structs::ELEMENT_HAS_ANIMATION_ONLY_DIRTY_DESCENDANTS_FOR_SERVO; use gecko_bindings::structs::ELEMENT_HAS_ANIMATION_ONLY_DIRTY_DESCENDANTS_FOR_SERVO;
use gecko_bindings::structs::ELEMENT_HAS_DIRTY_DESCENDANTS_FOR_SERVO; use gecko_bindings::structs::ELEMENT_HAS_DIRTY_DESCENDANTS_FOR_SERVO;
@ -104,14 +104,17 @@ impl<'ln> fmt::Debug for GeckoNode<'ln> {
} }
impl<'ln> GeckoNode<'ln> { impl<'ln> GeckoNode<'ln> {
#[inline]
fn from_content(content: &'ln nsIContent) -> Self { fn from_content(content: &'ln nsIContent) -> Self {
GeckoNode(&content._base) GeckoNode(&content._base)
} }
#[inline]
fn flags(&self) -> u32 { fn flags(&self) -> u32 {
(self.0)._base._base_1.mFlags (self.0)._base._base_1.mFlags
} }
#[inline]
fn node_info(&self) -> &structs::NodeInfo { fn node_info(&self) -> &structs::NodeInfo {
debug_assert!(!self.0.mNodeInfo.mRawPtr.is_null()); debug_assert!(!self.0.mNodeInfo.mRawPtr.is_null());
unsafe { &*self.0.mNodeInfo.mRawPtr } unsafe { &*self.0.mNodeInfo.mRawPtr }
@ -119,32 +122,43 @@ impl<'ln> GeckoNode<'ln> {
// These live in different locations depending on processor architecture. // These live in different locations depending on processor architecture.
#[cfg(target_pointer_width = "64")] #[cfg(target_pointer_width = "64")]
#[inline]
fn bool_flags(&self) -> u32 { fn bool_flags(&self) -> u32 {
(self.0)._base._base_1.mBoolFlags (self.0)._base._base_1.mBoolFlags
} }
#[cfg(target_pointer_width = "32")] #[cfg(target_pointer_width = "32")]
#[inline]
fn bool_flags(&self) -> u32 { fn bool_flags(&self) -> u32 {
(self.0).mBoolFlags (self.0).mBoolFlags
} }
#[inline]
fn get_bool_flag(&self, flag: nsINode_BooleanFlag) -> bool {
self.bool_flags() & (1u32 << flag as u32) != 0
}
fn owner_doc(&self) -> &structs::nsIDocument { fn owner_doc(&self) -> &structs::nsIDocument {
debug_assert!(!self.node_info().mDocument.is_null()); debug_assert!(!self.node_info().mDocument.is_null());
unsafe { &*self.node_info().mDocument } unsafe { &*self.node_info().mDocument }
} }
#[inline]
fn first_child(&self) -> Option<GeckoNode<'ln>> { fn first_child(&self) -> Option<GeckoNode<'ln>> {
unsafe { self.0.mFirstChild.as_ref().map(GeckoNode::from_content) } unsafe { self.0.mFirstChild.as_ref().map(GeckoNode::from_content) }
} }
#[inline]
fn last_child(&self) -> Option<GeckoNode<'ln>> { fn last_child(&self) -> Option<GeckoNode<'ln>> {
unsafe { Gecko_GetLastChild(self.0).map(GeckoNode) } unsafe { Gecko_GetLastChild(self.0).map(GeckoNode) }
} }
#[inline]
fn prev_sibling(&self) -> Option<GeckoNode<'ln>> { fn prev_sibling(&self) -> Option<GeckoNode<'ln>> {
unsafe { self.0.mPreviousSibling.as_ref().map(GeckoNode::from_content) } unsafe { self.0.mPreviousSibling.as_ref().map(GeckoNode::from_content) }
} }
#[inline]
fn next_sibling(&self) -> Option<GeckoNode<'ln>> { fn next_sibling(&self) -> Option<GeckoNode<'ln>> {
unsafe { self.0.mNextSibling.as_ref().map(GeckoNode::from_content) } unsafe { self.0.mNextSibling.as_ref().map(GeckoNode::from_content) }
} }
@ -186,9 +200,9 @@ impl<'ln> GeckoNode<'ln> {
} }
impl<'ln> NodeInfo for GeckoNode<'ln> { impl<'ln> NodeInfo for GeckoNode<'ln> {
#[inline]
fn is_element(&self) -> bool { fn is_element(&self) -> bool {
use gecko_bindings::structs::nsINode_BooleanFlag; self.get_bool_flag(nsINode_BooleanFlag::NodeIsElement)
self.bool_flags() & (1u32 << nsINode_BooleanFlag::NodeIsElement as u32) != 0
} }
fn is_text_node(&self) -> bool { fn is_text_node(&self) -> bool {
@ -408,10 +422,24 @@ impl<'le> GeckoElement<'le> {
} }
} }
#[inline]
fn may_have_animations(&self) -> bool { fn may_have_animations(&self) -> bool {
use gecko_bindings::structs::nsINode_BooleanFlag; self.as_node().get_bool_flag(nsINode_BooleanFlag::ElementHasAnimations)
self.as_node().bool_flags() & }
(1u32 << nsINode_BooleanFlag::ElementHasAnimations as u32) != 0
#[inline]
fn has_id(&self) -> bool {
self.as_node().get_bool_flag(nsINode_BooleanFlag::ElementHasID)
}
#[inline]
fn may_have_class(&self) -> bool {
self.as_node().get_bool_flag(nsINode_BooleanFlag::ElementMayHaveClass)
}
#[inline]
fn may_have_style_attribute(&self) -> bool {
self.as_node().get_bool_flag(nsINode_BooleanFlag::ElementMayHaveStyle)
} }
} }
@ -564,8 +592,12 @@ impl<'le> TElement for GeckoElement<'le> {
} }
fn style_attribute(&self) -> Option<&Arc<Locked<PropertyDeclarationBlock>>> { fn style_attribute(&self) -> Option<&Arc<Locked<PropertyDeclarationBlock>>> {
if !self.may_have_style_attribute() {
return None;
}
let declarations = unsafe { Gecko_GetStyleAttrDeclarationBlock(self.0) }; let declarations = unsafe { Gecko_GetStyleAttrDeclarationBlock(self.0) };
declarations.map(|s| s.as_arc_opt()).unwrap_or(None) declarations.map_or(None, |s| s.as_arc_opt())
} }
fn get_smil_override(&self) -> Option<&Arc<Locked<PropertyDeclarationBlock>>> { fn get_smil_override(&self) -> Option<&Arc<Locked<PropertyDeclarationBlock>>> {
@ -1245,6 +1277,10 @@ impl<'le> ::selectors::Element for GeckoElement<'le> {
} }
fn get_id(&self) -> Option<Atom> { fn get_id(&self) -> Option<Atom> {
if !self.has_id() {
return None;
}
let ptr = unsafe { let ptr = unsafe {
bindings::Gecko_AtomAttrValue(self.0, bindings::Gecko_AtomAttrValue(self.0,
atom!("id").as_ptr()) atom!("id").as_ptr())
@ -1258,6 +1294,10 @@ impl<'le> ::selectors::Element for GeckoElement<'le> {
} }
fn has_class(&self, name: &Atom) -> bool { fn has_class(&self, name: &Atom) -> bool {
if !self.may_have_class() {
return false;
}
snapshot_helpers::has_class(self.0, snapshot_helpers::has_class(self.0,
name, name,
Gecko_ClassOrClassList) Gecko_ClassOrClassList)
@ -1266,6 +1306,10 @@ impl<'le> ::selectors::Element for GeckoElement<'le> {
fn each_class<F>(&self, callback: F) fn each_class<F>(&self, callback: F)
where F: FnMut(&Atom) where F: FnMut(&Atom)
{ {
if !self.may_have_class() {
return;
}
snapshot_helpers::each_class(self.0, snapshot_helpers::each_class(self.0,
callback, callback,
Gecko_ClassOrClassList) Gecko_ClassOrClassList)