Make style contexts know if they are the if-visited style. (Bug 557287) r=bzbarsky
authorL. David Baron <dbaron@dbaron.org>
Tue, 06 Apr 2010 12:42:41 -0700
changeset 40497 8eba981e2c9f1291cc5cb5c933b548d1a5d9a7a4
parent 40496 3f7faac350f1b2fc905b5675f76421536f376be5
child 40498 363849c0170b1493960b7ed527cef775401ec43b
push id12634
push userdbaron@mozilla.com
push dateTue, 06 Apr 2010 19:43:29 +0000
treeherdermozilla-central@aa2b262d938a [default view] [failures only]
perfherder[talos] [build metrics] [platform microbench] (compared to previous push)
reviewersbzbarsky
bugs557287
milestone1.9.3a4pre
first release with
nightly linux32
nightly linux64
nightly mac
nightly win32
nightly win64
last release without
nightly linux32
nightly linux64
nightly mac
nightly win32
Make style contexts know if they are the if-visited style. (Bug 557287) r=bzbarsky
layout/style/nsStyleContext.cpp
layout/style/nsStyleContext.h
layout/style/nsStyleSet.cpp
layout/style/nsStyleStruct.h
--- a/layout/style/nsStyleContext.cpp
+++ b/layout/style/nsStyleContext.cpp
@@ -180,16 +180,17 @@ nsStyleContext::FindChildWithRules(const
   nsStyleContext* result = nsnull;
   nsStyleContext *list = aRuleNode->IsRoot() ? mEmptyChild : mChild;
 
   if (list) {
     nsStyleContext *child = list;
     do {
       if (child->mRuleNode == aRuleNode &&
           child->mPseudoTag == aPseudoTag &&
+          !child->IsStyleIfVisited() &&
           child->RelevantLinkVisited() == aRelevantLinkVisited) {
         PRBool match = PR_FALSE;
         if (aRulesIfVisited) {
           match = child->GetStyleIfVisited() &&
                   child->GetStyleIfVisited()->mRuleNode == aRulesIfVisited;
         } else {
           match = !child->GetStyleIfVisited();
         }
--- a/layout/style/nsStyleContext.h
+++ b/layout/style/nsStyleContext.h
@@ -140,16 +140,26 @@ public:
     { return !!(mBits & NS_STYLE_HAS_PSEUDO_ELEMENT_DATA); }
 
   // Is the only link whose visitedness is allowed to influence the
   // style of the node this style context is for (which is that element
   // or its nearest ancestor that is a link) visited?
   PRBool RelevantLinkVisited() const
     { return !!(mBits & NS_STYLE_RELEVANT_LINK_VISITED); }
 
+  // Is this style context the GetStyleIfVisited() for some other style
+  // context?
+  PRBool IsStyleIfVisited() const
+    { return !!(mBits & NS_STYLE_IS_STYLE_IF_VISITED); }
+
+  // Tells this style context that it should return true from
+  // IsStyleIfVisited.
+  void SetIsStyleIfVisited()
+    { mBits |= NS_STYLE_IS_STYLE_IF_VISITED; }
+
   // Return the style context whose style data should be used for the R,
   // G, and B components of color, background-color, and border-*-color
   // if RelevantLinkIsVisited().
   //
   // GetPseudo() and GetPseudoType() on this style context return the
   // same as on |this|, and its depth in the tree (number of GetParent()
   // calls until null is returned) is the same as |this|, since its
   // parent is either |this|'s parent or |this|'s parent's
@@ -160,16 +170,21 @@ public:
   // both (1) lead to a privacy leak and (2) lead to dynamic change bugs
   // related to the Peek code in nsStyleContext::CalcStyleDifference.
   nsStyleContext* GetStyleIfVisited()
     { return mStyleIfVisited; }
 
   // To be called only from nsStyleSet.
   void SetStyleIfVisited(already_AddRefed<nsStyleContext> aStyleIfVisited)
   {
+    NS_ABORT_IF_FALSE(!IsStyleIfVisited(), "this context is not visited data");
+    NS_ABORT_IF_FALSE(aStyleIfVisited.get()->IsStyleIfVisited(),
+                      "other context is visited data");
+    NS_ABORT_IF_FALSE(!aStyleIfVisited.get()->GetStyleIfVisited(),
+                      "other context does not have visited data");
     NS_ASSERTION(!mStyleIfVisited, "should only be set once");
     mStyleIfVisited = aStyleIfVisited;
 
     NS_ASSERTION(GetStyleIfVisited()->GetPseudo() == GetPseudo(),
                  "pseudo tag mismatch");
     if (GetParent() && GetParent()->GetStyleIfVisited()) {
       NS_ASSERTION(GetStyleIfVisited()->GetParent() ==
                      GetParent()->GetStyleIfVisited() ||
--- a/layout/style/nsStyleSet.cpp
+++ b/layout/style/nsStyleSet.cpp
@@ -495,16 +495,17 @@ nsStyleSet::GetContext(nsStyleContext* a
       return nsnull;
     if (aVisitedRuleNode) {
       nsRefPtr<nsStyleContext> resultIfVisited =
         NS_NewStyleContext(parentIfVisited, aPseudoTag, aPseudoType,
                            aVisitedRuleNode, PresContext());
       if (!resultIfVisited) {
         return nsnull;
       }
+      resultIfVisited->SetIsStyleIfVisited();
       result->SetStyleIfVisited(resultIfVisited.forget());
 
       PRBool relevantLinkVisited =
         aIsLink ? aIsVisitedLink
                 : (aParentContext && aParentContext->RelevantLinkVisited());
       if (relevantLinkVisited) {
         result->AddStyleBit(NS_STYLE_RELEVANT_LINK_VISITED);
       }
--- a/layout/style/nsStyleStruct.h
+++ b/layout/style/nsStyleStruct.h
@@ -81,16 +81,18 @@ class imgIContainer;
 
 // Additional bits for nsStyleContext's mBits:
 // See nsStyleContext::HasTextDecorations
 #define NS_STYLE_HAS_TEXT_DECORATIONS     0x01000000
 // See nsStyleContext::HasPseudoElementData.
 #define NS_STYLE_HAS_PSEUDO_ELEMENT_DATA  0x02000000
 // See nsStyleContext::RelevantLinkIsVisited
 #define NS_STYLE_RELEVANT_LINK_VISITED    0x04000000
+// See nsStyleContext::IsStyleIfVisited
+#define NS_STYLE_IS_STYLE_IF_VISITED      0x08000000
 // See nsStyleContext::GetPseudoEnum
 #define NS_STYLE_CONTEXT_TYPE_MASK        0xf0000000
 #define NS_STYLE_CONTEXT_TYPE_SHIFT       28
 
 // Additional bits for nsRuleNode's mDependentBits:
 #define NS_RULE_NODE_GC_MARK              0x02000000
 #define NS_RULE_NODE_IS_IMPORTANT         0x08000000
 #define NS_RULE_NODE_LEVEL_MASK           0xf0000000