Bug 525952 part 3. Introduce an enum for pseudo-clases. r=dbaron
authorBoris Zbarsky <bzbarsky@mit.edu>
Fri, 11 Dec 2009 02:37:41 -0500
changeset 35562 40b14411b05a2e33d313174275fce116dd028a13
parent 35561 5bcdfa447ae5683c8c89b045f755987577325648
child 35563 9af2a428dcb1b54773e517e426daa4eec05246f6
push id10635
push userbzbarsky@mozilla.com
push dateFri, 11 Dec 2009 07:38:06 +0000
treeherdermozilla-central@9af2a428dcb1 [default view] [failures only]
perfherder[talos] [build metrics] [platform microbench] (compared to previous push)
reviewersdbaron
bugs525952
milestone1.9.3a1pre
Bug 525952 part 3. Introduce an enum for pseudo-clases. r=dbaron
layout/style/nsCSSParser.cpp
layout/style/nsCSSPseudoClasses.cpp
layout/style/nsCSSPseudoClasses.h
layout/style/nsCSSStyleRule.cpp
layout/style/nsICSSStyleRule.h
--- a/layout/style/nsCSSParser.cpp
+++ b/layout/style/nsCSSParser.cpp
@@ -360,20 +360,22 @@ protected:
   nsSelectorParsingStatus ParseAttributeSelector(PRInt32&       aDataMask,
                                                  nsCSSSelector& aSelector);
 
   nsSelectorParsingStatus ParseTypeOrUniversalSelector(PRInt32&       aDataMask,
                                                        nsCSSSelector& aSelector,
                                                        PRBool         aIsNegated);
 
   nsSelectorParsingStatus ParsePseudoClassWithIdentArg(nsCSSSelector& aSelector,
-                                                       nsIAtom*       aPseudo);
+                                                       nsIAtom*       aPseudo,
+                                                       nsCSSPseudoClasses::Type aType);
 
   nsSelectorParsingStatus ParsePseudoClassWithNthPairArg(nsCSSSelector& aSelector,
-                                                         nsIAtom*       aPseudo);
+                                                         nsIAtom*       aPseudo,
+                                                         nsCSSPseudoClasses::Type aType);
 
   nsSelectorParsingStatus ParseNegatedSimpleSelector(PRInt32&       aDataMask,
                                                      nsCSSSelector& aSelector);
 
   nsSelectorParsingStatus ParseSelector(nsCSSSelector& aSelectorResult,
                                         nsIAtom** aPseudoElement,
                                         nsPseudoClassList** aPseudoElementArgs,
                                         nsCSSPseudoElements::Type* aPseudoElementType);
