Import Cobalt 13.102542

Change-Id: I6bda7b03a2e33edfd735efcb981e2a731696b90d
diff --git a/src/v8/test/debugger/debug/es6/debug-blockscopes.js b/src/v8/test/debugger/debug/es6/debug-blockscopes.js
new file mode 100644
index 0000000..1cb279b
--- /dev/null
+++ b/src/v8/test/debugger/debug/es6/debug-blockscopes.js
@@ -0,0 +1,487 @@
+// 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: --noanalyze-environment-liveness --opt
+// The functions used for testing backtraces. They are at the top to make the
+// testing of source line/column easier.
+
+"use strict";
+
+var Debug = debug.Debug;
+
+var test_name;
+var listener_delegate;
+var listener_called;
+var exception;
+var begin_test_count = 0;
+var end_test_count = 0;
+var break_count = 0;
+var global_marker = 7;
+
+
+// Debug event listener which delegates.
+function listener(event, exec_state, event_data, data) {
+  try {
+    if (event == Debug.DebugEvent.Break) {
+      break_count++;
+      listener_called = true;
+      listener_delegate(exec_state);
+    }
+  } catch (e) {
+    print(e, e.stack);
+    exception = e;
+  }
+}
+
+// Add the debug event listener.
+Debug.setListener(listener);
+
+
+// Initialize for a new test.
+function BeginTest(name) {
+  test_name = name;
+  listener_delegate = null;
+  listener_called = false;
+  exception = null;
+  begin_test_count++;
+}
+
+
+// Check result of a test.
+function EndTest() {
+  assertTrue(listener_called, "listener not called for " + test_name);
+  assertNull(exception, test_name, exception);
+  end_test_count++;
+}
+
+var global_object = this;
+
+// Check that the scope chain contains the expected types of scopes.
+function CheckScopeChain(scopes, exec_state) {
+  assertEquals(scopes.length, exec_state.frame().scopeCount());
+  for (var i = 0; i < scopes.length; i++) {
+    var scope = exec_state.frame().scope(i);
+    assertEquals(scopes[i], scope.scopeType());
+
+    // Check the global object when hitting the global scope.
+    if (scopes[i] == debug.ScopeType.Global) {
+      // Objects don't have same class (one is "global", other is "Object",
+      // so just check the properties directly.
+      assertEquals(global_object.global_marker,
+                   scope.scopeObject().value().global_marker);
+    }
+  }
+}
+
+// Check that the content of the scope is as expected. For functions just check
+// that there is a function.
+function CheckScopeContent(content, number, exec_state) {
+  var scope = exec_state.frame().scope(number);
+  var count = 0;
+  for (var p in content) {
+    var property_mirror = scope.scopeObject().property(p);
+    if (property_mirror.isUndefined()) {
+      print('property ' + p + ' not found in scope');
+    }
+    assertFalse(property_mirror.isUndefined(),
+                'property ' + p + ' not found in scope');
+    assertEquals(content[p], property_mirror.value().value(),
+                 'property ' + p + ' has unexpected value');
+    count++;
+  }
+
+  // 'arguments' and might be exposed in the local and closure scope. Just
+  // ignore this.
+  var scope_size = scope.scopeObject().properties().length;
+  if (!scope.scopeObject().property('arguments').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:');
+    var names = scope.scopeObject().propertyNames();
+    for (var i = 0; i < names.length; i++) {
+      print(names[i]);
+    }
+  }
+  assertEquals(count, scope_size);
+}
+
+
+function assertEqualsUnlessOptimized(expected, value, f) {
+  try {
+    assertEquals(expected, value);
+  } catch (e) {
+    assertOptimized(f);
+  }
+}
+
+// Simple empty block scope in local scope.
+BeginTest("Local block 1");
+
+function local_block_1() {
+  {
+    debugger;
+  }
+}
+
+listener_delegate = function(exec_state) {
+  CheckScopeChain([debug.ScopeType.Local,
+                   debug.ScopeType.Script,
+                   debug.ScopeType.Global], exec_state);
+  CheckScopeContent({}, 0, exec_state);
+};
+local_block_1();
+EndTest();
+
+
+// Simple empty block scope in local scope with a parameter.
+BeginTest("Local 2");
+
+function local_2(a) {
+  {
+    debugger;
+  }
+}
+
+listener_delegate = function(exec_state) {
+  CheckScopeChain([debug.ScopeType.Local,
+                   debug.ScopeType.Script,
+                   debug.ScopeType.Global], exec_state);
+  CheckScopeContent({a:1}, 0, exec_state);
+};
+local_2(1);
+EndTest();
+
+
+// Local scope with a parameter and a local variable.
+BeginTest("Local 3");
+
+function local_3(a) {
+  let x = 3;
+  debugger;
+}
+
+listener_delegate = function(exec_state) {
+  CheckScopeChain([debug.ScopeType.Local,
+                   debug.ScopeType.Script,
+                   debug.ScopeType.Global], exec_state);
+  CheckScopeContent({a:1,x:3}, 0, exec_state);
+};
+local_3(1);
+EndTest();
+
+
+// Local scope with parameters and local variables.
+BeginTest("Local 4");
+
+function local_4(a, b) {
+  let x = 3;
+  let y = 4;
+  debugger;
+}
+
+listener_delegate = function(exec_state) {
+  CheckScopeChain([debug.ScopeType.Local,
+                   debug.ScopeType.Script,
+                   debug.ScopeType.Global], exec_state);
+  CheckScopeContent({a:1,b:2,x:3,y:4}, 0, exec_state);
+};
+local_4(1, 2);
+EndTest();
+
+
+// Single variable in a block scope.
+BeginTest("Local 5");
+
+function local_5(a) {
+  {
+    let x = 5;
+    debugger;
+  }
+}
+
+listener_delegate = function(exec_state) {
+  CheckScopeChain([debug.ScopeType.Block,
+                   debug.ScopeType.Local,
+                   debug.ScopeType.Script,
+                   debug.ScopeType.Global], exec_state);
+  CheckScopeContent({x:5}, 0, exec_state);
+  CheckScopeContent({a:1}, 1, exec_state);
+};
+local_5(1);
+EndTest();
+
+
+// Two variables in a block scope.
+BeginTest("Local 6");
+
+function local_6(a) {
+  {
+    let x = 6;
+    let y = 7;
+    debugger;
+  }
+}
+
+listener_delegate = function(exec_state) {
+  CheckScopeChain([debug.ScopeType.Block,
+                   debug.ScopeType.Local,
+                   debug.ScopeType.Script,
+                   debug.ScopeType.Global], exec_state);
+  CheckScopeContent({x:6,y:7}, 0, exec_state);
+  CheckScopeContent({a:1}, 1, exec_state);
+};
+local_6(1);
+EndTest();
+
+
+// Two variables in a block scope.
+BeginTest("Local 7");
+
+function local_7(a) {
+  {
+    {
+      let x = 8;
+      debugger;
+    }
+  }
+}
+
+listener_delegate = function(exec_state) {
+  CheckScopeChain([debug.ScopeType.Block,
+                   debug.ScopeType.Local,
+                   debug.ScopeType.Script,
+                   debug.ScopeType.Global], exec_state);
+  CheckScopeContent({x:8}, 0, exec_state);
+  CheckScopeContent({a:1}, 1, exec_state);
+};
+local_7(1);
+EndTest();
+
+
+// Simple closure formed by returning an inner function referering to an outer
+// block local variable and an outer function's parameter.
+BeginTest("Closure 1");
+
+function closure_1(a) {
+  var x = 2;
+  let y = 3;
+  if (true) {
+    let z = 4;
+    function f() {
+      debugger;
+      return a + x + y + z;
+    };
+    return f;
+  }
+}
+
+listener_delegate = function(exec_state) {
+  CheckScopeChain([debug.ScopeType.Local,
+                   debug.ScopeType.Block,
+                   debug.ScopeType.Closure,
+                   debug.ScopeType.Script,
+                   debug.ScopeType.Global], exec_state);
+  CheckScopeContent({}, 0, exec_state);
+  CheckScopeContent({a:1,x:2,y:3}, 2, exec_state);
+};
+closure_1(1)();
+EndTest();
+
+
+// Simple for-in loop over the keys of an object.
+BeginTest("For loop 1");
+
+function for_loop_1() {
+  for (let x in {y:undefined}) {
+    debugger;
+  }
+}
+
+listener_delegate = function(exec_state) {
+  CheckScopeChain([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.
+};
+for_loop_1();
+EndTest();
+
+
+// For-in loop over the keys of an object with a block scoped let variable
+// shadowing the iteration variable.
+BeginTest("For loop 2");
+
+function for_loop_2() {
+  for (let x in {y:undefined}) {
+    let x = 3;
+    debugger;
+  }
+}
+
+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:'y'}, 1, exec_state);
+  // The function scope contains a temporary iteration variable, hidden to the
+  // debugger.
+};
+for_loop_2();
+EndTest();
+
+
+// Simple for loop.
+BeginTest("For loop 3");
+
+function for_loop_3() {
+  for (let x = 3; x < 4; ++x) {
+    debugger;
+  }
+}
+
+listener_delegate = function(exec_state) {
+  CheckScopeChain([debug.ScopeType.Block,
+                   debug.ScopeType.Local,
+                   debug.ScopeType.Script,
+                   debug.ScopeType.Global], exec_state);
+  CheckScopeContent({x:3}, 0, exec_state);
+  CheckScopeContent({}, 1, exec_state);
+};
+for_loop_3();
+EndTest();
+
+
+// For loop with a block scoped let variable shadowing the iteration variable.
+BeginTest("For loop 4");
+
+function for_loop_4() {
+  for (let x = 3; x < 4; ++x) {
+    let x = 5;
+    debugger;
+  }
+}
+
+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:5}, 0, exec_state);
+  CheckScopeContent({x:3}, 1, exec_state);
+  CheckScopeContent({}, 2, exec_state);
+};
+for_loop_4();
+EndTest();
+
+
+// For loop with two variable declarations.
+BeginTest("For loop 5");
+
+function for_loop_5() {
+  for (let x = 3, y = 5; x < 4; ++x) {
+    debugger;
+  }
+}
+
+listener_delegate = function(exec_state) {
+  CheckScopeChain([debug.ScopeType.Block,
+                   debug.ScopeType.Local,
+                   debug.ScopeType.Script,
+                   debug.ScopeType.Global], exec_state);
+  CheckScopeContent({x:3,y:5}, 0, exec_state);
+  CheckScopeContent({}, 1, exec_state);
+};
+for_loop_5();
+EndTest();
+
+
+// Uninitialized variables
+BeginTest("Uninitialized 1");
+
+function uninitialized_1() {
+  {
+    debugger;
+    let x = 1;
+  }
+}
+
+listener_delegate = function(exec_state) {
+  CheckScopeChain([debug.ScopeType.Block,
+                   debug.ScopeType.Local,
+                   debug.ScopeType.Script,
+                   debug.ScopeType.Global], exec_state);
+  CheckScopeContent({x:undefined}, 0, exec_state);
+};
+uninitialized_1();
+EndTest();
+
+
+// Block scopes shadowing
+BeginTest("Block scopes shadowing 1");
+function shadowing_1() {
+  let i = 0;
+  {
+    let i = 5;
+    debugger;
+  }
+  assertEquals(0, i);
+}
+
+listener_delegate = function (exec_state) {
+  assertEqualsUnlessOptimized(5, exec_state.frame(0).evaluate("i").value());
+}
+shadowing_1();
+EndTest();
+
+
+// Block scopes shadowing
+BeginTest("Block scopes shadowing 2");
+function shadowing_2() {
+  let i = 0;
+  {
+    let j = 5;
+    debugger;
+  }
+}
+
+listener_delegate = function (exec_state) {
+  assertEqualsUnlessOptimized(0, exec_state.frame(0).evaluate("i").value());
+  assertEqualsUnlessOptimized(5, exec_state.frame(0).evaluate("j").value());
+}
+shadowing_2();
+EndTest();
diff --git a/src/v8/test/debugger/debug/es6/debug-break-default-constructor.js b/src/v8/test/debugger/debug/es6/debug-break-default-constructor.js
new file mode 100644
index 0000000..d13e0a7
--- /dev/null
+++ b/src/v8/test/debugger/debug/es6/debug-break-default-constructor.js
@@ -0,0 +1,41 @@
+// 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.
+
+
+"use strict";
+
+var Debug = debug.Debug;
+var exception = null;
+var super_called = false;
+var step_count = 0;
+
+function listener(event, execState, eventData, data) {
+  if (event != Debug.DebugEvent.Break) return;
+  try {
+    execState.prepareStep(Debug.StepAction.StepIn);
+    var s = execState.frame().sourceLineText();
+    step_count++;
+    assertTrue(s.indexOf('// ' + step_count + '.') >= 0);
+  } catch (e) {
+    exception = e;
+  }
+}
+
+class Base {
+  constructor() {
+    var x = 1;     // 2.
+  }                // 3.
+}
+
+class Derived extends Base {}  // 1. // 4.
+
+Debug.setListener(listener);
+var bp = Debug.setBreakPoint(Derived, 0);
+
+new Derived();
+
+Debug.setListener(null);  // 5.
+
+assertNull(exception);
+assertEquals(5, step_count);
diff --git a/src/v8/test/debugger/debug/es6/debug-evaluate-arrow-function-receiver.js b/src/v8/test/debugger/debug/es6/debug-evaluate-arrow-function-receiver.js
new file mode 100644
index 0000000..6410e8d
--- /dev/null
+++ b/src/v8/test/debugger/debug/es6/debug-evaluate-arrow-function-receiver.js
@@ -0,0 +1,115 @@
+// 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 that debug-evaluate can find the correct this value for an arrow
+// function, if "this" is referenced within the arrow function scope.
+
+Debug = debug.Debug
+
+var break_count = 0;
+var exception = null;
+
+function listener(event, exec_state, event_data, data) {
+  if (event != Debug.DebugEvent.Break) return;
+  try {
+    for (var i = 0; i < exec_state.frameCount() - 1; i++) {
+      var frame = exec_state.frame(i);
+      var this_value = frame.evaluate("'' + this").value();
+      var expected = frame.sourceLineText().match(/\/\/ (.*$)/)[1];
+      print(expected, this_value, frame.sourceLineText());
+      assertEquals(String(expected), String(this_value));
+    }
+    break_count++;
+  } catch (e) {
+    exception = e;
+    print(e + e.stack);
+  }
+}
+
+// Context-allocated receiver.
+function f() {
+  debugger;                          // foo
+  return () => {
+    debugger;                        // foo
+    with ({}) {
+      return () => {
+        debugger;                    // foo
+        try {
+          throw new Error();
+        } catch (e) {
+          return () => {
+            (() => this);            // bind this.
+            debugger;                // foo
+            return () => {
+              debugger;              // undefined
+              return g.call("goo");  // undefined
+            }
+          };
+        }
+      };
+    }
+  };
+}
+
+// Stack-allocated receiver.
+function g() {
+  debugger;                        // goo
+  return () => {
+    debugger;                      // undefined
+    with ({}) {
+      return () => {
+        debugger;                  // undefined
+        try {
+          throw new Error();
+        } catch (e) {
+          return () => {
+            debugger;              // undefined
+            return f.call("foo");  // undefined
+          };
+        }
+      };
+    }
+  };
+}
+
+Debug.setListener(listener);
+
+var h = f.call("foo");
+for (var i = 0; i < 20; i++) h = h();
+var h = g.call("goo");
+for (var i = 0; i < 20; i++) h = h();
+
+function x() {
+  (() => this);      // bind this.
+  function y() {
+    (() => {
+      (() => this);  // bind this.
+      debugger;      // Y
+     })();           // Y
+  }
+  y.call("Y");       // X
+}
+x.call("X");
+
+function u() {
+  (() => this);
+  function v() {
+    (() => {
+      debugger;      // undefined
+     })();           // V
+  }
+  v.call("V");       // U
+}
+u.call("U");
+
+(() => {
+  (() => this);
+  debugger;          // [object global]
+})();
+
+Debug.setListener(null);
+
+assertEquals(55, break_count);
+assertNull(exception);
diff --git a/src/v8/test/debugger/debug/es6/debug-evaluate-blockscopes.js b/src/v8/test/debugger/debug/es6/debug-evaluate-blockscopes.js
new file mode 100644
index 0000000..026754d
--- /dev/null
+++ b/src/v8/test/debugger/debug/es6/debug-evaluate-blockscopes.js
@@ -0,0 +1,113 @@
+// 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 debug evaluation for functions without local context, but with
+// nested catch contexts.
+
+// Flags: --no-always-opt
+
+"use strict";
+
+var x;
+var result;
+
+function f() {
+  {                   // Line 1.
+    let i = 1;        // Line 2.
+    try {             // Line 3.
+      throw 'stuff';  // Line 4.
+    } catch (e) {     // Line 5.
+      x = 2;          // Line 6.
+    }
+  }
+};
+
+var Debug = debug.Debug
+
+function listener(event, exec_state, event_data, data) {
+  if (event == Debug.DebugEvent.Break) {
+    result = exec_state.frame().evaluate("i").value();
+  }
+};
+
+// Add the debug event listener.
+Debug.setListener(listener);
+
+//Set breakpoint on line 6.
+var bp = Debug.setBreakPoint(f, 6);
+
+result = -1;
+f();
+assertEquals(1, result);
+
+// Clear breakpoint.
+Debug.clearBreakPoint(bp);
+// Get rid of the debug event listener.
+Debug.setListener(null);
+
+
+function f1() {
+  {
+    let i = 1;
+    debugger;
+    assertEquals(2, i);
+  }
+}
+
+function f2() {
+  {
+    let i = 1;
+    debugger;
+    assertEquals(2, i);
+    return function() { return i++; }
+  }
+}
+
+var exception;
+Debug.setListener(function (event, exec_state, event_data, data) {
+  try {
+    if (event == Debug.DebugEvent.Break) {
+      var frame = exec_state.frame();
+      assertEquals(1, frame.evaluate("i").value());
+      var allScopes = frame.allScopes();
+      assertEquals(1, allScopes[0].scopeObject().value().i);
+      allScopes[0].setVariableValue("i", 2);
+    }
+  } catch (e) {
+    exception = e;
+  }
+});
+
+exception = null;
+f1();
+assertEquals(null, exception, exception);
+exception = null;
+f2();
+assertEquals(null, exception, exception);
+
+Debug.setListener(null);
diff --git a/src/v8/test/debugger/debug/es6/debug-evaluate-receiver-before-super.js b/src/v8/test/debugger/debug/es6/debug-evaluate-receiver-before-super.js
new file mode 100644
index 0000000..8fa8645
--- /dev/null
+++ b/src/v8/test/debugger/debug/es6/debug-evaluate-receiver-before-super.js
@@ -0,0 +1,38 @@
+// 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.
+
+
+// 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;
+    assertTrue(result.indexOf("Cannot read property 'a' of undefined") >= 0);
+    super();
+    debugger;
+    assertEquals(239, result);
+  }
+}
+new B();
+
+Debug.setListener(null);
diff --git a/src/v8/test/debugger/debug/es6/debug-exception-generators.js b/src/v8/test/debugger/debug/es6/debug-exception-generators.js
new file mode 100644
index 0000000..192d64b
--- /dev/null
+++ b/src/v8/test/debugger/debug/es6/debug-exception-generators.js
@@ -0,0 +1,48 @@
+// 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.
+
+
+Debug = debug.Debug
+
+var exception = null;
+var log = [];
+
+function listener(event, exec_state, event_data, data) {
+  if (event != Debug.DebugEvent.Exception) return;
+  try {
+    var line = exec_state.frame(0).sourceLineText();
+    var match = /Exception (\w)/.exec(line);
+    assertNotNull(match);
+    assertEquals(match[1], event_data.exception());
+    log.push(match[1]);
+  } catch (e) {
+    exception = e;
+  }
+}
+
+
+function* g() {
+  try {
+    throw "a";  // Ordinary throw. Exception a
+  } catch (e) {}
+  try {
+    yield 1;  // Caught internally. Exception b
+  } catch (e) {}
+  yield 2;
+  yield 3;    // Caught externally. Exception c
+  yield 4;
+}
+
+Debug.setListener(listener);
+Debug.setBreakOnException();
+var g_obj = g();
+assertEquals(1, g_obj.next().value);
+assertEquals(2, g_obj.throw("b").value);
+assertEquals(3, g_obj.next().value);
+assertThrows(() => g_obj.throw("c"));
+assertThrows(() => g_obj.throw("d"));  // Closed generator. Exception d
+Debug.setListener(null);
+Debug.clearBreakOnException();
+assertEquals(["a", "b", "c", "d"], log);
+assertNull(exception);
diff --git a/src/v8/test/debugger/debug/es6/debug-function-scopes.js b/src/v8/test/debugger/debug/es6/debug-function-scopes.js
new file mode 100644
index 0000000..b64c4df
--- /dev/null
+++ b/src/v8/test/debugger/debug/es6/debug-function-scopes.js
@@ -0,0 +1,136 @@
+// Copyright 2012 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.
+
+
+"use strict";
+let top_level_let = 255;
+
+var Debug = debug.Debug;
+
+const ScopeType = debug.ScopeType;
+
+let exception = null;
+let listenerDelegate = null;
+
+const expected_break_count = 5;
+let break_count = 0;
+
+Debug.setListener(function(event, exec_state, event_data, data) {
+  if (event != Debug.DebugEvent.Break) return;
+  try {
+    break_count++;
+    listenerDelegate(exec_state);
+  } catch (e) {
+    exception = e;
+    print(e, e.stack);
+  }
+});
+
+function CheckScope(scope_frame, scope_expectations, expected_scope_type) {
+  assertEquals(expected_scope_type, scope_frame.scopeType());
+
+  var scope_object = scope_frame.scopeObject().value();
+
+  for (let name in scope_expectations) {
+    let actual = scope_object[name];
+    let expected = scope_expectations[name];
+    assertEquals(expected, actual);
+  }
+}
+
+// ---
+
+listenerDelegate = function(exec_state) {
+  const frame = exec_state.frame(0);
+
+  assertEquals(6, frame.scopeCount());
+
+  CheckScope(frame.scope(0), {}, ScopeType.Local);
+  CheckScope(frame.scope(1), { a: 4, b: 5 }, ScopeType.Closure);
+  CheckScope(frame.scope(2), { z: 22, w: 5, v: "Capybara" }, ScopeType.Closure);
+  CheckScope(frame.scope(3), { x: 5 }, ScopeType.Closure);
+  CheckScope(frame.scope(4), { top_level_let: 255 }, ScopeType.Script);
+  CheckScope(frame.scope(5), {}, ScopeType.Global);
+};
+
+(function F1(x) {
+  function F2(y) {
+    var z = x + y;
+    {
+      var w =  5;
+      var v = "Capybara";
+      var F3 = function(a, b) {
+        function F4(p) {
+          debugger;
+          return p + a + b + z + w + v.length;
+        }
+        return F4;
+      }
+      return F3(4, 5);
+    }
+  }
+  return F2(17);
+})(5)();
+
+// ---
+
+listenerDelegate = function(exec_state) {
+  const frame = exec_state.frame(0);
+
+  assertEquals(6, frame.scopeCount());
+
+  CheckScope(frame.scope(0), {}, ScopeType.Local);
+  CheckScope(frame.scope(1), { l3: 9 }, ScopeType.Block);
+  CheckScope(frame.scope(2), { l2: 7 }, ScopeType.Block);
+  CheckScope(frame.scope(3), { v1:3, l0: 0, v3: 5, v6: 11 }, ScopeType.Closure);
+  CheckScope(frame.scope(4), { top_level_let: 255 }, ScopeType.Script);
+  CheckScope(frame.scope(5), {}, ScopeType.Global);
+};
+
+(function() {
+  var v1 = 3;
+  var v2 = 4;
+  let l0 = 0;
+  {
+    var v3 = 5;
+    let l1 = 6;
+    let l2 = 7;
+    {
+      var v4 = 8;
+      let l3 = 9;
+      {
+        var v5 = "Cat";
+        let l4 = 11;
+        var v6 = l4;
+        return function() {
+          debugger;
+          return l0 + v1 + v3 + l2 + l3 + v6;
+        };
+      }
+    }
+  }
+})()();
diff --git a/src/v8/test/debugger/debug/es6/debug-liveedit-new-target-1.js b/src/v8/test/debugger/debug/es6/debug-liveedit-new-target-1.js
new file mode 100644
index 0000000..40dc816b
--- /dev/null
+++ b/src/v8/test/debugger/debug/es6/debug-liveedit-new-target-1.js
@@ -0,0 +1,93 @@
+// 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 that live-editing a frame that uses new.target fails.
+
+Debug = debug.Debug
+var calls = 0;
+var exceptions = 0;
+var results = [];
+var replace_again;
+
+eval(`
+  function LogNewTarget() {
+    calls++;
+    ReplaceOnce();
+    results.push(true);
+    results.push(new.target);
+  }
+`);
+
+function Dummy() {}
+
+function ExecuteInDebugContext(f) {
+  var result;
+  var exception = null;
+  Debug.setListener(function(event) {
+    if (event == Debug.DebugEvent.Break) {
+      try {
+        result = f();
+      } catch (e) {
+        // Rethrow this exception later.
+        exception = e;
+      }
+    }
+  });
+  debugger;
+  Debug.setListener(null);
+  if (exception !== null) throw exception;
+  return result;
+}
+
+function Replace(fun, original, patch) {
+  ExecuteInDebugContext(function() {
+    var change_log = [];
+    try {
+      var script = Debug.findScript(fun);
+      var patch_pos = script.source.indexOf(original);
+      Debug.LiveEdit.TestApi.ApplySingleChunkPatch(
+          script, patch_pos, original.length, patch, change_log);
+    } catch (e) {
+      assertEquals("BLOCKED_NO_NEW_TARGET_ON_RESTART",
+          change_log[0].functions_on_stack[0].replace_problem);
+      assertInstanceof(e, Debug.LiveEdit.Failure);
+      exceptions++;
+    }
+  });
+}
+
+function ReplaceOnce() {
+  if (replace_again) {
+    replace_again = false;
+    Replace(LogNewTarget, "true", "false");
+  }
+}
+
+function Revert() {
+  Replace(LogNewTarget, "false", "true");
+}
+
+replace_again = true;
+ReplaceOnce();
+new LogNewTarget();
+Revert();
+assertEquals(1, calls);
+assertEquals(0, exceptions);
+assertEquals([false, LogNewTarget], results);
+
+replace_again = true;
+LogNewTarget();
+
+replace_again = true;
+new LogNewTarget();
+
+replace_again = true;
+Reflect.construct(LogNewTarget, [], Dummy);
+
+assertEquals(
+    [false, LogNewTarget, true, undefined, true, LogNewTarget, true, Dummy],
+    results);
+assertEquals(4, calls);  // No restarts
+assertEquals(3, exceptions);  // Replace failed.
diff --git a/src/v8/test/debugger/debug/es6/debug-liveedit-new-target-2.js b/src/v8/test/debugger/debug/es6/debug-liveedit-new-target-2.js
new file mode 100644
index 0000000..764c57c
--- /dev/null
+++ b/src/v8/test/debugger/debug/es6/debug-liveedit-new-target-2.js
@@ -0,0 +1,81 @@
+// 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 that live-editing a frame to introduce new.target fails.
+
+Debug = debug.Debug
+var calls = 0;
+var exceptions = 0;
+var results = [];
+var replace_again;
+
+eval(`
+  function LogNewTarget() {
+    calls++;
+    ReplaceOnce();
+    results.push(true);
+  }
+`);
+
+function ExecuteInDebugContext(f) {
+  var result;
+  var exception = null;
+  Debug.setListener(function(event) {
+    if (event == Debug.DebugEvent.Break) {
+      try {
+        result = f();
+      } catch (e) {
+        // Rethrow this exception later.
+        exception = e;
+      }
+    }
+  });
+  debugger;
+  Debug.setListener(null);
+  if (exception !== null) throw exception;
+  return result;
+}
+
+function Replace(fun, original, patch) {
+  ExecuteInDebugContext(function() {
+    var change_log = [];
+    try {
+      var script = Debug.findScript(fun);
+      var patch_pos = script.source.indexOf(original);
+      Debug.LiveEdit.TestApi.ApplySingleChunkPatch(
+          script, patch_pos, original.length, patch, change_log);
+    } catch (e) {
+      assertEquals("BLOCKED_NO_NEW_TARGET_ON_RESTART",
+                   change_log[0].functions_on_stack[0].replace_problem);
+      assertInstanceof(e, Debug.LiveEdit.Failure);
+      exceptions++;
+    }
+  });
+}
+
+function ReplaceOnce(x) {
+  if (replace_again) {
+    replace_again = false;
+    Replace(LogNewTarget, "true", "new.target");
+  }
+}
+
+function Revert() {
+  Replace(LogNewTarget, "new.target", "true");
+}
+
+replace_again = true;
+ReplaceOnce();
+new LogNewTarget();
+Revert();
+assertEquals(1, calls);
+assertEquals(0, exceptions);
+assertEquals([LogNewTarget], results);
+
+replace_again = true;
+new LogNewTarget();
+assertEquals(2, calls);  // No restarts
+assertEquals(1, exceptions);  // Replace failed.
+assertEquals([LogNewTarget, true], results);
diff --git a/src/v8/test/debugger/debug/es6/debug-liveedit-new-target-3.js b/src/v8/test/debugger/debug/es6/debug-liveedit-new-target-3.js
new file mode 100644
index 0000000..60ec9a7
--- /dev/null
+++ b/src/v8/test/debugger/debug/es6/debug-liveedit-new-target-3.js
@@ -0,0 +1,91 @@
+// 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 that live-editing a frame above one that uses new.target succeeds.
+
+Debug = debug.Debug
+var wrapper_calls = 0;
+var construct_calls = 0;
+var exceptions = 0;
+var results = [];
+var replace_again;
+
+eval(`
+  function LogNewTarget(arg) {
+    construct_calls++;
+    results.push(new.target);
+  }
+  function Wrapper() {
+    wrapper_calls++;
+    ReplaceOnce();
+    new LogNewTarget(true);
+  }
+`);
+
+function ExecuteInDebugContext(f) {
+  var result;
+  var exception = null;
+  Debug.setListener(function(event) {
+    if (event == Debug.DebugEvent.Break) {
+      try {
+        result = f();
+      } catch (e) {
+        // Rethrow this exception later.
+        exception = e;
+      }
+    }
+  });
+  debugger;
+  Debug.setListener(null);
+  if (exception !== null) throw exception;
+  return result;
+}
+
+function Replace(fun, original, patch) {
+  ExecuteInDebugContext(function() {
+    var change_log = [];
+    try {
+      var script = Debug.findScript(fun);
+      var patch_pos = script.source.indexOf(original);
+      Debug.LiveEdit.TestApi.ApplySingleChunkPatch(
+          script, patch_pos, original.length, patch, change_log);
+    } catch (e) {
+      exceptions++;
+    }
+  });
+}
+
+function ReplaceOnce(x) {
+  if (replace_again) {
+    replace_again = false;
+    Replace(Wrapper, "true", "false");
+  }
+}
+
+function Revert() {
+  Replace(Wrapper, "false", "true");
+}
+
+replace_again = true;
+ReplaceOnce();
+Wrapper();
+Revert();
+assertEquals(1, construct_calls);
+assertEquals(1, wrapper_calls);
+assertEquals(0, exceptions);  // Replace succeeds
+assertEquals([LogNewTarget], results);
+
+Wrapper();
+assertEquals(2, construct_calls);
+assertEquals(2, wrapper_calls);
+assertEquals(0, exceptions);  // Replace succeeds
+assertEquals([LogNewTarget, LogNewTarget], results);
+
+replace_again = true;
+Wrapper();
+assertEquals(3, construct_calls);
+assertEquals(4, wrapper_calls);  // Restarts
+assertEquals(0, exceptions);  // Replace succeeds
+assertEquals([LogNewTarget, LogNewTarget, LogNewTarget], results);
diff --git a/src/v8/test/debugger/debug/es6/debug-promises/evaluate-across-microtasks.js b/src/v8/test/debugger/debug/es6/debug-promises/evaluate-across-microtasks.js
new file mode 100644
index 0000000..71b0747
--- /dev/null
+++ b/src/v8/test/debugger/debug/es6/debug-promises/evaluate-across-microtasks.js
@@ -0,0 +1,65 @@
+// 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.
+
+
+var Debug = debug.Debug;
+var listenerComplete = false;
+var exception = null;
+var count = 0;
+var log = [];
+var done = false;
+
+function LogX(x) {
+  var stored_count = count;
+  return function() {
+    log.push(`[${stored_count}] ${x}`);
+  };
+}
+
+function DebuggerStatement() {
+  log.push(`[${count}] debugger`);
+  if (count++ < 3) {
+    debugger;
+  }
+}
+
+function listener(event, exec_state, event_data, data) {
+  if (event != Debug.DebugEvent.Break) return;
+  try {
+    var p = Promise.resolve();
+    var q = p.then(LogX("then 1"));
+    p.then(LogX("then 2"));
+    q.then(LogX("then 3"));
+    q.then(DebuggerStatement);
+    var r = q.then(() => { throw 1; });
+    r.catch(LogX("catch"));
+    listenerComplete = true;
+  } catch (e) {
+    exception = e;
+    print(e, e.stack);
+    quit(1);
+  };
+};
+
+// Add the debug event listener.
+Debug.setListener(listener);
+
+DebuggerStatement();
+LogX("start")();
+
+// Make sure that the debug event listener was invoked.
+assertTrue(listenerComplete);
+
+%RunMicrotasks();
+
+var expectation =
+  [ "[0] debugger", "[1] start", "[1] then 1",
+    "[1] then 2", "[1] then 3", "[1] debugger",
+    "[2] then 1", "[2] then 2", "[1] catch",
+    "[2] then 3", "[2] debugger", "[3] then 1",
+    "[3] then 2", "[2] catch", "[3] then 3",
+    "[3] debugger", "[3] catch",
+  ];
+
+assertEquals(expectation, log);
diff --git a/src/v8/test/debugger/debug/es6/debug-promises/promise-all-caught.js b/src/v8/test/debugger/debug/es6/debug-promises/promise-all-caught.js
new file mode 100644
index 0000000..639564a
--- /dev/null
+++ b/src/v8/test/debugger/debug/es6/debug-promises/promise-all-caught.js
@@ -0,0 +1,39 @@
+// 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 debug events when we only listen to uncaught exceptions and a
+// Promise p3 created by Promise.all has a catch handler, and is rejected
+// because one of the Promises p2 passed to Promise.all is rejected. We
+// expect no Exception debug event to be triggered, since p3 and by
+// extension p2 have a catch handler.
+
+var Debug = debug.Debug;
+
+var expected_events = 2;
+
+var p1 = Promise.resolve();
+p1.name = "p1";
+
+var p2 = p1.then(function() {
+  throw new Error("caught");
+});
+
+p2.name = "p2";
+
+var p3 = Promise.all([p2]);
+p3.name = "p3";
+
+p3.catch(function(e) {});
+
+function listener(event, exec_state, event_data, data) {
+  try {
+    assertTrue(event != Debug.DebugEvent.Exception)
+  } catch (e) {
+    %AbortJS(e + "\n" + e.stack);
+  }
+}
+
+Debug.setBreakOnUncaughtException();
+Debug.setListener(listener);
diff --git a/src/v8/test/debugger/debug/es6/debug-promises/promise-all-uncaught.js b/src/v8/test/debugger/debug/es6/debug-promises/promise-all-uncaught.js
new file mode 100644
index 0000000..55185e3
--- /dev/null
+++ b/src/v8/test/debugger/debug/es6/debug-promises/promise-all-uncaught.js
@@ -0,0 +1,67 @@
+// 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 debug events when we only listen to uncaught exceptions and a
+// Promise p3 created by Promise.all has no catch handler, and is rejected
+// because one of the Promises p2 passed to Promise.all is rejected.
+// We expect one event for p2; the system recognizes the rejection of p3
+// to be redundant and based on the rejection of p2 and does not trigger
+// an additional rejection.
+
+var Debug = debug.Debug;
+
+var expected_events = 1;
+var log = [];
+
+function listener(event, exec_state, event_data, data) {
+  if (event != Debug.DebugEvent.Exception) return;
+  try {
+    expected_events--;
+    assertTrue(expected_events >= 0);
+    assertEquals("uncaught", event_data.exception().message);
+    // Assert that the debug event is triggered at the throw site.
+    assertTrue(exec_state.frame(0).sourceLineText().indexOf("// event") > 0);
+    assertTrue(event_data.uncaught());
+  } catch (e) {
+    %AbortJS(e + "\n" + e.stack);
+  }
+}
+
+Debug.setBreakOnUncaughtException();
+Debug.setListener(listener);
+
+var p1 = Promise.resolve();
+p1.name = "p1";
+
+var p2 = p1.then(function() {
+  log.push("throw");
+  throw new Error("uncaught");  // event
+});
+
+p2.name = "p2";
+
+var p3 = Promise.all([p2]);
+p3.name = "p3";
+
+log.push("end main");
+
+function testDone(iteration) {
+  function checkResult() {
+    try {
+      assertTrue(iteration < 10);
+      if (expected_events === 0) {
+        assertEquals(["end main", "throw"], log);
+      } else {
+        testDone(iteration + 1);
+      }
+    } catch (e) {
+      %AbortJS(e + "\n" + e.stack);
+    }
+  }
+
+  %EnqueueMicrotask(checkResult);
+}
+
+testDone(0);
diff --git a/src/v8/test/debugger/debug/es6/debug-promises/promise-race-caught.js b/src/v8/test/debugger/debug/es6/debug-promises/promise-race-caught.js
new file mode 100644
index 0000000..d75ddea
--- /dev/null
+++ b/src/v8/test/debugger/debug/es6/debug-promises/promise-race-caught.js
@@ -0,0 +1,39 @@
+// 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 debug events when we only listen to uncaught exceptions and a
+// Promise p3 created by Promise.race has a catch handler, and is rejected
+// because one of the Promises p2 passed to Promise.all is rejected. We
+// expect no Exception debug event to be triggered, since p3 and by
+// extension p2 have a catch handler.
+
+var Debug = debug.Debug;
+
+var expected_events = 2;
+
+var p1 = Promise.resolve();
+p1.name = "p1";
+
+var p2 = p1.then(function() {
+  throw new Error("caught");
+});
+
+p2.name = "p2";
+
+var p3 = Promise.all([p2]);
+p3.name = "p3";
+
+p3.catch(function(e) {});
+
+function listener(event, exec_state, event_data, data) {
+  try {
+    assertTrue(event != Debug.DebugEvent.Exception)
+  } catch (e) {
+    %AbortJS(e + "\n" + e.stack);
+  }
+}
+
+Debug.setBreakOnUncaughtException();
+Debug.setListener(listener);
diff --git a/src/v8/test/debugger/debug/es6/debug-promises/promise-race-uncaught.js b/src/v8/test/debugger/debug/es6/debug-promises/promise-race-uncaught.js
new file mode 100644
index 0000000..bd44634
--- /dev/null
+++ b/src/v8/test/debugger/debug/es6/debug-promises/promise-race-uncaught.js
@@ -0,0 +1,67 @@
+// 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 debug events when we only listen to uncaught exceptions and a
+// Promise p3 created by Promise.race has no catch handler, and is rejected
+// because one of the Promises p2 passed to Promise.race is rejected.
+// We expect one event for p2; the system recognizes the rejection of p3
+// to be redundant and based on the rejection of p2 and does not trigger
+// an additional rejection.
+
+var Debug = debug.Debug;
+
+var expected_events = 1;
+var log = [];
+
+function listener(event, exec_state, event_data, data) {
+  if (event != Debug.DebugEvent.Exception) return;
+  try {
+    expected_events--;
+    assertTrue(expected_events >= 0);
+    assertEquals("uncaught", event_data.exception().message);
+    // Assert that the debug event is triggered at the throw site.
+    assertTrue(exec_state.frame(0).sourceLineText().indexOf("// event") > 0);
+    assertTrue(event_data.uncaught());
+  } catch (e) {
+    %AbortJS(e + "\n" + e.stack);
+  }
+}
+
+Debug.setBreakOnUncaughtException();
+Debug.setListener(listener);
+
+var p1 = Promise.resolve();
+p1.name = "p1";
+
+var p2 = p1.then(function() {
+  log.push("throw");
+  throw new Error("uncaught");  // event
+});
+
+p2.name = "p2";
+
+var p3 = Promise.race([p2]);
+p3.name = "p3";
+
+log.push("end main");
+
+function testDone(iteration) {
+  function checkResult() {
+    try {
+      assertTrue(iteration < 10);
+      if (expected_events === 0) {
+        assertEquals(["end main", "throw"], log);
+      } else {
+        testDone(iteration + 1);
+      }
+    } catch (e) {
+      %AbortJS(e + "\n" + e.stack);
+    }
+  }
+
+  %EnqueueMicrotask(checkResult);
+}
+
+testDone(0);
diff --git a/src/v8/test/debugger/debug/es6/debug-promises/reentry.js b/src/v8/test/debugger/debug/es6/debug-promises/reentry.js
new file mode 100644
index 0000000..bb7f48f
--- /dev/null
+++ b/src/v8/test/debugger/debug/es6/debug-promises/reentry.js
@@ -0,0 +1,16 @@
+// 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.
+
+
+// Test reentry of special try catch for Promises.
+
+Debug = debug.Debug;
+
+Debug.setBreakOnUncaughtException();
+Debug.setListener(function(event, exec_state, event_data, data) { });
+
+var p = new Promise(function(resolve, reject) { resolve(); });
+var q = p.then(function() {
+  new Promise(function(resolve, reject) { resolve(); });
+});
diff --git a/src/v8/test/debugger/debug/es6/debug-promises/reject-after-resolve.js b/src/v8/test/debugger/debug/es6/debug-promises/reject-after-resolve.js
new file mode 100644
index 0000000..0bf3c59
--- /dev/null
+++ b/src/v8/test/debugger/debug/es6/debug-promises/reject-after-resolve.js
@@ -0,0 +1,36 @@
+// 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.
+
+
+// Test debug events when we listen to uncaught exceptions and
+// the Promise is rejected in a chained closure after it has been resolved.
+// We expect no Exception debug event to be triggered.
+
+Debug = debug.Debug;
+
+var log = [];
+
+var p = new Promise(function(resolve, reject) {
+  log.push("resolve");
+  resolve(reject);
+});
+
+var q = p.then(
+  function(value) {
+    assertEquals(["resolve", "end main"], log);
+    value(new Error("reject"));
+  });
+
+function listener(event, exec_state, event_data, data) {
+  try {
+    assertTrue(event != Debug.DebugEvent.Exception);
+  } catch (e) {
+    %AbortJS(e + "\n" + e.stack);
+  }
+}
+
+Debug.setBreakOnException();
+Debug.setListener(listener);
+
+log.push("end main");
diff --git a/src/v8/test/debugger/debug/es6/debug-promises/reject-caught-all.js b/src/v8/test/debugger/debug/es6/debug-promises/reject-caught-all.js
new file mode 100644
index 0000000..9424ca7
--- /dev/null
+++ b/src/v8/test/debugger/debug/es6/debug-promises/reject-caught-all.js
@@ -0,0 +1,67 @@
+// 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.
+
+
+// Test debug events when we listen to all exceptions and
+// there is a catch handler for the to-be-rejected Promise.
+// We expect a normal Exception debug event to be triggered.
+
+Debug = debug.Debug;
+
+var log = [];
+var expected_events = 1;
+
+var p = new Promise(function(resolve, reject) {
+  log.push("resolve");
+  resolve();
+});
+
+var q = p.then(
+  function(value) {
+    log.push("reject");
+    return Promise.reject(new Error("reject"));
+  });
+
+q.catch(
+  function(e) {
+    assertEquals("reject", e.message);
+  });
+
+
+function listener(event, exec_state, event_data, data) {
+  try {
+    if (event == Debug.DebugEvent.Exception) {
+      expected_events--;
+      assertTrue(expected_events >= 0);
+      assertEquals("reject", event_data.exception().message);
+      assertFalse(event_data.uncaught());
+    }
+  } catch (e) {
+    %AbortJS(e + "\n" + e.stack);
+  }
+}
+
+Debug.setBreakOnException();
+Debug.setListener(listener);
+
+log.push("end main");
+
+function testDone(iteration) {
+  function checkResult() {
+    try {
+      assertTrue(iteration < 10);
+      if (expected_events === 0) {
+        assertEquals(["resolve", "end main", "reject"], log);
+      } else {
+        testDone(iteration + 1);
+      }
+    } catch (e) {
+      %AbortJS(e + "\n" + e.stack);
+    }
+  }
+
+  %EnqueueMicrotask(checkResult);
+}
+
+testDone(0);
diff --git a/src/v8/test/debugger/debug/es6/debug-promises/reject-caught-by-default-reject-handler.js b/src/v8/test/debugger/debug/es6/debug-promises/reject-caught-by-default-reject-handler.js
new file mode 100644
index 0000000..bb22afc
--- /dev/null
+++ b/src/v8/test/debugger/debug/es6/debug-promises/reject-caught-by-default-reject-handler.js
@@ -0,0 +1,74 @@
+// 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.
+
+
+// Test debug events when we only listen to uncaught exceptions and
+// there is only a default reject handler for the to-be-rejected Promise.
+// We expect only one debug event: when the first Promise is rejected
+// and only has default reject handlers. No event is triggered when
+// simply forwarding the rejection with .then's default handler.
+
+Debug = debug.Debug;
+
+var expected_events = 1;
+var log = [];
+
+var resolve, reject;
+var p0 = new Promise(function(res, rej) { resolve = res; reject = rej; });
+var p1 = p0.then(function() {
+  log.push("p0.then");
+  return Promise.reject(new Error("123"));
+});
+var p2 = p1.then(function() {
+  log.push("p1.then");
+});
+
+var q = new Promise(function(res, rej) {
+  log.push("resolve q");
+  res();
+});
+
+q.then(function() {
+  log.push("resolve p");
+  resolve();
+})
+
+
+function listener(event, exec_state, event_data, data) {
+  try {
+    if (event == Debug.DebugEvent.Exception) {
+      expected_events--;
+      assertTrue(expected_events >= 0);
+      assertTrue(event_data.uncaught());
+      // p1 is rejected, uncaught, with the error from the Promise.reject line
+      assertNotNull(event_data.sourceLineText().match("Promise.reject"));
+    }
+  } catch (e) {
+    %AbortJS(e + "\n" + e.stack);
+  }
+}
+
+Debug.setBreakOnUncaughtException();
+Debug.setListener(listener);
+
+log.push("end main");
+
+function testDone(iteration) {
+  function checkResult() {
+    try {
+      assertTrue(iteration < 10);
+      if (expected_events === 0) {
+        assertEquals(["resolve q", "end main", "resolve p", "p0.then"], log);
+      } else {
+        testDone(iteration + 1);
+      }
+    } catch (e) {
+      %AbortJS(e + "\n" + e.stack);
+    }
+  }
+
+  %EnqueueMicrotask(checkResult);
+}
+
+testDone(0);
diff --git a/src/v8/test/debugger/debug/es6/debug-promises/reject-caught-late.js b/src/v8/test/debugger/debug/es6/debug-promises/reject-caught-late.js
new file mode 100644
index 0000000..b54516e
--- /dev/null
+++ b/src/v8/test/debugger/debug/es6/debug-promises/reject-caught-late.js
@@ -0,0 +1,33 @@
+// 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.
+
+
+// Test debug events when we only listen to uncaught exceptions, the Promise
+// is rejected, and a catch handler is installed right before the rejection.
+// We expect no debug event to be triggered.
+
+Debug = debug.Debug;
+
+var p = new Promise(function(resolve, reject) {
+  resolve();
+});
+
+var q = p.then(
+  function() {
+    q.catch(function(e) {
+      assertEquals("caught", e.message);
+    });
+    return Promise.reject(Error("caught"));
+  });
+
+function listener(event, exec_state, event_data, data) {
+  try {
+    assertTrue(event != Debug.DebugEvent.Exception);
+  } catch (e) {
+    %AbortJS(e + "\n" + e.stack);
+  }
+}
+
+Debug.setBreakOnUncaughtException();
+Debug.setListener(listener);
diff --git a/src/v8/test/debugger/debug/es6/debug-promises/reject-caught-uncaught.js b/src/v8/test/debugger/debug/es6/debug-promises/reject-caught-uncaught.js
new file mode 100644
index 0000000..873e8ca
--- /dev/null
+++ b/src/v8/test/debugger/debug/es6/debug-promises/reject-caught-uncaught.js
@@ -0,0 +1,35 @@
+// 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.
+
+
+// Test debug events when we only listen to uncaught exceptions and
+// there is a catch handler for the to-be-rejected Promise.
+// We expect no debug event to be triggered.
+
+Debug = debug.Debug;
+
+var p = new Promise(function(resolve, reject) {
+  resolve();
+});
+
+var q = p.then(
+  function() {
+    return Promise.reject(Error("caught reject"));
+  });
+
+q.catch(
+  function(e) {
+    assertEquals("caught reject", e.message);
+  });
+
+function listener(event, exec_state, event_data, data) {
+  try {
+    assertTrue(event != Debug.DebugEvent.Exception);
+  } catch (e) {
+    %AbortJS(e + "\n" + e.stack);
+  }
+}
+
+Debug.setBreakOnUncaughtException();
+Debug.setListener(listener);
diff --git a/src/v8/test/debugger/debug/es6/debug-promises/reject-in-constructor.js b/src/v8/test/debugger/debug/es6/debug-promises/reject-in-constructor.js
new file mode 100644
index 0000000..5d7e830
--- /dev/null
+++ b/src/v8/test/debugger/debug/es6/debug-promises/reject-in-constructor.js
@@ -0,0 +1,37 @@
+// 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.
+
+
+// Test debug events when we only listen to uncaught exceptions and
+// the Promise is rejected in the Promise constructor.
+// We expect an Exception debug event with a promise to be triggered.
+
+Debug = debug.Debug;
+
+var steps = 0;
+var exception = null;
+
+function listener(event, exec_state, event_data, data) {
+  try {
+    if (event == Debug.DebugEvent.Exception) {
+      steps++;
+      assertEquals("uncaught", event_data.exception().message);
+      assertTrue(event_data.uncaught());
+      // Assert that the debug event is triggered at the throw site.
+      assertTrue(exec_state.frame(0).sourceLineText().indexOf("// event") > 0);
+    }
+  } catch (e) {
+    exception = e;
+  }
+}
+
+Debug.setBreakOnUncaughtException();
+Debug.setListener(listener);
+
+var p = new Promise(function(resolve, reject) {
+  reject(new Error("uncaught"));  // event
+});
+
+assertEquals(1, steps);
+assertNull(exception);
diff --git a/src/v8/test/debugger/debug/es6/debug-promises/reject-uncaught-all.js b/src/v8/test/debugger/debug/es6/debug-promises/reject-uncaught-all.js
new file mode 100644
index 0000000..1d81545
--- /dev/null
+++ b/src/v8/test/debugger/debug/es6/debug-promises/reject-uncaught-all.js
@@ -0,0 +1,63 @@
+// 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.
+
+
+// Test debug events when we listen to all exceptions and
+// there is a catch handler for the to-be-rejected Promise.
+// We expect an Exception debug event with a promise to be triggered.
+
+Debug = debug.Debug;
+
+var expected_events = 1;
+var log = [];
+
+var p = new Promise(function(resolve, reject) {
+  log.push("resolve");
+  resolve();
+});
+
+var q = p.then(
+  function() {
+    log.push("reject");
+    return Promise.reject(new Error("uncaught reject"));
+  });
+
+function listener(event, exec_state, event_data, data) {
+  try {
+    if (event == Debug.DebugEvent.Exception) {
+      expected_events--;
+      assertTrue(expected_events >= 0);
+      assertEquals("uncaught reject", event_data.exception().message);
+      assertTrue(event_data.uncaught());
+      // The frame comes from the Promise.reject call
+      assertNotNull(/Promise\.reject/.exec(event_data.sourceLineText()));
+    }
+  } catch (e) {
+    %AbortJS(e + "\n" + e.stack);
+  }
+}
+
+Debug.setBreakOnException();
+Debug.setListener(listener);
+
+log.push("end main");
+
+function testDone(iteration) {
+  function checkResult() {
+    try {
+      assertTrue(iteration < 10);
+      if (expected_events === 0) {
+        assertEquals(["resolve", "end main", "reject"], log);
+      } else {
+        testDone(iteration + 1);
+      }
+    } catch (e) {
+      %AbortJS(e + "\n" + e.stack);
+    }
+  }
+
+  %EnqueueMicrotask(checkResult);
+}
+
+testDone(0);
diff --git a/src/v8/test/debugger/debug/es6/debug-promises/reject-uncaught-late.js b/src/v8/test/debugger/debug/es6/debug-promises/reject-uncaught-late.js
new file mode 100644
index 0000000..454899d
--- /dev/null
+++ b/src/v8/test/debugger/debug/es6/debug-promises/reject-uncaught-late.js
@@ -0,0 +1,70 @@
+// 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.
+
+
+// Test debug events when we only listen to uncaught exceptions and
+// there is a catch handler for the to-be-rejected Promise.
+// We expect an Exception debug event with a promise to be triggered.
+
+Debug = debug.Debug;
+
+var expected_events = 1;
+var log = [];
+
+var reject_closure;
+
+var p = new Promise(function(resolve, reject) {
+  log.push("postpone p");
+  reject_closure = reject;
+});
+
+var q = new Promise(function(resolve, reject) {
+  log.push("resolve q");
+  resolve();
+});
+
+q.then(function() {
+  log.push("reject p");
+  reject_closure(new Error("uncaught reject p"));  // event
+})
+
+
+function listener(event, exec_state, event_data, data) {
+  try {
+    if (event == Debug.DebugEvent.Exception) {
+      expected_events--;
+      assertTrue(expected_events >= 0);
+      assertEquals("uncaught reject p", event_data.exception().message);
+      assertTrue(event_data.uncaught());
+      // Assert that the debug event is triggered at the throw site.
+      assertTrue(exec_state.frame(0).sourceLineText().indexOf("// event") > 0);
+    }
+  } catch (e) {
+    %AbortJS(e + "\n" + e.stack);
+  }
+}
+
+Debug.setBreakOnUncaughtException();
+Debug.setListener(listener);
+
+log.push("end main");
+
+function testDone(iteration) {
+  function checkResult() {
+    try {
+      assertTrue(iteration < 10);
+      if (expected_events === 0) {
+        assertEquals(["postpone p", "resolve q", "end main", "reject p"], log);
+      } else {
+        testDone(iteration + 1);
+      }
+    } catch (e) {
+      %AbortJS(e + "\n" + e.stack);
+    }
+  }
+
+  %EnqueueMicrotask(checkResult);
+}
+
+testDone(0);
diff --git a/src/v8/test/debugger/debug/es6/debug-promises/reject-uncaught-uncaught.js b/src/v8/test/debugger/debug/es6/debug-promises/reject-uncaught-uncaught.js
new file mode 100644
index 0000000..1afe4b7
--- /dev/null
+++ b/src/v8/test/debugger/debug/es6/debug-promises/reject-uncaught-uncaught.js
@@ -0,0 +1,63 @@
+// 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.
+
+
+// Test debug events when we only listen to uncaught exceptions and
+// there is no catch handler for the to-be-rejected Promise.
+// We expect an Exception debug event with a promise to be triggered.
+
+Debug = debug.Debug;
+
+var expected_events = 1;
+var log = [];
+
+var p = new Promise(function(resolve, reject) {
+  log.push("resolve");
+  resolve();
+});
+
+var q = p.then(
+  function() {
+    log.push("reject");
+    return Promise.reject(Error("uncaught reject"));  // event
+  });
+
+function listener(event, exec_state, event_data, data) {
+  try {
+    if (event == Debug.DebugEvent.Exception) {
+      expected_events--;
+      assertTrue(expected_events >= 0);
+      assertEquals("uncaught reject", event_data.exception().message);
+      assertTrue(event_data.uncaught());
+      // The JavaScript frame is from the Promise rejection
+      assertTrue(/Promise\.reject/.test(event_data.sourceLineText()));
+    }
+  } catch (e) {
+    %AbortJS(e + "\n" + e.stack);
+  }
+}
+
+Debug.setBreakOnUncaughtException();
+Debug.setListener(listener);
+
+log.push("end main");
+
+function testDone(iteration) {
+  function checkResult() {
+    try {
+      assertTrue(iteration < 10);
+      if (expected_events === 0) {
+        assertEquals(["resolve", "end main", "reject"], log);
+      } else {
+        testDone(iteration + 1);
+      }
+    } catch (e) {
+      %AbortJS(e + "\n" + e.stack);
+    }
+  }
+
+  %EnqueueMicrotask(checkResult);
+}
+
+testDone(0);
diff --git a/src/v8/test/debugger/debug/es6/debug-promises/reject-with-invalid-reject.js b/src/v8/test/debugger/debug/es6/debug-promises/reject-with-invalid-reject.js
new file mode 100644
index 0000000..78331b9
--- /dev/null
+++ b/src/v8/test/debugger/debug/es6/debug-promises/reject-with-invalid-reject.js
@@ -0,0 +1,73 @@
+// 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.
+
+
+// Test debug events when a Promise is rejected, which is caught by a custom
+// promise, which has a number for reject closure.  We expect an Exception debug
+// events trying to call the invalid reject closure.
+
+Debug = debug.Debug;
+
+var expected_events = 1;
+var log = [];
+
+var p = new Promise(function(resolve, reject) {
+  log.push("resolve");
+  resolve();
+});
+
+function MyPromise(resolver) {
+  var reject = 1;
+  var resolve = function() { };
+  log.push("construct");
+  resolver(resolve, reject);
+};
+
+MyPromise.prototype = new Promise(function() {});
+p.constructor = MyPromise;
+
+var q = p.then(
+  function() {
+    log.push("reject caught");
+    return Promise.reject(new Error("caught"));
+  });
+
+function listener(event, exec_state, event_data, data) {
+  try {
+    if (event == Debug.DebugEvent.Exception) {
+      expected_events--;
+      assertTrue(expected_events >= 0);
+      assertEquals("number is not a function", event_data.exception().message);
+      // All of the frames on the stack are from native Javascript.
+      assertEquals(0, exec_state.frameCount());
+    }
+  } catch (e) {
+    %AbortJS(e + "\n" + e.stack);
+  }
+}
+
+Debug.setBreakOnUncaughtException();
+Debug.setListener(listener);
+
+function testDone(iteration) {
+  function checkResult() {
+    try {
+      assertTrue(iteration < 10);
+      if (expected_events === 0) {
+        assertEquals(["resolve", "construct", "end main", "reject caught"],
+                     log);
+      } else {
+        testDone(iteration + 1);
+      }
+    } catch (e) {
+      %AbortJS(e + "\n" + e.stack);
+    }
+  }
+
+  %EnqueueMicrotask(checkResult);
+}
+
+testDone(0);
+
+log.push("end main");
diff --git a/src/v8/test/debugger/debug/es6/debug-promises/reject-with-throw-in-reject.js b/src/v8/test/debugger/debug/es6/debug-promises/reject-with-throw-in-reject.js
new file mode 100644
index 0000000..2181190
--- /dev/null
+++ b/src/v8/test/debugger/debug/es6/debug-promises/reject-with-throw-in-reject.js
@@ -0,0 +1,83 @@
+// 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.
+
+
+// Test debug events when a Promise is rejected, which is caught by a
+// custom promise, which throws a new exception in its reject handler.
+// We expect two Exception debug events:
+//  1) when promise q is rejected.
+//  2) when the custom reject closure in MyPromise throws an exception.
+
+Debug = debug.Debug;
+
+var expected_events = 1;
+var log = [];
+
+var p = new Promise(function(resolve, reject) {
+  log.push("resolve");
+  resolve();
+});
+
+function MyPromise(resolver) {
+  var reject = function() {
+    log.push("throw in reject");
+    throw new Error("reject");  // event
+  };
+  var resolve = function() { };
+  log.push("construct");
+  resolver(resolve, reject);
+};
+
+MyPromise.prototype = new Promise(function() {});
+p.constructor = MyPromise;
+
+var q = p.then(
+  function() {
+    log.push("reject caught");
+    return Promise.reject(new Error("caught"));
+  });
+
+function listener(event, exec_state, event_data, data) {
+  try {
+    if (event == Debug.DebugEvent.Exception) {
+      expected_events--;
+      assertTrue(expected_events >= 0);
+      assertEquals("reject", event_data.exception().message);
+      // Assert that the debug event is triggered at the throw site.
+      assertTrue(
+          exec_state.frame(0).sourceLineText().indexOf("// event") > 0);
+    }
+  } catch (e) {
+    // Signal a failure with exit code 1.  This is necessary since the
+    // debugger swallows exceptions and we expect the chained function
+    // and this listener to be executed after the main script is finished.
+    print("Unexpected exception: " + e + "\n" + e.stack);
+    quit(1);
+  }
+}
+
+Debug.setBreakOnUncaughtException();
+Debug.setListener(listener);
+
+log.push("end main");
+
+function testDone(iteration) {
+  function checkResult() {
+    try {
+      assertTrue(iteration < 10);
+      if (expected_events === 0) {
+        assertEquals(["resolve", "construct", "end main",
+                      "reject caught", "throw in reject"], log);
+      } else {
+        testDone(iteration + 1);
+      }
+    } catch (e) {
+      %AbortJS(e + "\n" + e.stack);
+    }
+  }
+
+  %EnqueueMicrotask(checkResult);
+}
+
+testDone(0);
diff --git a/src/v8/test/debugger/debug/es6/debug-promises/reject-with-undefined-reject.js b/src/v8/test/debugger/debug/es6/debug-promises/reject-with-undefined-reject.js
new file mode 100644
index 0000000..53d6db6
--- /dev/null
+++ b/src/v8/test/debugger/debug/es6/debug-promises/reject-with-undefined-reject.js
@@ -0,0 +1,73 @@
+// 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.
+
+
+// Test debug events when a Promise is rejected, which is caught by a custom
+// promise, which has undefined for reject closure.  We expect an Exception
+// debug even calling the (undefined) custom rejected closure.
+
+Debug = debug.Debug;
+
+var expected_events = 1;
+var log = [];
+
+var p = new Promise(function(resolve, reject) {
+  log.push("resolve");
+  resolve();
+});
+
+function MyPromise(resolver) {
+  var reject = undefined;
+  var resolve = function() { };
+  log.push("construct");
+  resolver(resolve, reject);
+};
+
+MyPromise.prototype = new Promise(function() {});
+p.constructor = MyPromise;
+
+var q = p.then(
+  function() {
+    log.push("reject caught");
+    return Promise.reject(new Error("caught"));
+  });
+
+function listener(event, exec_state, event_data, data) {
+  try {
+    if (event == Debug.DebugEvent.Exception) {
+      expected_events--;
+      assertTrue(expected_events >= 0);
+      assertEquals("caught", event_data.exception().message);
+      // All of the frames on the stack are from native Javascript.
+      assertEquals(0, exec_state.frameCount());
+    }
+  } catch (e) {
+    %AbortJS(e + "\n" + e.stack);
+  }
+}
+
+Debug.setBreakOnUncaughtException();
+Debug.setListener(listener);
+
+function testDone(iteration) {
+  function checkResult() {
+    try {
+      assertTrue(iteration < 10);
+      if (expected_events === 0) {
+        assertEquals(["resolve", "construct", "end main", "reject caught"],
+                     log);
+      } else {
+        testDone(iteration + 1);
+      }
+    } catch (e) {
+      %AbortJS(e + "\n" + e.stack);
+    }
+  }
+
+  %EnqueueMicrotask(checkResult);
+}
+
+testDone(0);
+
+log.push("end main");
diff --git a/src/v8/test/debugger/debug/es6/debug-promises/stepin-constructor.js b/src/v8/test/debugger/debug/es6/debug-promises/stepin-constructor.js
new file mode 100644
index 0000000..dd18968
--- /dev/null
+++ b/src/v8/test/debugger/debug/es6/debug-promises/stepin-constructor.js
@@ -0,0 +1,46 @@
+// 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 Debug = debug.Debug;
+var exception = null;
+var breaks = [];
+
+function listener(event, exec_state, event_data, data) {
+  if (event != Debug.DebugEvent.Break) return;
+  try {
+    breaks.push(exec_state.frame(0).sourceLineText().trimLeft());
+    exec_state.prepareStep(Debug.StepAction.StepIn);
+  } catch (e) {
+    exception = e;
+  }
+}
+
+Debug.setListener(listener);
+
+function resolver(resolve, reject) {
+  print(1);
+  print(2);
+  print(3);
+  resolve();
+}
+
+debugger;
+var p = new Promise(resolver);
+
+Debug.setListener(null);
+
+var expected_breaks = [
+  "debugger;",
+  "var p = new Promise(resolver);",
+  "print(1);",
+  "print(2);",
+  "print(3);",
+  "resolve();",
+  "}",
+  "Debug.setListener(null);"
+];
+
+assertEquals(expected_breaks, breaks);
+assertNull(exception);
diff --git a/src/v8/test/debugger/debug/es6/debug-promises/stepin-handler.js b/src/v8/test/debugger/debug/es6/debug-promises/stepin-handler.js
new file mode 100644
index 0000000..a897693
--- /dev/null
+++ b/src/v8/test/debugger/debug/es6/debug-promises/stepin-handler.js
@@ -0,0 +1,60 @@
+// 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: --noalways-opt
+// Tests stepping into through Promises.
+
+Debug = debug.Debug
+var exception = null;
+var break_count = 0;
+const expected_breaks = 9;
+
+function listener(event, exec_state, event_data, data) {
+  try {
+    if (event == Debug.DebugEvent.Break) {
+      assertTrue(exec_state.frameCount() != 0, "FAIL: Empty stack trace");
+      var source = exec_state.frame(0).sourceLineText();
+      print("paused at: " + source);
+      assertTrue(source.indexOf("// Break " + break_count + ".") > 0,
+                 "Unexpected pause at: " + source + "\n" +
+                 "Expected: // Break " + break_count + ".");
+      ++break_count;
+      if (break_count !== expected_breaks) {
+        exec_state.prepareStep(Debug.StepAction.StepIn);
+      }
+    }
+  } catch(e) {
+    exception = e;
+    print(e, e.stack);
+  }
+};
+
+Debug.setListener(listener);
+
+Promise.resolve(42)
+  .then(
+    function f0() {
+      debugger;  // Break 0.
+    } // Break 1.
+  )
+  .then(callback)
+  .then(callback.bind(null))
+  .then(Object)
+  .then(callback.bind(null).bind(null))
+  .then(finalize)
+  .catch(function(err) {
+    %AbortJS("FAIL: " + err);
+  });
+
+function callback(x) {
+  return x // Break 2. // Break 4. // Break 6.
+  ; // Break 3. // Break 5. // Break 7.
+}
+
+function finalize() {
+  assertNull(exception); // Break 8.
+  assertEquals(expected_breaks, break_count);
+
+  Debug.setListener(null);
+}
diff --git a/src/v8/test/debugger/debug/es6/debug-promises/throw-caught-all.js b/src/v8/test/debugger/debug/es6/debug-promises/throw-caught-all.js
new file mode 100644
index 0000000..9b6e4fc
--- /dev/null
+++ b/src/v8/test/debugger/debug/es6/debug-promises/throw-caught-all.js
@@ -0,0 +1,66 @@
+// 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.
+
+
+// Test debug events when we listen to all exceptions and
+// there is a catch handler for the exception thrown in a Promise.
+// We expect a normal Exception debug event to be triggered.
+
+Debug = debug.Debug;
+
+var expected_events = 1;
+var log = [];
+
+var p = new Promise(function(resolve, reject) {
+  log.push("resolve");
+  resolve();
+});
+
+var q = p.then(
+  function() {
+    log.push("throw");
+    throw new Error("caught");
+  });
+
+q.catch(
+  function(e) {
+    assertEquals("caught", e.message);
+  });
+
+function listener(event, exec_state, event_data, data) {
+  try {
+    if (event == Debug.DebugEvent.Exception) {
+      expected_events--;
+      assertTrue(expected_events >= 0);
+      assertEquals("caught", event_data.exception().message);
+      assertFalse(event_data.uncaught());
+    }
+  } catch (e) {
+    %AbortJS(e + "\n" + e.stack);
+  }
+}
+
+Debug.setBreakOnException();
+Debug.setListener(listener);
+
+log.push("end main");
+
+function testDone(iteration) {
+  function checkResult() {
+    try {
+      assertTrue(iteration < 10);
+      if (expected_events === 0) {
+        assertEquals(["resolve", "end main", "throw"], log);
+      } else {
+        testDone(iteration + 1);
+      }
+    } catch (e) {
+      %AbortJS(e + "\n" + e.stack);
+    }
+  }
+
+  %EnqueueMicrotask(checkResult);
+}
+
+testDone(0);
diff --git a/src/v8/test/debugger/debug/es6/debug-promises/throw-caught-by-default-reject-handler.js b/src/v8/test/debugger/debug/es6/debug-promises/throw-caught-by-default-reject-handler.js
new file mode 100644
index 0000000..8d6319a
--- /dev/null
+++ b/src/v8/test/debugger/debug/es6/debug-promises/throw-caught-by-default-reject-handler.js
@@ -0,0 +1,75 @@
+// 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.
+
+
+// Test debug events when we only listen to uncaught exceptions and
+// there is only a default reject handler for the to-be-rejected Promise.
+// We expect only one debug event: when the first Promise is rejected
+// and only has default reject handlers. No event is triggered when
+// simply forwarding the rejection with .then's default handler.
+
+Debug = debug.Debug;
+
+var expected_events = 1;
+var log = [];
+
+var resolve, reject;
+var p0 = new Promise(function(res, rej) { resolve = res; reject = rej; });
+var p1 = p0.then(function() {
+  log.push("p0.then");
+  throw new Error("123");  // event
+});
+var p2 = p1.then(function() {
+  log.push("p1.then");
+});
+
+var q = new Promise(function(res, rej) {
+  log.push("resolve q");
+  res();
+});
+
+q.then(function() {
+  log.push("resolve p");
+  resolve();
+})
+
+
+function listener(event, exec_state, event_data, data) {
+  try {
+    if (event == Debug.DebugEvent.Exception) {
+      expected_events--;
+      assertTrue(expected_events >= 0);
+      assertTrue(event_data.uncaught());
+      // p1 is rejected, uncaught except for its default reject handler.
+      assertTrue(
+          exec_state.frame(0).sourceLineText().indexOf("// event") > 0);
+    }
+  } catch (e) {
+    %AbortJS(e + "\n" + e.stack);
+  }
+}
+
+Debug.setBreakOnUncaughtException();
+Debug.setListener(listener);
+
+log.push("end main");
+
+function testDone(iteration) {
+  function checkResult() {
+    try {
+      assertTrue(iteration < 10);
+      if (expected_events === 0) {
+        assertEquals(["resolve q", "end main", "resolve p", "p0.then"], log);
+      } else {
+        testDone(iteration + 1);
+      }
+    } catch (e) {
+      %AbortJS(e + "\n" + e.stack);
+    }
+  }
+
+  %EnqueueMicrotask(checkResult);
+}
+
+testDone(0);
diff --git a/src/v8/test/debugger/debug/es6/debug-promises/throw-caught-late.js b/src/v8/test/debugger/debug/es6/debug-promises/throw-caught-late.js
new file mode 100644
index 0000000..a8109fa
--- /dev/null
+++ b/src/v8/test/debugger/debug/es6/debug-promises/throw-caught-late.js
@@ -0,0 +1,33 @@
+// 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.
+
+
+// Test debug events when we only listen to uncaught exceptions, the Promise
+// throws, and a catch handler is installed right before throwing.
+// We expect no debug event to be triggered.
+
+Debug = debug.Debug;
+
+var p = new Promise(function(resolve, reject) {
+  resolve();
+});
+
+var q = p.then(
+  function() {
+    q.catch(function(e) {
+      assertEquals("caught", e.message);
+    });
+    throw new Error("caught");
+  });
+
+function listener(event, exec_state, event_data, data) {
+  try {
+    assertTrue(event != Debug.DebugEvent.Exception);
+  } catch (e) {
+    %AbortJS(e + "\n" + e.stack);
+  }
+}
+
+Debug.setBreakOnUncaughtException();
+Debug.setListener(listener);
diff --git a/src/v8/test/debugger/debug/es6/debug-promises/throw-caught-uncaught.js b/src/v8/test/debugger/debug/es6/debug-promises/throw-caught-uncaught.js
new file mode 100644
index 0000000..756c0f1
--- /dev/null
+++ b/src/v8/test/debugger/debug/es6/debug-promises/throw-caught-uncaught.js
@@ -0,0 +1,35 @@
+// 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.
+
+
+// Test debug events when we only listen to uncaught exceptions and
+// there is a catch handler for the exception thrown in a Promise.
+// We expect no debug event to be triggered.
+
+Debug = debug.Debug;
+
+var p = new Promise(function(resolve, reject) {
+  resolve();
+});
+
+var q = p.then(
+  function() {
+    throw new Error("caught throw");
+  });
+
+q.catch(
+  function(e) {
+    assertEquals("caught throw", e.message);
+  });
+
+function listener(event, exec_state, event_data, data) {
+  try {
+    assertTrue(event != Debug.DebugEvent.Exception);
+  } catch (e) {
+    %AbortJS(e + "\n" + e.stack);
+  }
+}
+
+Debug.setBreakOnUncaughtException();
+Debug.setListener(listener);
diff --git a/src/v8/test/debugger/debug/es6/debug-promises/throw-eventually-caught.js b/src/v8/test/debugger/debug/es6/debug-promises/throw-eventually-caught.js
new file mode 100644
index 0000000..76cce14
--- /dev/null
+++ b/src/v8/test/debugger/debug/es6/debug-promises/throw-eventually-caught.js
@@ -0,0 +1,41 @@
+// 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.
+
+
+// Test debug events when we only listen to uncaught exceptions and
+// there is a catch handler for the to-be-rejected Promise.
+// We expect no Exception debug events, since the default reject handler passes
+// the rejection on to a user-defined reject handler.
+
+Debug = debug.Debug;
+
+var resolve, reject;
+var p0 = new Promise(function(res, rej) { resolve = res; reject = rej; });
+
+var p1 = p0.then(function() {
+  throw new Error();
+});
+
+var p2 = p1.then(function() { });
+var p3 = p2.catch(function() { });
+
+var q = new Promise(function(res, rej) {
+  res();
+});
+
+q.then(function() {
+  resolve();
+})
+
+
+function listener(event, exec_state, event_data, data) {
+  try {
+    assertTrue(event != Debug.DebugEvent.Exception);
+  } catch (e) {
+    %AbortJS(e + "\n" + e.stack);
+  }
+}
+
+Debug.setBreakOnUncaughtException();
+Debug.setListener(listener);
diff --git a/src/v8/test/debugger/debug/es6/debug-promises/throw-finally-caught-all.js b/src/v8/test/debugger/debug/es6/debug-promises/throw-finally-caught-all.js
new file mode 100644
index 0000000..bb63367
--- /dev/null
+++ b/src/v8/test/debugger/debug/es6/debug-promises/throw-finally-caught-all.js
@@ -0,0 +1,70 @@
+// 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.
+
+
+// Test debug events when we listen to all exceptions and
+// there is a catch handler for the exception thrown in a Promise, first
+// caught by a try-finally, and immediately rethrown.
+// We expect a normal Exception debug event to be triggered.
+
+Debug = debug.Debug;
+
+var expected_events = 1;
+var log = [];
+
+var p = new Promise(function(resolve, reject) {
+  log.push("resolve");
+  resolve();
+});
+
+var q = p.then(
+  function() {
+    log.push("throw");
+    try {
+      throw new Error("caught");
+    } finally {
+    }
+  });
+
+q.catch(
+  function(e) {
+    assertEquals("caught", e.message);
+  });
+
+function listener(event, exec_state, event_data, data) {
+  try {
+    if (event == Debug.DebugEvent.Exception) {
+      expected_events--;
+      assertTrue(expected_events >= 0);
+      assertEquals("caught", event_data.exception().message);
+      assertFalse(event_data.uncaught());
+    }
+  } catch (e) {
+    %AbortJS(e + "\n" + e.stack);
+  }
+}
+
+Debug.setBreakOnException();
+Debug.setListener(listener);
+
+log.push("end main");
+
+function testDone(iteration) {
+  function checkResult() {
+    try {
+      assertTrue(iteration < 10);
+      if (expected_events === 0) {
+        assertEquals(["resolve", "end main", "throw"], log);
+      } else {
+        testDone(iteration + 1);
+      }
+    } catch (e) {
+      %AbortJS(e + "\n" + e.stack);
+    }
+  }
+
+  %EnqueueMicrotask(checkResult);
+}
+
+testDone(0);
diff --git a/src/v8/test/debugger/debug/es6/debug-promises/throw-in-constructor.js b/src/v8/test/debugger/debug/es6/debug-promises/throw-in-constructor.js
new file mode 100644
index 0000000..a1febf4
--- /dev/null
+++ b/src/v8/test/debugger/debug/es6/debug-promises/throw-in-constructor.js
@@ -0,0 +1,38 @@
+// 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.
+
+
+// Test debug events when we only listen to uncaught exceptions and
+// an exception is thrown in the Promise constructor.
+// We expect an Exception debug event with a promise to be triggered.
+
+Debug = debug.Debug;
+
+var step = 0;
+var exception = null;
+
+function listener(event, exec_state, event_data, data) {
+  try {
+    if (event == Debug.DebugEvent.Exception) {
+      assertEquals(0, step);
+      assertEquals("uncaught", event_data.exception().message);
+      assertTrue(event_data.uncaught());
+      // Assert that the debug event is triggered at the throw site.
+      assertTrue(exec_state.frame(0).sourceLineText().indexOf("// event") > 0);
+      step++;
+    }
+  } catch (e) {
+    exception = e;
+  }
+}
+
+Debug.setBreakOnUncaughtException();
+Debug.setListener(listener);
+
+var p = new Promise(function(resolve, reject) {
+  throw new Error("uncaught");  // event
+});
+
+assertEquals(1, step);
+assertNull(exception);
diff --git a/src/v8/test/debugger/debug/es6/debug-promises/throw-uncaught-all.js b/src/v8/test/debugger/debug/es6/debug-promises/throw-uncaught-all.js
new file mode 100644
index 0000000..8b6f343
--- /dev/null
+++ b/src/v8/test/debugger/debug/es6/debug-promises/throw-uncaught-all.js
@@ -0,0 +1,64 @@
+// 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.
+
+
+// Test debug events when we listen to all exceptions and
+// there is no catch handler for the exception thrown in a Promise.
+// We expect an Exception debug event with a promise to be triggered.
+
+Debug = debug.Debug;
+
+var expected_events = 1;
+var log = [];
+
+var p = new Promise(function(resolve, reject) {
+  log.push("resolve");
+  resolve();
+});
+
+var q = p.then(
+  function() {
+    log.push("throw");
+    throw new Error("uncaught");  // event
+  });
+
+function listener(event, exec_state, event_data, data) {
+  try {
+    // Ignore exceptions during startup in stress runs.
+    if (event == Debug.DebugEvent.Exception) {
+      expected_events--;
+      assertTrue(expected_events >= 0);
+      assertEquals("uncaught", event_data.exception().message);
+      assertTrue(event_data.uncaught());
+      // Assert that the debug event is triggered at the throw site.
+      assertTrue(exec_state.frame(0).sourceLineText().indexOf("// event") > 0);
+    }
+  } catch (e) {
+    %AbortJS(e + "\n" + e.stack);
+  }
+}
+
+Debug.setBreakOnException();
+Debug.setListener(listener);
+
+log.push("end main");
+
+function testDone(iteration) {
+  function checkResult() {
+    try {
+      assertTrue(iteration < 10);
+      if (expected_events === 0) {
+        assertEquals(["resolve", "end main", "throw"], log);
+      } else {
+        testDone(iteration + 1);
+      }
+    } catch (e) {
+      %AbortJS(e + "\n" + e.stack);
+    }
+  }
+
+  %EnqueueMicrotask(checkResult);
+}
+
+testDone(0);
diff --git a/src/v8/test/debugger/debug/es6/debug-promises/throw-uncaught-uncaught.js b/src/v8/test/debugger/debug/es6/debug-promises/throw-uncaught-uncaught.js
new file mode 100644
index 0000000..abdc267
--- /dev/null
+++ b/src/v8/test/debugger/debug/es6/debug-promises/throw-uncaught-uncaught.js
@@ -0,0 +1,63 @@
+// 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.
+
+
+// Test debug events when we only listen to uncaught exceptions and
+// there is a catch handler for the exception thrown in a Promise.
+// We expect an Exception debug event with a promise to be triggered.
+
+Debug = debug.Debug;
+
+var expected_events = 1;
+var log = [];
+
+var p = new Promise(function(resolve, reject) {
+  log.push("resolve");
+  resolve();
+});
+
+var q = p.then(
+  function() {
+    log.push("throw");
+    throw new Error("uncaught");  // event
+  });
+
+function listener(event, exec_state, event_data, data) {
+  try {
+    if (event == Debug.DebugEvent.Exception) {
+      expected_events--;
+      assertTrue(expected_events >= 0);
+      assertEquals("uncaught", event_data.exception().message);
+      assertTrue(event_data.uncaught());
+      // Assert that the debug event is triggered at the throw site.
+      assertTrue(exec_state.frame(0).sourceLineText().indexOf("// event") > 0);
+    }
+  } catch (e) {
+    %AbortJS(e + "\n" + e.stack);
+  }
+}
+
+Debug.setBreakOnUncaughtException();
+Debug.setListener(listener);
+
+log.push("end main");
+
+function testDone(iteration) {
+  function checkResult() {
+    try {
+      assertTrue(iteration < 10);
+      if (expected_events === 0) {
+        assertEquals(["resolve", "end main", "throw"], log);
+      } else {
+        testDone(iteration + 1);
+      }
+    } catch (e) {
+      %AbortJS(e + "\n" + e.stack);
+    }
+  }
+
+  %EnqueueMicrotask(checkResult);
+}
+
+testDone(0);
diff --git a/src/v8/test/debugger/debug/es6/debug-promises/throw-with-throw-in-reject.js b/src/v8/test/debugger/debug/es6/debug-promises/throw-with-throw-in-reject.js
new file mode 100644
index 0000000..b17054b
--- /dev/null
+++ b/src/v8/test/debugger/debug/es6/debug-promises/throw-with-throw-in-reject.js
@@ -0,0 +1,84 @@
+// 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.
+
+
+// Test debug events when an exception is thrown inside a Promise, which is
+// caught by a custom promise, which throws a new exception in its reject
+// handler. We expect two Exception debug events:
+//  1) when the exception is thrown in the promise q.
+//  2) when the custom reject closure in MyPromise throws an exception.
+
+Debug = debug.Debug;
+
+var expected_events = 1;
+var log = [];
+
+var p = new Promise(function(resolve, reject) {
+  log.push("resolve");
+  resolve();
+});
+
+function MyPromise(resolver) {
+  var reject = function() {
+    log.push("throw in reject");
+    throw new Error("reject");  // event
+  };
+  var resolve = function() { };
+  log.push("construct");
+  resolver(resolve, reject);
+};
+
+MyPromise.prototype = new Promise(function() {});
+MyPromise.__proto__ = Promise;
+p.constructor = MyPromise;
+
+var q = p.then(
+  function() {
+    log.push("throw caught");
+    throw new Error("caught");  // event
+  });
+
+function listener(event, exec_state, event_data, data) {
+  try {
+    if (event == Debug.DebugEvent.Exception) {
+      expected_events--;
+      assertTrue(expected_events >= 0);
+      if (expected_events == 0) {
+        assertEquals(["resolve", "construct", "end main",
+                      "throw caught"], log);
+        assertEquals("caught", event_data.exception().message);
+      } else {
+        assertUnreachable();
+      }
+      assertTrue(exec_state.frame(0).sourceLineText().indexOf('// event') > 0);
+    }
+  } catch (e) {
+    %AbortJS(e + "\n" + e.stack);
+  }
+}
+
+Debug.setBreakOnUncaughtException();
+Debug.setListener(listener);
+
+log.push("end main");
+
+function testDone(iteration) {
+  function checkResult() {
+    try {
+      assertTrue(iteration < 10);
+      if (expected_events === 0) {
+        assertEquals(["resolve", "construct", "end main",
+                      "throw caught", "throw in reject"], log);
+      } else {
+        testDone(iteration + 1);
+      }
+    } catch (e) {
+      %AbortJS(e + "\n" + e.stack);
+    }
+  }
+
+  %EnqueueMicrotask(checkResult);
+}
+
+testDone(0);
diff --git a/src/v8/test/debugger/debug/es6/debug-promises/try-reject-in-constructor.js b/src/v8/test/debugger/debug/es6/debug-promises/try-reject-in-constructor.js
new file mode 100644
index 0000000..e11dc34
--- /dev/null
+++ b/src/v8/test/debugger/debug/es6/debug-promises/try-reject-in-constructor.js
@@ -0,0 +1,40 @@
+// 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.
+
+
+// Test debug events when we only listen to uncaught exceptions and
+// the Promise is rejected within a try-catch in the Promise constructor.
+// We expect an Exception debug event with a promise to be triggered.
+
+Debug = debug.Debug;
+
+var step = 0;
+var exception = null;
+
+function listener(event, exec_state, event_data, data) {
+  try {
+    if (event == Debug.DebugEvent.Exception) {
+      assertEquals(0, step);
+      assertEquals("uncaught", event_data.exception().message);
+      assertTrue(event_data.uncaught());
+      // Assert that the debug event is triggered at the throw site.
+      assertTrue(exec_state.frame(0).sourceLineText().indexOf("// event") > 0);
+      step++;
+    }
+  } catch (e) {
+    exception = e;
+  }
+}
+
+Debug.setBreakOnUncaughtException();
+Debug.setListener(listener);
+
+var p = new Promise(function(resolve, reject) {
+  try {  // This try-catch must not prevent this uncaught reject event.
+    reject(new Error("uncaught"));  // event
+  } catch (e) { }
+});
+
+assertEquals(1, step);
+assertNull(exception);
diff --git a/src/v8/test/debugger/debug/es6/debug-promises/try-throw-reject-in-constructor.js b/src/v8/test/debugger/debug/es6/debug-promises/try-throw-reject-in-constructor.js
new file mode 100644
index 0000000..484ce14
--- /dev/null
+++ b/src/v8/test/debugger/debug/es6/debug-promises/try-throw-reject-in-constructor.js
@@ -0,0 +1,42 @@
+// 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.
+
+
+// Test debug events when we only listen to uncaught exceptions and
+// an exception is thrown in the Promise constructor, but caught in an
+// inner try-catch.  The Promise is rejected afterwards.
+// We expect an Exception debug event with a promise to be triggered.
+
+Debug = debug.Debug;
+
+var step = 0;
+var exception = null;
+
+function listener(event, exec_state, event_data, data) {
+  try {
+    if (event == Debug.DebugEvent.Exception) {
+      assertEquals(0, step);
+      assertEquals("uncaught", event_data.exception().message);
+      assertTrue(event_data.uncaught());
+      // Assert that the debug event is triggered at the throw site.
+      assertTrue(exec_state.frame(0).sourceLineText().indexOf("// event") > 0);
+      step++;
+    }
+  } catch (e) {
+    exception = e;
+  }
+}
+
+Debug.setBreakOnUncaughtException();
+Debug.setListener(listener);
+
+var p = new Promise(function(resolve, reject) {
+  try {  // This try-catch must not prevent this uncaught reject event.
+    throw new Error("caught");
+  } catch (e) { }
+  reject(new Error("uncaught"));  // event
+});
+
+assertEquals(1, step);
+assertNull(exception);
diff --git a/src/v8/test/debugger/debug/es6/debug-scope-default-param-with-eval.js b/src/v8/test/debugger/debug/es6/debug-scope-default-param-with-eval.js
new file mode 100644
index 0000000..b60eceb
--- /dev/null
+++ b/src/v8/test/debugger/debug/es6/debug-scope-default-param-with-eval.js
@@ -0,0 +1,60 @@
+// 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.
+
+
+// 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/src/v8/test/debugger/debug/es6/debug-step-destructuring-assignment.js b/src/v8/test/debugger/debug/es6/debug-step-destructuring-assignment.js
new file mode 100644
index 0000000..cbbd4c5
--- /dev/null
+++ b/src/v8/test/debugger/debug/es6/debug-step-destructuring-assignment.js
@@ -0,0 +1,85 @@
+// 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 exception = null;
+var Debug = debug.Debug;
+var break_count = 0;
+
+function listener(event, exec_state, event_data, data) {
+  if (event != Debug.DebugEvent.Break) return;
+  try {
+    var source = exec_state.frame(0).sourceLineText();
+    print(source);
+    assertTrue(source.indexOf(`// B${break_count++}`) > 0);
+    if (source.indexOf("assertEquals") > 0) {
+      exec_state.prepareStep(Debug.StepAction.StepNext);
+    } else {
+      exec_state.prepareStep(Debug.StepAction.StepIn);
+    }
+  } catch (e) {
+    exception = e;
+    print(e);
+  }
+};
+
+Debug.setListener(listener);
+
+function f() {
+  var a, b, c, d;
+  debugger;                                       // B0
+  [                                               // B1
+    a,                                            // B2
+    b,                                            // B3
+    c = 3                                         // B4
+  ] = [1, 2];
+  assertEquals({a:1,b:2,c:3}, {a, b, c});         // B5
+
+  [                                               // B6
+    a,                                            // B7
+    [
+      b,                                          // B8
+      c                                           // B9
+    ],
+    d                                             // B10
+  ] = [5, [6, 7], 8];
+  assertEquals({a:5,b:6,c:7,d:8}, {a, b, c, d});  // B11
+
+  [                                               // B12
+    a,                                            // B13
+    b,                                            // B14
+    ...c                                          // B15
+  ] = [1, 2, 3, 4];
+  assertEquals({a:1,b:2,c:[3,4]}, {a, b, c});     // B16
+
+  ({                                              // B17
+    a,                                            // B18
+    b,                                            // B19
+    c = 7                                         // B20
+  } = {a: 5, b: 6});
+  assertEquals({a:5,b:6,c:7}, {a, b, c});         // B21
+
+  ({                                              // B22
+    a,                                            // B23
+    b = return1(),                                // B24
+    c = return1()                                 // B25
+  } = {a: 5, b: 6});
+  assertEquals({a:5,b:6,c:1}, {a, b, c});         // B28
+
+  ({                                              // B29
+    x : a,                                        // B30
+    y : b,                                        // B31
+    z : c = 3                                     // B32
+  } = {x: 1, y: 2});
+  assertEquals({a:1,b:2,c:3}, {a, b, c});         // B33
+}                                                 // B34
+
+function return1() {
+  return 1                                        // B26
+  ;                                               // B27
+}
+
+f();
+Debug.setListener(null);                          // B35
+assertNull(exception);
diff --git a/src/v8/test/debugger/debug/es6/debug-step-destructuring-bind.js b/src/v8/test/debugger/debug/es6/debug-step-destructuring-bind.js
new file mode 100644
index 0000000..2e707b9
--- /dev/null
+++ b/src/v8/test/debugger/debug/es6/debug-step-destructuring-bind.js
@@ -0,0 +1,109 @@
+// 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 exception = null;
+var Debug = debug.Debug;
+var break_count = 0;
+
+function listener(event, exec_state, event_data, data) {
+  if (event != Debug.DebugEvent.Break) return;
+  try {
+    var source = exec_state.frame(0).sourceLineText();
+    print(source, break_count);
+    assertTrue(source.indexOf(`B${break_count++}`) > 0);
+    if (source.indexOf("assertEquals") > 0) {
+      exec_state.prepareStep(Debug.StepAction.StepNext);
+    } else {
+      exec_state.prepareStep(Debug.StepAction.StepIn);
+    }
+  } catch (e) {
+    exception = e;
+    print(e);
+  }
+};
+
+Debug.setListener(listener);
+
+var id = x => x;                                  // B9 B10 B36 B37
+
+function test() {
+  debugger;                                       // B0
+  function fx1([
+                a,                                // B2
+                b                                 // B3
+              ]) {
+    assertEquals([1, 2], [a, b]);                 // B4
+  }                                               // B5
+  fx1([1, 2, 3]);                                 // B1
+
+  function f2([
+                a,                                // B7
+                b = id(3)                         // B8
+              ]) {
+    assertEquals([4, 3], [a, b]);                 // B11
+  }                                               // B12
+  f2([4]);                                        // B6
+
+  function f3({
+                x: a,                             // B14
+                y: b                              // B15
+              }) {
+    assertEquals([5, 6], [a, b]);                 // B16
+  }                                               // B17
+  f3({y: 6, x: 5});                               // B13
+
+  function f4([
+                a,                                // B19
+                {
+                  b,                              // B20
+                  c,                              // B21
+                }
+              ]) {
+    assertEquals([2, 4, 6], [a, b, c]);           // B22
+  }                                               // B23
+  f4([2, {c: 6, b: 4}]);                          // B18
+
+  function f5([
+                {
+                  a,                              // B25
+                  b = 7                           // B26
+                },
+                c = 3                             // B27
+              ] = [{a:1}]) {
+    assertEquals([1, 7, 3], [a, b, c]);           // B28
+  }                                               // B29
+  f5();                                           // B24
+
+  var name = "x";                                 // B30
+  function f6({
+                [id(name)]: a,                    // B34 B35
+                b = a                             // B38
+              }) {
+    assertEquals([9, 9], [a, b]);                 // B39
+  }                                               // B40
+  var o6 = {};                                    // B31
+  o6[name] = 9;                                   // B32
+  f6(o6);                                         // B33
+
+  try {
+    throw [3, 4];                                 // B41
+  } catch ([
+             a,                                   // B42
+             b,                                   // B43
+             c = 6                                // B44
+           ]) {
+    assertEquals([3, 4, 6], [a, b, c]);           // B45
+  }
+
+  var {
+    x: a,
+    y: b = 9
+  } = { x: 4 };                                   // B46
+  assertEquals([4, 9], [a, b]);                   // B47
+}                                                 // B48
+
+test();
+Debug.setListener(null);                          // B49
+assertNull(exception);
diff --git a/src/v8/test/debugger/debug/es6/debug-step-into-class-extends.js b/src/v8/test/debugger/debug/es6/debug-step-into-class-extends.js
new file mode 100644
index 0000000..fb988bc
--- /dev/null
+++ b/src/v8/test/debugger/debug/es6/debug-step-into-class-extends.js
@@ -0,0 +1,41 @@
+// 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.
+
+
+'use strict';
+
+var Debug = debug.Debug
+
+var done = false;
+var stepCount = 0;
+
+function listener(event, execState, eventData, data) {
+  if (event == Debug.DebugEvent.Break) {
+    if (!done) {
+      execState.prepareStep(Debug.StepAction.StepIn);
+      var s = execState.frame().sourceLineText();
+      assertTrue(s.indexOf('// ' + stepCount + '.') !== -1);
+      stepCount++;
+    }
+  }
+};
+
+Debug.setListener(listener);
+
+function GetBase() {
+  var x = 1;   // 1.
+  var y = 2;   // 2.
+  done = true; // 3.
+  return null;
+}
+
+function f() {
+  class Derived extends GetBase() {} // 0.
+}
+
+var bp = Debug.setBreakPoint(f, 0);
+f();
+assertEquals(4, stepCount);
+
+Debug.setListener(null);
diff --git a/src/v8/test/debugger/debug/es6/debug-step-into-constructor.js b/src/v8/test/debugger/debug/es6/debug-step-into-constructor.js
new file mode 100644
index 0000000..0729059
--- /dev/null
+++ b/src/v8/test/debugger/debug/es6/debug-step-into-constructor.js
@@ -0,0 +1,117 @@
+// 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.
+
+
+'use strict';
+
+var Debug = debug.Debug
+var done, stepCount;
+var exception = null;
+
+function listener(event, execState, eventData, data) {
+  if (event != Debug.DebugEvent.Break) return;
+  try {
+    if (!done) {
+      execState.prepareStep(Debug.StepAction.StepIn);
+      var s = execState.frame().sourceLineText();
+      assertTrue(s.indexOf('// ' + stepCount + '.') !== -1);
+      stepCount++;
+    }
+  } catch (e) {
+    exception = e;
+  }
+};
+
+Debug.setListener(listener);
+
+
+class Base {
+  constructor() {
+    var x = 1;    // 1.
+    var y = 2;    // 2.
+    done = true;  // 3.
+  }
+}
+
+class Derived extends Base {}  // 0.
+
+
+(function TestBreakPointInConstructor() {
+  done = false;
+  stepCount = 1;
+  var bp = Debug.setBreakPoint(Base, 0);
+
+  new Base();
+  assertEquals(4, stepCount);
+
+  Debug.clearBreakPoint(bp);
+})();
+
+
+(function TestDefaultConstructor() {
+  done = false;
+  stepCount = 1;
+
+  var bp = Debug.setBreakPoint(Base, 0);
+  new Derived();
+  assertEquals(4, stepCount);
+
+  Debug.clearBreakPoint(bp);
+})();
+
+
+(function TestStepInto() {
+  done = false;
+  stepCount = -1;
+
+  function f() {
+    new Derived();  // -1.
+  }
+
+  var bp = Debug.setBreakPoint(f, 0);
+  f();
+  assertEquals(4, stepCount);
+
+  Debug.clearBreakPoint(bp);
+})();
+
+
+(function TestExtraIndirection() {
+  done = false;
+  stepCount = -2;
+
+  class Derived2 extends Derived {}  // -1.
+
+  function f() {
+    new Derived2();  // -2.
+  }
+
+  var bp = Debug.setBreakPoint(f, 0);
+  f();
+  assertEquals(4, stepCount);
+
+  Debug.clearBreakPoint(bp);
+})();
+
+
+(function TestBoundClass() {
+  done = false;
+  stepCount = -1;
+
+  var bound = Derived.bind(null);
+
+  function f() {
+    new bound();  // -1.
+  }
+
+  var bp = Debug.setBreakPoint(f, 0);
+  f();
+  assertEquals(4, stepCount);
+
+  Debug.clearBreakPoint(bp);
+})();
+
+
+Debug.setListener(null);
+assertNull(exception);
diff --git a/src/v8/test/debugger/debug/es6/debug-step-into-regexp-subclass.js b/src/v8/test/debugger/debug/es6/debug-step-into-regexp-subclass.js
new file mode 100644
index 0000000..4b0648f
--- /dev/null
+++ b/src/v8/test/debugger/debug/es6/debug-step-into-regexp-subclass.js
@@ -0,0 +1,36 @@
+// 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.
+
+
+Debug = debug.Debug
+
+var exception = null;
+var break_count = 0;
+
+function listener(event, exec_state, event_data, data) {
+  if (event != Debug.DebugEvent.Break) return;
+  try {
+    print(event_data.sourceLineText());
+    assertTrue(
+        event_data.sourceLineText().indexOf(`Break ${break_count++}.`) > 0);
+    exec_state.prepareStep(Debug.StepAction.StepIn);
+  } catch (e) {
+    exception = e;
+  }
+};
+
+function customSplit() {
+  return "x"               // Break 2.
+  ;                        // Break 3.
+}
+var o = {};
+o[Symbol.split] = customSplit;
+
+Debug.setListener(listener);
+debugger;                  // Break 0.
+var result = "".split(o);  // Break 1.
+Debug.setListener(null);   // Break 4.
+
+assertEquals("x", result);
+assertNull(exception);
diff --git a/src/v8/test/debugger/debug/es6/debug-stepin-collections-foreach.js b/src/v8/test/debugger/debug/es6/debug-stepin-collections-foreach.js
new file mode 100644
index 0000000..32601d5
--- /dev/null
+++ b/src/v8/test/debugger/debug/es6/debug-stepin-collections-foreach.js
@@ -0,0 +1,99 @@
+// 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.
+//
+
+Debug = debug.Debug
+
+var exception = null;
+
+function listener(event, exec_state, event_data, data) {
+  try {
+    if (event == Debug.DebugEvent.Break) {
+      exec_state.prepareStep(Debug.StepAction.StepIn);
+      print(event_data.sourceLineText());
+      assertTrue(
+          event_data.sourceLineText().indexOf(`B${breaks++}`) > 0);
+    }
+  } catch (e) {
+    print(e);
+    quit();
+    exception = e;
+  }
+}
+
+function cb_set(num) {
+  print("element " + num);  // B2 B5 B8
+  return true;              // B3 B6 B9
+}                           // B4 B7 B10
+
+function cb_map(key, val) {
+  print("key " + key + ", value " + val);  // B2 B5 B8
+  return true;                             // B3 B6 B9
+}                                          // B4 B7 B10
+
+var s = new Set();
+s.add(1);
+s.add(2);
+s.add(3);
+
+var m = new Map();
+m.set('foo', 1);
+m.set('bar', 2);
+m.set('baz', 3);
+
+var breaks = 0;
+Debug.setListener(listener);
+debugger;                 // B0
+s.forEach(cb_set);        // B1
+Debug.setListener(null);  // B11
+assertNull(exception);
+assertEquals(12, breaks);
+
+breaks = 0;
+Debug.setListener(listener);
+debugger;                 // B0
+m.forEach(cb_map);        // B1
+Debug.setListener(null);  // B11
+assertNull(exception);
+assertEquals(12, breaks);
+
+// Test two levels of builtin callbacks:
+// Array.forEach calls a callback function, which by itself uses
+// Array.forEach with another callback function.
+
+function cb_set_2(num) {
+  print("element " + num);  // B3 B6 B9  B15 B18 B21 B27 B30 B33
+  return true;              // B4 B7 B10 B16 B19 B22 B28 B31 B34
+}                           // B5 B8 B11 B17 B20 B23 B29 B32 B35
+
+function cb_map_2(k, v) {
+  print(`key ${k}, value ${v}`);  // B3 B6 B9  B15 B18 B21 B27 B30 B33
+  return true;                    // B4 B7 B10 B16 B19 B22 B28 B31 B34
+}                                 // B5 B8 B11 B17 B20 B23 B29 B32 B35
+
+function cb_set_foreach(num) {
+  s.forEach(cb_set_2);      // B2  B14 B26
+  print("back.");           // B12 B24 B36
+}                           // B13 B25 B37
+
+function cb_map_foreach(key, val) {
+  m.forEach(cb_map_2);      // B2  B14 B26
+  print("back.");           // B12 B24 B36
+}                           // B13 B25 B37
+
+breaks = 0;
+Debug.setListener(listener);
+debugger;                   // B0
+s.forEach(cb_set_foreach);  // B1
+Debug.setListener(null);    // B38
+assertNull(exception);
+assertEquals(39, breaks);
+
+breaks = 0;
+Debug.setListener(listener);
+debugger;                   // B0
+m.forEach(cb_map_foreach);  // B1
+Debug.setListener(null);    // B38
+assertNull(exception);
+assertEquals(39, breaks);
diff --git a/src/v8/test/debugger/debug/es6/debug-stepin-default-parameters.js b/src/v8/test/debugger/debug/es6/debug-stepin-default-parameters.js
new file mode 100644
index 0000000..9f8eda5
--- /dev/null
+++ b/src/v8/test/debugger/debug/es6/debug-stepin-default-parameters.js
@@ -0,0 +1,45 @@
+// 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.
+
+
+Debug = debug.Debug
+
+var exception = null;
+var log = [];
+
+function listener(event, exec_state, event_data, data) {
+  if (event != Debug.DebugEvent.Break) return;
+  try {
+    print(event_data.sourceLineText());
+    var entry = "";
+    for (var i = 0; i < exec_state.frameCount(); i++) {
+      entry += exec_state.frame(i).sourceLineText().substr(-1);
+      entry += exec_state.frame(i).sourceColumn();
+    }
+    log.push(entry);
+    exec_state.prepareStep(Debug.StepAction.StepIn);
+  } catch (e) {
+    exception = e;
+  }
+};
+
+function default_arg(x) {
+  return "default";                 // d
+}                                   // e
+
+function f(arg0 = default_arg()) {  // f
+  return arg0;                      // g
+}                                   // h
+
+
+Debug.setListener(listener);
+debugger;                           // a
+var result = f();                   // b
+Debug.setListener(null);            // c
+
+assertNull(exception);
+assertEquals("default", result);
+
+assertEquals(["a0","b13","f18b13","d2f18b13","d19f18b13","g14b13","c0"],
+             log);
diff --git a/src/v8/test/debugger/debug/es6/debug-stepin-generators.js b/src/v8/test/debugger/debug/es6/debug-stepin-generators.js
new file mode 100644
index 0000000..f92c756
--- /dev/null
+++ b/src/v8/test/debugger/debug/es6/debug-stepin-generators.js
@@ -0,0 +1,48 @@
+// 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.
+
+
+Debug = debug.Debug
+var exception = null;
+var yields = 0;
+
+function listener(event, exec_state, event_data, data) {
+  if (event != Debug.DebugEvent.Break) return;
+  try {
+    var source = exec_state.frame(0).sourceLineText();
+    print(source);
+    if (/stop stepping/.test(source)) return;
+    if (/yield/.test(source)) yields++;
+    if (yields == 4) {
+      exec_state.prepareStep(Debug.StepAction.StepOut);
+    } else {
+      exec_state.prepareStep(Debug.StepAction.StepIn);
+    }
+  } catch (e) {
+    print(e, e.stack);
+    exception = e;
+  }
+};
+
+Debug.setListener(listener);
+
+function* g() {
+  for (var i = 0; i < 3; ++i) {
+    yield i;
+  }
+}
+
+var i = g();
+debugger;
+for (var num of g()) {}
+i.next();
+
+print(); // stop stepping
+
+// Not stepped into.
+i.next();
+i.next();
+
+assertNull(exception);
+assertEquals(4, yields);
diff --git a/src/v8/test/debugger/debug/es6/debug-stepin-microtasks.js b/src/v8/test/debugger/debug/es6/debug-stepin-microtasks.js
new file mode 100644
index 0000000..d3e4e6e
--- /dev/null
+++ b/src/v8/test/debugger/debug/es6/debug-stepin-microtasks.js
@@ -0,0 +1,79 @@
+// 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.
+
+
+Debug = debug.Debug
+var exception = null;
+var break_count = 0;
+const expected_breaks = 10;
+
+function listener(event, exec_state, event_data, data) {
+  try {
+    if (event == Debug.DebugEvent.Break) {
+      assertTrue(exec_state.frameCount() != 0, "FAIL: Empty stack trace");
+      var source = exec_state.frame(0).sourceLineText();
+      print("paused at: " + source);
+      assertTrue(source.indexOf("// Break " + break_count + ".") > 0,
+                 "Unexpected pause at: " + source + "\n" +
+                 "Expected: // Break " + break_count + ".");
+      if (source.indexOf("StepOver.") !== -1) {
+        exec_state.prepareStep(Debug.StepAction.StepNext);
+      } else if (source.indexOf("StepOut.") !== -1) {
+        exec_state.prepareStep(Debug.StepAction.StepOut);
+      } else {
+        exec_state.prepareStep(Debug.StepAction.StepIn);
+      }
+      ++break_count;
+    }
+  } catch (e) {
+    exception = e;
+    print(e, e.stack);
+  }
+};
+
+Debug.setListener(listener);
+
+Promise.resolve(42)
+  .then(promise1)
+  .then(Object) // Should skip stepping into native.
+  .then(Boolean) // Should skip stepping into native.
+  .then(promise2)
+  .catch(promise3)
+  .then(promise4)
+  .catch(function(e) {
+    %AbortJS("FAIL: uncaught exception " + e);
+  });
+
+function promise1() {
+  debugger; // Break 0.
+  return exception || 1 // Break 1.
+  ; // Break 2. StepOver.
+}
+
+function promise2() {
+  throw new Error; // Break 3.
+}
+
+function promise3() {
+  return break_count // Break 4.
+  ; // Break 5.
+}
+
+function promise4() {
+  finalize(); // Break 6. StepOver.
+  return 0 // Break 7.
+  ; // Break 8. StepOut.
+}
+
+function finalize() {
+  Promise.resolve().then(function() {
+    if (expected_breaks !== break_count) { // Break 9. StepOut.
+      %AbortJS("FAIL: expected <" + expected_breaks + "> breaks instead of <" +
+               break_count + ">");
+    }
+    if (exception !== null) {
+      %AbortJS("FAIL: exception: " + exception);
+    }
+  });
+}
diff --git a/src/v8/test/debugger/debug/es6/debug-stepin-proxies.js b/src/v8/test/debugger/debug/es6/debug-stepin-proxies.js
new file mode 100644
index 0000000..546ee64
--- /dev/null
+++ b/src/v8/test/debugger/debug/es6/debug-stepin-proxies.js
@@ -0,0 +1,60 @@
+// 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.
+
+
+Debug = debug.Debug
+
+var exception = null;
+var log = [];
+
+function listener(event, exec_state, event_data, data) {
+  if (event != Debug.DebugEvent.Break) return;
+  try {
+    print(event_data.sourceLineText());
+    var entry = "";
+    for (var i = 0; i < exec_state.frameCount(); i++) {
+      entry += exec_state.frame(i).sourceLineText().substr(-1);
+      entry += exec_state.frame(i).sourceColumn();
+    }
+    log.push(entry);
+    exec_state.prepareStep(Debug.StepAction.StepIn);
+  } catch (e) {
+    exception = e;
+  }
+};
+
+var target = {};
+var handler = {
+  has: function(target, name) {
+    return true;                     // h
+  },                                 // i
+  get: function(target, name) {
+    return 42;                       // j
+  },                                 // k
+  set: function(target, name, value) {
+    return false;                    // l
+  },                                 // m
+}
+
+var proxy = new Proxy(target, handler);
+
+Debug.setListener(listener);
+debugger;                            // a
+var has = "step" in proxy;           // b
+var get = proxy.step;                // c
+proxy.step = 43;                     // d
+
+Debug.setListener(null);             // g
+
+assertNull(exception);
+assertTrue(has);
+assertEquals(42, get);
+
+assertEquals([
+  "a0",
+  "b10", "h4b17", "h16b17", // [[Has]]
+  "c10", "j4c16", "j14c16", // [[Get]]
+  "d0", "l4d11", "l17d11",  // [[Set]]
+  "g0"
+], log);
diff --git a/src/v8/test/debugger/debug/es6/debug-stepin-string-template.js b/src/v8/test/debugger/debug/es6/debug-stepin-string-template.js
new file mode 100644
index 0000000..178424a
--- /dev/null
+++ b/src/v8/test/debugger/debug/es6/debug-stepin-string-template.js
@@ -0,0 +1,59 @@
+// 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.
+
+
+Debug = debug.Debug
+
+var exception = null;
+var log = [];
+
+function listener(event, exec_state, event_data, data) {
+  if (event != Debug.DebugEvent.Break) return;
+  try {
+    print(event_data.sourceLineText());
+    var entry = "";
+    for (var i = 0; i < exec_state.frameCount(); i++) {
+      entry += exec_state.frame(i).sourceLineText().substr(-1);
+      entry += exec_state.frame(i).sourceColumn();
+    }
+    log.push(entry);
+    exec_state.prepareStep(Debug.StepAction.StepIn);
+  } catch (e) {
+    exception = e;
+  }
+};
+
+function u(x) {
+  return x.toUpperCase();                         // d
+}                                                 // e
+
+var n = 3;
+
+var o = {
+  toString: function() {
+    return "D";                                   // f
+  }                                               // g
+}
+
+
+
+Debug.setListener(listener);
+debugger;                                         // a
+var s = `1 ${u("a")} 2 ${u("b")} 3 ${n} 4 ${o}`;  // b
+Debug.setListener(null);                          // c
+
+assertNull(exception);
+
+assertEquals([
+  "a0",
+  "b8",
+  "d11b13",
+  "d25b13",
+  "b25",
+  "d11b25",
+  "d25b25",
+  "f4b44",
+  "f15b44",
+  "c0"
+], log);
diff --git a/src/v8/test/debugger/debug/es6/debug-stepnext-for.js b/src/v8/test/debugger/debug/es6/debug-stepnext-for.js
new file mode 100644
index 0000000..878dda9
--- /dev/null
+++ b/src/v8/test/debugger/debug/es6/debug-stepnext-for.js
@@ -0,0 +1,135 @@
+// 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
+
+Debug = debug.Debug;
+var break_count = 0
+var exception = null;
+var log = []
+
+var s = 0;
+var a = [1, 2, 3];
+var b = [1, 2, 3, 4];
+var null_value = null;
+var i = 0;
+
+function f() {
+  "use strict";
+  debugger;                      // Break a
+  var j;                         // Break b
+
+  for (var i in null_value) {    // Break c
+    s += a[i];
+  }
+
+  for (j in null_value) {        // Break d
+    s += a[j];
+  }
+
+  for (var i in a) {             // Break e
+    s += a[i];                   // Break E
+  }
+
+  for (j in a) {                 // Break f
+    s += a[j];                   // Break F
+  }
+
+  for (let i in a) {             // Break g
+    s += a[i];                   // Break G
+  }
+
+  for (var i of a) {             // Break h
+    s += i;                      // Break H
+  }
+
+  for (j of a) {                 // Break i
+    s += j;                      // Break I
+  }
+
+  for (let i  of  a) {           // Break j
+    s += i;                      // Break J
+  }
+
+  for (var i = 0; i < 3; i++) {  // Break k
+    s += a[i];                   // Break K
+  }
+
+  for (j = 0; j < 3; j++) {      // Break l
+    s += a[j];                   // Break L
+  }
+
+  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) {
+  if (event != Debug.DebugEvent.Break) return;
+  try {
+    var line = exec_state.frame(0).sourceLineText();
+    var col = exec_state.frame(0).sourceColumn();
+    print(line);
+    var match = line.match(/\/\/ Break (\w)$/);
+    assertEquals(2, match.length);
+    log.push(match[1] + col);
+    exec_state.prepareStep(Debug.StepAction.StepNext);
+    break_count++;
+  } catch (e) {
+    exception = e;
+  }
+}
+
+Debug.setListener(listener);
+f();
+Debug.setListener(null);         // Break z
+
+print("log:\n"+ JSON.stringify(log));
+// The let declaration differs from var in that the loop variable
+// is declared in every iteration.
+// TODO(verwaest): For-of has hacky position numbers for Symbol.iterator and
+// .next. Restore to proper positions once the CallPrinter can disambiguate
+// based on other values.
+var expected = [
+  // Entry
+  "a2",
+  // Empty for-in-var: get enumerable
+  "c16",
+  // Empty for-in: get enumerable
+  "d12",
+  // For-in-var: get enumerable, assign, body, assign, body, ...
+  "e16","e11","E4","e11","E4","e11","E4","e11",
+  // For-in: get enumerable, assign, body, assign, body, ...
+  "f12","f7","F4","f7","F4","f7","F4","f7",
+  // 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","h11","H4","h11","H4","h11","H4","h11",
+  // For-of: [Symbol.iterator](), next(), body, next(), body, ...
+  "i12","i7","I4","i7","I4","i7","I4","i7",
+  // For-of-let: [Symbol.iterator](), next(), body, next(), ...
+  "j18","j11","J4","j11","J4","j11","J4","j11",
+  // 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", "n11",
+  // Spread: expression statement, spread
+  "o2", "o9",
+  // Exit.
+  "y0","z0",
+]
+print("expected:\n"+ JSON.stringify(expected));
+
+assertArrayEquals(expected, log);
+assertEquals(54, s);
+assertNull(exception);
diff --git a/src/v8/test/debugger/debug/es6/debug-stepnext-generators.js b/src/v8/test/debugger/debug/es6/debug-stepnext-generators.js
new file mode 100644
index 0000000..9660300
--- /dev/null
+++ b/src/v8/test/debugger/debug/es6/debug-stepnext-generators.js
@@ -0,0 +1,48 @@
+// 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.
+
+Debug = debug.Debug
+var exception = null;
+var breaks = 0;
+
+function listener(event, exec_state, event_data, data) {
+  if (event != Debug.DebugEvent.Break) return;
+  try {
+    var source = exec_state.frame(0).sourceLineText();
+    assertTrue(RegExp(`B${breaks++}`).test(source));
+    if (/stop/.test(source)) return;
+    if (/step out/.test(source)) {
+      exec_state.prepareStep(Debug.StepAction.StepOut);
+    } else if (/step in/.test(source)) {
+      exec_state.prepareStep(Debug.StepAction.StepIn);
+    } else {
+      exec_state.prepareStep(Debug.StepAction.StepNext);
+    }
+  } catch (e) {
+    print(e, e.stack);
+    exception = e;
+  }
+}
+
+Debug.setListener(listener);
+
+function * g() {
+  debugger;  // B0
+  yield 1;   // B1
+  yield 2;   // B2 step out
+  yield 3;   // B5
+  yield 4;   // B6 step out
+  return 2 * (yield 5);
+}
+
+var i = g();
+assertEquals(1, i.next().value);
+assertEquals(2, i.next().value);   // B3
+assertEquals(3, i.next().value);   // B4 step in
+assertEquals(4, i.next().value);   // B7
+assertEquals(5, i.next().value);   // B8
+assertEquals(6, i.next(3).value);  // B9 stop
+
+assertNull(exception);
+assertEquals(10, breaks);
diff --git a/src/v8/test/debugger/debug/es6/default-parameters-debug.js b/src/v8/test/debugger/debug/es6/default-parameters-debug.js
new file mode 100644
index 0000000..87ff386
--- /dev/null
+++ b/src/v8/test/debugger/debug/es6/default-parameters-debug.js
@@ -0,0 +1,54 @@
+// 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: --noanalyze-environment-liveness
+
+
+Debug = debug.Debug
+
+listenerComplete = false;
+breakPointCount = 0;
+exception = null;
+
+function listener(event, exec_state, event_data, data) {
+  if (event != Debug.DebugEvent.Break) return;
+  try {
+    breakPointCount++;
+    if (breakPointCount == 1) {
+      // Break point in initializer for parameter `a`, invoked by
+      // initializer for parameter `b`
+      assertEquals('default', exec_state.frame(0).evaluate('mode').value());
+      assertTrue(exec_state.frame(1).evaluate('b').isUndefined());
+      assertTrue(exec_state.frame(1).evaluate('c').isUndefined());
+    } else if (breakPointCount == 2) {
+      // Break point in IIFE initializer for parameter `c`
+      assertEquals('modeFn', exec_state.frame(1).evaluate('a.name').value());
+      assertEquals('default', exec_state.frame(1).evaluate('b').value());
+      assertTrue(exec_state.frame(1).evaluate('c').isUndefined());
+    } else if (breakPointCount == 3) {
+      // Break point in function body --- `c` parameter is shadowed
+      assertEquals('modeFn', exec_state.frame(0).evaluate('a.name').value());
+      assertEquals('default', exec_state.frame(0).evaluate('b').value());
+      assertEquals('local', exec_state.frame(0).evaluate('d').value());
+    }
+  } catch (e) {
+    exception = e;
+  }
+};
+
+// Add the debug event listener.
+Debug.setListener(listener);
+
+function f(a = function modeFn(mode) { debugger; return mode; },
+           b = a("default"),
+           c = (function() { debugger; })()) {
+  var d = 'local';
+  debugger;
+};
+
+f();
+
+// Make sure that the debug event listener vas invoked.
+assertEquals(3, breakPointCount);
+assertNull(exception);
diff --git a/src/v8/test/debugger/debug/es6/generators-debug-liveedit.js b/src/v8/test/debugger/debug/es6/generators-debug-liveedit.js
new file mode 100644
index 0000000..3ae359a
--- /dev/null
+++ b/src/v8/test/debugger/debug/es6/generators-debug-liveedit.js
@@ -0,0 +1,137 @@
+// 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.
+
+
+var Debug = debug.Debug;
+var LiveEdit = Debug.LiveEdit;
+
+unique_id = 0;
+
+var Generator = (function*(){}).constructor;
+
+function assertIteratorResult(value, done, result) {
+  assertEquals({value: value, done: done}, result);
+}
+
+function MakeGenerator() {
+  // Prevents eval script caching.
+  unique_id++;
+  return Generator('callback',
+      "/* " + unique_id + "*/\n" +
+      "yield callback();\n" +
+      "return 'Cat';\n");
+}
+
+function MakeFunction() {
+  // Prevents eval script caching.
+  unique_id++;
+  return Function('callback',
+      "/* " + unique_id + "*/\n" +
+      "callback();\n" +
+      "return 'Cat';\n");
+}
+
+// First, try MakeGenerator with no perturbations.
+(function(){
+  var generator = MakeGenerator();
+  function callback() {};
+  var iter = generator(callback);
+  assertIteratorResult(undefined, false, iter.next());
+  assertIteratorResult("Cat", true, iter.next());
+})();
+
+function ExecuteInDebugContext(f) {
+  var result;
+  var exception = null;
+  Debug.setListener(function(event) {
+    if (event == Debug.DebugEvent.Break) {
+      try {
+        result = f();
+      } catch (e) {
+        // Rethrow this exception later.
+        exception = e;
+      }
+    }
+  });
+  debugger;
+  Debug.setListener(null);
+  if (exception !== null) throw exception;
+  return result;
+}
+
+function patch(fun, from, to) {
+  function debug() {
+    var log = new Array();
+    var script = Debug.findScript(fun);
+    var pos = script.source.indexOf(from);
+    try {
+      LiveEdit.TestApi.ApplySingleChunkPatch(script, pos, from.length, to,
+                                             log);
+    } finally {
+      print("Change log: " + JSON.stringify(log) + "\n");
+    }
+  }
+  ExecuteInDebugContext(debug);
+}
+
+// Try to edit a MakeGenerator while it's running, then again while it's
+// stopped.
+(function(){
+  var generator = MakeGenerator();
+
+  var gen_patch_attempted = false;
+  function attempt_gen_patch() {
+    assertFalse(gen_patch_attempted);
+    gen_patch_attempted = true;
+    assertThrows(function() { patch(generator, "'Cat'", "'Capybara'") },
+                 LiveEdit.Failure);
+  };
+  var iter = generator(attempt_gen_patch);
+  assertIteratorResult(undefined, false, iter.next());
+  // Patch should not succeed because there is a live generator activation on
+  // the stack.
+  assertIteratorResult("Cat", true, iter.next());
+  assertTrue(gen_patch_attempted);
+
+  // At this point one iterator is live, but closed, so the patch will succeed.
+  patch(generator, "'Cat'", "'Capybara'");
+  iter = generator(function(){});
+  assertIteratorResult(undefined, false, iter.next());
+  // Patch successful.
+  assertIteratorResult("Capybara", true, iter.next());
+
+  // Patching will fail however when a live iterator is suspended.
+  iter = generator(function(){});
+  assertIteratorResult(undefined, false, iter.next());
+  assertThrows(function() { patch(generator, "'Capybara'", "'Tapir'") },
+               LiveEdit.Failure);
+  assertIteratorResult("Capybara", true, iter.next());
+
+  // Try to patch functions with activations inside and outside generator
+  // function activations.  We should succeed in the former case, but not in the
+  // latter.
+  var fun_outside = MakeFunction();
+  var fun_inside = MakeFunction();
+  var fun_patch_attempted = false;
+  var fun_patch_restarted = false;
+  function attempt_fun_patches() {
+    if (fun_patch_attempted) {
+      assertFalse(fun_patch_restarted);
+      fun_patch_restarted = true;
+      return;
+    }
+    fun_patch_attempted = true;
+    // Patching outside a generator activation must fail.
+    assertThrows(function() { patch(fun_outside, "'Cat'", "'Cobra'") },
+                 LiveEdit.Failure);
+    // Patching inside a generator activation may succeed.
+    patch(fun_inside, "'Cat'", "'Koala'");
+  }
+  iter = generator(function() { return fun_inside(attempt_fun_patches) });
+  assertEquals('Cat',
+               fun_outside(function () {
+                 assertIteratorResult('Koala', false, iter.next());
+                 assertTrue(fun_patch_restarted);
+               }));
+})();
diff --git a/src/v8/test/debugger/debug/es6/generators-debug-scopes.js b/src/v8/test/debugger/debug/es6/generators-debug-scopes.js
new file mode 100644
index 0000000..a46dc8b
--- /dev/null
+++ b/src/v8/test/debugger/debug/es6/generators-debug-scopes.js
@@ -0,0 +1,284 @@
+// 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: --noanalyze-environment-liveness
+
+var Debug = debug.Debug;
+var global_marker = 7;
+
+function RunTest(name, formals_and_body, args, handler, continuation) {
+  var handler_called = false;
+  var exception = null;
+
+  function listener(event, exec_state, event_data, data) {
+    try {
+      if (event == Debug.DebugEvent.Break) {
+        handler_called = true;
+        handler(exec_state);
+      }
+    } catch (e) {
+      exception = e;
+    }
+  }
+
+  function run(thunk) {
+    handler_called = false;
+    exception = null;
+
+    var res = thunk();
+    if (continuation)
+      continuation(res);
+
+    assertTrue(handler_called, "listener not called for " + name);
+    assertNull(exception, name + " / " + exception);
+  }
+
+  var fun = Function.apply(null, formals_and_body);
+  var gen = (function*(){}).constructor.apply(null, formals_and_body);
+
+  Debug.setListener(listener);
+
+  run(function () { return fun.apply(null, args) });
+  run(function () { return gen.apply(null, args).next().value });
+
+  // TODO(wingo): Uncomment after bug 2838 is fixed.
+  // Debug.setListener(null);
+}
+
+// Check that two scope are the same.
+function assertScopeMirrorEquals(scope1, scope2) {
+  assertEquals(scope1.scopeType(), scope2.scopeType());
+  assertEquals(scope1.frameIndex(), scope2.frameIndex());
+  assertEquals(scope1.scopeIndex(), scope2.scopeIndex());
+  assertPropertiesEqual(scope1.scopeObject().value(), scope2.scopeObject().value());
+}
+
+function CheckFastAllScopes(scopes, exec_state) {
+  var fast_all_scopes = exec_state.frame().allScopes(true);
+  var length = fast_all_scopes.length;
+  assertTrue(scopes.length >= length);
+  for (var i = 0; i < scopes.length && i < length; i++) {
+    var scope = fast_all_scopes[length - i - 1];
+    assertEquals(scopes[scopes.length - i - 1], scope.scopeType());
+  }
+}
+
+// Check that the scope chain contains the expected types of scopes.
+function CheckScopeChain(scopes, exec_state) {
+  var all_scopes = exec_state.frame().allScopes();
+  assertEquals(scopes.length, exec_state.frame().scopeCount());
+  assertEquals(scopes.length, all_scopes.length, "FrameMirror.allScopes length");
+  for (var i = 0; i < scopes.length; i++) {
+    var scope = exec_state.frame().scope(i);
+    assertEquals(scopes[i], scope.scopeType());
+    assertScopeMirrorEquals(all_scopes[i], scope);
+
+    // Check the global object when hitting the global scope.
+    if (scopes[i] == debug.ScopeType.Global) {
+      assertEquals(global_marker, scope.scopeObject().value().global_marker);
+    }
+  }
+  CheckFastAllScopes(scopes, exec_state);
+}
+
+// Check that the content of the scope is as expected. For functions just check
+// that there is a function.
+function CheckScopeContent(content, number, exec_state) {
+  var scope = exec_state.frame().scope(number);
+  var count = 0;
+  for (var p in content) {
+    var property_mirror = scope.scopeObject().property(p);
+    assertFalse(property_mirror.isUndefined(),
+                'property ' + p + ' not found in scope');
+    assertEquals(content[p], property_mirror.value().value(),
+                 'property ' + p + ' has unexpected value');
+    count++;
+  }
+
+  // 'arguments' and might be exposed in the local and closure scope. Just
+  // ignore this.
+  var scope_size = scope.scopeObject().properties().length;
+  if (!scope.scopeObject().property('arguments').isUndefined()) {
+    scope_size--;
+  }
+  // Skip property with empty name.
+  if (!scope.scopeObject().property('').isUndefined()) {
+    scope_size--;
+  }
+
+  if (scope_size < count) {
+    print('Names found in scope:');
+    var names = scope.scopeObject().propertyNames();
+    for (var i = 0; i < names.length; i++) {
+      print(names[i]);
+    }
+  }
+  assertTrue(scope_size >= count);
+}
+
+
+// Simple empty local scope.
+RunTest("Local 1",
+        ['debugger;'],
+        [],
+        function (exec_state) {
+          CheckScopeChain([debug.ScopeType.Local,
+                           debug.ScopeType.Script,
+                           debug.ScopeType.Global], exec_state);
+          CheckScopeContent({}, 0, exec_state);
+        });
+
+// Local scope with a parameter.
+RunTest("Local 2",
+        ['a', 'debugger;'],
+        [1],
+        function (exec_state) {
+          CheckScopeChain([debug.ScopeType.Local,
+                           debug.ScopeType.Script,
+                           debug.ScopeType.Global], exec_state);
+          CheckScopeContent({a:1}, 0, exec_state);
+        });
+
+// Local scope with a parameter and a local variable.
+RunTest("Local 3",
+        ['a', 'var x = 3; debugger;'],
+        [1],
+        function (exec_state) {
+          CheckScopeChain([debug.ScopeType.Local,
+                           debug.ScopeType.Script,
+                           debug.ScopeType.Global], exec_state);
+          CheckScopeContent({a:1,x:3}, 0, exec_state);
+        });
+
+// Local scope with parameters and local variables.
+RunTest("Local 4",
+        ['a', 'b', 'var x = 3; var y = 4; debugger;'],
+        [1, 2],
+        function (exec_state) {
+          CheckScopeChain([debug.ScopeType.Local,
+                           debug.ScopeType.Script,
+                           debug.ScopeType.Global], exec_state);
+          CheckScopeContent({a:1,b:2,x:3,y:4}, 0, exec_state);
+        });
+
+// Empty local scope with use of eval.
+RunTest("Local 5",
+        ['eval(""); debugger;'],
+        [],
+        function (exec_state) {
+          CheckScopeChain([debug.ScopeType.Local,
+                           debug.ScopeType.Script,
+                           debug.ScopeType.Global], exec_state);
+          CheckScopeContent({}, 0, exec_state);
+        });
+
+// Local introducing local variable using eval.
+RunTest("Local 6",
+        ['eval("var i = 5"); debugger;'],
+        [],
+        function (exec_state) {
+          CheckScopeChain([debug.ScopeType.Local,
+                           debug.ScopeType.Script,
+                           debug.ScopeType.Global], exec_state);
+          CheckScopeContent({i:5}, 0, exec_state);
+        });
+
+// Local scope with parameters, local variables and local variable introduced
+// using eval.
+RunTest("Local 7",
+        ['a', 'b',
+         "var x = 3; var y = 4;\n"
+         + "eval('var i = 5'); eval ('var j = 6');\n"
+         + "debugger;"],
+        [1, 2],
+        function (exec_state) {
+          CheckScopeChain([debug.ScopeType.Local,
+                           debug.ScopeType.Script,
+                           debug.ScopeType.Global], exec_state);
+          CheckScopeContent({a:1,b:2,x:3,y:4,i:5,j:6}, 0, exec_state);
+        });
+
+// Nested empty with blocks.
+RunTest("With",
+        ["with ({a:1}) { with ({b:2}) { debugger; } }"],
+        [],
+        function (exec_state) {
+          CheckScopeChain([debug.ScopeType.With,
+                           debug.ScopeType.With,
+                           debug.ScopeType.Local,
+                           debug.ScopeType.Script,
+                           debug.ScopeType.Global], exec_state);
+          CheckScopeContent({b:2}, 0, exec_state);
+          CheckScopeContent({a:1}, 1, exec_state);
+        });
+
+// Simple closure formed by returning an inner function referering the outer
+// functions arguments.
+RunTest("Closure 1",
+        ['a', 'return function() { debugger; return a; }'],
+        [1],
+        function (exec_state) {
+          CheckScopeChain([debug.ScopeType.Local,
+                           debug.ScopeType.Closure,
+                           debug.ScopeType.Script,
+                           debug.ScopeType.Global], exec_state);
+          CheckScopeContent({a:1}, 1, exec_state);
+        },
+       function (result) { result() });
+
+RunTest("The full monty",
+        ['a', 'b',
+         "var x = 3;\n" +
+         "var y = 4;\n" +
+         "eval('var i = 5');\n" +
+         "eval('var j = 6');\n" +
+         "function f(a, b) {\n" +
+         "  var x = 9;\n" +
+         "  var y = 10;\n" +
+         "  eval('var i = 11');\n" +
+         "  eval('var j = 12');\n" +
+         "  with ({j:13}){\n" +
+         "    return function() {\n" +
+         "      var x = 14;\n" +
+         "      with ({a:15}) {\n" +
+         "        with ({b:16}) {\n" +
+         "          debugger;\n" +
+         "          some_global = a;\n" +
+         "          return f;\n" +
+         "        }\n" +
+         "      }\n" +
+         "    };\n" +
+         "  }\n" +
+         "}\n" +
+         "return f(a, b);"],
+        [1, 2],
+        function (exec_state) {
+          CheckScopeChain([debug.ScopeType.With,
+                           debug.ScopeType.With,
+                           debug.ScopeType.Local,
+                           debug.ScopeType.With,
+                           debug.ScopeType.Closure,
+                           debug.ScopeType.Closure,
+                           debug.ScopeType.Script,
+                           debug.ScopeType.Global], exec_state);
+          CheckScopeContent({b:16}, 0, exec_state);
+          CheckScopeContent({a:15}, 1, exec_state);
+          CheckScopeContent({x:14}, 2, exec_state);
+          CheckScopeContent({j:13}, 3, exec_state);
+          CheckScopeContent({a:1,b:2,x:9,y:10,i:11,j:12}, 4, exec_state);
+          CheckScopeContent({a:1,b:2,x:3,y:4,i:5,j:6,f:undefined}, 5,
+                            exec_state);
+        },
+        function (result) { result() });
+
+RunTest("Catch block 1",
+        ["try { throw 'Exception'; } catch (e) { debugger; }"],
+        [],
+        function (exec_state) {
+          CheckScopeChain([debug.ScopeType.Catch,
+                           debug.ScopeType.Local,
+                           debug.ScopeType.Script,
+                           debug.ScopeType.Global], exec_state);
+          CheckScopeContent({e:'Exception'}, 0, exec_state);
+        });
diff --git a/src/v8/test/debugger/debug/es6/generators-relocation.js b/src/v8/test/debugger/debug/es6/generators-relocation.js
new file mode 100644
index 0000000..78413fd
--- /dev/null
+++ b/src/v8/test/debugger/debug/es6/generators-relocation.js
@@ -0,0 +1,60 @@
+// 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.
+
+
+var Debug = debug.Debug;
+
+function assertIteratorResult(value, done, result) {
+  assertEquals({value: value, done: done}, result);
+}
+
+function RunTest(formals_and_body, args, value1, value2) {
+  // A null listener. It isn't important what the listener does.
+  function listener(event, exec_state, event_data, data) {
+  }
+
+  // Create the generator function outside a debugging context. It will probably
+  // be lazily compiled.
+  var gen = (function*(){}).constructor.apply(null, formals_and_body);
+
+  // Instantiate the generator object.
+  var obj = gen.apply(null, args);
+
+  // Advance to the first yield.
+  assertIteratorResult(value1, false, obj.next());
+
+  // Enable the debugger, which should force recompilation of the generator
+  // function and relocation of the suspended generator activation.
+  Debug.setListener(listener);
+
+  // Add a breakpoint on line 3 (the second yield).
+  var bp = Debug.setBreakPoint(gen, 3);
+
+  // Check that the generator resumes and suspends properly.
+  assertIteratorResult(value2, false, obj.next());
+
+  // Disable debugger -- should not force recompilation.
+  Debug.clearBreakPoint(bp);
+  Debug.setListener(null);
+
+  // Run to completion.
+  assertIteratorResult(undefined, true, obj.next());
+}
+
+function prog(a, b, c) {
+  return a + ';\n' + 'yield ' + b + ';\n' + 'yield ' + c;
+}
+
+// Simple empty local scope.
+RunTest([prog('', '1', '2')], [], 1, 2);
+
+RunTest([prog('for (;;) break', '1', '2')], [], 1, 2);
+
+RunTest([prog('while (0) foo()', '1', '2')], [], 1, 2);
+
+RunTest(['a', prog('var x = 3', 'a', 'x')], [1], 1, 3);
+
+RunTest(['a', prog('', '1', '2')], [42], 1, 2);
+
+RunTest(['a', prog('for (;;) break', '1', '2')], [42], 1, 2);
diff --git a/src/v8/test/debugger/debug/es6/regress/regress-3280.js b/src/v8/test/debugger/debug/es6/regress/regress-3280.js
new file mode 100644
index 0000000..30d970a
--- /dev/null
+++ b/src/v8/test/debugger/debug/es6/regress/regress-3280.js
@@ -0,0 +1,24 @@
+// 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.
+
+
+var Debug = debug.Debug;
+
+var listener_called;
+
+function listener(event, exec_state, event_data, data) {
+  if (event == Debug.DebugEvent.Break) {
+    listener_called = true;
+    exec_state.frame().allScopes();
+  }
+}
+
+Debug.setListener(listener);
+
+function *generator_local_2(a) {
+  debugger;
+}
+generator_local_2(1).next();
+
+assertTrue(listener_called, "listener not called");
diff --git a/src/v8/test/debugger/debug/es6/regress/regress-468661.js b/src/v8/test/debugger/debug/es6/regress/regress-468661.js
new file mode 100644
index 0000000..229253d
--- /dev/null
+++ b/src/v8/test/debugger/debug/es6/regress/regress-468661.js
@@ -0,0 +1,70 @@
+// 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.
+
+
+Debug = debug.Debug
+var exception = null;
+var break_count = 0;
+const expected_breaks = 9;
+
+var expected_values =
+  [ReferenceError, undefined, 0, 0, 0, 0, 1,
+   ReferenceError, ReferenceError];
+
+function listener(event, exec_state, event_data, data) {
+  try {
+    if (event == Debug.DebugEvent.Break) {
+      assertTrue(exec_state.frameCount() != 0, "FAIL: Empty stack trace");
+      var frameMirror = exec_state.frame(0);
+
+      var v = null;;
+      try {
+        v = frameMirror.evaluate('i').value();
+      } catch(e) {
+        v = e;
+      }
+      frameMirror.allScopes();
+      var source = frameMirror.sourceLineText();
+      print("paused at: " + source);
+      assertTrue(source.indexOf("// Break " + break_count + ".") > 0,
+                 "Unexpected pause at: " + source + "\n" +
+                 "Expected: // Break " + break_count + ".");
+      if (expected_values[break_count] === ReferenceError) {
+        assertTrue(v instanceof ReferenceError);
+      } else {
+        assertSame(expected_values[break_count], v);
+      }
+      ++break_count;
+
+      if (break_count !== expected_breaks) {
+        exec_state.prepareStep(Debug.StepAction.StepIn);
+        print("Next step prepared");
+      }
+    }
+  } catch(e) {
+    exception = e;
+    print(e, e.stack);
+  }
+};
+
+Debug.setListener(listener);
+
+var sum = 0;
+(function (){
+  'use strict';
+
+  debugger; // Break 0.
+
+  for (let i=0; // Break 1.
+       i < 1;   // Break 2.  // Break 6.
+       i++) {   // Break 5.
+    let key = i; // Break 3.
+    sum += key;   // Break 4.
+  }
+}()); // Break 7.
+
+assertNull(exception); // Break 8.
+assertEquals(expected_breaks, break_count);
+
+Debug.setListener(null);