Chromium Code Reviews| Index: src/parser.cc |
| diff --git a/src/parser.cc b/src/parser.cc |
| index 50551ea98d386efaadcf0b8c245ba308214cc71f..081bb17d684659a36729a98969d631ca4b0884f4 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(false, CHECK_OK); |
|
ulan
2014/02/05 16:05:42
I prefer enums to flags, because they are more rea
marja
2014/02/05 16:18:02
Done: kDontAllowEnumOrArguments and kAllowEnumOrAr
|
| #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(false, CHECK_OK); |
| #ifdef DEBUG |
| if (FLAG_print_interface_details) |
| PrintF("# Module variable %s ", name->ToAsciiArray()); |
| @@ -1261,13 +1261,13 @@ Statement* Parser::ParseExportDeclaration(bool* ok) { |
| switch (peek()) { |
| case Token::IDENTIFIER: { |
| int pos = position(); |
| - Handle<String> name = ParseIdentifier(CHECK_OK); |
| + Handle<String> name = ParseIdentifier(false, 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(false, CHECK_OK); |
| names.Add(name, zone()); |
| } |
| ExpectSemicolon(CHECK_OK); |
| @@ -1632,11 +1632,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(true, CHECK_OK); |
| Expect(Token::LPAREN, CHECK_OK); |
| bool done = (peek() == Token::RPAREN); |
| while (!done) { |
| - ParseIdentifier(CHECK_OK); |
| + ParseIdentifier(true, CHECK_OK); |
| done = (peek() == Token::RPAREN); |
| if (!done) { |
| Expect(Token::COMMA, CHECK_OK); |
| @@ -1900,16 +1901,9 @@ Block* Parser::ParseVariableDeclarations( |
| // Parse variable name. |
| if (nvars > 0) Consume(Token::COMMA); |
| - name = ParseIdentifier(CHECK_OK); |
| + name = ParseIdentifier(false, 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 +2218,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(true, CHECK_OK); |
| } |
| IterationStatement* target = NULL; |
| target = LookupContinueTarget(label, CHECK_OK); |
| @@ -2255,7 +2250,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(true, CHECK_OK); |
| } |
| // Parse labeled break statements that target themselves into |
| // empty statements, e.g. 'l1: l2: l3: break l2;' |
| @@ -2485,13 +2481,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(false, CHECK_OK); |
| Expect(Token::RPAREN, CHECK_OK); |
| @@ -2939,7 +2929,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 +3209,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 +3243,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 +3553,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(true, 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 +4294,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 +4389,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(true, CHECK_OK); |
| ZoneList<Expression*>* args = ParseArguments(CHECK_OK); |
| if (extension_ != NULL) { |
| @@ -4505,13 +4497,22 @@ 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_arguments is true, we allow "eval" or "arguments" as identifier |
| +// even in strict mode (this is needed in cases like "var foo = eval;"). |
| +Handle<String> Parser::ParseIdentifier(bool allow_eval_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_arguments && !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 +4567,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 +4574,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; |
| } |
| } |