Chromium Code Reviews| Index: src/preparser.h |
| diff --git a/src/preparser.h b/src/preparser.h |
| index 35b65853b3f553560df54e873043ea26efc2d128..178289a59daa5ba013f9f7881b8a757f506809eb 100644 |
| --- a/src/preparser.h |
| +++ b/src/preparser.h |
| @@ -146,9 +146,9 @@ class ParserBase : public Traits { |
| void set_allow_strong_mode(bool allow) { allow_strong_mode_ = allow; } |
| protected: |
| - enum AllowEvalOrArgumentsAsIdentifier { |
| - kAllowEvalOrArguments, |
| - kDontAllowEvalOrArguments |
| + enum AllowRestrictedIdentifiers { |
|
rossberg
2015/04/08 11:30:11
That's nicer indeed.
conradw
2015/04/09 12:24:17
Acknowledged.
|
| + kAllowRestrictedIdentifiers, |
| + kDontAllowRestrictedIdentifiers |
| }; |
| enum Mode { |
| @@ -479,6 +479,11 @@ class ParserBase : public Traits { |
| *ok = false; |
| return; |
| } |
| + if (is_strong(language_mode) && this->IsUndefined(function_name)) { |
| + Traits::ReportMessageAt(function_name_loc, "strong_undefined"); |
| + *ok = false; |
| + return; |
| + } |
| } |
| // Checking the parameter names of a function literal. This has to be done |
| @@ -486,6 +491,7 @@ class ParserBase : public Traits { |
| void CheckFunctionParameterNames(LanguageMode language_mode, |
| bool strict_params, |
| const Scanner::Location& eval_args_error_loc, |
| + const Scanner::Location& undefined_error_loc, |
| const Scanner::Location& dupe_error_loc, |
| const Scanner::Location& reserved_loc, |
| bool* ok) { |
| @@ -496,6 +502,11 @@ class ParserBase : public Traits { |
| *ok = false; |
| return; |
| } |
| + if (is_strong(language_mode) && undefined_error_loc.IsValid()) { |
| + Traits::ReportMessageAt(eval_args_error_loc, "strong_undefined"); |
| + *ok = false; |
| + return; |
| + } |
| // TODO(arv): When we add support for destructuring in setters we also need |
| // to check for duplicate names. |
| if (dupe_error_loc.IsValid()) { |
| @@ -547,9 +558,7 @@ class ParserBase : public Traits { |
| // 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;"). |
| - IdentifierT ParseIdentifier( |
| - AllowEvalOrArgumentsAsIdentifier, |
| - bool* ok); |
| + IdentifierT ParseIdentifier(AllowRestrictedIdentifiers, bool* ok); |
| // Parses an identifier or a strict mode future reserved word, and indicate |
| // whether it is strict mode future reserved. |
| IdentifierT ParseIdentifierOrStrictReservedWord( |
| @@ -702,6 +711,9 @@ class PreParserIdentifier { |
| static PreParserIdentifier Arguments() { |
| return PreParserIdentifier(kArgumentsIdentifier); |
| } |
| + static PreParserIdentifier Undefined() { |
| + return PreParserIdentifier(kUndefinedIdentifier); |
| + } |
| static PreParserIdentifier FutureReserved() { |
| return PreParserIdentifier(kFutureReservedIdentifier); |
| } |
| @@ -726,6 +738,7 @@ class PreParserIdentifier { |
| bool IsEval() const { return type_ == kEvalIdentifier; } |
| bool IsArguments() const { return type_ == kArgumentsIdentifier; } |
| bool IsEvalOrArguments() const { return IsEval() || IsArguments(); } |
| + bool IsUndefined() const { return type_ == kUndefinedIdentifier; } |
| bool IsLet() const { return type_ == kLetIdentifier; } |
| bool IsStatic() const { return type_ == kStaticIdentifier; } |
| bool IsYield() const { return type_ == kYieldIdentifier; } |
| @@ -737,7 +750,6 @@ class PreParserIdentifier { |
| type_ == kLetIdentifier || type_ == kStaticIdentifier || |
| type_ == kYieldIdentifier; |
| } |
| - bool IsValidStrictVariable() const { return type_ == kUnknownIdentifier; } |
| V8_INLINE bool IsValidArrowParam() const { |
| // A valid identifier can be an arrow function parameter |
| // except for eval, arguments, yield, and reserved keywords. |
| @@ -762,6 +774,7 @@ class PreParserIdentifier { |
| kYieldIdentifier, |
| kEvalIdentifier, |
| kArgumentsIdentifier, |
| + kUndefinedIdentifier, |
| kPrototypeIdentifier, |
| kConstructorIdentifier |
| }; |
| @@ -1237,6 +1250,10 @@ class PreParserTraits { |
| return identifier.IsEvalOrArguments(); |
| } |
| + static bool IsUndefined(PreParserIdentifier identifier) { |
| + return identifier.IsUndefined(); |
| + } |
| + |
| static bool IsPrototype(PreParserIdentifier identifier) { |
| return identifier.IsPrototype(); |
| } |
| @@ -1725,18 +1742,21 @@ void ParserBase<Traits>::ReportUnexpectedTokenAt( |
| } |
| -template<class Traits> |
| +template <class Traits> |
| typename ParserBase<Traits>::IdentifierT ParserBase<Traits>::ParseIdentifier( |
| - AllowEvalOrArgumentsAsIdentifier allow_eval_or_arguments, |
| - bool* ok) { |
| + AllowRestrictedIdentifiers allow_restricted_identifiers, bool* ok) { |
| Token::Value next = Next(); |
| if (next == Token::IDENTIFIER) { |
| IdentifierT name = this->GetSymbol(scanner()); |
| - if (allow_eval_or_arguments == kDontAllowEvalOrArguments) { |
| + if (allow_restricted_identifiers == kDontAllowRestrictedIdentifiers) { |
| if (is_strict(language_mode()) && this->IsEvalOrArguments(name)) { |
| ReportMessage("strict_eval_arguments"); |
| *ok = false; |
| } |
| + if (is_strong(language_mode()) && this->IsUndefined(name)) { |
| + ReportMessage("strong_undefined"); |
| + *ok = false; |
| + } |
| } else { |
| if (is_strong(language_mode()) && this->IsArguments(name)) { |
| ReportMessage("strong_arguments"); |
| @@ -1757,7 +1777,6 @@ typename ParserBase<Traits>::IdentifierT ParserBase<Traits>::ParseIdentifier( |
| } |
| } |
| - |
| template <class Traits> |
| typename ParserBase<Traits>::IdentifierT ParserBase< |
| Traits>::ParseIdentifierOrStrictReservedWord(bool* is_strict_reserved, |
| @@ -1896,7 +1915,7 @@ ParserBase<Traits>::ParsePrimaryExpression(bool* ok) { |
| case Token::YIELD: |
| case Token::FUTURE_STRICT_RESERVED_WORD: { |
| // Using eval or arguments in this context is OK even in strict mode. |
| - IdentifierT name = ParseIdentifier(kAllowEvalOrArguments, CHECK_OK); |
| + IdentifierT name = ParseIdentifier(kAllowRestrictedIdentifiers, CHECK_OK); |
| result = this->ExpressionFromIdentifier(name, beg_pos, end_pos, scope_, |
| factory()); |
| break; |
| @@ -2951,13 +2970,15 @@ ParserBase<Traits>::ParseArrowFunctionLiteral(int start_pos, |
| scope->set_end_position(scanner()->location().end_pos); |
| // Arrow function *parameter lists* are always checked as in strict mode. |
| - // TODO(arv): eval_args_error_loc and reserved_loc needs to be set by |
| - // DeclareArrowParametersFromExpression. |
| + // TODO(arv): eval_args_error_loc, undefined_error_loc, and reserved_loc |
| + // needs to be set by DeclareArrowParametersFromExpression. |
| Scanner::Location eval_args_error_loc = Scanner::Location::invalid(); |
| + Scanner::Location undefined_error_loc = Scanner::Location::invalid(); |
| Scanner::Location reserved_loc = Scanner::Location::invalid(); |
| const bool use_strict_params = true; |
| this->CheckFunctionParameterNames(language_mode(), use_strict_params, |
| - eval_args_error_loc, dupe_error_loc, reserved_loc, CHECK_OK); |
| + eval_args_error_loc, undefined_error_loc, |
| + dupe_error_loc, reserved_loc, CHECK_OK); |
| // Validate strict mode. |
| if (is_strict(language_mode())) { |
| @@ -3081,12 +3102,21 @@ typename ParserBase<Traits>::ExpressionT ParserBase< |
| Traits>::CheckAndRewriteReferenceExpression(ExpressionT expression, |
| Scanner::Location location, |
| const char* message, bool* ok) { |
| - if (is_strict(language_mode()) && this->IsIdentifier(expression) && |
| - this->IsEvalOrArguments(this->AsIdentifier(expression))) { |
| - this->ReportMessageAt(location, "strict_eval_arguments", kSyntaxError); |
| - *ok = false; |
| - return this->EmptyExpression(); |
| - } else if (expression->IsValidReferenceExpression()) { |
| + if (this->IsIdentifier(expression)) { |
| + if (is_strict(language_mode()) && |
| + this->IsEvalOrArguments(this->AsIdentifier(expression))) { |
| + this->ReportMessageAt(location, "strict_eval_arguments", kSyntaxError); |
| + *ok = false; |
| + return this->EmptyExpression(); |
| + } |
| + if (is_strong(language_mode()) && |
| + this->IsUndefined(this->AsIdentifier(expression))) { |
| + this->ReportMessageAt(location, "strong_undefined", kSyntaxError); |
| + *ok = false; |
| + return this->EmptyExpression(); |
| + } |
| + } |
| + if (expression->IsValidReferenceExpression()) { |
| return expression; |
| } else if (expression->IsCall()) { |
| // If it is a call, make it a runtime error for legacy web compatibility. |