@@ -3063,17 +3065,20 @@ CSSParserImpl::ParsePseudoSelector(PRInt
 #endif
   PRBool isPseudoElement =
     (pseudoElementType < nsCSSPseudoElements::ePseudo_PseudoElementCount);
   // anonymous boxes are only allowed if they're the tree boxes or we have
   // enabled unsafe rules
   PRBool isAnonBox = isTreePseudo ||
     (pseudoElementType == nsCSSPseudoElements::ePseudo_AnonBox &&
      mUnsafeRulesEnabled);
-  PRBool isPseudoClass = nsCSSPseudoClasses::IsPseudoClass(pseudo);
+  nsCSSPseudoClasses::Type pseudoClassType =
+    nsCSSPseudoClasses::GetPseudoType(pseudo);
+  PRBool isPseudoClass =
+    (pseudoClassType != nsCSSPseudoClasses::ePseudoClass_NotPseudoClass);
 
   NS_ASSERTION(!isPseudoClass ||
                pseudoElementType == nsCSSPseudoElements::ePseudo_NotPseudoElement,
                "Why is this atom both a pseudo-class and a pseudo-element?");
   NS_ASSERTION(isPseudoClass + isPseudoElement + isAnonBox <= 1,
                "Shouldn't be more than one of these");
 
   if (!isPseudoClass && !isPseudoElement && !isAnonBox) {
@@ -3120,30 +3125,30 @@ CSSParserImpl::ParsePseudoSelector(PRInt
     if (eSelectorParsingStatus_Continue != parsingStatus) {
       return parsingStatus;
     }
   }
   else if (!parsingPseudoElement && isPseudoClass) {
     aDataMask |= SEL_MASK_PCLASS;
     if (nsCSSPseudoClasses::HasStringArg(pseudo)) {
       nsSelectorParsingStatus parsingStatus =
-        ParsePseudoClassWithIdentArg(aSelector, pseudo);
+        ParsePseudoClassWithIdentArg(aSelector, pseudo, pseudoClassType);
       if (eSelectorParsingStatus_Continue != parsingStatus) {
         return parsingStatus;
       }
     }
     else if (nsCSSPseudoClasses::HasNthPairArg(pseudo)) {
       nsSelectorParsingStatus parsingStatus =
-        ParsePseudoClassWithNthPairArg(aSelector, pseudo);
+        ParsePseudoClassWithNthPairArg(aSelector, pseudo, pseudoClassType);
       if (eSelectorParsingStatus_Continue != parsingStatus) {
         return parsingStatus;
       }
     }
     else {
-      aSelector.AddPseudoClass(pseudo);
+      aSelector.AddPseudoClass(pseudo, pseudoClassType);
     }
   }
   else if (isPseudoElement || isAnonBox) {
     // Pseudo-element.  Make some more sanity checks.
 
     if (aIsNegated) { // pseudo-elements can't be negated
       REPORT_UNEXPECTED_TOKEN(PEPseudoSelPEInNot);
       UngetToken();
@@ -3286,17 +3291,18 @@ CSSParserImpl::ParseNegatedSimpleSelecto
   return eSelectorParsingStatus_Continue;
 }
 
 //
 // Parse the argument of a pseudo-class that has an ident arg
 //
 CSSParserImpl::nsSelectorParsingStatus
 CSSParserImpl::ParsePseudoClassWithIdentArg(nsCSSSelector& aSelector,
-                                            nsIAtom*       aPseudo)
+                                            nsIAtom*       aPseudo,
+                                            nsCSSPseudoClasses::Type aType)
 {
   // Check if we have the first parenthesis
   if (!ExpectSymbol('(', PR_FALSE)) {
     REPORT_UNEXPECTED_TOKEN(PEPseudoClassNoArg);
     return eSelectorParsingStatus_Error;
   }
 
   if (! GetToken(PR_TRUE)) { // premature eof
@@ -3315,31 +3321,32 @@ CSSParserImpl::ParsePseudoClassWithIdent
   if (aPseudo == nsCSSPseudoClasses::mozLocaleDir) {
     if (!mToken.mIdent.EqualsLiteral("ltr") &&
         !mToken.mIdent.EqualsLiteral("rtl")) {
       return eSelectorParsingStatus_Error;
     }
   }
 
   // Add the pseudo with the language parameter
-  aSelector.AddPseudoClass(aPseudo, mToken.mIdent.get());
+  aSelector.AddPseudoClass(aPseudo, aType, mToken.mIdent.get());
 
   // close the parenthesis
   if (!ExpectSymbol(')', PR_TRUE)) {
     REPORT_UNEXPECTED_TOKEN(PEPseudoClassNoClose);
     // XXX Call SkipUntil to the next ")"?
     return eSelectorParsingStatus_Error;
   }
 
   return eSelectorParsingStatus_Continue;
 }
 
 CSSParserImpl::nsSelectorParsingStatus
 CSSParserImpl::ParsePseudoClassWithNthPairArg(nsCSSSelector& aSelector,
-                                              nsIAtom*       aPseudo)
+                                              nsIAtom*       aPseudo,
+                                              nsCSSPseudoClasses::Type aType)
 {
   PRInt32 numbers[2] = { 0, 0 };
   PRBool lookForB = PR_TRUE;
 
   // Check whether we have the first parenthesis
   if (!ExpectSymbol('(', PR_FALSE)) {
     REPORT_UNEXPECTED_TOKEN(PEPseudoClassNoArg);
     return eSelectorParsingStatus_Error;
@@ -3452,17 +3459,17 @@ CSSParserImpl::ParsePseudoClassWithNthPa
       return eSelectorParsingStatus_Error;
     }
   }
   if (!mToken.IsSymbol(')')) {
     REPORT_UNEXPECTED_TOKEN(PEPseudoClassNoClose);
     // XXX Call SkipUntil to the next ")"?
     return eSelectorParsingStatus_Error;
   }
-  aSelector.AddPseudoClass(aPseudo, numbers);
+  aSelector.AddPseudoClass(aPseudo, aType, numbers);
   return eSelectorParsingStatus_Continue;
 }
 
 
 /**
  * This is the format for selectors:
  * operator? [[namespace |]? element_name]? [ ID | class | attrib | pseudo ]*
  */
@@ -3901,17 +3908,18 @@ CSSParserImpl::ParseTreePseudoElement(ns
   nsCSSSelector fakeSelector; // so we can reuse AddPseudoClass
   if (ExpectSymbol('(', PR_FALSE)) {
     while (!ExpectSymbol(')', PR_TRUE)) {
       if (!GetToken(PR_TRUE)) {
         return PR_FALSE;
       }
       if (eCSSToken_Ident == mToken.mType) {
         nsCOMPtr<nsIAtom> pseudo = do_GetAtom(mToken.mIdent);
-        fakeSelector.AddPseudoClass(pseudo);
+        fakeSelector.AddPseudoClass(pseudo,
+                                    nsCSSPseudoClasses::ePseudoClass_NotPseudoClass);
       }
       else if (!mToken.IsSymbol(',')) {
         SkipUntil(')');
         return PR_FALSE;
       }
     }
     *aPseudoElementArgs = fakeSelector.mPseudoClassList;
     fakeSelector.mPseudoClassList = nsnull;
--- a/layout/style/nsCSSPseudoClasses.cpp
+++ b/layout/style/nsCSSPseudoClasses.cpp
@@ -80,8 +80,20 @@ nsCSSPseudoClasses::HasStringArg(nsIAtom
 PRBool
 nsCSSPseudoClasses::HasNthPairArg(nsIAtom* aAtom)
 {
   return aAtom == nsCSSPseudoClasses::nthChild ||
          aAtom == nsCSSPseudoClasses::nthLastChild ||
          aAtom == nsCSSPseudoClasses::nthOfType ||
          aAtom == nsCSSPseudoClasses::nthLastOfType;
 }
+
+nsCSSPseudoClasses::Type
+nsCSSPseudoClasses::GetPseudoType(nsIAtom* aAtom)
+{
+  for (PRUint32 i = 0; i < NS_ARRAY_LENGTH(CSSPseudoClasses_info); ++i) {
+    if (*CSSPseudoClasses_info[i].mAtom == aAtom) {
+      return Type(i);
+    }
+  }
+
+  return nsCSSPseudoClasses::ePseudoClass_NotPseudoClass;
+}
--- a/layout/style/nsCSSPseudoClasses.h
+++ b/layout/style/nsCSSPseudoClasses.h
@@ -54,11 +54,22 @@ public:
 
   static PRBool IsPseudoClass(nsIAtom *aAtom);
   static PRBool HasStringArg(nsIAtom* aAtom);
   static PRBool HasNthPairArg(nsIAtom* aAtom);
 
 #define CSS_PSEUDO_CLASS(_name, _value) static nsICSSPseudoClass* _name;
 #include "nsCSSPseudoClassList.h"
 #undef CSS_PSEUDO_CLASS
+
+  enum Type {
+#define CSS_PSEUDO_CLASS(_name, _value) \
+    ePseudoClass_##_name,
+#include "nsCSSPseudoClassList.h"
+#undef CSS_PSEUDO_CLASS
+    ePseudoClass_Count,
+    ePseudoClass_NotPseudoClass
+  };
+
+  static Type GetPseudoType(nsIAtom* aAtom);
 };
 
 #endif /* nsCSSPseudoClasses_h___ */
--- a/layout/style/nsCSSStyleRule.cpp
+++ b/layout/style/nsCSSStyleRule.cpp
@@ -131,62 +131,70 @@ nsAtomList::Clone(PRBool aDeep) const
 }
 
 nsAtomList::~nsAtomList(void)
 {
   MOZ_COUNT_DTOR(nsAtomList);
   NS_CSS_DELETE_LIST_MEMBER(nsAtomList, this, mNext);
 }
 
-nsPseudoClassList::nsPseudoClassList(nsIAtom* aAtom)
+nsPseudoClassList::nsPseudoClassList(nsIAtom* aAtom,
+                                     nsCSSPseudoClasses::Type aType)
   : mAtom(aAtom),
+    mType(aType),
     mNext(nsnull)
 {
   NS_ASSERTION(!nsCSSPseudoClasses::HasStringArg(aAtom) &&
                !nsCSSPseudoClasses::HasNthPairArg(aAtom),
                "unexpected pseudo-class");
   MOZ_COUNT_CTOR(nsPseudoClassList);
   u.mMemory = nsnull;
 }
 
-nsPseudoClassList::nsPseudoClassList(nsIAtom* aAtom, const PRUnichar* aString)
+nsPseudoClassList::nsPseudoClassList(nsIAtom* aAtom,
+                                     nsCSSPseudoClasses::Type aType,
+                                     const PRUnichar* aString)
   : mAtom(aAtom),
+    mType(aType),
     mNext(nsnull)
 {
   NS_ASSERTION(nsCSSPseudoClasses::HasStringArg(aAtom),
                "unexpected pseudo-class");
   NS_ASSERTION(aString, "string expected");
   MOZ_COUNT_CTOR(nsPseudoClassList);
   u.mString = NS_strdup(aString);
 }
 
-nsPseudoClassList::nsPseudoClassList(nsIAtom* aAtom, const PRInt32* aIntPair)
+nsPseudoClassList::nsPseudoClassList(nsIAtom* aAtom,
+                                     nsCSSPseudoClasses::Type aType,
+                                     const PRInt32* aIntPair)
   : mAtom(aAtom),
+    mType(aType),
     mNext(nsnull)
 {
   NS_ASSERTION(nsCSSPseudoClasses::HasNthPairArg(aAtom),
                "unexpected pseudo-class");
   NS_ASSERTION(aIntPair, "integer pair expected");
   MOZ_COUNT_CTOR(nsPseudoClassList);
   u.mNumbers =
     static_cast<PRInt32*>(nsMemory::Clone(aIntPair, sizeof(PRInt32) * 2));
 }
 
 nsPseudoClassList*
 nsPseudoClassList::Clone(PRBool aDeep) const
 {
   nsPseudoClassList *result;
   if (!u.mMemory) {
-    result = new nsPseudoClassList(mAtom);
+    result = new nsPseudoClassList(mAtom, mType);
   } else if (nsCSSPseudoClasses::HasStringArg(mAtom)) {
-    result = new nsPseudoClassList(mAtom, u.mString);
+    result = new nsPseudoClassList(mAtom, mType, u.mString);
   } else {
     NS_ASSERTION(nsCSSPseudoClasses::HasNthPairArg(mAtom),
                  "unexpected pseudo-class");
-    result = new nsPseudoClassList(mAtom, u.mNumbers);
+    result = new nsPseudoClassList(mAtom, mType, u.mNumbers);
   }
 
   if (aDeep)
     NS_CSS_CLONE_LIST_MEMBER(nsPseudoClassList, this, mNext, result,
                              (PR_FALSE));
 
   return result;
 }
@@ -387,31 +395,34 @@ void nsCSSSelector::AddClass(const nsStr
     nsAtomList** list = &mClassList;
     while (nsnull != *list) {
       list = &((*list)->mNext);
     }
     *list = new nsAtomList(aClass);
   }
 }
 
-void nsCSSSelector::AddPseudoClass(nsIAtom* aPseudoClass)
+void nsCSSSelector::AddPseudoClass(nsIAtom* aPseudoClass,
+                                   nsCSSPseudoClasses::Type aType)
 {
-  AddPseudoClassInternal(new nsPseudoClassList(aPseudoClass));
+  AddPseudoClassInternal(new nsPseudoClassList(aPseudoClass, aType));
 }
 
 void nsCSSSelector::AddPseudoClass(nsIAtom* aPseudoClass,
+                                   nsCSSPseudoClasses::Type aType,
                                    const PRUnichar* aString)
 {
-  AddPseudoClassInternal(new nsPseudoClassList(aPseudoClass, aString));
+  AddPseudoClassInternal(new nsPseudoClassList(aPseudoClass, aType, aString));
 }
 
 void nsCSSSelector::AddPseudoClass(nsIAtom* aPseudoClass,
+                                   nsCSSPseudoClasses::Type aType,
                                    const PRInt32* aIntPair)
 {
-  AddPseudoClassInternal(new nsPseudoClassList(aPseudoClass, aIntPair));
+  AddPseudoClassInternal(new nsPseudoClassList(aPseudoClass, aType, aIntPair));
 }
 
 void nsCSSSelector::AddPseudoClassInternal(nsPseudoClassList *aPseudoClass)
 {
   nsPseudoClassList** list = &mPseudoClassList;
   while (nsnull != *list) {
     list = &((*list)->mNext);
   }
--- a/layout/style/nsICSSStyleRule.h
+++ b/layout/style/nsICSSStyleRule.h
@@ -48,16 +48,17 @@
 //#include <stdio.h>
 #include "nsICSSRule.h"
 #include "nsString.h"
 #include "nsCOMPtr.h"
 #include "nsCSSProps.h"
 #include "nsCSSValue.h"
 #include "nsIAtom.h"
 #include "nsCSSPseudoElements.h"
+#include "nsCSSPseudoClasses.h"
 
 class nsIAtom;
 class nsCSSDeclaration;
 class nsICSSStyleSheet;
 
 struct nsAtomList {
 public:
   nsAtomList(nsIAtom* aAtom);
@@ -74,19 +75,21 @@ private:
 
   // These are not supported and are not implemented! 
   nsAtomList(const nsAtomList& aCopy);
   nsAtomList& operator=(const nsAtomList& aCopy); 
 };
 
 struct nsPseudoClassList {
 public:
-  nsPseudoClassList(nsIAtom* aAtom);
-  nsPseudoClassList(nsIAtom* aAtom, const PRUnichar *aString);
-  nsPseudoClassList(nsIAtom* aAtom, const PRInt32 *aIntPair);
+  nsPseudoClassList(nsIAtom* aAtom, nsCSSPseudoClasses::Type aType);
+  nsPseudoClassList(nsIAtom* aAtom, nsCSSPseudoClasses::Type aType,
+                    const PRUnichar *aString);
+  nsPseudoClassList(nsIAtom* aAtom, nsCSSPseudoClasses::Type aType,
+                    const PRInt32 *aIntPair);
   ~nsPseudoClassList(void);
 
   /** Do a deep clone.  Should be used only on the first in the linked list. */
   nsPseudoClassList* Clone() const { return Clone(PR_TRUE); }
 
   nsCOMPtr<nsIAtom> mAtom;
   union {
     // For a given value of mAtom, we have either:
@@ -95,16 +98,17 @@ public:
     //   b. a string value, which means mString/mMemory is non-null
     //      (if nsCSSPseudoClasses::HasStringArg(mAtom))
     //   c. an integer pair value, which means mNumbers/mMemory is non-null
     //      (if nsCSSPseudoClasses::HasNthPairArg(mAtom))
     void*           mMemory; // both pointer types use NS_Alloc/NS_Free
     PRUnichar*      mString;
     PRInt32*        mNumbers;
   } u;
+  nsCSSPseudoClasses::Type mType;
   nsPseudoClassList* mNext;
 private: 
   nsPseudoClassList* Clone(PRBool aDeep) const;
 
   // These are not supported and are not implemented! 
   nsPseudoClassList(const nsPseudoClassList& aCopy);
   nsPseudoClassList& operator=(const nsPseudoClassList& aCopy); 
 };
@@ -154,19 +158,21 @@ public:
   /** Do a deep clone.  Should be used only on the first in the linked list. */
   nsCSSSelector* Clone() const { return Clone(PR_TRUE, PR_TRUE); }
 
   void Reset(void);
   void SetNameSpace(PRInt32 aNameSpace);
   void SetTag(const nsString& aTag);
   void AddID(const nsString& aID);
   void AddClass(const nsString& aClass);
-  void AddPseudoClass(nsIAtom* aPseudoClass);
-  void AddPseudoClass(nsIAtom* aPseudoClass, const PRUnichar* aString);
-  void AddPseudoClass(nsIAtom* aPseudoClass, const PRInt32* aIntPair);
+  void AddPseudoClass(nsIAtom* aPseudoClass, nsCSSPseudoClasses::Type aType);
+  void AddPseudoClass(nsIAtom* aPseudoClass, nsCSSPseudoClasses::Type aType,
+                      const PRUnichar* aString);
+  void AddPseudoClass(nsIAtom* aPseudoClass, nsCSSPseudoClasses::Type aType,
+                      const PRInt32* aIntPair);
   void AddAttribute(PRInt32 aNameSpace, const nsString& aAttr);
   void AddAttribute(PRInt32 aNameSpace, const nsString& aAttr, PRUint8 aFunc, 
                     const nsString& aValue, PRBool aCaseSensitive);
   void SetOperator(PRUnichar aOperator);
 
   inline PRBool HasTagSelector() const {
     return !!mCasedTag;
   }