Import Cobalt 13.102542

Change-Id: I6bda7b03a2e33edfd735efcb981e2a731696b90d
diff --git a/src/v8/test/debugger/debug/compiler/debug-catch-prediction.js b/src/v8/test/debugger/debug/compiler/debug-catch-prediction.js
new file mode 100644
index 0000000..50fbf58
--- /dev/null
+++ b/src/v8/test/debugger/debug/compiler/debug-catch-prediction.js
@@ -0,0 +1,142 @@
+// 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 event catch prediction for thrown exceptions. We distinguish
+// between "caught" and "uncaught" based on the following assumptions:
+//  1) try-catch   : Will always catch the exception.
+//  2) try-finally : Will always re-throw the exception.
+
+Debug = debug.Debug;
+
+var log = [];
+
+function listener(event, exec_state, event_data, data) {
+  try {
+    if (event == Debug.DebugEvent.Exception) {
+      log.push([event_data.exception(), event_data.uncaught()]);
+    }
+  } catch (e) {
+    %AbortJS(e + "\n" + e.stack);
+  }
+}
+
+Debug.setBreakOnException();
+Debug.setListener(listener);
+
+(function TryCatch() {
+  log = [];  // Clear log.
+  function f(a) {
+    try {
+      throw "boom" + a;
+    } catch(e) {
+      return e;
+    }
+  }
+  assertEquals("boom1", f(1));
+  assertEquals("boom2", f(2));
+  %OptimizeFunctionOnNextCall(f);
+  assertEquals("boom3", f(3));
+  print("Collect log:", log);
+  assertEquals([["boom1",false], ["boom2",false], ["boom3",false]], log);
+})();
+
+(function TryFinally() {
+  log = [];  // Clear log.
+  function f(a) {
+    try {
+      throw "baem" + a;
+    } finally {
+      return a + 10;
+    }
+  }
+  assertEquals(11, f(1));
+  assertEquals(12, f(2));
+  %OptimizeFunctionOnNextCall(f);
+  assertEquals(13, f(3));
+  print("Collect log:", log);
+  assertEquals([["baem1",true], ["baem2",true], ["baem3",true]], log);
+})();
+
+(function TryCatchFinally() {
+  log = [];  // Clear log.
+  function f(a) {
+    try {
+      throw "wosh" + a;
+    } catch(e) {
+      return e + a;
+    } finally {
+      // Nothing.
+    }
+  }
+  assertEquals("wosh11", f(1));
+  assertEquals("wosh22", f(2));
+  %OptimizeFunctionOnNextCall(f);
+  assertEquals("wosh33", f(3));
+  print("Collect log:", log);
+  assertEquals([["wosh1",false], ["wosh2",false], ["wosh3",false]], log);
+})();
+
+(function TryCatchNestedFinally() {
+  log = [];  // Clear log.
+  function f(a) {
+    try {
+      try {
+        throw "bang" + a;
+      } finally {
+        // Nothing.
+      }
+    } catch(e) {
+      return e + a;
+    }
+  }
+  assertEquals("bang11", f(1));
+  assertEquals("bang22", f(2));
+  %OptimizeFunctionOnNextCall(f);
+  assertEquals("bang33", f(3));
+  print("Collect log:", log);
+  assertEquals([["bang1",false], ["bang2",false], ["bang3",false]], log);
+})();
+
+(function TryFinallyNestedCatch() {
+  log = [];  // Clear log.
+  function f(a) {
+    try {
+      try {
+        throw "peng" + a;
+      } catch(e) {
+        return e
+      }
+    } finally {
+      return a + 10;
+    }
+  }
+  assertEquals(11, f(1));
+  assertEquals(12, f(2));
+  %OptimizeFunctionOnNextCall(f);
+  assertEquals(13, f(3));
+  print("Collect log:", log);
+  assertEquals([["peng1",false], ["peng2",false], ["peng3",false]], log);
+})();
+
+(function TryFinallyNestedFinally() {
+  log = [];  // Clear log.
+  function f(a) {
+    try {
+      try {
+        throw "oops" + a;
+      } finally {
+        // Nothing.
+      }
+    } finally {
+      return a + 10;
+    }
+  }
+  assertEquals(11, f(1));
+  assertEquals(12, f(2));
+  %OptimizeFunctionOnNextCall(f);
+  assertEquals(13, f(3));
+  print("Collect log:", log);
+  assertEquals([["oops1",true], ["oops2",true], ["oops3",true]], log);
+})();
diff --git a/src/v8/test/debugger/debug/compiler/osr-typing-debug-change.js b/src/v8/test/debugger/debug/compiler/osr-typing-debug-change.js
new file mode 100644
index 0000000..92eb899
--- /dev/null
+++ b/src/v8/test/debugger/debug/compiler/osr-typing-debug-change.js
@@ -0,0 +1,114 @@
+// 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.
+
+
+var Debug = debug.Debug;
+
+var changed = false;
+
+function listenerSetJToResult(
+    event, exec_state, event_data, data) {
+
+  if (event == Debug.DebugEvent.Break) {
+    var scope = exec_state.frame(1).scope(0);
+    var newval = "result";
+    try {
+      scope.setVariableValue("j", newval);
+      changed = true;
+    } catch(e) {
+      changed = false;
+    }
+  }
+}
+
+Debug.setListener(listenerSetJToResult);
+
+function g() { debugger; }
+%NeverOptimizeFunction(g);
+
+function ChangeSmiConstantAndOsr() {
+  var j = 1;
+  for (var i = 0; i < 4; i++) {
+    if (i == 2) {
+      %OptimizeOsr();
+      g();
+    }
+  }
+  return j;
+}
+var r1 = ChangeSmiConstantAndOsr();
+if (changed) {
+  assertEquals("result", r1);
+} else {
+  assertEquals(1, r1);
+}
+
+function ChangeFloatConstantAndOsr() {
+  var j = 0.1;
+  for (var i = 0; i < 4; i++) {
+    if (i == 2) {
+      %OptimizeOsr();
+      g();
+    }
+  }
+  return j;
+}
+var r2 = ChangeFloatConstantAndOsr();
+if (changed) {
+  assertEquals("result", r2);
+} else {
+  assertEquals(0.1, r2);
+}
+
+function ChangeFloatVarAndOsr() {
+  var j = 0.1;
+  for (var i = 0; i < 4; i++) {
+    j = j + 0.1;
+    if (i == 2) {
+      %OptimizeOsr();
+      g();
+    }
+  }
+  return j;
+}
+var r3 = ChangeFloatVarAndOsr();
+if (changed) {
+  assertEquals("result0.1", r3);
+} else {
+  assertEquals(0.5, r3);
+}
+
+function listenerSetJToObject(
+    event, exec_state, event_data, data) {
+  if (event == Debug.DebugEvent.Break) {
+    var scope = exec_state.frame(1).scope(0);
+    try {
+      scope.setVariableValue("j", 100);
+      changed = true;
+    } catch(e) {
+      changed = false;
+    }
+  }
+}
+
+Debug.setListener(listenerSetJToObject);
+
+function ChangeIntVarAndOsr() {
+  var j = 1;
+  for (var i = 0; i < 4; i++) {
+    j = j + 1|0;
+    if (i == 2) {
+      %OptimizeOsr();
+      g();
+    }
+  }
+  return j;
+}
+
+var r4 = ChangeIntVarAndOsr();
+if (changed) {
+  assertEquals(101, r4);
+} else {
+  assertEquals(5, r4);
+}
diff --git a/src/v8/test/debugger/debug/debug-allscopes-on-debugger.js b/src/v8/test/debugger/debug/debug-allscopes-on-debugger.js
new file mode 100644
index 0000000..22dbb6e
--- /dev/null
+++ b/src/v8/test/debugger/debug/debug-allscopes-on-debugger.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.
+
+
+Debug = debug.Debug
+var exception = null;
+var break_count = 0;
+const expected_breaks = 8;
+
+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);
+
+      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 + ".");
+      ++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.
+  var i = 0; // Break 1.
+  i++; // Break 2.
+  i++; // Break 3.
+  debugger;  // Break 4.
+  return i  // Break 5.
+  ; // Break 6.
+}());
+
+assertNull(exception); // Break 7.
+assertEquals(expected_breaks, break_count);
+
+Debug.setListener(null);
diff --git a/src/v8/test/debugger/debug/debug-backtrace.js b/src/v8/test/debugger/debug/debug-backtrace.js
new file mode 100644
index 0000000..63bbe10
--- /dev/null
+++ b/src/v8/test/debugger/debug/debug-backtrace.js
@@ -0,0 +1,98 @@
+// Copyright 2008 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.
+
+// The functions used for testing backtraces. They are at the top to make the
+// testing of source line/column easier.
+function f(x, y) {
+  a=1;
+};
+
+var m = (0, function() {
+  new f(1);
+});
+
+function g() {
+  m();
+};
+
+
+Debug = debug.Debug
+
+listenerCalled = false;
+exception = false;
+
+function listener(event, exec_state, event_data, data) {
+  try {
+    if (event == Debug.DebugEvent.Break) {
+      // The expected backtrace is
+      // 0: f
+      // 1: m
+      // 2: g
+      // 3: [anonymous]
+      assertEquals(4, exec_state.frameCount());
+
+      var frame0 = exec_state.frame(0);
+      assertEquals("f", frame0.func().name());
+      assertEquals(0, frame0.index());
+      assertEquals(31, frame0.sourceLine());
+      assertEquals(2, frame0.sourceColumn());
+      assertEquals(2, frame0.localCount());
+      assertEquals("x", frame0.localName(0));
+      assertEquals(1, frame0.localValue(0).value());
+      assertEquals("y", frame0.localName(1));
+      assertEquals(undefined, frame0.localValue(1).value());
+
+      var frame1 = exec_state.frame(1);
+      assertEquals("m", frame1.func().name());
+      assertEquals(1, frame1.index());
+      assertEquals(35, frame1.sourceLine());
+      assertEquals(2, frame1.sourceColumn());
+      assertEquals(0, frame1.localCount());
+
+      var frame2 = exec_state.frame(2);
+      assertEquals("g", frame2.func().name());
+
+      var frame3 = exec_state.frame(3);
+      assertEquals("", frame3.func().name());
+
+      listenerCalled = true;
+    }
+  } catch (e) {
+    exception = e;
+  };
+};
+
+// Add the debug event listener.
+Debug.setListener(listener);
+
+// Set a break point and call to invoke the debug event listener.
+Debug.setBreakPoint(f, 0, 0);
+g();
+
+// Make sure that the debug event listener vas invoked.
+assertFalse(exception, "exception in listener");
+assertTrue(listenerCalled);
diff --git a/src/v8/test/debugger/debug/debug-break-inline.js b/src/v8/test/debugger/debug/debug-break-inline.js
new file mode 100644
index 0000000..18574ec
--- /dev/null
+++ b/src/v8/test/debugger/debug/debug-break-inline.js
@@ -0,0 +1,79 @@
+// 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.
+
+
+// This test tests that deoptimization due to debug breaks works for
+// inlined functions where the full-code is generated before the
+// debugger is attached.
+//
+//See http://code.google.com/p/chromium/issues/detail?id=105375
+
+Debug = debug.Debug;
+
+var count = 0;
+var break_count = 0;
+
+// Debug event listener which sets a breakpoint first time it is hit
+// and otherwise counts break points hit and checks that the expected
+// state is reached.
+function listener(event, exec_state, event_data, data) {
+  if (event == Debug.DebugEvent.Break) {
+    break_count++;
+    if (break_count == 1) {
+      Debug.setBreakPoint(g, 3);
+    }
+  }
+}
+
+function f() {
+  g();
+}
+
+function g() {
+  count++;
+  h();
+  var b = 1;  // Break point is set here.
+}
+
+function h() {
+  debugger;
+}
+
+f();f();f();
+%OptimizeFunctionOnNextCall(f);
+f();
+
+// Add the debug event listener.
+Debug.setListener(listener);
+
+f();
+
+assertEquals(5, count);
+assertEquals(2, break_count);
+
+// Get rid of the debug event listener.
+Debug.setListener(null);
diff --git a/src/v8/test/debugger/debug/debug-break-microtask.js b/src/v8/test/debugger/debug/debug-break-microtask.js
new file mode 100644
index 0000000..4a244b0
--- /dev/null
+++ b/src/v8/test/debugger/debug/debug-break-microtask.js
@@ -0,0 +1,52 @@
+// Copyright 2017 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) {
+  try {
+    if (event == Debug.DebugEvent.Break) {
+      var line = exec_state.frame(0).sourceLineText();
+      log.push(line);
+      if (!/STOP/.test(line)) {
+        exec_state.prepareStep(Debug.StepAction.StepIn);
+      }
+    }
+  } catch (e) {
+    exception = e;
+  }
+};
+
+Debug.setListener(listener);
+
+function f() {
+  print(1);
+}
+
+Promise.resolve().then(f).then(
+function() {
+  return 2;
+}
+).then(
+function() {
+  throw new Error();
+}
+).catch(
+function() {
+  print(3);
+}  // STOP
+);
+
+setTimeout(function() {
+  Debug.setListener(null);
+  assertNull(exception);
+  var expectation =
+    ["  print(1);","}","  return 2;","  return 2;",
+     "  throw new Error();","  print(3);","}  // STOP"];
+  assertEquals(log, expectation);
+});
+
+Debug.setBreakPoint(f, 1);
diff --git a/src/v8/test/debugger/debug/debug-break-native.js b/src/v8/test/debugger/debug/debug-break-native.js
new file mode 100644
index 0000000..10ed405
--- /dev/null
+++ b/src/v8/test/debugger/debug/debug-break-native.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.
+
+
+Debug = debug.Debug
+var exception = null;
+
+function breakListener(event, exec_state, event_data, data) {
+  if (event != Debug.DebugEvent.Break) return;
+  try {
+    exec_state.prepareStep(Debug.StepAction.StepIn);
+    // Assert that the break happens at an intended location.
+    assertTrue(exec_state.frame(0).sourceLineText().indexOf("// break") > 0);
+  } catch (e) {
+    exception = e;
+  }
+}
+
+Debug.setListener(breakListener);
+
+debugger;                          // break
+
+function f(x) {
+  return x;                        // break
+}                                  // break
+
+Debug.setBreakPoint(f, 0, 0);      // break
+Debug.scripts();                   // break
+
+new Error("123").stack;            // break
+Math.sin(0);                       // break
+
+f("this should break");            // break
+
+Debug.setListener(null);           // break
+
+f("this should not break");
+
+assertNull(exception);
diff --git a/src/v8/test/debugger/debug/debug-breakpoints.js b/src/v8/test/debugger/debug/debug-breakpoints.js
new file mode 100644
index 0000000..4240e8f
--- /dev/null
+++ b/src/v8/test/debugger/debug/debug-breakpoints.js
@@ -0,0 +1,120 @@
+// Copyright 2008 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.
+
+Debug = debug.Debug
+
+Debug.setListener(function() {});
+
+function f() {a=1;b=2}
+function g() {
+  a=1;
+  b=2;
+}
+
+bp = Debug.setBreakPoint(f, 0, 0);
+assertEquals("() {[B0]a=1;b=2}", Debug.showBreakPoints(f));
+Debug.clearBreakPoint(bp);
+assertEquals("() {a=1;b=2}", Debug.showBreakPoints(f));
+bp1 = Debug.setBreakPoint(f, 0, 8);
+assertEquals("() {a=1;[B0]b=2}", Debug.showBreakPoints(f));
+bp2 = Debug.setBreakPoint(f, 0, 4);
+assertEquals("() {[B0]a=1;[B1]b=2}", Debug.showBreakPoints(f));
+bp3 = Debug.setBreakPoint(f, 0, 11);
+assertEquals("() {[B0]a=1;[B1]b=2[B2]}", Debug.showBreakPoints(f));
+Debug.clearBreakPoint(bp1);
+assertEquals("() {[B0]a=1;b=2[B1]}", Debug.showBreakPoints(f));
+Debug.clearBreakPoint(bp2);
+assertEquals("() {a=1;b=2[B0]}", Debug.showBreakPoints(f));
+Debug.clearBreakPoint(bp3);
+assertEquals("() {a=1;b=2}", Debug.showBreakPoints(f));
+
+// The following test checks that the Debug.showBreakPoints(g) produces output
+// like follows when changein breakpoints.
+//
+// function g() {
+//   [BX]a=1;
+//   [BX]b=2;
+// }[BX]
+
+// Test set and clear breakpoint at the first possible location (line 0,
+// position 0).
+bp = Debug.setBreakPoint(g, 0, 0);
+// function g() {
+//   [B0]a=1;
+//   b=2;
+// }
+assertTrue(Debug.showBreakPoints(g).indexOf("[B0]a=1;") > 0);
+Debug.clearBreakPoint(bp);
+// function g() {
+//   a=1;
+//   b=2;
+// }
+assertTrue(Debug.showBreakPoints(g).indexOf("[B0]") < 0);
+
+// Second test set and clear breakpoints on lines 1, 2 and 3 (position = 0).
+bp1 = Debug.setBreakPoint(g, 2, 0);
+// function g() {
+//   a=1;
+//   [B0]b=2;
+// }
+assertTrue(Debug.showBreakPoints(g).indexOf("[B0]b=2;") > 0);
+bp2 = Debug.setBreakPoint(g, 1, 0);
+// function g() {
+//   [B0]a=1;
+//   [B1]b=2;
+// }
+assertTrue(Debug.showBreakPoints(g).indexOf("[B0]a=1;") > 0);
+assertTrue(Debug.showBreakPoints(g).indexOf("[B1]b=2;") > 0);
+bp3 = Debug.setBreakPoint(g, 3, 0);
+// function g() {
+//   [B0]a=1;
+//   [B1]b=2;
+// }[B2]
+assertTrue(Debug.showBreakPoints(g).indexOf("[B0]a=1;") > 0);
+assertTrue(Debug.showBreakPoints(g).indexOf("[B1]b=2;") > 0);
+assertTrue(Debug.showBreakPoints(g).indexOf("[B2]}") > 0);
+Debug.clearBreakPoint(bp1);
+// function g() {
+//   [B0]a=1;
+//   b=2;
+// }[B1]
+assertTrue(Debug.showBreakPoints(g).indexOf("[B0]a=1;") > 0);
+assertTrue(Debug.showBreakPoints(g).indexOf("[B1]}") > 0);
+assertTrue(Debug.showBreakPoints(g).indexOf("[B2]") < 0);
+Debug.clearBreakPoint(bp2);
+// function g() {
+//   a=1;
+//   b=2;
+// }[B0]
+assertTrue(Debug.showBreakPoints(g).indexOf("[B0]}") > 0);
+assertTrue(Debug.showBreakPoints(g).indexOf("[B1]") < 0);
+Debug.clearBreakPoint(bp3);
+// function g() {
+//   a=1;
+//   b=2;
+// }
+assertTrue(Debug.showBreakPoints(g).indexOf("[B0]") < 0);
diff --git a/src/v8/test/debugger/debug/debug-clearbreakpoint.js b/src/v8/test/debugger/debug/debug-clearbreakpoint.js
new file mode 100644
index 0000000..0c8267c
--- /dev/null
+++ b/src/v8/test/debugger/debug/debug-clearbreakpoint.js
@@ -0,0 +1,60 @@
+// Copyright 2008 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.
+
+Debug = debug.Debug
+
+// Simple function which stores the last debug event.
+listenerComplete = false;
+exception = false;
+
+var breakpoint = -1;
+
+function listener(event, exec_state, event_data, data) {
+  try {
+    if (event == Debug.DebugEvent.Break) {
+      // Clear once.
+      Debug.clearBreakPoint(breakpoint);
+      // Indicate that all was processed.
+      listenerComplete = true;
+    }
+  } catch (e) {
+    exception = e
+  };
+};
+
+// Add the debug event listener.
+Debug.setListener(listener);
+
+function g() {};
+
+// Set a break point and call to invoke the debug event listener.
+breakpoint = Debug.setBreakPoint(g, 0, 0);
+g();
+
+// Make sure that the debug event listener vas invoked.
+assertTrue(listenerComplete, "listener did not run to completion");
+assertFalse(exception, "exception in listener")
diff --git a/src/v8/test/debugger/debug/debug-compile-event.js b/src/v8/test/debugger/debug/debug-compile-event.js
new file mode 100644
index 0000000..2e52609
--- /dev/null
+++ b/src/v8/test/debugger/debug/debug-compile-event.js
@@ -0,0 +1,122 @@
+// Copyright 2009 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.
+
+Debug = debug.Debug
+
+var exception = false;  // Exception in debug event listener.
+var after_compile_count = 0;
+var compile_error_count = 0;
+var current_source = '';  // Current source being compiled.
+var source_count = 0;  // Total number of scources compiled.
+var mute_listener = false;
+
+function compileSource(source) {
+  current_source = source;
+  eval(current_source);
+  source_count++;
+}
+
+function safeEval(code) {
+  try {
+    mute_listener = true;
+    return eval('(' + code + ')');
+  } catch (e) {
+    assertEquals(void 0, e);
+    return undefined;
+  } finally {
+    mute_listener = false;
+  }
+}
+
+function listener(event, exec_state, event_data, data) {
+  if (mute_listener) return;
+  try {
+    if (event == Debug.DebugEvent.BeforeCompile ||
+        event == Debug.DebugEvent.AfterCompile ||
+        event == Debug.DebugEvent.CompileError) {
+      // Count the events.
+      if (event == Debug.DebugEvent.AfterCompile) {
+        after_compile_count++;
+      } else if (event == Debug.DebugEvent.CompileError) {
+        compile_error_count++;
+      }
+
+      // If the compiled source contains 'eval' there will be additional compile
+      // events for the source inside eval.
+      if (current_source.indexOf('eval') == 0) {
+        // For source with 'eval' there will be compile events with substrings
+        // as well as with with the exact source.
+        assertTrue(current_source.indexOf(event_data.script().source()) >= 0);
+      } else {
+        // For source without 'eval' there will be a compile events with the
+        // exact source.
+        assertEquals(current_source, event_data.script().source());
+      }
+
+      // Check that we pick script name from //# sourceURL, iff present
+      if (event == Debug.DebugEvent.AfterCompile) {
+        assertEquals(current_source.indexOf('sourceURL') >= 0 ?
+            'myscript.js' : undefined,
+                     event_data.script().name());
+      }
+    }
+  } catch (e) {
+    exception = e
+  }
+};
+
+
+// Add the debug event listener.
+Debug.setListener(listener);
+
+// Compile different sources.
+compileSource('a=1');
+compileSource('(function(){})');
+compileSource('eval("a=2")');
+source_count++;  // Using eval causes additional compilation event.
+compileSource('eval("eval(\'(function(){return a;})\')")');
+source_count += 2;  // Using eval causes additional compilation event.
+compileSource('JSON.parse(\'{"a":1,"b":2}\')');
+// Using JSON.parse does not causes additional compilation events.
+compileSource('x=1; //# sourceURL=myscript.js');
+
+try {
+  compileSource('}');
+} catch(e) {
+}
+
+// Make sure that the debug event listener was invoked.
+assertFalse(exception, "exception in listener")
+
+// Number of before and after + error events should be the same.
+assertEquals(compile_error_count, 1);
+
+// Check the actual number of events (no compilation through the API as all
+// source compiled through eval).
+assertEquals(source_count, after_compile_count);
+
+Debug.setListener(null);
diff --git a/src/v8/test/debugger/debug/debug-compile-optimized.js b/src/v8/test/debugger/debug/debug-compile-optimized.js
new file mode 100644
index 0000000..33f199a
--- /dev/null
+++ b/src/v8/test/debugger/debug/debug-compile-optimized.js
@@ -0,0 +1,31 @@
+// 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: --opt --no-always-opt
+
+Debug = debug.Debug;
+
+Debug.setListener(function() {});
+
+function f() {}
+f();
+f();
+%OptimizeFunctionOnNextCall(f);
+f();
+assertOptimized(f);
+
+var bp = Debug.setBreakPoint(f);
+assertUnoptimized(f);
+f();
+f();
+%OptimizeFunctionOnNextCall(f);
+f();
+assertUnoptimized(f);
+
+Debug.clearBreakPoint(bp);
+%OptimizeFunctionOnNextCall(f);
+f();
+assertOptimized(f);
+
+Debug.setListener(null);
diff --git a/src/v8/test/debugger/debug/debug-conditional-breakpoints.js b/src/v8/test/debugger/debug/debug-conditional-breakpoints.js
new file mode 100644
index 0000000..b4b7314
--- /dev/null
+++ b/src/v8/test/debugger/debug/debug-conditional-breakpoints.js
@@ -0,0 +1,137 @@
+// Copyright 2008 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.
+
+Debug = debug.Debug
+
+// Simple debug event handler which just counts the number of break points hit.
+var break_point_hit_count;
+
+function listener(event, exec_state, event_data, data) {
+  if (event == Debug.DebugEvent.Break) {
+    break_point_hit_count++;
+  }
+};
+
+// Add the debug event listener.
+Debug.setListener(listener);
+
+// Test functions.
+count = 0;
+function f() {};
+function g() {h(count++)};
+function h(x) {var a=x; return a};
+
+
+// Conditional breakpoint which syntax error.
+break_point_hit_count = 0;
+bp = Debug.setBreakPoint(f, 0, 0, '{{{');
+f();
+assertEquals(0, break_point_hit_count);
+Debug.clearBreakPoint(bp);
+
+// Conditional breakpoint which evaluates to false.
+break_point_hit_count = 0;
+bp = Debug.setBreakPoint(f, 0, 0, 'false');
+f();
+assertEquals(0, break_point_hit_count);
+Debug.clearBreakPoint(bp);
+
+// Conditional breakpoint which evaluates to true.
+break_point_hit_count = 0;
+bp = Debug.setBreakPoint(f, 0, 0, 'true');
+f();
+assertEquals(1, break_point_hit_count);
+Debug.clearBreakPoint(bp);
+
+// Conditional breakpoint which different types of quotes.
+break_point_hit_count = 0;
+bp = Debug.setBreakPoint(f, 0, 0, '"a" == "a"');
+f();
+assertEquals(1, break_point_hit_count);
+Debug.clearBreakPoint(bp);
+break_point_hit_count = 0;
+bp = Debug.setBreakPoint(f, 0, 0, "'a' == 'a'");
+f();
+assertEquals(1, break_point_hit_count);
+Debug.clearBreakPoint(bp);
+
+// Conditional breakpoint which checks global variable.
+break_point_hit_count = 0;
+bp = Debug.setBreakPoint(f, 0, 0, 'x==1');
+f();
+assertEquals(0, break_point_hit_count);
+x=1;
+f();
+assertEquals(1, break_point_hit_count);
+Debug.clearBreakPoint(bp);
+
+// Conditional breakpoint which checks global variable.
+break_point_hit_count = 0;
+bp = Debug.setBreakPoint(g, 0, 0, 'count % 2 == 0');
+for (var i = 0; i < 10; i++) {
+  g();
+}
+assertEquals(5, break_point_hit_count);
+Debug.clearBreakPoint(bp);
+
+// Conditional breakpoint which checks a parameter.
+break_point_hit_count = 0;
+bp = Debug.setBreakPoint(h, 0, 0, 'x % 2 == 0');
+for (var i = 0; i < 10; i++) {
+  g();
+}
+assertEquals(5, break_point_hit_count);
+Debug.clearBreakPoint(bp);
+
+// Conditional breakpoint which checks a local variable.
+break_point_hit_count = 0;
+bp = Debug.setBreakPoint(h, 0, 22, 'a % 2 == 0');
+for (var i = 0; i < 10; i++) {
+  g();
+}
+assertEquals(5, break_point_hit_count);
+Debug.clearBreakPoint(bp);
+
+// Multiple conditional breakpoint which the same condition.
+break_point_hit_count = 0;
+bp1 = Debug.setBreakPoint(h, 0, 22, 'a % 2 == 0');
+assertThrows(() => Debug.setBreakPoint(h, 0, 22, 'a % 2 == 0'));
+for (var i = 0; i < 10; i++) {
+  g();
+}
+assertEquals(5, break_point_hit_count);
+Debug.clearBreakPoint(bp1);
+
+// Multiple conditional breakpoint which different conditions.
+break_point_hit_count = 0;
+bp1 = Debug.setBreakPoint(h, 0, 22, 'a % 2 == 0');
+assertThrows(() => Debug.setBreakPoint(h, 0, 22, '(a + 1) % 2 == 0'));
+for (var i = 0; i < 10; i++) {
+  g();
+}
+assertEquals(5, break_point_hit_count);
+Debug.clearBreakPoint(bp1);
diff --git a/src/v8/test/debugger/debug/debug-constructor.js b/src/v8/test/debugger/debug/debug-constructor.js
new file mode 100644
index 0000000..4f0317a
--- /dev/null
+++ b/src/v8/test/debugger/debug/debug-constructor.js
@@ -0,0 +1,76 @@
+// Copyright 2008 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.
+
+Debug = debug.Debug
+
+// Simple function which collects a simple call graph.
+var call_graph = "";
+function listener(event, exec_state, event_data, data) {
+  if (event == Debug.DebugEvent.Break)
+  {
+    call_graph += exec_state.frame().func().name();
+    exec_state.prepareStep(Debug.StepAction.StepIn);
+  }
+};
+
+// Add the debug event listener.
+Debug.setListener(listener);
+
+// Test debug event for constructor.
+function a() {
+  new c();
+}
+
+function b() {
+  x = 1;
+  new c();
+}
+
+function c() {
+  this.x = 1;
+  d();
+}
+
+function d() {
+}
+
+// Break point stops on "new c()" and steps into c.
+Debug.setBreakPoint(a, 1);
+call_graph = "";
+a();
+Debug.clearStepping();  // Clear stepping as the listener leaves it on.
+assertEquals("accdca", call_graph);
+
+// Break point stops on "x = 1" and steps to "new c()" and then into c.
+Debug.setBreakPoint(b, 1);
+call_graph = "";
+b();
+Debug.clearStepping();  // Clear stepping as the listener leaves it on.
+assertEquals("bbccdcb", call_graph);
+
+// Get rid of the debug event listener.
+Debug.setListener(null);
diff --git a/src/v8/test/debugger/debug/debug-enable-disable-breakpoints.js b/src/v8/test/debugger/debug/debug-enable-disable-breakpoints.js
new file mode 100644
index 0000000..25db3ea
--- /dev/null
+++ b/src/v8/test/debugger/debug/debug-enable-disable-breakpoints.js
@@ -0,0 +1,62 @@
+// Copyright 2008 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.
+
+Debug = debug.Debug
+
+// Simple debug event handler which just counts the number of break points hit.
+var break_point_hit_count;
+
+function listener(event, exec_state, event_data, data) {
+  if (event == Debug.DebugEvent.Break) {
+    break_point_hit_count++;
+  }
+};
+
+// Add the debug event listener.
+Debug.setListener(listener);
+
+// Test function.
+function f() {a=1;b=2;};
+
+// This tests enabeling and disabling of break points including the case
+// with several break points in the same location.
+break_point_hit_count = 0;
+
+// Set a breakpoint in f.
+bp1 = Debug.setBreakPoint(f);
+f();
+assertEquals(1, break_point_hit_count);
+
+// Deactivate all breakpoints.
+Debug.debuggerFlags().breakPointsActive.setValue(false);
+f();
+assertEquals(1, break_point_hit_count);
+
+// Activate all breakpoints.
+Debug.debuggerFlags().breakPointsActive.setValue(true);
+f();
+assertEquals(2, break_point_hit_count);
diff --git a/src/v8/test/debugger/debug/debug-eval-scope.js b/src/v8/test/debugger/debug/debug-eval-scope.js
new file mode 100644
index 0000000..093c4df
--- /dev/null
+++ b/src/v8/test/debugger/debug/debug-eval-scope.js
@@ -0,0 +1,144 @@
+// Copyright 2016 the V8 project authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+// Flags: --no-always-opt
+
+// Test that the (strict) eval scope is visible to the debugger.
+
+var Debug = debug.Debug;
+var exception = null;
+var delegate = null;
+
+function listener(event, exec_state, event_data, data) {
+  if (event != Debug.DebugEvent.Break) return;
+  try {
+    delegate(exec_state);
+  } catch (e) {
+    exception = e;
+  }
+}
+
+Debug.setListener(listener);
+
+// Current function is the top-level eval.
+// We can access stack- and context-allocated values in the eval-scope.
+delegate = function(exec_state) {
+  assertEquals([ debug.ScopeType.Eval,
+                 debug.ScopeType.Script,
+                 debug.ScopeType.Global ],
+               exec_state.frame(0).allScopes().map(s => s.scopeType()));
+  var scope = exec_state.frame(0).scope(0);
+  assertEquals(1, scope.scopeObject().property("a").value().value());
+  assertEquals(1, exec_state.frame(0).evaluate("a").value());
+  scope.setVariableValue("a", 2);
+  assertEquals(2, exec_state.frame(0).evaluate("a++").value());
+}
+
+eval("'use strict';      \n" +
+     "var a = 1;         \n" +
+     "debugger;          \n" +
+     "assertEquals(3, a);\n");
+
+eval("'use strict';      \n" +
+     "var a = 1;         \n" +
+     "(x=>a);            \n" +  // Force context-allocation.
+     "debugger;          \n" +
+     "assertEquals(3, a);\n");
+
+// Current function is an inner function.
+// We cannot access stack-allocated values in the eval-scope.
+delegate = function(exec_state) {
+  assertEquals([ debug.ScopeType.Local,
+                 debug.ScopeType.Script,
+                 debug.ScopeType.Global ],
+               exec_state.frame(0).allScopes().map(s => s.scopeType()));
+  assertEquals([ debug.ScopeType.Eval,
+                 debug.ScopeType.Script,
+                 debug.ScopeType.Global ],
+               exec_state.frame(1).allScopes().map(s => s.scopeType()));
+  var scope = exec_state.frame(0).scope(0);
+  assertThrows(() => exec_state.frame(0).evaluate("a"), ReferenceError);
+  assertTrue(scope.scopeObject().property("a").isUndefined());
+}
+
+eval("'use strict';       \n" +
+     "var a = 1;          \n" +
+     "(() => {debugger})()\n");
+
+// Current function is an escaped inner function.
+delegate = function(exec_state) {
+  assertEquals([ debug.ScopeType.Local,
+                 debug.ScopeType.Script,
+                 debug.ScopeType.Global ],
+               exec_state.frame(0).allScopes().map(s => s.scopeType()));
+  assertEquals([ debug.ScopeType.Script,
+                 debug.ScopeType.Global ],
+               exec_state.frame(1).allScopes().map(s => s.scopeType()));
+  var scope = exec_state.frame(0).scope(0);
+  assertThrows(() => exec_state.frame(0).evaluate("a"), ReferenceError);
+  assertTrue(scope.scopeObject().property("a").isUndefined());
+}
+
+var f = eval("'use strict';   \n" +
+             "var a = 1;      \n" +
+             "() => {debugger}\n");
+f();
+
+// Current function is an inner function.
+// We can access context-allocated values in the eval-scope.
+delegate = function(exec_state) {
+  assertEquals([ debug.ScopeType.Local,
+                 debug.ScopeType.Closure,
+                 debug.ScopeType.Script,
+                 debug.ScopeType.Global ],
+               exec_state.frame(0).allScopes().map(s => s.scopeType()));
+  assertEquals([ debug.ScopeType.Eval,
+                 debug.ScopeType.Script,
+                 debug.ScopeType.Global ],
+               exec_state.frame(1).allScopes().map(s => s.scopeType()));
+  var scope = exec_state.frame(1).scope(0);
+  assertEquals(1, scope.scopeObject().property("a").value().value());
+  assertEquals(1, exec_state.frame(1).evaluate("a").value());
+  assertEquals(1, exec_state.frame(0).evaluate("a").value());
+  scope.setVariableValue("a", 2);
+  assertEquals(2, exec_state.frame(0).evaluate("a++").value());
+  assertEquals(3, exec_state.frame(1).evaluate("a++").value());
+}
+
+eval("'use strict';               \n" +
+     "var a = 1;                  \n" +
+     "(() => { a;                 \n" +  // Force context-allocation.
+     "         debugger;          \n" +
+     "         assertEquals(4, a);\n" +
+     "       })();                \n"
+     );
+
+// Current function is an escaped inner function.
+// We can access context-allocated values in the eval-scope.
+delegate = function(exec_state) {
+  assertEquals([ debug.ScopeType.Local,
+                 debug.ScopeType.Closure,
+                 debug.ScopeType.Script,
+                 debug.ScopeType.Global ],
+               exec_state.frame(0).allScopes().map(s => s.scopeType()));
+  assertEquals([ debug.ScopeType.Script,
+                 debug.ScopeType.Global ],
+               exec_state.frame(1).allScopes().map(s => s.scopeType()));
+  var scope = exec_state.frame(0).scope(1);
+  assertEquals(1, scope.scopeObject().property("a").value().value());
+  assertEquals(1, exec_state.frame(0).evaluate("a").value());
+  scope.setVariableValue("a", 2);
+  assertEquals(2, exec_state.frame(0).evaluate("a++").value());
+}
+
+var g = eval("'use strict';              \n" +
+             "var a = 1;                 \n" +
+             "() => { a;                 \n" +
+             "        debugger;          \n" +
+             "        assertEquals(3, a);\n" +
+             "      }                    \n");
+g();
+
+Debug.setListener(null);
+assertNull(exception);
diff --git a/src/v8/test/debugger/debug/debug-evaluate-bool-constructor.js b/src/v8/test/debugger/debug/debug-evaluate-bool-constructor.js
new file mode 100644
index 0000000..83a0f06
--- /dev/null
+++ b/src/v8/test/debugger/debug/debug-evaluate-bool-constructor.js
@@ -0,0 +1,64 @@
+// Copyright 2009 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
+Debug = debug.Debug
+
+var listenerComplete = false;
+var exception = false;
+
+function listener(event, exec_state, event_data, data) {
+  try {
+    if (event == Debug.DebugEvent.Break) {
+      var a = exec_state.frame(0).evaluate("a");
+      assertEquals('object', a.type());
+      assertEquals('Object', a.className());
+
+      // Indicate that all was processed.
+      listenerComplete = true;
+    }
+  } catch (e) {
+    print(e);
+    exception = e
+  };
+};
+
+// Add the debug event listener.
+Debug.setListener(listener);
+
+function callDebugger() {
+  // Add set constructor field to a non-function value.
+  var a = {constructor:true};
+  debugger;
+}
+
+callDebugger();
+
+
+// Make sure that the debug event listener vas invoked.
+assertFalse(exception, "exception in listener")
+assertTrue(listenerComplete, "listener did not run to completion");
diff --git a/src/v8/test/debugger/debug/debug-evaluate-closure.js b/src/v8/test/debugger/debug/debug-evaluate-closure.js
new file mode 100644
index 0000000..d4f3867
--- /dev/null
+++ b/src/v8/test/debugger/debug/debug-evaluate-closure.js
@@ -0,0 +1,92 @@
+// Copyright 2013 the V8 project authors. All rights reserved.
+// Redistribution and use in source and binary forms, with or without
+// modification, are permitted provided that the following conditions are
+// met:
+//
+//     * Redistributions of source code must retain the above copyright
+//       notice, this list of conditions and the following disclaimer.
+//     * Redistributions in binary form must reproduce the above
+//       copyright notice, this list of conditions and the following
+//       disclaimer in the documentation and/or other materials provided
+//       with the distribution.
+//     * Neither the name of Google Inc. nor the names of its
+//       contributors may be used to endorse or promote products derived
+//       from this software without specific prior written permission.
+//
+// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+
+// Flags: --no-always-opt
+
+Debug = debug.Debug;
+var listened = false;
+
+function listener(event, exec_state, event_data, data) {
+  if (event != Debug.DebugEvent.Break) return;
+  try {
+    assertEquals("goo", exec_state.frame(0).evaluate("goo").value());
+    exec_state.frame(0).evaluate("goo = 'goo foo'");
+    assertEquals("bar return", exec_state.frame(0).evaluate("bar()").value());
+    assertEquals("inner bar", exec_state.frame(0).evaluate("inner").value());
+    assertEquals("outer bar", exec_state.frame(0).evaluate("outer").value());
+
+    assertEquals("baz inner", exec_state.frame(0).evaluate("baz").value());
+    assertEquals("baz outer", exec_state.frame(1).evaluate("baz").value());
+    exec_state.frame(0).evaluate("w = 'w foo'");
+    exec_state.frame(0).evaluate("inner = 'inner foo'");
+    exec_state.frame(0).evaluate("outer = 'outer foo'");
+    exec_state.frame(0).evaluate("baz = 'baz inner foo'");
+    exec_state.frame(1).evaluate("baz = 'baz outer foo'");
+    listened = true;
+  } catch (e) {
+    print(e);
+    print(e.stack);
+  }
+}
+
+Debug.setListener(listener);
+
+var outer = "outer";
+var baz = "baz outer";
+
+function foo() {
+  var inner = "inner";
+  var baz = "baz inner";
+  var goo = "goo";
+  var withw = { w: "w" };
+  var withv = { v: "v" };
+
+  with (withv) {
+    var bar = function bar() {
+      assertEquals("goo foo", goo);
+      inner = "inner bar";
+      outer = "outer bar";
+      v = "v bar";
+      return "bar return";
+    };
+  }
+
+  with (withw) {
+    debugger;
+  }
+
+  assertEquals("inner foo", inner);
+  assertEquals("baz inner foo", baz);
+  assertEquals("w foo", withw.w);
+  assertEquals("v bar", withv.v);
+}
+
+foo();
+assertEquals("outer foo", outer);
+assertEquals("baz outer foo", baz);
+assertTrue(listened);
+Debug.setListener(null);
diff --git a/src/v8/test/debugger/debug/debug-evaluate-declaration.js b/src/v8/test/debugger/debug/debug-evaluate-declaration.js
new file mode 100644
index 0000000..c562b73
--- /dev/null
+++ b/src/v8/test/debugger/debug/debug-evaluate-declaration.js
@@ -0,0 +1,43 @@
+// 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 only resolves variables that are used by
+// the function inside which we debug-evaluate. This is to avoid
+// incorrect variable resolution when a context-allocated variable is
+// shadowed by a stack-allocated variable.
+
+"use strict";
+
+var Debug = debug.Debug
+
+var exception = null;
+function listener(event, exec_state, event_data, data) {
+  if (event != Debug.DebugEvent.Break) return;
+  try {
+    exec_state.frame(0).evaluate("var x = 2");
+    exec_state.frame(0).evaluate("'use strict'; let y = 3");
+    exec_state.frame(0).evaluate("var z = 4");
+    exec_state.frame(0).evaluate("function bar() { return 5; }");
+  } catch (e) {
+    exception = e;
+    print(e + e.stack);
+  }
+}
+
+Debug.setListener(listener);
+
+var z = 1;
+
+(function() {
+  debugger;
+})();
+
+assertEquals(2, x);                     // declaration
+assertThrows(() => y, ReferenceError);  // let-declaration does not stick
+assertEquals(4, z);                     // re-declaration
+assertEquals(5, bar());                 // function declaration
+
+Debug.setListener(null);
+assertNull(exception);
diff --git a/src/v8/test/debugger/debug/debug-evaluate-locals-capturing.js b/src/v8/test/debugger/debug/debug-evaluate-locals-capturing.js
new file mode 100644
index 0000000..0ca1d97
--- /dev/null
+++ b/src/v8/test/debugger/debug/debug-evaluate-locals-capturing.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.
+
+// Flags: --no-always-opt --no-stress-opt
+
+Debug = debug.Debug
+var exception = null;
+var break_count = 0;
+
+var f = null;
+var i = null;
+function listener(event, exec_state, event_data, data) {
+  try {
+    if (event == Debug.DebugEvent.Break) {
+      var frameMirror = exec_state.frame(0);
+
+      var i = frameMirror.evaluate('f = function() { i = 5; }, f(), i').value();
+      assertEquals(5, i);
+    }
+  } catch(e) {
+    exception = e;
+    print(e, e.stack);
+  }
+};
+
+Debug.setListener(listener);
+
+(function (){
+
+  var i = 0;
+
+  try {
+    throw new Error();
+  } catch (e) {
+    assertEquals(0, i);
+    debugger;
+    assertEquals(5, i);
+  }
+}());
+
+assertNull(exception);
+
+assertNull(i);
+f();
+assertNull(i);
+
+Debug.setListener(null);
diff --git a/src/v8/test/debugger/debug/debug-evaluate-locals-optimized-double.js b/src/v8/test/debugger/debug/debug-evaluate-locals-optimized-double.js
new file mode 100644
index 0000000..462194c
--- /dev/null
+++ b/src/v8/test/debugger/debug/debug-evaluate-locals-optimized-double.js
@@ -0,0 +1,200 @@
+// 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.
+
+// Flags: --expose-gc
+
+Debug = debug.Debug
+
+var listenerComplete = false;
+var exception = false;
+
+var testingConstructCall = false;
+
+var input = [
+  {a: 1, b: 2},
+  {a: 3, b: 4},
+  {a: 5, b: 6},
+  {a: 7, b: 8},
+  {a: 9, b: 10}
+];
+
+var expected = [
+  { locals: {i: 0, x0: 3.03, y0: 4.04, a0: 1.01, b0: 2.02},
+    args: { names: ["i", "x0", "y0"], values: [0, 3.03, 4.04] } },
+  { locals: {i: 1, x1: 5.05, y1: 6.06, a1: 3.03, b1: 4.04},
+    args: { names: ["i", "x1", "y1"], values: [1, 5.05, 6.06] } },
+  { locals: {i: 2, a2: 5.05, b2: 6.06},
+    args: { names: ["i"], values: [2] } },
+  { locals: {i: 3, x3: 9.09, y3: 10.10, z3: undefined, a3: 7.07, b3: 8.08},
+    args: { names: ["i", "x3", "y3", "z3"],
+            values: [3, 9.09, 10.10, undefined] } },
+  { locals: {i: 4, x4: 11.11, y4: 12.12, a4: 9.09, b4: 10.10},
+    args: { names: ["i", "x4", "y4"], values: [4, 11.11, 12.12] } }
+];
+
+function listener(event, exec_state, event_data, data) {
+  try {
+    if (event == Debug.DebugEvent.Break)
+    {
+      assertEquals(6, exec_state.frameCount());
+
+      for (var i = 0; i < exec_state.frameCount(); i++) {
+        var frame = exec_state.frame(i);
+        if (i < exec_state.frameCount() - 1) {
+          var expected_args = expected[i].args;
+          var expected_locals = expected[i].locals;
+
+          // All frames except the bottom one have expected locals.
+          var locals = {};
+          for (var j = 0; j < frame.localCount(); j++) {
+            locals[frame.localName(j)] = frame.localValue(j).value();
+          }
+          assertPropertiesEqual(expected_locals, locals);
+
+          // All frames except the bottom one have two scopes.
+          assertEquals(3, frame.scopeCount());
+          assertEquals(debug.ScopeType.Local, frame.scope(0).scopeType());
+          assertEquals(debug.ScopeType.Script, frame.scope(1).scopeType());
+          assertEquals(debug.ScopeType.Global, frame.scope(2).scopeType());
+
+          Object.keys(expected_locals).forEach(function (name) {
+            assertEquals(expected_locals[name],
+                         frame.scope(0).scopeObject().value()[name]);
+          });
+
+          for (var j = 0; j < expected_args.names.length; j++) {
+            var arg_name = expected_args.names[j];
+            var arg_value = expected_args.values[j];
+            assertEquals(arg_value,
+                         frame.scope(0).scopeObject().value()[arg_name]);
+          }
+
+          // Evaluate in the inlined frame.
+          Object.keys(expected_locals).forEach(function (name) {
+            assertEquals(expected_locals[name], frame.evaluate(name).value());
+          });
+
+          for (var j = 0; j < expected_args.names.length; j++) {
+            var arg_name = expected_args.names[j];
+            var arg_value = expected_args.values[j];
+            assertEquals(arg_value, frame.evaluate(arg_name).value());
+            assertEquals(arg_value, frame.evaluate('arguments['+j+']').value());
+          }
+        } else {
+          // The bottom frame only have the global scope.
+          assertEquals(2, frame.scopeCount());
+          assertEquals(debug.ScopeType.Script, frame.scope(0).scopeType());
+          assertEquals(debug.ScopeType.Global, frame.scope(1).scopeType());
+        }
+
+        // Check the frame function.
+        switch (i) {
+          case 0: assertEquals("h", frame.func().name()); break;
+          case 1: assertEquals("g3", frame.func().name()); break;
+          case 2: assertEquals("g2", frame.func().name()); break;
+          case 3: assertEquals("g1", frame.func().name()); break;
+          case 4: assertEquals("f", frame.func().name()); break;
+          case 5: break;
+          default: assertUnreachable();
+        }
+      }
+
+      // Indicate that all was processed.
+      listenerComplete = true;
+    }
+  } catch (e) {
+    exception = e.toString() + e.stack;
+  };
+};
+
+for (var i = 0; i < 4; i++) f(input.length - 1, 11.11, 12.12);
+%OptimizeFunctionOnNextCall(f);
+f(input.length - 1, 11.11, 12.12);
+
+// Add the debug event listener.
+Debug.setListener(listener);
+
+function h(i, x0, y0) {
+  var a0 = input[i].a;
+  var b0 = input[i].b;
+  a0 = a0 + a0 / 100;
+  b0 = b0 + b0 / 100;
+  debugger;  // Breakpoint.
+  return a0 + b0;
+};
+
+function g3(i, x1, y1) {
+  var a1 = input[i].a;
+  var b1 = input[i].b;
+  a1 = a1 + a1 / 100;
+  b1 = b1 + b1 / 100;
+  h(i - 1, a1, b1);
+  return a1 + b1;
+};
+
+function g2(i) {
+  var a2 = input[i].a;
+  var b2 = input[i].b;
+  a2 = a2 + a2 / 100;
+  b2 = b2 + b2 / 100;
+  g3(i - 1, a2, b2);
+  return a2 + b2;
+};
+
+function g1(i, x3, y3, z3) {
+  var a3 = input[i].a;
+  var b3 = input[i].b;
+  a3 = a3 + a3 / 100;
+  b3 = b3 + b3 / 100;
+  new g2(i - 1, a3, b3);
+  return a3 + b3;
+};
+
+function f(i, x4, y4) {
+  var a4 = input[i].a;
+  var b4 = input[i].b;
+  a4 = a4 + a4 / 100;
+  b4 = b4 + b4 / 100;
+  g1(i - 1, a4, b4);
+  return a4 + b4;
+};
+
+// Test calling f normally and as a constructor.
+f(input.length - 1, 11.11, 12.12);
+f(input.length - 1, 11.11, 12.12, "");
+testingConstructCall = true;
+new f(input.length - 1, 11.11, 12.12);
+new f(input.length - 1, 11.11, 12.12, "");
+
+// Make sure that the debug event listener was invoked.
+assertFalse(exception, "exception in listener " + exception)
+assertTrue(listenerComplete);
+
+//Throw away type information for next run.
+gc();
+
+Debug.setListener(null);
diff --git a/src/v8/test/debugger/debug/debug-evaluate-locals-optimized.js b/src/v8/test/debugger/debug/debug-evaluate-locals-optimized.js
new file mode 100644
index 0000000..93c90b5
--- /dev/null
+++ b/src/v8/test/debugger/debug/debug-evaluate-locals-optimized.js
@@ -0,0 +1,181 @@
+// 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.
+
+// Flags: --expose-gc
+
+Debug = debug.Debug
+
+var listenerComplete = false;
+var exception = false;
+
+var testingConstructCall = false;
+
+var expected = [
+  { locals: {i: 0, x0: 3, y0: 4, a0: 1, b0: 2},
+    args: { names: ["i", "x0", "y0"], values: [0, 3, 4] } },
+  { locals: {i: 1, x1: 5, y1: 6, a1: 3, b1: 4},
+    args: { names: ["i", "x1", "y1"], values: [1, 5, 6] } },
+  { locals: {i: 2, a2: 5, b2: 6},
+    args: { names: ["i"], values: [2] } },
+  { locals: {i: 3, x3: 9, y3: 10, z3: undefined, a3: 7, b3: 8},
+    args: { names: ["i", "x3", "y3", "z3"], values: [3, 9, 10, undefined] } },
+  { locals: {i: 4, x4: 11, y4: 12, a4: 9, b4: 10},
+    args: { names: ["i", "x4", "y4"], values: [4, 11, 12] } }
+];
+
+function listener(event, exec_state, event_data, data) {
+  try {
+    if (event == Debug.DebugEvent.Break)
+    {
+      assertEquals(6, exec_state.frameCount());
+
+      for (var i = 0; i < exec_state.frameCount(); i++) {
+        var frame = exec_state.frame(i);
+        if (i < exec_state.frameCount() - 1) {
+          var expected_args = expected[i].args;
+          var expected_locals = expected[i].locals;
+
+          // All frames except the bottom one have expected locals.
+          var locals = {};
+          for (var j = 0; j < frame.localCount(); j++) {
+            locals[frame.localName(j)] = frame.localValue(j).value();
+          }
+          assertPropertiesEqual(expected_locals, locals);
+
+          // All frames except the bottom one have three scopes.
+          assertEquals(3, frame.scopeCount());
+          assertEquals(debug.ScopeType.Local, frame.scope(0).scopeType());
+          assertEquals(debug.ScopeType.Script, frame.scope(1).scopeType());
+          assertEquals(debug.ScopeType.Global, frame.scope(2).scopeType());
+
+          Object.keys(expected_locals).forEach(function (name) {
+            assertEquals(expected_locals[name],
+                         frame.scope(0).scopeObject().value()[name]);
+          });
+
+          for (var j = 0; j < expected_args.names.length; j++) {
+            var arg_name = expected_args.names[j];
+            var arg_value = expected_args.values[j];
+            assertEquals(arg_value,
+                         frame.scope(0).scopeObject().value()[arg_name]);
+          }
+
+          // Evaluate in the inlined frame.
+          Object.keys(expected_locals).forEach(function (name) {
+            assertEquals(expected_locals[name], frame.evaluate(name).value());
+          });
+
+          for (var j = 0; j < expected_args.names.length; j++) {
+            var arg_name = expected_args.names[j];
+            var arg_value = expected_args.values[j];
+            assertEquals(arg_value, frame.evaluate(arg_name).value());
+            assertEquals(arg_value, frame.evaluate('arguments['+j+']').value());
+          }
+        } else {
+          // The bottom frame only have the script scope and the global scope.
+          assertEquals(2, frame.scopeCount());
+          assertEquals(debug.ScopeType.Script, frame.scope(0).scopeType());
+          assertEquals(debug.ScopeType.Global, frame.scope(1).scopeType());
+        }
+
+        // Check the frame function.
+        switch (i) {
+          case 0: assertEquals("h", frame.func().name()); break;
+          case 1: assertEquals("g3", frame.func().name()); break;
+          case 2: assertEquals("g2", frame.func().name()); break;
+          case 3: assertEquals("g1", frame.func().name()); break;
+          case 4: assertEquals("f", frame.func().name()); break;
+          case 5: break;
+          default: assertUnreachable();
+        }
+      }
+
+      // Indicate that all was processed.
+      listenerComplete = true;
+    }
+  } catch (e) {
+    exception = e.toString() + e.stack;
+  };
+};
+
+for (var i = 0; i < 4; i++) f(expected.length - 1, 11, 12);
+%OptimizeFunctionOnNextCall(f);
+f(expected.length - 1, 11, 12);
+
+// Add the debug event listener.
+Debug.setListener(listener);
+
+function h(i, x0, y0) {
+  var a0 = expected[i].locals.a0;
+  var b0 = expected[i].locals.b0;
+  debugger;  // Breakpoint.
+  return a0 + b0;
+}
+
+function g3(i, x1, y1) {
+  var a1 = expected[i].locals.a1;
+  var b1 = expected[i].locals.b1;
+  h(i - 1, a1, b1);
+  return a1 + b1;
+}
+
+function g2(i) {
+  var a2 = expected[i].locals.a2;
+  var b2 = expected[i].locals.b2;
+  g3(i - 1, a2, b2);
+  return a2 + b2;
+}
+
+function g1(i, x3, y3, z3) {
+  var a3 = expected[i].locals.a3;
+  var b3 = expected[i].locals.b3;
+  new g2(i - 1, a3, b3);
+  return a3 + b3;
+}
+
+function f(i, x4, y4) {
+  var a4 = expected[i].locals.a4;
+  var b4 = expected[i].locals.b4;
+  g1(i - 1, a4, b4);
+  return a4 + b4;
+}
+
+// Test calling f normally and as a constructor.
+f(expected.length - 1, 11, 12);
+f(expected.length - 1, 11, 12, 0);
+testingConstructCall = true;
+new f(expected.length - 1, 11, 12);
+new f(expected.length - 1, 11, 12, 0);
+
+// Make sure that the debug event listener was invoked.
+assertFalse(exception, "exception in listener " + exception)
+assertTrue(listenerComplete);
+
+// Throw away type information for next run.
+gc();
+
+Debug.setListener(null);
diff --git a/src/v8/test/debugger/debug/debug-evaluate-locals.js b/src/v8/test/debugger/debug/debug-evaluate-locals.js
new file mode 100644
index 0000000..0108acf
--- /dev/null
+++ b/src/v8/test/debugger/debug/debug-evaluate-locals.js
@@ -0,0 +1,149 @@
+// Copyright 2008 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.
+
+Debug = debug.Debug
+
+listenerComplete = false;
+exception = false;
+
+
+function h() {
+  var a = 1;
+  var b = 2;
+  var eval = 5;  // Overriding eval should not break anything.
+  debugger;  // Breakpoint.
+  return a;
+}
+
+function checkFrame0(frame) {
+  // Frame 0 (h) has normal variables a and b.
+  var count = frame.localCount();
+  assertEquals(3, count);
+  for (var i = 0; i < count; ++i) {
+    var name = frame.localName(i);
+    var value = frame.localValue(i).value();
+    if (name == 'a') {
+      assertEquals(1, value);
+    } else if (name !='eval') {
+      assertEquals('b', name);
+      assertEquals(2, value);
+    }
+  }
+}
+
+
+function g() {
+  var a = 3;
+  eval("var b = 4;");
+  return h() + a;
+}
+
+function checkFrame1(frame) {
+  // Frame 1 (g) has normal variable a, b (and arguments).
+  var count = frame.localCount();
+  assertEquals(3, count);
+  for (var i = 0; i < count; ++i) {
+    var name = frame.localName(i);
+    var value = frame.localValue(i).value();
+    if (name == 'a') {
+      assertEquals(3, value);
+    } else if (name == 'b') {
+      assertEquals(4, value);
+    } else {
+      assertEquals('arguments', name);
+    }
+  }
+}
+
+
+function f() {
+  var a = 5;
+  var b = 0;
+  with ({b:6}) {
+    return g();
+  }
+}
+
+function checkFrame2(frame) {
+  // Frame 2 (f) has normal variables a and b.
+  var count = frame.localCount();
+  assertEquals(2, count);
+  for (var i = 0; i < count; ++i) {
+    var name = frame.localName(i);
+    var value = frame.localValue(i).value();
+    if (name == 'a') {
+      assertEquals(5, value);
+    } else {
+      assertEquals('b', name);
+      assertEquals(0, value);
+    }
+  }
+}
+
+
+function listener(event, exec_state, event_data, data) {
+  try {
+    if (event == Debug.DebugEvent.Break)
+    {
+      checkFrame0(exec_state.frame(0));
+      checkFrame1(exec_state.frame(1));
+      checkFrame2(exec_state.frame(2));
+
+      assertEquals(1, exec_state.frame(0).evaluate('a').value());
+      assertEquals(2, exec_state.frame(0).evaluate('b').value());
+      assertEquals(5, exec_state.frame(0).evaluate('eval').value());
+      assertEquals(3, exec_state.frame(1).evaluate('a').value());
+      assertEquals(4, exec_state.frame(1).evaluate('b').value());
+      assertEquals("function",
+                   exec_state.frame(1).evaluate('typeof eval').value());
+      assertEquals(5, exec_state.frame(2).evaluate('a').value());
+      assertEquals(6, exec_state.frame(2).evaluate('b').value());
+      assertEquals("function",
+                   exec_state.frame(2).evaluate('typeof eval').value());
+      assertEquals("foo",
+                   exec_state.frame(0).evaluate('a = "foo"').value());
+      assertEquals("bar",
+                   exec_state.frame(1).evaluate('a = "bar"').value());
+      // Indicate that all was processed.
+      listenerComplete = true;
+    }
+  } catch (e) {
+    exception = e;
+    print("Caught something. " + e + " " + e.stack);
+  };
+};
+
+// Add the debug event listener.
+Debug.setListener(listener);
+
+var f_result = f();
+
+assertEquals("foobar", f_result);
+
+// Make sure that the debug event listener was invoked.
+assertFalse(exception, "exception in listener")
+assertTrue(listenerComplete);
diff --git a/src/v8/test/debugger/debug/debug-evaluate-modify-catch-block-scope.js b/src/v8/test/debugger/debug/debug-evaluate-modify-catch-block-scope.js
new file mode 100644
index 0000000..656399b
--- /dev/null
+++ b/src/v8/test/debugger/debug/debug-evaluate-modify-catch-block-scope.js
@@ -0,0 +1,43 @@
+// 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: --no-always-opt --no-stress-opt
+
+Debug = debug.Debug
+
+var exception = null;
+function listener(event, exec_state, event_data, data) {
+  if (event != Debug.DebugEvent.Break) return;
+  try {
+    exec_state.frame(0).evaluate("a = 2");
+    exec_state.frame(0).evaluate("e = 3");
+    exec_state.frame(0).evaluate("bar()");
+    exec_state.frame(0).evaluate("a++");
+    exec_state.frame(0).evaluate("e++");
+  } catch (e) {
+    exception = e;
+    print(e + e.stack);
+  }
+}
+
+Debug.setListener(listener);
+
+(function() {
+  "use strict";
+  try {
+    throw 1;
+  } catch (e) {
+    let a = 1;
+    function bar() {
+      a *= 2;
+      e *= 2;
+    }
+    debugger;
+    assertEquals(5, a);
+    assertEquals(7, e);
+  }
+})();
+
+Debug.setListener(null);
+assertNull(exception);
diff --git a/src/v8/test/debugger/debug/debug-evaluate-modify-this.js b/src/v8/test/debugger/debug/debug-evaluate-modify-this.js
new file mode 100644
index 0000000..18a343b
--- /dev/null
+++ b/src/v8/test/debugger/debug/debug-evaluate-modify-this.js
@@ -0,0 +1,32 @@
+// 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 f = () => { debugger; }
+var g = function() { debugger; }
+var h = (function() { return () => { debugger; }; }).call({});
+
+function listener(event, exec_state, event_data, data) {
+  if (event != Debug.DebugEvent.Break) return;
+  try {
+    assertThrows(() => exec_state.frame(0).evaluate("this = 2"));
+  } catch (e) {
+    exception = e;
+    print("Caught something. " + e + " " + e.stack);
+  };
+};
+
+Debug.setListener(listener);
+
+f();
+g();
+g.call({});
+h();
+
+Debug.setListener(null);
+assertNull(exception);
diff --git a/src/v8/test/debugger/debug/debug-evaluate-nested-let.js b/src/v8/test/debugger/debug/debug-evaluate-nested-let.js
new file mode 100644
index 0000000..726c28f
--- /dev/null
+++ b/src/v8/test/debugger/debug/debug-evaluate-nested-let.js
@@ -0,0 +1,52 @@
+// Copyright 2016 the V8 project authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+// Flags: --opt
+
+Debug = debug.Debug
+
+var exception = null;
+
+function f() {
+  let a = 0;
+  function g() {
+    let a = 1;
+    {
+      let a = 2;
+      debugger;  // Breakpoint.
+      if (a !== 3) {
+        // We cannot change stack locals in optimized frames.
+        assertEquals(2, a);
+        assertOptimized(g);
+      }
+    }
+    assertEquals(1, a);
+  }
+  g.call(1);
+  if (a !== 4) {
+    // We cannot change stack locals in optimized frames.
+    assertEquals(0, a);
+    assertOptimized(f);
+  }
+}
+
+
+function listener(event, exec_state, event_data, data) {
+  if (event != Debug.DebugEvent.Break) return;
+  try {
+    exec_state.frame(0).evaluate("a = 3");
+    exec_state.frame(1).evaluate("a = 4");
+    assertThrows(() => exec_state.frame(0).evaluate("this = 2"));
+  } catch (e) {
+    exception = e;
+    print("Caught something. " + e + " " + e.stack);
+  };
+};
+
+Debug.setListener(listener);
+
+f();
+
+Debug.setListener(null);
+assertNull(exception);
diff --git a/src/v8/test/debugger/debug/debug-evaluate-no-side-effect-async.js b/src/v8/test/debugger/debug/debug-evaluate-no-side-effect-async.js
new file mode 100644
index 0000000..c5c8eeb
--- /dev/null
+++ b/src/v8/test/debugger/debug/debug-evaluate-no-side-effect-async.js
@@ -0,0 +1,48 @@
+// Copyright 2017 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 asynchronous features do not work with
+// side-effect free debug-evaluate.
+
+Debug = debug.Debug
+
+var exception = null;
+
+function* generator() {
+  yield 1;
+}
+
+async function async() {
+  return 1;
+}
+
+var g = generator();
+
+function listener(event, exec_state, event_data, data) {
+  if (event != Debug.DebugEvent.Break) return;
+  try {
+    function fail(source) {
+      assertThrows(() => exec_state.frame(0).evaluate(source, true),
+                   EvalError);
+    }
+    fail("new Promise()");
+    fail("generator()");
+    fail("g.next()");
+    fail("async()");
+  } catch (e) {
+    exception = e;
+    print(e, e.stack);
+  };
+};
+
+// Add the debug event listener.
+Debug.setListener(listener);
+
+function f() {
+  debugger;
+};
+
+f();
+
+assertNull(exception);
diff --git a/src/v8/test/debugger/debug/debug-evaluate-no-side-effect-builtins-2.js b/src/v8/test/debugger/debug/debug-evaluate-no-side-effect-builtins-2.js
new file mode 100644
index 0000000..1b357ef
--- /dev/null
+++ b/src/v8/test/debugger/debug/debug-evaluate-no-side-effect-builtins-2.js
@@ -0,0 +1,88 @@
+// Copyright 2017 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 date = new Date();
+var map = new Map().set("a", "b").set("c", "d");
+
+function listener(event, exec_state, event_data, data) {
+  if (event != Debug.DebugEvent.Break) return;
+  try {
+    function success(expectation, source) {
+      var result = exec_state.frame(0).evaluate(source, true).value();
+      if (expectation !== undefined) assertEquals(expectation, result);
+    }
+    function fail(source) {
+      assertThrows(() => exec_state.frame(0).evaluate(source, true),
+                   EvalError);
+    }
+
+    // Test Date.prototype functions.
+    success(undefined, `Date()`);
+    success(undefined, `new Date()`);
+    success(undefined, `Date.now()`);
+    success(undefined, `Date.parse(1)`);
+    for (f of Object.getOwnPropertyNames(Date.prototype)) {
+      if (typeof Date.prototype[f] === "function") {
+        if (f.startsWith("set")) {
+          fail(`date.${f}(5);`, true);
+        } else if (f.startsWith("toLocale")) {
+          if (typeof Intl === "undefined") continue;
+          fail(`date.${f}();`, true);
+        } else {
+          success(undefined, `date.${f}();`, true);
+        }
+      }
+    }
+
+    // Test Boolean.
+    success(true, `Boolean(1)`);
+    success(new Boolean(true), `new Boolean(1)`);
+    success("true", `true.toString()`);
+    success(true, `true.valueOf()`);
+
+    // Test global functions.
+    success(1, `parseInt("1")`);
+    success(1.3, `parseFloat("1.3")`);
+    success("abc", `decodeURI("abc")`);
+    success("abc", `encodeURI("abc")`);
+    success("abc", `decodeURIComponent("abc")`);
+    success("abc", `encodeURIComponent("abc")`);
+    success("abc", `escape("abc")`);
+    success("abc", `unescape("abc")`);
+    success(true, `isFinite(0)`);
+    success(true, `isNaN(0/0)`);
+
+    // Test Map functions.
+    success(undefined, `new Map()`);
+    success("[object Map]", `map.toString()`);
+    success("b", `map.get("a")`);
+    success(true, `map.get("x") === undefined`);
+    success(undefined, `map.entries()`);
+    success(undefined, `map.keys()`);
+    success(undefined, `map.values()`);
+    success(2, `map.size`);
+    fail(`map.has("c")`);  // This sets a hash on the object.
+    fail(`map.forEach(()=>1)`);
+    fail(`map.delete("a")`);
+    fail(`map.clear()`);
+    fail(`map.set("x", "y")`);
+  } catch (e) {
+    exception = e;
+    print(e, e.stack);
+  };
+};
+
+// Add the debug event listener.
+Debug.setListener(listener);
+
+function f() {
+  debugger;
+};
+
+f();
+
+assertNull(exception);
diff --git a/src/v8/test/debugger/debug/debug-evaluate-no-side-effect-builtins.js b/src/v8/test/debugger/debug/debug-evaluate-no-side-effect-builtins.js
new file mode 100644
index 0000000..73edb03
--- /dev/null
+++ b/src/v8/test/debugger/debug/debug-evaluate-no-side-effect-builtins.js
@@ -0,0 +1,167 @@
+// Copyright 2017 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 object_with_symbol_key = {[Symbol("a")]: 1};
+var object_with_callbacks = { toString: () => "string", valueOf: () => 3};
+var symbol_for_a = Symbol.for("a");
+
+function listener(event, exec_state, event_data, data) {
+  if (event != Debug.DebugEvent.Break) return;
+  try {
+    function success(expectation, source) {
+      var result = exec_state.frame(0).evaluate(source, true).value();
+      if (expectation !== undefined) assertEquals(expectation, result);
+    }
+    function fail(source) {
+      assertThrows(() => exec_state.frame(0).evaluate(source, true),
+                   EvalError);
+    }
+
+    // Test some Object functions.
+    success({}, `new Object()`);
+    success({p : 3}, `Object.create({}, { p: { value: 3 } })`);
+    success("[[\"a\",1],[\"b\",2]]",
+            `JSON.stringify(Object.entries({a:1, b:2}))`);
+    success({value: 1, writable: true, enumerable: true, configurable: true},
+            `Object.getOwnPropertyDescriptor({a: 1}, "a")`);
+    success("{\"a\":{\"value\":1,\"writable\":true," +
+            "\"enumerable\":true,\"configurable\":true}}",
+            `JSON.stringify(Object.getOwnPropertyDescriptors({a: 1}))`);
+    success(["a"], `Object.getOwnPropertyNames({a: 1})`);
+    success(undefined, `Object.getOwnPropertySymbols(object_with_symbol_key)`);
+    success({}, `Object.getPrototypeOf(Object.create({}))`);
+    success(true, `Object.is(Object, Object)`);
+    success(true, `Object.isExtensible({})`);
+    success(false, `Object.isFrozen({})`);
+    success(false, `Object.isSealed({})`);
+    success([1, 2], `Object.values({a:1, b:2})`);
+
+    fail(`Object.assign({}, {})`);
+    fail(`Object.defineProperties({}, [{p:{value:3}}])`);
+    fail(`Object.defineProperty({}, {p:{value:3}})`);
+    fail(`Object.freeze({})`);
+    fail(`Object.preventExtensions({})`);
+    fail(`Object.seal({})`);
+    fail(`Object.setPrototypeOf({}, {})`);
+
+    // Test some Object.prototype functions.
+    success(true, `({a:1}).hasOwnProperty("a")`);
+    success(true, `Object.prototype.isPrototypeOf({})`);
+    success(true, `({a:1}).propertyIsEnumerable("a")`);
+    success("[object Object]", `({a:1}).toString()`);
+    success("string", `(object_with_callbacks).toString()`);
+    success(3, `(object_with_callbacks).valueOf()`);
+
+    // Test Array functions.
+    success([], `new Array()`);
+    var function_param = [
+      "forEach", "every", "some", "reduce", "reduceRight", "find", "filter",
+      "map", "findIndex"
+    ];
+    var fails = ["toString", "join", "toLocaleString", "pop", "push",
+      "reverse", "shift", "unshift", "slice", "splice", "sort", "filter",
+      "map", "copyWithin", "fill", "concat"];
+    for (f of Object.getOwnPropertyNames(Array.prototype)) {
+      if (typeof Array.prototype[f] === "function") {
+        if (fails.includes(f)) {
+          if (function_param.includes(f)) {
+            fail(`[1, 2, 3].${f}(()=>{});`);
+          } else {
+            fail(`[1, 2, 3].${f}();`);
+          }
+        } else if (function_param.includes(f)) {
+          exec_state.frame(0).evaluate(`[1, 2, 3].${f}(()=>{});`, true);
+        } else {
+          exec_state.frame(0).evaluate(`[1, 2, 3].${f}();`, true);
+        }
+      }
+    }
+
+    // Test Math functions.
+    for (f of Object.getOwnPropertyNames(Math)) {
+      if (typeof Math[f] === "function") {
+        var result = exec_state.frame(0).evaluate(
+                         `Math.${f}(0.5, -0.5);`, true).value();
+        if (f != "random") assertEquals(Math[f](0.5, -0.5), result);
+      }
+    }
+
+    // Test Number functions.
+    success(new Number(0), `new Number()`);
+    for (f of Object.getOwnPropertyNames(Number)) {
+      if (typeof Number[f] === "function") {
+        success(Number[f](0.5), `Number.${f}(0.5);`);
+      }
+    }
+    for (f of Object.getOwnPropertyNames(Number.prototype)) {
+      if (typeof Number.prototype[f] === "function") {
+        if (f == "toLocaleString") continue;
+        success(Number(0.5)[f](5), `Number(0.5).${f}(5);`);
+      }
+    }
+
+    // Test String functions.
+    success(new String(), `new String()`);
+    success(" ", "String.fromCodePoint(0x20)");
+    success(" ", "String.fromCharCode(0x20)");
+    for (f of Object.getOwnPropertyNames(String.prototype)) {
+      if (typeof String.prototype[f] === "function") {
+        // Do not expect locale-specific or regexp-related functions to work.
+        // {Lower,Upper}Case (Locale-specific or not) do not work either
+        // if Intl is enabled.
+        if (f.indexOf("locale") >= 0) continue;
+        if (f.indexOf("Locale") >= 0) continue;
+        if (typeof Intl !== 'undefined') {
+          if (f == "toUpperCase") continue;
+          if (f == "toLowerCase") continue;
+        }
+        if (f == "normalize") continue;
+        if (f == "match") continue;
+        if (f == "search") continue;
+        if (f == "split" || f == "replace") {
+          fail(`'abcd'.${f}(2)`);
+          continue;
+        }
+        success("abcd"[f](2), `"abcd".${f}(2);`);
+      }
+    }
+    fail("'abCd'.toLocaleLowerCase()");
+    fail("'abcd'.toLocaleUpperCase()");
+    if (typeof Intl !== 'undefined') {
+      fail("'abCd'.toLowerCase()");
+      fail("'abcd'.toUpperCase()");
+    }
+    fail("'abcd'.match(/a/)");
+    fail("'abcd'.replace(/a/)");
+    fail("'abcd'.search(/a/)");
+    fail("'abcd'.split(/a/)");
+
+    // Test JSON functions.
+    success('{"abc":[1,2]}', "JSON.stringify(JSON.parse('{\"abc\":[1,2]}'))");
+
+    // Test Symbol functions.
+    success(undefined, `Symbol("a")`);
+    fail(`Symbol.for("a")`);  // Symbol.for can be observed via Symbol.keyFor.
+    success("a", `Symbol.keyFor(symbol_for_a)`);
+    success("Symbol(a)", `symbol_for_a.valueOf().toString()`);
+    success("Symbol(a)", `symbol_for_a[Symbol.toPrimitive]().toString()`);
+  } catch (e) {
+    exception = e;
+    print(e, e.stack);
+  };
+};
+
+// Add the debug event listener.
+Debug.setListener(listener);
+
+function f() {
+  debugger;
+};
+
+f();
+
+assertNull(exception);
diff --git a/src/v8/test/debugger/debug/debug-evaluate-no-side-effect-control.js b/src/v8/test/debugger/debug/debug-evaluate-no-side-effect-control.js
new file mode 100644
index 0000000..e19a277
--- /dev/null
+++ b/src/v8/test/debugger/debug/debug-evaluate-no-side-effect-control.js
@@ -0,0 +1,107 @@
+// Copyright 2017 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 o = { p : 1 };
+
+var successes = [
+  [45,
+   `(function() {
+      var sum = 0;
+      for (var i = 0; i < 10; i++) sum += i;
+      return sum;
+    })()`
+  ],
+  ["0012",
+   `(function() {
+      var sum = 0;
+      for (var i in [1, 2, 3]) sum += i;
+      return sum;
+    })()`
+  ],
+  [15,
+   `(function() {
+      var sum = 1;
+      while (sum < 12) sum += sum + 1;
+      return sum;
+    })()`
+  ],
+  [15,
+   `(function() {
+      var sum = 1;
+      do { sum += sum + 1; } while (sum < 12);
+      return sum;
+    })()`
+  ],
+  ["023",
+   `(function() {
+      var sum = "";
+      for (var i = 0; i < 4; i++) {
+        switch (i) {
+          case 0:
+          case 1:
+            if (i == 0) sum += i;
+            break;
+          default:
+          case 3:
+            sum += i;
+            break;
+        }
+      }
+      return sum;
+    })()`
+  ],
+  ["oups",
+   `(function() {
+      try {
+        if (Math.sin(1) < 1) throw new Error("oups");
+      } catch (e) {
+        return e.message;
+      }
+    })()`
+  ],
+];
+
+var fails = [
+  `(function() {  // Iterator.prototype.next performs stores.
+     var sum = 0;
+     for (let i of [1, 2, 3]) sum += i;
+     return sum;
+   })()`,
+  `(function() {  // Store to scope object.
+     with (o) {
+       p = 2;
+     }
+   })()`,
+];
+
+function listener(event, exec_state, event_data, data) {
+  if (event != Debug.DebugEvent.Break) return;
+  try {
+    successes.forEach(function ([expectation, source]) {
+      assertEquals(expectation,
+                   exec_state.frame(0).evaluate(source, true).value());
+    });
+    fails.forEach(function (test) {
+      assertThrows(() => exec_state.frame(0).evaluate(test, true), EvalError);
+    });
+  } catch (e) {
+    exception = e;
+    print(e, e.stack);
+  };
+};
+
+// Add the debug event listener.
+Debug.setListener(listener);
+
+function f() {
+  debugger;
+};
+
+f();
+
+assertNull(exception);
diff --git a/src/v8/test/debugger/debug/debug-evaluate-no-side-effect-iife.js b/src/v8/test/debugger/debug/debug-evaluate-no-side-effect-iife.js
new file mode 100644
index 0000000..c8dc2a5
--- /dev/null
+++ b/src/v8/test/debugger/debug/debug-evaluate-no-side-effect-iife.js
@@ -0,0 +1,67 @@
+// Copyright 2017 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 declaring local variables in IIFEs works with
+// side-effect free debug-evaluate.
+
+Debug = debug.Debug
+
+var exception = null;
+
+function listener(event, exec_state, event_data, data) {
+  if (event != Debug.DebugEvent.Break) return;
+  try {
+    function success(expectation, source) {
+      assertEquals(expectation,
+                   exec_state.frame(0).evaluate(source, true).value());
+    }
+    function fail(source) {
+      assertThrows(() => exec_state.frame(0).evaluate(source, true),
+                   EvalError);
+    }
+    // Declaring 'a' sets a property to the global object.
+    fail("var a = 3");
+    exec_state.frame(0).evaluate("var a = 2", false);
+    assertEquals(2, a);
+    // Wrapping into an IIFE would be fine, since 'a' is local.
+    success(100,
+            `(function(x) {
+                var a = 0;
+                for (var i = 0; i < x; i++) {
+                  a += x;
+                }
+                return a;
+              })(10);`);
+    success(100,
+            `(x => {
+                let a = 0;
+                for (var i = 0; i < x; i++) {
+                  a += x;
+                }
+                return a;
+              })(10);`);
+    // Not using 'var' to declare would make the access go to global object.
+    fail(   `(function(x) {
+                a = 0;
+                for (var i = 0; i < x; i++) {
+                  a += x;
+                }
+                return a;
+              })(10);`);
+  } catch (e) {
+    exception = e;
+    print(e, e.stack);
+  };
+};
+
+// Add the debug event listener.
+Debug.setListener(listener);
+
+function f() {
+  debugger;
+};
+
+f();
+
+assertNull(exception);
diff --git a/src/v8/test/debugger/debug/debug-evaluate-no-side-effect-ops.js b/src/v8/test/debugger/debug/debug-evaluate-no-side-effect-ops.js
new file mode 100644
index 0000000..b7e49dc
--- /dev/null
+++ b/src/v8/test/debugger/debug/debug-evaluate-no-side-effect-ops.js
@@ -0,0 +1,97 @@
+// Copyright 2017 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 date = new Date();
+var T = true;
+var F = false;
+var one = 1;
+var two = 2;
+var string = "s";
+var array = [1, 2, 3];
+function max(...rest) {
+  return Math.max(...rest);
+}
+
+function def(a = 1) {
+  return a;
+}
+
+function d1([a, b = 'b']) {
+  return a + b;
+}
+
+function d2({ x: c, y, z = 'z' } = {x: 'x', y: 'y' }) {
+  return c + y + z;
+}
+
+function listener(event, exec_state, event_data, data) {
+  if (event != Debug.DebugEvent.Break) return;
+  try {
+    function success(expectation, source) {
+      var result = exec_state.frame(0).evaluate(source, true).value();
+      if (expectation !== undefined) assertEquals(expectation, result);
+    }
+    function fail(source) {
+      assertThrows(() => exec_state.frame(0).evaluate(source, true),
+                   EvalError);
+    }
+    success(false, `Object == {}`);
+    success(false, `Object === {}`);
+    success(true, `Object != {}`);
+    success(true, `Object !== {}`);
+    success(true, `'s' == string`);
+    success(true, `'s' === string`);
+    success(true, `1 < Math.cos(0) * 2`);
+    success(false, `1 < string`);
+    success(true, `'a' < string`);
+    success("s", `string[0]`);
+    success(0, `[0][0]`);
+    success(1, `T^F`);
+    success(0, `T&F`);
+    success(1, `T|F`);
+    success(false, `T&&F`);
+    success(true, `T||F`);
+    success(false, `T?F:T`);
+    success(false, `!T`);
+    success(1, `+one`);
+    success(-1, `-one`);
+    success(-2, `~one`);
+    success(4, `one << two`);
+    success(1, `two >> one`);
+    success(1, `two >>> one`);
+    success(3, `two + one`);
+    success(2, `two * one`);
+    success(0.5, `one / two`);
+    success(0, `(one / two) | 0`);
+    success(1, `one ** two`);
+    success(NaN, `string * two`);
+    success("s2", `string + two`);
+    success("s2", `string + two`);
+    fail(`[...array]`);
+    success(3, `max(...array)`);
+    fail(`({[string]:1})`);
+    fail(`[a, b] = [1, 2]`);
+    success(2, `def(2)`);
+    success(1, `def()`);
+    fail(`d1(['a'])`);  // Iterator.prototype.next performs stores.
+    success("XYz", `d2({x:'X', y:'Y'})`);
+  } catch (e) {
+    exception = e;
+    print(e, e.stack);
+  };
+};
+
+// Add the debug event listener.
+Debug.setListener(listener);
+
+function f() {
+  debugger;
+};
+
+f();
+
+assertNull(exception);
diff --git a/src/v8/test/debugger/debug/debug-evaluate-no-side-effect.js b/src/v8/test/debugger/debug/debug-evaluate-no-side-effect.js
new file mode 100644
index 0000000..26cf258
--- /dev/null
+++ b/src/v8/test/debugger/debug/debug-evaluate-no-side-effect.js
@@ -0,0 +1,97 @@
+// Copyright 2017 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;
+let a = 1;
+var object = { property : 2,
+               get getter() { return 3; }
+             };
+var string1 = { toString() { return "x"; } };
+var string2 = { toString() { print("x"); return "x"; } };
+var array = [4, 5];
+var error = new Error();
+
+function set_a() { a = 2; }
+function get_a() { return a; }
+var bound = get_a.bind(0);
+
+var global_eval = eval;
+
+function listener(event, exec_state, event_data, data) {
+  if (event != Debug.DebugEvent.Break) return;
+  try {
+    function success(expectation, source) {
+      assertEquals(expectation,
+                   exec_state.frame(0).evaluate(source, true).value());
+    }
+    function fail(source) {
+      assertThrows(() => exec_state.frame(0).evaluate(source, true),
+                   EvalError);
+    }
+    // Simple test.
+    success(3, "1 + 2");
+    // Dymanic load.
+    success(array, "array");
+    // Context load.
+    success(1, "a");
+    // Global and named property load.
+    success(2, "object.property");
+    // Load via read-only getter.
+    success(3, "object.getter");
+    // Implicit call to read-only toString.
+    success("xy", "string1 + 'y'");
+    // Keyed property load.
+    success(5, "array[1]");
+    // Call to read-only function.
+    success(1, "get_a()");
+    success(1, "bound()");
+    success({}, "new get_a()");
+    // Call to read-only function within try-catch.
+    success(1, "try { get_a() } catch (e) {}");
+    // Call to C++ built-in.
+    success(Math.sin(2), "Math.sin(2)");
+    // Call to whitelisted get accessors.
+    success(3, "'abc'.length");
+    success(2, "array.length");
+    success(1, "'x'.length");
+    success(0, "set_a.length");
+    success("set_a", "set_a.name");
+    success(0, "bound.length");
+    success("bound get_a", "bound.name");
+    // Test that non-read-only code fails.
+    fail("exception = 1");
+    // Test that calling a non-read-only function fails.
+    fail("set_a()");
+    fail("new set_a()");
+    // Test that implicit call to a non-read-only function fails.
+    fail("string2 + 'y'");
+    // Test that try-catch does not catch the EvalError.
+    fail("try { set_a() } catch (e) {}");
+    // Test that call to set accessor fails.
+    fail("array.length = 4");
+    // Test that call to non-whitelisted get accessor fails.
+    fail("error.stack");
+    // Eval is not allowed.
+    fail("eval('Math.sin(1)')");
+    fail("eval('exception = 1')");
+    fail("global_eval('1')");
+  } catch (e) {
+    exception = e;
+    print(e, e.stack);
+  };
+};
+
+// Add the debug event listener.
+Debug.setListener(listener);
+
+function f() {
+  debugger;
+};
+
+f();
+
+assertNull(exception);
+assertEquals(1, a);
diff --git a/src/v8/test/debugger/debug/debug-evaluate-shadowed-context-2.js b/src/v8/test/debugger/debug/debug-evaluate-shadowed-context-2.js
new file mode 100644
index 0000000..5edd03c
--- /dev/null
+++ b/src/v8/test/debugger/debug/debug-evaluate-shadowed-context-2.js
@@ -0,0 +1,40 @@
+// 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 correctly collects free outer variables
+// and does not get confused by variables in nested scopes.
+
+Debug = debug.Debug
+
+var exception = null;
+function listener(event, exec_state, event_data, data) {
+  if (event != Debug.DebugEvent.Break) return;
+  try {
+    assertThrows(() => exec_state.frame(0).evaluate("x").value());
+  } catch (e) {
+    exception = e;
+    print(e + e.stack);
+  }
+}
+
+Debug.setListener(listener);
+
+(function() {
+  var x = 1;     // context allocate x
+  (() => x);
+  (function() {
+    var x = 2;   // stack allocate shadowing x
+    (function() {
+      {          // context allocate x in a nested scope
+        let x = 3;
+        (() => x);
+      }
+      debugger;
+    })();
+  })();
+})();
+
+Debug.setListener(null);
+assertNull(exception);
diff --git a/src/v8/test/debugger/debug/debug-evaluate-shadowed-context.js b/src/v8/test/debugger/debug/debug-evaluate-shadowed-context.js
new file mode 100644
index 0000000..564bdc6
--- /dev/null
+++ b/src/v8/test/debugger/debug/debug-evaluate-shadowed-context.js
@@ -0,0 +1,83 @@
+// 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: --no-analyze-environment-liveness
+
+// Test that debug-evaluate only resolves variables that are used by
+// the function inside which we debug-evaluate. This is to avoid
+// incorrect variable resolution when a context-allocated variable is
+// shadowed by a stack-allocated variable.
+
+Debug = debug.Debug
+
+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 value;
+      try {
+        value = frame.evaluate("x").value();
+      } catch (e) {
+        value = e.name;
+      }
+      print(frame.sourceLineText());
+      var expected = frame.sourceLineText().match(/\/\/ (.*$)/)[1];
+      assertEquals(String(expected), String(value));
+    }
+    assertEquals("[object global]",
+                 String(exec_state.frame(0).evaluate("this").value()));
+    assertEquals("y", exec_state.frame(0).evaluate("y").value());
+    assertEquals("a", exec_state.frame(0).evaluate("a").value());
+    exec_state.frame(0).evaluate("a = 'A'");
+    assertThrows(() => exec_state.frame(0).evaluate("z"), ReferenceError);
+  } catch (e) {
+    exception = e;
+    print(e + e.stack);
+  }
+}
+
+Debug.setListener(listener);
+
+var a = "a";
+(function() {
+  var x = 1;     // context allocate x
+  (() => x);
+  var y = "y";
+  var z = "z";
+  (function() {
+    var x = 2;   // stack allocate shadowing x
+    (function() {
+      y;         // access y
+      debugger;  // ReferenceError
+    })();        // 2
+  })();          // 1
+  return y;
+})();
+
+assertEquals("A", a);
+a = "a";
+
+(function() {
+  var x = 1;     // context allocate x
+  (() => x);
+  var y = "y";
+  var z = "z";
+  (function() {
+    var x = 2;   // stack allocate shadowing x
+    (() => {
+      y;
+      a;
+      this;      // context allocate receiver
+      debugger;  // ReferenceError
+    })();        // 2
+  })();          // 1
+  return y;
+})();
+
+assertEquals("A", a);
+
+Debug.setListener(null);
+assertNull(exception);
diff --git a/src/v8/test/debugger/debug/debug-evaluate-with.js b/src/v8/test/debugger/debug/debug-evaluate-with.js
new file mode 100644
index 0000000..260114d
--- /dev/null
+++ b/src/v8/test/debugger/debug/debug-evaluate-with.js
@@ -0,0 +1,82 @@
+// Copyright 2008 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
+
+
+Debug = debug.Debug
+
+listenerComplete = false;
+exception = false;
+breakPointCount = 0;
+
+function listener(event, exec_state, event_data, data) {
+  try {
+    if (event == Debug.DebugEvent.Break)
+    {
+      breakPointCount++;
+      if (breakPointCount == 1) {
+        // Break point in first with block.
+        assertEquals(2, exec_state.frame(0).evaluate('a').value());
+        assertEquals(2, exec_state.frame(0).evaluate('b').value());
+      } else if (breakPointCount == 2) {
+        // Break point in second with block.
+        assertEquals(3, exec_state.frame(0).evaluate('a').value());
+        assertEquals(1, exec_state.frame(0).evaluate('b').value());
+      } else if (breakPointCount == 3) {
+        // Break point in eval with block.
+        assertEquals('local', exec_state.frame(0).evaluate('foo').value());
+      }
+    }
+  } catch (e) {
+    exception = e
+  };
+};
+
+// Add the debug event listener.
+Debug.setListener(listener);
+
+function f() {
+  var a = 1;
+  var b = 2;
+  with ({a:2}) {
+    debugger;  // Breakpoint.
+    x = {a:3,b:1};
+    with (x) {
+      debugger;  // Breakpoint.
+    }
+  }
+};
+
+f();
+
+var foo = "global";
+eval("with({bar:'with'}) { (function g() { var foo = 'local'; debugger; })(); }");
+
+// Make sure that the debug event listener vas invoked.
+assertEquals(3, breakPointCount);
+assertFalse(exception, "exception in listener")
diff --git a/src/v8/test/debugger/debug/debug-evaluate.js b/src/v8/test/debugger/debug/debug-evaluate.js
new file mode 100644
index 0000000..9328c32
--- /dev/null
+++ b/src/v8/test/debugger/debug/debug-evaluate.js
@@ -0,0 +1,85 @@
+// Copyright 2008 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.
+
+Debug = debug.Debug
+
+listenerComplete = false;
+exception = false;
+
+function listener(event, exec_state, event_data, data) {
+  try {
+    if (event == Debug.DebugEvent.Break) {
+      assertEquals(3, exec_state.frame(0).evaluate("1+2").value());
+      assertEquals(5, exec_state.frame(0).evaluate("a+2").value());
+      assertEquals(4, exec_state.frame(0).evaluate("({a:1,b:2}).b+2").value());
+
+      assertEquals(3, exec_state.frame(0).evaluate("a").value());
+      assertEquals(2, exec_state.frame(1).evaluate("a").value());
+      assertEquals(1, exec_state.frame(2).evaluate("a").value());
+
+      assertEquals(1, exec_state.evaluateGlobal("a").value());
+      assertEquals(1, exec_state.evaluateGlobal("this.a").value());
+
+      assertEquals(longString,
+                   exec_state.evaluateGlobal("this.longString").value());
+
+      // Indicate that all was processed.
+      listenerComplete = true;
+    }
+  } catch (e) {
+   exception = e
+  };
+};
+
+// Add the debug event listener.
+Debug.setListener(listener);
+
+function f() {
+  var a = 3;
+};
+
+function g() {
+  var a = 2;
+  f();
+  return a;  // Use the value to prevent it being removed by DCE.
+};
+
+a = 1;
+
+// String which is longer than 80 chars.
+var longString = "1234567890_";
+for (var i = 0; i < 4; i++) {
+  longString += longString;
+}
+
+// Set a break point at return in f and invoke g to hit the breakpoint.
+Debug.setBreakPoint(f, 2, 0);
+g();
+
+assertFalse(exception, "exception in listener")
+// Make sure that the debug event listener vas invoked.
+assertTrue(listenerComplete, "listener did not run to completion");
diff --git a/src/v8/test/debugger/debug/debug-event-listener.js b/src/v8/test/debugger/debug/debug-event-listener.js
new file mode 100644
index 0000000..d89bf80
--- /dev/null
+++ b/src/v8/test/debugger/debug/debug-event-listener.js
@@ -0,0 +1,71 @@
+// Copyright 2008 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.
+
+Debug = debug.Debug
+
+// Simple function which stores the last debug event.
+lastDebugEvent = new Object();
+function listener(event, exec_state, event_data, data) {
+  if (event == Debug.DebugEvent.Break ||
+      event == Debug.DebugEvent.Exception)
+  {
+    lastDebugEvent.event = event;
+    lastDebugEvent.frameFuncName = exec_state.frame().func().name();
+    lastDebugEvent.event_data = event_data;
+  }
+};
+
+// Add the debug event listener.
+Debug.setListener(listener);
+// Get events from handled exceptions.
+Debug.setBreakOnException();
+
+// Test debug event for handled exception.
+(function f(){
+  try {
+    x();
+  } catch(e) {
+    // Do nothing. Ignore exception.
+  }
+})();
+assertTrue(lastDebugEvent.event == Debug.DebugEvent.Exception);
+assertEquals(lastDebugEvent.frameFuncName, "f");
+assertFalse(lastDebugEvent.event_data.uncaught());
+Debug.clearBreakOnException();
+
+// Test debug event for break point.
+function a() {
+  x = 1;
+  y = 2;
+  z = 3;
+};
+Debug.setBreakPoint(a, 1);
+a();
+assertTrue(lastDebugEvent.event == Debug.DebugEvent.Break);
+assertEquals(lastDebugEvent.frameFuncName, "a");
+
+Debug.setListener(null);
diff --git a/src/v8/test/debugger/debug/debug-exceptions.js b/src/v8/test/debugger/debug/debug-exceptions.js
new file mode 100644
index 0000000..4209077
--- /dev/null
+++ b/src/v8/test/debugger/debug/debug-exceptions.js
@@ -0,0 +1,87 @@
+// 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
+
+let error = false;
+let uncaught;
+
+function listener(event, exec_state, event_data, data) {
+  if (event != Debug.DebugEvent.Exception) return;
+  try {
+    uncaught = event_data.uncaught();
+  } catch (e) {
+    error = true;
+  }
+}
+
+Debug.setBreakOnException();
+Debug.setListener(listener);
+
+
+function assertCaught(f) {
+  try {f()} finally {
+    assertFalse(uncaught);
+    return;
+  }
+}
+
+function assertUncaught(f) {
+  try {f()} finally {
+    assertTrue(uncaught);
+    return;
+  }
+}
+
+
+assertUncaught(() => {
+  for (var a of [1, 2, 3]) {
+    throw a
+  }
+});
+
+assertUncaught(() => {
+  for (var a of [1, 2, 3]) {
+    try {throw a} finally {}
+  }
+});
+
+assertCaught(() => {
+  for (var a of [1, 2, 3]) {
+    try {
+      try {throw a} finally {}
+    } catch(_) {}
+  }
+});
+
+assertCaught(() => {
+  try {
+    for (var a of [1, 2, 3]) {
+      try {throw a} finally {}
+    }
+  } catch(_) {}
+});
+
+
+// Check that an internal exception in our yield* desugaring is not observable.
+{
+  uncaught = null;
+
+  let iter = {
+    next() {return {value:42, done:false}},
+    throw() {return {done:true}}
+  };
+  let iterable = {[Symbol.iterator]() {return iter}};
+  function* f() { yield* iterable }
+
+  let g = f();
+  g.next();
+  assertEquals({value: undefined, done: true}, g.throw());
+  assertNull(uncaught);  // No exception event was generated.
+}
+
+
+assertFalse(error);
diff --git a/src/v8/test/debugger/debug/debug-function-scopes.js b/src/v8/test/debugger/debug/debug-function-scopes.js
new file mode 100644
index 0000000..caca211
--- /dev/null
+++ b/src/v8/test/debugger/debug/debug-function-scopes.js
@@ -0,0 +1,191 @@
+// 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.
+
+
+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 (var name in scope_expectations) {
+    var actual = scope_object[name];
+    var expected = scope_expectations[name];
+    assertEquals(expected, actual);
+  }
+}
+
+// ---
+
+listenerDelegate = function(exec_state) {
+  const frame = exec_state.frame(0);
+
+  assertEquals(7, frame.scopeCount());
+
+  CheckScope(frame.scope(0), {}, ScopeType.Local);
+  CheckScope(frame.scope(1), { a: 4, b: 5 }, ScopeType.Closure);
+  CheckScope(frame.scope(2), { w: 5, v: "Capybara" }, ScopeType.With);
+  CheckScope(frame.scope(3), { z: 22 }, ScopeType.Closure);
+  CheckScope(frame.scope(4), { x: 5 }, ScopeType.Closure);
+  CheckScope(frame.scope(5), {}, ScopeType.Script);
+  CheckScope(frame.scope(6), {}, ScopeType.Global);
+};
+
+(function F1(x) {
+  function F2(y) {
+    var z = x + y;
+    with ({w: 5, 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(3, frame.scopeCount());
+
+  CheckScope(frame.scope(0), {}, ScopeType.Local);
+  CheckScope(frame.scope(1), {}, ScopeType.Script);
+  CheckScope(frame.scope(2), {}, ScopeType.Global);
+};
+
+(function() { debugger; return 5; })();
+
+// ---
+
+listenerDelegate = function(exec_state) {
+  const frame = exec_state.frame(0);
+
+  assertEquals(5, frame.scopeCount());
+
+  CheckScope(frame.scope(0), {}, ScopeType.Local);
+  CheckScope(frame.scope(1), { visible2: 20 }, ScopeType.Closure);
+  CheckScope(frame.scope(2), { visible1: 10 }, ScopeType.Closure);
+  CheckScope(frame.scope(3), {}, ScopeType.Script);
+  CheckScope(frame.scope(4), {}, ScopeType.Global);
+};
+
+(function F1(invisible_parameter) {
+  var invisible1 = 1;
+  var visible1 = 10;
+  return (function F2() {
+    var invisible2 = 2;
+    return (function F3() {
+      var visible2 = 20;
+      return (function () { debugger; return visible1 + visible2; });
+    })();
+  })();
+})(5)();
+
+// ---
+
+listenerDelegate = function(exec_state) {
+  const frame = exec_state.frame(0);
+
+  assertEquals(5, frame.scopeCount());
+
+  CheckScope(frame.scope(0), {}, ScopeType.Local);
+  CheckScope(frame.scope(1), { e2: "I'm error 2" }, ScopeType.Catch);
+  CheckScope(frame.scope(2), { e1: "I'm error 1" }, ScopeType.Catch);
+  CheckScope(frame.scope(3), {}, ScopeType.Script);
+  CheckScope(frame.scope(4), {}, ScopeType.Global);
+};
+
+(function One() {
+  try {
+    throw "I'm error 1";
+  } catch (e1) {
+    try {
+      throw "I'm error 2";
+    } catch (e2) {
+      return function GetError() {
+        debugger;
+        return e1 + e2;
+      };
+    }
+  }
+})()();
+
+// ---
+
+listenerDelegate = function(exec_state) {
+  const frame = exec_state.frame(0);
+
+  assertEquals(5, frame.scopeCount());
+
+  CheckScope(frame.scope(0), {}, ScopeType.Local);
+  CheckScope(frame.scope(1), { p4: 20, p6: 22 }, ScopeType.Closure);
+  CheckScope(frame.scope(2), { p1: 1 }, ScopeType.Closure);
+  CheckScope(frame.scope(3), {}, ScopeType.Script);
+  CheckScope(frame.scope(4), {}, ScopeType.Global);
+};
+
+(function Raz(p1, p2) {
+  var p3 = p1 + p2;
+  return (function() {
+    var p4 = 20;
+    var p5 = 21;
+    var p6 = 22;
+    return eval("(function(p7){ debugger; return p1 + p4 + p6 + p7})");
+  })();
+})(1,2)();
+
+// ---
+
+assertNull(exception);
+assertEquals(expected_break_count, break_count);
diff --git a/src/v8/test/debugger/debug/debug-generator-break-on-stack.js b/src/v8/test/debugger/debug/debug-generator-break-on-stack.js
new file mode 100644
index 0000000..6d0d881
--- /dev/null
+++ b/src/v8/test/debugger/debug/debug-generator-break-on-stack.js
@@ -0,0 +1,45 @@
+// 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.
+
+
+var 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 {
+    break_count++;
+    var line = exec_state.frame(0).sourceLineText();
+    print(line);
+    assertTrue(line.indexOf(`B${break_count}`) > 0);
+  } catch (e) {
+    exception = e;
+  }
+}
+
+
+function* g() {
+  setbreaks();
+  yield 1;  // B1
+}
+
+function* f() {
+  yield* g();
+  return 2;  // B2
+}
+
+function setbreaks() {
+  Debug.setListener(listener);
+  Debug.setBreakPoint(g, 2);
+  Debug.setBreakPoint(f, 2);
+}
+
+for (let _ of f()) { }
+
+assertEquals(2, break_count);
+assertNull(exception);
+
+Debug.setListener(null);
diff --git a/src/v8/test/debugger/debug/debug-generator-break.js b/src/v8/test/debugger/debug/debug-generator-break.js
new file mode 100644
index 0000000..7974ab9
--- /dev/null
+++ b/src/v8/test/debugger/debug/debug-generator-break.js
@@ -0,0 +1,43 @@
+// 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.
+
+
+var 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 {
+    break_count++;
+    var line = exec_state.frame(0).sourceLineText();
+    assertTrue(line.indexOf(`B${break_count}`) > 0);
+  } catch (e) {
+    exception = e;
+  }
+}
+
+Debug.setListener(listener);
+
+function* g() {
+  yield 1;
+}
+
+function* f() {
+  yield* g();                    // B1
+  assertEquals(2, break_count);  // B2
+  return 1;                      // B3
+}
+
+Debug.setBreakPoint(f, 1);
+Debug.setBreakPoint(f, 2);
+Debug.setBreakPoint(f, 3);
+
+for (let _ of f()) { }
+
+assertEquals(3, break_count);
+assertNull(exception);
+
+Debug.setListener(null);
diff --git a/src/v8/test/debugger/debug/debug-liveedit-1.js b/src/v8/test/debugger/debug/debug-liveedit-1.js
new file mode 100644
index 0000000..950a2fa
--- /dev/null
+++ b/src/v8/test/debugger/debug/debug-liveedit-1.js
@@ -0,0 +1,46 @@
+// Copyright 2010 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.
+
+
+Debug = debug.Debug
+
+eval("var something1 = 25; "
+     + " function ChooseAnimal() { return          'Cat';          } "
+     + " ChooseAnimal.Helper = function() { return 'Help!'; }");
+
+assertEquals("Cat", ChooseAnimal());
+
+var script = Debug.findScript(ChooseAnimal);
+
+var orig_animal = "Cat";
+var patch_pos = script.source.indexOf(orig_animal);
+var new_animal_patch = "Cap' + 'y' + 'bara";
+
+var change_log = new Array();
+Debug.LiveEdit.TestApi.ApplySingleChunkPatch(script, patch_pos, orig_animal.length, new_animal_patch, change_log);
+
+assertEquals("Capybara", ChooseAnimal());
diff --git a/src/v8/test/debugger/debug/debug-liveedit-2.js b/src/v8/test/debugger/debug/debug-liveedit-2.js
new file mode 100644
index 0000000..408ee5a
--- /dev/null
+++ b/src/v8/test/debugger/debug/debug-liveedit-2.js
@@ -0,0 +1,65 @@
+// Copyright 2010 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: --noalways-opt
+
+
+Debug = debug.Debug
+
+eval("function ChooseAnimal(p) {\n " +
+     "  if (p == 7) {\n" + // Use p
+     "    return;\n" +
+     "  }\n" +
+     "  return function Chooser() {\n" +
+     "    return 'Cat';\n" +
+     "  };\n" +
+     "}\n");
+
+var old_closure = ChooseAnimal(19);
+
+assertEquals("Cat", old_closure());
+
+var script = Debug.findScript(ChooseAnimal);
+
+var orig_animal = "'Cat'";
+var patch_pos = script.source.indexOf(orig_animal);
+var new_animal_patch = "'Capybara' + p";
+
+// We patch innermost function "Chooser".
+// However, this does not actually patch existing "Chooser" instances,
+// because old value of parameter "p" was not saved.
+// Instead it patches ChooseAnimal.
+var change_log = new Array();
+Debug.LiveEdit.TestApi.ApplySingleChunkPatch(script, patch_pos, orig_animal.length, new_animal_patch, change_log);
+print("Change log: " + JSON.stringify(change_log) + "\n");
+
+var new_closure = ChooseAnimal(19);
+// New instance of closure is patched.
+assertEquals("Capybara19", new_closure());
+
+// Old instance of closure is not patched.
+assertEquals("Cat", old_closure());
diff --git a/src/v8/test/debugger/debug/debug-liveedit-3.js b/src/v8/test/debugger/debug/debug-liveedit-3.js
new file mode 100644
index 0000000..c075453
--- /dev/null
+++ b/src/v8/test/debugger/debug/debug-liveedit-3.js
@@ -0,0 +1,66 @@
+// Copyright 2010 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.
+
+
+// In this test case we edit a script so that techincally function text
+// hasen't been changed. However actually function became one level more nested
+// and must be recompiled because it uses variable from outer scope.
+
+
+Debug = debug.Debug
+
+var function_z_text =
+"  function Z() {\n"
++ "    return 2 + p;\n"
++ "  }\n";
+
+eval(
+"function Factory(p) {\n"
++ "return (\n"
++ function_z_text
++ ");\n"
++ "}\n"
+);
+
+var z6 = Factory(6);
+assertEquals(8, z6());
+
+var script = Debug.findScript(Factory);
+
+var new_source = script.source.replace(function_z_text, "function Intermediate() {\nreturn (\n" + function_z_text + ")\n;\n}\n");
+print("new source: " + new_source);
+
+var change_log = new Array();
+var result = Debug.LiveEdit.SetScriptSource(script, new_source, false, change_log);
+print("Result: " + JSON.stringify(result) + "\n");
+print("Change log: " + JSON.stringify(change_log) + "\n");
+
+assertEquals(8, z6());
+
+var z100 = Factory(100)();
+
+assertEquals(102, z100());
diff --git a/src/v8/test/debugger/debug/debug-liveedit-4.js b/src/v8/test/debugger/debug/debug-liveedit-4.js
new file mode 100644
index 0000000..0b94ece
--- /dev/null
+++ b/src/v8/test/debugger/debug/debug-liveedit-4.js
@@ -0,0 +1,68 @@
+// Copyright 2010 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: --noalways-opt
+
+// In this test case we edit a script so that techincally function text
+// hasen't been changed. However actually function became one level more nested
+// and must be recompiled because it uses variable from outer scope.
+
+
+Debug = debug.Debug
+
+eval(
+"function TestFunction() {\n"
++ "  var a = 'a';\n"
++ "  var b = 'b';\n"
++ "  var c = 'c';\n"
++ "  function A() {\n"
++ "    return 2013;\n"
++ "  }\n"
++ "  function B() {\n"
++ "    return String([a, c]);\n"
++ "  }\n"
++ "  return B();\n"
++ "}\n"
+);
+
+var res = TestFunction();
+print(res);
+assertEquals('a,c', res);
+
+var script = Debug.findScript(TestFunction);
+var new_source = script.source.replace("2013", "b");
+print("new source: " + new_source);
+var change_log = new Array();
+var result = Debug.LiveEdit.SetScriptSource(script, new_source, false, change_log);
+
+print("Result: " + JSON.stringify(result) + "\n");
+print("Change log: " + JSON.stringify(change_log) + "\n");
+
+var res = TestFunction();
+print(res);
+// This might be 'a,b' without a bug fixed.
+assertEquals('a,c', res);
diff --git a/src/v8/test/debugger/debug/debug-liveedit-check-stack.js b/src/v8/test/debugger/debug/debug-liveedit-check-stack.js
new file mode 100644
index 0000000..e016a53
--- /dev/null
+++ b/src/v8/test/debugger/debug/debug-liveedit-check-stack.js
@@ -0,0 +1,157 @@
+// Copyright 2010 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.
+
+
+Debug = debug.Debug
+
+unique_id = 1;
+
+function TestBase(name) {
+  print("TestBase constructor: " + name);
+
+  this.ChooseAnimal = eval(
+      "/* " + unique_id + "*/\n" +
+      "(function ChooseAnimal(callback) {\n " +
+      "  callback();\n" +
+      "  return 'Cat';\n" +
+      "})\n"
+  );
+  // Prevents eval script caching.
+  unique_id++;
+
+  var script = Debug.findScript(this.ChooseAnimal);
+
+  var orig_animal = "'Cat'";
+  var patch_pos = script.source.indexOf(orig_animal);
+  var new_animal_patch = "'Capybara'";
+
+  var got_exception = false;
+  var successfully_changed = false;
+
+  // Should be called from Debug context.
+  this.ScriptChanger = function() {
+    assertEquals(false, successfully_changed, "applying patch second time");
+    // Runs in debugger context.
+    var change_log = new Array();
+    try {
+      Debug.LiveEdit.TestApi.ApplySingleChunkPatch(script, patch_pos, orig_animal.length, new_animal_patch, change_log);
+    } finally {
+      print("Change log: " + JSON.stringify(change_log) + "\n");
+    }
+    successfully_changed = true;
+  };
+}
+
+function Noop() {}
+
+function WrapInCatcher(f, holder) {
+  return function() {
+    delete holder[0];
+    try {
+      f();
+    } catch (e) {
+      if (e instanceof Debug.LiveEdit.Failure) {
+        holder[0] = e;
+      } else {
+        throw e;
+      }
+    }
+  };
+}
+
+function WrapInNativeCall(f) {
+  return function() {
+    return %Call(f, undefined);
+  };
+}
+
+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 WrapInDebuggerCall(f) {
+  return function() {
+    return ExecuteInDebugContext(f);
+  };
+}
+
+function WrapInRestartProof(f) {
+  var already_called = false;
+  return function() {
+    if (already_called) {
+      return;
+    }
+    already_called = true;
+    f();
+  }
+}
+
+function WrapInConstructor(f) {
+  return function() {
+    return new function() {
+      f();
+    };
+  }
+}
+
+
+// A series of tests. In each test we call ChooseAnimal function that calls
+// a callback that attempts to modify the function on the fly.
+
+test = new TestBase("First test ChooseAnimal without edit");
+assertEquals("Cat", test.ChooseAnimal(Noop));
+
+test = new TestBase("Test without function on stack");
+test.ScriptChanger();
+assertEquals("Capybara", test.ChooseAnimal(Noop));
+
+test = new TestBase("Test with function on stack");
+assertEquals("Capybara", test.ChooseAnimal(WrapInDebuggerCall(WrapInRestartProof(test.ScriptChanger))));
+
+
+test = new TestBase("Test with function on stack and with constructor frame");
+assertEquals("Capybara", test.ChooseAnimal(WrapInConstructor(WrapInDebuggerCall(WrapInRestartProof(test.ScriptChanger)))));
+
+test = new TestBase("Test with C++ frame above ChooseAnimal frame");
+exception_holder = {};
+assertEquals("Cat", test.ChooseAnimal(WrapInNativeCall(WrapInDebuggerCall(WrapInCatcher(test.ScriptChanger, exception_holder)))));
+assertTrue(!!exception_holder[0]);
diff --git a/src/v8/test/debugger/debug/debug-liveedit-compile-error.js b/src/v8/test/debugger/debug/debug-liveedit-compile-error.js
new file mode 100644
index 0000000..24068eb
--- /dev/null
+++ b/src/v8/test/debugger/debug/debug-liveedit-compile-error.js
@@ -0,0 +1,56 @@
+// 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.
+
+
+Debug = debug.Debug
+
+eval("var something1 = 25; \n"
+     + " function ChooseAnimal() { return          'Cat';          } \n"
+     + " ChooseAnimal.Helper = function() { return 'Help!'; }\n");
+
+assertEquals("Cat", ChooseAnimal());
+
+var script = Debug.findScript(ChooseAnimal);
+
+var orig_animal = "Cat";
+var patch_pos = script.source.indexOf(orig_animal);
+var new_animal_patch = "Cap' + ) + 'bara";
+
+var change_log = new Array();
+var caught_exception = null;
+try {
+  Debug.LiveEdit.TestApi.ApplySingleChunkPatch(script, patch_pos,
+      orig_animal.length, new_animal_patch, change_log);
+} catch (e) {
+  caught_exception = e;
+}
+
+assertNotNull(caught_exception);
+assertEquals("Unexpected token )",
+    caught_exception.details.syntaxErrorMessage);
+
+assertEquals(2, caught_exception.details.position.start.line);
diff --git a/src/v8/test/debugger/debug/debug-liveedit-diff.js b/src/v8/test/debugger/debug/debug-liveedit-diff.js
new file mode 100644
index 0000000..d049cb0
--- /dev/null
+++ b/src/v8/test/debugger/debug/debug-liveedit-diff.js
@@ -0,0 +1,110 @@
+// Copyright 2010 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.
+
+
+Debug = debug.Debug
+
+function CheckCompareOneWay(s1, s2) {
+  var diff_array = Debug.LiveEdit.TestApi.CompareStrings(s1, s2);
+
+  var pos1 = 0;
+  var pos2 = 0;
+  print("Compare:");
+  print("s1='" + s1 + "'");
+  print("s2='" + s2 + "'");
+  print("Diff:");
+  print("" + diff_array);
+  for (var i = 0; i < diff_array.length; i += 3) {
+    var similar_length = diff_array[i] - pos1;
+    assertEquals(s1.substring(pos1, pos1 + similar_length),
+                 s2.substring(pos2, pos2 + similar_length));
+
+    print(s1.substring(pos1, pos1 + similar_length));
+    pos1 += similar_length;
+    pos2 += similar_length;
+    print("<<< " + pos1 + " " + diff_array[i + 1]);
+    print(s1.substring(pos1, diff_array[i + 1]));
+    print("===");
+    print(s2.substring(pos2, diff_array[i + 2]));
+    print(">>> " + pos2 + " " + diff_array[i + 2]);
+    pos1 = diff_array[i + 1];
+    pos2 = diff_array[i + 2];
+  }
+  {
+    // After last change
+    var similar_length = s1.length - pos1;
+    assertEquals(similar_length, s2.length - pos2);
+    assertEquals(s1.substring(pos1, pos1 + similar_length),
+                 s2.substring(pos2, pos2 + similar_length));
+
+    print(s1.substring(pos1, pos1 + similar_length));
+  }
+  print("");
+}
+
+function CheckCompareOneWayPlayWithLF(s1, s2) {
+  var s1Oneliner = s1.replace(/\n/g, ' ');
+  var s2Oneliner = s2.replace(/\n/g, ' ');
+  CheckCompareOneWay(s1, s2);
+  CheckCompareOneWay(s1Oneliner, s2);
+  CheckCompareOneWay(s1, s2Oneliner);
+  CheckCompareOneWay(s1Oneliner, s2Oneliner);
+}
+
+function CheckCompare(s1, s2) {
+  CheckCompareOneWayPlayWithLF(s1, s2);
+  CheckCompareOneWayPlayWithLF(s2, s1);
+}
+
+CheckCompare("", "");
+
+CheckCompare("a", "b");
+
+CheckCompare(
+    "yesterday\nall\nmy\ntroubles\nseemed\nso\nfar\naway",
+    "yesterday\nall\nmy\ntroubles\nseem\nso\nfar\naway"
+);
+
+CheckCompare(
+    "yesterday\nall\nmy\ntroubles\nseemed\nso\nfar\naway",
+    "\nall\nmy\ntroubles\nseemed\nso\nfar\naway"
+);
+
+CheckCompare(
+    "yesterday\nall\nmy\ntroubles\nseemed\nso\nfar\naway",
+    "all\nmy\ntroubles\nseemed\nso\nfar\naway"
+);
+
+CheckCompare(
+    "yesterday\nall\nmy\ntroubles\nseemed\nso\nfar\naway",
+    "yesterday\nall\nmy\ntroubles\nseemed\nso\nfar\naway\n"
+);
+
+CheckCompare(
+    "yesterday\nall\nmy\ntroubles\nseemed\nso\nfar\naway",
+    "yesterday\nall\nmy\ntroubles\nseemed\nso\n"
+);
diff --git a/src/v8/test/debugger/debug/debug-liveedit-double-call.js b/src/v8/test/debugger/debug/debug-liveedit-double-call.js
new file mode 100644
index 0000000..77d800e
--- /dev/null
+++ b/src/v8/test/debugger/debug/debug-liveedit-double-call.js
@@ -0,0 +1,140 @@
+// 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.
+
+// Flags: --noalways-opt
+
+Debug = debug.Debug
+
+function TestCase(test_scenario, expected_output) {
+  // Global variable, accessed from eval'd script.
+  test_output = "";
+
+  var script_text_generator = (function() {
+    var variables = { a: 1, b: 1, c: 1, d: 1, e: 1, f: 1 };
+
+    return {
+      get: function() {
+        return "(function() {\n " +
+            "  function A() {\n " +
+            "    test_output += 'a' + " + variables.a + ";\n " +
+            "    test_output += '=';\n " +
+            "    debugger;\n " +
+            "    return 'Capybara';\n " +
+            "  }\n " +
+            "  function B(p1, p2) {\n " +
+            "    test_output += 'b' + " + variables.b + ";\n " +
+            "    return A();\n " +
+            "  }\n " +
+            "  function C() {\n " +
+            "    test_output += 'c' + " + variables.c + ";\n " +
+            "    // Function call with argument adaptor is intentional.\n " +
+            "    return B();\n " +
+            "  }\n " +
+            "  function D() {\n " +
+            "    test_output += 'd' + " + variables.d + ";\n " +
+            "    // Function call with argument adaptor is intentional.\n " +
+            "    return C(1, 2);\n " +
+            "  }\n " +
+            "  function E() {\n " +
+            "    test_output += 'e' + " + variables.e + ";\n " +
+            "    return D();\n " +
+            "  }\n " +
+            "  function F() {\n " +
+            "    test_output += 'f' + " + variables.f + ";\n " +
+            "    return E();\n " +
+            "  }\n " +
+            "  return F();\n " +
+            "})\n";
+      },
+      change: function(var_name) {
+        variables[var_name]++;
+      }
+    };
+  })();
+
+  var test_fun = eval(script_text_generator.get());
+
+  var script = Debug.findScript(test_fun);
+
+  var scenario_pos = 0;
+
+  function DebuggerStatementHandler() {
+    while (true) {
+      assertTrue(scenario_pos < test_scenario.length);
+      var change_var = test_scenario[scenario_pos++];
+      if (change_var == '=') {
+        // Continue.
+        return;
+      }
+      script_text_generator.change(change_var);
+      try {
+        Debug.LiveEdit.SetScriptSource(script, script_text_generator.get(),
+            false, []);
+      } catch (e) {
+        print("LiveEdit exception: " + e);
+        throw e;
+      }
+    }
+  }
+
+  var saved_exception = null;
+
+  function listener(event, exec_state, event_data, data) {
+    if (event == Debug.DebugEvent.Break) {
+      try {
+        DebuggerStatementHandler();
+      } catch (e) {
+        saved_exception = e;
+      }
+    } else {
+      print("Other: " + event);
+    }
+  }
+
+  Debug.setListener(listener);
+  assertEquals("Capybara", test_fun());
+  Debug.setListener(null);
+
+  if (saved_exception) {
+    print("Exception: " + saved_exception);
+    assertUnreachable();
+  }
+
+  print(test_output);
+
+  assertEquals(expected_output, test_output);
+}
+
+TestCase(['='], "f1e1d1c1b1a1=");
+
+TestCase(['c', '=', '='], "f1e1d1c1b1a1=c2b1a1=");
+
+TestCase(['b', 'c', 'd', 'e', '=', '='], "f1e1d1c1b1a1=e2d2c2b2a1=");
+
+TestCase(['b', 'c', '=', 'b', 'c', 'd', 'e', '=', '='], "f1e1d1c1b1a1=c2b2a1=e2d2c3b3a1=");
+
+TestCase(['e', 'f', '=', '='], "f1e1d1c1b1a1=f2e2d1c1b1a1=");
diff --git a/src/v8/test/debugger/debug/debug-liveedit-exceptions.js b/src/v8/test/debugger/debug/debug-liveedit-exceptions.js
new file mode 100644
index 0000000..36463b3
--- /dev/null
+++ b/src/v8/test/debugger/debug/debug-liveedit-exceptions.js
@@ -0,0 +1,66 @@
+// 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
+
+function BestEditor() {
+  throw 'Emacs';
+}
+
+var exception = null;
+var results = [];
+var log = []
+
+function listener(event, exec_state, event_data, data) {
+  if (event != Debug.DebugEvent.Exception) return;
+  try {
+    var source_line = event_data.sourceLineText();
+    print(source_line);
+    log.push(source_line);
+    switch (results.length) {
+      case 0:
+        Replace(BestEditor, "Emacs", "Eclipse");
+        break;
+      case 1:
+        Replace(BestEditor, "Eclipse", "Vim");
+        break;
+      case 2:
+        break;
+      default:
+        assertUnreachable();
+    }
+  } catch (e) {
+    exception = e;
+  }
+};
+
+function Replace(fun, original, patch) {
+  var script = Debug.findScript(fun);
+  if (fun.toString().indexOf(original) < 0) return;
+  var patch_pos = script.source.indexOf(original);
+  var change_log = [];
+  Debug.LiveEdit.TestApi.ApplySingleChunkPatch(script, patch_pos, original.length, patch, change_log);
+}
+
+Debug.setListener(listener);
+Debug.setBreakOnException();
+
+for (var i = 0; i < 3; i++) {
+  try {
+    BestEditor();
+  } catch (e) {
+    results.push(e);
+  }
+}
+Debug.setListener(null);
+
+assertNull(exception);
+assertEquals(["Emacs", "Eclipse", "Vim"], results);
+print(JSON.stringify(log, 1));
+assertEquals([
+  "  throw 'Emacs';",
+  "  throw 'Eclipse';",
+  "  throw 'Vim';",
+], log);
diff --git a/src/v8/test/debugger/debug/debug-liveedit-inline.js b/src/v8/test/debugger/debug/debug-liveedit-inline.js
new file mode 100644
index 0000000..4d20991
--- /dev/null
+++ b/src/v8/test/debugger/debug/debug-liveedit-inline.js
@@ -0,0 +1,30 @@
+// Copyright 2017 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: --allow-natives-syntax --enable-inspector
+
+Debug = debug.Debug
+
+eval("var something1 = 25; "
+     + " function ChooseAnimal() { return          'Cat';          } "
+     + " ChooseAnimal.Helper = function() { return 'Help!'; }");
+
+function foo() {  return ChooseAnimal() }
+
+assertEquals("Cat", foo());
+    %OptimizeFunctionOnNextCall(foo);
+
+foo();
+
+var script = Debug.findScript(ChooseAnimal);
+
+var orig_animal = "Cat";
+var patch_pos = script.source.indexOf(orig_animal);
+var new_animal_patch = "Cap' + 'y' + 'bara";
+
+var change_log = new Array();
+
+Debug.LiveEdit.TestApi.ApplySingleChunkPatch(script, patch_pos, orig_animal.length, new_animal_patch, change_log);
+
+assertEquals("Capybara", foo());
diff --git a/src/v8/test/debugger/debug/debug-liveedit-literals.js b/src/v8/test/debugger/debug/debug-liveedit-literals.js
new file mode 100644
index 0000000..08edec3
--- /dev/null
+++ b/src/v8/test/debugger/debug/debug-liveedit-literals.js
@@ -0,0 +1,92 @@
+// Copyright 2010 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.
+
+
+Debug = debug.Debug
+
+function Test(old_expression, new_expression) {
+    // Generate several instances of function to test that we correctly fix
+    // all functions in memory.
+    var function_instance_number = 11;
+    eval("var t1 =1;\n" +
+         "ChooseAnimalArray = [];\n" +
+         "for (var i = 0; i < function_instance_number; i++) {\n" +
+         "    ChooseAnimalArray.push(\n" +
+         "        function ChooseAnimal() {\n" +
+         "            return " + old_expression + ";\n" +
+         "        });\n" +
+         "}\n" +
+         "var t2 =1;\n");
+
+    for (var i = 0; i < ChooseAnimalArray.length; i++) {
+        assertEquals("Cat", ChooseAnimalArray[i]());
+    }
+
+    var script = Debug.findScript(ChooseAnimalArray[0]);
+
+    var patch_pos = script.source.indexOf(old_expression);
+    var new_animal_patch = new_expression;
+
+    var change_log = new Array();
+    Debug.LiveEdit.TestApi.ApplySingleChunkPatch(script, patch_pos,
+        old_expression.length, new_expression, change_log);
+
+    for (var i = 0; i < ChooseAnimalArray.length; i++) {
+        assertEquals("Capybara", ChooseAnimalArray[i]());
+    }
+}
+
+// Check that old literal boilerplate was reset.
+Test("['Cat'][0]", "['Capybara'][0]");
+Test("['Cat'][0]", "{a:'Capybara'}.a");
+
+// No literals -> 1 literal.
+Test("'Cat'", "['Capybara'][0]");
+
+// No literals -> 2 literals.
+Test("'Cat'", "['Capy'][0] + {a:'bara'}.a");
+
+// 1 literal -> no literals.
+Test("['Cat'][0]", "'Capybara'");
+
+// 2 literals -> no literals.
+Test("['Ca'][0] + {a:'t'}.a", "'Capybara'");
+
+// No literals -> regexp.
+Test("'Cat'", "(/.A.Y.A.A/i).exec('Capybara')[0]");
+
+// Array literal -> regexp.
+Test("['Cat'][0]", "(/.A.Y.A.A/i).exec('Capybara')[0]");
+
+// Regexp -> object literal.
+Test("(/.A./i).exec('Cat')[0]", "{c:'Capybara'}.c");
+
+// No literals -> regexp.
+Test("'Cat'", "(/.A.Y.A.A/i).exec('Capybara')[0]");
+
+// Regexp -> no literals.
+Test("(/.A./i).exec('Cat')[0]", "'Capybara'");
diff --git a/src/v8/test/debugger/debug/debug-liveedit-newsource.js b/src/v8/test/debugger/debug/debug-liveedit-newsource.js
new file mode 100644
index 0000000..e6f55bb
--- /dev/null
+++ b/src/v8/test/debugger/debug/debug-liveedit-newsource.js
@@ -0,0 +1,75 @@
+// Copyright 2010 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.
+
+
+Debug = debug.Debug
+
+eval("var something1 = 25; \n"
+     + "var something2 = 2010; \n"
+     + "// Array(); \n"
+     + "function ChooseAnimal() {\n"
+     + "  return 'Cat';\n"
+     + "} \n"
+     + "function ChooseFurniture() {\n"
+     + "  return 'Table';\n"
+     + "} \n"
+     + "function ChooseNumber() { return 17; } \n"
+     + "ChooseAnimal.Factory = function Factory() {\n"
+     + "  return function FactoryImpl(name) {\n"
+     + "    return 'Help ' + name;\n"
+     + "  }\n"
+     + "}\n");
+
+assertEquals("Cat", ChooseAnimal());
+assertEquals(25, something1);
+
+var script = Debug.findScript(ChooseAnimal);
+
+var new_source = script.source.replace("Cat", "Cap' + 'yb' + 'ara");
+var new_source = new_source.replace("25", "26");
+var new_source = new_source.replace("Help", "Hello");
+var new_source = new_source.replace("17", "18");
+// The call to array causes a change in the number of type feedback slots for
+// the script.
+//
+// TODO(mvstanton): For now, the inclusion of the Array() call at the top level
+// of the script causes us to visit a corner case, but I'd like to validate
+// correctness more explicitly.
+var new_source = new_source.replace("// Array", "Array");
+print("new source: " + new_source);
+
+var change_log = new Array();
+var result = Debug.LiveEdit.SetScriptSource(script, new_source, false, change_log);
+print("Result: " + JSON.stringify(result) + "\n");
+print("Change log: " + JSON.stringify(change_log) + "\n");
+
+assertEquals("Capybara", ChooseAnimal());
+// Global variable do not get changed (without restarting script).
+assertEquals(25, something1);
+// We should support changes in oneliners.
+assertEquals(18, ChooseNumber());
+assertEquals("Hello Peter", ChooseAnimal.Factory()("Peter"));
diff --git a/src/v8/test/debugger/debug/debug-liveedit-patch-positions-replace.js b/src/v8/test/debugger/debug/debug-liveedit-patch-positions-replace.js
new file mode 100644
index 0000000..374ffde
--- /dev/null
+++ b/src/v8/test/debugger/debug/debug-liveedit-patch-positions-replace.js
@@ -0,0 +1,81 @@
+// Copyright 2010 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.
+
+
+// Scenario: a function is being changed, which causes enclosing function to
+// have its positions patched; position changing requires new instance of Code
+// object to be introduced; the function happens to be on stack at this moment;
+// later it will resume over new instance of Code.
+// Before the change 2 rinfo are 22 characters away from each other. After the
+// change they are 114 characters away from each other. New instance of Code is
+// required when those numbers cross the border value of 64 (in any direction).
+
+Debug = debug.Debug
+
+eval(
+    "function BeingReplaced(changer, opt_x, opt_y) {\n" +
+    "  changer();\n" +
+    "  var res = new Object();\n" +
+    "  if (opt_x) { res.y = opt_y; }\n" +
+    "  res.a = (function() {})();\n" +
+    "  return res.a;\n" +
+    "}"
+);
+
+var script = Debug.findScript(BeingReplaced);
+
+var orig_body = "{}";
+var patch_pos = script.source.indexOf(orig_body);
+// Line long enough to change rinfo encoding.
+var new_body_patch = "{return 'Capybara';" +
+    "                                                                          " +
+    "}";
+
+var change_log = new Array();
+function Changer() {
+  Debug.LiveEdit.TestApi.ApplySingleChunkPatch(script, patch_pos, orig_body.length, new_body_patch, change_log);
+  print("Change log: " + JSON.stringify(change_log) + "\n");
+}
+
+function NoOp() {
+}
+
+function CallM(changer) {
+  // We expect call IC here after several function runs.
+  return BeingReplaced(changer);
+}
+
+// This several iterations should cause call IC for BeingReplaced call. This IC
+// will keep reference to code object of BeingRepalced function. This reference
+// should also be patched. Unfortunately, this is a manually checked fact (from
+// debugger or debug print) and doesn't work as an automatic test.
+CallM(NoOp);
+CallM(NoOp);
+CallM(NoOp);
+
+var res = CallM(Changer);
+assertEquals("Capybara", res);
diff --git a/src/v8/test/debugger/debug/debug-liveedit-replace-code.js b/src/v8/test/debugger/debug/debug-liveedit-replace-code.js
new file mode 100644
index 0000000..a3b83bb
--- /dev/null
+++ b/src/v8/test/debugger/debug/debug-liveedit-replace-code.js
@@ -0,0 +1,33 @@
+// Copyright 2017 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 counter = 0;
+var exception = null;
+
+function f() {
+  if (++counter > 5) return;
+  debugger;
+  return counter;
+}
+
+function listener(event, exec_state, event_data, data) {
+  if (event != Debug.DebugEvent.Break) return;
+  try {
+    var script = Debug.findScript(f);
+    var original = 'debugger;';
+    var patch = 'debugger;\n';
+    var position = script.source.indexOf(original);
+    Debug.LiveEdit.TestApi.ApplySingleChunkPatch(
+        script, position, original.length, patch, []);
+  } catch (e) {
+    exception = e;
+  }
+}
+
+Debug.setListener(listener);
+f();
+Debug.setListener(null);
+assertNull(exception);
+assertEquals(6, counter);
diff --git a/src/v8/test/debugger/debug/debug-liveedit-restart-frame.js b/src/v8/test/debugger/debug/debug-liveedit-restart-frame.js
new file mode 100644
index 0000000..659e3c7
--- /dev/null
+++ b/src/v8/test/debugger/debug/debug-liveedit-restart-frame.js
@@ -0,0 +1,154 @@
+// 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.
+//
+// Flags: --noanalyze-environment-liveness
+
+
+Debug = debug.Debug
+
+function FindCallFrame(exec_state, frame_code) {
+  var number = Number(frame_code);
+  if (number >= 0) {
+    return exec_state.frame(number);
+  } else {
+    for (var i = 0; i < exec_state.frameCount(); i++) {
+      var frame = exec_state.frame(i);
+      var func_mirror = frame.func();
+      if (frame_code == func_mirror.name()) {
+        return frame;
+      }
+    }
+  }
+  throw new Error("Failed to find function name " + function_name);
+}
+
+function TestCase(test_scenario, expected_output) {
+  // Global variable, accessed from eval'd script.
+  test_output = "";
+
+  function TestCode() {
+    function A() {
+      // Extra stack variable. To make function not slim.
+      // Restarter doesn't work on slim function when stopped on 'debugger'
+      // statement. (There is no padding for 'debugger' statement).
+      var o = {};
+      test_output += 'A';
+      test_output += '=';
+      debugger;
+      return 'Capybara';
+    }
+    function B(p1, p2) {
+      test_output += 'B';
+      return A();
+    }
+    function C() {
+      test_output += 'C';
+      // Function call with argument adaptor is intentional.
+      return B();
+    }
+    function D() {
+      test_output += 'D';
+      // Function call with argument adaptor is intentional.
+      return C(1, 2);
+    }
+    function E() {
+      test_output += 'E';
+      return D();
+    }
+    function F() {
+      test_output += 'F';
+      return E();
+    }
+    return F();
+  }
+
+  var scenario_pos = 0;
+
+  function DebuggerStatementHandler(exec_state) {
+    while (true) {
+      assertTrue(scenario_pos < test_scenario.length);
+      var change_code = test_scenario[scenario_pos++];
+      if (change_code == '=') {
+        // Continue.
+        return;
+      }
+      var frame = FindCallFrame(exec_state, change_code);
+      var error = frame.restart();
+      if (typeof error === 'string')
+          throw new Error(error);
+    }
+  }
+
+  var saved_exception = null;
+
+  function listener(event, exec_state, event_data, data) {
+    if (saved_exception != null) {
+      return;
+    }
+    if (event == Debug.DebugEvent.Break) {
+      try {
+        DebuggerStatementHandler(exec_state);
+      } catch (e) {
+        saved_exception = e;
+      }
+    } else {
+      print("Other: " + event);
+    }
+  }
+
+  Debug.setListener(listener);
+  assertEquals("Capybara", TestCode());
+  Debug.setListener(null);
+
+  if (saved_exception) {
+    print("Exception: " + saved_exception);
+    print("Stack: " + saved_exception.stack);
+    assertUnreachable();
+  }
+
+  print(test_output);
+
+  assertEquals(expected_output, test_output);
+}
+
+TestCase('0==', "FEDCBA=A=");
+TestCase('1==', "FEDCBA=BA=");
+TestCase('2==', "FEDCBA=CBA=");
+TestCase('3==', "FEDCBA=DCBA=");
+TestCase('4==', "FEDCBA=EDCBA=");
+TestCase('5==', "FEDCBA=FEDCBA=");
+
+TestCase('=', "FEDCBA=");
+
+TestCase('C==', "FEDCBA=CBA=");
+
+TestCase('B=C=A=D==', "FEDCBA=BA=CBA=A=DCBA=");
+
+// Successive restarts don't work now and require additional fix.
+//TestCase('BCDE==', "FEDCBA=EDCBA=");
+//TestCase('BC=BCDE==', "FEDCBA=CBA=EDCBA=");
+//TestCase('EF==', "FEDCBA=FEDCBA=");
diff --git a/src/v8/test/debugger/debug/debug-liveedit-stack-padding.js b/src/v8/test/debugger/debug/debug-liveedit-stack-padding.js
new file mode 100644
index 0000000..d0cc77a
--- /dev/null
+++ b/src/v8/test/debugger/debug/debug-liveedit-stack-padding.js
@@ -0,0 +1,88 @@
+// 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.
+
+
+Debug = debug.Debug;
+Debug.setListener(listener);
+
+SlimFunction = eval(
+    "(function() {\n " +
+    "  return 'Cat';\n" +
+    "})\n"
+);
+
+var script = Debug.findScript(SlimFunction);
+
+Debug.setScriptBreakPointById(script.id, 1, 0);
+
+var orig_animal = "'Cat'";
+var patch_pos = script.source.indexOf(orig_animal);
+var new_animal_patch = "'Capybara'";
+
+debugger_handler = (function() {
+  var already_called = false;
+  return function() {
+    if (already_called) {
+      return;
+    }
+    already_called = true;
+
+    var change_log = new Array();
+    try {
+      Debug.LiveEdit.TestApi.ApplySingleChunkPatch(script, patch_pos,
+          orig_animal.length, new_animal_patch, change_log);
+    } finally {
+      print("Change log: " + JSON.stringify(change_log) + "\n");
+    }
+  };
+})();
+
+var saved_exception = null;
+
+function listener(event, exec_state, event_data, data) {
+  if (event == Debug.DebugEvent.Break) {
+    try {
+      debugger_handler();
+    } catch (e) {
+      saved_exception = e;
+    }
+  } else {
+    print("Other: " + event);
+  }
+}
+
+
+var animal = SlimFunction();
+
+if (saved_exception) {
+  print("Exception: " + saved_exception);
+  assertUnreachable();
+}
+
+assertEquals("Capybara", animal);
+
+Debug.setListener(null);
diff --git a/src/v8/test/debugger/debug/debug-liveedit-stepin.js b/src/v8/test/debugger/debug/debug-liveedit-stepin.js
new file mode 100644
index 0000000..f96a079
--- /dev/null
+++ b/src/v8/test/debugger/debug/debug-liveedit-stepin.js
@@ -0,0 +1,77 @@
+// 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
+
+function BestEditor() {
+  return 'Emacs';
+}
+
+var exception = null;
+var results = [];
+var log = []
+
+function listener(event, exec_state, event_data, data) {
+  if (event != Debug.DebugEvent.Break) return;
+  try {
+    var source_line = event_data.sourceLineText();
+    log.push(source_line);
+    if (source_line.indexOf("return") >= 0) {
+      switch (results.length) {
+        case 0:
+          break;
+        case 1:
+          Replace(BestEditor, "Emacs", "Eclipse");
+          break;
+        case 2:
+          Replace(BestEditor, "Eclipse", "Vim");
+          break;
+        default:
+          assertUnreachable();
+      }
+    }
+    exec_state.prepareStep(Debug.StepAction.StepIn);
+  } catch (e) {
+    exception = e;
+  }
+};
+
+function Replace(fun, original, patch) {
+  var script = Debug.findScript(fun);
+  if (fun.toString().indexOf(original) < 0) return;
+  var patch_pos = script.source.indexOf(original);
+  var change_log = [];
+  Debug.LiveEdit.TestApi.ApplySingleChunkPatch(script, patch_pos, original.length, patch, change_log);
+}
+
+Debug.setListener(listener);
+
+debugger;
+results.push(BestEditor());
+results.push(BestEditor());
+results.push(BestEditor());
+Debug.setListener(null);
+
+assertNull(exception);
+assertEquals(["Emacs", "Eclipse", "Vim"], results);
+print(JSON.stringify(log, 1));
+assertEquals([
+  "debugger;",
+  "results.push(BestEditor());",
+  "  return 'Emacs';",
+  "  return 'Emacs';",
+  "results.push(BestEditor());",
+  "results.push(BestEditor());",
+  "  return 'Emacs';",
+  "  return 'Eclipse';",
+  "  return 'Eclipse';",
+  "results.push(BestEditor());",
+  "results.push(BestEditor());",
+  "  return 'Eclipse';",
+  "  return 'Vim';",
+  "  return 'Vim';",
+  "results.push(BestEditor());",
+  "Debug.setListener(null);"
+], log);
diff --git a/src/v8/test/debugger/debug/debug-liveedit-utils.js b/src/v8/test/debugger/debug/debug-liveedit-utils.js
new file mode 100644
index 0000000..df63181
--- /dev/null
+++ b/src/v8/test/debugger/debug/debug-liveedit-utils.js
@@ -0,0 +1,93 @@
+// Copyright 2010 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.
+
+
+Debug = debug.Debug
+
+function Return2010() {
+  return 2010;
+}
+
+
+// Diff it trivial: zero chunks
+var NoChunkTranslator = new Debug.LiveEdit.TestApi.PosTranslator([]);
+
+assertEquals(0, NoChunkTranslator.Translate(0));
+assertEquals(10, NoChunkTranslator.Translate(10));
+
+
+// Diff has one chunk
+var SingleChunkTranslator = new Debug.LiveEdit.TestApi.PosTranslator([20, 30, 25]);
+
+assertEquals(0, SingleChunkTranslator.Translate(0));
+assertEquals(5, SingleChunkTranslator.Translate(5));
+assertEquals(10, SingleChunkTranslator.Translate(10));
+assertEquals(19, SingleChunkTranslator.Translate(19));
+assertEquals(2010, SingleChunkTranslator.Translate(20, Return2010));
+assertEquals(25, SingleChunkTranslator.Translate(30));
+assertEquals(26, SingleChunkTranslator.Translate(31));
+assertEquals(2010, SingleChunkTranslator.Translate(26, Return2010));
+
+try {
+  SingleChunkTranslator.Translate(21);
+  assertTrue(false);
+} catch (ignore) {
+}
+try {
+  SingleChunkTranslator.Translate(24);
+  assertTrue(false);
+} catch (ignore) {
+}
+
+
+// Diff has several chunk (3). See the table below.
+
+/*
+chunks: (new <- old)
+ 10   10
+ 15   20
+
+ 35   40
+ 50   40
+
+ 70   60
+ 70   70
+*/
+
+var MultiChunkTranslator = new Debug.LiveEdit.TestApi.PosTranslator([10, 20, 15, 40, 40, 50, 60, 70, 70 ]);
+assertEquals(5, MultiChunkTranslator.Translate(5));
+assertEquals(9, MultiChunkTranslator.Translate(9));
+assertEquals(2010, MultiChunkTranslator.Translate(10, Return2010));
+assertEquals(15, MultiChunkTranslator.Translate(20));
+assertEquals(20, MultiChunkTranslator.Translate(25));
+assertEquals(34, MultiChunkTranslator.Translate(39));
+assertEquals(50, MultiChunkTranslator.Translate(40, Return2010));
+assertEquals(55, MultiChunkTranslator.Translate(45));
+assertEquals(69, MultiChunkTranslator.Translate(59));
+assertEquals(2010, MultiChunkTranslator.Translate(60, Return2010));
+assertEquals(70, MultiChunkTranslator.Translate(70));
+assertEquals(75, MultiChunkTranslator.Translate(75));
diff --git a/src/v8/test/debugger/debug/debug-materialized.js b/src/v8/test/debugger/debug/debug-materialized.js
new file mode 100644
index 0000000..dd22e1e
--- /dev/null
+++ b/src/v8/test/debugger/debug/debug-materialized.js
@@ -0,0 +1,40 @@
+// 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.
+
+
+function dbg(x) {
+  debugger;
+}
+
+function foo() {
+  arguments[0];
+  dbg();
+}
+
+function bar() {
+  var t = { a : 1 };
+  dbg();
+  return t.a;
+}
+
+foo(1);
+foo(1);
+bar(1);
+bar(1);
+%OptimizeFunctionOnNextCall(foo);
+%OptimizeFunctionOnNextCall(bar);
+
+var Debug = debug.Debug;
+Debug.setListener(function(event, exec_state, event_data, data) {
+  if (event != Debug.DebugEvent.Break) return;
+  for (var i = 0; i < exec_state.frameCount(); i++) {
+    var f = exec_state.frame(i);
+    for (var j = 0; j < f.localCount(); j++) {
+      print("'" + f.localName(j) + "' = " + f.localValue(j).value());
+    }
+  }
+});
+
+foo(1);
+bar(1);
diff --git a/src/v8/test/debugger/debug/debug-modules-set-variable-value.js b/src/v8/test/debugger/debug/debug-modules-set-variable-value.js
new file mode 100644
index 0000000..61c032f
--- /dev/null
+++ b/src/v8/test/debugger/debug/debug-modules-set-variable-value.js
@@ -0,0 +1,378 @@
+// 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.
+
+// MODULE
+// Flags: --no-always-opt
+
+// The first part of this file is copied over from debug-set-variable-value.js
+// (a few tests were removed because they make no sense for modules). The second
+// part is new.
+
+var Debug = debug.Debug;
+
+// Accepts a function/closure 'fun' that must have a debugger statement inside.
+// A variable 'variable_name' must be initialized before debugger statement
+// and returned after the statement. The test will alter variable value when
+// on debugger statement and check that returned value reflects the change.
+function RunPauseTest(scope_number, expected_old_result, variable_name,
+    new_value, expected_new_result, fun) {
+  var actual_old_result = fun();
+  assertEquals(expected_old_result, actual_old_result);
+
+  var listener_delegate;
+  var listener_called = false;
+  var exception = null;
+
+  function listener_delegate(exec_state) {
+    var scope = exec_state.frame(0).scope(scope_number);
+    scope.setVariableValue(variable_name, new_value);
+  }
+
+  function listener(event, exec_state, event_data, data) {
+    try {
+      if (event == Debug.DebugEvent.Break) {
+        listener_called = true;
+        listener_delegate(exec_state);
+      }
+    } catch (e) {
+      exception = e;
+    }
+  }
+
+  // Add the debug event listener.
+  Debug.setListener(listener);
+
+  var actual_new_result;
+  try {
+    actual_new_result = fun();
+  } finally {
+    Debug.setListener(null);
+  }
+
+  if (exception != null) {
+   assertUnreachable("Exception in listener\n" + exception.stack);
+  }
+  assertTrue(listener_called);
+
+  assertEquals(expected_new_result, actual_new_result);
+}
+
+
+function ClosureTestCase(scope_index, old_result, variable_name, new_value,
+    new_result, success_expected, factory) {
+  this.scope_index_ = scope_index;
+  this.old_result_ = old_result;
+  this.variable_name_ = variable_name;
+  this.new_value_ = new_value;
+  this.new_result_ = new_result;
+  this.success_expected_ = success_expected;
+  this.factory_ = factory;
+}
+
+ClosureTestCase.prototype.run_pause_test = function() {
+  var th = this;
+  var fun = this.factory_(true);
+  this.run_and_catch_(function() {
+    RunPauseTest(th.scope_index_ + 1, th.old_result_, th.variable_name_,
+        th.new_value_, th.new_result_, fun);
+  });
+}
+
+ClosureTestCase.prototype.run_and_catch_ = function(runnable) {
+  if (this.success_expected_) {
+    runnable();
+  } else {
+    assertThrows(runnable);
+  }
+}
+
+
+// Test scopes visible from closures.
+
+var closure_test_cases = [
+  new ClosureTestCase(0, 'cat', 'v1', 5, 5, true,
+      function Factory(debug_stop) {
+    var v1 = 'cat';
+    return function() {
+      if (debug_stop) debugger;
+      return v1;
+    }
+  }),
+
+  new ClosureTestCase(0, 4, 't', 7, 9, true, function Factory(debug_stop) {
+    var t = 2;
+    var r = eval("t");
+    return function() {
+      if (debug_stop) debugger;
+      return r + t;
+    }
+  }),
+
+  new ClosureTestCase(0, 6, 't', 10, 13, true, function Factory(debug_stop) {
+    var t = 2;
+    var r = eval("t = 3");
+    return function() {
+      if (debug_stop) debugger;
+      return r + t;
+    }
+  }),
+
+  new ClosureTestCase(2, 'capybara', 'foo', 77, 77, true,
+      function Factory(debug_stop) {
+    var foo = "capybara";
+    return (function() {
+      var bar = "fish";
+      try {
+        throw {name: "test exception"};
+      } catch (e) {
+        return function() {
+          if (debug_stop) debugger;
+          bar = "beast";
+          return foo;
+        }
+      }
+    })();
+  }),
+
+  new ClosureTestCase(0, 'AlphaBeta', 'eee', 5, '5Beta', true,
+      function Factory(debug_stop) {
+    var foo = "Beta";
+    return (function() {
+      var bar = "fish";
+      try {
+        throw "Alpha";
+      } catch (eee) {
+        return function() {
+          if (debug_stop) debugger;
+          return eee + foo;
+        }
+      }
+    })();
+  })
+];
+
+for (var i = 0; i < closure_test_cases.length; i++) {
+  closure_test_cases[i].run_pause_test();
+}
+
+
+// Test local scope.
+
+RunPauseTest(0, 'HelloYou', 'u', 'We', 'HelloWe', (function Factory() {
+  return function() {
+    var u = "You";
+    var v = "Hello";
+    debugger;
+    return v + u;
+  }
+})());
+
+RunPauseTest(0, 'Helloworld', 'p', 'GoodBye', 'HelloGoodBye',
+    (function Factory() {
+  function H(p) {
+    var v = "Hello";
+    debugger;
+    return v + p;
+  }
+  return function() {
+    return H("world");
+  }
+})());
+
+RunPauseTest(0, 'mouse', 'v1', 'dog', 'dog', (function Factory() {
+  return function() {
+    var v1 = 'cat';
+    eval("v1 = 'mouse'");
+    debugger;
+    return v1;
+  }
+})());
+
+// Check that we correctly update local variable that
+// is referenced from an inner closure.
+RunPauseTest(0, 'Blue', 'v', 'Green', 'Green', (function Factory() {
+  return function() {
+    function A() {
+      var v = "Blue";
+      function Inner() {
+        return void v;
+      }
+      debugger;
+      return v;
+    }
+    return A();
+  }
+})());
+
+// Check that we correctly update parameter, that is known to be stored
+// both on stack and in heap.
+RunPauseTest(0, 5, 'p', 2012, 2012, (function Factory() {
+  return function() {
+    function A(p) {
+      function Inner() {
+        return void p;
+      }
+      debugger;
+      return p;
+    }
+    return A(5);
+  }
+})());
+
+
+////////////////////////////////////////////////////////////////////////////////
+// From here on we test the module scope.
+////////////////////////////////////////////////////////////////////////////////
+
+
+// Non-existing variable.
+{
+  let exception;
+  function listener(event, exec_state) {
+    if (event == Debug.DebugEvent.Break) {
+      let module_scope = exec_state.frame().scope(1);
+      assertEquals(debug.ScopeType.Module, module_scope.scopeType());
+      try {
+        module_scope.setVariableValue('spargel', 42);
+      } catch(e) { exception = e; }
+    }
+  }
+
+  Debug.setListener(listener);
+  assertThrows(() => spargel, ReferenceError);
+  debugger;
+  assertThrows(() => spargel, ReferenceError);
+  assertTrue(exception !== undefined);
+}
+
+
+// Local (non-exported) variable.
+let salat = 12;
+{
+  function listener(event, exec_state) {
+    if (event == Debug.DebugEvent.Break) {
+      let module_scope = exec_state.frame().scope(1);
+      assertEquals(debug.ScopeType.Module, module_scope.scopeType());
+      module_scope.setVariableValue('salat', 42);
+    }
+  }
+
+  Debug.setListener(listener);
+  assertEquals(12, salat);
+  debugger;
+  assertEquals(42, salat);
+}
+
+
+// Local (non-exported) variable, nested access.
+let salad = 12;
+{
+  function listener(event, exec_state) {
+    if (event == Debug.DebugEvent.Break) {
+      let scope_count = exec_state.frame().scopeCount();
+      let module_scope = exec_state.frame().scope(2);
+      assertEquals(debug.ScopeType.Module, module_scope.scopeType());
+      module_scope.setVariableValue('salad', 42);
+    }
+  }
+
+  Debug.setListener(listener);
+  function foo() {
+    assertEquals(12, salad);
+    debugger;
+    assertEquals(42, salad);
+  };
+  foo();
+}
+
+
+// Exported variable.
+export let salami = 1;
+{
+  function listener(event, exec_state) {
+    if (event == Debug.DebugEvent.Break) {
+      let module_scope = exec_state.frame().scope(1);
+      assertEquals(debug.ScopeType.Module, module_scope.scopeType());
+      module_scope.setVariableValue('salami', 2);
+    }
+  }
+
+  Debug.setListener(listener);
+  assertEquals(1, salami);
+  debugger;
+  assertEquals(2, salami);
+}
+
+
+// Exported variable, nested access.
+export let ham = 1;
+{
+  function listener(event, exec_state) {
+    if (event == Debug.DebugEvent.Break) {
+      let scope_count = exec_state.frame().scopeCount();
+      let module_scope = exec_state.frame().scope(2);
+      assertEquals(debug.ScopeType.Module, module_scope.scopeType());
+      module_scope.setVariableValue('ham', 2);
+    }
+  }
+
+  Debug.setListener(listener);
+  function foo() {
+    assertEquals(1, ham);
+    debugger;
+    assertEquals(2, ham);
+  };
+  foo();
+}
+
+
+// Imported variable. Setting is currently not supported.
+import { salami as wurst } from "./debug-modules-set-variable-value.js";
+{
+  let exception;
+  function listener(event, exec_state) {
+    if (event == Debug.DebugEvent.Break) {
+      let module_scope = exec_state.frame().scope(1);
+      assertEquals(debug.ScopeType.Module, module_scope.scopeType());
+      try {
+        module_scope.setVariableValue('wurst', 3);
+      } catch(e) { exception = e; }
+    }
+  }
+
+  Debug.setListener(listener);
+  assertEquals(2, wurst);
+  debugger;
+  assertEquals(2, wurst);
+  assertTrue(exception !== undefined);
+}
+
+
+// Imported variable, nested access. Setting is currently not supported.
+import { salami as wurstl } from "./debug-modules-set-variable-value.js";
+{
+  let exception;
+  function listener(event, exec_state) {
+    if (event == Debug.DebugEvent.Break) {
+      let scope_count = exec_state.frame().scopeCount();
+      let module_scope = exec_state.frame().scope(2);
+      assertEquals(debug.ScopeType.Module, module_scope.scopeType());
+      try {
+        module_scope.setVariableValue('wurstl', 3);
+      } catch(e) { exception = e; }
+    }
+  }
+
+  Debug.setListener(listener);
+  function foo() {
+    assertEquals(2, wurstl);
+    debugger;
+    assertEquals(2, wurstl);
+    assertTrue(exception !== undefined);
+  };
+  foo();
+}
+
+
+Debug.setListener(null);
diff --git a/src/v8/test/debugger/debug/debug-multiple-breakpoints.js b/src/v8/test/debugger/debug/debug-multiple-breakpoints.js
new file mode 100644
index 0000000..6e19140
--- /dev/null
+++ b/src/v8/test/debugger/debug/debug-multiple-breakpoints.js
@@ -0,0 +1,92 @@
+// Copyright 2008 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.
+
+Debug = debug.Debug
+
+// Simple debug event handler which just counts the number of break points hit.
+var break_point_hit_count;
+
+function listener(event, exec_state, event_data, data) {
+  if (event == Debug.DebugEvent.Break) {
+    break_point_hit_count++;
+  }
+};
+
+// Add the debug event listener.
+Debug.setListener(listener);
+
+// Test functions
+function f() {a=1;b=2;};
+function g() {f();}
+function h() {}
+
+// This test sets several break points at the same place and checks that
+// several break points at the same place only makes one debug break event
+// and that when the last break point is removed no more debug break events
+// occours.
+break_point_hit_count = 0;
+
+// Set a breakpoint in f.
+bp1 = Debug.setBreakPoint(f);
+f();
+assertEquals(1, break_point_hit_count);
+
+// Set another breakpoint in f at the same place.
+assertThrows(() => Debug.setBreakPoint(f));
+f();
+assertEquals(2, break_point_hit_count);
+
+// Remove the break points.
+Debug.clearBreakPoint(bp1);
+f();
+assertEquals(2, break_point_hit_count);
+
+// Perform the same test using function g (this time removing the break points
+// in the another order).
+break_point_hit_count = 0;
+bp1 = Debug.setBreakPoint(g);
+g();
+assertEquals(1, break_point_hit_count);
+assertThrows(() => Debug.setBreakPoint(g));
+g();
+assertEquals(2, break_point_hit_count);
+Debug.clearBreakPoint(bp1);
+g();
+assertEquals(2, break_point_hit_count);
+
+// Finally test with many break points.
+test_count = 10;
+break_point_hit_count = 0;
+for (var i = 0; i < test_count; i++) {
+  if (i == 0) {
+    Debug.setBreakPoint(h);
+  } else {
+    assertThrows(() => Debug.setBreakPoint(h));
+  }
+  h();
+}
+assertEquals(test_count, break_point_hit_count);
diff --git a/src/v8/test/debugger/debug/debug-multiple-var-decl.js b/src/v8/test/debugger/debug/debug-multiple-var-decl.js
new file mode 100644
index 0000000..2406546
--- /dev/null
+++ b/src/v8/test/debugger/debug/debug-multiple-var-decl.js
@@ -0,0 +1,74 @@
+// 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 we break at every assignment in a var-statement with multiple
+// variable declarations.
+
+var exception = null;
+var log = []
+
+function f() {
+  var l1 = 1,    // l
+      l2,        // m
+      l3 = 3;    // n
+  let l4,        // o
+      l5 = 5,    // p
+      l6 = 6;    // q
+  const l7 = 7,  // r
+        l8 = 8,  // s
+        l9 = 9;  // t
+  return 0       // u
+  ;              // v
+}
+
+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(/\/\/ (\w)$/);
+    assertEquals(2, match.length);
+    log.push(match[1] + col);
+    if (match[1] != "v") {
+      exec_state.prepareStep(Debug.StepAction.StepIn);
+    }
+  } catch (e) {
+    exception = e;
+  }
+}
+
+var Debug = debug.Debug;
+Debug.setListener(listener);
+
+debugger;        // a
+var g1 = 1,      // b
+    g2 = 2,      // c
+    g3;          // d
+let g4 = 4,      // e
+    g5,          // f
+    g6 = 6;      // g
+const g7 = 7,    // h
+      g8 = 8,    // i
+      g9 = f();  // j
+
+Debug.setListener(null);
+
+assertNull(exception);
+
+// Note that let declarations, if not explicitly initialized, implicitly
+// initialize to undefined.
+
+var expected = [
+  "a0",               // debugger statement
+  "b9","c9",          // global var
+  "e9","f4","g9",     // global let
+  "h11","i11","j11",  // global const
+  "l11","n11",        // local var
+  "o6","p11","q11",   // local let
+  "r13","s13","t13",  // local const
+  "u2","v3",          // return
+];
+assertEquals(expected, log);
diff --git a/src/v8/test/debugger/debug/debug-negative-break-points.js b/src/v8/test/debugger/debug/debug-negative-break-points.js
new file mode 100644
index 0000000..51ce21b
--- /dev/null
+++ b/src/v8/test/debugger/debug/debug-negative-break-points.js
@@ -0,0 +1,98 @@
+// 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.
+
+
+var Debug = debug.Debug;
+var break_count = 0;
+var exception_count = 0;
+
+function assertCount(expected_breaks, expected_exceptions) {
+  assertEquals(expected_breaks, break_count);
+  assertEquals(expected_exceptions, exception_count);
+}
+
+function listener(event, exec_state, event_data, data) {
+  if (event == Debug.DebugEvent.Break) {
+    break_count++;
+  } else if (event == Debug.DebugEvent.Exception) {
+    exception_count++;
+  }
+}
+
+function f(x) {
+  debugger;
+  return x + 1;
+}
+
+function g(x) {
+  try {
+    throw x;
+  } catch (e) {
+  }
+}
+
+function h(x) {
+  var a = undefined;
+  try {
+    var x = a();
+  } catch (e) {
+  }
+}
+
+Debug.setListener(listener);
+
+assertCount(0, 0);
+f(0);
+assertCount(1, 0);
+g(0);
+assertCount(1, 0);
+
+Debug.setBreakOnException();
+f(0);
+assertCount(2, 0);
+g(0);
+assertCount(2, 1);
+
+Debug.setBreakPoint(f, 1, 0, "x == 1");
+f(1);
+assertCount(3, 1);
+f(2);
+assertCount(3, 1);
+f(1);
+assertCount(4, 1);
+
+assertThrows(() => Debug.setBreakPoint(f, 1, 0, "x > 0"));
+f(1);
+assertCount(5, 2);
+f(0);
+assertCount(5, 2);
+
+Debug.setBreakPoint(g, 2, 0, "1 == 2");
+g(1);
+assertCount(5, 2);
+
+assertThrows(() => Debug.setBreakPoint(g, 2, 0, "x == 1"));
+g(1);
+assertCount(5, 3);
+g(2);
+assertCount(5, 3);
+g(1);
+assertCount(5, 3);
+
+assertThrows(() => Debug.setBreakPoint(g, 2, 0, "x > 0"));
+g(1);
+assertCount(5, 4);
+g(0);
+assertCount(5, 4);
+
+h(0);
+assertCount(5, 5);
+Debug.setBreakPoint(h, 3, 0, "x > 0");
+h(1);
+assertCount(6, 6);
+h(0);
+assertCount(6, 6);
+
+Debug.clearBreakOnException();
+Debug.setListener(null);
diff --git a/src/v8/test/debugger/debug/debug-optimize.js b/src/v8/test/debugger/debug/debug-optimize.js
new file mode 100644
index 0000000..f296816
--- /dev/null
+++ b/src/v8/test/debugger/debug/debug-optimize.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: --opt --no-always-opt
+
+var Debug = debug.Debug;
+
+function f1() {
+  return 1;
+}
+
+function f2() {
+  return 2;
+}
+
+function f3() {
+  return f1();
+}
+
+function f4() {
+  return 4;
+}
+
+
+function optimize(f) {
+  f();
+  f();
+  %OptimizeFunctionOnNextCall(f);
+  f();
+}
+
+optimize(f1);
+optimize(f2);
+optimize(f3);
+
+Debug.setListener(function() {});
+
+assertOptimized(f1);
+assertOptimized(f2);
+assertOptimized(f3);
+
+Debug.setBreakPoint(f1, 1);
+
+// Setting break point deoptimizes f1 and f3 (which inlines f1).
+assertUnoptimized(f1);
+assertOptimized(f2);
+assertUnoptimized(f3);
+
+// We can optimize with break points set.
+optimize(f4);
+assertOptimized(f4);
+
+Debug.setListener(null);
diff --git a/src/v8/test/debugger/debug/debug-print.js b/src/v8/test/debugger/debug/debug-print.js
new file mode 100644
index 0000000..9b054d9
--- /dev/null
+++ b/src/v8/test/debugger/debug/debug-print.js
@@ -0,0 +1,46 @@
+// 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.
+
+
+// Make sure printing different element kinds doesn't crash.
+
+var array;
+var obj = {};
+
+array = [];
+%DebugPrint(array);
+
+// PACKED_SMI_ELEMENTS
+array = [1, 2, 3];
+%DebugPrint(array);
+
+// HOLEY_SMI_ELEMENTS
+array[10] = 100;
+array[11] = 100;
+%DebugPrint(array);
+
+// PACKED_ELEMENTS
+array = [1, obj, obj];
+%DebugPrint(array);
+
+// HOLEY_ELEMENTS
+array[100] = obj;
+array[101] = obj;
+%DebugPrint(array);
+
+// PACKED_DOUBLE_ELEMENTS
+array = [1.1, 2.2, 3.3, 3.3, 3.3, NaN];
+%DebugPrint(array);
+array.push(NaN);
+array.push(NaN);
+%DebugPrint(array);
+
+// HOLEY_DOUBLE_ELEMENTS
+array[100] = 1.2;
+array[101] = 1.2;
+%DebugPrint(array);
+
+// DICTIONARY_ELEMENTS
+%NormalizeElements(array);
+%DebugPrint(array);
diff --git a/src/v8/test/debugger/debug/debug-receiver.js b/src/v8/test/debugger/debug/debug-receiver.js
new file mode 100644
index 0000000..d93c313
--- /dev/null
+++ b/src/v8/test/debugger/debug/debug-receiver.js
@@ -0,0 +1,122 @@
+// 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.
+
+Debug = debug.Debug;
+
+var test_name;
+var listener_delegate;
+var listener_called;
+var exception;
+var expected_receiver;
+var begin_test_count = 0;
+var end_test_count = 0;
+var break_count = 0;
+
+// Debug event listener which delegates. Exceptions have to be
+// explicitly caught here and checked later because exception in the
+// listener are not propagated to the surrounding JavaScript code.
+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) {
+    exception = e;
+  }
+}
+
+// Add the debug event listener.
+Debug.setListener(listener);
+
+
+// Initialize for a new test.
+function BeginTest(name) {
+  test_name = name;
+  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);
+  end_test_count++;
+}
+
+
+// Check that the debugger correctly reflects that the receiver is not
+// converted to object for strict mode functions.
+function Strict() { "use strict"; debugger; }
+function TestStrict(receiver) {
+  expected_receiver = receiver;
+  Strict.call(receiver);
+}
+
+listener_delegate = function(exec_state) {
+  var receiver = exec_state.frame().receiver();
+  assertEquals(expected_receiver, receiver.value())
+}
+
+BeginTest("strict: undefined"); TestStrict(undefined); EndTest();
+BeginTest("strict: null"); TestStrict(null); EndTest();
+BeginTest("strict: 1"); TestStrict(1); EndTest();
+BeginTest("strict: 1.2"); TestStrict(1.2); EndTest();
+BeginTest("strict: 'asdf'"); TestStrict('asdf'); EndTest();
+BeginTest("strict: true"); TestStrict(true); EndTest();
+
+
+// Check that the debugger correctly reflects the object conversion of
+// the receiver for non-strict mode functions.
+function NonStrict() { debugger; }
+function TestNonStrict(receiver) {
+  // null and undefined should be transformed to the global object and
+  // primitives should be wrapped.
+  expected_receiver = (receiver == null) ? this : Object(receiver);
+  NonStrict.call(receiver);
+}
+
+listener_delegate = function(exec_state) {
+  var receiver = exec_state.frame().receiver();
+  assertEquals(expected_receiver, receiver.value());
+}
+
+BeginTest("non-strict: undefined"); TestNonStrict(undefined); EndTest();
+BeginTest("non-strict: null"); TestNonStrict(null); EndTest();
+BeginTest("non-strict: 1"); TestNonStrict(1); EndTest();
+BeginTest("non-strict: 1.2"); TestNonStrict(1.2); EndTest();
+BeginTest("non-strict: 'asdf'"); TestNonStrict('asdf'); EndTest();
+BeginTest("non-strict: true"); TestNonStrict(true); EndTest();
+
+
+assertEquals(begin_test_count, break_count,
+             'one or more tests did not enter the debugger');
+assertEquals(begin_test_count, end_test_count,
+             'one or more tests did not have its result checked');
diff --git a/src/v8/test/debugger/debug/debug-return-value.js b/src/v8/test/debugger/debug/debug-return-value.js
new file mode 100644
index 0000000..77717ce
--- /dev/null
+++ b/src/v8/test/debugger/debug/debug-return-value.js
@@ -0,0 +1,116 @@
+// Copyright 2010 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.
+
+Debug = debug.Debug
+
+listener_complete = false;
+exception = false;
+break_count = 0;
+expected_return_value = 0;
+expected_source_position = [];
+debugger_source_position = 0;
+
+// Listener which expects to do four steps to reach returning from the function.
+function listener(event, exec_state, event_data, data) {
+  try {
+    if (event == Debug.DebugEvent.Break)
+    {
+      break_count++;
+      if (break_count < 4) {
+        switch (break_count) {
+          case 1:
+            // Collect the position of the debugger statement.
+            debugger_source_position = exec_state.frame(0).sourcePosition();
+            break;
+          case 2:
+            // Position now at the if statement.
+            assertEquals(expected_source_position.shift() + debugger_source_position,
+                         exec_state.frame(0).sourcePosition());
+            break;
+          case 3:
+            // Position now at either of the returns.
+            assertEquals(expected_source_position.shift() + debugger_source_position,
+                         exec_state.frame(0).sourcePosition());
+            break;
+          default:
+            fail("Unexpected");
+        }
+        exec_state.prepareStep(Debug.StepAction.StepIn);
+      } else {
+        // Position at the end of the function.
+        assertEquals(expected_source_position.shift() + debugger_source_position,
+                     exec_state.frame(0).sourcePosition());
+        // Just about to return from the function.
+        assertEquals(expected_return_value,
+                     exec_state.frame(0).returnValue().value());
+
+        listener_complete = true;
+      }
+    }
+  } catch (e) {
+    exception = e
+    print(e + e.stack)
+  };
+};
+
+// Add the debug event listener.
+Debug.setListener(listener);
+
+// Four steps from the debugger statement in this function will position us at
+// the function return.
+//             0         1         2         3         4         5
+//             0123456789012345678901234567890123456789012345678901
+
+function f(x) {debugger; if (x) { return 1; } else { return 2; } };
+
+// Call f expecting different return values.
+break_count = 0;
+expected_return_value = 2;
+expected_source_position = [10, 38, 47];
+listener_complete = false;
+f();
+assertFalse(exception, "exception in listener")
+assertTrue(listener_complete);
+assertEquals(4, break_count);
+
+break_count = 0;
+expected_return_value = 1;
+expected_source_position = [10, 19, 28];
+listener_complete = false;
+f(true);
+assertFalse(exception, "exception in listener")
+assertTrue(listener_complete);
+assertEquals(4, break_count);
+
+break_count = 0;
+expected_return_value = 2;
+expected_source_position = [10, 38, 47];
+listener_complete = false;
+f(false);
+assertFalse(exception, "exception in listener")
+assertTrue(listener_complete);
+assertEquals(4, break_count);
diff --git a/src/v8/test/debugger/debug/debug-scopes-suspended-generators.js b/src/v8/test/debugger/debug/debug-scopes-suspended-generators.js
new file mode 100644
index 0000000..2d9d253
--- /dev/null
+++ b/src/v8/test/debugger/debug/debug-scopes-suspended-generators.js
@@ -0,0 +1,458 @@
+// 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.
+
+// The functions used for testing backtraces. They are at the top to make the
+// testing of source line/column easier.
+
+var Debug = debug.Debug;
+
+var test_name;
+var exception;
+var begin_test_count = 0;
+var end_test_count = 0;
+
+// Initialize for a new test.
+function BeginTest(name) {
+  test_name = name;
+  exception = null;
+  begin_test_count++;
+}
+
+// Check result of a test.
+function EndTest() {
+  assertNull(exception, test_name + " / " + exception);
+  end_test_count++;
+}
+
+// Check that two scope are the same.
+function assertScopeMirrorEquals(scope1, scope2) {
+  assertEquals(scope1.scopeType(), scope2.scopeType());
+  assertEquals(scope1.scopeIndex(), scope2.scopeIndex());
+  assertPropertiesEqual(scope1.scopeObject().value(),
+                        scope2.scopeObject().value());
+}
+
+// Check that the scope chain contains the expected types of scopes.
+function CheckScopeChain(scopes, gen) {
+  var all_scopes = Debug.generatorScopes(gen);
+  assertEquals(scopes.length, Debug.generatorScopeCount(gen));
+  assertEquals(scopes.length, all_scopes.length,
+               "FrameMirror.allScopes length");
+  for (var i = 0; i < scopes.length; i++) {
+    var scope = all_scopes[i];
+    assertEquals(scopes[i], scope.scopeType(),
+                 `Scope ${i} has unexpected type`);
+
+    // 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.
+      assertPropertiesEqual(this, scope.scopeObject().value());
+    }
+  }
+}
+
+// Check that the content of the scope is as expected. For functions just check
+// that there is a function.
+function CheckScopeContent(content, number, gen) {
+  var scope = Debug.generatorScope(gen, number);
+  var count = 0;
+  for (var p in content) {
+    var property_mirror = scope.scopeObject().property(p);
+    if (content[p] === undefined) {
+      assertTrue(property_mirror === undefined);
+    } else {
+      assertFalse(property_mirror === undefined,
+                  'property ' + p + ' not found in scope');
+    }
+    if (typeof(content[p]) === 'function') {
+      assertTrue(typeof property_mirror == "function");
+    } else {
+      assertEquals(content[p], property_mirror,
+                   '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') !== undefined) {
+    scope_size--;
+  }
+  // Ditto for 'this'.
+  if (scope.scopeObject().property('this') !== undefined) {
+    scope_size--;
+  }
+  // Temporary variables introduced by the parser have not been materialized.
+  assertTrue(scope.scopeObject().property('') === undefined);
+
+  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);
+}
+
+// Simple empty closure scope.
+
+function *gen1() {
+  yield 1;
+  return 2;
+}
+
+var g = gen1();
+CheckScopeChain([debug.ScopeType.Local,
+                 debug.ScopeType.Script,
+                 debug.ScopeType.Global], g);
+CheckScopeContent({}, 0, g);
+
+// Closure scope with a parameter.
+
+function *gen2(a) {
+  yield a;
+  return 2;
+}
+
+g = gen2(42);
+CheckScopeChain([debug.ScopeType.Local,
+                 debug.ScopeType.Script,
+                 debug.ScopeType.Global], g);
+CheckScopeContent({a: 42}, 0, g);
+
+// Closure scope with a parameter.
+
+function *gen3(a) {
+  var b = 1
+  yield a;
+  return b;
+}
+
+g = gen3(0);
+CheckScopeChain([debug.ScopeType.Local,
+                 debug.ScopeType.Script,
+                 debug.ScopeType.Global], g);
+CheckScopeContent({a: 0, b: undefined}, 0, g);
+
+g.next();  // Create b.
+CheckScopeContent({a: 0, b: 1}, 0, g);
+
+// Closure scope with a parameter.
+
+function *gen4(a, b) {
+  var x = 2;
+  yield a;
+  var y = 3;
+  yield a;
+  return b;
+}
+
+g = gen4(0, 1);
+CheckScopeChain([debug.ScopeType.Local,
+                 debug.ScopeType.Script,
+                 debug.ScopeType.Global], g);
+CheckScopeContent({a: 0, b: 1, x: undefined, y: undefined}, 0, g);
+
+g.next();  // Create x.
+CheckScopeContent({a: 0, b: 1, x: 2, y: undefined}, 0, g);
+
+g.next();  // Create y.
+CheckScopeContent({a: 0, b: 1, x: 2, y: 3}, 0, g);
+
+// Closure introducing local variable using eval.
+
+function *gen5(a) {
+  eval('var b = 2');
+  yield a;
+  return b;
+}
+
+g = gen5(1);
+g.next();
+CheckScopeChain([debug.ScopeType.Local,
+                 debug.ScopeType.Script,
+                 debug.ScopeType.Global], g);
+CheckScopeContent({a: 1, b: 2}, 0, g);
+
+// Single empty with block.
+
+function *gen6() {
+  with({}) {
+    yield 1;
+  }
+  yield 2;
+  return 3;
+}
+
+g = gen6();
+g.next();
+CheckScopeChain([debug.ScopeType.With,
+                 debug.ScopeType.Local,
+                 debug.ScopeType.Script,
+                 debug.ScopeType.Global], g);
+CheckScopeContent({}, 0, g);
+
+g.next();
+CheckScopeChain([debug.ScopeType.Local,
+                 debug.ScopeType.Script,
+                 debug.ScopeType.Global], g);
+
+// Nested empty with blocks.
+
+function *gen7() {
+  with({}) {
+    with({}) {
+      yield 1;
+    }
+    yield 2;
+  }
+  return 3;
+}
+
+g = gen7();
+g.next();
+CheckScopeChain([debug.ScopeType.With,
+                 debug.ScopeType.With,
+                 debug.ScopeType.Local,
+                 debug.ScopeType.Script,
+                 debug.ScopeType.Global], g);
+CheckScopeContent({}, 0, g);
+
+// Nested with blocks using in-place object literals.
+
+function *gen8() {
+  with({a: 1,b: 2}) {
+    with({a: 2,b: 1}) {
+      yield a;
+    }
+    yield a;
+  }
+  return 3;
+}
+
+g = gen8();
+g.next();
+CheckScopeChain([debug.ScopeType.With,
+                 debug.ScopeType.With,
+                 debug.ScopeType.Local,
+                 debug.ScopeType.Script,
+                 debug.ScopeType.Global], g);
+CheckScopeContent({a: 2, b: 1}, 0, g);
+
+g.next();
+CheckScopeContent({a: 1, b: 2}, 0, g);
+
+// Catch block.
+
+function *gen9() {
+  try {
+    throw 42;
+  } catch (e) {
+    yield e;
+  }
+  return 3;
+}
+
+g = gen9();
+g.next();
+CheckScopeChain([debug.ScopeType.Catch,
+                 debug.ScopeType.Local,
+                 debug.ScopeType.Script,
+                 debug.ScopeType.Global], g);
+CheckScopeContent({e: 42}, 0, g);
+
+// For statement with block scope.
+
+function *gen10() {
+  for (let i = 0; i < 42; i++) yield i;
+  return 3;
+}
+
+g = gen10();
+g.next();
+CheckScopeChain([debug.ScopeType.Block,
+                 debug.ScopeType.Local,
+                 debug.ScopeType.Script,
+                 debug.ScopeType.Global], g);
+CheckScopeContent({i: 0}, 0, g);
+
+g.next();
+CheckScopeContent({i: 1}, 0, g);
+
+// Nested generators.
+
+var gen12;
+function *gen11() {
+  var b = 2;
+  gen12 = function*() {
+    var a = 1;
+    yield 1;
+    return b;
+  }();
+
+  var a = 0;
+  yield* gen12;
+}
+
+gen11().next();
+g = gen12;
+
+CheckScopeChain([debug.ScopeType.Local,
+                 debug.ScopeType.Closure,
+                 debug.ScopeType.Script,
+                 debug.ScopeType.Global], g);
+CheckScopeContent({a: 1}, 0, g);
+CheckScopeContent({b: 2}, 1, g);
+
+// Set a variable in an empty scope.
+
+function *gen13() {
+  yield 1;
+  return 2;
+}
+
+var g = gen13();
+assertThrows(() => Debug.generatorScope(g, 0).setVariableValue("a", 42));
+CheckScopeContent({}, 0, g);
+
+// Set a variable in a simple scope.
+
+function *gen14() {
+  var a = 0;
+  yield 1;
+  yield a;
+  return 2;
+}
+
+var g = gen14();
+assertEquals(1, g.next().value);
+
+CheckScopeContent({a: 0}, 0, g);
+
+Debug.generatorScope(g, 0).setVariableValue("a", 1);
+CheckScopeContent({a: 1}, 0, g);
+
+assertEquals(1, g.next().value);
+
+// Set a variable in nested with blocks using in-place object literals.
+
+function *gen15() {
+  var c = 3;
+  with({a: 1,b: 2}) {
+    var d = 4;
+    yield a;
+    var e = 5;
+  }
+  yield e;
+  return e;
+}
+
+var g = gen15();
+assertEquals(1, g.next().value);
+
+CheckScopeChain([debug.ScopeType.With,
+                 debug.ScopeType.Local,
+                 debug.ScopeType.Script,
+                 debug.ScopeType.Global], g);
+CheckScopeContent({a: 1, b: 2}, 0, g);
+CheckScopeContent({c: 3, d: 4, e: undefined}, 1, g);
+
+// Variables don't exist in given scope.
+assertThrows(() => Debug.generatorScope(g, 0).setVariableValue("c", 42));
+assertThrows(() => Debug.generatorScope(g, 1).setVariableValue("a", 42));
+
+// Variables in with scope are immutable.
+assertThrows(() => Debug.generatorScope(g, 0).setVariableValue("a", 3));
+assertThrows(() => Debug.generatorScope(g, 0).setVariableValue("b", 3));
+
+Debug.generatorScope(g, 1).setVariableValue("c", 1);
+Debug.generatorScope(g, 1).setVariableValue("e", 42);
+
+CheckScopeContent({a: 1, b: 2}, 0, g);
+CheckScopeContent({c: 1, d: 4, e: 42}, 1, g);
+assertEquals(5, g.next().value);  // Initialized after set.
+
+CheckScopeChain([debug.ScopeType.Local,
+                 debug.ScopeType.Script,
+                 debug.ScopeType.Global], g);
+
+Debug.generatorScope(g, 0).setVariableValue("e", 42);
+
+CheckScopeContent({c: 1, d: 4, e: 42}, 0, g);
+assertEquals(42, g.next().value);
+
+// Set a variable in nested with blocks using in-place object literals plus a
+// nested block scope.
+
+function *gen16() {
+  var c = 3;
+  with({a: 1,b: 2}) {
+    let d = 4;
+    yield a;
+    let e = 5;
+    yield d;
+  }
+  return 3;
+}
+
+var g = gen16();
+g.next();
+
+CheckScopeChain([debug.ScopeType.Block,
+                 debug.ScopeType.With,
+                 debug.ScopeType.Local,
+                 debug.ScopeType.Script,
+                 debug.ScopeType.Global], g);
+CheckScopeContent({d: 4, e: undefined}, 0, g);
+CheckScopeContent({a: 1, b: 2}, 1, g);
+CheckScopeContent({c: 3}, 2, g);
+
+Debug.generatorScope(g, 0).setVariableValue("d", 1);
+CheckScopeContent({d: 1, e: undefined}, 0, g);
+
+assertEquals(1, g.next().value);
+
+// Set variable in catch block.
+
+var yyzyzzyz = 4829;
+let xxxyyxxyx = 42284;
+function *gen17() {
+  try {
+    throw 42;
+  } catch (e) {
+    yield e;
+    yield e;
+  }
+  return 3;
+}
+
+g = gen17();
+g.next();
+
+CheckScopeChain([debug.ScopeType.Catch,
+                 debug.ScopeType.Local,
+                 debug.ScopeType.Script,
+                 debug.ScopeType.Global], g);
+CheckScopeContent({e: 42}, 0, g);
+CheckScopeContent({xxxyyxxyx: 42284,
+                   printProtocolMessages : printProtocolMessages,
+                   activeWrapper : activeWrapper,
+                   DebugWrapper : DebugWrapper
+                  }, 2, g);
+
+Debug.generatorScope(g, 0).setVariableValue("e", 1);
+CheckScopeContent({e: 1}, 0, g);
+
+assertEquals(1, g.next().value);
+
+// Script scope.
+Debug.generatorScope(g, 2).setVariableValue("xxxyyxxyx", 42);
+assertEquals(42, xxxyyxxyx);
+
+// Global scope.
+assertThrows(() => Debug.generatorScope(g, 3).setVariableValue("yyzyzzyz", 42));
+assertEquals(4829, yyzyzzyz);
diff --git a/src/v8/test/debugger/debug/debug-scopes.js b/src/v8/test/debugger/debug/debug-scopes.js
new file mode 100644
index 0000000..6f01cec
--- /dev/null
+++ b/src/v8/test/debugger/debug/debug-scopes.js
@@ -0,0 +1,1287 @@
+// 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
+// The functions used for testing backtraces. They are at the top to make the
+// testing of source line/column easier.
+
+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) {
+    exception = e;
+    print(e, e.stack);
+  }
+}
+
+// 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++;
+}
+
+
+// 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) {
+      // Just check the marker of the global object.
+      assertEquals(scope.scopeObject().value().global_marker, global_marker);
+    }
+  }
+  CheckFastAllScopes(scopes, exec_state);
+}
+
+
+// Check that the scope chain contains the expected names of scopes.
+function CheckScopeChainNames(names, exec_state) {
+  var all_scopes = exec_state.frame().allScopes();
+  assertEquals(names.length, all_scopes.length, "FrameMirror.allScopes length");
+  for (var i = 0; i < names.length; i++) {
+    var scope = exec_state.frame().scope(i);
+    assertEquals(names[i], scope.details().name())
+  }
+}
+
+
+// Check that the scope contains at least minimum_content. For functions just
+// check that there is a function.
+function CheckScopeContent(minimum_content, number, exec_state) {
+  var scope = exec_state.frame().scope(number);
+  var minimum_count = 0;
+  for (var p in minimum_content) {
+    var property_mirror = scope.scopeObject().property(p);
+    assertFalse(property_mirror.isUndefined(),
+                'property ' + p + ' not found in scope');
+    assertEquals(minimum_content[p], property_mirror.value().value(),
+                 'property ' + p + ' has unexpected value');
+    minimum_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--;
+  }
+  // Ditto for 'this'.
+  if (!scope.scopeObject().property('this').isUndefined()) {
+    scope_size--;
+  }
+  // Temporary variables introduced by the parser have not been materialized.
+  assertTrue(scope.scopeObject().property('').isUndefined());
+
+  if (scope_size < minimum_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 >= minimum_count);
+}
+
+// Check that the scopes have positions as expected.
+function CheckScopeChainPositions(positions, exec_state) {
+  var all_scopes = exec_state.frame().allScopes();
+  assertEquals(positions.length, all_scopes.length, "FrameMirror.allScopes length");
+  for (var i = 0; i < positions.length; i++) {
+    var scope = exec_state.frame().scope(i);
+    var position = positions[i];
+    if (!position)
+      continue;
+
+    assertEquals(position.start, scope.details().startPosition())
+    assertEquals(position.end, scope.details().endPosition())
+  }
+}
+
+// Simple empty local scope.
+BeginTest("Local 1");
+
+function local_1() {
+  debugger;
+}
+
+listener_delegate = function(exec_state) {
+  CheckScopeChain([debug.ScopeType.Local,
+                   debug.ScopeType.Script,
+                   debug.ScopeType.Global], exec_state);
+  CheckScopeContent({}, 0, exec_state);
+};
+local_1();
+EndTest();
+
+
+// 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) {
+  var 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) {
+  var x = 3;
+  var 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();
+
+
+// Empty local scope with use of eval.
+BeginTest("Local 5");
+
+function local_5() {
+  eval('');
+  debugger;
+}
+
+listener_delegate = function(exec_state) {
+  CheckScopeChain([debug.ScopeType.Local,
+                   debug.ScopeType.Script,
+                   debug.ScopeType.Global], exec_state);
+  CheckScopeContent({}, 0, exec_state);
+};
+local_5();
+EndTest();
+
+
+// Local introducing local variable using eval.
+BeginTest("Local 6");
+
+function local_6() {
+  eval('var i = 5');
+  debugger;
+}
+
+listener_delegate = function(exec_state) {
+  CheckScopeChain([debug.ScopeType.Local,
+                   debug.ScopeType.Script,
+                   debug.ScopeType.Global], exec_state);
+  CheckScopeContent({i:5}, 0, exec_state);
+};
+local_6();
+EndTest();
+
+
+// Local scope with parameters, local variables and local variable introduced
+// using eval.
+BeginTest("Local 7");
+
+function local_7(a, b) {
+  var x = 3;
+  var y = 4;
+  eval('var i = 5');
+  eval('var j = 6');
+  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,i:5,j:6}, 0, exec_state);
+};
+local_7(1, 2);
+EndTest();
+
+
+// Single empty with block.
+BeginTest("With 1");
+
+function with_1() {
+  with({}) {
+    debugger;
+  }
+}
+
+listener_delegate = function(exec_state) {
+  CheckScopeChain([debug.ScopeType.With,
+                   debug.ScopeType.Local,
+                   debug.ScopeType.Script,
+                   debug.ScopeType.Global], exec_state);
+  CheckScopeContent({}, 0, exec_state);
+};
+with_1();
+EndTest();
+
+
+// Nested empty with blocks.
+BeginTest("With 2");
+
+function with_2() {
+  with({}) {
+    with({}) {
+      debugger;
+    }
+  }
+}
+
+listener_delegate = function(exec_state) {
+  CheckScopeChain([debug.ScopeType.With,
+                   debug.ScopeType.With,
+                   debug.ScopeType.Local,
+                   debug.ScopeType.Script,
+                   debug.ScopeType.Global], exec_state);
+  CheckScopeContent({}, 0, exec_state);
+  CheckScopeContent({}, 1, exec_state);
+};
+with_2();
+EndTest();
+
+
+// With block using an in-place object literal.
+BeginTest("With 3");
+
+function with_3() {
+  with({a:1,b:2}) {
+    debugger;
+  }
+}
+
+listener_delegate = function(exec_state) {
+  CheckScopeChain([debug.ScopeType.With,
+                   debug.ScopeType.Local,
+                   debug.ScopeType.Script,
+                   debug.ScopeType.Global], exec_state);
+  CheckScopeContent({a:1,b:2}, 0, exec_state);
+};
+with_3();
+EndTest();
+
+
+// Nested with blocks using in-place object literals.
+BeginTest("With 4");
+
+function with_4() {
+  with({a:1,b:2}) {
+    with({a:2,b:1}) {
+      debugger;
+    }
+  }
+}
+
+listener_delegate = function(exec_state) {
+  CheckScopeChain([debug.ScopeType.With,
+                   debug.ScopeType.With,
+                   debug.ScopeType.Local,
+                   debug.ScopeType.Script,
+                   debug.ScopeType.Global], exec_state);
+  CheckScopeContent({a:2,b:1}, 0, exec_state);
+  CheckScopeContent({a:1,b:2}, 1, exec_state);
+};
+with_4();
+EndTest();
+
+
+// Nested with blocks using existing object.
+BeginTest("With 5");
+
+var with_object = {c:3,d:4};
+function with_5() {
+  with(with_object) {
+    with(with_object) {
+      debugger;
+    }
+  }
+}
+
+listener_delegate = function(exec_state) {
+  CheckScopeChain([debug.ScopeType.With,
+                   debug.ScopeType.With,
+                   debug.ScopeType.Local,
+                   debug.ScopeType.Script,
+                   debug.ScopeType.Global], exec_state);
+  CheckScopeContent(with_object, 0, exec_state);
+  CheckScopeContent(with_object, 1, exec_state);
+  assertEquals(exec_state.frame().scope(0).scopeObject().value(),
+               exec_state.frame().scope(1).scopeObject().value());
+  assertEquals(with_object, exec_state.frame().scope(1).scopeObject().value());
+};
+with_5();
+EndTest();
+
+
+// Nested with blocks using existing object in global code.
+BeginTest("With 6");
+listener_delegate = function(exec_state) {
+  CheckScopeChain([debug.ScopeType.With,
+                   debug.ScopeType.With,
+                   debug.ScopeType.Script,
+                   debug.ScopeType.Global], exec_state);
+  CheckScopeContent(with_object, 0, exec_state);
+  CheckScopeContent(with_object, 1, exec_state);
+  assertEquals(exec_state.frame().scope(0).scopeObject().value(),
+               exec_state.frame().scope(1).scopeObject().value());
+  assertEquals(with_object, exec_state.frame().scope(1).scopeObject().value());
+};
+
+var with_object = {c:3,d:4};
+with(with_object) {
+  with(with_object) {
+    debugger;
+  }
+}
+EndTest();
+
+
+// With block in function that is marked for optimization while being executed.
+BeginTest("With 7");
+
+function with_7() {
+  with({}) {
+    %OptimizeFunctionOnNextCall(with_7);
+    debugger;
+  }
+}
+
+listener_delegate = function(exec_state) {
+  CheckScopeChain([debug.ScopeType.With,
+                   debug.ScopeType.Local,
+                   debug.ScopeType.Script,
+                   debug.ScopeType.Global], exec_state);
+  CheckScopeContent({}, 0, exec_state);
+};
+with_7();
+EndTest();
+
+
+// Simple closure formed by returning an inner function referering the outer
+// functions arguments.
+BeginTest("Closure 1");
+
+function closure_1(a) {
+  function f() {
+    debugger;
+    return a;
+  };
+  return f;
+}
+
+listener_delegate = function(exec_state) {
+  CheckScopeChain([debug.ScopeType.Local,
+                   debug.ScopeType.Closure,
+                   debug.ScopeType.Script,
+                   debug.ScopeType.Global], exec_state);
+  CheckScopeContent({a:1}, 1, exec_state);
+  CheckScopeChainNames(["f", "closure_1", undefined, undefined], exec_state);
+};
+closure_1(1)();
+EndTest();
+
+
+// Simple closure formed by returning an inner function referering the outer
+// functions arguments. Due to VM optimizations parts of the actual closure is
+// missing from the debugger information.
+BeginTest("Closure 2");
+
+function closure_2(a, b) {
+  var x = a + 2;
+  var y = b + 2;
+  function f() {
+    debugger;
+    return a + x;
+  };
+  return f;
+}
+
+listener_delegate = function(exec_state) {
+  CheckScopeChain([debug.ScopeType.Local,
+                   debug.ScopeType.Closure,
+                   debug.ScopeType.Script,
+                   debug.ScopeType.Global], exec_state);
+  CheckScopeContent({a:1,x:3}, 1, exec_state);
+  CheckScopeChainNames(["f", "closure_2", undefined, undefined], exec_state);
+};
+closure_2(1, 2)();
+EndTest();
+
+
+// Simple closure formed by returning an inner function referering the outer
+// functions arguments. Using all arguments and locals from the outer function
+// in the inner function makes these part of the debugger information on the
+// closure.
+BeginTest("Closure 3");
+
+function closure_3(a, b) {
+  var x = a + 2;
+  var y = b + 2;
+  function f() {
+    debugger;
+    return a + b + x + y;
+  };
+  return f;
+}
+
+listener_delegate = function(exec_state) {
+  CheckScopeChain([debug.ScopeType.Local,
+                   debug.ScopeType.Closure,
+                   debug.ScopeType.Script,
+                   debug.ScopeType.Global], exec_state);
+  CheckScopeContent({a:1,b:2,x:3,y:4}, 1, exec_state);
+  CheckScopeChainNames(["f", "closure_3", undefined, undefined], exec_state);
+};
+closure_3(1, 2)();
+EndTest();
+
+
+
+// Simple closure formed by returning an inner function referering the outer
+// functions arguments. Using all arguments and locals from the outer function
+// in the inner function makes these part of the debugger information on the
+// closure. Use the inner function as well...
+BeginTest("Closure 4");
+
+function closure_4(a, b) {
+  var x = a + 2;
+  var y = b + 2;
+  function f() {
+    debugger;
+    if (f) {
+      return a + b + x + y;
+    }
+  };
+  return f;
+}
+
+listener_delegate = function(exec_state) {
+  CheckScopeChain([debug.ScopeType.Local,
+                   debug.ScopeType.Closure,
+                   debug.ScopeType.Script,
+                   debug.ScopeType.Global], exec_state);
+  CheckScopeContent({a:1,b:2,x:3,y:4,f:undefined}, 1, exec_state);
+  CheckScopeChainNames(["f", "closure_4", undefined, undefined], exec_state);
+};
+closure_4(1, 2)();
+EndTest();
+
+
+
+// Simple closure formed by returning an inner function referering the outer
+// functions arguments. In the presence of eval all arguments and locals
+// (including the inner function itself) from the outer function becomes part of
+// the debugger infformation on the closure.
+BeginTest("Closure 5");
+
+function closure_5(a, b) {
+  var x = 3;
+  var y = 4;
+  function f() {
+    eval('');
+    debugger;
+    return 1;
+  };
+  return f;
+}
+
+listener_delegate = function(exec_state) {
+  CheckScopeChain([debug.ScopeType.Local,
+                   debug.ScopeType.Closure,
+                   debug.ScopeType.Script,
+                   debug.ScopeType.Global], exec_state);
+  CheckScopeContent({a:1,b:2,x:3,y:4,f:undefined}, 1, exec_state);
+  CheckScopeChainNames(["f", "closure_5", undefined, undefined], exec_state)
+};
+closure_5(1, 2)();
+EndTest();
+
+
+// Two closures. Due to optimizations only the parts actually used are provided
+// through the debugger information.
+BeginTest("Closure 6");
+function closure_6(a, b) {
+  function f(a, b) {
+    var x = 3;
+    var y = 4;
+    return function() {
+      var x = 3;
+      var y = 4;
+      debugger;
+      some_global = a;
+      return f;
+    };
+  }
+  return f(a, b);
+}
+
+listener_delegate = function(exec_state) {
+  CheckScopeChain([debug.ScopeType.Local,
+                   debug.ScopeType.Closure,
+                   debug.ScopeType.Closure,
+                   debug.ScopeType.Script,
+                   debug.ScopeType.Global], exec_state);
+  CheckScopeContent({a:1}, 1, exec_state);
+  CheckScopeContent({f:undefined}, 2, exec_state);
+  CheckScopeChainNames([undefined, "f", "closure_6", undefined, undefined],
+                       exec_state);
+};
+closure_6(1, 2)();
+EndTest();
+
+
+// Two closures. In the presence of eval all information is provided as the
+// compiler cannot determine which parts are used.
+BeginTest("Closure 7");
+function closure_7(a, b) {
+  var x = 3;
+  var y = 4;
+  eval('var i = 5');
+  eval('var j = 6');
+  function f(a, b) {
+    var x = 3;
+    var y = 4;
+    eval('var i = 5');
+    eval('var j = 6');
+    return function() {
+      debugger;
+      some_global = a;
+      return f;
+    };
+  }
+  return f(a, b);
+}
+
+listener_delegate = function(exec_state) {
+  CheckScopeChain([debug.ScopeType.Local,
+                   debug.ScopeType.Closure,
+                   debug.ScopeType.Closure,
+                   debug.ScopeType.Script,
+                   debug.ScopeType.Global], exec_state);
+  CheckScopeContent({}, 0, exec_state);
+  CheckScopeContent({a:1,b:2,x:3,y:4,i:5,j:6}, 1, exec_state);
+  CheckScopeContent({a:1,b:2,x:3,y:4,i:5,j:6,f:undefined}, 2, exec_state);
+  CheckScopeChainNames([undefined, "f", "closure_7", undefined, undefined],
+                       exec_state);
+};
+closure_7(1, 2)();
+EndTest();
+
+
+// Closure that may be optimized out.
+BeginTest("Closure 8");
+function closure_8() {
+  (function inner(x) {
+    debugger;
+  })(2);
+}
+
+listener_delegate = function(exec_state) {
+  CheckScopeChain([debug.ScopeType.Local,
+                   debug.ScopeType.Script,
+                   debug.ScopeType.Global], exec_state);
+  CheckScopeContent({x: 2}, 0, exec_state);
+  CheckScopeChainNames(["inner", undefined, undefined], exec_state);
+};
+closure_8();
+EndTest();
+
+
+BeginTest("Closure 9");
+function closure_9() {
+  eval("var y = 1;");
+  eval("var z = 1;");
+  (function inner(x) {
+    y++;
+    z++;
+    debugger;
+  })(2);
+}
+
+listener_delegate = function(exec_state) {
+  CheckScopeChain([debug.ScopeType.Local,
+                   debug.ScopeType.Closure,
+                   debug.ScopeType.Script,
+                   debug.ScopeType.Global], exec_state);
+  CheckScopeChainNames(["inner", "closure_9", undefined, undefined],
+                       exec_state);
+};
+closure_9();
+EndTest();
+
+
+BeginTest("Closure passed to optimized Array.prototype.forEach");
+function closure_10(a) {
+  var x = a + 2;
+  function closure_11(b) {
+    debugger;
+    return a + b + x;
+  }
+  [42].forEach(closure_11);
+}
+
+listener_delegate = function(exec_state) {
+  CheckScopeChain([debug.ScopeType.Local,
+                   debug.ScopeType.Closure,
+                   debug.ScopeType.Script,
+                   debug.ScopeType.Global], exec_state);
+  CheckScopeContent({b:42}, 0, exec_state);
+  CheckScopeContent({a:5, x:7}, 1, exec_state);
+  CheckScopeChainNames(
+      ["closure_11", "closure_10", undefined, undefined], exec_state);
+};
+begin_test_count++; closure_10(5); end_test_count++;
+begin_test_count++; closure_10(5); end_test_count++;
+%OptimizeFunctionOnNextCall(closure_10);
+closure_10(5);
+EndTest();
+
+
+// Test a mixture of scopes.
+BeginTest("The full monty");
+function the_full_monty(a, b) {
+  var x = 3;
+  var y = 4;
+  eval('var i = 5');
+  eval('var j = 6');
+  function f(a, b) {
+    var x = 9;
+    var y = 10;
+    eval('var i = 11');
+    eval('var j = 12');
+    with ({j:13}){
+      return function() {
+        var x = 14;
+        with ({a:15}) {
+          with ({b:16}) {
+            debugger;
+            some_global = a;
+            return f;
+          }
+        }
+      };
+    }
+  }
+  return f(a, b);
+}
+
+listener_delegate = 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);
+  CheckScopeChainNames([undefined, undefined, undefined, "f", "f",
+                        "the_full_monty", undefined, undefined], exec_state);
+};
+the_full_monty(1, 2)();
+EndTest();
+
+
+BeginTest("Closure inside With 1");
+function closure_in_with_1() {
+  with({x:1}) {
+    (function inner(x) {
+      debugger;
+    })(2);
+  }
+}
+
+listener_delegate = function(exec_state) {
+  CheckScopeChain([debug.ScopeType.Local,
+                   debug.ScopeType.With,
+                   debug.ScopeType.Script,
+                   debug.ScopeType.Global], exec_state);
+  CheckScopeContent({x: 2}, 0, exec_state);
+  CheckScopeContent({x: 1}, 1, exec_state);
+};
+closure_in_with_1();
+EndTest();
+
+
+BeginTest("Closure inside With 2");
+function closure_in_with_2() {
+  with({x:1}) {
+    (function inner(x) {
+      with({x:3}) {
+        debugger;
+      }
+    })(2);
+  }
+}
+
+listener_delegate = function(exec_state) {
+  CheckScopeChain([debug.ScopeType.With,
+                   debug.ScopeType.Local,
+                   debug.ScopeType.With,
+                   debug.ScopeType.Script,
+                   debug.ScopeType.Global], exec_state);
+  CheckScopeContent({x: 3}, 0, exec_state);
+  CheckScopeContent({x: 2}, 1, exec_state);
+  CheckScopeContent({x: 1}, 2, exec_state);
+  CheckScopeChainNames(["inner", "inner", "closure_in_with_2",
+                        undefined, undefined], exec_state);
+};
+closure_in_with_2();
+EndTest();
+
+
+BeginTest("Closure inside With 3");
+function createClosure(a) {
+   var b = a + 1;
+   return function closure() {
+     var c = b;
+     (function inner(x) {
+       with({x:c}) {
+         debugger;
+       }
+     })(2);
+   };
+}
+
+function closure_in_with_3() {
+  var f = createClosure(0);
+  f();
+}
+
+listener_delegate = function(exec_state) {
+  CheckScopeChain([debug.ScopeType.With,
+                   debug.ScopeType.Local,
+                   debug.ScopeType.Closure,
+                   debug.ScopeType.Closure,
+                   debug.ScopeType.Script,
+                   debug.ScopeType.Global], exec_state);
+  CheckScopeChainNames(["inner", "inner", "closure", "createClosure",
+                        undefined, undefined], exec_state);
+}
+closure_in_with_3();
+EndTest();
+
+
+BeginTest("Closure inside With 4");
+listener_delegate = function(exec_state) {
+  CheckScopeChain([debug.ScopeType.Local,
+                   debug.ScopeType.With,
+                   debug.ScopeType.Script,
+                   debug.ScopeType.Global], exec_state);
+  CheckScopeContent({x: 2}, 0, exec_state);
+  CheckScopeContent({x: 1}, 1, exec_state);
+  CheckScopeChainNames([undefined, undefined, undefined, undefined],
+                       exec_state);
+};
+
+with({x:1}) {
+  (function(x) {
+    debugger;
+  })(2);
+}
+EndTest();
+
+
+// Test global scope.
+BeginTest("Global");
+listener_delegate = function(exec_state) {
+  CheckScopeChain([debug.ScopeType.Script, debug.ScopeType.Global],
+                  exec_state);
+  CheckScopeChainNames([undefined, undefined], exec_state);
+};
+debugger;
+EndTest();
+
+
+BeginTest("Catch block 1");
+function catch_block_1() {
+  try {
+    throw 'Exception';
+  } catch (e) {
+    debugger;
+  }
+};
+
+
+listener_delegate = function(exec_state) {
+  CheckScopeChain([debug.ScopeType.Catch,
+                   debug.ScopeType.Local,
+                   debug.ScopeType.Script,
+                   debug.ScopeType.Global], exec_state);
+  CheckScopeContent({e:'Exception'}, 0, exec_state);
+  CheckScopeChainNames(["catch_block_1", "catch_block_1",
+                        undefined, undefined], exec_state);
+};
+catch_block_1();
+EndTest();
+
+
+BeginTest("Catch block 2");
+function catch_block_2() {
+  try {
+    throw 'Exception';
+  } catch (e) {
+    with({n:10}) {
+      debugger;
+    }
+  }
+};
+
+
+listener_delegate = function(exec_state) {
+  CheckScopeChain([debug.ScopeType.With,
+                   debug.ScopeType.Catch,
+                   debug.ScopeType.Local,
+                   debug.ScopeType.Script,
+                   debug.ScopeType.Global], exec_state);
+  CheckScopeContent({n:10}, 0, exec_state);
+  CheckScopeContent({e:'Exception'}, 1, exec_state);
+  CheckScopeChainNames(["catch_block_2", "catch_block_2", "catch_block_2",
+                        undefined, undefined], exec_state);
+};
+catch_block_2();
+EndTest();
+
+
+BeginTest("Catch block 3");
+function catch_block_3() {
+  // Do eval to dynamically declare a local variable so that the context's
+  // extension slot is initialized with JSContextExtensionObject.
+  eval("var y = 78;");
+  try {
+    throw 'Exception';
+  } catch (e) {
+    debugger;
+  }
+};
+
+
+listener_delegate = function(exec_state) {
+  CheckScopeChain([debug.ScopeType.Catch,
+                   debug.ScopeType.Local,
+                   debug.ScopeType.Script,
+                   debug.ScopeType.Global], exec_state);
+  CheckScopeContent({e:'Exception'}, 0, exec_state);
+  CheckScopeContent({y:78}, 1, exec_state);
+  CheckScopeChainNames(["catch_block_3", "catch_block_3",
+                        undefined, undefined], exec_state);
+};
+catch_block_3();
+EndTest();
+
+
+BeginTest("Catch block 4");
+function catch_block_4() {
+  // Do eval to dynamically declare a local variable so that the context's
+  // extension slot is initialized with JSContextExtensionObject.
+  eval("var y = 98;");
+  try {
+    throw 'Exception';
+  } catch (e) {
+    with({n:10}) {
+      debugger;
+    }
+  }
+};
+
+listener_delegate = function(exec_state) {
+  CheckScopeChain([debug.ScopeType.With,
+                   debug.ScopeType.Catch,
+                   debug.ScopeType.Local,
+                   debug.ScopeType.Script,
+                   debug.ScopeType.Global], exec_state);
+  CheckScopeContent({n:10}, 0, exec_state);
+  CheckScopeContent({e:'Exception'}, 1, exec_state);
+  CheckScopeContent({y:98}, 2, exec_state);
+  CheckScopeChainNames(["catch_block_4", "catch_block_4", "catch_block_4",
+                        undefined, undefined], exec_state);
+};
+catch_block_4();
+EndTest();
+
+
+// Test catch in global scope.
+BeginTest("Catch block 5");
+listener_delegate = function(exec_state) {
+  CheckScopeChain([debug.ScopeType.Catch,
+                   debug.ScopeType.Script,
+                   debug.ScopeType.Global], exec_state);
+  CheckScopeContent({e:'Exception'}, 0, exec_state);
+  CheckScopeChainNames([undefined, undefined, undefined], exec_state);
+};
+
+try {
+  throw 'Exception';
+} catch (e) {
+  debugger;
+}
+
+EndTest();
+
+
+// Closure inside catch in global code.
+BeginTest("Catch block 6");
+listener_delegate = function(exec_state) {
+  CheckScopeChain([debug.ScopeType.Local,
+                   debug.ScopeType.Catch,
+                   debug.ScopeType.Script,
+                   debug.ScopeType.Global], exec_state);
+  CheckScopeContent({x: 2}, 0, exec_state);
+  CheckScopeContent({e:'Exception'}, 1, exec_state);
+  CheckScopeChainNames([undefined, undefined, undefined, undefined],
+                       exec_state);
+};
+
+try {
+  throw 'Exception';
+} catch (e) {
+  (function(x) {
+    debugger;
+  })(2);
+}
+EndTest();
+
+
+// Catch block in function that is marked for optimization while being executed.
+BeginTest("Catch block 7");
+function catch_block_7() {
+  %OptimizeFunctionOnNextCall(catch_block_7);
+  try {
+    throw 'Exception';
+  } catch (e) {
+    debugger;
+  }
+};
+
+
+listener_delegate = function(exec_state) {
+  CheckScopeChain([debug.ScopeType.Catch,
+                   debug.ScopeType.Local,
+                   debug.ScopeType.Script,
+                   debug.ScopeType.Global], exec_state);
+  CheckScopeContent({e:'Exception'}, 0, exec_state);
+  CheckScopeChainNames(["catch_block_7", "catch_block_7",
+                        undefined, undefined], exec_state);
+};
+catch_block_7();
+EndTest();
+
+
+BeginTest("Classes and methods 1");
+
+listener_delegate = function(exec_state) {
+  "use strict"
+  CheckScopeChain([debug.ScopeType.Local,
+                   debug.ScopeType.Script,
+                   debug.ScopeType.Global], exec_state);
+  CheckScopeContent({}, 1, exec_state);
+  CheckScopeChainNames(["m", undefined, undefined], exec_state);
+};
+
+(function() {
+  "use strict";
+  class C1 {
+    m() {
+      debugger;
+    }
+  }
+  new C1().m();
+})();
+
+EndTest();
+
+BeginTest("Scope positions");
+var code1 = "function f() {        \n" +
+            "  var a = 1;          \n" +
+            "  function b() {      \n" +
+            "    debugger;         \n" +
+            "    return a + 1;     \n" +
+            "  }                   \n" +
+            "  b();                \n" +
+            "}                     \n" +
+            "f();                  \n";
+
+listener_delegate = function(exec_state) {
+  CheckScopeChainPositions(
+      [{start: 58, end: 118}, {start: 10, end: 162}, {}, {}], exec_state);
+}
+eval(code1);
+EndTest();
+
+
+function catch_block_2() {
+  try {
+    throw 'Exception';
+  } catch (e) {
+    with({n:10}) {
+      debugger;
+    }
+  }
+};
+
+BeginTest("Scope positions in catch and 'with' statement");
+var code2 = "function catch_block() {   \n" +
+            "  try {                    \n" +
+            "    throw 'Exception';     \n" +
+            "  } catch (e) {            \n" +
+            "    with({n : 10}) {       \n" +
+            "      debugger;            \n" +
+            "    }                      \n" +
+            "  }                        \n" +
+            "}                          \n" +
+            "catch_block();             \n";
+
+listener_delegate = function(exec_state) {
+  CheckScopeChainPositions([{start: 131, end: 173},
+                            {start: 94, end: 199},
+                            {start: 20, end: 225},
+                            {}, {}], exec_state);
+}
+eval(code2);
+EndTest();
+
+BeginTest("Scope positions in for statement");
+var code3 = "function for_statement() {         \n" +
+            "  for (let i = 0; i < 1; i++) {    \n" +
+            "    debugger;                      \n" +
+            "  }                                \n" +
+            "}                                  \n" +
+            "for_statement();                   \n";
+
+listener_delegate = function(exec_state) {
+  CheckScopeChain([debug.ScopeType.Block,
+                   debug.ScopeType.Local,
+                   debug.ScopeType.Script,
+                   debug.ScopeType.Global], exec_state);
+  CheckScopeChainPositions(
+      [{start: 42, end: 111}, {start: 22, end: 145}, {}, {}], exec_state);
+}
+eval(code3);
+EndTest();
+
+BeginTest("Scope positions in for statement with lexical block");
+var code4 = "function for_statement() {         \n" +
+            "  for (let i = 0; i < 1; i++) {    \n" +
+            "    let j;                         \n" +
+            "    debugger;                      \n" +
+            "  }                                \n" +
+            "}                                  \n" +
+            "for_statement();                   \n";
+
+listener_delegate = function(exec_state) {
+  CheckScopeChain([debug.ScopeType.Block,
+                   debug.ScopeType.Block,
+                   debug.ScopeType.Local,
+                   debug.ScopeType.Script,
+                   debug.ScopeType.Global], exec_state);
+  CheckScopeChainPositions([{start: 66, end: 147},
+                            {start: 42, end: 147},
+                            {start: 22, end: 181},
+                            {}, {}], exec_state);
+}
+eval(code4);
+EndTest();
+
+BeginTest("Scope positions in lexical for each statement");
+var code5 = "function for_each_statement() {    \n" +
+            "  for (let i of [0]) {             \n" +
+            "    debugger;                      \n" +
+            "  }                                \n" +
+            "}                                  \n" +
+            "for_each_statement();              \n";
+
+listener_delegate = function(exec_state) {
+  CheckScopeChain([debug.ScopeType.Block,
+                   debug.ScopeType.Local,
+                   debug.ScopeType.Script,
+                   debug.ScopeType.Global], exec_state);
+  CheckScopeChainPositions(
+      [{start: 55, end: 111}, {start: 27, end: 145}, {}, {}], exec_state);
+}
+eval(code5);
+EndTest();
+
+BeginTest("Scope positions in lexical for each statement with lexical block");
+var code6 = "function for_each_statement() {    \n" +
+            "  for (let i of [0]) {             \n" +
+            "    let j;                         \n" +
+            "    debugger;                      \n" +
+            "  }                                \n" +
+            "}                                  \n" +
+            "for_each_statement();              \n";
+
+listener_delegate = function(exec_state) {
+  CheckScopeChain([debug.ScopeType.Block,
+                   debug.ScopeType.Block,
+                   debug.ScopeType.Local,
+                   debug.ScopeType.Script,
+                   debug.ScopeType.Global], exec_state);
+  CheckScopeChainPositions([{start: 57, end: 147},
+                            {start: 55, end: 147},
+                            {start: 27, end: 181},
+                            {}, {}], exec_state);
+}
+eval(code6);
+EndTest();
+
+BeginTest("Scope positions in non-lexical for each statement");
+var code7 = "function for_each_statement() {    \n" +
+            "  var i;                           \n" +
+            "  for (i of [0]) {                 \n" +
+            "    debugger;                      \n" +
+            "  }                                \n" +
+            "}                                  \n" +
+            "for_each_statement();              \n";
+
+listener_delegate = function(exec_state) {
+  CheckScopeChain([debug.ScopeType.Local,
+                   debug.ScopeType.Script,
+                   debug.ScopeType.Global], exec_state);
+  CheckScopeChainPositions([{start: 27, end: 181}, {}, {}], exec_state);
+}
+eval(code7);
+EndTest();
+
+BeginTest(
+    "Scope positions in non-lexical for each statement with lexical block");
+var code8 = "function for_each_statement() {    \n" +
+            "  var i;                           \n" +
+            "  for (i of [0]) {                 \n" +
+            "    let j;                         \n" +
+            "    debugger;                      \n" +
+            "  }                                \n" +
+            "}                                  \n" +
+            "for_each_statement();              \n";
+
+listener_delegate = function(exec_state) {
+  CheckScopeChain([debug.ScopeType.Block,
+                   debug.ScopeType.Local,
+                   debug.ScopeType.Script,
+                   debug.ScopeType.Global], exec_state);
+  CheckScopeChainPositions(
+      [{start: 89, end: 183}, {start: 27, end: 217}, {}, {}], exec_state);
+}
+eval(code8);
+EndTest();
+
+assertEquals(begin_test_count, break_count,
+             'one or more tests did not enter the debugger');
+assertEquals(begin_test_count, end_test_count,
+             'one or more tests did not have its result checked');
diff --git a/src/v8/test/debugger/debug/debug-script.js b/src/v8/test/debugger/debug/debug-script.js
new file mode 100644
index 0000000..98aa555
--- /dev/null
+++ b/src/v8/test/debugger/debug/debug-script.js
@@ -0,0 +1,111 @@
+// Copyright 2008 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: --expose-gc --send-idle-notification
+// Flags: --expose-natives-as natives
+// Flags: --noharmony-shipping
+// Flags: --nostress-opt
+
+// --nostress-opt is specified because in stress mode the compilation cache
+// may hold on to old copies of scripts (see bug 1641).
+
+// Note: this test checks that that the number of scripts reported as native
+// by Debug.scripts() is the same as a number of core native scripts.
+// Native scripts that are added by --harmony-shipping are classified
+// as 'experimental', but are still returned by Debug.scripts(), so
+// we disable harmony-shipping for this test
+
+Debug = debug.Debug;
+Debug.setListener(function(){});
+
+Date();
+RegExp();
+
+// Count script types.
+var named_native_count = 0;
+var named_native_names = {};
+var extension_count = 0;
+var normal_count = 0;
+var inspector_count = 0;
+var scripts = Debug.scripts();
+for (i = 0; i < scripts.length; i++) {
+  if (scripts[i].type == Debug.ScriptType.Native) {
+    if (scripts[i].name) {
+      // TODO(1641): Remove check for equally named native scripts once the
+      // underlying issue is fixed.
+      if (!named_native_names[scripts[i].name]) {
+        named_native_names[scripts[i].name] = true;
+        named_native_count++;
+      }
+    }
+  } else if (scripts[i].type == Debug.ScriptType.Extension) {
+    extension_count++;
+  } else if (scripts[i].type == Debug.ScriptType.Normal) {
+    normal_count++;
+  } else if (scripts[i].type == Debug.ScriptType.Inspector) {
+    inspector_count++;
+  } else {
+    assertUnreachable('Unexpected type ' + scripts[i].type);
+  }
+}
+
+// This has to be updated if the number of native scripts change.
+assertEquals(%NativeScriptsCount(), named_native_count);
+// The 'gc' extension and one or two extras scripts are loaded.
+assertTrue(extension_count == 2 || extension_count == 3);
+// This script, test-api.js and mjsunit.js has been loaded.  If using d8, d8
+// loads a normal script during startup too.
+assertTrue(normal_count == 3 || normal_count == 4);
+assertTrue(inspector_count == 0);
+
+// Test a builtins script.
+var array_script = Debug.findScript('native array.js');
+assertEquals('native array.js', array_script.name);
+assertEquals(Debug.ScriptType.Native, array_script.type);
+
+// Test a debugger script.
+var debug_delay_script = Debug.findScript('native debug.js');
+assertEquals('native debug.js', debug_delay_script.name);
+assertEquals(Debug.ScriptType.Native, debug_delay_script.type);
+
+// Test an extension script.
+var extension_gc_script = Debug.findScript('v8/gc');
+if (extension_gc_script) {
+  assertEquals('v8/gc', extension_gc_script.name);
+  assertEquals(Debug.ScriptType.Extension, extension_gc_script.type);
+}
+
+// Test a normal script.
+var debug_script = Debug.findScript(/debug-script.js/);
+assertTrue(/debug-script.js/.test(debug_script.name));
+assertEquals(Debug.ScriptType.Normal, debug_script.type);
+
+// Check a nonexistent script.
+var dummy_script = Debug.findScript('dummy.js');
+assertTrue(typeof dummy_script == 'undefined');
+
+Debug.setListener(null);
diff --git a/src/v8/test/debugger/debug/debug-set-variable-value.js b/src/v8/test/debugger/debug/debug-set-variable-value.js
new file mode 100644
index 0000000..602588a
--- /dev/null
+++ b/src/v8/test/debugger/debug/debug-set-variable-value.js
@@ -0,0 +1,287 @@
+// 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.
+
+// Flags: --noalways-opt
+
+// Flags: --no-always-opt
+
+var Debug = debug.Debug;
+
+// Accepts a function/closure 'fun' that must have a debugger statement inside.
+// A variable 'variable_name' must be initialized before debugger statement
+// and returned after the statement. The test will alter variable value when
+// on debugger statement and check that returned value reflects the change.
+function RunPauseTest(scope_number, expected_old_result, variable_name,
+    new_value, expected_new_result, fun) {
+  var actual_old_result = fun();
+  assertEquals(expected_old_result, actual_old_result);
+
+  var listener_delegate;
+  var listener_called = false;
+  var exception = null;
+
+  function listener_delegate(exec_state) {
+    var scope = exec_state.frame(0).scope(scope_number);
+    scope.setVariableValue(variable_name, new_value);
+  }
+
+  function listener(event, exec_state, event_data, data) {
+    try {
+      if (event == Debug.DebugEvent.Break) {
+        listener_called = true;
+        listener_delegate(exec_state);
+      }
+    } catch (e) {
+      exception = e;
+    }
+  }
+
+  // Add the debug event listener.
+  Debug.setListener(listener);
+
+  var actual_new_result;
+  try {
+    actual_new_result = fun();
+  } finally {
+    Debug.setListener(null);
+  }
+
+  if (exception != null) {
+   assertUnreachable("Exception in listener\n" + exception.stack);
+  }
+  assertTrue(listener_called);
+
+  assertEquals(expected_new_result, actual_new_result);
+}
+
+
+function ClosureTestCase(scope_index, old_result, variable_name, new_value,
+    new_result, success_expected, factory) {
+  this.scope_index_ = scope_index;
+  this.old_result_ = old_result;
+  this.variable_name_ = variable_name;
+  this.new_value_ = new_value;
+  this.new_result_ = new_result;
+  this.success_expected_ = success_expected;
+  this.factory_ = factory;
+}
+
+ClosureTestCase.prototype.run_pause_test = function() {
+  var th = this;
+  var fun = this.factory_(true);
+  this.run_and_catch_(function() {
+    RunPauseTest(th.scope_index_ + 1, th.old_result_, th.variable_name_,
+        th.new_value_, th.new_result_, fun);
+  });
+}
+
+ClosureTestCase.prototype.run_and_catch_ = function(runnable) {
+  if (this.success_expected_) {
+    runnable();
+  } else {
+    assertThrows(runnable);
+  }
+}
+
+
+// Test scopes visible from closures.
+
+var closure_test_cases = [
+  new ClosureTestCase(0, 'cat', 'v1', 5, 5, true,
+      function Factory(debug_stop) {
+    var v1 = 'cat';
+    return function() {
+      if (debug_stop) debugger;
+      return v1;
+    }
+  }),
+
+  new ClosureTestCase(0, 4, 't', 7, 9, true, function Factory(debug_stop) {
+    var t = 2;
+    var r = eval("t");
+    return function() {
+      if (debug_stop) debugger;
+      return r + t;
+    }
+  }),
+
+  new ClosureTestCase(0, 6, 't', 10, 13, true, function Factory(debug_stop) {
+    var t = 2;
+    var r = eval("t = 3");
+    return function() {
+      if (debug_stop) debugger;
+      return r + t;
+    }
+  }),
+
+  new ClosureTestCase(0, 17, 's', 'Bird', 'Bird', true,
+      function Factory(debug_stop) {
+    eval("var s = 17");
+    return function() {
+      if (debug_stop) debugger;
+      return s;
+    }
+  }),
+
+  new ClosureTestCase(2, 'capybara', 'foo', 77, 77, true,
+      function Factory(debug_stop) {
+    var foo = "capybara";
+    return (function() {
+      var bar = "fish";
+      try {
+        throw {name: "test exception"};
+      } catch (e) {
+        return function() {
+          if (debug_stop) debugger;
+          bar = "beast";
+          return foo;
+        }
+      }
+    })();
+  }),
+
+  new ClosureTestCase(0, 'AlphaBeta', 'eee', 5, '5Beta', true,
+      function Factory(debug_stop) {
+    var foo = "Beta";
+    return (function() {
+      var bar = "fish";
+      try {
+        throw "Alpha";
+      } catch (eee) {
+        return function() {
+          if (debug_stop) debugger;
+          return eee + foo;
+        }
+      }
+    })();
+  })
+];
+
+for (var i = 0; i < closure_test_cases.length; i++) {
+  closure_test_cases[i].run_pause_test();
+}
+
+
+// Test local scope.
+
+RunPauseTest(0, 'HelloYou', 'u', 'We', 'HelloWe', (function Factory() {
+  return function() {
+    var u = "You";
+    var v = "Hello";
+    debugger;
+    return v + u;
+  }
+})());
+
+RunPauseTest(0, 'Helloworld', 'p', 'GoodBye', 'HelloGoodBye',
+    (function Factory() {
+  function H(p) {
+    var v = "Hello";
+    debugger;
+    return v + p;
+  }
+  return function() {
+    return H("world");
+  }
+})());
+
+RunPauseTest(0, 'mouse', 'v1', 'dog', 'dog', (function Factory() {
+  return function() {
+    var v1 = 'cat';
+    eval("v1 = 'mouse'");
+    debugger;
+    return v1;
+  }
+})());
+
+RunPauseTest(0, 'mouse', 'v1', 'dog', 'dog', (function Factory() {
+  return function() {
+    eval("var v1 = 'mouse'");
+    debugger;
+    return v1;
+  }
+})());
+
+
+// Check that we correctly update local variable that
+// is referenced from an inner closure.
+RunPauseTest(0, 'Blue', 'v', 'Green', 'Green', (function Factory() {
+  return function() {
+    function A() {
+      var v = "Blue";
+      function Inner() {
+        return void v;
+      }
+      debugger;
+      return v;
+    }
+    return A();
+  }
+})());
+
+// Check that we correctly update parameter, that is known to be stored
+// both on stack and in heap.
+RunPauseTest(0, 5, 'p', 2012, 2012, (function Factory() {
+  return function() {
+    function A(p) {
+      function Inner() {
+        return void p;
+      }
+      debugger;
+      return p;
+    }
+    return A(5);
+  }
+})());
+
+
+// Test script-scope variable.
+let abc = 12;
+{
+  let exception;
+  function listener(event, exec_state) {
+    try {
+      if (event == Debug.DebugEvent.Break) {
+        let scope_count = exec_state.frame().scopeCount();
+        let script_scope = exec_state.frame().scope(scope_count - 2);
+        assertEquals(debug.ScopeType.Script, script_scope.scopeType());
+        script_scope.setVariableValue('abc', 42);
+      }
+    } catch(e) { exception = e }
+  }
+
+  Debug.setListener(listener);
+  assertEquals(12, abc);
+  debugger;
+  assertEquals(42, abc);
+
+  if (exception != null) {
+    assertUnreachable("Exception in listener\n" + exception.stack);
+  }
+}
+
+Debug.setListener(null);
diff --git a/src/v8/test/debugger/debug/debug-setbreakpoint.js b/src/v8/test/debugger/debug/debug-setbreakpoint.js
new file mode 100644
index 0000000..bfcab7c
--- /dev/null
+++ b/src/v8/test/debugger/debug/debug-setbreakpoint.js
@@ -0,0 +1,140 @@
+// Copyright 2008 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.
+
+Debug = debug.Debug
+
+// Simple function which stores the last debug event.
+var listenerComplete = false;
+var exception = false;
+var f_script_id = 0;
+var g_script_id = 0;
+var h_script_id = 0;
+var f_line = 0;
+var g_line = 0;
+var h_line = 0;
+
+function listener(event, exec_state, event_data, data) {
+  try {
+    if (event == Debug.DebugEvent.Break) {
+      if (listenerComplete) return;
+
+      Debug.setScriptBreakPointById(f_script_id, f_line);
+      Debug.setScriptBreakPointById(g_script_id, g_line);
+      Debug.setScriptBreakPointById(h_script_id, h_line);
+
+      // Indicate that all was processed.
+      listenerComplete = true;
+    }
+  } catch (e) {
+    exception = e
+    print(e)
+  };
+};
+
+// Add the debug event listener.
+Debug.setListener(listener);
+
+function f() {
+  a=1;
+};
+
+function g() {
+  // Comment.
+  f();
+};
+
+eval('function h(){}');
+eval('function sourceUrlFunc() { a = 2; }\n//# sourceURL=sourceUrlScript');
+
+o = {a:function(){},b:function(){}}
+
+// Check the script ids for the test functions.
+f_script_id = Debug.findScript(f).id;
+g_script_id = Debug.findScript(g).id;
+h_script_id = Debug.findScript(h).id;
+sourceURL_script_id = Debug.findScript(sourceUrlFunc).id;
+
+assertTrue(f_script_id > 0, "invalid script id for f");
+assertTrue(g_script_id > 0, "invalid script id for g");
+assertTrue(h_script_id > 0, "invalid script id for h");
+assertTrue(sourceURL_script_id > 0, "invalid script id for sourceUrlFunc");
+assertEquals(f_script_id, g_script_id);
+
+// Get the source line for the test functions.
+f_line = Debug.findFunctionSourceLocation(f).line;
+g_line = Debug.findFunctionSourceLocation(g).line;
+h_line = Debug.findFunctionSourceLocation(h).line;
+assertTrue(f_line > 0, "invalid line for f");
+assertTrue(g_line > 0, "invalid line for g");
+assertTrue(f_line < g_line);
+assertEquals(h_line, 0, "invalid line for h");
+
+// Set a break point and call to invoke the debug event listener.
+Debug.setBreakPoint(g, 0, 0);
+g();
+
+// Make sure that the debug event listener was invoked.
+assertTrue(listenerComplete, "listener did not run to completion: " + exception);
+
+// Try setting breakpoint by url specified in sourceURL
+
+var breakListenerCalled = false;
+
+function breakListener(event) {
+  if (event == Debug.DebugEvent.Break)
+    breakListenerCalled = true;
+}
+
+Debug.setBreakPoint(sourceUrlFunc);
+
+Debug.setListener(breakListener);
+
+sourceUrlFunc();
+
+assertTrue(breakListenerCalled, "Break listener not called on breakpoint set by sourceURL");
+
+
+// Breakpoint in a script with no statements test case. If breakpoint is set
+// to the script body, its actual position is taken from the nearest statement
+// below or like in this case is reset to the very end of the script.
+// Unless some precautions made, this position becomes out-of-range and
+// we get an exception.
+
+// Gets a script of 'i1' function and sets the breakpoint at line #4 which
+// should be empty.
+function SetBreakpointInI1Script() {
+  var i_script = Debug.findScript(i1);
+  assertTrue(!!i_script, "invalid script for i1");
+  Debug.setScriptBreakPoint(Debug.ScriptBreakPointType.ScriptId,
+                            i_script.id, 4);
+}
+
+// Creates the eval script and tries to set the breakpoint.
+// The tricky part is that the script function must be strongly reachable at the
+// moment. Since there's no way of simply getting the pointer to the function,
+// we run this code while the script function is being activated on stack.
+eval('SetBreakpointInI1Script()\nfunction i1(){}\n\n\n\nfunction i2(){}\n');
diff --git a/src/v8/test/debugger/debug/debug-sourceinfo.js b/src/v8/test/debugger/debug/debug-sourceinfo.js
new file mode 100644
index 0000000..1085dca
--- /dev/null
+++ b/src/v8/test/debugger/debug/debug-sourceinfo.js
@@ -0,0 +1,199 @@
+// Copyright 2008 the V8 project authors. All rights reserved.
+// Redistribution and use in source and binary forms, with or without
+// modification, are permitted provided that the following conditions are
+// met:
+//
+//     * Redistributions of source code must retain the above copyright
+//       notice, this list of conditions and the following disclaimer.
+//     * Redistributions in binary form must reproduce the above
+//       copyright notice, this list of conditions and the following
+//       disclaimer in the documentation and/or other materials provided
+//       with the distribution.
+//     * Neither the name of Google Inc. nor the names of its
+//       contributors may be used to endorse or promote products derived
+//       from this software without specific prior written permission.
+//
+// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+
+function a() { b(); };
+function    b() {
+  c(true);
+};
+  function c(x) {
+    if (x) {
+      return 1;
+    } else {
+      return 1;
+    }
+  };
+function d(x) {
+  x = 1 ;
+  x = 2 ;
+  x = 3 ;
+  x = 4 ;
+  x = 5 ;
+  x = 6 ;
+  x = 7 ;
+  x = 8 ;
+  x = 9 ;
+  x = 10;
+  x = 11;
+  x = 12;
+  x = 13;
+  x = 14;
+  x = 15;
+}
+
+Debug = debug.Debug
+
+// This is the number of comment lines above the first test function.
+var comment_lines = 27;
+
+// This is the last position in the entire file (note: this equals
+// file size of <debug-sourceinfo.js> - 1, since starting at 0).
+var last_position = 8022;
+// This is the last line of entire file (note: starting at 0).
+var last_line = 198;
+// This is the last column of last line (note: starting at 0).
+var last_column = 71;
+
+// This magic number is the length or the first line comment (actually number
+// of characters before 'function a(...'.
+var comment_line_length = 1599;
+var start_a = 9 + comment_line_length;
+var start_b = 35 + comment_line_length;
+var start_c = 66 + comment_line_length;
+var start_d = 151 + comment_line_length;
+
+// The position of the first line of d(), i.e. "x = 1 ;".
+var start_code_d = start_d + 6;
+// The line # of the first line of d() (note: starting at 0).
+var start_line_d = 39;
+var line_length_d = 10;
+var num_lines_d = 15;
+
+assertEquals(start_a, Debug.sourcePosition(a));
+assertEquals(start_b, Debug.sourcePosition(b));
+assertEquals(start_c, Debug.sourcePosition(c));
+assertEquals(start_d, Debug.sourcePosition(d));
+
+var script = Debug.findScript(a);
+assertTrue(script.data === Debug.findScript(b).data);
+assertTrue(script.data === Debug.findScript(c).data);
+assertTrue(script.data === Debug.findScript(d).data);
+assertTrue(script.source === Debug.findScript(b).source);
+assertTrue(script.source === Debug.findScript(c).source);
+assertTrue(script.source === Debug.findScript(d).source);
+
+// Test that when running through source positions the position, line and
+// column progresses as expected.
+var position;
+var line;
+var column;
+for (var p = 0; p < 100; p++) {
+  var location = script.locationFromPosition(p);
+  if (p > 0) {
+    assertEquals(position + 1, location.position);
+    if (line == location.line) {
+      assertEquals(column + 1, location.column);
+    } else {
+      assertEquals(line + 1, location.line);
+      assertEquals(0, location.column);
+    }
+  } else {
+    assertEquals(0, location.position);
+    assertEquals(0, location.line);
+    assertEquals(0, location.column);
+  }
+
+  // Remember the location.
+  position = location.position;
+  line = location.line;
+  column = location.column;
+}
+
+// Every line of d() is the same length.  Verify we can loop through all
+// positions and find the right line # for each.
+var p = start_code_d;
+for (line = 0; line < num_lines_d; line++) {
+  for (column = 0; column < line_length_d; column++) {
+    var location = script.locationFromPosition(p);
+    assertEquals(p, location.position);
+    assertEquals(start_line_d + line, location.line);
+    assertEquals(column, location.column);
+    p++;
+  }
+}
+
+// Test first position.
+assertEquals(0, script.locationFromPosition(0).position);
+assertEquals(0, script.locationFromPosition(0).line);
+assertEquals(0, script.locationFromPosition(0).column);
+
+// Test second position.
+assertEquals(1, script.locationFromPosition(1).position);
+assertEquals(0, script.locationFromPosition(1).line);
+assertEquals(1, script.locationFromPosition(1).column);
+
+// Test first position in function a().
+assertEquals(start_a, script.locationFromPosition(start_a).position);
+assertEquals(0, script.locationFromPosition(start_a).line - comment_lines);
+assertEquals(10, script.locationFromPosition(start_a).column);
+
+// Test first position in function b().
+assertEquals(start_b, script.locationFromPosition(start_b).position);
+assertEquals(1, script.locationFromPosition(start_b).line - comment_lines);
+assertEquals(13, script.locationFromPosition(start_b).column);
+
+// Test first position in function c().
+assertEquals(start_c, script.locationFromPosition(start_c).position);
+assertEquals(4, script.locationFromPosition(start_c).line - comment_lines);
+assertEquals(12, script.locationFromPosition(start_c).column);
+
+// Test first position in function d().
+assertEquals(start_d, script.locationFromPosition(start_d).position);
+assertEquals(11, script.locationFromPosition(start_d).line - comment_lines);
+assertEquals(10, script.locationFromPosition(start_d).column);
+
+// Test the Debug.findSourcePosition which wraps SourceManager.
+assertEquals(0 + start_a, Debug.findFunctionSourceLocation(a, 0, 0).position);
+assertEquals(0 + start_b, Debug.findFunctionSourceLocation(b, 0, 0).position);
+assertEquals(5 + start_b, Debug.findFunctionSourceLocation(b, 1, 0).position);
+assertEquals(7 + start_b, Debug.findFunctionSourceLocation(b, 1, 2).position);
+assertEquals(16 + start_b, Debug.findFunctionSourceLocation(b, 2, 0).position);
+assertEquals(0 + start_c, Debug.findFunctionSourceLocation(c, 0, 0).position);
+assertEquals(6 + start_c, Debug.findFunctionSourceLocation(c, 1, 0).position);
+assertEquals(19 + start_c, Debug.findFunctionSourceLocation(c, 2, 0).position);
+assertEquals(35 + start_c, Debug.findFunctionSourceLocation(c, 3, 0).position);
+assertEquals(48 + start_c, Debug.findFunctionSourceLocation(c, 4, 0).position);
+assertEquals(64 + start_c, Debug.findFunctionSourceLocation(c, 5, 0).position);
+assertEquals(70 + start_c, Debug.findFunctionSourceLocation(c, 6, 0).position);
+assertEquals(0 + start_d, Debug.findFunctionSourceLocation(d, 0, 0).position);
+assertEquals(6 + start_d, Debug.findFunctionSourceLocation(d, 1, 0).position);
+for (i = 1; i <= num_lines_d; i++) {
+  assertEquals(6 + (i * line_length_d) + start_d,
+               Debug.findFunctionSourceLocation(d, (i + 1), 0).position);
+}
+assertEquals(158 + start_d, Debug.findFunctionSourceLocation(d, 17, 0).position);
+
+// Make sure invalid inputs work properly.
+assertEquals(0, script.locationFromPosition(-1).line);
+assertEquals(null, script.locationFromPosition(last_position + 2));
+
+// Test last position.
+assertEquals(last_position, script.locationFromPosition(last_position).position);
+assertEquals(last_line, script.locationFromPosition(last_position).line);
+assertEquals(last_column, script.locationFromPosition(last_position).column);
+assertEquals(last_line + 1,
+             script.locationFromPosition(last_position + 1).line);
+assertEquals(0, script.locationFromPosition(last_position + 1).column);
diff --git a/src/v8/test/debugger/debug/debug-stack-check-position.js b/src/v8/test/debugger/debug/debug-stack-check-position.js
new file mode 100644
index 0000000..5684d2b
--- /dev/null
+++ b/src/v8/test/debugger/debug/debug-stack-check-position.js
@@ -0,0 +1,29 @@
+// 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.
+
+
+var Debug = debug.Debug;
+var exception = null;
+var loop = true;
+
+function listener(event, exec_state, event_data, data) {
+  if (event != Debug.DebugEvent.Break) return;
+  try {
+    assertTrue(exec_state.frame(0).sourceLineText().indexOf("BREAK") > 0);
+  } catch (e) {
+    exception = e;
+  }
+}
+
+function f() {     // BREAK
+  return 1;
+}
+
+Debug.setListener(listener);
+
+%ScheduleBreak();  // Break on function entry.
+f();
+
+Debug.setListener(null);
+assertNull(exception);
diff --git a/src/v8/test/debugger/debug/debug-step-2.js b/src/v8/test/debugger/debug/debug-step-2.js
new file mode 100644
index 0000000..e47816a
--- /dev/null
+++ b/src/v8/test/debugger/debug/debug-step-2.js
@@ -0,0 +1,61 @@
+// Copyright 2016 the V8 project authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+const Debug = new DebugWrapper();
+Debug.enable();
+
+// This test tests that full code compiled without debug break slots
+// is recompiled with debug break slots when debugging is started.
+
+var bp;
+var done = false;
+var step_count = 0;
+
+// Debug event listener which steps until the global variable done is true.
+function listener(event, exec_state, event_data, data) {
+  if (event == Debug.DebugEvent.Break) {
+    if (!done) Debug.stepOver();
+    step_count++;
+  }
+};
+
+// Set the global variables state to prpare the stepping test.
+function prepare_step_test() {
+  done = false;
+  step_count = 0;
+}
+
+// Test function to step through.
+function f() {
+  var i = 1;
+  var j = 2;
+  done = true;
+};
+
+prepare_step_test();
+f();
+
+// Add the debug event listener.
+Debug.setListener(listener);
+
+bp = Debug.setBreakPoint(f, 1);
+
+prepare_step_test();
+f();
+assertEquals(4, step_count);
+Debug.clearBreakPoint(bp);
+
+// Set a breakpoint on the first var statement (line 1).
+bp = Debug.setBreakPoint(f, 1);
+
+// Step through the function ensuring that the var statements are hit as well.
+prepare_step_test();
+f();
+assertEquals(4, step_count);
+
+// Clear the breakpoint and check that no stepping happens.
+Debug.clearBreakPoint(bp);
+prepare_step_test();
+f();
+assertEquals(0, step_count);
diff --git a/src/v8/test/debugger/debug/debug-step-3.js b/src/v8/test/debugger/debug/debug-step-3.js
new file mode 100644
index 0000000..ea0b5d6
--- /dev/null
+++ b/src/v8/test/debugger/debug/debug-step-3.js
@@ -0,0 +1,68 @@
+// 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.
+
+const Debug = new DebugWrapper();
+Debug.enable();
+
+// This test tests that full code compiled without debug break slots
+// is recompiled with debug break slots when debugging is started.
+
+var bp;
+var done = false;
+var step_count = 0;
+var set_bp = false
+
+// Debug event listener which steps until the global variable done is true.
+function listener(event, exec_state, event_data, data) {
+  if (event == Debug.DebugEvent.Break) {
+    if (!done) Debug.stepOver();
+    step_count++;
+  }
+};
+
+// Set the global variables state to prepare the stepping test.
+function prepare_step_test() {
+  done = false;
+  step_count = 0;
+}
+
+// Test function to step through.
+function f() {
+  var a = 0;
+  if (set_bp) { bp = Debug.setBreakPoint(f, 3); }
+  var i = 1;
+  var j = 2;
+  done = true;
+};
+
+prepare_step_test();
+f();
+
+// Add the debug event listener.
+Debug.setListener(listener);
+
+// Make f set a breakpoint with an activation on the stack.
+prepare_step_test();
+set_bp = true;
+f();
+assertEquals(4, step_count);
+Debug.clearBreakPoint(bp);
+
+// Set a breakpoint on the first var statement (line 1).
+set_bp = false;
+bp = Debug.setBreakPoint(f, 3);
+
+// Step through the function ensuring that the var statements are hit as well.
+prepare_step_test();
+f();
+assertEquals(4, step_count);
+
+// Clear the breakpoint and check that no stepping happens.
+Debug.clearBreakPoint(bp);
+prepare_step_test();
+f();
+assertEquals(0, step_count);
+
+// Get rid of the debug event listener.
+Debug.setListener(null);
diff --git a/src/v8/test/debugger/debug/debug-step-4.js b/src/v8/test/debugger/debug/debug-step-4.js
new file mode 100644
index 0000000..95afaca
--- /dev/null
+++ b/src/v8/test/debugger/debug/debug-step-4.js
@@ -0,0 +1,80 @@
+// 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.
+
+const Debug = new DebugWrapper();
+Debug.enable();
+
+// Tests how debugger can step over not necessarily in the top frame.
+
+// Simple 3 functions, that protocol their execution state in global
+// variable state.
+var state;
+
+function f() {
+  var a = 1978;
+  for (state[2] = 0; state[2] < 3; state[2]++) {
+    void String(a);
+  }
+}
+function g() {
+  for (state[1] = 0; state[1] < 3; state[1]++) {
+    f();
+  }
+}
+function h() {
+  state = [-1, -1, -1];
+  for (state[0] = 0; state[0] < 3; state[0]++) {
+    g();
+  }
+}
+
+function TestCase(expected_final_state) {
+  var listener_exception = null;
+  var state_snapshot;
+  var listener_state;
+  var bp;
+
+  function listener(event, exec_state, event_data, data) {
+    const location = exec_state.frames[0].location
+    print("Here (" + event + "/" + listener_state + "): " +
+          location.lineNumber + ":" + location.columnNumber);
+    try {
+      if (event == Debug.DebugEvent.Break) {
+        if (listener_state == 0) {
+          Debug.clearBreakPoint(bp);
+          Debug.stepOver();
+          listener_state = 1;
+        } else if (listener_state == 1) {
+          state_snapshot = String(state);
+          print("State: " + state_snapshot);
+          Debug.setListener(null);
+          listener_state = 2;
+        }
+      }
+    } catch (e) {
+      listener_exception = e;
+    }
+  }
+
+
+  // Add the debug event listener.
+  listener_state = 0;
+  Debug.setListener(listener);
+  bp = Debug.setBreakPoint(f, 1);
+
+  h();
+  Debug.setListener(null);
+  if (listener_exception !== null) {
+    print("Exception caught: " + listener_exception);
+    assertUnreachable();
+  }
+
+  assertEquals(expected_final_state, state_snapshot);
+}
+
+
+// Warm-up -- make sure all is compiled and ready for breakpoint.
+h();
+
+TestCase("0,0,-1");
diff --git a/src/v8/test/debugger/debug/debug-step-end-of-script.js b/src/v8/test/debugger/debug/debug-step-end-of-script.js
new file mode 100644
index 0000000..92a381e
--- /dev/null
+++ b/src/v8/test/debugger/debug/debug-step-end-of-script.js
@@ -0,0 +1,20 @@
+// 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 expected = ["debugger;", "debugger;"];
+
+function listener(event, exec_state, event_data, data) {
+  if (event != Debug.DebugEvent.Break) return;
+  try {
+    assertEquals(expected.shift(), exec_state.frame(0).sourceLineText());
+    exec_state.prepareStep(Debug.StepAction.StepNext);
+  } catch (e) {
+    %AbortJS(e + "\n" + e.stack);
+  }
+}
+
+Debug.setListener(listener);
+debugger;
diff --git a/src/v8/test/debugger/debug/debug-step-into-json.js b/src/v8/test/debugger/debug/debug-step-into-json.js
new file mode 100644
index 0000000..75bfde3
--- /dev/null
+++ b/src/v8/test/debugger/debug/debug-step-into-json.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 toJsonCallback() {
+  return "x"                     // Break 2.
+  ;                              // Break 3.
+}
+var o = {};
+o.toJSON = toJsonCallback;
+
+Debug.setListener(listener);
+debugger;                        // Break 0.
+var result = JSON.stringify(o);  // Break 1.
+Debug.setListener(null);         // Break 4.
+
+assertEquals('"x"', result);
+assertNull(exception);
diff --git a/src/v8/test/debugger/debug/debug-step-into-valueof.js b/src/v8/test/debugger/debug/debug-step-into-valueof.js
new file mode 100644
index 0000000..b70bb2f
--- /dev/null
+++ b/src/v8/test/debugger/debug/debug-step-into-valueof.js
@@ -0,0 +1,35 @@
+// 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 valueOfCallback() {
+  return 2                // Break 2.
+  ;                       // Break 3.
+}
+var o = {};
+o.valueOf = valueOfCallback;
+
+Debug.setListener(listener);
+debugger;                 // Break 0.
+var result = 1 + o;       // Break 1.
+Debug.setListener(null);  // Break 4.
+
+assertEquals(3, result);
+assertNull(exception);
diff --git a/src/v8/test/debugger/debug/debug-step-microtask.js b/src/v8/test/debugger/debug/debug-step-microtask.js
new file mode 100644
index 0000000..258f235
--- /dev/null
+++ b/src/v8/test/debugger/debug/debug-step-microtask.js
@@ -0,0 +1,52 @@
+// Copyright 2017 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) {
+  try {
+    if (event == Debug.DebugEvent.Break) {
+      var line = exec_state.frame(0).sourceLineText();
+      log.push(line);
+      if (!/STOP/.test(line)) {
+        exec_state.prepareStep(Debug.StepAction.StepIn);
+      }
+    }
+  } catch (e) {
+    exception = e;
+  }
+};
+
+Debug.setListener(listener);
+
+Promise.resolve().then(
+function() {
+  print(1);
+}
+).then(
+function() {
+  return 2;
+}
+).then(
+function() {
+  throw new Error();
+}
+).catch(
+function() {
+  print(3);
+}  // STOP
+);
+
+setTimeout(function() {
+  Debug.setListener(null);
+  assertNull(exception);
+  var expectation =
+    ["debugger;","debugger;","  print(1);","}","  return 2;","  return 2;",
+     "  throw new Error();","  print(3);","}  // STOP"];
+  assertEquals(log, expectation);
+});
+
+debugger;
diff --git a/src/v8/test/debugger/debug/debug-step-stub-callfunction.js b/src/v8/test/debugger/debug/debug-step-stub-callfunction.js
new file mode 100644
index 0000000..8c74d4c
--- /dev/null
+++ b/src/v8/test/debugger/debug/debug-step-stub-callfunction.js
@@ -0,0 +1,85 @@
+// Copyright 2008 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.
+
+Debug = debug.Debug
+
+// Simple debug event handler which counts the number of breaks hit and steps.
+var break_break_point_hit_count = 0;
+function listener(event, exec_state, event_data, data) {
+  if (event == Debug.DebugEvent.Break) {
+    break_break_point_hit_count++;
+    // Continue stepping until returned to bottom frame.
+    if (exec_state.frameCount() > 1) {
+      exec_state.prepareStep(Debug.StepAction.StepIn);
+    }
+  }
+};
+
+// Add the debug event listener.
+Debug.setListener(listener);
+
+// Use 'eval' to ensure that the call to print is through CodeStub CallFunction.
+// See Ia32CodeGenerator::VisitCall and Ia32CodeGenerator::CallWithArguments.
+function f() {
+  debugger;
+  eval('');
+  print('Hello, world!');
+};
+
+break_break_point_hit_count = 0;
+f();
+assertEquals(6, break_break_point_hit_count);
+
+// Use an inner function to ensure that the function call is through CodeStub
+// CallFunction see Ia32CodeGenerator::VisitCall and
+// Ia32CodeGenerator::CallWithArguments.
+function g() {
+  function h() {}
+  debugger;
+  h();
+};
+
+break_break_point_hit_count = 0;
+g();
+assertEquals(5, break_break_point_hit_count);
+
+
+// Use an inner function to ensure that the function call is through CodeStub
+// CallFunction.
+function testCallInExpreesion() {
+  function h() {}
+  debugger;
+  var x = 's' + h(10, 20);
+};
+
+break_break_point_hit_count = 0;
+testCallInExpreesion();
+assertEquals(5, break_break_point_hit_count);
+
+
+// Get rid of the debug event listener.
+Debug.setListener(null);
diff --git a/src/v8/test/debugger/debug/debug-step-turbofan.js b/src/v8/test/debugger/debug/debug-step-turbofan.js
new file mode 100644
index 0000000..a40114b
--- /dev/null
+++ b/src/v8/test/debugger/debug/debug-step-turbofan.js
@@ -0,0 +1,57 @@
+// 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: --turbo-filter=g
+
+// Test that Debug::PrepareForBreakPoints can deal with turbofan code (g)
+// on the stack.  Without deoptimization support, we will not be able to
+// replace optimized code for g by unoptimized code with debug break slots.
+// This would cause stepping to fail (V8 issue 3660).
+
+function f(x) {
+  g(x);
+  var a = 0;              // Break 6
+  return a;               // Break 7
+}                         // Break 8
+
+function g(x) {
+  if (x) h();
+  var a = 0;              // Break 2
+  var b = 1;              // Break 3
+  return a + b;           // Break 4
+}                         // Break 5
+
+function h() {
+  debugger;               // Break 0
+}                         // Break 1
+
+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 {
+    exec_state.prepareStep(Debug.StepAction.StepNext);
+    print(exec_state.frame(0).sourceLineText());
+    var match = exec_state.frame(0).sourceLineText().match(/Break (\d)/);
+    assertNotNull(match);
+    assertEquals(break_count++, parseInt(match[1]));
+  } catch (e) {
+    print(e + e.stack);
+    exception = e;
+  }
+}
+
+f(0);
+f(0);
+%OptimizeFunctionOnNextCall(g);
+
+Debug.setListener(listener);
+
+f(1);
+
+Debug.setListener(null);  // Break 9
+assertNull(exception);
+assertEquals(10, break_count);
diff --git a/src/v8/test/debugger/debug/debug-step.js b/src/v8/test/debugger/debug/debug-step.js
new file mode 100644
index 0000000..a850341
--- /dev/null
+++ b/src/v8/test/debugger/debug/debug-step.js
@@ -0,0 +1,49 @@
+// Copyright 2016 the V8 project authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+// Flags: --cache=code
+
+Debug = debug.Debug
+
+// Simple debug event handler which first time hit will perform 1000 steps and
+// second time hit will evaluate and store the value of "i". If requires that
+// the global property "state" is initially zero.
+
+var bp1, bp2;
+
+function listener(event, exec_state, event_data, data) {
+  if (event == Debug.DebugEvent.Break) {
+    if (step_count > 0) {
+      exec_state.prepareStep(Debug.StepAction.StepIn);
+      step_count--;
+    } else {
+      result = exec_state.frame().evaluate("i").value();
+      // Clear the break point on line 2 if set.
+      if (bp2) {
+        Debug.clearBreakPoint(bp2);
+      }
+    }
+  }
+};
+
+// Add the debug event listener.
+Debug.setListener(listener);
+
+// Test debug event for break point.
+function f() {
+  var i;                        // Line 1.
+  for (i = 0; i < 1000; i++) {  // Line 2.
+    x = 1;                      // Line 3.
+  }
+};
+
+// Set a breakpoint on the for statement (line 1).
+bp1 = Debug.setBreakPoint(f, 1);
+
+// Check that performing 1000 steps will make i 333.
+var step_count = 1000;
+result = -1;
+f();
+assertEquals(333, result);
+Debug.setListener(null);
diff --git a/src/v8/test/debugger/debug/debug-stepin-accessor-ic.js b/src/v8/test/debugger/debug/debug-stepin-accessor-ic.js
new file mode 100644
index 0000000..d83402a
--- /dev/null
+++ b/src/v8/test/debugger/debug/debug-stepin-accessor-ic.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.
+
+
+function get() {
+  return 3;                       // Break
+}                                 // Break
+
+function set(x) {
+  this.x = x;                     // Break
+}                                 // Break
+
+var o = {};
+Object.defineProperty(o, "get", { get : get });
+Object.defineProperty(o, "set", { set : set });
+
+function f() {
+  for (var i = 0; i < 10; i++) {  // Break
+    o.get;                        // Break
+    o.set = 1;                    // Break
+  }
+}                                 // Break
+
+var break_count = 0;
+var exception = null;
+
+function listener(event, exec_state, event_data, data) {
+  if (event != Debug.DebugEvent.Break) return;
+  try {
+    var source_line = exec_state.frame(0).sourceLineText();
+    assertTrue(source_line.indexOf("// Break") > 0);
+    exec_state.prepareStep(Debug.StepAction.StepIn);
+    break_count++;
+  } catch (e) {
+    exception = e;
+  }
+}
+
+var Debug = debug.Debug;
+Debug.setListener(listener);
+
+debugger;                         // Break
+f();                              // Break
+
+Debug.setListener(null);          // Break
+assertEquals(86, break_count);
+assertNull(exception);
diff --git a/src/v8/test/debugger/debug/debug-stepin-accessor.js b/src/v8/test/debugger/debug/debug-stepin-accessor.js
new file mode 100644
index 0000000..64bebb8
--- /dev/null
+++ b/src/v8/test/debugger/debug/debug-stepin-accessor.js
@@ -0,0 +1,247 @@
+// 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.
+
+
+Debug = debug.Debug
+
+var exception = null;
+var state = 1;
+var expected_source_line_text = null;
+var expected_function_name = null;
+
+// Simple debug event handler which first time will cause 'step in' action
+// to get into g.call and than check that execution is stopped inside
+// function 'g'.
+function listener(event, exec_state, event_data, data) {
+  try {
+    if (event == Debug.DebugEvent.Break) {
+      if (state == 3) {
+        assertEquals(expected_source_line_text,
+                     event_data.sourceLineText());
+        assertEquals(expected_function_name, event_data.func().name());
+        state = 4;
+      } else {
+        exec_state.prepareStep(Debug.StepAction.StepIn);
+        state++;
+      }
+    }
+  } catch(e) {
+    exception = e;
+  }
+};
+
+// Add the debug event listener.
+Debug.setListener(listener);
+
+
+var c = {
+  name: 'name ',
+  get getter1() {
+    return this.name;  // getter 1
+  },
+  get getter2() {
+    return {  // getter 2
+     'a': c.name
+    };
+  },
+  set setter1(n) {
+    this.name = n;  // setter 1
+  }
+};
+
+c.__defineGetter__('y', function getterY() {
+  return this.name;  // getter y
+});
+
+c.__defineGetter__(3, function getter3() {
+  return this.name;  // getter 3
+});
+
+c.__defineSetter__('y', function setterY(n) {
+  this.name = n;  // setter y
+});
+
+c.__defineSetter__(3, function setter3(n) {
+  this.name = n;  // setter 3
+});
+
+var d = {
+  'c': c,
+};
+
+function testGetter1_1() {
+  expected_function_name = 'get getter1';
+  expected_source_line_text = '    return this.name;  // getter 1';
+  debugger;
+  var x = c.getter1;
+}
+
+function testGetter1_2() {
+  expected_function_name = 'get getter1';
+  expected_source_line_text = '    return this.name;  // getter 1';
+  debugger;
+  var x = c['getter1'];
+}
+
+function testGetter1_3() {
+  expected_function_name = 'get getter1';
+  expected_source_line_text = '    return this.name;  // getter 1';
+  for (var i = 1; i < 2; i++) {
+    debugger;
+    var x = c['getter' + i];
+  }
+}
+
+function testGetter1_4() {
+  expected_function_name = 'get getter1';
+  expected_source_line_text = '    return this.name;  // getter 1';
+  debugger;
+  var x = d.c.getter1;
+}
+
+function testGetter1_5() {
+  expected_function_name = 'get getter1';
+  expected_source_line_text = '    return this.name;  // getter 1';
+  for (var i = 2; i != 1; i--);
+  debugger;
+  var x = d.c['getter' + i];
+}
+
+function testGetter2_1() {
+  expected_function_name = 'get getter2';
+  expected_source_line_text = '    return {  // getter 2';
+  for (var i = 2; i != 1; i--);
+  debugger;
+  var t = d.c.getter2.name;
+}
+
+
+function testGetterY_1() {
+  expected_function_name = 'getterY';
+  expected_source_line_text = '  return this.name;  // getter y';
+  debugger;
+  var t = d.c.y;
+}
+
+function testIndexedGetter3_1() {
+  expected_function_name = 'getter3';
+  expected_source_line_text = '  return this.name;  // getter 3';
+  debugger;
+  var r = d.c[3];
+}
+
+function testSetterY_1() {
+  expected_function_name = 'setterY';
+  expected_source_line_text = '  this.name = n;  // setter y';
+  debugger;
+  d.c.y = 'www';
+}
+
+function testIndexedSetter3_1() {
+  expected_function_name = 'setter3';
+  expected_source_line_text = '  this.name = n;  // setter 3';
+  var i = 3
+  debugger;
+  d.c[3] = 'www';
+}
+
+function testSetter1_1() {
+  expected_function_name = 'set setter1';
+  expected_source_line_text = '    this.name = n;  // setter 1';
+  debugger;
+  d.c.setter1 = 'aa';
+}
+
+function testSetter1_2() {
+  expected_function_name = 'set setter1';
+  expected_source_line_text = '    this.name = n;  // setter 1';
+  debugger;
+  d.c['setter1'] = 'bb';
+}
+
+function testSetter1_3() {
+  expected_function_name = 'set setter1';
+  expected_source_line_text = '    this.name = n;  // setter 1';
+  for (var i = 2; i != 1; i--);
+  debugger;
+  d.c['setter' + i] = i;
+}
+
+var e = {
+  name: 'e'
+};
+e.__proto__ = c;
+
+function testProtoGetter1_1() {
+  expected_function_name = 'get getter1';
+  expected_source_line_text = '    return this.name;  // getter 1';
+  debugger;
+  var x = e.getter1;
+}
+
+function testProtoSetter1_1() {
+  expected_function_name = 'set setter1';
+  expected_source_line_text = '    this.name = n;  // setter 1';
+  debugger;
+  e.setter1 = 'aa';
+}
+
+function testProtoIndexedGetter3_1() {
+  expected_function_name = 'getter3';
+  expected_source_line_text = '  return this.name;  // getter 3';
+  debugger;
+  var x = e[3];
+}
+
+function testProtoIndexedSetter3_1() {
+  expected_function_name = 'setter3';
+  expected_source_line_text = '  this.name = n;  // setter 3';
+  debugger;
+  e[3] = 'new val';
+}
+
+function testProtoSetter1_2() {
+  expected_function_name = 'set setter1';
+  expected_source_line_text = '    this.name = n;  // setter 1';
+  for (var i = 2; i != 1; i--);
+  debugger;
+  e['setter' + i] = 'aa';
+}
+
+for (var n in this) {
+  if (n.substr(0, 4) != 'test' ||
+    n == 'testRunner' || n == 'testAsync') {
+    continue;
+  }
+  state = 1;
+  this[n]();
+  if (exception) throw exception;
+  assertEquals(4, state);
+}
+
+// Get rid of the debug event listener.
+Debug.setListener(null);
diff --git a/src/v8/test/debugger/debug/debug-stepin-builtin-callback-opt.js b/src/v8/test/debugger/debug/debug-stepin-builtin-callback-opt.js
new file mode 100644
index 0000000..1fb9ce7
--- /dev/null
+++ b/src/v8/test/debugger/debug/debug-stepin-builtin-callback-opt.js
@@ -0,0 +1,37 @@
+// 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 replaceCallback(a) {
+  return "x"                                    // Break 2.
+  ;                                             // Break 3.
+}
+
+var re = /x/g;
+// Optimize the inner helper function for string replace.
+for (var i = 0; i < 10000; i++) "x".replace(re, replaceCallback);
+
+Debug.setListener(listener);
+debugger;                                       // Break 0.
+var result = "x".replace(re, replaceCallback);  // Break 1.
+Debug.setListener(null);                        // Break 4.
+
+assertNull(exception);
diff --git a/src/v8/test/debugger/debug/debug-stepin-builtin-callback.js b/src/v8/test/debugger/debug/debug-stepin-builtin-callback.js
new file mode 100644
index 0000000..0a09a0b
--- /dev/null
+++ b/src/v8/test/debugger/debug/debug-stepin-builtin-callback.js
@@ -0,0 +1,143 @@
+// 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.
+
+
+// Test stepping into callbacks passed to builtin functions.
+
+Debug = debug.Debug
+
+var exception = null;
+
+function array_listener(event, exec_state, event_data, data) {
+  try {
+    if (event == Debug.DebugEvent.Break) {
+      print(event_data.sourceLineText(), breaks);
+      assertTrue(event_data.sourceLineText().indexOf(`B${breaks++}`) > 0);
+      exec_state.prepareStep(Debug.StepAction.StepIn);
+    }
+  } catch (e) {
+    print(e);
+    quit();
+    exception = e;
+  }
+};
+
+function cb_false(num) {
+  print("element " + num);  // B2 B5 B8
+  return false;             // B3 B6 B9
+}                           // B4 B7 B10
+
+function cb_true(num) {
+  print("element " + num);  // B2 B5 B8
+  return true;              // B3 B6 B9
+}                           // B4 B7 B10
+
+function cb_reduce(a, b) {
+  print("elements " + a + " and " + b);  // B2 B5
+  return a + b;                          // B3 B6
+}                                        // B4 B7
+
+var a = [1, 2, 3];
+
+var breaks = 0;
+Debug.setListener(array_listener);
+debugger;                 // B0
+a.forEach(cb_true);       // B1
+Debug.setListener(null);  // B11
+assertNull(exception);
+assertEquals(12, breaks);
+
+breaks = 0;
+Debug.setListener(array_listener);
+debugger;                 // B0
+a.some(cb_false);         // B1
+Debug.setListener(null);  // B11
+assertNull(exception);
+assertEquals(12, breaks);
+
+breaks = 0;
+Debug.setListener(array_listener);
+debugger;                 // B0
+a.every(cb_true);         // B1
+Debug.setListener(null);  // B11
+assertNull(exception);
+assertEquals(12, breaks);
+
+breaks = 0;
+Debug.setListener(array_listener);
+debugger;                 // B0
+a.map(cb_true);           // B1
+Debug.setListener(null);  // B11
+assertNull(exception);
+assertEquals(12, breaks);
+
+breaks = 0;
+Debug.setListener(array_listener);
+debugger;                 // B0
+a.filter(cb_true);        // B1
+Debug.setListener(null);  // B11
+assertNull(exception);
+assertEquals(12, breaks);
+
+breaks = 0;
+Debug.setListener(array_listener);
+debugger;                 // B0
+a.reduce(cb_reduce);      // B1
+Debug.setListener(null);  // B8
+assertNull(exception);
+assertEquals(9, breaks);
+
+breaks = 0;
+Debug.setListener(array_listener);
+debugger;                  // B0
+a.reduceRight(cb_reduce);  // B1
+Debug.setListener(null);   // B8
+assertNull(exception);
+assertEquals(9, 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_true_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_foreach(num) {
+  a.forEach(cb_true_2);     // B2  B14 B20 B26
+  print("back.");           // B12 B18 B24 B36
+}                           // B13 B19 B25 B37
+
+breaks = 0;
+Debug.setListener(array_listener);
+debugger;                   // B0
+a.forEach(cb_foreach);      // B1
+Debug.setListener(null);    // B38
+assertNull(exception);
+assertEquals(39, breaks);
diff --git a/src/v8/test/debugger/debug/debug-stepin-builtin.js b/src/v8/test/debugger/debug/debug-stepin-builtin.js
new file mode 100644
index 0000000..f58019a
--- /dev/null
+++ b/src/v8/test/debugger/debug/debug-stepin-builtin.js
@@ -0,0 +1,76 @@
+// Copyright 2009 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.
+
+
+Debug = debug.Debug
+
+var exception = null;
+var state = 1;
+var expected_source_line_text = null;
+var expected_function_name = null;
+
+// Simple debug event handler which first time will cause 'step in' action
+// and than check that execution is paused inside function
+// expected_function_name.
+function listener(event, exec_state, event_data, data) {
+  try {
+    if (event == Debug.DebugEvent.Break) {
+      if (state == 3) {
+        assertEquals(expected_function_name, event_data.func().name());
+        assertEquals(expected_source_line_text,
+                     event_data.sourceLineText());
+        state = 4;
+      } else {
+        exec_state.prepareStep(Debug.StepAction.StepIn);
+        state++;
+      }
+    }
+  } catch(e) {
+    exception = e;
+  }
+};
+
+// Add the debug event listener.
+Debug.setListener(listener);
+
+var a = [1,2,3,4,5];
+
+// Test step into function call from a function without local variables.
+function testStepInArraySlice() {
+  expected_function_name = 'testStepInArraySlice';
+  expected_source_line_text = '}  // expected line';
+  debugger;
+  var s = Array.prototype.slice.call(a, 2,3);
+}  // expected line
+
+state = 1;
+testStepInArraySlice();
+assertNull(exception);
+assertEquals(4, state);
+
+// Get rid of the debug event listener.
+Debug.setListener(null);
diff --git a/src/v8/test/debugger/debug/debug-stepin-call-function-stub.js b/src/v8/test/debugger/debug/debug-stepin-call-function-stub.js
new file mode 100644
index 0000000..092f2da
--- /dev/null
+++ b/src/v8/test/debugger/debug/debug-stepin-call-function-stub.js
@@ -0,0 +1,115 @@
+// Copyright 2009 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.
+
+Debug = debug.Debug
+
+var exception = null;
+var state = 0;
+var expected_function_name = null;
+var expected_source_line_text = null;
+var expected_caller_source_line = null;
+var step_in_count = 2;
+
+// Simple debug event handler which first time will cause 'step in' action
+// to get into g.call and than check that execution is pauesed inside
+// function 'g'.
+function listener(event, exec_state, event_data, data) {
+  try {
+    if (event == Debug.DebugEvent.Break) {
+      if (state < step_in_count) {
+        // Step into f().
+        exec_state.prepareStep(Debug.StepAction.StepIn);
+        state++;
+      } else {
+        assertEquals(expected_source_line_text,
+                     event_data.sourceLineText());
+        assertEquals(expected_function_name, event_data.func().name());
+        state = 3;
+      }
+    }
+  } catch(e) {
+    exception = e;
+  }
+};
+
+// Add the debug event listener.
+Debug.setListener(listener);
+
+
+function g() {
+   return "s";  // expected line
+}
+
+function testFunction() {
+  var f = g;
+  var s = 1 +f(10);
+}
+
+function g2() {
+   return "s2";  // expected line
+}
+
+function testFunction2() {
+  var f = g2;
+  var s = 1 +f(10, 20);
+}
+
+// Run three times. First time the function will be compiled lazily,
+// second time cached version will be used.
+for (var i = 0; i < 3; i++) {
+  state = 0;
+  expected_function_name = 'g';
+  expected_source_line_text = '   return "s";  // expected line';
+  step_in_count = 2;
+  // Set a break point and call to invoke the debug event listener.
+  const breakid = Debug.setBreakPoint(testFunction, 1, 0);
+  testFunction();
+  Debug.clearBreakPoint(breakid);
+  assertNull(exception);
+  assertEquals(3, state);
+}
+
+// Test stepping into function call when a breakpoint is set at the place
+// of call. Use different pair of functions so that g2 is compiled lazily.
+// Run twice: first time function will be compiled lazily, second time
+// cached version will be used.
+for (var i = 0; i < 3; i++) {
+  state = 0;
+  expected_function_name = 'g2';
+  expected_source_line_text = '   return "s2";  // expected line';
+  step_in_count = 1;
+  // Set a break point and call to invoke the debug event listener.
+  const breakid = Debug.setBreakPoint(testFunction2, 2, 0);
+  testFunction2();
+  Debug.clearBreakPoint(breakid);
+  assertNull(exception);
+  assertEquals(3, state);
+}
+
+
+// Get rid of the debug event listener.
+Debug.setListener(null);
diff --git a/src/v8/test/debugger/debug/debug-stepin-construct-call.js b/src/v8/test/debugger/debug/debug-stepin-construct-call.js
new file mode 100644
index 0000000..c405a05
--- /dev/null
+++ b/src/v8/test/debugger/debug/debug-stepin-construct-call.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.
+
+
+var break_count = 0;
+var exception = null;
+
+function listener(event, exec_state, event_data, data) {
+  if (event != Debug.DebugEvent.Break) return;
+  try {
+    var source_line = exec_state.frame(0).sourceLineText();
+    print(source_line);
+    exec_state.prepareStep(Debug.StepAction.StepIn);
+    break_count++;
+  } catch (e) {
+    exception = e;
+  }
+}
+
+var Debug = debug.Debug;
+Debug.setListener(listener);
+
+
+function f() {
+  this.x = 1;
+}
+
+function g() {
+  new f();
+}
+
+Debug.setBreakPoint(g, 6);
+
+g();
+Debug.setListener(null);
+
+assertEquals(6, break_count);
+assertNull(exception);
diff --git a/src/v8/test/debugger/debug/debug-stepin-constructor.js b/src/v8/test/debugger/debug/debug-stepin-constructor.js
new file mode 100644
index 0000000..b6aaec8
--- /dev/null
+++ b/src/v8/test/debugger/debug/debug-stepin-constructor.js
@@ -0,0 +1,73 @@
+// Copyright 2008 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.
+
+Debug = debug.Debug
+
+// Simple debug event handler which counts the number of breaks hit and steps.
+var break_break_point_hit_count = 0;
+function listener(event, exec_state, event_data, data) {
+  if (event == Debug.DebugEvent.Break) {
+    break_break_point_hit_count++;
+    // Continue stepping until returned to bottom frame.
+    if (exec_state.frameCount() > 1) {
+      exec_state.prepareStep(Debug.StepAction.StepIn);
+    }
+  }
+};
+
+// Add the debug event listener.
+Debug.setListener(listener);
+
+// Test step into constructor with simple constructor.
+function X() {
+}
+
+function f() {
+  debugger;
+  new X();
+};
+
+break_break_point_hit_count = 0;
+f();
+assertEquals(5, break_break_point_hit_count);
+f();
+assertEquals(10, break_break_point_hit_count);
+f();
+assertEquals(15, break_break_point_hit_count);
+
+// Test step into constructor with builtin constructor.
+function g() {
+  debugger;
+  new Date();
+};
+
+break_break_point_hit_count = 0;
+g();
+assertEquals(4, break_break_point_hit_count);
+
+// Get rid of the debug event listener.
+Debug.setListener(null);
diff --git a/src/v8/test/debugger/debug/debug-stepin-foreach.js b/src/v8/test/debugger/debug/debug-stepin-foreach.js
new file mode 100644
index 0000000..36fcf16
--- /dev/null
+++ b/src/v8/test/debugger/debug/debug-stepin-foreach.js
@@ -0,0 +1,47 @@
+// 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.
+
+// Tests stepping into through Array.prototype.forEach callbacks.
+
+Debug = debug.Debug
+var exception = null;
+var break_count = 0;
+var expected_breaks = 11;
+
+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);
+var bound_callback = callback.bind(null);
+
+debugger; // Break 0.
+[1,2].forEach(callback); // Break 1.
+[3,4].forEach(bound_callback); // Break 6.
+
+function callback(x) {
+  return x // Break 2. // Break 4. // Break 7. // Break 9.
+  ; // Break 3. // Break 5. // Break 8. // Break 10.
+}
+
+assertNull(exception); // Break 11.
+assertEquals(expected_breaks, break_count);
+
+Debug.setListener(null);
diff --git a/src/v8/test/debugger/debug/debug-stepin-function-call.js b/src/v8/test/debugger/debug/debug-stepin-function-call.js
new file mode 100644
index 0000000..0227ccd
--- /dev/null
+++ b/src/v8/test/debugger/debug/debug-stepin-function-call.js
@@ -0,0 +1,173 @@
+// Copyright 2008 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.
+
+Debug = debug.Debug
+
+var exception = null;
+var state = 0;
+
+// Simple debug event handler which first time will cause 'step in' action
+// to get into g.call and than check that execution is pauesed inside
+// function 'g'.
+function listener(event, exec_state, event_data, data) {
+  try {
+    if (event == Debug.DebugEvent.Break) {
+      if (state < 2) {
+        // Step into f2.call:
+        exec_state.prepareStep(Debug.StepAction.StepIn);
+        state++;
+      } else {
+        assertEquals('g', event_data.func().name());
+        assertEquals('  return t + 1; // expected line',
+                     event_data.sourceLineText());
+        state = 3;
+      }
+    }
+  } catch(e) {
+    exception = e;
+  }
+};
+
+// Add the debug event listener.
+Debug.setListener(listener);
+
+
+// Sample functions.
+function g(t) {
+  return t + 1; // expected line
+}
+
+// Test step into function call from a function without local variables.
+function call1() {
+  debugger;
+  g.call(null, 3);
+}
+
+
+// Test step into function call from a function with some local variables.
+function call2() {
+  var aLocalVar = 'test';
+  var anotherLocalVar  = g(aLocalVar) + 's';
+  var yetAnotherLocal = 10;
+  debugger;
+  g.call(null, 3);
+}
+
+// Test step into function call which is a part of an expression.
+function call3() {
+  var alias = g;
+  debugger;
+  var r = 10 + alias.call(null, 3);
+  var aLocalVar = 'test';
+  var anotherLocalVar  = g(aLocalVar) + 's';
+  var yetAnotherLocal = 10;
+}
+
+// Test step into function call from a function with some local variables.
+function call4() {
+  var alias = g;
+  debugger;
+  alias.call(null, 3);
+  var aLocalVar = 'test';
+  var anotherLocalVar  = g(aLocalVar) + 's';
+  var yetAnotherLocal = 10;
+}
+
+// Test step into function apply from a function without local variables.
+function apply1() {
+  debugger;
+  g.apply(null, [3]);
+}
+
+
+// Test step into function apply from a function with some local variables.
+function apply2() {
+  var aLocalVar = 'test';
+  var anotherLocalVar  = g(aLocalVar) + 's';
+  var yetAnotherLocal = 10;
+  debugger;
+  g.apply(null, [3, 4]);
+}
+
+// Test step into function apply which is a part of an expression.
+function apply3() {
+  var alias = g;
+  debugger;
+  var r = 10 + alias.apply(null, [3, 'unused arg']);
+  var aLocalVar = 'test';
+  var anotherLocalVar  = g(aLocalVar) + 's';
+  var yetAnotherLocal = 10;
+}
+
+// Test step into function apply from a function with some local variables.
+function apply4() {
+  var alias = g;
+  debugger;
+  alias.apply(null, [3]);
+  var aLocalVar = 'test';
+  var anotherLocalVar  = g(aLocalVar) + 's';
+  var yetAnotherLocal = 10;
+}
+
+// Test step into bound function.
+function bind1() {
+  var bound = g.bind(null, 3);
+  debugger;
+  bound();
+}
+
+// Test step into apply of bound function.
+function applyAndBind1() {
+  var bound = g.bind(null, 3);
+  debugger;
+  bound.apply(null, [3]);
+  var aLocalVar = 'test';
+  var anotherLocalVar  = g(aLocalVar) + 's';
+  var yetAnotherLocal = 10;
+}
+
+var testFunctions =
+    [call1, call2, call3, call4, apply1, apply2, apply3, apply4, bind1,
+    applyAndBind1];
+
+for (var i = 0; i < testFunctions.length; i++) {
+  state = 0;
+  testFunctions[i]();
+  assertNull(exception);
+  assertEquals(3, state);
+}
+
+// Test global bound function.
+state = 0;
+var globalBound = g.bind(null, 3);
+debugger;
+globalBound();
+assertNull(exception);
+assertEquals(3, state);
+
+// Get rid of the debug event listener.
+Debug.setListener(null);
diff --git a/src/v8/test/debugger/debug/debug-stepin-property-function-call.js b/src/v8/test/debugger/debug/debug-stepin-property-function-call.js
new file mode 100644
index 0000000..454518a
--- /dev/null
+++ b/src/v8/test/debugger/debug/debug-stepin-property-function-call.js
@@ -0,0 +1,152 @@
+// Copyright 2014 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: --noopt
+Debug = debug.Debug
+
+var exception = null;
+var state = 1;
+
+// Simple debug event handler which first time will cause 'step in' action
+// to get into g.call and than check that execution is stopped inside
+// function 'g'.
+function listener(event, exec_state, event_data, data) {
+  try {
+    if (event == Debug.DebugEvent.Break) {
+      if (state < 4) {
+        exec_state.prepareStep(Debug.StepAction.StepIn);
+        state++;
+      } else {
+        assertTrue(event_data.sourceLineText().indexOf("Expected to step") > 0,
+          "source line: \"" + event_data.sourceLineText() + "\"");
+        state = 5;
+      }
+    }
+  } catch(e) {
+    print("Exception: " + e);
+    exception = e;
+  }
+};
+
+// Add the debug event listener.
+Debug.setListener(listener);
+
+var count = 0;
+var obj = {
+  fun: function() {
+    ++count;
+    return count; // Expected to step
+  }
+};
+obj.fun2 = obj.fun;
+
+function testCall_Dots() {
+  debugger;
+  obj.fun();
+}
+
+function testCall_Quotes() {
+  debugger;
+  obj["fun"]();
+}
+
+function testCall_Call() {
+  debugger;
+  obj.fun.call(obj);
+}
+
+function testCall_Apply() {
+  debugger;
+  obj.fun.apply(obj);
+}
+
+function testCall_Variable() {
+  var functionName = "fun";
+  debugger;
+  obj[functionName]();
+}
+
+function testCall_Fun2() {
+  debugger;
+  obj.fun2();
+}
+
+function testCall_InternStrings() {
+  var cache = { "fun": "fun" };
+  var functionName = "fu" + "n";
+  debugger;
+  obj[cache[functionName]]();
+}
+
+function testCall_ViaFunRef() {
+  var functionName = "fu" + "n";
+  var funRef = obj[functionName];
+  debugger;
+  funRef();
+}
+
+// bug 2888
+function testCall_RuntimeVariable1() {
+  var functionName = "fu" + "n";
+  debugger;
+  obj[functionName]();
+}
+
+// bug 2888
+function testCall_RuntimeVariable2() {
+  var functionName = "un".replace(/u/, "fu");
+  debugger;
+  obj[functionName]();
+}
+
+// bug 2888
+function testCall_RuntimeVariable3() {
+  var expr = "fu" + "n";
+  const functionName = expr;
+  assertEquals("fun", functionName);
+  debugger;
+  obj[functionName]();
+}
+
+var functionsCalled = 0;
+for (var n in this) {
+  if (n.substr(0, 4) != 'test' || typeof this[n] !== "function" || n == 'testAsync') {
+    continue;
+  }
+  state = 1;
+  print("Running " + n + "...");
+  this[n]();
+  ++functionsCalled;
+  assertNull(exception, n);
+  assertEquals(5, state, n);
+  assertEquals(functionsCalled, count, n);
+}
+
+assertEquals(11, functionsCalled);
+
+// Get rid of the debug event listener.
+Debug.setListener(null);
diff --git a/src/v8/test/debugger/debug/debug-stepnext-do-while.js b/src/v8/test/debugger/debug/debug-stepnext-do-while.js
new file mode 100644
index 0000000..92382b2
--- /dev/null
+++ b/src/v8/test/debugger/debug/debug-stepnext-do-while.js
@@ -0,0 +1,77 @@
+// Copyright 2009 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.
+
+Debug = debug.Debug
+
+var exception = null;
+var break_break_point_hit_count = 0;
+
+function listener(event, exec_state, event_data, data) {
+  try {
+    if (event == Debug.DebugEvent.Break) {
+      if (break_break_point_hit_count == 0) {
+        assertEquals('    debugger;',
+                     event_data.sourceLineText());
+        assertEquals('runDoWhile', event_data.func().name());
+      } else if (break_break_point_hit_count == 1) {
+        assertEquals('  } while(condition());',
+                     event_data.sourceLineText());
+        assertEquals('runDoWhile', event_data.func().name());
+      }
+
+      break_break_point_hit_count++;
+      // Continue stepping until returned to bottom frame.
+      if (exec_state.frameCount() > 1) {
+        exec_state.prepareStep(Debug.StepAction.StepNext);
+      }
+
+    }
+  } catch(e) {
+    exception = e;
+  }
+};
+
+// Add the debug event listener.
+Debug.setListener(listener);
+
+function condition() {
+  return false;
+}
+
+function runDoWhile() {
+  do {
+    debugger;
+  } while(condition());
+};
+
+break_break_point_hit_count = 0;
+runDoWhile();
+assertNull(exception);
+assertEquals(4, break_break_point_hit_count);
+
+// Get rid of the debug event listener.
+Debug.setListener(null);
diff --git a/src/v8/test/debugger/debug/debug-stepout-recursive-function.js b/src/v8/test/debugger/debug/debug-stepout-recursive-function.js
new file mode 100644
index 0000000..3c674a3
--- /dev/null
+++ b/src/v8/test/debugger/debug/debug-stepout-recursive-function.js
@@ -0,0 +1,99 @@
+// Copyright 2009 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.
+
+Debug = debug.Debug
+
+var exception = null;
+
+// Simple debug event handler which counts the number of breaks hit and steps.
+var break_point_hit_count = 0;
+function listener(event, exec_state, event_data, data) {
+  try {
+    if (event == Debug.DebugEvent.Break) {
+      break_point_hit_count++;
+      // Continue stepping until returned to bottom frame.
+      if (exec_state.frameCount() > 1) {
+        exec_state.prepareStep(Debug.StepAction.StepOut);
+      }
+
+    }
+  } catch(e) {
+    exception = e;
+  }
+
+};
+
+function BeginTest(name) {
+  test_name = name;
+  break_point_hit_count = 0;
+  exception = null;
+}
+
+function EndTest(expected_break_point_hit_count) {
+  assertEquals(expected_break_point_hit_count, break_point_hit_count, test_name);
+  assertNull(exception, test_name);
+  test_name = null;
+}
+
+// Add the debug event listener.
+Debug.setListener(listener);
+
+
+var shouldBreak = null;
+function fact(x) {
+  if (shouldBreak(x)) {
+    debugger;
+  }
+  if (x < 2) {
+    return 1;
+  } else {
+    return x*fact(x-1);
+  }
+}
+
+BeginTest('Test 1');
+shouldBreak = function(x) { return x == 3; };
+fact(3);
+EndTest(2);
+
+BeginTest('Test 2');
+shouldBreak = function(x) { return x == 2; };
+fact(3);
+EndTest(3);
+
+BeginTest('Test 3');
+shouldBreak = function(x) { return x == 1; };
+fact(3);
+EndTest(4);
+
+BeginTest('Test 4');
+shouldBreak = function(x) { return x == 1 || x == 3; };
+fact(3);
+EndTest(5);
+
+// Get rid of the debug event listener.
+Debug.setListener(null);
diff --git a/src/v8/test/debugger/debug/debug-stepout-scope-part1.js b/src/v8/test/debugger/debug/debug-stepout-scope-part1.js
new file mode 100644
index 0000000..32acc24
--- /dev/null
+++ b/src/v8/test/debugger/debug/debug-stepout-scope-part1.js
@@ -0,0 +1,187 @@
+// 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.
+
+
+// Check that the ScopeIterator can properly recreate the scope at
+// every point when stepping through functions.
+
+var Debug = debug.Debug;
+
+function listener(event, exec_state, event_data, data) {
+  if (event == Debug.DebugEvent.Break) {
+    // Access scope details.
+    var scope_count = exec_state.frame().scopeCount();
+    for (var i = 0; i < scope_count; i++) {
+      var scope = exec_state.frame().scope(i);
+      // assertTrue(scope.isScope());
+      scope.scopeType();
+      scope.scopeObject();
+    }
+
+    // Do steps until we reach the global scope again.
+    exec_state.prepareStep(Debug.StepAction.StepIn);
+  }
+}
+
+Debug.setListener(listener);
+
+
+function test1() {
+  debugger;
+  with ({x:1}) {
+    x = 2;
+  }
+}
+test1();
+
+
+function test2() {
+  if (true) {
+    with ({}) {
+      debugger;
+    }
+  } else {
+    with ({}) {
+      return 10;
+    }
+  }
+}
+test2();
+
+
+function test3() {
+  if (true) {
+    debugger;
+  } else {
+    with ({}) {
+      return 10;
+    }
+  }
+}
+test3();
+
+
+function test4() {
+  debugger;
+  with ({x:1}) x = 1
+}
+test4();
+
+
+function test5() {
+  debugger;
+  var dummy = 1;
+  with ({}) {
+    with ({}) {
+      dummy = 2;
+    }
+  }
+  dummy = 3;
+}
+test5();
+
+
+function test6() {
+  debugger;
+  try {
+    throw 'stuff';
+  } catch (e) {
+    e = 1;
+  }
+}
+test6();
+
+
+function test7() {
+  debugger;
+  function foo() {}
+}
+test7();
+
+
+function test8() {
+  debugger;
+  (function foo() {})();
+}
+test8();
+
+
+function test10() {
+  debugger;
+  with ({}) {
+    return 10;
+  }
+}
+test10();
+
+
+function test11() {
+  debugger;
+  try {
+    throw 'stuff';
+  } catch (e) {
+    return 10;
+  }
+}
+test11();
+
+
+var prefixes = [
+    "debugger; ",
+    "if (false) { try { throw 0; } catch(x) { return x; } }; debugger; " ];
+
+
+// Return from function constructed with Function constructor.
+var anon = 12;
+for (var i = 0; i < prefixes.length; ++i) {
+  var pre = prefixes[i];
+  Function(pre + "return 42")();
+  Function(pre + "return 42 ")();
+  Function(pre + "return 42;")();
+  Function(pre + "return 42; ")();
+  Function(pre + "return anon")();
+  Function(pre + "return anon ")();
+  Function(pre + "return anon;")();
+  Function(pre + "return anon; ")();
+}
+
+
+try {
+  with({}) {
+    debugger;
+    eval("{}$%:^");
+  }
+} catch(e) {
+  nop();
+}
+
+
+function nop() {}
+
+
+// With block as the last(!) statement in global code.
+with ({}) { debugger; }
diff --git a/src/v8/test/debugger/debug/debug-stepout-scope-part2.js b/src/v8/test/debugger/debug/debug-stepout-scope-part2.js
new file mode 100644
index 0000000..ef1acd5
--- /dev/null
+++ b/src/v8/test/debugger/debug/debug-stepout-scope-part2.js
@@ -0,0 +1,80 @@
+// 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.
+
+
+// Check that the ScopeIterator can properly recreate the scope at
+// every point when stepping through functions.
+
+var Debug = debug.Debug;
+
+function listener(event, exec_state, event_data, data) {
+  if (event == Debug.DebugEvent.Break) {
+    // Access scope details.
+    var scope_count = exec_state.frame().scopeCount();
+    for (var i = 0; i < scope_count; i++) {
+      var scope = exec_state.frame().scope(i);
+      // assertTrue(scope.isScope());
+      scope.scopeType();
+      scope.scopeObject();
+    }
+
+    // Do steps until we reach the global scope again.
+    exec_state.prepareStep(Debug.StepAction.StepIn);
+  }
+}
+
+Debug.setListener(listener);
+
+var q = 42;
+var prefixes = [ "debugger; ",
+                 "if (false) { try { throw 0; } catch(x) { this.x = x; } }; debugger; " ];
+var bodies = [ "1",
+               "1 ",
+               "1;",
+               "1; ",
+               "q",
+               "q ",
+               "q;",
+               "q; ",
+               "try { throw 'stuff' } catch (e) { e = 1; }",
+               "try { throw 'stuff' } catch (e) { e = 1; } ",
+               "try { throw 'stuff' } catch (e) { e = 1; };",
+               "try { throw 'stuff' } catch (e) { e = 1; }; " ];
+
+
+function test9() {
+  debugger;
+  for (var i = 0; i < prefixes.length; ++i) {
+    var pre = prefixes[i];
+    for (var j = 0; j < bodies.length; ++j) {
+      var body = bodies[j];
+      eval(pre + body);
+      eval("'use strict'; " + pre + body);
+    }
+  }
+}
+test9();
diff --git a/src/v8/test/debugger/debug/debug-stepout-scope-part3.js b/src/v8/test/debugger/debug/debug-stepout-scope-part3.js
new file mode 100644
index 0000000..ac5f8f2
--- /dev/null
+++ b/src/v8/test/debugger/debug/debug-stepout-scope-part3.js
@@ -0,0 +1,77 @@
+// 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.
+
+
+// Check that the ScopeIterator can properly recreate the scope at
+// every point when stepping through functions.
+
+var Debug = debug.Debug;
+
+function listener(event, exec_state, event_data, data) {
+  if (event == Debug.DebugEvent.Break) {
+    // Access scope details.
+    var scope_count = exec_state.frame().scopeCount();
+    for (var i = 0; i < scope_count; i++) {
+      var scope = exec_state.frame().scope(i);
+      // assertTrue(scope.isScope());
+      scope.scopeType();
+      scope.scopeObject();
+    }
+
+    // Do steps until we reach the global scope again.
+    exec_state.prepareStep(Debug.StepAction.StepIn);
+  }
+}
+
+Debug.setListener(listener);
+
+var q = 42;
+var prefixes = [
+    "debugger; ",
+    "if (false) { try { throw 0; } catch(x) { this.x = x; } }; debugger; " ];
+var with_bodies = [ "with ({}) {}",
+                    "with ({x:1}) x",
+                    "with ({x:1}) x = 1",
+                    "with ({x:1}) x ",
+                    "with ({x:1}) x = 1 ",
+                    "with ({x:1}) x;",
+                    "with ({x:1}) x = 1;",
+                    "with ({x:1}) x; ",
+                    "with ({x:1}) x = 1; " ];
+
+
+function test9() {
+  debugger;
+  for (var i = 0; i < prefixes.length; ++i) {
+    var pre = prefixes[i];
+    for (var j = 0; j < with_bodies.length; ++j) {
+      var body = with_bodies[j];
+      eval(pre + body);
+    }
+  }
+}
+test9();
diff --git a/src/v8/test/debugger/debug/debug-stepout-scope-part4.js b/src/v8/test/debugger/debug/debug-stepout-scope-part4.js
new file mode 100644
index 0000000..ea7e8af
--- /dev/null
+++ b/src/v8/test/debugger/debug/debug-stepout-scope-part4.js
@@ -0,0 +1,77 @@
+// 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.
+
+
+// Check that the ScopeIterator can properly recreate the scope at
+// every point when stepping through functions.
+
+var Debug = debug.Debug;
+
+function listener(event, exec_state, event_data, data) {
+  if (event == Debug.DebugEvent.Break) {
+    // Access scope details.
+    var scope_count = exec_state.frame().scopeCount();
+    for (var i = 0; i < scope_count; i++) {
+      var scope = exec_state.frame().scope(i);
+      // assertTrue(scope.isScope());
+      scope.scopeType();
+      scope.scopeObject();
+    }
+
+    // Do steps until we reach the global scope again.
+    exec_state.prepareStep(Debug.StepAction.StepIn);
+  }
+}
+
+Debug.setListener(listener);
+
+var q = 42;
+var prefixes = [
+  "debugger; ",
+  "if (false) { try { throw 0; } catch(x) { this.x = x; } }; debugger; " ];
+var bodies = [ "1",
+               "1 ",
+               "1;",
+               "1; ",
+               "q",
+               "q ",
+               "q;",
+               "q; ",
+               "try { throw 'stuff' } catch (e) { e = 1; }",
+               "try { throw 'stuff' } catch (e) { e = 1; } ",
+               "try { throw 'stuff' } catch (e) { e = 1; };",
+               "try { throw 'stuff' } catch (e) { e = 1; }; " ];
+
+
+// Test global eval and function constructor.
+for (var i = 0; i < prefixes.length; ++i) {
+  var pre = prefixes[i];
+  for (var j = 0; j < bodies.length; ++j) {
+    var body = bodies[j];
+    eval(pre + body);
+  }
+}
diff --git a/src/v8/test/debugger/debug/debug-stepout-scope-part5.js b/src/v8/test/debugger/debug/debug-stepout-scope-part5.js
new file mode 100644
index 0000000..ee67c19
--- /dev/null
+++ b/src/v8/test/debugger/debug/debug-stepout-scope-part5.js
@@ -0,0 +1,74 @@
+// 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.
+
+
+// Check that the ScopeIterator can properly recreate the scope at
+// every point when stepping through functions.
+
+var Debug = debug.Debug;
+
+function listener(event, exec_state, event_data, data) {
+  if (event == Debug.DebugEvent.Break) {
+    // Access scope details.
+    var scope_count = exec_state.frame().scopeCount();
+    for (var i = 0; i < scope_count; i++) {
+      var scope = exec_state.frame().scope(i);
+      // assertTrue(scope.isScope());
+      scope.scopeType();
+      scope.scopeObject();
+    }
+
+    // Do steps until we reach the global scope again.
+    exec_state.prepareStep(Debug.StepAction.StepIn);
+  }
+}
+
+Debug.setListener(listener);
+
+var q = 42;
+var prefixes = [ "debugger; ",
+                 "if (false) { try { throw 0; } catch(x) { this.x = x; } }; debugger; " ];
+var with_bodies = [ "with ({}) {}",
+                    "with ({x:1}) x",
+                    "with ({x:1}) x = 1",
+                    "with ({x:1}) x ",
+                    "with ({x:1}) x = 1 ",
+                    "with ({x:1}) x;",
+                    "with ({x:1}) x = 1;",
+                    "with ({x:1}) x; ",
+                    "with ({x:1}) x = 1; " ];
+
+
+// Test global eval and function constructor.
+for (var i = 0; i < prefixes.length; ++i) {
+  var pre = prefixes[i];
+  for (var j = 0; j < with_bodies.length; ++j) {
+    var body = with_bodies[j];
+    eval(pre + body);
+    Function(pre + body)();
+  }
+}
diff --git a/src/v8/test/debugger/debug/debug-stepout-scope-part6.js b/src/v8/test/debugger/debug/debug-stepout-scope-part6.js
new file mode 100644
index 0000000..9545b5b
--- /dev/null
+++ b/src/v8/test/debugger/debug/debug-stepout-scope-part6.js
@@ -0,0 +1,76 @@
+// 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.
+
+
+// Check that the ScopeIterator can properly recreate the scope at
+// every point when stepping through functions.
+
+var Debug = debug.Debug;
+
+function listener(event, exec_state, event_data, data) {
+  if (event == Debug.DebugEvent.Break) {
+    // Access scope details.
+    var scope_count = exec_state.frame().scopeCount();
+    for (var i = 0; i < scope_count; i++) {
+      var scope = exec_state.frame().scope(i);
+      // assertTrue(scope.isScope());
+      scope.scopeType();
+      scope.scopeObject();
+    }
+
+    // Do steps until we reach the global scope again.
+    exec_state.prepareStep(Debug.StepAction.StepIn);
+  }
+}
+
+Debug.setListener(listener);
+
+var q = 42;
+var prefixes = [ "debugger; ",
+                 "if (false) { try { throw 0; } catch(x) { this.x = x; } }; debugger; " ];
+var bodies = [ "1",
+               "1 ",
+               "1;",
+               "1; ",
+               "q",
+               "q ",
+               "q;",
+               "q; ",
+               "try { throw 'stuff' } catch (e) { e = 1; }",
+               "try { throw 'stuff' } catch (e) { e = 1; } ",
+               "try { throw 'stuff' } catch (e) { e = 1; };",
+               "try { throw 'stuff' } catch (e) { e = 1; }; " ];
+
+
+// Test global eval and function constructor.
+for (var i = 0; i < prefixes.length; ++i) {
+  var pre = prefixes[i];
+  for (var j = 0; j < bodies.length; ++j) {
+    var body = bodies[j];
+    eval("'use strict'; " + pre + body);
+  }
+}
diff --git a/src/v8/test/debugger/debug/debug-stepout-scope-part7.js b/src/v8/test/debugger/debug/debug-stepout-scope-part7.js
new file mode 100644
index 0000000..1ab2065
--- /dev/null
+++ b/src/v8/test/debugger/debug/debug-stepout-scope-part7.js
@@ -0,0 +1,76 @@
+// 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.
+
+
+// Check that the ScopeIterator can properly recreate the scope at
+// every point when stepping through functions.
+
+var Debug = debug.Debug;
+
+function listener(event, exec_state, event_data, data) {
+  if (event == Debug.DebugEvent.Break) {
+    // Access scope details.
+    var scope_count = exec_state.frame().scopeCount();
+    for (var i = 0; i < scope_count; i++) {
+      var scope = exec_state.frame().scope(i);
+      // assertTrue(scope.isScope());
+      scope.scopeType();
+      scope.scopeObject();
+    }
+
+    // Do steps until we reach the global scope again.
+    exec_state.prepareStep(Debug.StepAction.StepIn);
+  }
+}
+
+Debug.setListener(listener);
+
+var q = 42;
+var prefixes = [ "debugger; ",
+                 "if (false) { try { throw 0; } catch(x) { return x; } }; debugger; " ];
+var bodies = [ "1",
+               "1 ",
+               "1;",
+               "1; ",
+               "q",
+               "q ",
+               "q;",
+               "q; ",
+               "try { throw 'stuff' } catch (e) { e = 1; }",
+               "try { throw 'stuff' } catch (e) { e = 1; } ",
+               "try { throw 'stuff' } catch (e) { e = 1; };",
+               "try { throw 'stuff' } catch (e) { e = 1; }; " ];
+
+
+// Test global eval and function constructor.
+for (var i = 0; i < prefixes.length; ++i) {
+  var pre = prefixes[i];
+  for (var j = 0; j < bodies.length; ++j) {
+    var body = bodies[j];
+    Function(pre + body)();
+  }
+}
diff --git a/src/v8/test/debugger/debug/debug-stepout-scope-part8.js b/src/v8/test/debugger/debug/debug-stepout-scope-part8.js
new file mode 100644
index 0000000..5b3585c
--- /dev/null
+++ b/src/v8/test/debugger/debug/debug-stepout-scope-part8.js
@@ -0,0 +1,231 @@
+// 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.
+
+
+// Check that the ScopeIterator can properly recreate the scope at
+// every point when stepping through functions.
+
+var Debug = debug.Debug;
+
+function listener(event, exec_state, event_data, data) {
+  if (event == Debug.DebugEvent.Break) {
+    // Access scope details.
+    var scope_count = exec_state.frame().scopeCount();
+    for (var i = 0; i < scope_count; i++) {
+      var scope = exec_state.frame().scope(i);
+      // assertTrue(scope.isScope());
+      scope.scopeType();
+      scope.scopeObject();
+    }
+
+    // Do steps until we reach the global scope again.
+    exec_state.prepareStep(Debug.StepAction.StepIn);
+  }
+}
+
+Debug.setListener(listener);
+
+
+function nop() {}
+
+
+function stress() {
+  debugger;
+
+  L: with ({x:12}) {
+    break L;
+  }
+
+
+  with ({x: 'outer'}) {
+    label: {
+      with ({x: 'inner'}) {
+        break label;
+      }
+    }
+  }
+
+
+  with ({x: 'outer'}) {
+    label: {
+      with ({x: 'inner'}) {
+        break label;
+      }
+    }
+    nop();
+  }
+
+
+  with ({x: 'outer'}) {
+    label: {
+      with ({x: 'middle'}) {
+        with ({x: 'inner'}) {
+          break label;
+        }
+      }
+    }
+  }
+
+
+  with ({x: 'outer'}) {
+    label: {
+      with ({x: 'middle'}) {
+        with ({x: 'inner'}) {
+          break label;
+        }
+      }
+    }
+    nop();
+  }
+
+
+  with ({x: 'outer'}) {
+    for (var i = 0; i < 3; ++i) {
+      with ({x: 'inner' + i}) {
+        continue;
+      }
+    }
+  }
+
+
+  with ({x: 'outer'}) {
+    label: for (var i = 0; i < 3; ++i) {
+      with ({x: 'middle' + i}) {
+        for (var j = 0; j < 3; ++j) {
+          with ({x: 'inner' + j}) {
+            continue label;
+          }
+        }
+      }
+    }
+  }
+
+
+  with ({x: 'outer'}) {
+    try {
+      with ({x: 'inner'}) {
+        throw 0;
+      }
+    } catch (e) {
+    }
+  }
+
+
+  with ({x: 'outer'}) {
+    try {
+      with ({x: 'inner'}) {
+        throw 0;
+      }
+    } catch (e) {
+      nop();
+    }
+  }
+
+
+  with ({x: 'outer'}) {
+    try {
+      with ({x: 'middle'}) {
+        with ({x: 'inner'}) {
+          throw 0;
+        }
+      }
+    } catch (e) {
+    }
+  }
+
+
+  try {
+    with ({x: 'outer'}) {
+      try {
+        with ({x: 'inner'}) {
+          throw 0;
+        }
+      } finally {
+      }
+    }
+  } catch (e) {
+  }
+
+
+  try {
+    with ({x: 'outer'}) {
+      try {
+        with ({x: 'inner'}) {
+          throw 0;
+        }
+      } finally {
+        nop();
+      }
+    }
+  } catch (e) {
+  }
+
+
+  function stress1() {
+    with ({x:12}) {
+      return x;
+    }
+  }
+  stress1();
+
+
+  function stress2() {
+    with ({x: 'outer'}) {
+      with ({x: 'inner'}) {
+        return x;
+      }
+    }
+  }
+  stress2();
+
+  function stress3() {
+    try {
+      with ({x: 'inner'}) {
+        throw 0;
+      }
+    } catch (e) {
+      return e;
+    }
+  }
+  stress3();
+
+
+  function stress4() {
+    try {
+      with ({x: 'inner'}) {
+        throw 0;
+      }
+    } catch (e) {
+      with ({x: 'inner'}) {
+        return e;
+      }
+    }
+  }
+  stress4();
+
+}
+stress();
diff --git a/src/v8/test/debugger/debug/debug-stepout-to-builtin.js b/src/v8/test/debugger/debug/debug-stepout-to-builtin.js
new file mode 100644
index 0000000..905e07f
--- /dev/null
+++ b/src/v8/test/debugger/debug/debug-stepout-to-builtin.js
@@ -0,0 +1,82 @@
+// Copyright 2009 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.
+
+
+Debug = debug.Debug
+
+var exception = null;
+var state = 1;
+var expected_source_line_text = null;
+var expected_function_name = null;
+
+// Simple debug event handler which first time will cause 'step out' action
+// and than check that execution is paused inside function
+// expected_function_name.
+function listener(event, exec_state, event_data, data) {
+  try {
+    if (event == Debug.DebugEvent.Break) {
+      if (state == 1) {
+        exec_state.prepareStep(Debug.StepAction.StepOut);
+        state++;
+      } else {
+        assertEquals(expected_function_name, event_data.func().name());
+        assertEquals(expected_source_line_text,
+                     event_data.sourceLineText());
+        state = 3;
+      }
+    }
+  } catch(e) {
+    exception = e;
+  }
+};
+
+// Add the debug event listener.
+Debug.setListener(listener);
+
+var obj = {key:10};
+
+function replacer(key, value) {
+  if (key == 'key') {
+    debugger;
+  }
+  return value;
+}
+
+// Test step into function call from a function without local variables.
+function testStepOutToBuiltIn() {
+  expected_function_name = 'testStepOutToBuiltIn';
+  expected_source_line_text = '}  // expected line';
+  JSON.stringify(obj, replacer);
+}  // expected line
+
+state = 1;
+testStepOutToBuiltIn();
+assertNull(exception);
+assertEquals(3, state);
+
+// Get rid of the debug event listener.
+Debug.setListener(null);
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);
diff --git a/src/v8/test/debugger/debug/es8/async-debug-basic.js b/src/v8/test/debugger/debug/es8/async-debug-basic.js
new file mode 100644
index 0000000..9423fe5
--- /dev/null
+++ b/src/v8/test/debugger/debug/es8/async-debug-basic.js
@@ -0,0 +1,37 @@
+// 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
+
+listenerComplete = false;
+breakPointCount = 0;
+
+async function f() {
+  await (async function() { var a = "a"; await 1; debugger; })();
+
+  var b = "b";
+
+  assertTrue(listenerDone);
+  assertFalse(exception);
+  assertEquals(1, breakpointCount);
+}
+
+function listener(event, exec_state, event_data, data) {
+  try {
+    if (event != Debug.DebugEvent.Break) return;
+
+    breakpointCount++;
+    listenerDone = true;
+    assertEquals("a", exec_state.frame(0).evaluate("a"));
+    assertEquals("b", exec_state.frame(1).evaluate("b"));
+    assertEquals("c", exec_state.frame(2).evaluate("c"));
+  } catch (e) {
+    exception = e;
+  };
+};
+
+Debug.setListener(listener);
+
+var c = "c";
+f();
diff --git a/src/v8/test/debugger/debug/es8/async-debug-builtin-predictions.js b/src/v8/test/debugger/debug/es8/async-debug-builtin-predictions.js
new file mode 100644
index 0000000..70f1b57
--- /dev/null
+++ b/src/v8/test/debugger/debug/es8/async-debug-builtin-predictions.js
@@ -0,0 +1,64 @@
+// Copyright 2017 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) {
+  if (event != Debug.DebugEvent.Exception) return;
+  try {
+    var line = exec_state.frame(0).sourceLineText();
+    var match = /Exception/.exec(line);
+    assertNotNull(match);
+  } catch (e) {
+    exception = e;
+  }
+}
+
+// Caught throw, events on any exception.
+Debug.setListener(listener);
+Debug.setBreakOnException();
+
+var thenable = {
+  get then() {
+    throw new Error();  // Exception
+  }
+};
+
+class MyPromise extends Promise {
+    get then()  {
+        throw new Error();
+    }
+}
+
+MyPromise.resolve(thenable);
+
+var p = Promise.resolve(thenable);
+
+async function foo() {
+  return thenable;
+}
+
+foo();
+
+async function foo() {
+  await thenable;
+}
+
+foo();
+
+async function foo() {
+  try {
+    await thenable;
+  } catch (e) {}
+}
+
+foo();
+
+%RunMicrotasks();
+
+Debug.setListener(null);
+Debug.clearBreakOnException();
+assertNull(exception);
diff --git a/src/v8/test/debugger/debug/es8/async-debug-caught-exception-cases.js b/src/v8/test/debugger/debug/es8/async-debug-caught-exception-cases.js
new file mode 100644
index 0000000..f5c1ed9
--- /dev/null
+++ b/src/v8/test/debugger/debug/es8/async-debug-caught-exception-cases.js
@@ -0,0 +1,213 @@
+// 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
+
+let events = 0;
+
+function listener(event, exec_state, event_data, data) {
+  if (event != Debug.DebugEvent.Exception) return;
+  events++;
+}
+
+async function thrower() {
+  throw "a";  // Exception a
+}
+
+var reject = () => Promise.reject("b");  // Exception b
+
+async function awaitReturn() { await 1; return; }
+
+async function scalar() { return 1; }
+
+function nothing() { return 1; }
+
+function rejectConstructor() {
+  return new Promise((resolve, reject) => reject("c"));  // Exception c
+}
+
+async function argThrower(x = (() => { throw "d"; })()) { }  // Exception d
+
+async function awaitThrow() {
+  await undefined;
+  throw "e";  // Exception e
+}
+
+function constructorThrow() {
+  return new Promise((resolve, reject) =>
+    Promise.resolve().then(() =>
+      reject("f")  // Exception f
+    )
+  );
+}
+
+function suppressThrow() {
+  return thrower();
+}
+
+async function caught(producer) {
+  try {
+    await producer();
+  } catch (e) {
+  }
+}
+
+async function uncaught(producer) {
+  await producer();
+}
+
+async function indirectUncaught(producer) {
+  await uncaught(producer);
+}
+
+async function indirectCaught(producer) {
+  try {
+    await uncaught(producer);
+  } catch (e) {
+  }
+}
+
+function dotCatch(producer) {
+  Promise.resolve(producer()).catch(() => {});
+}
+
+function indirectReturnDotCatch(producer) {
+  (async() => producer())().catch(() => {});
+}
+
+function indirectAwaitDotCatch(producer) {
+  (async() => await producer())().catch(() => {});
+}
+
+function nestedDotCatch(producer) {
+  Promise.resolve(producer()).then().catch(() => {});
+}
+
+async function indirectAwaitCatch(producer) {
+  try {
+    await (() => producer())();
+  } catch (e) {
+  }
+}
+
+function switchCatch(producer) {
+  let resolve;
+  let promise = new Promise(r => resolve = r);
+  async function localCaught() {
+    try {
+      await promise;  // force switching to localUncaught and back
+      await producer();
+    } catch (e) { }
+  }
+  async function localUncaught() {
+    await undefined;
+    resolve();
+  }
+  localCaught();
+  localUncaught();
+}
+
+function switchDotCatch(producer) {
+  let resolve;
+  let promise = new Promise(r => resolve = r);
+  async function localCaught() {
+    await promise;  // force switching to localUncaught and back
+    await producer();
+  }
+  async function localUncaught() {
+    await undefined;
+    resolve();
+  }
+  localCaught().catch(() => {});
+  localUncaught();
+}
+
+let catches = [caught,
+               indirectCaught,
+               indirectAwaitCatch,
+               switchCatch,
+               switchDotCatch];
+let noncatches = [uncaught, indirectUncaught];
+let lateCatches = [dotCatch,
+                   indirectReturnDotCatch,
+                   indirectAwaitDotCatch,
+                   nestedDotCatch];
+
+let throws = [thrower, reject, argThrower, suppressThrow];
+let nonthrows = [awaitReturn, scalar, nothing];
+let lateThrows = [awaitThrow, constructorThrow];
+let uncatchable = [rejectConstructor];
+
+let cases = [];
+
+for (let producer of throws.concat(lateThrows)) {
+  for (let consumer of catches) {
+    cases.push({ producer, consumer, expectedEvents: 1, caught: true });
+    cases.push({ producer, consumer, expectedEvents: 0, caught: false });
+  }
+}
+
+for (let producer of throws.concat(lateThrows)) {
+  for (let consumer of noncatches) {
+    cases.push({ producer, consumer, expectedEvents: 1, caught: true });
+    cases.push({ producer, consumer, expectedEvents: 1, caught: false });
+  }
+}
+
+for (let producer of nonthrows) {
+  for (let consumer of catches.concat(noncatches, lateCatches)) {
+    cases.push({ producer, consumer, expectedEvents: 0, caught: true });
+    cases.push({ producer, consumer, expectedEvents: 0, caught: false });
+  }
+}
+
+for (let producer of uncatchable) {
+  for (let consumer of catches.concat(noncatches, lateCatches)) {
+    cases.push({ producer, consumer, expectedEvents: 1, caught: true });
+    cases.push({ producer, consumer, expectedEvents: 1, caught: false });
+  }
+}
+
+for (let producer of lateThrows) {
+  for (let consumer of lateCatches) {
+    cases.push({ producer, consumer, expectedEvents: 1, caught: true });
+    cases.push({ producer, consumer, expectedEvents: 0, caught: false });
+  }
+}
+
+for (let producer of throws) {
+  for (let consumer of lateCatches) {
+    cases.push({ producer, consumer, expectedEvents: 1, caught: true });
+    cases.push({ producer, consumer, expectedEvents: 1, caught: false });
+  }
+}
+
+
+function runPart(n) {
+  let subcases = cases.slice(n * cases.length / 4,
+                             ((n + 1) * cases.length) / 4);
+  for (let {producer, consumer, expectedEvents, caught} of subcases) {
+    Debug.setListener(listener);
+    if (caught) {
+      Debug.setBreakOnException();
+    } else {
+      Debug.setBreakOnUncaughtException();
+    }
+
+    events = 0;
+    consumer(producer);
+    %RunMicrotasks();
+
+    Debug.setListener(null);
+    if (caught) {
+      Debug.clearBreakOnException();
+    } else {
+      Debug.clearBreakOnUncaughtException();
+    }
+    if (expectedEvents != events) {
+      %AbortJS(`producer ${producer} consumer ${consumer} expectedEvents ` +
+               `${expectedEvents} caught ${caught} events ${events}`);
+    }
+  }
+}
diff --git a/src/v8/test/debugger/debug/es8/async-debug-caught-exception-cases0.js b/src/v8/test/debugger/debug/es8/async-debug-caught-exception-cases0.js
new file mode 100644
index 0000000..15b4f39
--- /dev/null
+++ b/src/v8/test/debugger/debug/es8/async-debug-caught-exception-cases0.js
@@ -0,0 +1,7 @@
+// 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.
+
+// Files: test/debugger/debug/es8/async-debug-caught-exception-cases.js
+
+runPart(0);
diff --git a/src/v8/test/debugger/debug/es8/async-debug-caught-exception-cases1.js b/src/v8/test/debugger/debug/es8/async-debug-caught-exception-cases1.js
new file mode 100644
index 0000000..35c2c75
--- /dev/null
+++ b/src/v8/test/debugger/debug/es8/async-debug-caught-exception-cases1.js
@@ -0,0 +1,7 @@
+// 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.
+
+// Files: test/debugger/debug/es8/async-debug-caught-exception-cases.js
+
+runPart(1);
diff --git a/src/v8/test/debugger/debug/es8/async-debug-caught-exception-cases2.js b/src/v8/test/debugger/debug/es8/async-debug-caught-exception-cases2.js
new file mode 100644
index 0000000..58dcb47
--- /dev/null
+++ b/src/v8/test/debugger/debug/es8/async-debug-caught-exception-cases2.js
@@ -0,0 +1,7 @@
+// 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.
+
+// Files: test/debugger/debug/es8/async-debug-caught-exception-cases.js
+
+runPart(2);
diff --git a/src/v8/test/debugger/debug/es8/async-debug-caught-exception-cases3.js b/src/v8/test/debugger/debug/es8/async-debug-caught-exception-cases3.js
new file mode 100644
index 0000000..1302e64
--- /dev/null
+++ b/src/v8/test/debugger/debug/es8/async-debug-caught-exception-cases3.js
@@ -0,0 +1,7 @@
+// 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.
+
+// Files: test/debugger/debug/es8/async-debug-caught-exception-cases.js
+
+runPart(3);
diff --git a/src/v8/test/debugger/debug/es8/async-debug-caught-exception.js b/src/v8/test/debugger/debug/es8/async-debug-caught-exception.js
new file mode 100644
index 0000000..2feecc0
--- /dev/null
+++ b/src/v8/test/debugger/debug/es8/async-debug-caught-exception.js
@@ -0,0 +1,142 @@
+// 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);
+    log.push(match[1]);
+  } catch (e) {
+    exception = e;
+  }
+}
+
+async function thrower() {
+  throw "a";  // Exception a
+}
+
+async function caught_throw() {
+  try {
+    await thrower();
+  } catch (e) {
+    assertEquals("a", e);
+  }
+}
+
+
+// Caught throw, events on any exception.
+log = [];
+Debug.setListener(listener);
+Debug.setBreakOnException();
+caught_throw();
+%RunMicrotasks();
+Debug.setListener(null);
+Debug.clearBreakOnException();
+assertEquals(["a"], log);
+assertNull(exception);
+
+// Caught throw, events on uncaught exception.
+log = [];
+Debug.setListener(listener);
+Debug.setBreakOnUncaughtException();
+caught_throw();
+%RunMicrotasks();
+Debug.setListener(null);
+Debug.clearBreakOnUncaughtException();
+assertEquals([], log);
+assertNull(exception);
+
+var reject = Promise.reject("b");
+
+async function caught_reject() {
+  try {
+    await reject;
+  } catch (e) {
+    assertEquals("b", e);
+  }
+}
+
+// Caught reject, events on any exception.
+log = [];
+Debug.setListener(listener);
+Debug.setBreakOnException();
+caught_reject();
+%RunMicrotasks();
+Debug.setListener(null);
+Debug.clearBreakOnException();
+assertEquals([], log);
+assertNull(exception);
+
+// Caught reject, events on uncaught exception.
+log = [];
+Debug.setListener(listener);
+Debug.setBreakOnUncaughtException();
+caught_reject();
+%RunMicrotasks();
+Debug.setListener(null);
+Debug.clearBreakOnUncaughtException();
+assertEquals([], log);
+assertNull(exception);
+
+log = [];
+Debug.setListener(listener);
+Debug.setBreakOnException();
+
+// "rethrown" uncaught exceptions in return don't cause another event
+async function propagate_inner() { return thrower(); }
+async function propagate_outer() { return propagate_inner(); }
+
+propagate_outer();
+%RunMicrotasks();
+assertEquals(["a"], log);
+assertNull(exception);
+
+// Also don't propagate if an await interceded
+log = [];
+async function propagate_await() { await 1; return thrower(); }
+async function propagate_await_outer() { return propagate_await(); }
+propagate_await_outer();
+%RunMicrotasks();
+assertEquals(["a"], log);
+assertNull(exception);
+
+Debug.clearBreakOnException();
+Debug.setBreakOnUncaughtException();
+
+log = [];
+Promise.resolve().then(() => Promise.reject()).catch(() => log.push("d")); // Exception c
+%RunMicrotasks();
+assertEquals(["d"], log);
+assertNull(exception);
+
+Debug.clearBreakOnUncaughtException();
+Debug.setListener(null);
+
+// If devtools is turned on in the middle, then catch prediction
+// could be wrong (here, it mispredicts the exception as caught),
+// but shouldn't crash.
+
+log = [];
+
+var resolve;
+var turnOnListenerPromise = new Promise(r => resolve = r);
+async function confused() {
+  await turnOnListenerPromise;
+  throw foo
+}
+confused();
+Promise.resolve().then(() => {
+  Debug.setListener(listener);
+  Debug.setBreakOnUncaughtException();
+  resolve();
+});
+
+assertEquals([], log);
diff --git a/src/v8/test/debugger/debug/es8/async-debug-step-abort-at-break.js b/src/v8/test/debugger/debug/es8/async-debug-step-abort-at-break.js
new file mode 100644
index 0000000..85232b0
--- /dev/null
+++ b/src/v8/test/debugger/debug/es8/async-debug-step-abort-at-break.js
@@ -0,0 +1,53 @@
+// 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.
+
+var Debug = debug.Debug;
+var step_count = 0;
+
+function listener(event, execState, eventData, data) {
+  if (event != Debug.DebugEvent.Break) return;
+  try {
+    var line = execState.frame(0).sourceLineText();
+    print(line);
+    var [match, expected_count, step] = /\/\/ B(\d) (\w+)$/.exec(line);
+    assertEquals(step_count++, parseInt(expected_count));
+    if (step != "Continue") execState.prepareStep(Debug.StepAction[step]);
+  } catch (e) {
+    print(e, e.stack);
+    quit(1);
+  }
+}
+
+Debug.setListener(listener);
+
+var late_resolve;
+
+function g() {
+  return new Promise( // B2 StepOut
+    function(res, rej) {
+      late_resolve = res;
+    }
+  );
+}
+
+async function f() {
+  var a = 1;
+  debugger;          // B0 StepNext
+  a +=
+       await         // B1 StepIn
+             g();    // B2 StepIn
+  return a;
+}
+
+f();
+
+// Starting a new step action at an intermediate break point
+// means that we will abort the current async step.
+debugger;            // B3 StepNext
+
+late_resolve(3);     // B4 Continue
+
+%RunMicrotasks();
+
+assertEquals(5, step_count);
diff --git a/src/v8/test/debugger/debug/es8/async-debug-step-continue-at-break.js b/src/v8/test/debugger/debug/es8/async-debug-step-continue-at-break.js
new file mode 100644
index 0000000..a4726bd
--- /dev/null
+++ b/src/v8/test/debugger/debug/es8/async-debug-step-continue-at-break.js
@@ -0,0 +1,53 @@
+// 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.
+
+var Debug = debug.Debug;
+var step_count = 0;
+
+function listener(event, execState, eventData, data) {
+  if (event != Debug.DebugEvent.Break) return;
+  try {
+    var line = execState.frame(0).sourceLineText();
+    print(line);
+    var [match, expected_count, step] = /\/\/ B(\d) (\w+)$/.exec(line);
+    assertEquals(step_count++, parseInt(expected_count));
+    if (step != "Continue") execState.prepareStep(Debug.StepAction[step]);
+  } catch (e) {
+    print(e, e.stack);
+    quit(1);
+  }
+}
+
+Debug.setListener(listener);
+
+var late_resolve;
+
+function g() {
+  return new Promise( // B2 StepOut
+    function(res, rej) {
+      late_resolve = res;
+    }
+  );
+}
+
+async function f() {
+  var a = 1;
+  debugger;          // B0 StepNext
+  a +=
+       await         // B1 StepIn
+             g();    // B2 StepIn
+  return a;          // B4 StepNext
+}                    // B5 Continue
+
+f();
+
+// Continuing at an intermediate break point means that we will
+// carry on with the current async step.
+debugger;            // B3 Continue
+
+late_resolve(3);
+
+%RunMicrotasks();
+
+assertEquals(6, step_count);
diff --git a/src/v8/test/debugger/debug/es8/async-debug-step-in-and-out.js b/src/v8/test/debugger/debug/es8/async-debug-step-in-and-out.js
new file mode 100644
index 0000000..43fb16f
--- /dev/null
+++ b/src/v8/test/debugger/debug/es8/async-debug-step-in-and-out.js
@@ -0,0 +1,49 @@
+// 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.
+
+var Debug = debug.Debug;
+var step_count = 0;
+
+function listener(event, execState, eventData, data) {
+  if (event != Debug.DebugEvent.Break) return;
+  try {
+    var line = execState.frame(0).sourceLineText();
+    print(line);
+    var [match, expected_count, step] = /\/\/ B(\d) (\w+)$/.exec(line);
+    assertEquals(step_count++, parseInt(expected_count));
+    if (step != "Continue") execState.prepareStep(Debug.StepAction[step]);
+  } catch (e) {
+    print(e, e.stack);
+    quit(1);
+  }
+}
+
+Debug.setListener(listener);
+
+var late_resolve;
+
+function g() {
+  return new Promise(  // B2 StepOut
+    function(res, rej) {
+      late_resolve = res;
+    }
+  );
+}
+
+async function f() {
+  var a = 1;
+  debugger;            // B0 StepNext
+  a +=
+       await           // B1 StepIn
+             g();
+  return a;            // B3 StepNext
+}                      // B4 Continue
+
+f();
+
+late_resolve(3);
+
+%RunMicrotasks();
+
+assertEquals(5, step_count);
diff --git a/src/v8/test/debugger/debug/es8/async-debug-step-in-out-out.js b/src/v8/test/debugger/debug/es8/async-debug-step-in-out-out.js
new file mode 100644
index 0000000..c1d8fd7
--- /dev/null
+++ b/src/v8/test/debugger/debug/es8/async-debug-step-in-out-out.js
@@ -0,0 +1,49 @@
+// 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.
+
+var Debug = debug.Debug;
+var step_count = 0;
+
+function listener(event, execState, eventData, data) {
+  if (event != Debug.DebugEvent.Break) return;
+  try {
+    var line = execState.frame(0).sourceLineText();
+    print(line);
+    var [match, expected_count, step] = /\/\/ B(\d) (\w+)$/.exec(line);
+    assertEquals(step_count++, parseInt(expected_count));
+    if (step != "Continue") execState.prepareStep(Debug.StepAction[step]);
+  } catch (e) {
+    print(e, e.stack);
+    quit(1);
+  }
+}
+
+Debug.setListener(listener);
+
+var late_resolve;
+
+function g() {
+  return new Promise( // B2 StepOut
+    function(res, rej) {
+      late_resolve = res;
+    }
+  );
+}
+
+async function f() {
+  var a = 1;
+  debugger;        // B0 StepNext
+  a +=
+       await       // B1 StepIn
+             g();
+  return a;        // B3 Continue
+}
+
+f();
+
+late_resolve(3);
+
+%RunMicrotasks();
+
+assertEquals(4, step_count);
diff --git a/src/v8/test/debugger/debug/es8/async-debug-step-in.js b/src/v8/test/debugger/debug/es8/async-debug-step-in.js
new file mode 100644
index 0000000..c32fa2f
--- /dev/null
+++ b/src/v8/test/debugger/debug/es8/async-debug-step-in.js
@@ -0,0 +1,49 @@
+// 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.
+
+var Debug = debug.Debug;
+var step_count = 0;
+
+function listener(event, execState, eventData, data) {
+  if (event != Debug.DebugEvent.Break) return;
+  try {
+    var line = execState.frame(0).sourceLineText();
+    print(line);
+    var [match, expected_count, step] = /\/\/ B(\d) (\w+)$/.exec(line);
+    assertEquals(step_count++, parseInt(expected_count));
+    if (step != "Continue") execState.prepareStep(Debug.StepAction[step]);
+  } catch (e) {
+    print(e, e.stack);
+    quit(1);
+  }
+}
+
+Debug.setListener(listener);
+
+var late_resolve;
+
+function g() {
+  return new Promise(  // B2 StepIn
+    function(res, rej) {
+      late_resolve = res;  // B3 StepIn
+    }                      // B4 StepIn
+  );                       // B5 StepIn
+}
+
+async function f() {
+  var a = 1;
+  debugger;            // B0 StepNext
+  a +=
+       await           // B1 StepIn
+             g();
+  return a;            // B6 StepIn
+}                      // B7 Continue
+
+f().then(value => assertEquals(4, value));
+
+late_resolve(3);
+
+%RunMicrotasks();
+
+assertEquals(8, step_count);
diff --git a/src/v8/test/debugger/debug/es8/async-debug-step-nested.js b/src/v8/test/debugger/debug/es8/async-debug-step-nested.js
new file mode 100644
index 0000000..79e8dfaa
--- /dev/null
+++ b/src/v8/test/debugger/debug/es8/async-debug-step-nested.js
@@ -0,0 +1,56 @@
+// 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.
+
+var Debug = debug.Debug;
+var step_count = 0;
+
+function listener(event, execState, eventData, data) {
+  if (event != Debug.DebugEvent.Break) return;
+  try {
+    var line = execState.frame(0).sourceLineText();
+    print(line);
+    var [match, expected_count, step] = /\/\/ B(\d) (\w+)$/.exec(line);
+    assertEquals(step_count++, parseInt(expected_count));
+    if (step != "Continue") execState.prepareStep(Debug.StepAction[step]);
+  } catch (e) {
+    print(e, e.stack);
+    quit(1);
+  }
+}
+
+Debug.setListener(listener);
+
+var late_resolve;
+
+function g() {
+  return new Promise( // B3 StepOut
+    function(res, rej) {
+      late_resolve = res;
+    }
+  );
+}
+
+async function f1() {
+  var a = 1;
+  debugger;          // B0 StepNext
+  a +=
+       await         // B1 StepIn
+             f2();   // B2 StepIn
+  return a;          // B5 StepNext
+}                    // B6 Continue
+
+async function f2() {
+  var b = 0 +        // B2 StepIn
+          await
+                g();
+  return b;          // B4 StepOut
+}
+
+f1();
+
+late_resolve(3);
+
+%RunMicrotasks();
+
+assertEquals(7, step_count);
diff --git a/src/v8/test/debugger/debug/es8/async-debug-step-next-constant.js b/src/v8/test/debugger/debug/es8/async-debug-step-next-constant.js
new file mode 100644
index 0000000..32833ac
--- /dev/null
+++ b/src/v8/test/debugger/debug/es8/async-debug-step-next-constant.js
@@ -0,0 +1,37 @@
+// 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.
+
+var Debug = debug.Debug;
+var step_count = 0;
+
+function listener(event, execState, eventData, data) {
+  if (event != Debug.DebugEvent.Break) return;
+  try {
+    var line = execState.frame(0).sourceLineText();
+    print(line);
+    var [match, expected_count, step] = /\/\/ B(\d) (\w+)$/.exec(line);
+    assertEquals(step_count++, parseInt(expected_count));
+    if (step != "Continue") execState.prepareStep(Debug.StepAction[step]);
+  } catch (e) {
+    print(e, e.stack);
+    quit(1);
+  }
+}
+
+Debug.setListener(listener);
+
+async function f() {
+  var a = 1;
+  debugger;          // B0 StepNext
+  a +=               // B1 StepNext
+       await
+             5;
+  return a;          // B2 StepNext
+}                    // B3 Continue
+
+f();
+
+%RunMicrotasks();
+
+assertEquals(4, step_count);
diff --git a/src/v8/test/debugger/debug/es8/async-debug-step-next.js b/src/v8/test/debugger/debug/es8/async-debug-step-next.js
new file mode 100644
index 0000000..597afd3
--- /dev/null
+++ b/src/v8/test/debugger/debug/es8/async-debug-step-next.js
@@ -0,0 +1,49 @@
+// 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.
+
+var Debug = debug.Debug;
+var step_count = 0;
+
+function listener(event, execState, eventData, data) {
+  if (event != Debug.DebugEvent.Break) return;
+  try {
+    var line = execState.frame(0).sourceLineText();
+    print(line);
+    var [match, expected_count, step] = /\/\/ B(\d) (\w+)$/.exec(line);
+    assertEquals(step_count++, parseInt(expected_count));
+    if (step != "Continue") execState.prepareStep(Debug.StepAction[step]);
+  } catch (e) {
+    print(e, e.stack);
+    quit(1);
+  }
+}
+
+Debug.setListener(listener);
+
+var late_resolve;
+
+function g() {
+  return new Promise(
+    function(res, rej) {
+      late_resolve = res;
+    }
+  );
+}
+
+async function f() {
+  var a = 1;
+  debugger;        // B0 StepNext
+  a +=
+       await       // B1 StepNext
+             g();
+  return a;        // B2 StepNext
+}                  // B3 Continue
+
+f();
+
+late_resolve(3);
+
+%RunMicrotasks();
+
+assertEquals(4, step_count);
diff --git a/src/v8/test/debugger/debug/es8/async-debug-step-out.js b/src/v8/test/debugger/debug/es8/async-debug-step-out.js
new file mode 100644
index 0000000..3ec6dd3
--- /dev/null
+++ b/src/v8/test/debugger/debug/es8/async-debug-step-out.js
@@ -0,0 +1,47 @@
+// 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.
+
+var Debug = debug.Debug;
+var step_count = 0;
+
+function listener(event, execState, eventData, data) {
+  if (event != Debug.DebugEvent.Break) return;
+  try {
+    var line = execState.frame(0).sourceLineText();
+    print(line);
+    var [match, expected_count, step] = /\/\/ B(\d) (\w+)$/.exec(line);
+    assertEquals(step_count++, parseInt(expected_count));
+    if (step != "Continue") execState.prepareStep(Debug.StepAction[step]);
+  } catch (e) {
+    print(e, e.stack);
+    quit(1);
+  }
+}
+
+Debug.setListener(listener);
+
+var late_resolve;
+
+function g() {
+  return new Promise(
+    function(res, rej) {
+      late_resolve = res;
+    }
+  );
+}
+
+async function f() {
+  var a = 1;
+  debugger;        // B0 StepNext
+  a += await g();  // B1 StepOut
+  return a;
+}
+
+f();
+
+late_resolve(3);   // B2 Continue
+
+%RunMicrotasks();
+
+assertEquals(3, step_count);
diff --git a/src/v8/test/debugger/debug/es8/async-function-debug-evaluate.js b/src/v8/test/debugger/debug/es8/async-function-debug-evaluate.js
new file mode 100644
index 0000000..c1fe532
--- /dev/null
+++ b/src/v8/test/debugger/debug/es8/async-function-debug-evaluate.js
@@ -0,0 +1,137 @@
+// Copyright 2016 the V8 project authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+// Flags: --noalways-opt
+
+var Debug = debug.Debug;
+var breakPointCount = 0;
+
+function listener(event, exec_state, event_data, data) {
+  if (event != Debug.DebugEvent.Break) return;
+  ++breakPointCount;
+  try {
+    if (breakPointCount === 1) {
+      assertEquals(
+          "inner", exec_state.frame(0).evaluate("inner").value());
+      // Variables in TDZ have 'undefined' as their values.
+      assertEquals(undefined, exec_state.frame(0).evaluate("letInner").value());
+      assertEquals(undefined, exec_state.frame(0).evaluate("constInner").value());
+
+      assertEquals("outer", exec_state.frame(0).evaluate("outer").value());
+      assertEquals(
+          "const outer", exec_state.frame(0).evaluate("constOuter").value());
+      assertEquals(
+          "let outer", exec_state.frame(0).evaluate("letOuter").value());
+
+      assertEquals("outer", exec_state.frame(1).evaluate("outer").value());
+      assertEquals(
+          "const outer", exec_state.frame(1).evaluate("constOuter").value());
+      assertEquals(
+          "let outer", exec_state.frame(1).evaluate("letOuter").value());
+
+      // Variables in TDZ have 'undefined' as their values.
+      assertEquals(undefined, exec_state.frame(0).evaluate("withVar").value());
+
+    } else if (breakPointCount === 2) {
+      assertEquals(
+          "inner", exec_state.frame(0).evaluate("inner").value());
+      // Variables in TDZ have 'undefined' as their values.
+      assertEquals(undefined, exec_state.frame(0).evaluate("letInner").value());
+      assertEquals(undefined, exec_state.frame(0).evaluate("constInner").value());
+
+      assertEquals(57, exec_state.frame(0).evaluate("x").value());
+      assertEquals(100, exec_state.frame(0).evaluate("y").value());
+
+      // From breakPointCount === 1 and later, it's not possible to access
+      // earlier framestates.
+      assertEquals("outer", exec_state.frame(0).evaluate("outer").value());
+      assertEquals(
+          "const outer", exec_state.frame(0).evaluate("constOuter").value());
+      assertEquals(
+          "let outer", exec_state.frame(0).evaluate("letOuter").value());
+
+      exec_state.frame(0).evaluate("x = `x later(${x})`");
+      exec_state.frame(0).evaluate("y = `y later(${y})`");
+      exec_state.frame(0).evaluate("z = `ZEE`");
+
+    } else if (breakPointCount === 3) {
+      assertEquals(
+          "inner", exec_state.frame(0).evaluate("inner").value());
+      assertEquals(
+          "let inner", exec_state.frame(0).evaluate("letInner").value());
+      assertEquals(
+          "const inner", exec_state.frame(0).evaluate("constInner").value());
+
+    } else if (breakPointCount === 4) {
+      assertEquals(
+          "oop", exec_state.frame(0).evaluate("error.message").value());
+      assertEquals(
+          "Error",
+          exec_state.frame(0).evaluate("error.constructor.name").value());
+      assertEquals("floof", exec_state.frame(0).evaluate("bun").value());
+      // Variables in TDZ have 'undefined' as their values.
+      assertEquals(undefined, exec_state.frame(0).evaluate("cow").value())
+
+      assertEquals("outer", exec_state.frame(0).evaluate("outer").value());
+      assertEquals(
+          "const outer", exec_state.frame(0).evaluate("constOuter").value());
+      assertEquals(
+          "let outer", exec_state.frame(0).evaluate("letOuter").value());
+    }
+  } catch (e) {
+    print(e.stack);
+    quit(1);
+  }
+}
+
+Debug.setListener(listener);
+
+var outer = "outer";
+const constOuter = "const outer";
+let letOuter = "let outer"
+
+async function thrower() {
+  return Promise.reject(new Error("oop"));
+}
+
+async function testLater() {
+  return { x: 57, y: 100 };
+}
+
+async function test() {
+  var inner = "inner";
+  debugger;
+
+  let withVar = await testLater();
+  with (withVar) {
+    debugger;
+  }
+
+  assertEquals("x later(57)", withVar.x);
+  assertEquals("y later(100)", withVar.y);
+  assertEquals(undefined, withVar.z);
+  assertEquals("ZEE", z);
+
+  let letInner = "let inner";
+  const constInner = "const inner";
+  debugger;
+
+  try {
+    await thrower();
+  } catch (error) {
+    const bun = "floof";
+    debugger;
+    let cow = "moo";
+  }
+}
+
+test().
+then(x => {
+  Debug.setListener(null);
+}).
+catch(error => {
+  print(error.stack);
+  quit(1);
+  Debug.setListener(null);
+});
diff --git a/src/v8/test/debugger/debug/es8/async-function-debug-scopes.js b/src/v8/test/debugger/debug/es8/async-function-debug-scopes.js
new file mode 100644
index 0000000..172ec8f
--- /dev/null
+++ b/src/v8/test/debugger/debug/es8/async-function-debug-scopes.js
@@ -0,0 +1,550 @@
+// Copyright 2016 the V8 project authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+// Flags: --noalways-opt
+
+var Debug = debug.Debug;
+var global_marker = 7;
+
+async function thrower() { throw 'Exception'; }
+
+async function test(name, func, 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;
+    }
+  }
+
+  Debug.setListener(listener);
+
+  var result;
+  if (typeof func === "object")
+    result = await func.method.apply(func, args);
+  else
+    result = await func.apply(null, args);
+
+  if (typeof continuation === "function") {
+    await continuation(result);
+  }
+
+  assertTrue(handler_called, `Expected ${name} handler to be called`);
+  if (exception) {
+    exception.message = `${name} / ${exception.message}`;
+    print(exception.stack);
+    quit(1);
+  }
+
+  Debug.setListener(null);
+}
+
+async function runTests() {
+
+// Simple
+await test(
+    "(AsyncFunctionExpression) Local 1",
+    async function() { debugger; }, [],
+    exec_state => {
+      CheckScopeChain([debug.ScopeType.Local,
+                       debug.ScopeType.Closure,
+                       debug.ScopeType.Script,
+                       debug.ScopeType.Global], exec_state);
+      CheckScopeContent({}, 0, exec_state);
+    });
+
+await test(
+    "(AsyncFunctionExpression) Local 1 --- resume normal",
+    async function() { let z = await 2; debugger; }, [],
+    exec_state => {
+      CheckScopeChain([debug.ScopeType.Local,
+                       debug.ScopeType.Closure,
+                       debug.ScopeType.Script,
+                       debug.ScopeType.Global], exec_state);
+      CheckScopeContent({z: 2}, 0, exec_state);
+    });
+
+await test(
+    "(AsyncFunctionExpression) Local 1 --- resume throw",
+    async function() { let q = await 1;
+                       try { let z = await thrower(); }
+                       catch (e) { debugger; } }, [],
+    exec_state => {
+      CheckScopeChain([debug.ScopeType.Catch,
+                       debug.ScopeType.Local,
+                       debug.ScopeType.Closure,
+                       debug.ScopeType.Script,
+                       debug.ScopeType.Global], exec_state);
+      CheckScopeContent({e: 'Exception'}, 0, exec_state);
+      CheckScopeContent({q: 1}, 1, exec_state);
+
+    });
+
+// Simple With Parameter
+await test(
+    "(AsyncFunctionExpression) Local 2",
+    async function(a) { debugger; }, [1],
+    exec_state => {
+      CheckScopeChain([debug.ScopeType.Local,
+                       debug.ScopeType.Closure,
+                       debug.ScopeType.Script,
+                       debug.ScopeType.Global], exec_state);
+      CheckScopeContent({ a: 1 }, 0, exec_state);
+    });
+
+await test(
+    "(AsyncFunctionExpression) Local 2 --- resume normal",
+    async function(a) { let z = await 2; debugger; }, [1],
+    exec_state => {
+      CheckScopeChain([debug.ScopeType.Local,
+                       debug.ScopeType.Closure,
+                       debug.ScopeType.Script,
+                       debug.ScopeType.Global], exec_state);
+      CheckScopeContent({ a: 1, z: 2 }, 0, exec_state);
+    });
+
+await test(
+    "(AsyncFunctionExpression) Local 2 --- resume throw",
+    async function(a) { let z = await 2;
+                        try { await thrower(); } catch (e) { debugger; } }, [1],
+    exec_state => {
+      CheckScopeChain([debug.ScopeType.Catch,
+                       debug.ScopeType.Local,
+                       debug.ScopeType.Closure,
+                       debug.ScopeType.Script,
+                       debug.ScopeType.Global], exec_state);
+      CheckScopeContent({ e: 'Exception' }, 0, exec_state);
+      CheckScopeContent({ a: 1, z: 2 }, 1, exec_state);
+    });
+
+// Simple With Parameter and Variable
+await test(
+    "(AsyncFunctionExpression) Local 3",
+    async function(a) { var b = 2; debugger; }, [1],
+    exec_state => {
+      CheckScopeChain([debug.ScopeType.Local,
+                       debug.ScopeType.Closure,
+                       debug.ScopeType.Script,
+                       debug.ScopeType.Global], exec_state);
+      CheckScopeContent({ a: 1, b: 2 }, 0, exec_state);
+    });
+
+await test(
+    "(AsyncFunctionExpression) Local 3 --- resume normal",
+    async function(a) { let y = await 3; var b = 2; let z = await 4;
+                        debugger; }, [1],
+    exec_state => {
+      CheckScopeChain([debug.ScopeType.Local,
+                       debug.ScopeType.Closure,
+                       debug.ScopeType.Script,
+                       debug.ScopeType.Global], exec_state);
+      CheckScopeContent({ a: 1, b: 2, y: 3, z: 4 }, 0, exec_state);
+    });
+
+await test(
+    "(AsyncFunctionExpression) Local 3 --- resume throw",
+    async function(a) { let y = await 3;
+                        try { var b = 2; let z = await thrower(); }
+                        catch (e) { debugger; } }, [1],
+    exec_state => {
+      CheckScopeChain([debug.ScopeType.Catch,
+                       debug.ScopeType.Local,
+                       debug.ScopeType.Closure,
+                       debug.ScopeType.Script,
+                       debug.ScopeType.Global], exec_state);
+      CheckScopeContent({ e: 'Exception' }, 0, exec_state);
+      CheckScopeContent({ a: 1, b: 2, y: 3 }, 1, exec_state);
+    });
+
+// Local scope with parameters and local variables.
+await test(
+    "(AsyncFunctionExpression) Local 4",
+    async function(a, b) { var x = 3; var y = 4; debugger; }, [1, 2],
+    exec_state => {
+      CheckScopeChain([debug.ScopeType.Local,
+                       debug.ScopeType.Closure,
+                       debug.ScopeType.Script,
+                       debug.ScopeType.Global], exec_state);
+      CheckScopeContent({a:1,b:2,x:3,y:4}, 0, exec_state);
+    });
+
+await test(
+    "(AsyncFunctionExpression) Local 4 --- resume normal",
+    async function(a, b) { let q = await 5; var x = 3; var y = 4;
+                           let r = await 6; debugger; }, [1, 2],
+    exec_state => {
+      CheckScopeChain([debug.ScopeType.Local,
+                       debug.ScopeType.Closure,
+                       debug.ScopeType.Script,
+                       debug.ScopeType.Global], exec_state);
+      CheckScopeContent({a:1,b:2,x:3,y:4, q: 5, r: 6}, 0, exec_state);
+    });
+
+await test(
+    "(AsyncFunctionExpression) Local 4 --- resume throw",
+    async function(a, b) { let q = await 5; var x = 3; var y = 4;
+                           try { let r = await thrower(); }
+                           catch (e) { debugger; } }, [1, 2],
+    exec_state => {
+      CheckScopeChain([debug.ScopeType.Catch,
+                       debug.ScopeType.Local,
+                       debug.ScopeType.Closure,
+                       debug.ScopeType.Script,
+                       debug.ScopeType.Global], exec_state);
+      CheckScopeContent({e: 'Exception'}, 0, exec_state);
+      CheckScopeContent({a:1,b:2,x:3,y:4, q: 5}, 1, exec_state);
+    });
+
+// Empty local scope with use of eval.
+await test(
+    "(AsyncFunctionExpression) Local 5",
+    async function() { eval(""); debugger; }, [],
+    exec_state => {
+      CheckScopeChain([debug.ScopeType.Local,
+                       debug.ScopeType.Closure,
+                       debug.ScopeType.Script,
+                       debug.ScopeType.Global], exec_state);
+      CheckScopeContent({}, 0, exec_state);
+    });
+
+await test(
+    "(AsyncFunctionExpression) Local 5 --- resume normal",
+    async function() { let x = await 1; eval(""); let y = await 2;
+                       debugger; }, [],
+    exec_state => {
+      CheckScopeChain([debug.ScopeType.Local,
+                       debug.ScopeType.Closure,
+                       debug.ScopeType.Script,
+                       debug.ScopeType.Global], exec_state);
+      CheckScopeContent({ x: 1, y: 2 }, 0, exec_state);
+    });
+
+await test(
+    "(AsyncFunctionExpression) Local 5 --- resume throw",
+    async function() { let x = await 1; eval("");
+                       try { let y = await thrower(); }
+                       catch (e) { debugger; } }, [],
+    exec_state => {
+      CheckScopeChain([debug.ScopeType.Catch,
+                       debug.ScopeType.Local,
+                       debug.ScopeType.Closure,
+                       debug.ScopeType.Script,
+                       debug.ScopeType.Global], exec_state);
+      CheckScopeContent({ e: 'Exception' }, 0, exec_state);
+      CheckScopeContent({ x: 1 }, 1, exec_state);
+    });
+
+// Local introducing local variable using eval.
+await test(
+    "(AsyncFunctionExpression) Local 6",
+    async function() { eval("var i = 5"); debugger; }, [],
+    exec_state => {
+      CheckScopeChain([debug.ScopeType.Local,
+                       debug.ScopeType.Closure,
+                       debug.ScopeType.Script,
+                       debug.ScopeType.Global], exec_state);
+      CheckScopeContent({i:5}, 0, exec_state);
+    });
+
+await test(
+    "(AsyncFunctionExpression) Local 6 --- resume normal",
+    async function() { let x = await 1; eval("var i = 5"); let y = await 2;
+                       debugger; }, [],
+    exec_state => {
+      CheckScopeChain([debug.ScopeType.Local,
+                       debug.ScopeType.Closure,
+                       debug.ScopeType.Script,
+                       debug.ScopeType.Global], exec_state);
+      CheckScopeContent({i:5, x: 1, y: 2}, 0, exec_state);
+    });
+
+await test(
+    "(AsyncFunctionExpression) Local 6 --- resume throw",
+    async function() { let x = await 1; eval("var i = 5");
+                       try { let y = await thrower(); }
+                       catch (e) { debugger; } }, [],
+    exec_state => {
+      CheckScopeChain([debug.ScopeType.Catch,
+                       debug.ScopeType.Local,
+                       debug.ScopeType.Closure,
+                       debug.ScopeType.Script,
+                       debug.ScopeType.Global], exec_state);
+      CheckScopeContent({e: 'Exception' }, 0, exec_state);
+      CheckScopeContent({i:5, x: 1}, 1, exec_state);
+    });
+
+// Local scope with parameters, local variables and local variable introduced
+// using eval.
+await test(
+    "(AsyncFunctionExpression) Local 7",
+    async function(a, b) { var x = 3; var y = 4;
+                           eval("var i = 5;"); eval("var j = 6");
+                           debugger; }, [1, 2],
+    exec_state => {
+      CheckScopeChain([debug.ScopeType.Local,
+                       debug.ScopeType.Closure,
+                       debug.ScopeType.Script,
+                       debug.ScopeType.Global], exec_state);
+      CheckScopeContent({a:1,b:2,x:3,y:4,i:5,j:6}, 0, exec_state);
+    });
+
+await test(
+    "(AsyncFunctionExpression) Local 7 --- resume normal",
+    async function(a, b) { let z = await 7; var x = 3; var y = 4;
+                           eval("var i = 5;"); eval("var j = 6");
+                           let q = await 8;
+                           debugger; }, [1, 2],
+    exec_state => {
+      CheckScopeChain([debug.ScopeType.Local,
+                       debug.ScopeType.Closure,
+                       debug.ScopeType.Script,
+                       debug.ScopeType.Global], exec_state);
+      CheckScopeContent({a:1,b:2,x:3,y:4,i:5,j:6, z:7, q:8}, 0, exec_state);
+    });
+
+await test(
+    "(AsyncFunctionExpression) Local 7 --- resume throw",
+    async function(a, b) { let z = await 7; var x = 3; var y = 4;
+                           eval("var i = 5;"); eval("var j = 6");
+                           try { let q = await thrower(); }
+                           catch (e) { debugger; } }, [1, 2],
+    exec_state => {
+      CheckScopeChain([debug.ScopeType.Catch,
+                       debug.ScopeType.Local,
+                       debug.ScopeType.Closure,
+                       debug.ScopeType.Script,
+                       debug.ScopeType.Global], exec_state);
+      CheckScopeContent({e: 'Exception'}, 0, exec_state);
+      //CheckScopeContent({a:1,b:2,x:3,y:4,i:5,j:6, z:7}, 1, exec_state);
+    });
+
+// Nested empty with blocks.
+await test(
+    "(AsyncFunctionExpression) With",
+    async function() { with ({}) { with ({}) { debugger; } } }, [],
+    exec_state => {
+      CheckScopeChain([debug.ScopeType.With,
+                       debug.ScopeType.With,
+                       debug.ScopeType.Local,
+                       debug.ScopeType.Closure,
+                       debug.ScopeType.Script,
+                       debug.ScopeType.Global], exec_state);
+      CheckScopeContent({}, 0, exec_state);
+      CheckScopeContent({}, 1, exec_state);
+    });
+
+await test(
+    "(AsyncFunctionExpression) With --- resume normal",
+    async function() { let x = await 1; with ({}) { with ({}) {
+                       let y = await 2; debugger; } } }, [],
+    exec_state => {
+      CheckScopeChain([debug.ScopeType.Block,
+                       debug.ScopeType.With,
+                       debug.ScopeType.With,
+                       debug.ScopeType.Local,
+                       debug.ScopeType.Closure,
+                       debug.ScopeType.Script,
+                       debug.ScopeType.Global], exec_state);
+      CheckScopeContent({y:2}, 0, exec_state);
+      CheckScopeContent({}, 1, exec_state);
+      CheckScopeContent({}, 2, exec_state);
+      CheckScopeContent({x:1}, 3, exec_state);
+    });
+
+await test(
+    "(AsyncFunctionExpression) With --- resume throw",
+    async function() { let x = await 1; with ({}) { with ({}) {
+                       try { let y = await thrower(); }
+                       catch (e) { debugger; } } } }, [],
+    exec_state => {
+      CheckScopeChain([debug.ScopeType.Catch,
+                       debug.ScopeType.With,
+                       debug.ScopeType.With,
+                       debug.ScopeType.Local,
+                       debug.ScopeType.Closure,
+                       debug.ScopeType.Script,
+                       debug.ScopeType.Global], exec_state);
+      CheckScopeContent({ e: 'Exception'}, 0, exec_state);
+      CheckScopeContent({}, 1, exec_state);
+      CheckScopeContent({}, 2, exec_state);
+      CheckScopeContent({x:1}, 3, exec_state);
+    });
+
+// Simple closure formed by returning an inner function referering the outer
+// functions arguments.
+await test(
+    "(AsyncFunctionExpression) Closure 1",
+    async function(a) { return function() { debugger; return a; } }, [1],
+    exec_state => {
+      CheckScopeChain([debug.ScopeType.Local,
+                       debug.ScopeType.Closure,
+                       debug.ScopeType.Closure,
+                       debug.ScopeType.Script,
+                       debug.ScopeType.Global], exec_state);
+      CheckScopeContent({a:1}, 1, exec_state);
+    },
+    result => result());
+
+await test(
+    "(AsyncFunctionExpression) Closure 1 --- resume normal",
+    async function(a) { let x = await 2;
+                        return function() { debugger; return a; } }, [1],
+    exec_state => {
+      CheckScopeChain([debug.ScopeType.Local,
+                       debug.ScopeType.Closure,
+                       debug.ScopeType.Closure,
+                       debug.ScopeType.Script,
+                       debug.ScopeType.Global], exec_state);
+      CheckScopeContent({a:1}, 1, exec_state);
+    },
+    result => result());
+
+await test(
+    "(AsyncFunctionExpression) Closure 1 --- resume throw",
+    async function(a) { let x = await 2;
+                        return async function() {
+                            try { await thrower(); }
+                            catch (e) { debugger; } return a; }; }, [1],
+    exec_state => {
+      CheckScopeChain([debug.ScopeType.Catch,
+                       debug.ScopeType.Local,
+                       debug.ScopeType.Closure,
+                       debug.ScopeType.Closure,
+                       debug.ScopeType.Script,
+                       debug.ScopeType.Global], exec_state);
+      CheckScopeContent({e: 'Exception'}, 0, exec_state);
+      CheckScopeContent({a:1}, 2, exec_state);
+    },
+    result => result());
+
+await test(
+    "(AsyncFunctionExpression) Catch block 1",
+    async function() { try { throw 'Exception'; } catch (e) { debugger; } }, [],
+    exec_state => {
+      CheckScopeChain([debug.ScopeType.Catch,
+                       debug.ScopeType.Local,
+                       debug.ScopeType.Closure,
+                       debug.ScopeType.Script,
+                       debug.ScopeType.Global], exec_state);
+      CheckScopeContent({e:'Exception'}, 0, exec_state);
+    });
+
+await test(
+    "(AsyncFunctionExpression) Catch block 1 --- resume normal",
+    async function() {
+      let x = await 1;
+      try { throw 'Exception'; } catch (e) { let y = await 2; debugger; } }, [],
+    exec_state => {
+      CheckScopeChain([debug.ScopeType.Block,
+                       debug.ScopeType.Catch,
+                       debug.ScopeType.Local,
+                       debug.ScopeType.Closure,
+                       debug.ScopeType.Script,
+                       debug.ScopeType.Global], exec_state);
+      CheckScopeContent({y: 2}, 0, exec_state);
+      CheckScopeContent({e:'Exception'}, 1, exec_state);
+      CheckScopeContent({x: 1}, 2, exec_state);
+    });
+
+await test(
+    "(AsyncFunctionExpression) Catch block 1 --- resume throw",
+    async function() {
+      let x = await 1;
+      try { throw 'Exception!'; } catch (e) {
+        try { let y = await thrower(); } catch (e) { debugger; } } }, [],
+    exec_state => {
+      CheckScopeChain([debug.ScopeType.Catch,
+                       debug.ScopeType.Catch,
+                       debug.ScopeType.Local,
+                       debug.ScopeType.Closure,
+                       debug.ScopeType.Script,
+                       debug.ScopeType.Global], exec_state);
+      CheckScopeContent({e:'Exception'}, 0, exec_state);
+      CheckScopeContent({e:'Exception!'}, 1, exec_state);
+      CheckScopeContent({x: 1}, 2, exec_state);
+    });
+}
+
+runTests().catch(error => {
+  print(error.stack);
+  quit(1);
+})
+
+// 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, 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);
+}
diff --git a/src/v8/test/debugger/debug/es8/debug-async-break-on-stack.js b/src/v8/test/debugger/debug/es8/debug-async-break-on-stack.js
new file mode 100644
index 0000000..df389f3
--- /dev/null
+++ b/src/v8/test/debugger/debug/es8/debug-async-break-on-stack.js
@@ -0,0 +1,75 @@
+// 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.
+
+var Debug = debug.Debug;
+
+function assertEqualsAsync(expected, run, msg) {
+  var actual;
+  var hadValue = false;
+  var hadError = false;
+  var promise = run();
+
+  if (typeof promise !== "object" || typeof promise.then !== "function") {
+    throw new MjsUnitAssertionError(
+        "Expected " + run.toString() +
+        " to return a Promise, but it returned " + promise);
+  }
+
+  promise.then(function(value) { hadValue = true; actual = value; },
+               function(error) { hadError = true; actual = error; });
+
+  assertFalse(hadValue || hadError);
+
+  %RunMicrotasks();
+
+  if (hadError) throw actual;
+
+  assertTrue(
+      hadValue, "Expected '" + run.toString() + "' to produce a value");
+
+  assertEquals(expected, actual, msg);
+}
+
+var break_count = 0;
+var exception = null;
+
+function listener(event, exec_state, event_data, data) {
+  if (event != Debug.DebugEvent.Break) return;
+  try {
+    break_count++;
+    var line = exec_state.frame(0).sourceLineText();
+    print(line);
+    assertTrue(line.indexOf(`B${break_count}`) > 0);
+  } catch (e) {
+    exception = e;
+  }
+}
+
+
+async function g() {
+  setbreaks();
+  throw 1;  // B1
+}
+
+async function f() {
+  try {
+    await g();
+  } catch (e) {}
+  return 2;  // B2
+}
+
+function setbreaks() {
+  Debug.setListener(listener);
+  Debug.setBreakPoint(g, 2);
+  Debug.setBreakPoint(f, 4);
+}
+
+f();
+
+%RunMicrotasks();
+
+assertEqualsAsync(2, async () => break_count);
+assertEqualsAsync(null, async () => exception);
+
+Debug.setListener(null);
diff --git a/src/v8/test/debugger/debug/es8/debug-async-break.js b/src/v8/test/debugger/debug/es8/debug-async-break.js
new file mode 100644
index 0000000..3e07ba9
--- /dev/null
+++ b/src/v8/test/debugger/debug/es8/debug-async-break.js
@@ -0,0 +1,73 @@
+// 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.
+
+var Debug = debug.Debug;
+
+function assertEqualsAsync(expected, run, msg) {
+  var actual;
+  var hadValue = false;
+  var hadError = false;
+  var promise = run();
+
+  if (typeof promise !== "object" || typeof promise.then !== "function") {
+    throw new MjsUnitAssertionError(
+        "Expected " + run.toString() +
+        " to return a Promise, but it returned " + promise);
+  }
+
+  promise.then(function(value) { hadValue = true; actual = value; },
+               function(error) { hadError = true; actual = error; });
+
+  assertFalse(hadValue || hadError);
+
+  %RunMicrotasks();
+
+  if (hadError) throw actual;
+
+  assertTrue(
+      hadValue, "Expected '" + run.toString() + "' to produce a value");
+
+  assertEquals(expected, actual, msg);
+}
+
+var break_count = 0;
+var exception = null;
+
+function listener(event, exec_state, event_data, data) {
+  if (event != Debug.DebugEvent.Break) return;
+  try {
+    break_count++;
+    var line = exec_state.frame(0).sourceLineText();
+    assertTrue(line.indexOf(`B${break_count}`) > 0);
+  } catch (e) {
+    exception = e;
+  }
+}
+
+Debug.setListener(listener);
+
+async function g() {
+  throw 1;
+}
+
+async function f() {
+  try {
+    await g();                   // B1
+  } catch (e) {}
+  assertEquals(2, break_count);  // B2
+  return 1;                      // B3
+}
+
+Debug.setBreakPoint(f, 2);
+Debug.setBreakPoint(f, 4);
+Debug.setBreakPoint(f, 5);
+
+f();
+
+%RunMicrotasks();
+
+assertEqualsAsync(3, async () => break_count);
+assertEqualsAsync(null, async () => exception);
+
+Debug.setListener(null);
diff --git a/src/v8/test/debugger/debug/es8/debug-async-liveedit.js b/src/v8/test/debugger/debug/es8/debug-async-liveedit.js
new file mode 100644
index 0000000..761a24f
--- /dev/null
+++ b/src/v8/test/debugger/debug/es8/debug-async-liveedit.js
@@ -0,0 +1,149 @@
+// 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.
+
+var Debug = debug.Debug;
+var LiveEdit = Debug.LiveEdit;
+
+unique_id = 0;
+
+var AsyncFunction = (async function(){}).constructor;
+
+function assertPromiseValue(value, promise) {
+  promise.then(resolve => {
+    went = true;
+    if (resolve !== value) {
+      print(`expected ${value} found ${resolve}`);
+      quit(1);
+    }
+  }, reject => {
+    print(`rejected ${reject}`);
+    quit(1);
+  });
+}
+
+function MakeAsyncFunction() {
+  // Prevents eval script caching.
+  unique_id++;
+  return AsyncFunction('callback',
+      "/* " + unique_id + "*/\n" +
+      "await 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 asyncfn = MakeAsyncFunction();
+  function callback() {};
+  var promise = asyncfn(callback);
+  assertPromiseValue('Cat', promise);
+})();
+
+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);
+    print(`pos ${pos}`);
+    try {
+      LiveEdit.TestApi.ApplySingleChunkPatch(script, pos, from.length, to,
+                                             log);
+    } finally {
+      print("Change log: " + JSON.stringify(log) + "\n");
+    }
+  }
+  ExecuteInDebugContext(debug);
+}
+
+// Try to edit a MakeAsyncFunction while it's running, then again while it's
+// stopped.
+(function(){
+  var asyncfn = MakeAsyncFunction();
+
+  var patch_attempted = false;
+  function attempt_patch() {
+    assertFalse(patch_attempted);
+    patch_attempted = true;
+    assertThrows(function() { patch(asyncfn, "'Cat'", "'Capybara'") },
+                 LiveEdit.Failure);
+  };
+  var promise = asyncfn(attempt_patch);
+  // Patch should not succeed because there is a live async function activation
+  // on the stack.
+  assertPromiseValue("Cat", promise);
+  assertTrue(patch_attempted);
+
+  %RunMicrotasks();
+
+  // At this point one iterator is live, but closed, so the patch will succeed.
+  patch(asyncfn, "'Cat'", "'Capybara'");
+  promise = asyncfn(function(){});
+  // Patch successful.
+  assertPromiseValue("Capybara", promise);
+
+  // Patching will fail however when an async function is suspended.
+  var resolve;
+  promise = asyncfn(function(){return new Promise(function(r){resolve = r})});
+  assertThrows(function() { patch(asyncfn, "'Capybara'", "'Tapir'") },
+               LiveEdit.Failure);
+  resolve();
+  assertPromiseValue("Capybara", promise);
+
+  // Try to patch functions with activations inside and outside async
+  // 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 an async function activation must fail.
+    assertThrows(function() { patch(fun_outside, "'Cat'", "'Cobra'") },
+                 LiveEdit.Failure);
+    // Patching inside an async function activation may succeed.
+    patch(fun_inside, "'Cat'", "'Koala'");
+  }
+  promise = asyncfn(function() { return fun_inside(attempt_fun_patches) });
+  assertEquals('Cat',
+               fun_outside(function () {
+                 assertPromiseValue('Capybara', promise);
+                 assertTrue(fun_patch_restarted);
+                 assertTrue(fun_inside.toString().includes("'Koala'"));
+               }));
+})();
+
+%RunMicrotasks();
diff --git a/src/v8/test/debugger/debug/es8/promise-finally.js b/src/v8/test/debugger/debug/es8/promise-finally.js
new file mode 100644
index 0000000..2598ae0
--- /dev/null
+++ b/src/v8/test/debugger/debug/es8/promise-finally.js
@@ -0,0 +1,46 @@
+// Copyright 2017 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-promise-finally
+
+Debug = debug.Debug
+
+var exception = null;
+var step = 0;
+
+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/.exec(line);
+    assertNotNull(match);
+    step++;
+  } catch (e) {
+    exception = e;
+  }
+}
+
+// Caught throw, events on any exception.
+Debug.setListener(listener);
+Debug.setBreakOnException();
+
+var thenable = {
+  get then() {
+    throw new Error('err');  // Exception
+  }
+};
+
+var caughtException = null;
+
+Promise.resolve()
+  .finally(() => thenable)
+  .catch(e => caughtException = e);
+
+%RunMicrotasks();
+
+Debug.setListener(null);
+Debug.clearBreakOnException();
+assertNull(exception);
+assertNotNull(caughtException);
+assertEquals(1, step);
diff --git a/src/v8/test/debugger/debug/for-in-opt.js b/src/v8/test/debugger/debug/for-in-opt.js
new file mode 100644
index 0000000..405199d
--- /dev/null
+++ b/src/v8/test/debugger/debug/for-in-opt.js
@@ -0,0 +1,156 @@
+// 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";
+
+// Test non-JSObject receiver.
+function f(o) {
+  var result = [];
+  for (var i in o) {
+    result.push(i);
+  }
+  return result;
+}
+
+assertEquals(["0"], f("a"));
+assertEquals(["0"], f("a"));
+
+%OptimizeFunctionOnNextCall(f);
+assertEquals(["0","1","2"], f("bla"));
+
+// Test the lazy deopt points.
+var keys = ["a", "b", "c", "d"];
+var property_descriptor_keys = [];
+var deopt_enum = false;
+var deopt_property_descriptor = false;
+
+var handler = {
+  ownKeys() {
+    if (deopt_enum) {
+      %DeoptimizeFunction(f2);
+      deopt_enum = false;
+    }
+    return keys;
+  },
+  getOwnPropertyDescriptor(target, k) {
+    if (deopt_property_descriptor) {
+      %DeoptimizeFunction(f2);
+      deopt_property_descriptor = false;
+    }
+    property_descriptor_keys.push(k);
+    return { enumerable: true, configurable: true }
+  },
+};
+
+
+var proxy = new Proxy({}, handler);
+var o = {__proto__: proxy};
+
+function f2(o) {
+  var result = [];
+  for (var i in o) {
+    result.push(i);
+  }
+  return result;
+}
+
+function check_f2() {
+  assertEquals(keys, f2(o));
+  assertEquals(keys, property_descriptor_keys);
+  property_descriptor_keys.length = 0;
+}
+
+check_f2();
+check_f2();
+
+// Test lazy deopt after ForInEnumerate
+%OptimizeFunctionOnNextCall(f2);
+deopt_enum = true;
+check_f2();
+
+// Test lazy deopt after FILTER_KEY
+%OptimizeFunctionOnNextCall(f2);
+deopt_property_descriptor = true;
+check_f2();
+
+
+function f3(o) {
+  for (var i in o) {
+  }
+}
+
+f3({__proto__:{x:1}});
+f3({__proto__:{x:1}});
+
+%OptimizeFunctionOnNextCall(f3);
+f3(undefined);
+f3(null);
+
+// Reliable repro for an issue previously flushed out by GC stress.
+var p = {x: "x"}
+
+function f4(o, p) {
+  var result = [];
+  for (var i in o) {
+    var j = p.x + "str";
+    result.push(i);
+  }
+  return result;
+}
+
+function check_f4() {
+  assertEquals(keys, f4(o, p));
+  assertEquals(keys, property_descriptor_keys);
+  property_descriptor_keys.length = 0;
+}
+
+check_f4();
+check_f4();
+
+%OptimizeFunctionOnNextCall(f4);
+
+p.y = "y";  // Change map, cause eager deopt.
+check_f4();
+
+// Repro for Turbofan equivalent.
+var x;
+var count = 0;
+
+var Debug = debug.Debug;
+
+function listener(event, exec_state, event_data, data) {
+  if (event == Debug.DebugEvent.Break) {
+    %DeoptimizeFunction(f5);
+  }
+}
+
+var handler3 = {
+  ownKeys() { return ["a", "b"] },
+  getOwnPropertyDescriptor(target, k) {
+    if (k == "a") count++;
+    if (x) %ScheduleBreak()
+    return { enumerable: true, configurable: true }
+  }
+};
+
+var proxy3 = new Proxy({}, handler3);
+var o3 = {__proto__: proxy3};
+
+function f5() {
+  for (var p in o3) {
+    print(p);
+  }
+}
+
+x = false;
+
+f5(); f5(); f5();
+%OptimizeFunctionOnNextCall(f5);
+x = true;
+count = 0;
+Debug.setListener(listener);
+f5();
+Debug.setListener(null);
+assertEquals(1, count);
diff --git a/src/v8/test/debugger/debug/function-source.js b/src/v8/test/debugger/debug/function-source.js
new file mode 100644
index 0000000..c5ebcfe
--- /dev/null
+++ b/src/v8/test/debugger/debug/function-source.js
@@ -0,0 +1,47 @@
+// Copyright 2008 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.
+
+Debug = debug.Debug
+
+// Check that the script source for all functions in a script is the same.
+function f() {
+  function h() {
+    assertEquals(Debug.scriptSource(f), Debug.scriptSource(h));
+  }
+  h();
+}
+
+function g() {
+  function h() {
+    assertEquals(Debug.scriptSource(f), Debug.scriptSource(h));
+  }
+  h();
+}
+
+assertEquals(Debug.scriptSource(f), Debug.scriptSource(g));
+f();
+g();
diff --git a/src/v8/test/debugger/debug/harmony/modules-debug-scopes1.js b/src/v8/test/debugger/debug/harmony/modules-debug-scopes1.js
new file mode 100644
index 0000000..cbecca9
--- /dev/null
+++ b/src/v8/test/debugger/debug/harmony/modules-debug-scopes1.js
@@ -0,0 +1,871 @@
+// 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.
+
+// MODULE
+// Flags: --allow-natives-syntax --noanalyze-environment-liveness
+
+// These tests are copied from mjsunit/debug-scopes.js and adapted for modules.
+
+
+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;
+
+
+// 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) {
+    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++;
+}
+
+
+// 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);
+  }
+  CheckFastAllScopes(scopes, exec_state);
+}
+
+
+// Check that the scope chain contains the expected names of scopes.
+function CheckScopeChainNames(names, exec_state) {
+  var all_scopes = exec_state.frame().allScopes();
+  assertEquals(names.length, all_scopes.length, "FrameMirror.allScopes length");
+  for (var i = 0; i < names.length; i++) {
+    var scope = exec_state.frame().scope(i);
+    assertEquals(names[i], scope.details().name())
+  }
+}
+
+
+// Check that the scope contains at least minimum_content. For functions just
+// check that there is a function.
+function CheckScopeContent(minimum_content, number, exec_state) {
+  var scope = exec_state.frame().scope(number);
+  var minimum_count = 0;
+  for (var p in minimum_content) {
+    var property_mirror = scope.scopeObject().property(p);
+    assertFalse(property_mirror.isUndefined(),
+                'property ' + p + ' not found in scope');
+    assertEquals(minimum_content[p], property_mirror.value().value(),
+                 'property ' + p + ' has unexpected value');
+    minimum_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--;
+  }
+  // Ditto for 'this'.
+  if (!scope.scopeObject().property('this').isUndefined()) {
+    scope_size--;
+  }
+  // Temporary variables introduced by the parser have not been materialized.
+  assertTrue(scope.scopeObject().property('').isUndefined());
+
+  if (scope_size < minimum_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 >= minimum_count);
+}
+
+// Check that the scopes have positions as expected.
+function CheckScopeChainPositions(positions, exec_state) {
+  var all_scopes = exec_state.frame().allScopes();
+  assertTrue(positions.length <= all_scopes.length,
+             "FrameMirror.allScopes length");
+  for (var i = 0; i < positions.length; i++) {
+    var scope = exec_state.frame().scope(i);
+    var position = positions[i];
+    if (!position)
+      continue;
+
+    print(
+        `Checking position.start = ${position.start}, .end = ${position.end}`);
+    assertEquals(position.start, scope.details().startPosition())
+    assertEquals(position.end, scope.details().endPosition())
+  }
+}
+
+// Simple empty local scope.
+BeginTest("Local 1");
+
+function local_1() {
+  debugger;
+}
+
+listener_delegate = function(exec_state) {
+  CheckScopeChain([debug.ScopeType.Local,
+                   debug.ScopeType.Module,
+                   debug.ScopeType.Script,
+                   debug.ScopeType.Global], exec_state);
+  CheckScopeContent({}, 0, exec_state);
+};
+local_1();
+EndTest();
+
+
+// Local scope with a parameter.
+BeginTest("Local 2");
+
+function local_2(a) {
+  debugger;
+}
+
+listener_delegate = function(exec_state) {
+  CheckScopeChain([debug.ScopeType.Local,
+                   debug.ScopeType.Module,
+                   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) {
+  var x = 3;
+  debugger;
+}
+
+listener_delegate = function(exec_state) {
+  CheckScopeChain([debug.ScopeType.Local,
+                   debug.ScopeType.Module,
+                   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) {
+  var x = 3;
+  var y = 4;
+  debugger;
+}
+
+listener_delegate = function(exec_state) {
+  CheckScopeChain([debug.ScopeType.Local,
+                   debug.ScopeType.Module,
+                   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();
+
+
+// Empty local scope with use of eval.
+BeginTest("Local 5");
+
+function local_5() {
+  eval('');
+  debugger;
+}
+
+listener_delegate = function(exec_state) {
+  CheckScopeChain([debug.ScopeType.Local,
+                   debug.ScopeType.Module,
+                   debug.ScopeType.Script,
+                   debug.ScopeType.Global], exec_state);
+  CheckScopeContent({}, 0, exec_state);
+};
+local_5();
+EndTest();
+
+
+// Local introducing local variable using eval.
+BeginTest("Local 6");
+
+function local_6() {
+  eval('var i = 5');
+  debugger;
+}
+
+listener_delegate = function(exec_state) {
+  CheckScopeChain([debug.ScopeType.Local,
+                   debug.ScopeType.Module,
+                   debug.ScopeType.Script,
+                   debug.ScopeType.Global], exec_state);
+  CheckScopeContent({}, 0, exec_state);
+};
+local_6();
+EndTest();
+
+
+// Local scope with parameters and local variables.
+BeginTest("Local 7");
+
+function local_7(a, b) {
+  var x = 3;
+  var y = 4;
+  eval('var i = 5');
+  eval('var j = 6');
+  debugger;
+}
+
+listener_delegate = function(exec_state) {
+  CheckScopeChain([debug.ScopeType.Local,
+                   debug.ScopeType.Module,
+                   debug.ScopeType.Script,
+                   debug.ScopeType.Global], exec_state);
+  CheckScopeContent({a:1,b:2,x:3,y:4}, 0, exec_state);
+};
+local_7(1, 2);
+EndTest();
+
+
+// Simple closure formed by returning an inner function referering the outer
+// functions arguments.
+BeginTest("Closure 1");
+
+function closure_1(a) {
+  function f() {
+    debugger;
+    return a;
+  };
+  return f;
+}
+
+listener_delegate = function(exec_state) {
+  CheckScopeChain([debug.ScopeType.Local,
+                   debug.ScopeType.Closure,
+                   debug.ScopeType.Module,
+                   debug.ScopeType.Script,
+                   debug.ScopeType.Global], exec_state);
+  CheckScopeContent({a:1}, 1, exec_state);
+  CheckScopeChainNames(["f", "closure_1", undefined, undefined, undefined], exec_state)
+};
+closure_1(1)();
+EndTest();
+
+
+// Simple closure formed by returning an inner function referering the outer
+// functions arguments. Due to VM optimizations parts of the actual closure is
+// missing from the debugger information.
+BeginTest("Closure 2");
+
+function closure_2(a, b) {
+  var x = a + 2;
+  var y = b + 2;
+  function f() {
+    debugger;
+    return a + x;
+  };
+  return f;
+}
+
+listener_delegate = function(exec_state) {
+  CheckScopeChain([debug.ScopeType.Local,
+                   debug.ScopeType.Closure,
+                   debug.ScopeType.Module,
+                   debug.ScopeType.Script,
+                   debug.ScopeType.Global], exec_state);
+  CheckScopeContent({a:1,x:3}, 1, exec_state);
+  CheckScopeChainNames(["f", "closure_2", undefined, undefined, undefined],
+                       exec_state)
+};
+closure_2(1, 2)();
+EndTest();
+
+
+// Simple closure formed by returning an inner function referering the outer
+// functions arguments. Using all arguments and locals from the outer function
+// in the inner function makes these part of the debugger information on the
+// closure.
+BeginTest("Closure 3");
+
+function closure_3(a, b) {
+  var x = a + 2;
+  var y = b + 2;
+  function f() {
+    debugger;
+    return a + b + x + y;
+  };
+  return f;
+}
+
+listener_delegate = function(exec_state) {
+  CheckScopeChain([debug.ScopeType.Local,
+                   debug.ScopeType.Closure,
+                   debug.ScopeType.Module,
+                   debug.ScopeType.Script,
+                   debug.ScopeType.Global], exec_state);
+  CheckScopeContent({a:1,b:2,x:3,y:4}, 1, exec_state);
+  CheckScopeChainNames(["f", "closure_3", undefined, undefined, undefined],
+                       exec_state)
+};
+closure_3(1, 2)();
+EndTest();
+
+
+
+// Simple closure formed by returning an inner function referering the outer
+// functions arguments. Using all arguments and locals from the outer function
+// in the inner function makes these part of the debugger information on the
+// closure. Use the inner function as well...
+BeginTest("Closure 4");
+
+function closure_4(a, b) {
+  var x = a + 2;
+  var y = b + 2;
+  function f() {
+    debugger;
+    if (f) {
+      return a + b + x + y;
+    }
+  };
+  return f;
+}
+
+listener_delegate = function(exec_state) {
+  CheckScopeChain([debug.ScopeType.Local,
+                   debug.ScopeType.Closure,
+                   debug.ScopeType.Module,
+                   debug.ScopeType.Script,
+                   debug.ScopeType.Global], exec_state);
+  CheckScopeContent({a:1,b:2,x:3,y:4,f:undefined}, 1, exec_state);
+  CheckScopeChainNames(["f", "closure_4", undefined, undefined, undefined],
+                       exec_state)
+};
+closure_4(1, 2)();
+EndTest();
+
+
+
+// Simple closure formed by returning an inner function referering the outer
+// functions arguments. In the presence of eval all arguments and locals
+// (including the inner function itself) from the outer function becomes part of
+// the debugger infformation on the closure.
+BeginTest("Closure 5");
+
+function closure_5(a, b) {
+  var x = 3;
+  var y = 4;
+  function f() {
+    eval('');
+    debugger;
+    return 1;
+  };
+  return f;
+}
+
+listener_delegate = function(exec_state) {
+  CheckScopeChain([debug.ScopeType.Local,
+                   debug.ScopeType.Closure,
+                   debug.ScopeType.Module,
+                   debug.ScopeType.Script,
+                   debug.ScopeType.Global], exec_state);
+  CheckScopeContent({a:1,b:2,x:3,y:4,f:undefined}, 1, exec_state);
+  CheckScopeChainNames(["f", "closure_5", undefined, undefined, undefined],
+                       exec_state)
+};
+closure_5(1, 2)();
+EndTest();
+
+
+// Two closures. Due to optimizations only the parts actually used are provided
+// through the debugger information.
+BeginTest("Closure 6");
+let some_global;
+function closure_6(a, b) {
+  function f(a, b) {
+    var x = 3;
+    var y = 4;
+    return function() {
+      var x = 3;
+      var y = 4;
+      debugger;
+      some_global = a;
+      return f;
+    };
+  }
+  return f(a, b);
+}
+
+listener_delegate = function(exec_state) {
+  CheckScopeChain([debug.ScopeType.Local,
+                   debug.ScopeType.Closure,
+                   debug.ScopeType.Closure,
+                   debug.ScopeType.Module,
+                   debug.ScopeType.Script,
+                   debug.ScopeType.Global], exec_state);
+  CheckScopeContent({a:1}, 1, exec_state);
+  CheckScopeContent({f:undefined}, 2, exec_state);
+  CheckScopeChainNames(
+      [undefined, "f", "closure_6", undefined, undefined, undefined],
+      exec_state);
+};
+closure_6(1, 2)();
+EndTest();
+
+
+// Two closures. In the presence of eval all information is provided as the
+// compiler cannot determine which parts are used.
+BeginTest("Closure 7");
+function closure_7(a, b) {
+  var x = 3;
+  var y = 4;
+  eval('var i = 5');
+  eval('var j = 6');
+  function f(a, b) {
+    var x = 3;
+    var y = 4;
+    eval('var i = 5');
+    eval('var j = 6');
+    return function() {
+      debugger;
+      some_global = a;
+      return f;
+    };
+  }
+  return f(a, b);
+}
+
+listener_delegate = function(exec_state) {
+  CheckScopeChain([debug.ScopeType.Local,
+                   debug.ScopeType.Closure,
+                   debug.ScopeType.Closure,
+                   debug.ScopeType.Module,
+                   debug.ScopeType.Script,
+                   debug.ScopeType.Global], exec_state);
+  CheckScopeContent({}, 0, exec_state);
+  CheckScopeContent({a:1,b:2,x:3,y:4}, 1, exec_state);
+  CheckScopeContent({a:1,b:2,x:3,y:4,f:undefined}, 2, exec_state);
+  CheckScopeChainNames(
+      [undefined, "f", "closure_7", undefined, undefined, undefined],
+      exec_state);
+};
+closure_7(1, 2)();
+EndTest();
+
+
+// Closure that may be optimized out.
+BeginTest("Closure 8");
+function closure_8() {
+  (function inner(x) {
+    debugger;
+  })(2);
+}
+
+listener_delegate = function(exec_state) {
+  CheckScopeChain([debug.ScopeType.Local,
+                   debug.ScopeType.Module,
+                   debug.ScopeType.Script,
+                   debug.ScopeType.Global], exec_state);
+  CheckScopeContent({x: 2}, 0, exec_state);
+  CheckScopeChainNames(["inner", undefined, undefined, undefined], exec_state);
+};
+closure_8();
+EndTest();
+
+
+BeginTest("Closure 9");
+let closure_9 = Function(' \
+  eval("var y = 1;"); \
+  eval("var z = 1;"); \
+  (function inner(x) { \
+    y++; \
+    z++; \
+    debugger; \
+  })(2); \
+')
+
+listener_delegate = function(exec_state) {
+  CheckScopeChain([debug.ScopeType.Local,
+                   debug.ScopeType.Closure,
+                   debug.ScopeType.Script,
+                   debug.ScopeType.Global], exec_state);
+  CheckScopeChainNames(["inner", undefined, undefined, undefined], exec_state);
+};
+closure_9();
+EndTest();
+
+
+// Test global scope.
+BeginTest("Global");
+listener_delegate = function(exec_state) {
+  CheckScopeChain(
+      [debug.ScopeType.Module, debug.ScopeType.Script, debug.ScopeType.Global],
+      exec_state);
+  CheckScopeChainNames([undefined, undefined, undefined], exec_state);
+};
+debugger;
+EndTest();
+
+
+BeginTest("Catch block 1");
+function catch_block_1() {
+  try {
+    throw 'Exception';
+  } catch (e) {
+    debugger;
+  }
+};
+
+
+listener_delegate = function(exec_state) {
+  CheckScopeChain([debug.ScopeType.Catch,
+                   debug.ScopeType.Local,
+                   debug.ScopeType.Module,
+                   debug.ScopeType.Script,
+                   debug.ScopeType.Global], exec_state);
+  CheckScopeContent({e:'Exception'}, 0, exec_state);
+  CheckScopeChainNames(
+      ["catch_block_1", "catch_block_1", undefined, undefined, undefined],
+      exec_state);
+};
+catch_block_1();
+EndTest();
+
+
+BeginTest("Catch block 3");
+function catch_block_3() {
+  eval("var y = 78;");
+  try {
+    throw 'Exception';
+  } catch (e) {
+    debugger;
+  }
+};
+
+
+listener_delegate = function(exec_state) {
+  CheckScopeChain([debug.ScopeType.Catch,
+                   debug.ScopeType.Local,
+                   debug.ScopeType.Module,
+                   debug.ScopeType.Script,
+                   debug.ScopeType.Global], exec_state);
+  CheckScopeContent({e:'Exception'}, 0, exec_state);
+  CheckScopeContent({}, 1, exec_state);
+  CheckScopeChainNames(
+      ["catch_block_3", "catch_block_3", undefined, undefined, undefined],
+      exec_state);
+};
+catch_block_3();
+EndTest();
+
+
+// Test catch in global scope.
+BeginTest("Catch block 5");
+listener_delegate = function(exec_state) {
+  CheckScopeChain([debug.ScopeType.Catch,
+                   debug.ScopeType.Module,
+                   debug.ScopeType.Script,
+                   debug.ScopeType.Global], exec_state);
+  CheckScopeContent({e:'Exception'}, 0, exec_state);
+  CheckScopeChainNames([undefined, undefined, undefined, undefined],
+                       exec_state);
+};
+
+try {
+  throw 'Exception';
+} catch (e) {
+  debugger;
+}
+
+EndTest();
+
+
+// Closure inside catch in global code.
+BeginTest("Catch block 6");
+listener_delegate = function(exec_state) {
+  CheckScopeChain([debug.ScopeType.Local,
+                   debug.ScopeType.Catch,
+                   debug.ScopeType.Module,
+                   debug.ScopeType.Script,
+                   debug.ScopeType.Global], exec_state);
+  CheckScopeContent({x: 2}, 0, exec_state);
+  CheckScopeContent({e:'Exception'}, 1, exec_state);
+  CheckScopeChainNames([undefined, undefined, undefined, undefined, undefined],
+                       exec_state);
+};
+
+try {
+  throw 'Exception';
+} catch (e) {
+  (function(x) {
+    debugger;
+  })(2);
+}
+EndTest();
+
+
+// Catch block in function that is marked for optimization while being executed.
+BeginTest("Catch block 7");
+function catch_block_7() {
+  %OptimizeFunctionOnNextCall(catch_block_7);
+  try {
+    throw 'Exception';
+  } catch (e) {
+    debugger;
+  }
+};
+
+
+listener_delegate = function(exec_state) {
+  CheckScopeChain([debug.ScopeType.Catch,
+                   debug.ScopeType.Local,
+                   debug.ScopeType.Module,
+                   debug.ScopeType.Script,
+                   debug.ScopeType.Global], exec_state);
+  CheckScopeContent({e:'Exception'}, 0, exec_state);
+  CheckScopeChainNames(
+      ["catch_block_7", "catch_block_7", undefined, undefined, undefined],
+      exec_state);
+};
+catch_block_7();
+EndTest();
+
+
+BeginTest("Classes and methods 1");
+
+listener_delegate = function(exec_state) {
+  "use strict"
+  CheckScopeChain([debug.ScopeType.Local,
+                   debug.ScopeType.Module,
+                   debug.ScopeType.Script,
+                   debug.ScopeType.Global], exec_state);
+  CheckScopeContent({}, 1, exec_state);
+  CheckScopeChainNames(["m", undefined, undefined, undefined], exec_state);
+};
+
+(function() {
+  "use strict";
+  class C1 {
+    m() {
+      debugger;
+    }
+  }
+  new C1().m();
+})();
+
+EndTest();
+
+BeginTest("Scope positions");
+var code1 = "function f() {        \n" +
+            "  var a = 1;          \n" +
+            "  function b() {      \n" +
+            "    debugger;         \n" +
+            "    return a + 1;     \n" +
+            "  }                   \n" +
+            "  b();                \n" +
+            "}                     \n" +
+            "f();                  \n";
+
+listener_delegate = function(exec_state) {
+  CheckScopeChainPositions([{start: 58, end: 118}, {start: 10, end: 162}],
+                           exec_state);
+}
+eval(code1);
+EndTest();
+
+
+BeginTest("Scope positions in for statement");
+var code3 = "function for_statement() {         \n" +
+            "  for (let i = 0; i < 1; i++) {    \n" +
+            "    debugger;                      \n" +
+            "  }                                \n" +
+            "}                                  \n" +
+            "for_statement();                   \n";
+
+listener_delegate = function(exec_state) {
+  CheckScopeChain([debug.ScopeType.Block,
+                   debug.ScopeType.Local,
+                   debug.ScopeType.Module,
+                   debug.ScopeType.Script,
+                   debug.ScopeType.Global], exec_state);
+  CheckScopeChainPositions([{start: 42, end: 111}, {start: 22, end: 145}],
+                           exec_state);
+}
+eval(code3);
+EndTest();
+
+BeginTest("Scope positions in for statement with lexical block");
+var code4 = "function for_statement() {         \n" +
+            "  for (let i = 0; i < 1; i++) {    \n" +
+            "    let j;                         \n" +
+            "    debugger;                      \n" +
+            "  }                                \n" +
+            "}                                  \n" +
+            "for_statement();                   \n";
+
+listener_delegate = function(exec_state) {
+  CheckScopeChain([debug.ScopeType.Block,
+                   debug.ScopeType.Block,
+                   debug.ScopeType.Local,
+                   debug.ScopeType.Module,
+                   debug.ScopeType.Script,
+                   debug.ScopeType.Global], exec_state);
+  CheckScopeChainPositions([{start: 66, end: 147},
+                            {start: 42, end: 147},
+                            {start: 22, end: 181}], exec_state);
+}
+eval(code4);
+EndTest();
+
+BeginTest("Scope positions in lexical for each statement");
+var code5 = "function for_each_statement() {    \n" +
+            "  for (let i of [0]) {             \n" +
+            "    debugger;                      \n" +
+            "  }                                \n" +
+            "}                                  \n" +
+            "for_each_statement();              \n";
+
+listener_delegate = function(exec_state) {
+  CheckScopeChain([debug.ScopeType.Block,
+                   debug.ScopeType.Local,
+                   debug.ScopeType.Module,
+                   debug.ScopeType.Script,
+                   debug.ScopeType.Global], exec_state);
+  CheckScopeChainPositions([{start: 55, end: 111}, {start: 27, end: 145}],
+                           exec_state);
+}
+eval(code5);
+EndTest();
+
+BeginTest("Scope positions in lexical for each statement with lexical block");
+var code6 = "function for_each_statement() {    \n" +
+            "  for (let i of [0]) {             \n" +
+            "    let j;                         \n" +
+            "    debugger;                      \n" +
+            "  }                                \n" +
+            "}                                  \n" +
+            "for_each_statement();              \n";
+
+listener_delegate = function(exec_state) {
+  CheckScopeChain([debug.ScopeType.Block,
+                   debug.ScopeType.Block,
+                   debug.ScopeType.Local,
+                   debug.ScopeType.Module,
+                   debug.ScopeType.Script,
+                   debug.ScopeType.Global], exec_state);
+  CheckScopeChainPositions([{start: 57, end: 147},
+                            {start: 55, end: 147},
+                            {start: 27, end: 181}], exec_state);
+}
+eval(code6);
+EndTest();
+
+BeginTest("Scope positions in non-lexical for each statement");
+var code7 = "function for_each_statement() {    \n" +
+            "  var i;                           \n" +
+            "  for (i of [0]) {                 \n" +
+            "    debugger;                      \n" +
+            "  }                                \n" +
+            "}                                  \n" +
+            "for_each_statement();              \n";
+
+listener_delegate = function(exec_state) {
+  CheckScopeChain([debug.ScopeType.Local,
+                   debug.ScopeType.Module,
+                   debug.ScopeType.Script,
+                   debug.ScopeType.Global], exec_state);
+  CheckScopeChainPositions([{start: 27, end: 181}], exec_state);
+}
+eval(code7);
+EndTest();
+
+BeginTest(
+    "Scope positions in non-lexical for each statement with lexical block");
+var code8 = "function for_each_statement() {    \n" +
+            "  var i;                           \n" +
+            "  for (i of [0]) {                 \n" +
+            "    let j;                         \n" +
+            "    debugger;                      \n" +
+            "  }                                \n" +
+            "}                                  \n" +
+            "for_each_statement();              \n";
+
+listener_delegate = function(exec_state) {
+  CheckScopeChain([debug.ScopeType.Block,
+                   debug.ScopeType.Local,
+                   debug.ScopeType.Module,
+                   debug.ScopeType.Script,
+                   debug.ScopeType.Global], exec_state);
+  CheckScopeChainPositions([{start: 89, end: 183}, {start: 27, end: 217}],
+                           exec_state);
+}
+eval(code8);
+EndTest();
+
+assertEquals(begin_test_count, break_count,
+             'one or more tests did not enter the debugger');
+assertEquals(begin_test_count, end_test_count,
+             'one or more tests did not have its result checked');
diff --git a/src/v8/test/debugger/debug/harmony/modules-debug-scopes2.js b/src/v8/test/debugger/debug/harmony/modules-debug-scopes2.js
new file mode 100644
index 0000000..8b9b9e8
--- /dev/null
+++ b/src/v8/test/debugger/debug/harmony/modules-debug-scopes2.js
@@ -0,0 +1,185 @@
+// 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.
+
+// MODULE
+
+
+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;
+
+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) {
+    exception = e;
+  }
+}
+
+Debug.setListener(listener);
+
+
+function BeginTest(name) {
+  test_name = name;
+  listener_delegate = null;
+  listener_called = false;
+  exception = null;
+  begin_test_count++;
+}
+
+function EndTest() {
+  assertTrue(listener_called, "listener not called for " + test_name);
+  assertNull(exception, test_name + " / " + exception);
+  end_test_count++;
+}
+
+
+// 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);
+  }
+  CheckFastAllScopes(scopes, exec_state);
+}
+
+
+function CheckScopeDoesNotHave(properties, number, exec_state) {
+  var scope = exec_state.frame().scope(number);
+  for (var p of properties) {
+    var property_mirror = scope.scopeObject().property(p);
+    assertTrue(property_mirror.isUndefined(),
+               'property ' + p + ' found in scope');
+  }
+}
+
+
+// Check that the scope contains at least minimum_content. For functions just
+// check that there is a function.
+function CheckScopeContent(minimum_content, number, exec_state) {
+  var scope = exec_state.frame().scope(number);
+  var minimum_count = 0;
+  for (var p in minimum_content) {
+    var property_mirror = scope.scopeObject().property(p);
+    assertFalse(property_mirror.isUndefined(),
+                'property ' + p + ' not found in scope');
+    assertEquals(minimum_content[p], property_mirror.value().value(),
+                 'property ' + p + ' has unexpected value');
+    minimum_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--;
+  }
+  // Ditto for 'this'.
+  if (!scope.scopeObject().property('this').isUndefined()) {
+    scope_size--;
+  }
+  // Temporary variables introduced by the parser have not been materialized.
+  assertTrue(scope.scopeObject().property('').isUndefined());
+
+  if (scope_size < minimum_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 >= minimum_count);
+}
+
+
+////////////////////////////////////////////////////////////////////////////////
+// Actual tests.
+////////////////////////////////////////////////////////////////////////////////
+
+
+BeginTest();
+listener_delegate = function(exec_state) {
+  CheckScopeChain([debug.ScopeType.Module,
+                   debug.ScopeType.Script,
+                   debug.ScopeType.Global], exec_state);
+  CheckScopeContent(
+      {local_var: undefined, exported_var: undefined, imported_var: undefined},
+      0, exec_state);
+  CheckScopeDoesNotHave(
+      ["doesnotexist", "local_let", "exported_let", "imported_let"],
+      0, exec_state);
+};
+debugger;
+EndTest();
+
+let local_let = 1;
+var local_var = 2;
+export let exported_let = 3;
+export var exported_var = 4;
+import {exported_let as imported_let} from "modules-debug-scopes2.js";
+import {exported_var as imported_var} from "modules-debug-scopes2.js";
+
+BeginTest();
+listener_delegate = function(exec_state) {
+  CheckScopeChain([debug.ScopeType.Module,
+                   debug.ScopeType.Script,
+                   debug.ScopeType.Global], exec_state);
+  CheckScopeContent(
+      {local_let: 1, local_var: 2, exported_let: 3, exported_var: 4,
+       imported_let: 3, imported_var: 4}, 0, exec_state);
+};
+debugger;
+EndTest();
+
+local_let += 10;
+local_var += 10;
+exported_let += 10;
+exported_var += 10;
+
+BeginTest();
+listener_delegate = function(exec_state) {
+  CheckScopeChain([debug.ScopeType.Module,
+                   debug.ScopeType.Script,
+                   debug.ScopeType.Global], exec_state);
+  CheckScopeContent(
+      {local_let: 11, local_var: 12, exported_let: 13, exported_var: 14,
+       imported_let: 13, imported_var: 14}, 0, exec_state);
+};
+debugger;
+EndTest();
diff --git a/src/v8/test/debugger/debug/ignition/debug-break-on-stack.js b/src/v8/test/debugger/debug/ignition/debug-break-on-stack.js
new file mode 100644
index 0000000..846fb4c
--- /dev/null
+++ b/src/v8/test/debugger/debug/ignition/debug-break-on-stack.js
@@ -0,0 +1,47 @@
+// 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.
+
+
+var 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 {
+    break_count++;
+    var line = exec_state.frame(0).sourceLineText();
+    print(line);
+    assertTrue(line.indexOf(`B${break_count}`) > 0);
+  } catch (e) {
+    exception = e;
+  }
+}
+
+
+function g() {
+  setbreaks();
+  throw 1;  // B1
+}
+
+function f() {
+  try {
+    g();
+  } catch (e) {}
+  return 2;  // B2
+}
+
+function setbreaks() {
+  Debug.setListener(listener);
+  Debug.setBreakPoint(g, 2, 0);
+  Debug.setBreakPoint(f, 4, 0);
+}
+
+f();
+
+assertEquals(2, break_count);
+assertNull(exception);
+
+Debug.setListener(null);
diff --git a/src/v8/test/debugger/debug/ignition/debug-break.js b/src/v8/test/debugger/debug/ignition/debug-break.js
new file mode 100644
index 0000000..3678587
--- /dev/null
+++ b/src/v8/test/debugger/debug/ignition/debug-break.js
@@ -0,0 +1,45 @@
+// 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.
+
+
+var 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 {
+    break_count++;
+    var line = exec_state.frame(0).sourceLineText();
+    assertTrue(line.indexOf(`B${break_count}`) > 0);
+  } catch (e) {
+    exception = e;
+  }
+}
+
+Debug.setListener(listener);
+
+function g() {
+  throw 1;
+}
+
+function f() {
+  try {
+    g();                         // B1
+  } catch (e) {}
+  assertEquals(2, break_count);  // B2
+  return 1;                      // B3
+}
+
+Debug.setBreakPoint(f, 2, 0);
+Debug.setBreakPoint(f, 4, 1);
+Debug.setBreakPoint(f, 5, 1);
+
+f();
+
+assertEquals(3, break_count);
+assertNull(exception);
+
+Debug.setListener(null);
diff --git a/src/v8/test/debugger/debug/ignition/debug-scope-on-return.js b/src/v8/test/debugger/debug/ignition/debug-scope-on-return.js
new file mode 100644
index 0000000..70a80b1
--- /dev/null
+++ b/src/v8/test/debugger/debug/ignition/debug-scope-on-return.js
@@ -0,0 +1,30 @@
+// 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.
+
+
+// Check that the we are still in function context when we break on return.
+
+var Debug = debug.Debug;
+
+function listener(event, exec_state, event_data, data) {
+  if (event == Debug.DebugEvent.Break) {
+    // Access scope details to check the context is correct.
+    var scope_count = exec_state.frame().scopeCount();
+    // Do steps until we reach the global scope again.
+    exec_state.prepareStep(Debug.StepAction.StepIn);
+  }
+}
+
+Debug.setListener(listener);
+
+function f() {
+  debugger;
+
+  L: with ({x:12}) {
+    break L;
+  }
+
+  return;
+}
+f();
diff --git a/src/v8/test/debugger/debug/ignition/debug-step-prefix-bytecodes.js b/src/v8/test/debugger/debug/ignition/debug-step-prefix-bytecodes.js
new file mode 100644
index 0000000..4635003
--- /dev/null
+++ b/src/v8/test/debugger/debug/ignition/debug-step-prefix-bytecodes.js
@@ -0,0 +1,372 @@
+// 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.
+
+// This test tests that full code compiled without debug break slots
+// is recompiled with debug break slots when debugging is started.
+
+Debug = debug.Debug
+
+var done = false;
+var step_count = 0;
+var values = [];
+
+// Debug event listener which steps until the global variable done is true.
+function listener(event, exec_state, event_data, data) {
+  if (event == Debug.DebugEvent.Break) {
+    if (!done) exec_state.prepareStep(Debug.StepAction.StepNext);
+    step_count++;
+  }
+};
+
+// Set the global variables state to prpare the stepping test.
+function prepare_step_test() {
+  done = false;
+  step_count = 0;
+}
+
+// Test function to step through, uses widended bytecodes.
+function f() {
+var x = 10000000;
+var y = x + 1;
+var _aa = 0; values[_aa] = _aa;
+var _ab = 1; values[_ab] = _ab;
+var _ac = 2; values[_ac] = _ac;
+var _ad = 3; values[_ad] = _ad;
+var _ae = 4; values[_ae] = _ae;
+var _af = 5; values[_af] = _af;
+var _ag = 6; values[_ag] = _ag;
+var _ah = 7; values[_ah] = _ah;
+var _ai = 8; values[_ai] = _ai;
+var _aj = 9; values[_aj] = _aj;
+var _ak = 10; values[_ak] = _ak;
+var _al = 11; values[_al] = _al;
+var _am = 12; values[_am] = _am;
+var _an = 13; values[_an] = _an;
+var _ao = 14; values[_ao] = _ao;
+var _ap = 15; values[_ap] = _ap;
+var _ba = 16; values[_ba] = _ba;
+var _bb = 17; values[_bb] = _bb;
+var _bc = 18; values[_bc] = _bc;
+var _bd = 19; values[_bd] = _bd;
+var _be = 20; values[_be] = _be;
+var _bf = 21; values[_bf] = _bf;
+var _bg = 22; values[_bg] = _bg;
+var _bh = 23; values[_bh] = _bh;
+var _bi = 24; values[_bi] = _bi;
+var _bj = 25; values[_bj] = _bj;
+var _bk = 26; values[_bk] = _bk;
+var _bl = 27; values[_bl] = _bl;
+var _bm = 28; values[_bm] = _bm;
+var _bn = 29; values[_bn] = _bn;
+var _bo = 30; values[_bo] = _bo;
+var _bp = 31; values[_bp] = _bp;
+var _ca = 32; values[_ca] = _ca;
+var _cb = 33; values[_cb] = _cb;
+var _cc = 34; values[_cc] = _cc;
+var _cd = 35; values[_cd] = _cd;
+var _ce = 36; values[_ce] = _ce;
+var _cf = 37; values[_cf] = _cf;
+var _cg = 38; values[_cg] = _cg;
+var _ch = 39; values[_ch] = _ch;
+var _ci = 40; values[_ci] = _ci;
+var _cj = 41; values[_cj] = _cj;
+var _ck = 42; values[_ck] = _ck;
+var _cl = 43; values[_cl] = _cl;
+var _cm = 44; values[_cm] = _cm;
+var _cn = 45; values[_cn] = _cn;
+var _co = 46; values[_co] = _co;
+var _cp = 47; values[_cp] = _cp;
+var _da = 48; values[_da] = _da;
+var _db = 49; values[_db] = _db;
+var _dc = 50; values[_dc] = _dc;
+var _dd = 51; values[_dd] = _dd;
+var _de = 52; values[_de] = _de;
+var _df = 53; values[_df] = _df;
+var _dg = 54; values[_dg] = _dg;
+var _dh = 55; values[_dh] = _dh;
+var _di = 56; values[_di] = _di;
+var _dj = 57; values[_dj] = _dj;
+var _dk = 58; values[_dk] = _dk;
+var _dl = 59; values[_dl] = _dl;
+var _dm = 60; values[_dm] = _dm;
+var _dn = 61; values[_dn] = _dn;
+var _do = 62; values[_do] = _do;
+var _dp = 63; values[_dp] = _dp;
+var _ea = 64; values[_ea] = _ea;
+var _eb = 65; values[_eb] = _eb;
+var _ec = 66; values[_ec] = _ec;
+var _ed = 67; values[_ed] = _ed;
+var _ee = 68; values[_ee] = _ee;
+var _ef = 69; values[_ef] = _ef;
+var _eg = 70; values[_eg] = _eg;
+var _eh = 71; values[_eh] = _eh;
+var _ei = 72; values[_ei] = _ei;
+var _ej = 73; values[_ej] = _ej;
+var _ek = 74; values[_ek] = _ek;
+var _el = 75; values[_el] = _el;
+var _em = 76; values[_em] = _em;
+var _en = 77; values[_en] = _en;
+var _eo = 78; values[_eo] = _eo;
+var _ep = 79; values[_ep] = _ep;
+var _fa = 80; values[_fa] = _fa;
+var _fb = 81; values[_fb] = _fb;
+var _fc = 82; values[_fc] = _fc;
+var _fd = 83; values[_fd] = _fd;
+var _fe = 84; values[_fe] = _fe;
+var _ff = 85; values[_ff] = _ff;
+var _fg = 86; values[_fg] = _fg;
+var _fh = 87; values[_fh] = _fh;
+var _fi = 88; values[_fi] = _fi;
+var _fj = 89; values[_fj] = _fj;
+var _fk = 90; values[_fk] = _fk;
+var _fl = 91; values[_fl] = _fl;
+var _fm = 92; values[_fm] = _fm;
+var _fn = 93; values[_fn] = _fn;
+var _fo = 94; values[_fo] = _fo;
+var _fp = 95; values[_fp] = _fp;
+var _ga = 96; values[_ga] = _ga;
+var _gb = 97; values[_gb] = _gb;
+var _gc = 98; values[_gc] = _gc;
+var _gd = 99; values[_gd] = _gd;
+var _ge = 100; values[_ge] = _ge;
+var _gf = 101; values[_gf] = _gf;
+var _gg = 102; values[_gg] = _gg;
+var _gh = 103; values[_gh] = _gh;
+var _gi = 104; values[_gi] = _gi;
+var _gj = 105; values[_gj] = _gj;
+var _gk = 106; values[_gk] = _gk;
+var _gl = 107; values[_gl] = _gl;
+var _gm = 108; values[_gm] = _gm;
+var _gn = 109; values[_gn] = _gn;
+var _go = 110; values[_go] = _go;
+var _gp = 111; values[_gp] = _gp;
+var _ha = 112; values[_ha] = _ha;
+var _hb = 113; values[_hb] = _hb;
+var _hc = 114; values[_hc] = _hc;
+var _hd = 115; values[_hd] = _hd;
+var _he = 116; values[_he] = _he;
+var _hf = 117; values[_hf] = _hf;
+var _hg = 118; values[_hg] = _hg;
+var _hh = 119; values[_hh] = _hh;
+var _hi = 120; values[_hi] = _hi;
+var _hj = 121; values[_hj] = _hj;
+var _hk = 122; values[_hk] = _hk;
+var _hl = 123; values[_hl] = _hl;
+var _hm = 124; values[_hm] = _hm;
+var _hn = 125; values[_hn] = _hn;
+var _ho = 126; values[_ho] = _ho;
+var _hp = 127; values[_hp] = _hp;
+var _ia = 128; values[_ia] = _ia;
+var _ib = 129; values[_ib] = _ib;
+var _ic = 130; values[_ic] = _ic;
+var _id = 131; values[_id] = _id;
+var _ie = 132; values[_ie] = _ie;
+var _if = 133; values[_if] = _if;
+var _ig = 134; values[_ig] = _ig;
+var _ih = 135; values[_ih] = _ih;
+var _ii = 136; values[_ii] = _ii;
+var _ij = 137; values[_ij] = _ij;
+var _ik = 138; values[_ik] = _ik;
+var _il = 139; values[_il] = _il;
+var _im = 140; values[_im] = _im;
+var _in = 141; values[_in] = _in;
+var _io = 142; values[_io] = _io;
+var _ip = 143; values[_ip] = _ip;
+var _ja = 144; values[_ja] = _ja;
+var _jb = 145; values[_jb] = _jb;
+var _jc = 146; values[_jc] = _jc;
+var _jd = 147; values[_jd] = _jd;
+var _je = 148; values[_je] = _je;
+var _jf = 149; values[_jf] = _jf;
+var _jg = 150; values[_jg] = _jg;
+var _jh = 151; values[_jh] = _jh;
+var _ji = 152; values[_ji] = _ji;
+var _jj = 153; values[_jj] = _jj;
+var _jk = 154; values[_jk] = _jk;
+var _jl = 155; values[_jl] = _jl;
+var _jm = 156; values[_jm] = _jm;
+var _jn = 157; values[_jn] = _jn;
+var _jo = 158; values[_jo] = _jo;
+var _jp = 159; values[_jp] = _jp;
+var _ka = 160; values[_ka] = _ka;
+var _kb = 161; values[_kb] = _kb;
+var _kc = 162; values[_kc] = _kc;
+var _kd = 163; values[_kd] = _kd;
+var _ke = 164; values[_ke] = _ke;
+var _kf = 165; values[_kf] = _kf;
+var _kg = 166; values[_kg] = _kg;
+var _kh = 167; values[_kh] = _kh;
+var _ki = 168; values[_ki] = _ki;
+var _kj = 169; values[_kj] = _kj;
+var _kk = 170; values[_kk] = _kk;
+var _kl = 171; values[_kl] = _kl;
+var _km = 172; values[_km] = _km;
+var _kn = 173; values[_kn] = _kn;
+var _ko = 174; values[_ko] = _ko;
+var _kp = 175; values[_kp] = _kp;
+var _la = 176; values[_la] = _la;
+var _lb = 177; values[_lb] = _lb;
+var _lc = 178; values[_lc] = _lc;
+var _ld = 179; values[_ld] = _ld;
+var _le = 180; values[_le] = _le;
+var _lf = 181; values[_lf] = _lf;
+var _lg = 182; values[_lg] = _lg;
+var _lh = 183; values[_lh] = _lh;
+var _li = 184; values[_li] = _li;
+var _lj = 185; values[_lj] = _lj;
+var _lk = 186; values[_lk] = _lk;
+var _ll = 187; values[_ll] = _ll;
+var _lm = 188; values[_lm] = _lm;
+var _ln = 189; values[_ln] = _ln;
+var _lo = 190; values[_lo] = _lo;
+var _lp = 191; values[_lp] = _lp;
+var _ma = 192; values[_ma] = _ma;
+var _mb = 193; values[_mb] = _mb;
+var _mc = 194; values[_mc] = _mc;
+var _md = 195; values[_md] = _md;
+var _me = 196; values[_me] = _me;
+var _mf = 197; values[_mf] = _mf;
+var _mg = 198; values[_mg] = _mg;
+var _mh = 199; values[_mh] = _mh;
+var _mi = 200; values[_mi] = _mi;
+var _mj = 201; values[_mj] = _mj;
+var _mk = 202; values[_mk] = _mk;
+var _ml = 203; values[_ml] = _ml;
+var _mm = 204; values[_mm] = _mm;
+var _mn = 205; values[_mn] = _mn;
+var _mo = 206; values[_mo] = _mo;
+var _mp = 207; values[_mp] = _mp;
+var _na = 208; values[_na] = _na;
+var _nb = 209; values[_nb] = _nb;
+var _nc = 210; values[_nc] = _nc;
+var _nd = 211; values[_nd] = _nd;
+var _ne = 212; values[_ne] = _ne;
+var _nf = 213; values[_nf] = _nf;
+var _ng = 214; values[_ng] = _ng;
+var _nh = 215; values[_nh] = _nh;
+var _ni = 216; values[_ni] = _ni;
+var _nj = 217; values[_nj] = _nj;
+var _nk = 218; values[_nk] = _nk;
+var _nl = 219; values[_nl] = _nl;
+var _nm = 220; values[_nm] = _nm;
+var _nn = 221; values[_nn] = _nn;
+var _no = 222; values[_no] = _no;
+var _np = 223; values[_np] = _np;
+var _oa = 224; values[_oa] = _oa;
+var _ob = 225; values[_ob] = _ob;
+var _oc = 226; values[_oc] = _oc;
+var _od = 227; values[_od] = _od;
+var _oe = 228; values[_oe] = _oe;
+var _of = 229; values[_of] = _of;
+var _og = 230; values[_og] = _og;
+var _oh = 231; values[_oh] = _oh;
+var _oi = 232; values[_oi] = _oi;
+var _oj = 233; values[_oj] = _oj;
+var _ok = 234; values[_ok] = _ok;
+var _ol = 235; values[_ol] = _ol;
+var _om = 236; values[_om] = _om;
+var _on = 237; values[_on] = _on;
+var _oo = 238; values[_oo] = _oo;
+var _op = 239; values[_op] = _op;
+var _pa = 240; values[_pa] = _pa;
+var _pb = 241; values[_pb] = _pb;
+var _pc = 242; values[_pc] = _pc;
+var _pd = 243; values[_pd] = _pd;
+var _pe = 244; values[_pe] = _pe;
+var _pf = 245; values[_pf] = _pf;
+var _pg = 246; values[_pg] = _pg;
+var _ph = 247; values[_ph] = _ph;
+var _pi = 248; values[_pi] = _pi;
+var _pj = 249; values[_pj] = _pj;
+var _pk = 250; values[_pk] = _pk;
+var _pl = 251; values[_pl] = _pl;
+var _pm = 252; values[_pm] = _pm;
+var _pn = 253; values[_pn] = _pn;
+var _po = 254; values[_po] = _po;
+var _pp = 255; values[_pp] = _pp;
+var _qa = 256; values[_qa] = _qa;
+var _qb = 257; values[_qb] = _qb;
+var _qc = 258; values[_qc] = _qc;
+var _qd = 259; values[_qd] = _qd;
+var _qe = 260; values[_qe] = _qe;
+var _qf = 261; values[_qf] = _qf;
+var _qg = 262; values[_qg] = _qg;
+var _qh = 263; values[_qh] = _qh;
+var _qi = 264; values[_qi] = _qi;
+var _qj = 265; values[_qj] = _qj;
+var _qk = 266; values[_qk] = _qk;
+var _ql = 267; values[_ql] = _ql;
+var _qm = 268; values[_qm] = _qm;
+var _qn = 269; values[_qn] = _qn;
+var _qo = 270; values[_qo] = _qo;
+var _qp = 271; values[_qp] = _qp;
+var _ra = 272; values[_ra] = _ra;
+var _rb = 273; values[_rb] = _rb;
+var _rc = 274; values[_rc] = _rc;
+var _rd = 275; values[_rd] = _rd;
+var _re = 276; values[_re] = _re;
+var _rf = 277; values[_rf] = _rf;
+var _rg = 278; values[_rg] = _rg;
+var _rh = 279; values[_rh] = _rh;
+var _ri = 280; values[_ri] = _ri;
+var _rj = 281; values[_rj] = _rj;
+var _rk = 282; values[_rk] = _rk;
+var _rl = 283; values[_rl] = _rl;
+var _rm = 284; values[_rm] = _rm;
+var _rn = 285; values[_rn] = _rn;
+var _ro = 286; values[_ro] = _ro;
+var _rp = 287; values[_rp] = _rp;
+  done = true;
+};
+
+function check_values() {
+  for (var i = 0; i < values.length; i++) {
+    assertEquals(values[i], i);
+    values[i] = -i;
+  }
+}
+
+// Pass 1 - no debugger, no steps seen
+prepare_step_test();
+f();
+check_values();
+assertEquals(0, step_count);
+
+// Pass 2 - debugger attached and stepping from BP
+Debug.setListener(listener);
+var bp = Debug.setBreakPoint(f, 1);
+prepare_step_test();
+f();
+check_values();
+assertEquals(580, step_count);
+Debug.clearBreakPoint(bp);
+
+// Pass 3 - debugger attached and no BP
+prepare_step_test();
+f();
+check_values();
+assertEquals(0, step_count);
diff --git a/src/v8/test/debugger/debug/ignition/debugger-statement.js b/src/v8/test/debugger/debug/ignition/debugger-statement.js
new file mode 100644
index 0000000..ddc0b38
--- /dev/null
+++ b/src/v8/test/debugger/debug/ignition/debugger-statement.js
@@ -0,0 +1,29 @@
+// 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.
+
+var Debug = debug.Debug;
+
+var break_count = 0;
+
+function f() {
+  debugger;
+}
+
+function listener(event, exec_data) {
+  if (event != Debug.DebugEvent.Break) return;
+  break_count++;
+}
+
+f();
+assertEquals(0, break_count);
+
+Debug.setListener(listener);
+
+f();
+assertEquals(1, break_count);
+
+Debug.setListener(null);
+
+f();
+assertEquals(1, break_count);
diff --git a/src/v8/test/debugger/debug/ignition/elided-instruction.js b/src/v8/test/debugger/debug/ignition/elided-instruction.js
new file mode 100644
index 0000000..4663f36
--- /dev/null
+++ b/src/v8/test/debugger/debug/ignition/elided-instruction.js
@@ -0,0 +1,36 @@
+// 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 break_count = 0;
+
+function listener(event, exec_state, event_data, data) {
+  if (event != Debug.DebugEvent.Break) return;
+  try {
+    print(event_data.sourceLineText());
+    var column = event_data.sourceColumn();
+    assertTrue(event_data.sourceLineText().indexOf(
+        `Break ${break_count++}. ${column}.`) > 0);
+    exec_state.prepareStep(Debug.StepAction.StepIn);
+  } catch (e) {
+    print(e + e.stack);
+    exception = e;
+  }
+};
+
+function f() {
+  var a = 1;                     // Break 2. 10.
+  return a;                      // Break 3. 11.
+}
+
+Debug.setListener(listener);
+debugger;                        // Break 0. 0.
+f();                             // Break 1. 0.
+Debug.setListener(null);         // Break 4. 0.
+
+assertNull(exception);
+assertEquals(5, break_count);
diff --git a/src/v8/test/debugger/debug/ignition/optimized-debug-frame.js b/src/v8/test/debugger/debug/ignition/optimized-debug-frame.js
new file mode 100644
index 0000000..cc85b47
--- /dev/null
+++ b/src/v8/test/debugger/debug/ignition/optimized-debug-frame.js
@@ -0,0 +1,37 @@
+// 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 PC in optimized frame would correctly translate into
+// unoptimized frame when retrieving frame information in the debugger.
+
+function f() {
+  debugger;
+}
+
+function g(x) {
+  return f();
+}
+
+var break_count = 0;
+
+function listener(event, exec_state, event_data, data) {
+  if (event != Debug.DebugEvent.Break) return;
+  assertEquals(14, exec_state.frame(1).sourceLine());
+  assertEquals(9, exec_state.frame(1).sourceColumn());
+  break_count++;
+}
+
+g();
+g();
+%OptimizeFunctionOnNextCall(g);
+
+var Debug = debug.Debug;
+Debug.setListener(listener);
+
+g();
+
+Debug.setListener(null);
+
+assertEquals(1, break_count);
diff --git a/src/v8/test/debugger/debug/regress-3225.js b/src/v8/test/debugger/debug/regress-3225.js
new file mode 100644
index 0000000..454ff6e
--- /dev/null
+++ b/src/v8/test/debugger/debug/regress-3225.js
@@ -0,0 +1,52 @@
+// 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: --noalways-opt
+
+Debug = debug.Debug
+
+var debug_step = 0;
+var failure = null;
+
+function listener(event, exec_state, event_data, data) {
+  if (event != Debug.DebugEvent.Break) return;
+  try {
+    if (debug_step == 0) {
+      assertEquals(1, exec_state.frame(0).evaluate('a').value());
+      assertEquals(3, exec_state.frame(0).evaluate('b').value());
+      exec_state.frame(0).evaluate("a = 4").value();
+      debug_step++;
+    } else {
+      assertEquals(4, exec_state.frame(0).evaluate('a').value());
+      assertEquals(3, exec_state.frame(0).evaluate('b').value());
+      exec_state.frame(0).evaluate("set_a_to_5()");
+      exec_state.frame(0).evaluate("b = 5").value();
+    }
+  } catch (e) {
+    failure = e;
+  }
+}
+
+Debug.setListener(listener);
+
+function* generator(a, b) {
+  function set_a_to_5() { a = 5 }
+  var b = 3;  // Shadows a parameter.
+  debugger;
+  yield a;
+  yield b;
+  debugger;
+  yield a;
+  return b;
+}
+
+var foo = generator(1, 2);
+
+assertEquals(4, foo.next().value);
+assertEquals(3, foo.next().value);
+assertEquals(5, foo.next().value);
+assertEquals(5, foo.next().value);
+assertNull(failure);
+
+Debug.setListener(null);
diff --git a/src/v8/test/debugger/debug/regress-5207.js b/src/v8/test/debugger/debug/regress-5207.js
new file mode 100644
index 0000000..f2b3d7c
--- /dev/null
+++ b/src/v8/test/debugger/debug/regress-5207.js
@@ -0,0 +1,31 @@
+// Copyright 2012 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
+
+
+'use strict';
+var Debug = debug.Debug;
+var exception = null;
+
+function listener(event, exec_state, event_data, data) {
+  if (event != Debug.DebugEvent.Break) return;
+  try {
+    var scopes = exec_state.frame(0).allScopes();
+    assertEquals(debug.ScopeType.Eval, scopes[0].scopeType());
+    assertEquals(1, scopes[0].scopeObject().value().a);
+    assertEquals(debug.ScopeType.Script, scopes[1].scopeType());
+    assertEquals(undefined, scopes[1].scopeObject().value().a);
+    assertEquals(debug.ScopeType.Global, scopes[2].scopeType());
+    assertEquals(undefined, scopes[2].scopeObject().value().a);
+  } catch (e) {
+    exception = e;
+  }
+}
+
+Debug.setListener(listener);
+// Eval inherits strict mode.
+eval("var a = 1; debugger;");
+Debug.setListener(null);
+assertNull(exception);
diff --git a/src/v8/test/debugger/debug/regress/debug-prepare-step-in.js b/src/v8/test/debugger/debug/regress/debug-prepare-step-in.js
new file mode 100644
index 0000000..fbbc1c9
--- /dev/null
+++ b/src/v8/test/debugger/debug/regress/debug-prepare-step-in.js
@@ -0,0 +1,55 @@
+// Copyright 2013 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: --expose-gc
+Debug = debug.Debug
+
+function breakListener(event, exec_state, event_data, data) {
+  exec_state.prepareStep(Debug.StepAction.StepIn);
+}
+
+Debug.setListener(breakListener);
+
+var o = {x:function() { return 10; }};
+
+function f(o) {
+  var m = "x";
+  o[m]();
+}
+
+Debug.setBreakPoint(f, 2, 0);
+
+f(o);
+
+%NotifyContextDisposed();
+function g() {
+  gc();
+}
+
+g();
+
+Debug.setListener(null);
diff --git a/src/v8/test/debugger/debug/regress/regress-102153.js b/src/v8/test/debugger/debug/regress/regress-102153.js
new file mode 100644
index 0000000..af66245
--- /dev/null
+++ b/src/v8/test/debugger/debug/regress/regress-102153.js
@@ -0,0 +1,56 @@
+// 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.
+
+
+// Test that the break point is set before initializing the loop variable
+// so that we break before any iteration has been run.
+
+Debug = debug.Debug;
+
+var break_hit = false;
+
+function listener(event, exec_state, event_data, data) {
+  if (event == Debug.DebugEvent.Break) {
+    break_hit = true;
+  }
+}
+
+Debug.setListener(listener);
+
+function test() {
+  for (var i = 0; i < 3; i++) {  // Break here.
+    if (i == 0) break;
+  }
+}
+
+Debug.setBreakPoint(test, 1, 0);
+
+assertTrue(Debug.showBreakPoints(test).indexOf("// Break here.") >= 0);
+
+test();
+
+assertTrue(break_hit);
diff --git a/src/v8/test/debugger/debug/regress/regress-1081309.js b/src/v8/test/debugger/debug/regress/regress-1081309.js
new file mode 100644
index 0000000..5e4cd88
--- /dev/null
+++ b/src/v8/test/debugger/debug/regress/regress-1081309.js
@@ -0,0 +1,72 @@
+// Copyright 2008 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.
+
+Debug = debug.Debug
+
+// Make sure that the backtrace command can be processed when the receiver is
+// undefined.
+listenerCalled = false;
+exception = false;
+
+function listener(event, exec_state, event_data, data) {
+  try {
+    if (event == Debug.DebugEvent.Exception) {
+      // The expected backtrace is
+      // 1: g
+      // 0: [anonymous]
+
+      assertEquals(2, exec_state.frameCount());
+      assertEquals("g", exec_state.frame(0).func().name());
+      assertEquals("", exec_state.frame(1).func().name());
+
+      listenerCalled = true;
+    }
+  } catch (e) {
+    print(e);
+    exception = e
+  };
+};
+
+// Add the debug event listener.
+Debug.setListener(listener);
+
+// Call method on undefined.
+function g() {
+  (void 0).f();
+};
+
+// Break on the exception to do a backtrace with undefined as receiver.
+Debug.setBreakOnException(true);
+try {
+  g();
+} catch(e) {
+  // Ignore the exception "Cannot call method 'x' of undefined"
+}
+
+assertFalse(exception, "exception in listener", exception)
+// Make sure that the debug event listener vas invoked.
+assertTrue(listenerCalled, "listener not called");
diff --git a/src/v8/test/debugger/debug/regress/regress-109195.js b/src/v8/test/debugger/debug/regress/regress-109195.js
new file mode 100644
index 0000000..abf31d6
--- /dev/null
+++ b/src/v8/test/debugger/debug/regress/regress-109195.js
@@ -0,0 +1,65 @@
+// 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.
+
+var Debug = debug.Debug;
+
+function listener(event, exec_state, event_data, data) {
+  if (event != Debug.DebugEvent.Break) return;
+  for (var i = 0, n = exec_state.frameCount(); i < n; i++) {
+    exec_state.frame().scopeCount(i);
+  }
+  exec_state.prepareStep(Debug.StepAction.StepNext);
+}
+
+Debug.setListener(listener);
+
+var F = function () {
+  1, function () {
+    var d = 0;
+    (function () { d; });
+    debugger;
+  }();
+};
+
+var src = "(" + F.toString() + ")()";
+eval(src);
+
+Function.prototype.__defineGetter__("f", function () {
+  debugger;
+  return 0;
+});
+
+var G = function () {
+  1, function () {
+    var d = 0;
+    (function () { d; });
+    debugger;
+  }['f'];
+};
+
+var src = "(" + G.toString() + ")()";
+eval(src);
diff --git a/src/v8/test/debugger/debug/regress/regress-1170187.js b/src/v8/test/debugger/debug/regress/regress-1170187.js
new file mode 100644
index 0000000..165a308
--- /dev/null
+++ b/src/v8/test/debugger/debug/regress/regress-1170187.js
@@ -0,0 +1,80 @@
+// Copyright 2008 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.
+
+
+// Make sure that the retreival of local variables are performed correctly even
+// when an adapter frame is present.
+
+Debug = debug.Debug
+
+listenerCalled = false;
+exception = false;
+
+
+function checkName(name) {
+  const validNames = new Set([ 'a', 'b', 'c', 'x', 'y' ]);
+  assertTrue(validNames.has(name));
+}
+
+
+function checkValue(value) {
+  assertEquals(void 0, value);
+}
+
+
+function listener(event, exec_state, event_data, data) {
+  try {
+    if (event == Debug.DebugEvent.Break) {
+      var local0Name = exec_state.frame(0).localName(0);
+      var local1Name = exec_state.frame(0).localName(1);
+      var local2Name = exec_state.frame(0).localName(2);
+      checkName(local0Name);
+      checkName(local1Name);
+      checkName(local2Name);
+      var local0Value = exec_state.frame(0).localValue(0).value();
+      var local1Value = exec_state.frame(0).localValue(1).value();
+      var local2Value = exec_state.frame(0).localValue(2).value();
+      checkValue(local0Value);
+      checkValue(local1Value);
+      checkValue(local2Value);
+      listenerCalled = true;
+    }
+  } catch (e) {
+    exception = e;
+  };
+};
+
+// Add the debug event listener.
+Debug.setListener(listener);
+
+// Call a function with local variables passing a different number parameters
+// that the number of arguments.
+(function(x,y){var a,b,c; debugger; return 3})()
+
+// Make sure that the debug event listener vas invoked (again).
+assertTrue(listenerCalled);
+assertFalse(exception, "exception in listener")
diff --git a/src/v8/test/debugger/debug/regress/regress-119609.js b/src/v8/test/debugger/debug/regress/regress-119609.js
new file mode 100644
index 0000000..b6da891
--- /dev/null
+++ b/src/v8/test/debugger/debug/regress/regress-119609.js
@@ -0,0 +1,66 @@
+// 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.
+
+
+Debug = debug.Debug;
+
+var exception = false;
+
+function listener(event, exec_state, event_data, data) {
+  try {
+    if (event == Debug.DebugEvent.Break) {
+      function lookup(name) {
+        return exec_state.frame(0).evaluate(name).value();
+      }
+
+      assertEquals(3, lookup("e"));
+      assertEquals(4, lookup("f"));
+      assertEquals(1, lookup("a"));
+
+      assertThrows(() => lookup("b"), ReferenceError);
+    }
+  } catch (e) {
+    exception = e.toString() + e.stack;
+  }
+}
+
+Debug.setListener(listener);
+
+function f(a, b) {
+  var c = 3;
+  function d(e, f) {
+    var g = a;
+    var h = c;
+    debugger;
+  }
+
+  return d;
+}
+
+f(1, 2)(3, 4);
+
+assertFalse(exception);
diff --git a/src/v8/test/debugger/debug/regress/regress-131994.js b/src/v8/test/debugger/debug/regress/regress-131994.js
new file mode 100644
index 0000000..66bde74
--- /dev/null
+++ b/src/v8/test/debugger/debug/regress/regress-131994.js
@@ -0,0 +1,70 @@
+// 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.
+//
+// Flags: --noanalyze-environment-liveness
+
+
+// Test that a variable in the local scope that shadows a context-allocated
+// variable is correctly resolved when being evaluated in the debugger.
+
+Debug = debug.Debug;
+
+var exception = false;
+
+function listener(event, exec_state, event_data, data) {
+  if (event != Debug.DebugEvent.Break) return;
+  var breakpoint = exec_state.frame(0);
+  try {
+    // Assert correct break point.
+    assertTrue(breakpoint.sourceLineText().indexOf("// Break") > -1);
+    // Assert correct value.
+    assertEquals(3, breakpoint.evaluate('x').value());
+  } catch (e) {
+    exception = e;
+  }
+}
+
+Debug.setListener(listener);
+
+function h() {
+  var x;  // Context-allocated due to g().
+
+  var g = function g() {
+    x = -7;
+  };
+
+  var f = function f() {
+    var x = 3;  // Allocated in the local scope.
+    debugger;  // Break.
+  };
+
+  f();
+}
+
+h();
+
+assertFalse(exception);
diff --git a/src/v8/test/debugger/debug/regress/regress-147497.js b/src/v8/test/debugger/debug/regress/regress-147497.js
new file mode 100644
index 0000000..c0369d0
--- /dev/null
+++ b/src/v8/test/debugger/debug/regress/regress-147497.js
@@ -0,0 +1,44 @@
+// Copyright 2013 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.
+
+
+Debug = debug.Debug;
+
+function listener(event, exec_state, event_data, data) {
+  if (event == Debug.DebugEvent.Break) {
+    exec_state.prepareStep(Debug.StepAction.StepNext);
+  }
+};
+
+Debug.setListener(listener);
+
+var statement = "";
+for (var i = 0; i < 1024; i++) statement += "z";
+statement = 'with(0)' + statement + '=function foo(){}';
+
+debugger;
+eval(statement);
diff --git a/src/v8/test/debugger/debug/regress/regress-1523.js b/src/v8/test/debugger/debug/regress/regress-1523.js
new file mode 100644
index 0000000..2a6a99c
--- /dev/null
+++ b/src/v8/test/debugger/debug/regress/regress-1523.js
@@ -0,0 +1,67 @@
+// 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.
+
+// See: http://code.google.com/p/v8/issues/detail?id=1523
+
+
+Debug = debug.Debug
+
+var listenerCalled = false;
+var result = -1;
+
+function listener(event, exec_state, event_data, data) {
+  listenerCalled = true;
+};
+
+// Add the debug event listener.
+Debug.setListener(listener);
+
+function test_and(x) {
+  if (x && (bar === this.baz))
+    return 0;
+  return 1;
+}
+
+function test_or(x) {
+  if (x || (bar === this.baz))
+    return 0;
+  return 1;
+}
+
+// Set a break points and call each function to invoke the debug event listener.
+Debug.setBreakPoint(test_and, 0, 0);
+Debug.setBreakPoint(test_or, 0, 0);
+
+listenerCalled = false;
+result = test_and(false);
+assertEquals(1, result);
+assertTrue(listenerCalled);
+
+listenerCalled = false;
+result = test_or(true);
+assertEquals(0, result);
+assertTrue(listenerCalled);
diff --git a/src/v8/test/debugger/debug/regress/regress-1586.js b/src/v8/test/debugger/debug/regress/regress-1586.js
new file mode 100644
index 0000000..9975d36
--- /dev/null
+++ b/src/v8/test/debugger/debug/regress/regress-1586.js
@@ -0,0 +1,64 @@
+// 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.
+
+function f() {
+  var i = 1;          // Line 1.
+  {                   // Line 2.
+    try {             // Line 3.
+      throw 'stuff';  // Line 4.
+    } catch (e) {     // Line 5.
+      x = 2;          // Line 6.
+    }
+  }
+};
+
+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);
diff --git a/src/v8/test/debugger/debug/regress/regress-1639.js b/src/v8/test/debugger/debug/regress/regress-1639.js
new file mode 100644
index 0000000..eaaca51
--- /dev/null
+++ b/src/v8/test/debugger/debug/regress/regress-1639.js
@@ -0,0 +1,75 @@
+// 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.
+
+Debug = debug.Debug
+var breaks = 0;
+var exception = false;
+
+function listener(event, exec_state, event_data, data) {
+  try {
+    if (event == Debug.DebugEvent.Break) {
+      var line = event_data.sourceLineText();
+      print('break: ' + line);
+
+      assertEquals(-1, line.indexOf('NOBREAK'),
+                   "should not break on unexpected lines")
+      assertEquals('BREAK ' + breaks, line.substr(-7));
+      breaks++;
+      if (breaks < 4) exec_state.prepareStep(Debug.StepAction.StepNext);
+    }
+  } catch (e) {
+    print(e);
+    exception = true;
+  }
+}
+
+// Add the debug event listener.
+Debug.setListener(listener);
+
+function a(f) {
+  if (f) {  // NOBREAK: should not break here!
+    try {
+      f();
+    } catch(e) {
+    }
+  }
+}  // BREAK 2
+
+function b() {
+  c();  // BREAK 0
+}  // BREAK 1
+
+function c() {
+  a();
+}
+
+// Set a break point and call to invoke the debug event listener.
+Debug.setBreakPoint(b, 0, 0);
+a(b);
+a(); // BREAK 3
+
+assertFalse(exception);
diff --git a/src/v8/test/debugger/debug/regress/regress-1853.js b/src/v8/test/debugger/debug/regress/regress-1853.js
new file mode 100644
index 0000000..8c6e940
--- /dev/null
+++ b/src/v8/test/debugger/debug/regress/regress-1853.js
@@ -0,0 +1,99 @@
+// 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.
+
+
+// Test whether scripts compiled after setting the break point are
+// updated correctly.
+
+Debug = debug.Debug;
+
+var break_count = 0;
+var test_break_1 = false;
+var test_break_2 = false;
+
+function setBreakPointByName(state) {
+  var scripts = Debug.scripts();
+  for (var script of scripts) {
+    if (script.source_url == "testScriptOne") {
+      Debug.setScriptBreakPointById(script.id, 2);
+    }
+  }
+}
+
+function setBreakPointByRegExp(state) {
+  var scripts = Debug.scripts();
+  for (var script of scripts) {
+    if (/Scrip.Two/.test(script.source_url)) {
+      Debug.setScriptBreakPointById(script.id, 2);
+    }
+  }
+}
+
+function listener(event, exec_state, event_data, data) {
+  try {
+    if (event == Debug.DebugEvent.Break) {
+      switch (break_count) {
+        case 0:
+          // Set break points before the code has been compiled.
+          setBreakPointByName(exec_state);
+          setBreakPointByRegExp(exec_state);
+          break;
+        case 1:
+          // Set the flag to prove that we hit the first break point.
+          test_break_1 = true;
+          break;
+        case 2:
+          // Set the flag to prove that we hit the second break point.
+          test_break_2 = true;
+          break;
+      }
+      break_count++;
+    }
+  } catch (e) {
+    print(e);
+  }
+}
+
+Debug.setListener(listener);
+
+eval('function test1() {                \n' +
+     '  assertFalse(test_break_1);      \n' +
+     '  assertTrue(test_break_1);       \n' +
+     '}                                 \n' +
+     '//# sourceURL=testScriptOne');
+
+eval('function test2() {                \n' +
+     '  assertFalse(test_break_2);      \n' +
+     '  assertTrue(test_break_2);       \n' +
+     '}                                 \n' +
+     '//# sourceURL=testScriptTwo');
+
+debugger;
+
+test1();
+test2();
+assertEquals(3, break_count);
diff --git a/src/v8/test/debugger/debug/regress/regress-2296.js b/src/v8/test/debugger/debug/regress/regress-2296.js
new file mode 100644
index 0000000..230d042
--- /dev/null
+++ b/src/v8/test/debugger/debug/regress/regress-2296.js
@@ -0,0 +1,43 @@
+// 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.
+
+
+Debug = debug.Debug
+
+function listener(event, exec_state, event_data, data) {
+  try {
+    event_data.script().setSource(1);
+  } catch (e) {
+    assertTrue(String(e).indexOf("Source is not a string") > 0);
+  }
+};
+
+Debug.setListener(listener);
+
+eval('0');
+
+Debug.setListener(null);
diff --git a/src/v8/test/debugger/debug/regress/regress-269.js b/src/v8/test/debugger/debug/regress/regress-269.js
new file mode 100644
index 0000000..83b15ac
--- /dev/null
+++ b/src/v8/test/debugger/debug/regress/regress-269.js
@@ -0,0 +1,47 @@
+// Copyright 2008 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.
+
+Debug = debug.Debug
+
+function listener(event, exec_state, event_data, data) {
+  if (event == Debug.DebugEvent.Break) {
+    exec_state.prepareStep(Debug.StepAction.StepIn);
+  }
+};
+
+// Add the debug event listener.
+Debug.setListener(listener);
+
+function g() {
+}
+
+function f() {
+  debugger;
+  g.apply(null, ['']);
+}
+
+f()
diff --git a/src/v8/test/debugger/debug/regress/regress-2825.js b/src/v8/test/debugger/debug/regress/regress-2825.js
new file mode 100644
index 0000000..01bdddf
--- /dev/null
+++ b/src/v8/test/debugger/debug/regress/regress-2825.js
Binary files differ
diff --git a/src/v8/test/debugger/debug/regress/regress-325676.js b/src/v8/test/debugger/debug/regress/regress-325676.js
new file mode 100644
index 0000000..b9864e8
--- /dev/null
+++ b/src/v8/test/debugger/debug/regress/regress-325676.js
@@ -0,0 +1,68 @@
+// Copyright 2013 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.
+
+
+// If a function parameter is forced to be context allocated,
+// debug evaluate need to resolve it to a context slot instead of
+// parameter slot on the stack.
+
+var Debug = debug.Debug;
+
+var expected;
+var exception = null;
+
+function listener(event, exec_state, event_data, data) {
+  if (event != Debug.DebugEvent.Break) return;
+  try {
+    assertEquals(expected, exec_state.frame(0).evaluate('arg').value());
+    exec_state.frame(0).evaluate('arg = "evaluated";');  // no effect
+  } catch (e) {
+    exception = e;
+  }
+}
+
+Debug.setListener(listener);
+
+function f(arg) {
+  expected = arg;
+  debugger;
+  assertEquals("evaluated", arg);
+
+  arg = "value";
+  expected = arg;
+  debugger;
+  assertEquals("evaluated", arg);
+
+  // Forces arg to be context allocated even though a parameter.
+  function g() { arg; }
+}
+
+f();
+f(1);
+f(1, 2);
+
+assertNull(exception);
diff --git a/src/v8/test/debugger/debug/regress/regress-3717.js b/src/v8/test/debugger/debug/regress/regress-3717.js
new file mode 100644
index 0000000..c9949fc
--- /dev/null
+++ b/src/v8/test/debugger/debug/regress/regress-3717.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.
+
+// Flags: --no-lazy
+
+Debug = debug.Debug;
+var exception = null;
+var break_count = 0;
+
+function f() {
+  function g(p) {
+    return 1;
+  }
+  g(1);
+};
+
+function listener(event, exec_state, event_data, data) {
+  try {
+    if (event == Debug.DebugEvent.Break) break_count++;
+  } catch (e) {
+    exception = e;
+  }
+}
+
+Debug.setListener(listener);
+var bp = Debug.setBreakPoint(f, 2);
+f();
+Debug.clearBreakPoint(bp);
+Debug.setListener(null);
+
+assertEquals(1, break_count);
+assertNull(exception);
diff --git a/src/v8/test/debugger/debug/regress/regress-392114.js b/src/v8/test/debugger/debug/regress/regress-392114.js
new file mode 100644
index 0000000..b9ca4ed
--- /dev/null
+++ b/src/v8/test/debugger/debug/regress/regress-392114.js
@@ -0,0 +1,65 @@
+// Copyright 2014 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.
+
+
+Debug = debug.Debug;
+
+function dummy(x) {
+  return x + 100;
+}
+
+function create_closure() {
+  var f = function(arg) {
+    if (arg) { %DeoptimizeFunction(f); }
+    var a = Array(10);
+    for (var i = 0; i < a.length; i++) {
+      a[i] = i;
+    }
+  }
+  return f;
+}
+
+var c = create_closure();
+c();
+
+// c CallIC state now has custom Array handler installed.
+
+// Turn on the debugger.
+Debug.setListener(function () {});
+
+var d = create_closure();
+%OptimizeFunctionOnNextCall(d);
+// Thanks to the debugger, we recreate the full code too. We deopt and run
+// it, stomping on the unexpected AllocationSite in the type vector slot.
+d(true);
+
+// CallIC in c misinterprets type vector slot contents as an AllocationSite,
+// corrupting the heap.
+c();
+
+// CallIC MISS - crash due to corruption.
+dummy();
diff --git a/src/v8/test/debugger/debug/regress/regress-3960.js b/src/v8/test/debugger/debug/regress/regress-3960.js
new file mode 100644
index 0000000..6580d4b
--- /dev/null
+++ b/src/v8/test/debugger/debug/regress/regress-3960.js
@@ -0,0 +1,35 @@
+// 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 setting break point works correctly when the debugger is
+// activated late, which leads to duplicate shared function infos.
+
+(function() {
+  var Debug = %GetDebugContext().Debug;
+
+  function listener(event, exec_state, event_data, data) {
+    if (event != Debug.DebugEvent.Break) return;
+    try {
+      assertTrue(/foo/.test(exec_state.frame(0).sourceLineText()));
+      break_count++;
+    } catch (e) {
+      exception = e;
+    }
+  }
+
+  for (var i = 0; i < 3; i++) {
+    var foo = function() { a = 1; }
+    var exception = null;
+    var break_count = 0;
+    Debug.setListener(listener);
+    if (i < 2) Debug.setBreakPoint(foo, 0, 0);
+    assertTrue(/\[B\d\]a = 1/.test(Debug.showBreakPoints(foo)));
+    foo();
+    assertEquals(1, break_count);
+    assertNull(exception);
+  }
+
+  Debug.setListener(null);
+})();
diff --git a/src/v8/test/debugger/debug/regress/regress-419663.js b/src/v8/test/debugger/debug/regress/regress-419663.js
new file mode 100644
index 0000000..51bd85a
--- /dev/null
+++ b/src/v8/test/debugger/debug/regress/regress-419663.js
@@ -0,0 +1,32 @@
+// Copyright 2012 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 o = {
+  f: function(x) {
+    var a = x + 1;
+    o = 1;
+  }
+}
+
+function sentinel() {}
+
+var Debug = debug.Debug;
+
+Debug.setListener(function() {});
+
+var script = Debug.findScript(sentinel);
+
+// Used in Debug.setScriptBreakPointById.
+var p = Debug.findScriptSourcePosition(script, 8, 0);
+var q = Debug.setBreakPointByScriptIdAndPosition(script.id, p).actual_position;
+
+function assertLocation(p, l, c) {
+  var location = script.locationFromPosition(p, false);
+  assertEquals(l, location.line);
+  assertEquals(c, location.column);
+}
+
+assertLocation(p, 8, 0);
+assertLocation(q, 8, 4);
diff --git a/src/v8/test/debugger/debug/regress/regress-4309-1.js b/src/v8/test/debugger/debug/regress/regress-4309-1.js
new file mode 100644
index 0000000..2e7ef47
--- /dev/null
+++ b/src/v8/test/debugger/debug/regress/regress-4309-1.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.
+
+
+var Debug = debug.Debug;
+
+var exception = null;
+
+function listener(event, exec_state, event_data, data) {
+  if (event != Debug.DebugEvent.Break) return;
+  try {
+    var scopes = exec_state.frame().allScopes();
+    assertEquals(3, scopes.length);
+    assertEquals(debug.ScopeType.Local, scopes[0].scopeType());
+    assertEquals(debug.ScopeType.Script, scopes[1].scopeType());
+    assertEquals(debug.ScopeType.Global, scopes[2].scopeType());
+  } catch (e) {
+    exception = e;
+  }
+}
+
+function f() {
+  eval('');
+  debugger;
+}
+
+f();
+f();
+
+%OptimizeFunctionOnNextCall(f);
+Debug.setListener(listener);
+
+f();
+
+assertNull(exception);
diff --git a/src/v8/test/debugger/debug/regress/regress-4309-2.js b/src/v8/test/debugger/debug/regress/regress-4309-2.js
new file mode 100644
index 0000000..e93c8ec
--- /dev/null
+++ b/src/v8/test/debugger/debug/regress/regress-4309-2.js
@@ -0,0 +1,33 @@
+// Copyright 2015 the V8 project authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+
+var Debug = debug.Debug;
+
+var exception = null;
+
+function listener(event, exec_state, event_data, data) {
+  if (event != Debug.DebugEvent.Break) return;
+  try {
+    var scope = exec_state.frame().scope(0);
+    assertEquals(5, scope.scopeObject().property("i").value().value());
+  } catch (e) {
+    exception = e;
+  }
+}
+
+function f() {
+  eval('var i = 5');
+  debugger;
+}
+
+f();
+f();
+
+%OptimizeFunctionOnNextCall(f);
+Debug.setListener(listener);
+
+f();
+
+assertNull(exception);
diff --git a/src/v8/test/debugger/debug/regress/regress-4309-3.js b/src/v8/test/debugger/debug/regress/regress-4309-3.js
new file mode 100644
index 0000000..026a7cb
--- /dev/null
+++ b/src/v8/test/debugger/debug/regress/regress-4309-3.js
@@ -0,0 +1,38 @@
+// 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;
+
+function listener(event, exec_state, event_data, data) {
+  if (event != Debug.DebugEvent.Break) return;
+  try {
+    var scopes = exec_state.frame().allScopes();
+    assertEquals(4, scopes.length);
+    assertEquals(debug.ScopeType.With, scopes[0].scopeType());
+    assertEquals(debug.ScopeType.Local, scopes[1].scopeType());
+    assertEquals(debug.ScopeType.Script, scopes[2].scopeType());
+    assertEquals(debug.ScopeType.Global, scopes[3].scopeType());
+  } catch (e) {
+    exception = e;
+  }
+}
+
+function f() {
+  with({}) {
+    debugger;
+  }
+}
+
+f();
+f();
+
+%OptimizeFunctionOnNextCall(f);
+Debug.setListener(listener);
+
+f();
+
+assertNull(exception);
diff --git a/src/v8/test/debugger/debug/regress/regress-4320.js b/src/v8/test/debugger/debug/regress/regress-4320.js
new file mode 100644
index 0000000..5d88cc3
--- /dev/null
+++ b/src/v8/test/debugger/debug/regress/regress-4320.js
@@ -0,0 +1,20 @@
+// 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;
+
+function f() { g(); }
+
+function g() { }
+
+f();
+f();
+%OptimizeFunctionOnNextCall(f);
+f();
+
+Debug.setListener(function() {});
+Debug.setBreakPoint(g, 0);
+
+f();
diff --git a/src/v8/test/debugger/debug/regress/regress-4703.js b/src/v8/test/debugger/debug/regress/regress-4703.js
new file mode 100644
index 0000000..68832a7
--- /dev/null
+++ b/src/v8/test/debugger/debug/regress/regress-4703.js
@@ -0,0 +1,35 @@
+// 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.
+
+
+var exception = null;
+
+function listener(event, exec_state, event_data, data) {
+  if (event != debug.Debug.DebugEvent.Break) return;
+  try {
+    var all_scopes = exec_state.frame().allScopes();
+    assertEquals([ debug.ScopeType.Block,
+                   debug.ScopeType.Local,
+                   debug.ScopeType.Script,
+                   debug.ScopeType.Global ],
+                 all_scopes.map(scope => scope.scopeType()));
+  } catch (e) {
+    exception = e;
+    print(e);
+  }
+}
+
+debug.Debug.setListener(listener);
+
+(function(arg, ...rest) {
+  var one = 1;
+  function inner() {
+    one;
+    arg;
+  }
+  debugger;
+})();
+
+debug.Debug.setListener(null);
+assertNull(exception);
diff --git a/src/v8/test/debugger/debug/regress/regress-491536.js b/src/v8/test/debugger/debug/regress/regress-491536.js
new file mode 100644
index 0000000..cbe0368
--- /dev/null
+++ b/src/v8/test/debugger/debug/regress/regress-491536.js
@@ -0,0 +1,9 @@
+// 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.
+
+
+if (this["debug"]) debug.Debug.setListener(function() {});
+var source = "var outer = 0; function test() {'use strict'; outer = 1; } test(); print('ok');";
+function test_function() { eval(source); }
+assertDoesNotThrow(test_function);
diff --git a/src/v8/test/debugger/debug/regress/regress-5071.js b/src/v8/test/debugger/debug/regress/regress-5071.js
new file mode 100644
index 0000000..54557fe
--- /dev/null
+++ b/src/v8/test/debugger/debug/regress/regress-5071.js
@@ -0,0 +1,34 @@
+// Copyright 2016 the V8 project authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+//
+// Flags: --noanalyze-environment-liveness
+
+
+var Debug = debug.Debug;
+var exception = null;
+
+function listener(event, exec_state, event_data, data) {
+  if (event != Debug.DebugEvent.Break) return;
+  try {
+    assertEquals(2, exec_state.frameCount());
+    assertEquals("a", exec_state.frame(0).localName(0));
+    assertEquals(1, exec_state.frame(0).localValue(0).value());
+    assertEquals(1, exec_state.frame(0).localCount());
+  } catch (e) {
+    exception = e;
+  }
+}
+
+function f() {
+  var a = 1;
+  {
+    let b = 2;
+    debugger;
+  }
+}
+
+Debug.setListener(listener);
+f();
+Debug.setListener(null);
+assertNull(exception);
diff --git a/src/v8/test/debugger/debug/regress/regress-514362.js b/src/v8/test/debugger/debug/regress/regress-514362.js
new file mode 100644
index 0000000..beebf4c
--- /dev/null
+++ b/src/v8/test/debugger/debug/regress/regress-514362.js
@@ -0,0 +1,20 @@
+// 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.
+
+
+function bar(x) { debugger; }
+function foo() { bar(arguments[0]); }
+function wrap() { return foo(1); }
+
+wrap();
+wrap();
+%OptimizeFunctionOnNextCall(wrap);
+
+var Debug = debug.Debug;
+Debug.setListener(function(event, exec_state, event_data, data) {
+  if (event != Debug.DebugEvent.Break) return;
+  for (var i = 0; i < exec_state.frameCount(); i++) exec_state.frame(i);
+});
+
+wrap();
diff --git a/src/v8/test/debugger/debug/regress/regress-5164.js b/src/v8/test/debugger/debug/regress/regress-5164.js
new file mode 100644
index 0000000..2ac9d7a
--- /dev/null
+++ b/src/v8/test/debugger/debug/regress/regress-5164.js
@@ -0,0 +1,43 @@
+// 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.
+//
+
+var failure = null;
+var args;
+
+function listener(event, exec_state, event_data, data) {
+  if (event != debug.Debug.DebugEvent.Break) return;
+  try {
+    args = exec_state.frame(0).evaluate('arguments').value();
+  } catch (e) {
+    failure = e;
+  }
+}
+
+debug.Debug.setListener(listener);
+
+function* gen(a, b) {
+  debugger;
+  yield a;
+  yield b;
+}
+
+var foo = gen(1, 2);
+
+foo.next()
+assertEquals(2, args.length);
+assertEquals(undefined, args[0]);
+assertEquals(undefined, args[1]);
+
+foo.next()
+assertEquals(2, args.length);
+assertEquals(undefined, args[0]);
+assertEquals(undefined, args[1]);
+
+foo.next()
+assertEquals(2, args.length);
+assertEquals(undefined, args[0]);
+assertEquals(undefined, args[1]);
+
+assertNull(failure);
diff --git a/src/v8/test/debugger/debug/regress/regress-5279.js b/src/v8/test/debugger/debug/regress/regress-5279.js
new file mode 100644
index 0000000..4a30ac5
--- /dev/null
+++ b/src/v8/test/debugger/debug/regress/regress-5279.js
@@ -0,0 +1,15 @@
+// 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.
+
+
+var Debug = debug.Debug;
+
+Debug.setListener(() => undefined);
+
+const myObj = {};
+
+for (let i = 0; i < 10; i++) {
+  %OptimizeOsr();
+  %ScheduleBreak();
+}
diff --git a/src/v8/test/debugger/debug/regress/regress-5559.js b/src/v8/test/debugger/debug/regress/regress-5559.js
new file mode 100644
index 0000000..7c29f49
--- /dev/null
+++ b/src/v8/test/debugger/debug/regress/regress-5559.js
@@ -0,0 +1,37 @@
+// 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 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.StepOut);
+  } catch (e) {
+    exception = e;
+  }
+};
+
+function thrower() {
+  try {
+    debugger;             // Break 0.
+    throw 'error';
+  } catch (err) {
+  }
+}
+
+
+Debug.setListener(listener);
+thrower();
+Debug.setListener(null);  // Break 1.
+
+assertNull(exception);
+assertEquals(2, break_count);
diff --git a/src/v8/test/debugger/debug/regress/regress-617882.js b/src/v8/test/debugger/debug/regress/regress-617882.js
new file mode 100644
index 0000000..21c8ef4
--- /dev/null
+++ b/src/v8/test/debugger/debug/regress/regress-617882.js
@@ -0,0 +1,29 @@
+// Copyright 2016 the V8 project authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+// Flags: --invoke-weak-callbacks --omit-quit --gc-interval=355
+
+var __v_33 = {};
+__v_4 = 70000;
+function __f_18() {
+  if ((__v_7 % 50) != 0) {
+  } else {
+    return __v_33 + 0.5;
+  }
+}
+function __f_17(a) {
+  for (var __v_7= 0; __v_7 < __v_4; ++__v_7 ) {
+    a[__v_7] = __f_18();
+  }
+}
+for (var __v_7= 0; __v_7 < __v_4; __v_7 += 500 ) {
+}
+__v_9 = new Array();
+__f_17(__v_9);
+__v_9.length = 100;
+Debug = debug.Debug
+function __f_26() {
+      }
+__v_29 = "(function() {\
+         })()";
diff --git a/src/v8/test/debugger/debug/regress/regress-662674.js b/src/v8/test/debugger/debug/regress/regress-662674.js
new file mode 100644
index 0000000..46054a5
--- /dev/null
+++ b/src/v8/test/debugger/debug/regress/regress-662674.js
@@ -0,0 +1,14 @@
+// Copyright 2016 the V8 project authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+// Flags: --stack-size=100
+
+Debug = debug.Debug
+
+function overflow() {
+  return overflow();
+}
+
+Debug.setBreakOnException();
+assertThrows(overflow, RangeError);
diff --git a/src/v8/test/debugger/debug/regress/regress-662935.js b/src/v8/test/debugger/debug/regress/regress-662935.js
new file mode 100644
index 0000000..04ed6d9
--- /dev/null
+++ b/src/v8/test/debugger/debug/regress/regress-662935.js
@@ -0,0 +1,15 @@
+// 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
+function overflow() {
+  return new Promise(function foo() { foo() });
+}
+
+function listener(event, exec_state, event_data, data) { }
+
+Debug.setListener(listener);
+
+assertEquals(Promise, overflow().constructor);
diff --git a/src/v8/test/debugger/debug/regress/regress-crbug-107996.js b/src/v8/test/debugger/debug/regress/regress-crbug-107996.js
new file mode 100644
index 0000000..f671ca8
--- /dev/null
+++ b/src/v8/test/debugger/debug/regress/regress-crbug-107996.js
@@ -0,0 +1,68 @@
+// 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.
+
+
+Debug = debug.Debug;
+
+Debug.setListener(listener);
+var exception = null;
+var fourteen;
+var four_in_debugger = [];
+
+function listener(event, exec_state, event_data, data) {
+  if (event == Debug.DebugEvent.Break) {
+    try {
+      for (var i = 0; i < exec_state.frameCount() - 1; i++) {
+        var frame = exec_state.frame(i);
+        four_in_debugger[i] = frame.evaluate("four", false).value();
+      }
+    } catch (e) {
+      exception = e;
+    }
+  }
+}
+
+function f1() {
+  var three = 3;
+  var four = 4;
+  (function f2() {
+     var seven = 7;
+     (function f3() {
+        debugger;
+        fourteen = three + four + seven;
+     })();
+  })();
+}
+
+f1();
+assertEquals(14, fourteen);
+assertEquals(4, four_in_debugger[0]);
+assertEquals(4, four_in_debugger[1]);
+assertEquals(4, four_in_debugger[2]);
+
+Debug.setListener(null);
+assertNull(exception);
diff --git a/src/v8/test/debugger/debug/regress/regress-crbug-119800.js b/src/v8/test/debugger/debug/regress/regress-crbug-119800.js
new file mode 100644
index 0000000..b3f39b9
--- /dev/null
+++ b/src/v8/test/debugger/debug/regress/regress-crbug-119800.js
@@ -0,0 +1,37 @@
+// 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.
+
+
+function f() {
+  print(1);
+  print(2);
+  print(3);
+}
+
+var Debug = debug.Debug;
+var exception = null;
+var breaks = [];
+
+function listener(event, exec_state, event_data, data) {
+  if (event != Debug.DebugEvent.Break) return;
+  try {
+    Debug.debuggerFlags().breakPointsActive.setValue(false);
+    breaks.push(exec_state.frame().sourceLineText().trimLeft());
+    exec_state.prepareStep(Debug.StepAction.StepIn);
+  } catch (e) {
+    exception = e;
+  }
+}
+
+Debug.setListener(listener);
+Debug.setBreakPoint(f, 0, 0);
+
+f();
+
+Debug.setListener(null);
+Debug.debuggerFlags().breakPointsActive.setValue(true);
+
+assertNull(exception);
+assertEquals(breaks, ["print(1);", "print(2);", "print(3);", "}",
+                      "Debug.setListener(null);"]);
diff --git a/src/v8/test/debugger/debug/regress/regress-crbug-171715.js b/src/v8/test/debugger/debug/regress/regress-crbug-171715.js
new file mode 100644
index 0000000..7024cdf
--- /dev/null
+++ b/src/v8/test/debugger/debug/regress/regress-crbug-171715.js
@@ -0,0 +1,87 @@
+// Copyright 2013 the V8 project authors. All rights reserved.
+// Redistribution and use in source and binary forms, with or without
+// modification, are permitted provided that the following conditions are
+// met:
+//
+//     * Redistributions of source code must retain the above copyright
+//       notice, this list of conditions and the following disclaimer.
+//     * Redistributions in binary form must reproduce the above
+//       copyright notice, this list of conditions and the following
+//       disclaimer in the documentation and/or other materials provided
+//       with the distribution.
+//     * Neither the name of Google Inc. nor the names of its
+//       contributors may be used to endorse or promote products derived
+//       from this software without specific prior written permission.
+//
+// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+
+// Flags: --no-always-opt --no-stress-opt
+
+Debug = debug.Debug
+
+var error = null;
+var test = 0;
+
+function check_v(expected, exec_state, frame_id) {
+  assertEquals(expected, exec_state.frame(frame_id).evaluate('v').value());
+}
+
+function listener(event, exec_state, event_data, data) {
+  try {
+    if (event != Debug.DebugEvent.Break) return;
+    test++;
+    if (test == 1) {
+      check_v('inner0', exec_state, 0);
+      check_v('inner0', exec_state, 1);
+      check_v('outer',  exec_state, 2);
+      assertArrayEquals(["a", "b", "c"],
+                        exec_state.frame(0).evaluate('arguments').value());
+    } else if (test == 2) {
+      check_v('inner1', exec_state, 0);
+      check_v('inner1', exec_state, 1);
+      check_v('outer',  exec_state, 2);
+      assertArrayEquals(["a", "b", "c"],
+                        exec_state.frame(0).evaluate('arguments').value());
+    } else {
+      assertEquals(3, test);
+      check_v('inner2', exec_state, 0);
+      check_v('inner1', exec_state, 1);
+      check_v('inner1', exec_state, 2);
+      check_v('outer',  exec_state, 3);
+      assertArrayEquals(["x", "y", "z"],
+                        exec_state.frame(0).evaluate('arguments').value());
+      assertArrayEquals(["a", "b", "c"],
+                        exec_state.frame(1).evaluate('arguments').value());
+    }
+  } catch (e) {
+    error = e;
+  }
+};
+
+Debug.setListener(listener);
+
+var v = 'outer';
+(function() {  // Test 1 and 2
+  var v = 'inner0';
+  eval("debugger; var v = 'inner1'; debugger;");
+  assertEquals('inner1', v);  // Overwritten by local eval.
+})("a", "b", "c");
+assertNull(error);
+
+(function() {  // Test 3
+  var v = 'inner0';  // Local eval overwrites this value.
+  eval("var v = 'inner1'; " +
+       "(function() { var v = 'inner2'; debugger; })('x', 'y', 'z');");
+  assertEquals('inner1', v);  // Overwritten by local eval.
+})("a", "b", "c");
+assertNull(error);
diff --git a/src/v8/test/debugger/debug/regress/regress-crbug-222893.js b/src/v8/test/debugger/debug/regress/regress-crbug-222893.js
new file mode 100644
index 0000000..b7838bb
--- /dev/null
+++ b/src/v8/test/debugger/debug/regress/regress-crbug-222893.js
@@ -0,0 +1,85 @@
+// Copyright 2013 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
+
+Debug = debug.Debug
+
+var error = null;
+var array = ["a", "b", "c"];
+var result = null;
+
+function listener(event, exec_state, event_data, data) {
+  try {
+    if (event == Debug.DebugEvent.Break) {
+      result = exec_state.frame(0).evaluate('arguments').value();
+    }
+  } catch (e) {
+    error = e;
+  }
+};
+
+Debug.setListener(listener);
+
+
+function f(a, b) {
+  arguments;
+  debugger;  // Arguments object is already materialized.
+}
+
+result = null;
+f.apply(this, array);
+assertArrayEquals(array, result);
+result = null;
+f("a", "b", "c");
+assertArrayEquals(array, result);
+assertNull(error);
+
+function g(a, b) {
+  debugger;  // Arguments object is not yet materialized.
+}
+
+result = null;
+g.apply(this, array);
+assertArrayEquals(array, result);
+result = null;
+g("a", "b", "c");
+assertArrayEquals(array, result);
+assertNull(error);
+
+function h(a, b) {
+  var arguments = undefined;
+  debugger;  // Arguments already used as local variable.
+}
+
+result = null;
+h.apply(this, array);
+assertEquals(undefined, result);
+result = null;
+h("a", "b", "c");
+assertEquals(undefined, result);
+assertNull(error);
diff --git a/src/v8/test/debugger/debug/regress/regress-crbug-323936.js b/src/v8/test/debugger/debug/regress/regress-crbug-323936.js
new file mode 100644
index 0000000..391b095
--- /dev/null
+++ b/src/v8/test/debugger/debug/regress/regress-crbug-323936.js
@@ -0,0 +1,52 @@
+// Copyright 2014 the V8 project authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+// Flags: --no-always-opt
+
+Debug = debug.Debug;
+
+var step = 0;
+var exception = null;
+
+function listener(event, exec_state, event_data, data) {
+  if (event != Debug.DebugEvent.Break) return;
+  try {
+    if (step == 0) {
+      assertEquals("error", exec_state.frame(0).evaluate("e").value());
+      exec_state.frame(0).evaluate("write_0('foo')");
+      exec_state.frame(0).evaluate("write_1('modified')");
+    } else {
+      assertEquals("argument", exec_state.frame(0).evaluate("e").value());
+      exec_state.frame(0).evaluate("write_2('bar')");
+    }
+    step++;
+  } catch (e) {
+    print(e + e.stack);
+    exception = e;
+  }
+}
+
+Debug.setListener(listener);
+
+function f(e, x) {
+  try {
+    throw "error";
+  } catch(e) {
+    // In ES2015 hoisting semantics, 'x' binds to the argument
+    // and 'e' binds to the exception.
+    function write_0(v) { e = v }
+    function write_1(v) { x = v }
+    debugger;
+    assertEquals("foo", e);  // overwritten by the debugger
+  }
+  assertEquals("argument", e);  // debugger did not overwrite
+  function write_2(v) { e = v }
+  debugger;
+  assertEquals("bar", e);
+  assertEquals("modified", x);
+}
+
+f("argument")
+assertNull(exception);
+assertEquals(2, step);
diff --git a/src/v8/test/debugger/debug/regress/regress-crbug-387599.js b/src/v8/test/debugger/debug/regress/regress-crbug-387599.js
new file mode 100644
index 0000000..bf15cba
--- /dev/null
+++ b/src/v8/test/debugger/debug/regress/regress-crbug-387599.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.
+
+
+Debug = debug.Debug;
+Debug.setListener(function() {});
+
+function f() {
+  for (var i = 0; i < 100; i++) %OptimizeOsr();
+}
+
+Debug.setBreakPoint(f, 0, 0);
+f();
+f();
+Debug.setListener(null);
diff --git a/src/v8/test/debugger/debug/regress/regress-crbug-401915.js b/src/v8/test/debugger/debug/regress/regress-crbug-401915.js
new file mode 100644
index 0000000..7c791e4
--- /dev/null
+++ b/src/v8/test/debugger/debug/regress/regress-crbug-401915.js
@@ -0,0 +1,19 @@
+// 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;
+Debug.setListener(function() {});
+Debug.setBreakOnException();
+
+try {
+  try {
+    %DebugPushPromise(new Promise(function() {}));
+  } catch (e) {
+  }
+  throw new Error();
+} catch (e) {
+}
+
+Debug.setListener(null);
diff --git a/src/v8/test/debugger/debug/regress/regress-crbug-405922.js b/src/v8/test/debugger/debug/regress/regress-crbug-405922.js
new file mode 100644
index 0000000..116eabd
--- /dev/null
+++ b/src/v8/test/debugger/debug/regress/regress-crbug-405922.js
@@ -0,0 +1,29 @@
+// 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);
+    }
+  } catch (e) {
+    exception = e;
+  }
+}
+
+Debug.setListener(listener);
+
+function f(x) {
+  if (x > 0) %_Call(f, null, x-1);
+}
+
+debugger;
+f(2);
+
+Debug.setListener(null);
+assertNull(exception);
diff --git a/src/v8/test/debugger/debug/regress/regress-crbug-409614.js b/src/v8/test/debugger/debug/regress/regress-crbug-409614.js
new file mode 100644
index 0000000..609aa80
--- /dev/null
+++ b/src/v8/test/debugger/debug/regress/regress-crbug-409614.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.
+
+
+Debug = debug.Debug;
+var exception = null;
+var error_count = 0;
+
+function f() {
+  return 0;  // Break
+}            // Break
+
+function listener(event, exec_state, event_data, data) {
+  if (event != Debug.DebugEvent.Break) return;
+  try {
+    if (exec_state.frame(0).sourceLineText().indexOf("Break") <0) {
+      error_count++;
+    }
+    exec_state.prepareStep(Debug.StepAction.StepIn);
+    f();  // We should not break in this call of f().
+  } catch (e) {
+    print(e + e.stack);
+    exception = e;
+  }
+}
+
+Debug.setListener(listener);
+
+debugger;  // Break
+f();       // Break
+
+Debug.setListener(null);  // Break
+
+assertNull(exception);
+assertEquals(0, error_count);
diff --git a/src/v8/test/debugger/debug/regress/regress-crbug-424142.js b/src/v8/test/debugger/debug/regress/regress-crbug-424142.js
new file mode 100644
index 0000000..bda061c
--- /dev/null
+++ b/src/v8/test/debugger/debug/regress/regress-crbug-424142.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.
+
+
+(function outer() {
+  var C = (function C_() {
+    var y = 1;
+    function CC() {
+      this.x = 0;
+    }
+    CC.prototype.f = function CCf() {
+      this.x += y;
+      return this.x;
+    };
+    return CC;
+  })();
+
+  var c = new C(0);
+})
+
+function sentinel() {}
+
+Debug = debug.Debug;
+Debug.setListener(function(){});
+
+var script = Debug.findScript(sentinel);
+var line = 13;
+var line_start = Debug.findScriptSourcePosition(script, line, 0);
+var line_end = Debug.findScriptSourcePosition(script, line + 1, 0) - 1;
+var actual = Debug.setBreakPointByScriptIdAndPosition(
+                 script.id, line_start).actual_position;
+// Make sure the actual break position is within the line where we set
+// the break point.
+assertTrue(line_start <= actual);
+assertTrue(actual <= line_end);
+
+Debug.setListener(null);
diff --git a/src/v8/test/debugger/debug/regress/regress-crbug-432493.js b/src/v8/test/debugger/debug/regress/regress-crbug-432493.js
new file mode 100644
index 0000000..37a7558
--- /dev/null
+++ b/src/v8/test/debugger/debug/regress/regress-crbug-432493.js
@@ -0,0 +1,56 @@
+// Copyright 2014 the V8 project authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+
+function f() {
+  var a = 1;
+  var b = 2;
+  return a + b;
+}
+
+var exception = null;
+var break_count = 0;
+var throw_count = 0;
+
+function listener(event, exec_state, event_data, data) {
+  try {
+    if (event == Debug.DebugEvent.Break) {
+      break_count++;
+      // Disable all breakpoints from within the debug event callback.
+      Debug.debuggerFlags().breakPointsActive.setValue(false);
+    } else if (event = Debug.DebugEvent.Exception) {
+      throw_count++;
+      // Enable all breakpoints from within the debug event callback.
+      Debug.debuggerFlags().breakPointsActive.setValue(true);
+    }
+  } catch (e) {
+    exception = e;
+  }
+}
+
+Debug = debug.Debug;
+
+Debug.setListener(listener);
+Debug.setBreakOnException();
+Debug.setBreakPoint(f, 2);
+
+f();
+f();
+
+assertEquals(1, break_count);
+assertEquals(0, throw_count);
+
+// Trigger exception event.
+try { throw 1; } catch (e) {}
+
+f();
+f();
+
+Debug.setListener(null);
+Debug.clearBreakOnException();
+Debug.debuggerFlags().breakPointsActive.setValue(true);
+
+assertEquals(2, break_count);
+assertEquals(1, throw_count);
+assertNull(exception);
diff --git a/src/v8/test/debugger/debug/regress/regress-crbug-465298.js b/src/v8/test/debugger/debug/regress/regress-crbug-465298.js
new file mode 100644
index 0000000..512a9e0
--- /dev/null
+++ b/src/v8/test/debugger/debug/regress/regress-crbug-465298.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: --noturbo-inlining
+
+var stdlib = this;
+var buffer = new ArrayBuffer(64 * 1024);
+var foreign = { thrower: thrower, debugme: debugme }
+
+Debug = debug.Debug;
+
+var listenerCalled = false;
+function listener(event, exec_state, event_data, data) {
+  try {
+    if (event == Debug.DebugEvent.Break) {
+      var frame = exec_state.frame(1);
+      assertEquals("foo", frame.func().name());
+      listenerCalled = true;
+    }
+  } catch (e) {
+    print("Caught: " + e + " " + e.stack);
+  };
+}
+
+function thrower() { throw "boom"; }
+function debugme() { Debug.setListener(listener); debugger; }
+
+function Module(stdlib, foreign, heap) {
+  "use asm";
+  var thrower = foreign.thrower;
+  var debugme = foreign.debugme;
+  function foo(i) {
+    i = i|0;
+    var a = 101;  // Local variables exist ...
+    var b = 102;  // ... to make the debugger ...
+    var c = 103;  // ... inspect them during break.
+    if (i > 0) {
+      debugme();
+      i = 23;
+    } else {
+      thrower();
+      i = 42;
+    }
+    return i|0;
+  }
+  return { foo: foo };
+}
+
+var m = Module(stdlib, foreign, buffer);
+
+assertThrows("m.foo(0)");
+assertEquals(23, m.foo(1));
+assertTrue(listenerCalled);
diff --git a/src/v8/test/debugger/debug/regress/regress-crbug-467180.js b/src/v8/test/debugger/debug/regress/regress-crbug-467180.js
new file mode 100644
index 0000000..71e38c3
--- /dev/null
+++ b/src/v8/test/debugger/debug/regress/regress-crbug-467180.js
@@ -0,0 +1,40 @@
+// 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.
+
+
+function f() {
+  for (var i = 10; i < 14; i++) {  // 1
+    i *= 1;                        // 2
+  }
+}                                  // 3
+
+var state = "conditional";
+var log = [];
+var exception = null;
+
+function listener(event, exec_state, event_data, data) {
+  if (event != Debug.DebugEvent.Break) return;
+  try {
+    var label = +exec_state.frame(0).sourceLineText().substr(-1);
+    log.push(label);
+    if (label == 2) log.push(exec_state.frame(0).evaluate("i").value());
+    exec_state.prepareStep(Debug.StepAction.StepNext);
+  } catch (e) {
+    exception = e;
+    print("Caught something. " + e + " " + e.stack);
+  };
+};
+
+
+var Debug = debug.Debug;
+Debug.setListener(listener);
+
+Debug.setBreakPoint(f, 2, 0, "i == 12");
+
+f();
+
+Debug.setListener(null);  // 4
+
+assertEquals([2,12,1,1,2,13,1,1,3,4], log);
+assertNull(exception);
diff --git a/src/v8/test/debugger/debug/regress/regress-crbug-481896.js b/src/v8/test/debugger/debug/regress/regress-crbug-481896.js
new file mode 100644
index 0000000..d123980
--- /dev/null
+++ b/src/v8/test/debugger/debug/regress/regress-crbug-481896.js
@@ -0,0 +1,55 @@
+// 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.
+
+
+function static() {
+  print("> static");  // Break
+}
+
+var 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("breakpoint hit at " + exec_state.frame(0).sourceLineText());
+    assertTrue(exec_state.frame(0).sourceLineText().indexOf("// Break") > 0);
+    break_count++;
+  } catch (e) {
+    exception = e;
+  }
+}
+
+Debug.setListener(listener);
+
+function install() {
+  eval("this.dynamic = function dynamic() { \n" +
+       "  print(\"> dynamic\");  // Break\n" +
+       "}\n" +
+       "//@ sourceURL=dynamicScript");
+}
+
+install();
+
+var scripts = Debug.scripts();
+var dynamic_script;
+var static_script;
+for (var script of scripts) {
+  if (script.source_url == "dynamicScript") dynamic_script = script;
+  if (script.source_url == "staticScript") static_script = script;
+}
+
+Debug.setScriptBreakPointById(dynamic_script.id, 1);
+Debug.setScriptBreakPointById(static_script.id, 6);
+
+dynamic();
+static();
+
+Debug.setListener(null);
+
+assertNull(exception);
+assertEquals(2, break_count);
+
+//@ sourceURL=staticScript
diff --git a/src/v8/test/debugger/debug/regress/regress-crbug-487289.js b/src/v8/test/debugger/debug/regress/regress-crbug-487289.js
new file mode 100644
index 0000000..b1815e4
--- /dev/null
+++ b/src/v8/test/debugger/debug/regress/regress-crbug-487289.js
@@ -0,0 +1,19 @@
+// 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 receiver = null;
+
+Debug.setListener(function(event, exec_state, event_data, data) {
+  if (event != Debug.DebugEvent.Break) return;
+  receiver = exec_state.frame(0).evaluate('this').value();
+});
+
+function f() { debugger; }
+
+var expected = {};
+f.call(expected);
+
+assertEquals(expected, receiver);
diff --git a/src/v8/test/debugger/debug/regress/regress-crbug-491943.js b/src/v8/test/debugger/debug/regress/regress-crbug-491943.js
new file mode 100644
index 0000000..39b4a60
--- /dev/null
+++ b/src/v8/test/debugger/debug/regress/regress-crbug-491943.js
@@ -0,0 +1,24 @@
+// 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 receiver = null;
+
+Debug.setListener(function(event, exec_state, event_data, data) {
+  if (event != Debug.DebugEvent.Break) return;
+  receiver = exec_state.frame(0).evaluate('this').value();
+});
+
+
+function f() {
+  var context_local = 1;
+  (function() { return context_local; })();
+  debugger;
+}
+
+var expected = {};
+f.call(expected);
+
+assertEquals(expected, receiver);
diff --git a/src/v8/test/debugger/debug/regress/regress-crbug-517592.js b/src/v8/test/debugger/debug/regress/regress-crbug-517592.js
new file mode 100644
index 0000000..e4a905d
--- /dev/null
+++ b/src/v8/test/debugger/debug/regress/regress-crbug-517592.js
@@ -0,0 +1,34 @@
+// 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 source =
+  "var foo = function foo() {\n" +
+  "  return 1;\n" +
+  "}\n" +
+  "//@ sourceURL=test";
+
+Debug = debug.Debug;
+Debug.setListener(listener);
+var exception = null;
+var break_count = 0;
+
+function listener(event, exec_state, event_data, data) {
+  if (event == Debug.DebugEvent.Break) break_count++;
+  if (event != Debug.DebugEvent.AfterCompile) return;
+  try {
+    var name = event_data.script().name();
+    var id = event_data.script().id();
+    assertEquals("test", name);
+    Debug.setScriptBreakPointById(id, 2);
+  } catch (e) {
+    exception = e;
+  }
+}
+
+eval(source);
+
+assertEquals(0, break_count);
+foo();
+assertEquals(1, break_count);
+assertNull(exception);
diff --git a/src/v8/test/debugger/debug/regress/regress-crbug-568477-1.js b/src/v8/test/debugger/debug/regress/regress-crbug-568477-1.js
new file mode 100644
index 0000000..f9a7ba4
--- /dev/null
+++ b/src/v8/test/debugger/debug/regress/regress-crbug-568477-1.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.
+
+
+var Debug = debug.Debug;
+var expected = ["debugger;", "var x = y;", "debugger;", "var x = y;"];
+var log = [];
+
+function listener(event, exec_state, event_data, data) {
+  if (event != Debug.DebugEvent.Break) return;
+  try {
+    var line = exec_state.frame(0).sourceLineText().trimLeft();
+    log.push(line);
+    if (line == "debugger;") exec_state.prepareStep(Debug.StepAction.StepNext);
+  } catch (e) {
+    %AbortJS(e + "\n" + e.stack);
+  }
+}
+
+Debug.setListener(listener);
+
+function f() {
+  var a = 1;
+  debugger;
+  var x = y;
+  print(x);
+}
+
+function call_f_with_deeper_stack() {
+  (() => () => () => f())()()();
+}
+
+Promise.resolve().then(f).catch(call_f_with_deeper_stack);
+
+// Schedule microtask to check against expectation at the end.
+function testDone(iteration) {
+  function checkResult() {
+    try {
+      assertTrue(iteration < 10);
+      if (expected.length == log.length) {
+        assertEquals(expected, log);
+      } else {
+        testDone(iteration + 1);
+      }
+    } catch (e) {
+      %AbortJS(e + "\n" + e.stack);
+    }
+  }
+
+  %EnqueueMicrotask(checkResult);
+}
+
+testDone(0);
diff --git a/src/v8/test/debugger/debug/regress/regress-crbug-568477-2.js b/src/v8/test/debugger/debug/regress/regress-crbug-568477-2.js
new file mode 100644
index 0000000..0ea4b7e
--- /dev/null
+++ b/src/v8/test/debugger/debug/regress/regress-crbug-568477-2.js
@@ -0,0 +1,37 @@
+// 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 expected = ["debugger;",
+                "var x = y;",
+                "debugger;",
+                "var x = y;"];
+
+function listener(event, exec_state, event_data, data) {
+  if (event != Debug.DebugEvent.Break) return;
+  try {
+    var line = exec_state.frame(0).sourceLineText().trimLeft();
+    assertEquals(expected.shift(), line);
+    if (line == "debugger;") exec_state.prepareStep(Debug.StepAction.StepNext);
+  } catch (e) {
+    %AbortJS(e + "\n" + e.stack);
+  }
+}
+
+Debug.setListener(listener);
+
+function f() {
+  var a = 1;
+  debugger;
+  var x = y;
+  print(x);
+}
+
+function call_f_with_deeper_stack() {
+  (() => () => () => f())()()();
+}
+
+new Promise(f).catch(call_f_with_deeper_stack);
+var a = 1;
diff --git a/src/v8/test/debugger/debug/regress/regress-crbug-568477-3.js b/src/v8/test/debugger/debug/regress/regress-crbug-568477-3.js
new file mode 100644
index 0000000..fcc16bf
--- /dev/null
+++ b/src/v8/test/debugger/debug/regress/regress-crbug-568477-3.js
@@ -0,0 +1,56 @@
+// 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 expected = ["debugger;", "var x = y;", "debugger;", "var x = y;"];
+var log = [];
+
+function listener(event, exec_state, event_data, data) {
+  if (event != Debug.DebugEvent.Break) return;
+  try {
+    var line = exec_state.frame(0).sourceLineText().trimLeft();
+    log.push(line);
+    if (line == "debugger;") exec_state.prepareStep(Debug.StepAction.StepNext);
+  } catch (e) {
+    %AbortJS(e + "\n" + e.stack);
+  }
+}
+
+Debug.setListener(listener);
+
+function f() {
+  var a = 1;
+  debugger;
+  var x = y;
+  print(x);
+}
+
+function call_f_with_deeper_stack() {
+  (() => () => () => f())()()();
+}
+
+var p = Promise.resolve();
+p.then(f);
+p.then(call_f_with_deeper_stack);
+
+// Schedule microtask to check against expectation at the end.
+function testDone(iteration) {
+  function checkResult() {
+    try {
+      assertTrue(iteration < 10);
+      if (expected.length == log.length) {
+        assertEquals(expected, log);
+      } else {
+        testDone(iteration + 1);
+      }
+    } catch (e) {
+      %AbortJS(e + "\n" + e.stack);
+    }
+  }
+
+  %EnqueueMicrotask(checkResult);
+}
+
+testDone(0);
diff --git a/src/v8/test/debugger/debug/regress/regress-crbug-568477-4.js b/src/v8/test/debugger/debug/regress/regress-crbug-568477-4.js
new file mode 100644
index 0000000..95bc939
--- /dev/null
+++ b/src/v8/test/debugger/debug/regress/regress-crbug-568477-4.js
@@ -0,0 +1,38 @@
+// 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 expected = ["debugger;", "var x = y;"];
+var log = [];
+
+function listener(event, exec_state, event_data, data) {
+  if (event != Debug.DebugEvent.Break) return;
+  try {
+    var line = exec_state.frame(0).sourceLineText().trimLeft();
+    log.push(line);
+    if (line == "debugger;") exec_state.prepareStep(Debug.StepAction.StepNext);
+  } catch (e) {
+    %AbortJS(e + "\n" + e.stack);
+  }
+}
+
+Debug.setListener(listener);
+
+function f() {
+  var a = 1;
+  debugger;
+  var x = y;
+  print(x);
+}
+
+try {
+  %Call(f, {});
+} catch (e) {
+  var b = 2;
+}
+
+Debug.setListener(null);
+
+assertEquals(expected, log);
diff --git a/src/v8/test/debugger/debug/regress/regress-crbug-582048.js b/src/v8/test/debugger/debug/regress/regress-crbug-582048.js
new file mode 100644
index 0000000..77efe3c
--- /dev/null
+++ b/src/v8/test/debugger/debug/regress/regress-crbug-582048.js
@@ -0,0 +1,30 @@
+// 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.
+
+
+var Debug = debug.Debug;
+
+function listener(event, exec_state, event_data, data) {
+  if (event != Debug.DebugEvent.Break) return;
+  try {
+    var frame_count = exec_state.frameCount();
+    for (var i = 0; i < frame_count; i++) {
+      var frame = exec_state.frame(i);
+      var scope_count = frame.scopeCount();
+      for (var j = 0; j < scope_count; j++) {
+        var scope = frame.scope(j);
+        assertTrue(scope.scopeObject().property('').isUndefined());
+      }
+    }
+  } catch (e) {
+    print(e, e.stack);
+    exception = e;
+  }
+}
+
+Debug.setListener(listener);
+
+(function(a = 1) { debugger; })();
+
+Debug.setListener(null);
diff --git a/src/v8/test/debugger/debug/regress/regress-crbug-582051.js b/src/v8/test/debugger/debug/regress/regress-crbug-582051.js
new file mode 100644
index 0000000..65dea82
--- /dev/null
+++ b/src/v8/test/debugger/debug/regress/regress-crbug-582051.js
@@ -0,0 +1,43 @@
+// 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.
+
+
+var test_y = false;
+
+function foo(a = 1) {
+  var x = 2;
+  debugger;
+  eval("var y = 3");
+  test_y = true;
+  debugger;
+}
+
+var exception = null;
+var break_count = 0;
+var Debug = debug.Debug;
+var ScopeType = debug.ScopeType;
+
+function listener(event, exec_state) {
+  if (event != Debug.DebugEvent.Break) return;
+  try {
+    var scopes = exec_state.frame(0).allScopes();
+    var expectation = [ ScopeType.Block,
+                        ScopeType.Local,
+                        ScopeType.Script,
+                        ScopeType.Global ];
+    assertEquals(expectation, scopes.map(x => x.scopeType()));
+    assertEquals(2, scopes[0].scopeObject().value().x);
+    if (test_y) assertEquals(3, scopes[0].scopeObject().value().y);
+    assertEquals(1, scopes[1].scopeObject().value().a);
+    break_count++;
+  } catch (e) {
+    print(e);
+    exception = e;
+  }
+}
+Debug.setListener(listener);
+foo();
+
+assertNull(exception);
+assertEquals(2, break_count);
diff --git a/src/v8/test/debugger/debug/regress/regress-crbug-605581.js b/src/v8/test/debugger/debug/regress/regress-crbug-605581.js
new file mode 100644
index 0000000..f151b92
--- /dev/null
+++ b/src/v8/test/debugger/debug/regress/regress-crbug-605581.js
@@ -0,0 +1,27 @@
+// 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.
+
+
+var Debug = debug.Debug;
+var exception = null;
+
+function listener(event, exec_state, event_data, data) {
+  if (event != Debug.DebugEvent.Break) return;
+  try {
+    assertThrows(() => exec_state.frame(0).evaluate("bar.baz"), ReferenceError);
+  } catch (e) {
+    exception = e;
+  }
+}
+
+Debug.setListener(listener);
+
+(function() {
+  debugger;    // bar is still in TDZ at this point.
+  let bar = 1;
+  (x => bar);  // force bar to be context-allocated.
+})();
+
+Debug.setListener(null);
+assertNull(exception);
diff --git a/src/v8/test/debugger/debug/regress/regress-crbug-609046.js b/src/v8/test/debugger/debug/regress/regress-crbug-609046.js
new file mode 100644
index 0000000..1bc91fb
--- /dev/null
+++ b/src/v8/test/debugger/debug/regress/regress-crbug-609046.js
@@ -0,0 +1,35 @@
+// 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 hidden scopes are correctly walked in the scope chain.
+
+var Debug = debug.Debug;
+var exception = null;
+var delegate = null;
+var done = false;
+
+function listener(event, exec_state, event_data, data) {
+  if (event != Debug.DebugEvent.Break) return;
+  try {
+    assertEquals([ debug.ScopeType.Block,
+                   debug.ScopeType.Script,
+                   debug.ScopeType.Global ],
+                 exec_state.frame(0).allScopes().map(s => s.scopeType()));
+    done = true;
+  } catch (e) {
+    exception = e;
+  }
+}
+
+Debug.setListener(listener);
+
+for(let a = 0; a < 3; a++) {
+  debugger;
+  eval();  // Force context-allocation of everything.
+}
+
+Debug.setListener(null);
+assertNull(exception);
+assertTrue(done);
diff --git a/src/v8/test/debugger/debug/regress/regress-crbug-621361.js b/src/v8/test/debugger/debug/regress/regress-crbug-621361.js
new file mode 100644
index 0000000..b66767f
--- /dev/null
+++ b/src/v8/test/debugger/debug/regress/regress-crbug-621361.js
@@ -0,0 +1,39 @@
+// Copyright 2016 the V8 project authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+
+var Debug = debug.Debug;
+var steps = 0;
+var exception = null;
+
+function listener(event, execState, eventData, data) {
+  if (event != Debug.DebugEvent.Break) return;
+  try {
+    assertEquals([ debug.ScopeType.Local,
+                   debug.ScopeType.Script,
+                   debug.ScopeType.Global],
+                 execState.frame().allScopes().map(s => s.scopeType()));
+    var x_value = execState.frame().evaluate("String(x)").value();
+    if (steps < 2) {
+      assertEquals("undefined", x_value);
+      execState.prepareStep(Debug.StepAction.StepIn);
+    } else {
+      assertEquals("l => l", x_value);
+    }
+    steps++;
+  } catch (e) {
+    exception = e;
+  }
+}
+
+Debug.setListener(listener);
+
+(function() {
+  debugger;
+  var x = l => l;
+})();
+
+Debug.setListener(null);
+assertNull(exception);
+assertEquals(3, steps);
diff --git a/src/v8/test/debugger/debug/regress/regress-crbug-633999.js b/src/v8/test/debugger/debug/regress/regress-crbug-633999.js
new file mode 100644
index 0000000..ebaabd7
--- /dev/null
+++ b/src/v8/test/debugger/debug/regress/regress-crbug-633999.js
@@ -0,0 +1,40 @@
+// Copyright 2016 the V8 project authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+// Flags: --opt --no-turbo
+
+var Debug = debug.Debug
+var exception = null;
+var step = 0;
+
+function listener(event, exec_state, event_data, data) {
+  if (event != Debug.DebugEvent.Exception) return;
+  try {
+    step++;
+  } catch (e) {
+    exception = e;
+  }
+}
+
+Debug.setBreakOnException();
+Debug.setListener(listener);
+
+(function () {
+  "use asm";
+  function f() {
+    try {
+      throw 666;
+    } catch (e) {
+    }
+  }
+  f();
+  f();
+  %OptimizeFunctionOnNextCall(f);
+  f();
+  assertOptimized(f);
+})();
+
+Debug.setListener(null);
+assertNull(exception);
+assertEquals(3, step);
diff --git a/src/v8/test/debugger/debug/regress/regress-debug-code-recompilation.js b/src/v8/test/debugger/debug/regress/regress-debug-code-recompilation.js
new file mode 100644
index 0000000..ce6ce86
--- /dev/null
+++ b/src/v8/test/debugger/debug/regress/regress-debug-code-recompilation.js
@@ -0,0 +1,48 @@
+// 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.
+
+Debug = debug.Debug
+Debug.setListener(function(){});
+
+function f() {a=1;b=2};
+function g() {
+  a=1;
+  b=2;
+}
+
+bp = Debug.setBreakPoint(f, 0, 0);
+Debug.clearBreakPoint(bp);
+%OptimizeFunctionOnNextCall(Debug.setBreakPoint);
+bp = Debug.setBreakPoint(f, 0, 0);
+Debug.clearBreakPoint(bp);
+bp = Debug.setBreakPoint(f, 0, 0);
+Debug.clearBreakPoint(bp);
+%OptimizeFunctionOnNextCall(Debug.setBreakPoint);
+bp = Debug.setBreakPoint(f, 0, 0);
+Debug.clearBreakPoint(bp);
+
+Debug.setListener(null);
diff --git a/src/v8/test/debugger/debug/regress/regress-debug-context-load.js b/src/v8/test/debugger/debug/regress/regress-debug-context-load.js
new file mode 100644
index 0000000..d9fe074
--- /dev/null
+++ b/src/v8/test/debugger/debug/regress/regress-debug-context-load.js
@@ -0,0 +1,7 @@
+// 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;
+Debug.setListener(null);
diff --git a/src/v8/test/debugger/debug/regress/regress-debug-deopt-while-recompile.js b/src/v8/test/debugger/debug/regress/regress-debug-deopt-while-recompile.js
new file mode 100644
index 0000000..e8336a8
--- /dev/null
+++ b/src/v8/test/debugger/debug/regress/regress-debug-deopt-while-recompile.js
@@ -0,0 +1,83 @@
+// Copyright 2013 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.
+
+
+Debug = debug.Debug;
+
+function listener(event, exec_state, event_data, data) {
+  if (event != Debug.DebugEvent.Break) return;
+  try {
+    assertEquals("foo", exec_state.frame(0).evaluate("bar").value());
+  } catch (e) {
+    exception = e;
+  };
+  listened++;
+};
+
+var exception = null;
+var listened = 0;
+
+var f = function() {
+  var bar = "foo";
+  var baz = bar;  // Break point should be here.
+  return bar;
+}
+
+var g = function() {
+  var bar = "foo";
+  var baz = bar;  // Break point should be here.
+  return bar;
+}
+
+f();
+f();
+g();
+g();
+
+// Mark with builtin.
+%OptimizeFunctionOnNextCall(f);
+if (%IsConcurrentRecompilationSupported()) {
+  %OptimizeFunctionOnNextCall(g, "concurrent");
+}
+
+// Activate debugger.
+Debug.setListener(listener);
+
+ // Set break point.
+Debug.setBreakPoint(f, 2, 0);
+Debug.setBreakPoint(g, 2, 0);
+
+// Trigger break point.
+f();
+g();
+
+// Assert that break point is set at expected location.
+assertTrue(Debug.showBreakPoints(f).indexOf("var baz = [B0]bar;") > 0);
+assertTrue(Debug.showBreakPoints(g).indexOf("var baz = [B0]bar;") > 0);
+
+assertEquals(2, listened);
+assertNull(exception);
diff --git a/src/v8/test/debugger/debug/regress/regress-frame-details-null-receiver.js b/src/v8/test/debugger/debug/regress/regress-frame-details-null-receiver.js
new file mode 100644
index 0000000..2a6bbae
--- /dev/null
+++ b/src/v8/test/debugger/debug/regress/regress-frame-details-null-receiver.js
@@ -0,0 +1,50 @@
+// Copyright 2013 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.
+
+
+Debug = debug.Debug;
+var listened = false;
+
+function listener(event, exec_state, event_data, data) {
+  if (event == Debug.DebugEvent.Exception) {
+    for (var i = 0; i < exec_state.frameCount(); i++) {
+      print(exec_state.frame(i).receiver());
+      print(exec_state.frame(i).func().name());
+    }
+  }
+  listened = true;
+}
+
+Debug.setListener(listener);
+Debug.setBreakOnException();
+
+assertThrows(function() { delete null['foo']; });
+
+Debug.clearBreakOnException();
+Debug.setListener(null);
+
+assertTrue(listened);
diff --git a/src/v8/test/debugger/debug/regress/regress-opt-after-debug-deopt.js b/src/v8/test/debugger/debug/regress/regress-opt-after-debug-deopt.js
new file mode 100644
index 0000000..2b11357
--- /dev/null
+++ b/src/v8/test/debugger/debug/regress/regress-opt-after-debug-deopt.js
@@ -0,0 +1,76 @@
+// Copyright 2013 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: --concurrent-recompilation --block-concurrent-recompilation
+// Flags: --no-always-opt
+
+if (!%IsConcurrentRecompilationSupported()) {
+  print("Concurrent recompilation is disabled. Skipping this test.");
+  quit();
+}
+
+Debug = debug.Debug;
+
+function listener(event, exec_state, event_data, data) {
+  if (event != Debug.DebugEvent.Break) return;
+  try {
+    assertEquals("foo", exec_state.frame(0).evaluate("a").value());
+  } catch (e) {
+    exception = e;
+  };
+  listened++;
+};
+
+var exception = null;
+var listened = 0;
+
+var f = function() {
+  var a = "foo";
+  var b = a.substring("1");
+  [a, b].sort();
+  return a;
+}
+
+f();
+f();
+%OptimizeFunctionOnNextCall(f, "concurrent");  // Mark with builtin.
+f();                           // Kick off concurrent recompilation.
+
+// After compile graph has been created...
+Debug.setListener(listener);   // Activate debugger.
+Debug.setBreakPoint(f, 2, 0);  // Force deopt.
+
+// At this point, concurrent recompilation is still being blocked.
+assertUnoptimized(f, "no sync");
+// Let concurrent recompilation proceed.
+%UnblockConcurrentRecompilation();
+// Sync with optimization thread.  But no optimized code is installed.
+assertUnoptimized(f, "sync");
+
+f();                           // Trigger break point.
+assertEquals(1, listened);
+assertNull(exception);
diff --git a/src/v8/test/debugger/debug/regress/regress-prepare-break-while-recompile.js b/src/v8/test/debugger/debug/regress/regress-prepare-break-while-recompile.js
new file mode 100644
index 0000000..3b56254
--- /dev/null
+++ b/src/v8/test/debugger/debug/regress/regress-prepare-break-while-recompile.js
@@ -0,0 +1,70 @@
+// Copyright 2013 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: --concurrent-recompilation --block-concurrent-recompilation
+// Flags: --no-always-opt
+
+if (!%IsConcurrentRecompilationSupported()) {
+  print("Concurrent recompilation is disabled. Skipping this test.");
+  quit();
+}
+
+Debug = debug.Debug
+
+function foo() {
+  var x = 1;
+  return x;
+}
+
+function bar() {
+  var x = 2;
+  return x;
+}
+
+foo();
+foo();
+// Mark and kick off recompilation.
+%OptimizeFunctionOnNextCall(foo, "concurrent");
+foo();
+
+// Set break points on an unrelated function. This clears both optimized
+// and (shared) unoptimized code on foo, and sets both to lazy-compile builtin.
+// Clear the break point immediately after to deactivate the debugger.
+// Do all of this after compile graph has been created.
+Debug.setListener(function(){});
+Debug.setBreakPoint(bar, 0, 0);
+Debug.clearAllBreakPoints();
+Debug.setListener(null);
+
+// At this point, concurrent recompilation is still blocked.
+assertUnoptimized(foo, "no sync");
+// Let concurrent recompilation proceed.
+%UnblockConcurrentRecompilation();
+
+// Install optimized code when concurrent optimization finishes.
+// This needs to be able to deal with shared code being a builtin.
+assertUnoptimized(foo, "sync");
diff --git a/src/v8/test/debugger/debug/wasm/asm-debug.js b/src/v8/test/debugger/debug/wasm/asm-debug.js
new file mode 100644
index 0000000..47ed4f2
--- /dev/null
+++ b/src/v8/test/debugger/debug/wasm/asm-debug.js
@@ -0,0 +1,82 @@
+// Copyright 2016 the V8 project authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+// Flags: --expose-wasm --validate-asm
+
+Debug = debug.Debug
+
+// Initialized in setup().
+var exception;
+var break_count;
+var num_wasm_scripts;
+var module;
+
+var expected_stack_entries = [];
+
+function listener(event, exec_state, event_data, data) {
+  try {
+    if (event == Debug.DebugEvent.Break) {
+      ++break_count;
+      // Request frame details.
+      var num_frames = exec_state.frameCount();
+      assertEquals(
+          expected_stack_entries.length, num_frames, 'number of frames');
+      print('Stack Trace (length ' + num_frames + '):');
+      for (var i = 0; i < num_frames; ++i) {
+        var frame = exec_state.frame(i);
+        var line = frame.sourceLine();
+        var column = frame.sourceColumn() + 1;
+        var funcName = frame.func().name();
+        print(
+            '  [' + i + '] ' + funcName + ' (' + line + ':' + column + ')');
+        assertEquals(
+            expected_stack_entries[i][0], funcName, 'function name at ' + i);
+        assertEquals(expected_stack_entries[i][1], line, 'line at ' + i);
+        assertEquals(expected_stack_entries[i][2], column, 'column at ' + i);
+      }
+    }
+  } catch (e) {
+    print('exception: ' + e);
+    exception = e;
+  }
+};
+
+function generateWasmFromAsmJs(stdlib, foreign, heap) {
+  'use asm';
+  var debugger_fun = foreign.call_debugger;
+  function callDebugger() {
+    debugger_fun();
+  }
+  function redirectFun() {
+    callDebugger();
+  }
+  return redirectFun;
+}
+
+function call_debugger() {
+  debugger;
+}
+
+function setup() {
+  exception = null;
+  break_count = 0;
+}
+
+(function FrameInspection() {
+  setup();
+  var fun =
+      generateWasmFromAsmJs(this, {'call_debugger': call_debugger}, undefined);
+  expected_stack_entries = [
+    ['call_debugger', 58, 3],    // --
+    ['callDebugger', 49, 5],     // --
+    ['redirectFun', 52, 5],      // --
+    ['FrameInspection', 78, 3],  // --
+    ['', 82, 3]
+  ];
+  Debug.setListener(listener);
+  fun();
+  Debug.setListener(null);
+  assertEquals(1, break_count);
+  if (exception) throw exception;
+})();
diff --git a/src/v8/test/debugger/debug/wasm/frame-inspection.js b/src/v8/test/debugger/debug/wasm/frame-inspection.js
new file mode 100644
index 0000000..45fa8a9
--- /dev/null
+++ b/src/v8/test/debugger/debug/wasm/frame-inspection.js
@@ -0,0 +1,72 @@
+// Copyright 2016 the V8 project authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+// Flags: --expose-wasm
+
+load("test/mjsunit/wasm/wasm-constants.js");
+load("test/mjsunit/wasm/wasm-module-builder.js");
+
+Debug = debug.Debug
+
+var exception = null;
+var break_count = 0;
+
+const expected_frames = [
+  // func-name; wasm?; pos; line; col
+  ['call_debugger', false],        // --
+  ['wasm_2', true, 56, 2, 2],      // --
+  ['wasm_1', true, 52, 3, 2],      // --
+  ['testFrameInspection', false],  // --
+  ['', false]
+];
+
+function listener(event, exec_state, event_data, data) {
+  if (event != Debug.DebugEvent.Break) return;
+  ++break_count;
+  try {
+    var break_id = exec_state.break_id;
+    var frame_count = exec_state.frameCount();
+    assertEquals(expected_frames.length, frame_count, 'frame count');
+
+    for (var i = 0; i < frame_count; ++i) {
+      var frame = exec_state.frame(i);
+      assertEquals(expected_frames[i][0], frame.func().name(), 'name at ' + i);
+      if (expected_frames[i][1]) {  // wasm frame?
+        assertEquals(expected_frames[i][3], frame.sourceLine(), 'line at ' + i);
+        assertEquals(expected_frames[i][4], frame.sourceColumn(),
+            'column at ' + i);
+      }
+    }
+  } catch (e) {
+    exception = e;
+  }
+};
+
+var builder = new WasmModuleBuilder();
+
+// wasm_1 calls wasm_2 on offset 2.
+// wasm_2 calls call_debugger on offset 1.
+
+builder.addImport("mod", 'func', kSig_v_v);
+
+builder.addFunction('wasm_1', kSig_v_v)
+    .addBody([kExprNop, kExprCallFunction, 2])
+    .exportAs('main');
+
+builder.addFunction('wasm_2', kSig_v_v).addBody([kExprCallFunction, 0]);
+
+function call_debugger() {
+  debugger;
+}
+
+var module = builder.instantiate({mod: {func: call_debugger}});
+
+(function testFrameInspection() {
+  Debug.setListener(listener);
+  module.exports.main();
+  Debug.setListener(null);
+
+  assertEquals(1, break_count);
+  if (exception) throw exception;
+})();