Bug 653881 - Add a compatibility hack to allow <xbl:children> elements to be optional when selecting via the child CSS selector. This allows old CSS selectors selecting default content to continue working in the new world. r=dbaron
authorBlake Kaplan <mrbkap@gmail.com>
Fri, 28 Jun 2013 18:48:13 -0700
changeset 136876 1b8207252e9ca1194eccd3adc14b961785fb4e8e
parent 136875 989747f479ee1bb8d24c51f24308bf1070be3ff7
child 136877 dc039d7f5e004d19d8b563992d48d2beb3b44b1e
push idunknown
push userunknown
push dateunknown
reviewersdbaron
bugs653881
milestone25.0a1
Bug 653881 - Add a compatibility hack to allow <xbl:children> elements to be optional when selecting via the child CSS selector. This allows old CSS selectors selecting default content to continue working in the new world. r=dbaron
layout/reftests/dom/reftest.list
layout/reftests/dom/xbl-children-1-ref.xhtml
layout/reftests/dom/xbl-children-1.xhtml
layout/style/nsCSSRuleProcessor.cpp
--- a/layout/reftests/dom/reftest.list
+++ b/layout/reftests/dom/reftest.list
@@ -43,8 +43,10 @@ skip-if(B2G) == multipleinsertionpoints-
 # insert several elements
 skip-if(B2G) == multipleinsertionpoints-insertmultiple.xhtml multipleinsertionpoints-ref.xhtml # bug 773482
 
 # test appending some nodes whose frame construction should be done lazily
 # followed by appending a node that might not be done lazily
 == multipleappendwithxul.xhtml multipleappendwithxul-ref.xhtml
 == multipleappendwithinput.xhtml multipleappendwithinput-ref.xhtml
 == multipleappendwitheditable.xhtml multipleappendwitheditable-ref.xhtml
+
+skip-if(B2G) == xbl-children-1.xhtml xbl-children-1-ref.xhtml
new file mode 100644
--- /dev/null
+++ b/layout/reftests/dom/xbl-children-1-ref.xhtml
@@ -0,0 +1,16 @@
+<html xmlns="http://www.w3.org/1999/xhtml">
+  <head>
+    <style>
+      #result {
+        color: green;
+        text-decoration: underline;
+        text-transform: lowercase;
+        background: yellow;
+      }
+    </style>
+  </head>
+  <body>
+    <div id="result">text</div>
+  </body>
+</html>
+
new file mode 100644
--- /dev/null
+++ b/layout/reftests/dom/xbl-children-1.xhtml
@@ -0,0 +1,39 @@
+<html xmlns="http://www.w3.org/1999/xhtml">
+<head>
+
+<bindings xmlns="http://www.mozilla.org/xbl"
+          xmlns:xhtml="http://www.w3.org/1999/xhtml">
+  <binding id="a">
+    <content>
+      <xhtml:div class="aparent">
+        <xhtml:div class="a">
+          <children>
+            <xhtml:div class="b">
+              TEXT
+            </xhtml:div>
+          </children>
+        </xhtml:div>
+      </xhtml:div>
+    </content>
+  </binding>
+</bindings>
+
+<style>
+
+  @namespace xbl "http://www.mozilla.org/xbl";
+  .a > .b { color: green; }
+  .a > xbl|children > .b { text-decoration: underline; }
+  .a .b { text-transform: lowercase; }
+  .aparent > * > .b { background: yellow; }
+
+  /* Inverse cases. */
+  .a > * > xbl|children > .b { color: red !important; }
+
+</style>
+
+</head>
+
+<body>
+<div style="-moz-binding: url(#a);" />
+</body>
+</html>
--- a/layout/style/nsCSSRuleProcessor.cpp
+++ b/layout/style/nsCSSRuleProcessor.cpp
@@ -2282,16 +2282,37 @@ static bool SelectorMatchesTree(Element*
         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
           // traverse further up the tree.
           aTreeMatchContext.PopStyleScopeForSelectorMatching(element);
         }
+
+        // Compatibility hack: First try matching this selector as though the
+        // <xbl:children> element wasn't in the tree to allow old selectors
+        // were written before <xbl:children> participated in CSS selector
+        // matching to work.
+        if (selector->mOperator == '>' &&
+            element->NodeInfo()->Equals(nsGkAtoms::children,
+                                        kNameSpaceID_XBL)) {
+          Element* styleScope = aTreeMatchContext.mCurrentStyleScope;
+          if (SelectorMatchesTree(element, selector, aTreeMatchContext,
+                                  aLookForRelevantLink)) {
+            // It matched, don't try matching on the <xbl:children> element at
+            // all.
+            return true;
+          }
+          // We want to reset mCurrentStyleScope on aTreeMatchContext
+          // back to its state before the SelectorMatchesTree call, in
+          // case that call happens to traverse past the style scope element
+          // and sets it to null.
+          aTreeMatchContext.mCurrentStyleScope = styleScope;
+        }
       }
     }
     if (!element) {
       return false;
     }
     NodeMatchContext nodeContext(nsEventStates(),
                                  aLookForRelevantLink &&
                                    nsCSSRuleProcessor::IsLink(element));