| Index: src/parsing/parser.cc
 | 
| diff --git a/src/parsing/parser.cc b/src/parsing/parser.cc
 | 
| index 15fcae536a3d962824128a59a36ff29721baf3fd..3b67ea241896f89251e94f0108e2ca974195f5a5 100644
 | 
| --- a/src/parsing/parser.cc
 | 
| +++ b/src/parsing/parser.cc
 | 
| @@ -715,7 +715,7 @@ FunctionLiteral* Parser::DoParseProgram(ParseInfo* info) {
 | 
|        // pre-existing bindings should be made writable, enumerable and
 | 
|        // nonconfigurable if possible, whereas this code will leave attributes
 | 
|        // unchanged if the property already exists.
 | 
| -      InsertSloppyBlockFunctionVarBindings(scope, nullptr, &ok);
 | 
| +      InsertSloppyBlockFunctionVarBindings(scope, &ok);
 | 
|      }
 | 
|      if (ok) {
 | 
|        CheckConflictingVarDeclarations(scope, &ok);
 | 
| @@ -1365,14 +1365,10 @@ VariableProxy* Parser::NewUnresolved(const AstRawString* name) {
 | 
|                                  scanner()->location().end_pos);
 | 
|  }
 | 
|  
 | 
| -InitializationFlag Parser::DefaultInitializationFlag(VariableMode mode) {
 | 
| -  DCHECK(IsDeclaredVariableMode(mode));
 | 
| -  return mode == VAR ? kCreatedInitialized : kNeedsInitialization;
 | 
| -}
 | 
| -
 | 
|  Declaration* Parser::DeclareVariable(const AstRawString* name,
 | 
|                                       VariableMode mode, int pos, bool* ok) {
 | 
| -  return DeclareVariable(name, mode, DefaultInitializationFlag(mode), pos, ok);
 | 
| +  return DeclareVariable(name, mode, Variable::DefaultInitializationFlag(mode),
 | 
| +                         pos, ok);
 | 
|  }
 | 
|  
 | 
