mirror of
https://github.com/mozilla/gecko-dev.git
synced 2024-11-25 13:51:41 +00:00
Bug 525608 part 5. Change anonymous box rule matching to just use a separate hashtable and not ever run SelectorMatches. r=dbaron
This commit is contained in:
parent
430b782ab4
commit
a94a034494
@ -727,12 +727,15 @@ struct RuleCascadeData {
|
||||
{
|
||||
PL_DHashTableInit(&mAttributeSelectors, &AttributeSelectorOps, nsnull,
|
||||
sizeof(AttributeSelectorEntry), 16);
|
||||
PL_DHashTableInit(&mAnonBoxRules, &RuleHash_TagTable_Ops, nsnull,
|
||||
sizeof(RuleHashTagTableEntry), 16);
|
||||
memset(mPseudoElementRuleHashes, 0, sizeof(mPseudoElementRuleHashes));
|
||||
}
|
||||
|
||||
~RuleCascadeData()
|
||||
{
|
||||
PL_DHashTableFinish(&mAttributeSelectors);
|
||||
PL_DHashTableFinish(&mAnonBoxRules);
|
||||
for (PRUint32 i = 0; i < NS_ARRAY_LENGTH(mPseudoElementRuleHashes); ++i) {
|
||||
delete mPseudoElementRuleHashes[i];
|
||||
}
|
||||
@ -744,6 +747,7 @@ struct RuleCascadeData {
|
||||
nsTArray<nsCSSSelector*> mClassSelectors;
|
||||
nsTArray<nsCSSSelector*> mIDSelectors;
|
||||
PLDHashTable mAttributeSelectors;
|
||||
PLDHashTable mAnonBoxRules;
|
||||
|
||||
nsTArray<nsFontFaceRuleContainer> mFontFaceRules;
|
||||
|
||||
@ -2079,6 +2083,32 @@ nsCSSRuleProcessor::RulesMatching(PseudoElementRuleProcessorData* aData)
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
NS_IMETHODIMP
|
||||
nsCSSRuleProcessor::RulesMatching(AnonBoxRuleProcessorData* aData)
|
||||
{
|
||||
RuleCascadeData* cascade = GetRuleCascade(aData->mPresContext);
|
||||
|
||||
if (cascade && cascade->mAnonBoxRules.entryCount) {
|
||||
RuleHashTagTableEntry* entry = static_cast<RuleHashTagTableEntry*>
|
||||
(PL_DHashTableOperate(&cascade->mAnonBoxRules, aData->mPseudoTag,
|
||||
PL_DHASH_LOOKUP));
|
||||
if (PL_DHASH_ENTRY_IS_BUSY(entry)) {
|
||||
for (RuleValue *value = entry->mRules; value; value = value->mNext) {
|
||||
// for performance, require that every implementation of
|
||||
// nsICSSStyleRule return the same pointer for nsIStyleRule (why
|
||||
// would anything multiply inherit nsIStyleRule anyway?)
|
||||
#ifdef DEBUG
|
||||
nsCOMPtr<nsIStyleRule> iRule = do_QueryInterface(value->mRule);
|
||||
NS_ASSERTION(static_cast<nsIStyleRule*>(value->mRule) == iRule.get(),
|
||||
"Please fix QI so this performance optimization is valid");
|
||||
#endif
|
||||
aData->mRuleWalker->Forward(static_cast<nsIStyleRule*>(value->mRule));
|
||||
}
|
||||
}
|
||||
}
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
static void PseudoEnumFunc(nsICSSStyleRule* aRule, nsCSSSelector* aSelector,
|
||||
void* aData)
|
||||
{
|
||||
@ -2418,6 +2448,18 @@ AddRule(RuleValue* aRuleInfo, void* aCascade)
|
||||
"Unexpected mNext combinator");
|
||||
aRuleInfo->mSelector = aRuleInfo->mSelector->mNext;
|
||||
ruleHash->PrependRule(aRuleInfo);
|
||||
} else if (pseudoType == nsCSSPseudoElements::ePseudo_AnonBox) {
|
||||
RuleHashTagTableEntry *entry = static_cast<RuleHashTagTableEntry*>
|
||||
(PL_DHashTableOperate(&cascade->mAnonBoxRules,
|
||||
aRuleInfo->mSelector->mLowercaseTag,
|
||||
PL_DHASH_ADD));
|
||||
if (!entry)
|
||||
return PR_FALSE;
|
||||
|
||||
entry->mTag = aRuleInfo->mSelector->mLowercaseTag;
|
||||
// Index doesn't matter here, since we'll just be walking these
|
||||
// rules in order; just pass 0.
|
||||
entry->mRules = aRuleInfo->Add(0, entry->mRules);
|
||||
} else {
|
||||
cascade->mRuleHash.PrependRule(aRuleInfo);
|
||||
}
|
||||
|
@ -93,6 +93,8 @@ public:
|
||||
|
||||
NS_IMETHOD RulesMatching(PseudoElementRuleProcessorData* aData);
|
||||
|
||||
NS_IMETHOD RulesMatching(AnonBoxRuleProcessorData* aData);
|
||||
|
||||
NS_IMETHOD RulesMatching(PseudoRuleProcessorData* aData);
|
||||
|
||||
NS_IMETHOD HasStateDependentStyle(StateRuleProcessorData* aData,
|
||||
|
@ -91,6 +91,8 @@ public:
|
||||
|
||||
NS_IMETHOD RulesMatching(PseudoElementRuleProcessorData* aData);
|
||||
|
||||
NS_IMETHOD RulesMatching(AnonBoxRuleProcessorData* aData);
|
||||
|
||||
NS_IMETHOD RulesMatching(PseudoRuleProcessorData* aData);
|
||||
|
||||
NS_IMETHOD HasStateDependentStyle(StateRuleProcessorData* aData,
|
||||
@ -164,6 +166,12 @@ HTMLCSSStyleSheetImpl::RulesMatching(PseudoElementRuleProcessorData* aData)
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
NS_IMETHODIMP
|
||||
HTMLCSSStyleSheetImpl::RulesMatching(AnonBoxRuleProcessorData* aData)
|
||||
{
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
NS_IMETHODIMP
|
||||
HTMLCSSStyleSheetImpl::RulesMatching(PseudoRuleProcessorData* aData)
|
||||
{
|
||||
|
@ -569,7 +569,7 @@ nsHTMLStyleSheet::RulesMatching(PseudoElementRuleProcessorData* aData)
|
||||
}
|
||||
|
||||
NS_IMETHODIMP
|
||||
nsHTMLStyleSheet::RulesMatching(PseudoRuleProcessorData* aData)
|
||||
nsHTMLStyleSheet::RulesMatching(AnonBoxRuleProcessorData* aData)
|
||||
{
|
||||
nsIAtom* pseudoTag = aData->mPseudoTag;
|
||||
if (pseudoTag == nsCSSAnonBoxes::tableCol) {
|
||||
@ -581,6 +581,12 @@ nsHTMLStyleSheet::RulesMatching(PseudoRuleProcessorData* aData)
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
NS_IMETHODIMP
|
||||
nsHTMLStyleSheet::RulesMatching(PseudoRuleProcessorData* aData)
|
||||
{
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
|
||||
// nsIStyleSheet api
|
||||
NS_IMETHODIMP
|
||||
|
@ -80,6 +80,7 @@ public:
|
||||
// nsIStyleRuleProcessor API
|
||||
NS_IMETHOD RulesMatching(ElementRuleProcessorData* aData);
|
||||
NS_IMETHOD RulesMatching(PseudoElementRuleProcessorData* aData);
|
||||
NS_IMETHOD RulesMatching(AnonBoxRuleProcessorData* aData);
|
||||
NS_IMETHOD RulesMatching(PseudoRuleProcessorData* aData);
|
||||
NS_IMETHOD HasStateDependentStyle(StateRuleProcessorData* aData,
|
||||
nsReStyleHint* aResult);
|
||||
|
@ -52,6 +52,7 @@
|
||||
struct RuleProcessorData;
|
||||
struct ElementRuleProcessorData;
|
||||
struct PseudoElementRuleProcessorData;
|
||||
struct AnonBoxRuleProcessorData;
|
||||
struct PseudoRuleProcessorData;
|
||||
struct StateRuleProcessorData;
|
||||
struct AttributeRuleProcessorData;
|
||||
@ -92,6 +93,11 @@ public:
|
||||
*/
|
||||
NS_IMETHOD RulesMatching(PseudoElementRuleProcessorData* aData) = 0;
|
||||
|
||||
/**
|
||||
* Just like the previous |RulesMatching|, except for a given anonymous box.
|
||||
*/
|
||||
NS_IMETHOD RulesMatching(AnonBoxRuleProcessorData* aData) = 0;
|
||||
|
||||
/**
|
||||
* Just like the previous |RulesMatching|, except for a given content
|
||||
* node <em>and pseudo</em>.
|
||||
|
@ -193,6 +193,24 @@ struct PseudoElementRuleProcessorData : public RuleProcessorData {
|
||||
nsCSSPseudoElements::Type mPseudoType;
|
||||
};
|
||||
|
||||
struct AnonBoxRuleProcessorData {
|
||||
AnonBoxRuleProcessorData(nsPresContext* aPresContext,
|
||||
nsIAtom* aPseudoTag,
|
||||
nsRuleWalker* aRuleWalker)
|
||||
: mPresContext(aPresContext),
|
||||
mPseudoTag(aPseudoTag),
|
||||
mRuleWalker(aRuleWalker)
|
||||
{
|
||||
NS_PRECONDITION(mPresContext, "Must have prescontext");
|
||||
NS_PRECONDITION(aPseudoTag, "Must have pseudo tag");
|
||||
NS_PRECONDITION(aRuleWalker, "Must have rule walker");
|
||||
}
|
||||
|
||||
nsPresContext* mPresContext;
|
||||
nsIAtom* mPseudoTag;
|
||||
nsRuleWalker* mRuleWalker;
|
||||
};
|
||||
|
||||
struct PseudoRuleProcessorData : public RuleProcessorData {
|
||||
PseudoRuleProcessorData(nsPresContext* aPresContext,
|
||||
nsIContent* aParentContent,
|
||||
|
@ -531,7 +531,8 @@ nsStyleSet::AssertNoCSSRules(nsRuleNode* aCurrLevelNode,
|
||||
// Enumerate the rules in a way that cares about the order of the rules.
|
||||
void
|
||||
nsStyleSet::FileRules(nsIStyleRuleProcessor::EnumFunc aCollectorFunc,
|
||||
RuleProcessorData* aData, nsRuleWalker* aRuleWalker)
|
||||
void* aData, nsIContent* aContent,
|
||||
nsRuleWalker* aRuleWalker)
|
||||
{
|
||||
// Cascading order:
|
||||
// [least important]
|
||||
@ -564,7 +565,7 @@ nsStyleSet::FileRules(nsIStyleRuleProcessor::EnumFunc aCollectorFunc,
|
||||
|
||||
aRuleWalker->SetLevel(eUserSheet, PR_FALSE, PR_TRUE);
|
||||
PRBool skipUserStyles =
|
||||
aData->mContent && aData->mContent->IsInNativeAnonymousSubtree();
|
||||
aContent && aContent->IsInNativeAnonymousSubtree();
|
||||
if (!skipUserStyles && mRuleProcessors[eUserSheet]) // NOTE: different
|
||||
(*aCollectorFunc)(mRuleProcessors[eUserSheet], aData);
|
||||
nsRuleNode* lastUserRN = aRuleWalker->GetCurrentNode();
|
||||
@ -577,9 +578,11 @@ nsStyleSet::FileRules(nsIStyleRuleProcessor::EnumFunc aCollectorFunc,
|
||||
|
||||
aRuleWalker->SetLevel(eDocSheet, PR_FALSE, PR_TRUE);
|
||||
PRBool cutOffInheritance = PR_FALSE;
|
||||
if (mBindingManager) {
|
||||
if (mBindingManager && aContent) {
|
||||
// We can supply additional document-level sheets that should be walked.
|
||||
mBindingManager->WalkRules(aCollectorFunc, aData, &cutOffInheritance);
|
||||
mBindingManager->WalkRules(aCollectorFunc,
|
||||
static_cast<RuleProcessorData*>(aData),
|
||||
&cutOffInheritance);
|
||||
}
|
||||
if (!skipUserStyles && !cutOffInheritance &&
|
||||
mRuleProcessors[eDocSheet]) // NOTE: different
|
||||
@ -746,7 +749,7 @@ nsStyleSet::ResolveStyleFor(nsIContent* aContent,
|
||||
if (aContent && presContext) {
|
||||
nsRuleWalker ruleWalker(mRuleTree);
|
||||
ElementRuleProcessorData data(presContext, aContent, &ruleWalker);
|
||||
FileRules(EnumRulesMatching, &data, &ruleWalker);
|
||||
FileRules(EnumRulesMatching, &data, aContent, &ruleWalker);
|
||||
result = GetContext(presContext, aParentContext,
|
||||
ruleWalker.GetCurrentNode(), nsnull,
|
||||
nsCSSPseudoElements::ePseudo_NotPseudoElement).get();
|
||||
@ -849,7 +852,7 @@ nsStyleSet::ResolvePseudoStyleFor(nsIContent* aParentContent,
|
||||
nsRuleWalker ruleWalker(mRuleTree);
|
||||
PseudoRuleProcessorData data(presContext, aParentContent, aPseudoTag,
|
||||
aComparator, &ruleWalker);
|
||||
FileRules(EnumPseudoRulesMatching, &data, &ruleWalker);
|
||||
FileRules(EnumPseudoRulesMatching, &data, aParentContent, &ruleWalker);
|
||||
|
||||
result = GetContext(presContext, aParentContext,
|
||||
ruleWalker.GetCurrentNode(), aPseudoTag,
|
||||
@ -887,7 +890,7 @@ nsStyleSet::ResolvePseudoElementStyle(nsIContent* aParentContent,
|
||||
PseudoElementRuleProcessorData data(presContext, aParentContent, &ruleWalker,
|
||||
aType);
|
||||
WalkRestrictionRule(aType, &ruleWalker);
|
||||
FileRules(EnumPseudoElementRulesMatching, &data, &ruleWalker);
|
||||
FileRules(EnumPseudoElementRulesMatching, &data, aParentContent, &ruleWalker);
|
||||
|
||||
return GetContext(presContext, aParentContext, ruleWalker.GetCurrentNode(),
|
||||
nsCSSPseudoElements::GetPseudoAtom(aType), aType);
|
||||
@ -916,7 +919,7 @@ nsStyleSet::ProbePseudoElementStyle(nsIContent* aParentContent,
|
||||
WalkRestrictionRule(aType, &ruleWalker);
|
||||
// not the root if there was a restriction rule
|
||||
nsRuleNode *adjustedRoot = ruleWalker.GetCurrentNode();
|
||||
FileRules(EnumPseudoElementRulesMatching, &data, &ruleWalker);
|
||||
FileRules(EnumPseudoElementRulesMatching, &data, aParentContent, &ruleWalker);
|
||||
|
||||
nsRuleNode *ruleNode = ruleWalker.GetCurrentNode();
|
||||
if (ruleNode == adjustedRoot) {
|
||||
@ -944,6 +947,40 @@ nsStyleSet::ProbePseudoElementStyle(nsIContent* aParentContent,
|
||||
return result.forget();
|
||||
}
|
||||
|
||||
static PRBool
|
||||
EnumAnonBoxRulesMatching(nsIStyleRuleProcessor* aProcessor, void* aData)
|
||||
{
|
||||
AnonBoxRuleProcessorData* data =
|
||||
static_cast<AnonBoxRuleProcessorData*>(aData);
|
||||
|
||||
aProcessor->RulesMatching(data);
|
||||
return PR_TRUE;
|
||||
}
|
||||
|
||||
already_AddRefed<nsStyleContext>
|
||||
nsStyleSet::ResolveAnonymousBoxStyle(nsIAtom* aPseudoTag,
|
||||
nsStyleContext* aParentContext)
|
||||
{
|
||||
NS_ENSURE_FALSE(mInShutdown, nsnull);
|
||||
|
||||
#ifdef DEBUG
|
||||
PRBool isAnonBox = nsCSSAnonBoxes::IsAnonBox(aPseudoTag)
|
||||
#ifdef MOZ_XUL
|
||||
&& !nsCSSAnonBoxes::IsTreePseudoElement(aPseudoTag)
|
||||
#endif
|
||||
;
|
||||
NS_PRECONDITION(isAnonBox, "Unexpected pseudo");
|
||||
#endif
|
||||
|
||||
nsRuleWalker ruleWalker(mRuleTree);
|
||||
nsPresContext *presContext = PresContext();
|
||||
AnonBoxRuleProcessorData data(presContext, aPseudoTag, &ruleWalker);
|
||||
FileRules(EnumAnonBoxRulesMatching, &data, nsnull, &ruleWalker);
|
||||
|
||||
return GetContext(presContext, aParentContext, ruleWalker.GetCurrentNode(),
|
||||
aPseudoTag, nsCSSPseudoElements::ePseudo_AnonBox);
|
||||
}
|
||||
|
||||
PRBool
|
||||
nsStyleSet::AppendFontFaceRules(nsPresContext* aPresContext,
|
||||
nsTArray<nsFontFaceRuleContainer>& aArray)
|
||||
|
@ -140,20 +140,7 @@ class nsStyleSet
|
||||
// Get a style context for an anonymous box. aPseudoTag is the
|
||||
// pseudo-tag to use and must be non-null.
|
||||
already_AddRefed<nsStyleContext>
|
||||
ResolveAnonymousBoxStyle(nsIAtom* aPseudoTag,
|
||||
nsStyleContext* aParentContext) {
|
||||
#ifdef DEBUG
|
||||
PRBool isAnonBox = nsCSSAnonBoxes::IsAnonBox(aPseudoTag)
|
||||
#ifdef MOZ_XUL
|
||||
&& !nsCSSAnonBoxes::IsTreePseudoElement(aPseudoTag)
|
||||
#endif
|
||||
;
|
||||
NS_PRECONDITION(isAnonBox, "Unexpected pseudo");
|
||||
#endif
|
||||
return ResolvePseudoStyleFor(nsnull, aPseudoTag,
|
||||
nsCSSPseudoElements::ePseudo_AnonBox,
|
||||
aParentContext);
|
||||
}
|
||||
ResolveAnonymousBoxStyle(nsIAtom* aPseudoTag, nsStyleContext* aParentContext);
|
||||
|
||||
#ifdef MOZ_XUL
|
||||
// Get a style context for a XUL tree pseudo. aPseudoTag is the
|
||||
@ -348,8 +335,11 @@ public:
|
||||
|
||||
// Enumerate the rules in a way that cares about the order of the
|
||||
// rules.
|
||||
// aContent is the node the rules are for. It might be null. aData
|
||||
// is the closure to pass to aCollectorFunc. If aContent is not null,
|
||||
// aData must be a RuleProcessorData*
|
||||
void FileRules(nsIStyleRuleProcessor::EnumFunc aCollectorFunc,
|
||||
RuleProcessorData* aData, nsRuleWalker* aRuleWalker);
|
||||
void* aData, nsIContent* aContent, nsRuleWalker* aRuleWalker);
|
||||
|
||||
// Enumerate all the rules in a way that doesn't care about the order
|
||||
// of the rules and break out if the enumeration is halted.
|
||||
|
@ -761,6 +761,12 @@ nsTransitionManager::RulesMatching(PseudoElementRuleProcessorData* aData)
|
||||
return WalkTransitionRule(aData, aData->mPseudoType);
|
||||
}
|
||||
|
||||
NS_IMETHODIMP
|
||||
nsTransitionManager::RulesMatching(AnonBoxRuleProcessorData* aData)
|
||||
{
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
NS_IMETHODIMP
|
||||
nsTransitionManager::RulesMatching(PseudoRuleProcessorData* aData)
|
||||
{
|
||||
|
@ -87,6 +87,7 @@ public:
|
||||
// nsIStyleRuleProcessor
|
||||
NS_IMETHOD RulesMatching(ElementRuleProcessorData* aData);
|
||||
NS_IMETHOD RulesMatching(PseudoElementRuleProcessorData* aData);
|
||||
NS_IMETHOD RulesMatching(AnonBoxRuleProcessorData* aData);
|
||||
NS_IMETHOD RulesMatching(PseudoRuleProcessorData* aData);
|
||||
NS_IMETHOD HasStateDependentStyle(StateRuleProcessorData* aData,
|
||||
nsReStyleHint* aResult);
|
||||
|
Loading…
Reference in New Issue
Block a user