Bug 523288 part 1. Move matching on id and class to right after matching on tag in SelectorMatches. r=dbaron
authorBoris Zbarsky <bzbarsky@mit.edu>
Thu, 10 Dec 2009 14:36:02 -0800
changeset 35530 1e9e3cd957f2160f66ae9df56ecaf37ea972c47d
parent 35529 b7824c1c8596ad93790c8f8e3c0f5135c8f2ddac
child 35531 b3636bfdc6d938963b31a682aae2608011bfd137
push id10631
push userbzbarsky@mozilla.com
push dateThu, 10 Dec 2009 22:48:24 +0000
treeherdermozilla-central@08b48be6951b [default view] [failures only]
perfherder[talos] [build metrics] [platform microbench] (compared to previous push)
reviewersdbaron
bugs523288
milestone1.9.3a1pre
Bug 523288 part 1. Move matching on id and class to right after matching on tag in SelectorMatches. r=dbaron
layout/style/nsCSSRuleProcessor.cpp
--- a/layout/style/nsCSSRuleProcessor.cpp
+++ b/layout/style/nsCSSRuleProcessor.cpp
@@ -1264,16 +1264,83 @@ static PRBool SelectorMatches(RuleProces
     data.mIsHTMLContent && data.mContent->GetOwnerDoc()->IsHTML();
 
   if (aSelector->mLowercaseTag && 
       (isHTML ? aSelector->mLowercaseTag : aSelector->mCasedTag) !=
         data.mContentTag) {
     return PR_FALSE;
   }
 
+  nsAtomList* IDList = aSelector->mIDList;
+  if (IDList) {
+    // test for ID match
+    if (aAttribute && aAttribute == data.mContent->GetIDAttributeName()) {
+      if (aDependence)
+        *aDependence = PR_TRUE;
+    }
+    else if (data.mContentID) {
+      // case sensitivity: bug 93371
+      const PRBool isCaseSensitive =
+        data.mCompatMode != eCompatibility_NavQuirks;
+
+      if (isCaseSensitive) {
+        do {
+          if (IDList->mAtom != data.mContentID) {
+            return PR_FALSE;
+          }
+          IDList = IDList->mNext;
+        } while (IDList);
+      } else {
+        const char* id1Str;
+        data.mContentID->GetUTF8String(&id1Str);
+        nsDependentCString id1(id1Str);
+        do {
+          const char* id2Str;
+          IDList->mAtom->GetUTF8String(&id2Str);
+          if (!id1.Equals(id2Str, nsCaseInsensitiveCStringComparator())) {
+            return PR_FALSE;
+          }
+          IDList = IDList->mNext;
+        } while (IDList);
+      }
+    } else {
+      // Element has no id but we have an id selector
+      return PR_FALSE;
+    }
+  }
+
+  nsAtomList* classList = aSelector->mClassList;
+  if (classList) {
+    // test for class match
+    if (aAttribute && aAttribute == data.mContent->GetClassAttributeName()) {
+      if (aDependence)
+        *aDependence = PR_TRUE;
+    }
+    else {
+      const nsAttrValue *elementClasses = data.mClasses;
+      if (!elementClasses) {
+        // Element has no classes but we have a class selector
+        return PR_FALSE;
+      }
+
+      // case sensitivity: bug 93371
+      const PRBool isCaseSensitive =
+        data.mCompatMode != eCompatibility_NavQuirks;
+
+      while (classList) {
+        if (!elementClasses->Contains(classList->mAtom,
+                                      isCaseSensitive ?
+                                        eCaseMatters : eIgnoreCase)) {
+          return PR_FALSE;
+        }
+        classList = classList->mNext;
+      }
+    }
+  }
+
   PRBool result = PR_TRUE;
   const PRBool isNegated = (aDependence != nsnull);
   // The selectors for which we set node bits are, unfortunately, early
   // in this function (because they're pseudo-classes, which are
   // generally quick to test, and thus earlier).  If they were later,
   // we'd probably avoid setting those bits in more cases where setting
   // them is unnecessary.
   const PRBool setNodeFlags = aForStyling && aStateMask == 0 && !aAttribute;
@@ -1796,81 +1863,17 @@ static PRBool SelectorMatches(RuleProces
           NS_ASSERTION(hasAttr, "HasAttr lied");
           result = AttrMatchesValue(attr, value, isHTML);
         }
         
         attr = attr->mNext;
       } while (attr && result);
     }
   }
-  nsAtomList* IDList = aSelector->mIDList;
-  if (result && IDList) {
-    // test for ID match
-    result = PR_FALSE;
 
-    if (aAttribute && aAttribute == data.mContent->GetIDAttributeName()) {
-      result = PR_TRUE;
-      if (aDependence)
-        *aDependence = PR_TRUE;
-    }
-    else if (nsnull != data.mContentID) {
-      // case sensitivity: bug 93371
-      const PRBool isCaseSensitive =
-        data.mCompatMode != eCompatibility_NavQuirks;
-
-      result = PR_TRUE;
-      if (isCaseSensitive) {
-        do {
-          if (IDList->mAtom != data.mContentID) {
-            result = PR_FALSE;
-            break;
-          }
-          IDList = IDList->mNext;
-        } while (IDList);
-      } else {
-        const char* id1Str;
-        data.mContentID->GetUTF8String(&id1Str);
-        nsDependentCString id1(id1Str);
-        do {
-          const char* id2Str;
-          IDList->mAtom->GetUTF8String(&id2Str);
-          if (!id1.Equals(id2Str, nsCaseInsensitiveCStringComparator())) {
-            result = PR_FALSE;
-            break;
-          }
-          IDList = IDList->mNext;
-        } while (IDList);
-      }
-    }
-  }
-    
-  if (result && aSelector->mClassList) {
-    // test for class match
-    if (aAttribute && aAttribute == data.mContent->GetClassAttributeName()) {
-      result = PR_TRUE;
-      if (aDependence)
-        *aDependence = PR_TRUE;
-    }
-    else {
-      // case sensitivity: bug 93371
-      const PRBool isCaseSensitive =
-        data.mCompatMode != eCompatibility_NavQuirks;
-
-      nsAtomList* classList = aSelector->mClassList;
-      const nsAttrValue *elementClasses = data.mClasses;
-      while (nsnull != classList) {
-        if (!(elementClasses && elementClasses->Contains(classList->mAtom, isCaseSensitive ? eCaseMatters : eIgnoreCase))) {
-          result = PR_FALSE;
-          break;
-        }
-        classList = classList->mNext;
-      }
-    }
-  }
-  
   // apply SelectorMatches to the negated selectors in the chain
   if (!isNegated) {
     for (nsCSSSelector *negation = aSelector->mNegations;
          result && negation; negation = negation->mNegations) {
       PRBool dependence = PR_FALSE;
       result = !SelectorMatches(data, negation, aStateMask,
                                 aAttribute, aForStyling, &dependence);
       // If the selector does match due to the dependence on aStateMask