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/debug/debug.h" | 5 #include "src/debug/debug.h" |
6 | 6 |
7 #include <memory> | 7 #include <memory> |
8 | 8 |
9 #include "src/api.h" | 9 #include "src/api.h" |
10 #include "src/arguments.h" | 10 #include "src/arguments.h" |
(...skipping 1702 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
1713 HandleScope scope(isolate_); | 1713 HandleScope scope(isolate_); |
1714 // Check whether the promise has been marked as having triggered a message. | 1714 // Check whether the promise has been marked as having triggered a message. |
1715 Handle<Symbol> key = isolate_->factory()->promise_debug_marker_symbol(); | 1715 Handle<Symbol> key = isolate_->factory()->promise_debug_marker_symbol(); |
1716 if (!promise->IsJSObject() || | 1716 if (!promise->IsJSObject() || |
1717 JSReceiver::GetDataProperty(Handle<JSObject>::cast(promise), key) | 1717 JSReceiver::GetDataProperty(Handle<JSObject>::cast(promise), key) |
1718 ->IsUndefined(isolate_)) { | 1718 ->IsUndefined(isolate_)) { |
1719 OnException(value, promise); | 1719 OnException(value, promise); |
1720 } | 1720 } |
1721 } | 1721 } |
1722 | 1722 |
| 1723 namespace { |
| 1724 v8::Local<v8::Context> GetDebugEventContext(Isolate* isolate) { |
| 1725 Handle<Context> context = isolate->debug()->debugger_entry()->GetContext(); |
| 1726 // Isolate::context() may have been NULL when "script collected" event |
| 1727 // occured. |
| 1728 if (context.is_null()) return v8::Local<v8::Context>(); |
| 1729 Handle<Context> native_context(context->native_context()); |
| 1730 return v8::Utils::ToLocal(native_context); |
| 1731 } |
| 1732 } // anonymous namespace |
| 1733 |
| 1734 void Debug::SetExceptionEventListener(debug::ExceptionEventListener listener, |
| 1735 void* data) { |
| 1736 exception_event_listener_ = listener; |
| 1737 exception_event_listener_data_ = data; |
| 1738 UpdateState(); |
| 1739 } |
1723 | 1740 |
1724 void Debug::OnException(Handle<Object> exception, Handle<Object> promise) { | 1741 void Debug::OnException(Handle<Object> exception, Handle<Object> promise) { |
1725 // We cannot generate debug events when JS execution is disallowed. | 1742 // We cannot generate debug events when JS execution is disallowed. |
1726 // TODO(5530): Reenable debug events within DisallowJSScopes once relevant | 1743 // TODO(5530): Reenable debug events within DisallowJSScopes once relevant |
1727 // code (MakeExceptionEvent and ProcessDebugEvent) have been moved to C++. | 1744 // code (MakeExceptionEvent and ProcessDebugEvent) have been moved to C++. |
1728 if (!AllowJavascriptExecution::IsAllowed(isolate_)) return; | 1745 if (!AllowJavascriptExecution::IsAllowed(isolate_)) return; |
1729 | 1746 |
1730 Isolate::CatchType catch_type = isolate_->PredictExceptionCatcher(); | 1747 Isolate::CatchType catch_type = isolate_->PredictExceptionCatcher(); |
1731 | 1748 |
1732 // Don't notify listener of exceptions that are internal to a desugaring. | 1749 // Don't notify listener of exceptions that are internal to a desugaring. |
(...skipping 19 matching lines...) Expand all Loading... |
1752 | 1769 |
1753 { | 1770 { |
1754 // Check whether the break location is muted. | 1771 // Check whether the break location is muted. |
1755 JavaScriptFrameIterator it(isolate_); | 1772 JavaScriptFrameIterator it(isolate_); |
1756 if (!it.done() && IsMutedAtCurrentLocation(it.frame())) return; | 1773 if (!it.done() && IsMutedAtCurrentLocation(it.frame())) return; |
1757 } | 1774 } |
1758 | 1775 |
1759 DebugScope debug_scope(this); | 1776 DebugScope debug_scope(this); |
1760 if (debug_scope.failed()) return; | 1777 if (debug_scope.failed()) return; |
1761 | 1778 |
| 1779 if (exception_event_listener_) { |
| 1780 HandleScope scope(isolate_); |
| 1781 |
| 1782 // Create the execution state. |
| 1783 Handle<Object> exec_state; |
| 1784 // Bail out and don't call debugger if exception. |
| 1785 if (!MakeExecutionState().ToHandle(&exec_state)) return; |
| 1786 |
| 1787 exception_event_listener_( |
| 1788 GetDebugEventContext(isolate_), |
| 1789 v8::Utils::ToLocal(Handle<JSObject>::cast(exec_state)), |
| 1790 v8::Utils::ToLocal(exception), promise->IsJSObject(), uncaught, |
| 1791 exception_event_listener_data_); |
| 1792 if (!non_inspector_listener_exists()) return; |
| 1793 } |
| 1794 |
1762 // Create the event data object. | 1795 // Create the event data object. |
1763 Handle<Object> event_data; | 1796 Handle<Object> event_data; |
1764 // Bail out and don't call debugger if exception. | 1797 // Bail out and don't call debugger if exception. |
1765 if (!MakeExceptionEvent( | 1798 if (!MakeExceptionEvent( |
1766 exception, uncaught, promise).ToHandle(&event_data)) { | 1799 exception, uncaught, promise).ToHandle(&event_data)) { |
1767 return; | 1800 return; |
1768 } | 1801 } |
1769 | 1802 |
1770 // Process debug event. | 1803 // Process debug event. |
1771 ProcessDebugEvent(v8::Exception, Handle<JSObject>::cast(event_data), false); | 1804 ProcessDebugEvent(v8::Exception, Handle<JSObject>::cast(event_data), false); |
1772 // Return to continue execution from where the exception was thrown. | 1805 // Return to continue execution from where the exception was thrown. |
1773 } | 1806 } |
1774 | 1807 |
| 1808 void Debug::SetBreakEventListener(debug::BreakEventListener listener, |
| 1809 void* data) { |
| 1810 break_event_listener_ = listener; |
| 1811 break_event_listener_data_ = data; |
| 1812 UpdateState(); |
| 1813 } |
| 1814 |
1775 void Debug::OnDebugBreak(Handle<Object> break_points_hit, bool auto_continue) { | 1815 void Debug::OnDebugBreak(Handle<Object> break_points_hit, bool auto_continue) { |
1776 // The caller provided for DebugScope. | 1816 // The caller provided for DebugScope. |
1777 AssertDebugContext(); | 1817 AssertDebugContext(); |
1778 // Bail out if there is no listener for this event | 1818 // Bail out if there is no listener for this event |
1779 if (ignore_events()) return; | 1819 if (ignore_events()) return; |
1780 | 1820 |
1781 #ifdef DEBUG | 1821 #ifdef DEBUG |
1782 PrintBreakLocation(); | 1822 PrintBreakLocation(); |
1783 #endif // DEBUG | 1823 #endif // DEBUG |
1784 | 1824 |
| 1825 if (break_event_listener_) { |
| 1826 HandleScope scope(isolate_); |
| 1827 |
| 1828 // Create the execution state. |
| 1829 Handle<Object> exec_state; |
| 1830 // Bail out and don't call debugger if exception. |
| 1831 if (!MakeExecutionState().ToHandle(&exec_state)) return; |
| 1832 |
| 1833 break_event_listener_( |
| 1834 GetDebugEventContext(isolate_), |
| 1835 v8::Utils::ToLocal(Handle<JSObject>::cast(exec_state)), |
| 1836 v8::Utils::ToLocal(break_points_hit), break_event_listener_data_); |
| 1837 if (!non_inspector_listener_exists()) return; |
| 1838 } |
| 1839 |
1785 HandleScope scope(isolate_); | 1840 HandleScope scope(isolate_); |
1786 // Create the event data object. | 1841 // Create the event data object. |
1787 Handle<Object> event_data; | 1842 Handle<Object> event_data; |
1788 // Bail out and don't call debugger if exception. | 1843 // Bail out and don't call debugger if exception. |
1789 if (!MakeBreakEvent(break_points_hit).ToHandle(&event_data)) return; | 1844 if (!MakeBreakEvent(break_points_hit).ToHandle(&event_data)) return; |
1790 | 1845 |
1791 // Process debug event. | 1846 // Process debug event. |
1792 ProcessDebugEvent(v8::Break, Handle<JSObject>::cast(event_data), | 1847 ProcessDebugEvent(v8::Break, Handle<JSObject>::cast(event_data), |
1793 auto_continue); | 1848 auto_continue); |
1794 } | 1849 } |
(...skipping 130 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
1925 Handle<Object> exec_state, | 1980 Handle<Object> exec_state, |
1926 Handle<Object> event_data, | 1981 Handle<Object> event_data, |
1927 v8::Debug::ClientData* client_data) { | 1982 v8::Debug::ClientData* client_data) { |
1928 // Prevent other interrupts from triggering, for example API callbacks, | 1983 // Prevent other interrupts from triggering, for example API callbacks, |
1929 // while dispatching event listners. | 1984 // while dispatching event listners. |
1930 PostponeInterruptsScope postpone(isolate_); | 1985 PostponeInterruptsScope postpone(isolate_); |
1931 bool previous = in_debug_event_listener_; | 1986 bool previous = in_debug_event_listener_; |
1932 in_debug_event_listener_ = true; | 1987 in_debug_event_listener_ = true; |
1933 if (event_listener_->IsForeign()) { | 1988 if (event_listener_->IsForeign()) { |
1934 // Invoke the C debug event listener. | 1989 // Invoke the C debug event listener. |
1935 debug::EventCallback callback = FUNCTION_CAST<debug::EventCallback>( | 1990 v8::Debug::EventCallback callback = FUNCTION_CAST<v8::Debug::EventCallback>( |
1936 Handle<Foreign>::cast(event_listener_)->foreign_address()); | 1991 Handle<Foreign>::cast(event_listener_)->foreign_address()); |
1937 EventDetailsImpl event_details(event, | 1992 EventDetailsImpl event_details(event, |
1938 Handle<JSObject>::cast(exec_state), | 1993 Handle<JSObject>::cast(exec_state), |
1939 Handle<JSObject>::cast(event_data), | 1994 Handle<JSObject>::cast(event_data), |
1940 event_listener_data_, | 1995 event_listener_data_, |
1941 client_data); | 1996 client_data); |
1942 callback(event_details); | 1997 callback(event_details); |
1943 CHECK(!isolate_->has_scheduled_exception()); | 1998 CHECK(!isolate_->has_scheduled_exception()); |
1944 } else { | 1999 } else { |
1945 // Invoke the JavaScript debug event listener. | 2000 // Invoke the JavaScript debug event listener. |
(...skipping 217 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
2163 message_handler_ = handler; | 2218 message_handler_ = handler; |
2164 UpdateState(); | 2219 UpdateState(); |
2165 if (handler == NULL && in_debug_scope()) { | 2220 if (handler == NULL && in_debug_scope()) { |
2166 // Send an empty command to the debugger if in a break to make JavaScript | 2221 // Send an empty command to the debugger if in a break to make JavaScript |
2167 // run again if the debugger is closed. | 2222 // run again if the debugger is closed. |
2168 EnqueueCommandMessage(Vector<const uint16_t>::empty()); | 2223 EnqueueCommandMessage(Vector<const uint16_t>::empty()); |
2169 } | 2224 } |
2170 } | 2225 } |
2171 | 2226 |
2172 void Debug::UpdateState() { | 2227 void Debug::UpdateState() { |
2173 bool is_active = message_handler_ != nullptr || !event_listener_.is_null() || | 2228 bool is_active = |
2174 async_task_listener_ != nullptr || | 2229 message_handler_ != nullptr || !event_listener_.is_null() || |
2175 compile_event_listener_ != nullptr; | 2230 async_task_listener_ != nullptr || compile_event_listener_ != nullptr || |
| 2231 break_event_listener_ != nullptr || exception_event_listener_ != nullptr; |
2176 if (is_active || in_debug_scope()) { | 2232 if (is_active || in_debug_scope()) { |
2177 // Note that the debug context could have already been loaded to | 2233 // Note that the debug context could have already been loaded to |
2178 // bootstrap test cases. | 2234 // bootstrap test cases. |
2179 isolate_->compilation_cache()->Disable(); | 2235 isolate_->compilation_cache()->Disable(); |
2180 is_active = Load(); | 2236 is_active = Load(); |
2181 } else if (is_loaded()) { | 2237 } else if (is_loaded()) { |
2182 isolate_->compilation_cache()->Enable(); | 2238 isolate_->compilation_cache()->Enable(); |
2183 Unload(); | 2239 Unload(); |
2184 } | 2240 } |
2185 is_active_ = is_active; | 2241 is_active_ = is_active; |
(...skipping 315 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
2501 Handle<Object> json; | 2557 Handle<Object> json; |
2502 if (!maybe_json.ToHandle(&json) || !json->IsString()) { | 2558 if (!maybe_json.ToHandle(&json) || !json->IsString()) { |
2503 return v8::Local<v8::String>(); | 2559 return v8::Local<v8::String>(); |
2504 } | 2560 } |
2505 return scope.Escape(v8::Utils::ToLocal(Handle<String>::cast(json))); | 2561 return scope.Escape(v8::Utils::ToLocal(Handle<String>::cast(json))); |
2506 } else { | 2562 } else { |
2507 return v8::Utils::ToLocal(response_json_); | 2563 return v8::Utils::ToLocal(response_json_); |
2508 } | 2564 } |
2509 } | 2565 } |
2510 | 2566 |
2511 namespace { | |
2512 v8::Local<v8::Context> GetDebugEventContext(Isolate* isolate) { | |
2513 Handle<Context> context = isolate->debug()->debugger_entry()->GetContext(); | |
2514 // Isolate::context() may have been NULL when "script collected" event | |
2515 // occured. | |
2516 if (context.is_null()) return v8::Local<v8::Context>(); | |
2517 Handle<Context> native_context(context->native_context()); | |
2518 return v8::Utils::ToLocal(native_context); | |
2519 } | |
2520 } // anonymous namespace | |
2521 | |
2522 v8::Local<v8::Context> MessageImpl::GetEventContext() const { | 2567 v8::Local<v8::Context> MessageImpl::GetEventContext() const { |
2523 Isolate* isolate = event_data_->GetIsolate(); | 2568 Isolate* isolate = event_data_->GetIsolate(); |
2524 v8::Local<v8::Context> context = GetDebugEventContext(isolate); | 2569 v8::Local<v8::Context> context = GetDebugEventContext(isolate); |
2525 // Isolate::context() may be NULL when "script collected" event occurs. | 2570 // Isolate::context() may be NULL when "script collected" event occurs. |
2526 DCHECK(!context.IsEmpty()); | 2571 DCHECK(!context.IsEmpty()); |
2527 return context; | 2572 return context; |
2528 } | 2573 } |
2529 | 2574 |
2530 v8::Debug::ClientData* MessageImpl::GetClientData() const { | 2575 v8::Debug::ClientData* MessageImpl::GetClientData() const { |
2531 return client_data_; | 2576 return client_data_; |
(...skipping 121 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
2653 logger_->DebugEvent("Put", message.text()); | 2698 logger_->DebugEvent("Put", message.text()); |
2654 } | 2699 } |
2655 | 2700 |
2656 void LockingCommandMessageQueue::Clear() { | 2701 void LockingCommandMessageQueue::Clear() { |
2657 base::LockGuard<base::Mutex> lock_guard(&mutex_); | 2702 base::LockGuard<base::Mutex> lock_guard(&mutex_); |
2658 queue_.Clear(); | 2703 queue_.Clear(); |
2659 } | 2704 } |
2660 | 2705 |
2661 } // namespace internal | 2706 } // namespace internal |
2662 } // namespace v8 | 2707 } // namespace v8 |
OLD | NEW |