Commit ab3110e8 authored by littledan's avatar littledan Committed by Commit bot

Add a lexical scope for the body of a with statement

For an edge case like the following in sloppy mode
  with ({}) function f() {}
a lexical scope needs to be created around the body in order
to hold the function declaration, so it can be hoisted according
to a loose interpretation of Annex B 3.3 (loose because ES2015
does not permit a function declaration as the body of a with
statement). This patch adds that scope.

BUG=chromium:542100
LOG=N
R=adamk

Review URL: https://codereview.chromium.org/1404803002

Cr-Commit-Position: refs/heads/master@{#31269}
parent d0618585
...@@ -2956,13 +2956,28 @@ Statement* Parser::ParseWithStatement(ZoneList<const AstRawString*>* labels, ...@@ -2956,13 +2956,28 @@ Statement* Parser::ParseWithStatement(ZoneList<const AstRawString*>* labels,
scope_->DeclarationScope()->RecordWithStatement(); scope_->DeclarationScope()->RecordWithStatement();
Scope* with_scope = NewScope(scope_, WITH_SCOPE); Scope* with_scope = NewScope(scope_, WITH_SCOPE);
Statement* stmt; Block* body;
{ BlockState block_state(&scope_, with_scope); { BlockState block_state(&scope_, with_scope);
with_scope->set_start_position(scanner()->peek_location().beg_pos); with_scope->set_start_position(scanner()->peek_location().beg_pos);
stmt = ParseSubStatement(labels, CHECK_OK);
// The body of the with statement must be enclosed in an additional
// lexical scope in case the body is a FunctionDeclaration.
body = factory()->NewBlock(labels, 1, false, RelocInfo::kNoPosition);
Scope* block_scope = NewScope(scope_, BLOCK_SCOPE);
block_scope->set_start_position(scanner()->location().beg_pos);
{
BlockState block_state(&scope_, block_scope);
Target target(&this->target_stack_, body);
Statement* stmt = ParseSubStatement(labels, CHECK_OK);
body->statements()->Add(stmt, zone());
block_scope->set_end_position(scanner()->location().end_pos);
block_scope = block_scope->FinalizeBlockScope();
body->set_scope(block_scope);
}
with_scope->set_end_position(scanner()->location().end_pos); with_scope->set_end_position(scanner()->location().end_pos);
} }
return factory()->NewWithStatement(with_scope, expr, stmt, pos); return factory()->NewWithStatement(with_scope, expr, body, pos);
} }
......
// Copyright 2015 the V8 project authors. All rights reserved.
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
// Flags: --harmony-sloppy --harmony-sloppy-function
(function() {
var x = {a: 1}
assertEquals("undefined", typeof f);
with (x)
function f() { return a; }
assertEquals("function", typeof f);
assertEquals(1, f());
x.a = 2;
assertEquals(2, f());
})();
var y = {b: 1}
assertEquals("undefined", typeof g);
with (y)
function g() { return b; }
assertEquals("function", typeof g);
assertEquals(1, g());
y.b = 2;
assertEquals(2, g());
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment