Index: src/parser.cc |
diff --git a/src/parser.cc b/src/parser.cc |
index 6f51d82e643d3e94625bc0505255f173c05efdac..fb9b3cd422cf7838b91e2893a07065a6f6e4cd20 100644 |
--- a/src/parser.cc |
+++ b/src/parser.cc |
@@ -2259,7 +2259,16 @@ Statement* Parser::ParseFunctionDeclaration( |
factory()->NewFunctionDeclaration(proxy, mode, fun, scope_, pos); |
Declare(declaration, DeclarationDescriptor::NORMAL, true, CHECK_OK); |
if (names) names->Add(name, zone()); |
- return factory()->NewEmptyStatement(RelocInfo::kNoPosition); |
+ EmptyStatement* empty = factory()->NewEmptyStatement(RelocInfo::kNoPosition); |
+ if (is_sloppy(language_mode()) && allow_harmony_sloppy_function() && |
+ !scope_->is_declaration_scope()) { |
+ SloppyBlockFunctionStatement* delegate = |
+ factory()->NewSloppyBlockFunctionStatement(empty, scope_); |
+ scope_->DeclarationScope()->sloppy_block_function_map()->Declare(name, |
+ delegate); |
+ return delegate; |
+ } |
+ return empty; |
} |
@@ -4277,6 +4286,9 @@ FunctionLiteral* Parser::ParseFunctionLiteral( |
CheckStrictOctalLiteral(scope->start_position(), scope->end_position(), |
CHECK_OK); |
} |
+ if (is_sloppy(language_mode) && allow_harmony_sloppy_function()) { |
+ InsertSloppyBlockFunctionVarBindings(scope, CHECK_OK); |
+ } |
if (is_strict(language_mode) || allow_harmony_sloppy()) { |
CheckConflictingVarDeclarations(scope, CHECK_OK); |
} |
@@ -4939,6 +4951,41 @@ void Parser::CheckConflictingVarDeclarations(Scope* scope, bool* ok) { |
} |
+void Parser::InsertSloppyBlockFunctionVarBindings(Scope* scope, bool* ok) { |
+ // For each variable which is used as a function declaration in a sloppy |
+ // block, |
+ DCHECK(scope->is_declaration_scope()); |
+ 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, |
+ Variable* var = scope->LookupLocal(name); |
+ if (var == nullptr || !IsLexicalVariableMode(var->mode())) { |
+ // Declare a var-style binding for the function in the outer scope |
+ VariableProxy* proxy = scope->NewUnresolved(factory(), name); |
+ Declaration* declaration = factory()->NewVariableDeclaration( |
+ proxy, VAR, scope, RelocInfo::kNoPosition); |
+ Declare(declaration, DeclarationDescriptor::NORMAL, true, ok, scope); |
+ DCHECK(ok); // Based on the preceding check, this should not fail |
+ if (!ok) return; |
+ |
+ // Write in assignments to var for each block-scoped function declaration |
+ auto delegates = static_cast<SloppyBlockFunctionMap::Vector*>(p->value); |
+ for (SloppyBlockFunctionStatement* delegate : *delegates) { |
+ // 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, RelocInfo::kNoPosition); |
+ Statement* statement = factory()->NewExpressionStatement( |
+ assignment, RelocInfo::kNoPosition); |
+ delegate->set_statement(statement); |
+ } |
+ } |
+ } |
+} |
+ |
+ |
// ---------------------------------------------------------------------------- |
// Parser support |