Bug 525952 part 3. Introduce an enum for pseudo-clases. r=dbaron
--- 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;
}