mirror of
https://github.com/mozilla/gecko-dev.git
synced 2024-10-11 12:25:53 +00:00
Bug 528096: unexpected-token error recovery paths in the CSS parser need to UngetToken() before calling SkipUntil(), for correct behavior when the unexpected token is ( [ { or FUNCTION. r=dbaron
This commit is contained in:
parent
3ad3950083
commit
1d78bfa0d0
34
layout/reftests/bugs/528096-1-ref.html
Normal file
34
layout/reftests/bugs/528096-1-ref.html
Normal file
@ -0,0 +1,34 @@
|
||||
<!DOCTYPE HTML>
|
||||
<!-- Test for some pieces of bug 528096; other pieces are tested in
|
||||
the mochitests test_font_face_parser.html,
|
||||
test_media_queries.html, and test_selectors.html -->
|
||||
<html><head>
|
||||
<title>Test for bug 528096 (counters and image rects)</title>
|
||||
<style>
|
||||
div { display: inline-block; vertical-align: bottom;
|
||||
margin-right: 6px; width: 16px; height: 16px;
|
||||
background-color: lime; }
|
||||
div::before { display: inline-block; height: 16px;
|
||||
content: url("checkmark.gif"); }
|
||||
</style>
|
||||
</head><body>
|
||||
|
||||
<table><tr>
|
||||
<td>-moz-image-rect()</td>
|
||||
<td><div id="i1"></td>
|
||||
</tr><tr>
|
||||
<td>counter()</td>
|
||||
<td><div id="c1"></div><div id="c2"></div></td>
|
||||
</tr><tr>
|
||||
<td>counters()</td>
|
||||
<td><div id="cs1"></div><div id="cs2"></div><div id="cs3"></div></td>
|
||||
</tr></table>
|
||||
|
||||
<p>
|
||||
<a target="_blank"
|
||||
href="https://bugzilla.mozilla.org/show_bug.cgi?id=528096">Mozilla
|
||||
bug 528096</a>. There should be no red or orange, and each square
|
||||
should have a black checkmark in it.
|
||||
</p>
|
||||
|
||||
</body></html>
|
70
layout/reftests/bugs/528096-1.html
Normal file
70
layout/reftests/bugs/528096-1.html
Normal file
@ -0,0 +1,70 @@
|
||||
<!DOCTYPE HTML>
|
||||
<!-- Test for some pieces of bug 528096; other pieces are tested in
|
||||
the mochitests test_font_face_parser.html,
|
||||
test_media_queries.html, and test_selectors.html -->
|
||||
<html><head>
|
||||
<title>Test for bug 528096 (counters and image rects)</title>
|
||||
<style>
|
||||
|
||||
div { display: inline-block; vertical-align: bottom;
|
||||
margin-right: 6px; width: 16px; height: 16px;
|
||||
background-color: orange; }
|
||||
div::before { display: inline-block; height: 16px; }
|
||||
|
||||
/* -moz-image-rect() */
|
||||
#i1::before {
|
||||
background-color: lime;
|
||||
background-image: -moz-image-rect((); background-color: red;);
|
||||
content: url("checkmark.gif");
|
||||
}
|
||||
|
||||
/* counter() */
|
||||
#c1::before {
|
||||
background-color: lime;
|
||||
content: counter((); background-color: red;);
|
||||
content: url("checkmark.gif");
|
||||
}
|
||||
#c2::before {
|
||||
background-color: lime;
|
||||
content: counter(foo,(); background-color: red;);
|
||||
content: url("checkmark.gif");
|
||||
}
|
||||
|
||||
/* counters() */
|
||||
#cs1::before {
|
||||
background-color: lime;
|
||||
content: counters((); background-color: red;);
|
||||
content: url("checkmark.gif");
|
||||
}
|
||||
#cs2::before {
|
||||
background-color: lime;
|
||||
content: counters(foo,(); background-color: red;);
|
||||
content: url("checkmark.gif");
|
||||
}
|
||||
#cs3::before {
|
||||
background-color: lime;
|
||||
content: counters(foo,"s",(); background-color: red;);
|
||||
content: url("checkmark.gif");
|
||||
}
|
||||
</style>
|
||||
</head><body>
|
||||
|
||||
<table><tr>
|
||||
<td>-moz-image-rect()</td>
|
||||
<td><div id="i1"></td>
|
||||
</tr><tr>
|
||||
<td>counter()</td>
|
||||
<td><div id="c1"></div><div id="c2"></div></td>
|
||||
</tr><tr>
|
||||
<td>counters()</td>
|
||||
<td><div id="cs1"></div><div id="cs2"></div><div id="cs3"></div></td>
|
||||
</tr></table>
|
||||
|
||||
<p>
|
||||
<a target="_blank"
|
||||
href="https://bugzilla.mozilla.org/show_bug.cgi?id=528096">Mozilla
|
||||
bug 528096</a>. There should be no red or orange, and each square
|
||||
should have a black checkmark in it.
|
||||
</p>
|
||||
|
||||
</body></html>
|
BIN
layout/reftests/bugs/checkmark.gif
Normal file
BIN
layout/reftests/bugs/checkmark.gif
Normal file
Binary file not shown.
After Width: | Height: | Size: 76 B |
@ -1369,6 +1369,7 @@ fails HTTP(..) == 518172-2b.html 518172-b-ref.html # bug 518172
|
||||
== 528038-1e.html 528038-1-ref.html
|
||||
== 528038-1f.html 528038-1-ref.html
|
||||
== 528038-2.html 528038-2-ref.html
|
||||
== 528096-1.html 528096-1-ref.html
|
||||
== 530686-1.html 530686-1-ref.html
|
||||
== 531098-1.html 531098-1-ref.html
|
||||
== 531371-1.html 531371-1-ref.html
|
||||
|
@ -293,7 +293,6 @@ protected:
|
||||
void SkipRuleSet(PRBool aInsideBraces);
|
||||
PRBool SkipAtRule();
|
||||
PRBool SkipDeclaration(PRBool aCheckForBraces);
|
||||
PRBool GetNonCloseParenToken(PRBool aSkipWS);
|
||||
|
||||
PRBool PushGroup(nsICSSGroupRule* aRule);
|
||||
void PopGroup(void);
|
||||
@ -1737,6 +1736,7 @@ CSSParserImpl::ParseMediaQueryExpression(nsMediaQuery* aQuery)
|
||||
}
|
||||
if (eCSSToken_Ident != mToken.mType) {
|
||||
REPORT_UNEXPECTED_TOKEN(PEMQExpectedFeatureName);
|
||||
UngetToken();
|
||||
SkipUntil(')');
|
||||
return PR_FALSE;
|
||||
}
|
||||
@ -1791,6 +1791,7 @@ CSSParserImpl::ParseMediaQueryExpression(nsMediaQuery* aQuery)
|
||||
|
||||
if (!mToken.IsSymbol(':')) {
|
||||
REPORT_UNEXPECTED_TOKEN(PEMQExpectedFeatureNameEnd);
|
||||
UngetToken();
|
||||
SkipUntil(')');
|
||||
return PR_FALSE;
|
||||
}
|
||||
@ -1831,19 +1832,24 @@ CSSParserImpl::ParseMediaQueryExpression(nsMediaQuery* aQuery)
|
||||
}
|
||||
break;
|
||||
case nsMediaFeature::eResolution:
|
||||
rv = GetToken(PR_TRUE) && mToken.mType == eCSSToken_Dimension &&
|
||||
rv = GetToken(PR_TRUE);
|
||||
if (!rv)
|
||||
break;
|
||||
rv = mToken.mType == eCSSToken_Dimension &&
|
||||
mToken.mIntegerValid && mToken.mNumber > 0.0f;
|
||||
if (rv) {
|
||||
// No worries about whether unitless zero is allowed, since the
|
||||
// value must be positive (and we checked that above).
|
||||
NS_ASSERTION(!mToken.mIdent.IsEmpty(), "unit lied");
|
||||
if (mToken.mIdent.LowerCaseEqualsLiteral("dpi")) {
|
||||
expr->mValue.SetFloatValue(mToken.mNumber, eCSSUnit_Inch);
|
||||
} else if (mToken.mIdent.LowerCaseEqualsLiteral("dpcm")) {
|
||||
expr->mValue.SetFloatValue(mToken.mNumber, eCSSUnit_Centimeter);
|
||||
} else {
|
||||
rv = PR_FALSE;
|
||||
}
|
||||
if (!rv) {
|
||||
UngetToken();
|
||||
break;
|
||||
}
|
||||
// No worries about whether unitless zero is allowed, since the
|
||||
// value must be positive (and we checked that above).
|
||||
NS_ASSERTION(!mToken.mIdent.IsEmpty(), "unit lied");
|
||||
if (mToken.mIdent.LowerCaseEqualsLiteral("dpi")) {
|
||||
expr->mValue.SetFloatValue(mToken.mNumber, eCSSUnit_Inch);
|
||||
} else if (mToken.mIdent.LowerCaseEqualsLiteral("dpcm")) {
|
||||
expr->mValue.SetFloatValue(mToken.mNumber, eCSSUnit_Centimeter);
|
||||
} else {
|
||||
rv = PR_FALSE;
|
||||
}
|
||||
break;
|
||||
case nsMediaFeature::eEnumerated:
|
||||
@ -2302,18 +2308,6 @@ CSSParserImpl::SkipUntilOneOf(const PRUnichar* aStopSymbolChars)
|
||||
}
|
||||
}
|
||||
|
||||
PRBool
|
||||
CSSParserImpl::GetNonCloseParenToken(PRBool aSkipWS)
|
||||
{
|
||||
if (!GetToken(aSkipWS))
|
||||
return PR_FALSE;
|
||||
if (mToken.mType == eCSSToken_Symbol && mToken.mSymbol == ')') {
|
||||
UngetToken();
|
||||
return PR_FALSE;
|
||||
}
|
||||
return PR_TRUE;
|
||||
}
|
||||
|
||||
PRBool
|
||||
CSSParserImpl::SkipDeclaration(PRBool aCheckForBraces)
|
||||
{
|
||||
@ -3926,6 +3920,7 @@ CSSParserImpl::ParseTreePseudoElement(nsPseudoClassList **aPseudoElementArgs)
|
||||
nsCSSPseudoClasses::ePseudoClass_NotPseudoClass);
|
||||
}
|
||||
else if (!mToken.IsSymbol(',')) {
|
||||
UngetToken();
|
||||
SkipUntil(')');
|
||||
return PR_FALSE;
|
||||
}
|
||||
@ -4642,59 +4637,67 @@ CSSParserImpl::ParseCounter(nsCSSValue& aValue)
|
||||
nsCSSUnit unit = (mToken.mIdent.LowerCaseEqualsLiteral("counter") ?
|
||||
eCSSUnit_Counter : eCSSUnit_Counters);
|
||||
|
||||
if (!GetNonCloseParenToken(PR_TRUE) ||
|
||||
eCSSToken_Ident != mToken.mType) {
|
||||
SkipUntil(')');
|
||||
return PR_FALSE;
|
||||
}
|
||||
|
||||
nsRefPtr<nsCSSValue::Array> val =
|
||||
nsCSSValue::Array::Create(unit == eCSSUnit_Counter ? 2 : 3);
|
||||
if (!val) {
|
||||
mScanner.SetLowLevelError(NS_ERROR_OUT_OF_MEMORY);
|
||||
return PR_FALSE;
|
||||
}
|
||||
|
||||
val->Item(0).SetStringValue(mToken.mIdent, eCSSUnit_Ident);
|
||||
|
||||
if (eCSSUnit_Counters == unit) {
|
||||
// get mandatory separator string
|
||||
if (!ExpectSymbol(',', PR_TRUE) ||
|
||||
!(GetNonCloseParenToken(PR_TRUE) &&
|
||||
eCSSToken_String == mToken.mType)) {
|
||||
SkipUntil(')');
|
||||
return PR_FALSE;
|
||||
// A non-iterative for loop to break out when an error occurs.
|
||||
for (;;) {
|
||||
if (!GetToken(PR_TRUE)) {
|
||||
break;
|
||||
}
|
||||
val->Item(1).SetStringValue(mToken.mIdent, eCSSUnit_String);
|
||||
}
|
||||
|
||||
// get optional type
|
||||
PRInt32 type = NS_STYLE_LIST_STYLE_DECIMAL;
|
||||
if (ExpectSymbol(',', PR_TRUE)) {
|
||||
nsCSSKeyword keyword;
|
||||
PRBool success = GetNonCloseParenToken(PR_TRUE) &&
|
||||
eCSSToken_Ident == mToken.mType &&
|
||||
(keyword = nsCSSKeywords::LookupKeyword(mToken.mIdent)) !=
|
||||
eCSSKeyword_UNKNOWN;
|
||||
if (success) {
|
||||
success = nsCSSProps::FindKeyword(keyword,
|
||||
nsCSSProps::kListStyleKTable, type);
|
||||
if (eCSSToken_Ident != mToken.mType) {
|
||||
UngetToken();
|
||||
break;
|
||||
}
|
||||
if (!success) {
|
||||
SkipUntil(')');
|
||||
return PR_FALSE;
|
||||
|
||||
nsRefPtr<nsCSSValue::Array> val =
|
||||
nsCSSValue::Array::Create(unit == eCSSUnit_Counter ? 2 : 3);
|
||||
if (!val) {
|
||||
mScanner.SetLowLevelError(NS_ERROR_OUT_OF_MEMORY);
|
||||
break;
|
||||
}
|
||||
}
|
||||
PRInt32 typeItem = eCSSUnit_Counters == unit ? 2 : 1;
|
||||
val->Item(typeItem).SetIntValue(type, eCSSUnit_Enumerated);
|
||||
|
||||
if (!ExpectSymbol(')', PR_TRUE)) {
|
||||
SkipUntil(')');
|
||||
return PR_FALSE;
|
||||
val->Item(0).SetStringValue(mToken.mIdent, eCSSUnit_Ident);
|
||||
|
||||
if (eCSSUnit_Counters == unit) {
|
||||
// must have a comma and then a separator string
|
||||
if (!ExpectSymbol(',', PR_TRUE) || !GetToken(PR_TRUE)) {
|
||||
break;
|
||||
}
|
||||
if (eCSSToken_String != mToken.mType) {
|
||||
UngetToken();
|
||||
break;
|
||||
}
|
||||
val->Item(1).SetStringValue(mToken.mIdent, eCSSUnit_String);
|
||||
}
|
||||
|
||||
// get optional type
|
||||
PRInt32 type = NS_STYLE_LIST_STYLE_DECIMAL;
|
||||
if (ExpectSymbol(',', PR_TRUE)) {
|
||||
if (!GetToken(PR_TRUE)) {
|
||||
break;
|
||||
}
|
||||
nsCSSKeyword keyword;
|
||||
if (eCSSToken_Ident != mToken.mType ||
|
||||
(keyword = nsCSSKeywords::LookupKeyword(mToken.mIdent)) ==
|
||||
eCSSKeyword_UNKNOWN ||
|
||||
!nsCSSProps::FindKeyword(keyword, nsCSSProps::kListStyleKTable,
|
||||
type)) {
|
||||
UngetToken();
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
PRInt32 typeItem = eCSSUnit_Counters == unit ? 2 : 1;
|
||||
val->Item(typeItem).SetIntValue(type, eCSSUnit_Enumerated);
|
||||
|
||||
if (!ExpectSymbol(')', PR_TRUE)) {
|
||||
break;
|
||||
}
|
||||
|
||||
aValue.SetArrayValue(val, unit);
|
||||
return PR_TRUE;
|
||||
}
|
||||
|
||||
aValue.SetArrayValue(val, unit);
|
||||
return PR_TRUE;
|
||||
SkipUntil(')');
|
||||
return PR_FALSE;
|
||||
}
|
||||
|
||||
PRBool
|
||||
@ -4839,6 +4842,7 @@ CSSParserImpl::ParseImageRect(nsCSSValue& aImage)
|
||||
if (!ParseURL(url))
|
||||
break;
|
||||
} else {
|
||||
UngetToken();
|
||||
break;
|
||||
}
|
||||
if (!ExpectSymbol(',', PR_TRUE))
|
||||
|
@ -163,6 +163,10 @@
|
||||
"src: url(\"/fonts/Cat\") format(\"Cat\"; src: local(Rat); )"),
|
||||
d: { "src" : "url(\"/fonts/Mouse\")" },
|
||||
noncanonical: true },
|
||||
{ rule: _("src: url(\"/fonts/Mouse\"); " +
|
||||
"src: url(\"/fonts/Cat\") format((); src: local(Rat); )"),
|
||||
d: { "src" : "url(\"/fonts/Mouse\")" },
|
||||
noncanonical: true },
|
||||
|
||||
// Correct unicode-range:
|
||||
{ rule: _("unicode-range: U+00A5;"), d: { "unicode-range" : "U+00A5" } },
|
||||
|
@ -590,6 +590,11 @@ function run() {
|
||||
should_apply("[badsyntax],all");
|
||||
should_not_apply("badmedium,[badsyntax]");
|
||||
should_not_apply("[badsyntax],badmedium");
|
||||
// bug 528096
|
||||
should_not_apply_unbalanced("((resolution),all");
|
||||
should_not_apply_unbalanced("(resolution(),all");
|
||||
should_not_apply_unbalanced("(resolution (),all");
|
||||
should_not_apply_unbalanced("(resolution:(),all");
|
||||
|
||||
handle_posted_items();
|
||||
}
|
||||
|
@ -754,6 +754,16 @@ function run() {
|
||||
bodychildset([0, 1, 2, 3, 4, 11]),
|
||||
bodychildset([5, 6, 7, 8, 9, 10]));
|
||||
|
||||
// bug 528096 (tree pseudos)
|
||||
test_selector_in_html(":-moz-tree-column((){} a", single_a,
|
||||
empty_set, set_single, html_default_ns);
|
||||
test_selector_in_html(":-moz-tree-column(x(){} a", single_a,
|
||||
empty_set, set_single, html_default_ns);
|
||||
test_selector_in_html(":-moz-tree-column(a b (){} a", single_a,
|
||||
empty_set, set_single, html_default_ns);
|
||||
test_selector_in_html(":-moz-tree-column(a, b (){} a", single_a,
|
||||
empty_set, set_single, html_default_ns);
|
||||
|
||||
run_deferred_tests();
|
||||
}
|
||||
|
||||
|
Loading…
Reference in New Issue
Block a user