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 20 matching lines...) Expand all Loading... | |
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 Loading... | |
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 Loading... | |
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 81 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
1766 } | 1765 } |
1767 // Bail out if exception breaks are not active | 1766 // Bail out if exception breaks are not active |
1768 if (uncaught) { | 1767 if (uncaught) { |
1769 // Uncaught exceptions are reported by either flags. | 1768 // Uncaught exceptions are reported by either flags. |
1770 if (!(break_on_uncaught_exception_ || break_on_exception_)) return; | 1769 if (!(break_on_uncaught_exception_ || break_on_exception_)) return; |
1771 } else { | 1770 } else { |
1772 // Caught exceptions are reported is activated. | 1771 // Caught exceptions are reported is activated. |
1773 if (!break_on_exception_) return; | 1772 if (!break_on_exception_) return; |
1774 } | 1773 } |
1775 | 1774 |
1776 bool empty_js_stack = false; | |
1777 { | 1775 { |
1778 JavaScriptFrameIterator it(isolate_); | 1776 JavaScriptFrameIterator it(isolate_); |
1779 // Check whether the top frame is blackboxed or the break location is muted. | 1777 // Check whether the top frame is blackboxed or the break location is muted. |
1780 if (!it.done() && (IsMutedAtCurrentLocation(it.frame()) || | 1778 if (!it.done() && (IsMutedAtCurrentLocation(it.frame()) || |
1781 IsExceptionBlackboxed(uncaught))) { | 1779 IsExceptionBlackboxed(uncaught))) { |
1782 return; | 1780 return; |
1783 } | 1781 } |
1784 empty_js_stack = it.done(); | 1782 if (it.done()) return; // Do not trigger an event with an empty stack. |
jgruber
2017/02/09 10:33:28
Is there corresponding code in inspector that we c
Yang
2017/02/09 11:24:11
As explained offline, this is not new. Alexey alre
| |
1785 } | 1783 } |
1786 | 1784 |
1785 if (!debug_delegate_) return; | |
jgruber
2017/02/09 10:33:28
Would it make sense to move this to the very top o
Yang
2017/02/09 11:24:11
Good idea. I did not move up above the side effect
| |
1787 DebugScope debug_scope(this); | 1786 DebugScope debug_scope(this); |
1788 if (debug_scope.failed()) return; | 1787 if (debug_scope.failed()) return; |
1788 HandleScope scope(isolate_); | |
1789 PostponeInterruptsScope postpone(isolate_); | |
1790 DisableBreak no_recursive_break(this); | |
1789 | 1791 |
1790 if (debug_delegate_ && !empty_js_stack) { | 1792 // Create the execution state. |
1791 HandleScope scope(isolate_); | 1793 Handle<Object> exec_state; |
1794 // Bail out and don't call debugger if exception. | |
1795 if (!MakeExecutionState().ToHandle(&exec_state)) return; | |
1792 | 1796 |
1793 // Create the execution state. | 1797 debug_delegate_->ExceptionThrown( |
1794 Handle<Object> exec_state; | 1798 GetDebugEventContext(isolate_), |
1795 // Bail out and don't call debugger if exception. | 1799 v8::Utils::ToLocal(Handle<JSObject>::cast(exec_state)), |
1796 if (!MakeExecutionState().ToHandle(&exec_state)) return; | 1800 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 } | 1801 } |
1817 | 1802 |
1818 void Debug::OnDebugBreak(Handle<Object> break_points_hit) { | 1803 void Debug::OnDebugBreak(Handle<Object> break_points_hit) { |
1819 // The caller provided for DebugScope. | 1804 // The caller provided for DebugScope. |
1820 AssertDebugContext(); | 1805 AssertDebugContext(); |
1821 // Bail out if there is no listener for this event | 1806 // Bail out if there is no listener for this event |
1822 if (ignore_events()) return; | 1807 if (ignore_events()) return; |
1823 | 1808 |
1824 #ifdef DEBUG | 1809 #ifdef DEBUG |
1825 PrintBreakLocation(); | 1810 PrintBreakLocation(); |
1826 #endif // DEBUG | 1811 #endif // DEBUG |
1827 | 1812 |
1828 if (debug_delegate_) { | 1813 if (!debug_delegate_) return; |
1829 HandleScope scope(isolate_); | 1814 HandleScope scope(isolate_); |
1815 PostponeInterruptsScope no_interrupts(isolate_); | |
1816 DisableBreak no_recursive_break(this); | |
1830 | 1817 |
1831 // Create the execution state. | 1818 // Create the execution state. |
1832 Handle<Object> exec_state; | 1819 Handle<Object> exec_state; |
1833 // Bail out and don't call debugger if exception. | 1820 // Bail out and don't call debugger if exception. |
1834 if (!MakeExecutionState().ToHandle(&exec_state)) return; | 1821 if (!MakeExecutionState().ToHandle(&exec_state)) return; |
1835 | 1822 |
1836 bool previous = in_debug_event_listener_; | 1823 debug_delegate_->BreakProgramRequested( |
1837 in_debug_event_listener_ = true; | 1824 GetDebugEventContext(isolate_), |
1838 debug_delegate_->BreakProgramRequested( | 1825 v8::Utils::ToLocal(Handle<JSObject>::cast(exec_state)), |
1839 GetDebugEventContext(isolate_), | 1826 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 } | 1827 } |
1855 | 1828 |
1856 | 1829 |
1857 void Debug::OnCompileError(Handle<Script> script) { | 1830 void Debug::OnCompileError(Handle<Script> script) { |
1858 ProcessCompileEvent(v8::CompileError, script); | 1831 ProcessCompileEvent(v8::CompileError, script); |
1859 } | 1832 } |
1860 | 1833 |
1861 | 1834 |
1862 // Handle debugger actions when a new script is compiled. | 1835 // Handle debugger actions when a new script is compiled. |
1863 void Debug::OnAfterCompile(Handle<Script> script) { | 1836 void Debug::OnAfterCompile(Handle<Script> script) { |
(...skipping 10 matching lines...) Expand all Loading... | |
1874 CollectedCallbackData(Object** location, int id, Debug* debug, | 1847 CollectedCallbackData(Object** location, int id, Debug* debug, |
1875 Isolate* isolate) | 1848 Isolate* isolate) |
1876 : location(location), id(id), debug(debug), isolate(isolate) {} | 1849 : location(location), id(id), debug(debug), isolate(isolate) {} |
1877 }; | 1850 }; |
1878 | 1851 |
1879 void SendAsyncTaskEventCancel(const v8::WeakCallbackInfo<void>& info) { | 1852 void SendAsyncTaskEventCancel(const v8::WeakCallbackInfo<void>& info) { |
1880 std::unique_ptr<CollectedCallbackData> data( | 1853 std::unique_ptr<CollectedCallbackData> data( |
1881 reinterpret_cast<CollectedCallbackData*>(info.GetParameter())); | 1854 reinterpret_cast<CollectedCallbackData*>(info.GetParameter())); |
1882 if (!data->debug->is_active()) return; | 1855 if (!data->debug->is_active()) return; |
1883 HandleScope scope(data->isolate); | 1856 HandleScope scope(data->isolate); |
1884 data->debug->OnAsyncTaskEvent(debug::kDebugPromiseCollected, data->id); | 1857 data->debug->OnAsyncTaskEvent(debug::kDebugPromiseCollected, data->id, 0); |
1885 } | 1858 } |
1886 | 1859 |
1887 void ResetPromiseHandle(const v8::WeakCallbackInfo<void>& info) { | 1860 void ResetPromiseHandle(const v8::WeakCallbackInfo<void>& info) { |
1888 CollectedCallbackData* data = | 1861 CollectedCallbackData* data = |
1889 reinterpret_cast<CollectedCallbackData*>(info.GetParameter()); | 1862 reinterpret_cast<CollectedCallbackData*>(info.GetParameter()); |
1890 GlobalHandles::Destroy(data->location); | 1863 GlobalHandles::Destroy(data->location); |
1891 info.SetSecondPassCallback(&SendAsyncTaskEventCancel); | 1864 info.SetSecondPassCallback(&SendAsyncTaskEventCancel); |
1892 } | 1865 } |
1893 | 1866 |
1894 // In an async function, reuse the existing stack related to the outer | 1867 // In an async function, reuse the existing stack related to the outer |
(...skipping 27 matching lines...) Expand all Loading... | |
1922 return Handle<Smi>::cast(async_task_id)->value(); | 1895 return Handle<Smi>::cast(async_task_id)->value(); |
1923 } | 1896 } |
1924 } // namespace | 1897 } // namespace |
1925 | 1898 |
1926 void Debug::RunPromiseHook(PromiseHookType type, Handle<JSPromise> promise, | 1899 void Debug::RunPromiseHook(PromiseHookType type, Handle<JSPromise> promise, |
1927 Handle<Object> parent) { | 1900 Handle<Object> parent) { |
1928 if (!debug_delegate_) return; | 1901 if (!debug_delegate_) return; |
1929 int id = GetReferenceAsyncTaskId(isolate_, promise); | 1902 int id = GetReferenceAsyncTaskId(isolate_, promise); |
1930 switch (type) { | 1903 switch (type) { |
1931 case PromiseHookType::kInit: | 1904 case PromiseHookType::kInit: |
1932 debug_delegate_->PromiseEventOccurred( | 1905 OnAsyncTaskEvent(debug::kDebugPromiseCreated, id, |
1933 debug::kDebugPromiseCreated, id, | 1906 parent->IsJSPromise() |
1934 parent->IsJSPromise() ? GetReferenceAsyncTaskId( | 1907 ? GetReferenceAsyncTaskId( |
1935 isolate_, Handle<JSPromise>::cast(parent)) | 1908 isolate_, Handle<JSPromise>::cast(parent)) |
1936 : 0); | 1909 : 0); |
1937 return; | 1910 return; |
1938 case PromiseHookType::kResolve: | 1911 case PromiseHookType::kResolve: |
1939 // We can't use this hook because it's called before promise object will | 1912 // We can't use this hook because it's called before promise object will |
1940 // get resolved status. | 1913 // get resolved status. |
1941 return; | 1914 return; |
1942 case PromiseHookType::kBefore: | 1915 case PromiseHookType::kBefore: |
1943 OnAsyncTaskEvent(debug::kDebugWillHandle, id); | 1916 OnAsyncTaskEvent(debug::kDebugWillHandle, id, 0); |
1944 return; | 1917 return; |
1945 case PromiseHookType::kAfter: | 1918 case PromiseHookType::kAfter: |
1946 OnAsyncTaskEvent(debug::kDebugDidHandle, id); | 1919 OnAsyncTaskEvent(debug::kDebugDidHandle, id, 0); |
1947 return; | 1920 return; |
1948 } | 1921 } |
1949 } | 1922 } |
1950 | 1923 |
1951 int Debug::NextAsyncTaskId(Handle<JSObject> promise) { | 1924 int Debug::NextAsyncTaskId(Handle<JSObject> promise) { |
1952 LookupIterator it(promise, isolate_->factory()->promise_async_id_symbol()); | 1925 LookupIterator it(promise, isolate_->factory()->promise_async_id_symbol()); |
1953 Maybe<bool> maybe = JSReceiver::HasProperty(&it); | 1926 Maybe<bool> maybe = JSReceiver::HasProperty(&it); |
1954 if (maybe.ToChecked()) { | 1927 if (maybe.ToChecked()) { |
1955 MaybeHandle<Object> result = Object::GetProperty(&it); | 1928 MaybeHandle<Object> result = Object::GetProperty(&it); |
1956 return Handle<Smi>::cast(result.ToHandleChecked())->value(); | 1929 return Handle<Smi>::cast(result.ToHandleChecked())->value(); |
(...skipping 24 matching lines...) Expand all Loading... | |
1981 Script::GetPositionInfo(script, source_position, &info, Script::WITH_OFFSET); | 1954 Script::GetPositionInfo(script, source_position, &info, Script::WITH_OFFSET); |
1982 return debug::Location(info.line, info.column); | 1955 return debug::Location(info.line, info.column); |
1983 } | 1956 } |
1984 } // namespace | 1957 } // namespace |
1985 | 1958 |
1986 bool Debug::IsBlackboxed(Handle<SharedFunctionInfo> shared) { | 1959 bool Debug::IsBlackboxed(Handle<SharedFunctionInfo> shared) { |
1987 if (!debug_delegate_) return false; | 1960 if (!debug_delegate_) return false; |
1988 if (!shared->computed_debug_is_blackboxed()) { | 1961 if (!shared->computed_debug_is_blackboxed()) { |
1989 bool is_blackboxed = false; | 1962 bool is_blackboxed = false; |
1990 if (shared->script()->IsScript()) { | 1963 if (shared->script()->IsScript()) { |
1964 SuppressDebug while_processing(this); | |
1991 HandleScope handle_scope(isolate_); | 1965 HandleScope handle_scope(isolate_); |
1966 PostponeInterruptsScope no_interrupts(isolate_); | |
1967 DisableBreak no_recursive_break(this); | |
1992 Handle<Script> script(Script::cast(shared->script())); | 1968 Handle<Script> script(Script::cast(shared->script())); |
1993 if (script->type() == i::Script::TYPE_NORMAL) { | 1969 if (script->type() == i::Script::TYPE_NORMAL) { |
1994 debug::Location start = | 1970 debug::Location start = |
1995 GetDebugLocation(script, shared->start_position()); | 1971 GetDebugLocation(script, shared->start_position()); |
1996 debug::Location end = GetDebugLocation(script, shared->end_position()); | 1972 debug::Location end = GetDebugLocation(script, shared->end_position()); |
1997 is_blackboxed = debug_delegate_->IsFunctionBlackboxed( | 1973 is_blackboxed = debug_delegate_->IsFunctionBlackboxed( |
1998 ToApiHandle<debug::Script>(script), start, end); | 1974 ToApiHandle<debug::Script>(script), start, end); |
1999 } | 1975 } |
2000 } | 1976 } |
2001 shared->set_debug_is_blackboxed(is_blackboxed); | 1977 shared->set_debug_is_blackboxed(is_blackboxed); |
2002 shared->set_computed_debug_is_blackboxed(true); | 1978 shared->set_computed_debug_is_blackboxed(true); |
2003 } | 1979 } |
2004 return shared->debug_is_blackboxed(); | 1980 return shared->debug_is_blackboxed(); |
2005 } | 1981 } |
2006 | 1982 |
2007 void Debug::OnAsyncTaskEvent(debug::PromiseDebugActionType type, int id) { | 1983 void Debug::OnAsyncTaskEvent(debug::PromiseDebugActionType type, int id, |
1984 int parent_id) { | |
2008 if (in_debug_scope() || ignore_events()) return; | 1985 if (in_debug_scope() || ignore_events()) return; |
2009 | 1986 if (!debug_delegate_) return; |
2010 if (debug_delegate_) { | 1987 SuppressDebug while_processing(this); |
2011 debug_delegate_->PromiseEventOccurred(type, id, 0); | 1988 DebugScope debug_scope(isolate_->debug()); |
2012 if (!non_inspector_listener_exists()) return; | 1989 if (debug_scope.failed()) return; |
2013 } | |
2014 | |
2015 HandleScope scope(isolate_); | 1990 HandleScope scope(isolate_); |
2016 DebugScope debug_scope(this); | 1991 PostponeInterruptsScope no_interrupts(isolate_); |
2017 if (debug_scope.failed()) return; | 1992 DisableBreak no_recursive_break(this); |
2018 | 1993 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 } | 1994 } |
2072 | 1995 |
2073 void Debug::ProcessCompileEvent(v8::DebugEvent event, Handle<Script> script) { | 1996 void Debug::ProcessCompileEvent(v8::DebugEvent event, Handle<Script> script) { |
2074 if (ignore_events()) return; | 1997 if (ignore_events()) return; |
2075 if (script->type() != i::Script::TYPE_NORMAL && | 1998 if (script->type() != i::Script::TYPE_NORMAL && |
2076 script->type() != i::Script::TYPE_WASM) { | 1999 script->type() != i::Script::TYPE_WASM) { |
2077 return; | 2000 return; |
2078 } | 2001 } |
2002 if (!debug_delegate_) return; | |
2079 SuppressDebug while_processing(this); | 2003 SuppressDebug while_processing(this); |
2080 DebugScope debug_scope(this); | 2004 DebugScope debug_scope(this); |
2081 if (debug_scope.failed()) return; | 2005 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_); | 2006 HandleScope scope(isolate_); |
2090 // Create the compile state object. | 2007 PostponeInterruptsScope postpone(isolate_); |
2091 Handle<Object> event_data; | 2008 DisableBreak no_recursive_break(this); |
2092 // Bail out and don't call debugger if exception. | 2009 debug_delegate_->ScriptCompiled(ToApiHandle<debug::Script>(script), |
2093 if (!MakeCompileEvent(script, event).ToHandle(&event_data)) return; | 2010 event != v8::AfterCompile); |
2094 | |
2095 // Process debug event. | |
2096 ProcessDebugEvent(event, Handle<JSObject>::cast(event_data)); | |
2097 } | 2011 } |
2098 | 2012 |
2099 | 2013 |
2100 Handle<Context> Debug::GetDebugContext() { | 2014 Handle<Context> Debug::GetDebugContext() { |
2101 if (!is_loaded()) return Handle<Context>(); | 2015 if (!is_loaded()) return Handle<Context>(); |
2102 DebugScope debug_scope(this); | 2016 DebugScope debug_scope(this); |
2103 if (debug_scope.failed()) return Handle<Context>(); | 2017 if (debug_scope.failed()) return Handle<Context>(); |
2104 // The global handle may be destroyed soon after. Return it reboxed. | 2018 // The global handle may be destroyed soon after. Return it reboxed. |
2105 return handle(*debug_context(), isolate_); | 2019 return handle(*debug_context(), isolate_); |
2106 } | 2020 } |
2107 | 2021 |
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() { | 2022 int Debug::CurrentFrameCount() { |
2130 StackTraceFrameIterator it(isolate_); | 2023 StackTraceFrameIterator it(isolate_); |
2131 if (break_frame_id() != StackFrame::NO_ID) { | 2024 if (break_frame_id() != StackFrame::NO_ID) { |
2132 // Skip to break frame. | 2025 // Skip to break frame. |
2133 DCHECK(in_debug_scope()); | 2026 DCHECK(in_debug_scope()); |
2134 while (!it.done() && it.frame()->id() != break_frame_id()) it.Advance(); | 2027 while (!it.done() && it.frame()->id() != break_frame_id()) it.Advance(); |
2135 } | 2028 } |
2136 int counter = 0; | 2029 int counter = 0; |
2137 while (!it.done()) { | 2030 while (!it.done()) { |
2138 if (it.frame()->is_optimized()) { | 2031 if (it.frame()->is_optimized()) { |
2139 List<SharedFunctionInfo*> infos; | 2032 List<SharedFunctionInfo*> infos; |
2140 OptimizedFrame::cast(it.frame())->GetFunctions(&infos); | 2033 OptimizedFrame::cast(it.frame())->GetFunctions(&infos); |
2141 counter += infos.length(); | 2034 counter += infos.length(); |
2142 } else { | 2035 } else { |
2143 counter++; | 2036 counter++; |
2144 } | 2037 } |
2145 it.Advance(); | 2038 it.Advance(); |
2146 } | 2039 } |
2147 return counter; | 2040 return counter; |
2148 } | 2041 } |
2149 | 2042 |
2150 void Debug::SetDebugDelegate(debug::DebugDelegate* delegate) { | 2043 void Debug::SetDebugDelegate(debug::DebugDelegate* delegate, |
2044 bool pass_ownership) { | |
2045 RemoveDebugDelegate(); | |
2151 debug_delegate_ = delegate; | 2046 debug_delegate_ = delegate; |
2047 owns_debug_delegate_ = pass_ownership; | |
2152 UpdateState(); | 2048 UpdateState(); |
2153 } | 2049 } |
2154 | 2050 |
2051 void Debug::RemoveDebugDelegate() { | |
2052 if (debug_delegate_ == nullptr) return; | |
2053 if (owns_debug_delegate_) { | |
2054 owns_debug_delegate_ = false; | |
2055 delete debug_delegate_; | |
2056 } | |
2057 debug_delegate_ = nullptr; | |
2058 } | |
2059 | |
2155 void Debug::UpdateState() { | 2060 void Debug::UpdateState() { |
2156 bool is_active = !event_listener_.is_null() || debug_delegate_ != nullptr; | 2061 bool is_active = debug_delegate_ != nullptr; |
2157 if (is_active || in_debug_scope()) { | 2062 if (is_active || in_debug_scope()) { |
2158 // Note that the debug context could have already been loaded to | 2063 // Note that the debug context could have already been loaded to |
2159 // bootstrap test cases. | 2064 // bootstrap test cases. |
2160 isolate_->compilation_cache()->Disable(); | 2065 isolate_->compilation_cache()->Disable(); |
2161 is_active = Load(); | 2066 is_active = Load(); |
2162 } else if (is_loaded()) { | 2067 } else if (is_loaded()) { |
2163 isolate_->compilation_cache()->Enable(); | 2068 isolate_->compilation_cache()->Enable(); |
2164 Unload(); | 2069 Unload(); |
2165 } | 2070 } |
2166 is_active_ = is_active; | 2071 is_active_ = is_active; |
(...skipping 184 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
2351 bool Debug::PerformSideEffectCheckForCallback(Address function) { | 2256 bool Debug::PerformSideEffectCheckForCallback(Address function) { |
2352 DCHECK(isolate_->needs_side_effect_check()); | 2257 DCHECK(isolate_->needs_side_effect_check()); |
2353 if (DebugEvaluate::CallbackHasNoSideEffect(function)) return true; | 2258 if (DebugEvaluate::CallbackHasNoSideEffect(function)) return true; |
2354 side_effect_check_failed_ = true; | 2259 side_effect_check_failed_ = true; |
2355 // Throw an uncatchable termination exception. | 2260 // Throw an uncatchable termination exception. |
2356 isolate_->TerminateExecution(); | 2261 isolate_->TerminateExecution(); |
2357 isolate_->OptionalRescheduleException(false); | 2262 isolate_->OptionalRescheduleException(false); |
2358 return false; | 2263 return false; |
2359 } | 2264 } |
2360 | 2265 |
2266 void LegacyDebugDelegate::PromiseEventOccurred( | |
2267 v8::debug::PromiseDebugActionType type, int id, int parent_id) { | |
2268 Handle<Object> event_data; | |
2269 if (isolate_->debug()->MakeAsyncTaskEvent(type, id).ToHandle(&event_data)) { | |
2270 ProcessDebugEvent(v8::AsyncTaskEvent, Handle<JSObject>::cast(event_data)); | |
2271 } | |
2272 } | |
2273 | |
2274 void LegacyDebugDelegate::ScriptCompiled(v8::Local<v8::debug::Script> script, | |
2275 bool is_compile_error) { | |
2276 Handle<Object> event_data; | |
2277 v8::DebugEvent event = is_compile_error ? v8::CompileError : v8::AfterCompile; | |
2278 if (isolate_->debug() | |
2279 ->MakeCompileEvent(v8::Utils::OpenHandle(*script), event) | |
2280 .ToHandle(&event_data)) { | |
2281 ProcessDebugEvent(event, Handle<JSObject>::cast(event_data)); | |
2282 } | |
2283 } | |
2284 | |
2285 void LegacyDebugDelegate::BreakProgramRequested( | |
2286 v8::Local<v8::Context> paused_context, v8::Local<v8::Object> exec_state, | |
2287 v8::Local<v8::Value> break_points_hit) { | |
2288 Handle<Object> event_data; | |
2289 if (isolate_->debug() | |
2290 ->MakeBreakEvent(v8::Utils::OpenHandle(*break_points_hit)) | |
2291 .ToHandle(&event_data)) { | |
2292 ProcessDebugEvent( | |
2293 v8::Break, Handle<JSObject>::cast(event_data), | |
2294 Handle<JSObject>::cast(v8::Utils::OpenHandle(*exec_state))); | |
2295 } | |
2296 } | |
2297 | |
2298 void LegacyDebugDelegate::ExceptionThrown(v8::Local<v8::Context> paused_context, | |
2299 v8::Local<v8::Object> exec_state, | |
2300 v8::Local<v8::Value> exception, | |
2301 v8::Local<v8::Value> promise, | |
2302 bool is_uncaught) { | |
2303 Handle<Object> event_data; | |
2304 if (isolate_->debug() | |
2305 ->MakeExceptionEvent(v8::Utils::OpenHandle(*exception), is_uncaught, | |
2306 v8::Utils::OpenHandle(*promise)) | |
2307 .ToHandle(&event_data)) { | |
2308 ProcessDebugEvent( | |
2309 v8::Exception, Handle<JSObject>::cast(event_data), | |
2310 Handle<JSObject>::cast(v8::Utils::OpenHandle(*exec_state))); | |
2311 } | |
2312 } | |
2313 | |
2314 void LegacyDebugDelegate::ProcessDebugEvent(v8::DebugEvent event, | |
2315 Handle<JSObject> event_data) { | |
2316 Handle<Object> exec_state; | |
2317 if (isolate_->debug()->MakeExecutionState().ToHandle(&exec_state)) { | |
2318 ProcessDebugEvent(event, event_data, Handle<JSObject>::cast(exec_state)); | |
2319 } | |
2320 } | |
2321 | |
2322 JavaScriptDebugDelegate::JavaScriptDebugDelegate(Isolate* isolate, | |
2323 Handle<JSFunction> listener, | |
2324 Handle<Object> data) | |
2325 : LegacyDebugDelegate(isolate) { | |
2326 GlobalHandles* global_handles = isolate->global_handles(); | |
2327 listener_ = Handle<JSFunction>::cast(global_handles->Create(*listener)); | |
2328 data_ = global_handles->Create(*data); | |
2329 } | |
2330 | |
2331 JavaScriptDebugDelegate::~JavaScriptDebugDelegate() { | |
2332 GlobalHandles::Destroy(Handle<Object>::cast(listener_).location()); | |
2333 GlobalHandles::Destroy(data_.location()); | |
2334 } | |
2335 | |
2336 void JavaScriptDebugDelegate::ProcessDebugEvent(v8::DebugEvent event, | |
2337 Handle<JSObject> event_data, | |
2338 Handle<JSObject> exec_state) { | |
2339 Handle<Object> argv[] = {Handle<Object>(Smi::FromInt(event), isolate_), | |
2340 exec_state, event_data, data_}; | |
2341 Handle<JSReceiver> global = isolate_->global_proxy(); | |
2342 // Listener must not throw. | |
2343 Execution::Call(isolate_, Handle<JSFunction>::cast(listener_), global, | |
jgruber
2017/02/09 10:33:28
Nit: the JSFunction cast is already done in the co
Yang
2017/02/09 11:24:11
Done.
| |
2344 arraysize(argv), argv) | |
2345 .ToHandleChecked(); | |
2346 } | |
2347 | |
2348 NativeDebugDelegate::NativeDebugDelegate(Isolate* isolate, | |
2349 v8::Debug::EventCallback callback, | |
2350 Handle<Object> data) | |
2351 : LegacyDebugDelegate(isolate), callback_(callback) { | |
2352 data_ = isolate->global_handles()->Create(*data); | |
2353 } | |
2354 | |
2355 NativeDebugDelegate::~NativeDebugDelegate() { | |
2356 GlobalHandles::Destroy(data_.location()); | |
2357 } | |
2358 | |
2359 NativeDebugDelegate::EventDetails::EventDetails(DebugEvent event, | |
2360 Handle<JSObject> exec_state, | |
2361 Handle<JSObject> event_data, | |
2362 Handle<Object> callback_data) | |
2363 : event_(event), | |
2364 exec_state_(exec_state), | |
2365 event_data_(event_data), | |
2366 callback_data_(callback_data) {} | |
2367 | |
2368 DebugEvent NativeDebugDelegate::EventDetails::GetEvent() const { | |
2369 return event_; | |
2370 } | |
2371 | |
2372 v8::Local<v8::Object> NativeDebugDelegate::EventDetails::GetExecutionState() | |
2373 const { | |
2374 return v8::Utils::ToLocal(exec_state_); | |
2375 } | |
2376 | |
2377 v8::Local<v8::Object> NativeDebugDelegate::EventDetails::GetEventData() const { | |
2378 return v8::Utils::ToLocal(event_data_); | |
2379 } | |
2380 | |
2381 v8::Local<v8::Context> NativeDebugDelegate::EventDetails::GetEventContext() | |
2382 const { | |
2383 return GetDebugEventContext(exec_state_->GetIsolate()); | |
2384 } | |
2385 | |
2386 v8::Local<v8::Value> NativeDebugDelegate::EventDetails::GetCallbackData() | |
2387 const { | |
2388 return v8::Utils::ToLocal(callback_data_); | |
2389 } | |
2390 | |
2391 v8::Isolate* NativeDebugDelegate::EventDetails::GetIsolate() const { | |
2392 return reinterpret_cast<v8::Isolate*>(exec_state_->GetIsolate()); | |
2393 } | |
2394 | |
2395 void NativeDebugDelegate::ProcessDebugEvent(v8::DebugEvent event, | |
2396 Handle<JSObject> event_data, | |
2397 Handle<JSObject> exec_state) { | |
2398 EventDetails event_details(event, exec_state, event_data, data_); | |
2399 Isolate* isolate = isolate_; | |
2400 callback_(event_details); | |
2401 CHECK(!isolate->has_scheduled_exception()); | |
2402 } | |
2403 | |
2361 NoSideEffectScope::~NoSideEffectScope() { | 2404 NoSideEffectScope::~NoSideEffectScope() { |
2362 if (isolate_->needs_side_effect_check() && | 2405 if (isolate_->needs_side_effect_check() && |
2363 isolate_->debug()->side_effect_check_failed_) { | 2406 isolate_->debug()->side_effect_check_failed_) { |
2364 DCHECK(isolate_->has_pending_exception()); | 2407 DCHECK(isolate_->has_pending_exception()); |
2365 DCHECK_EQ(isolate_->heap()->termination_exception(), | 2408 DCHECK_EQ(isolate_->heap()->termination_exception(), |
2366 isolate_->pending_exception()); | 2409 isolate_->pending_exception()); |
2367 // Convert the termination exception into a regular exception. | 2410 // Convert the termination exception into a regular exception. |
2368 isolate_->CancelTerminateExecution(); | 2411 isolate_->CancelTerminateExecution(); |
2369 isolate_->Throw(*isolate_->factory()->NewEvalError( | 2412 isolate_->Throw(*isolate_->factory()->NewEvalError( |
2370 MessageTemplate::kNoSideEffectDebugEvaluate)); | 2413 MessageTemplate::kNoSideEffectDebugEvaluate)); |
2371 } | 2414 } |
2372 isolate_->set_needs_side_effect_check(old_needs_side_effect_check_); | 2415 isolate_->set_needs_side_effect_check(old_needs_side_effect_check_); |
2373 isolate_->debug()->UpdateHookOnFunctionCall(); | 2416 isolate_->debug()->UpdateHookOnFunctionCall(); |
2374 isolate_->debug()->side_effect_check_failed_ = false; | 2417 isolate_->debug()->side_effect_check_failed_ = false; |
2375 } | 2418 } |
2376 | 2419 |
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 | 2420 } // namespace internal |
2416 } // namespace v8 | 2421 } // namespace v8 |
OLD | NEW |