Bug 525608 part 4. Change pseudo-element probing and resolution to not use EnumerateTagRules. r=dbaron

This commit is contained in:
Boris Zbarsky 2009-12-11 02:37:40 -05:00
Родитель db9b2aaefe
Коммит cfac13a4b6
11 изменённых файлов: 199 добавлений и 68 удалений

Просмотреть файл

@ -69,6 +69,7 @@
#include "nsDOMError.h" #include "nsDOMError.h"
#include "nsRuleWalker.h" #include "nsRuleWalker.h"
#include "nsCSSPseudoClasses.h" #include "nsCSSPseudoClasses.h"
#include "nsCSSPseudoElements.h"
#include "nsIContent.h" #include "nsIContent.h"
#include "nsCOMPtr.h" #include "nsCOMPtr.h"
#include "nsHashKeys.h" #include "nsHashKeys.h"
@ -363,7 +364,7 @@ public:
void PrependRule(RuleValue *aRuleInfo); void PrependRule(RuleValue *aRuleInfo);
void EnumerateAllRules(PRInt32 aNameSpace, nsIAtom* aTag, nsIAtom* aID, void EnumerateAllRules(PRInt32 aNameSpace, nsIAtom* aTag, nsIAtom* aID,
const nsAttrValue* aClassList, const nsAttrValue* aClassList,
RuleEnumFunc aFunc, void* aData); RuleEnumFunc aFunc, RuleProcessorData* aData);
void EnumerateTagRules(nsIAtom* aTag, void EnumerateTagRules(nsIAtom* aTag,
RuleEnumFunc aFunc, void* aData); RuleEnumFunc aFunc, void* aData);
PLArenaPool& Arena() { return mArena; } PLArenaPool& Arena() { return mArena; }
@ -428,6 +429,7 @@ RuleHash::RuleHash(PRBool aQuirksMode)
mPseudoTagCalls(0) mPseudoTagCalls(0)
#endif #endif
{ {
MOZ_COUNT_CTOR(RuleHash);
// Initialize our arena // Initialize our arena
PL_INIT_ARENA_POOL(&mArena, "RuleHashArena", NS_RULEHASH_ARENA_BLOCK_SIZE); PL_INIT_ARENA_POOL(&mArena, "RuleHashArena", NS_RULEHASH_ARENA_BLOCK_SIZE);
@ -447,6 +449,7 @@ RuleHash::RuleHash(PRBool aQuirksMode)
RuleHash::~RuleHash() RuleHash::~RuleHash()
{ {
MOZ_COUNT_DTOR(RuleHash);
#ifdef RULE_HASH_STATS #ifdef RULE_HASH_STATS
printf( printf(
"RuleHash(%p):\n" "RuleHash(%p):\n"
@ -574,7 +577,7 @@ void RuleHash::PrependRule(RuleValue *aRuleInfo)
void RuleHash::EnumerateAllRules(PRInt32 aNameSpace, nsIAtom* aTag, void RuleHash::EnumerateAllRules(PRInt32 aNameSpace, nsIAtom* aTag,
nsIAtom* aID, const nsAttrValue* aClassList, nsIAtom* aID, const nsAttrValue* aClassList,
RuleEnumFunc aFunc, void* aData) RuleEnumFunc aFunc, RuleProcessorData* aData)
{ {
PRInt32 classCount = aClassList ? aClassList->GetAtomCount() : 0; PRInt32 classCount = aClassList ? aClassList->GetAtomCount() : 0;
@ -599,7 +602,7 @@ void RuleHash::EnumerateAllRules(PRInt32 aNameSpace, nsIAtom* aTag,
} }
} }
// universal rules within the namespace // universal rules within the namespace
if (kNameSpaceID_Unknown != aNameSpace) { if (kNameSpaceID_Unknown != aNameSpace && mNameSpaceTable.entryCount) {
RuleHashTableEntry *entry = static_cast<RuleHashTableEntry*> RuleHashTableEntry *entry = static_cast<RuleHashTableEntry*>
(PL_DHashTableOperate(&mNameSpaceTable, NS_INT32_TO_PTR(aNameSpace), (PL_DHashTableOperate(&mNameSpaceTable, NS_INT32_TO_PTR(aNameSpace),
PL_DHASH_LOOKUP)); PL_DHASH_LOOKUP));
@ -609,7 +612,7 @@ void RuleHash::EnumerateAllRules(PRInt32 aNameSpace, nsIAtom* aTag,
RULE_HASH_STAT_INCREMENT_LIST_COUNT(value, mElementNameSpaceCalls); RULE_HASH_STAT_INCREMENT_LIST_COUNT(value, mElementNameSpaceCalls);
} }
} }
if (nsnull != aTag) { if (aTag && mTagTable.entryCount) {
RuleHashTableEntry *entry = static_cast<RuleHashTableEntry*> RuleHashTableEntry *entry = static_cast<RuleHashTableEntry*>
(PL_DHashTableOperate(&mTagTable, aTag, PL_DHASH_LOOKUP)); (PL_DHashTableOperate(&mTagTable, aTag, PL_DHASH_LOOKUP));
if (PL_DHASH_ENTRY_IS_BUSY(entry)) { if (PL_DHASH_ENTRY_IS_BUSY(entry)) {
@ -618,7 +621,7 @@ void RuleHash::EnumerateAllRules(PRInt32 aNameSpace, nsIAtom* aTag,
RULE_HASH_STAT_INCREMENT_LIST_COUNT(value, mElementTagCalls); RULE_HASH_STAT_INCREMENT_LIST_COUNT(value, mElementTagCalls);
} }
} }
if (nsnull != aID) { if (aID && mIdTable.entryCount) {
RuleHashTableEntry *entry = static_cast<RuleHashTableEntry*> RuleHashTableEntry *entry = static_cast<RuleHashTableEntry*>
(PL_DHashTableOperate(&mIdTable, aID, PL_DHASH_LOOKUP)); (PL_DHashTableOperate(&mIdTable, aID, PL_DHASH_LOOKUP));
if (PL_DHASH_ENTRY_IS_BUSY(entry)) { if (PL_DHASH_ENTRY_IS_BUSY(entry)) {
@ -627,7 +630,7 @@ void RuleHash::EnumerateAllRules(PRInt32 aNameSpace, nsIAtom* aTag,
RULE_HASH_STAT_INCREMENT_LIST_COUNT(value, mElementIdCalls); RULE_HASH_STAT_INCREMENT_LIST_COUNT(value, mElementIdCalls);
} }
} }
{ // extra scope to work around compiler bugs with |for| scoping. if (mClassTable.entryCount) {
for (PRInt32 index = 0; index < classCount; ++index) { for (PRInt32 index = 0; index < classCount; ++index) {
RuleHashTableEntry *entry = static_cast<RuleHashTableEntry*> RuleHashTableEntry *entry = static_cast<RuleHashTableEntry*>
(PL_DHashTableOperate(&mClassTable, aClassList->AtomAt(index), (PL_DHashTableOperate(&mClassTable, aClassList->AtomAt(index),
@ -719,17 +722,24 @@ struct RuleCascadeData {
: mRuleHash(aQuirksMode), : mRuleHash(aQuirksMode),
mStateSelectors(), mStateSelectors(),
mCacheKey(aMedium), mCacheKey(aMedium),
mNext(nsnull) mNext(nsnull),
mQuirksMode(aQuirksMode)
{ {
PL_DHashTableInit(&mAttributeSelectors, &AttributeSelectorOps, nsnull, PL_DHashTableInit(&mAttributeSelectors, &AttributeSelectorOps, nsnull,
sizeof(AttributeSelectorEntry), 16); sizeof(AttributeSelectorEntry), 16);
memset(mPseudoElementRuleHashes, 0, sizeof(mPseudoElementRuleHashes));
} }
~RuleCascadeData() ~RuleCascadeData()
{ {
PL_DHashTableFinish(&mAttributeSelectors); PL_DHashTableFinish(&mAttributeSelectors);
for (PRUint32 i = 0; i < NS_ARRAY_LENGTH(mPseudoElementRuleHashes); ++i) {
delete mPseudoElementRuleHashes[i];
}
} }
RuleHash mRuleHash; RuleHash mRuleHash;
RuleHash*
mPseudoElementRuleHashes[nsCSSPseudoElements::ePseudo_PseudoElementCount];
nsTArray<nsCSSSelector*> mStateSelectors; nsTArray<nsCSSSelector*> mStateSelectors;
nsTArray<nsCSSSelector*> mClassSelectors; nsTArray<nsCSSSelector*> mClassSelectors;
nsTArray<nsCSSSelector*> mIDSelectors; nsTArray<nsCSSSelector*> mIDSelectors;
@ -743,6 +753,8 @@ struct RuleCascadeData {
nsMediaQueryResultCacheKey mCacheKey; nsMediaQueryResultCacheKey mCacheKey;
RuleCascadeData* mNext; // for a different medium RuleCascadeData* mNext; // for a different medium
const PRBool mQuirksMode;
}; };
nsTArray<nsCSSSelector*>* nsTArray<nsCSSSelector*>*
@ -2007,7 +2019,7 @@ static PRBool SelectorMatchesTree(RuleProcessorData& aPrevData,
static void ContentEnumFunc(nsICSSStyleRule* aRule, nsCSSSelector* aSelector, static void ContentEnumFunc(nsICSSStyleRule* aRule, nsCSSSelector* aSelector,
void* aData) void* aData)
{ {
ElementRuleProcessorData* data = (ElementRuleProcessorData*)aData; RuleProcessorData* data = (RuleProcessorData*)aData;
if (SelectorMatches(*data, aSelector, 0, PR_TRUE)) { if (SelectorMatches(*data, aSelector, 0, PR_TRUE)) {
nsCSSSelector *next = aSelector->mNext; nsCSSSelector *next = aSelector->mNext;
@ -2045,6 +2057,28 @@ nsCSSRuleProcessor::RulesMatching(ElementRuleProcessorData *aData)
return NS_OK; return NS_OK;
} }
NS_IMETHODIMP
nsCSSRuleProcessor::RulesMatching(PseudoElementRuleProcessorData* aData)
{
NS_PRECONDITION(aData->mContent->IsNodeOfType(nsINode::eELEMENT),
"content must be element");
RuleCascadeData* cascade = GetRuleCascade(aData->mPresContext);
if (cascade) {
RuleHash* ruleHash = cascade->mPseudoElementRuleHashes[aData->mPseudoType];
if (ruleHash) {
ruleHash->EnumerateAllRules(aData->mNameSpaceID,
aData->mContentTag,
aData->mContentID,
aData->mClasses,
ContentEnumFunc,
aData);
}
}
return NS_OK;
}
static void PseudoEnumFunc(nsICSSStyleRule* aRule, nsCSSSelector* aSelector, static void PseudoEnumFunc(nsICSSStyleRule* aRule, nsCSSSelector* aSelector,
void* aData) void* aData)
{ {
@ -2368,7 +2402,25 @@ AddRule(RuleValue* aRuleInfo, void* aCascade)
RuleCascadeData *cascade = static_cast<RuleCascadeData*>(aCascade); RuleCascadeData *cascade = static_cast<RuleCascadeData*>(aCascade);
// Build the rule hash. // Build the rule hash.
cascade->mRuleHash.PrependRule(aRuleInfo); nsCSSPseudoElements::Type pseudoType = aRuleInfo->mSelector->PseudoType();
if (pseudoType < nsCSSPseudoElements::ePseudo_PseudoElementCount) {
RuleHash*& ruleHash = cascade->mPseudoElementRuleHashes[pseudoType];
if (!ruleHash) {
ruleHash = new RuleHash(cascade->mQuirksMode);
if (!ruleHash) {
// Out of memory; give up
return PR_FALSE;
}
}
NS_ASSERTION(aRuleInfo->mSelector->mNext,
"Must have mNext; parser screwed up");
NS_ASSERTION(aRuleInfo->mSelector->mNext->mOperator == '>',
"Unexpected mNext combinator");
aRuleInfo->mSelector = aRuleInfo->mSelector->mNext;
ruleHash->PrependRule(aRuleInfo);
} else {
cascade->mRuleHash.PrependRule(aRuleInfo);
}
nsTArray<nsCSSSelector*>* stateArray = &cascade->mStateSelectors; nsTArray<nsCSSSelector*>* stateArray = &cascade->mStateSelectors;
nsTArray<nsCSSSelector*>* classArray = &cascade->mClassSelectors; nsTArray<nsCSSSelector*>* classArray = &cascade->mClassSelectors;

Просмотреть файл

@ -91,6 +91,8 @@ public:
// nsIStyleRuleProcessor // nsIStyleRuleProcessor
NS_IMETHOD RulesMatching(ElementRuleProcessorData* aData); NS_IMETHOD RulesMatching(ElementRuleProcessorData* aData);
NS_IMETHOD RulesMatching(PseudoElementRuleProcessorData* aData);
NS_IMETHOD RulesMatching(PseudoRuleProcessorData* aData); NS_IMETHOD RulesMatching(PseudoRuleProcessorData* aData);
NS_IMETHOD HasStateDependentStyle(StateRuleProcessorData* aData, NS_IMETHOD HasStateDependentStyle(StateRuleProcessorData* aData,

Просмотреть файл

@ -89,6 +89,8 @@ public:
// nsIStyleRuleProcessor api // nsIStyleRuleProcessor api
NS_IMETHOD RulesMatching(ElementRuleProcessorData* aData); NS_IMETHOD RulesMatching(ElementRuleProcessorData* aData);
NS_IMETHOD RulesMatching(PseudoElementRuleProcessorData* aData);
NS_IMETHOD RulesMatching(PseudoRuleProcessorData* aData); NS_IMETHOD RulesMatching(PseudoRuleProcessorData* aData);
NS_IMETHOD HasStateDependentStyle(StateRuleProcessorData* aData, NS_IMETHOD HasStateDependentStyle(StateRuleProcessorData* aData,
@ -156,6 +158,12 @@ HTMLCSSStyleSheetImpl::RulesMatching(ElementRuleProcessorData* aData)
return NS_OK; return NS_OK;
} }
NS_IMETHODIMP
HTMLCSSStyleSheetImpl::RulesMatching(PseudoElementRuleProcessorData* aData)
{
return NS_OK;
}
NS_IMETHODIMP NS_IMETHODIMP
HTMLCSSStyleSheetImpl::RulesMatching(PseudoRuleProcessorData* aData) HTMLCSSStyleSheetImpl::RulesMatching(PseudoRuleProcessorData* aData)
{ {

Просмотреть файл

@ -562,6 +562,12 @@ nsHTMLStyleSheet::MediumFeaturesChanged(nsPresContext* aPresContext,
} }
NS_IMETHODIMP
nsHTMLStyleSheet::RulesMatching(PseudoElementRuleProcessorData* aData)
{
return NS_OK;
}
NS_IMETHODIMP NS_IMETHODIMP
nsHTMLStyleSheet::RulesMatching(PseudoRuleProcessorData* aData) nsHTMLStyleSheet::RulesMatching(PseudoRuleProcessorData* aData)
{ {

Просмотреть файл

@ -79,6 +79,7 @@ public:
// nsIStyleRuleProcessor API // nsIStyleRuleProcessor API
NS_IMETHOD RulesMatching(ElementRuleProcessorData* aData); NS_IMETHOD RulesMatching(ElementRuleProcessorData* aData);
NS_IMETHOD RulesMatching(PseudoElementRuleProcessorData* aData);
NS_IMETHOD RulesMatching(PseudoRuleProcessorData* aData); NS_IMETHOD RulesMatching(PseudoRuleProcessorData* aData);
NS_IMETHOD HasStateDependentStyle(StateRuleProcessorData* aData, NS_IMETHOD HasStateDependentStyle(StateRuleProcessorData* aData,
nsReStyleHint* aResult); nsReStyleHint* aResult);

Просмотреть файл

@ -51,6 +51,7 @@
struct RuleProcessorData; struct RuleProcessorData;
struct ElementRuleProcessorData; struct ElementRuleProcessorData;
struct PseudoElementRuleProcessorData;
struct PseudoRuleProcessorData; struct PseudoRuleProcessorData;
struct StateRuleProcessorData; struct StateRuleProcessorData;
struct AttributeRuleProcessorData; struct AttributeRuleProcessorData;
@ -89,6 +90,12 @@ public:
* Just like the previous |RulesMatching|, except for a given content * Just like the previous |RulesMatching|, except for a given content
* node <em>and pseudo-element</em>. * node <em>and pseudo-element</em>.
*/ */
NS_IMETHOD RulesMatching(PseudoElementRuleProcessorData* aData) = 0;
/**
* Just like the previous |RulesMatching|, except for a given content
* node <em>and pseudo</em>.
*/
NS_IMETHOD RulesMatching(PseudoRuleProcessorData* aData) = 0; NS_IMETHOD RulesMatching(PseudoRuleProcessorData* aData) = 0;
/** /**

Просмотреть файл

@ -48,6 +48,7 @@
#include "nsString.h" #include "nsString.h"
#include "nsChangeHint.h" #include "nsChangeHint.h"
#include "nsIContent.h" #include "nsIContent.h"
#include "nsCSSPseudoElements.h"
class nsIStyleSheet; class nsIStyleSheet;
class nsPresContext; class nsPresContext;
@ -174,6 +175,24 @@ struct ElementRuleProcessorData : public RuleProcessorData {
} }
}; };
struct PseudoElementRuleProcessorData : public RuleProcessorData {
PseudoElementRuleProcessorData(nsPresContext* aPresContext,
nsIContent* aParentContent,
nsRuleWalker* aRuleWalker,
nsCSSPseudoElements::Type aPseudoType)
: RuleProcessorData(aPresContext, aParentContent, aRuleWalker),
mPseudoType(aPseudoType)
{
NS_PRECONDITION(aPresContext, "null pointer");
NS_PRECONDITION(aPseudoType <
nsCSSPseudoElements::ePseudo_PseudoElementCount,
"null pointer");
NS_PRECONDITION(aRuleWalker, "null pointer");
}
nsCSSPseudoElements::Type mPseudoType;
};
struct PseudoRuleProcessorData : public RuleProcessorData { struct PseudoRuleProcessorData : public RuleProcessorData {
PseudoRuleProcessorData(nsPresContext* aPresContext, PseudoRuleProcessorData(nsPresContext* aPresContext,
nsIContent* aParentContent, nsIContent* aParentContent,

Просмотреть файл

@ -799,17 +799,15 @@ nsStyleSet::ResolveStyleForNonElement(nsStyleContext* aParentContext)
} }
void void
nsStyleSet::WalkRestrictionRule(nsIAtom* aPseudoType, nsStyleSet::WalkRestrictionRule(nsCSSPseudoElements::Type aPseudoType,
nsRuleWalker* aRuleWalker) nsRuleWalker* aRuleWalker)
{ {
// This needs to match GetPseudoRestriction in nsRuleNode.cpp. // This needs to match GetPseudoRestriction in nsRuleNode.cpp.
if (aPseudoType) { aRuleWalker->SetLevel(eAgentSheet, PR_FALSE, PR_FALSE);
aRuleWalker->SetLevel(eAgentSheet, PR_FALSE, PR_FALSE); if (aPseudoType == nsCSSPseudoElements::ePseudo_firstLetter)
if (aPseudoType == nsCSSPseudoElements::firstLetter) aRuleWalker->Forward(mFirstLetterRule);
aRuleWalker->Forward(mFirstLetterRule); else if (aPseudoType == nsCSSPseudoElements::ePseudo_firstLine)
else if (aPseudoType == nsCSSPseudoElements::firstLine) aRuleWalker->Forward(mFirstLineRule);
aRuleWalker->Forward(mFirstLineRule);
}
} }
static PRBool static PRBool
@ -851,7 +849,6 @@ nsStyleSet::ResolvePseudoStyleFor(nsIContent* aParentContent,
nsRuleWalker ruleWalker(mRuleTree); nsRuleWalker ruleWalker(mRuleTree);
PseudoRuleProcessorData data(presContext, aParentContent, aPseudoTag, PseudoRuleProcessorData data(presContext, aParentContent, aPseudoTag,
aComparator, &ruleWalker); aComparator, &ruleWalker);
WalkRestrictionRule(aPseudoTag, &ruleWalker);
FileRules(EnumPseudoRulesMatching, &data, &ruleWalker); FileRules(EnumPseudoRulesMatching, &data, &ruleWalker);
result = GetContext(presContext, aParentContext, result = GetContext(presContext, aParentContext,
@ -862,6 +859,40 @@ nsStyleSet::ResolvePseudoStyleFor(nsIContent* aParentContent,
return result; return result;
} }
static PRBool
EnumPseudoElementRulesMatching(nsIStyleRuleProcessor* aProcessor, void* aData)
{
PseudoElementRuleProcessorData* data =
static_cast<PseudoElementRuleProcessorData*>(aData);
aProcessor->RulesMatching(data);
return PR_TRUE;
}
already_AddRefed<nsStyleContext>
nsStyleSet::ResolvePseudoElementStyle(nsIContent* aParentContent,
nsCSSPseudoElements::Type aType,
nsStyleContext* aParentContext)
{
NS_ENSURE_FALSE(mInShutdown, nsnull);
NS_ASSERTION(aType < nsCSSPseudoElements::ePseudo_PseudoElementCount,
"must have pseudo element type");
NS_ASSERTION(aParentContent &&
aParentContent->IsNodeOfType(nsINode::eELEMENT),
"aParentContent must be element");
nsRuleWalker ruleWalker(mRuleTree);
nsPresContext *presContext = PresContext();
PseudoElementRuleProcessorData data(presContext, aParentContent, &ruleWalker,
aType);
WalkRestrictionRule(aType, &ruleWalker);
FileRules(EnumPseudoElementRulesMatching, &data, &ruleWalker);
return GetContext(presContext, aParentContext, ruleWalker.GetCurrentNode(),
nsCSSPseudoElements::GetPseudoAtom(aType), aType);
}
already_AddRefed<nsStyleContext> already_AddRefed<nsStyleContext>
nsStyleSet::ProbePseudoElementStyle(nsIContent* aParentContent, nsStyleSet::ProbePseudoElementStyle(nsIContent* aParentContent,
nsCSSPseudoElements::Type aType, nsCSSPseudoElements::Type aType,
@ -869,31 +900,32 @@ nsStyleSet::ProbePseudoElementStyle(nsIContent* aParentContent,
{ {
NS_ENSURE_FALSE(mInShutdown, nsnull); NS_ENSURE_FALSE(mInShutdown, nsnull);
nsIAtom* pseudoTag = nsCSSPseudoElements::GetPseudoAtom(aType); NS_ASSERTION(aType < nsCSSPseudoElements::ePseudo_PseudoElementCount,
"must have pseudo element type");
nsStyleContext* result = nsnull;
nsPresContext *presContext = PresContext();
NS_ASSERTION(pseudoTag, "must have pseudo tag");
NS_ASSERTION(aParentContent && NS_ASSERTION(aParentContent &&
aParentContent->IsNodeOfType(nsINode::eELEMENT), aParentContent->IsNodeOfType(nsINode::eELEMENT),
"aParentContent must be element"); "aParentContent must be element");
if (presContext) { nsIAtom* pseudoTag = nsCSSPseudoElements::GetPseudoAtom(aType);
nsRuleWalker ruleWalker(mRuleTree);
PseudoRuleProcessorData data(presContext, aParentContent, pseudoTag,
nsnull, &ruleWalker);
WalkRestrictionRule(pseudoTag, &ruleWalker);
// not the root if there was a restriction rule
nsRuleNode *adjustedRoot = ruleWalker.GetCurrentNode();
FileRules(EnumPseudoRulesMatching, &data, &ruleWalker);
nsRuleNode *ruleNode = ruleWalker.GetCurrentNode(); nsPresContext *presContext = PresContext();
if (ruleNode != adjustedRoot)
result = nsRuleWalker ruleWalker(mRuleTree);
GetContext(presContext, aParentContext, ruleNode, pseudoTag, aType).get(); PseudoElementRuleProcessorData data(presContext, aParentContent, &ruleWalker,
aType);
WalkRestrictionRule(aType, &ruleWalker);
// not the root if there was a restriction rule
nsRuleNode *adjustedRoot = ruleWalker.GetCurrentNode();
FileRules(EnumPseudoElementRulesMatching, &data, &ruleWalker);
nsRuleNode *ruleNode = ruleWalker.GetCurrentNode();
if (ruleNode == adjustedRoot) {
return nsnull;
} }
nsRefPtr<nsStyleContext> result =
GetContext(presContext, aParentContext, ruleNode, pseudoTag, aType);
// For :before and :after pseudo-elements, having display: none or no // For :before and :after pseudo-elements, having display: none or no
// 'content' property is equivalent to not having the pseudo-element // 'content' property is equivalent to not having the pseudo-element
// at all. // at all.
@ -905,12 +937,11 @@ nsStyleSet::ProbePseudoElementStyle(nsIContent* aParentContent,
// XXXldb What is contentCount for |content: ""|? // XXXldb What is contentCount for |content: ""|?
if (display->mDisplay == NS_STYLE_DISPLAY_NONE || if (display->mDisplay == NS_STYLE_DISPLAY_NONE ||
content->ContentCount() == 0) { content->ContentCount() == 0) {
result->Release();
result = nsnull; result = nsnull;
} }
} }
return result; return result.forget();
} }
PRBool PRBool

Просмотреть файл

@ -127,12 +127,7 @@ class nsStyleSet
already_AddRefed<nsStyleContext> already_AddRefed<nsStyleContext>
ResolvePseudoElementStyle(nsIContent* aParentContent, ResolvePseudoElementStyle(nsIContent* aParentContent,
nsCSSPseudoElements::Type aType, nsCSSPseudoElements::Type aType,
nsStyleContext* aParentContext) { nsStyleContext* aParentContext);
return ResolvePseudoStyleFor(aParentContent,
nsCSSPseudoElements::GetPseudoAtom(aType),
aType,
aParentContext);
}
// This functions just like ResolvePseudoElementStyle except that it will // This functions just like ResolvePseudoElementStyle except that it will
// return nsnull if there are no explicit style rules for that // return nsnull if there are no explicit style rules for that
@ -334,7 +329,7 @@ public:
// Move aRuleWalker forward by the appropriate rule if we need to add // Move aRuleWalker forward by the appropriate rule if we need to add
// a rule due to property restrictions on pseudo-elements. // a rule due to property restrictions on pseudo-elements.
void WalkRestrictionRule(nsIAtom* aPseudoType, void WalkRestrictionRule(nsCSSPseudoElements::Type aPseudoType,
nsRuleWalker* aRuleWalker); nsRuleWalker* aRuleWalker);
#ifdef DEBUG #ifdef DEBUG

Просмотреть файл

@ -49,7 +49,6 @@
#include "nsRuleData.h" #include "nsRuleData.h"
#include "nsSMILKeySpline.h" #include "nsSMILKeySpline.h"
#include "gfxColor.h" #include "gfxColor.h"
#include "nsCSSPseudoElements.h"
#include "nsCSSPropertySet.h" #include "nsCSSPropertySet.h"
#include "nsStyleAnimation.h" #include "nsStyleAnimation.h"
#include "nsCSSDataBlock.h" #include "nsCSSDataBlock.h"
@ -373,9 +372,10 @@ nsTransitionManager::StyleContextChanged(nsIContent *aElement,
return nsnull; return nsnull;
} }
nsIAtom *pseudo = aNewStyleContext->GetPseudo(); nsCSSPseudoElements::Type pseudoType = aNewStyleContext->GetPseudoType();
if (pseudo && (pseudo != nsCSSPseudoElements::before && if (pseudoType != nsCSSPseudoElements::ePseudo_NotPseudoElement &&
pseudo != nsCSSPseudoElements::after)) { pseudoType != nsCSSPseudoElements::ePseudo_before &&
pseudoType != nsCSSPseudoElements::ePseudo_after) {
return nsnull; return nsnull;
} }
if (aNewStyleContext->GetParent() && if (aNewStyleContext->GetParent() &&
@ -398,9 +398,7 @@ nsTransitionManager::StyleContextChanged(nsIContent *aElement,
// Check delay and duration first, since they default to zero, and // Check delay and duration first, since they default to zero, and
// when they're both zero, we can ignore the transition. // when they're both zero, we can ignore the transition.
if (t.GetDelay() != 0.0f || t.GetDuration() != 0.0f) { if (t.GetDelay() != 0.0f || t.GetDuration() != 0.0f) {
et = GetElementTransitions(aElement, et = GetElementTransitions(aElement, pseudoType, PR_FALSE);
aNewStyleContext->GetPseudo(),
PR_FALSE);
// We might have something to transition. See if any of the // We might have something to transition. See if any of the
// properties in question changed and are animatable. // properties in question changed and are animatable.
@ -614,7 +612,7 @@ nsTransitionManager::ConsiderStartingTransition(nsCSSProperty aProperty,
if (!aElementTransitions) { if (!aElementTransitions) {
aElementTransitions = aElementTransitions =
GetElementTransitions(aElement, aNewStyleContext->GetPseudo(), GetElementTransitions(aElement, aNewStyleContext->GetPseudoType(),
PR_TRUE); PR_TRUE);
if (!aElementTransitions) { if (!aElementTransitions) {
NS_WARNING("allocating ElementTransitions failed"); NS_WARNING("allocating ElementTransitions failed");
@ -648,16 +646,17 @@ nsTransitionManager::ConsiderStartingTransition(nsCSSProperty aProperty,
ElementTransitions* ElementTransitions*
nsTransitionManager::GetElementTransitions(nsIContent *aElement, nsTransitionManager::GetElementTransitions(nsIContent *aElement,
nsIAtom *aPseudo, nsCSSPseudoElements::Type aPseudoType,
PRBool aCreateIfNeeded) PRBool aCreateIfNeeded)
{ {
nsIAtom *propName; nsIAtom *propName;
if (aPseudo == nsCSSPseudoElements::before) { if (aPseudoType == nsCSSPseudoElements::ePseudo_before) {
propName = nsGkAtoms::transitionsOfBeforeProperty; propName = nsGkAtoms::transitionsOfBeforeProperty;
} else if (aPseudo == nsCSSPseudoElements::after) { } else if (aPseudoType == nsCSSPseudoElements::ePseudo_after) {
propName = nsGkAtoms::transitionsOfAfterProperty; propName = nsGkAtoms::transitionsOfAfterProperty;
} else { } else {
NS_ASSERTION(!aPseudo || !aCreateIfNeeded, NS_ASSERTION(aPseudoType == nsCSSPseudoElements::ePseudo_NotPseudoElement ||
!aCreateIfNeeded,
"should never try to create transitions for pseudo " "should never try to create transitions for pseudo "
"other than :before or :after"); "other than :before or :after");
propName = nsGkAtoms::transitionsProperty; propName = nsGkAtoms::transitionsProperty;
@ -711,7 +710,7 @@ NS_IMPL_QUERY_INTERFACE1(nsTransitionManager, nsIStyleRuleProcessor)
nsresult nsresult
nsTransitionManager::WalkTransitionRule(RuleProcessorData* aData, nsTransitionManager::WalkTransitionRule(RuleProcessorData* aData,
nsIAtom *aPseudo) nsCSSPseudoElements::Type aPseudoType)
{ {
if (!aData->mPresContext->IsProcessingAnimationStyleChange()) { if (!aData->mPresContext->IsProcessingAnimationStyleChange()) {
// If we're processing a normal style change rather than one from // If we're processing a normal style change rather than one from
@ -726,7 +725,7 @@ nsTransitionManager::WalkTransitionRule(RuleProcessorData* aData,
} }
ElementTransitions *et = ElementTransitions *et =
GetElementTransitions(aData->mContent, aPseudo, PR_FALSE); GetElementTransitions(aData->mContent, aPseudoType, PR_FALSE);
if (!et) { if (!et) {
return NS_OK; return NS_OK;
} }
@ -746,18 +745,26 @@ nsTransitionManager::RulesMatching(ElementRuleProcessorData* aData)
{ {
NS_ABORT_IF_FALSE(aData->mPresContext == mPresContext, NS_ABORT_IF_FALSE(aData->mPresContext == mPresContext,
"pres context mismatch"); "pres context mismatch");
return WalkTransitionRule(aData, nsnull); return WalkTransitionRule(aData,
nsCSSPseudoElements::ePseudo_NotPseudoElement);
}
NS_IMETHODIMP
nsTransitionManager::RulesMatching(PseudoElementRuleProcessorData* aData)
{
NS_ABORT_IF_FALSE(aData->mPresContext == mPresContext,
"pres context mismatch");
// Note: If we're the only thing keeping a pseudo-element frame alive
// (per ProbePseudoStyleContext), we still want to keep it alive, so
// this is ok.
return WalkTransitionRule(aData, aData->mPseudoType);
} }
NS_IMETHODIMP NS_IMETHODIMP
nsTransitionManager::RulesMatching(PseudoRuleProcessorData* aData) nsTransitionManager::RulesMatching(PseudoRuleProcessorData* aData)
{ {
NS_ABORT_IF_FALSE(aData->mPresContext == mPresContext, return NS_OK;
"pres context mismatch");
// Note: If we're the only thing keeping a pseudo-element frame alive
// (per ProbePseudoStyleContext), we still want to keep it alive, so
// this is ok.
return WalkTransitionRule(aData, aData->mPseudoTag);
} }
NS_IMETHODIMP NS_IMETHODIMP

Просмотреть файл

@ -44,6 +44,7 @@
#include "nsCSSProperty.h" #include "nsCSSProperty.h"
#include "nsIStyleRuleProcessor.h" #include "nsIStyleRuleProcessor.h"
#include "nsRefreshDriver.h" #include "nsRefreshDriver.h"
#include "nsCSSPseudoElements.h"
class nsStyleContext; class nsStyleContext;
class nsPresContext; class nsPresContext;
@ -85,6 +86,7 @@ public:
// nsIStyleRuleProcessor // nsIStyleRuleProcessor
NS_IMETHOD RulesMatching(ElementRuleProcessorData* aData); NS_IMETHOD RulesMatching(ElementRuleProcessorData* aData);
NS_IMETHOD RulesMatching(PseudoElementRuleProcessorData* aData);
NS_IMETHOD RulesMatching(PseudoRuleProcessorData* aData); NS_IMETHOD RulesMatching(PseudoRuleProcessorData* aData);
NS_IMETHOD HasStateDependentStyle(StateRuleProcessorData* aData, NS_IMETHOD HasStateDependentStyle(StateRuleProcessorData* aData,
nsReStyleHint* aResult); nsReStyleHint* aResult);
@ -108,11 +110,12 @@ private:
PRBool *aStartedAny, PRBool *aStartedAny,
nsCSSPropertySet *aWhichStarted); nsCSSPropertySet *aWhichStarted);
ElementTransitions* GetElementTransitions(nsIContent *aElement, ElementTransitions* GetElementTransitions(nsIContent *aElement,
nsIAtom *aPseudo, nsCSSPseudoElements::Type aPseudoType,
PRBool aCreateIfNeeded); PRBool aCreateIfNeeded);
void AddElementTransitions(ElementTransitions* aElementTransitions); void AddElementTransitions(ElementTransitions* aElementTransitions);
void TransitionsRemoved(); void TransitionsRemoved();
nsresult WalkTransitionRule(RuleProcessorData* aData, nsIAtom *aPseudo); nsresult WalkTransitionRule(RuleProcessorData* aData,
nsCSSPseudoElements::Type aPseudoType);
PRCList mElementTransitions; PRCList mElementTransitions;
nsPresContext *mPresContext; nsPresContext *mPresContext;