Revision: 23112
Author:   [email protected]
Date:     Thu Aug 14 06:57:48 2014 UTC
Log:      Ignore default reject handler when looking for reject handlers.

LOG=N
BUG=v8:3093
[email protected]

Review URL: https://codereview.chromium.org/461023002
http://code.google.com/p/v8/source/detail?r=23112

Added:
/branches/bleeding_edge/test/mjsunit/es6/reject-caught-by-default-reject-handler.js /branches/bleeding_edge/test/mjsunit/es6/throw-caught-by-default-reject-handler.js
Modified:
 /branches/bleeding_edge/src/promise.js

=======================================
--- /dev/null
+++ /branches/bleeding_edge/test/mjsunit/es6/reject-caught-by-default-reject-handler.js Thu Aug 14 06:57:48 2014 UTC
@@ -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.
+
+// 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 = 2;
+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());
+      assertTrue(event_data.promise() instanceof Promise);
+      if (expected_events == 1) {
+        // p1 is rejected, uncaught except for its default reject handler.
+        assertEquals(0, exec_state.frameCount());
+        assertSame(p1, event_data.promise());
+      } else {
+        // p2 is rejected by p1's default reject handler.
+        assertEquals(0, exec_state.frameCount());
+        assertSame(p2, 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 q", "end main", "resolve p", "p0.then"], 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/throw-caught-by-default-reject-handler.js Thu Aug 14 06:57:48 2014 UTC
@@ -0,0 +1,85 @@
+// 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 = 2;
+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());
+      assertTrue(event_data.promise() instanceof Promise);
+      if (expected_events == 1) {
+        // p1 is rejected, uncaught except for its default reject handler.
+        assertTrue(
+            exec_state.frame(0).sourceLineText().indexOf("// event") > 0);
+        assertSame(p1, event_data.promise());
+      } else {
+        // p2 is rejected by p1's default reject handler.
+        assertEquals(0, exec_state.frameCount());
+        assertSame(p2, 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 q", "end main", "resolve p", "p0.then"], 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);
=======================================
--- /branches/bleeding_edge/src/promise.js      Wed Aug  6 09:41:52 2014 UTC
+++ /branches/bleeding_edge/src/promise.js      Thu Aug 14 06:57:48 2014 UTC
@@ -325,11 +325,22 @@

   // Utility for debugger

+  function PromiseHasRejectHandlerRecursive(promise) {
+    var queue = GET_PRIVATE(promise, promiseOnReject);
+    if (IS_UNDEFINED(queue)) return false;
+    // Do a depth first search for a reject handler that's not
+    // the default PromiseIdRejectHandler.
+    for (var i = 0; i < queue.length; i += 2) {
+      if (queue[i] != PromiseIdRejectHandler) return true;
+      if (PromiseHasRejectHandlerRecursive(queue[i + 1])) return true;
+    }
+    return false;
+  }
+
   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;
+    return PromiseHasRejectHandlerRecursive(this);
   };

   // -------------------------------------------------------------------

--
--
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.

Reply via email to