Chromium Code Reviews| OLD | NEW |
|---|---|
| 1 // Copyright 2015 the V8 project authors. All rights reserved. | 1 // Copyright 2015 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-agent-impl.h" | 5 #include "src/inspector/v8-debugger-agent-impl.h" |
| 6 | 6 |
| 7 #include <algorithm> | 7 #include <algorithm> |
| 8 | 8 |
| 9 #include "src/debug/debug-interface.h" | 9 #include "src/debug/debug-interface.h" |
| 10 #include "src/inspector/injected-script.h" | 10 #include "src/inspector/injected-script.h" |
| (...skipping 113 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 124 V8DebuggerAgentImpl::V8DebuggerAgentImpl( | 124 V8DebuggerAgentImpl::V8DebuggerAgentImpl( |
| 125 V8InspectorSessionImpl* session, protocol::FrontendChannel* frontendChannel, | 125 V8InspectorSessionImpl* session, protocol::FrontendChannel* frontendChannel, |
| 126 protocol::DictionaryValue* state) | 126 protocol::DictionaryValue* state) |
| 127 : m_inspector(session->inspector()), | 127 : m_inspector(session->inspector()), |
| 128 m_debugger(m_inspector->debugger()), | 128 m_debugger(m_inspector->debugger()), |
| 129 m_session(session), | 129 m_session(session), |
| 130 m_enabled(false), | 130 m_enabled(false), |
| 131 m_state(state), | 131 m_state(state), |
| 132 m_frontend(frontendChannel), | 132 m_frontend(frontendChannel), |
| 133 m_isolate(m_inspector->isolate()), | 133 m_isolate(m_inspector->isolate()), |
| 134 m_breakReason(protocol::Debugger::Paused::ReasonEnum::Other), | |
| 135 m_scheduledDebuggerStep(NoStep), | 134 m_scheduledDebuggerStep(NoStep), |
| 136 m_javaScriptPauseScheduled(false), | 135 m_javaScriptPauseScheduled(false), |
| 137 m_recursionLevelForStepOut(0) { | 136 m_recursionLevelForStepOut(0) { |
| 138 clearBreakDetails(); | 137 clearBreakDetails(); |
| 139 } | 138 } |
| 140 | 139 |
| 141 V8DebuggerAgentImpl::~V8DebuggerAgentImpl() {} | 140 V8DebuggerAgentImpl::~V8DebuggerAgentImpl() {} |
| 142 | 141 |
| 143 void V8DebuggerAgentImpl::enableImpl() { | 142 void V8DebuggerAgentImpl::enableImpl() { |
| 144 m_enabled = true; | 143 m_enabled = true; |
| (...skipping 437 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 582 String16* scriptSource) { | 581 String16* scriptSource) { |
| 583 if (!enabled()) return Response::Error(kDebuggerNotEnabled); | 582 if (!enabled()) return Response::Error(kDebuggerNotEnabled); |
| 584 ScriptsMap::iterator it = m_scripts.find(scriptId); | 583 ScriptsMap::iterator it = m_scripts.find(scriptId); |
| 585 if (it == m_scripts.end()) | 584 if (it == m_scripts.end()) |
| 586 return Response::Error("No script for id: " + scriptId); | 585 return Response::Error("No script for id: " + scriptId); |
| 587 v8::HandleScope handles(m_isolate); | 586 v8::HandleScope handles(m_isolate); |
| 588 *scriptSource = it->second->source(m_isolate); | 587 *scriptSource = it->second->source(m_isolate); |
| 589 return Response::OK(); | 588 return Response::OK(); |
| 590 } | 589 } |
| 591 | 590 |
| 591 void V8DebuggerAgentImpl::pushBreakDetails( | |
| 592 const String16& breakReason, | |
| 593 std::unique_ptr<protocol::DictionaryValue> breakAuxData) { | |
| 594 m_breakReason.push_back(breakReason); | |
| 595 m_breakAuxData.push_back(std::move(breakAuxData)); | |
| 596 } | |
| 597 | |
| 598 void V8DebuggerAgentImpl::popBreakDetails() { | |
| 599 if (m_breakReason.empty()) return; | |
|
pfeldman
2017/02/07 19:01:05
Is it not strict enough to put DCHECK here? So we
kozy
2017/02/07 22:54:36
We cleanup break reasons on actual break and we do
| |
| 600 m_breakReason.pop_back(); | |
| 601 m_breakAuxData.pop_back(); | |
| 602 } | |
| 603 | |
| 604 void V8DebuggerAgentImpl::clearBreakDetails() { | |
| 605 std::vector<String16> emptyBreakReason; | |
| 606 m_breakReason.swap(emptyBreakReason); | |
| 607 std::vector<std::unique_ptr<protocol::DictionaryValue>> emptyBreakAuxData; | |
| 608 m_breakAuxData.swap(emptyBreakAuxData); | |
| 609 } | |
| 610 | |
| 592 void V8DebuggerAgentImpl::schedulePauseOnNextStatement( | 611 void V8DebuggerAgentImpl::schedulePauseOnNextStatement( |
| 593 const String16& breakReason, | 612 const String16& breakReason, |
| 594 std::unique_ptr<protocol::DictionaryValue> data) { | 613 std::unique_ptr<protocol::DictionaryValue> data) { |
| 595 if (!enabled() || m_scheduledDebuggerStep == StepInto || | 614 if (!enabled() || m_scheduledDebuggerStep == StepInto || |
| 596 m_javaScriptPauseScheduled || isPaused() || | 615 m_javaScriptPauseScheduled || isPaused() || |
| 597 !m_debugger->breakpointsActivated()) | 616 !m_debugger->breakpointsActivated()) |
| 598 return; | 617 return; |
| 599 m_breakReason = breakReason; | 618 if (m_breakReason.empty()) m_debugger->setPauseOnNextStatement(true); |
| 600 m_breakAuxData = std::move(data); | 619 pushBreakDetails(breakReason, std::move(data)); |
| 601 m_debugger->setPauseOnNextStatement(true); | |
| 602 } | 620 } |
| 603 | 621 |
| 604 void V8DebuggerAgentImpl::schedulePauseOnNextStatementIfSteppingInto() { | 622 void V8DebuggerAgentImpl::schedulePauseOnNextStatementIfSteppingInto() { |
| 605 DCHECK(enabled()); | 623 DCHECK(enabled()); |
| 606 if (m_scheduledDebuggerStep != StepInto || m_javaScriptPauseScheduled || | 624 if (m_scheduledDebuggerStep != StepInto || m_javaScriptPauseScheduled || |
| 607 isPaused()) | 625 isPaused()) |
| 608 return; | 626 return; |
| 609 clearBreakDetails(); | 627 clearBreakDetails(); |
| 610 m_debugger->setPauseOnNextStatement(true); | 628 m_debugger->setPauseOnNextStatement(true); |
| 611 } | 629 } |
| 612 | 630 |
| 613 void V8DebuggerAgentImpl::cancelPauseOnNextStatement() { | 631 void V8DebuggerAgentImpl::cancelPauseOnNextStatement() { |
| 614 if (m_javaScriptPauseScheduled || isPaused()) return; | 632 if (m_javaScriptPauseScheduled || isPaused()) return; |
| 615 clearBreakDetails(); | 633 popBreakDetails(); |
| 616 m_debugger->setPauseOnNextStatement(false); | 634 if (m_breakReason.empty()) m_debugger->setPauseOnNextStatement(false); |
| 617 } | 635 } |
| 618 | 636 |
| 619 Response V8DebuggerAgentImpl::pause() { | 637 Response V8DebuggerAgentImpl::pause() { |
| 620 if (!enabled()) return Response::Error(kDebuggerNotEnabled); | 638 if (!enabled()) return Response::Error(kDebuggerNotEnabled); |
| 621 if (m_javaScriptPauseScheduled || isPaused()) return Response::OK(); | 639 if (m_javaScriptPauseScheduled || isPaused()) return Response::OK(); |
| 622 clearBreakDetails(); | 640 clearBreakDetails(); |
| 623 m_javaScriptPauseScheduled = true; | 641 m_javaScriptPauseScheduled = true; |
| 624 m_scheduledDebuggerStep = NoStep; | 642 m_scheduledDebuggerStep = NoStep; |
| 625 m_debugger->setPauseOnNextStatement(true); | 643 m_debugger->setPauseOnNextStatement(true); |
| 626 return Response::OK(); | 644 return Response::OK(); |
| (...skipping 437 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 1064 | 1082 |
| 1065 void V8DebuggerAgentImpl::didPause(int contextId, | 1083 void V8DebuggerAgentImpl::didPause(int contextId, |
| 1066 v8::Local<v8::Value> exception, | 1084 v8::Local<v8::Value> exception, |
| 1067 const std::vector<String16>& hitBreakpoints, | 1085 const std::vector<String16>& hitBreakpoints, |
| 1068 bool isPromiseRejection, bool isUncaught, | 1086 bool isPromiseRejection, bool isUncaught, |
| 1069 bool isOOMBreak) { | 1087 bool isOOMBreak) { |
| 1070 JavaScriptCallFrames frames = m_debugger->currentCallFrames(); | 1088 JavaScriptCallFrames frames = m_debugger->currentCallFrames(); |
| 1071 m_pausedCallFrames.swap(frames); | 1089 m_pausedCallFrames.swap(frames); |
| 1072 v8::HandleScope handles(m_isolate); | 1090 v8::HandleScope handles(m_isolate); |
| 1073 | 1091 |
| 1092 String16 breakReason = m_breakReason.empty() | |
| 1093 ? protocol::Debugger::Paused::ReasonEnum::Other | |
| 1094 : m_breakReason.back(); | |
| 1095 std::unique_ptr<protocol::DictionaryValue> breakAuxData = | |
| 1096 m_breakAuxData.empty() ? nullptr : std::move(m_breakAuxData.back()); | |
| 1097 clearBreakDetails(); | |
| 1098 std::vector<std::unique_ptr<protocol::DictionaryValue>> emptyBreakAuxData; | |
| 1074 if (isOOMBreak) { | 1099 if (isOOMBreak) { |
| 1075 m_breakReason = protocol::Debugger::Paused::ReasonEnum::OOM; | 1100 breakReason = protocol::Debugger::Paused::ReasonEnum::OOM; |
| 1076 m_breakAuxData = nullptr; | 1101 breakAuxData = nullptr; |
| 1077 } else if (!exception.IsEmpty()) { | 1102 } else if (!exception.IsEmpty()) { |
| 1078 InjectedScript* injectedScript = nullptr; | 1103 InjectedScript* injectedScript = nullptr; |
| 1079 m_session->findInjectedScript(contextId, injectedScript); | 1104 m_session->findInjectedScript(contextId, injectedScript); |
| 1080 if (injectedScript) { | 1105 if (injectedScript) { |
| 1081 m_breakReason = | 1106 breakReason = |
| 1082 isPromiseRejection | 1107 isPromiseRejection |
| 1083 ? protocol::Debugger::Paused::ReasonEnum::PromiseRejection | 1108 ? protocol::Debugger::Paused::ReasonEnum::PromiseRejection |
| 1084 : protocol::Debugger::Paused::ReasonEnum::Exception; | 1109 : protocol::Debugger::Paused::ReasonEnum::Exception; |
| 1085 std::unique_ptr<protocol::Runtime::RemoteObject> obj; | 1110 std::unique_ptr<protocol::Runtime::RemoteObject> obj; |
| 1086 injectedScript->wrapObject(exception, kBacktraceObjectGroup, false, false, | 1111 injectedScript->wrapObject(exception, kBacktraceObjectGroup, false, false, |
| 1087 &obj); | 1112 &obj); |
| 1088 if (obj) { | 1113 if (obj) { |
| 1089 m_breakAuxData = obj->toValue(); | 1114 breakAuxData = obj->toValue(); |
| 1090 m_breakAuxData->setBoolean("uncaught", isUncaught); | 1115 breakAuxData->setBoolean("uncaught", isUncaught); |
| 1091 } else { | 1116 } else { |
| 1092 m_breakAuxData = nullptr; | 1117 breakAuxData = nullptr; |
| 1093 } | 1118 } |
| 1094 // m_breakAuxData might be null after this. | 1119 // breakAuxData might be null after this. |
| 1095 } | 1120 } |
| 1096 } | 1121 } |
| 1097 | 1122 |
| 1098 std::unique_ptr<Array<String16>> hitBreakpointIds = Array<String16>::create(); | 1123 std::unique_ptr<Array<String16>> hitBreakpointIds = Array<String16>::create(); |
| 1099 | 1124 |
| 1100 for (const auto& point : hitBreakpoints) { | 1125 for (const auto& point : hitBreakpoints) { |
| 1101 DebugServerBreakpointToBreakpointIdAndSourceMap::iterator | 1126 DebugServerBreakpointToBreakpointIdAndSourceMap::iterator |
| 1102 breakpointIterator = m_serverBreakpoints.find(point); | 1127 breakpointIterator = m_serverBreakpoints.find(point); |
| 1103 if (breakpointIterator != m_serverBreakpoints.end()) { | 1128 if (breakpointIterator != m_serverBreakpoints.end()) { |
| 1104 const String16& localId = breakpointIterator->second.first; | 1129 const String16& localId = breakpointIterator->second.first; |
| 1105 hitBreakpointIds->addItem(localId); | 1130 hitBreakpointIds->addItem(localId); |
| 1106 | 1131 |
| 1107 BreakpointSource source = breakpointIterator->second.second; | 1132 BreakpointSource source = breakpointIterator->second.second; |
| 1108 if (m_breakReason == protocol::Debugger::Paused::ReasonEnum::Other && | 1133 if (breakReason == protocol::Debugger::Paused::ReasonEnum::Other && |
| 1109 source == DebugCommandBreakpointSource) | 1134 source == DebugCommandBreakpointSource) |
| 1110 m_breakReason = protocol::Debugger::Paused::ReasonEnum::DebugCommand; | 1135 breakReason = protocol::Debugger::Paused::ReasonEnum::DebugCommand; |
| 1111 } | 1136 } |
| 1112 } | 1137 } |
| 1113 | 1138 |
| 1114 std::unique_ptr<Array<CallFrame>> protocolCallFrames; | 1139 std::unique_ptr<Array<CallFrame>> protocolCallFrames; |
| 1115 Response response = currentCallFrames(&protocolCallFrames); | 1140 Response response = currentCallFrames(&protocolCallFrames); |
| 1116 if (!response.isSuccess()) protocolCallFrames = Array<CallFrame>::create(); | 1141 if (!response.isSuccess()) protocolCallFrames = Array<CallFrame>::create(); |
| 1117 m_frontend.paused(std::move(protocolCallFrames), m_breakReason, | 1142 m_frontend.paused(std::move(protocolCallFrames), breakReason, |
| 1118 std::move(m_breakAuxData), std::move(hitBreakpointIds), | 1143 std::move(breakAuxData), std::move(hitBreakpointIds), |
| 1119 currentAsyncStackTrace()); | 1144 currentAsyncStackTrace()); |
| 1120 m_scheduledDebuggerStep = NoStep; | 1145 m_scheduledDebuggerStep = NoStep; |
| 1121 m_javaScriptPauseScheduled = false; | 1146 m_javaScriptPauseScheduled = false; |
| 1122 | 1147 |
| 1123 if (!m_continueToLocationBreakpointId.isEmpty()) { | 1148 if (!m_continueToLocationBreakpointId.isEmpty()) { |
| 1124 m_debugger->removeBreakpoint(m_continueToLocationBreakpointId); | 1149 m_debugger->removeBreakpoint(m_continueToLocationBreakpointId); |
| 1125 m_continueToLocationBreakpointId = ""; | 1150 m_continueToLocationBreakpointId = ""; |
| 1126 } | 1151 } |
| 1127 } | 1152 } |
| 1128 | 1153 |
| 1129 void V8DebuggerAgentImpl::didContinue() { | 1154 void V8DebuggerAgentImpl::didContinue() { |
| 1130 JavaScriptCallFrames emptyCallFrames; | 1155 JavaScriptCallFrames emptyCallFrames; |
| 1131 m_pausedCallFrames.swap(emptyCallFrames); | 1156 m_pausedCallFrames.swap(emptyCallFrames); |
| 1132 clearBreakDetails(); | 1157 clearBreakDetails(); |
| 1133 m_frontend.resumed(); | 1158 m_frontend.resumed(); |
| 1134 } | 1159 } |
| 1135 | 1160 |
| 1136 void V8DebuggerAgentImpl::breakProgram( | 1161 void V8DebuggerAgentImpl::breakProgram( |
| 1137 const String16& breakReason, | 1162 const String16& breakReason, |
| 1138 std::unique_ptr<protocol::DictionaryValue> data) { | 1163 std::unique_ptr<protocol::DictionaryValue> data) { |
| 1139 if (!enabled() || !m_debugger->canBreakProgram() || m_skipAllPauses) return; | 1164 if (!enabled() || !m_debugger->canBreakProgram() || m_skipAllPauses) return; |
| 1140 m_breakReason = breakReason; | 1165 pushBreakDetails(breakReason, std::move(data)); |
| 1141 m_breakAuxData = std::move(data); | |
| 1142 m_scheduledDebuggerStep = NoStep; | 1166 m_scheduledDebuggerStep = NoStep; |
| 1143 m_debugger->breakProgram(); | 1167 m_debugger->breakProgram(); |
| 1144 } | 1168 } |
| 1145 | 1169 |
| 1146 void V8DebuggerAgentImpl::breakProgramOnException( | 1170 void V8DebuggerAgentImpl::breakProgramOnException( |
| 1147 const String16& breakReason, | 1171 const String16& breakReason, |
| 1148 std::unique_ptr<protocol::DictionaryValue> data) { | 1172 std::unique_ptr<protocol::DictionaryValue> data) { |
| 1149 if (!enabled() || | 1173 if (!enabled() || |
| 1150 m_debugger->getPauseOnExceptionsState() == v8::debug::NoBreakOnException) | 1174 m_debugger->getPauseOnExceptionsState() == v8::debug::NoBreakOnException) |
| 1151 return; | 1175 return; |
| 1152 breakProgram(breakReason, std::move(data)); | 1176 breakProgram(breakReason, std::move(data)); |
| 1153 } | 1177 } |
| 1154 | 1178 |
| 1155 void V8DebuggerAgentImpl::clearBreakDetails() { | |
| 1156 m_breakReason = protocol::Debugger::Paused::ReasonEnum::Other; | |
| 1157 m_breakAuxData = nullptr; | |
| 1158 } | |
| 1159 | |
| 1160 void V8DebuggerAgentImpl::setBreakpointAt(const String16& scriptId, | 1179 void V8DebuggerAgentImpl::setBreakpointAt(const String16& scriptId, |
| 1161 int lineNumber, int columnNumber, | 1180 int lineNumber, int columnNumber, |
| 1162 BreakpointSource source, | 1181 BreakpointSource source, |
| 1163 const String16& condition) { | 1182 const String16& condition) { |
| 1164 ScriptBreakpoint breakpoint(scriptId, lineNumber, columnNumber, condition); | 1183 ScriptBreakpoint breakpoint(scriptId, lineNumber, columnNumber, condition); |
| 1165 String16 breakpointId = generateBreakpointId(breakpoint, source); | 1184 String16 breakpointId = generateBreakpointId(breakpoint, source); |
| 1166 resolveBreakpoint(breakpointId, breakpoint, source); | 1185 resolveBreakpoint(breakpointId, breakpoint, source); |
| 1167 } | 1186 } |
| 1168 | 1187 |
| 1169 void V8DebuggerAgentImpl::removeBreakpointAt(const String16& scriptId, | 1188 void V8DebuggerAgentImpl::removeBreakpointAt(const String16& scriptId, |
| 1170 int lineNumber, int columnNumber, | 1189 int lineNumber, int columnNumber, |
| 1171 BreakpointSource source) { | 1190 BreakpointSource source) { |
| 1172 removeBreakpointImpl(generateBreakpointId( | 1191 removeBreakpointImpl(generateBreakpointId( |
| 1173 ScriptBreakpoint(scriptId, lineNumber, columnNumber, String16()), | 1192 ScriptBreakpoint(scriptId, lineNumber, columnNumber, String16()), |
| 1174 source)); | 1193 source)); |
| 1175 } | 1194 } |
| 1176 | 1195 |
| 1177 void V8DebuggerAgentImpl::reset() { | 1196 void V8DebuggerAgentImpl::reset() { |
| 1178 if (!enabled()) return; | 1197 if (!enabled()) return; |
| 1179 m_scheduledDebuggerStep = NoStep; | 1198 m_scheduledDebuggerStep = NoStep; |
| 1180 m_blackboxedPositions.clear(); | 1199 m_blackboxedPositions.clear(); |
| 1181 resetBlackboxedStateCache(); | 1200 resetBlackboxedStateCache(); |
| 1182 m_scripts.clear(); | 1201 m_scripts.clear(); |
| 1183 m_breakpointIdToDebuggerBreakpointIds.clear(); | 1202 m_breakpointIdToDebuggerBreakpointIds.clear(); |
| 1184 } | 1203 } |
| 1185 | 1204 |
| 1186 } // namespace v8_inspector | 1205 } // namespace v8_inspector |
| OLD | NEW |