Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(577)

Unified Diff: src/debug.cc

Issue 440773004: Trigger exception debug events on Promise reject. (Closed) Base URL: https://v8.googlecode.com/svn/branches/bleeding_edge
Patch Set: comments Created 6 years, 4 months ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View side-by-side diff with in-line comments
Download patch
« no previous file with comments | « src/debug.h ('k') | src/isolate.cc » ('j') | no next file with comments »
Expand Comments ('e') | Collapse Comments ('c') | Show Comments Hide Comments ('s')
Index: src/debug.cc
diff --git a/src/debug.cc b/src/debug.cc
index 9f9bcd9a35c64a34ee8f5ef6b188a8298ef81f46..c6b936c33ba27abaf3c7a53fe89d2f6c827bc1bf 100644
--- a/src/debug.cc
+++ b/src/debug.cc
@@ -855,8 +855,8 @@ void Debug::Unload() {
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 @@ bool Debug::IsBreakOnException(ExceptionBreakType type) {
}
-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,35 +1302,40 @@ void Debug::PromiseHandleEpilogue() {
}
-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,
int step_count,
StackFrame::Id frame_id) {
@@ -2562,13 +2566,25 @@ MaybeHandle<Object> Debug::MakeAsyncTaskEvent(Handle<JSObject> task_event) {
}
-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.
« no previous file with comments | « src/debug.h ('k') | src/isolate.cc » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698