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

Side by Side Diff: src/debug/debug.cc

Issue 2622253004: [inspector] introduced debug::SetBreakEventListener,SetExceptionEventListener (Closed)
Patch Set: addressed comments Created 3 years, 11 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
« no previous file with comments | « src/debug/debug.h ('k') | src/debug/debug-interface.h » ('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/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 1697 matching lines...) Expand 10 before | Expand all | Expand 10 after
1708 HandleScope scope(isolate_); 1708 HandleScope scope(isolate_);
1709 // Check whether the promise has been marked as having triggered a message. 1709 // Check whether the promise has been marked as having triggered a message.
1710 Handle<Symbol> key = isolate_->factory()->promise_debug_marker_symbol(); 1710 Handle<Symbol> key = isolate_->factory()->promise_debug_marker_symbol();
1711 if (!promise->IsJSObject() || 1711 if (!promise->IsJSObject() ||
1712 JSReceiver::GetDataProperty(Handle<JSObject>::cast(promise), key) 1712 JSReceiver::GetDataProperty(Handle<JSObject>::cast(promise), key)
1713 ->IsUndefined(isolate_)) { 1713 ->IsUndefined(isolate_)) {
1714 OnException(value, promise); 1714 OnException(value, promise);
1715 } 1715 }
1716 } 1716 }
1717 1717
1718 namespace {
1719 v8::Local<v8::Context> GetDebugEventContext(Isolate* isolate) {
1720 Handle<Context> context = isolate->debug()->debugger_entry()->GetContext();
1721 // Isolate::context() may have been NULL when "script collected" event
1722 // occured.
1723 if (context.is_null()) return v8::Local<v8::Context>();
1724 Handle<Context> native_context(context->native_context());
1725 return v8::Utils::ToLocal(native_context);
1726 }
1727 } // anonymous namespace
1718 1728
1719 void Debug::OnException(Handle<Object> exception, Handle<Object> promise) { 1729 void Debug::OnException(Handle<Object> exception, Handle<Object> promise) {
1720 // We cannot generate debug events when JS execution is disallowed. 1730 // We cannot generate debug events when JS execution is disallowed.
1721 // TODO(5530): Reenable debug events within DisallowJSScopes once relevant 1731 // TODO(5530): Reenable debug events within DisallowJSScopes once relevant
1722 // code (MakeExceptionEvent and ProcessDebugEvent) have been moved to C++. 1732 // code (MakeExceptionEvent and ProcessDebugEvent) have been moved to C++.
1723 if (!AllowJavascriptExecution::IsAllowed(isolate_)) return; 1733 if (!AllowJavascriptExecution::IsAllowed(isolate_)) return;
1724 1734
1725 Isolate::CatchType catch_type = isolate_->PredictExceptionCatcher(); 1735 Isolate::CatchType catch_type = isolate_->PredictExceptionCatcher();
1726 1736
1727 // Don't notify listener of exceptions that are internal to a desugaring. 1737 // Don't notify listener of exceptions that are internal to a desugaring.
(...skipping 19 matching lines...) Expand all
1747 1757
1748 { 1758 {
1749 // Check whether the break location is muted. 1759 // Check whether the break location is muted.
1750 JavaScriptFrameIterator it(isolate_); 1760 JavaScriptFrameIterator it(isolate_);
1751 if (!it.done() && IsMutedAtCurrentLocation(it.frame())) return; 1761 if (!it.done() && IsMutedAtCurrentLocation(it.frame())) return;
1752 } 1762 }
1753 1763
1754 DebugScope debug_scope(this); 1764 DebugScope debug_scope(this);
1755 if (debug_scope.failed()) return; 1765 if (debug_scope.failed()) return;
1756 1766
1767 if (debug_event_listener_) {
1768 HandleScope scope(isolate_);
1769
1770 // Create the execution state.
1771 Handle<Object> exec_state;
1772 // Bail out and don't call debugger if exception.
1773 if (!MakeExecutionState().ToHandle(&exec_state)) return;
1774
1775 debug_event_listener_->ExceptionThrown(
1776 GetDebugEventContext(isolate_),
1777 v8::Utils::ToLocal(Handle<JSObject>::cast(exec_state)),
1778 v8::Utils::ToLocal(exception), promise->IsJSObject(), uncaught);
1779 if (!non_inspector_listener_exists()) return;
Yang 2017/01/19 08:55:48 Let's implement the non-inspector listener through
1780 }
1781
1757 // Create the event data object. 1782 // Create the event data object.
1758 Handle<Object> event_data; 1783 Handle<Object> event_data;
1759 // Bail out and don't call debugger if exception. 1784 // Bail out and don't call debugger if exception.
1760 if (!MakeExceptionEvent( 1785 if (!MakeExceptionEvent(
1761 exception, uncaught, promise).ToHandle(&event_data)) { 1786 exception, uncaught, promise).ToHandle(&event_data)) {
1762 return; 1787 return;
1763 } 1788 }
1764 1789
1765 // Process debug event. 1790 // Process debug event.
1766 ProcessDebugEvent(v8::Exception, Handle<JSObject>::cast(event_data), false); 1791 ProcessDebugEvent(v8::Exception, Handle<JSObject>::cast(event_data), false);
1767 // Return to continue execution from where the exception was thrown. 1792 // Return to continue execution from where the exception was thrown.
1768 } 1793 }
1769 1794
1770 void Debug::OnDebugBreak(Handle<Object> break_points_hit, bool auto_continue) { 1795 void Debug::OnDebugBreak(Handle<Object> break_points_hit, bool auto_continue) {
1771 // The caller provided for DebugScope. 1796 // The caller provided for DebugScope.
1772 AssertDebugContext(); 1797 AssertDebugContext();
1773 // Bail out if there is no listener for this event 1798 // Bail out if there is no listener for this event
1774 if (ignore_events()) return; 1799 if (ignore_events()) return;
1775 1800
1776 #ifdef DEBUG 1801 #ifdef DEBUG
1777 PrintBreakLocation(); 1802 PrintBreakLocation();
1778 #endif // DEBUG 1803 #endif // DEBUG
1779 1804
1805 if (debug_event_listener_) {
1806 HandleScope scope(isolate_);
1807
1808 // Create the execution state.
1809 Handle<Object> exec_state;
1810 // Bail out and don't call debugger if exception.
1811 if (!MakeExecutionState().ToHandle(&exec_state)) return;
1812
1813 bool previous = in_debug_event_listener_;
1814 in_debug_event_listener_ = true;
1815 debug_event_listener_->BreakProgramRequested(
1816 GetDebugEventContext(isolate_),
1817 v8::Utils::ToLocal(Handle<JSObject>::cast(exec_state)),
1818 v8::Utils::ToLocal(break_points_hit));
1819 in_debug_event_listener_ = previous;
1820 if (!non_inspector_listener_exists()) return;
1821 }
1822
1780 HandleScope scope(isolate_); 1823 HandleScope scope(isolate_);
1781 // Create the event data object. 1824 // Create the event data object.
1782 Handle<Object> event_data; 1825 Handle<Object> event_data;
1783 // Bail out and don't call debugger if exception. 1826 // Bail out and don't call debugger if exception.
1784 if (!MakeBreakEvent(break_points_hit).ToHandle(&event_data)) return; 1827 if (!MakeBreakEvent(break_points_hit).ToHandle(&event_data)) return;
1785 1828
1786 // Process debug event. 1829 // Process debug event.
1787 ProcessDebugEvent(v8::Break, Handle<JSObject>::cast(event_data), 1830 ProcessDebugEvent(v8::Break, Handle<JSObject>::cast(event_data),
1788 auto_continue); 1831 auto_continue);
1789 } 1832 }
(...skipping 57 matching lines...) Expand 10 before | Expand all | Expand 10 after
1847 // Since we holding promise when at least one microtask is scheduled (inside 1890 // Since we holding promise when at least one microtask is scheduled (inside
1848 // PromiseReactionJobInfo), we can send cancel event in weak callback. 1891 // PromiseReactionJobInfo), we can send cancel event in weak callback.
1849 GlobalHandles::MakeWeak( 1892 GlobalHandles::MakeWeak(
1850 global_handle.location(), 1893 global_handle.location(),
1851 new CollectedCallbackData(global_handle.location(), async_id->value(), 1894 new CollectedCallbackData(global_handle.location(), async_id->value(),
1852 this, isolate_), 1895 this, isolate_),
1853 &ResetPromiseHandle, v8::WeakCallbackType::kParameter); 1896 &ResetPromiseHandle, v8::WeakCallbackType::kParameter);
1854 return async_id->value(); 1897 return async_id->value();
1855 } 1898 }
1856 1899
1857 void Debug::SetAsyncTaskListener(debug::AsyncTaskListener listener,
1858 void* data) {
1859 async_task_listener_ = listener;
1860 async_task_listener_data_ = data;
1861 UpdateState();
1862 }
1863
1864 void Debug::OnAsyncTaskEvent(debug::PromiseDebugActionType type, int id) { 1900 void Debug::OnAsyncTaskEvent(debug::PromiseDebugActionType type, int id) {
1865 if (in_debug_scope() || ignore_events()) return; 1901 if (in_debug_scope() || ignore_events()) return;
1866 1902
1867 if (async_task_listener_) { 1903 if (debug_event_listener_) {
1868 async_task_listener_(type, id, async_task_listener_data_); 1904 debug_event_listener_->PromiseEventOccurred(type, id);
1869 if (!non_inspector_listener_exists()) return; 1905 if (!non_inspector_listener_exists()) return;
1870 } 1906 }
1871 1907
1872 HandleScope scope(isolate_); 1908 HandleScope scope(isolate_);
1873 DebugScope debug_scope(this); 1909 DebugScope debug_scope(this);
1874 if (debug_scope.failed()) return; 1910 if (debug_scope.failed()) return;
1875 1911
1876 // Create the script collected state object. 1912 // Create the script collected state object.
1877 Handle<Object> event_data; 1913 Handle<Object> event_data;
1878 // Bail out and don't call debugger if exception. 1914 // Bail out and don't call debugger if exception.
(...skipping 34 matching lines...) Expand 10 before | Expand all | Expand 10 after
1913 Handle<Object> exec_state, 1949 Handle<Object> exec_state,
1914 Handle<Object> event_data, 1950 Handle<Object> event_data,
1915 v8::Debug::ClientData* client_data) { 1951 v8::Debug::ClientData* client_data) {
1916 // Prevent other interrupts from triggering, for example API callbacks, 1952 // Prevent other interrupts from triggering, for example API callbacks,
1917 // while dispatching event listners. 1953 // while dispatching event listners.
1918 PostponeInterruptsScope postpone(isolate_); 1954 PostponeInterruptsScope postpone(isolate_);
1919 bool previous = in_debug_event_listener_; 1955 bool previous = in_debug_event_listener_;
1920 in_debug_event_listener_ = true; 1956 in_debug_event_listener_ = true;
1921 if (event_listener_->IsForeign()) { 1957 if (event_listener_->IsForeign()) {
1922 // Invoke the C debug event listener. 1958 // Invoke the C debug event listener.
1923 debug::EventCallback callback = FUNCTION_CAST<debug::EventCallback>( 1959 v8::Debug::EventCallback callback = FUNCTION_CAST<v8::Debug::EventCallback>(
1924 Handle<Foreign>::cast(event_listener_)->foreign_address()); 1960 Handle<Foreign>::cast(event_listener_)->foreign_address());
1925 EventDetailsImpl event_details(event, 1961 EventDetailsImpl event_details(event,
1926 Handle<JSObject>::cast(exec_state), 1962 Handle<JSObject>::cast(exec_state),
1927 Handle<JSObject>::cast(event_data), 1963 Handle<JSObject>::cast(event_data),
1928 event_listener_data_, 1964 event_listener_data_,
1929 client_data); 1965 client_data);
1930 callback(event_details); 1966 callback(event_details);
1931 CHECK(!isolate_->has_scheduled_exception()); 1967 CHECK(!isolate_->has_scheduled_exception());
1932 } else { 1968 } else {
1933 // Invoke the JavaScript debug event listener. 1969 // Invoke the JavaScript debug event listener.
1934 DCHECK(event_listener_->IsJSFunction()); 1970 DCHECK(event_listener_->IsJSFunction());
1935 Handle<Object> argv[] = { Handle<Object>(Smi::FromInt(event), isolate_), 1971 Handle<Object> argv[] = { Handle<Object>(Smi::FromInt(event), isolate_),
1936 exec_state, 1972 exec_state,
1937 event_data, 1973 event_data,
1938 event_listener_data_ }; 1974 event_listener_data_ };
1939 Handle<JSReceiver> global = isolate_->global_proxy(); 1975 Handle<JSReceiver> global = isolate_->global_proxy();
1940 MaybeHandle<Object> result = 1976 MaybeHandle<Object> result =
1941 Execution::Call(isolate_, Handle<JSFunction>::cast(event_listener_), 1977 Execution::Call(isolate_, Handle<JSFunction>::cast(event_listener_),
1942 global, arraysize(argv), argv); 1978 global, arraysize(argv), argv);
1943 CHECK(!result.is_null()); // Listeners must not throw. 1979 CHECK(!result.is_null()); // Listeners must not throw.
1944 } 1980 }
1945 in_debug_event_listener_ = previous; 1981 in_debug_event_listener_ = previous;
1946 } 1982 }
1947 1983
1948 void Debug::SetCompileEventListener(debug::CompileEventListener listener,
1949 void* data) {
1950 compile_event_listener_ = listener;
1951 compile_event_listener_data_ = data;
1952 UpdateState();
1953 }
1954
1955 void Debug::ProcessCompileEvent(v8::DebugEvent event, Handle<Script> script) { 1984 void Debug::ProcessCompileEvent(v8::DebugEvent event, Handle<Script> script) {
1956 if (ignore_events()) return; 1985 if (ignore_events()) return;
1957 if (script->type() != i::Script::TYPE_NORMAL && 1986 if (script->type() != i::Script::TYPE_NORMAL &&
1958 script->type() != i::Script::TYPE_WASM) { 1987 script->type() != i::Script::TYPE_WASM) {
1959 return; 1988 return;
1960 } 1989 }
1961 SuppressDebug while_processing(this); 1990 SuppressDebug while_processing(this);
1962 bool in_nested_debug_scope = in_debug_scope(); 1991 bool in_nested_debug_scope = in_debug_scope();
1963 DebugScope debug_scope(this); 1992 DebugScope debug_scope(this);
1964 if (debug_scope.failed()) return; 1993 if (debug_scope.failed()) return;
1965 1994
1966 if (compile_event_listener_) { 1995 if (debug_event_listener_) {
1967 compile_event_listener_(ToApiHandle<debug::Script>(script), 1996 debug_event_listener_->ScriptCompiled(ToApiHandle<debug::Script>(script),
1968 event != v8::AfterCompile, 1997 event != v8::AfterCompile);
1969 compile_event_listener_data_);
1970 if (!non_inspector_listener_exists()) return; 1998 if (!non_inspector_listener_exists()) return;
1971 } 1999 }
1972 2000
1973 HandleScope scope(isolate_); 2001 HandleScope scope(isolate_);
1974 // Create the compile state object. 2002 // Create the compile state object.
1975 Handle<Object> event_data; 2003 Handle<Object> event_data;
1976 // Bail out and don't call debugger if exception. 2004 // Bail out and don't call debugger if exception.
1977 if (!MakeCompileEvent(script, event).ToHandle(&event_data)) return; 2005 if (!MakeCompileEvent(script, event).ToHandle(&event_data)) return;
1978 2006
1979 // Don't call NotifyMessageHandler if already in debug scope to avoid running 2007 // Don't call NotifyMessageHandler if already in debug scope to avoid running
(...skipping 175 matching lines...) Expand 10 before | Expand all | Expand 10 after
2155 void Debug::SetMessageHandler(v8::Debug::MessageHandler handler) { 2183 void Debug::SetMessageHandler(v8::Debug::MessageHandler handler) {
2156 message_handler_ = handler; 2184 message_handler_ = handler;
2157 UpdateState(); 2185 UpdateState();
2158 if (handler == NULL && in_debug_scope()) { 2186 if (handler == NULL && in_debug_scope()) {
2159 // Send an empty command to the debugger if in a break to make JavaScript 2187 // Send an empty command to the debugger if in a break to make JavaScript
2160 // run again if the debugger is closed. 2188 // run again if the debugger is closed.
2161 EnqueueCommandMessage(Vector<const uint16_t>::empty()); 2189 EnqueueCommandMessage(Vector<const uint16_t>::empty());
2162 } 2190 }
2163 } 2191 }
2164 2192
2193 void Debug::SetDebugEventListener(debug::DebugEventListener* listener) {
2194 debug_event_listener_ = listener;
2195 UpdateState();
2196 }
2197
2165 void Debug::UpdateState() { 2198 void Debug::UpdateState() {
2166 bool is_active = message_handler_ != nullptr || !event_listener_.is_null() || 2199 bool is_active = message_handler_ != nullptr || !event_listener_.is_null() ||
2167 async_task_listener_ != nullptr || 2200 debug_event_listener_ != nullptr;
2168 compile_event_listener_ != nullptr;
2169 if (is_active || in_debug_scope()) { 2201 if (is_active || in_debug_scope()) {
2170 // Note that the debug context could have already been loaded to 2202 // Note that the debug context could have already been loaded to
2171 // bootstrap test cases. 2203 // bootstrap test cases.
2172 isolate_->compilation_cache()->Disable(); 2204 isolate_->compilation_cache()->Disable();
2173 is_active = Load(); 2205 is_active = Load();
2174 } else if (is_loaded()) { 2206 } else if (is_loaded()) {
2175 isolate_->compilation_cache()->Enable(); 2207 isolate_->compilation_cache()->Enable();
2176 Unload(); 2208 Unload();
2177 } 2209 }
2178 is_active_ = is_active; 2210 is_active_ = is_active;
(...skipping 317 matching lines...) Expand 10 before | Expand all | Expand 10 after
2496 Handle<Object> json; 2528 Handle<Object> json;
2497 if (!maybe_json.ToHandle(&json) || !json->IsString()) { 2529 if (!maybe_json.ToHandle(&json) || !json->IsString()) {
2498 return v8::Local<v8::String>(); 2530 return v8::Local<v8::String>();
2499 } 2531 }
2500 return scope.Escape(v8::Utils::ToLocal(Handle<String>::cast(json))); 2532 return scope.Escape(v8::Utils::ToLocal(Handle<String>::cast(json)));
2501 } else { 2533 } else {
2502 return v8::Utils::ToLocal(response_json_); 2534 return v8::Utils::ToLocal(response_json_);
2503 } 2535 }
2504 } 2536 }
2505 2537
2506 namespace {
2507 v8::Local<v8::Context> GetDebugEventContext(Isolate* isolate) {
2508 Handle<Context> context = isolate->debug()->debugger_entry()->GetContext();
2509 // Isolate::context() may have been NULL when "script collected" event
2510 // occured.
2511 if (context.is_null()) return v8::Local<v8::Context>();
2512 Handle<Context> native_context(context->native_context());
2513 return v8::Utils::ToLocal(native_context);
2514 }
2515 } // anonymous namespace
2516
2517 v8::Local<v8::Context> MessageImpl::GetEventContext() const { 2538 v8::Local<v8::Context> MessageImpl::GetEventContext() const {
2518 Isolate* isolate = event_data_->GetIsolate(); 2539 Isolate* isolate = event_data_->GetIsolate();
2519 v8::Local<v8::Context> context = GetDebugEventContext(isolate); 2540 v8::Local<v8::Context> context = GetDebugEventContext(isolate);
2520 // Isolate::context() may be NULL when "script collected" event occurs. 2541 // Isolate::context() may be NULL when "script collected" event occurs.
2521 DCHECK(!context.IsEmpty()); 2542 DCHECK(!context.IsEmpty());
2522 return context; 2543 return context;
2523 } 2544 }
2524 2545
2525 v8::Debug::ClientData* MessageImpl::GetClientData() const { 2546 v8::Debug::ClientData* MessageImpl::GetClientData() const {
2526 return client_data_; 2547 return client_data_;
(...skipping 121 matching lines...) Expand 10 before | Expand all | Expand 10 after
2648 logger_->DebugEvent("Put", message.text()); 2669 logger_->DebugEvent("Put", message.text());
2649 } 2670 }
2650 2671
2651 void LockingCommandMessageQueue::Clear() { 2672 void LockingCommandMessageQueue::Clear() {
2652 base::LockGuard<base::Mutex> lock_guard(&mutex_); 2673 base::LockGuard<base::Mutex> lock_guard(&mutex_);
2653 queue_.Clear(); 2674 queue_.Clear();
2654 } 2675 }
2655 2676
2656 } // namespace internal 2677 } // namespace internal
2657 } // namespace v8 2678 } // namespace v8
OLDNEW
« no previous file with comments | « src/debug/debug.h ('k') | src/debug/debug-interface.h » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698