Revision: 19067
Author: [email protected]
Date: Tue Feb 4 12:19:53 2014 UTC
Log: Tests and fixes for (pre)parse errors related to strict reserved
words.
This contains the following fixes:
- We had strict_reserved_word and unexpected_strict_reserved, which one to
use
was totally mixed in Parser and PreParser. Removed strict_reserved_word.
- When we saw a strict future reserved word when expecting something
completely
different (such as "(" in "function foo interface"), Parser reports
unexpected
identifier, whereas PreParser used to report unexpected strict reserved
word. Fixed PreParser to report unexpected identifier too.
- Unified parser and preparser error locations when the name of a function
is a
strict reserved word. Now both point to the name.
BUG=3126
LOG=N
[email protected]
Review URL: https://codereview.chromium.org/149253010
http://code.google.com/p/v8/source/detail?r=19067
Modified:
/branches/bleeding_edge/src/messages.js
/branches/bleeding_edge/src/parser.cc
/branches/bleeding_edge/src/preparser.cc
/branches/bleeding_edge/test/cctest/test-parsing.cc
=======================================
--- /branches/bleeding_edge/src/messages.js Fri Jan 31 12:21:17 2014 UTC
+++ /branches/bleeding_edge/src/messages.js Tue Feb 4 12:19:53 2014 UTC
@@ -170,7 +170,6 @@
strict_lhs_assignment: ["Assignment to eval or arguments is not
allowed in strict mode"],
strict_lhs_postfix: ["Postfix increment/decrement may not
have eval or arguments operand in strict mode"],
strict_lhs_prefix: ["Prefix increment/decrement may not have
eval or arguments operand in strict mode"],
- strict_reserved_word: ["Use of future reserved word in strict
mode"],
strict_delete: ["Delete of an unqualified identifier in
strict mode."],
strict_delete_property: ["Cannot delete property '", "%0", "'
of ", "%1"],
strict_const: ["Use of const in strict mode."],
=======================================
--- /branches/bleeding_edge/src/parser.cc Tue Feb 4 11:26:19 2014 UTC
+++ /branches/bleeding_edge/src/parser.cc Tue Feb 4 12:19:53 2014 UTC
@@ -4321,17 +4321,13 @@
return NULL;
}
if (name_is_strict_reserved) {
- int start_pos = scope->start_position();
- int position = function_token_pos != RelocInfo::kNoPosition
- ? function_token_pos : (start_pos > 0 ? start_pos - 1 :
start_pos);
- Scanner::Location location = Scanner::Location(position,
start_pos);
- ReportMessageAt(location, "strict_reserved_word",
+
ReportMessageAt(function_name_location, "unexpected_strict_reserved",
Vector<const char*>::empty());
*ok = false;
return NULL;
}
if (reserved_loc.IsValid()) {
- ReportMessageAt(reserved_loc, "strict_reserved_word",
+ ReportMessageAt(reserved_loc, "unexpected_strict_reserved",
Vector<const char*>::empty());
*ok = false;
return NULL;
=======================================
--- /branches/bleeding_edge/src/preparser.cc Tue Jan 28 19:11:13 2014 UTC
+++ /branches/bleeding_edge/src/preparser.cc Tue Feb 4 12:19:53 2014 UTC
@@ -121,7 +121,9 @@
return ReportMessageAt(source_location, "unexpected_reserved", NULL);
case Token::FUTURE_STRICT_RESERVED_WORD:
return ReportMessageAt(source_location,
- "unexpected_strict_reserved", NULL);
+
is_classic_mode() ? "unexpected_token_identifier"
+ : "unexpected_strict_reserved",
+ NULL);
default:
const char* name = Token::String(token);
ReportMessageAt(source_location, "unexpected_token", name);
@@ -304,7 +306,7 @@
// as name of strict function.
const char* type = "strict_function_name";
if (identifier.IsFutureStrictReserved() || identifier.IsYield()) {
- type = "strict_reserved_word";
+ type = "unexpected_strict_reserved";
}
ReportMessageAt(location, type, NULL);
*ok = false;
@@ -1511,7 +1513,7 @@
if (!is_classic_mode()) {
Scanner::Location location = scanner()->location();
ReportMessageAt(location.beg_pos, location.end_pos,
- "strict_reserved_word", NULL);
+ "unexpected_strict_reserved", NULL);
*ok = false;
}
// FALLTHROUGH
@@ -1565,7 +1567,7 @@
if (identifier.IsFutureReserved()) {
type = "reserved_word";
} else if (identifier.IsFutureStrictReserved() || identifier.IsYield()) {
- type = "strict_reserved_word";
+ type = "unexpected_strict_reserved";
}
if (!is_classic_mode()) {
ReportMessageAt(location, type, NULL);
=======================================
--- /branches/bleeding_edge/test/cctest/test-parsing.cc Tue Feb 4 11:26:19
2014 UTC
+++ /branches/bleeding_edge/test/cctest/test-parsing.cc Tue Feb 4 12:19:53
2014 UTC
@@ -1347,6 +1347,60 @@
}
+namespace {
+
+const char* use_strict_prefix = "\"use strict\";\n";
+
+const char* strict_catch_variable_preparse = "strict_catch_variable";
+const char* strict_catch_variable_parse =
+ "SyntaxError: Catch variable may not be eval or arguments in strict
mode";
+
+const char* strict_function_name_preparse = "strict_function_name";
+const char* strict_function_name_parse =
+ "SyntaxError: Function name may not be eval or arguments in strict
mode";
+
+const char* strict_lhs_assignment_preparse = "strict_lhs_assignment";
+const char* strict_lhs_assignment_parse =
+ "SyntaxError: Assignment to eval or arguments is not allowed in
strict "
+ "mode";
+
+const char* strict_lhs_postfix_preparse = "strict_lhs_postfix";
+const char* strict_lhs_postfix_parse =
+ "SyntaxError: Postfix increment/decrement may not have eval or
arguments "
+ "operand in strict mode";
+
+const char* strict_lhs_prefix_preparse = "strict_lhs_prefix";
+const char* strict_lhs_prefix_parse =
+ "SyntaxError: Prefix increment/decrement may not have eval or
arguments "
+ "operand in strict mode";
+
+const char* strict_param_name_preparse = "strict_param_name";
+const char* strict_param_name_parse =
+ "SyntaxError: Parameter name eval or arguments is not allowed in
strict "
+ "mode";
+
+const char* strict_var_name_preparse = "strict_var_name";
+const char* strict_var_name_parse =
+ "SyntaxError: Variable name may not be eval or arguments in strict
mode";
+
+const char* unexpected_strict_reserved_preparse
= "unexpected_strict_reserved";
+const char* unexpected_strict_reserved_parse =
+ "SyntaxError: Unexpected strict mode reserved word";
+
+const char* unexpected_token_identifier_preparse =
+ "unexpected_token_identifier";
+const char* unexpected_token_identifier_parse =
+ "SyntaxError: Unexpected identifier";
+
+struct ParseErrorTestCase {
+ const char* source;
+ int error_location_beg;
+ int error_location_end;
+ const char* preparse_error_message;
+ const char* parse_error_message;
+};
+
+
void VerifyPreParseAndParseNoError(v8::Handle<v8::String> source) {
v8::ScriptData* preparse = v8::ScriptData::PreCompile(source);
CHECK(!preparse->HasError());
@@ -1381,6 +1435,8 @@
CHECK_EQ(error_location_end, try_catch.Message()->GetEndPosition());
}
+} // namespace
+
TEST(ErrorsEvalAndArguments) {
// Tests that both preparsing and parsing produce the right kind of
errors for
@@ -1392,48 +1448,9 @@
v8::Local<v8::Context> context = v8::Context::New(isolate);
v8::Context::Scope context_scope(context);
- const char* use_strict_prefix = "\"use strict\";\n";
int prefix_length = i::StrLength(use_strict_prefix);
- const char* strict_var_name_preparse = "strict_var_name";
- const char* strict_var_name_parse =
- "SyntaxError: Variable name may not be eval or arguments in strict
mode";
-
- const char* strict_catch_variable_preparse = "strict_catch_variable";
- const char* strict_catch_variable_parse =
- "SyntaxError: Catch variable may not be eval or arguments in strict
mode";
-
- const char* strict_function_name_preparse = "strict_function_name";
- const char* strict_function_name_parse =
- "SyntaxError: Function name may not be eval or arguments in strict
mode";
-
- const char* strict_param_name_preparse = "strict_param_name";
- const char* strict_param_name_parse =
- "SyntaxError: Parameter name eval or arguments is not allowed in
strict "
- "mode";
-
- const char* strict_lhs_assignment_preparse = "strict_lhs_assignment";
- const char* strict_lhs_assignment_parse =
- "SyntaxError: Assignment to eval or arguments is not allowed in
strict "
- "mode";
-
- const char* strict_lhs_prefix_preparse = "strict_lhs_prefix";
- const char* strict_lhs_prefix_parse =
- "SyntaxError: Prefix increment/decrement may not have eval or
arguments "
- "operand in strict mode";
-
- const char* strict_lhs_postfix_preparse = "strict_lhs_postfix";
- const char* strict_lhs_postfix_parse =
- "SyntaxError: Postfix increment/decrement may not have eval or
arguments "
- "operand in strict mode";
-
- struct TestCase {
- const char* source;
- int error_location_beg;
- int error_location_end;
- const char* preparse_error_message;
- const char* parse_error_message;
- } test_cases[] = {
+ ParseErrorTestCase test_cases[] = {
{"var eval = 42;", 4, 8, strict_var_name_preparse,
strict_var_name_parse},
{"var arguments = 42;", 4, 13, strict_var_name_preparse,
strict_var_name_parse},
@@ -1472,18 +1489,154 @@
for (int i = 0; test_cases[i].source; ++i) {
v8::Handle<v8::String> source =
v8::String::NewFromUtf8(isolate, test_cases[i].source);
-
VerifyPreParseAndParseNoError(source);
v8::Handle<v8::String> strict_source = v8::String::Concat(
v8::String::NewFromUtf8(isolate, use_strict_prefix),
v8::String::NewFromUtf8(isolate, test_cases[i].source));
+ VerifyPreParseAndParseErrorMessages(
+ strict_source,
+ test_cases[i].error_location_beg + prefix_length,
+ test_cases[i].error_location_end + prefix_length,
+ test_cases[i].preparse_error_message,
+ test_cases[i].parse_error_message);
+ }
+ // Test cases which produce an error also in non-strict mode.
+ ParseErrorTestCase error_test_cases[] = {
+ // In this case we expect something completely different, "(", and get
+ // "eval". It's always "unexpected identifier, whether we are in
strict mode
+ // or not.
+ {"function foo eval", 13, 17, unexpected_token_identifier_preparse,
+ unexpected_token_identifier_parse},
+ {"\"use strict\"; function foo eval", 27, 31,
+ unexpected_token_identifier_preparse,
unexpected_token_identifier_parse},
+ {NULL, 0, 0, NULL, NULL}
+ };
+
+ for (int i = 0; error_test_cases[i].source; ++i) {
+ v8::Handle<v8::String> source =
+ v8::String::NewFromUtf8(isolate, error_test_cases[i].source);
VerifyPreParseAndParseErrorMessages(
+ source,
+ error_test_cases[i].error_location_beg,
+ error_test_cases[i].error_location_end,
+ error_test_cases[i].preparse_error_message,
+ error_test_cases[i].parse_error_message);
+ }
+
+ // Test cases where only a sub-scope is strict.
+ ParseErrorTestCase scoped_test_cases[] = {
+ {"var eval = 1; function foo() { \"use strict\"; var arguments = 2; }",
+ 49, 58, strict_var_name_preparse, strict_var_name_parse},
+ {NULL, 0, 0, NULL, NULL}
+ };
+
+ for (int i = 0; scoped_test_cases[i].source; ++i) {
+ v8::Handle<v8::String> source =
+ v8::String::NewFromUtf8(isolate, scoped_test_cases[i].source);
+ VerifyPreParseAndParseErrorMessages(
+ source,
+ scoped_test_cases[i].error_location_beg,
+ scoped_test_cases[i].error_location_end,
+ scoped_test_cases[i].preparse_error_message,
+ scoped_test_cases[i].parse_error_message);
+ }
+}
+
+
+TEST(ErrorsFutureStrictReservedWords) {
+ // Tests that both preparsing and parsing produce the right kind of
errors for
+ // using future strict reserved words as identifiers. Without the strict
mode,
+ // it's ok to use future strict reserved words as identifiers. With the
strict
+ // mode, it isn't.
+ v8::Isolate* isolate = CcTest::isolate();
+ v8::HandleScope handles(isolate);
+ v8::Local<v8::Context> context = v8::Context::New(isolate);
+ v8::Context::Scope context_scope(context);
+
+ const char* use_strict_prefix = "\"use strict\";\n";
+ int prefix_length = i::StrLength(use_strict_prefix);
+
+ ParseErrorTestCase test_cases[] = {
+ {"var interface = 42;", 4, 13, unexpected_strict_reserved_preparse,
+ unexpected_strict_reserved_parse},
+ {"var foo, interface;", 9, 18, unexpected_strict_reserved_preparse,
+ unexpected_strict_reserved_parse},
+ {"try { } catch (interface) { }", 15, 24,
+ unexpected_strict_reserved_preparse,
unexpected_strict_reserved_parse},
+ {"function interface() { }", 9, 18,
unexpected_strict_reserved_preparse,
+ unexpected_strict_reserved_parse},
+ {"function foo(interface) { }", 13, 22,
unexpected_strict_reserved_preparse,
+ unexpected_strict_reserved_parse},
+ {"function foo(bar, interface) { }", 18, 27,
+ unexpected_strict_reserved_preparse,
unexpected_strict_reserved_parse},
+ {"interface = 1;", 0, 9, unexpected_strict_reserved_preparse,
+ unexpected_strict_reserved_parse},
+ {"++interface;", 2, 11, unexpected_strict_reserved_preparse,
+ unexpected_strict_reserved_parse},
+ {"interface++;", 0, 9, unexpected_strict_reserved_preparse,
+ unexpected_strict_reserved_parse},
+ {NULL, 0, 0, NULL, NULL}
+ };
+
+ for (int i = 0; test_cases[i].source; ++i) {
+ v8::Handle<v8::String> source =
+ v8::String::NewFromUtf8(isolate, test_cases[i].source);
+ VerifyPreParseAndParseNoError(source);
+
+ v8::Handle<v8::String> strict_source = v8::String::Concat(
+ v8::String::NewFromUtf8(isolate, use_strict_prefix),
+ v8::String::NewFromUtf8(isolate, test_cases[i].source));
+ VerifyPreParseAndParseErrorMessages(
strict_source,
test_cases[i].error_location_beg + prefix_length,
test_cases[i].error_location_end + prefix_length,
test_cases[i].preparse_error_message,
test_cases[i].parse_error_message);
}
+
+ // Test cases which produce an error also in non-strict mode.
+ ParseErrorTestCase error_test_cases[] = {
+ // In this case we expect something completely different, "(", and get
a
+ // strict reserved word. Note that this differs from the "eval or
arguments"
+ // case; there we just report an unexpected identifier.
+ {"function foo interface", 13, 22,
+ unexpected_token_identifier_preparse,
+ unexpected_token_identifier_parse},
+ {"\"use strict\"; function foo interface", 27, 36,
+ unexpected_strict_reserved_preparse,
+ unexpected_strict_reserved_parse},
+ {NULL, 0, 0, NULL, NULL}
+ };
+
+ for (int i = 0; error_test_cases[i].source; ++i) {
+ v8::Handle<v8::String> source =
+ v8::String::NewFromUtf8(isolate, error_test_cases[i].source);
+ VerifyPreParseAndParseErrorMessages(
+ source,
+ error_test_cases[i].error_location_beg,
+ error_test_cases[i].error_location_end,
+ error_test_cases[i].preparse_error_message,
+ error_test_cases[i].parse_error_message);
+ }
+
+ // Test cases where only a sub-scope is strict.
+ ParseErrorTestCase scoped_test_cases[] = {
+ {"var interface = 1; function foo() { \"use strict\"; var interface =
2; }",
+ 54, 63, unexpected_strict_reserved_preparse,
+ unexpected_strict_reserved_parse},
+ {NULL, 0, 0, NULL, NULL}
+ };
+
+ for (int i = 0; scoped_test_cases[i].source; ++i) {
+ v8::Handle<v8::String> source =
+ v8::String::NewFromUtf8(isolate, scoped_test_cases[i].source);
+ VerifyPreParseAndParseErrorMessages(
+ source,
+ scoped_test_cases[i].error_location_beg,
+ scoped_test_cases[i].error_location_end,
+ scoped_test_cases[i].preparse_error_message,
+ scoped_test_cases[i].parse_error_message);
+ }
}
--
--
v8-dev mailing list
[email protected]
http://groups.google.com/group/v8-dev
---
You received this message because you are subscribed to the Google Groups "v8-dev" group.
To unsubscribe from this group and stop receiving emails from it, send an email
to [email protected].
For more options, visit https://groups.google.com/groups/opt_out.