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 |