Merge V8 5.2.361.47 DO NOT MERGE
https://chromium.googlesource.com/v8/v8/+/5.2.361.47
FPIIM-449
Change-Id: Ibec421b85a9b88cb3a432ada642e469fe7e78346
(cherry picked from commit bcf72ee8e3b26f1d0726869c7ddb3921c68b09a8)
diff --git a/test/mjsunit/es6/array-concat.js b/test/mjsunit/es6/array-concat.js
index fe320d6..00edfd6 100644
--- a/test/mjsunit/es6/array-concat.js
+++ b/test/mjsunit/es6/array-concat.js
@@ -1,7 +1,6 @@
// Copyright 2014 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.
-
(function testArrayConcatArity() {
"use strict";
assertEquals(1, Array.prototype.concat.length);
@@ -20,6 +19,15 @@
assertEquals(false, desc.enumerable);
})();
+(function testNonConcatSpreadableArray() {
+ "use strict"
+ var array = [1, 2, 3];
+ assertEquals(array, [].concat(array));
+ assertEquals(array, array.concat([]));
+ array[Symbol.isConcatSpreadable] = false;
+ assertEquals([[1,2,3]], [].concat(array));
+ assertEquals([[1,2,3]], array.concat([]));
+})();
(function testConcatArrayLike() {
"use strict";
diff --git a/test/mjsunit/es6/array-species-neg-zero.js b/test/mjsunit/es6/array-species-neg-zero.js
new file mode 100644
index 0000000..d60b8ba
--- /dev/null
+++ b/test/mjsunit/es6/array-species-neg-zero.js
@@ -0,0 +1,23 @@
+// 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.
+
+/**
+ * 9.4.2.3 ArraySpeciesCreate(originalArray, length)
+ *
+ * 1. Assert: length is an integer Number ≥ 0.
+ * 2. If length is −0, let length be +0.
+ * [...]
+ */
+
+var x = [];
+var deleteCount;
+
+x.constructor = function() {};
+x.constructor[Symbol.species] = function(param) {
+ deleteCount = param;
+};
+
+x.splice(0, -0);
+
+assertEquals(0, deleteCount);
diff --git a/test/mjsunit/es6/block-conflicts-sloppy.js b/test/mjsunit/es6/block-conflicts-sloppy.js
new file mode 100644
index 0000000..866abee
--- /dev/null
+++ b/test/mjsunit/es6/block-conflicts-sloppy.js
@@ -0,0 +1,177 @@
+// Copyright 2011 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.
+
+// Test for conflicting variable bindings.
+
+function CheckException(e) {
+ var string = e.toString();
+ assertTrue(string.indexOf("has already been declared") >= 0 ||
+ string.indexOf("redeclaration") >= 0);
+ return 'Conflict';
+}
+
+
+function TestGlobal(s,e) {
+ try {
+ return eval(s + e);
+ } catch (x) {
+ return CheckException(x);
+ }
+}
+
+
+function TestFunction(s,e) {
+ try {
+ return eval("(function(){" + s + " return " + e + "})")();
+ } catch (x) {
+ return CheckException(x);
+ }
+}
+
+
+function TestBlock(s,e) {
+ try {
+ return eval("(function(){ {" + s + "} return " + e + "})")();
+ } catch (x) {
+ return CheckException(x);
+ }
+}
+
+function TestAll(expected,s,opt_e) {
+ var e = "";
+ var msg = s;
+ if (opt_e) { e = opt_e; msg += opt_e; }
+ // TODO(littledan): Add tests using Realm.eval to ensure that global eval
+ // works as expected.
+ assertEquals(expected === 'LocalConflict' ? 'NoConflict' : expected,
+ TestGlobal(s,e), "global:'" + msg + "'");
+ assertEquals(expected === 'LocalConflict' ? 'NoConflict' : expected,
+ TestFunction(s,e), "function:'" + msg + "'");
+ assertEquals(expected === 'LocalConflict' ? 'Conflict' : expected,
+ TestBlock(s,e), "block:'" + msg + "'");
+}
+
+
+function TestConflict(s) {
+ TestAll('Conflict', s);
+ TestAll('Conflict', 'eval("' + s + '");');
+}
+
+function TestNoConflict(s) {
+ TestAll('NoConflict', s, "'NoConflict'");
+ TestAll('NoConflict', 'eval("' + s + '");', "'NoConflict'");
+}
+
+function TestLocalConflict(s) {
+ TestAll('LocalConflict', s, "'NoConflict'");
+ TestAll('NoConflict', 'eval("' + s + '");', "'NoConflict'");
+}
+
+var letbinds = [ "let x;",
+ "let x = 0;",
+ "let x = undefined;",
+ "let x = function() {};",
+ "let x, y;",
+ "let y, x;",
+ "const x = 0;",
+ "const x = undefined;",
+ "const x = function() {};",
+ "const x = 2, y = 3;",
+ "const y = 4, x = 5;",
+ "class x { }",
+ ];
+function forCompatible(bind) {
+ return !bind.startsWith('class');
+}
+var varbinds = [ "var x;",
+ "var x = 0;",
+ "var x = undefined;",
+ "var x = function() {};",
+ "var x, y;",
+ "var y, x;",
+ ];
+var funbind = "function x() {}";
+
+for (var l = 0; l < letbinds.length; ++l) {
+ // Test conflicting let/var bindings.
+ for (var v = 0; v < varbinds.length; ++v) {
+ // Same level.
+ TestConflict(letbinds[l] + varbinds[v]);
+ TestConflict(varbinds[v] + letbinds[l]);
+ // Different level.
+ TestConflict(letbinds[l] + '{' + varbinds[v] + '}');
+ TestConflict('{' + varbinds[v] +'}' + letbinds[l]);
+ TestNoConflict(varbinds[v] + '{' + letbinds[l] + '}');
+ TestNoConflict('{' + letbinds[l] + '}' + varbinds[v]);
+ // For loop.
+ if (forCompatible(letbinds[l])) {
+ TestConflict('for (' + letbinds[l] + '0;) {' + varbinds[v] + '}');
+ }
+ TestNoConflict('for (' + varbinds[v] + '0;) {' + letbinds[l] + '}');
+ }
+
+ // Test conflicting let/let bindings.
+ for (var k = 0; k < letbinds.length; ++k) {
+ // Same level.
+ TestConflict(letbinds[l] + letbinds[k]);
+ TestConflict(letbinds[k] + letbinds[l]);
+ // Different level.
+ TestNoConflict(letbinds[l] + '{ ' + letbinds[k] + '}');
+ TestNoConflict('{' + letbinds[k] +'} ' + letbinds[l]);
+ // For loop.
+ if (forCompatible(letbinds[l])) {
+ TestNoConflict('for (' + letbinds[l] + '0;) {' + letbinds[k] + '}');
+ }
+ if (forCompatible(letbinds[k])) {
+ TestNoConflict('for (' + letbinds[k] + '0;) {' + letbinds[l] + '}');
+ }
+ }
+
+ // Test conflicting function/let bindings.
+ // Same level.
+ TestConflict(letbinds[l] + funbind);
+ TestConflict(funbind + letbinds[l]);
+ // Different level.
+ TestNoConflict(letbinds[l] + '{' + funbind + '}');
+ TestNoConflict('{' + funbind + '}' + letbinds[l]);
+ TestNoConflict(funbind + '{' + letbinds[l] + '}');
+ TestNoConflict('{' + letbinds[l] + '}' + funbind);
+ // For loop.
+ if (forCompatible(letbinds[l])) {
+ TestNoConflict('for (' + letbinds[l] + '0;) {' + funbind + '}');
+ }
+
+ // Test conflicting parameter/let bindings.
+ TestConflict('(function(x) {' + letbinds[l] + '})();');
+}
+
+// Test conflicting function/var bindings.
+for (var v = 0; v < varbinds.length; ++v) {
+ // Same level.
+ TestLocalConflict(varbinds[v] + funbind);
+ TestLocalConflict(funbind + varbinds[v]);
+ // Different level.
+ TestLocalConflict(funbind + '{' + varbinds[v] + '}');
+ TestLocalConflict('{' + varbinds[v] +'}' + funbind);
+ TestNoConflict(varbinds[v] + '{' + funbind + '}');
+ TestNoConflict('{' + funbind + '}' + varbinds[v]);
+ // For loop.
+ TestNoConflict('for (' + varbinds[v] + '0;) {' + funbind + '}');
+}
+
+// Test conflicting catch/var bindings.
+for (var v = 0; v < varbinds.length; ++v) {
+ TestNoConflict('try {} catch(x) {' + varbinds[v] + '}');
+}
+
+// Test conflicting parameter/var bindings.
+for (var v = 0; v < varbinds.length; ++v) {
+ TestNoConflict('(function (x) {' + varbinds[v] + '})();');
+}
+
+// Test conflicting catch/function bindings.
+TestNoConflict('try {} catch(x) {' + funbind + '}');
+
+// Test conflicting parameter/function bindings.
+TestNoConflict('(function (x) {' + funbind + '})();');
diff --git a/test/mjsunit/es6/block-const-assign-sloppy.js b/test/mjsunit/es6/block-const-assign-sloppy.js
new file mode 100644
index 0000000..99024ef
--- /dev/null
+++ b/test/mjsunit/es6/block-const-assign-sloppy.js
@@ -0,0 +1,156 @@
+// Copyright 2011 the V8 project authors. All rights reserved.
+// Redistribution and use in source and binary forms, with or without
+// modification, are permitted provided that the following conditions are
+// met:
+//
+// * Redistributions of source code must retain the above copyright
+// notice, this list of conditions and the following disclaimer.
+// * Redistributions in binary form must reproduce the above
+// copyright notice, this list of conditions and the following
+// disclaimer in the documentation and/or other materials provided
+// with the distribution.
+// * Neither the name of Google Inc. nor the names of its
+// contributors may be used to endorse or promote products derived
+// from this software without specific prior written permission.
+//
+// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+
+// Test that we throw early syntax errors in harmony mode
+// when using an immutable binding in an assigment or with
+// prefix/postfix decrement/increment operators.
+
+const decls = [
+ // Const declaration.
+ function(use) { return "const c = 1; " + use + ";" }, TypeError,
+ function(use) { return "const x = 0, c = 1; " + use + ";" }, TypeError,
+ function(use) { return "const c = 1, x = (" + use + ");" }, TypeError,
+ function(use) { return use + "; const c = 1;" }, ReferenceError,
+ function(use) { return use + "; const x = 0, c = 1;" }, ReferenceError,
+ function(use) { return "const x = (" + use + "), c = 1;" }, ReferenceError,
+ function(use) { return "const c = (" + use + ");" }, ReferenceError,
+
+ // Function expression.
+ function(use) { return "(function c() { " + use + "; })();"; }, TypeError,
+ // TODO(rossberg): Once we have default parameters, test using 'c' there.
+
+ // Class expression.
+ function(use) {
+ return "new class c { constructor() { " + use + " } };";
+ }, TypeError,
+ function(use) {
+ return "(new class c { m() { " + use + " } }).m();";
+ }, TypeError,
+ function(use) {
+ return "(new class c { get a() { " + use + " } }).a;";
+ }, TypeError,
+ function(use) {
+ return "(new class c { set a(x) { " + use + " } }).a = 0;";
+ }, TypeError,
+ function(use) {
+ return "(class c { static m() { " + use + " } }).s();";
+ }, TypeError,
+ function(use) {
+ return "(class c extends (" + use + ") {});";
+ }, ReferenceError,
+ function(use) {
+ return "(class c { [" + use + "]() {} });";
+ }, ReferenceError,
+ function(use) {
+ return "(class c { get [" + use + "]() {} });";
+ }, ReferenceError,
+ function(use) {
+ return "(class c { set [" + use + "](x) {} });";
+ }, ReferenceError,
+ function(use) {
+ return "(class c { static [" + use + "]() {} });";
+ }, ReferenceError,
+
+ // For loop.
+ function(use) {
+ return "for (const c = 0; " + use + ";) {}"
+ }, TypeError,
+ function(use) {
+ return "for (const x = 0, c = 0; " + use + ";) {}"
+ }, TypeError,
+ function(use) {
+ return "for (const c = 0; ; " + use + ") {}"
+ }, TypeError,
+ function(use) {
+ return "for (const x = 0, c = 0; ; " + use + ") {}"
+ }, TypeError,
+ function(use) {
+ return "for (const c = 0; ;) { " + use + "; }"
+ }, TypeError,
+ function(use) {
+ return "for (const x = 0, c = 0; ;) { " + use + "; }"
+ }, TypeError,
+ function(use) {
+ return "for (const c in {a: 1}) { " + use + "; }"
+ }, TypeError,
+ function(use) {
+ return "for (const c of [1]) { " + use + "; }"
+ }, TypeError,
+ function(use) {
+ return "for (const x = (" + use + "), c = 0; ;) {}"
+ }, ReferenceError,
+ function(use) {
+ return "for (const c = (" + use + "); ;) {}"
+ }, ReferenceError,
+]
+
+let uses = [
+ 'c = 1',
+ 'c += 1',
+ '++c',
+ 'c--',
+];
+
+let declcontexts = [
+ function(decl) { return decl; },
+ function(decl) { return "eval(\'" + decl + "\')"; },
+ function(decl) { return "{ " + decl + " }"; },
+ function(decl) { return "(function() { " + decl + " })()"; },
+];
+
+let usecontexts = [
+ function(use) { return use; },
+ function(use) { return "eval(\"" + use + "\")"; },
+ function(use) { return "(function() { " + use + " })()"; },
+ function(use) { return "(function() { eval(\"" + use + "\"); })()"; },
+ function(use) { return "eval(\"(function() { " + use + "; })\")()"; },
+];
+
+function Test(program, error) {
+ program = "'use strict'; " + program;
+ try {
+ print(program, " // throw " + error.name);
+ eval(program);
+ } catch (e) {
+ assertInstanceof(e, error);
+ if (e === TypeError) {
+ assertTrue(e.toString().indexOf("Assignment to constant variable") >= 0);
+ }
+ return;
+ }
+ assertUnreachable();
+}
+
+for (var d = 0; d < decls.length; d += 2) {
+ for (var u = 0; u < uses.length; ++u) {
+ for (var o = 0; o < declcontexts.length; ++o) {
+ for (var i = 0; i < usecontexts.length; ++i) {
+ Test(declcontexts[o](decls[d](usecontexts[i](uses[u]))), decls[d + 1]);
+ }
+ }
+ }
+}
diff --git a/test/mjsunit/es6/block-early-errors.js b/test/mjsunit/es6/block-early-errors.js
deleted file mode 100644
index 4af6521..0000000
--- a/test/mjsunit/es6/block-early-errors.js
+++ /dev/null
@@ -1,54 +0,0 @@
-// Copyright 2011 the V8 project authors. All rights reserved.
-// Redistribution and use in source and binary forms, with or without
-// modification, are permitted provided that the following conditions are
-// met:
-//
-// * Redistributions of source code must retain the above copyright
-// notice, this list of conditions and the following disclaimer.
-// * Redistributions in binary form must reproduce the above
-// copyright notice, this list of conditions and the following
-// disclaimer in the documentation and/or other materials provided
-// with the distribution.
-// * Neither the name of Google Inc. nor the names of its
-// contributors may be used to endorse or promote products derived
-// from this software without specific prior written permission.
-//
-// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
-// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
-// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
-// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
-// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
-// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
-// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
-// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
-// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
-// (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: --no-harmony-sloppy-let
-
-function CheckException(e) {
- var string = e.toString();
- assertInstanceof(e, SyntaxError);
-}
-
-function Check(str) {
- try {
- eval("(function () { " + str + " })");
- assertUnreachable();
- } catch (e) {
- CheckException(e);
- }
- try {
- eval("(function () { { " + str + " } })");
- assertUnreachable();
- } catch (e) {
- CheckException(e);
- }
-}
-
-// Check for early syntax errors when using let
-// declarations outside of strict mode.
-Check("let x;");
-Check("let x = 1;");
-Check("let x, y;");
diff --git a/test/mjsunit/es6/block-eval-var-over-let.js b/test/mjsunit/es6/block-eval-var-over-let.js
new file mode 100644
index 0000000..febc83f
--- /dev/null
+++ b/test/mjsunit/es6/block-eval-var-over-let.js
@@ -0,0 +1,141 @@
+// 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.
+
+// Var-let conflict in a function throws, even if the var is in an eval
+
+// Throws at the top level of a function
+assertThrows(function() {
+ let x = 1;
+ eval('var x');
+}, TypeError);
+
+// If the eval is in its own block scope, throws
+assertThrows(function() {
+ let y = 1;
+ { eval('var y'); }
+}, TypeError);
+
+// If the let is in its own block scope, with the eval, throws
+assertThrows(function() {
+ {
+ let x = 1;
+ eval('var x');
+ }
+}, TypeError);
+
+// Legal if the let is no longer visible
+assertDoesNotThrow(function() {
+ {
+ let x = 1;
+ }
+ eval('var x');
+});
+
+// All the same works for const:
+// Throws at the top level of a function
+assertThrows(function() {
+ const x = 1;
+ eval('var x');
+}, TypeError);
+
+// If the eval is in its own block scope, throws
+assertThrows(function() {
+ const y = 1;
+ { eval('var y'); }
+}, TypeError);
+
+// If the const is in its own block scope, with the eval, throws
+assertThrows(function() {
+ {
+ const x = 1;
+ eval('var x');
+ }
+}, TypeError);
+
+// Legal if the const is no longer visible
+assertDoesNotThrow(function() {
+ {
+ const x = 1;
+ }
+ eval('var x');
+});
+
+// In global scope
+let caught = false;
+try {
+ let z = 1;
+ eval('var z');
+} catch (e) {
+ caught = true;
+}
+assertTrue(caught);
+
+// Let declarations beyond a function boundary don't conflict
+caught = false;
+try {
+ let a = 1;
+ (function() {
+ eval('var a');
+ })();
+} catch (e) {
+ caught = true;
+}
+assertFalse(caught);
+
+// var across with doesn't conflict
+caught = false;
+try {
+ (function() {
+ with ({x: 1}) {
+ eval("var x");
+ }
+ })();
+} catch (e) {
+ caught = true;
+}
+assertFalse(caught);
+
+// var can still conflict with let across a with
+caught = false;
+try {
+ (function() {
+ let x;
+ with ({x: 1}) {
+ eval("var x");
+ }
+ })();
+} catch (e) {
+ caught = true;
+}
+assertTrue(caught);
+
+// Functions declared in eval also conflict
+caught = false
+try {
+ (function() {
+ {
+ let x = 1;
+ eval('function x() {}');
+ }
+ })();
+} catch (e) {
+ caught = true;
+}
+assertTrue(caught);
+
+// TODO(littledan): Hoisting x out of the block should be
+// prevented in this case BUG(v8:4479)
+caught = false
+try {
+ (function() {
+ {
+ let x = 1;
+ eval('{ function x() {} }');
+ }
+ })();
+} catch (e) {
+ caught = true;
+}
+// TODO(littledan): switch to assertTrue when bug is fixed
+assertTrue(caught);
diff --git a/test/mjsunit/es6/block-for-sloppy.js b/test/mjsunit/es6/block-for-sloppy.js
new file mode 100644
index 0000000..4f0f63f
--- /dev/null
+++ b/test/mjsunit/es6/block-for-sloppy.js
@@ -0,0 +1,199 @@
+// Copyright 2011 the V8 project authors. All rights reserved.
+// Redistribution and use in source and binary forms, with or without
+// modification, are permitted provided that the following conditions are
+// met:
+//
+// * Redistributions of source code must retain the above copyright
+// notice, this list of conditions and the following disclaimer.
+// * Redistributions in binary form must reproduce the above
+// copyright notice, this list of conditions and the following
+// disclaimer in the documentation and/or other materials provided
+// with the distribution.
+// * Neither the name of Google Inc. nor the names of its
+// contributors may be used to endorse or promote products derived
+// from this software without specific prior written permission.
+//
+// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+
+function props(x) {
+ var array = [];
+ for (let p in x) array.push(p);
+ return array.sort();
+}
+
+assertEquals(0, props({}).length);
+assertEquals(1, props({x:1}).length);
+assertEquals(2, props({x:1, y:2}).length);
+
+assertArrayEquals(["x"], props({x:1}));
+assertArrayEquals(["x", "y"], props({x:1, y:2}));
+assertArrayEquals(["x", "y", "zoom"], props({x:1, y:2, zoom:3}));
+
+assertEquals(0, props([]).length);
+assertEquals(1, props([1]).length);
+assertEquals(2, props([1,2]).length);
+
+assertArrayEquals(["0"], props([1]));
+assertArrayEquals(["0", "1"], props([1,2]));
+assertArrayEquals(["0", "1", "2"], props([1,2,3]));
+
+var o = {};
+var a = [];
+let i = "outer_i";
+let s = "outer_s";
+for (let i = 0x0020; i < 0x01ff; i+=2) {
+ let s = 'char:' + String.fromCharCode(i);
+ a.push(s);
+ o[s] = i;
+}
+assertArrayEquals(a, props(o));
+assertEquals(i, "outer_i");
+assertEquals(s, "outer_s");
+
+var a = [];
+assertEquals(0, props(a).length);
+a[Math.pow(2,30)-1] = 0;
+assertEquals(1, props(a).length);
+a[Math.pow(2,31)-1] = 0;
+assertEquals(2, props(a).length);
+a[1] = 0;
+assertEquals(3, props(a).length);
+
+var result = '';
+for (let p in {a : [0], b : 1}) { result += p; }
+assertEquals('ab', result);
+
+var result = '';
+for (let p in {a : {v:1}, b : 1}) { result += p; }
+assertEquals('ab', result);
+
+var result = '';
+for (let p in { get a() {}, b : 1}) { result += p; }
+assertEquals('ab', result);
+
+var result = '';
+for (let p in { get a() {}, set a(x) {}, b : 1}) { result += p; }
+assertEquals('ab', result);
+
+
+// Check that there is exactly one variable without initializer
+// in a for-in statement with let variables.
+assertThrows("function foo() { 'use strict'; for (let in {}) { } }", SyntaxError);
+assertThrows("function foo() { 'use strict'; for (let x = 3 in {}) { } }", SyntaxError);
+assertThrows("function foo() { 'use strict'; for (let x, y in {}) { } }", SyntaxError);
+assertThrows("function foo() { 'use strict'; for (let x = 3, y in {}) { } }", SyntaxError);
+assertThrows("function foo() { 'use strict'; for (let x, y = 4 in {}) { } }", SyntaxError);
+assertThrows("function foo() { 'use strict'; for (let x = 3, y = 4 in {}) { } }", SyntaxError);
+
+
+// In a normal for statement the iteration variable is
+// freshly allocated for each iteration.
+function closures1() {
+ let a = [];
+ for (let i = 0; i < 5; ++i) {
+ a.push(function () { return i; });
+ }
+ for (let j = 0; j < 5; ++j) {
+ assertEquals(j, a[j]());
+ }
+}
+closures1();
+
+
+function closures2() {
+ let a = [], b = [];
+ for (let i = 0, j = 10; i < 5; ++i, ++j) {
+ a.push(function () { return i; });
+ b.push(function () { return j; });
+ }
+ for (let k = 0; k < 5; ++k) {
+ assertEquals(k, a[k]());
+ assertEquals(k + 10, b[k]());
+ }
+}
+closures2();
+
+
+function closure_in_for_init() {
+ let a = [];
+ for (let i = 0, f = function() { return i }; i < 5; ++i) {
+ a.push(f);
+ }
+ for (let k = 0; k < 5; ++k) {
+ assertEquals(0, a[k]());
+ }
+}
+closure_in_for_init();
+
+
+function closure_in_for_cond() {
+ let a = [];
+ for (let i = 0; a.push(function () { return i; }), i < 5; ++i) { }
+ for (let k = 0; k < 5; ++k) {
+ assertEquals(k, a[k]());
+ }
+}
+closure_in_for_cond();
+
+
+function closure_in_for_next() {
+ let a = [];
+ for (let i = 0; i < 5; a.push(function () { return i; }), ++i) { }
+ for (let k = 0; k < 5; ++k) {
+ assertEquals(k + 1, a[k]());
+ }
+}
+closure_in_for_next();
+
+
+// In a for-in statement the iteration variable is fresh
+// for each iteration.
+function closures3(x) {
+ let a = [];
+ for (let p in x) {
+ a.push(function () { return p; });
+ }
+ let k = 0;
+ for (let q in x) {
+ assertEquals(q, a[k]());
+ ++k;
+ }
+}
+closures3({a : [0], b : 1, c : {v : 1}, get d() {}, set e(x) {}});
+
+// Check normal for statement completion values.
+assertEquals(1, eval("for (let i = 0; i < 10; i++) { 1; }"));
+assertEquals(9, eval("for (let i = 0; i < 10; i++) { i; }"));
+assertEquals(undefined, eval("for (let i = 0; false;) { }"));
+assertEquals(undefined, eval("for (const i = 0; false;) { }"));
+assertEquals(undefined, eval("for (let i = 0; i < 10; i++) { }"));
+assertEquals(undefined, eval("for (let i = 0; false;) { i; }"));
+assertEquals(undefined, eval("for (const i = 0; false;) { i; }"));
+assertEquals(undefined, eval("for (let i = 0; true;) { break; }"));
+assertEquals(undefined, eval("for (const i = 0; true;) { break; }"));
+assertEquals(undefined, eval("for (let i = 0; i < 10; i++) { continue; }"));
+assertEquals(undefined, eval("for (let i = 0; true;) { break; i; }"));
+assertEquals(undefined, eval("for (const i = 0; true;) { break; i; }"));
+assertEquals(undefined, eval("for (let i = 0; i < 10; i++) { continue; i; }"));
+assertEquals(0, eval("for (let i = 0; true;) { i; break; }"));
+assertEquals(0, eval("for (const i = 0; true;) { i; break; }"));
+assertEquals(9, eval("for (let i = 0; i < 10; i++) { i; continue; }"));
+assertEquals(
+ undefined, eval("for (let i = 0; true; i++) { i; if (i >= 3) break; }"));
+assertEquals(
+ undefined, eval("for (let i = 0; true; i++) { if (i >= 3) break; i; }"));
+assertEquals(
+ undefined, eval("for (let i = 0; i < 10; i++) { if (i >= 3) continue; i; }"));
+assertEquals(undefined, eval("foo: for (let i = 0; true;) { break foo; }"));
+assertEquals(undefined, eval("foo: for (const i = 0; true;) { break foo; }"));
+assertEquals(3, eval("foo: for (let i = 3; true;) { i; break foo; }"));
diff --git a/test/mjsunit/es6/block-leave-sloppy.js b/test/mjsunit/es6/block-leave-sloppy.js
new file mode 100644
index 0000000..1313026
--- /dev/null
+++ b/test/mjsunit/es6/block-leave-sloppy.js
@@ -0,0 +1,222 @@
+// Copyright 2011 the V8 project authors. All rights reserved.
+// Redistribution and use in source and binary forms, with or without
+// modification, are permitted provided that the following conditions are
+// met:
+//
+// * Redistributions of source code must retain the above copyright
+// notice, this list of conditions and the following disclaimer.
+// * Redistributions in binary form must reproduce the above
+// copyright notice, this list of conditions and the following
+// disclaimer in the documentation and/or other materials provided
+// with the distribution.
+// * Neither the name of Google Inc. nor the names of its
+// contributors may be used to endorse or promote products derived
+// from this software without specific prior written permission.
+//
+// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+
+// We want to test the context chain shape. In each of the tests cases
+// below, the outer with is to force a runtime lookup of the identifier 'x'
+// to actually verify that the inner context has been discarded. A static
+// lookup of 'x' might accidentally succeed.
+
+{
+ let x = 2;
+ L: {
+ let x = 3;
+ assertEquals(3, x);
+ break L;
+ assertTrue(false);
+ }
+ assertEquals(2, x);
+}
+
+do {
+ let x = 4;
+ assertEquals(4,x);
+ {
+ let x = 5;
+ assertEquals(5, x);
+ continue;
+ assertTrue(false);
+ }
+} while (false);
+
+var caught = false;
+try {
+ {
+ let xx = 18;
+ throw 25;
+ assertTrue(false);
+ }
+} catch (e) {
+ caught = true;
+ assertEquals(25, e);
+ (function () {
+ try {
+ // NOTE: This checks that the block scope containing xx has been
+ // removed from the context chain.
+ eval('xx');
+ assertTrue(false); // should not reach here
+ } catch (e2) {
+ assertTrue(e2 instanceof ReferenceError);
+ }
+ })();
+}
+assertTrue(caught);
+
+
+(function(x) {
+ label: {
+ let x = 'inner';
+ break label;
+ }
+ assertEquals('outer', eval('x'));
+})('outer');
+
+
+(function(x) {
+ label: {
+ let x = 'middle';
+ {
+ let x = 'inner';
+ break label;
+ }
+ }
+ assertEquals('outer', eval('x'));
+})('outer');
+
+
+(function(x) {
+ for (var i = 0; i < 10; ++i) {
+ let x = 'inner' + i;
+ continue;
+ }
+ assertEquals('outer', eval('x'));
+})('outer');
+
+
+(function(x) {
+ label: for (var i = 0; i < 10; ++i) {
+ let x = 'middle' + i;
+ for (var j = 0; j < 10; ++j) {
+ let x = 'inner' + j;
+ continue label;
+ }
+ }
+ assertEquals('outer', eval('x'));
+})('outer');
+
+
+(function(x) {
+ try {
+ let x = 'inner';
+ throw 0;
+ } catch (e) {
+ assertEquals('outer', eval('x'));
+ }
+})('outer');
+
+
+(function(x) {
+ try {
+ let x = 'middle';
+ {
+ let x = 'inner';
+ throw 0;
+ }
+ } catch (e) {
+ assertEquals('outer', eval('x'));
+ }
+})('outer');
+
+
+try {
+ (function(x) {
+ try {
+ let x = 'inner';
+ throw 0;
+ } finally {
+ assertEquals('outer', eval('x'));
+ }
+ })('outer');
+} catch (e) {
+ if (e instanceof MjsUnitAssertionError) throw e;
+}
+
+
+try {
+ (function(x) {
+ try {
+ let x = 'middle';
+ {
+ let x = 'inner';
+ throw 0;
+ }
+ } finally {
+ assertEquals('outer', eval('x'));
+ }
+ })('outer');
+} catch (e) {
+ if (e instanceof MjsUnitAssertionError) throw e;
+}
+
+
+// Verify that the context is correctly set in the stack frame after exiting
+// from eval.
+function f() {}
+
+(function(x) {
+ label: {
+ let x = 'inner';
+ break label;
+ }
+ f(); // The context could be restored from the stack after the call.
+ assertEquals('outer', eval('x'));
+})('outer');
+
+
+(function(x) {
+ for (var i = 0; i < 10; ++i) {
+ let x = 'inner';
+ continue;
+ }
+ f();
+ assertEquals('outer', eval('x'));
+})('outer');
+
+
+(function(x) {
+ try {
+ let x = 'inner';
+ throw 0;
+ } catch (e) {
+ f();
+ assertEquals('outer', eval('x'));
+ }
+})('outer');
+
+
+try {
+ (function(x) {
+ try {
+ let x = 'inner';
+ throw 0;
+ } finally {
+ f();
+ assertEquals('outer', eval('x'));
+ }
+ })('outer');
+} catch (e) {
+ if (e instanceof MjsUnitAssertionError) throw e;
+}
diff --git a/test/mjsunit/es6/block-let-contextual-sloppy.js b/test/mjsunit/es6/block-let-contextual-sloppy.js
index ac7bca1..8282d77 100644
--- a/test/mjsunit/es6/block-let-contextual-sloppy.js
+++ b/test/mjsunit/es6/block-let-contextual-sloppy.js
@@ -2,8 +2,6 @@
// 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-let
-
// let is usable as a variable with var, but not let or ES6 const
(function (){
diff --git a/test/mjsunit/es6/block-let-crankshaft-sloppy.js b/test/mjsunit/es6/block-let-crankshaft-sloppy.js
new file mode 100644
index 0000000..b5e81f7
--- /dev/null
+++ b/test/mjsunit/es6/block-let-crankshaft-sloppy.js
@@ -0,0 +1,482 @@
+// Copyright 2011 the V8 project authors. All rights reserved.
+// Redistribution and use in source and binary forms, with or without
+// modification, are permitted provided that the following conditions are
+// met:
+//
+// * Redistributions of source code must retain the above copyright
+// notice, this list of conditions and the following disclaimer.
+// * Redistributions in binary form must reproduce the above
+// copyright notice, this list of conditions and the following
+// disclaimer in the documentation and/or other materials provided
+// with the distribution.
+// * Neither the name of Google Inc. nor the names of its
+// contributors may be used to endorse or promote products derived
+// from this software without specific prior written permission.
+//
+// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+// (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
+
+// Check that the following functions are optimizable.
+var functions = [ f1, f2, f3, f4, f5, f6, f7, f8, f9, f10, f11, f12, f13, f14,
+ f15, f16, f17, f18, f19, f20, f21, f22, f23, f24, f25, f26,
+ f27, f28, f29, f30, f31, f32, f33];
+
+for (var i = 0; i < functions.length; ++i) {
+ var func = functions[i];
+ print("Testing:");
+ print(func);
+ for (var j = 0; j < 10; ++j) {
+ func(12);
+ }
+ %OptimizeFunctionOnNextCall(func);
+ func(12);
+ assertOptimized(func);
+}
+
+function f1() { }
+
+function f2(x) { }
+
+function f3() {
+ let x;
+}
+
+function f4() {
+ function foo() {
+ }
+}
+
+function f5() {
+ let x = 1;
+}
+
+function f6() {
+ const x = 1;
+}
+
+function f7(x) {
+ return x;
+}
+
+function f8() {
+ let x;
+ return x;
+}
+
+function f9() {
+ function x() {
+ }
+ return x;
+}
+
+function f10(x) {
+ x = 1;
+}
+
+function f11() {
+ let x;
+ x = 1;
+}
+
+function f12() {
+ function x() {};
+ x = 1;
+}
+
+function f13(x) {
+ (function() { x; });
+}
+
+function f14() {
+ let x;
+ (function() { x; });
+}
+
+function f15() {
+ function x() {
+ }
+ (function() { x; });
+}
+
+function f16() {
+ let x = 1;
+ (function() { x; });
+}
+
+function f17() {
+ const x = 1;
+ (function() { x; });
+}
+
+function f18(x) {
+ return x;
+ (function() { x; });
+}
+
+function f19() {
+ let x;
+ return x;
+ (function() { x; });
+}
+
+function f20() {
+ function x() {
+ }
+ return x;
+ (function() { x; });
+}
+
+function f21(x) {
+ x = 1;
+ (function() { x; });
+}
+
+function f22() {
+ let x;
+ x = 1;
+ (function() { x; });
+}
+
+function f23() {
+ function x() { }
+ x = 1;
+ (function() { x; });
+}
+
+function f24() {
+ let x = 1;
+ {
+ let x = 2;
+ {
+ let x = 3;
+ assertEquals(3, x);
+ }
+ assertEquals(2, x);
+ }
+ assertEquals(1, x);
+}
+
+function f25() {
+ {
+ let x = 2;
+ L: {
+ let x = 3;
+ assertEquals(3, x);
+ break L;
+ assertTrue(false);
+ }
+ assertEquals(2, x);
+ }
+ assertTrue(true);
+}
+
+function f26() {
+ {
+ let x = 1;
+ L: {
+ let x = 2;
+ {
+ let x = 3;
+ assertEquals(3, x);
+ break L;
+ assertTrue(false);
+ }
+ assertTrue(false);
+ }
+ assertEquals(1, x);
+ }
+}
+
+
+function f27() {
+ do {
+ let x = 4;
+ assertEquals(4,x);
+ {
+ let x = 5;
+ assertEquals(5, x);
+ continue;
+ assertTrue(false);
+ }
+ } while (false);
+}
+
+function f28() {
+ label: for (var i = 0; i < 10; ++i) {
+ let x = 'middle' + i;
+ for (var j = 0; j < 10; ++j) {
+ let x = 'inner' + j;
+ continue label;
+ }
+ }
+}
+
+function f29() {
+ // Verify that the context is correctly set in the stack frame after exiting
+ // from with.
+
+ let x = 'outer';
+ label: {
+ let x = 'inner';
+ break label;
+ }
+ f(); // The context could be restored from the stack after the call.
+ assertEquals('outer', x);
+
+ function f() {
+ assertEquals('outer', x);
+ };
+}
+
+function f30() {
+ let x = 'outer';
+ for (var i = 0; i < 10; ++i) {
+ let x = 'inner';
+ continue;
+ }
+ f();
+ assertEquals('outer', x);
+
+ function f() {
+ assertEquals('outer', x);
+ };
+}
+
+function f31() {
+ {
+ let x = 'outer';
+ label: for (var i = 0; assertEquals('outer', x), i < 10; ++i) {
+ let x = 'middle' + i;
+ {
+ let x = 'inner' + j;
+ continue label;
+ }
+ }
+ assertEquals('outer', x);
+ }
+}
+
+var c = true;
+
+function f32() {
+ {
+ let x = 'outer';
+ L: {
+ {
+ let x = 'inner';
+ if (c) {
+ break L;
+ }
+ }
+ foo();
+ }
+ }
+
+ function foo() {
+ return 'bar';
+ }
+}
+
+function f33() {
+ {
+ let x = 'outer';
+ L: {
+ {
+ let x = 'inner';
+ if (c) {
+ break L;
+ }
+ foo();
+ }
+ }
+ }
+
+ function foo() {
+ return 'bar';
+ }
+}
+
+function TestThrow() {
+ function f() {
+ let x = 'outer';
+ {
+ let x = 'inner';
+ throw x;
+ }
+ }
+ for (var i = 0; i < 5; i++) {
+ try {
+ f();
+ } catch (e) {
+ assertEquals('inner', e);
+ }
+ }
+ %OptimizeFunctionOnNextCall(f);
+ try {
+ f();
+ } catch (e) {
+ assertEquals('inner', e);
+ }
+ assertOptimized(f);
+}
+
+TestThrow();
+
+// Test that temporal dead zone semantics for function and block scoped
+// let bindings are handled by the optimizing compiler.
+
+function TestFunctionLocal(s) {
+ 'use strict';
+ var func = eval("(function baz(){" + s + "; })");
+ print("Testing:");
+ print(func);
+ for (var i = 0; i < 5; ++i) {
+ try {
+ func();
+ assertUnreachable();
+ } catch (e) {
+ assertInstanceof(e, ReferenceError);
+ }
+ }
+ %OptimizeFunctionOnNextCall(func);
+ try {
+ func();
+ assertUnreachable();
+ } catch (e) {
+ assertInstanceof(e, ReferenceError);
+ }
+}
+
+function TestFunctionContext(s) {
+ 'use strict';
+ var func = eval("(function baz(){ " + s + "; (function() { x; }); })");
+ print("Testing:");
+ print(func);
+ for (var i = 0; i < 5; ++i) {
+ print(i);
+ try {
+ func();
+ assertUnreachable();
+ } catch (e) {
+ assertInstanceof(e, ReferenceError);
+ }
+ }
+ print("optimize");
+ %OptimizeFunctionOnNextCall(func);
+ try {
+ print("call");
+ func();
+ assertUnreachable();
+ } catch (e) {
+ print("catch");
+ assertInstanceof(e, ReferenceError);
+ }
+}
+
+function TestBlockLocal(s) {
+ 'use strict';
+ var func = eval("(function baz(){ { " + s + "; } })");
+ print("Testing:");
+ print(func);
+ for (var i = 0; i < 5; ++i) {
+ try {
+ func();
+ assertUnreachable();
+ } catch (e) {
+ assertInstanceof(e, ReferenceError);
+ }
+ }
+ %OptimizeFunctionOnNextCall(func);
+ try {
+ func();
+ assertUnreachable();
+ } catch (e) {
+ assertInstanceof(e, ReferenceError);
+ }
+}
+
+function TestBlockContext(s) {
+ 'use strict';
+ var func = eval("(function baz(){ { " + s + "; (function() { x; }); } })");
+ print("Testing:");
+ print(func);
+ for (var i = 0; i < 5; ++i) {
+ print(i);
+ try {
+ func();
+ assertUnreachable();
+ } catch (e) {
+ assertInstanceof(e, ReferenceError);
+ }
+ }
+ print("optimize");
+ %OptimizeFunctionOnNextCall(func);
+ try {
+ print("call");
+ func();
+ assertUnreachable();
+ } catch (e) {
+ print("catch");
+ assertInstanceof(e, ReferenceError);
+ }
+}
+
+function TestAll(s) {
+ TestFunctionLocal(s);
+ TestFunctionContext(s);
+ TestBlockLocal(s);
+ TestBlockContext(s);
+}
+
+// Use before initialization in declaration statement.
+TestAll('let x = x + 1');
+TestAll('let x = x += 1');
+TestAll('let x = x++');
+TestAll('let x = ++x');
+TestAll('const x = x + 1');
+
+// Use before initialization in prior statement.
+TestAll('x + 1; let x;');
+TestAll('x = 1; let x;');
+TestAll('x += 1; let x;');
+TestAll('++x; let x;');
+TestAll('x++; let x;');
+TestAll('let y = x; const x = 1;');
+
+
+function f(x) {
+ let y = x + 42;
+ return y;
+}
+
+function g(x) {
+ {
+ let y = x + 42;
+ return y;
+ }
+}
+
+for (var i=0; i<10; i++) {
+ f(i);
+ g(i);
+}
+
+%OptimizeFunctionOnNextCall(f);
+%OptimizeFunctionOnNextCall(g);
+
+f(12);
+g(12);
+
+assertTrue(%GetOptimizationStatus(f) != 2);
+assertTrue(%GetOptimizationStatus(g) != 2);
diff --git a/test/mjsunit/es6/block-let-declaration-sloppy.js b/test/mjsunit/es6/block-let-declaration-sloppy.js
new file mode 100644
index 0000000..ea0e39b
--- /dev/null
+++ b/test/mjsunit/es6/block-let-declaration-sloppy.js
@@ -0,0 +1,172 @@
+// Copyright 2011 the V8 project authors. All rights reserved.
+// Redistribution and use in source and binary forms, with or without
+// modification, are permitted provided that the following conditions are
+// met:
+//
+// * Redistributions of source code must retain the above copyright
+// notice, this list of conditions and the following disclaimer.
+// * Redistributions in binary form must reproduce the above
+// copyright notice, this list of conditions and the following
+// disclaimer in the documentation and/or other materials provided
+// with the distribution.
+// * Neither the name of Google Inc. nor the names of its
+// contributors may be used to endorse or promote products derived
+// from this software without specific prior written permission.
+//
+// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+
+// Test let declarations in various settings.
+
+// Global
+let x;
+let y = 2;
+const z = 4;
+class c { static foo() { return 1; } }
+
+// Block local
+{
+ let y;
+ let x = 3;
+ const z = 5;
+ class c { static foo() { return 2; } }
+}
+
+assertEquals(undefined, x);
+assertEquals(2,y);
+assertEquals(4,z);
+assertEquals(1, c.foo());
+
+if (true) {
+ let y;
+ assertEquals(undefined, y);
+}
+
+// Invalid declarations are early errors in harmony mode and thus should trigger
+// an exception in eval code during parsing, before even compiling or executing
+// the code. Thus the generated function is not called here.
+function TestLocalThrows(str, expect) {
+ assertThrows("(function(arg){ 'use strict'; " + str + "})", expect);
+}
+
+function TestLocalDoesNotThrow(str) {
+ assertDoesNotThrow("(function(arg){ 'use strict'; " + str + "})()");
+}
+
+// Test let declarations in statement positions.
+TestLocalThrows("if (true) let x;", SyntaxError);
+TestLocalThrows("if (true) {} else let x;", SyntaxError);
+TestLocalThrows("do let x; while (false)", SyntaxError);
+TestLocalThrows("while (false) let x;", SyntaxError);
+TestLocalThrows("label: let x;", SyntaxError);
+TestLocalThrows("for (;false;) let x;", SyntaxError);
+TestLocalDoesNotThrow("switch (true) { case true: let x; }");
+TestLocalDoesNotThrow("switch (true) { default: let x; }");
+
+// Test const declarations with initialisers in statement positions.
+TestLocalThrows("if (true) const x = 1;", SyntaxError);
+TestLocalThrows("if (true) {} else const x = 1;", SyntaxError);
+TestLocalThrows("do const x = 1; while (false)", SyntaxError);
+TestLocalThrows("while (false) const x = 1;", SyntaxError);
+TestLocalThrows("label: const x = 1;", SyntaxError);
+TestLocalThrows("for (;false;) const x = 1;", SyntaxError);
+TestLocalDoesNotThrow("switch (true) { case true: const x = 1; }");
+TestLocalDoesNotThrow("switch (true) { default: const x = 1; }");
+
+// Test const declarations without initialisers.
+TestLocalThrows("const x;", SyntaxError);
+TestLocalThrows("const x = 1, y;", SyntaxError);
+TestLocalThrows("const x, y = 1;", SyntaxError);
+
+// Test const declarations without initialisers in statement positions.
+TestLocalThrows("if (true) const x;", SyntaxError);
+TestLocalThrows("if (true) {} else const x;", SyntaxError);
+TestLocalThrows("do const x; while (false)", SyntaxError);
+TestLocalThrows("while (false) const x;", SyntaxError);
+TestLocalThrows("label: const x;", SyntaxError);
+TestLocalThrows("for (;false;) const x;", SyntaxError);
+TestLocalThrows("switch (true) { case true: const x; }", SyntaxError);
+TestLocalThrows("switch (true) { default: const x; }", SyntaxError);
+
+// Test var declarations in statement positions.
+TestLocalDoesNotThrow("if (true) var x;");
+TestLocalDoesNotThrow("if (true) {} else var x;");
+TestLocalDoesNotThrow("do var x; while (false)");
+TestLocalDoesNotThrow("while (false) var x;");
+TestLocalDoesNotThrow("label: var x;");
+TestLocalDoesNotThrow("for (;false;) var x;");
+TestLocalDoesNotThrow("switch (true) { case true: var x; }");
+TestLocalDoesNotThrow("switch (true) { default: var x; }");
+
+// Test class declarations with initialisers in statement positions.
+TestLocalThrows("if (true) class x { };", SyntaxError);
+TestLocalThrows("if (true) {} else class x { };", SyntaxError);
+TestLocalThrows("do class x { }; while (false)", SyntaxError);
+TestLocalThrows("while (false) class x { };", SyntaxError);
+TestLocalThrows("label: class x { };", SyntaxError);
+TestLocalThrows("for (;false;) class x { };", SyntaxError);
+TestLocalDoesNotThrow("switch (true) { case true: class x { }; }");
+TestLocalDoesNotThrow("switch (true) { default: class x { }; }");
+
+// Test that redeclarations of functions are only allowed in outermost scope.
+TestLocalThrows("{ let f; var f; }");
+TestLocalThrows("{ var f; let f; }");
+TestLocalThrows("{ function f() {} let f; }");
+TestLocalThrows("{ let f; function f() {} }");
+TestLocalThrows("{ function f() {} var f; }");
+TestLocalThrows("{ var f; function f() {} }");
+TestLocalThrows("{ function f() {} class f {} }");
+TestLocalThrows("{ class f {}; function f() {} }");
+TestLocalThrows("{ function f() {} function f() {} }");
+TestLocalThrows("function f() {} let f;");
+TestLocalThrows("let f; function f() {}");
+TestLocalThrows("function f() {} class f {}");
+TestLocalThrows("class f {}; function f() {}");
+TestLocalDoesNotThrow("function arg() {}");
+TestLocalDoesNotThrow("function f() {} var f;");
+TestLocalDoesNotThrow("var f; function f() {}");
+TestLocalDoesNotThrow("function f() {} function f() {}");
+
+function g(f) {
+ function f() { return 1 }
+ return f()
+}
+assertEquals(1, g(function() { return 2 }))
+
+
+// Test function declarations in source element and
+// sloppy statement positions.
+function f() {
+ // Sloppy source element positions.
+ function g0() {
+ "use strict";
+ // Strict source element positions.
+ function h() { }
+ {
+ function h1() { }
+ }
+ }
+ {
+ function g1() { }
+ }
+}
+f();
+
+// Test function declarations in statement position in strict mode.
+TestLocalThrows("function f() { if (true) function g() {} }", SyntaxError);
+TestLocalThrows("function f() { if (true) {} else function g() {} }", SyntaxError);
+TestLocalThrows("function f() { do function g() {} while (false) }", SyntaxError);
+TestLocalThrows("function f() { while (false) function g() {} }", SyntaxError);
+TestLocalThrows("function f() { label: function g() {} }", SyntaxError);
+TestLocalThrows("function f() { for (;false;) function g() {} }", SyntaxError);
+TestLocalDoesNotThrow("function f() { switch (true) { case true: function g() {} } }");
+TestLocalDoesNotThrow("function f() { switch (true) { default: function g() {} } }");
diff --git a/test/mjsunit/es6/block-let-semantics-sloppy.js b/test/mjsunit/es6/block-let-semantics-sloppy.js
new file mode 100644
index 0000000..4102ec8
--- /dev/null
+++ b/test/mjsunit/es6/block-let-semantics-sloppy.js
@@ -0,0 +1,191 @@
+// Copyright 2011 the V8 project authors. All rights reserved.
+// Redistribution and use in source and binary forms, with or without
+// modification, are permitted provided that the following conditions are
+// met:
+//
+// * Redistributions of source code must retain the above copyright
+// notice, this list of conditions and the following disclaimer.
+// * Redistributions in binary form must reproduce the above
+// copyright notice, this list of conditions and the following
+// disclaimer in the documentation and/or other materials provided
+// with the distribution.
+// * Neither the name of Google Inc. nor the names of its
+// contributors may be used to endorse or promote products derived
+// from this software without specific prior written permission.
+//
+// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+
+// Test temporal dead zone semantics of let bound variables in
+// function and block scopes.
+
+function TestFunctionLocal(s) {
+ try {
+ eval("(function(){" + s + "; })")();
+ } catch (e) {
+ assertInstanceof(e, ReferenceError);
+ return;
+ }
+ assertUnreachable();
+}
+
+function TestBlockLocal(s,e) {
+ try {
+ eval("(function(){ {" + s + ";} })")();
+ } catch (e) {
+ assertInstanceof(e, ReferenceError);
+ return;
+ }
+ assertUnreachable();
+}
+
+
+function TestAll(s) {
+ TestBlockLocal(s);
+ TestFunctionLocal(s);
+}
+
+// Use before initialization in declaration statement.
+TestAll('let x = x + 1');
+TestAll('let x = x += 1');
+TestAll('let x = x++');
+TestAll('let x = ++x');
+TestAll('const x = x + 1');
+
+// Use before initialization in prior statement.
+TestAll('x + 1; let x;');
+TestAll('x = 1; let x;');
+TestAll('x += 1; let x;');
+TestAll('++x; let x;');
+TestAll('x++; let x;');
+TestAll('let y = x; const x = 1;');
+TestAll('let y = x; class x {}');
+
+TestAll('f(); let x; function f() { return x + 1; }');
+TestAll('f(); let x; function f() { x = 1; }');
+TestAll('f(); let x; function f() { x += 1; }');
+TestAll('f(); let x; function f() { ++x; }');
+TestAll('f(); let x; function f() { x++; }');
+TestAll('f(); const x = 1; function f() { return x; }');
+TestAll('f(); class x { }; function f() { return x; }');
+
+TestAll('f()(); let x; function f() { return function() { return x + 1; } }');
+TestAll('f()(); let x; function f() { return function() { x = 1; } }');
+TestAll('f()(); let x; function f() { return function() { x += 1; } }');
+TestAll('f()(); let x; function f() { return function() { ++x; } }');
+TestAll('f()(); let x; function f() { return function() { x++; } }');
+TestAll('f()(); const x = 1; function f() { return function() { return x; } }');
+TestAll('f()(); class x { }; function f() { return function() { return x; } }');
+
+for (var kw of ['let x = 2', 'const x = 2', 'class x { }']) {
+ // Use before initialization with a dynamic lookup.
+ TestAll(`eval("x"); ${kw};`);
+ TestAll(`eval("x + 1;"); ${kw};`);
+ TestAll(`eval("x = 1;"); ${kw};`);
+ TestAll(`eval("x += 1;"); ${kw};`);
+ TestAll(`eval("++x;"); ${kw};`);
+ TestAll(`eval("x++;"); ${kw};`);
+
+ // Use before initialization with check for eval-shadowed bindings.
+ TestAll(`function f() { eval("var y = 2;"); x + 1; }; f(); ${kw};`);
+ TestAll(`function f() { eval("var y = 2;"); x = 1; }; f(); ${kw};`);
+ TestAll(`function f() { eval("var y = 2;"); x += 1; }; f(); ${kw};`);
+ TestAll(`function f() { eval("var y = 2;"); ++x; }; f(); ${kw};`);
+ TestAll(`function f() { eval("var y = 2;"); x++; }; f(); ${kw};`);
+}
+
+// Test that variables introduced by function declarations are created and
+// initialized upon entering a function / block scope.
+function f() {
+ {
+ assertEquals(2, g1());
+ assertEquals(2, eval("g1()"));
+
+ // block scoped function declaration
+ function g1() {
+ return 2;
+ }
+ }
+
+ assertEquals(3, g2());
+ assertEquals(3, eval("g2()"));
+ // function scoped function declaration
+ function g2() {
+ return 3;
+ }
+}
+f();
+
+// Test that a function declaration introduces a block scoped variable
+// and no function hoisting if there is a conflict.
+TestFunctionLocal('{ function k() { return 0; } }; k(); let k;');
+
+// Test that a function declaration sees the scope it resides in.
+function f2() {
+ let m, n, o, p;
+ {
+ m = g;
+ function g() {
+ return a;
+ }
+ let a = 1;
+ }
+ assertEquals(1, m());
+
+ try {
+ throw 2;
+ } catch(b) {
+ n = h;
+ function h() {
+ return b + c;
+ }
+ let c = 3;
+ }
+ assertEquals(5, n());
+
+ {
+ o = i;
+ function i() {
+ return d;
+ }
+ let d = 4;
+ }
+ assertEquals(4, o());
+
+ try {
+ throw 5;
+ } catch(e) {
+ p = j;
+ function j() {
+ return e + f;
+ }
+ let f = 6;
+ }
+ assertEquals(11, p());
+}
+f2();
+
+// Test that resolution of let bound variables works with scopes that call eval.
+function outer() {
+ function middle() {
+ function inner() {
+ return x;
+ }
+ eval("1 + 1");
+ return x + inner();
+ }
+
+ let x = 1;
+ return middle();
+}
+
+assertEquals(2, outer());
diff --git a/test/mjsunit/es6/block-non-strict-errors.js b/test/mjsunit/es6/block-non-strict-errors.js
deleted file mode 100644
index db7f558..0000000
--- a/test/mjsunit/es6/block-non-strict-errors.js
+++ /dev/null
@@ -1,42 +0,0 @@
-// Copyright 2014 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-sloppy-let --no-harmony-sloppy-function
-// Flags: --no-harmony-sloppy
-
-function CheckError(source) {
- var exception = null;
- try {
- eval(source);
- } catch (e) {
- exception = e;
- }
- assertNotNull(exception);
- assertEquals(
- "Block-scoped declarations (let, const, function, class) not yet supported outside strict mode",
- exception.message);
-}
-
-
-function CheckOk(source) {
- eval(source);
-}
-
-CheckError("let x = 1;");
-CheckError("{ let x = 1; }");
-CheckError("function f() { let x = 1; }");
-CheckError("for (let x = 1; x < 1; x++) {}");
-CheckError("for (let x of []) {}");
-CheckError("for (let x in []) {}");
-CheckError("class C {}");
-CheckError("class C extends Array {}");
-CheckError("(class {});");
-CheckError("(class extends Array {});");
-CheckError("(class C {});");
-CheckError("(class C exends Array {});");
-
-CheckOk("let = 1;");
-CheckOk("{ let = 1; }");
-CheckOk("function f() { let = 1; }");
-CheckOk("for (let = 1; let < 1; let++) {}");
diff --git a/test/mjsunit/es6/block-scope-class.js b/test/mjsunit/es6/block-scope-class.js
index 351feaa..7bbd49d 100644
--- a/test/mjsunit/es6/block-scope-class.js
+++ b/test/mjsunit/es6/block-scope-class.js
@@ -4,8 +4,6 @@
// Test for conflicting variable bindings.
-// Flags: --harmony-sloppy --harmony-sloppy-function
-
function AssertEqualsStrictAndSloppy(value, code) {
assertEquals(value, eval("(function() {" + code + "})()"));
assertEquals(value, eval("(function() { 'use strict'; " + code + "})()"));
diff --git a/test/mjsunit/es6/block-scoping-sloppy.js b/test/mjsunit/es6/block-scoping-sloppy.js
new file mode 100644
index 0000000..f5c5a63
--- /dev/null
+++ b/test/mjsunit/es6/block-scoping-sloppy.js
@@ -0,0 +1,309 @@
+// Copyright 2011 the V8 project authors. All rights reserved.
+// Redistribution and use in source and binary forms, with or without
+// modification, are permitted provided that the following conditions are
+// met:
+//
+// * Redistributions of source code must retain the above copyright
+// notice, this list of conditions and the following disclaimer.
+// * Redistributions in binary form must reproduce the above
+// copyright notice, this list of conditions and the following
+// disclaimer in the documentation and/or other materials provided
+// with the distribution.
+// * Neither the name of Google Inc. nor the names of its
+// contributors may be used to endorse or promote products derived
+// from this software without specific prior written permission.
+//
+// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+// (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
+// Test functionality of block scopes.
+
+// Hoisting of var declarations.
+function f1() {
+ {
+ var x = 1;
+ var y;
+ }
+ assertEquals(1, x)
+ assertEquals(undefined, y)
+}
+for (var j = 0; j < 5; ++j) f1();
+%OptimizeFunctionOnNextCall(f1);
+f1();
+assertTrue(%GetOptimizationStatus(f1) != 2);
+
+// Dynamic lookup in and through block contexts.
+function f2(one) {
+ var x = one + 1;
+ let y = one + 2;
+ const u = one + 4;
+ class a { static foo() { return one + 6; } }
+ {
+ let z = one + 3;
+ const v = one + 5;
+ class b { static foo() { return one + 7; } }
+ assertEquals(1, eval('one'));
+ assertEquals(2, eval('x'));
+ assertEquals(3, eval('y'));
+ assertEquals(4, eval('z'));
+ assertEquals(5, eval('u'));
+ assertEquals(6, eval('v'));
+ assertEquals(7, eval('a.foo()'));
+ assertEquals(8, eval('b.foo()'));
+ }
+}
+
+f2(1);
+
+// Lookup in and through block contexts.
+function f3(one) {
+ var x = one + 1;
+ let y = one + 2;
+ const u = one + 4;
+ class a { static foo() { return one + 6; } }
+ {
+ let z = one + 3;
+ const v = one + 5;
+ class b { static foo() { return one + 7; } }
+ assertEquals(1, one);
+ assertEquals(2, x);
+ assertEquals(3, y);
+ assertEquals(4, z);
+ assertEquals(5, u);
+ assertEquals(6, v);
+ assertEquals(7, a.foo());
+ assertEquals(8, b.foo());
+ }
+}
+for (var j = 0; j < 5; ++j) f3(1);
+%OptimizeFunctionOnNextCall(f3);
+f3(1);
+
+
+
+// Dynamic lookup from closure.
+function f4(one) {
+ var x = one + 1;
+ let y = one + 2;
+ const u = one + 4;
+ class a { static foo() { return one + 6; } }
+ {
+ let z = one + 3;
+ const v = one + 5;
+ class b { static foo() { return one + 7; } }
+ function f() {
+ assertEquals(1, eval('one'));
+ assertEquals(2, eval('x'));
+ assertEquals(3, eval('y'));
+ assertEquals(4, eval('z'));
+ assertEquals(5, eval('u'));
+ assertEquals(6, eval('v'));
+ assertEquals(7, eval('a.foo()'));
+ assertEquals(8, eval('b.foo()'));
+ }
+ f();
+ }
+}
+f4(1);
+
+
+// Lookup from closure.
+function f5(one) {
+ var x = one + 1;
+ let y = one + 2;
+ const u = one + 4;
+ class a { static foo() { return one + 6; } }
+ {
+ let z = one + 3;
+ const v = one + 5;
+ class b { static foo() { return one + 7; } }
+ function f() {
+ assertEquals(1, one);
+ assertEquals(2, x);
+ assertEquals(3, y);
+ assertEquals(4, z);
+ assertEquals(5, u);
+ assertEquals(6, v);
+ assertEquals(7, a.foo());
+ assertEquals(8, b.foo());
+ }
+ f();
+ }
+}
+f5(1);
+
+
+// Return from block.
+function f6() {
+ let x = 1;
+ const u = 3;
+ {
+ let y = 2;
+ const v = 4;
+ return x + y;
+ }
+}
+assertEquals(3, f6(6));
+
+
+// Variable shadowing and lookup.
+function f7(a) {
+ let b = 1;
+ var c = 1;
+ var d = 1;
+ const e = 1;
+ class f { static foo() { return 1; } }
+ { // let variables shadowing argument, let, const, class and var variables
+ let a = 2;
+ let b = 2;
+ let c = 2;
+ let e = 2;
+ let f = 2;
+ assertEquals(2,a);
+ assertEquals(2,b);
+ assertEquals(2,c);
+ assertEquals(2,e);
+ assertEquals(2,f);
+ }
+ { // const variables shadowing argument, let, const and var variables
+ const a = 2;
+ const b = 2;
+ const c = 2;
+ const e = 2;
+ const f = 2;
+ assertEquals(2,a);
+ assertEquals(2,b);
+ assertEquals(2,c);
+ assertEquals(2,e);
+ assertEquals(2,f);
+ }
+ { // class variables shadowing argument, let, const and var variables
+ class a { static foo() { return 2; } }
+ class b { static foo() { return 2; } }
+ class c { static foo() { return 2; } }
+ class d { static foo() { return 2; } }
+ class e { static foo() { return 2; } }
+ class f { static foo() { return 2; } }
+ assertEquals(2,a.foo());
+ assertEquals(2,b.foo());
+ assertEquals(2,c.foo());
+ assertEquals(2,e.foo());
+ assertEquals(2,f.foo());
+ }
+ try {
+ throw 'stuff1';
+ } catch (a) {
+ assertEquals('stuff1',a);
+ // catch variable shadowing argument
+ a = 2;
+ assertEquals(2,a);
+ {
+ // let variable shadowing catch variable
+ let a = 3;
+ assertEquals(3,a);
+ try {
+ throw 'stuff2';
+ } catch (a) {
+ assertEquals('stuff2',a);
+ // catch variable shadowing let variable
+ a = 4;
+ assertEquals(4,a);
+ }
+ assertEquals(3,a);
+ }
+ assertEquals(2,a);
+ }
+ try {
+ throw 'stuff3';
+ } catch (c) {
+ // catch variable shadowing var variable
+ assertEquals('stuff3',c);
+ {
+ // const variable shadowing catch variable
+ const c = 3;
+ assertEquals(3,c);
+ }
+ assertEquals('stuff3',c);
+ try {
+ throw 'stuff4';
+ } catch(c) {
+ assertEquals('stuff4',c);
+ // catch variable shadowing catch variable
+ c = 3;
+ assertEquals(3,c);
+ }
+ (function(c) {
+ // argument shadowing catch variable
+ c = 3;
+ assertEquals(3,c);
+ })();
+ assertEquals('stuff3', c);
+ (function() {
+ // var variable shadowing catch variable
+ var c = 3;
+ })();
+ assertEquals('stuff3', c);
+ c = 2;
+ }
+ assertEquals(1,c);
+ (function(a,b,c,e,f) {
+ // arguments shadowing argument, let, const, class and var variable
+ a = 2;
+ b = 2;
+ c = 2;
+ e = 2;
+ f = 2;
+ assertEquals(2,a);
+ assertEquals(2,b);
+ assertEquals(2,c);
+ assertEquals(2,e);
+ assertEquals(2,f);
+ // var variable shadowing var variable
+ var d = 2;
+ })(1,1);
+ assertEquals(1,a);
+ assertEquals(1,b);
+ assertEquals(1,c);
+ assertEquals(1,d);
+ assertEquals(1,e);
+ assertEquals(1,f.foo());
+}
+f7(1);
+
+
+// Ensure let and const variables are block local
+// and var variables function local.
+function f8() {
+ var let_accessors = [];
+ var var_accessors = [];
+ var const_accessors = [];
+ var class_accessors = [];
+ for (var i = 0; i < 10; i++) {
+ let x = i;
+ var y = i;
+ const z = i;
+ class a { static foo() { return x; } }
+ let_accessors[i] = function() { return x; }
+ var_accessors[i] = function() { return y; }
+ const_accessors[i] = function() { return z; }
+ class_accessors[i] = function() { return a; }
+ }
+ for (var j = 0; j < 10; j++) {
+ y = j + 10;
+ assertEquals(j, let_accessors[j]());
+ assertEquals(y, var_accessors[j]());
+ assertEquals(j, const_accessors[j]());
+ assertEquals(j, class_accessors[j]().foo());
+ }
+}
+f8();
diff --git a/test/mjsunit/es6/block-scoping-top-level-sloppy.js b/test/mjsunit/es6/block-scoping-top-level-sloppy.js
new file mode 100644
index 0000000..2a3b903
--- /dev/null
+++ b/test/mjsunit/es6/block-scoping-top-level-sloppy.js
@@ -0,0 +1,33 @@
+// 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: --min-preparse-length=0
+
+let xxx = 1;
+let f = undefined;
+{
+ let inner_x = xxx;
+ f = function() { return inner_x; };
+}
+
+assertSame(1, f());
+
+xxx = 42;
+{
+ f = function() { return inner_x1; };
+ let inner_x1 = xxx;
+}
+
+assertSame(42, f());
+
+xxx = 31;
+{
+ let inner_x1 = xxx;
+ try {
+ throw new Error();
+ } catch (e) {
+ f = function() { return inner_x1; };
+ }
+}
+assertSame(31, f());
diff --git a/test/mjsunit/es6/block-sloppy-function.js b/test/mjsunit/es6/block-sloppy-function.js
new file mode 100644
index 0000000..41063b4
--- /dev/null
+++ b/test/mjsunit/es6/block-sloppy-function.js
@@ -0,0 +1,298 @@
+// 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.
+
+// Test Annex B 3.3 semantics for functions declared in blocks in sloppy mode.
+// http://www.ecma-international.org/ecma-262/6.0/#sec-block-level-function-declarations-web-legacy-compatibility-semantics
+
+(function overridingLocalFunction() {
+ var x = [];
+ assertEquals('function', typeof f);
+ function f() {
+ x.push(1);
+ }
+ f();
+ {
+ f();
+ function f() {
+ x.push(2);
+ }
+ f();
+ }
+ f();
+ {
+ f();
+ function f() {
+ x.push(3);
+ }
+ f();
+ }
+ f();
+ assertArrayEquals([1, 2, 2, 2, 3, 3, 3], x);
+})();
+
+(function newFunctionBinding() {
+ var x = [];
+ assertEquals('undefined', typeof f);
+ {
+ f();
+ function f() {
+ x.push(2);
+ }
+ f();
+ }
+ f();
+ {
+ f();
+ function f() {
+ x.push(3);
+ }
+ f();
+ }
+ f();
+ assertArrayEquals([2, 2, 2, 3, 3, 3], x);
+})();
+
+(function shadowingLetDoesntBind() {
+ let f = 1;
+ assertEquals(1, f);
+ {
+ let y = 3;
+ function f() {
+ y = 2;
+ }
+ f();
+ assertEquals(2, y);
+ }
+ assertEquals(1, f);
+})();
+
+(function shadowingClassDoesntBind() {
+ class f { }
+ assertEquals('class f { }', f.toString());
+ {
+ let y = 3;
+ function f() {
+ y = 2;
+ }
+ f();
+ assertEquals(2, y);
+ }
+ assertEquals('class f { }', f.toString());
+})();
+
+(function shadowingConstDoesntBind() {
+ const f = 1;
+ assertEquals(1, f);
+ {
+ let y = 3;
+ function f() {
+ y = 2;
+ }
+ f();
+ assertEquals(2, y);
+ }
+ assertEquals(1, f);
+})();
+
+(function shadowingVarBinds() {
+ var f = 1;
+ assertEquals(1, f);
+ {
+ let y = 3;
+ function f() {
+ y = 2;
+ }
+ f();
+ assertEquals(2, y);
+ }
+ assertEquals('function', typeof f);
+})();
+
+(function conditional() {
+ if (true) {
+ function f() { return 1; }
+ } else {
+ function f() { return 2; }
+ }
+ assertEquals(1, f());
+
+ if (false) {
+ function g() { return 1; }
+ } else {
+ function g() { return 2; }
+ }
+ assertEquals(2, g());
+})();
+
+(function skipExecution() {
+ {
+ function f() { return 1; }
+ }
+ assertEquals(1, f());
+ {
+ function f() { return 2; }
+ }
+ assertEquals(2, f());
+ L: {
+ assertEquals(3, f());
+ break L;
+ function f() { return 3; }
+ }
+ assertEquals(2, f());
+})();
+
+// Test that shadowing arguments is fine
+(function shadowArguments(x) {
+ assertArrayEquals([1], arguments);
+ {
+ assertEquals('function', typeof arguments);
+ function arguments() {}
+ assertEquals('function', typeof arguments);
+ }
+ assertEquals('function', typeof arguments);
+})(1);
+
+// Shadow function parameter
+(function shadowParameter(x) {
+ assertEquals(1, x);
+ {
+ function x() {}
+ }
+ assertEquals('function', typeof x);
+})(1);
+
+// Shadow function parameter
+(function shadowDefaultParameter(x = 0) {
+ assertEquals(1, x);
+ {
+ function x() {}
+ }
+ // TODO(littledan): Once destructured parameters are no longer
+ // let-bound, enable this assertion. This is the core of the test.
+ // assertEquals('function', typeof x);
+})(1);
+
+(function shadowRestParameter(...x) {
+ assertArrayEquals([1], x);
+ {
+ function x() {}
+ }
+ // TODO(littledan): Once destructured parameters are no longer
+ // let-bound, enable this assertion. This is the core of the test.
+ // assertEquals('function', typeof x);
+})(1);
+
+assertThrows(function notInDefaultScope(x = y) {
+ {
+ function y() {}
+ }
+ assertEquals('function', typeof y);
+ assertEquals(x, undefined);
+}, ReferenceError);
+
+// Test that hoisting from blocks does happen in global scope
+function globalHoisted() { return 0; }
+{
+ function globalHoisted() { return 1; }
+}
+assertEquals(1, globalHoisted());
+
+// Also happens when not previously defined
+assertEquals(undefined, globalUndefinedHoisted);
+{
+ function globalUndefinedHoisted() { return 1; }
+}
+assertEquals(1, globalUndefinedHoisted());
+var globalUndefinedHoistedDescriptor =
+ Object.getOwnPropertyDescriptor(this, "globalUndefinedHoisted");
+assertFalse(globalUndefinedHoistedDescriptor.configurable);
+assertTrue(globalUndefinedHoistedDescriptor.writable);
+assertTrue(globalUndefinedHoistedDescriptor.enumerable);
+assertEquals(1, globalUndefinedHoistedDescriptor.value());
+
+// When a function property is hoisted, it should be
+// made enumerable.
+// BUG(v8:4451)
+Object.defineProperty(this, "globalNonEnumerable", {
+ value: false,
+ configurable: true,
+ writable: true,
+ enumerable: false
+});
+eval("{function globalNonEnumerable() { return 1; }}");
+var globalNonEnumerableDescriptor
+ = Object.getOwnPropertyDescriptor(this, "globalNonEnumerable");
+// BUG(v8:4451): Should be made non-configurable
+assertTrue(globalNonEnumerableDescriptor.configurable);
+assertTrue(globalNonEnumerableDescriptor.writable);
+// BUG(v8:4451): Should be made enumerable
+assertFalse(globalNonEnumerableDescriptor.enumerable);
+assertEquals(1, globalNonEnumerableDescriptor.value());
+
+// When a function property is hoisted, it should be overwritten and
+// made writable and overwritten, even if the property was non-writable.
+Object.defineProperty(this, "globalNonWritable", {
+ value: false,
+ configurable: true,
+ writable: false,
+ enumerable: true
+});
+eval("{function globalNonWritable() { return 1; }}");
+var globalNonWritableDescriptor
+ = Object.getOwnPropertyDescriptor(this, "globalNonWritable");
+// BUG(v8:4451): Should be made non-configurable
+assertTrue(globalNonWritableDescriptor.configurable);
+// BUG(v8:4451): Should be made writable
+assertFalse(globalNonWritableDescriptor.writable);
+assertFalse(globalNonEnumerableDescriptor.enumerable);
+// BUG(v8:4451): Should be overwritten
+assertEquals(false, globalNonWritableDescriptor.value);
+
+// Test that hoisting from blocks does happen in an eval
+eval(`
+ function evalHoisted() { return 0; }
+ {
+ function evalHoisted() { return 1; }
+ }
+ assertEquals(1, evalHoisted());
+`);
+
+// Test that hoisting from blocks happens from eval in a function
+!function() {
+ eval(`
+ function evalInFunctionHoisted() { return 0; }
+ {
+ function evalInFunctionHoisted() { return 1; }
+ }
+ assertEquals(1, evalInFunctionHoisted());
+ `);
+}();
+
+let dontHoistGlobal;
+{ function dontHoistGlobal() {} }
+assertEquals(undefined, dontHoistGlobal);
+
+let dontHoistEval;
+// BUG(v8:) This shouldn't hoist and shouldn't throw
+var throws = false;
+try {
+ eval("{ function dontHoistEval() {} }");
+} catch (e) {
+ throws = true;
+}
+assertTrue(throws);
+
+// When the global object is frozen, silently don't hoist
+// Currently this actually throws BUG(v8:4452)
+Object.freeze(this);
+throws = false;
+try {
+ eval('{ function hoistWhenFrozen() {} }');
+} catch (e) {
+ throws = true;
+}
+assertFalse(this.hasOwnProperty("hoistWhenFrozen"));
+assertThrows(() => hoistWhenFrozen, ReferenceError);
+// Should be assertFalse BUG(v8:4452)
+assertTrue(throws);
diff --git a/test/mjsunit/es6/class-computed-property-names-super.js b/test/mjsunit/es6/class-computed-property-names-super.js
index cb9f251..b5a2ac9 100644
--- a/test/mjsunit/es6/class-computed-property-names-super.js
+++ b/test/mjsunit/es6/class-computed-property-names-super.js
@@ -2,7 +2,6 @@
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
-// Flags: --harmony-sloppy
// Flags: --allow-natives-syntax
diff --git a/test/mjsunit/es6/class-property-name-eval-arguments.js b/test/mjsunit/es6/class-property-name-eval-arguments.js
index 72ff60f..bbd05cc 100644
--- a/test/mjsunit/es6/class-property-name-eval-arguments.js
+++ b/test/mjsunit/es6/class-property-name-eval-arguments.js
@@ -2,8 +2,6 @@
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
-// Flags: --harmony-sloppy
-
(function Method() {
class C {
diff --git a/test/mjsunit/es6/classes-derived-return-type.js b/test/mjsunit/es6/classes-derived-return-type.js
index 8283bcb..3f81a34 100644
--- a/test/mjsunit/es6/classes-derived-return-type.js
+++ b/test/mjsunit/es6/classes-derived-return-type.js
@@ -2,8 +2,6 @@
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
-// Flags: --harmony-sloppy
-
class Base {}
diff --git a/test/mjsunit/es6/classes.js b/test/mjsunit/es6/classes.js
index 4dabda8..fb77dbb 100644
--- a/test/mjsunit/es6/classes.js
+++ b/test/mjsunit/es6/classes.js
@@ -2,8 +2,7 @@
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
-// Flags: --harmony-sloppy --harmony-function-name --allow-natives-syntax
-// Flags: --harmony-do-expressions
+// Flags: --allow-natives-syntax --harmony-do-expressions
(function TestBasics() {
var C = class C {}
diff --git a/test/mjsunit/es6/completion.js b/test/mjsunit/es6/completion.js
index 7559514..988e970 100644
--- a/test/mjsunit/es6/completion.js
+++ b/test/mjsunit/es6/completion.js
@@ -2,8 +2,6 @@
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
-// Flags: --harmony-sloppy-let
-
function assertUndef(x) {
assertEquals(undefined, x);
diff --git a/test/mjsunit/es6/debug-blockscopes.js b/test/mjsunit/es6/debug-blockscopes.js
index 193ad70..bf04a0a 100644
--- a/test/mjsunit/es6/debug-blockscopes.js
+++ b/test/mjsunit/es6/debug-blockscopes.js
@@ -52,6 +52,7 @@
listener_delegate(exec_state);
}
} catch (e) {
+ print(e, e.stack);
exception = e;
}
}
@@ -147,10 +148,8 @@
if (!scope.scopeObject().property('arguments').isUndefined()) {
scope_size--;
}
- // Skip property with empty name.
- if (!scope.scopeObject().property('').isUndefined()) {
- scope_size--;
- }
+ // Temporary variables introduced by the parser have not been materialized.
+ assertTrue(scope.scopeObject().property('').isUndefined());
if (count != scope_size) {
print('Names found in scope:');
@@ -380,16 +379,12 @@
listener_delegate = function(exec_state) {
CheckScopeChain([debug.ScopeType.Block,
- debug.ScopeType.Block,
debug.ScopeType.Local,
debug.ScopeType.Script,
debug.ScopeType.Global], exec_state);
CheckScopeContent({x:'y'}, 0, exec_state);
// The function scope contains a temporary iteration variable, but it is
// hidden to the debugger.
- // TODO(adamk): This variable is only used to provide a TDZ for the enumerable
- // expression and should not be visible to the debugger.
- CheckScopeContent({x:undefined}, 1, exec_state);
};
for_loop_1();
EndTest();
@@ -409,7 +404,6 @@
listener_delegate = function(exec_state) {
CheckScopeChain([debug.ScopeType.Block,
debug.ScopeType.Block,
- debug.ScopeType.Block,
debug.ScopeType.Local,
debug.ScopeType.Script,
debug.ScopeType.Global], exec_state);
@@ -417,9 +411,6 @@
CheckScopeContent({x:'y'}, 1, exec_state);
// The function scope contains a temporary iteration variable, hidden to the
// debugger.
- // TODO(adamk): This variable is only used to provide a TDZ for the enumerable
- // expression and should not be visible to the debugger.
- CheckScopeContent({x:undefined}, 2, exec_state);
};
for_loop_2();
EndTest();
@@ -436,13 +427,11 @@
listener_delegate = function(exec_state) {
CheckScopeChain([debug.ScopeType.Block,
- debug.ScopeType.Block,
debug.ScopeType.Local,
debug.ScopeType.Script,
debug.ScopeType.Global], exec_state);
CheckScopeContent({x:3}, 0, exec_state);
- CheckScopeContent({x:3}, 1, exec_state);
- CheckScopeContent({}, 2, exec_state);
+ CheckScopeContent({}, 1, exec_state);
};
for_loop_3();
EndTest();
@@ -461,14 +450,12 @@
listener_delegate = function(exec_state) {
CheckScopeChain([debug.ScopeType.Block,
debug.ScopeType.Block,
- debug.ScopeType.Block,
debug.ScopeType.Local,
debug.ScopeType.Script,
debug.ScopeType.Global], exec_state);
CheckScopeContent({x:5}, 0, exec_state);
CheckScopeContent({x:3}, 1, exec_state);
- CheckScopeContent({x:3}, 2, exec_state);
- CheckScopeContent({}, 3, exec_state);
+ CheckScopeContent({}, 2, exec_state);
};
for_loop_4();
EndTest();
@@ -485,13 +472,11 @@
listener_delegate = function(exec_state) {
CheckScopeChain([debug.ScopeType.Block,
- debug.ScopeType.Block,
debug.ScopeType.Local,
debug.ScopeType.Script,
debug.ScopeType.Global], exec_state);
CheckScopeContent({x:3,y:5}, 0, exec_state);
- CheckScopeContent({x:3,y:5}, 1, exec_state);
- CheckScopeContent({}, 2, exec_state);
+ CheckScopeContent({}, 1, exec_state);
};
for_loop_5();
EndTest();
diff --git a/test/mjsunit/es6/debug-evaluate-receiver-before-super.js b/test/mjsunit/es6/debug-evaluate-receiver-before-super.js
new file mode 100644
index 0000000..dc8ce2c
--- /dev/null
+++ b/test/mjsunit/es6/debug-evaluate-receiver-before-super.js
@@ -0,0 +1,39 @@
+// 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: --expose-debug-as debug
+
+// Test that debug-evaluate doesn't crash when this is used before super() call
+// in constructor.
+
+Debug = debug.Debug
+
+var result;
+
+function listener(event, exec_state, event_data, data)
+{
+ try {
+ if (event == Debug.DebugEvent.Break) {
+ result = exec_state.frame(0).evaluate("this.a").value();
+ }
+ } catch (e) {
+ result = e.message;
+ }
+}
+
+Debug.setListener(listener);
+
+class A { constructor () { this.a = 239; } }
+class B extends A {
+ constructor () {
+ debugger;
+ assertEquals("Cannot read property 'a' of undefined", result);
+ super();
+ debugger;
+ assertEquals(239, result);
+ }
+}
+new B();
+
+Debug.setListener(null);
diff --git a/test/mjsunit/es6/debug-promises/stepin-constructor.js b/test/mjsunit/es6/debug-promises/stepin-constructor.js
index 906969e..6914ae0 100644
--- a/test/mjsunit/es6/debug-promises/stepin-constructor.js
+++ b/test/mjsunit/es6/debug-promises/stepin-constructor.js
@@ -21,9 +21,9 @@
Debug.setListener(listener);
function resolver(resolve, reject) {
- 1;
- 2;
- 3;
+ print(1);
+ print(2);
+ print(3);
resolve();
}
@@ -35,9 +35,9 @@
var expected_breaks = [
"debugger;",
"var p = new Promise(resolver);",
- "1;",
- "2;",
- "3;",
+ "print(1);",
+ "print(2);",
+ "print(3);",
"resolve();",
"}",
"Debug.setListener(null);"
diff --git a/test/mjsunit/es6/debug-scope-default-param-with-eval.js b/test/mjsunit/es6/debug-scope-default-param-with-eval.js
new file mode 100644
index 0000000..d4dc93f
--- /dev/null
+++ b/test/mjsunit/es6/debug-scope-default-param-with-eval.js
@@ -0,0 +1,61 @@
+// 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: --expose-debug-as debug
+
+// Test that the parameter initialization block scope set up for
+// sloppy eval is visible to the debugger.
+
+var Debug = debug.Debug;
+var exception = null;
+var break_count = 0;
+
+function call_for_break() {
+ return 5;
+}
+
+function test(x = eval("var y = 7; debugger; y") + call_for_break()) {
+ return x;
+}
+
+function listener(event, exec_state, event_data, data) {
+ if (event != Debug.DebugEvent.Break) return;
+ try {
+ var frame = exec_state.frame(0);
+ var block_scope;
+ if (break_count++ == 0) {
+ // Inside eval.
+ assertEquals([ debug.ScopeType.Eval,
+ debug.ScopeType.Block,
+ debug.ScopeType.Closure,
+ debug.ScopeType.Script,
+ debug.ScopeType.Global ],
+ frame.allScopes().map(s => s.scopeType()));
+ exec_state.prepareStep(Debug.StepAction.StepOut);
+ block_scope = frame.scope(1);
+ } else {
+ // Outside of eval.
+ assertEquals([ debug.ScopeType.Block,
+ debug.ScopeType.Local,
+ debug.ScopeType.Script,
+ debug.ScopeType.Global ],
+ frame.allScopes().map(s => s.scopeType()));
+ block_scope = frame.scope(0);
+ }
+ assertTrue(block_scope.scopeObject().propertyNames().includes('y'));
+ assertEquals(7, block_scope.scopeObject().property('y').value().value());
+ } catch (e) {
+ print(e);
+ exception = e;
+ }
+}
+
+Debug.setListener(listener);
+
+assertEquals(12, test());
+
+Debug.setListener(null);
+
+assertNull(exception);
+assertEquals(2, break_count);
diff --git a/test/mjsunit/es6/debug-stepin-microtasks.js b/test/mjsunit/es6/debug-stepin-microtasks.js
index 6a7c553..e541f0f 100644
--- a/test/mjsunit/es6/debug-stepin-microtasks.js
+++ b/test/mjsunit/es6/debug-stepin-microtasks.js
@@ -2,7 +2,6 @@
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
-// Flags: --harmony-object-observe
// Flags: --allow-natives-syntax --expose-debug-as debug
Debug = debug.Debug
@@ -46,6 +45,7 @@
.then(Boolean) // Should skip stepping into native.
.then(promise2)
.catch(promise3)
+ .then(promise4)
.catch(function(e) {
%AbortJS("FAIL: uncaught exception " + e);
});
@@ -60,36 +60,16 @@
}
function promise3() {
- installObservers(); // Break 4. StepOver.
- return break_count; // Break 5.
-} // Break 6.
-
-function installObservers() {
- var dummy = {};
- Object.observe(dummy, observer1);
- Object.observe(dummy, Object); // Should skip stepping into native.
- Object.observe(dummy, Boolean); // Should skip stepping into native.
- Object.observe(dummy, observer2);
- dummy.foo = 1;
-}
-
-function observer1() {
- return exception || 3; // Break 7.
-} // Break 8.
-
-function observer2() {
- Promise.resolve().then(promise4); // Break 9. StepOver.
- return break_count + 1; // Break 10.
-} // Break 11.
+ return break_count; // Break 4.
+} // Break 5.
function promise4() {
- finalize(); // Break 12. StepOver.
- return 0; // Break 13.
-} // Break 14. StepOver.
+ finalize(); // Break 6. StepOver.
+ return 0; // Break 7.
+} // Break 8. StepOver.
function finalize() {
- var dummy = {};
- Object.observe(dummy, function() {
+ Promise.resolve().then(function() {
if (expected_breaks !== break_count) {
%AbortJS("FAIL: expected <" + expected_breaks + "> breaks instead of <" +
break_count + ">");
@@ -98,5 +78,4 @@
%AbortJS("FAIL: exception: " + exception);
}
});
- dummy.foo = 1;
}
diff --git a/test/mjsunit/es6/debug-stepin-proxies.js b/test/mjsunit/es6/debug-stepin-proxies.js
index 4e71c79..72c01f0 100644
--- a/test/mjsunit/es6/debug-stepin-proxies.js
+++ b/test/mjsunit/es6/debug-stepin-proxies.js
@@ -54,7 +54,7 @@
assertEquals([
"a0",
- "b17", "h4b20", "i2b20", // [[Has]]
+ "b17", "h4b17", "i2b17", // [[Has]]
"c15", "j4c15", "k2c15", // [[Get]]
"d0", "l4d11", "m2d11", // [[Set]]
"g0"
diff --git a/test/mjsunit/es6/debug-stepnext-for.js b/test/mjsunit/es6/debug-stepnext-for.js
index 9d5641a..d425a46 100644
--- a/test/mjsunit/es6/debug-stepnext-for.js
+++ b/test/mjsunit/es6/debug-stepnext-for.js
@@ -11,6 +11,8 @@
var s = 0;
var a = [1, 2, 3];
+var b = [1, 2, 3, 4];
+var null_value = null;
var i = 0;
function f() {
@@ -18,11 +20,11 @@
debugger; // Break a
var j; // Break b
- for (var i in null) { // Break c
+ for (var i in null_value) { // Break c
s += a[i];
}
- for (j in null) { // Break d
+ for (j in null_value) { // Break d
s += a[j];
}
@@ -46,7 +48,7 @@
s += j; // Break I
}
- for (let i of a) { // Break j
+ for (let i of a) { // Break j
s += i; // Break J
}
@@ -61,6 +63,11 @@
for (let i = 0; i < 3; i++) { // Break m
s += a[i]; // Break M
}
+
+ for (let i of a) {} // Break n
+
+ [1, ...a] // Break o
+
} // Break y
function listener(event, exec_state, event_data, data) {
@@ -103,17 +110,21 @@
// For-in-let: get enumerable, next, body, next, ...
"g16","g11","G4","g11","G4","g11","G4","g11",
// For-of-var: [Symbol.iterator](), next(), body, next(), body, ...
- "h16","h14","h15","H4","h15","H4","h15","H4","h15",
+ "h16","h13","H4","h13","H4","h13","H4","h13",
// For-of: [Symbol.iterator](), next(), body, next(), body, ...
- "i12","i10","i11","I4","i11","I4","i11","I4","i11",
+ "i12","i9","I4","i9","I4","i9","I4","i9",
// For-of-let: [Symbol.iterator](), next(), body, next(), ...
- "j16","j14","j15","J4","j15","J4","j15","J4","j15",
+ "j18","j14","J4","j14","J4","j14","J4","j14",
// For-var: init, condition, body, next, condition, body, ...
"k15","k20","K4","k26","k20","K4","k26","k20","K4","k26","k20",
// For: init, condition, body, next, condition, body, ...
"l7","l16","L4","l22","l16","L4","l22","l16","L4","l22","l16",
// For-let: init, condition, body, next, condition, body, ...
"m15","m20","M4","m26","m20","M4","m26","m20","M4","m26","m20",
+ // For-of, empty: [Symbol.iterator](), next() once
+ "n16", "n13",
+ // Spread: expression statement, spread
+ "o2", "o9",
// Exit.
"y0","z0",
]
diff --git a/test/mjsunit/es6/generators-objects.js b/test/mjsunit/es6/generators-objects.js
index a0c3b80..2d23841 100644
--- a/test/mjsunit/es6/generators-objects.js
+++ b/test/mjsunit/es6/generators-objects.js
@@ -87,3 +87,29 @@
TestNonGenerator(g.prototype);
}
TestGeneratorObjectMethods();
+
+
+function TestPrototype() {
+ function* g() { }
+
+ let g_prototype = g.prototype;
+ assertEquals([], Reflect.ownKeys(g_prototype));
+
+ let generator_prototype = Object.getPrototypeOf(g_prototype);
+ assertSame(generator_prototype, Object.getPrototypeOf(g).prototype);
+
+ // Unchanged .prototype
+ assertSame(g_prototype, Object.getPrototypeOf(g()));
+
+ // Custom object as .prototype
+ {
+ let proto = {};
+ g.prototype = proto;
+ assertSame(proto, Object.getPrototypeOf(g()));
+ }
+
+ // Custom non-object as .prototype
+ g.prototype = null;
+ assertSame(generator_prototype, Object.getPrototypeOf(g()));
+}
+TestPrototype();
diff --git a/test/mjsunit/es6/microtask-delivery.js b/test/mjsunit/es6/microtask-delivery.js
index 01b971d..6b239be 100644
--- a/test/mjsunit/es6/microtask-delivery.js
+++ b/test/mjsunit/es6/microtask-delivery.js
@@ -25,7 +25,6 @@
// (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: --harmony-object-observe
// Flags: --allow-natives-syntax
var ordering = [];
@@ -71,22 +70,6 @@
};
}
-function newObserver(id, fn, obj) {
- var observer = {
- value: 1,
- recordCounts: []
- };
-
- Object.observe(observer, function(records) {
- ordering.push('o' + id);
- observer.recordCounts.push(records.length);
- if (fn) fn();
- });
-
- return observer;
-}
-
-
(function PromiseThens() {
reset();
@@ -98,72 +81,3 @@
assertOrdering(['p1', 'p2', 'p1:1', 'p2:1']);
})();
-
-
-(function ObserversBatch() {
- reset();
-
- var p1 = newPromise(1);
- var p2 = newPromise(2);
- var p3 = newPromise(3);
-
- var ob1 = newObserver(1);
- var ob2 = newObserver(2, function() {
- ob3.value++;
- p3.resolve();
- ob1.value++;
- });
- var ob3 = newObserver(3);
-
- p1.resolve();
- ob1.value++;
- p2.resolve();
- ob2.value++;
-
- assertOrdering(['p1', 'o1', 'o2', 'p2', 'o1', 'o3', 'p3']);
- assertArrayValues([1, 1], ob1.recordCounts);
- assertArrayValues([1], ob2.recordCounts);
- assertArrayValues([1], ob3.recordCounts);
-})();
-
-
-(function ObserversGetAllRecords() {
- reset();
-
- var p1 = newPromise(1);
- var p2 = newPromise(2);
- var ob1 = newObserver(1, function() {
- ob2.value++;
- });
- var ob2 = newObserver(2);
-
- p1.resolve();
- ob1.value++;
- p2.resolve();
- ob2.value++;
-
- assertOrdering(['p1', 'o1', 'o2', 'p2']);
- assertArrayValues([1], ob1.recordCounts);
- assertArrayValues([2], ob2.recordCounts);
-})();
-
-
-(function NewObserverDeliveryGetsNewMicrotask() {
- reset();
-
- var p1 = newPromise(1);
- var p2 = newPromise(2);
- var ob1 = newObserver(1);
- var ob2 = newObserver(2, function() {
- ob1.value++;
- });
-
- p1.resolve();
- ob1.value++;
- p2.resolve();
- ob2.value++;
-
- assertOrdering(['p1', 'o1', 'o2', 'p2', 'o1']);
- assertArrayValues([1, 1], ob1.recordCounts);
- assertArrayValues([1], ob2.recordCounts);
-})();
diff --git a/test/mjsunit/es6/mirror-collections.js b/test/mjsunit/es6/mirror-collections.js
index 81a98b8..4232ef9 100644
--- a/test/mjsunit/es6/mirror-collections.js
+++ b/test/mjsunit/es6/mirror-collections.js
@@ -88,16 +88,21 @@
assertSame(o2, values[0]);
assertEquals(undefined, values[1]);
+function initWeakMap(weakMap) {
+ weakMap.set(o1, 11);
+ weakMap.set(new Object(), 22);
+ weakMap.set(o3, 33);
+ weakMap.set(new Object(), 44);
+ var weakMapMirror = debug.MakeMirror(weakMap);
+ testMapMirror(weakMapMirror);
+ weakMap.set(new Object(), 55);
+ assertTrue(weakMapMirror.entries().length <= 5);
+ return weakMapMirror;
+}
+
// Test the mirror object for WeakMaps
var weakMap = new WeakMap();
-weakMap.set(o1, 11);
-weakMap.set(new Object(), 22);
-weakMap.set(o3, 33);
-weakMap.set(new Object(), 44);
-var weakMapMirror = debug.MakeMirror(weakMap);
-testMapMirror(weakMapMirror);
-weakMap.set(new Object(), 55);
-assertTrue(weakMapMirror.entries().length <= 5);
+var weakMapMirror = initWeakMap(weakMap);
gc();
function testWeakMapEntries(weakMapMirror) {
@@ -121,18 +126,23 @@
testWeakMapEntries(weakMapMirror);
+function initWeakSet(weakSet) {
+ weakSet.add(o1);
+ weakSet.add(new Object());
+ weakSet.add(o2);
+ weakSet.add(new Object());
+ weakSet.add(new Object());
+ weakSet.add(o3);
+ weakSet.delete(o2);
+ var weakSetMirror = debug.MakeMirror(weakSet);
+ testSetMirror(weakSetMirror);
+ assertTrue(weakSetMirror.values().length <= 5);
+ return weakSetMirror;
+}
+
// Test the mirror object for WeakSets
var weakSet = new WeakSet();
-weakSet.add(o1);
-weakSet.add(new Object());
-weakSet.add(o2);
-weakSet.add(new Object());
-weakSet.add(new Object());
-weakSet.add(o3);
-weakSet.delete(o2);
-var weakSetMirror = debug.MakeMirror(weakSet);
-testSetMirror(weakSetMirror);
-assertTrue(weakSetMirror.values().length <= 5);
+var weakSetMirror = initWeakSet(weakSet);
gc();
function testWeakSetValues(weakSetMirror) {
diff --git a/test/mjsunit/es6/proxies-for.js b/test/mjsunit/es6/proxies-for.js
index 5b81845..a171227 100644
--- a/test/mjsunit/es6/proxies-for.js
+++ b/test/mjsunit/es6/proxies-for.js
@@ -209,10 +209,15 @@
assertThrowsEquals(() => {keys(proxy)}, "error");
})();
-
-(function () {
- var symbol = Symbol();
- var p = new Proxy({}, {ownKeys() { return ["1", symbol, "2"] }});
- assertEquals(["1","2"], Object.getOwnPropertyNames(p));
- assertEquals([symbol], Object.getOwnPropertySymbols(p));
+(function testNestedProxy() {
+ var handler = {
+ ownKeys() {
+ return ['c'];
+ },
+ getOwnPropertyDescriptor() { return {configurable: true, enumerable: true } }
+ }
+ var proxy = new Proxy({}, handler);
+ var proxy2 = new Proxy(proxy, {});
+ assertEquals(['c'], keys(proxy));
+ assertEquals(['c'], keys(proxy2));
})();
diff --git a/test/mjsunit/es6/proxies-keys.js b/test/mjsunit/es6/proxies-keys.js
index 7344032..65dea6a 100644
--- a/test/mjsunit/es6/proxies-keys.js
+++ b/test/mjsunit/es6/proxies-keys.js
@@ -37,3 +37,14 @@
handler.ownKeys = undefined;
assertEquals(["target"], Object.keys(proxy));
assertEquals(["target"], Object.keys(target));
+
+var proxy2 = new Proxy(proxy, {});
+assertEquals(["target"], Object.keys(proxy2));
+
+
+(function testForSymbols() {
+ var symbol = Symbol();
+ var p = new Proxy({}, {ownKeys() { return ["1", symbol, "2"] }});
+ assertEquals(["1","2"], Object.getOwnPropertyNames(p));
+ assertEquals([symbol], Object.getOwnPropertySymbols(p));
+})();
diff --git a/test/mjsunit/es6/reflect-define-property.js b/test/mjsunit/es6/reflect-define-property.js
index b19c5aa..d62a934 100644
--- a/test/mjsunit/es6/reflect-define-property.js
+++ b/test/mjsunit/es6/reflect-define-property.js
@@ -441,8 +441,7 @@
}
-// Test runtime calls to DefineDataPropertyUnchecked and
-// DefineAccessorPropertyUnchecked - make sure we don't
+// Test runtime calls to DefineAccessorPropertyUnchecked - make sure we don't
// crash.
try {
%DefineAccessorPropertyUnchecked(0, 0, 0, 0, 0);
@@ -451,29 +450,11 @@
}
try {
- %DefineDataPropertyUnchecked(0, 0, 0, 0);
-} catch (e) {
- assertTrue(/illegal access/.test(e));
-}
-
-try {
- %DefineDataPropertyUnchecked(null, null, null, null);
-} catch (e) {
- assertTrue(/illegal access/.test(e));
-}
-
-try {
%DefineAccessorPropertyUnchecked(null, null, null, null, null);
} catch (e) {
assertTrue(/illegal access/.test(e));
}
-try {
- %DefineDataPropertyUnchecked({}, null, null, null);
-} catch (e) {
- assertTrue(/illegal access/.test(e));
-}
-
// Defining properties null should fail even when we have
// other allowed values
try {
@@ -482,12 +463,6 @@
assertTrue(/illegal access/.test(e));
}
-try {
- %DefineDataPropertyUnchecked(null, 'foo', 0, 0);
-} catch (e) {
- assertTrue(/illegal access/.test(e));
-}
-
// Test that all possible differences in step 6 in DefineOwnProperty are
// exercised, i.e., any difference in the given property descriptor and the
// existing properties should not return true, but throw an error if the
diff --git a/test/mjsunit/es6/regress/regress-3750.js b/test/mjsunit/es6/regress/regress-3750.js
deleted file mode 100644
index 10509bf..0000000
--- a/test/mjsunit/es6/regress/regress-3750.js
+++ /dev/null
@@ -1,9 +0,0 @@
-// Copyright 2014 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-object-observe
-
-'use strict';
-class Example { }
-Object.observe(Example.prototype, function(){});
diff --git a/test/mjsunit/es6/regress/regress-4482.js b/test/mjsunit/es6/regress/regress-4482.js
new file mode 100644
index 0000000..d813d21
--- /dev/null
+++ b/test/mjsunit/es6/regress/regress-4482.js
@@ -0,0 +1,7 @@
+// 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.
+
+assertEquals("function", (function f() { f = 42; return typeof f })());
+assertEquals("function",
+ (function* g() { g = 42; yield typeof g })().next().value);
diff --git a/test/mjsunit/es6/regress/regress-468661.js b/test/mjsunit/es6/regress/regress-468661.js
index 4a42350..4a58a71 100644
--- a/test/mjsunit/es6/regress/regress-468661.js
+++ b/test/mjsunit/es6/regress/regress-468661.js
@@ -9,7 +9,8 @@
var break_count = 0;
var expected_values =
- [ReferenceError, undefined, 0, 0, 0, 0, 1, ReferenceError, ReferenceError];
+ [ReferenceError, undefined, 0, 0, 0, 0, 1,
+ ReferenceError, ReferenceError];
function listener(event, exec_state, event_data, data) {
try {
@@ -39,7 +40,6 @@
assertTrue(v instanceof ReferenceError);
} else {
assertSame(expected_values[break_count], v);
-
}
++break_count;
diff --git a/test/mjsunit/es6/spread-call-new-class.js b/test/mjsunit/es6/spread-call-new-class.js
index 1fdf25b..de88cff 100644
--- a/test/mjsunit/es6/spread-call-new-class.js
+++ b/test/mjsunit/es6/spread-call-new-class.js
@@ -2,8 +2,6 @@
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
-// Flags: --harmony-sloppy
-
(function testConstructClassStrict() {
"use strict";
diff --git a/test/mjsunit/es6/spread-call-super-property.js b/test/mjsunit/es6/spread-call-super-property.js
index b298a69..a85ea41 100644
--- a/test/mjsunit/es6/spread-call-super-property.js
+++ b/test/mjsunit/es6/spread-call-super-property.js
@@ -2,8 +2,6 @@
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
-// Flags: --harmony-sloppy
-
(function testCallSuperPropertyStrict() {
"use strict";
class BaseClass {
diff --git a/test/mjsunit/es6/super.js b/test/mjsunit/es6/super.js
index a2ba1e8..4c80ce7 100644
--- a/test/mjsunit/es6/super.js
+++ b/test/mjsunit/es6/super.js
@@ -3,7 +3,6 @@
// found in the LICENSE file.
// Flags: --allow-natives-syntax
-// Flags: --harmony-sloppy
(function TestSuperNamedLoads() {
function Base() { }
diff --git a/test/mjsunit/es6/tail-call.js b/test/mjsunit/es6/tail-call.js
index d0d00f4..6ecf04f 100644
--- a/test/mjsunit/es6/tail-call.js
+++ b/test/mjsunit/es6/tail-call.js
@@ -3,6 +3,8 @@
// found in the LICENSE file.
// Flags: --allow-natives-syntax --harmony-tailcalls
+// Flags: --harmony-do-expressions
+
"use strict";
Error.prepareStackTrace = (error,stack) => {
@@ -259,9 +261,8 @@
}
%NeverOptimizeFunction(g);
- var context = 10;
function f(v) {
- return g(context);
+ return g();
}
%SetForceInlineFlag(f);
@@ -319,10 +320,57 @@
return f([f, g3, test], 13), f([f, test], 153);
}
+ function g4(a) {
+ return f([f, g4, test], false) ||
+ (f([f, g4, test], true) && f([f, test], true));
+ }
+
+ function g5(a) {
+ return f([f, g5, test], true) &&
+ (f([f, g5, test], false) || f([f, test], true));
+ }
+
+ function g6(a) {
+ return f([f, g6, test], 13), f([f, g6, test], 42),
+ f([f, test], 153);
+ }
+
+ function g7(a) {
+ return f([f, g7, test], false) ||
+ (f([f, g7, test], false) ? f([f, test], true)
+ : f([f, test], true));
+ }
+
+ function g8(a) {
+ return f([f, g8, test], false) || f([f, g8, test], true) &&
+ f([f, test], true);
+ }
+
+ function g9(a) {
+ return f([f, g9, test], true) && f([f, g9, test], false) ||
+ f([f, test], true);
+ }
+
+ function g10(a) {
+ return f([f, g10, test], true) && f([f, g10, test], false) ||
+ f([f, g10, test], true) ?
+ f([f, g10, test], true) && f([f, g10, test], false) ||
+ f([f, test], true) :
+ f([f, g10, test], true) && f([f, g10, test], false) ||
+ f([f, test], true);
+ }
+
function test() {
assertEquals(true, g1());
assertEquals(true, g2());
assertEquals(153, g3());
+ assertEquals(true, g4());
+ assertEquals(true, g5());
+ assertEquals(153, g6());
+ assertEquals(true, g7());
+ assertEquals(true, g8());
+ assertEquals(true, g9());
+ assertEquals(true, g10());
}
test();
test();
@@ -534,9 +582,34 @@
return (() => f_153([f_153, test]))();
}
+ function g3(a) {
+ var closure = () => f([f, closure, test], true)
+ ? f_153([f_153, test])
+ : f_153([f_153, test]);
+ return closure();
+ }
+
function test() {
assertEquals(153, g1());
assertEquals(153, g2());
+ assertEquals(153, g3());
+ }
+ test();
+ test();
+ %OptimizeFunctionOnNextCall(test);
+ test();
+})();
+
+
+// Test tail calls from do expressions.
+(function () {
+ function g1(a) {
+ var a = do { return f_153([f_153, test]); 42; };
+ return a;
+ }
+
+ function test() {
+ assertEquals(153, g1());
}
test();
test();