diff --git a/layout/style/crashtests/147777-1.html b/layout/style/crashtests/147777-1.html
new file mode 100644
index 000000000000..2500fae9fb0f
--- /dev/null
+++ b/layout/style/crashtests/147777-1.html
@@ -0,0 +1,6 @@
+
+
crashtest for NS_ABORT_IF_FALSE during development of 147777
+
+example
diff --git a/layout/style/crashtests/crashtests.list b/layout/style/crashtests/crashtests.list
index 474d070cb1af..a10c7ebae100 100644
--- a/layout/style/crashtests/crashtests.list
+++ b/layout/style/crashtests/crashtests.list
@@ -1,4 +1,5 @@
load 105619-1.html
+load 147777-1.html
load 187671-1.html
load 192408-1.html
load 286707-1.html
diff --git a/layout/style/nsStyleSet.cpp b/layout/style/nsStyleSet.cpp
index fcc1a66327a2..de087ed35655 100644
--- a/layout/style/nsStyleSet.cpp
+++ b/layout/style/nsStyleSet.cpp
@@ -59,6 +59,7 @@
#include "nsContentUtils.h"
#include "nsRuleProcessorData.h"
#include "nsTransitionManager.h"
+#include "nsIEventStateManager.h"
NS_IMPL_ISUPPORTS1(nsEmptyStyleRule, nsIStyleRule)
@@ -435,6 +436,12 @@ nsStyleSet::GetContext(nsStyleContext* aParentContext,
// because aParentContext has one, then aRuleNode
// should be used.)
nsRuleNode* aVisitedRuleNode,
+ // NB: ReparentStyleContext and
+ // ResolveStyleByAddingRules pass bogus values
+ // that work based on what this function is known
+ // to do with aIsLink and aIsVisitedLink
+ PRBool aIsLink,
+ PRBool aIsVisitedLink,
nsIAtom* aPseudoTag,
nsCSSPseudoElements::Type aPseudoType)
{
@@ -472,7 +479,7 @@ nsStyleSet::GetContext(nsStyleContext* aParentContext,
if (aParentContext)
result = aParentContext->FindChildWithRules(aPseudoTag, aRuleNode,
aVisitedRuleNode,
- PR_FALSE);
+ aIsVisitedLink);
#ifdef NOISY_DEBUG
if (result)
@@ -494,6 +501,13 @@ nsStyleSet::GetContext(nsStyleContext* aParentContext,
return nsnull;
}
result->SetStyleIfVisited(resultIfVisited.forget());
+
+ PRBool relevantLinkVisited =
+ aIsLink ? aIsVisitedLink
+ : (aParentContext && aParentContext->RelevantLinkVisited());
+ if (relevantLinkVisited) {
+ result->AddStyleBit(NS_STYLE_RELEVANT_LINK_VISITED);
+ }
}
if (!aParentContext)
mRoots.AppendElement(result);
@@ -798,6 +812,8 @@ nsStyleSet::ResolveStyleFor(nsIContent* aContent,
}
return GetContext(aParentContext, ruleNode, visitedRuleNode,
+ data.IsLink(),
+ (data.ContentState() & NS_EVENT_STATE_VISITED) != 0,
nsnull, nsCSSPseudoElements::ePseudo_NotPseudoElement);
}
@@ -816,6 +832,7 @@ nsStyleSet::ResolveStyleForRules(nsStyleContext* aParentContext,
}
return GetContext(aParentContext, ruleWalker.CurrentNode(), nsnull,
+ PR_FALSE, PR_FALSE,
nsnull, nsCSSPseudoElements::ePseudo_NotPseudoElement);
}
@@ -846,6 +863,9 @@ nsStyleSet::ResolveStyleByAddingRules(nsStyleContext* aBaseContext,
}
return GetContext(aBaseContext->GetParent(), ruleNode, visitedRuleNode,
+ // bogus values for aIsLink and aIsVisitedLink that
+ // we know will make GetContext do the right thing.
+ PR_TRUE, aBaseContext->RelevantLinkVisited(),
aBaseContext->GetPseudo(),
aBaseContext->GetPseudoType());
}
@@ -854,6 +874,7 @@ already_AddRefed
nsStyleSet::ResolveStyleForNonElement(nsStyleContext* aParentContext)
{
return GetContext(aParentContext, mRuleTree, nsnull,
+ PR_FALSE, PR_FALSE,
nsCSSAnonBoxes::mozNonElement,
nsCSSPseudoElements::ePseudo_AnonBox);
}
@@ -901,6 +922,9 @@ nsStyleSet::ResolvePseudoElementStyle(nsIContent* aParentContent,
}
return GetContext(aParentContext, ruleNode, visitedRuleNode,
+ // For pseudos, |data.IsLink()| being true means that
+ // our parent node is a link.
+ PR_FALSE, PR_FALSE,
nsCSSPseudoElements::GetPseudoAtom(aType), aType);
}
@@ -943,6 +967,9 @@ nsStyleSet::ProbePseudoElementStyle(nsIContent* aParentContent,
nsRefPtr result =
GetContext(aParentContext, ruleNode, visitedRuleNode,
+ // For pseudos, |data.IsLink()| being true means that
+ // our parent node is a link.
+ PR_FALSE, PR_FALSE,
pseudoTag, aType);
// For :before and :after pseudo-elements, having display: none or no
@@ -984,6 +1011,7 @@ nsStyleSet::ResolveAnonymousBoxStyle(nsIAtom* aPseudoTag,
&ruleWalker);
return GetContext(aParentContext, ruleWalker.CurrentNode(), nsnull,
+ PR_FALSE, PR_FALSE,
aPseudoTag, nsCSSPseudoElements::ePseudo_AnonBox);
}
@@ -1019,6 +1047,9 @@ nsStyleSet::ResolveXULTreePseudoStyle(nsIContent* aParentContent,
}
return GetContext(aParentContext, ruleNode, visitedRuleNode,
+ // For pseudos, |data.IsLink()| being true means that
+ // our parent node is a link.
+ PR_FALSE, PR_FALSE,
aPseudoTag, nsCSSPseudoElements::ePseudo_XULTree);
}
#endif
@@ -1142,6 +1173,9 @@ nsStyleSet::ReparentStyleContext(nsStyleContext* aStyleContext,
}
return GetContext(aNewParentContext, ruleNode, visitedRuleNode,
+ // bogus values for aIsLink and aIsVisitedLink that
+ // we know will make GetContext do the right thing.
+ PR_TRUE, aStyleContext->RelevantLinkVisited(),
pseudoTag, pseudoType);
}
diff --git a/layout/style/nsStyleSet.h b/layout/style/nsStyleSet.h
index 4c585bf388e4..ac3f1e50f84f 100644
--- a/layout/style/nsStyleSet.h
+++ b/layout/style/nsStyleSet.h
@@ -340,6 +340,8 @@ class nsStyleSet
GetContext(nsStyleContext* aParentContext,
nsRuleNode* aRuleNode,
nsRuleNode* aVisitedRuleNode,
+ PRBool aIsLink,
+ PRBool aIsVisitedLink,
nsIAtom* aPseudoTag,
nsCSSPseudoElements::Type aPseudoType);