| Index: src/preparser.cc
|
| diff --git a/src/preparser.cc b/src/preparser.cc
|
| index c14d14122af8621f750a8905d3a0d7a6fb43ef45..7d48dd8651757d6b0ce9d6436b1901918142e1ab 100644
|
| --- a/src/preparser.cc
|
| +++ b/src/preparser.cc
|
| @@ -296,16 +296,19 @@ PreParser::Statement PreParser::ParseFunctionDeclaration(bool* ok) {
|
| Expect(Token::FUNCTION, CHECK_OK);
|
|
|
| bool is_generator = allow_generators() && Check(Token::MUL);
|
| - Identifier identifier = ParseIdentifier(CHECK_OK);
|
| + Identifier identifier = ParseIdentifier(kDontAllowEvalOrArguments, CHECK_OK);
|
| Scanner::Location location = scanner()->location();
|
|
|
| Expression function_value = ParseFunctionLiteral(is_generator, CHECK_OK);
|
|
|
| + // If we're in strict mode, ParseIdentifier will catch using eval, arguments
|
| + // or a strict reserved word as function name. However, if only the function
|
| + // is strict, we need to do an extra check.
|
| if (function_value.IsStrictFunction() &&
|
| !identifier.IsValidStrictVariable()) {
|
| // Strict mode violation, using either reserved word or eval/arguments
|
| // as name of strict function.
|
| - const char* type = "strict_function_name";
|
| + const char* type = "strict_eval_arguments";
|
| if (identifier.IsFutureStrictReserved() || identifier.IsYield()) {
|
| type = "unexpected_strict_reserved";
|
| }
|
| @@ -446,14 +449,7 @@ PreParser::Statement PreParser::ParseVariableDeclarations(
|
| do {
|
| // Parse variable name.
|
| if (nvars > 0) Consume(Token::COMMA);
|
| - Identifier identifier = ParseIdentifier(CHECK_OK);
|
| - if (!is_classic_mode() && !identifier.IsValidStrictVariable()) {
|
| - StrictModeIdentifierViolation(scanner()->location(),
|
| - "strict_var_name",
|
| - identifier,
|
| - ok);
|
| - return Statement::Default();
|
| - }
|
| + ParseIdentifier(kDontAllowEvalOrArguments, CHECK_OK);
|
| nvars++;
|
| if (peek() == Token::ASSIGN || require_initializer) {
|
| Expect(Token::ASSIGN, CHECK_OK);
|
| @@ -519,7 +515,8 @@ PreParser::Statement PreParser::ParseContinueStatement(bool* ok) {
|
| tok != Token::SEMICOLON &&
|
| tok != Token::RBRACE &&
|
| tok != Token::EOS) {
|
| - ParseIdentifier(CHECK_OK);
|
| + // ECMA allows "eval" or "arguments" as labels even in strict mode.
|
| + ParseIdentifier(kAllowEvalOrArguments, CHECK_OK);
|
| }
|
| ExpectSemicolon(CHECK_OK);
|
| return Statement::Default();
|
| @@ -536,7 +533,8 @@ PreParser::Statement PreParser::ParseBreakStatement(bool* ok) {
|
| tok != Token::SEMICOLON &&
|
| tok != Token::RBRACE &&
|
| tok != Token::EOS) {
|
| - ParseIdentifier(CHECK_OK);
|
| + // ECMA allows "eval" or "arguments" as labels even in strict mode.
|
| + ParseIdentifier(kAllowEvalOrArguments, CHECK_OK);
|
| }
|
| ExpectSemicolon(CHECK_OK);
|
| return Statement::Default();
|
| @@ -753,14 +751,7 @@ PreParser::Statement PreParser::ParseTryStatement(bool* ok) {
|
| if (peek() == Token::CATCH) {
|
| Consume(Token::CATCH);
|
| Expect(Token::LPAREN, CHECK_OK);
|
| - Identifier id = ParseIdentifier(CHECK_OK);
|
| - if (!is_classic_mode() && !id.IsValidStrictVariable()) {
|
| - StrictModeIdentifierViolation(scanner()->location(),
|
| - "strict_catch_variable",
|
| - id,
|
| - ok);
|
| - return Statement::Default();
|
| - }
|
| + ParseIdentifier(kDontAllowEvalOrArguments, CHECK_OK);
|
| Expect(Token::RPAREN, CHECK_OK);
|
| { Scope::InsideWith iw(scope_);
|
| ParseBlock(CHECK_OK);
|
| @@ -841,7 +832,7 @@ PreParser::Expression PreParser::ParseAssignmentExpression(bool accept_IN,
|
| expression.AsIdentifier().IsEvalOrArguments()) {
|
| Scanner::Location after = scanner()->location();
|
| ReportMessageAt(before.beg_pos, after.end_pos,
|
| - "strict_lhs_assignment", NULL);
|
| + "strict_eval_arguments", NULL);
|
| *ok = false;
|
| return Expression::Default();
|
| }
|
| @@ -935,7 +926,7 @@ PreParser::Expression PreParser::ParseUnaryExpression(bool* ok) {
|
| expression.AsIdentifier().IsEvalOrArguments()) {
|
| Scanner::Location after = scanner()->location();
|
| ReportMessageAt(before.beg_pos, after.end_pos,
|
| - "strict_lhs_prefix", NULL);
|
| + "strict_eval_arguments", NULL);
|
| *ok = false;
|
| }
|
| return Expression::Default();
|
| @@ -958,7 +949,7 @@ PreParser::Expression PreParser::ParsePostfixExpression(bool* ok) {
|
| expression.AsIdentifier().IsEvalOrArguments()) {
|
| Scanner::Location after = scanner()->location();
|
| ReportMessageAt(before.beg_pos, after.end_pos,
|
| - "strict_lhs_postfix", NULL);
|
| + "strict_eval_arguments", NULL);
|
| *ok = false;
|
| return Expression::Default();
|
| }
|
| @@ -1059,12 +1050,15 @@ PreParser::Expression PreParser::ParseMemberWithNewPrefixesExpression(
|
| bool is_generator = allow_generators() && Check(Token::MUL);
|
| Identifier identifier = Identifier::Default();
|
| if (peek_any_identifier()) {
|
| - identifier = ParseIdentifier(CHECK_OK);
|
| + identifier = ParseIdentifier(kDontAllowEvalOrArguments, CHECK_OK);
|
| }
|
| result = ParseFunctionLiteral(is_generator, CHECK_OK);
|
| + // If we're in strict mode, ParseIdentifier will catch using eval, arguments
|
| + // or a strict reserved word as function name. However, if only the function
|
| + // is strict, we need to do an extra check.
|
| if (result.IsStrictFunction() && !identifier.IsValidStrictVariable()) {
|
| StrictModeIdentifierViolation(scanner()->location(),
|
| - "strict_function_name",
|
| + "strict_eval_arguments",
|
| identifier,
|
| ok);
|
| return Expression::Default();
|
| @@ -1137,7 +1131,8 @@ PreParser::Expression PreParser::ParsePrimaryExpression(bool* ok) {
|
| case Token::FUTURE_STRICT_RESERVED_WORD:
|
| case Token::YIELD:
|
| case Token::IDENTIFIER: {
|
| - Identifier id = ParseIdentifier(CHECK_OK);
|
| + // Using eval or arguments in this context is OK even in strict mode.
|
| + Identifier id = ParseIdentifier(kAllowEvalOrArguments, CHECK_OK);
|
| result = Expression::FromIdentifier(id);
|
| break;
|
| }
|
| @@ -1354,13 +1349,7 @@ PreParser::Expression PreParser::ParseFunctionLiteral(bool is_generator,
|
| bool done = (peek() == Token::RPAREN);
|
| DuplicateFinder duplicate_finder(scanner()->unicode_cache());
|
| while (!done) {
|
| - Identifier id = ParseIdentifier(CHECK_OK);
|
| - if (!id.IsValidStrictVariable()) {
|
| - StrictModeIdentifierViolation(scanner()->location(),
|
| - "strict_param_name",
|
| - id,
|
| - CHECK_OK);
|
| - }
|
| + ParseIdentifier(kDontAllowEvalOrArguments, CHECK_OK);
|
| int prev_value;
|
| if (scanner()->is_literal_ascii()) {
|
| prev_value =
|
| @@ -1434,7 +1423,8 @@ PreParser::Expression PreParser::ParseV8Intrinsic(bool* ok) {
|
| *ok = false;
|
| return Expression::Default();
|
| }
|
| - ParseIdentifier(CHECK_OK);
|
| + // Allow "eval" or "arguments" for backward compatibility.
|
| + ParseIdentifier(kAllowEvalOrArguments, CHECK_OK);
|
| ParseArguments(ok);
|
|
|
| return Expression::Default();
|
| @@ -1493,12 +1483,26 @@ PreParser::Identifier PreParser::GetIdentifierSymbol() {
|
| }
|
|
|
|
|
| -PreParser::Identifier PreParser::ParseIdentifier(bool* ok) {
|
| +// Parses an identifier that is valid for the current scope, in particular it
|
| +// 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;").
|
| +PreParser::Identifier PreParser::ParseIdentifier(
|
| + AllowEvalOrArgumentsAsIdentifier allow_eval_or_arguments,
|
| + bool* ok) {
|
| Token::Value next = Next();
|
| - if (next == Token::IDENTIFIER ||
|
| - (is_classic_mode() &&
|
| - (next == Token::FUTURE_STRICT_RESERVED_WORD ||
|
| - (next == Token::YIELD && !scope_->is_generator())))) {
|
| + if (next == Token::IDENTIFIER) {
|
| + PreParser::Identifier name = GetIdentifierSymbol();
|
| + if (allow_eval_or_arguments == kDontAllowEvalOrArguments &&
|
| + !is_classic_mode() && name.IsEvalOrArguments()) {
|
| + StrictModeIdentifierViolation(
|
| + scanner()->location(), "strict_eval_arguments", name, ok);
|
| + }
|
| + return name;
|
| + } else if (is_classic_mode() &&
|
| + (next == Token::FUTURE_STRICT_RESERVED_WORD ||
|
| + (next == Token::YIELD && !scope_->is_generator()))) {
|
| return GetIdentifierSymbol();
|
| } else {
|
| ReportUnexpectedToken(next);
|
|
|