mirror of
https://github.com/mozilla/gecko-dev.git
synced 2024-12-12 00:50:40 +00:00
Bug 1434429 - Use the current offset, not the offset of the start of the current token, when reporting errors for unterminated string/template literals. r=till
--HG-- extra : rebase_source : 102061eec263a03b0eeef9da7159a850234bb216
This commit is contained in:
parent
2b933cb9ed
commit
d2ef6ad9ca
@ -984,11 +984,12 @@ TokenStreamSpecific<CharT, AnyCharsAccess>::error(unsigned errorNumber, ...)
|
||||
va_list args;
|
||||
va_start(args, errorNumber);
|
||||
|
||||
TokenStreamAnyChars& anyChars = anyCharsAccess();
|
||||
ErrorMetadata metadata;
|
||||
if (computeErrorMetadata(&metadata, anyChars.currentToken().pos.begin))
|
||||
if (computeErrorMetadata(&metadata, userbuf.offset())) {
|
||||
TokenStreamAnyChars& anyChars = anyCharsAccess();
|
||||
ReportCompileError(anyChars.cx, Move(metadata), nullptr, JSREPORT_ERROR, errorNumber,
|
||||
args);
|
||||
}
|
||||
|
||||
va_end(args);
|
||||
}
|
||||
@ -1000,11 +1001,12 @@ TokenStreamSpecific<CharT, AnyCharsAccess>::errorAt(uint32_t offset, unsigned er
|
||||
va_list args;
|
||||
va_start(args, errorNumber);
|
||||
|
||||
TokenStreamAnyChars& anyChars = anyCharsAccess();
|
||||
ErrorMetadata metadata;
|
||||
if (computeErrorMetadata(&metadata, offset))
|
||||
if (computeErrorMetadata(&metadata, offset)) {
|
||||
TokenStreamAnyChars& anyChars = anyCharsAccess();
|
||||
ReportCompileError(anyChars.cx, Move(metadata), nullptr, JSREPORT_ERROR, errorNumber,
|
||||
args);
|
||||
}
|
||||
|
||||
va_end(args);
|
||||
}
|
||||
@ -1707,7 +1709,7 @@ TokenStreamSpecific<CharT, AnyCharsAccess>::getTokenInternal(TokenKind* ttp, Mod
|
||||
// Look for a string or a template string.
|
||||
//
|
||||
if (c1kind == String) {
|
||||
if (!getStringOrTemplateToken(c, &tp))
|
||||
if (!getStringOrTemplateToken(static_cast<char>(c), &tp))
|
||||
goto error;
|
||||
goto out;
|
||||
}
|
||||
@ -2131,8 +2133,11 @@ TokenStreamSpecific<CharT, AnyCharsAccess>::getTokenInternal(TokenKind* ttp, Mod
|
||||
|
||||
template<typename CharT, class AnyCharsAccess>
|
||||
bool
|
||||
TokenStreamSpecific<CharT, AnyCharsAccess>::getStringOrTemplateToken(int untilChar, Token** tp)
|
||||
TokenStreamSpecific<CharT, AnyCharsAccess>::getStringOrTemplateToken(char untilChar, Token** tp)
|
||||
{
|
||||
MOZ_ASSERT(untilChar == '\'' || untilChar == '"' || untilChar == '`',
|
||||
"unexpected string/template literal delimiter");
|
||||
|
||||
int c;
|
||||
int nc = -1;
|
||||
|
||||
@ -2147,7 +2152,8 @@ TokenStreamSpecific<CharT, AnyCharsAccess>::getStringOrTemplateToken(int untilCh
|
||||
while ((c = getCharIgnoreEOL()) != untilChar) {
|
||||
if (c == EOF) {
|
||||
ungetCharIgnoreEOL(c);
|
||||
error(JSMSG_UNTERMINATED_STRING);
|
||||
const char delimiters[] = { untilChar, untilChar, '\0' };
|
||||
error(JSMSG_EOF_BEFORE_END_OF_LITERAL, delimiters);
|
||||
return false;
|
||||
}
|
||||
|
||||
@ -2159,7 +2165,13 @@ TokenStreamSpecific<CharT, AnyCharsAccess>::getStringOrTemplateToken(int untilCh
|
||||
if (!getChar(&c))
|
||||
return false;
|
||||
|
||||
switch (c) {
|
||||
if (c == EOF) {
|
||||
const char delimiters[] = { untilChar, untilChar, '\0' };
|
||||
error(JSMSG_EOF_IN_ESCAPE_IN_LITERAL, delimiters);
|
||||
return false;
|
||||
}
|
||||
|
||||
switch (static_cast<CharT>(c)) {
|
||||
case 'b': c = '\b'; break;
|
||||
case 'f': c = '\f'; break;
|
||||
case 'n': c = '\n'; break;
|
||||
@ -2345,7 +2357,8 @@ TokenStreamSpecific<CharT, AnyCharsAccess>::getStringOrTemplateToken(int untilCh
|
||||
} else if (TokenBuf::isRawEOLChar(c)) {
|
||||
if (!parsingTemplate) {
|
||||
ungetCharIgnoreEOL(c);
|
||||
error(JSMSG_UNTERMINATED_STRING);
|
||||
const char delimiters[] = { untilChar, untilChar, '\0' };
|
||||
error(JSMSG_EOL_BEFORE_END_OF_STRING, delimiters);
|
||||
return false;
|
||||
}
|
||||
if (c == '\r') {
|
||||
|
@ -1437,7 +1437,7 @@ class MOZ_STACK_CLASS TokenStreamSpecific
|
||||
|
||||
MOZ_MUST_USE bool getTokenInternal(TokenKind* ttp, Modifier modifier);
|
||||
|
||||
MOZ_MUST_USE bool getStringOrTemplateToken(int untilChar, Token** tp);
|
||||
MOZ_MUST_USE bool getStringOrTemplateToken(char untilChar, Token** tp);
|
||||
|
||||
// Try to get the next character, normalizing '\r', '\r\n', and '\n' into
|
||||
// '\n'. Also updates internal line-counter state. Return true on success
|
||||
|
@ -338,7 +338,9 @@ MSG_DEF(JSMSG_UNNAMED_CLASS_STMT, 0, JSEXN_SYNTAXERR, "class statement requ
|
||||
MSG_DEF(JSMSG_UNNAMED_FUNCTION_STMT, 0, JSEXN_SYNTAXERR, "function statement requires a name")
|
||||
MSG_DEF(JSMSG_UNTERMINATED_COMMENT, 0, JSEXN_SYNTAXERR, "unterminated comment")
|
||||
MSG_DEF(JSMSG_UNTERMINATED_REGEXP, 0, JSEXN_SYNTAXERR, "unterminated regular expression literal")
|
||||
MSG_DEF(JSMSG_UNTERMINATED_STRING, 0, JSEXN_SYNTAXERR, "unterminated string literal")
|
||||
MSG_DEF(JSMSG_EOF_BEFORE_END_OF_LITERAL,1,JSEXN_SYNTAXERR, "{0} literal not terminated before end of script")
|
||||
MSG_DEF(JSMSG_EOL_BEFORE_END_OF_STRING,1, JSEXN_SYNTAXERR, "{0} string literal contains an unescaped line break")
|
||||
MSG_DEF(JSMSG_EOF_IN_ESCAPE_IN_LITERAL,1, JSEXN_SYNTAXERR, "reached end of script in the middle of an escape sequence in a {0} literal")
|
||||
MSG_DEF(JSMSG_USELESS_EXPR, 0, JSEXN_TYPEERR, "useless expression")
|
||||
MSG_DEF(JSMSG_USE_ASM_DIRECTIVE_FAIL, 0, JSEXN_SYNTAXERR, "\"use asm\" is only meaningful in the Directive Prologue of a function body")
|
||||
MSG_DEF(JSMSG_VAR_HIDES_ARG, 1, JSEXN_TYPEERR, "variable {0} redeclares argument")
|
||||
|
@ -0,0 +1,119 @@
|
||||
/*
|
||||
* Any copyright is dedicated to the Public Domain.
|
||||
* http://creativecommons.org/licenses/publicdomain/
|
||||
*/
|
||||
|
||||
var BUGNUMBER = 9999999;
|
||||
var summary =
|
||||
"Report unterminated string/template literal errors with the line/column " +
|
||||
"number of the point of non-termination";
|
||||
|
||||
function test(f, quotes, [line, col])
|
||||
{
|
||||
var caught = false;
|
||||
try
|
||||
{
|
||||
f();
|
||||
}
|
||||
catch (e)
|
||||
{
|
||||
caught = true;
|
||||
assertEq(e.lineNumber, line, "line number");
|
||||
assertEq(e.columnNumber, col, "column number");
|
||||
assertEq(e.message.includes(quotes), true,
|
||||
"message must contain delimiter");
|
||||
}
|
||||
|
||||
assertEq(caught, true);
|
||||
}
|
||||
|
||||
test(function() {
|
||||
//0123
|
||||
eval("'hi");
|
||||
}, "''", [1, 3]);
|
||||
|
||||
test(function() {
|
||||
//0123 4
|
||||
eval("'hi\\");
|
||||
}, "''", [1, 4]);
|
||||
|
||||
test(function() {
|
||||
//0123456
|
||||
eval(" 'hi");
|
||||
}, "''", [1, 6]);
|
||||
|
||||
test(function() {
|
||||
//0123456 7
|
||||
eval(" 'hi\\");
|
||||
}, "''", [1, 7]);
|
||||
|
||||
test(function() {
|
||||
//01234567 01234567
|
||||
eval('var x =\n "hi');
|
||||
}, '""', [2, 7]);
|
||||
|
||||
test(function() {
|
||||
//0123456 01234567 8
|
||||
eval('var x =\n "hi\\');
|
||||
}, '""', [2, 8]);
|
||||
|
||||
test(function() {
|
||||
// 1
|
||||
//0123456 01234567 012345678 01234567890123
|
||||
eval('var x =\n "hi\\\n bye\\\n no really');
|
||||
}, '""', [4, 13]);
|
||||
|
||||
test(function() {
|
||||
// 1
|
||||
//0123456 01234567 012345678 01234567890123 4
|
||||
eval('var x =\n "hi\\\n bye\\\n no really\\');
|
||||
}, '""', [4, 14]);
|
||||
|
||||
test(function() {
|
||||
//0123456 01234567 012345678
|
||||
eval('var x =\n "hi\\\n bye\n');
|
||||
}, '""', [3, 8]);
|
||||
|
||||
test(function() {
|
||||
//0123456 01234567 012345678 9
|
||||
eval('var x =\n "hi\\\n bye\\');
|
||||
}, '""', [3, 9]);
|
||||
|
||||
test(function() {
|
||||
//0123456 01234567
|
||||
eval('var x =\n `');
|
||||
}, '``', [2, 7]);
|
||||
|
||||
test(function() {
|
||||
//0123456 01234567 8
|
||||
eval('var x =\n `\\');
|
||||
}, '``', [2, 8]);
|
||||
|
||||
test(function() {
|
||||
// 1
|
||||
//0123456 0123456789012345
|
||||
eval('var x =\n htmlEscape`');
|
||||
}, '``', [2, 15]);
|
||||
|
||||
test(function() {
|
||||
// 1
|
||||
//0123456 0123456789012345 6
|
||||
eval('var x =\n htmlEscape`\\');
|
||||
}, '``', [2, 16]);
|
||||
|
||||
test(function() {
|
||||
// 1
|
||||
//0123456 01234567890123 01234
|
||||
eval('var x =\n htmlEscape\n `');
|
||||
}, '``', [3, 4]);
|
||||
|
||||
test(function() {
|
||||
// 1
|
||||
//0123456 01234567890123 01234 5
|
||||
eval('var x =\n htmlEscape\n `\\');
|
||||
}, '``', [3, 5]);
|
||||
|
||||
if (typeof reportCompare === "function")
|
||||
reportCompare(0, 0, "ok");
|
||||
|
||||
print("Tests complete");
|
Loading…
Reference in New Issue
Block a user