Index: src/preparser.h |
diff --git a/src/preparser.h b/src/preparser.h |
index 986ad80ef9ba22de32a0cbb7de873d9c03c51efb..a7c27c1c649153dc250bbadb3b005c5d75bcdc69 100644 |
--- a/src/preparser.h |
+++ b/src/preparser.h |
@@ -495,27 +495,26 @@ class ParserBase : public Traits { |
// after parsing the function, since the function can declare itself strict. |
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& eval_args_loc, |
+ const Scanner::Location& undefined_loc, |
+ const Scanner::Location& dupe_loc, |
const Scanner::Location& reserved_loc, |
bool* ok) { |
if (is_sloppy(language_mode) && !strict_params) return; |
- |
- if (is_strict(language_mode) && eval_args_error_loc.IsValid()) { |
- Traits::ReportMessageAt(eval_args_error_loc, "strict_eval_arguments"); |
+ if (is_strict(language_mode) && eval_args_loc.IsValid()) { |
+ Traits::ReportMessageAt(eval_args_loc, "strict_eval_arguments"); |
*ok = false; |
return; |
} |
- if (is_strong(language_mode) && undefined_error_loc.IsValid()) { |
- Traits::ReportMessageAt(eval_args_error_loc, "strong_undefined"); |
+ if (is_strong(language_mode) && undefined_loc.IsValid()) { |
+ Traits::ReportMessageAt(undefined_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()) { |
- Traits::ReportMessageAt(dupe_error_loc, "strict_param_dupe"); |
+ if (dupe_loc.IsValid()) { |
+ Traits::ReportMessageAt(dupe_loc, "strict_param_dupe"); |
*ok = false; |
return; |
} |
@@ -757,11 +756,6 @@ class PreParserIdentifier { |
type_ == kLetIdentifier || type_ == kStaticIdentifier || |
type_ == kYieldIdentifier; |
} |
- V8_INLINE bool IsValidArrowParam() const { |
- // A valid identifier can be an arrow function parameter |
- // except for eval, arguments, yield, and reserved keywords. |
- return !(IsEval() || IsArguments() || IsFutureStrictReserved()); |
- } |
// Allow identifier->name()[->length()] to work. The preparser |
// does not need the actual positions/lengths of the identifiers. |
@@ -785,6 +779,7 @@ class PreParserIdentifier { |
kPrototypeIdentifier, |
kConstructorIdentifier |
}; |
+ |
explicit PreParserIdentifier(Type type) : type_(type) {} |
Type type_; |
@@ -810,10 +805,11 @@ class PreParserExpression { |
static PreParserExpression BinaryOperation(PreParserExpression left, |
Token::Value op, |
PreParserExpression right) { |
- bool valid_arrow_param_list = |
- op == Token::COMMA && !left.is_parenthesized() && |
- !right.is_parenthesized() && left.IsValidArrowParams() && |
- right.IsValidArrowParams(); |
+ ValidArrowParam valid_arrow_param_list = |
+ (op == Token::COMMA && !left.is_parenthesized() && |
+ !right.is_parenthesized()) ? |
+ std::min(left.ValidateArrowParams(), right.ValidateArrowParams()) |
+ : kInvalidArrowParam; |
return PreParserExpression( |
TypeField::encode(kBinaryOperationExpression) | |
IsValidArrowParamListField::encode(valid_arrow_param_list)); |
@@ -915,10 +911,21 @@ class PreParserExpression { |
return IsIdentifier() || IsProperty(); |
} |
- bool IsValidArrowParamList() const { |
- return IsValidArrowParams() && |
- ParenthesizationField::decode(code_) != |
- kMultiParenthesizedExpression; |
+ bool IsValidArrowParamList(Scanner::Location* undefined_loc) const { |
+ ValidArrowParam valid = ValidateArrowParams(); |
+ if (ParenthesizationField::decode(code_) == kMultiParenthesizedExpression) { |
+ return false; |
+ } |
+ if (valid == kValidArrowParam) { |
+ return true; |
+ } else if (valid == kInvalidStrongArrowParam) { |
+ // Return true for now regardless of strong mode for compatibility with |
+ // parser. |
+ *undefined_loc = Scanner::Location(); |
+ return true; |
+ } else { |
+ return false; |
+ } |
} |
// At the moment PreParser doesn't track these expression types. |
@@ -984,13 +991,34 @@ class PreParserExpression { |
kNoTemplateTagExpression |
}; |
+ enum ValidArrowParam { |
+ kInvalidArrowParam, |
+ kInvalidStrongArrowParam, |
+ kValidArrowParam |
+ }; |
+ |
explicit PreParserExpression(uint32_t expression_code) |
: code_(expression_code) {} |
- V8_INLINE bool IsValidArrowParams() const { |
- return IsBinaryOperation() |
- ? IsValidArrowParamListField::decode(code_) |
- : (IsIdentifier() && AsIdentifier().IsValidArrowParam()); |
+ V8_INLINE ValidArrowParam ValidateArrowParams() const { |
+ if (IsBinaryOperation()) { |
+ return IsValidArrowParamListField::decode(code_); |
+ } |
+ if (!IsIdentifier()) { |
+ return kInvalidArrowParam; |
+ } |
+ PreParserIdentifier ident = AsIdentifier(); |
+ // A valid identifier can be an arrow function parameter |
+ // except for eval, arguments, yield, and reserved keywords. |
+ if (ident.IsEval() || ident.IsArguments() || |
+ ident.IsFutureStrictReserved()) { |
+ return kInvalidArrowParam; |
+ } |
+ // In strong mode, 'undefined' is similarly restricted. |
+ if (ident.IsUndefined()) { |
+ return kInvalidStrongArrowParam; |
+ } |
+ return kValidArrowParam; |
} |
// The first five bits are for the Type and Parenthesization. |
@@ -1003,7 +1031,7 @@ class PreParserExpression { |
ExpressionTypeField; |
typedef BitField<bool, ParenthesizationField::kNext, 1> IsUseStrictField; |
typedef BitField<bool, IsUseStrictField::kNext, 1> IsUseStrongField; |
- typedef BitField<bool, ParenthesizationField::kNext, 1> |
+ typedef BitField<ValidArrowParam, ParenthesizationField::kNext, 2> |
IsValidArrowParamListField; |
typedef BitField<PreParserIdentifier::Type, ParenthesizationField::kNext, 10> |
IdentifierTypeField; |
@@ -1491,10 +1519,11 @@ class PreParserTraits { |
// Utility functions |
int DeclareArrowParametersFromExpression(PreParserExpression expression, |
Scope* scope, |
+ Scanner::Location* undefined_loc, |
Scanner::Location* dupe_loc, |
bool* ok) { |
// TODO(aperez): Detect duplicated identifiers in paramlists. |
- *ok = expression.IsValidArrowParamList(); |
+ *ok = expression.IsValidArrowParamList(undefined_loc); |
return 0; |
} |
@@ -3022,10 +3051,11 @@ ParserBase<Traits>::ParseArrowFunctionLiteral(int start_pos, |
typename Traits::Type::Factory function_factory(ast_value_factory()); |
FunctionState function_state(&function_state_, &scope_, scope, |
kArrowFunction, &function_factory); |
- Scanner::Location dupe_error_loc = Scanner::Location::invalid(); |
- // TODO(arv): Pass in eval_args_error_loc and reserved_loc here. |
+ Scanner::Location undefined_loc = Scanner::Location::invalid(); |
+ Scanner::Location dupe_loc = Scanner::Location::invalid(); |
+ // TODO(arv): Pass in eval_args_loc and reserved_loc here. |
num_parameters = Traits::DeclareArrowParametersFromExpression( |
- params_ast, scope_, &dupe_error_loc, ok); |
+ params_ast, scope_, &undefined_loc, &dupe_loc, ok); |
if (!*ok) { |
ReportMessageAt( |
Scanner::Location(start_pos, scanner()->location().beg_pos), |
@@ -3033,6 +3063,11 @@ ParserBase<Traits>::ParseArrowFunctionLiteral(int start_pos, |
return this->EmptyExpression(); |
} |
+ if (undefined_loc.IsValid()) { |
+ // Workaround for preparser not keeping track of positions. |
+ undefined_loc = Scanner::Location(start_pos, |
+ scanner()->location().end_pos); |
+ } |
if (num_parameters > Code::kMaxArguments) { |
ReportMessageAt(Scanner::Location(params_ast->position(), position()), |
"too_many_parameters"); |
@@ -3043,7 +3078,7 @@ ParserBase<Traits>::ParseArrowFunctionLiteral(int start_pos, |
Expect(Token::ARROW, CHECK_OK); |
if (peek() == Token::LBRACE) { |
- // Multiple statemente body |
+ // Multiple statement body |
Consume(Token::LBRACE); |
bool is_lazily_parsed = |
(mode() == PARSE_LAZILY && scope_->AllowsLazyCompilation()); |
@@ -3078,15 +3113,14 @@ 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, 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(); |
+ // TODO(arv): eval_args_loc and reserved_loc needs to be set by |
+ // DeclareArrowParametersFromExpression. |
+ Scanner::Location eval_args_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, undefined_error_loc, |
- dupe_error_loc, reserved_loc, CHECK_OK); |
+ eval_args_loc, undefined_loc, dupe_loc, |
+ reserved_loc, CHECK_OK); |
// Validate strict mode. |
if (is_strict(language_mode())) { |