Reset the rule walker before calling NS_NewStyleContext. (Bug 513741) r=bzbarsky
authorL. David Baron <dbaron@dbaron.org>
Tue, 29 Sep 2009 12:24:18 -0700
changeset 33275 320f3de0b43ff00ce67fe267e53d465a8d8b7dec
parent 33274 7f98f7dd1044708d7f7a9431f4c15f530a120c87
child 33276 dab2d59ebd97cf652d26c6b9ee751923f69800b9
push idunknown
push userunknown
push dateunknown
reviewersbzbarsky
bugs513741
milestone1.9.3a1pre
Reset the rule walker before calling NS_NewStyleContext. (Bug 513741) r=bzbarsky
layout/style/nsStyleSet.cpp
--- a/layout/style/nsStyleSet.cpp
+++ b/layout/style/nsStyleSet.cpp
@@ -436,16 +436,19 @@ EnumRulesMatching(nsIStyleRuleProcessor*
  */
 already_AddRefed<nsStyleContext>
 nsStyleSet::GetContext(nsPresContext* aPresContext, 
                        nsStyleContext* aParentContext, 
                        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();
 
 #ifdef NOISY_DEBUG
   if (result)
     fprintf(stdout, "--- SharedSC %d ---\n", ++gSharedCount);
   else
@@ -716,19 +719,17 @@ nsStyleSet::ResolveStyleForRules(nsStyle
       mRuleWalker->SetCurrentNode(aRuleNode);
     // FIXME: Perhaps this should be passed in, but it probably doesn't
     // matter.
     mRuleWalker->SetLevel(eDocSheet, PR_FALSE);
     for (PRInt32 i = 0; i < aRules.Count(); i++) {
       mRuleWalker->Forward(aRules.ObjectAt(i));
     }
     result = GetContext(presContext, aParentContext, aPseudoTag).get();
-
-    // Now reset the walker back to the root of the tree.
-    mRuleWalker->Reset();
+    NS_ASSERTION(mRuleWalker->AtRoot(), "rule walker must be at root");
   }
   return result;
 }
 
 already_AddRefed<nsStyleContext>
 nsStyleSet::ResolveStyleForNonElement(nsStyleContext* aParentContext)
 {
   nsStyleContext* result = nsnull;
@@ -791,19 +792,17 @@ nsStyleSet::ResolvePseudoStyleFor(nsICon
   if (aPseudoTag && presContext) {
     NS_ASSERTION(mRuleWalker->AtRoot(), "rule walker must be at root");
     PseudoRuleProcessorData data(presContext, aParentContent, aPseudoTag,
                                  aComparator, mRuleWalker);
     WalkRestrictionRule(aPseudoTag);
     FileRules(EnumPseudoRulesMatching, &data);
 
     result = GetContext(presContext, aParentContext, aPseudoTag).get();
-
-    // Now reset the walker back to the root of the tree.
-    mRuleWalker->Reset();
+    NS_ASSERTION(mRuleWalker->AtRoot(), "rule walker must be at root");
   }
 
   return result;
 }
 
 already_AddRefed<nsStyleContext>
 nsStyleSet::ProbePseudoStyleFor(nsIContent* aParentContent,
                                 nsIAtom* aPseudoTag,
@@ -833,19 +832,20 @@ nsStyleSet::ProbePseudoStyleFor(nsIConte
                                  nsnull, mRuleWalker);
     WalkRestrictionRule(aPseudoTag);
     // not the root if there was a restriction rule
     nsRuleNode *adjustedRoot = mRuleWalker->GetCurrentNode();
     FileRules(EnumPseudoRulesMatching, &data);
 
     if (mRuleWalker->GetCurrentNode() != adjustedRoot)
       result = GetContext(presContext, aParentContext, aPseudoTag).get();
+    else
+      mRuleWalker->Reset();
 
-    // Now reset the walker back to the root of the tree.
-    mRuleWalker->Reset();
+    NS_ASSERTION(mRuleWalker->AtRoot(), "rule walker must be at root");
   }
 
   // For :before and :after pseudo-elements, having display: none or no
   // 'content' property is equivalent to not having the pseudo-element
   // at all.
   if (result &&
       (aPseudoTag == nsCSSPseudoElements::before ||
        aPseudoTag == nsCSSPseudoElements::after)) {
@@ -900,17 +900,17 @@ nsStyleSet::Shutdown(nsPresContext* aPre
     --i;
     mOldRuleTrees[i]->Destroy();
   }
   mOldRuleTrees.Clear();
 
   mDefaultStyleData.Destroy(0, aPresContext);
 }
 
-static const PRInt32 kGCInterval = 300;
+static const PRUint32 kGCInterval = 300;
 
 void
 nsStyleSet::NotifyStyleContextDestroyed(nsPresContext* aPresContext,
                                         nsStyleContext* aStyleContext)
 {
   if (mInShutdown)
     return;
 
@@ -978,17 +978,17 @@ nsStyleSet::ReParentStyleContext(nsPresC
     else {  // really a new parent
       nsIAtom* pseudoTag = aStyleContext->GetPseudoType();
 
       nsRuleNode* ruleNode = aStyleContext->GetRuleNode();
       mRuleWalker->SetCurrentNode(ruleNode);
 
       already_AddRefed<nsStyleContext> result =
           GetContext(aPresContext, aNewParentContext, pseudoTag);
-      mRuleWalker->Reset();
+      NS_ASSERTION(mRuleWalker->AtRoot(), "rule walker must be at root");
       return result;
     }
   }
   return nsnull;
 }
 
 struct StatefulData : public StateRuleProcessorData {
   StatefulData(nsPresContext* aPresContext,