|  Declaration* Parser::DeclareVariable(const AstRawString* name,
 | 
| @@ -1535,7 +1531,6 @@ Statement* Parser::ParseHoistableDeclaration(
 | 
|    Declare(declaration, DeclarationDescriptor::NORMAL, mode, kCreatedInitialized,
 | 
|            CHECK_OK);
 | 
|    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
 | 
|    // sloppy_block_function_map. Don't add them to the map for async functions.
 | 
| @@ -1544,12 +1539,12 @@ Statement* Parser::ParseHoistableDeclaration(
 | 
|    if (is_sloppy(language_mode()) && !scope()->is_declaration_scope() &&
 | 
|        !is_async && !(allow_harmony_restrictive_generators() && is_generator)) {
 | 
|      SloppyBlockFunctionStatement* delegate =
 | 
| -        factory()->NewSloppyBlockFunctionStatement(empty, scope());
 | 
| +        factory()->NewSloppyBlockFunctionStatement(scope());
 | 
|      DeclarationScope* target_scope = GetDeclarationScope();
 | 
|      target_scope->DeclareSloppyBlockFunction(variable_name, delegate);
 | 
|      return delegate;
 | 
|    }
 | 
| -  return empty;
 | 
| +  return factory()->NewEmptyStatement(kNoSourcePosition);
 | 
|  }
 | 
|  
 | 
|  Statement* Parser::ParseClassDeclaration(ZoneList<const AstRawString*>* names,
 | 
| @@ -4112,8 +4107,7 @@ ZoneList<Statement*>* Parser::ParseEagerFunctionBody(
 | 
|      Block* init_block = BuildParameterInitializationBlock(parameters, CHECK_OK);
 | 
|  
 | 
|      if (is_sloppy(inner_scope->language_mode())) {
 | 
| -      InsertSloppyBlockFunctionVarBindings(inner_scope, function_scope,
 | 
| -                                           CHECK_OK);
 | 
| +      InsertSloppyBlockFunctionVarBindings(inner_scope, CHECK_OK);
 | 
|      }
 | 
|  
 | 
|      // TODO(littledan): Merge the two rejection blocks into one
 | 
| @@ -4135,7 +4129,7 @@ ZoneList<Statement*>* Parser::ParseEagerFunctionBody(
 | 
|    } else {
 | 
|      DCHECK_EQ(inner_scope, function_scope);
 | 
|      if (is_sloppy(function_scope->language_mode())) {
 | 
| -      InsertSloppyBlockFunctionVarBindings(function_scope, nullptr, CHECK_OK);
 | 
| +      InsertSloppyBlockFunctionVarBindings(function_scope, CHECK_OK);
 | 
|      }
 | 
|    }
 | 
|  
 | 
| @@ -4222,7 +4216,7 @@ Expression* Parser::ParseClassLiteral(const AstRawString* name,
 | 
|      Declaration* declaration =
 | 
|          factory()->NewVariableDeclaration(proxy, block_state.scope(), pos);
 | 
|      Declare(declaration, DeclarationDescriptor::NORMAL, CONST,
 | 
| -            DefaultInitializationFlag(CONST), CHECK_OK);
 | 
| +            Variable::DefaultInitializationFlag(CONST), CHECK_OK);
 | 
|    }
 | 
|  
 | 
|    Expression* extends = nullptr;
 | 
| @@ -4419,86 +4413,20 @@ void Parser::InsertShadowingVarBindingInitializers(Block* inner_block) {
 | 
|  }
 | 
|  
 | 
|  void Parser::InsertSloppyBlockFunctionVarBindings(DeclarationScope* scope,
 | 
| -                                                  Scope* complex_params_scope,
 | 
|                                                    bool* ok) {
 | 
| -  // For each variable which is used as a function declaration in a sloppy
 | 
| -  // block,
 | 
| +  scope->HoistSloppyBlockFunctions(factory(), CHECK_OK_VOID);
 | 
| +
 | 
|    SloppyBlockFunctionMap* map = scope->sloppy_block_function_map();
 | 
|    for (ZoneHashMap::Entry* p = map->Start(); p != nullptr; p = map->Next(p)) {
 | 
| -    AstRawString* name = static_cast<AstRawString*>(p->key);
 | 
| -
 | 
| -    // If the variable wouldn't conflict with a lexical declaration
 | 
| -    // or parameter,
 | 
| -
 | 
| -    // Check if there's a conflict with a parameter.
 | 
| -    // This depends on the fact that functions always have a scope solely to
 | 
| -    // hold complex parameters, and the names local to that scope are
 | 
| -    // precisely the names of the parameters. IsDeclaredParameter(name) does
 | 
| -    // not hold for names declared by complex parameters, nor are those
 | 
| -    // bindings necessarily declared lexically, so we have to check for them
 | 
| -    // explicitly. On the other hand, if there are not complex parameters,
 | 
| -    // it is sufficient to just check IsDeclaredParameter.
 | 
| -    if (complex_params_scope != nullptr) {
 | 
| -      if (complex_params_scope->LookupLocal(name) != nullptr) {
 | 
| -        continue;
 | 
| -      }
 | 
| -    } else {
 | 
| -      if (scope->IsDeclaredParameter(name)) {
 | 
| -        continue;
 | 
| -      }
 | 
| -    }
 | 
| -
 | 
| -    bool var_created = false;
 | 
| -
 | 
|      // Write in assignments to var for each block-scoped function declaration
 | 
|      auto delegates = static_cast<SloppyBlockFunctionStatement*>(p->value);
 | 
| -
 | 
| -    DeclarationScope* decl_scope = scope;
 | 
| -    while (decl_scope->is_eval_scope()) {
 | 
| -      decl_scope = decl_scope->outer_scope()->GetDeclarationScope();
 | 
| -    }
 | 
| -    Scope* outer_scope = decl_scope->outer_scope();
 | 
| -
 | 
|      for (SloppyBlockFunctionStatement* delegate = delegates;
 | 
|           delegate != nullptr; delegate = delegate->next()) {
 | 
| -      // Check if there's a conflict with a lexical declaration
 | 
| -      Scope* query_scope = delegate->scope()->outer_scope();
 | 
| -      Variable* var = nullptr;
 | 
| -      bool should_hoist = true;
 | 
| -
 | 
| -      // Note that we perform this loop for each delegate named 'name',
 | 
| -      // which may duplicate work if those delegates share scopes.
 | 
| -      // It is not sufficient to just do a Lookup on query_scope: for
 | 
| -      // example, that does not prevent hoisting of the function in
 | 
| -      // `{ let e; try {} catch (e) { function e(){} } }`
 | 
| -      do {
 | 
| -        var = query_scope->LookupLocal(name);
 | 
| -        if (var != nullptr && IsLexicalVariableMode(var->mode())) {
 | 
| -          should_hoist = false;
 | 
| -          break;
 | 
| -        }
 | 
| -        query_scope = query_scope->outer_scope();
 | 
| -      } while (query_scope != outer_scope);
 | 
| -
 | 
| -      if (!should_hoist) continue;
 | 
| -
 | 
| -      // Declare a var-style binding for the function in the outer scope
 | 
| -      if (!var_created) {
 | 
| -        var_created = true;
 | 
| -        VariableProxy* proxy = scope->NewUnresolved(factory(), name);
 | 
| -        Declaration* declaration =
 | 
| -            factory()->NewVariableDeclaration(proxy, scope, kNoSourcePosition);
 | 
| -        Declare(declaration, DeclarationDescriptor::NORMAL, VAR,
 | 
| -                DefaultInitializationFlag(VAR), ok, scope);
 | 
| -        DCHECK(*ok);  // Based on the preceding check, this should not fail
 | 
| -        if (!*ok) return;
 | 
| +      if (delegate->to() == nullptr) {
 | 
| +        continue;
 | 
|        }
 | 
| -
 | 
| -      // Read from the local lexical scope and write to the function scope
 | 
| -      VariableProxy* to = scope->NewUnresolved(factory(), name);
 | 
| -      VariableProxy* from = delegate->scope()->NewUnresolved(factory(), name);
 | 
| -      Expression* assignment =
 | 
| -          factory()->NewAssignment(Token::ASSIGN, to, from, kNoSourcePosition);
 | 
| +      Expression* assignment = factory()->NewAssignment(
 | 
| +          Token::ASSIGN, delegate->to(), delegate->from(), kNoSourcePosition);
 | 
|        Statement* statement =
 | 
|            factory()->NewExpressionStatement(assignment, kNoSourcePosition);
 | 
|        delegate->set_statement(statement);
 | 
| 
 |