Index: src/parser.cc |
diff --git a/src/parser.cc b/src/parser.cc |
index 50551ea98d386efaadcf0b8c245ba308214cc71f..211f737d6d89c9fd202f9b1cd0af233c50a04627 100644 |
--- a/src/parser.cc |
+++ b/src/parser.cc |
@@ -983,7 +983,7 @@ Statement* Parser::ParseModuleDeclaration(ZoneStringList* names, bool* ok) { |
// 'module' Identifier Module |
int pos = peek_position(); |
- Handle<String> name = ParseIdentifier(CHECK_OK); |
+ Handle<String> name = ParseIdentifier(kDontAllowEvalOrArguments, CHECK_OK); |
#ifdef DEBUG |
if (FLAG_print_interface_details) |
@@ -1136,7 +1136,7 @@ Module* Parser::ParseModuleVariable(bool* ok) { |
// Identifier |
int pos = peek_position(); |
- Handle<String> name = ParseIdentifier(CHECK_OK); |
+ Handle<String> name = ParseIdentifier(kDontAllowEvalOrArguments, CHECK_OK); |
#ifdef DEBUG |
if (FLAG_print_interface_details) |
PrintF("# Module variable %s ", name->ToAsciiArray()); |
@@ -1261,13 +1261,14 @@ Statement* Parser::ParseExportDeclaration(bool* ok) { |
switch (peek()) { |
case Token::IDENTIFIER: { |
int pos = position(); |
- Handle<String> name = ParseIdentifier(CHECK_OK); |
+ Handle<String> name = |
+ ParseIdentifier(kDontAllowEvalOrArguments, CHECK_OK); |
// Handle 'module' as a context-sensitive keyword. |
if (!name->IsOneByteEqualTo(STATIC_ASCII_VECTOR("module"))) { |
names.Add(name, zone()); |
while (peek() == Token::COMMA) { |
Consume(Token::COMMA); |
- name = ParseIdentifier(CHECK_OK); |
+ name = ParseIdentifier(kDontAllowEvalOrArguments, CHECK_OK); |
names.Add(name, zone()); |
} |
ExpectSemicolon(CHECK_OK); |
@@ -1632,11 +1633,12 @@ void Parser::Declare(Declaration* declaration, bool resolve, bool* ok) { |
Statement* Parser::ParseNativeDeclaration(bool* ok) { |
int pos = peek_position(); |
Expect(Token::FUNCTION, CHECK_OK); |
- Handle<String> name = ParseIdentifier(CHECK_OK); |
+ // Allow "eval" or "arguments" for backward compatibility. |
+ Handle<String> name = ParseIdentifier(kAllowEvalOrArguments, CHECK_OK); |
Expect(Token::LPAREN, CHECK_OK); |
bool done = (peek() == Token::RPAREN); |
while (!done) { |
- ParseIdentifier(CHECK_OK); |
+ ParseIdentifier(kAllowEvalOrArguments, CHECK_OK); |
done = (peek() == Token::RPAREN); |
if (!done) { |
Expect(Token::COMMA, CHECK_OK); |
@@ -1900,16 +1902,9 @@ Block* Parser::ParseVariableDeclarations( |
// Parse variable name. |
if (nvars > 0) Consume(Token::COMMA); |
- name = ParseIdentifier(CHECK_OK); |
+ name = ParseIdentifier(kDontAllowEvalOrArguments, CHECK_OK); |
if (fni_ != NULL) fni_->PushVariableName(name); |
- // Strict mode variables may not be named eval or arguments |
- if (!declaration_scope->is_classic_mode() && IsEvalOrArguments(name)) { |
- ReportMessage("strict_var_name", Vector<const char*>::empty()); |
- *ok = false; |
- return NULL; |
- } |
- |
// Declare variable. |
// Note that we *always* must treat the initial value via a separate init |
// assignment for variables and constants because the value must be assigned |
@@ -2224,7 +2219,8 @@ Statement* Parser::ParseContinueStatement(bool* ok) { |
Token::Value tok = peek(); |
if (!scanner().HasAnyLineTerminatorBeforeNext() && |
tok != Token::SEMICOLON && tok != Token::RBRACE && tok != Token::EOS) { |
- label = ParseIdentifier(CHECK_OK); |
+ // ECMA allows "eval" or "arguments" as labels even in strict mode. |
+ label = ParseIdentifier(kAllowEvalOrArguments, CHECK_OK); |
} |
IterationStatement* target = NULL; |
target = LookupContinueTarget(label, CHECK_OK); |
@@ -2255,7 +2251,8 @@ Statement* Parser::ParseBreakStatement(ZoneStringList* labels, bool* ok) { |
Token::Value tok = peek(); |
if (!scanner().HasAnyLineTerminatorBeforeNext() && |
tok != Token::SEMICOLON && tok != Token::RBRACE && tok != Token::EOS) { |
- label = ParseIdentifier(CHECK_OK); |
+ // ECMA allows "eval" or "arguments" as labels even in strict mode. |
+ label = ParseIdentifier(kAllowEvalOrArguments, CHECK_OK); |
} |
// Parse labeled break statements that target themselves into |
// empty statements, e.g. 'l1: l2: l3: break l2;' |
@@ -2485,13 +2482,7 @@ TryStatement* Parser::ParseTryStatement(bool* ok) { |
Expect(Token::LPAREN, CHECK_OK); |
catch_scope = NewScope(top_scope_, CATCH_SCOPE); |
catch_scope->set_start_position(scanner().location().beg_pos); |
- name = ParseIdentifier(CHECK_OK); |
- |
- if (!top_scope_->is_classic_mode() && IsEvalOrArguments(name)) { |
- ReportMessage("strict_catch_variable", Vector<const char*>::empty()); |
- *ok = false; |
- return NULL; |
- } |
+ name = ParseIdentifier(kDontAllowEvalOrArguments, CHECK_OK); |
Expect(Token::RPAREN, CHECK_OK); |
@@ -2939,7 +2930,7 @@ Expression* Parser::ParseAssignmentExpression(bool accept_IN, bool* ok) { |
if (!top_scope_->is_classic_mode()) { |
// Assignment to eval or arguments is disallowed in strict mode. |
- CheckStrictModeLValue(expression, "strict_lhs_assignment", CHECK_OK); |
+ CheckStrictModeLValue(expression, CHECK_OK); |
} |
MarkAsLValue(expression); |
@@ -3219,7 +3210,7 @@ Expression* Parser::ParseUnaryExpression(bool* ok) { |
if (!top_scope_->is_classic_mode()) { |
// Prefix expression operand in strict mode may not be eval or arguments. |
- CheckStrictModeLValue(expression, "strict_lhs_prefix", CHECK_OK); |
+ CheckStrictModeLValue(expression, CHECK_OK); |
} |
MarkAsLValue(expression); |
@@ -3253,7 +3244,7 @@ Expression* Parser::ParsePostfixExpression(bool* ok) { |
if (!top_scope_->is_classic_mode()) { |
// Postfix expression operand in strict mode may not be eval or arguments. |
- CheckStrictModeLValue(expression, "strict_lhs_postfix", CHECK_OK); |
+ CheckStrictModeLValue(expression, CHECK_OK); |
} |
MarkAsLValue(expression); |
@@ -3563,7 +3554,8 @@ Expression* Parser::ParsePrimaryExpression(bool* ok) { |
case Token::IDENTIFIER: |
case Token::YIELD: |
case Token::FUTURE_STRICT_RESERVED_WORD: { |
- Handle<String> name = ParseIdentifier(CHECK_OK); |
+ // Using eval or arguments in this context is OK even in strict mode. |
+ Handle<String> name = ParseIdentifier(kAllowEvalOrArguments, CHECK_OK); |
if (fni_ != NULL) fni_->PushVariableName(name); |
// The name may refer to a module instance object, so its type is unknown. |
#ifdef DEBUG |
@@ -4303,13 +4295,13 @@ FunctionLiteral* Parser::ParseFunctionLiteral( |
if (!top_scope_->is_classic_mode()) { |
if (IsEvalOrArguments(function_name)) { |
ReportMessageAt(function_name_location, |
- "strict_function_name", |
+ "strict_eval_arguments", |
Vector<const char*>::empty()); |
*ok = false; |
return NULL; |
} |
if (name_loc.IsValid()) { |
- ReportMessageAt(name_loc, "strict_param_name", |
+ ReportMessageAt(name_loc, "strict_eval_arguments", |
Vector<const char*>::empty()); |
*ok = false; |
return NULL; |
@@ -4398,7 +4390,8 @@ Expression* Parser::ParseV8Intrinsic(bool* ok) { |
int pos = peek_position(); |
Expect(Token::MOD, CHECK_OK); |
- Handle<String> name = ParseIdentifier(CHECK_OK); |
+ // Allow "eval" or "arguments" for backward compatibility. |
+ Handle<String> name = ParseIdentifier(kAllowEvalOrArguments, CHECK_OK); |
ZoneList<Expression*>* args = ParseArguments(CHECK_OK); |
if (extension_ != NULL) { |
@@ -4505,13 +4498,25 @@ Literal* Parser::GetLiteralTheHole(int position) { |
// Parses an identifier that is valid for the current scope, in particular it |
-// fails on strict mode future reserved keywords in a strict scope. |
-Handle<String> Parser::ParseIdentifier(bool* ok) { |
+// fails on strict mode future reserved keywords in a strict scope. If |
+// allow_eval_or_arguments is kAllowEvalOrArguments, we allow "eval" or |
+// "arguments" as identifier even in strict mode (this is needed in cases like |
+// "var foo = eval;"). |
+Handle<String> Parser::ParseIdentifier( |
+ AllowEvalOrArgumentsAsIdentifier allow_eval_or_arguments, |
+ bool* ok) { |
Token::Value next = Next(); |
- if (next == Token::IDENTIFIER || |
- (top_scope_->is_classic_mode() && |
- (next == Token::FUTURE_STRICT_RESERVED_WORD || |
- (next == Token::YIELD && !is_generator())))) { |
+ if (next == Token::IDENTIFIER) { |
+ Handle<String> name = GetSymbol(); |
+ if (allow_eval_or_arguments == kDontAllowEvalOrArguments && |
+ !top_scope_->is_classic_mode() && IsEvalOrArguments(name)) { |
+ ReportMessage("strict_eval_arguments", Vector<const char*>::empty()); |
+ *ok = false; |
+ } |
+ return name; |
+ } else if (top_scope_->is_classic_mode() && |
+ (next == Token::FUTURE_STRICT_RESERVED_WORD || |
+ (next == Token::YIELD && !is_generator()))) { |
return GetSymbol(); |
} else { |
ReportUnexpectedToken(next); |
@@ -4566,7 +4571,6 @@ void Parser::MarkAsLValue(Expression* expression) { |
// Checks LHS expression for assignment and prefix/postfix increment/decrement |
// in strict mode. |
void Parser::CheckStrictModeLValue(Expression* expression, |
- const char* error, |
bool* ok) { |
ASSERT(!top_scope_->is_classic_mode()); |
VariableProxy* lhs = expression != NULL |
@@ -4574,7 +4578,7 @@ void Parser::CheckStrictModeLValue(Expression* expression, |
: NULL; |
if (lhs != NULL && !lhs->is_this() && IsEvalOrArguments(lhs->name())) { |
- ReportMessage(error, Vector<const char*>::empty()); |
+ ReportMessage("strict_eval_arguments", Vector<const char*>::empty()); |
*ok = false; |
} |
} |