Merge backout, a=bustage fix

This commit is contained in:
Benoit Jacob 2011-05-03 17:19:23 -04:00
commit c10fe6c238
6 changed files with 121 additions and 32 deletions

View File

@ -874,7 +874,7 @@ nsresult nsPluginStreamListenerPeer::ServeStreamAsFile(nsIRequest *request,
window->window = widget->GetNativeData(NS_NATIVE_PLUGIN_PORT);
}
#endif
mOwner->SetWindow();
owner->SetWindow();
}
mSeekable = PR_FALSE;

View File

@ -971,7 +971,11 @@ nsCSSScanner::NextURL(nsCSSToken& aToken)
ch = Read();
if (ch < 0) break;
if (ch == CSS_ESCAPE) {
ParseAndAppendEscape(ident);
if (!ParseAndAppendEscape(ident, PR_FALSE)) {
ok = PR_FALSE;
Pushback(ch);
break;
}
} else if (IsWhitespace(ch)) {
// Whitespace is allowed at the end of the URL
EatWhiteSpace();
@ -1002,17 +1006,21 @@ nsCSSScanner::NextURL(nsCSSToken& aToken)
}
void
nsCSSScanner::ParseAndAppendEscape(nsString& aOutput)
/**
* Returns whether an escape was succesfully parsed; if it was not,
* the backslash needs to be its own symbol token.
*/
PRBool
nsCSSScanner::ParseAndAppendEscape(nsString& aOutput, PRBool aInString)
{
PRInt32 ch = Peek();
PRInt32 ch = Read();
if (ch < 0) {
aOutput.Append(CSS_ESCAPE);
return;
return PR_FALSE;
}
if (IsHexDigit(ch)) {
PRInt32 rv = 0;
int i;
Pushback(ch);
for (i = 0; i < 6; i++) { // up to six digits
ch = Read();
if (ch < 0) {
@ -1054,15 +1062,26 @@ nsCSSScanner::ParseAndAppendEscape(nsString& aOutput)
if (IsWhitespace(ch))
Pushback(ch);
}
return;
return PR_TRUE;
}
// "Any character except a hexidecimal digit can be escaped to
// remove its special meaning by putting a backslash in front"
// -- CSS1 spec section 7.1
ch = Read(); // Consume the escaped character
if ((ch > 0) && (ch != '\n')) {
if (ch == '\n') {
if (!aInString) {
// Outside of strings (which includes url() that contains a
// string), escaped newlines aren't special, and just tokenize as
// eCSSToken_Symbol (DELIM).
Pushback(ch);
return PR_FALSE;
}
// In strings (and in url() containing a string), escaped newlines
// are just dropped to allow splitting over multiple lines.
} else {
aOutput.Append(ch);
}
return PR_TRUE;
}
/**
@ -1071,12 +1090,18 @@ nsCSSScanner::ParseAndAppendEscape(nsString& aOutput)
* will be aIdent with all of the identifier characters appended
* until the first non-identifier character is seen. The termination
* character is unread for the future re-reading.
*
* Returns failure when the character sequence does not form an ident at
* all, in which case the caller is responsible for pushing back or
* otherwise handling aChar. (This occurs only when aChar is '\'.)
*/
PRBool
nsCSSScanner::GatherIdent(PRInt32 aChar, nsString& aIdent)
{
if (aChar == CSS_ESCAPE) {
ParseAndAppendEscape(aIdent);
if (!ParseAndAppendEscape(aIdent, PR_FALSE)) {
return PR_FALSE;
}
}
else if (0 < aChar) {
aIdent.Append(aChar);
@ -1103,7 +1128,10 @@ nsCSSScanner::GatherIdent(PRInt32 aChar, nsString& aIdent)
aChar = Read();
if (aChar < 0) break;
if (aChar == CSS_ESCAPE) {
ParseAndAppendEscape(aIdent);
if (!ParseAndAppendEscape(aIdent, PR_FALSE)) {
Pushback(aChar);
break;
}
} else if (IsIdent(aChar)) {
aIdent.Append(PRUnichar(aChar));
} else {
@ -1117,19 +1145,24 @@ nsCSSScanner::GatherIdent(PRInt32 aChar, nsString& aIdent)
PRBool
nsCSSScanner::ParseRef(PRInt32 aChar, nsCSSToken& aToken)
{
aToken.mIdent.SetLength(0);
aToken.mType = eCSSToken_Ref;
// Fall back for when we don't have name characters following:
aToken.mType = eCSSToken_Symbol;
aToken.mSymbol = aChar;
PRInt32 ch = Read();
if (ch < 0) {
return PR_FALSE;
return PR_TRUE;
}
if (IsIdent(ch) || ch == CSS_ESCAPE) {
// First char after the '#' is a valid ident char (or an escape),
// so it makes sense to keep going
if (StartsIdent(ch, Peek())) {
aToken.mType = eCSSToken_ID;
nsCSSTokenType type =
StartsIdent(ch, Peek()) ? eCSSToken_ID : eCSSToken_Ref;
aToken.mIdent.SetLength(0);
if (GatherIdent(ch, aToken.mIdent)) {
aToken.mType = type;
return PR_TRUE;
}
return GatherIdent(ch, aToken.mIdent);
}
// No ident chars after the '#'. Just unread |ch| and get out of here.
@ -1143,7 +1176,9 @@ nsCSSScanner::ParseIdent(PRInt32 aChar, nsCSSToken& aToken)
nsString& ident = aToken.mIdent;
ident.SetLength(0);
if (!GatherIdent(aChar, ident)) {
return PR_FALSE;
aToken.mType = eCSSToken_Symbol;
aToken.mSymbol = aChar;
return PR_TRUE;
}
nsCSSTokenType tokenType = eCSSToken_Ident;
@ -1167,7 +1202,11 @@ nsCSSScanner::ParseAtKeyword(PRInt32 aChar, nsCSSToken& aToken)
{
aToken.mIdent.SetLength(0);
aToken.mType = eCSSToken_AtKeyword;
return GatherIdent(0, aToken.mIdent);
if (!GatherIdent(0, aToken.mIdent)) {
aToken.mType = eCSSToken_Symbol;
aToken.mSymbol = PRUnichar('@');
}
return PR_TRUE;
}
PRBool
@ -1287,10 +1326,9 @@ nsCSSScanner::ParseNumber(PRInt32 c, nsCSSToken& aToken)
// Look at character that terminated the number
if (c >= 0) {
if (StartsIdent(c, Peek())) {
if (!GatherIdent(c, ident)) {
return PR_FALSE;
if (GatherIdent(c, ident)) {
type = eCSSToken_Dimension;
}
type = eCSSToken_Dimension;
} else if ('%' == c) {
type = eCSSToken_Percentage;
value = value / 100.0f;
@ -1367,7 +1405,21 @@ nsCSSScanner::ParseString(PRInt32 aStop, nsCSSToken& aToken)
break;
}
if (ch == CSS_ESCAPE) {
ParseAndAppendEscape(aToken.mIdent);
if (!ParseAndAppendEscape(aToken.mIdent, PR_TRUE)) {
aToken.mType = eCSSToken_Bad_String;
Pushback(ch);
#ifdef CSS_REPORT_PARSE_ERRORS
// For strings, the only case where ParseAndAppendEscape will
// return false is when there's a backslash to start an escape
// immediately followed by end-of-stream. In that case, the
// correct tokenization is badstring *followed* by a DELIM for
// the backslash, but as far as the author is concerned, it
// works pretty much the same as an unterminated string, so we
// use the same error message.
ReportUnexpectedToken(aToken, "SEUnterminatedString");
#endif
break;
}
} else {
aToken.mIdent.Append(ch);
}

View File

@ -214,8 +214,8 @@ protected:
PRBool LookAhead(PRUnichar aChar);
PRBool LookAheadOrEOF(PRUnichar aChar); // expect either aChar or EOF
void EatWhiteSpace();
void ParseAndAppendEscape(nsString& aOutput);
PRBool ParseAndAppendEscape(nsString& aOutput, PRBool aInString);
PRBool ParseIdent(PRInt32 aChar, nsCSSToken& aResult);
PRBool ParseAtKeyword(PRInt32 aChar, nsCSSToken& aResult);
PRBool ParseNumber(PRInt32 aChar, nsCSSToken& aResult);

View File

@ -48,7 +48,7 @@ base + "#a {color: rgb\n(255, 0, 0)}",
"@threedee maroon url('asdf\n) ra('asdf\n); " + base,
"@threedee {maroon url('asdf\n) ra('asdf\n);} " + base,
"div[title='zxcv weeqweqeweasd\\D\\A a']{color:green}",
"div[title~='weeqweqeweasd\\D\\A a']{color:green}",
"div[title~='weeqweqeweasd']{color:green}",
base + "#a\\\n{color:red}",
base + "#a\v{color:red}",
@ -129,11 +129,7 @@ base + "#a {color: rgb(255.0, 0, 0)}",
"#a {color: rgb(0, 128, 0)}",
"#a {color: rgb(0%, 50%, 0%)}",
"#a {color: rgb(0%, 49.999999999999%, 0%)}",
], prop: "color", pseudo: "",
todo: {
"div[title~='weeqweqeweasd\\D\\A a']{color:green}" : 1,
"div {color:green}#a\\\n{color:red}" : 1
}
], prop: "color", pseudo: ""
},
// Border tests

View File

@ -180,6 +180,13 @@ div.setAttribute("style", "color: url(/*); color: green");
is(div.style.color, 'green',
"URL tokenized correctly outside properties taking URLs");
div.style.listStyleImage = 'url("foo\\\nbar1")';
is(div.style.listStyleImage, 'url("foobar1")',
"escaped newline allowed in string form of URL");
div.style.listStyleImage = 'url(foo\\\nbar2)';
is(div.style.listStyleImage, 'url("foobar1")',
"escaped newline NOT allowed in NON-string form of URL");
</script>
</pre>
</body>

View File

@ -233,6 +233,18 @@ function run() {
});
}
function test_unparseable_via_api(selector)
{
try {
// Test that it is also unparseable when followed by EOF.
ifdoc.body.mozMatchesSelector(selector);
ok(false, "selector '" + selector + "' plus EOF is parse error");
} catch(ex) {
is(ex.code, DOMException.SYNTAX_ERR,
"selector '" + selector + "' plus EOF is parse error");
}
}
function test_balanced_unparseable(selector)
{
var zi1 = ++gCounter;
@ -248,6 +260,7 @@ function run() {
"selector " + selector + " error was recovered from");
ifdoc.body.innerHTML = "";
style_text.data = "";
test_unparseable_via_api(selector);
}
function test_unbalanced_unparseable(selector)
@ -263,6 +276,7 @@ function run() {
"sheet should have no rules since " + selector + " is parse error");
ifdoc.body.innerHTML = "";
style_text.data = "";
test_unparseable_via_api(selector);
}
@ -891,6 +905,26 @@ function run() {
bodychildset([2, 3, 8]),
bodychildset([0, 1, 4, 5, 6, 7]));
// Test that we don't tokenize an empty HASH.
test_balanced_unparseable("#");
test_balanced_unparseable("# ");
test_balanced_unparseable("#, p");
test_balanced_unparseable("# , p");
test_balanced_unparseable("p #");
test_balanced_unparseable("p # ");
test_balanced_unparseable("p #, p");
test_balanced_unparseable("p # , p");
// Test that a backslash alone is not treated as an escape.
test_unparseable_via_api("#\\");
// Test that newline escapes are only supported in strings.
test_balanced_unparseable("di\\\nv");
test_balanced_unparseable("div \\\n p");
test_balanced_unparseable("div\\\n p");
test_balanced_unparseable("div \\\np");
test_balanced_unparseable("div\\\np");
run_deferred_tests();
}