Index: src/parser.cc |
diff --git a/src/parser.cc b/src/parser.cc |
index 4412b8a98cdca5618ec0b7caf1a77caf246718b3..75a4f2517562aba9e566fb316641a06faffe6e38 100644 |
--- a/src/parser.cc |
+++ b/src/parser.cc |
@@ -465,6 +465,9 @@ bool ParserTraits::IsEvalOrArguments(const AstRawString* identifier) const { |
return IsEval(identifier) || IsArguments(identifier); |
} |
+bool ParserTraits::IsUndefined(const AstRawString* identifier) const { |
+ return identifier == parser_->ast_value_factory()->undefined_string(); |
+} |
bool ParserTraits::IsPrototype(const AstRawString* identifier) const { |
return identifier == parser_->ast_value_factory()->prototype_string(); |
@@ -1475,6 +1478,10 @@ ZoneList<ImportDeclaration*>* Parser::ParseNamedImports(int pos, bool* ok) { |
*ok = false; |
ReportMessage("strict_eval_arguments"); |
return NULL; |
+ } else if (is_strong(language_mode()) && IsUndefined(local_name)) { |
+ *ok = false; |
+ ReportMessage("strong_undefined"); |
+ return NULL; |
} |
VariableProxy* proxy = NewUnresolved(local_name, IMPORT); |
ImportDeclaration* declaration = |
@@ -1524,7 +1531,7 @@ Statement* Parser::ParseImportDeclaration(bool* ok) { |
ImportDeclaration* import_default_declaration = NULL; |
if (tok != Token::MUL && tok != Token::LBRACE) { |
const AstRawString* local_name = |
- ParseIdentifier(kDontAllowEvalOrArguments, CHECK_OK); |
+ ParseIdentifier(kDontAllowRestrictedIdentifiers, CHECK_OK); |
VariableProxy* proxy = NewUnresolved(local_name, IMPORT); |
import_default_declaration = factory()->NewImportDeclaration( |
proxy, ast_value_factory()->default_string(), NULL, scope_, pos); |
@@ -1539,7 +1546,7 @@ Statement* Parser::ParseImportDeclaration(bool* ok) { |
Consume(Token::MUL); |
ExpectContextualKeyword(CStrVector("as"), CHECK_OK); |
module_instance_binding = |
- ParseIdentifier(kDontAllowEvalOrArguments, CHECK_OK); |
+ ParseIdentifier(kDontAllowRestrictedIdentifiers, CHECK_OK); |
// TODO(ES6): Add an appropriate declaration. |
break; |
} |
@@ -2028,11 +2035,12 @@ Statement* Parser::ParseNativeDeclaration(bool* ok) { |
int pos = peek_position(); |
Expect(Token::FUNCTION, CHECK_OK); |
// Allow "eval" or "arguments" for backward compatibility. |
- const AstRawString* name = ParseIdentifier(kAllowEvalOrArguments, CHECK_OK); |
+ const AstRawString* name = |
+ ParseIdentifier(kAllowRestrictedIdentifiers, CHECK_OK); |
Expect(Token::LPAREN, CHECK_OK); |
bool done = (peek() == Token::RPAREN); |
while (!done) { |
- ParseIdentifier(kAllowEvalOrArguments, CHECK_OK); |
+ ParseIdentifier(kAllowRestrictedIdentifiers, CHECK_OK); |
done = (peek() == Token::RPAREN); |
if (!done) { |
Expect(Token::COMMA, CHECK_OK); |
@@ -2314,7 +2322,7 @@ Block* Parser::ParseVariableDeclarations( |
// Parse variable name. |
if (nvars > 0) Consume(Token::COMMA); |
- name = ParseIdentifier(kDontAllowEvalOrArguments, CHECK_OK); |
+ name = ParseIdentifier(kDontAllowRestrictedIdentifiers, CHECK_OK); |
if (!first_name) first_name = name; |
Scanner::Location variable_loc = scanner()->location(); |
if (fni_ != NULL) fni_->PushVariableName(name); |
@@ -2666,7 +2674,7 @@ Statement* Parser::ParseContinueStatement(bool* ok) { |
if (!scanner()->HasAnyLineTerminatorBeforeNext() && |
tok != Token::SEMICOLON && tok != Token::RBRACE && tok != Token::EOS) { |
// ECMA allows "eval" or "arguments" as labels even in strict mode. |
- label = ParseIdentifier(kAllowEvalOrArguments, CHECK_OK); |
+ label = ParseIdentifier(kAllowRestrictedIdentifiers, CHECK_OK); |
} |
IterationStatement* target = LookupContinueTarget(label, CHECK_OK); |
if (target == NULL) { |
@@ -2696,7 +2704,7 @@ Statement* Parser::ParseBreakStatement(ZoneList<const AstRawString*>* labels, |
if (!scanner()->HasAnyLineTerminatorBeforeNext() && |
tok != Token::SEMICOLON && tok != Token::RBRACE && tok != Token::EOS) { |
// ECMA allows "eval" or "arguments" as labels even in strict mode. |
- label = ParseIdentifier(kAllowEvalOrArguments, CHECK_OK); |
+ label = ParseIdentifier(kAllowRestrictedIdentifiers, CHECK_OK); |
} |
// Parse labeled break statements that target themselves into |
// empty statements, e.g. 'l1: l2: l3: break l2;' |
@@ -2921,7 +2929,7 @@ TryStatement* Parser::ParseTryStatement(bool* ok) { |
Expect(Token::LPAREN, CHECK_OK); |
catch_scope = NewScope(scope_, CATCH_SCOPE); |
catch_scope->set_start_position(scanner()->location().beg_pos); |
- name = ParseIdentifier(kDontAllowEvalOrArguments, CHECK_OK); |
+ name = ParseIdentifier(kDontAllowRestrictedIdentifiers, CHECK_OK); |
Expect(Token::RPAREN, CHECK_OK); |
@@ -3868,6 +3876,9 @@ FunctionLiteral* Parser::ParseFunctionLiteral( |
Scanner::Location dupe_error_loc = Scanner::Location::invalid(); |
Scanner::Location reserved_error_loc = Scanner::Location::invalid(); |
+ // Similarly for strong mode. |
+ Scanner::Location undefined_error_loc = Scanner::Location::invalid(); |
+ |
bool is_rest = false; |
bool done = arity_restriction == FunctionLiteral::GETTER_ARITY || |
(peek() == Token::RPAREN && |
@@ -3886,6 +3897,9 @@ FunctionLiteral* Parser::ParseFunctionLiteral( |
if (!eval_args_error_loc.IsValid() && IsEvalOrArguments(param_name)) { |
eval_args_error_loc = scanner()->location(); |
} |
+ if (!undefined_error_loc.IsValid() && IsUndefined(param_name)) { |
+ undefined_error_loc = scanner()->location(); |
+ } |
if (!reserved_error_loc.IsValid() && is_strict_reserved) { |
reserved_error_loc = scanner()->location(); |
} |
@@ -4004,8 +4018,8 @@ FunctionLiteral* Parser::ParseFunctionLiteral( |
CHECK_OK); |
const bool use_strict_params = is_rest || IsConciseMethod(kind); |
CheckFunctionParameterNames(language_mode(), use_strict_params, |
- eval_args_error_loc, dupe_error_loc, |
- reserved_error_loc, CHECK_OK); |
+ eval_args_error_loc, undefined_error_loc, |
+ dupe_error_loc, reserved_error_loc, CHECK_OK); |
if (is_strict(language_mode())) { |
CheckStrictOctalLiteral(scope->start_position(), scope->end_position(), |
@@ -4257,6 +4271,11 @@ ClassLiteral* Parser::ParseClassLiteral(const AstRawString* name, |
*ok = false; |
return NULL; |
} |
+ if (is_strong(language_mode()) && IsUndefined(name)) { |
+ ReportMessageAt(class_name_location, "strong_undefined"); |
+ *ok = false; |
+ return NULL; |
+ } |
// Create a block scope which is additionally tagged as class scope; this is |
// important for resolving variable references to the class name in the strong |
@@ -4348,7 +4367,8 @@ Expression* Parser::ParseV8Intrinsic(bool* ok) { |
int pos = peek_position(); |
Expect(Token::MOD, CHECK_OK); |
// Allow "eval" or "arguments" for backward compatibility. |
- const AstRawString* name = ParseIdentifier(kAllowEvalOrArguments, CHECK_OK); |
+ const AstRawString* name = |
+ ParseIdentifier(kAllowRestrictedIdentifiers, CHECK_OK); |
ZoneList<Expression*>* args = ParseArguments(CHECK_OK); |
if (extension_ != NULL) { |