Bug 525952 part 1. Make sure pseudo-element selectors never land inside SelectorMatches (because tree pseudo-elements do weird stuff with pseudo-classes). r=dbaron

This commit is contained in:
Boris Zbarsky 2009-12-10 14:36:07 -08:00
Родитель 09521a0bf2
Коммит 453f48a20f
5 изменённых файлов: 79 добавлений и 2 удалений

Просмотреть файл

@ -5140,6 +5140,8 @@ nsGenericElement::GetLinkTarget(nsAString& aTarget)
} }
// NOTE: The aPresContext pointer is NOT addrefed. // NOTE: The aPresContext pointer is NOT addrefed.
// *aSelectorList might be null even if NS_OK is returned; this
// happens when all the selectors were pseudo-element selectors.
static nsresult static nsresult
ParseSelectorList(nsINode* aNode, ParseSelectorList(nsINode* aNode,
const nsAString& aSelectorString, const nsAString& aSelectorString,
@ -5155,13 +5157,28 @@ ParseSelectorList(nsINode* aNode,
nsresult rv = doc->CSSLoader()->GetParserFor(nsnull, getter_AddRefs(parser)); nsresult rv = doc->CSSLoader()->GetParserFor(nsnull, getter_AddRefs(parser));
NS_ENSURE_SUCCESS(rv, rv); NS_ENSURE_SUCCESS(rv, rv);
nsCSSSelectorList* selectorList;
rv = parser->ParseSelectorString(aSelectorString, rv = parser->ParseSelectorString(aSelectorString,
doc->GetDocumentURI(), doc->GetDocumentURI(),
0, // XXXbz get the right line number! 0, // XXXbz get the right line number!
aSelectorList); &selectorList);
doc->CSSLoader()->RecycleParser(parser); doc->CSSLoader()->RecycleParser(parser);
NS_ENSURE_SUCCESS(rv, rv); NS_ENSURE_SUCCESS(rv, rv);
// Filter out pseudo-element selectors from selectorList
nsCSSSelectorList** slot = &selectorList;
do {
nsCSSSelectorList* cur = *slot;
if (cur->mSelectors->IsPseudoElement()) {
*slot = cur->mNext;
cur->mNext = nsnull;
delete cur;
} else {
slot = &cur->mNext;
}
} while (*slot);
*aSelectorList = selectorList;
// It's not strictly necessary to have a prescontext here, but it's // It's not strictly necessary to have a prescontext here, but it's
// a bit of an optimization for various stuff. // a bit of an optimization for various stuff.
*aPresContext = nsnull; *aPresContext = nsnull;

Просмотреть файл

@ -1278,6 +1278,8 @@ static PRBool SelectorMatches(RuleProcessorData &data,
PRBool* const aDependence = nsnull) PRBool* const aDependence = nsnull)
{ {
NS_PRECONDITION(!aSelector->IsPseudoElement(),
"Pseudo-element snuck into SelectorMatches?");
// namespace/tag match // namespace/tag match
// optimization : bail out early if we can // optimization : bail out early if we can
if ((kNameSpaceID_Unknown != aSelector->mNameSpace && if ((kNameSpaceID_Unknown != aSelector->mNameSpace &&
@ -2421,6 +2423,13 @@ AddRule(RuleValue* aRuleInfo, RuleCascadeData* aCascade)
for (nsCSSSelector* selector = aRuleInfo->mSelector; for (nsCSSSelector* selector = aRuleInfo->mSelector;
selector; selector = selector->mNext) { selector; selector = selector->mNext) {
if (selector->IsPseudoElement()) {
NS_ASSERTION(!selector->mNegations, "Shouldn't have negations");
// Make sure these selectors don't end up in the hashtables we use to
// match against actual elements, no matter what. Normally they wouldn't
// anyway, but trees overload mPseudoClassList with weird stuff.
continue;
}
// It's worth noting that this loop over negations isn't quite // It's worth noting that this loop over negations isn't quite
// optimal for two reasons. One, we could add something to one of // optimal for two reasons. One, we could add something to one of
// these lists twice, which means we'll check it twice, but I don't // these lists twice, which means we'll check it twice, but I don't
@ -2736,6 +2745,7 @@ nsCSSRuleProcessor::SelectorListMatches(RuleProcessorData& aData,
while (aSelectorList) { while (aSelectorList) {
nsCSSSelector* sel = aSelectorList->mSelectors; nsCSSSelector* sel = aSelectorList->mSelectors;
NS_ASSERTION(sel, "Should have *some* selectors"); NS_ASSERTION(sel, "Should have *some* selectors");
NS_ASSERTION(!sel->IsPseudoElement(), "Shouldn't have been called");
if (SelectorMatches(aData, sel, 0, PR_FALSE)) { if (SelectorMatches(aData, sel, 0, PR_FALSE)) {
nsCSSSelector* next = sel->mNext; nsCSSSelector* next = sel->mNext;
if (!next || SelectorMatchesTree(aData, next, PR_FALSE)) { if (!next || SelectorMatchesTree(aData, next, PR_FALSE)) {

Просмотреть файл

@ -83,7 +83,9 @@ public:
/* /*
* Returns true if the given RuleProcessorData matches one of the * Returns true if the given RuleProcessorData matches one of the
* selectors in aSelectorList. Note that this method will assume * selectors in aSelectorList. Note that this method will assume
* the matching is not for styling purposes. * the matching is not for styling purposes. aSelectorList must not
* include any pseudo-element selectors. aSelectorList is allowed
* to be null; in this case PR_FALSE will be returned.
*/ */
static PRBool SelectorListMatches(RuleProcessorData& aData, static PRBool SelectorListMatches(RuleProcessorData& aData,
nsCSSSelectorList* aSelectorList); nsCSSSelectorList* aSelectorList);

Просмотреть файл

@ -172,6 +172,7 @@ _TEST_FILES = test_acid3_test46.html \
media_queries_dynamic_xbl_style.css \ media_queries_dynamic_xbl_style.css \
bug453896_iframe.html \ bug453896_iframe.html \
bug517224.sjs \ bug517224.sjs \
test_bug525952.html \
$(NULL) $(NULL)
_BROWSER_FILES = \ _BROWSER_FILES = \

Просмотреть файл

@ -0,0 +1,47 @@
<!DOCTYPE HTML>
<html>
<!--
https://bugzilla.mozilla.org/show_bug.cgi?id=525952
-->
<head>
<title>Test for Bug 525952</title>
<script type="application/javascript" src="/MochiKit/packed.js"></script>
<script type="application/javascript" src="/tests/SimpleTest/SimpleTest.js"></script>
<link rel="stylesheet" type="text/css" href="/tests/SimpleTest/test.css"/>
</head>
<body>
<a target="_blank" href="https://bugzilla.mozilla.org/show_bug.cgi?id=525952">Mozilla Bug 525952</a>
<p id="display"></p>
<div id="content" style="display: none">
</div>
<pre id="test">
<script type="application/javascript">
/** Test for Bug 525952 **/
var bodies = document.querySelectorAll("::before, div::before, body");
is(bodies.length, 1, "Unexpected length");
is(bodies[0], document.body, "Unexpected element");
is(document.querySelector("div > ::after, body"), document.body,
"Unexpected return value");
var emptyList = document.querySelectorAll("::before, div::before");
is(emptyList.length, 0, "Unexpected empty list length");
is(document.querySelectorAll("div > ::after").length, 0,
"Pseudo-element matched something?");
is(document.body.mozMatchesSelector("::first-line"), false,
"body shouldn't match ::first-line");
is(document.body.mozMatchesSelector("::first-line, body"), true,
"body should match 'body'");
is(document.body.mozMatchesSelector("::first-line, body, ::first-letter"), true,
"body should match 'body' here too");
</script>
</pre>
</body>
</html>