зеркало из https://github.com/mozilla/pjs.git
Make nsStyleSet use nsRuleWalker objects on the stack rather than in a member variable. (Bug 492675) r=bzbarsky
This commit is contained in:
Родитель
228d52dbc8
Коммит
6063b4accf
|
@ -84,7 +84,6 @@ static const nsStyleSet::sheetType gCSSSheetTypes[] = {
|
|||
|
||||
nsStyleSet::nsStyleSet()
|
||||
: mRuleTree(nsnull),
|
||||
mRuleWalker(nsnull),
|
||||
mUnusedRuleNodeCount(0),
|
||||
mBatching(0),
|
||||
mInShutdown(PR_FALSE),
|
||||
|
@ -114,13 +113,6 @@ nsStyleSet::Init(nsPresContext *aPresContext)
|
|||
return NS_ERROR_OUT_OF_MEMORY;
|
||||
}
|
||||
|
||||
mRuleWalker = new nsRuleWalker(mRuleTree);
|
||||
if (!mRuleWalker) {
|
||||
mRuleTree->Destroy();
|
||||
mDefaultStyleData.Destroy(0, aPresContext);
|
||||
return NS_ERROR_OUT_OF_MEMORY;
|
||||
}
|
||||
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
|
@ -135,20 +127,12 @@ nsStyleSet::BeginReconstruct()
|
|||
nsRuleNode::CreateRootNode(mRuleTree->GetPresContext());
|
||||
if (!newTree)
|
||||
return NS_ERROR_OUT_OF_MEMORY;
|
||||
nsRuleWalker* ruleWalker = new nsRuleWalker(newTree);
|
||||
if (!ruleWalker) {
|
||||
newTree->Destroy();
|
||||
return NS_ERROR_OUT_OF_MEMORY;
|
||||
}
|
||||
|
||||
// Save the old rule tree so we can destroy it later
|
||||
if (!mOldRuleTrees.AppendElement(mRuleTree)) {
|
||||
delete ruleWalker;
|
||||
newTree->Destroy();
|
||||
return NS_ERROR_OUT_OF_MEMORY;
|
||||
}
|
||||
// Delete mRuleWalker because it holds a reference to the rule tree root
|
||||
delete mRuleWalker;
|
||||
|
||||
// We need to keep mRoots so that the rule tree GC will only free the
|
||||
// rule trees that really aren't referenced anymore (which should be
|
||||
|
@ -156,7 +140,6 @@ nsStyleSet::BeginReconstruct()
|
|||
|
||||
mInReconstruct = PR_TRUE;
|
||||
mRuleTree = newTree;
|
||||
mRuleWalker = ruleWalker;
|
||||
|
||||
return NS_OK;
|
||||
}
|
||||
|
@ -437,16 +420,13 @@ EnumRulesMatching(nsIStyleRuleProcessor* aProcessor, void* aData)
|
|||
already_AddRefed<nsStyleContext>
|
||||
nsStyleSet::GetContext(nsPresContext* aPresContext,
|
||||
nsStyleContext* aParentContext,
|
||||
nsRuleNode* aRuleNode,
|
||||
nsIAtom* aPseudoTag)
|
||||
{
|
||||
nsStyleContext* result = nsnull;
|
||||
nsRuleNode* ruleNode = mRuleWalker->GetCurrentNode();
|
||||
// Must reset before NS_NewStyleContext, since that could cause more
|
||||
// rule matching (see stack in bug 513741).
|
||||
mRuleWalker->Reset();
|
||||
|
||||
if (aParentContext)
|
||||
result = aParentContext->FindChildWithRules(aPseudoTag, ruleNode).get();
|
||||
result = aParentContext->FindChildWithRules(aPseudoTag, aRuleNode).get();
|
||||
|
||||
#ifdef NOISY_DEBUG
|
||||
if (result)
|
||||
|
@ -456,7 +436,7 @@ nsStyleSet::GetContext(nsPresContext* aPresContext,
|
|||
#endif
|
||||
|
||||
if (!result) {
|
||||
result = NS_NewStyleContext(aParentContext, aPseudoTag, ruleNode,
|
||||
result = NS_NewStyleContext(aParentContext, aPseudoTag, aRuleNode,
|
||||
aPresContext).get();
|
||||
if (!aParentContext && result)
|
||||
mRoots.AppendElement(result);
|
||||
|
@ -467,7 +447,8 @@ nsStyleSet::GetContext(nsPresContext* aPresContext,
|
|||
|
||||
void
|
||||
nsStyleSet::AddImportantRules(nsRuleNode* aCurrLevelNode,
|
||||
nsRuleNode* aLastPrevLevelNode)
|
||||
nsRuleNode* aLastPrevLevelNode,
|
||||
nsRuleWalker* aRuleWalker)
|
||||
{
|
||||
if (!aCurrLevelNode)
|
||||
return;
|
||||
|
@ -485,7 +466,7 @@ nsStyleSet::AddImportantRules(nsRuleNode* aCurrLevelNode,
|
|||
}
|
||||
|
||||
for (PRUint32 i = importantRules.Length(); i-- != 0; ) {
|
||||
mRuleWalker->Forward(importantRules[i]);
|
||||
aRuleWalker->Forward(importantRules[i]);
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -527,7 +508,7 @@ 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)
|
||||
RuleProcessorData* aData, nsRuleWalker* aRuleWalker)
|
||||
{
|
||||
// Cascading order:
|
||||
// [least important]
|
||||
|
@ -547,29 +528,29 @@ nsStyleSet::FileRules(nsIStyleRuleProcessor::EnumFunc aCollectorFunc,
|
|||
SheetCount(eHTMLPresHintSheet) == 0,
|
||||
"Can't have both types of preshint sheets at once!");
|
||||
|
||||
mRuleWalker->SetLevel(eAgentSheet, PR_FALSE);
|
||||
aRuleWalker->SetLevel(eAgentSheet, PR_FALSE);
|
||||
if (mRuleProcessors[eAgentSheet])
|
||||
(*aCollectorFunc)(mRuleProcessors[eAgentSheet], aData);
|
||||
nsRuleNode* lastAgentRN = mRuleWalker->GetCurrentNode();
|
||||
nsRuleNode* lastAgentRN = aRuleWalker->GetCurrentNode();
|
||||
|
||||
mRuleWalker->SetLevel(ePresHintSheet, PR_FALSE);
|
||||
aRuleWalker->SetLevel(ePresHintSheet, PR_FALSE);
|
||||
if (mRuleProcessors[ePresHintSheet])
|
||||
(*aCollectorFunc)(mRuleProcessors[ePresHintSheet], aData);
|
||||
nsRuleNode* lastPresHintRN = mRuleWalker->GetCurrentNode();
|
||||
nsRuleNode* lastPresHintRN = aRuleWalker->GetCurrentNode();
|
||||
|
||||
mRuleWalker->SetLevel(eUserSheet, PR_FALSE);
|
||||
aRuleWalker->SetLevel(eUserSheet, PR_FALSE);
|
||||
PRBool skipUserStyles =
|
||||
aData->mContent && aData->mContent->IsInNativeAnonymousSubtree();
|
||||
if (!skipUserStyles && mRuleProcessors[eUserSheet]) // NOTE: different
|
||||
(*aCollectorFunc)(mRuleProcessors[eUserSheet], aData);
|
||||
nsRuleNode* lastUserRN = mRuleWalker->GetCurrentNode();
|
||||
nsRuleNode* lastUserRN = aRuleWalker->GetCurrentNode();
|
||||
|
||||
mRuleWalker->SetLevel(eHTMLPresHintSheet, PR_FALSE);
|
||||
aRuleWalker->SetLevel(eHTMLPresHintSheet, PR_FALSE);
|
||||
if (mRuleProcessors[eHTMLPresHintSheet])
|
||||
(*aCollectorFunc)(mRuleProcessors[eHTMLPresHintSheet], aData);
|
||||
nsRuleNode* lastHTMLPresHintRN = mRuleWalker->GetCurrentNode();
|
||||
nsRuleNode* lastHTMLPresHintRN = aRuleWalker->GetCurrentNode();
|
||||
|
||||
mRuleWalker->SetLevel(eDocSheet, PR_FALSE);
|
||||
aRuleWalker->SetLevel(eDocSheet, PR_FALSE);
|
||||
PRBool cutOffInheritance = PR_FALSE;
|
||||
if (mBindingManager) {
|
||||
// We can supply additional document-level sheets that should be walked.
|
||||
|
@ -578,32 +559,32 @@ nsStyleSet::FileRules(nsIStyleRuleProcessor::EnumFunc aCollectorFunc,
|
|||
if (!skipUserStyles && !cutOffInheritance &&
|
||||
mRuleProcessors[eDocSheet]) // NOTE: different
|
||||
(*aCollectorFunc)(mRuleProcessors[eDocSheet], aData);
|
||||
mRuleWalker->SetLevel(eStyleAttrSheet, PR_FALSE);
|
||||
aRuleWalker->SetLevel(eStyleAttrSheet, PR_FALSE);
|
||||
if (mRuleProcessors[eStyleAttrSheet])
|
||||
(*aCollectorFunc)(mRuleProcessors[eStyleAttrSheet], aData);
|
||||
nsRuleNode* lastDocRN = mRuleWalker->GetCurrentNode();
|
||||
nsRuleNode* lastDocRN = aRuleWalker->GetCurrentNode();
|
||||
|
||||
mRuleWalker->SetLevel(eOverrideSheet, PR_FALSE);
|
||||
aRuleWalker->SetLevel(eOverrideSheet, PR_FALSE);
|
||||
if (mRuleProcessors[eOverrideSheet])
|
||||
(*aCollectorFunc)(mRuleProcessors[eOverrideSheet], aData);
|
||||
nsRuleNode* lastOvrRN = mRuleWalker->GetCurrentNode();
|
||||
nsRuleNode* lastOvrRN = aRuleWalker->GetCurrentNode();
|
||||
|
||||
mRuleWalker->SetLevel(eDocSheet, PR_TRUE);
|
||||
AddImportantRules(lastDocRN, lastHTMLPresHintRN); // doc
|
||||
mRuleWalker->SetLevel(eOverrideSheet, PR_TRUE);
|
||||
AddImportantRules(lastOvrRN, lastDocRN); // override
|
||||
aRuleWalker->SetLevel(eDocSheet, PR_TRUE);
|
||||
AddImportantRules(lastDocRN, lastHTMLPresHintRN, aRuleWalker); // doc
|
||||
aRuleWalker->SetLevel(eOverrideSheet, PR_TRUE);
|
||||
AddImportantRules(lastOvrRN, lastDocRN, aRuleWalker); // override
|
||||
#ifdef DEBUG
|
||||
AssertNoCSSRules(lastHTMLPresHintRN, lastUserRN);
|
||||
AssertNoImportantRules(lastHTMLPresHintRN, lastUserRN); // HTML preshints
|
||||
#endif
|
||||
mRuleWalker->SetLevel(eUserSheet, PR_TRUE);
|
||||
AddImportantRules(lastUserRN, lastPresHintRN); //user
|
||||
aRuleWalker->SetLevel(eUserSheet, PR_TRUE);
|
||||
AddImportantRules(lastUserRN, lastPresHintRN, aRuleWalker); //user
|
||||
#ifdef DEBUG
|
||||
AssertNoCSSRules(lastPresHintRN, lastAgentRN);
|
||||
AssertNoImportantRules(lastPresHintRN, lastAgentRN); // preshints
|
||||
#endif
|
||||
mRuleWalker->SetLevel(eAgentSheet, PR_TRUE);
|
||||
AddImportantRules(lastAgentRN, nsnull); //agent
|
||||
aRuleWalker->SetLevel(eAgentSheet, PR_TRUE);
|
||||
AddImportantRules(lastAgentRN, nsnull, aRuleWalker); //agent
|
||||
|
||||
}
|
||||
|
||||
|
@ -691,13 +672,11 @@ nsStyleSet::ResolveStyleFor(nsIContent* aContent,
|
|||
"content must be element");
|
||||
|
||||
if (aContent && presContext) {
|
||||
NS_ASSERTION(mRuleWalker->AtRoot(), "rule walker must be at root");
|
||||
ElementRuleProcessorData data(presContext, aContent, mRuleWalker);
|
||||
FileRules(EnumRulesMatching, &data);
|
||||
result = GetContext(presContext, aParentContext, nsnull).get();
|
||||
|
||||
// Now reset the walker back to the root of the tree.
|
||||
mRuleWalker->Reset();
|
||||
nsRuleWalker ruleWalker(mRuleTree);
|
||||
ElementRuleProcessorData data(presContext, aContent, &ruleWalker);
|
||||
FileRules(EnumRulesMatching, &data, &ruleWalker);
|
||||
result = GetContext(presContext, aParentContext,
|
||||
ruleWalker.GetCurrentNode(), nsnull).get();
|
||||
}
|
||||
|
||||
return result;
|
||||
|
@ -714,17 +693,17 @@ nsStyleSet::ResolveStyleForRules(nsStyleContext* aParentContext,
|
|||
nsPresContext *presContext = PresContext();
|
||||
|
||||
if (presContext) {
|
||||
NS_ASSERTION(mRuleWalker->AtRoot(), "rule walker must be at root");
|
||||
nsRuleWalker ruleWalker(mRuleTree);
|
||||
if (aRuleNode)
|
||||
mRuleWalker->SetCurrentNode(aRuleNode);
|
||||
ruleWalker.SetCurrentNode(aRuleNode);
|
||||
// FIXME: Perhaps this should be passed in, but it probably doesn't
|
||||
// matter.
|
||||
mRuleWalker->SetLevel(eDocSheet, PR_FALSE);
|
||||
ruleWalker.SetLevel(eDocSheet, PR_FALSE);
|
||||
for (PRInt32 i = 0; i < aRules.Count(); i++) {
|
||||
mRuleWalker->Forward(aRules.ObjectAt(i));
|
||||
ruleWalker.Forward(aRules.ObjectAt(i));
|
||||
}
|
||||
result = GetContext(presContext, aParentContext, aPseudoTag).get();
|
||||
NS_ASSERTION(mRuleWalker->AtRoot(), "rule walker must be at root");
|
||||
result = GetContext(presContext, aParentContext,
|
||||
ruleWalker.GetCurrentNode(), aPseudoTag).get();
|
||||
}
|
||||
return result;
|
||||
}
|
||||
|
@ -736,25 +715,24 @@ nsStyleSet::ResolveStyleForNonElement(nsStyleContext* aParentContext)
|
|||
nsPresContext *presContext = PresContext();
|
||||
|
||||
if (presContext) {
|
||||
NS_ASSERTION(mRuleWalker->AtRoot(), "rule walker must be at root");
|
||||
result = GetContext(presContext, aParentContext,
|
||||
result = GetContext(presContext, aParentContext, mRuleTree,
|
||||
nsCSSAnonBoxes::mozNonElement).get();
|
||||
NS_ASSERTION(mRuleWalker->AtRoot(), "rule walker must be at root");
|
||||
}
|
||||
|
||||
return result;
|
||||
}
|
||||
|
||||
void
|
||||
nsStyleSet::WalkRestrictionRule(nsIAtom* aPseudoType)
|
||||
nsStyleSet::WalkRestrictionRule(nsIAtom* aPseudoType,
|
||||
nsRuleWalker* aRuleWalker)
|
||||
{
|
||||
// This needs to match GetPseudoRestriction in nsRuleNode.cpp.
|
||||
if (aPseudoType) {
|
||||
mRuleWalker->SetLevel(eAgentSheet, PR_FALSE);
|
||||
aRuleWalker->SetLevel(eAgentSheet, PR_FALSE);
|
||||
if (aPseudoType == nsCSSPseudoElements::firstLetter)
|
||||
mRuleWalker->Forward(mFirstLetterRule);
|
||||
aRuleWalker->Forward(mFirstLetterRule);
|
||||
else if (aPseudoType == nsCSSPseudoElements::firstLine)
|
||||
mRuleWalker->Forward(mFirstLineRule);
|
||||
aRuleWalker->Forward(mFirstLineRule);
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -791,14 +769,14 @@ nsStyleSet::ResolvePseudoStyleFor(nsIContent* aParentContent,
|
|||
"aPseudoTag must be pseudo-element or anonymous box");
|
||||
|
||||
if (aPseudoTag && presContext) {
|
||||
NS_ASSERTION(mRuleWalker->AtRoot(), "rule walker must be at root");
|
||||
nsRuleWalker ruleWalker(mRuleTree);
|
||||
PseudoRuleProcessorData data(presContext, aParentContent, aPseudoTag,
|
||||
aComparator, mRuleWalker);
|
||||
WalkRestrictionRule(aPseudoTag);
|
||||
FileRules(EnumPseudoRulesMatching, &data);
|
||||
aComparator, &ruleWalker);
|
||||
WalkRestrictionRule(aPseudoTag, &ruleWalker);
|
||||
FileRules(EnumPseudoRulesMatching, &data, &ruleWalker);
|
||||
|
||||
result = GetContext(presContext, aParentContext, aPseudoTag).get();
|
||||
NS_ASSERTION(mRuleWalker->AtRoot(), "rule walker must be at root");
|
||||
result = GetContext(presContext, aParentContext,
|
||||
ruleWalker.GetCurrentNode(), aPseudoTag).get();
|
||||
}
|
||||
|
||||
return result;
|
||||
|
@ -828,20 +806,18 @@ nsStyleSet::ProbePseudoStyleFor(nsIContent* aParentContent,
|
|||
"aPseudoTag must be pseudo-element or anonymous box");
|
||||
|
||||
if (aPseudoTag && presContext) {
|
||||
NS_ASSERTION(mRuleWalker->AtRoot(), "rule walker must be at root");
|
||||
nsRuleWalker ruleWalker(mRuleTree);
|
||||
PseudoRuleProcessorData data(presContext, aParentContent, aPseudoTag,
|
||||
nsnull, mRuleWalker);
|
||||
WalkRestrictionRule(aPseudoTag);
|
||||
nsnull, &ruleWalker);
|
||||
WalkRestrictionRule(aPseudoTag, &ruleWalker);
|
||||
// not the root if there was a restriction rule
|
||||
nsRuleNode *adjustedRoot = mRuleWalker->GetCurrentNode();
|
||||
FileRules(EnumPseudoRulesMatching, &data);
|
||||
nsRuleNode *adjustedRoot = ruleWalker.GetCurrentNode();
|
||||
FileRules(EnumPseudoRulesMatching, &data, &ruleWalker);
|
||||
|
||||
if (mRuleWalker->GetCurrentNode() != adjustedRoot)
|
||||
result = GetContext(presContext, aParentContext, aPseudoTag).get();
|
||||
else
|
||||
mRuleWalker->Reset();
|
||||
|
||||
NS_ASSERTION(mRuleWalker->AtRoot(), "rule walker must be at root");
|
||||
nsRuleNode *ruleNode = ruleWalker.GetCurrentNode();
|
||||
if (ruleNode != adjustedRoot)
|
||||
result =
|
||||
GetContext(presContext, aParentContext, ruleNode, aPseudoTag).get();
|
||||
}
|
||||
|
||||
// For :before and :after pseudo-elements, having display: none or no
|
||||
|
@ -888,9 +864,6 @@ nsStyleSet::BeginShutdown(nsPresContext* aPresContext)
|
|||
void
|
||||
nsStyleSet::Shutdown(nsPresContext* aPresContext)
|
||||
{
|
||||
delete mRuleWalker;
|
||||
mRuleWalker = nsnull;
|
||||
|
||||
mRuleTree->Destroy();
|
||||
mRuleTree = nsnull;
|
||||
|
||||
|
@ -915,8 +888,6 @@ nsStyleSet::NotifyStyleContextDestroyed(nsPresContext* aPresContext,
|
|||
if (mInShutdown)
|
||||
return;
|
||||
|
||||
NS_ASSERTION(mRuleWalker->AtRoot(), "Rule walker should be at root");
|
||||
|
||||
// Remove style contexts from mRoots even if mOldRuleTree is non-null. This
|
||||
// could be a style context from the new ruletree!
|
||||
if (!aStyleContext->GetParent()) {
|
||||
|
@ -978,13 +949,10 @@ nsStyleSet::ReParentStyleContext(nsPresContext* aPresContext,
|
|||
}
|
||||
else { // really a new parent
|
||||
nsIAtom* pseudoTag = aStyleContext->GetPseudoType();
|
||||
|
||||
nsRuleNode* ruleNode = aStyleContext->GetRuleNode();
|
||||
mRuleWalker->SetCurrentNode(ruleNode);
|
||||
|
||||
already_AddRefed<nsStyleContext> result =
|
||||
GetContext(aPresContext, aNewParentContext, pseudoTag);
|
||||
NS_ASSERTION(mRuleWalker->AtRoot(), "rule walker must be at root");
|
||||
GetContext(aPresContext, aNewParentContext, ruleNode, pseudoTag);
|
||||
return result;
|
||||
}
|
||||
}
|
||||
|
|
|
@ -275,11 +275,13 @@ class nsStyleSet
|
|||
nsresult GatherRuleProcessors(sheetType aType);
|
||||
|
||||
void AddImportantRules(nsRuleNode* aCurrLevelNode,
|
||||
nsRuleNode* aLastPrevLevelNode);
|
||||
nsRuleNode* aLastPrevLevelNode,
|
||||
nsRuleWalker* aRuleWalker);
|
||||
|
||||
// Move mRuleWalker 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.
|
||||
void WalkRestrictionRule(nsIAtom* aPseudoType);
|
||||
void WalkRestrictionRule(nsIAtom* aPseudoType,
|
||||
nsRuleWalker* aRuleWalker);
|
||||
|
||||
#ifdef DEBUG
|
||||
// Just like AddImportantRules except it doesn't actually add anything; it
|
||||
|
@ -298,7 +300,7 @@ class nsStyleSet
|
|||
// Enumerate the rules in a way that cares about the order of the
|
||||
// rules.
|
||||
void FileRules(nsIStyleRuleProcessor::EnumFunc aCollectorFunc,
|
||||
RuleProcessorData* aData);
|
||||
RuleProcessorData* aData, 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.
|
||||
|
@ -307,6 +309,7 @@ class nsStyleSet
|
|||
|
||||
already_AddRefed<nsStyleContext> GetContext(nsPresContext* aPresContext,
|
||||
nsStyleContext* aParentContext,
|
||||
nsRuleNode* aRuleNode,
|
||||
nsIAtom* aPseudoTag);
|
||||
|
||||
nsPresContext* PresContext() { return mRuleTree->GetPresContext(); }
|
||||
|
@ -330,8 +333,6 @@ class nsStyleSet
|
|||
nsRuleNode* mRuleTree; // This is the root of our rule tree. It is a
|
||||
// lexicographic tree of matched rules that style
|
||||
// contexts use to look up properties.
|
||||
nsRuleWalker* mRuleWalker; // This is an instance of a rule walker that can
|
||||
// be used to navigate through our tree.
|
||||
|
||||
PRUint32 mUnusedRuleNodeCount; // used to batch rule node GC
|
||||
nsTArray<nsStyleContext*> mRoots; // style contexts with no parent
|
||||
|
|
Загрузка…
Ссылка в новой задаче