OLD | NEW |
1 // Copyright 2016 the V8 project authors. All rights reserved. | 1 // Copyright 2016 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/inspector/v8-debugger.h" | 5 #include "src/inspector/v8-debugger.h" |
6 | 6 |
7 #include "src/inspector/debugger-script.h" | 7 #include "src/inspector/debugger-script.h" |
8 #include "src/inspector/inspected-context.h" | 8 #include "src/inspector/inspected-context.h" |
9 #include "src/inspector/protocol/Protocol.h" | 9 #include "src/inspector/protocol/Protocol.h" |
10 #include "src/inspector/script-breakpoint.h" | 10 #include "src/inspector/script-breakpoint.h" |
(...skipping 280 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
291 m_executionState.Clear(); | 291 m_executionState.Clear(); |
292 } | 292 } |
293 | 293 |
294 void V8Debugger::stepIntoStatement() { | 294 void V8Debugger::stepIntoStatement() { |
295 DCHECK(isPaused()); | 295 DCHECK(isPaused()); |
296 DCHECK(!m_executionState.IsEmpty()); | 296 DCHECK(!m_executionState.IsEmpty()); |
297 v8::debug::PrepareStep(m_isolate, v8::debug::StepIn); | 297 v8::debug::PrepareStep(m_isolate, v8::debug::StepIn); |
298 continueProgram(); | 298 continueProgram(); |
299 } | 299 } |
300 | 300 |
| 301 Response V8Debugger::stepIntoAsync() { |
| 302 DCHECK(isPaused()); |
| 303 DCHECK(!m_executionState.IsEmpty()); |
| 304 if (!m_currentCreatedAsyncTask) { |
| 305 return Response::Error("No scheduled chained callback"); |
| 306 } |
| 307 m_asyncTasksWithScheduledBreak.insert(m_currentCreatedAsyncTask); |
| 308 v8::debug::ClearStepping(m_isolate); |
| 309 continueProgram(); |
| 310 return Response::OK(); |
| 311 } |
| 312 |
301 void V8Debugger::stepOverStatement() { | 313 void V8Debugger::stepOverStatement() { |
302 DCHECK(isPaused()); | 314 DCHECK(isPaused()); |
303 DCHECK(!m_executionState.IsEmpty()); | 315 DCHECK(!m_executionState.IsEmpty()); |
304 v8::debug::PrepareStep(m_isolate, v8::debug::StepNext); | 316 v8::debug::PrepareStep(m_isolate, v8::debug::StepNext); |
305 continueProgram(); | 317 continueProgram(); |
306 } | 318 } |
307 | 319 |
308 void V8Debugger::stepOutOfFunction() { | 320 void V8Debugger::stepOutOfFunction() { |
309 DCHECK(isPaused()); | 321 DCHECK(isPaused()); |
310 DCHECK(!m_executionState.IsEmpty()); | 322 DCHECK(!m_executionState.IsEmpty()); |
(...skipping 519 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
830 return v8::Null(m_isolate); | 842 return v8::Null(m_isolate); |
831 if (!markAsInternal(context, location, V8InternalValueType::kLocation)) | 843 if (!markAsInternal(context, location, V8InternalValueType::kLocation)) |
832 return v8::Null(m_isolate); | 844 return v8::Null(m_isolate); |
833 return location; | 845 return location; |
834 } | 846 } |
835 | 847 |
836 bool V8Debugger::isPaused() { return !m_pausedContext.IsEmpty(); } | 848 bool V8Debugger::isPaused() { return !m_pausedContext.IsEmpty(); } |
837 | 849 |
838 std::unique_ptr<V8StackTraceImpl> V8Debugger::createStackTrace( | 850 std::unique_ptr<V8StackTraceImpl> V8Debugger::createStackTrace( |
839 v8::Local<v8::StackTrace> stackTrace) { | 851 v8::Local<v8::StackTrace> stackTrace) { |
840 int contextGroupId = | 852 return V8StackTraceImpl::create(this, currentContextGroupId(), stackTrace, |
841 m_isolate->InContext() | |
842 ? m_inspector->contextGroupId(m_isolate->GetCurrentContext()) | |
843 : 0; | |
844 return V8StackTraceImpl::create(this, contextGroupId, stackTrace, | |
845 V8StackTraceImpl::maxCallStackSizeToCapture); | 853 V8StackTraceImpl::maxCallStackSizeToCapture); |
846 } | 854 } |
847 | 855 |
848 void V8Debugger::setAsyncCallStackDepth(V8DebuggerAgentImpl* agent, int depth) { | 856 void V8Debugger::setAsyncCallStackDepth(V8DebuggerAgentImpl* agent, int depth) { |
849 if (depth <= 0) | 857 if (depth <= 0) |
850 m_maxAsyncCallStackDepthMap.erase(agent); | 858 m_maxAsyncCallStackDepthMap.erase(agent); |
851 else | 859 else |
852 m_maxAsyncCallStackDepthMap[agent] = depth; | 860 m_maxAsyncCallStackDepthMap[agent] = depth; |
853 | 861 |
854 int maxAsyncCallStackDepth = 0; | 862 int maxAsyncCallStackDepth = 0; |
(...skipping 26 matching lines...) Expand all Loading... |
881 // We don't need to pass context group id here because we gets this callback | 889 // We don't need to pass context group id here because we gets this callback |
882 // from V8 for promise events only. | 890 // from V8 for promise events only. |
883 // Passing one as maxStackSize forces no async chain for the new stack and | 891 // Passing one as maxStackSize forces no async chain for the new stack and |
884 // allows us to not grow exponentially. | 892 // allows us to not grow exponentially. |
885 std::unique_ptr<V8StackTraceImpl> creationStack = | 893 std::unique_ptr<V8StackTraceImpl> creationStack = |
886 V8StackTraceImpl::capture(this, 0, 1, String16()); | 894 V8StackTraceImpl::capture(this, 0, 1, String16()); |
887 if (creationStack && !creationStack->isEmpty()) { | 895 if (creationStack && !creationStack->isEmpty()) { |
888 m_asyncTaskCreationStacks[task] = std::move(creationStack); | 896 m_asyncTaskCreationStacks[task] = std::move(creationStack); |
889 registerAsyncTaskIfNeeded(task); | 897 registerAsyncTaskIfNeeded(task); |
890 } | 898 } |
| 899 if (!parentTask) return; |
| 900 V8DebuggerAgentImpl* agent = |
| 901 m_inspector->enabledDebuggerAgentForGroup(currentContextGroupId()); |
| 902 if (!agent) return; |
| 903 m_currentCreatedAsyncTask = task; |
| 904 agent->asyncTaskCreated(); |
| 905 m_currentCreatedAsyncTask = nullptr; |
891 } | 906 } |
892 | 907 |
893 void V8Debugger::asyncTaskScheduled(const StringView& taskName, void* task, | 908 void V8Debugger::asyncTaskScheduled(const StringView& taskName, void* task, |
894 bool recurring) { | 909 bool recurring) { |
895 if (!m_maxAsyncCallStackDepth) return; | 910 if (!m_maxAsyncCallStackDepth) return; |
896 asyncTaskScheduled(toString16(taskName), task, recurring); | 911 asyncTaskScheduled(toString16(taskName), task, recurring); |
897 } | 912 } |
898 | 913 |
899 void V8Debugger::asyncTaskScheduled(const String16& taskName, void* task, | 914 void V8Debugger::asyncTaskScheduled(const String16& taskName, void* task, |
900 bool recurring) { | 915 bool recurring) { |
901 if (!m_maxAsyncCallStackDepth) return; | 916 if (!m_maxAsyncCallStackDepth) return; |
902 v8::HandleScope scope(m_isolate); | 917 v8::HandleScope scope(m_isolate); |
903 int contextGroupId = | |
904 m_isolate->InContext() | |
905 ? m_inspector->contextGroupId(m_isolate->GetCurrentContext()) | |
906 : 0; | |
907 std::unique_ptr<V8StackTraceImpl> chain = V8StackTraceImpl::capture( | 918 std::unique_ptr<V8StackTraceImpl> chain = V8StackTraceImpl::capture( |
908 this, contextGroupId, V8StackTraceImpl::maxCallStackSizeToCapture, | 919 this, currentContextGroupId(), |
909 taskName); | 920 V8StackTraceImpl::maxCallStackSizeToCapture, taskName); |
910 if (chain) { | 921 if (chain) { |
911 m_asyncTaskStacks[task] = std::move(chain); | 922 m_asyncTaskStacks[task] = std::move(chain); |
912 if (recurring) m_recurringTasks.insert(task); | 923 if (recurring) m_recurringTasks.insert(task); |
913 registerAsyncTaskIfNeeded(task); | 924 registerAsyncTaskIfNeeded(task); |
914 } | 925 } |
915 } | 926 } |
916 | 927 |
917 void V8Debugger::asyncTaskCanceled(void* task) { | 928 void V8Debugger::asyncTaskCanceled(void* task) { |
918 if (!m_maxAsyncCallStackDepth) return; | 929 if (!m_maxAsyncCallStackDepth) return; |
919 m_asyncTaskStacks.erase(task); | 930 m_asyncTaskStacks.erase(task); |
920 m_recurringTasks.erase(task); | 931 m_recurringTasks.erase(task); |
921 m_parentTask.erase(task); | 932 m_parentTask.erase(task); |
922 m_asyncTaskCreationStacks.erase(task); | 933 m_asyncTaskCreationStacks.erase(task); |
| 934 if (m_currentCreatedAsyncTask == task) m_currentCreatedAsyncTask = nullptr; |
| 935 m_asyncTasksWithScheduledBreak.erase(task); |
923 auto it = m_taskToId.find(task); | 936 auto it = m_taskToId.find(task); |
924 if (it == m_taskToId.end()) return; | 937 if (it == m_taskToId.end()) return; |
925 m_idToTask.erase(it->second); | 938 m_idToTask.erase(it->second); |
926 m_taskToId.erase(it); | 939 m_taskToId.erase(it); |
927 } | 940 } |
928 | 941 |
929 void V8Debugger::asyncTaskStarted(void* task) { | 942 void V8Debugger::asyncTaskStarted(void* task) { |
930 if (!m_maxAsyncCallStackDepth) return; | 943 if (!m_maxAsyncCallStackDepth) return; |
931 m_currentTasks.push_back(task); | 944 m_currentTasks.push_back(task); |
932 auto parentIt = m_parentTask.find(task); | 945 auto parentIt = m_parentTask.find(task); |
933 AsyncTaskToStackTrace::iterator stackIt = m_asyncTaskStacks.find( | 946 AsyncTaskToStackTrace::iterator stackIt = m_asyncTaskStacks.find( |
934 parentIt == m_parentTask.end() ? task : parentIt->second); | 947 parentIt == m_parentTask.end() ? task : parentIt->second); |
935 // Needs to support following order of events: | 948 // Needs to support following order of events: |
936 // - asyncTaskScheduled | 949 // - asyncTaskScheduled |
937 // <-- attached here --> | 950 // <-- attached here --> |
938 // - asyncTaskStarted | 951 // - asyncTaskStarted |
939 // - asyncTaskCanceled <-- canceled before finished | 952 // - asyncTaskCanceled <-- canceled before finished |
940 // <-- async stack requested here --> | 953 // <-- async stack requested here --> |
941 // - asyncTaskFinished | 954 // - asyncTaskFinished |
942 std::unique_ptr<V8StackTraceImpl> stack; | 955 std::unique_ptr<V8StackTraceImpl> stack; |
943 if (stackIt != m_asyncTaskStacks.end() && stackIt->second) | 956 if (stackIt != m_asyncTaskStacks.end() && stackIt->second) |
944 stack = stackIt->second->cloneImpl(); | 957 stack = stackIt->second->cloneImpl(); |
945 auto itCreation = m_asyncTaskCreationStacks.find(task); | 958 auto itCreation = m_asyncTaskCreationStacks.find(task); |
946 if (stack && itCreation != m_asyncTaskCreationStacks.end()) { | 959 if (stack && itCreation != m_asyncTaskCreationStacks.end()) { |
947 stack->setCreation(itCreation->second->cloneImpl()); | 960 stack->setCreation(itCreation->second->cloneImpl()); |
948 } | 961 } |
949 m_currentStacks.push_back(std::move(stack)); | 962 m_currentStacks.push_back(std::move(stack)); |
| 963 if (m_asyncTasksWithScheduledBreak.find(task) == |
| 964 m_asyncTasksWithScheduledBreak.end()) |
| 965 return; |
| 966 V8DebuggerAgentImpl* agent = |
| 967 m_inspector->enabledDebuggerAgentForGroup(currentContextGroupId()); |
| 968 if (!agent) return; |
| 969 agent->asyncTaskStarted(); |
950 } | 970 } |
951 | 971 |
952 void V8Debugger::asyncTaskFinished(void* task) { | 972 void V8Debugger::asyncTaskFinished(void* task) { |
953 if (!m_maxAsyncCallStackDepth) return; | 973 if (!m_maxAsyncCallStackDepth) return; |
954 // We could start instrumenting half way and the stack is empty. | 974 // We could start instrumenting half way and the stack is empty. |
955 if (!m_currentStacks.size()) return; | 975 if (!m_currentStacks.size()) return; |
956 | 976 |
957 DCHECK(m_currentTasks.back() == task); | 977 DCHECK(m_currentTasks.back() == task); |
958 m_currentTasks.pop_back(); | 978 m_currentTasks.pop_back(); |
959 | 979 |
960 m_currentStacks.pop_back(); | 980 m_currentStacks.pop_back(); |
| 981 if (m_asyncTasksWithScheduledBreak.find(task) != |
| 982 m_asyncTasksWithScheduledBreak.end()) { |
| 983 V8DebuggerAgentImpl* agent = |
| 984 m_inspector->enabledDebuggerAgentForGroup(currentContextGroupId()); |
| 985 if (!agent) return; |
| 986 agent->asyncTaskFinished(); |
| 987 m_asyncTasksWithScheduledBreak.erase(task); |
| 988 } |
| 989 |
961 if (m_recurringTasks.find(task) == m_recurringTasks.end()) { | 990 if (m_recurringTasks.find(task) == m_recurringTasks.end()) { |
962 asyncTaskCanceled(task); | 991 asyncTaskCanceled(task); |
963 } | 992 } |
964 } | 993 } |
965 | 994 |
966 void V8Debugger::allAsyncTasksCanceled() { | 995 void V8Debugger::allAsyncTasksCanceled() { |
967 m_asyncTaskStacks.clear(); | 996 m_asyncTaskStacks.clear(); |
968 m_recurringTasks.clear(); | 997 m_recurringTasks.clear(); |
969 m_currentStacks.clear(); | 998 m_currentStacks.clear(); |
970 m_currentTasks.clear(); | 999 m_currentTasks.clear(); |
971 m_parentTask.clear(); | 1000 m_parentTask.clear(); |
972 m_asyncTaskCreationStacks.clear(); | 1001 m_asyncTaskCreationStacks.clear(); |
| 1002 m_currentCreatedAsyncTask = nullptr; |
| 1003 m_asyncTasksWithScheduledBreak.clear(); |
973 m_idToTask.clear(); | 1004 m_idToTask.clear(); |
974 m_taskToId.clear(); | 1005 m_taskToId.clear(); |
975 m_lastTaskId = 0; | 1006 m_lastTaskId = 0; |
976 } | 1007 } |
977 | 1008 |
978 void V8Debugger::muteScriptParsedEvents() { | 1009 void V8Debugger::muteScriptParsedEvents() { |
979 ++m_ignoreScriptParsedEventsCounter; | 1010 ++m_ignoreScriptParsedEventsCounter; |
980 } | 1011 } |
981 | 1012 |
982 void V8Debugger::unmuteScriptParsedEvents() { | 1013 void V8Debugger::unmuteScriptParsedEvents() { |
983 --m_ignoreScriptParsedEventsCounter; | 1014 --m_ignoreScriptParsedEventsCounter; |
984 DCHECK_GE(m_ignoreScriptParsedEventsCounter, 0); | 1015 DCHECK_GE(m_ignoreScriptParsedEventsCounter, 0); |
985 } | 1016 } |
986 | 1017 |
987 std::unique_ptr<V8StackTraceImpl> V8Debugger::captureStackTrace( | 1018 std::unique_ptr<V8StackTraceImpl> V8Debugger::captureStackTrace( |
988 bool fullStack) { | 1019 bool fullStack) { |
989 if (!m_isolate->InContext()) return nullptr; | 1020 int contextGroupId = currentContextGroupId(); |
| 1021 if (!contextGroupId) return nullptr; |
990 | 1022 |
991 v8::HandleScope handles(m_isolate); | 1023 v8::HandleScope handles(m_isolate); |
992 int contextGroupId = | |
993 m_inspector->contextGroupId(m_isolate->GetCurrentContext()); | |
994 if (!contextGroupId) return nullptr; | |
995 | |
996 size_t stackSize = | 1024 size_t stackSize = |
997 fullStack ? V8StackTraceImpl::maxCallStackSizeToCapture : 1; | 1025 fullStack ? V8StackTraceImpl::maxCallStackSizeToCapture : 1; |
998 if (m_inspector->enabledRuntimeAgentForGroup(contextGroupId)) | 1026 if (m_inspector->enabledRuntimeAgentForGroup(contextGroupId)) |
999 stackSize = V8StackTraceImpl::maxCallStackSizeToCapture; | 1027 stackSize = V8StackTraceImpl::maxCallStackSizeToCapture; |
1000 | 1028 |
1001 return V8StackTraceImpl::capture(this, contextGroupId, stackSize); | 1029 return V8StackTraceImpl::capture(this, contextGroupId, stackSize); |
1002 } | 1030 } |
1003 | 1031 |
| 1032 int V8Debugger::currentContextGroupId() { |
| 1033 if (!m_isolate->InContext()) return 0; |
| 1034 return m_inspector->contextGroupId(m_isolate->GetCurrentContext()); |
| 1035 } |
| 1036 |
1004 } // namespace v8_inspector | 1037 } // namespace v8_inspector |
OLD | NEW |