| Index: src/parsing/parser.cc | 
| diff --git a/src/parsing/parser.cc b/src/parsing/parser.cc | 
| index 24df10cb9d7a4021d1541c90c77e09caee97ed6a..21b316e94042a3d3c2436f08e0517e29e1c9ab8c 100644 | 
| --- a/src/parsing/parser.cc | 
| +++ b/src/parsing/parser.cc | 
| @@ -1285,10 +1285,10 @@ Statement* Parser::ParseStatementListItem(bool* ok) { | 
| const Token::Value peeked = peek(); | 
| switch (peeked) { | 
| case Token::FUNCTION: | 
| -      return ParseHoistableDeclaration(NULL, ok); | 
| +      return ParseHoistableDeclaration(NULL, false, ok); | 
| case Token::CLASS: | 
| Consume(Token::CLASS); | 
| -      return ParseClassDeclaration(NULL, ok); | 
| +      return ParseClassDeclaration(NULL, false, ok); | 
| case Token::CONST: | 
| return ParseVariableStatement(kStatementListItem, NULL, ok); | 
| case Token::VAR: | 
| @@ -1302,7 +1302,7 @@ Statement* Parser::ParseStatementListItem(bool* ok) { | 
| if (allow_harmony_async_await() && PeekAhead() == Token::FUNCTION && | 
| !scanner()->HasAnyLineTerminatorAfterNext()) { | 
| Consume(Token::ASYNC); | 
| -        return ParseAsyncFunctionDeclaration(NULL, ok); | 
| +        return ParseAsyncFunctionDeclaration(NULL, false, ok); | 
| } | 
| /* falls through */ | 
| default: | 
| @@ -1576,66 +1576,20 @@ Statement* Parser::ParseExportDefault(bool* ok) { | 
| Statement* result = nullptr; | 
| Expression* default_export = nullptr; | 
| switch (peek()) { | 
| -    case Token::FUNCTION: { | 
| -      Consume(Token::FUNCTION); | 
| -      int pos = position(); | 
| -      bool is_generator = Check(Token::MUL); | 
| -      if (peek() == Token::LPAREN) { | 
| -        // FunctionDeclaration[+Default] :: | 
| -        //   'function' '(' FormalParameters ')' '{' FunctionBody '}' | 
| -        // | 
| -        // GeneratorDeclaration[+Default] :: | 
| -        //   'function' '*' '(' FormalParameters ')' '{' FunctionBody '}' | 
| -        default_export = ParseFunctionLiteral( | 
| -            default_string, Scanner::Location::invalid(), | 
| -            kSkipFunctionNameCheck, | 
| -            is_generator ? FunctionKind::kGeneratorFunction | 
| -                         : FunctionKind::kNormalFunction, | 
| -            pos, FunctionLiteral::kDeclaration, language_mode(), CHECK_OK); | 
| -        result = factory()->NewEmptyStatement(kNoSourcePosition); | 
| -      } else { | 
| -        result = ParseHoistableDeclaration( | 
| -            pos, is_generator ? ParseFunctionFlags::kIsGenerator | 
| -                              : ParseFunctionFlags::kIsNormal, | 
| -            &names, CHECK_OK); | 
| -      } | 
| +    case Token::FUNCTION: | 
| +      result = ParseHoistableDeclaration(&names, true, CHECK_OK); | 
| break; | 
| -    } | 
|  | 
| case Token::CLASS: | 
| Consume(Token::CLASS); | 
| -      if (peek() == Token::EXTENDS || peek() == Token::LBRACE) { | 
| -        // ClassDeclaration[+Default] :: | 
| -        //   'class' ('extends' LeftHandExpression)? '{' ClassBody '}' | 
| -        default_export = ParseClassLiteral(nullptr, default_string, | 
| -                                           Scanner::Location::invalid(), false, | 
| -                                           position(), CHECK_OK); | 
| -        result = factory()->NewEmptyStatement(kNoSourcePosition); | 
| -      } else { | 
| -        result = ParseClassDeclaration(&names, CHECK_OK); | 
| -      } | 
| +      result = ParseClassDeclaration(&names, true, CHECK_OK); | 
| break; | 
|  | 
| case Token::ASYNC: | 
| if (allow_harmony_async_await() && PeekAhead() == Token::FUNCTION && | 
| !scanner()->HasAnyLineTerminatorAfterNext()) { | 
| Consume(Token::ASYNC); | 
| -        Consume(Token::FUNCTION); | 
| -        int pos = position(); | 
| -        if (peek() == Token::LPAREN) { | 
| -          // AsyncFunctionDeclaration[+Default] :: | 
| -          //   async [no LineTerminator here] function ( FormalParameters ) { | 
| -          //      AsyncFunctionBody | 
| -          //   } | 
| -          default_export = ParseFunctionLiteral( | 
| -              default_string, Scanner::Location::invalid(), | 
| -              kSkipFunctionNameCheck, FunctionKind::kAsyncFunction, pos, | 
| -              FunctionLiteral::kDeclaration, language_mode(), CHECK_OK); | 
| -          result = factory()->NewEmptyStatement(kNoSourcePosition); | 
| -        } else { | 
| -          result = ParseHoistableDeclaration(pos, ParseFunctionFlags::kIsAsync, | 
| -                                             &names, CHECK_OK); | 
| -        } | 
| +        result = ParseAsyncFunctionDeclaration(&names, true, CHECK_OK); | 
| break; | 
| } | 
| /* falls through */ | 
| @@ -1750,12 +1704,12 @@ Statement* Parser::ParseExportDeclaration(bool* ok) { | 
| } | 
|  | 
| case Token::FUNCTION: | 
| -      result = ParseHoistableDeclaration(&names, CHECK_OK); | 
| +      result = ParseHoistableDeclaration(&names, false, CHECK_OK); | 
| break; | 
|  | 
| case Token::CLASS: | 
| Consume(Token::CLASS); | 
| -      result = ParseClassDeclaration(&names, CHECK_OK); | 
| +      result = ParseClassDeclaration(&names, false, CHECK_OK); | 
| break; | 
|  | 
| case Token::VAR: | 
| @@ -1767,7 +1721,7 @@ Statement* Parser::ParseExportDeclaration(bool* ok) { | 
| case Token::ASYNC: | 
| if (allow_harmony_async_await()) { | 
| Consume(Token::ASYNC); | 
| -        result = ParseAsyncFunctionDeclaration(&names, CHECK_OK); | 
| +        result = ParseAsyncFunctionDeclaration(&names, false, CHECK_OK); | 
| break; | 
| } | 
| /* falls through */ | 
| @@ -2139,20 +2093,19 @@ Statement* Parser::ParseNativeDeclaration(bool* ok) { | 
| pos); | 
| } | 
|  | 
| - | 
| Statement* Parser::ParseHoistableDeclaration( | 
| -    ZoneList<const AstRawString*>* names, bool* ok) { | 
| +    ZoneList<const AstRawString*>* names, bool default_export, bool* ok) { | 
| Expect(Token::FUNCTION, CHECK_OK); | 
| int pos = position(); | 
| ParseFunctionFlags flags = ParseFunctionFlags::kIsNormal; | 
| if (Check(Token::MUL)) { | 
| flags |= ParseFunctionFlags::kIsGenerator; | 
| } | 
| -  return ParseHoistableDeclaration(pos, flags, names, ok); | 
| +  return ParseHoistableDeclaration(pos, flags, names, default_export, ok); | 
| } | 
|  | 
| Statement* Parser::ParseAsyncFunctionDeclaration( | 
| -    ZoneList<const AstRawString*>* names, bool* ok) { | 
| +    ZoneList<const AstRawString*>* names, bool default_export, bool* ok) { | 
| DCHECK_EQ(scanner()->current_token(), Token::ASYNC); | 
| int pos = position(); | 
| if (scanner()->HasAnyLineTerminatorBeforeNext()) { | 
| @@ -2162,25 +2115,41 @@ Statement* Parser::ParseAsyncFunctionDeclaration( | 
| } | 
| Expect(Token::FUNCTION, CHECK_OK); | 
| ParseFunctionFlags flags = ParseFunctionFlags::kIsAsync; | 
| -  return ParseHoistableDeclaration(pos, flags, names, ok); | 
| +  return ParseHoistableDeclaration(pos, flags, names, default_export, ok); | 
| } | 
|  | 
| Statement* Parser::ParseHoistableDeclaration( | 
| int pos, ParseFunctionFlags flags, ZoneList<const AstRawString*>* names, | 
| -    bool* ok) { | 
| +    bool default_export, bool* ok) { | 
| // FunctionDeclaration :: | 
| //   'function' Identifier '(' FormalParameters ')' '{' FunctionBody '}' | 
| +  //   'function' '(' FormalParameters ')' '{' FunctionBody '}' | 
| // GeneratorDeclaration :: | 
| //   'function' '*' Identifier '(' FormalParameters ')' '{' FunctionBody '}' | 
| +  //   'function' '*' '(' FormalParameters ')' '{' FunctionBody '}' | 
| +  // | 
| +  // The anonymous forms are allowed iff [default_export] is true. | 
| // | 
| // 'function' and '*' (if present) have been consumed by the caller. | 
| + | 
| const bool is_generator = flags & ParseFunctionFlags::kIsGenerator; | 
| const bool is_async = flags & ParseFunctionFlags::kIsAsync; | 
| DCHECK(!is_generator || !is_async); | 
|  | 
| -  bool is_strict_reserved = false; | 
| -  const AstRawString* name = ParseIdentifierOrStrictReservedWord( | 
| -      &is_strict_reserved, CHECK_OK); | 
| +  const AstRawString* name; | 
| +  FunctionNameValidity name_validity; | 
| +  const AstRawString* variable_name; | 
| +  if (default_export && peek() == Token::LPAREN) { | 
| +    name = ast_value_factory()->default_string(); | 
| +    name_validity = kSkipFunctionNameCheck; | 
| +    variable_name = ast_value_factory()->star_default_star_string(); | 
| +  } else { | 
| +    bool is_strict_reserved; | 
| +    name = ParseIdentifierOrStrictReservedWord(&is_strict_reserved, CHECK_OK); | 
| +    name_validity = is_strict_reserved ? kFunctionNameIsStrictReserved | 
| +                                       : kFunctionNameValidityUnknown; | 
| +    variable_name = name; | 
| +  } | 
|  | 
| if (V8_UNLIKELY(is_async_function() && this->IsAwait(name))) { | 
| ReportMessageAt(scanner()->location(), | 
| @@ -2192,9 +2161,7 @@ Statement* Parser::ParseHoistableDeclaration( | 
| FuncNameInferrer::State fni_state(fni_); | 
| if (fni_ != NULL) fni_->PushEnclosingName(name); | 
| FunctionLiteral* fun = ParseFunctionLiteral( | 
| -      name, scanner()->location(), | 
| -      is_strict_reserved ? kFunctionNameIsStrictReserved | 
| -                         : kFunctionNameValidityUnknown, | 
| +      name, scanner()->location(), name_validity, | 
| is_generator ? FunctionKind::kGeneratorFunction | 
| : is_async ? FunctionKind::kAsyncFunction | 
| : FunctionKind::kNormalFunction, | 
| @@ -2208,11 +2175,11 @@ Statement* Parser::ParseHoistableDeclaration( | 
| VariableMode mode = | 
| (!scope_->is_declaration_scope() || scope_->is_module_scope()) ? LET | 
| : VAR; | 
| -  VariableProxy* proxy = NewUnresolved(name, mode); | 
| +  VariableProxy* proxy = NewUnresolved(variable_name, mode); | 
| Declaration* declaration = | 
| factory()->NewFunctionDeclaration(proxy, mode, fun, scope_, pos); | 
| Declare(declaration, DeclarationDescriptor::NORMAL, true, CHECK_OK); | 
| -  if (names) names->Add(name, zone()); | 
| +  if (names) names->Add(variable_name, zone()); | 
| EmptyStatement* empty = factory()->NewEmptyStatement(kNoSourcePosition); | 
| // Async functions don't undergo sloppy mode block scoped hoisting, and don't | 
| // allow duplicates in a block. Both are represented by the | 
| @@ -2223,18 +2190,20 @@ Statement* Parser::ParseHoistableDeclaration( | 
| !is_async && !(allow_harmony_restrictive_generators() && is_generator)) { | 
| SloppyBlockFunctionStatement* delegate = | 
| factory()->NewSloppyBlockFunctionStatement(empty, scope_); | 
| -    scope_->DeclarationScope()->sloppy_block_function_map()->Declare(name, | 
| -                                                                     delegate); | 
| +    scope_->DeclarationScope()->sloppy_block_function_map()->Declare( | 
| +        variable_name, delegate); | 
| return delegate; | 
| } | 
| return empty; | 
| } | 
|  | 
| - | 
| Statement* Parser::ParseClassDeclaration(ZoneList<const AstRawString*>* names, | 
| -                                         bool* ok) { | 
| +                                         bool default_export, bool* ok) { | 
| // ClassDeclaration :: | 
| //   'class' Identifier ('extends' LeftHandExpression)? '{' ClassBody '}' | 
| +  //   'class' ('extends' LeftHandExpression)? '{' ClassBody '}' | 
| +  // | 
| +  // The anonymous form is allowed iff [default_export] is true. | 
| // | 
| // 'class' is expected to be consumed by the caller. | 
| // | 
| @@ -2249,13 +2218,23 @@ Statement* Parser::ParseClassDeclaration(ZoneList<const AstRawString*>* names, | 
| // so rewrite it as such. | 
|  | 
| int pos = position(); | 
| -  bool is_strict_reserved = false; | 
| -  const AstRawString* name = | 
| -      ParseIdentifierOrStrictReservedWord(&is_strict_reserved, CHECK_OK); | 
| + | 
| +  const AstRawString* name; | 
| +  bool is_strict_reserved; | 
| +  const AstRawString* variable_name; | 
| +  if (default_export && (peek() == Token::EXTENDS || peek() == Token::LBRACE)) { | 
| +    name = ast_value_factory()->default_string(); | 
| +    is_strict_reserved = false; | 
| +    variable_name = ast_value_factory()->star_default_star_string(); | 
| +  } else { | 
| +    name = ParseIdentifierOrStrictReservedWord(&is_strict_reserved, CHECK_OK); | 
| +    variable_name = name; | 
| +  } | 
| + | 
| ClassLiteral* value = ParseClassLiteral(nullptr, name, scanner()->location(), | 
| is_strict_reserved, pos, CHECK_OK); | 
|  | 
| -  VariableProxy* proxy = NewUnresolved(name, LET); | 
| +  VariableProxy* proxy = NewUnresolved(variable_name, LET); | 
| Declaration* declaration = | 
| factory()->NewVariableDeclaration(proxy, LET, scope_, pos); | 
| Declare(declaration, DeclarationDescriptor::NORMAL, true, CHECK_OK); | 
| @@ -2264,7 +2243,7 @@ Statement* Parser::ParseClassDeclaration(ZoneList<const AstRawString*>* names, | 
| factory()->NewAssignment(Token::INIT, proxy, value, pos); | 
| Statement* assignment_statement = | 
| factory()->NewExpressionStatement(assignment, kNoSourcePosition); | 
| -  if (names) names->Add(name, zone()); | 
| +  if (names) names->Add(variable_name, zone()); | 
| return assignment_statement; | 
| } | 
|  | 
| @@ -2524,7 +2503,7 @@ Statement* Parser::ParseFunctionDeclaration(bool* ok) { | 
| } | 
| } | 
|  | 
| -  return ParseHoistableDeclaration(pos, flags, nullptr, CHECK_OK); | 
| +  return ParseHoistableDeclaration(pos, flags, nullptr, false, CHECK_OK); | 
| } | 
|  | 
| Statement* Parser::ParseExpressionOrLabelledStatement( | 
|  |