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