v8/test/mjsunit/harmony/sloppy-implicit-block-function.js
littledan 0e7f095c6d Restrict FunctionDeclarations in Statement position
ES2015 generally bans FunctionDeclarations in positions which expect a Statement,
as opposed to a StatementListItem, such as a FunctionDeclaration which constitutes
the body of a for loop. However, Annex B 3.2 and 3.4 make exceptions for labeled
function declarations and function declarations as the body of an if statement in
sloppy mode, in the latter case specifying that the semantics are as if the
function declaration occurred in a block. Chrome has historically permitted
further extensions, for the body of any flow control construct.

This patch addresses both the syntactic and semantic mismatches between V8 and
the spec. For the semantic mismatch, function declarations as the body of if
statements change from unconditionally hoisting in certain cases to acquiring
the sloppy mode function in block semantics (based on Annex B 3.3). For the
extra syntax permitted, this patch adds a flag,
--harmony-restrictive-declarations, which excludes disallowed function declaration
cases. A new UseCounter, LegacyFunctionDeclaration, is added to count how often
function declarations occur as the body of other constructs in sloppy mode. With
this patch, the code generally follows the form of the specification with respect
to parsing FunctionDeclarations, rather than allowing them in arbitrary Statement
positions, and makes it more clear where our extensions occur.

BUG=v8:4647
R=adamk
LOG=Y

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

Cr-Commit-Position: refs/heads/master@{#34470}
2016-03-03 21:34:26 +00:00

98 lines
2.1 KiB
JavaScript

// Copyright 2016 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: --no-harmony-restrictive-declarations
// ES#sec-functiondeclarations-in-ifstatement-statement-clauses
// Annex B 3.4 FunctionDeclarations in IfStatement Statement Clauses
// In sloppy mode, function declarations in if statements act like
// they have a block around them. Prohibited in strict mode.
(function() {
assertEquals(undefined, f);
if (false) function f() { };
assertEquals(undefined, f);
})();
(function() {
assertEquals(undefined, f);
if (true) function f() { };
assertEquals('function', typeof f);
})();
(function() {
assertEquals(undefined, f);
if (true) {} else function f() { };
assertEquals(undefined, f);
})();
(function() {
assertEquals(undefined, f);
if (false) {} else function f() { };
assertEquals('function', typeof f);
})();
// For legacy reasons, we also support these types of semantics as
// the body of a for or with statement.
(function() {
for (;false;) function f() { };
assertEquals(undefined, f);
})();
(function() {
for (var x in {}) function f() { };
assertEquals(undefined, f);
})();
(function() {
var x;
for (x in {}) function f() { };
assertEquals(undefined, f);
})();
(function() {
for (var i = 0; i < 1; i++) function f() { };
assertEquals('function', typeof f);
})();
(function() {
for (var x in {a: 1}) function f() { };
assertEquals('function', typeof f);
})();
(function() {
var x;
for (x in {a: 1}) function f() { };
assertEquals('function', typeof f);
})();
(function() {
with ({}) function f() { };
assertEquals('function', typeof f);
})();
(function() {
do function f() {} while (0);
assertEquals('function', typeof f);
})();
// Labeled function declarations undergo the same hoisting/FiB semantics as if
// they were unalbeled.
(function() {
function bar() {
return f;
x: function f() {}
}
assertEquals('function', typeof bar());
})();
(function() {
function bar() {
return f;
{
x: function f() {}
}
}
assertEquals(undefined, bar());
})();