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 1705 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
1716 HandleScope scope(isolate_); | 1716 HandleScope scope(isolate_); |
1717 // Check whether the promise has been marked as having triggered a message. | 1717 // Check whether the promise has been marked as having triggered a message. |
1718 Handle<Symbol> key = isolate_->factory()->promise_debug_marker_symbol(); | 1718 Handle<Symbol> key = isolate_->factory()->promise_debug_marker_symbol(); |
1719 if (!promise->IsJSObject() || | 1719 if (!promise->IsJSObject() || |
1720 JSReceiver::GetDataProperty(Handle<JSObject>::cast(promise), key) | 1720 JSReceiver::GetDataProperty(Handle<JSObject>::cast(promise), key) |
1721 ->IsUndefined(isolate_)) { | 1721 ->IsUndefined(isolate_)) { |
1722 OnException(value, promise); | 1722 OnException(value, promise); |
1723 } | 1723 } |
1724 } | 1724 } |
1725 | 1725 |
| 1726 namespace { |
| 1727 v8::Local<v8::Context> GetDebugEventContext(Isolate* isolate) { |
| 1728 Handle<Context> context = isolate->debug()->debugger_entry()->GetContext(); |
| 1729 // Isolate::context() may have been NULL when "script collected" event |
| 1730 // occured. |
| 1731 if (context.is_null()) return v8::Local<v8::Context>(); |
| 1732 Handle<Context> native_context(context->native_context()); |
| 1733 return v8::Utils::ToLocal(native_context); |
| 1734 } |
| 1735 } // anonymous namespace |
1726 | 1736 |
1727 void Debug::OnException(Handle<Object> exception, Handle<Object> promise) { | 1737 void Debug::OnException(Handle<Object> exception, Handle<Object> promise) { |
1728 // We cannot generate debug events when JS execution is disallowed. | 1738 // We cannot generate debug events when JS execution is disallowed. |
1729 // TODO(5530): Reenable debug events within DisallowJSScopes once relevant | 1739 // TODO(5530): Reenable debug events within DisallowJSScopes once relevant |
1730 // code (MakeExceptionEvent and ProcessDebugEvent) have been moved to C++. | 1740 // code (MakeExceptionEvent and ProcessDebugEvent) have been moved to C++. |
1731 if (!AllowJavascriptExecution::IsAllowed(isolate_)) return; | 1741 if (!AllowJavascriptExecution::IsAllowed(isolate_)) return; |
1732 | 1742 |
1733 Isolate::CatchType catch_type = isolate_->PredictExceptionCatcher(); | 1743 Isolate::CatchType catch_type = isolate_->PredictExceptionCatcher(); |
1734 | 1744 |
1735 // Don't notify listener of exceptions that are internal to a desugaring. | 1745 // Don't notify listener of exceptions that are internal to a desugaring. |
(...skipping 19 matching lines...) Expand all Loading... |
1755 | 1765 |
1756 { | 1766 { |
1757 // Check whether the break location is muted. | 1767 // Check whether the break location is muted. |
1758 JavaScriptFrameIterator it(isolate_); | 1768 JavaScriptFrameIterator it(isolate_); |
1759 if (!it.done() && IsMutedAtCurrentLocation(it.frame())) return; | 1769 if (!it.done() && IsMutedAtCurrentLocation(it.frame())) return; |
1760 } | 1770 } |
1761 | 1771 |
1762 DebugScope debug_scope(this); | 1772 DebugScope debug_scope(this); |
1763 if (debug_scope.failed()) return; | 1773 if (debug_scope.failed()) return; |
1764 | 1774 |
| 1775 if (debug_event_listener_) { |
| 1776 HandleScope scope(isolate_); |
| 1777 |
| 1778 // Create the execution state. |
| 1779 Handle<Object> exec_state; |
| 1780 // Bail out and don't call debugger if exception. |
| 1781 if (!MakeExecutionState().ToHandle(&exec_state)) return; |
| 1782 |
| 1783 debug_event_listener_->OnExceptionEvent( |
| 1784 GetDebugEventContext(isolate_), |
| 1785 v8::Utils::ToLocal(Handle<JSObject>::cast(exec_state)), |
| 1786 v8::Utils::ToLocal(exception), promise->IsJSObject(), uncaught); |
| 1787 if (!non_inspector_listener_exists()) return; |
| 1788 } |
| 1789 |
1765 // Create the event data object. | 1790 // Create the event data object. |
1766 Handle<Object> event_data; | 1791 Handle<Object> event_data; |
1767 // Bail out and don't call debugger if exception. | 1792 // Bail out and don't call debugger if exception. |
1768 if (!MakeExceptionEvent( | 1793 if (!MakeExceptionEvent( |
1769 exception, uncaught, promise).ToHandle(&event_data)) { | 1794 exception, uncaught, promise).ToHandle(&event_data)) { |
1770 return; | 1795 return; |
1771 } | 1796 } |
1772 | 1797 |
1773 // Process debug event. | 1798 // Process debug event. |
1774 ProcessDebugEvent(v8::Exception, Handle<JSObject>::cast(event_data), false); | 1799 ProcessDebugEvent(v8::Exception, Handle<JSObject>::cast(event_data), false); |
1775 // Return to continue execution from where the exception was thrown. | 1800 // Return to continue execution from where the exception was thrown. |
1776 } | 1801 } |
1777 | 1802 |
1778 void Debug::OnDebugBreak(Handle<Object> break_points_hit, bool auto_continue) { | 1803 void Debug::OnDebugBreak(Handle<Object> break_points_hit, bool auto_continue) { |
1779 // The caller provided for DebugScope. | 1804 // The caller provided for DebugScope. |
1780 AssertDebugContext(); | 1805 AssertDebugContext(); |
1781 // Bail out if there is no listener for this event | 1806 // Bail out if there is no listener for this event |
1782 if (ignore_events()) return; | 1807 if (ignore_events()) return; |
1783 | 1808 |
1784 #ifdef DEBUG | 1809 #ifdef DEBUG |
1785 PrintBreakLocation(); | 1810 PrintBreakLocation(); |
1786 #endif // DEBUG | 1811 #endif // DEBUG |
1787 | 1812 |
| 1813 if (debug_event_listener_) { |
| 1814 HandleScope scope(isolate_); |
| 1815 |
| 1816 // Create the execution state. |
| 1817 Handle<Object> exec_state; |
| 1818 // Bail out and don't call debugger if exception. |
| 1819 if (!MakeExecutionState().ToHandle(&exec_state)) return; |
| 1820 |
| 1821 bool previous = in_debug_event_listener_; |
| 1822 in_debug_event_listener_ = true; |
| 1823 debug_event_listener_->OnBreakEvent( |
| 1824 GetDebugEventContext(isolate_), |
| 1825 v8::Utils::ToLocal(Handle<JSObject>::cast(exec_state)), |
| 1826 v8::Utils::ToLocal(break_points_hit)); |
| 1827 in_debug_event_listener_ = previous; |
| 1828 if (!non_inspector_listener_exists()) return; |
| 1829 } |
| 1830 |
1788 HandleScope scope(isolate_); | 1831 HandleScope scope(isolate_); |
1789 // Create the event data object. | 1832 // Create the event data object. |
1790 Handle<Object> event_data; | 1833 Handle<Object> event_data; |
1791 // Bail out and don't call debugger if exception. | 1834 // Bail out and don't call debugger if exception. |
1792 if (!MakeBreakEvent(break_points_hit).ToHandle(&event_data)) return; | 1835 if (!MakeBreakEvent(break_points_hit).ToHandle(&event_data)) return; |
1793 | 1836 |
1794 // Process debug event. | 1837 // Process debug event. |
1795 ProcessDebugEvent(v8::Break, Handle<JSObject>::cast(event_data), | 1838 ProcessDebugEvent(v8::Break, Handle<JSObject>::cast(event_data), |
1796 auto_continue); | 1839 auto_continue); |
1797 } | 1840 } |
(...skipping 57 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
1855 // Since we holding promise when at least one microtask is scheduled (inside | 1898 // Since we holding promise when at least one microtask is scheduled (inside |
1856 // PromiseReactionJobInfo), we can send cancel event in weak callback. | 1899 // PromiseReactionJobInfo), we can send cancel event in weak callback. |
1857 GlobalHandles::MakeWeak( | 1900 GlobalHandles::MakeWeak( |
1858 global_handle.location(), | 1901 global_handle.location(), |
1859 new CollectedCallbackData(global_handle.location(), async_id->value(), | 1902 new CollectedCallbackData(global_handle.location(), async_id->value(), |
1860 this, isolate_), | 1903 this, isolate_), |
1861 &ResetPromiseHandle, v8::WeakCallbackType::kParameter); | 1904 &ResetPromiseHandle, v8::WeakCallbackType::kParameter); |
1862 return async_id->value(); | 1905 return async_id->value(); |
1863 } | 1906 } |
1864 | 1907 |
1865 void Debug::SetAsyncTaskListener(debug::AsyncTaskListener listener, | |
1866 void* data) { | |
1867 async_task_listener_ = listener; | |
1868 async_task_listener_data_ = data; | |
1869 UpdateState(); | |
1870 } | |
1871 | |
1872 void Debug::OnAsyncTaskEvent(debug::PromiseDebugActionType type, int id) { | 1908 void Debug::OnAsyncTaskEvent(debug::PromiseDebugActionType type, int id) { |
1873 if (in_debug_scope() || ignore_events()) return; | 1909 if (in_debug_scope() || ignore_events()) return; |
1874 | 1910 |
1875 if (async_task_listener_) { | 1911 if (debug_event_listener_) { |
1876 async_task_listener_(type, id, async_task_listener_data_); | 1912 debug_event_listener_->OnAsyncTaskEvent(type, id); |
1877 if (!non_inspector_listener_exists()) return; | 1913 if (!non_inspector_listener_exists()) return; |
1878 } | 1914 } |
1879 | 1915 |
1880 HandleScope scope(isolate_); | 1916 HandleScope scope(isolate_); |
1881 DebugScope debug_scope(this); | 1917 DebugScope debug_scope(this); |
1882 if (debug_scope.failed()) return; | 1918 if (debug_scope.failed()) return; |
1883 | 1919 |
1884 // Create the script collected state object. | 1920 // Create the script collected state object. |
1885 Handle<Object> event_data; | 1921 Handle<Object> event_data; |
1886 // Bail out and don't call debugger if exception. | 1922 // Bail out and don't call debugger if exception. |
(...skipping 34 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
1921 Handle<Object> exec_state, | 1957 Handle<Object> exec_state, |
1922 Handle<Object> event_data, | 1958 Handle<Object> event_data, |
1923 v8::Debug::ClientData* client_data) { | 1959 v8::Debug::ClientData* client_data) { |
1924 // Prevent other interrupts from triggering, for example API callbacks, | 1960 // Prevent other interrupts from triggering, for example API callbacks, |
1925 // while dispatching event listners. | 1961 // while dispatching event listners. |
1926 PostponeInterruptsScope postpone(isolate_); | 1962 PostponeInterruptsScope postpone(isolate_); |
1927 bool previous = in_debug_event_listener_; | 1963 bool previous = in_debug_event_listener_; |
1928 in_debug_event_listener_ = true; | 1964 in_debug_event_listener_ = true; |
1929 if (event_listener_->IsForeign()) { | 1965 if (event_listener_->IsForeign()) { |
1930 // Invoke the C debug event listener. | 1966 // Invoke the C debug event listener. |
1931 debug::EventCallback callback = FUNCTION_CAST<debug::EventCallback>( | 1967 v8::Debug::EventCallback callback = FUNCTION_CAST<v8::Debug::EventCallback>( |
1932 Handle<Foreign>::cast(event_listener_)->foreign_address()); | 1968 Handle<Foreign>::cast(event_listener_)->foreign_address()); |
1933 EventDetailsImpl event_details(event, | 1969 EventDetailsImpl event_details(event, |
1934 Handle<JSObject>::cast(exec_state), | 1970 Handle<JSObject>::cast(exec_state), |
1935 Handle<JSObject>::cast(event_data), | 1971 Handle<JSObject>::cast(event_data), |
1936 event_listener_data_, | 1972 event_listener_data_, |
1937 client_data); | 1973 client_data); |
1938 callback(event_details); | 1974 callback(event_details); |
1939 CHECK(!isolate_->has_scheduled_exception()); | 1975 CHECK(!isolate_->has_scheduled_exception()); |
1940 } else { | 1976 } else { |
1941 // Invoke the JavaScript debug event listener. | 1977 // Invoke the JavaScript debug event listener. |
1942 DCHECK(event_listener_->IsJSFunction()); | 1978 DCHECK(event_listener_->IsJSFunction()); |
1943 Handle<Object> argv[] = { Handle<Object>(Smi::FromInt(event), isolate_), | 1979 Handle<Object> argv[] = { Handle<Object>(Smi::FromInt(event), isolate_), |
1944 exec_state, | 1980 exec_state, |
1945 event_data, | 1981 event_data, |
1946 event_listener_data_ }; | 1982 event_listener_data_ }; |
1947 Handle<JSReceiver> global = isolate_->global_proxy(); | 1983 Handle<JSReceiver> global = isolate_->global_proxy(); |
1948 MaybeHandle<Object> result = | 1984 MaybeHandle<Object> result = |
1949 Execution::Call(isolate_, Handle<JSFunction>::cast(event_listener_), | 1985 Execution::Call(isolate_, Handle<JSFunction>::cast(event_listener_), |
1950 global, arraysize(argv), argv); | 1986 global, arraysize(argv), argv); |
1951 CHECK(!result.is_null()); // Listeners must not throw. | 1987 CHECK(!result.is_null()); // Listeners must not throw. |
1952 } | 1988 } |
1953 in_debug_event_listener_ = previous; | 1989 in_debug_event_listener_ = previous; |
1954 } | 1990 } |
1955 | 1991 |
1956 void Debug::SetCompileEventListener(debug::CompileEventListener listener, | |
1957 void* data) { | |
1958 compile_event_listener_ = listener; | |
1959 compile_event_listener_data_ = data; | |
1960 UpdateState(); | |
1961 } | |
1962 | |
1963 void Debug::ProcessCompileEvent(v8::DebugEvent event, Handle<Script> script) { | 1992 void Debug::ProcessCompileEvent(v8::DebugEvent event, Handle<Script> script) { |
1964 if (ignore_events()) return; | 1993 if (ignore_events()) return; |
1965 if (script->type() != i::Script::TYPE_NORMAL && | 1994 if (script->type() != i::Script::TYPE_NORMAL && |
1966 script->type() != i::Script::TYPE_WASM) { | 1995 script->type() != i::Script::TYPE_WASM) { |
1967 return; | 1996 return; |
1968 } | 1997 } |
1969 SuppressDebug while_processing(this); | 1998 SuppressDebug while_processing(this); |
1970 | 1999 |
1971 if (compile_event_listener_) { | 2000 if (debug_event_listener_) { |
1972 compile_event_listener_(ToApiHandle<debug::Script>(script), | 2001 debug_event_listener_->OnCompileEvent(ToApiHandle<debug::Script>(script), |
1973 event != v8::AfterCompile, | 2002 event != v8::AfterCompile); |
1974 compile_event_listener_data_); | |
1975 if (!non_inspector_listener_exists()) return; | 2003 if (!non_inspector_listener_exists()) return; |
1976 } | 2004 } |
1977 | 2005 |
1978 bool in_nested_debug_scope = in_debug_scope(); | 2006 bool in_nested_debug_scope = in_debug_scope(); |
1979 HandleScope scope(isolate_); | 2007 HandleScope scope(isolate_); |
1980 DebugScope debug_scope(this); | 2008 DebugScope debug_scope(this); |
1981 if (debug_scope.failed()) return; | 2009 if (debug_scope.failed()) return; |
1982 | 2010 |
1983 // Create the compile state object. | 2011 // Create the compile state object. |
1984 Handle<Object> event_data; | 2012 Handle<Object> event_data; |
(...skipping 179 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
2164 void Debug::SetMessageHandler(v8::Debug::MessageHandler handler) { | 2192 void Debug::SetMessageHandler(v8::Debug::MessageHandler handler) { |
2165 message_handler_ = handler; | 2193 message_handler_ = handler; |
2166 UpdateState(); | 2194 UpdateState(); |
2167 if (handler == NULL && in_debug_scope()) { | 2195 if (handler == NULL && in_debug_scope()) { |
2168 // Send an empty command to the debugger if in a break to make JavaScript | 2196 // Send an empty command to the debugger if in a break to make JavaScript |
2169 // run again if the debugger is closed. | 2197 // run again if the debugger is closed. |
2170 EnqueueCommandMessage(Vector<const uint16_t>::empty()); | 2198 EnqueueCommandMessage(Vector<const uint16_t>::empty()); |
2171 } | 2199 } |
2172 } | 2200 } |
2173 | 2201 |
| 2202 void Debug::SetDebugEventListener(debug::DebugEventListener* listener) { |
| 2203 debug_event_listener_ = listener; |
| 2204 UpdateState(); |
| 2205 } |
| 2206 |
2174 void Debug::UpdateState() { | 2207 void Debug::UpdateState() { |
2175 bool is_active = message_handler_ != nullptr || !event_listener_.is_null() || | 2208 bool is_active = message_handler_ != nullptr || !event_listener_.is_null() || |
2176 async_task_listener_ != nullptr || | 2209 debug_event_listener_ != nullptr; |
2177 compile_event_listener_ != nullptr; | |
2178 if (is_active || in_debug_scope()) { | 2210 if (is_active || in_debug_scope()) { |
2179 // Note that the debug context could have already been loaded to | 2211 // Note that the debug context could have already been loaded to |
2180 // bootstrap test cases. | 2212 // bootstrap test cases. |
2181 isolate_->compilation_cache()->Disable(); | 2213 isolate_->compilation_cache()->Disable(); |
2182 is_active = Load(); | 2214 is_active = Load(); |
2183 } else if (is_loaded()) { | 2215 } else if (is_loaded()) { |
2184 isolate_->compilation_cache()->Enable(); | 2216 isolate_->compilation_cache()->Enable(); |
2185 Unload(); | 2217 Unload(); |
2186 } | 2218 } |
2187 is_active_ = is_active; | 2219 is_active_ = is_active; |
(...skipping 317 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
2505 Handle<Object> json; | 2537 Handle<Object> json; |
2506 if (!maybe_json.ToHandle(&json) || !json->IsString()) { | 2538 if (!maybe_json.ToHandle(&json) || !json->IsString()) { |
2507 return v8::Local<v8::String>(); | 2539 return v8::Local<v8::String>(); |
2508 } | 2540 } |
2509 return scope.Escape(v8::Utils::ToLocal(Handle<String>::cast(json))); | 2541 return scope.Escape(v8::Utils::ToLocal(Handle<String>::cast(json))); |
2510 } else { | 2542 } else { |
2511 return v8::Utils::ToLocal(response_json_); | 2543 return v8::Utils::ToLocal(response_json_); |
2512 } | 2544 } |
2513 } | 2545 } |
2514 | 2546 |
2515 namespace { | |
2516 v8::Local<v8::Context> GetDebugEventContext(Isolate* isolate) { | |
2517 Handle<Context> context = isolate->debug()->debugger_entry()->GetContext(); | |
2518 // Isolate::context() may have been NULL when "script collected" event | |
2519 // occured. | |
2520 if (context.is_null()) return v8::Local<v8::Context>(); | |
2521 Handle<Context> native_context(context->native_context()); | |
2522 return v8::Utils::ToLocal(native_context); | |
2523 } | |
2524 } // anonymous namespace | |
2525 | |
2526 v8::Local<v8::Context> MessageImpl::GetEventContext() const { | 2547 v8::Local<v8::Context> MessageImpl::GetEventContext() const { |
2527 Isolate* isolate = event_data_->GetIsolate(); | 2548 Isolate* isolate = event_data_->GetIsolate(); |
2528 v8::Local<v8::Context> context = GetDebugEventContext(isolate); | 2549 v8::Local<v8::Context> context = GetDebugEventContext(isolate); |
2529 // Isolate::context() may be NULL when "script collected" event occurs. | 2550 // Isolate::context() may be NULL when "script collected" event occurs. |
2530 DCHECK(!context.IsEmpty()); | 2551 DCHECK(!context.IsEmpty()); |
2531 return context; | 2552 return context; |
2532 } | 2553 } |
2533 | 2554 |
2534 v8::Debug::ClientData* MessageImpl::GetClientData() const { | 2555 v8::Debug::ClientData* MessageImpl::GetClientData() const { |
2535 return client_data_; | 2556 return client_data_; |
(...skipping 121 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
2657 logger_->DebugEvent("Put", message.text()); | 2678 logger_->DebugEvent("Put", message.text()); |
2658 } | 2679 } |
2659 | 2680 |
2660 void LockingCommandMessageQueue::Clear() { | 2681 void LockingCommandMessageQueue::Clear() { |
2661 base::LockGuard<base::Mutex> lock_guard(&mutex_); | 2682 base::LockGuard<base::Mutex> lock_guard(&mutex_); |
2662 queue_.Clear(); | 2683 queue_.Clear(); |
2663 } | 2684 } |
2664 | 2685 |
2665 } // namespace internal | 2686 } // namespace internal |
2666 } // namespace v8 | 2687 } // namespace v8 |
OLD | NEW |