Revision: 22913
Author: [email protected]
Date: Wed Aug 6 09:41:52 2014 UTC
Log: Trigger exception debug events on Promise reject.
[email protected], [email protected]
BUG=393913
LOG=Y
Review URL: https://codereview.chromium.org/440773004
http://code.google.com/p/v8/source/detail?r=22913
Added:
/branches/bleeding_edge/test/mjsunit/es6/debug-promises
/branches/bleeding_edge/test/mjsunit/es6/debug-promises/async-task-event.js
/branches/bleeding_edge/test/mjsunit/es6/debug-promises/events.js
/branches/bleeding_edge/test/mjsunit/es6/debug-promises/reentry.js
/branches/bleeding_edge/test/mjsunit/es6/debug-promises/reject-after-resolve.js
/branches/bleeding_edge/test/mjsunit/es6/debug-promises/reject-caught-all.js
/branches/bleeding_edge/test/mjsunit/es6/debug-promises/reject-caught-late.js
/branches/bleeding_edge/test/mjsunit/es6/debug-promises/reject-caught-uncaught.js
/branches/bleeding_edge/test/mjsunit/es6/debug-promises/reject-in-constructor.js
/branches/bleeding_edge/test/mjsunit/es6/debug-promises/reject-uncaught-all.js
/branches/bleeding_edge/test/mjsunit/es6/debug-promises/reject-uncaught-late.js
/branches/bleeding_edge/test/mjsunit/es6/debug-promises/reject-uncaught-uncaught.js
/branches/bleeding_edge/test/mjsunit/es6/debug-promises/reject-with-invalid-reject.js
/branches/bleeding_edge/test/mjsunit/es6/debug-promises/reject-with-throw-in-reject.js
/branches/bleeding_edge/test/mjsunit/es6/debug-promises/reject-with-undefined-reject.js
/branches/bleeding_edge/test/mjsunit/es6/debug-promises/throw-caught-all.js
/branches/bleeding_edge/test/mjsunit/es6/debug-promises/throw-caught-late.js
/branches/bleeding_edge/test/mjsunit/es6/debug-promises/throw-caught-uncaught.js
/branches/bleeding_edge/test/mjsunit/es6/debug-promises/throw-in-constructor.js
/branches/bleeding_edge/test/mjsunit/es6/debug-promises/throw-uncaught-all.js
/branches/bleeding_edge/test/mjsunit/es6/debug-promises/throw-uncaught-uncaught.js
/branches/bleeding_edge/test/mjsunit/es6/debug-promises/throw-with-throw-in-reject.js
/branches/bleeding_edge/test/mjsunit/es6/debug-promises/throw-with-undefined-reject.js
/branches/bleeding_edge/test/mjsunit/es6/debug-promises/try-reject-in-constructor.js
/branches/bleeding_edge/test/mjsunit/es6/debug-promises/try-throw-reject-in-constructor.js
/branches/bleeding_edge/test/mjsunit/runtime-gen/debugpoppromise.js
/branches/bleeding_edge/test/mjsunit/runtime-gen/debugpromiserejectevent.js
/branches/bleeding_edge/test/mjsunit/runtime-gen/debugpushpromise.js
Deleted:
/branches/bleeding_edge/test/mjsunit/es6/debug-promise-events.js
/branches/bleeding_edge/test/mjsunit/es6/debug-promises-async-task-event.js
/branches/bleeding_edge/test/mjsunit/es6/debug-promises-caught-all.js
/branches/bleeding_edge/test/mjsunit/es6/debug-promises-caught-late.js
/branches/bleeding_edge/test/mjsunit/es6/debug-promises-caught-uncaught.js
/branches/bleeding_edge/test/mjsunit/es6/debug-promises-reentry.js
/branches/bleeding_edge/test/mjsunit/es6/debug-promises-throw-in-constructor.js
/branches/bleeding_edge/test/mjsunit/es6/debug-promises-throw-in-reject.js
/branches/bleeding_edge/test/mjsunit/es6/debug-promises-uncaught-all.js
/branches/bleeding_edge/test/mjsunit/es6/debug-promises-uncaught-uncaught.js
/branches/bleeding_edge/test/mjsunit/es6/debug-promises-undefined-reject.js
/branches/bleeding_edge/test/mjsunit/runtime-gen/debugpromisehandleepilogue.js
/branches/bleeding_edge/test/mjsunit/runtime-gen/debugpromisehandleprologue.js
Modified:
/branches/bleeding_edge/src/debug.cc
/branches/bleeding_edge/src/debug.h
/branches/bleeding_edge/src/isolate.cc
/branches/bleeding_edge/src/promise.js
/branches/bleeding_edge/src/runtime.cc
/branches/bleeding_edge/src/runtime.h
/branches/bleeding_edge/test/mjsunit/mjsunit.status
/branches/bleeding_edge/tools/generate-runtime-tests.py
=======================================
--- /dev/null
+++
/branches/bleeding_edge/test/mjsunit/es6/debug-promises/async-task-event.js
Wed Aug 6 09:41:52 2014 UTC
@@ -0,0 +1,61 @@
+// 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: --expose-debug-as debug
+
+Debug = debug.Debug;
+
+var base_id = -1;
+var exception = null;
+var expected = [
+ "enqueue #1",
+ "willHandle #1",
+ "then #1",
+ "enqueue #2",
+ "didHandle #1",
+ "willHandle #2",
+ "then #2",
+ "enqueue #3",
+ "didHandle #2",
+ "willHandle #3",
+ "didHandle #3"
+];
+
+function assertLog(msg) {
+ print(msg);
+ assertTrue(expected.length > 0);
+ assertEquals(expected.shift(), msg);
+ if (!expected.length) {
+ Debug.setListener(null);
+ }
+}
+
+function listener(event, exec_state, event_data, data) {
+ if (event != Debug.DebugEvent.AsyncTaskEvent) return;
+ try {
+ if (base_id < 0)
+ base_id = event_data.id();
+ var id = event_data.id() - base_id + 1;
+ assertEquals("Promise.resolve", event_data.name());
+ assertLog(event_data.type() + " #" + id);
+ } catch (e) {
+ print(e + e.stack)
+ exception = e;
+ }
+}
+
+Debug.setListener(listener);
+
+var resolver;
+var p = new Promise(function(resolve, reject) {
+ resolver = resolve;
+});
+p.then(function() {
+ assertLog("then #1");
+}).then(function() {
+ assertLog("then #2");
+});
+resolver();
+
+assertNull(exception);
=======================================
--- /dev/null
+++ /branches/bleeding_edge/test/mjsunit/es6/debug-promises/events.js Wed
Aug 6 09:41:52 2014 UTC
@@ -0,0 +1,124 @@
+// 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: --allow-natives-syntax --expose-debug-as debug
+
+Debug = debug.Debug;
+
+var eventsExpected = 16;
+var exception = null;
+var result = [];
+
+function updatePromise(promise, parentPromise, status, value) {
+ var i;
+ for (i = 0; i < result.length; ++i) {
+ if (result[i].promise === promise) {
+ result[i].parentPromise = parentPromise || result[i].parentPromise;
+ result[i].status = status || result[i].status;
+ result[i].value = value || result[i].value;
+ break;
+ }
+ }
+ assertTrue(i < result.length);
+}
+
+function listener(event, exec_state, event_data, data) {
+ if (event != Debug.DebugEvent.PromiseEvent) return;
+ try {
+ eventsExpected--;
+ assertTrue(event_data.promise().isPromise());
+ if (event_data.status() === 0) {
+ // New promise.
+ assertEquals("pending", event_data.promise().status());
+ result.push({ promise: event_data.promise().value(), status: 0 });
+ assertTrue(exec_state.frame(0).sourceLineText().indexOf("// event")
0);
+ } else if (event_data.status() !== undefined) {
+ // Resolve/reject promise.
+ updatePromise(event_data.promise().value(),
+ undefined,
+ event_data.status(),
+ event_data.value().value());
+ } else {
+ // Chain promises.
+ assertTrue(event_data.parentPromise().isPromise());
+ updatePromise(event_data.promise().value(),
+ event_data.parentPromise().value());
+ assertTrue(exec_state.frame(0).sourceLineText().indexOf("// event")
0);
+ }
+ } catch (e) {
+ print(e + e.stack)
+ exception = e;
+ }
+}
+
+Debug.setListener(listener);
+
+function resolver(resolve, reject) { resolve(); }
+
+var p1 = new Promise(resolver); // event
+var p2 = p1.then().then(); // event
+var p3 = new Promise(function(resolve, reject) { // event
+ reject("rejected");
+});
+var p4 = p3.then(); // event
+var p5 = p1.then(); // event
+
+function assertAsync(b, s) {
+ if (b) {
+ print(s, "succeeded");
+ } else {
+ %AbortJS(s + " FAILED!");
+ }
+}
+
+function testDone(iteration) {
+ function checkResult() {
+ if (eventsExpected === 0) {
+ assertAsync(result.length === 6, "result.length");
+
+ assertAsync(result[0].promise === p1, "result[0].promise");
+ assertAsync(result[0].parentPromise === undefined,
+ "result[0].parentPromise");
+ assertAsync(result[0].status === 1, "result[0].status");
+ assertAsync(result[0].value === undefined, "result[0].value");
+
+ assertAsync(result[1].parentPromise === p1,
+ "result[1].parentPromise");
+ assertAsync(result[1].status === 1, "result[1].status");
+
+ assertAsync(result[2].promise === p2, "result[2].promise");
+
+ assertAsync(result[3].promise === p3, "result[3].promise");
+ assertAsync(result[3].parentPromise === undefined,
+ "result[3].parentPromise");
+ assertAsync(result[3].status === -1, "result[3].status");
+ assertAsync(result[3].value === "rejected", "result[3].value");
+
+ assertAsync(result[4].promise === p4, "result[4].promise");
+ assertAsync(result[4].parentPromise === p3,
+ "result[4].parentPromise");
+ assertAsync(result[4].status === -1, "result[4].status");
+ assertAsync(result[4].value === "rejected", "result[4].value");
+
+ assertAsync(result[5].promise === p5, "result[5].promise");
+ assertAsync(result[5].parentPromise === p1,
+ "result[5].parentPromise");
+ assertAsync(result[5].status === 1, "result[5].status");
+
+ assertAsync(exception === null, "exception === null");
+ Debug.setListener(null);
+ } else if (iteration > 10) {
+ %AbortJS("Not all events were received!");
+ } else {
+ testDone(iteration + 1);
+ }
+ }
+
+ var iteration = iteration || 0;
+ var dummy = {};
+ Object.observe(dummy, checkResult);
+ dummy.dummy = dummy;
+}
+
+testDone();
=======================================
--- /dev/null
+++ /branches/bleeding_edge/test/mjsunit/es6/debug-promises/reentry.js Wed
Aug 6 09:41:52 2014 UTC
@@ -0,0 +1,17 @@
+// 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: --expose-debug-as debug
+
+// 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.chain(function() {
+ new Promise(function(resolve, reject) { resolve(); });
+});
=======================================
--- /dev/null
+++
/branches/bleeding_edge/test/mjsunit/es6/debug-promises/reject-after-resolve.js
Wed Aug 6 09:41:52 2014 UTC
@@ -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.
+
+// Flags: --expose-debug-as debug --allow-natives-syntax
+
+// 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.chain(
+ 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");
=======================================
--- /dev/null
+++
/branches/bleeding_edge/test/mjsunit/es6/debug-promises/reject-caught-all.js
Wed Aug 6 09:41:52 2014 UTC
@@ -0,0 +1,72 @@
+// 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: --expose-debug-as debug --allow-natives-syntax
+
+// 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.chain(
+ 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);
+ assertEquals(q, event_data.promise());
+ 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);
+ }
+ }
+
+ // Run testDone through the Object.observe processing loop.
+ var dummy = {};
+ Object.observe(dummy, checkResult);
+ dummy.dummy = dummy;
+}
+
+testDone(0);
=======================================
--- /dev/null
+++
/branches/bleeding_edge/test/mjsunit/es6/debug-promises/reject-caught-late.js
Wed Aug 6 09:41:52 2014 UTC
@@ -0,0 +1,34 @@
+// 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: --expose-debug-as debug --allow-natives-syntax
+
+// 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.chain(
+ 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);
=======================================
--- /dev/null
+++
/branches/bleeding_edge/test/mjsunit/es6/debug-promises/reject-caught-uncaught.js
Wed Aug 6 09:41:52 2014 UTC
@@ -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.
+
+// Flags: --expose-debug-as debug --allow-natives-syntax
+
+// 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.chain(
+ 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);
=======================================
--- /dev/null
+++
/branches/bleeding_edge/test/mjsunit/es6/debug-promises/reject-in-constructor.js
Wed Aug 6 09:41:52 2014 UTC
@@ -0,0 +1,39 @@
+// 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: --expose-debug-as debug
+
+// 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.promise() instanceof Promise);
+ 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);
=======================================
--- /dev/null
+++
/branches/bleeding_edge/test/mjsunit/es6/debug-promises/reject-uncaught-all.js
Wed Aug 6 09:41:52 2014 UTC
@@ -0,0 +1,69 @@
+// 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: --expose-debug-as debug --allow-natives-syntax
+
+// 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.chain(
+ 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.promise() instanceof Promise);
+ assertEquals(q, event_data.promise());
+ assertTrue(event_data.uncaught());
+ // All of the frames on the stack are from native Javascript.
+ assertEquals(0, exec_state.frameCount());
+ }
+ } 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);
+ }
+ }
+
+ // Run testDone through the Object.observe processing loop.
+ var dummy = {};
+ Object.observe(dummy, checkResult);
+ dummy.dummy = dummy;
+}
+
+testDone(0);
=======================================
--- /dev/null
+++
/branches/bleeding_edge/test/mjsunit/es6/debug-promises/reject-uncaught-late.js
Wed Aug 6 09:41:52 2014 UTC
@@ -0,0 +1,76 @@
+// 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: --expose-debug-as debug --allow-natives-syntax
+
+// 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.promise() instanceof Promise);
+ assertEquals(p, event_data.promise());
+ 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);
+ }
+ }
+
+ // Run testDone through the Object.observe processing loop.
+ var dummy = {};
+ Object.observe(dummy, checkResult);
+ dummy.dummy = dummy;
+}
+
+testDone(0);
=======================================
--- /dev/null
+++
/branches/bleeding_edge/test/mjsunit/es6/debug-promises/reject-uncaught-uncaught.js
Wed Aug 6 09:41:52 2014 UTC
@@ -0,0 +1,69 @@
+// 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: --expose-debug-as debug --allow-natives-syntax
+
+// 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.chain(
+ 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.promise() instanceof Promise);
+ assertEquals(q, event_data.promise());
+ assertTrue(event_data.uncaught());
+ // 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);
+
+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);
+ }
+ }
+
+ // Run testDone through the Object.observe processing loop.
+ var dummy = {};
+ Object.observe(dummy, checkResult);
+ dummy.dummy = dummy;
+}
+
+testDone(0);
=======================================
--- /dev/null
+++
/branches/bleeding_edge/test/mjsunit/es6/debug-promises/reject-with-invalid-reject.js
Wed Aug 6 09:41:52 2014 UTC
@@ -0,0 +1,78 @@
+// 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: --expose-debug-as debug --allow-natives-syntax
+
+// 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.chain(
+ 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());
+ assertEquals(q, event_data.promise());
+ }
+ } 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);
+ }
+ }
+
+ // Run testDone through the Object.observe processing loop.
+ var dummy = {};
+ Object.observe(dummy, checkResult);
+ dummy.dummy = dummy;
+}
+
+testDone(0);
+
+log.push("end main");
=======================================
--- /dev/null
+++
/branches/bleeding_edge/test/mjsunit/es6/debug-promises/reject-with-throw-in-reject.js
Wed Aug 6 09:41:52 2014 UTC
@@ -0,0 +1,87 @@
+// 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: --expose-debug-as debug --allow-natives-syntax
+
+// 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.chain(
+ 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);
+ }
+ }
+
+ // Run testDone through the Object.observe processing loop.
+ var dummy = {};
+ Object.observe(dummy, checkResult);
+ dummy.dummy = dummy;
+}
+
+testDone(0);
=======================================
--- /dev/null
+++
/branches/bleeding_edge/test/mjsunit/es6/debug-promises/reject-with-undefined-reject.js
Wed Aug 6 09:41:52 2014 UTC
@@ -0,0 +1,78 @@
+// 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: --expose-debug-as debug --allow-natives-syntax
+
+// 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.chain(
+ 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());
+ assertEquals(q, event_data.promise());
+ }
+ } 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);
+ }
+ }
+
+ // Run testDone through the Object.observe processing loop.
+ var dummy = {};
+ Object.observe(dummy, checkResult);
+ dummy.dummy = dummy;
+}
+
+testDone(0);
+
+log.push("end main");
=======================================
--- /dev/null
+++
/branches/bleeding_edge/test/mjsunit/es6/debug-promises/throw-caught-all.js
Wed Aug 6 09:41:52 2014 UTC
@@ -0,0 +1,71 @@
+// 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: --expose-debug-as debug --allow-natives-syntax
+
+// 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.chain(
+ 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);
+ assertEquals(q, event_data.promise());
+ 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);
+ }
+ }
+
+ // Run testDone through the Object.observe processing loop.
+ var dummy = {};
+ Object.observe(dummy, checkResult);
+ dummy.dummy = dummy;
+}
+
+testDone(0);
=======================================
--- /dev/null
+++
/branches/bleeding_edge/test/mjsunit/es6/debug-promises/throw-caught-late.js
Wed Aug 6 09:41:52 2014 UTC
@@ -0,0 +1,34 @@
+// 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: --expose-debug-as debug --allow-natives-syntax
+
+// 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.chain(
+ 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);
=======================================
--- /dev/null
+++
/branches/bleeding_edge/test/mjsunit/es6/debug-promises/throw-caught-uncaught.js
Wed Aug 6 09:41:52 2014 UTC
@@ -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.
+
+// Flags: --expose-debug-as debug --allow-natives-syntax
+
+// 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.chain(
+ 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);
=======================================
--- /dev/null
+++
/branches/bleeding_edge/test/mjsunit/es6/debug-promises/throw-in-constructor.js
Wed Aug 6 09:41:52 2014 UTC
@@ -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.
+
+// Flags: --expose-debug-as debug
+
+// 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.promise() instanceof Promise);
+ 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);
=======================================
--- /dev/null
+++
/branches/bleeding_edge/test/mjsunit/es6/debug-promises/throw-uncaught-all.js
Wed Aug 6 09:41:52 2014 UTC
@@ -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.
+
+// Flags: --expose-debug-as debug --allow-natives-syntax
+
+// 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.chain(
+ 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.promise() instanceof Promise);
+ assertEquals(q, event_data.promise());
+ 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);
+ }
+ }
+
+ // Rerun testDone through the Object.observe processing loop.
+ var dummy = {};
+ Object.observe(dummy, checkResult);
+ dummy.dummy = dummy;
+}
+
+testDone(0);
=======================================
--- /dev/null
+++
/branches/bleeding_edge/test/mjsunit/es6/debug-promises/throw-uncaught-uncaught.js
Wed Aug 6 09:41:52 2014 UTC
@@ -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.
+
+// Flags: --expose-debug-as debug --allow-natives-syntax
+
+// 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.chain(
+ function() {
+ log.push("throw");
+ throw new Error("uncaught"); // event
+ });
+
+function listener(event, exec_state, event_data, data) {
+ if (event == Debug.DebugEvent.AsyncTaskEvent) return;
+ try {
+ if (event == Debug.DebugEvent.Exception) {
+ expected_events--;
+ assertTrue(expected_events >= 0);
+ assertEquals("uncaught", event_data.exception().message);
+ assertTrue(event_data.promise() instanceof Promise);
+ assertEquals(q, event_data.promise());
+ 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);
+ }
+ }
+
+ // Run testDone through the Object.observe processing loop.
+ var dummy = {};
+ Object.observe(dummy, checkResult);
+ dummy.dummy = dummy;
+}
+
+testDone(0);
=======================================
--- /dev/null
+++
/branches/bleeding_edge/test/mjsunit/es6/debug-promises/throw-with-throw-in-reject.js
Wed Aug 6 09:41:52 2014 UTC
@@ -0,0 +1,90 @@
+// 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: --expose-debug-as debug --allow-natives-syntax
+
+// 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 = 2;
+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.chain(
+ 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 == 1) {
+ assertEquals(["resolve", "construct", "end main",
+ "throw caught"], log);
+ assertEquals("caught", event_data.exception().message);
+ } else if (expected_events == 0) {
+ assertEquals("reject", event_data.exception().message);
+ } else {
+ assertUnreachable();
+ }
+ assertEquals(q, event_data.promise());
+ 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);
+ }
+ }
+
+ // Run testDone through the Object.observe processing loop.
+ var dummy = {};
+ Object.observe(dummy, checkResult);
+ dummy.dummy = dummy;
+}
+
+testDone(0);
=======================================
--- /dev/null
+++
/branches/bleeding_edge/test/mjsunit/es6/debug-promises/throw-with-undefined-reject.js
Wed Aug 6 09:41:52 2014 UTC
@@ -0,0 +1,88 @@
+// 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: --expose-debug-as debug --allow-natives-syntax
+
+// Test debug events when an exception is thrown inside a Promise, which is
+// caught by a custom promise, which has no reject handler.
+// We expect two Exception debug events:
+// 1) when the exception is thrown in the promise q.
+// 2) when calling the undefined custom reject closure in MyPromise
throws.
+
+Debug = debug.Debug;
+
+var expected_events = 2;
+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.chain(
+ 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 == 1) {
+ assertTrue(
+ exec_state.frame(0).sourceLineText().indexOf('// event') > 0);
+ assertEquals("caught", event_data.exception().message);
+ } else if (expected_events == 0) {
+ // All of the frames on the stack are from native Javascript.
+ assertEquals(0, exec_state.frameCount());
+ assertEquals("undefined is not a function",
+ event_data.exception().message);
+ } else {
+ assertUnreachable();
+ }
+ assertEquals(q, event_data.promise());
+ }
+ } 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"],
log);
+ } else {
+ testDone(iteration + 1);
+ }
+ } catch (e) {
+ %AbortJS(e + "\n" + e.stack);
+ }
+ }
+
+ // Run testDone through the Object.observe processing loop.
+ var dummy = {};
+ Object.observe(dummy, checkResult);
+ dummy.dummy = dummy;
+}
+
+testDone(0);
=======================================
--- /dev/null
+++
/branches/bleeding_edge/test/mjsunit/es6/debug-promises/try-reject-in-constructor.js
Wed Aug 6 09:41:52 2014 UTC
@@ -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.
+
+// Flags: --expose-debug-as debug
+
+// 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.promise() instanceof Promise);
+ 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);
=======================================
--- /dev/null
+++
/branches/bleeding_edge/test/mjsunit/es6/debug-promises/try-throw-reject-in-constructor.js
Wed Aug 6 09:41:52 2014 UTC
@@ -0,0 +1,44 @@
+// 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: --expose-debug-as debug
+
+// 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.promise() instanceof Promise);
+ 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);
=======================================
--- /dev/null
+++ /branches/bleeding_edge/test/mjsunit/runtime-gen/debugpoppromise.js Wed
Aug 6 09:41:52 2014 UTC
@@ -0,0 +1,4 @@
+// Copyright 2014 the V8 project authors. All rights reserved.
+// AUTO-GENERATED BY tools/generate-runtime-tests.py, DO NOT MODIFY
+// Flags: --allow-natives-syntax --harmony
+%DebugPopPromise();
=======================================
--- /dev/null
+++
/branches/bleeding_edge/test/mjsunit/runtime-gen/debugpromiserejectevent.js
Wed Aug 6 09:41:52 2014 UTC
@@ -0,0 +1,6 @@
+// Copyright 2014 the V8 project authors. All rights reserved.
+// AUTO-GENERATED BY tools/generate-runtime-tests.py, DO NOT MODIFY
+// Flags: --allow-natives-syntax --harmony
+var _promise = new Object();
+var _value = new Object();
+%DebugPromiseRejectEvent(_promise, _value);
=======================================
--- /dev/null
+++ /branches/bleeding_edge/test/mjsunit/runtime-gen/debugpushpromise.js
Wed Aug 6 09:41:52 2014 UTC
@@ -0,0 +1,5 @@
+// Copyright 2014 the V8 project authors. All rights reserved.
+// AUTO-GENERATED BY tools/generate-runtime-tests.py, DO NOT MODIFY
+// Flags: --allow-natives-syntax --harmony
+var _promise = new Object();
+%DebugPushPromise(_promise);
=======================================
--- /branches/bleeding_edge/test/mjsunit/es6/debug-promise-events.js Tue
Aug 5 08:16:02 2014 UTC
+++ /dev/null
@@ -1,124 +0,0 @@
-// Copyright 2014 the V8 project authors. All rights reserved.
-// Use of this source code is governed by a BSD-style license that can be
-// found in the LICENSE file.
-
-// Flags: --allow-natives-syntax --expose-debug-as debug
-
-Debug = debug.Debug;
-
-var eventsExpected = 16;
-var exception = null;
-var result = [];
-
-function updatePromise(promise, parentPromise, status, value) {
- var i;
- for (i = 0; i < result.length; ++i) {
- if (result[i].promise === promise) {
- result[i].parentPromise = parentPromise || result[i].parentPromise;
- result[i].status = status || result[i].status;
- result[i].value = value || result[i].value;
- break;
- }
- }
- assertTrue(i < result.length);
-}
-
-function listener(event, exec_state, event_data, data) {
- if (event != Debug.DebugEvent.PromiseEvent) return;
- try {
- eventsExpected--;
- assertTrue(event_data.promise().isPromise());
- if (event_data.status() === 0) {
- // New promise.
- assertEquals("pending", event_data.promise().status());
- result.push({ promise: event_data.promise().value(), status: 0 });
- assertTrue(exec_state.frame(0).sourceLineText().indexOf("// event")
0);
- } else if (event_data.status() !== undefined) {
- // Resolve/reject promise.
- updatePromise(event_data.promise().value(),
- undefined,
- event_data.status(),
- event_data.value().value());
- } else {
- // Chain promises.
- assertTrue(event_data.parentPromise().isPromise());
- updatePromise(event_data.promise().value(),
- event_data.parentPromise().value());
- assertTrue(exec_state.frame(0).sourceLineText().indexOf("// event")
0);
- }
- } catch (e) {
- print(e + e.stack)
- exception = e;
- }
-}
-
-Debug.setListener(listener);
-
-function resolver(resolve, reject) { resolve(); }
-
-var p1 = new Promise(resolver); // event
-var p2 = p1.then().then(); // event
-var p3 = new Promise(function(resolve, reject) { // event
- reject("rejected");
-});
-var p4 = p3.then(); // event
-var p5 = p1.then(); // event
-
-function assertAsync(b, s) {
- if (b) {
- print(s, "succeeded");
- } else {
- %AbortJS(s + " FAILED!");
- }
-}
-
-function testDone(iteration) {
- function checkResult() {
- if (eventsExpected === 0) {
- assertAsync(result.length === 6, "result.length");
-
- assertAsync(result[0].promise === p1, "result[0].promise");
- assertAsync(result[0].parentPromise === undefined,
- "result[0].parentPromise");
- assertAsync(result[0].status === 1, "result[0].status");
- assertAsync(result[0].value === undefined, "result[0].value");
-
- assertAsync(result[1].parentPromise === p1,
- "result[1].parentPromise");
- assertAsync(result[1].status === 1, "result[1].status");
-
- assertAsync(result[2].promise === p2, "result[2].promise");
-
- assertAsync(result[3].promise === p3, "result[3].promise");
- assertAsync(result[3].parentPromise === undefined,
- "result[3].parentPromise");
- assertAsync(result[3].status === -1, "result[3].status");
- assertAsync(result[3].value === "rejected", "result[3].value");
-
- assertAsync(result[4].promise === p4, "result[4].promise");
- assertAsync(result[4].parentPromise === p3,
- "result[4].parentPromise");
- assertAsync(result[4].status === -1, "result[4].status");
- assertAsync(result[4].value === "rejected", "result[4].value");
-
- assertAsync(result[5].promise === p5, "result[5].promise");
- assertAsync(result[5].parentPromise === p1,
- "result[5].parentPromise");
- assertAsync(result[5].status === 1, "result[5].status");
-
- assertAsync(exception === null, "exception === null");
- Debug.setListener(null);
- } else if (iteration > 10) {
- %AbortJS("Not all events were received!");
- } else {
- testDone(iteration + 1);
- }
- }
-
- var iteration = iteration || 0;
- var dummy = {};
- Object.observe(dummy, checkResult);
- dummy.dummy = dummy;
-}
-
-testDone();
=======================================
---
/branches/bleeding_edge/test/mjsunit/es6/debug-promises-async-task-event.js
Tue Jul 8 14:45:57 2014 UTC
+++ /dev/null
@@ -1,61 +0,0 @@
-// Copyright 2014 the V8 project authors. All rights reserved.
-// Use of this source code is governed by a BSD-style license that can be
-// found in the LICENSE file.
-
-// Flags: --expose-debug-as debug
-
-Debug = debug.Debug;
-
-var base_id = -1;
-var exception = null;
-var expected = [
- "enqueue #1",
- "willHandle #1",
- "then #1",
- "enqueue #2",
- "didHandle #1",
- "willHandle #2",
- "then #2",
- "enqueue #3",
- "didHandle #2",
- "willHandle #3",
- "didHandle #3"
-];
-
-function assertLog(msg) {
- print(msg);
- assertTrue(expected.length > 0);
- assertEquals(expected.shift(), msg);
- if (!expected.length) {
- Debug.setListener(null);
- }
-}
-
-function listener(event, exec_state, event_data, data) {
- if (event != Debug.DebugEvent.AsyncTaskEvent) return;
- try {
- if (base_id < 0)
- base_id = event_data.id();
- var id = event_data.id() - base_id + 1;
- assertEquals("Promise.resolve", event_data.name());
- assertLog(event_data.type() + " #" + id);
- } catch (e) {
- print(e + e.stack)
- exception = e;
- }
-}
-
-Debug.setListener(listener);
-
-var resolver;
-var p = new Promise(function(resolve, reject) {
- resolver = resolve;
-});
-p.then(function() {
- assertLog("then #1");
-}).then(function() {
- assertLog("then #2");
-});
-resolver();
-
-assertNull(exception);
=======================================
--- /branches/bleeding_edge/test/mjsunit/es6/debug-promises-caught-all.js
Thu Jul 3 15:56:01 2014 UTC
+++ /dev/null
@@ -1,56 +0,0 @@
-// Copyright 2014 the V8 project authors. All rights reserved.
-// Use of this source code is governed by a BSD-style license that can be
-// found in the LICENSE file.
-
-// Flags: --expose-debug-as debug
-
-// 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 log = [];
-var step = 0;
-
-var p = new Promise(function(resolve, reject) {
- log.push("resolve");
- resolve();
-});
-
-var q = p.chain(
- function() {
- log.push("throw");
- throw new Error("caught");
- });
-
-q.catch(
- function(e) {
- assertEquals("caught", e.message);
- });
-
-function listener(event, exec_state, event_data, data) {
- if (event == Debug.DebugEvent.AsyncTaskEvent) return;
- try {
- // Ignore exceptions during startup in stress runs.
- if (step >= 1) return;
- assertEquals(["resolve", "end main", "throw"], log);
- if (event == Debug.DebugEvent.Exception) {
- assertEquals("caught", event_data.exception().message);
- assertEquals(undefined, event_data.promise());
- assertFalse(event_data.uncaught());
- step++;
- }
- } 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.setBreakOnException();
-Debug.setListener(listener);
-
-log.push("end main");
=======================================
--- /branches/bleeding_edge/test/mjsunit/es6/debug-promises-caught-late.js
Fri Jun 20 10:47:50 2014 UTC
+++ /dev/null
@@ -1,38 +0,0 @@
-// Copyright 2014 the V8 project authors. All rights reserved.
-// Use of this source code is governed by a BSD-style license that can be
-// found in the LICENSE file.
-
-// Flags: --expose-debug-as debug
-
-// 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.chain(
- 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) {
- // 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);
=======================================
---
/branches/bleeding_edge/test/mjsunit/es6/debug-promises-caught-uncaught.js
Fri Jun 20 10:47:50 2014 UTC
+++ /dev/null
@@ -1,40 +0,0 @@
-// Copyright 2014 the V8 project authors. All rights reserved.
-// Use of this source code is governed by a BSD-style license that can be
-// found in the LICENSE file.
-
-// Flags: --expose-debug-as debug
-
-// 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.chain(
- function() {
- throw new Error("caught");
- });
-
-q.catch(
- function(e) {
- assertEquals("caught", e.message);
- });
-
-function listener(event, exec_state, event_data, data) {
- try {
- assertTrue(event != Debug.DebugEvent.Exception);
- } 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);
=======================================
--- /branches/bleeding_edge/test/mjsunit/es6/debug-promises-reentry.js Fri
Jun 20 10:47:50 2014 UTC
+++ /dev/null
@@ -1,17 +0,0 @@
-// Copyright 2014 the V8 project authors. All rights reserved.
-// Use of this source code is governed by a BSD-style license that can be
-// found in the LICENSE file.
-
-// Flags: --expose-debug-as debug
-
-// 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.chain(function() {
- new Promise(function(resolve, reject) { resolve(); });
-});
=======================================
---
/branches/bleeding_edge/test/mjsunit/es6/debug-promises-throw-in-constructor.js
Fri Jun 20 10:47:50 2014 UTC
+++ /dev/null
@@ -1,46 +0,0 @@
-// Copyright 2014 the V8 project authors. All rights reserved.
-// Use of this source code is governed by a BSD-style license that can be
-// found in the LICENSE file.
-
-// Flags: --expose-debug-as debug
-
-// Test debug events when we only listen to uncaught exceptions and
-// an exception is thrown in the 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 {
- // Ignore exceptions during startup in stress runs.
- if (step >= 1) return;
- if (event == Debug.DebugEvent.Exception) {
- assertEquals(0, step);
- assertEquals("uncaught", event_data.exception().message);
- assertTrue(event_data.promise() instanceof Promise);
- 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) {
- // 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);
- exception = e;
- }
-}
-
-Debug.setBreakOnUncaughtException();
-Debug.setListener(listener);
-
-var p = new Promise(function(resolve, reject) {
- throw new Error("uncaught"); // event
-});
-
-assertEquals(1, step);
-assertNull(exception);
=======================================
---
/branches/bleeding_edge/test/mjsunit/es6/debug-promises-throw-in-reject.js
Fri Jun 20 10:47:50 2014 UTC
+++ /dev/null
@@ -1,61 +0,0 @@
-// Copyright 2014 the V8 project authors. All rights reserved.
-// Use of this source code is governed by a BSD-style license that can be
-// found in the LICENSE file.
-
-// Flags: --expose-debug-as debug
-
-// 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 an Exception debug event with a promise to be
triggered.
-
-Debug = debug.Debug;
-
-var log = [];
-var step = 0;
-
-var p = new Promise(function(resolve, reject) {
- log.push("resolve");
- resolve();
-});
-
-function MyPromise(resolver) {
- var reject = function() {
- log.push("throw reject");
- throw new Error("reject"); // event
- };
- var resolve = function() { };
- log.push("construct");
- resolver(resolve, reject);
-};
-
-MyPromise.prototype = p;
-p.constructor = MyPromise;
-
-var q = p.chain(
- function() {
- log.push("throw caught");
- throw new Error("caught");
- });
-
-function listener(event, exec_state, event_data, data) {
- try {
- if (event == Debug.DebugEvent.Exception) {
- assertEquals(["resolve", "construct", "end main",
- "throw caught", "throw reject"], log);
- assertEquals("reject", event_data.exception().message);
- assertEquals(q, event_data.promise());
- 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");
=======================================
--- /branches/bleeding_edge/test/mjsunit/es6/debug-promises-uncaught-all.js
Thu Jul 3 15:56:01 2014 UTC
+++ /dev/null
@@ -1,56 +0,0 @@
-// Copyright 2014 the V8 project authors. All rights reserved.
-// Use of this source code is governed by a BSD-style license that can be
-// found in the LICENSE file.
-
-// Flags: --expose-debug-as debug
-
-// Test debug events when we listen to all 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 log = [];
-var step = 0;
-var exception = undefined;
-
-var p = new Promise(function(resolve, reject) {
- log.push("resolve");
- resolve();
-});
-
-var q = p.chain(
- function() {
- log.push("throw");
- throw new Error("uncaught"); // event
- });
-
-function listener(event, exec_state, event_data, data) {
- if (event == Debug.DebugEvent.AsyncTaskEvent) return;
- try {
- // Ignore exceptions during startup in stress runs.
- if (step >= 1) return;
- assertEquals(["resolve", "end main", "throw"], log);
- if (event == Debug.DebugEvent.Exception) {
- assertEquals(0, step);
- assertEquals("uncaught", event_data.exception().message);
- assertTrue(event_data.promise() instanceof Promise);
- assertEquals(q, event_data.promise());
- 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) {
- // 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.setBreakOnException();
-Debug.setListener(listener);
-
-log.push("end main");
=======================================
---
/branches/bleeding_edge/test/mjsunit/es6/debug-promises-uncaught-uncaught.js
Thu Jul 3 15:56:01 2014 UTC
+++ /dev/null
@@ -1,55 +0,0 @@
-// Copyright 2014 the V8 project authors. All rights reserved.
-// Use of this source code is governed by a BSD-style license that can be
-// found in the LICENSE file.
-
-// Flags: --expose-debug-as debug
-
-// 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 log = [];
-var step = 0;
-
-var p = new Promise(function(resolve, reject) {
- log.push("resolve");
- resolve();
-});
-
-var q = p.chain(
- function() {
- log.push("throw");
- throw new Error("uncaught"); // event
- });
-
-function listener(event, exec_state, event_data, data) {
- if (event == Debug.DebugEvent.AsyncTaskEvent) return;
- try {
- // Ignore exceptions during startup in stress runs.
- if (step >= 1) return;
- assertEquals(["resolve", "end main", "throw"], log);
- if (event == Debug.DebugEvent.Exception) {
- assertEquals(0, step);
- assertEquals("uncaught", event_data.exception().message);
- assertTrue(event_data.promise() instanceof Promise);
- assertEquals(q, event_data.promise());
- 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) {
- // 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");
=======================================
---
/branches/bleeding_edge/test/mjsunit/es6/debug-promises-undefined-reject.js
Fri Jun 20 10:47:50 2014 UTC
+++ /dev/null
@@ -1,57 +0,0 @@
-// Copyright 2014 the V8 project authors. All rights reserved.
-// Use of this source code is governed by a BSD-style license that can be
-// found in the LICENSE file.
-
-// Flags: --expose-debug-as debug
-
-// Test debug events when an exception is thrown inside a Promise, which is
-// caught by a custom promise, which has no reject handler.
-// We expect an Exception event with a promise to be triggered.
-
-Debug = debug.Debug;
-
-var log = [];
-var step = 0;
-
-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 = p;
-p.constructor = MyPromise;
-
-var q = p.chain(
- function() {
- log.push("throw caught");
- throw new Error("caught"); // event
- });
-
-function listener(event, exec_state, event_data, data) {
- try {
- if (event == Debug.DebugEvent.Exception) {
- assertEquals(["resolve", "construct", "end main", "throw caught"],
log);
- assertEquals("undefined is not a function",
- event_data.exception().message);
- assertEquals(q, event_data.promise());
- }
- } 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");
=======================================
---
/branches/bleeding_edge/test/mjsunit/runtime-gen/debugpromisehandleepilogue.js
Thu May 8 13:11:59 2014 UTC
+++ /dev/null
@@ -1,4 +0,0 @@
-// Copyright 2014 the V8 project authors. All rights reserved.
-// AUTO-GENERATED BY tools/generate-runtime-tests.py, DO NOT MODIFY
-// Flags: --allow-natives-syntax --harmony
-%DebugPromiseHandleEpilogue();
=======================================
---
/branches/bleeding_edge/test/mjsunit/runtime-gen/debugpromisehandleprologue.js
Thu May 8 13:11:59 2014 UTC
+++ /dev/null
@@ -1,5 +0,0 @@
-// Copyright 2014 the V8 project authors. All rights reserved.
-// AUTO-GENERATED BY tools/generate-runtime-tests.py, DO NOT MODIFY
-// Flags: --allow-natives-syntax --harmony
-var _promise_getter = function() {};
-%DebugPromiseHandlePrologue(_promise_getter);
=======================================
--- /branches/bleeding_edge/src/debug.cc Mon Aug 4 11:34:54 2014 UTC
+++ /branches/bleeding_edge/src/debug.cc Wed Aug 6 09:41:52 2014 UTC
@@ -855,8 +855,8 @@
ClearAllBreakPoints();
ClearStepping();
- // Match unmatched PromiseHandlePrologue calls.
- while (thread_local_.promise_on_stack_) PromiseHandleEpilogue();
+ // Match unmatched PopPromise calls.
+ while (thread_local_.promise_on_stack_) PopPromise();
// Return debugger is not loaded.
if (!is_loaded()) return;
@@ -1272,30 +1272,29 @@
}
-PromiseOnStack::PromiseOnStack(Isolate* isolate,
- PromiseOnStack* prev,
- Handle<JSFunction> getter)
+PromiseOnStack::PromiseOnStack(Isolate* isolate, PromiseOnStack* prev,
+ Handle<JSObject> promise)
: isolate_(isolate), prev_(prev) {
handler_ = StackHandler::FromAddress(
Isolate::handler(isolate->thread_local_top()));
- getter_ = Handle<JSFunction>::cast(
- isolate->global_handles()->Create(*getter));
+ promise_ =
+ Handle<JSObject>::cast(isolate->global_handles()->Create(*promise));
}
PromiseOnStack::~PromiseOnStack() {
-
isolate_->global_handles()->Destroy(Handle<Object>::cast(getter_).location());
+ isolate_->global_handles()->Destroy(
+ Handle<Object>::cast(promise_).location());
}
-void Debug::PromiseHandlePrologue(Handle<JSFunction> promise_getter) {
+void Debug::PushPromise(Handle<JSObject> promise) {
PromiseOnStack* prev = thread_local_.promise_on_stack_;
- thread_local_.promise_on_stack_ =
- new PromiseOnStack(isolate_, prev, promise_getter);
+ thread_local_.promise_on_stack_ = new PromiseOnStack(isolate_, prev,
promise);
}
-void Debug::PromiseHandleEpilogue() {
+void Debug::PopPromise() {
if (thread_local_.promise_on_stack_ == NULL) return;
PromiseOnStack* prev = thread_local_.promise_on_stack_->prev();
delete thread_local_.promise_on_stack_;
@@ -1303,33 +1302,38 @@
}
-Handle<Object> Debug::GetPromiseForUncaughtException() {
+Handle<Object> Debug::GetPromiseOnStackOnThrow() {
Handle<Object> undefined = isolate_->factory()->undefined_value();
if (thread_local_.promise_on_stack_ == NULL) return undefined;
- Handle<JSFunction> promise_getter =
thread_local_.promise_on_stack_->getter();
- StackHandler* promise_catch = thread_local_.promise_on_stack_->handler();
+ StackHandler* promise_try = thread_local_.promise_on_stack_->handler();
// Find the top-most try-catch handler.
StackHandler* handler = StackHandler::FromAddress(
Isolate::handler(isolate_->thread_local_top()));
- while (handler != NULL && !handler->is_catch()) {
+ do {
+ if (handler == promise_try) {
+ // Mark the pushed try-catch handler to prevent a later duplicate
event
+ // triggered with the following reject.
+ return thread_local_.promise_on_stack_->promise();
+ }
handler = handler->next();
- }
-#ifdef DEBUG
- // Make sure that our promise catch handler is in the list of handlers,
- // even if it's not the top-most try-catch handler.
- StackHandler* temp = handler;
- while (temp != promise_catch && !temp->is_catch()) {
- temp = temp->next();
- CHECK(temp != NULL);
- }
-#endif // DEBUG
-
- if (handler == promise_catch) {
- return Execution::Call(
- isolate_, promise_getter, undefined, 0, NULL).ToHandleChecked();
- }
+ // There must be a try-catch handler if a promise is on stack.
+ DCHECK_NE(NULL, handler);
+ // Throwing inside a Promise can be intercepted by an inner try-catch,
so
+ // we stop at the first try-catch handler.
+ } while (!handler->is_catch());
return undefined;
}
+
+
+bool Debug::PromiseHasRejectHandler(Handle<JSObject> promise) {
+ Handle<JSFunction> fun = Handle<JSFunction>::cast(
+ JSObject::GetDataProperty(isolate_->js_builtins_object(),
+
isolate_->factory()->NewStringFromStaticAscii(
+ "PromiseHasRejectHandler")));
+ Handle<Object> result =
+ Execution::Call(isolate_, fun, promise, 0, NULL).ToHandleChecked();
+ return result->IsTrue();
+}
void Debug::PrepareStep(StepAction step_action,
@@ -2562,13 +2566,25 @@
}
-void Debug::OnException(Handle<Object> exception, bool uncaught) {
+void Debug::OnThrow(Handle<Object> exception, bool uncaught) {
if (in_debug_scope() || ignore_events()) return;
+ HandleScope scope(isolate_);
+ OnException(exception, uncaught, GetPromiseOnStackOnThrow());
+}
+
+void Debug::OnPromiseReject(Handle<JSObject> promise, Handle<Object>
value) {
+ if (in_debug_scope() || ignore_events()) return;
HandleScope scope(isolate_);
- Handle<Object> promise = GetPromiseForUncaughtException();
- uncaught |= !promise->IsUndefined();
+ OnException(value, false, promise);
+}
+
+void Debug::OnException(Handle<Object> exception, bool uncaught,
+ Handle<Object> promise) {
+ if (promise->IsJSObject()) {
+ uncaught |= !PromiseHasRejectHandler(Handle<JSObject>::cast(promise));
+ }
// Bail out if exception breaks are not active
if (uncaught) {
// Uncaught exceptions are reported by either flags.
=======================================
--- /branches/bleeding_edge/src/debug.h Mon Aug 4 11:34:54 2014 UTC
+++ /branches/bleeding_edge/src/debug.h Wed Aug 6 09:41:52 2014 UTC
@@ -335,17 +335,16 @@
class PromiseOnStack {
public:
- PromiseOnStack(Isolate* isolate,
- PromiseOnStack* prev,
- Handle<JSFunction> getter);
+ PromiseOnStack(Isolate* isolate, PromiseOnStack* prev,
+ Handle<JSObject> getter);
~PromiseOnStack();
StackHandler* handler() { return handler_; }
- Handle<JSFunction> getter() { return getter_; }
+ Handle<JSObject> promise() { return promise_; }
PromiseOnStack* prev() { return prev_; }
private:
Isolate* isolate_;
StackHandler* handler_;
- Handle<JSFunction> getter_;
+ Handle<JSObject> promise_;
PromiseOnStack* prev_;
};
@@ -361,7 +360,9 @@
public:
// Debug event triggers.
void OnDebugBreak(Handle<Object> break_points_hit, bool auto_continue);
- void OnException(Handle<Object> exception, bool uncaught);
+
+ void OnThrow(Handle<Object> exception, bool uncaught);
+ void OnPromiseReject(Handle<JSObject> promise, Handle<Object> value);
void OnCompileError(Handle<Script> script);
void OnBeforeCompile(Handle<Script> script);
void OnAfterCompile(Handle<Script> script);
@@ -452,8 +453,9 @@
bool IsBreakAtReturn(JavaScriptFrame* frame);
// Promise handling.
- void PromiseHandlePrologue(Handle<JSFunction> promise_getter);
- void PromiseHandleEpilogue();
+ // Push and pop a promise and the current try-catch handler.
+ void PushPromise(Handle<JSObject> promise);
+ void PopPromise();
// Support for LiveEdit
void FramesHaveBeenDropped(StackFrame::Id new_break_frame_id,
@@ -522,6 +524,9 @@
// Check whether there are commands in the command queue.
inline bool has_commands() const { return !command_queue_.IsEmpty(); }
inline bool ignore_events() const { return is_suppressed_ |
| !is_active_; }
+
+ void OnException(Handle<Object> exception, bool uncaught,
+ Handle<Object> promise);
// Constructors for debug event objects.
MUST_USE_RESULT MaybeHandle<Object> MakeJSObject(
@@ -545,8 +550,9 @@
// Mirror cache handling.
void ClearMirrorCache();
- // Returns a promise if it does not have a reject handler.
- Handle<Object> GetPromiseForUncaughtException();
+ // Returns a promise if the pushed try-catch handler matches the current
one.
+ Handle<Object> GetPromiseOnStackOnThrow();
+ bool PromiseHasRejectHandler(Handle<JSObject> promise);
void CallEventCallback(v8::DebugEvent event,
Handle<Object> exec_state,
=======================================
--- /branches/bleeding_edge/src/isolate.cc Tue Aug 5 08:18:22 2014 UTC
+++ /branches/bleeding_edge/src/isolate.cc Wed Aug 6 09:41:52 2014 UTC
@@ -1026,7 +1026,7 @@
// Notify debugger of exception.
if (catchable_by_javascript) {
- debug()->OnException(exception_handle, report_exception);
+ debug()->OnThrow(exception_handle, report_exception);
}
// Generate the message if required.
=======================================
--- /branches/bleeding_edge/src/promise.js Tue Aug 5 07:42:06 2014 UTC
+++ /branches/bleeding_edge/src/promise.js Wed Aug 6 09:41:52 2014 UTC
@@ -18,6 +18,7 @@
var PromiseChain;
var PromiseCatch;
var PromiseThen;
+var PromiseHasRejectHandler;
// mirror-debugger.js currently uses builtins.promiseStatus. It would be
nice
// if we could move these property names into the closure below.
@@ -29,6 +30,7 @@
var promiseOnResolve = GLOBAL_PRIVATE("Promise#onResolve");
var promiseOnReject = GLOBAL_PRIVATE("Promise#onReject");
var promiseRaw = GLOBAL_PRIVATE("Promise#raw");
+var promiseDebug = GLOBAL_PRIVATE("Promise#debug");
var lastMicrotaskId = 0;
(function() {
@@ -40,13 +42,13 @@
throw MakeTypeError('resolver_not_a_function', [resolver]);
var promise = PromiseInit(this);
try {
- %DebugPromiseHandlePrologue(function() { return promise });
+ %DebugPushPromise(promise);
resolver(function(x) { PromiseResolve(promise, x) },
function(r) { PromiseReject(promise, r) });
} catch (e) {
PromiseReject(promise, e);
} finally {
- %DebugPromiseHandleEpilogue();
+ %DebugPopPromise();
}
}
@@ -98,11 +100,7 @@
function PromiseHandle(value, handler, deferred) {
try {
- %DebugPromiseHandlePrologue(
- function() {
- var queue = GET_PRIVATE(deferred.promise, promiseOnReject);
- return (queue && queue.length == 0) ? deferred.promise :
UNDEFINED;
- });
+ %DebugPushPromise(deferred.promise);
var result = handler(value);
if (result === deferred.promise)
throw MakeTypeError('promise_cyclic', [result]);
@@ -111,14 +109,9 @@
else
deferred.resolve(result);
} catch (exception) {
- try {
- %DebugPromiseHandlePrologue(function() { return deferred.promise
});
- deferred.reject(exception);
- } catch (e) { } finally {
- %DebugPromiseHandleEpilogue();
- }
+ try { deferred.reject(exception); } catch (e) { }
} finally {
- %DebugPromiseHandleEpilogue();
+ %DebugPopPromise();
}
}
@@ -165,6 +158,13 @@
}
PromiseReject = function PromiseReject(promise, r) {
+ // Check promise status to confirm that this reject has an effect.
+ // Check promiseDebug property to avoid duplicate event.
+ if (DEBUG_IS_ACTIVE &&
+ GET_PRIVATE(promise, promiseStatus) == 0 &&
+ !HAS_PRIVATE(promise, promiseDebug)) {
+ %DebugPromiseRejectEvent(promise, r);
+ }
PromiseDone(promise, -1, r, promiseOnReject)
}
@@ -321,6 +321,16 @@
}
return deferred.promise;
}
+
+
+ // Utility for debugger
+
+ PromiseHasRejectHandler = function PromiseHasRejectHandler() {
+ // Mark promise as already having triggered a reject event.
+ SET_PRIVATE(this, promiseDebug, true);
+ var queue = GET_PRIVATE(this, promiseOnReject);
+ return !IS_UNDEFINED(queue) && queue.length > 0;
+ };
// -------------------------------------------------------------------
// Install exported functions.
=======================================
--- /branches/bleeding_edge/src/runtime.cc Tue Aug 5 08:16:02 2014 UTC
+++ /branches/bleeding_edge/src/runtime.cc Wed Aug 6 09:41:52 2014 UTC
@@ -5465,22 +5465,19 @@
}
-// The argument is a closure that is kept until the epilogue is called.
-// On exception, the closure is called, which returns the promise if the
-// exception is considered uncaught, or undefined otherwise.
-RUNTIME_FUNCTION(Runtime_DebugPromiseHandlePrologue) {
+RUNTIME_FUNCTION(Runtime_DebugPushPromise) {
DCHECK(args.length() == 1);
HandleScope scope(isolate);
- CONVERT_ARG_HANDLE_CHECKED(JSFunction, promise_getter, 0);
- isolate->debug()->PromiseHandlePrologue(promise_getter);
+ CONVERT_ARG_HANDLE_CHECKED(JSObject, promise, 0);
+ isolate->debug()->PushPromise(promise);
return isolate->heap()->undefined_value();
}
-RUNTIME_FUNCTION(Runtime_DebugPromiseHandleEpilogue) {
+RUNTIME_FUNCTION(Runtime_DebugPopPromise) {
DCHECK(args.length() == 0);
SealHandleScope shs(isolate);
- isolate->debug()->PromiseHandleEpilogue();
+ isolate->debug()->PopPromise();
return isolate->heap()->undefined_value();
}
@@ -5492,6 +5489,16 @@
isolate->debug()->OnPromiseEvent(data);
return isolate->heap()->undefined_value();
}
+
+
+RUNTIME_FUNCTION(Runtime_DebugPromiseRejectEvent) {
+ DCHECK(args.length() == 2);
+ HandleScope scope(isolate);
+ CONVERT_ARG_HANDLE_CHECKED(JSObject, promise, 0);
+ CONVERT_ARG_HANDLE_CHECKED(Object, value, 1);
+ isolate->debug()->OnPromiseReject(promise, value);
+ return isolate->heap()->undefined_value();
+}
RUNTIME_FUNCTION(Runtime_DebugAsyncTaskEvent) {
=======================================
--- /branches/bleeding_edge/src/runtime.h Fri Aug 1 09:23:07 2014 UTC
+++ /branches/bleeding_edge/src/runtime.h Wed Aug 6 09:41:52 2014 UTC
@@ -76,9 +76,10 @@
F(SetInlineBuiltinFlag, 1, 1) \
F(StoreArrayLiteralElement, 5, 1) \
F(DebugPrepareStepInIfStepping, 1, 1) \
- F(DebugPromiseHandlePrologue, 1, 1) \
- F(DebugPromiseHandleEpilogue, 0, 1) \
+ F(DebugPushPromise, 1, 1) \
+ F(DebugPopPromise, 0, 1) \
F(DebugPromiseEvent, 1, 1) \
+ F(DebugPromiseRejectEvent, 2, 1) \
F(DebugAsyncTaskEvent, 1, 1) \
F(FlattenString, 1, 1) \
F(LoadMutableDouble, 2, 1) \
=======================================
--- /branches/bleeding_edge/test/mjsunit/mjsunit.status Tue Aug 5 09:24:27
2014 UTC
+++ /branches/bleeding_edge/test/mjsunit/mjsunit.status Wed Aug 6 09:41:52
2014 UTC
@@ -127,10 +127,14 @@
'debug-stepout-scope-part3': [PASS, NO_VARIANTS],
'debug-stepout-scope-part7': [PASS, NO_VARIANTS],
'debug-stepout-to-builtin': [PASS, NO_VARIANTS],
- 'es6/debug-promises-throw-in-constructor': [PASS, NO_VARIANTS],
- 'es6/debug-promises-throw-in-reject': [PASS, NO_VARIANTS],
- 'es6/debug-promises-uncaught-all': [PASS, NO_VARIANTS],
- 'es6/debug-promises-uncaught-uncaught': [PASS, NO_VARIANTS],
+ 'es6/debug-promises/throw-in-constructor': [PASS, NO_VARIANTS],
+ 'es6/debug-promises/reject-in-constructor': [PASS, NO_VARIANTS],
+ 'es6/debug-promises/throw-with-undefined-reject': [PASS, NO_VARIANTS],
+ 'es6/debug-promises/throw-with-throw-in-reject': [PASS, NO_VARIANTS],
+ 'es6/debug-promises/reject-with-throw-in-reject': [PASS, NO_VARIANTS],
+ 'es6/debug-promises/throw-uncaught-all': [PASS, NO_VARIANTS],
+ 'es6/debug-promises/throw-uncaught-uncaught': [PASS, NO_VARIANTS],
+ 'es6/debug-promises/reject-uncaught-late': [PASS, NO_VARIANTS],
'harmony/debug-blockscopes': [PASS, NO_VARIANTS],
'harmony/generators-debug-scopes': [PASS, NO_VARIANTS],
'regress/regress-1081309': [PASS, NO_VARIANTS],
=======================================
--- /branches/bleeding_edge/tools/generate-runtime-tests.py Tue Aug 5
07:42:06 2014 UTC
+++ /branches/bleeding_edge/tools/generate-runtime-tests.py Wed Aug 6
09:41:52 2014 UTC
@@ -47,8 +47,8 @@
# that the parser doesn't bit-rot. Change the values as needed when you
add,
# remove or change runtime functions, but make sure we don't lose our
ability
# to parse them!
-EXPECTED_FUNCTION_COUNT = 425
-EXPECTED_FUZZABLE_COUNT = 328
+EXPECTED_FUNCTION_COUNT = 426
+EXPECTED_FUZZABLE_COUNT = 329
EXPECTED_CCTEST_COUNT = 7
EXPECTED_UNKNOWN_COUNT = 16
EXPECTED_BUILTINS_COUNT = 813
--
--
v8-dev mailing list
[email protected]
http://groups.google.com/group/v8-dev
---
You received this message because you are subscribed to the Google Groups "v8-dev" group.
To unsubscribe from this group and stop receiving emails from it, send an email
to [email protected].
For more options, visit https://groups.google.com/d/optout.