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

Side by Side 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 unified diff | Download patch | Annotate | Revision Log
« no previous file with comments | « src/debug.h ('k') | src/isolate.cc » ('j') | no next file with comments »
Toggle Intra-line Diffs ('i') | Expand Comments ('e') | Collapse Comments ('c') | Show Comments Hide Comments ('s')
OLDNEW
1 // Copyright 2012 the V8 project authors. All rights reserved. 1 // Copyright 2012 the V8 project authors. All rights reserved.
2 // Use of this source code is governed by a BSD-style license that can be 2 // Use of this source code is governed by a BSD-style license that can be
3 // found in the LICENSE file. 3 // found in the LICENSE file.
4 4
5 #include "src/v8.h" 5 #include "src/v8.h"
6 6
7 #include "src/api.h" 7 #include "src/api.h"
8 #include "src/arguments.h" 8 #include "src/arguments.h"
9 #include "src/bootstrapper.h" 9 #include "src/bootstrapper.h"
10 #include "src/code-stubs.h" 10 #include "src/code-stubs.h"
(...skipping 837 matching lines...) Expand 10 before | Expand all | Expand 10 after
848 debug_context_ = Handle<Context>::cast( 848 debug_context_ = Handle<Context>::cast(
849 isolate_->global_handles()->Create(*context)); 849 isolate_->global_handles()->Create(*context));
850 return true; 850 return true;
851 } 851 }
852 852
853 853
854 void Debug::Unload() { 854 void Debug::Unload() {
855 ClearAllBreakPoints(); 855 ClearAllBreakPoints();
856 ClearStepping(); 856 ClearStepping();
857 857
858 // Match unmatched PromiseHandlePrologue calls. 858 // Match unmatched PopPromise calls.
859 while (thread_local_.promise_on_stack_) PromiseHandleEpilogue(); 859 while (thread_local_.promise_on_stack_) PopPromise();
860 860
861 // Return debugger is not loaded. 861 // Return debugger is not loaded.
862 if (!is_loaded()) return; 862 if (!is_loaded()) return;
863 863
864 // Clear the script cache. 864 // Clear the script cache.
865 if (script_cache_ != NULL) { 865 if (script_cache_ != NULL) {
866 delete script_cache_; 866 delete script_cache_;
867 script_cache_ = NULL; 867 script_cache_ = NULL;
868 } 868 }
869 869
(...skipping 395 matching lines...) Expand 10 before | Expand all | Expand 10 after
1265 1265
1266 bool Debug::IsBreakOnException(ExceptionBreakType type) { 1266 bool Debug::IsBreakOnException(ExceptionBreakType type) {
1267 if (type == BreakUncaughtException) { 1267 if (type == BreakUncaughtException) {
1268 return break_on_uncaught_exception_; 1268 return break_on_uncaught_exception_;
1269 } else { 1269 } else {
1270 return break_on_exception_; 1270 return break_on_exception_;
1271 } 1271 }
1272 } 1272 }
1273 1273
1274 1274
1275 PromiseOnStack::PromiseOnStack(Isolate* isolate, 1275 PromiseOnStack::PromiseOnStack(Isolate* isolate, PromiseOnStack* prev,
1276 PromiseOnStack* prev, 1276 Handle<JSObject> promise)
1277 Handle<JSFunction> getter)
1278 : isolate_(isolate), prev_(prev) { 1277 : isolate_(isolate), prev_(prev) {
1279 handler_ = StackHandler::FromAddress( 1278 handler_ = StackHandler::FromAddress(
1280 Isolate::handler(isolate->thread_local_top())); 1279 Isolate::handler(isolate->thread_local_top()));
1281 getter_ = Handle<JSFunction>::cast( 1280 promise_ =
1282 isolate->global_handles()->Create(*getter)); 1281 Handle<JSObject>::cast(isolate->global_handles()->Create(*promise));
1283 } 1282 }
1284 1283
1285 1284
1286 PromiseOnStack::~PromiseOnStack() { 1285 PromiseOnStack::~PromiseOnStack() {
1287 isolate_->global_handles()->Destroy(Handle<Object>::cast(getter_).location()); 1286 isolate_->global_handles()->Destroy(
1287 Handle<Object>::cast(promise_).location());
1288 } 1288 }
1289 1289
1290 1290
1291 void Debug::PromiseHandlePrologue(Handle<JSFunction> promise_getter) { 1291 void Debug::PushPromise(Handle<JSObject> promise) {
1292 PromiseOnStack* prev = thread_local_.promise_on_stack_; 1292 PromiseOnStack* prev = thread_local_.promise_on_stack_;
1293 thread_local_.promise_on_stack_ = 1293 thread_local_.promise_on_stack_ = new PromiseOnStack(isolate_, prev, promise);
1294 new PromiseOnStack(isolate_, prev, promise_getter);
1295 } 1294 }
1296 1295
1297 1296
1298 void Debug::PromiseHandleEpilogue() { 1297 void Debug::PopPromise() {
1299 if (thread_local_.promise_on_stack_ == NULL) return; 1298 if (thread_local_.promise_on_stack_ == NULL) return;
1300 PromiseOnStack* prev = thread_local_.promise_on_stack_->prev(); 1299 PromiseOnStack* prev = thread_local_.promise_on_stack_->prev();
1301 delete thread_local_.promise_on_stack_; 1300 delete thread_local_.promise_on_stack_;
1302 thread_local_.promise_on_stack_ = prev; 1301 thread_local_.promise_on_stack_ = prev;
1303 } 1302 }
1304 1303
1305 1304
1306 Handle<Object> Debug::GetPromiseForUncaughtException() { 1305 Handle<Object> Debug::GetPromiseOnStackOnThrow() {
1307 Handle<Object> undefined = isolate_->factory()->undefined_value(); 1306 Handle<Object> undefined = isolate_->factory()->undefined_value();
1308 if (thread_local_.promise_on_stack_ == NULL) return undefined; 1307 if (thread_local_.promise_on_stack_ == NULL) return undefined;
1309 Handle<JSFunction> promise_getter = thread_local_.promise_on_stack_->getter(); 1308 StackHandler* promise_try = thread_local_.promise_on_stack_->handler();
1310 StackHandler* promise_catch = thread_local_.promise_on_stack_->handler();
1311 // Find the top-most try-catch handler. 1309 // Find the top-most try-catch handler.
1312 StackHandler* handler = StackHandler::FromAddress( 1310 StackHandler* handler = StackHandler::FromAddress(
1313 Isolate::handler(isolate_->thread_local_top())); 1311 Isolate::handler(isolate_->thread_local_top()));
1314 while (handler != NULL && !handler->is_catch()) { 1312 do {
1313 if (handler == promise_try) {
1314 // Mark the pushed try-catch handler to prevent a later duplicate event
1315 // triggered with the following reject.
1316 return thread_local_.promise_on_stack_->promise();
1317 }
1315 handler = handler->next(); 1318 handler = handler->next();
1316 } 1319 // There must be a try-catch handler if a promise is on stack.
1317 #ifdef DEBUG 1320 DCHECK_NE(NULL, handler);
1318 // Make sure that our promise catch handler is in the list of handlers, 1321 // Throwing inside a Promise can be intercepted by an inner try-catch, so
1319 // even if it's not the top-most try-catch handler. 1322 // we stop at the first try-catch handler.
1320 StackHandler* temp = handler; 1323 } while (!handler->is_catch());
1321 while (temp != promise_catch && !temp->is_catch()) { 1324 return undefined;
1322 temp = temp->next(); 1325 }
1323 CHECK(temp != NULL);
1324 }
1325 #endif // DEBUG
1326 1326
1327 if (handler == promise_catch) { 1327
1328 return Execution::Call( 1328 bool Debug::PromiseHasRejectHandler(Handle<JSObject> promise) {
1329 isolate_, promise_getter, undefined, 0, NULL).ToHandleChecked(); 1329 Handle<JSFunction> fun = Handle<JSFunction>::cast(
1330 } 1330 JSObject::GetDataProperty(isolate_->js_builtins_object(),
1331 return undefined; 1331 isolate_->factory()->NewStringFromStaticAscii(
1332 "PromiseHasRejectHandler")));
1333 Handle<Object> result =
1334 Execution::Call(isolate_, fun, promise, 0, NULL).ToHandleChecked();
1335 return result->IsTrue();
1332 } 1336 }
1333 1337
1334 1338
1335 void Debug::PrepareStep(StepAction step_action, 1339 void Debug::PrepareStep(StepAction step_action,
1336 int step_count, 1340 int step_count,
1337 StackFrame::Id frame_id) { 1341 StackFrame::Id frame_id) {
1338 HandleScope scope(isolate_); 1342 HandleScope scope(isolate_);
1339 1343
1340 PrepareForBreakPoints(); 1344 PrepareForBreakPoints();
1341 1345
(...skipping 1213 matching lines...) Expand 10 before | Expand all | Expand 10 after
2555 } 2559 }
2556 2560
2557 2561
2558 MaybeHandle<Object> Debug::MakeAsyncTaskEvent(Handle<JSObject> task_event) { 2562 MaybeHandle<Object> Debug::MakeAsyncTaskEvent(Handle<JSObject> task_event) {
2559 // Create the async task event object. 2563 // Create the async task event object.
2560 Handle<Object> argv[] = { task_event }; 2564 Handle<Object> argv[] = { task_event };
2561 return MakeJSObject("MakeAsyncTaskEvent", ARRAY_SIZE(argv), argv); 2565 return MakeJSObject("MakeAsyncTaskEvent", ARRAY_SIZE(argv), argv);
2562 } 2566 }
2563 2567
2564 2568
2565 void Debug::OnException(Handle<Object> exception, bool uncaught) { 2569 void Debug::OnThrow(Handle<Object> exception, bool uncaught) {
2566 if (in_debug_scope() || ignore_events()) return; 2570 if (in_debug_scope() || ignore_events()) return;
2571 HandleScope scope(isolate_);
2572 OnException(exception, uncaught, GetPromiseOnStackOnThrow());
2573 }
2567 2574
2575
2576 void Debug::OnPromiseReject(Handle<JSObject> promise, Handle<Object> value) {
2577 if (in_debug_scope() || ignore_events()) return;
2568 HandleScope scope(isolate_); 2578 HandleScope scope(isolate_);
2569 Handle<Object> promise = GetPromiseForUncaughtException(); 2579 OnException(value, false, promise);
2570 uncaught |= !promise->IsUndefined(); 2580 }
2571 2581
2582
2583 void Debug::OnException(Handle<Object> exception, bool uncaught,
2584 Handle<Object> promise) {
2585 if (promise->IsJSObject()) {
2586 uncaught |= !PromiseHasRejectHandler(Handle<JSObject>::cast(promise));
2587 }
2572 // Bail out if exception breaks are not active 2588 // Bail out if exception breaks are not active
2573 if (uncaught) { 2589 if (uncaught) {
2574 // Uncaught exceptions are reported by either flags. 2590 // Uncaught exceptions are reported by either flags.
2575 if (!(break_on_uncaught_exception_ || break_on_exception_)) return; 2591 if (!(break_on_uncaught_exception_ || break_on_exception_)) return;
2576 } else { 2592 } else {
2577 // Caught exceptions are reported is activated. 2593 // Caught exceptions are reported is activated.
2578 if (!break_on_exception_) return; 2594 if (!break_on_exception_) return;
2579 } 2595 }
2580 2596
2581 DebugScope debug_scope(this); 2597 DebugScope debug_scope(this);
(...skipping 820 matching lines...) Expand 10 before | Expand all | Expand 10 after
3402 logger_->DebugEvent("Put", message.text()); 3418 logger_->DebugEvent("Put", message.text());
3403 } 3419 }
3404 3420
3405 3421
3406 void LockingCommandMessageQueue::Clear() { 3422 void LockingCommandMessageQueue::Clear() {
3407 base::LockGuard<base::Mutex> lock_guard(&mutex_); 3423 base::LockGuard<base::Mutex> lock_guard(&mutex_);
3408 queue_.Clear(); 3424 queue_.Clear();
3409 } 3425 }
3410 3426
3411 } } // namespace v8::internal 3427 } } // namespace v8::internal
OLDNEW
« 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