Bug 265894 - Part 6. (Stylo) Fix counterpart of Part 2 and Part 4 in stylo
MozReview-Commit-ID: Jg2r5Zwcijo
--- a/layout/style/ServoBindings.cpp
+++ b/layout/style/ServoBindings.cpp
@@ -180,17 +180,17 @@ Gecko_GetLastChild(RawGeckoNodeBorrowed
return aNode->GetLastChild();
}
RawGeckoNodeBorrowedOrNull
Gecko_GetPrevSibling(RawGeckoNodeBorrowed aNode)
{
return aNode->GetPreviousSibling();
}
-
+
RawGeckoNodeBorrowedOrNull
Gecko_GetNextSibling(RawGeckoNodeBorrowed aNode)
{
return aNode->GetNextSibling();
}
RawGeckoElementBorrowedOrNull
Gecko_GetParentElement(RawGeckoElementBorrowed aElement)
@@ -774,16 +774,41 @@ Gecko_GetXMLLangValue(RawGeckoElementBor
{
nsString string;
if (aElement->GetAttr(kNameSpaceID_XML, nsGkAtoms::lang, string)) {
return NS_Atomize(string).take();
}
return nullptr;
}
+nsIAtom* Gecko_GetTagName(RawGeckoElementBorrowed aElement)
+{
+ return aElement->GetTagNameAtom();
+}
+
+RawGeckoElementBorrowedOrNull
+Gecko_GetParentInsideUseElementShadowTree(RawGeckoNodeBorrowed aNode)
+{
+ if (!aNode->IsElement()) {
+ return nullptr;
+ }
+
+ nsIContent* parent = aNode->AsElement()->GetParentInsideUseElementShadowTree();
+ return parent ? parent->AsElement() : nullptr;
+}
+
+bool Gecko_IsAnonymousContentInSVGUseSubtree(RawGeckoNodeBorrowed aNode)
+{
+ if (!aNode->IsInAnonymousSubtree()) {
+ return false;
+ }
+
+ return aNode->IsAnonymousContentInSVGUseSubtree();
+}
+
template <typename Implementor>
static nsIAtom*
AtomAttrValue(Implementor* aElement, nsIAtom* aName)
{
const nsAttrValue* attr = aElement->GetParsedAttr(aName);
return attr ? attr->GetAtomValue() : nullptr;
}
--- a/layout/style/ServoBindings.h
+++ b/layout/style/ServoBindings.h
@@ -158,17 +158,19 @@ uint64_t Gecko_ElementState(RawGeckoElem
bool Gecko_IsTextNode(RawGeckoNodeBorrowed node);
bool Gecko_IsRootElement(RawGeckoElementBorrowed element);
bool Gecko_MatchesElement(mozilla::CSSPseudoClassType type, RawGeckoElementBorrowed element);
nsIAtom* Gecko_LocalName(RawGeckoElementBorrowed element);
nsIAtom* Gecko_Namespace(RawGeckoElementBorrowed element);
nsIAtom* Gecko_GetElementId(RawGeckoElementBorrowed element);
nsIAtom* Gecko_GetXMLLangValue(RawGeckoElementBorrowed element);
-
+nsIAtom* Gecko_GetTagName(RawGeckoElementBorrowed element);
+bool Gecko_IsAnonymousContentInSVGUseSubtree(RawGeckoNodeBorrowed node);
+RawGeckoElementBorrowedOrNull Gecko_GetParentInsideUseElementShadowTree(RawGeckoNodeBorrowed node);
// Attributes.
#define SERVO_DECLARE_ELEMENT_ATTR_MATCHING_FUNCTIONS(prefix_, implementor_) \
nsIAtom* prefix_##AtomAttrValue(implementor_ element, nsIAtom* attribute); \
bool prefix_##HasAttr(implementor_ element, nsIAtom* ns, nsIAtom* name); \
bool prefix_##AttrEquals(implementor_ element, nsIAtom* ns, nsIAtom* name, \
nsIAtom* str, bool ignoreCase); \
bool prefix_##AttrDashEquals(implementor_ element, nsIAtom* ns, \
nsIAtom* name, nsIAtom* str); \
--- a/servo/components/selectors/matching.rs
+++ b/servo/components/selectors/matching.rs
@@ -435,18 +435,23 @@ fn matches_complex_selector_internal<E,
Combinator::NextSibling | Combinator::LaterSibling => {
// Only ancestor combinators are allowed while looking for
// relevant links, so switch to not looking.
relevant_link = RelevantLinkStatus::NotLooking;
(element.prev_sibling_element(),
SelectorMatchingResult::NotMatchedAndRestartFromClosestDescendant)
}
Combinator::Child | Combinator::Descendant => {
- (element.parent_element(),
- SelectorMatchingResult::NotMatchedGlobally)
+ if element.is_in_use_element_shadow_tree() {
+ (element.parent_element_in_use_element_tree(),
+ SelectorMatchingResult::NotMatchedGlobally)
+ } else {
+ (element.parent_element(),
+ SelectorMatchingResult::NotMatchedGlobally)
+ }
}
Combinator::PseudoElement => {
(element.pseudo_element_originating_element(),
SelectorMatchingResult::NotMatchedGlobally)
}
};
loop {
@@ -484,17 +489,21 @@ fn matches_complex_selector_internal<E,
// or the Combinator::LaterSibling combinator and the status is
// NotMatchedAndRestartFromClosestDescendant
// can continue to matching on the next candidate element.
_ => {},
}
next_element = if siblings {
element.prev_sibling_element()
} else {
- element.parent_element()
+ if element.is_in_use_element_shadow_tree() {
+ element.parent_element_in_use_element_tree()
+ } else {
+ element.parent_element()
+ }
};
}
}
}
}
/// Determines whether the given element matches the given single selector.
#[inline]
--- a/servo/components/selectors/tree.rs
+++ b/servo/components/selectors/tree.rs
@@ -9,16 +9,23 @@ use attr::{AttrSelectorOperation, Namesp
use matching::{ElementSelectorFlags, MatchingContext, RelevantLinkStatus};
use parser::SelectorImpl;
pub trait Element: Sized {
type Impl: SelectorImpl;
fn parent_element(&self) -> Option<Self>;
+ /// Whether this element in inside of an use-element shadow tree.
+ fn is_in_use_element_shadow_tree(&self) -> bool;
+
+ /// Get parent of this element inside an use-element shadow tree.
+ /// Can/should be used only if is_in_use_element_shadow_tree return true.
+ fn parent_element_in_use_element_tree(&self) -> Option<Self>;
+
/// The parent of a given pseudo-element, after matching a pseudo-element
/// selector.
///
/// This is guaranteed to be called in a pseudo-element.
fn pseudo_element_originating_element(&self) -> Option<Self> {
self.parent_element()
}
--- a/servo/components/style/gecko/wrapper.rs
+++ b/servo/components/style/gecko/wrapper.rs
@@ -24,17 +24,17 @@ use element_state::ElementState;
use error_reporting::RustLogReporter;
use font_metrics::{FontMetrics, FontMetricsProvider, FontMetricsQueryResult};
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_ElementState, Gecko_GetLastChild, Gecko_GetNextStyleChild};
-use gecko_bindings::bindings::{Gecko_IsRootElement, Gecko_MatchesElement, Gecko_Namespace};
+use gecko_bindings::bindings::{Gecko_IsRootElement, Gecko_MatchesElement, Gecko_Namespace, Gecko_GetTagName, Gecko_IsAnonymousContentInSVGUseSubtree, Gecko_GetParentInsideUseElementShadowTree};
use gecko_bindings::bindings::{Gecko_SetNodeFlags, Gecko_UnsetNodeFlags};
use gecko_bindings::bindings::Gecko_ClassOrClassList;
use gecko_bindings::bindings::Gecko_ElementHasAnimations;
use gecko_bindings::bindings::Gecko_ElementHasCSSAnimations;
use gecko_bindings::bindings::Gecko_ElementHasCSSTransitions;
use gecko_bindings::bindings::Gecko_GetAnimationRule;
use gecko_bindings::bindings::Gecko_GetExtraContentStyleDeclarations;
use gecko_bindings::bindings::Gecko_GetHTMLPresentationAttrDeclarationBlock;
@@ -1127,16 +1127,33 @@ impl<'le> PresentationalHintsSynthesizer
impl<'le> ::selectors::Element for GeckoElement<'le> {
type Impl = SelectorImpl;
fn parent_element(&self) -> Option<Self> {
let parent_node = self.as_node().parent_node();
parent_node.and_then(|n| n.as_element())
}
+ fn is_in_use_element_shadow_tree(&self) -> bool {
+ unsafe {
+ Gecko_IsAnonymousContentInSVGUseSubtree(self.as_node().0)
+ }
+ }
+
+ fn parent_element_in_use_element_tree(&self) -> Option<Self> {
+ debug_assert!(self.is_in_use_element_shadow_tree());
+
+ unsafe {
+ match Gecko_GetParentInsideUseElementShadowTree(self.as_node().0) {
+ Some(parent) => Some(GeckoElement(parent)),
+ None => None
+ }
+ }
+ }
+
fn pseudo_element_originating_element(&self) -> Option<Self> {
debug_assert!(self.implemented_pseudo_element().is_some());
self.closest_non_native_anonymous_ancestor()
}
fn first_child_element(&self) -> Option<Self> {
let mut child = self.as_node().first_child();
while let Some(child_node) = child {
@@ -1252,17 +1269,17 @@ impl<'le> ::selectors::Element for Gecko
fn is_empty(&self) -> bool {
!self.as_node().dom_children().any(|child| unsafe {
Gecko_IsSignificantChild(child.0, true, true)
})
}
fn get_local_name(&self) -> &WeakAtom {
unsafe {
- WeakAtom::new(self.as_node().node_info().mInner.mName.raw::<nsIAtom>())
+ WeakAtom::new(Gecko_GetTagName(self.0))
}
}
fn get_namespace(&self) -> &WeakNamespace {
unsafe {
WeakNamespace::new(Gecko_Namespace(self.0))
}
}
--- a/servo/components/style/restyle_hints.rs
+++ b/servo/components/style/restyle_hints.rs
@@ -709,17 +709,22 @@ impl<'a, E> Element for ElementWrapper<'
&RelevantLinkStatus::default(),
&mut |_, _| {})
}
fn parent_element(&self) -> Option<Self> {
self.element.parent_element()
.map(|e| ElementWrapper::new(e, self.snapshot_map))
}
-
+ fn is_in_use_element_shadow_tree(&self) -> bool {
+ false
+ }
+ fn parent_element_in_use_element_tree(&self) -> Option<Self> {
+ self.parent_element()
+ }
fn first_child_element(&self) -> Option<Self> {
self.element.first_child_element()
.map(|e| ElementWrapper::new(e, self.snapshot_map))
}
fn last_child_element(&self) -> Option<Self> {
self.element.last_child_element()
.map(|e| ElementWrapper::new(e, self.snapshot_map))