From 5788b34a166b593ae0a7788af1afded2738e9a95 Mon Sep 17 00:00:00 2001 From: "marja@chromium.org" Date: Fri, 7 Feb 2014 10:47:01 +0000 Subject: [PATCH] Unify function name validation in Parser and PreParser. BUG=3126 LOG=N R=ulan@chromium.org Review URL: https://codereview.chromium.org/140183005 git-svn-id: http://v8.googlecode.com/svn/branches/bleeding_edge@19193 ce2b1a6d-e550-0410-aec6-3dcde31c8c00 --- src/parser.cc | 14 ++++---- src/parser.h | 4 +-- src/preparser.cc | 97 ++++++++++++++++++++++++++++++++++++-------------------- src/preparser.h | 9 +++++- 4 files changed, 79 insertions(+), 45 deletions(-) diff --git a/src/parser.cc b/src/parser.cc index b0fdbee..21beacc 100644 --- a/src/parser.cc +++ b/src/parser.cc @@ -3388,7 +3388,7 @@ Expression* Parser::ParseMemberWithNewPrefixesExpression(PositionStack* stack, // Parse the initial primary or function expression. Expression* result = NULL; if (peek() == Token::FUNCTION) { - Expect(Token::FUNCTION, CHECK_OK); + Consume(Token::FUNCTION); int function_token_position = position(); bool is_generator = allow_generators() && Check(Token::MUL); Handle name; @@ -4265,20 +4265,20 @@ FunctionLiteral* Parser::ParseFunctionLiteral( *ok = false; return NULL; } - if (name_loc.IsValid()) { - ReportMessageAt(name_loc, "strict_eval_arguments", + if (name_is_strict_reserved) { + ReportMessageAt(function_name_location, "unexpected_strict_reserved", Vector::empty()); *ok = false; return NULL; } - if (dupe_loc.IsValid()) { - ReportMessageAt(dupe_loc, "strict_param_dupe", + if (name_loc.IsValid()) { + ReportMessageAt(name_loc, "strict_eval_arguments", Vector::empty()); *ok = false; return NULL; } - if (name_is_strict_reserved) { - ReportMessageAt(function_name_location, "unexpected_strict_reserved", + if (dupe_loc.IsValid()) { + ReportMessageAt(dupe_loc, "strict_param_dupe", Vector::empty()); *ok = false; return NULL; diff --git a/src/parser.h b/src/parser.h index 1fc1403..2b0995a 100644 --- a/src/parser.h +++ b/src/parser.h @@ -649,9 +649,9 @@ class Parser : public ParserBase { ZoneList* ParseArguments(bool* ok); FunctionLiteral* ParseFunctionLiteral( - Handle var_name, + Handle name, Scanner::Location function_name_location, - bool name_is_reserved, + bool name_is_strict_reserved, bool is_generator, int function_token_position, FunctionLiteral::FunctionType type, diff --git a/src/preparser.cc b/src/preparser.cc index 4182c8c..4caf906 100644 --- a/src/preparser.cc +++ b/src/preparser.cc @@ -265,25 +265,14 @@ PreParser::Statement PreParser::ParseFunctionDeclaration(bool* ok) { Expect(Token::FUNCTION, CHECK_OK); bool is_generator = allow_generators() && Check(Token::MUL); - 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_eval_arguments"; - if (identifier.IsFutureStrictReserved() || identifier.IsYield()) { - type = "unexpected_strict_reserved"; - } - ReportMessageAt(location, type, NULL); - *ok = false; - } + bool is_strict_reserved = false; + Identifier name = ParseIdentifierOrStrictReservedWord( + &is_strict_reserved, CHECK_OK); + ParseFunctionLiteral(name, + scanner()->location(), + is_strict_reserved, + is_generator, + CHECK_OK); return Statement::FunctionDeclaration(); } @@ -1021,20 +1010,19 @@ PreParser::Expression PreParser::ParseMemberWithNewPrefixesExpression( Consume(Token::FUNCTION); bool is_generator = allow_generators() && Check(Token::MUL); - Identifier identifier = Identifier::Default(); + Identifier name = Identifier::Default(); + bool is_strict_reserved_name = false; + Scanner::Location function_name_location = Scanner::Location::invalid(); if (peek_any_identifier()) { - 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(), - identifier, - ok); - return Expression::Default(); + name = ParseIdentifierOrStrictReservedWord(&is_strict_reserved_name, + CHECK_OK); + function_name_location = scanner()->location(); } + result = ParseFunctionLiteral(name, + function_name_location, + is_strict_reserved_name, + is_generator, + CHECK_OK); } else { result = ParsePrimaryExpression(CHECK_OK); } @@ -1216,7 +1204,11 @@ PreParser::Expression PreParser::ParseObjectLiteral(bool* ok) { } PropertyKind type = is_getter ? kGetterProperty : kSetterProperty; checker.CheckProperty(name, type, CHECK_OK); - ParseFunctionLiteral(false, CHECK_OK); + ParseFunctionLiteral(Identifier::Default(), + scanner()->location(), + false, // reserved words are allowed here + false, // not a generator + CHECK_OK); if (peek() != Token::RBRACE) { Expect(Token::COMMA, CHECK_OK); } @@ -1302,9 +1294,12 @@ PreParser::Arguments PreParser::ParseArguments(bool* ok) { return argc; } - -PreParser::Expression PreParser::ParseFunctionLiteral(bool is_generator, - bool* ok) { +PreParser::Expression PreParser::ParseFunctionLiteral( + Identifier name, + Scanner::Location function_name_location, + bool name_is_strict_reserved, + bool is_generator, + bool* ok) { // Function :: // '(' FormalParameterList? ')' '{' FunctionBody '}' @@ -1358,7 +1353,20 @@ PreParser::Expression PreParser::ParseFunctionLiteral(bool is_generator, } Expect(Token::RBRACE, CHECK_OK); + // Validate strict mode. if (!scope_->is_classic_mode()) { + if (name.IsEvalOrArguments()) { + ReportMessageAt(function_name_location, "strict_eval_arguments", NULL); + *ok = false; + return Expression::Default(); + } + if (name_is_strict_reserved) { + ReportMessageAt( + function_name_location, "unexpected_strict_reserved", NULL); + *ok = false; + return Expression::Default(); + } + int end_position = scanner()->location().end_pos; CheckOctalLiteral(start_position, end_position, CHECK_OK); CheckDelayedStrictModeViolation(start_position, end_position, CHECK_OK); @@ -1534,6 +1542,25 @@ void PreParser::StrictModeIdentifierViolation(Scanner::Location location, } +// Parses and identifier or a strict mode future reserved word, and indicate +// whether it is strict mode future reserved. +PreParser::Identifier PreParser::ParseIdentifierOrStrictReservedWord( + bool* is_strict_reserved, bool* ok) { + Token::Value next = Next(); + if (next == Token::IDENTIFIER) { + *is_strict_reserved = false; + } else if (next == Token::FUTURE_STRICT_RESERVED_WORD || + (next == Token::YIELD && !scope_->is_generator())) { + *is_strict_reserved = true; + } else { + ReportUnexpectedToken(next); + *ok = false; + return Identifier::Default(); + } + return GetIdentifierSymbol(); +} + + PreParser::Identifier PreParser::ParseIdentifierName(bool* ok) { Token::Value next = Next(); if (next != Token::IDENTIFIER && diff --git a/src/preparser.h b/src/preparser.h index dc6bdd1..0f417f1 100644 --- a/src/preparser.h +++ b/src/preparser.h @@ -616,10 +616,17 @@ class PreParser : public ParserBase { Expression ParseV8Intrinsic(bool* ok); Arguments ParseArguments(bool* ok); - Expression ParseFunctionLiteral(bool is_generator, bool* ok); + Expression ParseFunctionLiteral( + Identifier name, + Scanner::Location function_name_location, + bool name_is_strict_reserved, + bool is_generator, + bool* ok); void ParseLazyFunctionLiteralBody(bool* ok); Identifier ParseIdentifier(AllowEvalOrArgumentsAsIdentifier, bool* ok); + Identifier ParseIdentifierOrStrictReservedWord(bool* is_strict_reserved, + bool* ok); Identifier ParseIdentifierName(bool* ok); Identifier ParseIdentifierNameOrGetOrSet(bool* is_get, bool* is_set, -- 2.7.4