| Index: src/preparser.h
 | 
| diff --git a/src/preparser.h b/src/preparser.h
 | 
| index ce2c6c429239742a3cca7c4438f377a14c348111..b66053b94697a7d82a59969e1f06a6cd4fd1b3fc 100644
 | 
| --- a/src/preparser.h
 | 
| +++ b/src/preparser.h
 | 
| @@ -70,6 +70,8 @@ class ParserBase : public Traits {
 | 
|    typedef typename Traits::Type::FunctionLiteral FunctionLiteralT;
 | 
|    typedef typename Traits::Type::Literal LiteralT;
 | 
|    typedef typename Traits::Type::ObjectLiteralProperty ObjectLiteralPropertyT;
 | 
| +  typedef typename Traits::Type::FormalParameterParsingState
 | 
| +      FormalParameterParsingStateT;
 | 
|  
 | 
|    ParserBase(Zone* zone, Scanner* scanner, uintptr_t stack_limit,
 | 
|               v8::Extension* extension, AstValueFactory* ast_value_factory,
 | 
| @@ -557,7 +559,7 @@ class ParserBase : public Traits {
 | 
|                                       ExpressionT expr, bool* ok) {
 | 
|      if (classifier->is_valid_binding_pattern()) {
 | 
|        // A simple arrow formal parameter: IDENTIFIER => BODY.
 | 
| -      if (!allow_harmony_destructuring() && !this->IsIdentifier(expr)) {
 | 
| +      if (!this->IsIdentifier(expr)) {
 | 
|          Traits::ReportMessageAt(scanner()->location(),
 | 
|                                  MessageTemplate::kUnexpectedToken,
 | 
|                                  Token::String(scanner()->current_token()));
 | 
| @@ -646,9 +648,9 @@ class ParserBase : public Traits {
 | 
|    ExpressionT ParseMemberExpression(ExpressionClassifier* classifier, bool* ok);
 | 
|    ExpressionT ParseMemberExpressionContinuation(
 | 
|        ExpressionT expression, ExpressionClassifier* classifier, bool* ok);
 | 
| -  ExpressionT ParseArrowFunctionLiteral(Scope* function_scope, bool has_rest,
 | 
| -                                        const ExpressionClassifier& classifier,
 | 
| -                                        bool* ok);
 | 
| +  ExpressionT ParseArrowFunctionLiteral(
 | 
| +      const FormalParameterParsingStateT& parsing_state,
 | 
| +      const ExpressionClassifier& classifier, bool* ok);
 | 
|    ExpressionT ParseTemplateLiteral(ExpressionT tag, int start,
 | 
|                                     ExpressionClassifier* classifier, bool* ok);
 | 
|    void AddTemplateExpression(ExpressionT);
 | 
| @@ -660,9 +662,10 @@ class ParserBase : public Traits {
 | 
|    ExpressionT ParseStrongSuperCallExpression(ExpressionClassifier* classifier,
 | 
|                                               bool* ok);
 | 
|  
 | 
| -  void ParseFormalParameter(Scope* scope, bool is_rest,
 | 
| +  void ParseFormalParameter(bool is_rest,
 | 
| +                            FormalParameterParsingStateT* parsing_result,
 | 
|                              ExpressionClassifier* classifier, bool* ok);
 | 
| -  int ParseFormalParameterList(Scope* scope, bool* has_rest,
 | 
| +  int ParseFormalParameterList(FormalParameterParsingStateT* parsing_state,
 | 
|                                 ExpressionClassifier* classifier, bool* ok);
 | 
|    void CheckArityRestrictions(
 | 
|        int param_count, FunctionLiteral::ArityRestriction arity_restriction,
 | 
| @@ -1254,6 +1257,15 @@ class PreParserFactory {
 | 
|  };
 | 
|  
 | 
|  
 | 
| +struct PreParserFormalParameterParsingState {
 | 
| +  explicit PreParserFormalParameterParsingState(Scope* scope)
 | 
| +      : scope(scope), has_rest(false), is_simple_parameter_list(true) {}
 | 
| +  Scope* scope;
 | 
| +  bool has_rest;
 | 
| +  bool is_simple_parameter_list;
 | 
| +};
 | 
| +
 | 
| +
 | 
|  class PreParser;
 | 
|  
 | 
|  class PreParserTraits {
 | 
| @@ -1280,6 +1292,7 @@ class PreParserTraits {
 | 
|      typedef PreParserExpressionList PropertyList;
 | 
|      typedef PreParserIdentifier FormalParameter;
 | 
|      typedef PreParserStatementList StatementList;
 | 
| +    typedef PreParserFormalParameterParsingState FormalParameterParsingState;
 | 
|  
 | 
|      // For constructing objects returned by the traversing functions.
 | 
|      typedef PreParserFactory Factory;
 | 
| @@ -1518,19 +1531,23 @@ class PreParserTraits {
 | 
|      return PreParserExpressionList();
 | 
|    }
 | 
|  
 | 
| +  static void AddParameterInitializationBlock(
 | 
| +      const PreParserFormalParameterParsingState& formal_parameters,
 | 
| +      PreParserStatementList list, bool* ok) {}
 | 
| +
 | 
|    V8_INLINE void SkipLazyFunctionBody(int* materialized_literal_count,
 | 
|                                        int* expected_property_count, bool* ok) {
 | 
|      UNREACHABLE();
 | 
|    }
 | 
|  
 | 
| -  V8_INLINE PreParserStatementList
 | 
| -  ParseEagerFunctionBody(PreParserIdentifier function_name, int pos,
 | 
| -                         Variable* fvar, Token::Value fvar_init_op,
 | 
| -                         FunctionKind kind, bool* ok);
 | 
| +  V8_INLINE PreParserStatementList ParseEagerFunctionBody(
 | 
| +      PreParserIdentifier function_name, int pos,
 | 
| +      const PreParserFormalParameterParsingState& formal_parameters,
 | 
| +      Variable* fvar, Token::Value fvar_init_op, FunctionKind kind, bool* ok);
 | 
|  
 | 
|    V8_INLINE void ParseArrowFunctionFormalParameters(
 | 
| -      Scope* scope, PreParserExpression expression,
 | 
| -      const Scanner::Location& params_loc, bool* has_rest,
 | 
| +      PreParserFormalParameterParsingState* parsing_state,
 | 
| +      PreParserExpression expression, const Scanner::Location& params_loc,
 | 
|        Scanner::Location* duplicate_loc, bool* ok);
 | 
|  
 | 
|    struct TemplateLiteralState {};
 | 
| @@ -1557,7 +1574,7 @@ class PreParserTraits {
 | 
|      return !tag.IsNoTemplateTag();
 | 
|    }
 | 
|  
 | 
| -  void DeclareFormalParameter(Scope* scope, PreParserExpression pattern,
 | 
| +  void DeclareFormalParameter(void* parsing_state, PreParserExpression pattern,
 | 
|                                ExpressionClassifier* classifier, bool is_rest) {}
 | 
|  
 | 
|    void CheckConflictingVarDeclarations(Scope* scope, bool* ok) {}
 | 
| @@ -1708,6 +1725,7 @@ class PreParser : public ParserBase<PreParserTraits> {
 | 
|                                        int* expected_property_count, bool* ok);
 | 
|    V8_INLINE PreParserStatementList
 | 
|    ParseEagerFunctionBody(PreParserIdentifier function_name, int pos,
 | 
| +                         const FormalParameterParsingStateT& formal_parameters,
 | 
|                           Variable* fvar, Token::Value fvar_init_op,
 | 
|                           FunctionKind kind, bool* ok);
 | 
|  
 | 
| @@ -1753,8 +1771,8 @@ PreParserExpression PreParserTraits::SpreadCallNew(PreParserExpression function,
 | 
|  
 | 
|  
 | 
|  void PreParserTraits::ParseArrowFunctionFormalParameters(
 | 
| -    Scope* scope, PreParserExpression params,
 | 
| -    const Scanner::Location& params_loc, bool* has_rest,
 | 
| +    PreParserFormalParameterParsingState* parsing_state,
 | 
| +    PreParserExpression params, const Scanner::Location& params_loc,
 | 
|      Scanner::Location* duplicate_loc, bool* ok) {
 | 
|    // TODO(wingo): Detect duplicated identifiers in paramlists.  Detect parameter
 | 
|    // lists that are too long.
 | 
| @@ -1762,8 +1780,9 @@ void PreParserTraits::ParseArrowFunctionFormalParameters(
 | 
|  
 | 
|  
 | 
|  PreParserStatementList PreParser::ParseEagerFunctionBody(
 | 
| -    PreParserIdentifier function_name, int pos, Variable* fvar,
 | 
| -    Token::Value fvar_init_op, FunctionKind kind, bool* ok) {
 | 
| +    PreParserIdentifier function_name, int pos,
 | 
| +    const PreParserFormalParameterParsingState& formal_parameters,
 | 
| +    Variable* fvar, Token::Value fvar_init_op, FunctionKind kind, bool* ok) {
 | 
|    ParsingModeScope parsing_mode(this, PARSE_EAGERLY);
 | 
|  
 | 
|    ParseStatementList(Token::RBRACE, ok);
 | 
| @@ -1775,10 +1794,11 @@ PreParserStatementList PreParser::ParseEagerFunctionBody(
 | 
|  
 | 
|  
 | 
|  PreParserStatementList PreParserTraits::ParseEagerFunctionBody(
 | 
| -    PreParserIdentifier function_name, int pos, Variable* fvar,
 | 
| -    Token::Value fvar_init_op, FunctionKind kind, bool* ok) {
 | 
| -  return pre_parser_->ParseEagerFunctionBody(function_name, pos, fvar,
 | 
| -                                             fvar_init_op, kind, ok);
 | 
| +    PreParserIdentifier function_name, int pos,
 | 
| +    const PreParserFormalParameterParsingState& formal_parameters,
 | 
| +    Variable* fvar, Token::Value fvar_init_op, FunctionKind kind, bool* ok) {
 | 
| +  return pre_parser_->ParseEagerFunctionBody(
 | 
| +      function_name, pos, formal_parameters, fvar, fvar_init_op, kind, ok);
 | 
|  }
 | 
|  
 | 
|  
 | 
| @@ -2162,20 +2182,22 @@ ParserBase<Traits>::ParsePrimaryExpression(ExpressionClassifier* classifier,
 | 
|          }
 | 
|          Scope* scope =
 | 
|              this->NewScope(scope_, ARROW_SCOPE, FunctionKind::kArrowFunction);
 | 
| +        FormalParameterParsingStateT parsing_state(scope);
 | 
|          scope->set_start_position(beg_pos);
 | 
|          ExpressionClassifier args_classifier;
 | 
| -        bool has_rest = false;
 | 
| -        result = this->ParseArrowFunctionLiteral(scope, has_rest,
 | 
| -                                                 args_classifier, CHECK_OK);
 | 
| +        result = this->ParseArrowFunctionLiteral(parsing_state, args_classifier,
 | 
| +                                                 CHECK_OK);
 | 
|        } else if (allow_harmony_arrow_functions() &&
 | 
|                   allow_harmony_rest_params() && Check(Token::ELLIPSIS)) {
 | 
|          // (...x) => y
 | 
|          Scope* scope =
 | 
|              this->NewScope(scope_, ARROW_SCOPE, FunctionKind::kArrowFunction);
 | 
| +        FormalParameterParsingStateT parsing_state(scope);
 | 
|          scope->set_start_position(beg_pos);
 | 
|          ExpressionClassifier args_classifier;
 | 
| -        const bool has_rest = true;
 | 
| -        this->ParseFormalParameter(scope, has_rest, &args_classifier, CHECK_OK);
 | 
| +        const bool is_rest = true;
 | 
| +        this->ParseFormalParameter(is_rest, &parsing_state, &args_classifier,
 | 
| +                                   CHECK_OK);
 | 
|          if (peek() == Token::COMMA) {
 | 
|            ReportMessageAt(scanner()->peek_location(),
 | 
|                            MessageTemplate::kParamAfterRest);
 | 
| @@ -2183,8 +2205,8 @@ ParserBase<Traits>::ParsePrimaryExpression(ExpressionClassifier* classifier,
 | 
|            return this->EmptyExpression();
 | 
|          }
 | 
|          Expect(Token::RPAREN, CHECK_OK);
 | 
| -        result = this->ParseArrowFunctionLiteral(scope, has_rest,
 | 
| -                                                 args_classifier, CHECK_OK);
 | 
| +        result = this->ParseArrowFunctionLiteral(parsing_state, args_classifier,
 | 
| +                                                 CHECK_OK);
 | 
|        } else {
 | 
|          // Heuristically try to detect immediately called functions before
 | 
|          // seeing the call parentheses.
 | 
| @@ -2524,6 +2546,11 @@ ParserBase<Traits>::ParsePropertyDefinition(
 | 
|      DCHECK(!*is_computed_name);
 | 
|      DCHECK(!is_static);
 | 
|  
 | 
| +    if (classifier->duplicate_finder() != nullptr &&
 | 
| +        scanner()->FindSymbol(classifier->duplicate_finder(), 1) != 0) {
 | 
| +      classifier->RecordDuplicateFormalParameterError(scanner()->location());
 | 
| +    }
 | 
| +
 | 
|      ExpressionT lhs = this->ExpressionFromIdentifier(
 | 
|          name, next_beg_pos, next_end_pos, scope_, factory());
 | 
|      if (peek() == Token::ASSIGN) {
 | 
| @@ -2707,7 +2734,7 @@ ParserBase<Traits>::ParseAssignmentExpression(bool accept_IN,
 | 
|  
 | 
|    if (fni_ != NULL) fni_->Enter();
 | 
|    ParserBase<Traits>::Checkpoint checkpoint(this);
 | 
| -  ExpressionClassifier arrow_formals_classifier;
 | 
| +  ExpressionClassifier arrow_formals_classifier(classifier->duplicate_finder());
 | 
|    if (peek() != Token::LPAREN) {
 | 
|      // The expression we are going to read is not a parenthesized arrow function
 | 
|      // formal parameter list.
 | 
| @@ -2726,15 +2753,15 @@ ParserBase<Traits>::ParseAssignmentExpression(bool accept_IN,
 | 
|          this->NewScope(scope_, ARROW_SCOPE, FunctionKind::kArrowFunction);
 | 
|      scope->set_start_position(lhs_location.beg_pos);
 | 
|      Scanner::Location duplicate_loc = Scanner::Location::invalid();
 | 
| -    bool has_rest = false;
 | 
| -    this->ParseArrowFunctionFormalParameters(scope, expression, loc, &has_rest,
 | 
| +    FormalParameterParsingStateT parsing_state(scope);
 | 
| +    this->ParseArrowFunctionFormalParameters(&parsing_state, expression, loc,
 | 
|                                               &duplicate_loc, CHECK_OK);
 | 
|      if (duplicate_loc.IsValid()) {
 | 
|        arrow_formals_classifier.RecordDuplicateFormalParameterError(
 | 
|            duplicate_loc);
 | 
|      }
 | 
|      expression = this->ParseArrowFunctionLiteral(
 | 
| -        scope, has_rest, arrow_formals_classifier, CHECK_OK);
 | 
| +        parsing_state, arrow_formals_classifier, CHECK_OK);
 | 
|      return expression;
 | 
|    }
 | 
|  
 | 
| @@ -3497,9 +3524,9 @@ ParserBase<Traits>::ParseMemberExpressionContinuation(
 | 
|  
 | 
|  
 | 
|  template <class Traits>
 | 
| -void ParserBase<Traits>::ParseFormalParameter(Scope* scope, bool is_rest,
 | 
| -                                              ExpressionClassifier* classifier,
 | 
| -                                              bool* ok) {
 | 
| +void ParserBase<Traits>::ParseFormalParameter(
 | 
| +    bool is_rest, FormalParameterParsingStateT* parsing_state,
 | 
| +    ExpressionClassifier* classifier, bool* ok) {
 | 
|    // FormalParameter[Yield,GeneratorParameter] :
 | 
|    //   BindingElement[?Yield, ?GeneratorParameter]
 | 
|  
 | 
| @@ -3516,13 +3543,24 @@ void ParserBase<Traits>::ParseFormalParameter(Scope* scope, bool is_rest,
 | 
|      return;
 | 
|    }
 | 
|  
 | 
| -  Traits::DeclareFormalParameter(scope, pattern, classifier, is_rest);
 | 
| +  if (parsing_state->is_simple_parameter_list) {
 | 
| +    parsing_state->is_simple_parameter_list =
 | 
| +        !is_rest && Traits::IsIdentifier(pattern);
 | 
| +  }
 | 
| +  parsing_state->has_rest = is_rest;
 | 
| +  if (is_rest && !Traits::IsIdentifier(pattern)) {
 | 
| +    ReportUnexpectedToken(next);
 | 
| +    *ok = false;
 | 
| +    return;
 | 
| +  }
 | 
| +  Traits::DeclareFormalParameter(parsing_state, pattern, classifier, is_rest);
 | 
|  }
 | 
|  
 | 
|  
 | 
|  template <class Traits>
 | 
|  int ParserBase<Traits>::ParseFormalParameterList(
 | 
| -    Scope* scope, bool* is_rest, ExpressionClassifier* classifier, bool* ok) {
 | 
| +    FormalParameterParsingStateT* parsing_state,
 | 
| +    ExpressionClassifier* classifier, bool* ok) {
 | 
|    // FormalParameters[Yield,GeneratorParameter] :
 | 
|    //   [empty]
 | 
|    //   FormalParameterList[?Yield, ?GeneratorParameter]
 | 
| @@ -3546,12 +3584,12 @@ int ParserBase<Traits>::ParseFormalParameterList(
 | 
|          *ok = false;
 | 
|          return -1;
 | 
|        }
 | 
| -      *is_rest = allow_harmony_rest_params() && Check(Token::ELLIPSIS);
 | 
| -      ParseFormalParameter(scope, *is_rest, classifier, ok);
 | 
| +      bool is_rest = allow_harmony_rest_params() && Check(Token::ELLIPSIS);
 | 
| +      ParseFormalParameter(is_rest, parsing_state, classifier, ok);
 | 
|        if (!*ok) return -1;
 | 
| -    } while (!*is_rest && Check(Token::COMMA));
 | 
| +    } while (!parsing_state->has_rest && Check(Token::COMMA));
 | 
|  
 | 
| -    if (*is_rest && peek() == Token::COMMA) {
 | 
| +    if (parsing_state->has_rest && peek() == Token::COMMA) {
 | 
|        ReportMessageAt(scanner()->peek_location(),
 | 
|                        MessageTemplate::kParamAfterRest);
 | 
|        *ok = false;
 | 
| @@ -3596,8 +3634,8 @@ void ParserBase<Traits>::CheckArityRestrictions(
 | 
|  template <class Traits>
 | 
|  typename ParserBase<Traits>::ExpressionT
 | 
|  ParserBase<Traits>::ParseArrowFunctionLiteral(
 | 
| -    Scope* scope, bool has_rest, const ExpressionClassifier& formals_classifier,
 | 
| -    bool* ok) {
 | 
| +    const FormalParameterParsingStateT& formal_parameters,
 | 
| +    const ExpressionClassifier& formals_classifier, bool* ok) {
 | 
|    if (peek() == Token::ARROW && scanner_->HasAnyLineTerminatorBeforeNext()) {
 | 
|      // ASI inserts `;` after arrow parameters if a line terminator is found.
 | 
|      // `=> ...` is never a valid expression, so report as syntax error.
 | 
| @@ -3608,15 +3646,16 @@ ParserBase<Traits>::ParseArrowFunctionLiteral(
 | 
|    }
 | 
|  
 | 
|    typename Traits::Type::StatementList body;
 | 
| -  int num_parameters = scope->num_parameters();
 | 
| +  int num_parameters = formal_parameters.scope->num_parameters();
 | 
|    int materialized_literal_count = -1;
 | 
|    int expected_property_count = -1;
 | 
|    Scanner::Location super_loc;
 | 
|  
 | 
|    {
 | 
|      typename Traits::Type::Factory function_factory(ast_value_factory());
 | 
| -    FunctionState function_state(&function_state_, &scope_, scope,
 | 
| -                                 kArrowFunction, &function_factory);
 | 
| +    FunctionState function_state(&function_state_, &scope_,
 | 
| +                                 formal_parameters.scope, kArrowFunction,
 | 
| +                                 &function_factory);
 | 
|  
 | 
|      Expect(Token::ARROW, CHECK_OK);
 | 
|  
 | 
| @@ -3631,8 +3670,8 @@ ParserBase<Traits>::ParseArrowFunctionLiteral(
 | 
|                                     &expected_property_count, CHECK_OK);
 | 
|        } else {
 | 
|          body = this->ParseEagerFunctionBody(
 | 
| -            this->EmptyIdentifier(), RelocInfo::kNoPosition, NULL,
 | 
| -            Token::INIT_VAR, kArrowFunction, CHECK_OK);
 | 
| +            this->EmptyIdentifier(), RelocInfo::kNoPosition, formal_parameters,
 | 
| +            NULL, Token::INIT_VAR, kArrowFunction, CHECK_OK);
 | 
|          materialized_literal_count =
 | 
|              function_state.materialized_literal_count();
 | 
|          expected_property_count = function_state.expected_property_count();
 | 
| @@ -3646,13 +3685,14 @@ ParserBase<Traits>::ParseArrowFunctionLiteral(
 | 
|            ParseAssignmentExpression(true, &classifier, CHECK_OK);
 | 
|        ValidateExpression(&classifier, CHECK_OK);
 | 
|        body = this->NewStatementList(1, zone());
 | 
| +      this->AddParameterInitializationBlock(formal_parameters, body, CHECK_OK);
 | 
|        body->Add(factory()->NewReturnStatement(expression, pos), zone());
 | 
|        materialized_literal_count = function_state.materialized_literal_count();
 | 
|        expected_property_count = function_state.expected_property_count();
 | 
|      }
 | 
|      super_loc = function_state.super_location();
 | 
|  
 | 
| -    scope->set_end_position(scanner()->location().end_pos);
 | 
| +    formal_parameters.scope->set_end_position(scanner()->location().end_pos);
 | 
|  
 | 
|      // Arrow function formal parameters are parsed as StrictFormalParameterList,
 | 
|      // which is not the same as "parameters of a strict function"; it only means
 | 
| @@ -3664,21 +3704,23 @@ ParserBase<Traits>::ParseArrowFunctionLiteral(
 | 
|  
 | 
|      // Validate strict mode.
 | 
|      if (is_strict(language_mode())) {
 | 
| -      CheckStrictOctalLiteral(scope->start_position(),
 | 
| +      CheckStrictOctalLiteral(formal_parameters.scope->start_position(),
 | 
|                                scanner()->location().end_pos, CHECK_OK);
 | 
| -      this->CheckConflictingVarDeclarations(scope, CHECK_OK);
 | 
| +      this->CheckConflictingVarDeclarations(formal_parameters.scope, CHECK_OK);
 | 
|      }
 | 
|    }
 | 
|  
 | 
|    FunctionLiteralT function_literal = factory()->NewFunctionLiteral(
 | 
| -      this->EmptyIdentifierString(), ast_value_factory(), scope, body,
 | 
| -      materialized_literal_count, expected_property_count, num_parameters,
 | 
| +      this->EmptyIdentifierString(), ast_value_factory(),
 | 
| +      formal_parameters.scope, body, materialized_literal_count,
 | 
| +      expected_property_count, num_parameters,
 | 
|        FunctionLiteral::kNoDuplicateParameters,
 | 
|        FunctionLiteral::ANONYMOUS_EXPRESSION, FunctionLiteral::kIsFunction,
 | 
|        FunctionLiteral::kShouldLazyCompile, FunctionKind::kArrowFunction,
 | 
| -      scope->start_position());
 | 
| +      formal_parameters.scope->start_position());
 | 
|  
 | 
| -  function_literal->set_function_token_position(scope->start_position());
 | 
| +  function_literal->set_function_token_position(
 | 
| +      formal_parameters.scope->start_position());
 | 
|    if (super_loc.IsValid()) function_state_->set_super_location(super_loc);
 | 
|  
 | 
|    if (fni_ != NULL) this->InferFunctionName(fni_, function_literal);
 | 
| 
 |