Bug 735481. Skip ancestor filtering on IDs and classes in quirks mode, because that matching needs to be case-insensitive. r=dbaron
authorBoris Zbarsky <bzbarsky@mit.edu>
Wed, 14 Mar 2012 00:44:13 -0500
changeset 92679 c1c473ede6289b53e4df543e0b3b5985e7ad7ff1
parent 92316 7a85d32044db370943b3ef32cbd32e0264c53b25
child 92680 edc0871b4e5b4230a27c3726ab95459fa1a46175
push id886
push userlsblakk@mozilla.com
push dateMon, 04 Jun 2012 19:57:52 +0000
treeherdermozilla-beta@bbd8d5efd6d1 [default view] [failures only]
perfherder[talos] [build metrics] [platform microbench] (compared to previous push)
reviewersdbaron
bugs735481
milestone14.0a1
first release with
nightly linux32
nightly linux64
nightly mac
nightly win32
nightly win64
last release without
nightly linux32
nightly linux64
nightly mac
nightly win32
nightly win64
Bug 735481. Skip ancestor filtering on IDs and classes in quirks mode, because that matching needs to be case-insensitive. r=dbaron
layout/reftests/bugs/735481-1-ref.html
layout/reftests/bugs/735481-1.html
layout/reftests/bugs/reftest.list
layout/style/nsCSSRuleProcessor.cpp
new file mode 100644
--- /dev/null
+++ b/layout/reftests/bugs/735481-1-ref.html
@@ -0,0 +1,10 @@
+<!-- This test is intentionally in quirks mode -->
+<style>
+  div { color: green; }
+</style>
+<div>
+  <div>This text should be green</div>
+</div>
+<div>
+  <div>This text should be green</div>
+</div>
new file mode 100644
--- /dev/null
+++ b/layout/reftests/bugs/735481-1.html
@@ -0,0 +1,12 @@
+<!-- This test is intentionally in quirks mode -->
+<style>
+  div { color: red; }
+  .TEST1 div { color: green; }
+  #TEST2 div { color: green; }
+</style>
+<div class="test1">
+  <div>This text should be green</div>
+</div>
+<div id="test2">
+  <div>This text should be green</div>
+</div>
--- a/layout/reftests/bugs/reftest.list
+++ b/layout/reftests/bugs/reftest.list
@@ -1690,8 +1690,9 @@ needs-focus != 703186-1.html 703186-2.ht
 == 714519-1-q.html 714519-1-ref.html
 == 714519-2-as.html 714519-2-ref.html
 == 714519-2-q.html 714519-2-ref.html
 fuzzy-if(d2d,1,19) fuzzy-if(cocoaWidget,1,170) == 718521.html 718521-ref.html
 == 720987.html 720987-ref.html
 == 722923-1.html 722923-1-ref.html
 == 729143-1.html 729143-1-ref.html
 needs-focus == 731726-1.html 731726-1-ref.html
