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();