Bug 265894 - Part 9. Selectors should not cross use-element shadow tree boundary.
MozReview-Commit-ID: 9xrZ5938FRV
--- a/dom/base/nsIContent.h
+++ b/dom/base/nsIContent.h
@@ -239,16 +239,24 @@ public:
NS_ASSERTION(!IsInNativeAnonymousSubtree() || GetBindingParent() ||
(!IsInUncomposedDoc() &&
static_cast<nsIContent*>(SubtreeRoot())->IsInNativeAnonymousSubtree()),
"Must have binding parent when in native anonymous subtree which is in document.\n"
"Native anonymous subtree which is not in document must have native anonymous root.");
return IsInNativeAnonymousSubtree() || (!IsInShadowTree() && GetBindingParent() != nullptr);
}
+ /*
+ * Return true if this node is the shadow root of an use-element shadow tree.
+ */
+ bool IsRootOfUseElementShadowTree() const {
+ return GetParent() && GetParent()->IsSVGElement(nsGkAtoms::use) &&
+ IsRootOfAnonymousSubtree();
+ }
+
/**
* Return true iff this node is in an HTML document (in the HTML5 sense of
* the term, i.e. not in an XHTML/XML document).
*/
inline bool IsInHTMLDocument() const;
/**
--- a/layout/style/nsCSSPseudoClasses.cpp
+++ b/layout/style/nsCSSPseudoClasses.cpp
@@ -135,19 +135,17 @@ nsCSSPseudoClasses::IsUserActionPseudoCl
/* static */ Maybe<bool>
nsCSSPseudoClasses::MatchesElement(Type aType, const dom::Element* aElement)
{
switch (aType) {
case CSSPseudoClassType::mozNativeAnonymous:
return Some(aElement->IsInNativeAnonymousSubtree());
case CSSPseudoClassType::mozUseShadowTreeRoot:
- return Some(aElement->IsRootOfAnonymousSubtree() &&
- aElement->GetParent() &&
- aElement->GetParent()->IsSVGElement(nsGkAtoms::use));
+ return Some(aElement->IsRootOfUseElementShadowTree());
case CSSPseudoClassType::mozTableBorderNonzero: {
if (!aElement->IsHTMLElement(nsGkAtoms::table)) {
return Some(false);
}
const nsAttrValue *val = aElement->GetParsedAttr(nsGkAtoms::border);
return Some(val && (val->Type() != nsAttrValue::eInteger ||
val->GetIntegerValue() != 0));
}
--- a/layout/style/nsCSSRuleProcessor.cpp
+++ b/layout/style/nsCSSRuleProcessor.cpp
@@ -2420,16 +2420,22 @@ SelectorMatchesTree(Element* aPrevElemen
element = prevElement->GetPreviousElementSibling();
}
}
// for descendant combinators and child combinators, the element
// to test against is the parent
else {
nsIContent *content = prevElement->GetParent();
+ if (prevElement->IsRootOfUseElementShadowTree()) {
+ // 'prevElement' is the shadow root of an use-element shadow tree.
+ // According to the spec, we should not match rules cross the shadow
+ // DOM boundary.
+ content = nullptr;
+ }
// GetParent could return a document fragment; we only want
// element parents.
if (content && content->IsElement()) {
element = content->AsElement();
if (aTreeMatchContext.mForScopedStyle) {
// We are moving up to the parent element; tell the
// TreeMatchContext, so that in case this element is the
// style scope element, selector matching stops before we