mirror of
https://github.com/mozilla/gecko-dev.git
synced 2024-11-30 08:12:05 +00:00
Bug 1364009 - Don't allow comments/spaces between signs,numbers,and n
in an+b syntax for nth-child; r=dbaron
In the an+b syntax, this continues to allow comments and spaces like so: ` an + b `. It does not allow `a n+b`, or `- an+b` or `+ an+b` (and the same for the `an-b` form). Similarly, it does not allow `- b` or `+ b`. Additionally, it *does* allow `+/*comment*/n+b` or `-/*comment*/n+b`, but not `+ n+b` or `-n+b`. This is specced; in this one case we parse two tokens but do not allow whitespace in between. MozReview-Commit-ID: INzFGeMPeK7 --HG-- extra : rebase_source : ca5bcf4034759823f79b9a925dc72998d8f0218b
This commit is contained in:
parent
b3c51a3e2d
commit
652a30c309
@ -4,24 +4,20 @@
|
||||
<title>Tests :nth-child(An+B) matching</title>
|
||||
<style type="text/css">
|
||||
|
||||
div :nth-child(+/**/3n-2) { color:white; }
|
||||
div :nth-child(+3n/**/-2) { background-color:black; }
|
||||
div :nth-child(+3n/**/-2) { font-size:12px; }
|
||||
div :nth-child(+3n-/**/2) { text-decoration: underline; }
|
||||
div :nth-child(+3n-2/**/) { border-left-width: 1px; }
|
||||
div :nth-child(+3/**/n-2) { border-right-width: 1px; }
|
||||
div :nth-child(+3n/**/-2) { border-top-width: 1px; }
|
||||
div :nth-child(+3n/**/-2) { border-bottom-width: 1px; }
|
||||
div :nth-child(+3n-/**/2) { border-style: solid; }
|
||||
div :nth-child(+3n-2/**/) { border-color: blue; }
|
||||
div :nth-child(+3n-/**/2) { border-right-width: 1px; }
|
||||
div :nth-child(+3n-2/**/) { border-style: solid; border-color: blue;}
|
||||
|
||||
/* valid but will not match anything */
|
||||
div :nth-child(-/**/n-2) { color:red; }
|
||||
div :nth-child(-n/**/-2) { color:red; }
|
||||
div :nth-child(-n/**/-2) { color:red; }
|
||||
div :nth-child(-n-/**/2) { color:red; }
|
||||
div :nth-child(-n-2/**/) { color:red; }
|
||||
div :nth-child(-1/**/n-2) { color:red; }
|
||||
div :nth-child(-1n/**/-2) { color:red; }
|
||||
div :nth-child(-1n/**/-2) { color:red; }
|
||||
div :nth-child(-1n-/**/2) { color:red; }
|
||||
@ -32,6 +28,8 @@
|
||||
div :nth-child(- /**/n-2) { color:red; }
|
||||
div :nth-child(+/**/ n-2) { color:red; }
|
||||
div :nth-child(+ /**/n-2) { color:red; }
|
||||
div :nth-child(+3/**/n-2) { color:red; }
|
||||
div :nth-child(-/**/n-2) {color: red;}
|
||||
|
||||
</style>
|
||||
</head>
|
||||
|
@ -4,24 +4,20 @@
|
||||
<title>Tests :nth-child(An+B) matching</title>
|
||||
<style type="text/css">
|
||||
|
||||
div :nth-child(+/**/3N-2) { color:white; }
|
||||
div :nth-child(+3N/**/-2) { background-color:black; }
|
||||
div :nth-child(+3N/**/-2) { font-size:12px; }
|
||||
div :nth-child(+3N-/**/2) { text-decoration: underline; }
|
||||
div :nth-child(+3N-2/**/) { border-left-width: 1px; }
|
||||
div :nth-child(+3/**/N-2) { border-right-width: 1px; }
|
||||
div :nth-child(+3N/**/-2) { border-top-width: 1px; }
|
||||
div :nth-child(+3N/**/-2) { border-bottom-width: 1px; }
|
||||
div :nth-child(+3N-/**/2) { border-style: solid; }
|
||||
div :nth-child(+3N-2/**/) { border-color: blue; }
|
||||
div :nth-child(+3N-/**/2) { border-right-width: 1px; }
|
||||
div :nth-child(+3N-2/**/) { border-style: solid; border-color: blue;}
|
||||
|
||||
/* valid but will not match anything */
|
||||
div :nth-child(-/**/N-2) { color:red; }
|
||||
div :nth-child(-N/**/-2) { color:red; }
|
||||
div :nth-child(-N/**/-2) { color:red; }
|
||||
div :nth-child(-N-/**/2) { color:red; }
|
||||
div :nth-child(-N-2/**/) { color:red; }
|
||||
div :nth-child(-1/**/N-2) { color:red; }
|
||||
div :nth-child(-1N/**/-2) { color:red; }
|
||||
div :nth-child(-1N/**/-2) { color:red; }
|
||||
div :nth-child(-1N-/**/2) { color:red; }
|
||||
@ -32,6 +28,8 @@
|
||||
div :nth-child(- /**/N-2) { color:red; }
|
||||
div :nth-child(+/**/ N-2) { color:red; }
|
||||
div :nth-child(+ /**/N-2) { color:red; }
|
||||
div :nth-child(+3/**/N-2) { color:red; }
|
||||
div :nth-child(-/**/N-2) {color: red;}
|
||||
|
||||
</style>
|
||||
</head>
|
||||
|
@ -4,7 +4,6 @@
|
||||
<title>Tests :nth-child(An+B) matching</title>
|
||||
<style type="text/css">
|
||||
|
||||
x { color:white; }
|
||||
x { background-color:black; }
|
||||
x { font-size:12px; }
|
||||
x { text-decoration: underline; }
|
||||
@ -12,8 +11,7 @@
|
||||
x { border-right-width: 1px; }
|
||||
x { border-top-width: 1px; }
|
||||
x { border-bottom-width: 1px; }
|
||||
x { border-style: solid; }
|
||||
x { border-color: blue; }
|
||||
x { border-style: solid; border-color: blue;}
|
||||
|
||||
</style>
|
||||
</head>
|
||||
|
@ -2,5 +2,5 @@
|
||||
== attr-case-insensitive-1.html attr-case-insensitive-1-ref.html
|
||||
== sibling-combinators-on-anon-content-1.xhtml sibling-combinators-on-anon-content-ref.xhtml
|
||||
== sibling-combinators-on-anon-content-2.xhtml sibling-combinators-on-anon-content-ref.xhtml
|
||||
fails-if(styloVsGecko||stylo) == nth-child-1.html nth-child-ref.html
|
||||
fails-if(styloVsGecko||stylo) == nth-child-2.html nth-child-ref.html
|
||||
== nth-child-1.html nth-child-ref.html
|
||||
== nth-child-2.html nth-child-ref.html
|
||||
|
@ -6331,9 +6331,10 @@ CSSParserImpl::ParsePseudoClassWithNthPairArg(nsCSSSelector& aSelector,
|
||||
CSSPseudoClassType aType)
|
||||
{
|
||||
int32_t numbers[2] = { 0, 0 };
|
||||
int32_t sign[2] = { 1, 1 };
|
||||
bool hasSign[2] = { false, false };
|
||||
bool lookForB = true;
|
||||
bool onlyN = false;
|
||||
int hasSign = false;
|
||||
int sign = 1;
|
||||
|
||||
// Follow the whitespace rules as proposed in
|
||||
// http://lists.w3.org/Archives/Public/www-style/2008Mar/0121.html
|
||||
@ -6343,17 +6344,6 @@ CSSParserImpl::ParsePseudoClassWithNthPairArg(nsCSSSelector& aSelector,
|
||||
return eSelectorParsingStatus_Error;
|
||||
}
|
||||
|
||||
if (mToken.IsSymbol('+') || mToken.IsSymbol('-')) {
|
||||
hasSign[0] = true;
|
||||
if (mToken.IsSymbol('-')) {
|
||||
sign[0] = -1;
|
||||
}
|
||||
if (! GetToken(false)) {
|
||||
REPORT_UNEXPECTED_EOF(PEPseudoClassArgEOF);
|
||||
return eSelectorParsingStatus_Error;
|
||||
}
|
||||
}
|
||||
|
||||
// A helper function that checks if the token starts with literal string
|
||||
// |aStr| using a case-insensitive match.
|
||||
auto TokenBeginsWith = [this] (const nsLiteralString& aStr) {
|
||||
@ -6361,6 +6351,21 @@ CSSParserImpl::ParsePseudoClassWithNthPairArg(nsCSSSelector& aSelector,
|
||||
nsASCIICaseInsensitiveStringComparator());
|
||||
};
|
||||
|
||||
if (mToken.IsSymbol('+') || mToken.IsSymbol('-')) {
|
||||
// This can only be +n or -n, since +an, -an, +a, -a will all
|
||||
// parse a number as the first token.
|
||||
numbers[0] = mToken.IsSymbol('+') ? 1 : -1;
|
||||
onlyN = true;
|
||||
|
||||
// consume the `n`
|
||||
// We do not allow whitespace here
|
||||
// https://drafts.csswg.org/css-syntax-3/#the-anb-type
|
||||
if (! GetToken(false)) {
|
||||
REPORT_UNEXPECTED_EOF(PEPseudoClassArgEOF);
|
||||
return eSelectorParsingStatus_Error; // our caller calls SkipUntil(')')
|
||||
}
|
||||
}
|
||||
|
||||
if (eCSSToken_Ident == mToken.mType || eCSSToken_Dimension == mToken.mType) {
|
||||
// The CSS tokenization doesn't handle :nth-child() containing - well:
|
||||
// 2n-1 is a dimension
|
||||
@ -6370,7 +6375,7 @@ CSSParserImpl::ParsePseudoClassWithNthPairArg(nsCSSSelector& aSelector,
|
||||
uint32_t truncAt = 0;
|
||||
if (TokenBeginsWith(NS_LITERAL_STRING("n-"))) {
|
||||
truncAt = 1;
|
||||
} else if (TokenBeginsWith(NS_LITERAL_STRING("-n-")) && !hasSign[0]) {
|
||||
} else if (TokenBeginsWith(NS_LITERAL_STRING("-n-"))) {
|
||||
truncAt = 2;
|
||||
}
|
||||
if (truncAt != 0) {
|
||||
@ -6379,76 +6384,58 @@ CSSParserImpl::ParsePseudoClassWithNthPairArg(nsCSSSelector& aSelector,
|
||||
}
|
||||
}
|
||||
|
||||
if (eCSSToken_Ident == mToken.mType) {
|
||||
if (mToken.mIdent.LowerCaseEqualsLiteral("odd") && !hasSign[0]) {
|
||||
numbers[0] = 2;
|
||||
numbers[1] = 1;
|
||||
lookForB = false;
|
||||
}
|
||||
else if (mToken.mIdent.LowerCaseEqualsLiteral("even") && !hasSign[0]) {
|
||||
numbers[0] = 2;
|
||||
numbers[1] = 0;
|
||||
lookForB = false;
|
||||
}
|
||||
else if (mToken.mIdent.LowerCaseEqualsLiteral("n")) {
|
||||
numbers[0] = sign[0];
|
||||
}
|
||||
else if (mToken.mIdent.LowerCaseEqualsLiteral("-n") && !hasSign[0]) {
|
||||
numbers[0] = -1;
|
||||
}
|
||||
else {
|
||||
if (onlyN) {
|
||||
// If we parsed a + or -, check that the truncated
|
||||
// token is an "n"
|
||||
if (eCSSToken_Ident != mToken.mType || !mToken.mIdent.LowerCaseEqualsLiteral("n")) {
|
||||
REPORT_UNEXPECTED_TOKEN(PEPseudoClassArgNotNth);
|
||||
return eSelectorParsingStatus_Error; // our caller calls SkipUntil(')')
|
||||
return eSelectorParsingStatus_Error;
|
||||
}
|
||||
}
|
||||
else if (eCSSToken_Number == mToken.mType) {
|
||||
if (!mToken.mIntegerValid) {
|
||||
REPORT_UNEXPECTED_TOKEN(PEPseudoClassArgNotNth);
|
||||
return eSelectorParsingStatus_Error; // our caller calls SkipUntil(')')
|
||||
}
|
||||
// for +-an case
|
||||
if (mToken.mHasSign && hasSign[0]) {
|
||||
REPORT_UNEXPECTED_TOKEN(PEPseudoClassArgNotNth);
|
||||
return eSelectorParsingStatus_Error; // our caller calls SkipUntil(')')
|
||||
}
|
||||
int32_t intValue = mToken.mInteger * sign[0];
|
||||
// for -a/**/n case
|
||||
if (! GetToken(false)) {
|
||||
numbers[1] = intValue;
|
||||
lookForB = false;
|
||||
}
|
||||
else {
|
||||
if (eCSSToken_Ident == mToken.mType && mToken.mIdent.LowerCaseEqualsLiteral("n")) {
|
||||
numbers[0] = intValue;
|
||||
}
|
||||
else if (eCSSToken_Ident == mToken.mType && TokenBeginsWith(NS_LITERAL_STRING("n-"))) {
|
||||
numbers[0] = intValue;
|
||||
mScanner->Backup(mToken.mIdent.Length() - 1);
|
||||
}
|
||||
else {
|
||||
UngetToken();
|
||||
numbers[1] = intValue;
|
||||
} else {
|
||||
if (eCSSToken_Ident == mToken.mType) {
|
||||
if (mToken.mIdent.LowerCaseEqualsLiteral("odd")) {
|
||||
numbers[0] = 2;
|
||||
numbers[1] = 1;
|
||||
lookForB = false;
|
||||
}
|
||||
else if (mToken.mIdent.LowerCaseEqualsLiteral("even")) {
|
||||
numbers[0] = 2;
|
||||
numbers[1] = 0;
|
||||
lookForB = false;
|
||||
}
|
||||
else if (mToken.mIdent.LowerCaseEqualsLiteral("n")) {
|
||||
numbers[0] = 1;
|
||||
}
|
||||
else if (mToken.mIdent.LowerCaseEqualsLiteral("-n")) {
|
||||
numbers[0] = -1;
|
||||
}
|
||||
else {
|
||||
REPORT_UNEXPECTED_TOKEN(PEPseudoClassArgNotNth);
|
||||
return eSelectorParsingStatus_Error; // our caller calls SkipUntil(')')
|
||||
}
|
||||
}
|
||||
}
|
||||
else if (eCSSToken_Dimension == mToken.mType) {
|
||||
if (!mToken.mIntegerValid || !mToken.mIdent.LowerCaseEqualsLiteral("n")) {
|
||||
else if (eCSSToken_Number == mToken.mType) {
|
||||
if (!mToken.mIntegerValid) {
|
||||
REPORT_UNEXPECTED_TOKEN(PEPseudoClassArgNotNth);
|
||||
return eSelectorParsingStatus_Error; // our caller calls SkipUntil(')')
|
||||
}
|
||||
|
||||
numbers[1] = mToken.mInteger;
|
||||
lookForB = false;
|
||||
}
|
||||
else if (eCSSToken_Dimension == mToken.mType) {
|
||||
if (!mToken.mIntegerValid || !mToken.mIdent.LowerCaseEqualsLiteral("n")) {
|
||||
REPORT_UNEXPECTED_TOKEN(PEPseudoClassArgNotNth);
|
||||
return eSelectorParsingStatus_Error; // our caller calls SkipUntil(')')
|
||||
}
|
||||
numbers[0] = mToken.mInteger;
|
||||
}
|
||||
// XXX If it's a ')', is that valid? (as 0n+0)
|
||||
else {
|
||||
REPORT_UNEXPECTED_TOKEN(PEPseudoClassArgNotNth);
|
||||
UngetToken();
|
||||
return eSelectorParsingStatus_Error; // our caller calls SkipUntil(')')
|
||||
}
|
||||
// for +-an case
|
||||
if ( mToken.mHasSign && hasSign[0] ) {
|
||||
REPORT_UNEXPECTED_TOKEN(PEPseudoClassArgNotNth);
|
||||
return eSelectorParsingStatus_Error; // our caller calls SkipUntil(')')
|
||||
}
|
||||
numbers[0] = mToken.mInteger * sign[0];
|
||||
}
|
||||
// XXX If it's a ')', is that valid? (as 0n+0)
|
||||
else {
|
||||
REPORT_UNEXPECTED_TOKEN(PEPseudoClassArgNotNth);
|
||||
UngetToken();
|
||||
return eSelectorParsingStatus_Error; // our caller calls SkipUntil(')')
|
||||
}
|
||||
|
||||
if (! GetToken(true)) {
|
||||
@ -6460,9 +6447,9 @@ CSSParserImpl::ParsePseudoClassWithNthPairArg(nsCSSSelector& aSelector,
|
||||
// If it is separated by whitespace from what follows it, it appears
|
||||
// as a separate token rather than part of the number token.
|
||||
if (mToken.IsSymbol('+') || mToken.IsSymbol('-')) {
|
||||
hasSign[1] = true;
|
||||
hasSign = true;
|
||||
if (mToken.IsSymbol('-')) {
|
||||
sign[1] = -1;
|
||||
sign = -1;
|
||||
}
|
||||
if (! GetToken(true)) {
|
||||
REPORT_UNEXPECTED_EOF(PEPseudoClassArgEOF);
|
||||
@ -6470,12 +6457,12 @@ CSSParserImpl::ParsePseudoClassWithNthPairArg(nsCSSSelector& aSelector,
|
||||
}
|
||||
}
|
||||
if (eCSSToken_Number != mToken.mType ||
|
||||
!mToken.mIntegerValid || mToken.mHasSign == hasSign[1]) {
|
||||
!mToken.mIntegerValid || mToken.mHasSign == hasSign) {
|
||||
REPORT_UNEXPECTED_TOKEN(PEPseudoClassArgNotNth);
|
||||
UngetToken();
|
||||
return eSelectorParsingStatus_Error; // our caller calls SkipUntil(')')
|
||||
}
|
||||
numbers[1] = mToken.mInteger * sign[1];
|
||||
numbers[1] = mToken.mInteger * sign;
|
||||
if (! GetToken(true)) {
|
||||
REPORT_UNEXPECTED_EOF(PEPseudoClassArgEOF);
|
||||
return eSelectorParsingStatus_Error;
|
||||
|
@ -140,7 +140,7 @@ to mochitest command.
|
||||
|
||||
* test_selectors_on_anonymous_content.html: xbl and :nth-child [1]
|
||||
* test_parse_rule.html `rgb(0, 128, 0)`: color properties not getting computed [5]
|
||||
* test_selectors.html `:nth-child`: <an+b> parsing difference bug 1364009 [14]
|
||||
* test_selectors.html `:nth-child`: https://github.com/servo/rust-cssparser/issues/153 [4]
|
||||
|
||||
## Ignore
|
||||
|
||||
|
@ -647,7 +647,7 @@ function run() {
|
||||
test_parseable(":nth-child(+n/**/+2)");
|
||||
test_parseable(":nth-child(+n+/**/2)");
|
||||
test_parseable(":nth-child(+n+2/**/)");
|
||||
test_parseable(":nth-child(+1/**/n+2)");
|
||||
test_balanced_unparseable(":nth-child(+1/**/n+2)");
|
||||
test_parseable(":nth-child(+1n/**/+2)");
|
||||
test_parseable(":nth-child(+1n/**/+2)");
|
||||
test_parseable(":nth-child(+1n+/**/2)");
|
||||
@ -657,7 +657,7 @@ function run() {
|
||||
test_parseable(":nth-child(-n/**/+2)");
|
||||
test_parseable(":nth-child(-n+/**/2)");
|
||||
test_parseable(":nth-child(-n+2/**/)");
|
||||
test_parseable(":nth-child(-1/**/n+2)");
|
||||
test_balanced_unparseable(":nth-child(-1/**/n+2)");
|
||||
test_parseable(":nth-child(-1n/**/+2)");
|
||||
test_parseable(":nth-child(-1n/**/+2)");
|
||||
test_parseable(":nth-child(-1n+/**/2)");
|
||||
@ -671,7 +671,7 @@ function run() {
|
||||
test_parseable(":nth-child(+n/**/-2)");
|
||||
test_parseable(":nth-child(+n-/**/2)");
|
||||
test_parseable(":nth-child(+n-2/**/)");
|
||||
test_parseable(":nth-child(+1/**/n-2)");
|
||||
test_balanced_unparseable(":nth-child(+1/**/n-2)");
|
||||
test_parseable(":nth-child(+1n/**/-2)");
|
||||
test_parseable(":nth-child(+1n/**/-2)");
|
||||
test_parseable(":nth-child(+1n-/**/2)");
|
||||
@ -681,7 +681,7 @@ function run() {
|
||||
test_parseable(":nth-child(-n/**/-2)");
|
||||
test_parseable(":nth-child(-n-/**/2)");
|
||||
test_parseable(":nth-child(-n-2/**/)");
|
||||
test_parseable(":nth-child(-1/**/n-2)");
|
||||
test_balanced_unparseable(":nth-child(-1/**/n-2)");
|
||||
test_parseable(":nth-child(-1n/**/-2)");
|
||||
test_parseable(":nth-child(-1n/**/-2)");
|
||||
test_parseable(":nth-child(-1n-/**/2)");
|
||||
@ -695,7 +695,7 @@ function run() {
|
||||
test_parseable(":nth-child(+N/**/-2)");
|
||||
test_parseable(":nth-child(+N-/**/2)");
|
||||
test_parseable(":nth-child(+N-2/**/)");
|
||||
test_parseable(":nth-child(+1/**/N-2)");
|
||||
test_balanced_unparseable(":nth-child(+1/**/N-2)");
|
||||
test_parseable(":nth-child(+1N/**/-2)");
|
||||
test_parseable(":nth-child(+1N/**/-2)");
|
||||
test_parseable(":nth-child(+1N-/**/2)");
|
||||
@ -705,7 +705,7 @@ function run() {
|
||||
test_parseable(":nth-child(-N/**/-2)");
|
||||
test_parseable(":nth-child(-N-/**/2)");
|
||||
test_parseable(":nth-child(-N-2/**/)");
|
||||
test_parseable(":nth-child(-1/**/N-2)");
|
||||
test_balanced_unparseable(":nth-child(-1/**/N-2)");
|
||||
test_parseable(":nth-child(-1N/**/-2)");
|
||||
test_parseable(":nth-child(-1N/**/-2)");
|
||||
test_parseable(":nth-child(-1N-/**/2)");
|
||||
@ -716,14 +716,14 @@ function run() {
|
||||
test_balanced_unparseable(":nth-child(+ /**/N-2)");
|
||||
test_parseable(":nth-child( +n + 1 )");
|
||||
test_parseable(":nth-child( +/**/n + 1 )");
|
||||
test_parseable(":nth-child( -/**/2/**/n/**/+/**/4 )");
|
||||
test_balanced_unparseable(":nth-child( -/**/ 2/**/n/**/+/**/4 )");
|
||||
test_balanced_unparseable(":nth-child( -/**/2 /**/n/**/+/**/4 )");
|
||||
test_balanced_unparseable(":nth-child( -/**/2/**/ n/**/+/**/4 )");
|
||||
test_parseable(":nth-child( -/**/2/**/n /**/+/**/4 )");
|
||||
test_parseable(":nth-child( -/**/2/**/n/**/ +/**/4 )");
|
||||
test_parseable(":nth-child(+1/**/n-1)");
|
||||
test_parseable(":nth-child(1/**/n-1)");
|
||||
test_balanced_unparseable(":nth-child( -/**/2/**/n/**/+/**/4 )");
|
||||
test_parseable(":nth-child( -2n/**/ + /**/4 )");
|
||||
test_parseable(":nth-child( -2n/**/+/**/4 )");
|
||||
test_parseable(":nth-child( -2n /**/+/**/4 )");
|
||||
test_parseable(":nth-child( -/**/n /**/+ /**/ 4 )");
|
||||
test_parseable(":nth-child( +/**/n /**/+ /**/ 4 )");
|
||||
test_balanced_unparseable(":nth-child(+1/**/n-1)");
|
||||
test_balanced_unparseable(":nth-child(1/**/n-1)");
|
||||
// bug 876570
|
||||
test_balanced_unparseable(":nth-child(+2n-)");
|
||||
test_balanced_unparseable(":nth-child(+n-)");
|
||||
|
Loading…
Reference in New Issue
Block a user