mirror of
https://gitlab.winehq.org/wine/wine-gecko.git
synced 2024-09-13 09:24:08 -07:00
Change CSS parser to close constructs open at end-of-file by changing ExpectSymbol not to fail on EOF when expecting one of }, ), ], or ;. (Bug 325064) r+sr=dbaron
This commit is contained in:
parent
a29f03503e
commit
a92b3b3f9f
@ -524,6 +524,9 @@ NS_NewCSSParser(nsICSSParser** aInstancePtrResult)
|
||||
#define REPORT_UNEXPECTED_EOF(lf_) \
|
||||
mScanner.ReportUnexpectedEOF(#lf_)
|
||||
|
||||
#define REPORT_UNEXPECTED_EOF_CHAR(ch_) \
|
||||
mScanner.ReportUnexpectedEOF(ch_)
|
||||
|
||||
#define REPORT_UNEXPECTED_TOKEN(msg_) \
|
||||
mScanner.ReportUnexpectedToken(mToken, #msg_)
|
||||
|
||||
@ -543,6 +546,7 @@ NS_NewCSSParser(nsICSSParser** aInstancePtrResult)
|
||||
#define REPORT_UNEXPECTED(msg_)
|
||||
#define REPORT_UNEXPECTED_P(msg_, params_)
|
||||
#define REPORT_UNEXPECTED_EOF(lf_)
|
||||
#define REPORT_UNEXPECTED_EOF_CHAR(ch_)
|
||||
#define REPORT_UNEXPECTED_TOKEN(msg_)
|
||||
#define REPORT_UNEXPECTED_TOKEN_P(msg_, params_)
|
||||
#define OUTPUT_ERROR()
|
||||
@ -1171,7 +1175,17 @@ PRBool CSSParserImpl::ExpectSymbol(nsresult& aErrorCode,
|
||||
PRBool aSkipWS)
|
||||
{
|
||||
if (!GetToken(aErrorCode, aSkipWS)) {
|
||||
return PR_FALSE;
|
||||
// CSS2.1 specifies that all "open constructs" are to be closed at
|
||||
// EOF. It simplifies higher layers if we claim to have found an
|
||||
// ), ], }, or ; if we encounter EOF while looking for one of them.
|
||||
// Do still issue a diagnostic, to aid debugging.
|
||||
if (aSymbol == ')' || aSymbol == ']' ||
|
||||
aSymbol == '}' || aSymbol == ';') {
|
||||
REPORT_UNEXPECTED_EOF_CHAR(aSymbol);
|
||||
return PR_TRUE;
|
||||
}
|
||||
else
|
||||
return PR_FALSE;
|
||||
}
|
||||
if (mToken.IsSymbol(aSymbol)) {
|
||||
return PR_TRUE;
|
||||
@ -1365,9 +1379,16 @@ PRBool CSSParserImpl::GatherMedia(nsresult& aErrorCode,
|
||||
aMedia->AppendAtom(medium);
|
||||
|
||||
if (!GetToken(aErrorCode, PR_TRUE)) {
|
||||
// expected termination by EOF
|
||||
if (aStopSymbol == PRUnichar(0))
|
||||
return PR_TRUE;
|
||||
|
||||
// unexpected termination by EOF; if we were looking for a
|
||||
// semicolon, return true anyway, for the same reason this is
|
||||
// done by ExpectSymbol().
|
||||
REPORT_UNEXPECTED_EOF(PEGatherMediaEOF);
|
||||
if (aStopSymbol == PRUnichar(';'))
|
||||
return PR_TRUE;
|
||||
break;
|
||||
}
|
||||
|
||||
|
@ -401,7 +401,7 @@ void nsCSSScanner::ReportUnexpectedParams(const char* aMessage,
|
||||
AddToError(str);
|
||||
}
|
||||
|
||||
// aMessage must take no parameters
|
||||
// aLookingFor is a plain string, not a format string
|
||||
void nsCSSScanner::ReportUnexpectedEOF(const char* aLookingFor)
|
||||
{
|
||||
ENSURE_STRINGBUNDLE;
|
||||
@ -420,6 +420,22 @@ void nsCSSScanner::ReportUnexpectedEOF(const char* aLookingFor)
|
||||
AddToError(str);
|
||||
}
|
||||
|
||||
// aLookingFor is a single character
|
||||
void nsCSSScanner::ReportUnexpectedEOF(PRUnichar aLookingFor)
|
||||
{
|
||||
ENSURE_STRINGBUNDLE;
|
||||
|
||||
const PRUnichar lookingForStr[] = {
|
||||
PRUnichar('\''), aLookingFor, PRUnichar('\''), PRUnichar(0)
|
||||
};
|
||||
const PRUnichar *params[] = { lookingForStr };
|
||||
nsXPIDLString str;
|
||||
gStringBundle->FormatStringFromName(NS_LITERAL_STRING("PEUnexpEOF2").get(),
|
||||
params, NS_ARRAY_LENGTH(params),
|
||||
getter_Copies(str));
|
||||
AddToError(str);
|
||||
}
|
||||
|
||||
// aMessage must take 1 parameter (for the string representation of the
|
||||
// unexpected token)
|
||||
void nsCSSScanner::ReportUnexpectedToken(nsCSSToken& tok,
|
||||
|
@ -157,8 +157,10 @@ class nsCSSScanner {
|
||||
NS_HIDDEN_(void) ReportUnexpectedParams(const char* aMessage,
|
||||
const PRUnichar **aParams,
|
||||
PRUint32 aParamsLength);
|
||||
// aMessage must take no parameters
|
||||
// aLookingFor is a plain string, not a format string
|
||||
NS_HIDDEN_(void) ReportUnexpectedEOF(const char* aLookingFor);
|
||||
// aLookingFor is a single character
|
||||
NS_HIDDEN_(void) ReportUnexpectedEOF(PRUnichar aLookingFor);
|
||||
// aMessage must take 1 parameter (for the string representation of the
|
||||
// unexpected token)
|
||||
NS_HIDDEN_(void) ReportUnexpectedToken(nsCSSToken& tok,
|
||||
|
@ -96,11 +96,12 @@ _TEST_FILES = test_bug73586.html \
|
||||
test_bug437915.html \
|
||||
test_cascade.html \
|
||||
test_compute_data_with_start_struct.html \
|
||||
test_css_eof_handling.html \
|
||||
test_dont_use_document_colors.html \
|
||||
test_inherit_storage.html \
|
||||
test_inherit_computation.html \
|
||||
test_initial_storage.html \
|
||||
test_inherit_storage.html \
|
||||
test_initial_computation.html \
|
||||
test_initial_storage.html \
|
||||
test_of_type_selectors.xhtml \
|
||||
test_parse_rule.html \
|
||||
test_property_database.html \
|
||||
@ -108,8 +109,8 @@ _TEST_FILES = test_bug73586.html \
|
||||
test_selectors.html \
|
||||
test_selectors_on_anonymous_content.html \
|
||||
test_style_struct_copy_constructors.html \
|
||||
test_value_storage.html \
|
||||
test_value_computation.html \
|
||||
test_value_storage.html \
|
||||
css_properties.js \
|
||||
property_database.js \
|
||||
unstyled.xml \
|
||||
|
283
layout/style/test/test_css_eof_handling.html
Normal file
283
layout/style/test/test_css_eof_handling.html
Normal file
@ -0,0 +1,283 @@
|
||||
<!DOCTYPE HTML>
|
||||
<html>
|
||||
<head>
|
||||
<title>Test for CSS EOF handling</title>
|
||||
<script type="text/javascript" src="/MochiKit/MochiKit.js"></script>
|
||||
<script type="text/javascript" src="/tests/SimpleTest/SimpleTest.js"></script>
|
||||
<link rel="stylesheet" type="text/css" href="/tests/SimpleTest/test.css" />
|
||||
</head>
|
||||
<body>
|
||||
<p><a target="_blank"
|
||||
href="https://bugzilla.mozilla.org/show_bug.cgi?id=311616">bug 311616</a>,
|
||||
<a target="_blank"
|
||||
href="https://bugzilla.mozilla.org/show_bug.cgi?id=325064">bug 325064</a></p>
|
||||
<iframe id="display"></iframe>
|
||||
<p id="log"></p>
|
||||
<pre id="test">
|
||||
<script class="testbody" type="text/javascript">
|
||||
const tests = [
|
||||
{
|
||||
name: "basic rule",
|
||||
ref: "#r {background-color : orange}",
|
||||
tst: "#t {background-color : orange",
|
||||
prop: "background-color", pseudo: ""
|
||||
},
|
||||
{
|
||||
name: "function",
|
||||
ref: "#r {background-color: rgb(0,255,0)}",
|
||||
tst: "#t {background-color: rgb(0,255,0",
|
||||
prop: "background-color", pseudo: ""
|
||||
},
|
||||
{
|
||||
name: "comment",
|
||||
ref: "#r {background-color: aqua/*marine*/}",
|
||||
tst: "#t {background-color: aqua/*marine",
|
||||
prop: "background-color", pseudo: ""
|
||||
},
|
||||
{
|
||||
name: "@media 1",
|
||||
ref: "@media all { #r { background-color: yellow } }",
|
||||
tst: "@media all { #t { background-color: yellow }",
|
||||
prop: "background-color", pseudo: ""
|
||||
},
|
||||
{
|
||||
name: "@media 2",
|
||||
ref: "@media all { #r { background-color: magenta } }",
|
||||
tst: "@media all { #t { background-color: magenta",
|
||||
prop: "background-color", pseudo: ""
|
||||
},
|
||||
{
|
||||
name: "@import 1",
|
||||
ref: "@import 'data:text/css,%23r%7Bbackground-color%3Agray%7D';",
|
||||
tst: "@import 'data:text/css,%23t%7Bbackground-color%3Agray%7D",
|
||||
prop: "background-color", pseudo: ""
|
||||
},
|
||||
{
|
||||
name: "@import 2",
|
||||
ref: "@import 'data:text/css,%23r%7Bbackground-color%3Ablack%7D' all;",
|
||||
tst: "@import 'data:text/css,%23t%7Bbackground-color%3Ablack%7D' all",
|
||||
prop: "background-color", pseudo: ""
|
||||
},
|
||||
{
|
||||
name: "url-token 1",
|
||||
ref: "#r { background-image: url(data:image/png;base64," +
|
||||
"iVBORw0KGgoAAAANSUhEUgAAAAQAAAAEAQAAAACBiqPTAAAADklEQVQI12NI" +
|
||||
"YJgAhAkAB4gB4Ry+pcoAAAAASUVORK5CYII=) }",
|
||||
tst: "#t { background-image: url(data:image/png;base64," +
|
||||
"iVBORw0KGgoAAAANSUhEUgAAAAQAAAAEAQAAAACBiqPTAAAADklEQVQI12NI" +
|
||||
"YJgAhAkAB4gB4Ry+pcoAAAAASUVORK5CYII=",
|
||||
prop: "background-image", pseudo: ""
|
||||
},
|
||||
{
|
||||
name: "url-token 2",
|
||||
ref: "#r { background-image: url('data:image/png;base64," +
|
||||
"iVBORw0KGgoAAAANSUhEUgAAAAQAAAAEAQAAAACBiqPTAAAAEElEQVQI12Mo" +
|
||||
"YNjAcIHhAQAJ2ALR4kRk1gAAAABJRU5ErkJggg==') }",
|
||||
tst: "#t { background-image: url('data:image/png;base64," +
|
||||
"iVBORw0KGgoAAAANSUhEUgAAAAQAAAAEAQAAAACBiqPTAAAAEElEQVQI12Mo" +
|
||||
"YNjAcIHhAQAJ2ALR4kRk1gAAAABJRU5ErkJggg==",
|
||||
prop: "background-image", pseudo: ""
|
||||
},
|
||||
{
|
||||
name: "url-token 3",
|
||||
ref: "#r { background-image: url('data:image/png;base64," +
|
||||
"iVBORw0KGgoAAAANSUhEUgAAAAQAAAAEAQAAAACBiqPTAAAAEElEQVQI12N4" +
|
||||
"wHCBYQNDAQAMuALRrGb97AAAAABJRU5ErkJggg==') }",
|
||||
tst: "#t { background-image: url('data:image/png;base64," +
|
||||
"iVBORw0KGgoAAAANSUhEUgAAAAQAAAAEAQAAAACBiqPTAAAAEElEQVQI12N4" +
|
||||
"wHCBYQNDAQAMuALRrGb97AAAAABJRU5ErkJggg=='",
|
||||
prop: "background-image", pseudo: ""
|
||||
},
|
||||
{
|
||||
name: "counter",
|
||||
ref: "#r::before { content: counter(tr, upper-alpha) }",
|
||||
tst: "#t::before { content: counter(tr, upper-alpha",
|
||||
prop: "content", pseudo: "::before"
|
||||
},
|
||||
{
|
||||
name: "string",
|
||||
ref: "#r::before { content: 'B' }",
|
||||
tst: "#t::before { content: 'B",
|
||||
prop: "content", pseudo: "::before"
|
||||
},
|
||||
|
||||
/* For these tests, there is no visible effect on computed style;
|
||||
instead we have to audit the DOM stylesheet object. */
|
||||
|
||||
{
|
||||
todo: 1,
|
||||
name: "selector 1",
|
||||
ref: "td[colspan='3'] {}",
|
||||
tst: "td[colspan='3"
|
||||
},
|
||||
{
|
||||
todo: 1,
|
||||
name: "selector 2",
|
||||
ref: "td[colspan='3'] {}",
|
||||
tst: "td[colspan='3'"
|
||||
},
|
||||
{
|
||||
todo: 1,
|
||||
name: "selector 3",
|
||||
ref: "td:lang(en) {}",
|
||||
tst: "td:lang(en"
|
||||
},
|
||||
|
||||
{
|
||||
name: "@charset 1",
|
||||
ref: "@charset 'utf-8';",
|
||||
tst: "@charset 'utf-8"
|
||||
},
|
||||
{
|
||||
name: "@charset 2",
|
||||
ref: "@charset 'utf-8';",
|
||||
tst: "@charset 'utf-8'"
|
||||
},
|
||||
{
|
||||
name: "@media 3",
|
||||
ref: "@media all {}",
|
||||
tst: "@media all {",
|
||||
},
|
||||
{
|
||||
name: "@namespace 1a",
|
||||
ref: "@namespace foo url('http://foo.example.com/');",
|
||||
tst: "@namespace foo url('http://foo.example.com/')"
|
||||
},
|
||||
{
|
||||
name: "@namespace 1b",
|
||||
ref: "@namespace foo url(http://foo.example.com/);",
|
||||
tst: "@namespace foo url(http://foo.example.com/"
|
||||
},
|
||||
{
|
||||
name: "@namespace 1c",
|
||||
ref: "@namespace foo url('http://foo.example.com/');",
|
||||
tst: "@namespace foo url('http://foo.example.com/"
|
||||
},
|
||||
{
|
||||
name: "@namespace 1d",
|
||||
ref: "@namespace foo 'http://foo.example.com/';",
|
||||
tst: "@namespace foo 'http://foo.example.com/'"
|
||||
},
|
||||
{
|
||||
name: "@namespace 1e",
|
||||
ref: "@namespace foo 'http://foo.example.com/';",
|
||||
tst: "@namespace foo 'http://foo.example.com/"
|
||||
},
|
||||
{
|
||||
name: "@namespace 2a",
|
||||
ref: "@namespace url('http://foo.example.com/');",
|
||||
tst: "@namespace url('http://foo.example.com/')"
|
||||
},
|
||||
{
|
||||
name: "@namespace 2b",
|
||||
ref: "@namespace url('http://foo.example.com/');",
|
||||
tst: "@namespace url('http://foo.example.com/'"
|
||||
},
|
||||
{
|
||||
name: "@namespace 2c",
|
||||
ref: "@namespace url('http://foo.example.com/');",
|
||||
tst: "@namespace url('http://foo.example.com/"
|
||||
},
|
||||
{
|
||||
name: "@namespace 2d",
|
||||
ref: "@namespace 'http://foo.example.com/';",
|
||||
tst: "@namespace 'http://foo.example.com/'"
|
||||
},
|
||||
{
|
||||
name: "@namespace 2e",
|
||||
ref: "@namespace 'http://foo.example.com/';",
|
||||
tst: "@namespace 'http://foo.example.com/"
|
||||
},
|
||||
{
|
||||
name: "@-moz-document 1",
|
||||
ref: "@-moz-document domain('example.com') {}",
|
||||
tst: "@-moz-document domain('example.com') {"
|
||||
},
|
||||
{
|
||||
name: "@-moz-document 2",
|
||||
ref: "@-moz-document domain('example.com') { p {} }",
|
||||
tst: "@-moz-document domain('example.com') { p {"
|
||||
}
|
||||
];
|
||||
|
||||
const basestyle = ("table {\n"+
|
||||
" border-collapse: collapse;\n"+
|
||||
"}\n"+
|
||||
"td {\n"+
|
||||
" width: 1.5em;\n"+
|
||||
" height: 1.5em;\n"+
|
||||
" border: 1px solid black;\n"+
|
||||
" text-align: center;\n"+
|
||||
" margin: 0;\n"+
|
||||
"}\n"+
|
||||
"tr { counter-increment: tr }\n");
|
||||
|
||||
/* This is more complicated than it might look like it needs to be,
|
||||
because for each subtest we have to splat stuff into the iframe,
|
||||
allow the renderer to run, and only then interrogate the computed
|
||||
styles. */
|
||||
|
||||
SimpleTest.waitForExplicitFinish();
|
||||
|
||||
window.onload = function() {
|
||||
const frame = document.getElementById("display");
|
||||
var curTest = 0;
|
||||
|
||||
const prepareTest = function() {
|
||||
var cd = frame.contentDocument;
|
||||
cd.open();
|
||||
cd.write('<!DOCTYPE HTML><html><head>' +
|
||||
'<style>\n' + basestyle + '</style>\n' +
|
||||
'<style>\n' + tests[curTest].ref + '</style>\n' +
|
||||
'<style>\n' + tests[curTest].tst + '</style>\n' +
|
||||
'</head><body>\n' +
|
||||
'<table><tr><td id="r"><td id="t"></table>' +
|
||||
'</body></html>');
|
||||
cd.close();
|
||||
};
|
||||
|
||||
const checkTest = function() {
|
||||
var cd = frame.contentDocument;
|
||||
var _is = tests[curTest].todo ? todo_is : is;
|
||||
var _ok = tests[curTest].todo ? todo : ok;
|
||||
|
||||
if (cd.styleSheets[1].cssRules.length == 1 &&
|
||||
cd.styleSheets[2].cssRules.length == 1) {
|
||||
// If we have a .prop for this test, the .cssText of the reference
|
||||
// and test rules will differ in the selector. Change #t to #r
|
||||
// in the test rule.
|
||||
var ref_canon = cd.styleSheets[1].cssRules[0].cssText;
|
||||
var tst_canon = cd.styleSheets[2].cssRules[0].cssText;
|
||||
tst_canon = tst_canon.replace(/(#|%23)t\b/, "$1r");
|
||||
_is(tst_canon, ref_canon,
|
||||
tests[curTest].name + " (canonicalized rule)");
|
||||
} else {
|
||||
_ok(false, tests[curTest].name + " (rule missing)");
|
||||
}
|
||||
if (tests[curTest].prop) {
|
||||
var prop = tests[curTest].prop;
|
||||
var pseudo = tests[curTest].pseudo;
|
||||
|
||||
var refElt = cd.getElementById("r");
|
||||
var tstElt = cd.getElementById("t");
|
||||
var refStyle = cd.defaultView.getComputedStyle(refElt, pseudo);
|
||||
var tstStyle = cd.defaultView.getComputedStyle(tstElt, pseudo);
|
||||
_is(tstStyle.getPropertyValue(prop),
|
||||
refStyle.getPropertyValue(prop),
|
||||
tests[curTest].name + " (computed style)");
|
||||
}
|
||||
curTest++;
|
||||
if (curTest < tests.length) {
|
||||
prepareTest();
|
||||
} else {
|
||||
SimpleTest.finish();
|
||||
}
|
||||
};
|
||||
|
||||
frame.onload = function(){setTimeout(checkTest, 0);};
|
||||
prepareTest();
|
||||
};
|
||||
</script>
|
||||
</pre>
|
||||
</body>
|
||||
</html>
|
@ -2,6 +2,7 @@
|
||||
<html lang=en>
|
||||
<script type="text/javascript" src="/MochiKit/MochiKit.js"></script>
|
||||
<script type="text/javascript" src="/tests/SimpleTest/SimpleTest.js"></script>
|
||||
<link rel="stylesheet" type="text/css" href="/tests/SimpleTest/test.css" />
|
||||
<META http-equiv="Content-Type" content="text/html; charset=UTF-8">
|
||||
<body>
|
||||
<iframe></iframe>
|
||||
@ -102,7 +103,7 @@ base + "#6ident, #a {color: red }",
|
||||
".\\6ident, .a { color: green; }",
|
||||
".\\--ident, .a { color: green; }",
|
||||
|
||||
// CSS2.1 section 4.1.5
|
||||
// CSS2.1 section 4.1.5 and 4.2
|
||||
"@import 'data:text/css,#a{color:green}';",
|
||||
"@import \"data:text/css,#a{color:green}\";",
|
||||
"@import url(data:text/css,#a{color:green});",
|
||||
@ -129,8 +130,7 @@ base + "#a {color: rgb(255.0, 0, 0)}",
|
||||
"#a {color: rgb(0%, 50%, 0%)}",
|
||||
"#a {color: rgb(0%, 49.999999999999%, 0%)}",
|
||||
], prop: "color", pseudo: "",
|
||||
todo: {"@import 'data:text/css,#a{color:green}'" : 1,
|
||||
"@import 'data:text/css,#a{color:green}" : 1,
|
||||
todo: {
|
||||
"div[title~='weeqweqeweasd\\D\\A a']{color:green}" : 1,
|
||||
"div {color:green}#a\\\n{color:red}" : 1
|
||||
}
|
||||
|
Loading…
Reference in New Issue
Block a user