Bug 265894 - Part 15. (Stylo) Fix counterpart of Part 8 and Part 9 in stylo.
MozReview-Commit-ID: 95ObxsatgbM
--- a/servo/components/selectors/matching.rs
+++ b/servo/components/selectors/matching.rs
@@ -527,18 +527,22 @@ 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.blocks_ancestor_combinators() {
+ (None, SelectorMatchingResult::NotMatchedGlobally)
+ } else {
+ (element.parent_element(),
+ SelectorMatchingResult::NotMatchedGlobally)
+ }
}
Combinator::PseudoElement => {
(element.pseudo_element_originating_element(),
SelectorMatchingResult::NotMatchedGlobally)
}
};
loop {
--- a/servo/components/selectors/tree.rs
+++ b/servo/components/selectors/tree.rs
@@ -80,9 +80,16 @@ pub trait Element: Sized + Debug {
fn is_empty(&self) -> bool;
/// Returns whether this element matches `:root`,
/// i.e. whether it is the root element of a document.
///
/// Note: this can be false even if `.parent_element()` is `None`
/// if the parent node is a `DocumentFragment`.
fn is_root(&self) -> bool;
+
+ /// Return true if we want to stop lookup ancestor of the current
+ /// element while matching complex selectors with descendant/child
+ /// combinator.
+ fn blocks_ancestor_combinators(&self) -> bool {
+ false
+ }
}
--- a/servo/components/style/gecko/non_ts_pseudo_class_list.rs
+++ b/servo/components/style/gecko/non_ts_pseudo_class_list.rs
@@ -102,16 +102,17 @@ macro_rules! apply_non_ts_list {
("-moz-meter-sub-sub-optimum", MozMeterSubSubOptimum, mozMeterSubSubOptimum, IN_SUB_SUB_OPTIMUM_STATE, _),
("-moz-user-disabled", MozUserDisabled, mozUserDisabled, IN_USER_DISABLED_STATE, PSEUDO_CLASS_INTERNAL),
("-moz-first-node", MozFirstNode, firstNode, _, _),
("-moz-last-node", MozLastNode, lastNode, _, _),
("-moz-only-whitespace", MozOnlyWhitespace, mozOnlyWhitespace, _, _),
("-moz-native-anonymous", MozNativeAnonymous, mozNativeAnonymous, _, PSEUDO_CLASS_INTERNAL),
+ ("-moz-use-shadow-tree-root", MozUseShadowTreeRoot, mozUseShadowTreeRoot, _, PSEUDO_CLASS_INTERNAL),
("-moz-is-html", MozIsHTML, mozIsHTML, _, _),
("-moz-placeholder", MozPlaceholder, mozPlaceholder, _, _),
],
string: [
("-moz-system-metric", MozSystemMetric, mozSystemMetric, _, PSEUDO_CLASS_INTERNAL),
("-moz-empty-except-children-with-localname", MozEmptyExceptChildrenWithLocalname,
mozEmptyExceptChildrenWithLocalname, _, PSEUDO_CLASS_INTERNAL),
("lang", Lang, lang, _, _),
--- a/servo/components/style/gecko/wrapper.rs
+++ b/servo/components/style/gecko/wrapper.rs
@@ -1558,17 +1558,18 @@ impl<'le> ::selectors::Element for Gecko
flags_setter(self, HAS_EMPTY_SELECTOR);
if self.as_node().dom_children().any(|c| c.contains_non_whitespace_content()) {
return false
}
true
}
NonTSPseudoClass::MozTableBorderNonzero |
NonTSPseudoClass::MozBrowserFrame |
- NonTSPseudoClass::MozNativeAnonymous => unsafe {
+ NonTSPseudoClass::MozNativeAnonymous |
+ NonTSPseudoClass::MozUseShadowTreeRoot => unsafe {
Gecko_MatchesElement(pseudo_class.to_gecko_pseudoclasstype().unwrap(), self.0)
},
NonTSPseudoClass::MozIsHTML => {
self.is_html_element_in_html_document()
}
NonTSPseudoClass::MozPlaceholder => false,
NonTSPseudoClass::MozAny(ref sels) => {
let old_value = context.hover_active_quirk_disabled;
@@ -1647,16 +1648,34 @@ impl<'le> ::selectors::Element for Gecko
}
fn is_html_element_in_html_document(&self) -> bool {
let node = self.as_node();
let node_info = node.node_info();
node_info.mInner.mNamespaceID == (structs::root::kNameSpaceID_XHTML as i32) &&
node.owner_doc().mType == structs::root::nsIDocument_Type::eHTML
}
+
+ fn blocks_ancestor_combinators(&self) -> bool {
+ use gecko_bindings::structs::NODE_IS_ANONYMOUS_ROOT;
+ if self.flags() & (NODE_IS_ANONYMOUS_ROOT as u32) == 0 {
+ return false
+ }
+
+ match self.parent_element() {
+ Some(e) => {
+ // If this element is the shadow root of an use-element shadow
+ // tree, according to the spec, we should not match rules
+ // cross the shadow DOM boundary.
+ e.get_local_name().as_ptr() == atom!("use").as_ptr() &&
+ e.get_namespace() == &*Namespace(atom!("http://www.w3.org/2000/svg"))
+ },
+ None => false,
+ }
+ }
}
/// A few helpers to help with attribute selectors and snapshotting.
pub trait NamespaceConstraintHelpers {
/// Returns the namespace of the selector, or null otherwise.
fn atom_or_null(&self) -> *mut nsIAtom;
}