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