Ship ES2015 sloppy-mode const semantics

This patch moves the semantics of 'const' in sloppy mode to match those
in strict mode, that is, const makes lexical (let-like) bindings, must
have an initializer, and does not create properties of the global object.

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

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

Cr-Commit-Position: refs/heads/master@{#33218}
This commit is contained in:
littledan 2016-01-11 15:09:27 -08:00 committed by Commit bot
parent ee9d7acafc
commit 95145fa826
41 changed files with 90 additions and 35 deletions

View File

@ -185,9 +185,9 @@ DEFINE_BOOL(harmony, false, "enable all completed harmony features")
DEFINE_BOOL(harmony_shipping, true, "enable all shipped harmony features")
DEFINE_IMPLICATION(es_staging, harmony)
DEFINE_BOOL(legacy_const, true, "legacy semantics for const in sloppy mode")
// ES2015 const semantics are staged
DEFINE_NEG_IMPLICATION(harmony, legacy_const)
DEFINE_BOOL(legacy_const, false, "legacy semantics for const in sloppy mode")
// ES2015 const semantics are shipped
DEFINE_NEG_VALUE_IMPLICATION(harmony_shipping, legacy_const, true)
DEFINE_BOOL(promise_extra, true, "additional V8 Promise functions")
// Removing extra Promise functions is staged

View File

@ -395,6 +395,7 @@ TEST(GlobalLoad) {
TEST(GlobalStoreSloppy) {
FLAG_legacy_const = true;
FunctionTester T("(function(a,b) { g = a + b; return g; })");
T.CheckCall(T.Val(33), T.Val(22), T.Val(11));

View File

@ -48,6 +48,7 @@ static const char* bind_tests[] = {
static void RunVariableTests(const char* source, const char* tests[]) {
i::FLAG_legacy_const = true;
EmbeddedVector<char, 512> buffer;
for (int i = 0; tests[i] != NULL; i += 3) {

View File

@ -29,6 +29,7 @@ class BytecodeGeneratorHelper {
i::FLAG_ignition_filter = StrDup(kFunctionName);
i::FLAG_always_opt = false;
i::FLAG_allow_natives_syntax = true;
i::FLAG_legacy_const = true;
CcTest::i_isolate()->interpreter()->Initialize();
}

View File

@ -227,6 +227,7 @@ v8::Local<Integer> DeclarationContext::Query(Local<Name> key) {
// Test global declaration of a property the interceptor doesn't know
// about and doesn't handle.
TEST(Unknown) {
i::FLAG_legacy_const = true;
HandleScope scope(CcTest::isolate());
v8::V8::Initialize();
@ -276,6 +277,7 @@ class AbsentPropertyContext: public DeclarationContext {
TEST(Absent) {
i::FLAG_legacy_const = true;
v8::Isolate* isolate = CcTest::isolate();
v8::V8::Initialize();
HandleScope scope(isolate);
@ -359,6 +361,7 @@ class AppearingPropertyContext: public DeclarationContext {
TEST(Appearing) {
i::FLAG_legacy_const = true;
v8::V8::Initialize();
HandleScope scope(CcTest::isolate());
@ -415,6 +418,7 @@ class ExistsInPrototypeContext: public DeclarationContext {
TEST(ExistsInPrototype) {
i::FLAG_legacy_const = true;
HandleScope scope(CcTest::isolate());
// Sanity check to make sure that the holder of the interceptor
@ -524,6 +528,7 @@ class ExistsInHiddenPrototypeContext: public DeclarationContext {
TEST(ExistsInHiddenPrototype) {
i::FLAG_legacy_const = true;
HandleScope scope(CcTest::isolate());
{ ExistsInHiddenPrototypeContext context;
@ -607,6 +612,7 @@ class SimpleContext {
TEST(CrossScriptReferences) {
i::FLAG_legacy_const = true;
v8::Isolate* isolate = CcTest::isolate();
HandleScope scope(isolate);

View File

@ -3571,6 +3571,7 @@ TEST(UseAsmUseCount) {
TEST(UseConstLegacyCount) {
i::FLAG_legacy_const = true;
i::Isolate* isolate = CcTest::i_isolate();
i::HandleScope scope(isolate);
LocalContext env;
@ -6425,6 +6426,7 @@ TEST(ArrowFunctionASIErrors) {
TEST(StrongModeFreeVariablesDeclaredByPreviousScript) {
i::FLAG_strong_mode = true;
i::FLAG_legacy_const = true;
v8::V8::Initialize();
v8::HandleScope scope(CcTest::isolate());
v8::Context::Scope context_scope(v8::Context::New(CcTest::isolate()));

View File

@ -26,7 +26,7 @@
// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
// Flags: --allow-natives-syntax
// Flags: --allow-natives-syntax --legacy-const
// Test correct handling of uninitialized const.

View File

@ -25,7 +25,7 @@
// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
// Flags: --allow-natives-syntax
// Flags: --allow-natives-syntax --legacy-const
// Test const initialization and assignments.
function f() {

View File

@ -25,6 +25,8 @@
// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
// Flags: --legacy-const
// Test handling of const variables in various settings.
(function () {

View File

@ -25,7 +25,7 @@
// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
// Flags: --allow-natives-syntax
// Flags: --allow-natives-syntax --legacy-const
// Test the handling of initialization of deleted const variables.
// This only makes sense in local scopes since the declaration and

View File

@ -25,6 +25,8 @@
// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
// Flags: --legacy-const
// Test for const semantics.

View File

@ -25,6 +25,8 @@
// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
// Flags: --legacy-const
// Test const properties and pre/postfix operation.
function f() {
const x = 1;

View File

@ -29,6 +29,8 @@
// The code generator now handles compile-time constants specially.
// Test the code generated when operands are known at compile time
// Flags: --legacy-const
// Test count operations involving constants
function test_count() {
var x = "foo";

View File

@ -25,7 +25,7 @@
// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
// Flags: --expose-debug-as debug --debug-eval-readonly-locals
// Flags: --expose-debug-as debug --debug-eval-readonly-locals --legacy-const
Debug = debug.Debug

View File

@ -33,7 +33,7 @@
// This exercises the code in runtime.cc in
// DeclareGlobal...Locally().
// Flags: --es52-globals
// Flags: --legacy-const
this.__proto__.foo = 42;
this.__proto__.bar = 87;

View File

@ -3,8 +3,10 @@
// found in the LICENSE file.
// Flags: --harmony-sloppy --harmony-sloppy-let --harmony-sloppy-function
// Flags: --legacy-const
// Var-let conflict in a function throws, even if the var is in an eval
// Legacy-const-let conflict in a function throws, even if the legacy const
// is in an eval
// Throws at the top level of a function
assertThrows(function() {
@ -56,7 +58,7 @@ try {
}
assertFalse(caught);
// var across with doesn't conflict
// legacy const across with doesn't conflict
caught = false;
try {
(function() {
@ -69,7 +71,7 @@ try {
}
assertFalse(caught);
// var can still conflict with let across a with
// legacy const can still conflict with let across a with
caught = false;
try {
(function() {

View File

@ -3,6 +3,7 @@
// found in the LICENSE file.
// Flags: --harmony-sloppy --harmony-sloppy-let --harmony-destructuring-bind
// Flags: --legacy-const
// let is usable as a variable with var or legacy const, not let or ES6 const

View File

@ -28,6 +28,8 @@
// Check that dynamically introducing conflicting consts/vars
// is silently ignored (and does not lead to exceptions).
// Flags: --legacy-const
var caught = 0;
eval("const a");

View File

@ -26,7 +26,7 @@
// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
// Flags: --nodead-code-elimination --concurrent-recompilation
// Flags: --allow-natives-syntax
// Flags: --allow-natives-syntax --legacy-const
if (!%IsConcurrentRecompilationSupported()) {
print("Concurrent recompilation is disabled. Skipping this test.");

View File

@ -25,6 +25,8 @@
// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
// Flags: --legacy-const
// Tests loading of properties across eval calls.
var x = 1;

View File

@ -25,6 +25,8 @@
// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
// Flags: --legacy-const
// Regression test cases for issue 1178598.
// Make sure const-initialization doesn't conflict

View File

@ -25,6 +25,8 @@
// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
// Flags: --legacy-const
var caught = false;
try {
(function () {

View File

@ -25,7 +25,7 @@
// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
// Flags: --allow-natives-syntax --es52-globals
// Flags: --allow-natives-syntax --legacy-const
// Make sure that we can introduce global variables (using
// both var and const) that shadow even READ_ONLY variables

View File

@ -25,6 +25,8 @@
// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
// Flags: --legacy-const
// Make sure this doesn't fail with an assertion
// failure during lazy compilation.

View File

@ -25,6 +25,8 @@
// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
// Flags: --legacy-const
try {
const x=n,Glo0al;
} catch(e){}

View File

@ -28,6 +28,8 @@
// Make sure that a const definition does not try
// to pass 'the hole' to a defined setter.
// Flags: --legacy-const
this.__defineSetter__('x', function(value) { assertTrue(value === 1); });
var caught = false;

View File

@ -25,6 +25,8 @@
// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
// Flags: --legacy-const
// Make sure that eval can introduce a local variable called __proto__.
// See http://code.google.com/p/v8/issues/detail?id=186

View File

@ -2,6 +2,8 @@
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
// Flags: --legacy-const
(function f(){
assertEquals("function", typeof f);
})();

View File

@ -2,7 +2,7 @@
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
// Flags: --allow-natives-syntax
// Flags: --allow-natives-syntax --legacy-const
function f(x) {
const x = 0;

View File

@ -27,6 +27,8 @@
// Regression test for http://code.google.com/p/v8/issues/detail?id=641.
// Flags: --legacy-const
function f(){
while (window + 1) {
const window=[,];

View File

@ -25,6 +25,8 @@
// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
// Flags: --legacy-const
// const variables should be read-only
const c = 42;
c = 87;

View File

@ -25,6 +25,8 @@
// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
// Flags: --legacy-const
// Regression test for a crash. A data property in the global object's
// prototype shadowed by a setter in the global object's prototype's
// prototype would crash or assert when seen by Runtime_DeclareContextSlot.

View File

@ -2,7 +2,7 @@
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
// Flags: --expose-debug-as debug
// Flags: --expose-debug-as debug --legacy-const
function f(x) {
// This function compiles into code that only throws a redeclaration

View File

@ -2,7 +2,7 @@
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
// Flags: --always-opt
// Flags: --always-opt --legacy-const
var x = 0;

View File

@ -98,6 +98,17 @@
# (https://bugzilla.mozilla.org/show_bug.cgi?id=1220457)
'js1_5/Regress/regress-418504': [FAIL],
# ES2015 const redefinition throws, initializers are required, and no
# global object properties are made, unlike Mozilla legacy const
'js1_5/Regress/regress-103602': [FAIL],
'js1_5/Regress/regress-321874': [FAIL],
'js1_5/Regress/regress-383674': [FAIL],
'js1_5/extensions/regress-452565': [FAIL],
'js1_5/extensions/scope-001': [FAIL],
# To add insult to injury, these tests time out in debug mode
'js1_5/Regress/regress-360969-03': [FAIL, ['mode == debug', TIMEOUT, NO_VARIANTS]],
'js1_5/Regress/regress-360969-04': [FAIL, ['mode == debug', TIMEOUT, NO_VARIANTS]],
##################### SKIPPED TESTS #####################
# This test checks that we behave properly in an out-of-memory
@ -161,8 +172,6 @@
##################### FLAKY TESTS #####################
# These tests time out in debug mode but pass in product mode
'js1_5/Regress/regress-360969-03': [PASS, ['mode == debug', TIMEOUT, NO_VARIANTS]],
'js1_5/Regress/regress-360969-04': [PASS, ['mode == debug', TIMEOUT, NO_VARIANTS]],
'js1_5/Regress/regress-360969-05': [PASS, ['mode == debug', TIMEOUT, NO_VARIANTS]],
'js1_5/Regress/regress-360969-06': [PASS, ['mode == debug', TIMEOUT, NO_VARIANTS]],
'js1_5/extensions/regress-365527': [PASS, SLOW, ['mode == debug', TIMEOUT, NO_VARIANTS]],

View File

@ -62,10 +62,6 @@
# https://code.google.com/p/v8/issues/detail?id=4405
'language/block-scope/leave/outermost-binding-updated-in-catch-block-nested-block-let-declaration-unseen-outside-of-block': [PASS, FAIL],
# https://code.google.com/p/v8/issues/detail?id=3305
# This times out in sloppy mode because sloppy const assignment does not throw.
'language/statements/const/syntax/const-invalid-assignment-next-expression-for': [SKIP],
# It's unclear what the right behavior for [[Enumerate]] is; we're awaiting
# clarification in the spec. Currently, our for-in implementation for
# Proxies checks all trap result values for being strings...

View File

@ -21,6 +21,8 @@
// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
// SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
// Flags: --legacy-const
description(
'Tests that declaring a const variable without initializing has the correct behavior and does not crash'
);

View File

@ -21,6 +21,8 @@
// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
// SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
// Flags: --legacy-const
description(
"This test checks exceptional cases for constant counting in the parser."
);

View File

@ -157,7 +157,7 @@ PASS access_after_delete_extra_5(1, 2, 3, 4, 5) is 5
PASS argumentsParam(true) is true
PASS argumentsFunctionConstructorParam(true) is true
PASS argumentsVarUndefined() is '[object Arguments]'
FAIL argumentsConstUndefined() should be [object Arguments]. Threw exception SyntaxError: Identifier 'arguments' has already been declared
FAIL argumentsConstUndefined() should be [object Arguments]. Threw exception SyntaxError: Missing initializer in const declaration
PASS argumentCalleeInException() is argumentCalleeInException
PASS shadowedArgumentsApply([true]) is true
PASS shadowedArgumentsLength([]) is 0

View File

@ -512,8 +512,8 @@ PASS compileAndSerializeLeftmostTest('var a, b, c') is 'var a, b, c'
PASS compileAndSerializeLeftmostTest('var a = 1, b = 2, c = 3') is 'var a = 1, b = 2, c = 3'
PASS compileAndSerializeLeftmostTest('const a = 1') is 'const a = 1'
PASS compileAndSerializeLeftmostTest('const a = (1, 2)') is 'const a = (1, 2)'
PASS compileAndSerializeLeftmostTest('const a, b = 1') is 'const a, b = 1'
PASS compileAndSerializeLeftmostTest('const a = 1, b') is 'const a = 1, b'
FAIL compileAndSerializeLeftmostTest('const a, b = 1') should be const a, b = 1. Threw exception SyntaxError: Missing initializer in const declaration
FAIL compileAndSerializeLeftmostTest('const a = 1, b') should be const a = 1, b. Threw exception SyntaxError: Missing initializer in const declaration
PASS compileAndSerializeLeftmostTest('const a = 1, b = 1') is 'const a = 1, b = 1'
PASS compileAndSerializeLeftmostTest('const a = (1, 2), b = 1') is 'const a = (1, 2), b = 1'
PASS compileAndSerializeLeftmostTest('const a = 1, b = (1, 2)') is 'const a = 1, b = (1, 2)'

View File

@ -325,16 +325,16 @@ PASS Invalid: "function f() { throw }"
var and const statements
PASS Valid: "var a, b = null"
PASS Valid: "function f() { var a, b = null }"
PASS Valid: "const a = 5, b, c"
PASS Valid: "function f() { const a = 5, b, c }"
FAIL Valid: "const a = 5, b, c" should NOT throw
FAIL Valid: "function f() { const a = 5, b, c }" should NOT throw
PASS Invalid: "var"
PASS Invalid: "function f() { var }"
PASS Invalid: "var = 7"
PASS Invalid: "function f() { var = 7 }"
PASS Invalid: "var c (6)"
PASS Invalid: "function f() { var c (6) }"
PASS Valid: "if (a) var a,b; else const b, c"
PASS Valid: "function f() { if (a) var a,b; else const b, c }"
FAIL Valid: "if (a) var a,b; else const b, c" should NOT throw
FAIL Valid: "function f() { if (a) var a,b; else const b, c }" should NOT throw
PASS Invalid: "var 5 = 6"
PASS Invalid: "function f() { var 5 = 6 }"
PASS Valid: "while (0) var a, b, c=6, d, e, f=5*6, g=f*h, h"
@ -343,8 +343,8 @@ PASS Invalid: "var a = if (b) { c }"
PASS Invalid: "function f() { var a = if (b) { c } }"
PASS Invalid: "var a = var b"
PASS Invalid: "function f() { var a = var b }"
PASS Valid: "const a = b += c, a, a, a = (b - f())"
PASS Valid: "function f() { const a = b += c, a, a, a = (b - f()) }"
FAIL Valid: "const a = b += c, a, a, a = (b - f())" should NOT throw
FAIL Valid: "function f() { const a = b += c, a, a, a = (b - f()) }" should NOT throw
PASS Invalid: "var a %= b | 5"
PASS Invalid: "function f() { var a %= b | 5 }"
PASS Invalid: "var (a) = 5"
@ -357,8 +357,8 @@ PASS Invalid: "var var = 3"
PASS Invalid: "function f() { var var = 3 }"
PASS Valid: "var varr = 3 in 1"
PASS Valid: "function f() { var varr = 3 in 1 }"
PASS Valid: "const a, a, a = void 7 - typeof 8, a = 8"
PASS Valid: "function f() { const a, a, a = void 7 - typeof 8, a = 8 }"
FAIL Valid: "const a, a, a = void 7 - typeof 8, a = 8" should NOT throw
FAIL Valid: "function f() { const a, a, a = void 7 - typeof 8, a = 8 }" should NOT throw
PASS Valid: "const x_x = 6 /= 7 ? e : f"
PASS Valid: "function f() { const x_x = 6 /= 7 ? e : f }"
PASS Invalid: "var a = ?"
@ -412,8 +412,8 @@ PASS Valid: "for (var a = b, c, d ; ; 1 in a()) break"
PASS Valid: "function f() { for (var a = b, c, d ; ; 1 in a()) break }"
PASS Invalid: "for ( ; var a ; ) break"
PASS Invalid: "function f() { for ( ; var a ; ) break }"
FAIL Invalid: "for (const a; ; ) break" should throw undefined
FAIL Invalid: "function f() { for (const a; ; ) break }" should throw undefined
PASS Invalid: "for (const a; ; ) break"
PASS Invalid: "function f() { for (const a; ; ) break }"
PASS Invalid: "for ( %a ; ; ) { }"
PASS Invalid: "function f() { for ( %a ; ; ) { } }"
PASS Valid: "for (a in b) break"