From cfac13a4b66a6dc2c8bb544ddb375d7c07f007a4 Mon Sep 17 00:00:00 2001 From: Boris Zbarsky Date: Fri, 11 Dec 2009 02:37:40 -0500 Subject: [PATCH] Bug 525608 part 4. Change pseudo-element probing and resolution to not use EnumerateTagRules. r=dbaron --- layout/style/nsCSSRuleProcessor.cpp | 70 +++++++++++++++++++--- layout/style/nsCSSRuleProcessor.h | 2 + layout/style/nsHTMLCSSStyleSheet.cpp | 8 +++ layout/style/nsHTMLStyleSheet.cpp | 6 ++ layout/style/nsHTMLStyleSheet.h | 1 + layout/style/nsIStyleRuleProcessor.h | 7 +++ layout/style/nsRuleProcessorData.h | 19 ++++++ layout/style/nsStyleSet.cpp | 89 +++++++++++++++++++--------- layout/style/nsStyleSet.h | 9 +-- layout/style/nsTransitionManager.cpp | 49 ++++++++------- layout/style/nsTransitionManager.h | 7 ++- 11 files changed, 199 insertions(+), 68 deletions(-) diff --git a/layout/style/nsCSSRuleProcessor.cpp b/layout/style/nsCSSRuleProcessor.cpp index 74a0bfd5d2a..0326faceefb 100644 --- a/layout/style/nsCSSRuleProcessor.cpp +++ b/layout/style/nsCSSRuleProcessor.cpp @@ -69,6 +69,7 @@ #include "nsDOMError.h" #include "nsRuleWalker.h" #include "nsCSSPseudoClasses.h" +#include "nsCSSPseudoElements.h" #include "nsIContent.h" #include "nsCOMPtr.h" #include "nsHashKeys.h" @@ -363,7 +364,7 @@ public: void PrependRule(RuleValue *aRuleInfo); void EnumerateAllRules(PRInt32 aNameSpace, nsIAtom* aTag, nsIAtom* aID, const nsAttrValue* aClassList, - RuleEnumFunc aFunc, void* aData); + RuleEnumFunc aFunc, RuleProcessorData* aData); void EnumerateTagRules(nsIAtom* aTag, RuleEnumFunc aFunc, void* aData); PLArenaPool& Arena() { return mArena; } @@ -428,6 +429,7 @@ RuleHash::RuleHash(PRBool aQuirksMode) mPseudoTagCalls(0) #endif { + MOZ_COUNT_CTOR(RuleHash); // Initialize our arena PL_INIT_ARENA_POOL(&mArena, "RuleHashArena", NS_RULEHASH_ARENA_BLOCK_SIZE); @@ -447,6 +449,7 @@ RuleHash::RuleHash(PRBool aQuirksMode) RuleHash::~RuleHash() { + MOZ_COUNT_DTOR(RuleHash); #ifdef RULE_HASH_STATS printf( "RuleHash(%p):\n" @@ -574,7 +577,7 @@ void RuleHash::PrependRule(RuleValue *aRuleInfo) void RuleHash::EnumerateAllRules(PRInt32 aNameSpace, nsIAtom* aTag, nsIAtom* aID, const nsAttrValue* aClassList, - RuleEnumFunc aFunc, void* aData) + RuleEnumFunc aFunc, RuleProcessorData* aData) { PRInt32 classCount = aClassList ? aClassList->GetAtomCount() : 0; @@ -599,7 +602,7 @@ void RuleHash::EnumerateAllRules(PRInt32 aNameSpace, nsIAtom* aTag, } } // universal rules within the namespace - if (kNameSpaceID_Unknown != aNameSpace) { + if (kNameSpaceID_Unknown != aNameSpace && mNameSpaceTable.entryCount) { RuleHashTableEntry *entry = static_cast (PL_DHashTableOperate(&mNameSpaceTable, NS_INT32_TO_PTR(aNameSpace), PL_DHASH_LOOKUP)); @@ -609,7 +612,7 @@ void RuleHash::EnumerateAllRules(PRInt32 aNameSpace, nsIAtom* aTag, RULE_HASH_STAT_INCREMENT_LIST_COUNT(value, mElementNameSpaceCalls); } } - if (nsnull != aTag) { + if (aTag && mTagTable.entryCount) { RuleHashTableEntry *entry = static_cast (PL_DHashTableOperate(&mTagTable, aTag, PL_DHASH_LOOKUP)); 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); } } - if (nsnull != aID) { + if (aID && mIdTable.entryCount) { RuleHashTableEntry *entry = static_cast (PL_DHashTableOperate(&mIdTable, aID, PL_DHASH_LOOKUP)); 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); } } - { // extra scope to work around compiler bugs with |for| scoping. + if (mClassTable.entryCount) { for (PRInt32 index = 0; index < classCount; ++index) { RuleHashTableEntry *entry = static_cast (PL_DHashTableOperate(&mClassTable, aClassList->AtomAt(index), @@ -719,17 +722,24 @@ struct RuleCascadeData { : mRuleHash(aQuirksMode), mStateSelectors(), mCacheKey(aMedium), - mNext(nsnull) + mNext(nsnull), + mQuirksMode(aQuirksMode) { PL_DHashTableInit(&mAttributeSelectors, &AttributeSelectorOps, nsnull, sizeof(AttributeSelectorEntry), 16); + memset(mPseudoElementRuleHashes, 0, sizeof(mPseudoElementRuleHashes)); } ~RuleCascadeData() { PL_DHashTableFinish(&mAttributeSelectors); + for (PRUint32 i = 0; i < NS_ARRAY_LENGTH(mPseudoElementRuleHashes); ++i) { + delete mPseudoElementRuleHashes[i]; + } } RuleHash mRuleHash; + RuleHash* + mPseudoElementRuleHashes[nsCSSPseudoElements::ePseudo_PseudoElementCount]; nsTArray mStateSelectors; nsTArray mClassSelectors; nsTArray mIDSelectors; @@ -743,6 +753,8 @@ struct RuleCascadeData { nsMediaQueryResultCacheKey mCacheKey; RuleCascadeData* mNext; // for a different medium + + const PRBool mQuirksMode; }; nsTArray* @@ -2007,7 +2019,7 @@ static PRBool SelectorMatchesTree(RuleProcessorData& aPrevData, static void ContentEnumFunc(nsICSSStyleRule* aRule, nsCSSSelector* aSelector, void* aData) { - ElementRuleProcessorData* data = (ElementRuleProcessorData*)aData; + RuleProcessorData* data = (RuleProcessorData*)aData; if (SelectorMatches(*data, aSelector, 0, PR_TRUE)) { nsCSSSelector *next = aSelector->mNext; @@ -2045,6 +2057,28 @@ nsCSSRuleProcessor::RulesMatching(ElementRuleProcessorData *aData) 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, void* aData) { @@ -2368,7 +2402,25 @@ AddRule(RuleValue* aRuleInfo, void* aCascade) RuleCascadeData *cascade = static_cast(aCascade); // 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* stateArray = &cascade->mStateSelectors; nsTArray* classArray = &cascade->mClassSelectors; diff --git a/layout/style/nsCSSRuleProcessor.h b/layout/style/nsCSSRuleProcessor.h index 126d739ac31..f6c491514c0 100644 --- a/layout/style/nsCSSRuleProcessor.h +++ b/layout/style/nsCSSRuleProcessor.h @@ -91,6 +91,8 @@ public: // nsIStyleRuleProcessor NS_IMETHOD RulesMatching(ElementRuleProcessorData* aData); + NS_IMETHOD RulesMatching(PseudoElementRuleProcessorData* aData); + NS_IMETHOD RulesMatching(PseudoRuleProcessorData* aData); NS_IMETHOD HasStateDependentStyle(StateRuleProcessorData* aData, diff --git a/layout/style/nsHTMLCSSStyleSheet.cpp b/layout/style/nsHTMLCSSStyleSheet.cpp index ca1ec494f37..2005e44d810 100644 --- a/layout/style/nsHTMLCSSStyleSheet.cpp +++ b/layout/style/nsHTMLCSSStyleSheet.cpp @@ -89,6 +89,8 @@ public: // nsIStyleRuleProcessor api NS_IMETHOD RulesMatching(ElementRuleProcessorData* aData); + NS_IMETHOD RulesMatching(PseudoElementRuleProcessorData* aData); + NS_IMETHOD RulesMatching(PseudoRuleProcessorData* aData); NS_IMETHOD HasStateDependentStyle(StateRuleProcessorData* aData, @@ -156,6 +158,12 @@ HTMLCSSStyleSheetImpl::RulesMatching(ElementRuleProcessorData* aData) return NS_OK; } +NS_IMETHODIMP +HTMLCSSStyleSheetImpl::RulesMatching(PseudoElementRuleProcessorData* aData) +{ + return NS_OK; +} + NS_IMETHODIMP HTMLCSSStyleSheetImpl::RulesMatching(PseudoRuleProcessorData* aData) { diff --git a/layout/style/nsHTMLStyleSheet.cpp b/layout/style/nsHTMLStyleSheet.cpp index 7ecd9de92de..1c8143432c2 100644 --- a/layout/style/nsHTMLStyleSheet.cpp +++ b/layout/style/nsHTMLStyleSheet.cpp @@ -562,6 +562,12 @@ nsHTMLStyleSheet::MediumFeaturesChanged(nsPresContext* aPresContext, } +NS_IMETHODIMP +nsHTMLStyleSheet::RulesMatching(PseudoElementRuleProcessorData* aData) +{ + return NS_OK; +} + NS_IMETHODIMP nsHTMLStyleSheet::RulesMatching(PseudoRuleProcessorData* aData) { diff --git a/layout/style/nsHTMLStyleSheet.h b/layout/style/nsHTMLStyleSheet.h index a72037226fe..ef675b9e954 100644 --- a/layout/style/nsHTMLStyleSheet.h +++ b/layout/style/nsHTMLStyleSheet.h @@ -79,6 +79,7 @@ public: // nsIStyleRuleProcessor API NS_IMETHOD RulesMatching(ElementRuleProcessorData* aData); + NS_IMETHOD RulesMatching(PseudoElementRuleProcessorData* aData); NS_IMETHOD RulesMatching(PseudoRuleProcessorData* aData); NS_IMETHOD HasStateDependentStyle(StateRuleProcessorData* aData, nsReStyleHint* aResult); diff --git a/layout/style/nsIStyleRuleProcessor.h b/layout/style/nsIStyleRuleProcessor.h index 65d5f7289a6..98b712970b6 100644 --- a/layout/style/nsIStyleRuleProcessor.h +++ b/layout/style/nsIStyleRuleProcessor.h @@ -51,6 +51,7 @@ struct RuleProcessorData; struct ElementRuleProcessorData; +struct PseudoElementRuleProcessorData; struct PseudoRuleProcessorData; struct StateRuleProcessorData; struct AttributeRuleProcessorData; @@ -89,6 +90,12 @@ public: * Just like the previous |RulesMatching|, except for a given content * node and pseudo-element. */ + NS_IMETHOD RulesMatching(PseudoElementRuleProcessorData* aData) = 0; + + /** + * Just like the previous |RulesMatching|, except for a given content + * node and pseudo. + */ NS_IMETHOD RulesMatching(PseudoRuleProcessorData* aData) = 0; /** diff --git a/layout/style/nsRuleProcessorData.h b/layout/style/nsRuleProcessorData.h index 21d79a4d369..3f54da5a3b0 100644 --- a/layout/style/nsRuleProcessorData.h +++ b/layout/style/nsRuleProcessorData.h @@ -48,6 +48,7 @@ #include "nsString.h" #include "nsChangeHint.h" #include "nsIContent.h" +#include "nsCSSPseudoElements.h" class nsIStyleSheet; 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 { PseudoRuleProcessorData(nsPresContext* aPresContext, nsIContent* aParentContent, diff --git a/layout/style/nsStyleSet.cpp b/layout/style/nsStyleSet.cpp index c3d3c241ed7..9302dc0a433 100644 --- a/layout/style/nsStyleSet.cpp +++ b/layout/style/nsStyleSet.cpp @@ -799,17 +799,15 @@ nsStyleSet::ResolveStyleForNonElement(nsStyleContext* aParentContext) } void -nsStyleSet::WalkRestrictionRule(nsIAtom* aPseudoType, +nsStyleSet::WalkRestrictionRule(nsCSSPseudoElements::Type aPseudoType, nsRuleWalker* aRuleWalker) { // This needs to match GetPseudoRestriction in nsRuleNode.cpp. - if (aPseudoType) { - aRuleWalker->SetLevel(eAgentSheet, PR_FALSE, PR_FALSE); - if (aPseudoType == nsCSSPseudoElements::firstLetter) - aRuleWalker->Forward(mFirstLetterRule); - else if (aPseudoType == nsCSSPseudoElements::firstLine) - aRuleWalker->Forward(mFirstLineRule); - } + aRuleWalker->SetLevel(eAgentSheet, PR_FALSE, PR_FALSE); + if (aPseudoType == nsCSSPseudoElements::ePseudo_firstLetter) + aRuleWalker->Forward(mFirstLetterRule); + else if (aPseudoType == nsCSSPseudoElements::ePseudo_firstLine) + aRuleWalker->Forward(mFirstLineRule); } static PRBool @@ -851,7 +849,6 @@ nsStyleSet::ResolvePseudoStyleFor(nsIContent* aParentContent, nsRuleWalker ruleWalker(mRuleTree); PseudoRuleProcessorData data(presContext, aParentContent, aPseudoTag, aComparator, &ruleWalker); - WalkRestrictionRule(aPseudoTag, &ruleWalker); FileRules(EnumPseudoRulesMatching, &data, &ruleWalker); result = GetContext(presContext, aParentContext, @@ -862,6 +859,40 @@ nsStyleSet::ResolvePseudoStyleFor(nsIContent* aParentContent, return result; } +static PRBool +EnumPseudoElementRulesMatching(nsIStyleRuleProcessor* aProcessor, void* aData) +{ + PseudoElementRuleProcessorData* data = + static_cast(aData); + + aProcessor->RulesMatching(data); + return PR_TRUE; +} + +already_AddRefed +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 nsStyleSet::ProbePseudoElementStyle(nsIContent* aParentContent, nsCSSPseudoElements::Type aType, @@ -869,31 +900,32 @@ nsStyleSet::ProbePseudoElementStyle(nsIContent* aParentContent, { NS_ENSURE_FALSE(mInShutdown, nsnull); - nsIAtom* pseudoTag = nsCSSPseudoElements::GetPseudoAtom(aType); - - nsStyleContext* result = nsnull; - nsPresContext *presContext = PresContext(); - - NS_ASSERTION(pseudoTag, "must have pseudo tag"); + NS_ASSERTION(aType < nsCSSPseudoElements::ePseudo_PseudoElementCount, + "must have pseudo element type"); NS_ASSERTION(aParentContent && aParentContent->IsNodeOfType(nsINode::eELEMENT), "aParentContent must be element"); - if (presContext) { - 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); + nsIAtom* pseudoTag = nsCSSPseudoElements::GetPseudoAtom(aType); - nsRuleNode *ruleNode = ruleWalker.GetCurrentNode(); - if (ruleNode != adjustedRoot) - result = - GetContext(presContext, aParentContext, ruleNode, pseudoTag, aType).get(); + nsPresContext *presContext = PresContext(); + + nsRuleWalker ruleWalker(mRuleTree); + 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 result = + GetContext(presContext, aParentContext, ruleNode, pseudoTag, aType); + // For :before and :after pseudo-elements, having display: none or no // 'content' property is equivalent to not having the pseudo-element // at all. @@ -905,12 +937,11 @@ nsStyleSet::ProbePseudoElementStyle(nsIContent* aParentContent, // XXXldb What is contentCount for |content: ""|? if (display->mDisplay == NS_STYLE_DISPLAY_NONE || content->ContentCount() == 0) { - result->Release(); result = nsnull; } } - return result; + return result.forget(); } PRBool diff --git a/layout/style/nsStyleSet.h b/layout/style/nsStyleSet.h index 3c90e9ec9eb..7e6eb6711a2 100644 --- a/layout/style/nsStyleSet.h +++ b/layout/style/nsStyleSet.h @@ -127,12 +127,7 @@ class nsStyleSet already_AddRefed ResolvePseudoElementStyle(nsIContent* aParentContent, nsCSSPseudoElements::Type aType, - nsStyleContext* aParentContext) { - return ResolvePseudoStyleFor(aParentContent, - nsCSSPseudoElements::GetPseudoAtom(aType), - aType, - aParentContext); - } + nsStyleContext* aParentContext); // This functions just like ResolvePseudoElementStyle except that it will // 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 // a rule due to property restrictions on pseudo-elements. - void WalkRestrictionRule(nsIAtom* aPseudoType, + void WalkRestrictionRule(nsCSSPseudoElements::Type aPseudoType, nsRuleWalker* aRuleWalker); #ifdef DEBUG diff --git a/layout/style/nsTransitionManager.cpp b/layout/style/nsTransitionManager.cpp index 6106279eb5f..a369b44f317 100644 --- a/layout/style/nsTransitionManager.cpp +++ b/layout/style/nsTransitionManager.cpp @@ -49,7 +49,6 @@ #include "nsRuleData.h" #include "nsSMILKeySpline.h" #include "gfxColor.h" -#include "nsCSSPseudoElements.h" #include "nsCSSPropertySet.h" #include "nsStyleAnimation.h" #include "nsCSSDataBlock.h" @@ -373,9 +372,10 @@ nsTransitionManager::StyleContextChanged(nsIContent *aElement, return nsnull; } - nsIAtom *pseudo = aNewStyleContext->GetPseudo(); - if (pseudo && (pseudo != nsCSSPseudoElements::before && - pseudo != nsCSSPseudoElements::after)) { + nsCSSPseudoElements::Type pseudoType = aNewStyleContext->GetPseudoType(); + if (pseudoType != nsCSSPseudoElements::ePseudo_NotPseudoElement && + pseudoType != nsCSSPseudoElements::ePseudo_before && + pseudoType != nsCSSPseudoElements::ePseudo_after) { return nsnull; } if (aNewStyleContext->GetParent() && @@ -398,9 +398,7 @@ nsTransitionManager::StyleContextChanged(nsIContent *aElement, // Check delay and duration first, since they default to zero, and // when they're both zero, we can ignore the transition. if (t.GetDelay() != 0.0f || t.GetDuration() != 0.0f) { - et = GetElementTransitions(aElement, - aNewStyleContext->GetPseudo(), - PR_FALSE); + et = GetElementTransitions(aElement, pseudoType, PR_FALSE); // We might have something to transition. See if any of the // properties in question changed and are animatable. @@ -614,7 +612,7 @@ nsTransitionManager::ConsiderStartingTransition(nsCSSProperty aProperty, if (!aElementTransitions) { aElementTransitions = - GetElementTransitions(aElement, aNewStyleContext->GetPseudo(), + GetElementTransitions(aElement, aNewStyleContext->GetPseudoType(), PR_TRUE); if (!aElementTransitions) { NS_WARNING("allocating ElementTransitions failed"); @@ -648,16 +646,17 @@ nsTransitionManager::ConsiderStartingTransition(nsCSSProperty aProperty, ElementTransitions* nsTransitionManager::GetElementTransitions(nsIContent *aElement, - nsIAtom *aPseudo, + nsCSSPseudoElements::Type aPseudoType, PRBool aCreateIfNeeded) { nsIAtom *propName; - if (aPseudo == nsCSSPseudoElements::before) { + if (aPseudoType == nsCSSPseudoElements::ePseudo_before) { propName = nsGkAtoms::transitionsOfBeforeProperty; - } else if (aPseudo == nsCSSPseudoElements::after) { + } else if (aPseudoType == nsCSSPseudoElements::ePseudo_after) { propName = nsGkAtoms::transitionsOfAfterProperty; } else { - NS_ASSERTION(!aPseudo || !aCreateIfNeeded, + NS_ASSERTION(aPseudoType == nsCSSPseudoElements::ePseudo_NotPseudoElement || + !aCreateIfNeeded, "should never try to create transitions for pseudo " "other than :before or :after"); propName = nsGkAtoms::transitionsProperty; @@ -711,7 +710,7 @@ NS_IMPL_QUERY_INTERFACE1(nsTransitionManager, nsIStyleRuleProcessor) nsresult nsTransitionManager::WalkTransitionRule(RuleProcessorData* aData, - nsIAtom *aPseudo) + nsCSSPseudoElements::Type aPseudoType) { if (!aData->mPresContext->IsProcessingAnimationStyleChange()) { // If we're processing a normal style change rather than one from @@ -726,7 +725,7 @@ nsTransitionManager::WalkTransitionRule(RuleProcessorData* aData, } ElementTransitions *et = - GetElementTransitions(aData->mContent, aPseudo, PR_FALSE); + GetElementTransitions(aData->mContent, aPseudoType, PR_FALSE); if (!et) { return NS_OK; } @@ -746,18 +745,26 @@ nsTransitionManager::RulesMatching(ElementRuleProcessorData* aData) { NS_ABORT_IF_FALSE(aData->mPresContext == mPresContext, "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 nsTransitionManager::RulesMatching(PseudoRuleProcessorData* 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->mPseudoTag); + return NS_OK; } NS_IMETHODIMP diff --git a/layout/style/nsTransitionManager.h b/layout/style/nsTransitionManager.h index c83a9aca5f5..706fcd23c2b 100644 --- a/layout/style/nsTransitionManager.h +++ b/layout/style/nsTransitionManager.h @@ -44,6 +44,7 @@ #include "nsCSSProperty.h" #include "nsIStyleRuleProcessor.h" #include "nsRefreshDriver.h" +#include "nsCSSPseudoElements.h" class nsStyleContext; class nsPresContext; @@ -85,6 +86,7 @@ public: // nsIStyleRuleProcessor NS_IMETHOD RulesMatching(ElementRuleProcessorData* aData); + NS_IMETHOD RulesMatching(PseudoElementRuleProcessorData* aData); NS_IMETHOD RulesMatching(PseudoRuleProcessorData* aData); NS_IMETHOD HasStateDependentStyle(StateRuleProcessorData* aData, nsReStyleHint* aResult); @@ -108,11 +110,12 @@ private: PRBool *aStartedAny, nsCSSPropertySet *aWhichStarted); ElementTransitions* GetElementTransitions(nsIContent *aElement, - nsIAtom *aPseudo, + nsCSSPseudoElements::Type aPseudoType, PRBool aCreateIfNeeded); void AddElementTransitions(ElementTransitions* aElementTransitions); void TransitionsRemoved(); - nsresult WalkTransitionRule(RuleProcessorData* aData, nsIAtom *aPseudo); + nsresult WalkTransitionRule(RuleProcessorData* aData, + nsCSSPseudoElements::Type aPseudoType); PRCList mElementTransitions; nsPresContext *mPresContext;