OLD | NEW |
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 Loading... |
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 Loading... |
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 Loading... |
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 Loading... |
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 |
OLD | NEW |