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

Side by Side Diff: src/inspector/v8-debugger-agent-impl.cc

Issue 2678313002: [inspector] support for nested scheduled breaks (Closed)
Patch Set: better test 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
OLDNEW
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
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();
139 } 137 }
140 138
141 V8DebuggerAgentImpl::~V8DebuggerAgentImpl() {} 139 V8DebuggerAgentImpl::~V8DebuggerAgentImpl() {}
142 140
143 void V8DebuggerAgentImpl::enableImpl() { 141 void V8DebuggerAgentImpl::enableImpl() {
144 m_enabled = true; 142 m_enabled = true;
145 m_state->setBoolean(DebuggerAgentState::debuggerEnabled, true); 143 m_state->setBoolean(DebuggerAgentState::debuggerEnabled, true);
146 m_debugger->enable(); 144 m_debugger->enable();
147 145
148 std::vector<std::unique_ptr<V8DebuggerScript>> compiledScripts; 146 std::vector<std::unique_ptr<V8DebuggerScript>> compiledScripts;
(...skipping 433 matching lines...) Expand 10 before | Expand all | Expand 10 after
582 String16* scriptSource) { 580 String16* scriptSource) {
583 if (!enabled()) return Response::Error(kDebuggerNotEnabled); 581 if (!enabled()) return Response::Error(kDebuggerNotEnabled);
584 ScriptsMap::iterator it = m_scripts.find(scriptId); 582 ScriptsMap::iterator it = m_scripts.find(scriptId);
585 if (it == m_scripts.end()) 583 if (it == m_scripts.end())
586 return Response::Error("No script for id: " + scriptId); 584 return Response::Error("No script for id: " + scriptId);
587 v8::HandleScope handles(m_isolate); 585 v8::HandleScope handles(m_isolate);
588 *scriptSource = it->second->source(m_isolate); 586 *scriptSource = it->second->source(m_isolate);
589 return Response::OK(); 587 return Response::OK();
590 } 588 }
591 589
590 void V8DebuggerAgentImpl::pushBreakDetails(
591 const String16& breakReason,
592 std::unique_ptr<protocol::DictionaryValue> breakAuxData) {
593 m_breakReason.push_back(std::make_pair(breakReason, std::move(breakAuxData)));
594 }
595
596 void V8DebuggerAgentImpl::popBreakDetails() {
597 if (m_breakReason.empty()) return;
598 m_breakReason.pop_back();
599 }
600
601 void V8DebuggerAgentImpl::clearBreakDetails() {
602 std::vector<BreakReason> emptyBreakReason;
603 m_breakReason.swap(emptyBreakReason);
604 }
605
592 void V8DebuggerAgentImpl::schedulePauseOnNextStatement( 606 void V8DebuggerAgentImpl::schedulePauseOnNextStatement(
593 const String16& breakReason, 607 const String16& breakReason,
594 std::unique_ptr<protocol::DictionaryValue> data) { 608 std::unique_ptr<protocol::DictionaryValue> data) {
595 if (!enabled() || m_scheduledDebuggerStep == StepInto || 609 if (!enabled() || m_scheduledDebuggerStep == StepInto ||
596 m_javaScriptPauseScheduled || isPaused() || 610 m_javaScriptPauseScheduled || isPaused() ||
597 !m_debugger->breakpointsActivated()) 611 !m_debugger->breakpointsActivated())
598 return; 612 return;
599 m_breakReason = breakReason; 613 if (m_breakReason.empty()) m_debugger->setPauseOnNextStatement(true);
600 m_breakAuxData = std::move(data); 614 pushBreakDetails(breakReason, std::move(data));
601 m_debugger->setPauseOnNextStatement(true);
602 } 615 }
603 616
604 void V8DebuggerAgentImpl::schedulePauseOnNextStatementIfSteppingInto() { 617 void V8DebuggerAgentImpl::schedulePauseOnNextStatementIfSteppingInto() {
605 DCHECK(enabled()); 618 DCHECK(enabled());
606 if (m_scheduledDebuggerStep != StepInto || m_javaScriptPauseScheduled || 619 if (m_scheduledDebuggerStep != StepInto || m_javaScriptPauseScheduled ||
607 isPaused()) 620 isPaused())
608 return; 621 return;
609 clearBreakDetails();
610 m_debugger->setPauseOnNextStatement(true); 622 m_debugger->setPauseOnNextStatement(true);
611 } 623 }
612 624
613 void V8DebuggerAgentImpl::cancelPauseOnNextStatement() { 625 void V8DebuggerAgentImpl::cancelPauseOnNextStatement() {
614 if (m_javaScriptPauseScheduled || isPaused()) return; 626 if (m_javaScriptPauseScheduled || isPaused()) return;
615 clearBreakDetails(); 627 popBreakDetails();
616 m_debugger->setPauseOnNextStatement(false); 628 if (m_breakReason.empty()) m_debugger->setPauseOnNextStatement(false);
617 } 629 }
618 630
619 Response V8DebuggerAgentImpl::pause() { 631 Response V8DebuggerAgentImpl::pause() {
620 if (!enabled()) return Response::Error(kDebuggerNotEnabled); 632 if (!enabled()) return Response::Error(kDebuggerNotEnabled);
621 if (m_javaScriptPauseScheduled || isPaused()) return Response::OK(); 633 if (m_javaScriptPauseScheduled || isPaused()) return Response::OK();
622 clearBreakDetails(); 634 clearBreakDetails();
623 m_javaScriptPauseScheduled = true; 635 m_javaScriptPauseScheduled = true;
624 m_scheduledDebuggerStep = NoStep; 636 m_scheduledDebuggerStep = NoStep;
625 m_debugger->setPauseOnNextStatement(true); 637 m_debugger->setPauseOnNextStatement(true);
626 return Response::OK(); 638 return Response::OK();
(...skipping 437 matching lines...) Expand 10 before | Expand all | Expand 10 after
1064 1076
1065 void V8DebuggerAgentImpl::didPause(int contextId, 1077 void V8DebuggerAgentImpl::didPause(int contextId,
1066 v8::Local<v8::Value> exception, 1078 v8::Local<v8::Value> exception,
1067 const std::vector<String16>& hitBreakpoints, 1079 const std::vector<String16>& hitBreakpoints,
1068 bool isPromiseRejection, bool isUncaught, 1080 bool isPromiseRejection, bool isUncaught,
1069 bool isOOMBreak) { 1081 bool isOOMBreak) {
1070 JavaScriptCallFrames frames = m_debugger->currentCallFrames(); 1082 JavaScriptCallFrames frames = m_debugger->currentCallFrames();
1071 m_pausedCallFrames.swap(frames); 1083 m_pausedCallFrames.swap(frames);
1072 v8::HandleScope handles(m_isolate); 1084 v8::HandleScope handles(m_isolate);
1073 1085
1086 std::vector<BreakReason> hitReasons;
1087
1074 if (isOOMBreak) { 1088 if (isOOMBreak) {
1075 m_breakReason = protocol::Debugger::Paused::ReasonEnum::OOM; 1089 hitReasons.push_back(
1076 m_breakAuxData = nullptr; 1090 std::make_pair(protocol::Debugger::Paused::ReasonEnum::OOM, nullptr));
1077 } else if (!exception.IsEmpty()) { 1091 } else if (!exception.IsEmpty()) {
1078 InjectedScript* injectedScript = nullptr; 1092 InjectedScript* injectedScript = nullptr;
1079 m_session->findInjectedScript(contextId, injectedScript); 1093 m_session->findInjectedScript(contextId, injectedScript);
1080 if (injectedScript) { 1094 if (injectedScript) {
1081 m_breakReason = 1095 String16 breakReason =
1082 isPromiseRejection 1096 isPromiseRejection
1083 ? protocol::Debugger::Paused::ReasonEnum::PromiseRejection 1097 ? protocol::Debugger::Paused::ReasonEnum::PromiseRejection
1084 : protocol::Debugger::Paused::ReasonEnum::Exception; 1098 : protocol::Debugger::Paused::ReasonEnum::Exception;
1085 std::unique_ptr<protocol::Runtime::RemoteObject> obj; 1099 std::unique_ptr<protocol::Runtime::RemoteObject> obj;
1086 injectedScript->wrapObject(exception, kBacktraceObjectGroup, false, false, 1100 injectedScript->wrapObject(exception, kBacktraceObjectGroup, false, false,
1087 &obj); 1101 &obj);
1102 std::unique_ptr<protocol::DictionaryValue> breakAuxData;
1088 if (obj) { 1103 if (obj) {
1089 m_breakAuxData = obj->toValue(); 1104 breakAuxData = obj->toValue();
1090 m_breakAuxData->setBoolean("uncaught", isUncaught); 1105 breakAuxData->setBoolean("uncaught", isUncaught);
1091 } else { 1106 } else {
1092 m_breakAuxData = nullptr; 1107 breakAuxData = nullptr;
1093 } 1108 }
1094 // m_breakAuxData might be null after this. 1109 hitReasons.push_back(
1110 std::make_pair(breakReason, std::move(breakAuxData)));
1095 } 1111 }
1096 } 1112 }
1097 1113
1098 std::unique_ptr<Array<String16>> hitBreakpointIds = Array<String16>::create(); 1114 std::unique_ptr<Array<String16>> hitBreakpointIds = Array<String16>::create();
1099 1115
1116 bool hasDebugCommandBreakpointReason = false;
1100 for (const auto& point : hitBreakpoints) { 1117 for (const auto& point : hitBreakpoints) {
1101 DebugServerBreakpointToBreakpointIdAndSourceMap::iterator 1118 DebugServerBreakpointToBreakpointIdAndSourceMap::iterator
1102 breakpointIterator = m_serverBreakpoints.find(point); 1119 breakpointIterator = m_serverBreakpoints.find(point);
1103 if (breakpointIterator != m_serverBreakpoints.end()) { 1120 if (breakpointIterator != m_serverBreakpoints.end()) {
1104 const String16& localId = breakpointIterator->second.first; 1121 const String16& localId = breakpointIterator->second.first;
1105 hitBreakpointIds->addItem(localId); 1122 hitBreakpointIds->addItem(localId);
1106 1123
1107 BreakpointSource source = breakpointIterator->second.second; 1124 BreakpointSource source = breakpointIterator->second.second;
1108 if (m_breakReason == protocol::Debugger::Paused::ReasonEnum::Other && 1125 if (!hasDebugCommandBreakpointReason &&
1109 source == DebugCommandBreakpointSource) 1126 source == DebugCommandBreakpointSource) {
1110 m_breakReason = protocol::Debugger::Paused::ReasonEnum::DebugCommand; 1127 hasDebugCommandBreakpointReason = true;
1128 hitReasons.push_back(std::make_pair(
1129 protocol::Debugger::Paused::ReasonEnum::DebugCommand, nullptr));
1130 }
1111 } 1131 }
1112 } 1132 }
1113 1133
1134 for (size_t i = 0; i < m_breakReason.size(); ++i) {
1135 hitReasons.push_back(std::move(m_breakReason[i]));
1136 }
1137 clearBreakDetails();
1138
1139 String16 breakReason = protocol::Debugger::Paused::ReasonEnum::Other;
1140 std::unique_ptr<protocol::DictionaryValue> breakAuxData;
1141 if (hitReasons.size() == 1) {
1142 breakReason = hitReasons[0].first;
1143 breakAuxData = std::move(hitReasons[0].second);
1144 } else if (hitReasons.size() > 1) {
1145 breakReason = protocol::Debugger::Paused::ReasonEnum::Ambiguous;
1146 std::unique_ptr<protocol::ListValue> reasons =
1147 protocol::ListValue::create();
1148 for (size_t i = 0; i < hitReasons.size(); ++i) {
1149 std::unique_ptr<protocol::DictionaryValue> reason =
1150 protocol::DictionaryValue::create();
1151 reason->setString("reason", hitReasons[i].first);
1152 if (hitReasons[i].second)
1153 reason->setObject("auxData", std::move(hitReasons[i].second));
1154 reasons->pushValue(std::move(reason));
1155 }
1156 breakAuxData = protocol::DictionaryValue::create();
1157 breakAuxData->setArray("reasons", std::move(reasons));
1158 }
1159
1114 std::unique_ptr<Array<CallFrame>> protocolCallFrames; 1160 std::unique_ptr<Array<CallFrame>> protocolCallFrames;
1115 Response response = currentCallFrames(&protocolCallFrames); 1161 Response response = currentCallFrames(&protocolCallFrames);
1116 if (!response.isSuccess()) protocolCallFrames = Array<CallFrame>::create(); 1162 if (!response.isSuccess()) protocolCallFrames = Array<CallFrame>::create();
1117 m_frontend.paused(std::move(protocolCallFrames), m_breakReason, 1163 m_frontend.paused(std::move(protocolCallFrames), breakReason,
1118 std::move(m_breakAuxData), std::move(hitBreakpointIds), 1164 std::move(breakAuxData), std::move(hitBreakpointIds),
1119 currentAsyncStackTrace()); 1165 currentAsyncStackTrace());
1120 m_scheduledDebuggerStep = NoStep; 1166 m_scheduledDebuggerStep = NoStep;
1121 m_javaScriptPauseScheduled = false; 1167 m_javaScriptPauseScheduled = false;
1122 1168
1123 if (!m_continueToLocationBreakpointId.isEmpty()) { 1169 if (!m_continueToLocationBreakpointId.isEmpty()) {
1124 m_debugger->removeBreakpoint(m_continueToLocationBreakpointId); 1170 m_debugger->removeBreakpoint(m_continueToLocationBreakpointId);
1125 m_continueToLocationBreakpointId = ""; 1171 m_continueToLocationBreakpointId = "";
1126 } 1172 }
1127 } 1173 }
1128 1174
1129 void V8DebuggerAgentImpl::didContinue() { 1175 void V8DebuggerAgentImpl::didContinue() {
1130 JavaScriptCallFrames emptyCallFrames; 1176 JavaScriptCallFrames emptyCallFrames;
1131 m_pausedCallFrames.swap(emptyCallFrames); 1177 m_pausedCallFrames.swap(emptyCallFrames);
1132 clearBreakDetails(); 1178 clearBreakDetails();
1133 m_frontend.resumed(); 1179 m_frontend.resumed();
1134 } 1180 }
1135 1181
1136 void V8DebuggerAgentImpl::breakProgram( 1182 void V8DebuggerAgentImpl::breakProgram(
1137 const String16& breakReason, 1183 const String16& breakReason,
1138 std::unique_ptr<protocol::DictionaryValue> data) { 1184 std::unique_ptr<protocol::DictionaryValue> data) {
1139 if (!enabled() || !m_debugger->canBreakProgram() || m_skipAllPauses) return; 1185 if (!enabled() || !m_debugger->canBreakProgram() || m_skipAllPauses) return;
1140 m_breakReason = breakReason; 1186 std::vector<BreakReason> currentScheduledReason;
1141 m_breakAuxData = std::move(data); 1187 currentScheduledReason.swap(m_breakReason);
1188 pushBreakDetails(breakReason, std::move(data));
1142 m_scheduledDebuggerStep = NoStep; 1189 m_scheduledDebuggerStep = NoStep;
1143 m_debugger->breakProgram(); 1190 m_debugger->breakProgram();
1191 popBreakDetails();
1192 m_breakReason.swap(currentScheduledReason);
1144 } 1193 }
1145 1194
1146 void V8DebuggerAgentImpl::breakProgramOnException( 1195 void V8DebuggerAgentImpl::breakProgramOnException(
1147 const String16& breakReason, 1196 const String16& breakReason,
1148 std::unique_ptr<protocol::DictionaryValue> data) { 1197 std::unique_ptr<protocol::DictionaryValue> data) {
1149 if (!enabled() || 1198 if (!enabled() ||
1150 m_debugger->getPauseOnExceptionsState() == v8::debug::NoBreakOnException) 1199 m_debugger->getPauseOnExceptionsState() == v8::debug::NoBreakOnException)
1151 return; 1200 return;
1152 breakProgram(breakReason, std::move(data)); 1201 breakProgram(breakReason, std::move(data));
1153 } 1202 }
1154 1203
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, 1204 void V8DebuggerAgentImpl::setBreakpointAt(const String16& scriptId,
1161 int lineNumber, int columnNumber, 1205 int lineNumber, int columnNumber,
1162 BreakpointSource source, 1206 BreakpointSource source,
1163 const String16& condition) { 1207 const String16& condition) {
1164 ScriptBreakpoint breakpoint(scriptId, lineNumber, columnNumber, condition); 1208 ScriptBreakpoint breakpoint(scriptId, lineNumber, columnNumber, condition);
1165 String16 breakpointId = generateBreakpointId(breakpoint, source); 1209 String16 breakpointId = generateBreakpointId(breakpoint, source);
1166 resolveBreakpoint(breakpointId, breakpoint, source); 1210 resolveBreakpoint(breakpointId, breakpoint, source);
1167 } 1211 }
1168 1212
1169 void V8DebuggerAgentImpl::removeBreakpointAt(const String16& scriptId, 1213 void V8DebuggerAgentImpl::removeBreakpointAt(const String16& scriptId,
1170 int lineNumber, int columnNumber, 1214 int lineNumber, int columnNumber,
1171 BreakpointSource source) { 1215 BreakpointSource source) {
1172 removeBreakpointImpl(generateBreakpointId( 1216 removeBreakpointImpl(generateBreakpointId(
1173 ScriptBreakpoint(scriptId, lineNumber, columnNumber, String16()), 1217 ScriptBreakpoint(scriptId, lineNumber, columnNumber, String16()),
1174 source)); 1218 source));
1175 } 1219 }
1176 1220
1177 void V8DebuggerAgentImpl::reset() { 1221 void V8DebuggerAgentImpl::reset() {
1178 if (!enabled()) return; 1222 if (!enabled()) return;
1179 m_scheduledDebuggerStep = NoStep; 1223 m_scheduledDebuggerStep = NoStep;
1180 m_blackboxedPositions.clear(); 1224 m_blackboxedPositions.clear();
1181 resetBlackboxedStateCache(); 1225 resetBlackboxedStateCache();
1182 m_scripts.clear(); 1226 m_scripts.clear();
1183 m_breakpointIdToDebuggerBreakpointIds.clear(); 1227 m_breakpointIdToDebuggerBreakpointIds.clear();
1184 } 1228 }
1185 1229
1186 } // namespace v8_inspector 1230 } // namespace v8_inspector
OLDNEW
« no previous file with comments | « src/inspector/v8-debugger-agent-impl.h ('k') | test/inspector/debugger/framework-nested-scheduled-break.js » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698