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

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

Issue 2682593003: [debugger] implement legacy debug event listeners via debug delegate. (Closed)
Patch Set: addressed comments Created 3 years, 10 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 20 matching lines...) Expand all
31 #include "src/wasm/wasm-module.h" 31 #include "src/wasm/wasm-module.h"
32 #include "src/wasm/wasm-objects.h" 32 #include "src/wasm/wasm-objects.h"
33 33
34 #include "include/v8-debug.h" 34 #include "include/v8-debug.h"
35 35
36 namespace v8 { 36 namespace v8 {
37 namespace internal { 37 namespace internal {
38 38
39 Debug::Debug(Isolate* isolate) 39 Debug::Debug(Isolate* isolate)
40 : debug_context_(Handle<Context>()), 40 : debug_context_(Handle<Context>()),
41 event_listener_(Handle<Object>()),
42 event_listener_data_(Handle<Object>()),
43 is_active_(false), 41 is_active_(false),
44 hook_on_function_call_(false), 42 hook_on_function_call_(false),
45 is_suppressed_(false), 43 is_suppressed_(false),
46 live_edit_enabled_(true), // TODO(yangguo): set to false by default. 44 live_edit_enabled_(true), // TODO(yangguo): set to false by default.
47 break_disabled_(false), 45 break_disabled_(false),
48 break_points_active_(true), 46 break_points_active_(true),
49 in_debug_event_listener_(false),
50 break_on_exception_(false), 47 break_on_exception_(false),
51 break_on_uncaught_exception_(false), 48 break_on_uncaught_exception_(false),
52 side_effect_check_failed_(false), 49 side_effect_check_failed_(false),
53 debug_info_list_(NULL), 50 debug_info_list_(NULL),
54 feature_tracker_(isolate), 51 feature_tracker_(isolate),
55 isolate_(isolate) { 52 isolate_(isolate) {
56 ThreadInit(); 53 ThreadInit();
57 } 54 }
58 55
59 BreakLocation BreakLocation::FromFrame(Handle<DebugInfo> debug_info, 56 BreakLocation BreakLocation::FromFrame(Handle<DebugInfo> debug_info,
(...skipping 406 matching lines...) Expand 10 before | Expand all | Expand 10 after
466 463
467 feature_tracker()->Track(DebugFeatureTracker::kActive); 464 feature_tracker()->Track(DebugFeatureTracker::kActive);
468 465
469 return true; 466 return true;
470 } 467 }
471 468
472 469
473 void Debug::Unload() { 470 void Debug::Unload() {
474 ClearAllBreakPoints(); 471 ClearAllBreakPoints();
475 ClearStepping(); 472 ClearStepping();
473 RemoveDebugDelegate();
476 474
477 // Return debugger is not loaded. 475 // Return debugger is not loaded.
478 if (!is_loaded()) return; 476 if (!is_loaded()) return;
479 477
480 // Clear debugger context global handle. 478 // Clear debugger context global handle.
481 GlobalHandles::Destroy(Handle<Object>::cast(debug_context_).location()); 479 GlobalHandles::Destroy(Handle<Object>::cast(debug_context_).location());
482 debug_context_ = Handle<Context>(); 480 debug_context_ = Handle<Context>();
483 } 481 }
484 482
485 void Debug::Break(JavaScriptFrame* frame) { 483 void Debug::Break(JavaScriptFrame* frame) {
486 HandleScope scope(isolate_); 484 HandleScope scope(isolate_);
487 485
488 // Initialize LiveEdit. 486 // Initialize LiveEdit.
489 LiveEdit::InitializeThreadLocal(this); 487 LiveEdit::InitializeThreadLocal(this);
490 488
491 // Just continue if breaks are disabled or debugger cannot be loaded. 489 // Just continue if breaks are disabled or debugger cannot be loaded.
492 if (break_disabled()) return; 490 if (break_disabled()) return;
493 491
494 // Enter the debugger. 492 // Enter the debugger.
495 DebugScope debug_scope(this); 493 DebugScope debug_scope(this);
496 if (debug_scope.failed()) return; 494 if (debug_scope.failed()) return;
497 495
498 // Postpone interrupt during breakpoint processing. 496 // Postpone interrupt during breakpoint processing.
499 PostponeInterruptsScope postpone(isolate_); 497 PostponeInterruptsScope postpone(isolate_);
498 DisableBreak no_recursive_break(this);
500 499
501 // Return if we fail to retrieve debug info. 500 // Return if we fail to retrieve debug info.
502 Handle<JSFunction> function(frame->function()); 501 Handle<JSFunction> function(frame->function());
503 Handle<SharedFunctionInfo> shared(function->shared()); 502 Handle<SharedFunctionInfo> shared(function->shared());
504 if (!EnsureDebugInfo(shared)) return; 503 if (!EnsureDebugInfo(shared)) return;
505 Handle<DebugInfo> debug_info(shared->GetDebugInfo(), isolate_); 504 Handle<DebugInfo> debug_info(shared->GetDebugInfo(), isolate_);
506 505
507 // Find the break location where execution has stopped. 506 // Find the break location where execution has stopped.
508 BreakLocation location = BreakLocation::FromFrame(debug_info, frame); 507 BreakLocation location = BreakLocation::FromFrame(debug_info, frame);
509 508
(...skipping 1150 matching lines...) Expand 10 before | Expand all | Expand 10 after
1660 1659
1661 MaybeHandle<Object> Debug::MakeCompileEvent(Handle<Script> script, 1660 MaybeHandle<Object> Debug::MakeCompileEvent(Handle<Script> script,
1662 v8::DebugEvent type) { 1661 v8::DebugEvent type) {
1663 // Create the compile event object. 1662 // Create the compile event object.
1664 Handle<Object> script_wrapper = Script::GetWrapper(script); 1663 Handle<Object> script_wrapper = Script::GetWrapper(script);
1665 Handle<Object> argv[] = { script_wrapper, 1664 Handle<Object> argv[] = { script_wrapper,
1666 isolate_->factory()->NewNumberFromInt(type) }; 1665 isolate_->factory()->NewNumberFromInt(type) };
1667 return CallFunction("MakeCompileEvent", arraysize(argv), argv); 1666 return CallFunction("MakeCompileEvent", arraysize(argv), argv);
1668 } 1667 }
1669 1668
1670 MaybeHandle<Object> Debug::MakeAsyncTaskEvent(Handle<Smi> type, 1669 MaybeHandle<Object> Debug::MakeAsyncTaskEvent(
1671 Handle<Smi> id) { 1670 v8::debug::PromiseDebugActionType type, int id) {
1672 DCHECK(id->IsNumber());
1673 // Create the async task event object. 1671 // Create the async task event object.
1674 Handle<Object> argv[] = {type, id}; 1672 Handle<Object> argv[] = {Handle<Smi>(Smi::FromInt(type), isolate_),
1673 Handle<Smi>(Smi::FromInt(id), isolate_)};
1675 return CallFunction("MakeAsyncTaskEvent", arraysize(argv), argv); 1674 return CallFunction("MakeAsyncTaskEvent", arraysize(argv), argv);
1676 } 1675 }
1677 1676
1678 1677
1679 void Debug::OnThrow(Handle<Object> exception) { 1678 void Debug::OnThrow(Handle<Object> exception) {
1680 if (in_debug_scope() || ignore_events()) return; 1679 if (in_debug_scope() || ignore_events()) return;
1681 // Temporarily clear any scheduled_exception to allow evaluating 1680 // Temporarily clear any scheduled_exception to allow evaluating
1682 // JavaScript from the debug event handler. 1681 // JavaScript from the debug event handler.
1683 HandleScope scope(isolate_); 1682 HandleScope scope(isolate_);
1684 Handle<Object> scheduled_exception; 1683 Handle<Object> scheduled_exception;
(...skipping 72 matching lines...) Expand 10 before | Expand all | Expand 10 after
1757 1756
1758 bool uncaught = catch_type == Isolate::NOT_CAUGHT; 1757 bool uncaught = catch_type == Isolate::NOT_CAUGHT;
1759 if (promise->IsJSObject()) { 1758 if (promise->IsJSObject()) {
1760 Handle<JSObject> jspromise = Handle<JSObject>::cast(promise); 1759 Handle<JSObject> jspromise = Handle<JSObject>::cast(promise);
1761 // Mark the promise as already having triggered a message. 1760 // Mark the promise as already having triggered a message.
1762 Handle<Symbol> key = isolate_->factory()->promise_debug_marker_symbol(); 1761 Handle<Symbol> key = isolate_->factory()->promise_debug_marker_symbol();
1763 JSObject::SetProperty(jspromise, key, key, STRICT).Assert(); 1762 JSObject::SetProperty(jspromise, key, key, STRICT).Assert();
1764 // Check whether the promise reject is considered an uncaught exception. 1763 // Check whether the promise reject is considered an uncaught exception.
1765 uncaught = !isolate_->PromiseHasUserDefinedRejectHandler(jspromise); 1764 uncaught = !isolate_->PromiseHasUserDefinedRejectHandler(jspromise);
1766 } 1765 }
1766
1767 if (!debug_delegate_) return;
1768
1767 // Bail out if exception breaks are not active 1769 // Bail out if exception breaks are not active
1768 if (uncaught) { 1770 if (uncaught) {
1769 // Uncaught exceptions are reported by either flags. 1771 // Uncaught exceptions are reported by either flags.
1770 if (!(break_on_uncaught_exception_ || break_on_exception_)) return; 1772 if (!(break_on_uncaught_exception_ || break_on_exception_)) return;
1771 } else { 1773 } else {
1772 // Caught exceptions are reported is activated. 1774 // Caught exceptions are reported is activated.
1773 if (!break_on_exception_) return; 1775 if (!break_on_exception_) return;
1774 } 1776 }
1775 1777
1776 bool empty_js_stack = false;
1777 { 1778 {
1778 JavaScriptFrameIterator it(isolate_); 1779 JavaScriptFrameIterator it(isolate_);
1779 // Check whether the top frame is blackboxed or the break location is muted. 1780 // Check whether the top frame is blackboxed or the break location is muted.
1780 if (!it.done() && (IsMutedAtCurrentLocation(it.frame()) || 1781 if (!it.done() && (IsMutedAtCurrentLocation(it.frame()) ||
1781 IsExceptionBlackboxed(uncaught))) { 1782 IsExceptionBlackboxed(uncaught))) {
1782 return; 1783 return;
1783 } 1784 }
1784 empty_js_stack = it.done(); 1785 if (it.done()) return; // Do not trigger an event with an empty stack.
1785 } 1786 }
1786 1787
1787 DebugScope debug_scope(this); 1788 DebugScope debug_scope(this);
1788 if (debug_scope.failed()) return; 1789 if (debug_scope.failed()) return;
1790 HandleScope scope(isolate_);
1791 PostponeInterruptsScope postpone(isolate_);
1792 DisableBreak no_recursive_break(this);
1789 1793
1790 if (debug_delegate_ && !empty_js_stack) { 1794 // Create the execution state.
1791 HandleScope scope(isolate_); 1795 Handle<Object> exec_state;
1796 // Bail out and don't call debugger if exception.
1797 if (!MakeExecutionState().ToHandle(&exec_state)) return;
1792 1798
1793 // Create the execution state. 1799 debug_delegate_->ExceptionThrown(
1794 Handle<Object> exec_state; 1800 GetDebugEventContext(isolate_),
1795 // Bail out and don't call debugger if exception. 1801 v8::Utils::ToLocal(Handle<JSObject>::cast(exec_state)),
1796 if (!MakeExecutionState().ToHandle(&exec_state)) return; 1802 v8::Utils::ToLocal(exception), v8::Utils::ToLocal(promise), uncaught);
1797
1798 debug_delegate_->ExceptionThrown(
1799 GetDebugEventContext(isolate_),
1800 v8::Utils::ToLocal(Handle<JSObject>::cast(exec_state)),
1801 v8::Utils::ToLocal(exception), promise->IsJSObject(), uncaught);
1802 }
1803 if (debug_delegate_ && !non_inspector_listener_exists()) return;
1804
1805 // Create the event data object.
1806 Handle<Object> event_data;
1807 // Bail out and don't call debugger if exception.
1808 if (!MakeExceptionEvent(
1809 exception, uncaught, promise).ToHandle(&event_data)) {
1810 return;
1811 }
1812
1813 // Process debug event.
1814 ProcessDebugEvent(v8::Exception, Handle<JSObject>::cast(event_data));
1815 // Return to continue execution from where the exception was thrown.
1816 } 1803 }
1817 1804
1818 void Debug::OnDebugBreak(Handle<Object> break_points_hit) { 1805 void Debug::OnDebugBreak(Handle<Object> break_points_hit) {
1819 // The caller provided for DebugScope. 1806 // The caller provided for DebugScope.
1820 AssertDebugContext(); 1807 AssertDebugContext();
1821 // Bail out if there is no listener for this event 1808 // Bail out if there is no listener for this event
1822 if (ignore_events()) return; 1809 if (ignore_events()) return;
1823 1810
1824 #ifdef DEBUG 1811 #ifdef DEBUG
1825 PrintBreakLocation(); 1812 PrintBreakLocation();
1826 #endif // DEBUG 1813 #endif // DEBUG
1827 1814
1828 if (debug_delegate_) { 1815 if (!debug_delegate_) return;
1829 HandleScope scope(isolate_); 1816 HandleScope scope(isolate_);
1817 PostponeInterruptsScope no_interrupts(isolate_);
1818 DisableBreak no_recursive_break(this);
1830 1819
1831 // Create the execution state. 1820 // Create the execution state.
1832 Handle<Object> exec_state; 1821 Handle<Object> exec_state;
1833 // Bail out and don't call debugger if exception. 1822 // Bail out and don't call debugger if exception.
1834 if (!MakeExecutionState().ToHandle(&exec_state)) return; 1823 if (!MakeExecutionState().ToHandle(&exec_state)) return;
1835 1824
1836 bool previous = in_debug_event_listener_; 1825 debug_delegate_->BreakProgramRequested(
1837 in_debug_event_listener_ = true; 1826 GetDebugEventContext(isolate_),
1838 debug_delegate_->BreakProgramRequested( 1827 v8::Utils::ToLocal(Handle<JSObject>::cast(exec_state)),
1839 GetDebugEventContext(isolate_), 1828 v8::Utils::ToLocal(break_points_hit));
1840 v8::Utils::ToLocal(Handle<JSObject>::cast(exec_state)),
1841 v8::Utils::ToLocal(break_points_hit));
1842 in_debug_event_listener_ = previous;
1843 if (!non_inspector_listener_exists()) return;
1844 }
1845
1846 HandleScope scope(isolate_);
1847 // Create the event data object.
1848 Handle<Object> event_data;
1849 // Bail out and don't call debugger if exception.
1850 if (!MakeBreakEvent(break_points_hit).ToHandle(&event_data)) return;
1851
1852 // Process debug event.
1853 ProcessDebugEvent(v8::Break, Handle<JSObject>::cast(event_data));
1854 } 1829 }
1855 1830
1856 1831
1857 void Debug::OnCompileError(Handle<Script> script) { 1832 void Debug::OnCompileError(Handle<Script> script) {
1858 ProcessCompileEvent(v8::CompileError, script); 1833 ProcessCompileEvent(v8::CompileError, script);
1859 } 1834 }
1860 1835
1861 1836
1862 // Handle debugger actions when a new script is compiled. 1837 // Handle debugger actions when a new script is compiled.
1863 void Debug::OnAfterCompile(Handle<Script> script) { 1838 void Debug::OnAfterCompile(Handle<Script> script) {
(...skipping 10 matching lines...) Expand all
1874 CollectedCallbackData(Object** location, int id, Debug* debug, 1849 CollectedCallbackData(Object** location, int id, Debug* debug,
1875 Isolate* isolate) 1850 Isolate* isolate)
1876 : location(location), id(id), debug(debug), isolate(isolate) {} 1851 : location(location), id(id), debug(debug), isolate(isolate) {}
1877 }; 1852 };
1878 1853
1879 void SendAsyncTaskEventCancel(const v8::WeakCallbackInfo<void>& info) { 1854 void SendAsyncTaskEventCancel(const v8::WeakCallbackInfo<void>& info) {
1880 std::unique_ptr<CollectedCallbackData> data( 1855 std::unique_ptr<CollectedCallbackData> data(
1881 reinterpret_cast<CollectedCallbackData*>(info.GetParameter())); 1856 reinterpret_cast<CollectedCallbackData*>(info.GetParameter()));
1882 if (!data->debug->is_active()) return; 1857 if (!data->debug->is_active()) return;
1883 HandleScope scope(data->isolate); 1858 HandleScope scope(data->isolate);
1884 data->debug->OnAsyncTaskEvent(debug::kDebugPromiseCollected, data->id); 1859 data->debug->OnAsyncTaskEvent(debug::kDebugPromiseCollected, data->id, 0);
1885 } 1860 }
1886 1861
1887 void ResetPromiseHandle(const v8::WeakCallbackInfo<void>& info) { 1862 void ResetPromiseHandle(const v8::WeakCallbackInfo<void>& info) {
1888 CollectedCallbackData* data = 1863 CollectedCallbackData* data =
1889 reinterpret_cast<CollectedCallbackData*>(info.GetParameter()); 1864 reinterpret_cast<CollectedCallbackData*>(info.GetParameter());
1890 GlobalHandles::Destroy(data->location); 1865 GlobalHandles::Destroy(data->location);
1891 info.SetSecondPassCallback(&SendAsyncTaskEventCancel); 1866 info.SetSecondPassCallback(&SendAsyncTaskEventCancel);
1892 } 1867 }
1893 1868
1894 // In an async function, reuse the existing stack related to the outer 1869 // In an async function, reuse the existing stack related to the outer
(...skipping 27 matching lines...) Expand all
1922 return Handle<Smi>::cast(async_task_id)->value(); 1897 return Handle<Smi>::cast(async_task_id)->value();
1923 } 1898 }
1924 } // namespace 1899 } // namespace
1925 1900
1926 void Debug::RunPromiseHook(PromiseHookType type, Handle<JSPromise> promise, 1901 void Debug::RunPromiseHook(PromiseHookType type, Handle<JSPromise> promise,
1927 Handle<Object> parent) { 1902 Handle<Object> parent) {
1928 if (!debug_delegate_) return; 1903 if (!debug_delegate_) return;
1929 int id = GetReferenceAsyncTaskId(isolate_, promise); 1904 int id = GetReferenceAsyncTaskId(isolate_, promise);
1930 switch (type) { 1905 switch (type) {
1931 case PromiseHookType::kInit: 1906 case PromiseHookType::kInit:
1932 debug_delegate_->PromiseEventOccurred( 1907 OnAsyncTaskEvent(debug::kDebugPromiseCreated, id,
1933 debug::kDebugPromiseCreated, id, 1908 parent->IsJSPromise()
1934 parent->IsJSPromise() ? GetReferenceAsyncTaskId( 1909 ? GetReferenceAsyncTaskId(
1935 isolate_, Handle<JSPromise>::cast(parent)) 1910 isolate_, Handle<JSPromise>::cast(parent))
1936 : 0); 1911 : 0);
1937 return; 1912 return;
1938 case PromiseHookType::kResolve: 1913 case PromiseHookType::kResolve:
1939 // We can't use this hook because it's called before promise object will 1914 // We can't use this hook because it's called before promise object will
1940 // get resolved status. 1915 // get resolved status.
1941 return; 1916 return;
1942 case PromiseHookType::kBefore: 1917 case PromiseHookType::kBefore:
1943 OnAsyncTaskEvent(debug::kDebugWillHandle, id); 1918 OnAsyncTaskEvent(debug::kDebugWillHandle, id, 0);
1944 return; 1919 return;
1945 case PromiseHookType::kAfter: 1920 case PromiseHookType::kAfter:
1946 OnAsyncTaskEvent(debug::kDebugDidHandle, id); 1921 OnAsyncTaskEvent(debug::kDebugDidHandle, id, 0);
1947 return; 1922 return;
1948 } 1923 }
1949 } 1924 }
1950 1925
1951 int Debug::NextAsyncTaskId(Handle<JSObject> promise) { 1926 int Debug::NextAsyncTaskId(Handle<JSObject> promise) {
1952 LookupIterator it(promise, isolate_->factory()->promise_async_id_symbol()); 1927 LookupIterator it(promise, isolate_->factory()->promise_async_id_symbol());
1953 Maybe<bool> maybe = JSReceiver::HasProperty(&it); 1928 Maybe<bool> maybe = JSReceiver::HasProperty(&it);
1954 if (maybe.ToChecked()) { 1929 if (maybe.ToChecked()) {
1955 MaybeHandle<Object> result = Object::GetProperty(&it); 1930 MaybeHandle<Object> result = Object::GetProperty(&it);
1956 return Handle<Smi>::cast(result.ToHandleChecked())->value(); 1931 return Handle<Smi>::cast(result.ToHandleChecked())->value();
(...skipping 24 matching lines...) Expand all
1981 Script::GetPositionInfo(script, source_position, &info, Script::WITH_OFFSET); 1956 Script::GetPositionInfo(script, source_position, &info, Script::WITH_OFFSET);
1982 return debug::Location(info.line, info.column); 1957 return debug::Location(info.line, info.column);
1983 } 1958 }
1984 } // namespace 1959 } // namespace
1985 1960
1986 bool Debug::IsBlackboxed(Handle<SharedFunctionInfo> shared) { 1961 bool Debug::IsBlackboxed(Handle<SharedFunctionInfo> shared) {
1987 if (!debug_delegate_) return false; 1962 if (!debug_delegate_) return false;
1988 if (!shared->computed_debug_is_blackboxed()) { 1963 if (!shared->computed_debug_is_blackboxed()) {
1989 bool is_blackboxed = false; 1964 bool is_blackboxed = false;
1990 if (shared->script()->IsScript()) { 1965 if (shared->script()->IsScript()) {
1966 SuppressDebug while_processing(this);
1991 HandleScope handle_scope(isolate_); 1967 HandleScope handle_scope(isolate_);
1968 PostponeInterruptsScope no_interrupts(isolate_);
1969 DisableBreak no_recursive_break(this);
1992 Handle<Script> script(Script::cast(shared->script())); 1970 Handle<Script> script(Script::cast(shared->script()));
1993 if (script->type() == i::Script::TYPE_NORMAL) { 1971 if (script->type() == i::Script::TYPE_NORMAL) {
1994 debug::Location start = 1972 debug::Location start =
1995 GetDebugLocation(script, shared->start_position()); 1973 GetDebugLocation(script, shared->start_position());
1996 debug::Location end = GetDebugLocation(script, shared->end_position()); 1974 debug::Location end = GetDebugLocation(script, shared->end_position());
1997 is_blackboxed = debug_delegate_->IsFunctionBlackboxed( 1975 is_blackboxed = debug_delegate_->IsFunctionBlackboxed(
1998 ToApiHandle<debug::Script>(script), start, end); 1976 ToApiHandle<debug::Script>(script), start, end);
1999 } 1977 }
2000 } 1978 }
2001 shared->set_debug_is_blackboxed(is_blackboxed); 1979 shared->set_debug_is_blackboxed(is_blackboxed);
2002 shared->set_computed_debug_is_blackboxed(true); 1980 shared->set_computed_debug_is_blackboxed(true);
2003 } 1981 }
2004 return shared->debug_is_blackboxed(); 1982 return shared->debug_is_blackboxed();
2005 } 1983 }
2006 1984
2007 void Debug::OnAsyncTaskEvent(debug::PromiseDebugActionType type, int id) { 1985 void Debug::OnAsyncTaskEvent(debug::PromiseDebugActionType type, int id,
1986 int parent_id) {
2008 if (in_debug_scope() || ignore_events()) return; 1987 if (in_debug_scope() || ignore_events()) return;
2009 1988 if (!debug_delegate_) return;
2010 if (debug_delegate_) { 1989 SuppressDebug while_processing(this);
2011 debug_delegate_->PromiseEventOccurred(type, id, 0); 1990 DebugScope debug_scope(isolate_->debug());
2012 if (!non_inspector_listener_exists()) return; 1991 if (debug_scope.failed()) return;
2013 }
2014
2015 HandleScope scope(isolate_); 1992 HandleScope scope(isolate_);
2016 DebugScope debug_scope(this); 1993 PostponeInterruptsScope no_interrupts(isolate_);
2017 if (debug_scope.failed()) return; 1994 DisableBreak no_recursive_break(this);
2018 1995 debug_delegate_->PromiseEventOccurred(type, id, parent_id);
2019 // Create the script collected state object.
2020 Handle<Object> event_data;
2021 // Bail out and don't call debugger if exception.
2022 if (!MakeAsyncTaskEvent(handle(Smi::FromInt(type), isolate_),
2023 handle(Smi::FromInt(id), isolate_))
2024 .ToHandle(&event_data))
2025 return;
2026
2027 // Process debug event.
2028 ProcessDebugEvent(v8::AsyncTaskEvent, Handle<JSObject>::cast(event_data));
2029 }
2030
2031 void Debug::ProcessDebugEvent(v8::DebugEvent event,
2032 Handle<JSObject> event_data) {
2033 // Notify registered debug event listener. This can be either a C or
2034 // a JavaScript function.
2035 if (event_listener_.is_null()) return;
2036 HandleScope scope(isolate_);
2037
2038 // Create the execution state.
2039 Handle<Object> exec_state;
2040 // Bail out and don't call debugger if exception.
2041 if (!MakeExecutionState().ToHandle(&exec_state)) return;
2042
2043 // Prevent other interrupts from triggering, for example API callbacks,
2044 // while dispatching event listners.
2045 PostponeInterruptsScope postpone(isolate_);
2046 bool previous = in_debug_event_listener_;
2047 in_debug_event_listener_ = true;
2048 if (event_listener_->IsForeign()) {
2049 // Invoke the C debug event listener.
2050 v8::Debug::EventCallback callback = FUNCTION_CAST<v8::Debug::EventCallback>(
2051 Handle<Foreign>::cast(event_listener_)->foreign_address());
2052 EventDetailsImpl event_details(event, Handle<JSObject>::cast(exec_state),
2053 Handle<JSObject>::cast(event_data),
2054 event_listener_data_);
2055 callback(event_details);
2056 CHECK(!isolate_->has_scheduled_exception());
2057 } else {
2058 // Invoke the JavaScript debug event listener.
2059 DCHECK(event_listener_->IsJSFunction());
2060 Handle<Object> argv[] = { Handle<Object>(Smi::FromInt(event), isolate_),
2061 exec_state,
2062 event_data,
2063 event_listener_data_ };
2064 Handle<JSReceiver> global = isolate_->global_proxy();
2065 MaybeHandle<Object> result =
2066 Execution::Call(isolate_, Handle<JSFunction>::cast(event_listener_),
2067 global, arraysize(argv), argv);
2068 CHECK(!result.is_null()); // Listeners must not throw.
2069 }
2070 in_debug_event_listener_ = previous;
2071 } 1996 }
2072 1997
2073 void Debug::ProcessCompileEvent(v8::DebugEvent event, Handle<Script> script) { 1998 void Debug::ProcessCompileEvent(v8::DebugEvent event, Handle<Script> script) {
2074 if (ignore_events()) return; 1999 if (ignore_events()) return;
2075 if (script->type() != i::Script::TYPE_NORMAL && 2000 if (script->type() != i::Script::TYPE_NORMAL &&
2076 script->type() != i::Script::TYPE_WASM) { 2001 script->type() != i::Script::TYPE_WASM) {
2077 return; 2002 return;
2078 } 2003 }
2004 if (!debug_delegate_) return;
2079 SuppressDebug while_processing(this); 2005 SuppressDebug while_processing(this);
2080 DebugScope debug_scope(this); 2006 DebugScope debug_scope(this);
2081 if (debug_scope.failed()) return; 2007 if (debug_scope.failed()) return;
2082
2083 if (debug_delegate_) {
2084 debug_delegate_->ScriptCompiled(ToApiHandle<debug::Script>(script),
2085 event != v8::AfterCompile);
2086 if (!non_inspector_listener_exists()) return;
2087 }
2088
2089 HandleScope scope(isolate_); 2008 HandleScope scope(isolate_);
2090 // Create the compile state object. 2009 PostponeInterruptsScope postpone(isolate_);
2091 Handle<Object> event_data; 2010 DisableBreak no_recursive_break(this);
2092 // Bail out and don't call debugger if exception. 2011 debug_delegate_->ScriptCompiled(ToApiHandle<debug::Script>(script),
2093 if (!MakeCompileEvent(script, event).ToHandle(&event_data)) return; 2012 event != v8::AfterCompile);
2094
2095 // Process debug event.
2096 ProcessDebugEvent(event, Handle<JSObject>::cast(event_data));
2097 } 2013 }
2098 2014
2099 2015
2100 Handle<Context> Debug::GetDebugContext() { 2016 Handle<Context> Debug::GetDebugContext() {
2101 if (!is_loaded()) return Handle<Context>(); 2017 if (!is_loaded()) return Handle<Context>();
2102 DebugScope debug_scope(this); 2018 DebugScope debug_scope(this);
2103 if (debug_scope.failed()) return Handle<Context>(); 2019 if (debug_scope.failed()) return Handle<Context>();
2104 // The global handle may be destroyed soon after. Return it reboxed. 2020 // The global handle may be destroyed soon after. Return it reboxed.
2105 return handle(*debug_context(), isolate_); 2021 return handle(*debug_context(), isolate_);
2106 } 2022 }
2107 2023
2108
2109 void Debug::SetEventListener(Handle<Object> callback,
2110 Handle<Object> data) {
2111 GlobalHandles* global_handles = isolate_->global_handles();
2112
2113 // Remove existing entry.
2114 GlobalHandles::Destroy(event_listener_.location());
2115 event_listener_ = Handle<Object>();
2116 GlobalHandles::Destroy(event_listener_data_.location());
2117 event_listener_data_ = Handle<Object>();
2118
2119 // Set new entry.
2120 if (!callback->IsNullOrUndefined(isolate_)) {
2121 event_listener_ = global_handles->Create(*callback);
2122 if (data.is_null()) data = isolate_->factory()->undefined_value();
2123 event_listener_data_ = global_handles->Create(*data);
2124 }
2125
2126 UpdateState();
2127 }
2128
2129 int Debug::CurrentFrameCount() { 2024 int Debug::CurrentFrameCount() {
2130 StackTraceFrameIterator it(isolate_); 2025 StackTraceFrameIterator it(isolate_);
2131 if (break_frame_id() != StackFrame::NO_ID) { 2026 if (break_frame_id() != StackFrame::NO_ID) {
2132 // Skip to break frame. 2027 // Skip to break frame.
2133 DCHECK(in_debug_scope()); 2028 DCHECK(in_debug_scope());
2134 while (!it.done() && it.frame()->id() != break_frame_id()) it.Advance(); 2029 while (!it.done() && it.frame()->id() != break_frame_id()) it.Advance();
2135 } 2030 }
2136 int counter = 0; 2031 int counter = 0;
2137 while (!it.done()) { 2032 while (!it.done()) {
2138 if (it.frame()->is_optimized()) { 2033 if (it.frame()->is_optimized()) {
2139 List<SharedFunctionInfo*> infos; 2034 List<SharedFunctionInfo*> infos;
2140 OptimizedFrame::cast(it.frame())->GetFunctions(&infos); 2035 OptimizedFrame::cast(it.frame())->GetFunctions(&infos);
2141 counter += infos.length(); 2036 counter += infos.length();
2142 } else { 2037 } else {
2143 counter++; 2038 counter++;
2144 } 2039 }
2145 it.Advance(); 2040 it.Advance();
2146 } 2041 }
2147 return counter; 2042 return counter;
2148 } 2043 }
2149 2044
2150 void Debug::SetDebugDelegate(debug::DebugDelegate* delegate) { 2045 void Debug::SetDebugDelegate(debug::DebugDelegate* delegate,
2046 bool pass_ownership) {
2047 RemoveDebugDelegate();
2151 debug_delegate_ = delegate; 2048 debug_delegate_ = delegate;
2049 owns_debug_delegate_ = pass_ownership;
2152 UpdateState(); 2050 UpdateState();
2153 } 2051 }
2154 2052
2053 void Debug::RemoveDebugDelegate() {
2054 if (debug_delegate_ == nullptr) return;
2055 if (owns_debug_delegate_) {
2056 owns_debug_delegate_ = false;
2057 delete debug_delegate_;
2058 }
2059 debug_delegate_ = nullptr;
2060 }
2061
2155 void Debug::UpdateState() { 2062 void Debug::UpdateState() {
2156 bool is_active = !event_listener_.is_null() || debug_delegate_ != nullptr; 2063 bool is_active = debug_delegate_ != nullptr;
2157 if (is_active || in_debug_scope()) { 2064 if (is_active || in_debug_scope()) {
2158 // Note that the debug context could have already been loaded to 2065 // Note that the debug context could have already been loaded to
2159 // bootstrap test cases. 2066 // bootstrap test cases.
2160 isolate_->compilation_cache()->Disable(); 2067 isolate_->compilation_cache()->Disable();
2161 is_active = Load(); 2068 is_active = Load();
2162 } else if (is_loaded()) { 2069 } else if (is_loaded()) {
2163 isolate_->compilation_cache()->Enable(); 2070 isolate_->compilation_cache()->Enable();
2164 Unload(); 2071 Unload();
2165 } 2072 }
2166 is_active_ = is_active; 2073 is_active_ = is_active;
(...skipping 184 matching lines...) Expand 10 before | Expand all | Expand 10 after
2351 bool Debug::PerformSideEffectCheckForCallback(Address function) { 2258 bool Debug::PerformSideEffectCheckForCallback(Address function) {
2352 DCHECK(isolate_->needs_side_effect_check()); 2259 DCHECK(isolate_->needs_side_effect_check());
2353 if (DebugEvaluate::CallbackHasNoSideEffect(function)) return true; 2260 if (DebugEvaluate::CallbackHasNoSideEffect(function)) return true;
2354 side_effect_check_failed_ = true; 2261 side_effect_check_failed_ = true;
2355 // Throw an uncatchable termination exception. 2262 // Throw an uncatchable termination exception.
2356 isolate_->TerminateExecution(); 2263 isolate_->TerminateExecution();
2357 isolate_->OptionalRescheduleException(false); 2264 isolate_->OptionalRescheduleException(false);
2358 return false; 2265 return false;
2359 } 2266 }
2360 2267
2268 void LegacyDebugDelegate::PromiseEventOccurred(
2269 v8::debug::PromiseDebugActionType type, int id, int parent_id) {
2270 Handle<Object> event_data;
2271 if (isolate_->debug()->MakeAsyncTaskEvent(type, id).ToHandle(&event_data)) {
2272 ProcessDebugEvent(v8::AsyncTaskEvent, Handle<JSObject>::cast(event_data));
2273 }
2274 }
2275
2276 void LegacyDebugDelegate::ScriptCompiled(v8::Local<v8::debug::Script> script,
2277 bool is_compile_error) {
2278 Handle<Object> event_data;
2279 v8::DebugEvent event = is_compile_error ? v8::CompileError : v8::AfterCompile;
2280 if (isolate_->debug()
2281 ->MakeCompileEvent(v8::Utils::OpenHandle(*script), event)
2282 .ToHandle(&event_data)) {
2283 ProcessDebugEvent(event, Handle<JSObject>::cast(event_data));
2284 }
2285 }
2286
2287 void LegacyDebugDelegate::BreakProgramRequested(
2288 v8::Local<v8::Context> paused_context, v8::Local<v8::Object> exec_state,
2289 v8::Local<v8::Value> break_points_hit) {
2290 Handle<Object> event_data;
2291 if (isolate_->debug()
2292 ->MakeBreakEvent(v8::Utils::OpenHandle(*break_points_hit))
2293 .ToHandle(&event_data)) {
2294 ProcessDebugEvent(
2295 v8::Break, Handle<JSObject>::cast(event_data),
2296 Handle<JSObject>::cast(v8::Utils::OpenHandle(*exec_state)));
2297 }
2298 }
2299
2300 void LegacyDebugDelegate::ExceptionThrown(v8::Local<v8::Context> paused_context,
2301 v8::Local<v8::Object> exec_state,
2302 v8::Local<v8::Value> exception,
2303 v8::Local<v8::Value> promise,
2304 bool is_uncaught) {
2305 Handle<Object> event_data;
2306 if (isolate_->debug()
2307 ->MakeExceptionEvent(v8::Utils::OpenHandle(*exception), is_uncaught,
2308 v8::Utils::OpenHandle(*promise))
2309 .ToHandle(&event_data)) {
2310 ProcessDebugEvent(
2311 v8::Exception, Handle<JSObject>::cast(event_data),
2312 Handle<JSObject>::cast(v8::Utils::OpenHandle(*exec_state)));
2313 }
2314 }
2315
2316 void LegacyDebugDelegate::ProcessDebugEvent(v8::DebugEvent event,
2317 Handle<JSObject> event_data) {
2318 Handle<Object> exec_state;
2319 if (isolate_->debug()->MakeExecutionState().ToHandle(&exec_state)) {
2320 ProcessDebugEvent(event, event_data, Handle<JSObject>::cast(exec_state));
2321 }
2322 }
2323
2324 JavaScriptDebugDelegate::JavaScriptDebugDelegate(Isolate* isolate,
2325 Handle<JSFunction> listener,
2326 Handle<Object> data)
2327 : LegacyDebugDelegate(isolate) {
2328 GlobalHandles* global_handles = isolate->global_handles();
2329 listener_ = Handle<JSFunction>::cast(global_handles->Create(*listener));
2330 data_ = global_handles->Create(*data);
2331 }
2332
2333 JavaScriptDebugDelegate::~JavaScriptDebugDelegate() {
2334 GlobalHandles::Destroy(Handle<Object>::cast(listener_).location());
2335 GlobalHandles::Destroy(data_.location());
2336 }
2337
2338 void JavaScriptDebugDelegate::ProcessDebugEvent(v8::DebugEvent event,
2339 Handle<JSObject> event_data,
2340 Handle<JSObject> exec_state) {
2341 Handle<Object> argv[] = {Handle<Object>(Smi::FromInt(event), isolate_),
2342 exec_state, event_data, data_};
2343 Handle<JSReceiver> global = isolate_->global_proxy();
2344 // Listener must not throw.
2345 Execution::Call(isolate_, listener_, global, arraysize(argv), argv)
2346 .ToHandleChecked();
2347 }
2348
2349 NativeDebugDelegate::NativeDebugDelegate(Isolate* isolate,
2350 v8::Debug::EventCallback callback,
2351 Handle<Object> data)
2352 : LegacyDebugDelegate(isolate), callback_(callback) {
2353 data_ = isolate->global_handles()->Create(*data);
2354 }
2355
2356 NativeDebugDelegate::~NativeDebugDelegate() {
2357 GlobalHandles::Destroy(data_.location());
2358 }
2359
2360 NativeDebugDelegate::EventDetails::EventDetails(DebugEvent event,
2361 Handle<JSObject> exec_state,
2362 Handle<JSObject> event_data,
2363 Handle<Object> callback_data)
2364 : event_(event),
2365 exec_state_(exec_state),
2366 event_data_(event_data),
2367 callback_data_(callback_data) {}
2368
2369 DebugEvent NativeDebugDelegate::EventDetails::GetEvent() const {
2370 return event_;
2371 }
2372
2373 v8::Local<v8::Object> NativeDebugDelegate::EventDetails::GetExecutionState()
2374 const {
2375 return v8::Utils::ToLocal(exec_state_);
2376 }
2377
2378 v8::Local<v8::Object> NativeDebugDelegate::EventDetails::GetEventData() const {
2379 return v8::Utils::ToLocal(event_data_);
2380 }
2381
2382 v8::Local<v8::Context> NativeDebugDelegate::EventDetails::GetEventContext()
2383 const {
2384 return GetDebugEventContext(exec_state_->GetIsolate());
2385 }
2386
2387 v8::Local<v8::Value> NativeDebugDelegate::EventDetails::GetCallbackData()
2388 const {
2389 return v8::Utils::ToLocal(callback_data_);
2390 }
2391
2392 v8::Isolate* NativeDebugDelegate::EventDetails::GetIsolate() const {
2393 return reinterpret_cast<v8::Isolate*>(exec_state_->GetIsolate());
2394 }
2395
2396 void NativeDebugDelegate::ProcessDebugEvent(v8::DebugEvent event,
2397 Handle<JSObject> event_data,
2398 Handle<JSObject> exec_state) {
2399 EventDetails event_details(event, exec_state, event_data, data_);
2400 Isolate* isolate = isolate_;
2401 callback_(event_details);
2402 CHECK(!isolate->has_scheduled_exception());
2403 }
2404
2361 NoSideEffectScope::~NoSideEffectScope() { 2405 NoSideEffectScope::~NoSideEffectScope() {
2362 if (isolate_->needs_side_effect_check() && 2406 if (isolate_->needs_side_effect_check() &&
2363 isolate_->debug()->side_effect_check_failed_) { 2407 isolate_->debug()->side_effect_check_failed_) {
2364 DCHECK(isolate_->has_pending_exception()); 2408 DCHECK(isolate_->has_pending_exception());
2365 DCHECK_EQ(isolate_->heap()->termination_exception(), 2409 DCHECK_EQ(isolate_->heap()->termination_exception(),
2366 isolate_->pending_exception()); 2410 isolate_->pending_exception());
2367 // Convert the termination exception into a regular exception. 2411 // Convert the termination exception into a regular exception.
2368 isolate_->CancelTerminateExecution(); 2412 isolate_->CancelTerminateExecution();
2369 isolate_->Throw(*isolate_->factory()->NewEvalError( 2413 isolate_->Throw(*isolate_->factory()->NewEvalError(
2370 MessageTemplate::kNoSideEffectDebugEvaluate)); 2414 MessageTemplate::kNoSideEffectDebugEvaluate));
2371 } 2415 }
2372 isolate_->set_needs_side_effect_check(old_needs_side_effect_check_); 2416 isolate_->set_needs_side_effect_check(old_needs_side_effect_check_);
2373 isolate_->debug()->UpdateHookOnFunctionCall(); 2417 isolate_->debug()->UpdateHookOnFunctionCall();
2374 isolate_->debug()->side_effect_check_failed_ = false; 2418 isolate_->debug()->side_effect_check_failed_ = false;
2375 } 2419 }
2376 2420
2377 EventDetailsImpl::EventDetailsImpl(DebugEvent event,
2378 Handle<JSObject> exec_state,
2379 Handle<JSObject> event_data,
2380 Handle<Object> callback_data)
2381 : event_(event),
2382 exec_state_(exec_state),
2383 event_data_(event_data),
2384 callback_data_(callback_data) {}
2385
2386 DebugEvent EventDetailsImpl::GetEvent() const {
2387 return event_;
2388 }
2389
2390
2391 v8::Local<v8::Object> EventDetailsImpl::GetExecutionState() const {
2392 return v8::Utils::ToLocal(exec_state_);
2393 }
2394
2395
2396 v8::Local<v8::Object> EventDetailsImpl::GetEventData() const {
2397 return v8::Utils::ToLocal(event_data_);
2398 }
2399
2400
2401 v8::Local<v8::Context> EventDetailsImpl::GetEventContext() const {
2402 return GetDebugEventContext(exec_state_->GetIsolate());
2403 }
2404
2405
2406 v8::Local<v8::Value> EventDetailsImpl::GetCallbackData() const {
2407 return v8::Utils::ToLocal(callback_data_);
2408 }
2409
2410
2411 v8::Isolate* EventDetailsImpl::GetIsolate() const {
2412 return reinterpret_cast<v8::Isolate*>(exec_state_->GetIsolate());
2413 }
2414
2415 } // namespace internal 2421 } // namespace internal
2416 } // namespace v8 2422 } // 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