Bug 265894 - Part 9. Selectors should not cross use-element shadow tree boundary. draft
authorcku <cku@mozilla.com>
Wed, 14 Jun 2017 23:06:30 +0800
changeset 597169 855e5ca287918978cf727c58466af829d2788750
parent 597168 71751d5a009cf53e49bf244741171eb2d2c8d28e
child 597170 457d30ac8276b29c6e3f30888bbc73d61987ff0e
push id64856
push userbmo:cku@mozilla.com
push dateTue, 20 Jun 2017 07:46:45 +0000
bugs265894
milestone56.0a1
Bug 265894 - Part 9. Selectors should not cross use-element shadow tree boundary. MozReview-Commit-ID: 9xrZ5938FRV
dom/base/nsIContent.h
layout/style/nsCSSPseudoClasses.cpp
layout/style/nsCSSRuleProcessor.cpp
--- 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