mirror of
https://github.com/servo/servo.git
synced 2025-08-05 13:40:08 +01:00
Auto merge of #17541 - heycam:is-needed, r=emilio
style: Make GeckoElement::traversal_children faster. From https://bugzilla.mozilla.org/show_bug.cgi?id=1372061. <!-- Reviewable:start --> --- This change is [<img src="https://reviewable.io/review_button.svg" height="34" align="absmiddle" alt="Reviewable"/>](https://reviewable.io/reviews/servo/servo/17541) <!-- Reviewable:end -->
This commit is contained in:
commit
a40e5353b3
7 changed files with 4663 additions and 4139 deletions
|
@ -187,12 +187,6 @@ impl<'ln> TNode for ServoLayoutNode<'ln> {
|
|||
self.children()
|
||||
}
|
||||
|
||||
fn children_and_traversal_children_might_differ(&self) -> bool {
|
||||
// Servo doesn't have to worry about nodes being rearranged in the
|
||||
// flattened tree like Gecko does (for XBL and Shadow DOM). Yet.
|
||||
false
|
||||
}
|
||||
|
||||
fn opaque(&self) -> OpaqueNode {
|
||||
unsafe { self.get_jsmanaged().opaque() }
|
||||
}
|
||||
|
|
|
@ -127,10 +127,6 @@ pub trait TNode : Sized + Copy + Clone + Debug + NodeInfo {
|
|||
/// Get this node's children from the perspective of a restyle traversal.
|
||||
fn traversal_children(&self) -> LayoutIterator<Self::ConcreteChildrenIterator>;
|
||||
|
||||
/// Returns whether `children()` and `traversal_children()` might return
|
||||
/// iterators over different nodes.
|
||||
fn children_and_traversal_children_might_differ(&self) -> bool;
|
||||
|
||||
/// Converts self into an `OpaqueNode`.
|
||||
fn opaque(&self) -> OpaqueNode;
|
||||
|
||||
|
|
|
@ -986,6 +986,8 @@ cfg_if! {
|
|||
pub static nsGkAtoms_handlers: *mut nsIAtom;
|
||||
#[link_name = "_ZN9nsGkAtoms4HARDE"]
|
||||
pub static nsGkAtoms_HARD: *mut nsIAtom;
|
||||
#[link_name = "_ZN9nsGkAtoms8haspopupE"]
|
||||
pub static nsGkAtoms_haspopup: *mut nsIAtom;
|
||||
#[link_name = "_ZN9nsGkAtoms11hasSameNodeE"]
|
||||
pub static nsGkAtoms_hasSameNode: *mut nsIAtom;
|
||||
#[link_name = "_ZN9nsGkAtoms4hboxE"]
|
||||
|
@ -1562,6 +1564,8 @@ cfg_if! {
|
|||
pub static nsGkAtoms_onchargingtimechange: *mut nsIAtom;
|
||||
#[link_name = "_ZN9nsGkAtoms10oncheckingE"]
|
||||
pub static nsGkAtoms_onchecking: *mut nsIAtom;
|
||||
#[link_name = "_ZN9nsGkAtoms21onCheckboxStateChangeE"]
|
||||
pub static nsGkAtoms_onCheckboxStateChange: *mut nsIAtom;
|
||||
#[link_name = "_ZN9nsGkAtoms7onclickE"]
|
||||
pub static nsGkAtoms_onclick: *mut nsIAtom;
|
||||
#[link_name = "_ZN9nsGkAtoms16onclirmodechangeE"]
|
||||
|
@ -1898,6 +1902,8 @@ cfg_if! {
|
|||
pub static nsGkAtoms_onptychange: *mut nsIAtom;
|
||||
#[link_name = "_ZN9nsGkAtoms18onradiostatechangeE"]
|
||||
pub static nsGkAtoms_onradiostatechange: *mut nsIAtom;
|
||||
#[link_name = "_ZN9nsGkAtoms18onRadioStateChangeE"]
|
||||
pub static nsGkAtoms_onRadioStateChange: *mut nsIAtom;
|
||||
#[link_name = "_ZN9nsGkAtoms13onrdsdisabledE"]
|
||||
pub static nsGkAtoms_onrdsdisabled: *mut nsIAtom;
|
||||
#[link_name = "_ZN9nsGkAtoms12onrdsenabledE"]
|
||||
|
@ -4208,6 +4214,8 @@ cfg_if! {
|
|||
pub static nsGkAtoms_paintRequestTime: *mut nsIAtom;
|
||||
#[link_name = "_ZN9nsGkAtoms14pseudoPropertyE"]
|
||||
pub static nsGkAtoms_pseudoProperty: *mut nsIAtom;
|
||||
#[link_name = "_ZN9nsGkAtoms17manualNACPropertyE"]
|
||||
pub static nsGkAtoms_manualNACProperty: *mut nsIAtom;
|
||||
#[link_name = "_ZN9nsGkAtoms8JapaneseE"]
|
||||
pub static nsGkAtoms_Japanese: *mut nsIAtom;
|
||||
#[link_name = "_ZN9nsGkAtoms7ChineseE"]
|
||||
|
@ -6099,6 +6107,8 @@ cfg_if! {
|
|||
pub static nsGkAtoms_handlers: *mut nsIAtom;
|
||||
#[link_name = "?HARD@nsGkAtoms@@2PEAVnsIAtom@@EA"]
|
||||
pub static nsGkAtoms_HARD: *mut nsIAtom;
|
||||
#[link_name = "?haspopup@nsGkAtoms@@2PEAVnsIAtom@@EA"]
|
||||
pub static nsGkAtoms_haspopup: *mut nsIAtom;
|
||||
#[link_name = "?hasSameNode@nsGkAtoms@@2PEAVnsIAtom@@EA"]
|
||||
pub static nsGkAtoms_hasSameNode: *mut nsIAtom;
|
||||
#[link_name = "?hbox@nsGkAtoms@@2PEAVnsIAtom@@EA"]
|
||||
|
@ -6675,6 +6685,8 @@ cfg_if! {
|
|||
pub static nsGkAtoms_onchargingtimechange: *mut nsIAtom;
|
||||
#[link_name = "?onchecking@nsGkAtoms@@2PEAVnsIAtom@@EA"]
|
||||
pub static nsGkAtoms_onchecking: *mut nsIAtom;
|
||||
#[link_name = "?onCheckboxStateChange@nsGkAtoms@@2PEAVnsIAtom@@EA"]
|
||||
pub static nsGkAtoms_onCheckboxStateChange: *mut nsIAtom;
|
||||
#[link_name = "?onclick@nsGkAtoms@@2PEAVnsIAtom@@EA"]
|
||||
pub static nsGkAtoms_onclick: *mut nsIAtom;
|
||||
#[link_name = "?onclirmodechange@nsGkAtoms@@2PEAVnsIAtom@@EA"]
|
||||
|
@ -7011,6 +7023,8 @@ cfg_if! {
|
|||
pub static nsGkAtoms_onptychange: *mut nsIAtom;
|
||||
#[link_name = "?onradiostatechange@nsGkAtoms@@2PEAVnsIAtom@@EA"]
|
||||
pub static nsGkAtoms_onradiostatechange: *mut nsIAtom;
|
||||
#[link_name = "?onRadioStateChange@nsGkAtoms@@2PEAVnsIAtom@@EA"]
|
||||
pub static nsGkAtoms_onRadioStateChange: *mut nsIAtom;
|
||||
#[link_name = "?onrdsdisabled@nsGkAtoms@@2PEAVnsIAtom@@EA"]
|
||||
pub static nsGkAtoms_onrdsdisabled: *mut nsIAtom;
|
||||
#[link_name = "?onrdsenabled@nsGkAtoms@@2PEAVnsIAtom@@EA"]
|
||||
|
@ -9321,6 +9335,8 @@ cfg_if! {
|
|||
pub static nsGkAtoms_paintRequestTime: *mut nsIAtom;
|
||||
#[link_name = "?pseudoProperty@nsGkAtoms@@2PEAVnsIAtom@@EA"]
|
||||
pub static nsGkAtoms_pseudoProperty: *mut nsIAtom;
|
||||
#[link_name = "?manualNACProperty@nsGkAtoms@@2PEAVnsIAtom@@EA"]
|
||||
pub static nsGkAtoms_manualNACProperty: *mut nsIAtom;
|
||||
#[link_name = "?Japanese@nsGkAtoms@@2PEAVnsIAtom@@EA"]
|
||||
pub static nsGkAtoms_Japanese: *mut nsIAtom;
|
||||
#[link_name = "?Chinese@nsGkAtoms@@2PEAVnsIAtom@@EA"]
|
||||
|
@ -11212,6 +11228,8 @@ cfg_if! {
|
|||
pub static nsGkAtoms_handlers: *mut nsIAtom;
|
||||
#[link_name = "\x01?HARD@nsGkAtoms@@2PAVnsIAtom@@A"]
|
||||
pub static nsGkAtoms_HARD: *mut nsIAtom;
|
||||
#[link_name = "\x01?haspopup@nsGkAtoms@@2PAVnsIAtom@@A"]
|
||||
pub static nsGkAtoms_haspopup: *mut nsIAtom;
|
||||
#[link_name = "\x01?hasSameNode@nsGkAtoms@@2PAVnsIAtom@@A"]
|
||||
pub static nsGkAtoms_hasSameNode: *mut nsIAtom;
|
||||
#[link_name = "\x01?hbox@nsGkAtoms@@2PAVnsIAtom@@A"]
|
||||
|
@ -11788,6 +11806,8 @@ cfg_if! {
|
|||
pub static nsGkAtoms_onchargingtimechange: *mut nsIAtom;
|
||||
#[link_name = "\x01?onchecking@nsGkAtoms@@2PAVnsIAtom@@A"]
|
||||
pub static nsGkAtoms_onchecking: *mut nsIAtom;
|
||||
#[link_name = "\x01?onCheckboxStateChange@nsGkAtoms@@2PAVnsIAtom@@A"]
|
||||
pub static nsGkAtoms_onCheckboxStateChange: *mut nsIAtom;
|
||||
#[link_name = "\x01?onclick@nsGkAtoms@@2PAVnsIAtom@@A"]
|
||||
pub static nsGkAtoms_onclick: *mut nsIAtom;
|
||||
#[link_name = "\x01?onclirmodechange@nsGkAtoms@@2PAVnsIAtom@@A"]
|
||||
|
@ -12124,6 +12144,8 @@ cfg_if! {
|
|||
pub static nsGkAtoms_onptychange: *mut nsIAtom;
|
||||
#[link_name = "\x01?onradiostatechange@nsGkAtoms@@2PAVnsIAtom@@A"]
|
||||
pub static nsGkAtoms_onradiostatechange: *mut nsIAtom;
|
||||
#[link_name = "\x01?onRadioStateChange@nsGkAtoms@@2PAVnsIAtom@@A"]
|
||||
pub static nsGkAtoms_onRadioStateChange: *mut nsIAtom;
|
||||
#[link_name = "\x01?onrdsdisabled@nsGkAtoms@@2PAVnsIAtom@@A"]
|
||||
pub static nsGkAtoms_onrdsdisabled: *mut nsIAtom;
|
||||
#[link_name = "\x01?onrdsenabled@nsGkAtoms@@2PAVnsIAtom@@A"]
|
||||
|
@ -14434,6 +14456,8 @@ cfg_if! {
|
|||
pub static nsGkAtoms_paintRequestTime: *mut nsIAtom;
|
||||
#[link_name = "\x01?pseudoProperty@nsGkAtoms@@2PAVnsIAtom@@A"]
|
||||
pub static nsGkAtoms_pseudoProperty: *mut nsIAtom;
|
||||
#[link_name = "\x01?manualNACProperty@nsGkAtoms@@2PAVnsIAtom@@A"]
|
||||
pub static nsGkAtoms_manualNACProperty: *mut nsIAtom;
|
||||
#[link_name = "\x01?Japanese@nsGkAtoms@@2PAVnsIAtom@@A"]
|
||||
pub static nsGkAtoms_Japanese: *mut nsIAtom;
|
||||
#[link_name = "\x01?Chinese@nsGkAtoms@@2PAVnsIAtom@@A"]
|
||||
|
@ -16328,6 +16352,8 @@ macro_rules! atom {
|
|||
{ unsafe { $crate::string_cache::atom_macro::atom_from_static($crate::string_cache::atom_macro::nsGkAtoms_handlers as *mut _) } };
|
||||
("HARD") =>
|
||||
{ unsafe { $crate::string_cache::atom_macro::atom_from_static($crate::string_cache::atom_macro::nsGkAtoms_HARD as *mut _) } };
|
||||
("haspopup") =>
|
||||
{ unsafe { $crate::string_cache::atom_macro::atom_from_static($crate::string_cache::atom_macro::nsGkAtoms_haspopup as *mut _) } };
|
||||
("has-same-node") =>
|
||||
{ unsafe { $crate::string_cache::atom_macro::atom_from_static($crate::string_cache::atom_macro::nsGkAtoms_hasSameNode as *mut _) } };
|
||||
("hbox") =>
|
||||
|
@ -16904,6 +16930,8 @@ macro_rules! atom {
|
|||
{ unsafe { $crate::string_cache::atom_macro::atom_from_static($crate::string_cache::atom_macro::nsGkAtoms_onchargingtimechange as *mut _) } };
|
||||
("onchecking") =>
|
||||
{ unsafe { $crate::string_cache::atom_macro::atom_from_static($crate::string_cache::atom_macro::nsGkAtoms_onchecking as *mut _) } };
|
||||
("onCheckboxStateChange") =>
|
||||
{ unsafe { $crate::string_cache::atom_macro::atom_from_static($crate::string_cache::atom_macro::nsGkAtoms_onCheckboxStateChange as *mut _) } };
|
||||
("onclick") =>
|
||||
{ unsafe { $crate::string_cache::atom_macro::atom_from_static($crate::string_cache::atom_macro::nsGkAtoms_onclick as *mut _) } };
|
||||
("onclirmodechange") =>
|
||||
|
@ -17240,6 +17268,8 @@ macro_rules! atom {
|
|||
{ unsafe { $crate::string_cache::atom_macro::atom_from_static($crate::string_cache::atom_macro::nsGkAtoms_onptychange as *mut _) } };
|
||||
("onradiostatechange") =>
|
||||
{ unsafe { $crate::string_cache::atom_macro::atom_from_static($crate::string_cache::atom_macro::nsGkAtoms_onradiostatechange as *mut _) } };
|
||||
("onRadioStateChange") =>
|
||||
{ unsafe { $crate::string_cache::atom_macro::atom_from_static($crate::string_cache::atom_macro::nsGkAtoms_onRadioStateChange as *mut _) } };
|
||||
("onrdsdisabled") =>
|
||||
{ unsafe { $crate::string_cache::atom_macro::atom_from_static($crate::string_cache::atom_macro::nsGkAtoms_onrdsdisabled as *mut _) } };
|
||||
("onrdsenabled") =>
|
||||
|
@ -19550,6 +19580,8 @@ macro_rules! atom {
|
|||
{ unsafe { $crate::string_cache::atom_macro::atom_from_static($crate::string_cache::atom_macro::nsGkAtoms_paintRequestTime as *mut _) } };
|
||||
("PseudoProperty") =>
|
||||
{ unsafe { $crate::string_cache::atom_macro::atom_from_static($crate::string_cache::atom_macro::nsGkAtoms_pseudoProperty as *mut _) } };
|
||||
("ManualNACProperty") =>
|
||||
{ unsafe { $crate::string_cache::atom_macro::atom_from_static($crate::string_cache::atom_macro::nsGkAtoms_manualNACProperty as *mut _) } };
|
||||
("ja") =>
|
||||
{ unsafe { $crate::string_cache::atom_macro::atom_from_static($crate::string_cache::atom_macro::nsGkAtoms_Japanese as *mut _) } };
|
||||
("zh-CN") =>
|
||||
|
|
|
@ -29,6 +29,7 @@ use gecko_bindings::structs::RawServoStyleRule;
|
|||
use gecko_bindings::structs::RawGeckoPresContext;
|
||||
use gecko_bindings::structs::RawGeckoPresContextOwned;
|
||||
use gecko_bindings::structs::RawGeckoStyleAnimationList;
|
||||
use gecko_bindings::structs::RawGeckoStyleChildrenIteratorBorrowedMut;
|
||||
use gecko_bindings::structs::RawGeckoServoStyleRuleList;
|
||||
use gecko_bindings::structs::RawGeckoURLExtraData;
|
||||
use gecko_bindings::structs::RawGeckoXBLBinding;
|
||||
|
@ -227,14 +228,6 @@ pub type RawServoStyleSetBorrowedMut<'a> = &'a mut RawServoStyleSet;
|
|||
pub type RawServoStyleSetBorrowedMutOrNull<'a> = Option<&'a mut RawServoStyleSet>;
|
||||
enum RawServoStyleSetVoid { }
|
||||
pub struct RawServoStyleSet(RawServoStyleSetVoid);
|
||||
pub type StyleChildrenIteratorOwned = ::gecko_bindings::sugar::ownership::Owned<StyleChildrenIterator>;
|
||||
pub type StyleChildrenIteratorOwnedOrNull = ::gecko_bindings::sugar::ownership::OwnedOrNull<StyleChildrenIterator>;
|
||||
pub type StyleChildrenIteratorBorrowed<'a> = &'a StyleChildrenIterator;
|
||||
pub type StyleChildrenIteratorBorrowedOrNull<'a> = Option<&'a StyleChildrenIterator>;
|
||||
pub type StyleChildrenIteratorBorrowedMut<'a> = &'a mut StyleChildrenIterator;
|
||||
pub type StyleChildrenIteratorBorrowedMutOrNull<'a> = Option<&'a mut StyleChildrenIterator>;
|
||||
enum StyleChildrenIteratorVoid { }
|
||||
pub struct StyleChildrenIterator(StyleChildrenIteratorVoid);
|
||||
pub type ServoElementSnapshotOwned = ::gecko_bindings::sugar::ownership::Owned<ServoElementSnapshot>;
|
||||
pub type ServoElementSnapshotOwnedOrNull = ::gecko_bindings::sugar::ownership::OwnedOrNull<ServoElementSnapshot>;
|
||||
pub type ServoElementSnapshotBorrowed<'a> = &'a ServoElementSnapshot;
|
||||
|
@ -532,14 +525,18 @@ extern "C" {
|
|||
*mut nsTArray<*mut nsIContent>);
|
||||
}
|
||||
extern "C" {
|
||||
pub fn Gecko_MaybeCreateStyleChildrenIterator(node: RawGeckoNodeBorrowed)
|
||||
-> StyleChildrenIteratorOwnedOrNull;
|
||||
pub fn Gecko_ConstructStyleChildrenIterator(aElement:
|
||||
RawGeckoElementBorrowed,
|
||||
aIterator:
|
||||
RawGeckoStyleChildrenIteratorBorrowedMut);
|
||||
}
|
||||
extern "C" {
|
||||
pub fn Gecko_DropStyleChildrenIterator(it: StyleChildrenIteratorOwned);
|
||||
pub fn Gecko_DestroyStyleChildrenIterator(aIterator:
|
||||
RawGeckoStyleChildrenIteratorBorrowedMut);
|
||||
}
|
||||
extern "C" {
|
||||
pub fn Gecko_GetNextStyleChild(it: StyleChildrenIteratorBorrowedMut)
|
||||
pub fn Gecko_GetNextStyleChild(it:
|
||||
RawGeckoStyleChildrenIteratorBorrowedMut)
|
||||
-> RawGeckoNodeBorrowedOrNull;
|
||||
}
|
||||
extern "C" {
|
||||
|
|
File diff suppressed because it is too large
Load diff
File diff suppressed because it is too large
Load diff
|
@ -30,7 +30,7 @@ use gecko::global_style_data::GLOBAL_STYLE_DATA;
|
|||
use gecko::selector_parser::{SelectorImpl, NonTSPseudoClass, PseudoElement};
|
||||
use gecko::snapshot_helpers;
|
||||
use gecko_bindings::bindings;
|
||||
use gecko_bindings::bindings::{Gecko_DropStyleChildrenIterator, Gecko_MaybeCreateStyleChildrenIterator};
|
||||
use gecko_bindings::bindings::{Gecko_ConstructStyleChildrenIterator, Gecko_DestroyStyleChildrenIterator};
|
||||
use gecko_bindings::bindings::{Gecko_ElementState, Gecko_GetDocumentLWTheme};
|
||||
use gecko_bindings::bindings::{Gecko_GetLastChild, Gecko_GetNextStyleChild};
|
||||
use gecko_bindings::bindings::{Gecko_IsRootElement, Gecko_MatchesElement, Gecko_Namespace};
|
||||
|
@ -227,6 +227,21 @@ impl<'ln> GeckoNode<'ln> {
|
|||
fn contains_non_whitespace_content(&self) -> bool {
|
||||
unsafe { Gecko_IsSignificantChild(self.0, true, false) }
|
||||
}
|
||||
|
||||
#[inline]
|
||||
fn may_have_anonymous_children(&self) -> bool {
|
||||
self.get_bool_flag(nsINode_BooleanFlag::ElementMayHaveAnonymousChildren)
|
||||
}
|
||||
|
||||
/// This logic is duplicated in Gecko's nsIContent::IsInAnonymousSubtree.
|
||||
#[inline]
|
||||
fn is_in_anonymous_subtree(&self) -> bool {
|
||||
use gecko_bindings::structs::NODE_IS_IN_NATIVE_ANONYMOUS_SUBTREE;
|
||||
use gecko_bindings::structs::NODE_IS_IN_SHADOW_TREE;
|
||||
self.flags() & (NODE_IS_IN_NATIVE_ANONYMOUS_SUBTREE as u32) != 0 ||
|
||||
((self.flags() & (NODE_IS_IN_SHADOW_TREE as u32) == 0) &&
|
||||
self.as_element().map_or(false, |e| e.has_xbl_binding_parent()))
|
||||
}
|
||||
}
|
||||
|
||||
impl<'ln> NodeInfo for GeckoNode<'ln> {
|
||||
|
@ -267,19 +282,23 @@ impl<'ln> TNode for GeckoNode<'ln> {
|
|||
}
|
||||
|
||||
fn traversal_children(&self) -> LayoutIterator<GeckoChildrenIterator<'ln>> {
|
||||
let maybe_iter = unsafe { Gecko_MaybeCreateStyleChildrenIterator(self.0) };
|
||||
if let Some(iter) = maybe_iter.into_owned_opt() {
|
||||
LayoutIterator(GeckoChildrenIterator::GeckoIterator(iter))
|
||||
} else {
|
||||
LayoutIterator(self.dom_children())
|
||||
if let Some(element) = self.as_element() {
|
||||
// This condition is similar to the check that
|
||||
// StyleChildrenIterator::IsNeeded does, except that it might return
|
||||
// true if we used to (but no longer) have anonymous content from
|
||||
// ::before/::after, XBL bindings, or nsIAnonymousContentCreators.
|
||||
if self.is_in_anonymous_subtree() ||
|
||||
element.has_xbl_binding_with_content() ||
|
||||
self.may_have_anonymous_children() {
|
||||
unsafe {
|
||||
let mut iter: structs::StyleChildrenIterator = ::std::mem::zeroed();
|
||||
Gecko_ConstructStyleChildrenIterator(element.0, &mut iter);
|
||||
return LayoutIterator(GeckoChildrenIterator::GeckoIterator(iter));
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
fn children_and_traversal_children_might_differ(&self) -> bool {
|
||||
match self.as_element() {
|
||||
Some(e) => e.xbl_binding_anonymous_content().is_some(),
|
||||
None => false,
|
||||
}
|
||||
LayoutIterator(self.dom_children())
|
||||
}
|
||||
|
||||
fn opaque(&self) -> OpaqueNode {
|
||||
|
@ -343,14 +362,14 @@ pub enum GeckoChildrenIterator<'a> {
|
|||
/// replaces it with the next sibling when requested.
|
||||
Current(Option<GeckoNode<'a>>),
|
||||
/// A Gecko-implemented iterator we need to drop appropriately.
|
||||
GeckoIterator(bindings::StyleChildrenIteratorOwned),
|
||||
GeckoIterator(structs::StyleChildrenIterator),
|
||||
}
|
||||
|
||||
impl<'a> Drop for GeckoChildrenIterator<'a> {
|
||||
fn drop(&mut self) {
|
||||
if let GeckoChildrenIterator::GeckoIterator(ref it) = *self {
|
||||
if let GeckoChildrenIterator::GeckoIterator(ref mut it) = *self {
|
||||
unsafe {
|
||||
Gecko_DropStyleChildrenIterator(ptr::read(it as *const _));
|
||||
Gecko_DestroyStyleChildrenIterator(it);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -373,10 +392,11 @@ impl<'a> Iterator for GeckoChildrenIterator<'a> {
|
|||
}
|
||||
|
||||
/// A Simple wrapper over a non-null Gecko `nsXBLBinding` pointer.
|
||||
#[derive(Clone, Copy)]
|
||||
pub struct GeckoXBLBinding<'lb>(pub &'lb RawGeckoXBLBinding);
|
||||
|
||||
impl<'lb> GeckoXBLBinding<'lb> {
|
||||
fn base_binding(&self) -> Option<GeckoXBLBinding> {
|
||||
fn base_binding(&self) -> Option<Self> {
|
||||
unsafe { self.0.mNextBinding.mRawPtr.as_ref().map(GeckoXBLBinding) }
|
||||
}
|
||||
|
||||
|
@ -388,6 +408,21 @@ impl<'lb> GeckoXBLBinding<'lb> {
|
|||
unsafe { bindings::Gecko_XBLBinding_InheritsStyle(self.0) }
|
||||
}
|
||||
|
||||
// This duplicates the logic in Gecko's
|
||||
// nsBindingManager::GetBindingWithContent.
|
||||
fn get_binding_with_content(&self) -> Option<Self> {
|
||||
let mut binding = *self;
|
||||
loop {
|
||||
if !binding.anon_content().is_null() {
|
||||
return Some(binding);
|
||||
}
|
||||
binding = match binding.base_binding() {
|
||||
Some(b) => b,
|
||||
None => return None,
|
||||
};
|
||||
}
|
||||
}
|
||||
|
||||
// Implements Gecko's nsXBLBinding::WalkRules().
|
||||
fn get_declarations_for<E, V>(&self,
|
||||
element: &E,
|
||||
|
@ -480,12 +515,71 @@ impl<'le> GeckoElement<'le> {
|
|||
unsafe { slots.as_ref() }
|
||||
}
|
||||
|
||||
#[inline]
|
||||
fn get_xbl_binding(&self) -> Option<GeckoXBLBinding> {
|
||||
if self.flags() & (structs::NODE_MAY_BE_IN_BINDING_MNGR as u32) == 0 {
|
||||
return None;
|
||||
}
|
||||
|
||||
unsafe { bindings::Gecko_GetXBLBinding(self.0).map(GeckoXBLBinding) }
|
||||
}
|
||||
|
||||
#[inline]
|
||||
fn get_xbl_binding_with_content(&self) -> Option<GeckoXBLBinding> {
|
||||
self.get_xbl_binding().and_then(|b| b.get_binding_with_content())
|
||||
}
|
||||
|
||||
#[inline]
|
||||
fn has_xbl_binding_with_content(&self) -> bool {
|
||||
!self.get_xbl_binding_with_content().is_none()
|
||||
}
|
||||
|
||||
/// This and has_xbl_binding_parent duplicate the logic in Gecko's virtual
|
||||
/// nsINode::GetBindingParent function, which only has two implementations:
|
||||
/// one for XUL elements, and one for other elements. We just hard code in
|
||||
/// our knowledge of those two implementations here.
|
||||
fn get_xbl_binding_parent(&self) -> Option<Self> {
|
||||
unsafe { bindings::Gecko_GetBindingParent(self.0).map(GeckoElement) }
|
||||
if self.is_xul_element() {
|
||||
// FIXME(heycam): Having trouble with bindgen on nsXULElement,
|
||||
// where the binding parent is stored in a member variable
|
||||
// rather than in slots. So just get it through FFI for now.
|
||||
unsafe { bindings::Gecko_GetBindingParent(self.0).map(GeckoElement) }
|
||||
} else {
|
||||
let binding_parent =
|
||||
unsafe { self.get_non_xul_xbl_binding_parent_raw_content().as_ref() }
|
||||
.map(GeckoNode::from_content)
|
||||
.and_then(|n| n.as_element());
|
||||
debug_assert!(binding_parent ==
|
||||
unsafe { bindings::Gecko_GetBindingParent(self.0).map(GeckoElement) });
|
||||
binding_parent
|
||||
}
|
||||
}
|
||||
|
||||
fn get_non_xul_xbl_binding_parent_raw_content(&self) -> *mut nsIContent {
|
||||
debug_assert!(!self.is_xul_element());
|
||||
match self.get_dom_slots() {
|
||||
Some(slots) => unsafe { *slots.__bindgen_anon_1.mBindingParent.as_ref() },
|
||||
None => ptr::null_mut(),
|
||||
}
|
||||
}
|
||||
|
||||
fn has_xbl_binding_parent(&self) -> bool {
|
||||
if self.is_xul_element() {
|
||||
// FIXME(heycam): Having trouble with bindgen on nsXULElement,
|
||||
// where the binding parent is stored in a member variable
|
||||
// rather than in slots. So just get it through FFI for now.
|
||||
unsafe { bindings::Gecko_GetBindingParent(self.0).is_some() }
|
||||
} else {
|
||||
!self.get_non_xul_xbl_binding_parent_raw_content().is_null()
|
||||
}
|
||||
}
|
||||
|
||||
fn namespace_id(&self) -> i32 {
|
||||
self.as_node().node_info().mInner.mNamespaceID
|
||||
}
|
||||
|
||||
fn is_xul_element(&self) -> bool {
|
||||
self.namespace_id() == (structs::root::kNameSpaceID_XUL as i32)
|
||||
}
|
||||
|
||||
/// Clear the element data for a given element.
|
||||
|
@ -1061,16 +1155,9 @@ impl<'le> TElement for GeckoElement<'le> {
|
|||
}
|
||||
|
||||
fn xbl_binding_anonymous_content(&self) -> Option<GeckoNode<'le>> {
|
||||
if self.flags() & (structs::NODE_MAY_BE_IN_BINDING_MNGR as u32) == 0 {
|
||||
return None;
|
||||
}
|
||||
|
||||
let anon_content = match self.get_xbl_binding() {
|
||||
Some(binding) => binding.anon_content(),
|
||||
None => return None,
|
||||
};
|
||||
|
||||
unsafe { anon_content.as_ref().map(GeckoNode::from_content) }
|
||||
self.get_xbl_binding_with_content()
|
||||
.map(|b| unsafe { b.anon_content().as_ref() }.unwrap())
|
||||
.map(GeckoNode::from_content)
|
||||
}
|
||||
|
||||
fn get_css_transitions_info(&self)
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue