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

Ship ES2015 sloppy-mode function hoisting, let, class

This patch doesn't ship all features of ES2015 variable/scoping
changes, notably omitting the removal of legacy const. I think
function hoisting, let and class in sloppy mode can stand to
themselves as a package, and the legacy const change is much
riskier and more likely to be reverted, so my intention is to
pursue those as a separate, follow-on patch.

R=adamk@chromium.org
BUG=v8:4285,v8:3305
LOG=Y
CQ_INCLUDE_TRYBOTS=tryserver.chromium.linux:linux_chromium_rel_ng;tryserver.blink:linux_blink_rel

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

Cr-Commit-Position: refs/heads/master@{#33133}
parent e27a3713
...@@ -212,9 +212,6 @@ DEFINE_IMPLICATION(es_staging, move_object_start) ...@@ -212,9 +212,6 @@ DEFINE_IMPLICATION(es_staging, move_object_start)
#define HARMONY_STAGED(V) \ #define HARMONY_STAGED(V) \
V(harmony_proxies, "harmony proxies") \ V(harmony_proxies, "harmony proxies") \
V(harmony_reflect, "harmony Reflect API") \ V(harmony_reflect, "harmony Reflect API") \
V(harmony_sloppy, "harmony features in sloppy mode") \
V(harmony_sloppy_let, "harmony let in sloppy mode") \
V(harmony_sloppy_function, "harmony sloppy function block scoping") \
V(harmony_regexp_lookbehind, "harmony regexp lookbehind") V(harmony_regexp_lookbehind, "harmony regexp lookbehind")
// Features that are shipping (turned on by default, but internal flag remains). // Features that are shipping (turned on by default, but internal flag remains).
...@@ -227,7 +224,10 @@ DEFINE_IMPLICATION(es_staging, move_object_start) ...@@ -227,7 +224,10 @@ DEFINE_IMPLICATION(es_staging, move_object_start)
V(harmony_tolength, "harmony ToLength") \ V(harmony_tolength, "harmony ToLength") \
V(harmony_tostring, "harmony toString") \ V(harmony_tostring, "harmony toString") \
V(harmony_completion, "harmony completion value semantics") \ V(harmony_completion, "harmony completion value semantics") \
V(harmony_regexps, "harmony regular expression extensions") V(harmony_regexps, "harmony regular expression extensions") \
V(harmony_sloppy, "harmony features in sloppy mode") \
V(harmony_sloppy_let, "harmony let in sloppy mode") \
V(harmony_sloppy_function, "harmony sloppy function block scoping")
// Once a shipping feature has proved stable in the wild, it will be dropped // Once a shipping feature has proved stable in the wild, it will be dropped
......
...@@ -2,6 +2,7 @@ ...@@ -2,6 +2,7 @@
// Use of this source code is governed by a BSD-style license that can be // Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file. // found in the LICENSE file.
// //
// Flags: --no-legacy-const // Flags: --no-legacy-const --no-harmony-sloppy --no-harmony-sloppy-let
// Flags: --no-harmony-sloppy-function
const = 42; const = 42;
*%(basename)s:7: SyntaxError: Unexpected token const *%(basename)s:8: SyntaxError: Unexpected token const
const = 42; const = 42;
^^^^^ ^^^^^
......
...@@ -2,6 +2,7 @@ ...@@ -2,6 +2,7 @@
// Use of this source code is governed by a BSD-style license that can be // Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file. // found in the LICENSE file.
// //
// Flags: --no-legacy-const // Flags: --no-legacy-const --no-harmony-sloppy --no-harmony-sloppy-let
// Flags: --no-harmony-sloppy-function
const const
*%(basename)s:7: SyntaxError: Unexpected token const *%(basename)s:8: SyntaxError: Unexpected token const
const const
^^^^^ ^^^^^
......
...@@ -2,6 +2,7 @@ ...@@ -2,6 +2,7 @@
// Use of this source code is governed by a BSD-style license that can be // Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file. // found in the LICENSE file.
// //
// Flags: --no-legacy-const // Flags: --no-legacy-const --no-harmony-sloppy --no-harmony-sloppy-let
// Flags: --no-harmony-sloppy-function
const x = 42; const x = 42;
*%(basename)s:7: SyntaxError: Unexpected token const *%(basename)s:8: SyntaxError: Unexpected token const
const x = 42; const x = 42;
^^^^^ ^^^^^
......
...@@ -25,6 +25,8 @@ ...@@ -25,6 +25,8 @@
// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE // (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. // OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
// Flags: --no-harmony-sloppy-let
function CheckException(e) { function CheckException(e) {
var string = e.toString(); var string = e.toString();
assertInstanceof(e, SyntaxError); assertInstanceof(e, SyntaxError);
......
...@@ -2,6 +2,9 @@ ...@@ -2,6 +2,9 @@
// Use of this source code is governed by a BSD-style license that can be // Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file. // found in the LICENSE file.
// Flags: --no-harmony-sloppy-let --no-harmony-sloppy-function
// Flags: --no-harmony-sloppy
function CheckError(source) { function CheckError(source) {
var exception = null; var exception = null;
try { try {
......
...@@ -991,8 +991,9 @@ ...@@ -991,8 +991,9 @@
function f20({x}) { function x() { return 2 }; return x(); } function f20({x}) { function x() { return 2 }; return x(); }
assertEquals(2, f20({x: 1})); assertEquals(2, f20({x: 1}));
// Function hoisting is blocked by the conflicting x declaration
function f21({x}) { { function x() { return 2 } } return x(); } function f21({x}) { { function x() { return 2 } } return x(); }
assertEquals(2, f21({x: 1})); assertThrows(() => f21({x: 1}), TypeError);
var g1 = ({x}) => { var x = 2; return x }; var g1 = ({x}) => { var x = 2; return x };
assertEquals(2, g1({x: 1})); assertEquals(2, g1({x: 1}));
...@@ -1025,7 +1026,7 @@ ...@@ -1025,7 +1026,7 @@
var g20 = ({x}) => { function x() { return 2 }; return x(); } var g20 = ({x}) => { function x() { return 2 }; return x(); }
assertEquals(2, g20({x: 1})); assertEquals(2, g20({x: 1}));
var g21 = ({x}) => { { function x() { return 2 } } return x(); } var g21 = ({x}) => { { function x() { return 2 } } return x(); }
assertEquals(2, g21({x: 1})); assertThrows(() => g21({x: 1}), TypeError);
assertThrows("'use strict'; function f(x) { let x = 0; }; f({});", SyntaxError); assertThrows("'use strict'; function f(x) { let x = 0; }; f({});", SyntaxError);
assertThrows("'use strict'; function f({x}) { let x = 0; }; f({});", SyntaxError); assertThrows("'use strict'; function f({x}) { let x = 0; }; f({});", SyntaxError);
......
...@@ -1081,6 +1081,10 @@ ...@@ -1081,6 +1081,10 @@
'with-prototype': [SKIP], 'with-prototype': [SKIP],
'with-readonly': [SKIP], 'with-readonly': [SKIP],
'with-value': [SKIP], 'with-value': [SKIP],
'regress/regress-builtinbust-7': [SKIP],
'regress/regress-crbug-451770': [SKIP],
'regress/regress-crbug-503968': [SKIP],
'regress/regress-crbug-504729': [SKIP],
}], # ignition == True }], # ignition == True
['ignition == True and (arch == arm or arch == arm64)', { ['ignition == True and (arch == arm or arch == arm64)', {
......
...@@ -25,24 +25,26 @@ ...@@ -25,24 +25,26 @@
// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE // (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. // OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
// We intend that the function declaration for g inside catch is hoisted to // With ES2015 function hoisting semantics, functions are only "hoisted" out
// function f's scope. Invoke it before try/catch, in the try block, in the // of blocks by writing their values into var-scoped declarations. Therefore,
// catch block, after try/catch, and outside f, and verify that it has // they access the catch binding when it syntactically appears so.
// access to the proper binding of x. // This is a potentially breaking change vs the old semantics, which would
// return 'function' from g() everywhere.
var x = 'global'; var x = 'global';
function f() { function f() {
var x = 'function'; var x = 'function';
assertEquals('function', g()); assertEquals(undefined, g);
try { try {
assertEquals('function', g()); assertEquals(undefined, g);
throw 'catch'; throw 'catch';
} catch (x) { } catch (x) {
function g() { return x; } function g() { return x; }
assertEquals('function', g()); assertEquals('catch', g());
} }
assertEquals('function', g()); assertEquals('catch', g());
return g; return g;
} }
assertEquals('function', f()()); assertEquals('catch', f()());
...@@ -17,7 +17,7 @@ function listener(event, exec_state, event_data, data) { ...@@ -17,7 +17,7 @@ function listener(event, exec_state, event_data, data) {
exec_state.frame(0).evaluate("write_0('foo')"); exec_state.frame(0).evaluate("write_0('foo')");
exec_state.frame(0).evaluate("write_1('modified')"); exec_state.frame(0).evaluate("write_1('modified')");
} else { } else {
assertEquals("foo", exec_state.frame(0).evaluate("e").value()); assertEquals("argument", exec_state.frame(0).evaluate("e").value());
exec_state.frame(0).evaluate("write_2('bar')"); exec_state.frame(0).evaluate("write_2('bar')");
} }
step++; step++;
...@@ -33,12 +33,14 @@ function f(e, x) { ...@@ -33,12 +33,14 @@ function f(e, x) {
try { try {
throw "error"; throw "error";
} catch(e) { } catch(e) {
// 'e' and 'x' bind to the argument due to hoisting // In ES2015 hoisting semantics, 'x' binds to the argument
// and 'e' binds to the exception.
function write_0(v) { e = v } function write_0(v) { e = v }
function write_1(v) { x = v } function write_1(v) { x = v }
debugger; debugger;
assertEquals("error", e); assertEquals("foo", e); // overwritten by the debugger
} }
assertEquals("argument", e); // debugger did not overwrite
function write_2(v) { e = v } function write_2(v) { e = v }
debugger; debugger;
assertEquals("bar", e); assertEquals("bar", e);
......
...@@ -606,16 +606,6 @@ ...@@ -606,16 +606,6 @@
'js1_5/Regress/regress-290575': [PASS, FAIL_OK], 'js1_5/Regress/regress-290575': [PASS, FAIL_OK],
# Fails because of the way function declarations are
# handled in V8/JSC. V8 follows IE behavior and introduce
# all nested function declarations when entering the
# surrounding function, whereas Spidermonkey declares
# them dynamically when the statement is executed.
'ecma_3/Function/scope-001': [FAIL_OK],
'ecma_3/FunExpr/fe-001': [FAIL_OK],
'js1_5/Scope/regress-184107': [FAIL_OK],
# Function is deletable in V8 and JSC. # Function is deletable in V8 and JSC.
'js1_5/Regress/regress-352604': [FAIL_OK], 'js1_5/Regress/regress-352604': [FAIL_OK],
...@@ -673,6 +663,9 @@ ...@@ -673,6 +663,9 @@
# We do not correctly handle assignments within "with" # We do not correctly handle assignments within "with"
'ecma_3/Statements/12.10-01': [FAIL], 'ecma_3/Statements/12.10-01': [FAIL],
# https://bugs.chromium.org/p/v8/issues/detail?id=4647
'ecma_3/FunExpr/fe-001': [FAIL_OK],
##################### MOZILLA EXTENSION TESTS ##################### ##################### MOZILLA EXTENSION TESTS #####################
'ecma/extensions/15.1.2.1-1': [FAIL_OK], 'ecma/extensions/15.1.2.1-1': [FAIL_OK],
......
...@@ -21,21 +21,24 @@ ...@@ -21,21 +21,24 @@
# (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS # (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
# SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. # SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
# Due to changes in ES2015 function hoisting semantics, this test is
# no longer really accurate and is expected to fail. test262 and mjsunit
# tests verify the correct semantics.
KDE JS Test KDE JS Test
On success, you will see a series of "PASS" messages, followed by "TEST COMPLETE". On success, you will see a series of "PASS" messages, followed by "TEST COMPLETE".
PASS Function declaration takes effect at entry FAIL Function declaration takes effect at entry: value has type undefined , not:function
PASS Decl not yet overwritten PASS Decl not yet overwritten
PASS After assign (0) PASS After assign (0)
PASS function decls have no execution content PASS function decls have no execution content
PASS After assign #2 (0) PASS After assign #2 (0)
PASS Decl already overwritten FAIL Decl already overwritten: value has type function , not:number
PASS After assign (1) PASS After assign (1)
PASS function decls have no execution content PASS function decls have no execution content
PASS After assign #2 (1) PASS After assign #2 (1)
PASS Decl already overwritten FAIL Decl already overwritten: value has type function , not:number
PASS After assign (2) PASS After assign (2)
PASS function decls have no execution content PASS function decls have no execution content
PASS After assign #2 (2) PASS After assign #2 (2)
......
...@@ -35,6 +35,9 @@ ...@@ -35,6 +35,9 @@
'dfg-inline-arguments-reset-changetype': [PASS, FAIL], 'dfg-inline-arguments-reset-changetype': [PASS, FAIL],
# TODO(turbofan): We run out of stack earlier on 64-bit for now. # TODO(turbofan): We run out of stack earlier on 64-bit for now.
'fast/js/deep-recursion-test': [PASS, NO_VARIANTS], 'fast/js/deep-recursion-test': [PASS, NO_VARIANTS],
# This test leads to a SyntaxError from conflicting let declarations
# in ES2015
'function-declarations-in-switch-statement': [FAIL],
}], # ALWAYS }], # ALWAYS
['mode == debug', { ['mode == debug', {
# Too slow in debug mode. # Too slow in debug mode.
......
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