Fix skipping of @-rules that are inside blocks to conform to new rule in CSS 2.1, which says that we must look for end-of-outer-block in addition to a semicolon or a block. (Bug 604175) r=bzbarsky

This fixes http://test.csswg.org/suites/css2.1/20110111/html4/at-rule-013.htm

Needed to help CSS 2.1 meet Proposed Recommendation entrance criteria.
This commit is contained in:
L. David Baron 2011-03-03 13:18:42 -08:00
Родитель 733c3e9498
Коммит 8c94d6c6b7
4 изменённых файлов: 110 добавлений и 5 удалений

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

@ -0,0 +1,25 @@
<!DOCTYPE html PUBLIC "-//W3C//DTD HTML 4.01//EN" "http://www.w3.org/TR/html4/strict.dtd">
<!--
from the CSS 2.1 test suite,
http://test.csswg.org/suites/css2.1/20110111/html4/at-rule-013.htm
See ../css3-namespace/LICENSE .
-->
<html>
<head>
<title>CSS Test: Ignoring at-rules inside @media blocks</title>
<link rel="author" title="L. David Baron" href="http://dbaron.org/">
<style type="text/css">
p {
color: green;
background: transparent;
}
</style>
</head>
<body>
<p>This sentence must be green.</p>
<p>This sentence must be green.</p>
<p>This sentence must be green.</p>
<p>This sentence must be green.</p>
</body>
</html>

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

@ -0,0 +1,68 @@
<!DOCTYPE html PUBLIC "-//W3C//DTD HTML 4.01//EN" "http://www.w3.org/TR/html4/strict.dtd">
<!--
from the CSS 2.1 test suite,
http://test.csswg.org/suites/css2.1/20110111/html4/at-rule-013.htm
See ../css3-namespace/LICENSE .
-->
<html>
<head>
<title>CSS Test: Ignoring at-rules inside @media blocks</title>
<link rel="author" title="Elika J. Etemad" href="http://fantasai.inkedblade.net/contact">
<link rel="help" href="http://www.w3.org/TR/CSS21/syndata.html#parsing-errors">
<link rel="help" href="http://www.w3.org/TR/CSS21/media.html#at-media-rule">
<meta name="flags" content="invalid">
<meta name="assert" content="At-rules inside @media blocks are ignored up to up to the end of the block that contains the invalid at-keyword, or up to and including the next semicolon (;) or up to and including the next block ({...}), whichever comes first.">
<style type="text/css">
p {
color: red;
background: red;
}
@media all {
#semicolon { background: transparent; }
@foo ] & | # $ % test-token \
[; # { background: red; } ]
(; #semicolon { background: red; } } } } )
'; #semicolon { background: red; } } } }',
"; #semicolon { background: red; }' } } }"
;
#semicolon { color: green; }
}
@media all {
#block { background: transparent; }
@foo ] & | # $ % test-token \
[; #block { background: red; } ]
(; #block { background: red; } )
'; #block { background: red; }',
"; #block { background: red; }'"
{; #block { background: red; }
#block { background: red; } }
#block { color: green; }
}
@media all {
#eob { background: transparent; }
@import "support/import-red.css"
}
#eob {
color: green;
}
@media all {
#eob-complex { background: transparent; }
@import "support/import-red.css"
[; #eob-complex { background: red; } ]
(; #eob-complex { background: red; } )
'; #eob-complex { background: red; }',
"; #eob-complex { background: red; }'"
}
#eob-complex {
color: green;
}
</style>
</head>
<body>
<p id="semicolon">This sentence must be green.</p>
<p id="block">This sentence must be green.</p>
<p id="eob">This sentence must be green.</p>
<p id="eob-complex">This sentence must be green.</p>
</body>
</html>

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

@ -1,2 +1,3 @@
== at-rule-013.html at-rule-013-ref.html
== invalid-url-handling.xhtml invalid-url-handling-ref.xhtml
== pseudo-elements-1.html pseudo-elements-1-ref.html

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

@ -310,7 +310,7 @@ protected:
void SkipUntil(PRUnichar aStopSymbol);
void SkipUntilOneOf(const PRUnichar* aStopSymbolChars);
void SkipRuleSet(PRBool aInsideBraces);
PRBool SkipAtRule();
PRBool SkipAtRule(PRBool aInsideBlock);
PRBool SkipDeclaration(PRBool aCheckForBraces);
PRBool PushGroup(nsICSSGroupRule* aRule);
@ -1434,7 +1434,7 @@ CSSParserImpl::NextIdent()
}
PRBool
CSSParserImpl::SkipAtRule()
CSSParserImpl::SkipAtRule(PRBool aInsideBlock)
{
for (;;) {
if (!GetToken(PR_TRUE)) {
@ -1446,6 +1446,11 @@ CSSParserImpl::SkipAtRule()
if (symbol == ';') {
break;
}
if (aInsideBlock && symbol == '}') {
// The closing } doesn't belong to us.
UngetToken();
break;
}
if (symbol == '{') {
SkipUntil('}');
break;
@ -1465,6 +1470,12 @@ PRBool
CSSParserImpl::ParseAtRule(RuleAppendFunc aAppendFunc,
void* aData)
{
// If we ever allow nested at-rules, we need to be very careful about
// the error handling rules in the CSS spec. In particular, we need
// to pass in to ParseAtRule whether we're inside a block, we need to
// ensure that all the individual at-rule parsing functions terminate
// immediately when they hit a '}', and then we need to pass whether
// we're inside a block to SkipAtRule below.
nsCSSSection newSection;
PRBool (CSSParserImpl::*parseFunc)(RuleAppendFunc, void*);
@ -1505,13 +1516,13 @@ CSSParserImpl::ParseAtRule(RuleAppendFunc aAppendFunc,
OUTPUT_ERROR();
}
// Skip over unsupported at rule, don't advance section
return SkipAtRule();
return SkipAtRule(PR_FALSE);
}
if (!(this->*parseFunc)(aAppendFunc, aData)) {
// Skip over invalid at rule, don't advance section
OUTPUT_ERROR();
return SkipAtRule();
return SkipAtRule(PR_FALSE);
}
mSection = newSection;
@ -1972,7 +1983,7 @@ CSSParserImpl::ParseGroupRule(nsICSSGroupRule* aRule,
break;
}
if (eCSSToken_AtKeyword == mToken.mType) {
SkipAtRule(); // group rules cannot contain @rules
SkipAtRule(PR_TRUE); // group rules cannot contain @rules
continue;
}
UngetToken();