+== 735481-1.html 735481-1-ref.html
--- a/layout/style/nsCSSRuleProcessor.cpp
+++ b/layout/style/nsCSSRuleProcessor.cpp
@@ -132,60 +132,65 @@ struct RuleSelectorPair {
  * (the ordering depending on the weight of mSelector and the order of
  * our rules to start with).
  */
 struct RuleValue : RuleSelectorPair {
   enum {
     eMaxAncestorHashes = 4
   };
 
-  RuleValue(const RuleSelectorPair& aRuleSelectorPair, PRInt32 aIndex) :
+  RuleValue(const RuleSelectorPair& aRuleSelectorPair, PRInt32 aIndex,
+            bool aQuirksMode) :
     RuleSelectorPair(aRuleSelectorPair),
     mIndex(aIndex)
   {
-    CollectAncestorHashes();
+    CollectAncestorHashes(aQuirksMode);
   }
 
   PRInt32 mIndex; // High index means high weight/order.
   uint32_t mAncestorSelectorHashes[eMaxAncestorHashes];
 
 private:
-  void CollectAncestorHashes() {
+  void CollectAncestorHashes(bool aQuirksMode) {
     // Collect up our mAncestorSelectorHashes.  It's not clear whether it's
     // better to stop once we've found eMaxAncestorHashes of them or to keep
     // going and preferentially collect information from selectors higher up the
     // chain...  Let's do the former for now.
     size_t hashIndex = 0;
     for (nsCSSSelector* sel = mSelector->mNext; sel; sel = sel->mNext) {
       if (!NS_IS_ANCESTOR_OPERATOR(sel->mOperator)) {
         // |sel| is going to select something that's not actually one of our
         // ancestors, so don't add it to mAncestorSelectorHashes.  But keep
         // going, because it'll select a sibling of one of our ancestors, so its
         // ancestors would be our ancestors too.
         continue;
       }
 
-      // Now sel is supposed to select one of our ancestors.  Grab whatever info
-      // we can from it into mAncestorSelectorHashes.
-      nsAtomList* ids = sel->mIDList;
-      while (ids) {
-        mAncestorSelectorHashes[hashIndex++] = ids->mAtom->hash();
-        if (hashIndex == eMaxAncestorHashes) {
-          return;
+      // Now sel is supposed to select one of our ancestors.  Grab
+      // whatever info we can from it into mAncestorSelectorHashes.
+      // But in qurks mode, don't grab IDs and classes because those
+      // need to be matched case-insensitively.
+      if (!aQuirksMode) {
+        nsAtomList* ids = sel->mIDList;
+        while (ids) {
+          mAncestorSelectorHashes[hashIndex++] = ids->mAtom->hash();
+          if (hashIndex == eMaxAncestorHashes) {
+            return;
+          }
+          ids = ids->mNext;
         }
-        ids = ids->mNext;
-      }
-
-      nsAtomList* classes = sel->mClassList;
-      while (classes) {
-        mAncestorSelectorHashes[hashIndex++] = classes->mAtom->hash();
-        if (hashIndex == eMaxAncestorHashes) {
-          return;
+
+        nsAtomList* classes = sel->mClassList;
+        while (classes) {
+          mAncestorSelectorHashes[hashIndex++] = classes->mAtom->hash();
+          if (hashIndex == eMaxAncestorHashes) {
+            return;
+          }
+          classes = classes->mNext;
         }
-        classes = classes->mNext;
       }
 
       // Only put in the tag name if it's all-lowercase.  Otherwise we run into
       // trouble because we may test the wrong one of mLowercaseTag and
       // mCasedTag against the filter.
       if (sel->mLowercaseTag && sel->mCasedTag == sel->mLowercaseTag) {
         mAncestorSelectorHashes[hashIndex++] = sel->mLowercaseTag->hash();
         if (hashIndex == eMaxAncestorHashes) {
@@ -623,17 +628,17 @@ RuleHash::~RuleHash()
 void RuleHash::AppendRuleToTable(PLDHashTable* aTable, const void* aKey,
                                  const RuleSelectorPair& aRuleInfo)
 {
   // Get a new or existing entry.
   RuleHashTableEntry *entry = static_cast<RuleHashTableEntry*>
                                          (PL_DHashTableOperate(aTable, aKey, PL_DHASH_ADD));
   if (!entry)
     return;
-  entry->mRules.AppendElement(RuleValue(aRuleInfo, mRuleCount++));
+  entry->mRules.AppendElement(RuleValue(aRuleInfo, mRuleCount++, mQuirksMode));
 }
 
 static void
 AppendRuleToTagTable(PLDHashTable* aTable, nsIAtom* aKey,
                      const RuleValue& aRuleInfo)
 {
   // Get a new or exisiting entry
   RuleHashTagTableEntry *entry = static_cast<RuleHashTagTableEntry*>
@@ -641,17 +646,17 @@ AppendRuleToTagTable(PLDHashTable* aTabl
   if (!entry)
     return;
 
   entry->mRules.AppendElement(aRuleInfo);
 }
 
 void RuleHash::AppendUniversalRule(const RuleSelectorPair& aRuleInfo)
 {
-  mUniversalRules.AppendElement(RuleValue(aRuleInfo, mRuleCount++));
+  mUniversalRules.AppendElement(RuleValue(aRuleInfo, mRuleCount++, mQuirksMode));
 }
 
 void RuleHash::AppendRule(const RuleSelectorPair& aRuleInfo)
 {
   nsCSSSelector *selector = aRuleInfo.mSelector;
   if (nsnull != selector->mIDList) {
     if (!mIdTable.ops) {
       PL_DHashTableInit(&mIdTable,
@@ -668,17 +673,17 @@ void RuleHash::AppendRule(const RuleSele
                         mQuirksMode ? &RuleHash_ClassTable_CIOps.ops
                                     : &RuleHash_ClassTable_CSOps.ops,
                         nsnull, sizeof(RuleHashTableEntry), 16);
     }
     AppendRuleToTable(&mClassTable, selector->mClassList->mAtom, aRuleInfo);
     RULE_HASH_STAT_INCREMENT(mClassSelectors);
   }
   else if (selector->mLowercaseTag) {
-    RuleValue ruleValue(aRuleInfo, mRuleCount++);
+    RuleValue ruleValue(aRuleInfo, mRuleCount++, mQuirksMode);
     if (!mTagTable.ops) {
       PL_DHashTableInit(&mTagTable, &RuleHash_TagTable_Ops, nsnull,
                         sizeof(RuleHashTagTableEntry), 16);
     }
     AppendRuleToTagTable(&mTagTable, selector->mLowercaseTag, ruleValue);
     RULE_HASH_STAT_INCREMENT(mTagSelectors);
     if (selector->mCasedTag && 
         selector->mCasedTag != selector->mLowercaseTag) {
@@ -2899,26 +2904,26 @@ AddRule(RuleSelectorPair* aRuleInfo, Rul
                  !aRuleInfo->mSelector->mNext &&
                  aRuleInfo->mSelector->mNameSpace == kNameSpaceID_Unknown,
                  "Parser messed up with anon box selector");
 
     // Index doesn't matter here, since we'll just be walking these
     // rules in order; just pass 0.
     AppendRuleToTagTable(&cascade->mAnonBoxRules,
                          aRuleInfo->mSelector->mLowercaseTag,
-                         RuleValue(*aRuleInfo, 0));
+                         RuleValue(*aRuleInfo, 0, aCascade->mQuirksMode));
   } else {
 #ifdef MOZ_XUL
     NS_ASSERTION(pseudoType == nsCSSPseudoElements::ePseudo_XULTree,
                  "Unexpected pseudo type");
     // Index doesn't matter here, since we'll just be walking these
     // rules in order; just pass 0.
     AppendRuleToTagTable(&cascade->mXULTreeRules,
                          aRuleInfo->mSelector->mLowercaseTag,
-                         RuleValue(*aRuleInfo, 0));
+                         RuleValue(*aRuleInfo, 0, aCascade->mQuirksMode));
 #else
     NS_NOTREACHED("Unexpected pseudo type");
 #endif
   }
 
   for (nsCSSSelector* selector = aRuleInfo->mSelector;
            selector; selector = selector->mNext) {
     if (selector->IsPseudoElement()) {