Revision: 19062
Author: [email protected]
Date: Tue Feb 4 11:26:19 2014 UTC
Log: Tests for (pre)parse errors when "eval" and "arguments" are found
in inappropriate places.
In addition:
- Fix a bug in parser discovered by the tests (prefix and postfix confused
in an
error message); the preparser had it right.
- Unify the parser and preparser error locations when the name of a
function is
"eval" or "arguments. Now both point to the name.
BUG=3126
LOG=N
[email protected]
Review URL: https://codereview.chromium.org/153693002
http://code.google.com/p/v8/source/detail?r=19062
Modified:
/branches/bleeding_edge/src/parser.cc
/branches/bleeding_edge/src/parser.h
/branches/bleeding_edge/test/cctest/test-parsing.cc
/branches/bleeding_edge/test/webkit/fast/js/basic-strict-mode-expected.txt
=======================================
--- /branches/bleeding_edge/src/parser.cc Tue Feb 4 10:00:36 2014 UTC
+++ /branches/bleeding_edge/src/parser.cc Tue Feb 4 11:26:19 2014 UTC
@@ -770,6 +770,7 @@
: FunctionLiteral::DECLARATION;
bool ok = true;
result = ParseFunctionLiteral(name,
+ Scanner::Location::invalid(),
false, // Strict mode name already
checked.
shared_info->is_generator(),
RelocInfo::kNoPosition,
@@ -1679,6 +1680,7 @@
Handle<String> name = ParseIdentifierOrStrictReservedWord(
&is_strict_reserved, CHECK_OK);
FunctionLiteral* fun = ParseFunctionLiteral(name,
+ scanner().location(),
is_strict_reserved,
is_generator,
pos,
@@ -3251,7 +3253,7 @@
if (!top_scope_->is_classic_mode()) {
// Postfix expression operand in strict mode may not be eval or
arguments.
- CheckStrictModeLValue(expression, "strict_lhs_prefix", CHECK_OK);
+ CheckStrictModeLValue(expression, "strict_lhs_postfix", CHECK_OK);
}
MarkAsLValue(expression);
@@ -3400,14 +3402,17 @@
bool is_generator = allow_generators() && Check(Token::MUL);
Handle<String> name;
bool is_strict_reserved_name = false;
+ Scanner::Location function_name_location =
Scanner::Location::invalid();
if (peek_any_identifier()) {
name = ParseIdentifierOrStrictReservedWord(&is_strict_reserved_name,
CHECK_OK);
+ function_name_location = scanner().location();
}
FunctionLiteral::FunctionType function_type = name.is_null()
? FunctionLiteral::ANONYMOUS_EXPRESSION
: FunctionLiteral::NAMED_EXPRESSION;
result = ParseFunctionLiteral(name,
+ function_name_location,
is_strict_reserved_name,
is_generator,
function_token_position,
@@ -3764,6 +3769,7 @@
: GetSymbol();
FunctionLiteral* value =
ParseFunctionLiteral(name,
+ scanner().location(),
false, // reserved words are allowed
here
false, // not a generator
RelocInfo::kNoPosition,
@@ -4010,6 +4016,7 @@
FunctionLiteral* Parser::ParseFunctionLiteral(
Handle<String> function_name,
+ Scanner::Location function_name_location,
bool name_is_strict_reserved,
bool is_generator,
int function_token_pos,
@@ -4295,12 +4302,9 @@
// Validate strict mode.
if (!top_scope_->is_classic_mode()) {
if (IsEvalOrArguments(function_name)) {
- 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_function_name", Vector<const
char*>::empty());
+ ReportMessageAt(function_name_location,
+ "strict_function_name",
+ Vector<const char*>::empty());
*ok = false;
return NULL;
}
=======================================
--- /branches/bleeding_edge/src/parser.h Tue Feb 4 10:00:36 2014 UTC
+++ /branches/bleeding_edge/src/parser.h Tue Feb 4 11:26:19 2014 UTC
@@ -645,13 +645,14 @@
Statement* body);
ZoneList<Expression*>* ParseArguments(bool* ok);
- FunctionLiteral* ParseFunctionLiteral(Handle<String> var_name,
- bool name_is_reserved,
- bool is_generator,
- int function_token_position,
- FunctionLiteral::FunctionType type,
- bool* ok);
-
+ FunctionLiteral* ParseFunctionLiteral(
+ Handle<String> var_name,
+ Scanner::Location function_name_location,
+ bool name_is_reserved,
+ bool is_generator,
+ int function_token_position,
+ FunctionLiteral::FunctionType type,
+ bool* ok);
// Magical syntax support.
Expression* ParseV8Intrinsic(bool* ok);
=======================================
--- /branches/bleeding_edge/test/cctest/test-parsing.cc Tue Feb 4 10:00:36
2014 UTC
+++ /branches/bleeding_edge/test/cctest/test-parsing.cc Tue Feb 4 11:26:19
2014 UTC
@@ -1345,3 +1345,145 @@
CHECK_EQ("SyntaxError: Octal literals are not allowed in strict mode.",
*exception);
}
+
+
+void VerifyPreParseAndParseNoError(v8::Handle<v8::String> source) {
+ v8::ScriptData* preparse = v8::ScriptData::PreCompile(source);
+ CHECK(!preparse->HasError());
+
+ v8::TryCatch try_catch;
+ v8::Script::Compile(source);
+ CHECK(!try_catch.HasCaught());
+}
+
+
+void VerifyPreParseAndParseErrorMessages(v8::Handle<v8::String> source,
+ int error_location_beg,
+ int error_location_end,
+ const char* preparse_error_message,
+ const char* parse_error_message) {
+ v8::ScriptData* preparse = v8::ScriptData::PreCompile(source);
+ CHECK(preparse->HasError());
+ i::ScriptDataImpl* pre_impl =
+ reinterpret_cast<i::ScriptDataImpl*>(preparse);
+ i::Scanner::Location error_location = pre_impl->MessageLocation();
+ const char* message = pre_impl->BuildMessage();
+ CHECK_EQ(0, strcmp(preparse_error_message, message));
+ CHECK_EQ(error_location_beg, error_location.beg_pos);
+ CHECK_EQ(error_location_end, error_location.end_pos);
+
+ v8::TryCatch try_catch;
+ v8::Script::Compile(source);
+ CHECK(try_catch.HasCaught());
+ v8::String::Utf8Value exception(try_catch.Exception());
+ CHECK_EQ(parse_error_message, *exception);
+ CHECK_EQ(error_location_beg, try_catch.Message()->GetStartPosition());
+ CHECK_EQ(error_location_end, try_catch.Message()->GetEndPosition());
+}
+
+
+TEST(ErrorsEvalAndArguments) {
+ // Tests that both preparsing and parsing produce the right kind of
errors for
+ // using "eval" and "arguments" as identifiers. Without the strict mode,
it's
+ // ok to use "eval" or "arguments" 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);
+
+ 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[] = {
+ {"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},
+ {"var foo, eval;", 9, 13, strict_var_name_preparse,
strict_var_name_parse},
+ {"var foo, arguments;", 9, 18, strict_var_name_preparse,
+ strict_var_name_parse},
+ {"try { } catch (eval) { }", 15, 19, strict_catch_variable_preparse,
+ strict_catch_variable_parse},
+ {"try { } catch (arguments) { }", 15, 24,
strict_catch_variable_preparse,
+ strict_catch_variable_parse},
+ {"function eval() { }", 9, 13, strict_function_name_preparse,
+ strict_function_name_parse},
+ {"function arguments() { }", 9, 18, strict_function_name_preparse,
+ strict_function_name_parse},
+ {"function foo(eval) { }", 13, 17, strict_param_name_preparse,
+ strict_param_name_parse},
+ {"function foo(arguments) { }", 13, 22, strict_param_name_preparse,
+ strict_param_name_parse},
+ {"function foo(bar, eval) { }", 18, 22, strict_param_name_preparse,
+ strict_param_name_parse},
+ {"function foo(bar, arguments) { }", 18, 27,
strict_param_name_preparse,
+ strict_param_name_parse},
+ {"eval = 1;", 0, 4, strict_lhs_assignment_preparse,
+ strict_lhs_assignment_parse},
+ {"arguments = 1;", 0, 9, strict_lhs_assignment_preparse,
+ strict_lhs_assignment_parse},
+ {"++eval;", 2, 6, strict_lhs_prefix_preparse, strict_lhs_prefix_parse},
+ {"++arguments;", 2, 11, strict_lhs_prefix_preparse,
+ strict_lhs_prefix_parse},
+ {"eval++;", 0, 4, strict_lhs_postfix_preparse,
strict_lhs_postfix_parse},
+ {"arguments++;", 0, 9, strict_lhs_postfix_preparse,
+ strict_lhs_postfix_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);
+ }
+}
=======================================
---
/branches/bleeding_edge/test/webkit/fast/js/basic-strict-mode-expected.txt
Thu Jul 25 19:54:24 2013 UTC
+++
/branches/bleeding_edge/test/webkit/fast/js/basic-strict-mode-expected.txt
Tue Feb 4 11:26:19 2014 UTC
@@ -136,20 +136,20 @@
PASS 'use strict'; delete objectWithReadonlyProperty[readonlyPropName]
threw exception TypeError: Cannot delete property 'prop' of #<Object>.
PASS 'use strict'; ++eval threw exception SyntaxError: Prefix
increment/decrement may not have eval or arguments operand in strict mode.
PASS (function(){'use strict'; ++eval}) threw exception SyntaxError:
Prefix increment/decrement may not have eval or arguments operand in strict
mode.
-PASS 'use strict'; eval++ threw exception SyntaxError: Prefix
increment/decrement may not have eval or arguments operand in strict mode.
-PASS (function(){'use strict'; eval++}) threw exception SyntaxError:
Prefix increment/decrement may not have eval or arguments operand in strict
mode.
+PASS 'use strict'; eval++ threw exception SyntaxError: Postfix
increment/decrement may not have eval or arguments operand in strict mode.
+PASS (function(){'use strict'; eval++}) threw exception SyntaxError:
Postfix increment/decrement may not have eval or arguments operand in
strict mode.
PASS 'use strict'; --eval threw exception SyntaxError: Prefix
increment/decrement may not have eval or arguments operand in strict mode.
PASS (function(){'use strict'; --eval}) threw exception SyntaxError:
Prefix increment/decrement may not have eval or arguments operand in strict
mode.
-PASS 'use strict'; eval-- threw exception SyntaxError: Prefix
increment/decrement may not have eval or arguments operand in strict mode.
-PASS (function(){'use strict'; eval--}) threw exception SyntaxError:
Prefix increment/decrement may not have eval or arguments operand in strict
mode.
+PASS 'use strict'; eval-- threw exception SyntaxError: Postfix
increment/decrement may not have eval or arguments operand in strict mode.
+PASS (function(){'use strict'; eval--}) threw exception SyntaxError:
Postfix increment/decrement may not have eval or arguments operand in
strict mode.
PASS 'use strict'; function f() { ++arguments } threw exception
SyntaxError: Prefix increment/decrement may not have eval or arguments
operand in strict mode.
PASS (function(){'use strict'; function f() { ++arguments }}) threw
exception SyntaxError: Prefix increment/decrement may not have eval or
arguments operand in strict mode.
-PASS 'use strict'; function f() { arguments++ } threw exception
SyntaxError: Prefix increment/decrement may not have eval or arguments
operand in strict mode.
-PASS (function(){'use strict'; function f() { arguments++ }}) threw
exception SyntaxError: Prefix increment/decrement may not have eval or
arguments operand in strict mode.
+PASS 'use strict'; function f() { arguments++ } threw exception
SyntaxError: Postfix increment/decrement may not have eval or arguments
operand in strict mode.
+PASS (function(){'use strict'; function f() { arguments++ }}) threw
exception SyntaxError: Postfix increment/decrement may not have eval or
arguments operand in strict mode.
PASS 'use strict'; function f() { --arguments } threw exception
SyntaxError: Prefix increment/decrement may not have eval or arguments
operand in strict mode.
PASS (function(){'use strict'; function f() { --arguments }}) threw
exception SyntaxError: Prefix increment/decrement may not have eval or
arguments operand in strict mode.
-PASS 'use strict'; function f() { arguments-- } threw exception
SyntaxError: Prefix increment/decrement may not have eval or arguments
operand in strict mode.
-PASS (function(){'use strict'; function f() { arguments-- }}) threw
exception SyntaxError: Prefix increment/decrement may not have eval or
arguments operand in strict mode.
+PASS 'use strict'; function f() { arguments-- } threw exception
SyntaxError: Postfix increment/decrement may not have eval or arguments
operand in strict mode.
+PASS (function(){'use strict'; function f() { arguments-- }}) threw
exception SyntaxError: Postfix increment/decrement may not have eval or
arguments operand in strict mode.
PASS global.eval('"use strict"; if (0) ++arguments; true;') threw
exception SyntaxError: Prefix increment/decrement may not have eval or
arguments operand in strict mode.
PASS 'use strict'; ++(1, eval) threw exception ReferenceError: Invalid
left-hand side expression in prefix operation.
FAIL (function(){'use strict'; ++(1, eval)}) should throw an exception.
Was function (){'use strict'; ++(1, eval)}.
--
--
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.