зеркало из https://github.com/mozilla/gecko-dev.git
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:
Родитель
09521a0bf2
Коммит
453f48a20f
|
@ -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>
|
Загрузка…
Ссылка в новой задаче