mirror of
https://github.com/mozilla/gecko-dev.git
synced 2025-05-13 17:07:01 +00:00
Bug 93371 (WRMB: Treat classes case insensitively in quirks mode). Back out ianh's patch in nsCSSParser.cpp and nsHTMLAttributes.cpp. Treat classes and IDs case insensitively as described in Bug 35522. r=glazman (+dbaron/jst) sr=hyatt
This commit is contained in:
parent
db01af7cd6
commit
c164042a1e
@ -42,7 +42,7 @@ public:
|
||||
|
||||
NS_IMETHOD GetID(nsIAtom*& aResult) const = 0;
|
||||
NS_IMETHOD GetClasses(nsVoidArray& aArray) const = 0;
|
||||
NS_IMETHOD HasClass(nsIAtom* aClass) const = 0;
|
||||
NS_IMETHOD HasClass(nsIAtom* aClass, PRBool aCaseSensitive) const = 0;
|
||||
|
||||
NS_IMETHOD WalkContentStyleRules(nsIRuleWalker* aRuleWalker) = 0;
|
||||
NS_IMETHOD WalkInlineStyleRules(nsIRuleWalker* aRuleWalker) = 0;
|
||||
|
@ -1808,7 +1808,7 @@ nsGenericElement::GetClasses(nsVoidArray& aArray) const
|
||||
}
|
||||
|
||||
NS_IMETHODIMP
|
||||
nsGenericElement::HasClass(nsIAtom* aClass) const
|
||||
nsGenericElement::HasClass(nsIAtom* aClass, PRBool aCaseSensitive) const
|
||||
{
|
||||
return NS_ERROR_NOT_IMPLEMENTED;
|
||||
}
|
||||
|
@ -272,7 +272,7 @@ public:
|
||||
// nsIStyledContent interface methods
|
||||
NS_IMETHOD GetID(nsIAtom*& aResult) const;
|
||||
NS_IMETHOD GetClasses(nsVoidArray& aArray) const;
|
||||
NS_IMETHOD HasClass(nsIAtom* aClass) const;
|
||||
NS_IMETHOD HasClass(nsIAtom* aClass, PRBool aCaseSensitive) const;
|
||||
NS_IMETHOD WalkContentStyleRules(nsIRuleWalker* aRuleWalker);
|
||||
NS_IMETHOD WalkInlineStyleRules(nsIRuleWalker* aRuleWalker);
|
||||
NS_IMETHOD GetMappedAttributeImpact(const nsIAtom* aAttribute, PRInt32 aModType,
|
||||
|
@ -2019,10 +2019,10 @@ nsGenericHTMLElement::GetClasses(nsVoidArray& aArray) const
|
||||
}
|
||||
|
||||
nsresult
|
||||
nsGenericHTMLElement::HasClass(nsIAtom* aClass) const
|
||||
nsGenericHTMLElement::HasClass(nsIAtom* aClass, PRBool aCaseSensitive) const
|
||||
{
|
||||
if (nsnull != mAttributes) {
|
||||
return mAttributes->HasClass(aClass);
|
||||
return mAttributes->HasClass(aClass, aCaseSensitive);
|
||||
}
|
||||
return NS_COMFALSE;
|
||||
}
|
||||
|
@ -150,7 +150,7 @@ public:
|
||||
NS_IMETHOD GetHTMLAttribute(nsIAtom* aAttribute, nsHTMLValue& aValue) const;
|
||||
NS_IMETHOD GetID(nsIAtom*& aResult) const;
|
||||
NS_IMETHOD GetClasses(nsVoidArray& aArray) const;
|
||||
NS_IMETHOD HasClass(nsIAtom* aClass) const;
|
||||
NS_IMETHOD HasClass(nsIAtom* aClass, PRBool aCaseSensitive) const;
|
||||
NS_IMETHOD WalkContentStyleRules(nsIRuleWalker* aRuleWalker);
|
||||
NS_IMETHOD WalkInlineStyleRules(nsIRuleWalker* aRuleWalker);
|
||||
NS_IMETHOD GetBaseURL(nsIURI*& aBaseURL) const;
|
||||
|
@ -1638,15 +1638,7 @@ void CSSParserImpl::ParseClassSelector(PRInt32& aDataMask,
|
||||
}
|
||||
aDataMask |= SEL_MASK_CLASS;
|
||||
|
||||
if (mNavQuirkMode) {
|
||||
// in quirks mode, we uppercase the class attribute and classes in CSS.
|
||||
// (see also nsHTMLAttributes.cpp)
|
||||
nsAutoString buffer;
|
||||
mToken.mIdent.ToUpperCase(buffer);
|
||||
aSelector.AddClass(buffer);
|
||||
} else {
|
||||
aSelector.AddClass(mToken.mIdent);
|
||||
}
|
||||
aSelector.AddClass(mToken.mIdent);
|
||||
|
||||
aParsingStatus = SELECTOR_PARSING_ENDED_OK;
|
||||
}
|
||||
|
@ -83,6 +83,24 @@
|
||||
|
||||
//#define DEBUG_RULES
|
||||
//#define EVENT_DEBUG
|
||||
//#define DEBUG_HASH
|
||||
|
||||
#ifdef DEBUG_HASH
|
||||
static void DebugHashCount(PRBool hash) {
|
||||
static gCountHash = 0;
|
||||
static gCountCompStr = 0;
|
||||
if (hash) {
|
||||
if (++gCountHash % 100 == 0) {
|
||||
printf("gCountHash = %ld\n", gCountHash);
|
||||
}
|
||||
}
|
||||
else {
|
||||
if (++gCountCompStr % 100 == 0) {
|
||||
printf("gCountCompStr = %ld\n", gCountCompStr);
|
||||
}
|
||||
}
|
||||
}
|
||||
#endif //DEBUG_HASH
|
||||
|
||||
|
||||
// ----------------------
|
||||
@ -97,7 +115,9 @@ class AtomKey_base : public nsHashKey {
|
||||
public:
|
||||
virtual PRUint32 HashCode(void) const;
|
||||
virtual PRBool Equals(const nsHashKey *aKey) const;
|
||||
virtual void SetKeyCaseSensitive(PRBool aCaseSensitive);
|
||||
nsIAtom* mAtom;
|
||||
PRBool mCaseSensitive;
|
||||
};
|
||||
|
||||
class AtomKey : public AtomKey_base {
|
||||
@ -108,11 +128,13 @@ public:
|
||||
virtual nsHashKey *Clone(void) const;
|
||||
};
|
||||
|
||||
|
||||
class DependentAtomKey : public AtomKey_base {
|
||||
public:
|
||||
DependentAtomKey(nsIAtom* aAtom)
|
||||
{
|
||||
mAtom = aAtom;
|
||||
SetKeyCaseSensitive(PR_TRUE);
|
||||
}
|
||||
DependentAtomKey(const DependentAtomKey& aKey);
|
||||
virtual ~DependentAtomKey(void)
|
||||
@ -121,26 +143,60 @@ public:
|
||||
virtual nsHashKey *Clone(void) const;
|
||||
};
|
||||
|
||||
void AtomKey_base::SetKeyCaseSensitive(PRBool aCaseSensitive)
|
||||
{
|
||||
mCaseSensitive = aCaseSensitive;
|
||||
}
|
||||
|
||||
PRUint32 AtomKey_base::HashCode(void) const
|
||||
{
|
||||
return NS_PTR_TO_INT32(mAtom);
|
||||
if (mCaseSensitive) {
|
||||
return NS_PTR_TO_INT32(mAtom);
|
||||
}
|
||||
else {
|
||||
#ifdef DEBUG_HASH
|
||||
DebugHashCount(PR_TRUE);
|
||||
#endif
|
||||
nsAutoString myStr;
|
||||
mAtom->ToString(myStr);
|
||||
myStr.ToUpperCase();
|
||||
return nsCRT::HashCode(myStr.get());
|
||||
}
|
||||
}
|
||||
|
||||
PRBool AtomKey_base::Equals(const nsHashKey* aKey) const
|
||||
{
|
||||
return PRBool (((AtomKey_base*)aKey)->mAtom == mAtom);
|
||||
if (mCaseSensitive) {
|
||||
return PRBool (((AtomKey_base*)aKey)->mAtom == mAtom);
|
||||
}
|
||||
|
||||
#ifdef DEBUG_HASH
|
||||
DebugHashCount(PR_FALSE);
|
||||
#endif
|
||||
const PRUnichar *myStr = nsnull;
|
||||
mAtom->GetUnicode(&myStr);
|
||||
|
||||
nsIAtom* theirAtom = ((AtomKey_base*)aKey)->mAtom;
|
||||
|
||||
const PRUnichar *theirStr = nsnull;
|
||||
theirAtom->GetUnicode(&theirStr);
|
||||
|
||||
return nsCRT::strcasecmp(myStr, theirStr) == 0;
|
||||
}
|
||||
|
||||
|
||||
AtomKey::AtomKey(nsIAtom* aAtom)
|
||||
{
|
||||
mAtom = aAtom;
|
||||
NS_ADDREF(mAtom);
|
||||
SetKeyCaseSensitive(PR_TRUE);
|
||||
}
|
||||
|
||||
AtomKey::AtomKey(const AtomKey_base& aKey)
|
||||
{
|
||||
mAtom = aKey.mAtom;
|
||||
NS_ADDREF(mAtom);
|
||||
SetKeyCaseSensitive(PR_TRUE);
|
||||
}
|
||||
|
||||
AtomKey::~AtomKey(void)
|
||||
@ -158,6 +214,7 @@ DependentAtomKey::DependentAtomKey(const DependentAtomKey& aKey)
|
||||
{
|
||||
NS_NOTREACHED("Should never clone to a dependent atom key.");
|
||||
mAtom = aKey.mAtom;
|
||||
SetKeyCaseSensitive(PR_TRUE);
|
||||
}
|
||||
|
||||
nsHashKey* DependentAtomKey::Clone(void) const
|
||||
@ -248,9 +305,10 @@ public:
|
||||
RuleEnumFunc aFunc, void* aData);
|
||||
void EnumerateTagRules(nsIAtom* aTag,
|
||||
RuleEnumFunc aFunc, void* aData);
|
||||
void SetCaseSensitive(PRBool aCaseSensitive) {mCaseSensitive = aCaseSensitive;};
|
||||
|
||||
protected:
|
||||
void AppendRuleToTable(nsHashtable& aTable, nsIAtom* aAtom, nsICSSStyleRule* aRule);
|
||||
void AppendRuleToTable(nsHashtable& aTable, nsIAtom* aAtom, nsICSSStyleRule* aRule, PRBool aCaseSensitive = PR_TRUE);
|
||||
void AppendRuleToTable(nsHashtable& aTable, PRInt32 aNameSpace, nsICSSStyleRule* aRule);
|
||||
|
||||
PRInt32 mRuleCount;
|
||||
@ -262,6 +320,7 @@ protected:
|
||||
RuleValue** mEnumList;
|
||||
PRInt32 mEnumListSize;
|
||||
RuleValue mEndValue;
|
||||
PRBool mCaseSensitive;
|
||||
|
||||
#ifdef RULE_HASH_STATS
|
||||
PRUint32 mUniversalSelectors;
|
||||
@ -287,7 +346,8 @@ RuleHash::RuleHash(void)
|
||||
: mRuleCount(0),
|
||||
mIdTable(), mClassTable(), mTagTable(), mNameSpaceTable(),
|
||||
mEnumList(nsnull), mEnumListSize(0),
|
||||
mEndValue(nsnull, -1)
|
||||
mEndValue(nsnull, -1),
|
||||
mCaseSensitive(PR_TRUE)
|
||||
#ifdef RULE_HASH_STATS
|
||||
,
|
||||
mUniversalSelectors(0),
|
||||
@ -357,11 +417,12 @@ RuleHash::~RuleHash(void)
|
||||
}
|
||||
}
|
||||
|
||||
void RuleHash::AppendRuleToTable(nsHashtable& aTable, nsIAtom* aAtom, nsICSSStyleRule* aRule)
|
||||
void RuleHash::AppendRuleToTable(nsHashtable& aTable, nsIAtom* aAtom, nsICSSStyleRule* aRule, PRBool aCaseSensitive)
|
||||
{
|
||||
NS_ASSERTION(nsnull != aAtom, "null hash key");
|
||||
|
||||
DependentAtomKey key(aAtom);
|
||||
key.SetKeyCaseSensitive(aCaseSensitive);
|
||||
RuleValue* value = (RuleValue*)aTable.Get(&key);
|
||||
|
||||
if (nsnull == value) {
|
||||
@ -403,13 +464,13 @@ void RuleHash::AppendRule(nsICSSStyleRule* aRule)
|
||||
{
|
||||
nsCSSSelector* selector = aRule->FirstSelector();
|
||||
if (nsnull != selector->mIDList) {
|
||||
AppendRuleToTable(mIdTable, selector->mIDList->mAtom, aRule);
|
||||
AppendRuleToTable(mIdTable, selector->mIDList->mAtom, aRule, mCaseSensitive);
|
||||
#ifdef RULE_HASH_STATS
|
||||
++mIdSelectors;
|
||||
#endif
|
||||
}
|
||||
else if (nsnull != selector->mClassList) {
|
||||
AppendRuleToTable(mClassTable, selector->mClassList->mAtom, aRule);
|
||||
AppendRuleToTable(mClassTable, selector->mClassList->mAtom, aRule, mCaseSensitive);
|
||||
#ifdef RULE_HASH_STATS
|
||||
++mClassSelectors;
|
||||
#endif
|
||||
@ -507,6 +568,7 @@ void RuleHash::EnumerateAllRules(PRInt32 aNameSpace, nsIAtom* aTag,
|
||||
}
|
||||
if (nsnull != aID) {
|
||||
DependentAtomKey idKey(aID);
|
||||
idKey.SetKeyCaseSensitive(mCaseSensitive);
|
||||
RuleValue* value = (RuleValue*)mIdTable.Get(&idKey);
|
||||
if (nsnull != value) {
|
||||
mEnumList[valueCount++] = value;
|
||||
@ -521,6 +583,7 @@ void RuleHash::EnumerateAllRules(PRInt32 aNameSpace, nsIAtom* aTag,
|
||||
for (index = 0; index < classCount; index++) {
|
||||
nsIAtom* classAtom = (nsIAtom*)aClassList.ElementAt(index);
|
||||
DependentAtomKey classKey(classAtom);
|
||||
classKey.SetKeyCaseSensitive(mCaseSensitive);
|
||||
RuleValue* value = (RuleValue*)mClassTable.Get(&classKey);
|
||||
if (nsnull != value) {
|
||||
mEnumList[valueCount++] = value;
|
||||
@ -648,7 +711,7 @@ public:
|
||||
virtual void SizeOf(nsISizeOfHandler *aSizeofHandler, PRUint32 &aSize);
|
||||
|
||||
protected:
|
||||
RuleCascadeData* GetRuleCascade(nsIAtom* aMedium);
|
||||
RuleCascadeData* GetRuleCascade(nsIPresContext* aPresContext, nsIAtom* aMedium);
|
||||
|
||||
static PRBool CascadeSheetRulesInto(nsISupports* aSheet, void* aData);
|
||||
|
||||
@ -3635,6 +3698,7 @@ static PRBool SelectorMatches(SelectorMatchesData &data,
|
||||
((nsnull != aSelector->mIDList) || (nsnull != aSelector->mClassList))) { // test for ID & class match
|
||||
result = localFalse;
|
||||
if (data.mStyledContent) {
|
||||
PRBool isCaseSensitive = !data.mIsQuirkMode; // bug 93371
|
||||
nsAtomList* IDList = aSelector->mIDList;
|
||||
if (nsnull == IDList) {
|
||||
result = PR_TRUE;
|
||||
@ -3642,7 +3706,18 @@ static PRBool SelectorMatches(SelectorMatchesData &data,
|
||||
else if (nsnull != data.mContentID) {
|
||||
result = PR_TRUE;
|
||||
while (nsnull != IDList) {
|
||||
if (localTrue == (IDList->mAtom != data.mContentID)) {
|
||||
PRBool dontMatch;
|
||||
if (isCaseSensitive) {
|
||||
dontMatch = (IDList->mAtom != data.mContentID);
|
||||
}
|
||||
else {
|
||||
nsAutoString s1;
|
||||
nsAutoString s2;
|
||||
IDList->mAtom->ToString(s1);
|
||||
data.mContentID->ToString(s2);
|
||||
dontMatch = !s1.EqualsIgnoreCase(s2);
|
||||
}
|
||||
if (localTrue == dontMatch) {
|
||||
result = PR_FALSE;
|
||||
break;
|
||||
}
|
||||
@ -3653,7 +3728,7 @@ static PRBool SelectorMatches(SelectorMatchesData &data,
|
||||
if (result) {
|
||||
nsAtomList* classList = aSelector->mClassList;
|
||||
while (nsnull != classList) {
|
||||
if (localTrue == (NS_COMFALSE == data.mStyledContent->HasClass(classList->mAtom))) {
|
||||
if (localTrue == (NS_COMFALSE == data.mStyledContent->HasClass(classList->mAtom, isCaseSensitive))) {
|
||||
result = PR_FALSE;
|
||||
break;
|
||||
}
|
||||
@ -3828,7 +3903,7 @@ CSSRuleProcessor::RulesMatching(nsIPresContext* aPresContext,
|
||||
NS_PRECONDITION(nsnull != aContent, "null arg");
|
||||
NS_PRECONDITION(nsnull != aRuleWalker, "null arg");
|
||||
|
||||
RuleCascadeData* cascade = GetRuleCascade(aMedium);
|
||||
RuleCascadeData* cascade = GetRuleCascade(aPresContext, aMedium);
|
||||
|
||||
if (cascade) {
|
||||
nsIAtom* idAtom = nsnull;
|
||||
@ -3942,7 +4017,7 @@ CSSRuleProcessor::RulesMatching(nsIPresContext* aPresContext,
|
||||
NS_PRECONDITION(nsnull != aPseudoTag, "null arg");
|
||||
NS_PRECONDITION(nsnull != aRuleWalker, "null arg");
|
||||
|
||||
RuleCascadeData* cascade = GetRuleCascade(aMedium);
|
||||
RuleCascadeData* cascade = GetRuleCascade(aPresContext, aMedium);
|
||||
|
||||
if (cascade) {
|
||||
PseudoEnumData data(aPresContext, aParentContent, aPseudoTag, aComparator, aRuleWalker);
|
||||
@ -3993,7 +4068,7 @@ CSSRuleProcessor::HasStateDependentStyle(nsIPresContext* aPresContext,
|
||||
{
|
||||
PRBool isStateful = PR_FALSE;
|
||||
|
||||
RuleCascadeData* cascade = GetRuleCascade(aMedium);
|
||||
RuleCascadeData* cascade = GetRuleCascade(aPresContext, aMedium);
|
||||
|
||||
if (cascade) {
|
||||
// look up content in state rule list
|
||||
@ -4142,8 +4217,8 @@ void CSSRuleProcessor::SizeOf(nsISizeOfHandler *aSizeOfHandler, PRUint32 &aSize)
|
||||
nsCOMPtr<nsIAtom> tag2 = getter_AddRefs(NS_NewAtom("RuleCascade"));
|
||||
CascadeSizeEnumData data(aSizeOfHandler, uniqueItems, tag2);
|
||||
for (RuleCascadeData *cascadeData = mRuleCascades;
|
||||
cascadeData;
|
||||
cascadeData = cascadeData->mNext) {
|
||||
cascadeData;
|
||||
cascadeData = cascadeData->mNext) {
|
||||
CascadeSizeEnumFunc(cascadeData, &data);
|
||||
}
|
||||
}
|
||||
@ -4353,7 +4428,7 @@ static void PutRulesInList(nsSupportsHashtable* aRuleArrays,
|
||||
}
|
||||
|
||||
RuleCascadeData*
|
||||
CSSRuleProcessor::GetRuleCascade(nsIAtom* aMedium)
|
||||
CSSRuleProcessor::GetRuleCascade(nsIPresContext* aPresContext, nsIAtom* aMedium)
|
||||
{
|
||||
RuleCascadeData **cascadep = &mRuleCascades;
|
||||
RuleCascadeData *cascade;
|
||||
@ -4372,6 +4447,11 @@ CSSRuleProcessor::GetRuleCascade(nsIAtom* aMedium)
|
||||
mSheets->EnumerateForwards(CascadeSheetRulesInto, &data);
|
||||
PutRulesInList(&data.mRuleArrays, cascade->mWeightedRules);
|
||||
|
||||
nsCompatibility quirkMode = eCompatibility_Standard;
|
||||
aPresContext->GetCompatibilityMode(&quirkMode);
|
||||
PRBool isQuirksMode = (eCompatibility_Standard == quirkMode ? PR_FALSE : PR_TRUE);
|
||||
|
||||
cascade->mRuleHash.SetCaseSensitive(!isQuirksMode);
|
||||
cascade->mWeightedRules->EnumerateBackwards(BuildHashEnum, &(cascade->mRuleHash));
|
||||
cascade->mWeightedRules->EnumerateBackwards(BuildStateEnum, &(cascade->mStateSelectors));
|
||||
}
|
||||
|
@ -828,7 +828,7 @@ public:
|
||||
|
||||
NS_IMETHOD GetID(nsIAtom*& aResult) const;
|
||||
NS_IMETHOD GetClasses(nsVoidArray& aArray) const;
|
||||
NS_IMETHOD HasClass(nsIAtom* aClass) const;
|
||||
NS_IMETHOD HasClass(nsIAtom* aClass, PRBool aCaseSensitive) const;
|
||||
|
||||
NS_IMETHOD Clone(nsIHTMLAttributes** aInstancePtrResult) const;
|
||||
|
||||
@ -968,37 +968,11 @@ NS_IMPL_ISUPPORTS1(HTMLAttributesImpl, nsIHTMLAttributes)
|
||||
|
||||
const PRUnichar kNullCh = PRUnichar('\0');
|
||||
|
||||
static void ParseClasses(const nsAReadableString& aClassString, nsClassList& aClassList, nsIHTMLContent* aContent)
|
||||
static void ParseClasses(const nsAReadableString& aClassString, nsClassList& aClassList)
|
||||
{
|
||||
nsAutoString classStr(aClassString); // copy to work buffer
|
||||
classStr.Append(kNullCh); // put an extra null at the end
|
||||
|
||||
// Find out if we're in quirks mode by walking from aContent
|
||||
// to the presContext (null-checking all the way)
|
||||
nsCOMPtr<nsINodeInfo> ni;
|
||||
aContent->GetNodeInfo(*getter_AddRefs(ni));
|
||||
if (ni) {
|
||||
nsCOMPtr<nsIDocument> doc;
|
||||
ni->GetDocument(*getter_AddRefs(doc));
|
||||
if (doc) {
|
||||
nsCOMPtr<nsIPresShell> shell;
|
||||
doc->GetShellAt(0, getter_AddRefs(shell));
|
||||
if (shell) {
|
||||
nsCOMPtr<nsIPresContext> presContext;
|
||||
shell->GetPresContext(getter_AddRefs(presContext));
|
||||
if (presContext) {
|
||||
nsCompatibility mode;
|
||||
presContext->GetCompatibilityMode(&mode);
|
||||
if (mode == eCompatibility_NavQuirks) {
|
||||
// in quirks mode, we uppercase the class attribute and classes in CSS.
|
||||
// (see also nsCSSParser.cpp)
|
||||
classStr.ToUpperCase();
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
PRUnichar* start = (PRUnichar*)(const PRUnichar*)classStr.get();
|
||||
PRUnichar* end = start;
|
||||
|
||||
@ -1163,7 +1137,7 @@ HTMLAttributesImpl::SetAttributeFor(nsIAtom* aAttrName, const nsAReadableString&
|
||||
}
|
||||
else if (nsHTMLAtoms::kClass == aAttrName) {
|
||||
mFirstClass.Reset();
|
||||
ParseClasses(aValue, mFirstClass, aContent);
|
||||
ParseClasses(aValue, mFirstClass);
|
||||
}
|
||||
|
||||
PRBool haveAttr;
|
||||
@ -1226,7 +1200,7 @@ HTMLAttributesImpl::SetAttributeFor(nsIAtom* aAttrName,
|
||||
if (eHTMLUnit_String == aValue.GetUnit()) {
|
||||
nsAutoString buffer;
|
||||
aValue.GetStringValue(buffer);
|
||||
ParseClasses(buffer, mFirstClass, aContent);
|
||||
ParseClasses(buffer, mFirstClass);
|
||||
}
|
||||
}
|
||||
|
||||
@ -1399,12 +1373,27 @@ HTMLAttributesImpl::GetClasses(nsVoidArray& aArray) const
|
||||
}
|
||||
|
||||
NS_IMETHODIMP
|
||||
HTMLAttributesImpl::HasClass(nsIAtom* aClass) const
|
||||
HTMLAttributesImpl::HasClass(nsIAtom* aClass, PRBool aCaseSensitive) const
|
||||
{
|
||||
const nsClassList* classList = &mFirstClass;
|
||||
while (classList) {
|
||||
if (classList->mAtom == aClass) {
|
||||
return NS_OK;
|
||||
if (aCaseSensitive) {
|
||||
if (classList->mAtom == aClass) {
|
||||
return NS_OK;
|
||||
}
|
||||
}
|
||||
else {
|
||||
nsAutoString s1;
|
||||
nsAutoString s2;
|
||||
if (classList->mAtom) {
|
||||
classList->mAtom->ToString(s1);
|
||||
}
|
||||
if (aClass) {
|
||||
aClass->ToString(s2);
|
||||
}
|
||||
if (s1.EqualsIgnoreCase(s2)) {
|
||||
return NS_OK;
|
||||
}
|
||||
}
|
||||
classList = classList->mNext;
|
||||
}
|
||||
|
@ -73,7 +73,7 @@ public:
|
||||
|
||||
NS_IMETHOD GetID(nsIAtom*& aResult) const = 0;
|
||||
NS_IMETHOD GetClasses(nsVoidArray& aArray) const = 0;
|
||||
NS_IMETHOD HasClass(nsIAtom* aClass) const = 0;
|
||||
NS_IMETHOD HasClass(nsIAtom* aClass, PRBool aCaseSensitive) const = 0;
|
||||
|
||||
NS_IMETHOD Clone(nsIHTMLAttributes** aInstancePtrResult) const = 0;
|
||||
|
||||
|
@ -4273,7 +4273,7 @@ nsXULElement::GetClasses(nsVoidArray& aArray) const
|
||||
}
|
||||
|
||||
NS_IMETHODIMP
|
||||
nsXULElement::HasClass(nsIAtom* aClass) const
|
||||
nsXULElement::HasClass(nsIAtom* aClass, PRBool /*aCaseSensitive*/) const
|
||||
{
|
||||
nsresult rv = NS_ERROR_NULL_POINTER;
|
||||
if (Attributes()) {
|
||||
|
@ -417,7 +417,7 @@ public:
|
||||
// nsIStyledContent
|
||||
NS_IMETHOD GetID(nsIAtom*& aResult) const;
|
||||
NS_IMETHOD GetClasses(nsVoidArray& aArray) const;
|
||||
NS_IMETHOD HasClass(nsIAtom* aClass) const;
|
||||
NS_IMETHOD HasClass(nsIAtom* aClass, PRBool aCaseSensitive) const;
|
||||
|
||||
NS_IMETHOD WalkContentStyleRules(nsIRuleWalker* aRuleWalker);
|
||||
NS_IMETHOD WalkInlineStyleRules(nsIRuleWalker* aRuleWalker);
|
||||
|
@ -1638,15 +1638,7 @@ void CSSParserImpl::ParseClassSelector(PRInt32& aDataMask,
|
||||
}
|
||||
aDataMask |= SEL_MASK_CLASS;
|
||||
|
||||
if (mNavQuirkMode) {
|
||||
// in quirks mode, we uppercase the class attribute and classes in CSS.
|
||||
// (see also nsHTMLAttributes.cpp)
|
||||
nsAutoString buffer;
|
||||
mToken.mIdent.ToUpperCase(buffer);
|
||||
aSelector.AddClass(buffer);
|
||||
} else {
|
||||
aSelector.AddClass(mToken.mIdent);
|
||||
}
|
||||
aSelector.AddClass(mToken.mIdent);
|
||||
|
||||
aParsingStatus = SELECTOR_PARSING_ENDED_OK;
|
||||
}
|
||||
|
@ -83,6 +83,24 @@
|
||||
|
||||
//#define DEBUG_RULES
|
||||
//#define EVENT_DEBUG
|
||||
//#define DEBUG_HASH
|
||||
|
||||
#ifdef DEBUG_HASH
|
||||
static void DebugHashCount(PRBool hash) {
|
||||
static gCountHash = 0;
|
||||
static gCountCompStr = 0;
|
||||
if (hash) {
|
||||
if (++gCountHash % 100 == 0) {
|
||||
printf("gCountHash = %ld\n", gCountHash);
|
||||
}
|
||||
}
|
||||
else {
|
||||
if (++gCountCompStr % 100 == 0) {
|
||||
printf("gCountCompStr = %ld\n", gCountCompStr);
|
||||
}
|
||||
}
|
||||
}
|
||||
#endif //DEBUG_HASH
|
||||
|
||||
|
||||
// ----------------------
|
||||
@ -97,7 +115,9 @@ class AtomKey_base : public nsHashKey {
|
||||
public:
|
||||
virtual PRUint32 HashCode(void) const;
|
||||
virtual PRBool Equals(const nsHashKey *aKey) const;
|
||||
virtual void SetKeyCaseSensitive(PRBool aCaseSensitive);
|
||||
nsIAtom* mAtom;
|
||||
PRBool mCaseSensitive;
|
||||
};
|
||||
|
||||
class AtomKey : public AtomKey_base {
|
||||
@ -108,11 +128,13 @@ public:
|
||||
virtual nsHashKey *Clone(void) const;
|
||||
};
|
||||
|
||||
|
||||
class DependentAtomKey : public AtomKey_base {
|
||||
public:
|
||||
DependentAtomKey(nsIAtom* aAtom)
|
||||
{
|
||||
mAtom = aAtom;
|
||||
SetKeyCaseSensitive(PR_TRUE);
|
||||
}
|
||||
DependentAtomKey(const DependentAtomKey& aKey);
|
||||
virtual ~DependentAtomKey(void)
|
||||
@ -121,26 +143,60 @@ public:
|
||||
virtual nsHashKey *Clone(void) const;
|
||||
};
|
||||
|
||||
void AtomKey_base::SetKeyCaseSensitive(PRBool aCaseSensitive)
|
||||
{
|
||||
mCaseSensitive = aCaseSensitive;
|
||||
}
|
||||
|
||||
PRUint32 AtomKey_base::HashCode(void) const
|
||||
{
|
||||
return NS_PTR_TO_INT32(mAtom);
|
||||
if (mCaseSensitive) {
|
||||
return NS_PTR_TO_INT32(mAtom);
|
||||
}
|
||||
else {
|
||||
#ifdef DEBUG_HASH
|
||||
DebugHashCount(PR_TRUE);
|
||||
#endif
|
||||
nsAutoString myStr;
|
||||
mAtom->ToString(myStr);
|
||||
myStr.ToUpperCase();
|
||||
return nsCRT::HashCode(myStr.get());
|
||||
}
|
||||
}
|
||||
|
||||
PRBool AtomKey_base::Equals(const nsHashKey* aKey) const
|
||||
{
|
||||
return PRBool (((AtomKey_base*)aKey)->mAtom == mAtom);
|
||||
if (mCaseSensitive) {
|
||||
return PRBool (((AtomKey_base*)aKey)->mAtom == mAtom);
|
||||
}
|
||||
|
||||
#ifdef DEBUG_HASH
|
||||
DebugHashCount(PR_FALSE);
|
||||
#endif
|
||||
const PRUnichar *myStr = nsnull;
|
||||
mAtom->GetUnicode(&myStr);
|
||||
|
||||
nsIAtom* theirAtom = ((AtomKey_base*)aKey)->mAtom;
|
||||
|
||||
const PRUnichar *theirStr = nsnull;
|
||||
theirAtom->GetUnicode(&theirStr);
|
||||
|
||||
return nsCRT::strcasecmp(myStr, theirStr) == 0;
|
||||
}
|
||||
|
||||
|
||||
AtomKey::AtomKey(nsIAtom* aAtom)
|
||||
{
|
||||
mAtom = aAtom;
|
||||
NS_ADDREF(mAtom);
|
||||
SetKeyCaseSensitive(PR_TRUE);
|
||||
}
|
||||
|
||||
AtomKey::AtomKey(const AtomKey_base& aKey)
|
||||
{
|
||||
mAtom = aKey.mAtom;
|
||||
NS_ADDREF(mAtom);
|
||||
SetKeyCaseSensitive(PR_TRUE);
|
||||
}
|
||||
|
||||
AtomKey::~AtomKey(void)
|
||||
@ -158,6 +214,7 @@ DependentAtomKey::DependentAtomKey(const DependentAtomKey& aKey)
|
||||
{
|
||||
NS_NOTREACHED("Should never clone to a dependent atom key.");
|
||||
mAtom = aKey.mAtom;
|
||||
SetKeyCaseSensitive(PR_TRUE);
|
||||
}
|
||||
|
||||
nsHashKey* DependentAtomKey::Clone(void) const
|
||||
@ -248,9 +305,10 @@ public:
|
||||
RuleEnumFunc aFunc, void* aData);
|
||||
void EnumerateTagRules(nsIAtom* aTag,
|
||||
RuleEnumFunc aFunc, void* aData);
|
||||
void SetCaseSensitive(PRBool aCaseSensitive) {mCaseSensitive = aCaseSensitive;};
|
||||
|
||||
protected:
|
||||
void AppendRuleToTable(nsHashtable& aTable, nsIAtom* aAtom, nsICSSStyleRule* aRule);
|
||||
void AppendRuleToTable(nsHashtable& aTable, nsIAtom* aAtom, nsICSSStyleRule* aRule, PRBool aCaseSensitive = PR_TRUE);
|
||||
void AppendRuleToTable(nsHashtable& aTable, PRInt32 aNameSpace, nsICSSStyleRule* aRule);
|
||||
|
||||
PRInt32 mRuleCount;
|
||||
@ -262,6 +320,7 @@ protected:
|
||||
RuleValue** mEnumList;
|
||||
PRInt32 mEnumListSize;
|
||||
RuleValue mEndValue;
|
||||
PRBool mCaseSensitive;
|
||||
|
||||
#ifdef RULE_HASH_STATS
|
||||
PRUint32 mUniversalSelectors;
|
||||
@ -287,7 +346,8 @@ RuleHash::RuleHash(void)
|
||||
: mRuleCount(0),
|
||||
mIdTable(), mClassTable(), mTagTable(), mNameSpaceTable(),
|
||||
mEnumList(nsnull), mEnumListSize(0),
|
||||
mEndValue(nsnull, -1)
|
||||
mEndValue(nsnull, -1),
|
||||
mCaseSensitive(PR_TRUE)
|
||||
#ifdef RULE_HASH_STATS
|
||||
,
|
||||
mUniversalSelectors(0),
|
||||
@ -357,11 +417,12 @@ RuleHash::~RuleHash(void)
|
||||
}
|
||||
}
|
||||
|
||||
void RuleHash::AppendRuleToTable(nsHashtable& aTable, nsIAtom* aAtom, nsICSSStyleRule* aRule)
|
||||
void RuleHash::AppendRuleToTable(nsHashtable& aTable, nsIAtom* aAtom, nsICSSStyleRule* aRule, PRBool aCaseSensitive)
|
||||
{
|
||||
NS_ASSERTION(nsnull != aAtom, "null hash key");
|
||||
|
||||
DependentAtomKey key(aAtom);
|
||||
key.SetKeyCaseSensitive(aCaseSensitive);
|
||||
RuleValue* value = (RuleValue*)aTable.Get(&key);
|
||||
|
||||
if (nsnull == value) {
|
||||
@ -403,13 +464,13 @@ void RuleHash::AppendRule(nsICSSStyleRule* aRule)
|
||||
{
|
||||
nsCSSSelector* selector = aRule->FirstSelector();
|
||||
if (nsnull != selector->mIDList) {
|
||||
AppendRuleToTable(mIdTable, selector->mIDList->mAtom, aRule);
|
||||
AppendRuleToTable(mIdTable, selector->mIDList->mAtom, aRule, mCaseSensitive);
|
||||
#ifdef RULE_HASH_STATS
|
||||
++mIdSelectors;
|
||||
#endif
|
||||
}
|
||||
else if (nsnull != selector->mClassList) {
|
||||
AppendRuleToTable(mClassTable, selector->mClassList->mAtom, aRule);
|
||||
AppendRuleToTable(mClassTable, selector->mClassList->mAtom, aRule, mCaseSensitive);
|
||||
#ifdef RULE_HASH_STATS
|
||||
++mClassSelectors;
|
||||
#endif
|
||||
@ -507,6 +568,7 @@ void RuleHash::EnumerateAllRules(PRInt32 aNameSpace, nsIAtom* aTag,
|
||||
}
|
||||
if (nsnull != aID) {
|
||||
DependentAtomKey idKey(aID);
|
||||
idKey.SetKeyCaseSensitive(mCaseSensitive);
|
||||
RuleValue* value = (RuleValue*)mIdTable.Get(&idKey);
|
||||
if (nsnull != value) {
|
||||
mEnumList[valueCount++] = value;
|
||||
@ -521,6 +583,7 @@ void RuleHash::EnumerateAllRules(PRInt32 aNameSpace, nsIAtom* aTag,
|
||||
for (index = 0; index < classCount; index++) {
|
||||
nsIAtom* classAtom = (nsIAtom*)aClassList.ElementAt(index);
|
||||
DependentAtomKey classKey(classAtom);
|
||||
classKey.SetKeyCaseSensitive(mCaseSensitive);
|
||||
RuleValue* value = (RuleValue*)mClassTable.Get(&classKey);
|
||||
if (nsnull != value) {
|
||||
mEnumList[valueCount++] = value;
|
||||
@ -648,7 +711,7 @@ public:
|
||||
virtual void SizeOf(nsISizeOfHandler *aSizeofHandler, PRUint32 &aSize);
|
||||
|
||||
protected:
|
||||
RuleCascadeData* GetRuleCascade(nsIAtom* aMedium);
|
||||
RuleCascadeData* GetRuleCascade(nsIPresContext* aPresContext, nsIAtom* aMedium);
|
||||
|
||||
static PRBool CascadeSheetRulesInto(nsISupports* aSheet, void* aData);
|
||||
|
||||
@ -3635,6 +3698,7 @@ static PRBool SelectorMatches(SelectorMatchesData &data,
|
||||
((nsnull != aSelector->mIDList) || (nsnull != aSelector->mClassList))) { // test for ID & class match
|
||||
result = localFalse;
|
||||
if (data.mStyledContent) {
|
||||
PRBool isCaseSensitive = !data.mIsQuirkMode; // bug 93371
|
||||
nsAtomList* IDList = aSelector->mIDList;
|
||||
if (nsnull == IDList) {
|
||||
result = PR_TRUE;
|
||||
@ -3642,7 +3706,18 @@ static PRBool SelectorMatches(SelectorMatchesData &data,
|
||||
else if (nsnull != data.mContentID) {
|
||||
result = PR_TRUE;
|
||||
while (nsnull != IDList) {
|
||||
if (localTrue == (IDList->mAtom != data.mContentID)) {
|
||||
PRBool dontMatch;
|
||||
if (isCaseSensitive) {
|
||||
dontMatch = (IDList->mAtom != data.mContentID);
|
||||
}
|
||||
else {
|
||||
nsAutoString s1;
|
||||
nsAutoString s2;
|
||||
IDList->mAtom->ToString(s1);
|
||||
data.mContentID->ToString(s2);
|
||||
dontMatch = !s1.EqualsIgnoreCase(s2);
|
||||
}
|
||||
if (localTrue == dontMatch) {
|
||||
result = PR_FALSE;
|
||||
break;
|
||||
}
|
||||
@ -3653,7 +3728,7 @@ static PRBool SelectorMatches(SelectorMatchesData &data,
|
||||
if (result) {
|
||||
nsAtomList* classList = aSelector->mClassList;
|
||||
while (nsnull != classList) {
|
||||
if (localTrue == (NS_COMFALSE == data.mStyledContent->HasClass(classList->mAtom))) {
|
||||
if (localTrue == (NS_COMFALSE == data.mStyledContent->HasClass(classList->mAtom, isCaseSensitive))) {
|
||||
result = PR_FALSE;
|
||||
break;
|
||||
}
|
||||
@ -3828,7 +3903,7 @@ CSSRuleProcessor::RulesMatching(nsIPresContext* aPresContext,
|
||||
NS_PRECONDITION(nsnull != aContent, "null arg");
|
||||
NS_PRECONDITION(nsnull != aRuleWalker, "null arg");
|
||||
|
||||
RuleCascadeData* cascade = GetRuleCascade(aMedium);
|
||||
RuleCascadeData* cascade = GetRuleCascade(aPresContext, aMedium);
|
||||
|
||||
if (cascade) {
|
||||
nsIAtom* idAtom = nsnull;
|
||||
@ -3942,7 +4017,7 @@ CSSRuleProcessor::RulesMatching(nsIPresContext* aPresContext,
|
||||
NS_PRECONDITION(nsnull != aPseudoTag, "null arg");
|
||||
NS_PRECONDITION(nsnull != aRuleWalker, "null arg");
|
||||
|
||||
RuleCascadeData* cascade = GetRuleCascade(aMedium);
|
||||
RuleCascadeData* cascade = GetRuleCascade(aPresContext, aMedium);
|
||||
|
||||
if (cascade) {
|
||||
PseudoEnumData data(aPresContext, aParentContent, aPseudoTag, aComparator, aRuleWalker);
|
||||
@ -3993,7 +4068,7 @@ CSSRuleProcessor::HasStateDependentStyle(nsIPresContext* aPresContext,
|
||||
{
|
||||
PRBool isStateful = PR_FALSE;
|
||||
|
||||
RuleCascadeData* cascade = GetRuleCascade(aMedium);
|
||||
RuleCascadeData* cascade = GetRuleCascade(aPresContext, aMedium);
|
||||
|
||||
if (cascade) {
|
||||
// look up content in state rule list
|
||||
@ -4142,8 +4217,8 @@ void CSSRuleProcessor::SizeOf(nsISizeOfHandler *aSizeOfHandler, PRUint32 &aSize)
|
||||
nsCOMPtr<nsIAtom> tag2 = getter_AddRefs(NS_NewAtom("RuleCascade"));
|
||||
CascadeSizeEnumData data(aSizeOfHandler, uniqueItems, tag2);
|
||||
for (RuleCascadeData *cascadeData = mRuleCascades;
|
||||
cascadeData;
|
||||
cascadeData = cascadeData->mNext) {
|
||||
cascadeData;
|
||||
cascadeData = cascadeData->mNext) {
|
||||
CascadeSizeEnumFunc(cascadeData, &data);
|
||||
}
|
||||
}
|
||||
@ -4353,7 +4428,7 @@ static void PutRulesInList(nsSupportsHashtable* aRuleArrays,
|
||||
}
|
||||
|
||||
RuleCascadeData*
|
||||
CSSRuleProcessor::GetRuleCascade(nsIAtom* aMedium)
|
||||
CSSRuleProcessor::GetRuleCascade(nsIPresContext* aPresContext, nsIAtom* aMedium)
|
||||
{
|
||||
RuleCascadeData **cascadep = &mRuleCascades;
|
||||
RuleCascadeData *cascade;
|
||||
@ -4372,6 +4447,11 @@ CSSRuleProcessor::GetRuleCascade(nsIAtom* aMedium)
|
||||
mSheets->EnumerateForwards(CascadeSheetRulesInto, &data);
|
||||
PutRulesInList(&data.mRuleArrays, cascade->mWeightedRules);
|
||||
|
||||
nsCompatibility quirkMode = eCompatibility_Standard;
|
||||
aPresContext->GetCompatibilityMode(&quirkMode);
|
||||
PRBool isQuirksMode = (eCompatibility_Standard == quirkMode ? PR_FALSE : PR_TRUE);
|
||||
|
||||
cascade->mRuleHash.SetCaseSensitive(!isQuirksMode);
|
||||
cascade->mWeightedRules->EnumerateBackwards(BuildHashEnum, &(cascade->mRuleHash));
|
||||
cascade->mWeightedRules->EnumerateBackwards(BuildStateEnum, &(cascade->mStateSelectors));
|
||||
}
|
||||
|
Loading…
x
Reference in New Issue
Block a user