| 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 36 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 47 // Breakpoint properties. | 47 // Breakpoint properties. |
| 48 static const char url[] = "url"; | 48 static const char url[] = "url"; |
| 49 static const char isRegex[] = "isRegex"; | 49 static const char isRegex[] = "isRegex"; |
| 50 static const char lineNumber[] = "lineNumber"; | 50 static const char lineNumber[] = "lineNumber"; |
| 51 static const char columnNumber[] = "columnNumber"; | 51 static const char columnNumber[] = "columnNumber"; |
| 52 static const char condition[] = "condition"; | 52 static const char condition[] = "condition"; |
| 53 static const char skipAllPauses[] = "skipAllPauses"; | 53 static const char skipAllPauses[] = "skipAllPauses"; |
| 54 | 54 |
| 55 } // namespace DebuggerAgentState | 55 } // namespace DebuggerAgentState |
| 56 | 56 |
| 57 static const int maxSkipStepFrameCount = 128; | 57 static const int kMaxSkipStepFrameCount = 128; |
| 58 static const char backtraceObjectGroup[] = "backtrace"; | 58 static const char kBacktraceObjectGroup[] = "backtrace"; |
| 59 static const char kDebuggerNotEnabled[] = "Debugger agent is not enabled"; |
| 60 static const char kDebuggerNotPaused[] = |
| 61 "Can only perform operation while paused."; |
| 59 | 62 |
| 60 static String16 breakpointIdSuffix( | 63 static String16 breakpointIdSuffix( |
| 61 V8DebuggerAgentImpl::BreakpointSource source) { | 64 V8DebuggerAgentImpl::BreakpointSource source) { |
| 62 switch (source) { | 65 switch (source) { |
| 63 case V8DebuggerAgentImpl::UserBreakpointSource: | 66 case V8DebuggerAgentImpl::UserBreakpointSource: |
| 64 break; | 67 break; |
| 65 case V8DebuggerAgentImpl::DebugCommandBreakpointSource: | 68 case V8DebuggerAgentImpl::DebugCommandBreakpointSource: |
| 66 return ":debug"; | 69 return ":debug"; |
| 67 case V8DebuggerAgentImpl::MonitorCommandBreakpointSource: | 70 case V8DebuggerAgentImpl::MonitorCommandBreakpointSource: |
| 68 return ":monitor"; | 71 return ":monitor"; |
| 69 } | 72 } |
| 70 return String16(); | 73 return String16(); |
| 71 } | 74 } |
| 72 | 75 |
| 73 static String16 generateBreakpointId( | 76 static String16 generateBreakpointId( |
| 74 const String16& scriptId, int lineNumber, int columnNumber, | 77 const String16& scriptId, int lineNumber, int columnNumber, |
| 75 V8DebuggerAgentImpl::BreakpointSource source) { | 78 V8DebuggerAgentImpl::BreakpointSource source) { |
| 76 return scriptId + ":" + String16::fromInteger(lineNumber) + ":" + | 79 return scriptId + ":" + String16::fromInteger(lineNumber) + ":" + |
| 77 String16::fromInteger(columnNumber) + breakpointIdSuffix(source); | 80 String16::fromInteger(columnNumber) + breakpointIdSuffix(source); |
| 78 } | 81 } |
| 79 | 82 |
| 80 static bool positionComparator(const std::pair<int, int>& a, | 83 static bool positionComparator(const std::pair<int, int>& a, |
| 81 const std::pair<int, int>& b) { | 84 const std::pair<int, int>& b) { |
| 82 if (a.first != b.first) return a.first < b.first; | 85 if (a.first != b.first) return a.first < b.first; |
| 83 return a.second < b.second; | 86 return a.second < b.second; |
| 84 } | 87 } |
| 85 | 88 |
| 86 static bool hasInternalError(ErrorString* errorString, bool hasError) { | |
| 87 if (hasError) *errorString = "Internal error"; | |
| 88 return hasError; | |
| 89 } | |
| 90 | |
| 91 static std::unique_ptr<protocol::Debugger::Location> buildProtocolLocation( | 89 static std::unique_ptr<protocol::Debugger::Location> buildProtocolLocation( |
| 92 const String16& scriptId, int lineNumber, int columnNumber) { | 90 const String16& scriptId, int lineNumber, int columnNumber) { |
| 93 return protocol::Debugger::Location::create() | 91 return protocol::Debugger::Location::create() |
| 94 .setScriptId(scriptId) | 92 .setScriptId(scriptId) |
| 95 .setLineNumber(lineNumber) | 93 .setLineNumber(lineNumber) |
| 96 .setColumnNumber(columnNumber) | 94 .setColumnNumber(columnNumber) |
| 97 .build(); | 95 .build(); |
| 98 } | 96 } |
| 99 | 97 |
| 100 V8DebuggerAgentImpl::V8DebuggerAgentImpl( | 98 V8DebuggerAgentImpl::V8DebuggerAgentImpl( |
| (...skipping 14 matching lines...) Expand all Loading... |
| 115 m_pausingOnNativeEvent(false), | 113 m_pausingOnNativeEvent(false), |
| 116 m_skippedStepFrameCount(0), | 114 m_skippedStepFrameCount(0), |
| 117 m_recursionLevelForStepOut(0), | 115 m_recursionLevelForStepOut(0), |
| 118 m_recursionLevelForStepFrame(0), | 116 m_recursionLevelForStepFrame(0), |
| 119 m_skipAllPauses(false) { | 117 m_skipAllPauses(false) { |
| 120 clearBreakDetails(); | 118 clearBreakDetails(); |
| 121 } | 119 } |
| 122 | 120 |
| 123 V8DebuggerAgentImpl::~V8DebuggerAgentImpl() {} | 121 V8DebuggerAgentImpl::~V8DebuggerAgentImpl() {} |
| 124 | 122 |
| 125 bool V8DebuggerAgentImpl::checkEnabled(ErrorString* errorString) { | 123 void V8DebuggerAgentImpl::enableImpl() { |
| 126 if (enabled()) return true; | |
| 127 *errorString = "Debugger agent is not enabled"; | |
| 128 return false; | |
| 129 } | |
| 130 | |
| 131 void V8DebuggerAgentImpl::enable() { | |
| 132 // m_inspector->addListener may result in reporting all parsed scripts to | 124 // m_inspector->addListener may result in reporting all parsed scripts to |
| 133 // the agent so it should already be in enabled state by then. | 125 // the agent so it should already be in enabled state by then. |
| 134 m_enabled = true; | 126 m_enabled = true; |
| 135 m_state->setBoolean(DebuggerAgentState::debuggerEnabled, true); | 127 m_state->setBoolean(DebuggerAgentState::debuggerEnabled, true); |
| 136 m_debugger->enable(); | 128 m_debugger->enable(); |
| 137 | 129 |
| 138 std::vector<std::unique_ptr<V8DebuggerScript>> compiledScripts; | 130 std::vector<std::unique_ptr<V8DebuggerScript>> compiledScripts; |
| 139 m_debugger->getCompiledScripts(m_session->contextGroupId(), compiledScripts); | 131 m_debugger->getCompiledScripts(m_session->contextGroupId(), compiledScripts); |
| 140 for (size_t i = 0; i < compiledScripts.size(); i++) | 132 for (size_t i = 0; i < compiledScripts.size(); i++) |
| 141 didParseSource(std::move(compiledScripts[i]), true); | 133 didParseSource(std::move(compiledScripts[i]), true); |
| 142 | 134 |
| 143 // FIXME(WK44513): breakpoints activated flag should be synchronized between | 135 // FIXME(WK44513): breakpoints activated flag should be synchronized between |
| 144 // all front-ends | 136 // all front-ends |
| 145 m_debugger->setBreakpointsActivated(true); | 137 m_debugger->setBreakpointsActivated(true); |
| 146 } | 138 } |
| 147 | 139 |
| 148 bool V8DebuggerAgentImpl::enabled() { return m_enabled; } | 140 bool V8DebuggerAgentImpl::enabled() { return m_enabled; } |
| 149 | 141 |
| 150 void V8DebuggerAgentImpl::enable(ErrorString* errorString) { | 142 Response V8DebuggerAgentImpl::enable() { |
| 151 if (enabled()) return; | 143 if (enabled()) return Response::OK(); |
| 152 | 144 |
| 153 if (!m_inspector->client()->canExecuteScripts(m_session->contextGroupId())) { | 145 if (!m_inspector->client()->canExecuteScripts(m_session->contextGroupId())) |
| 154 *errorString = "Script execution is prohibited"; | 146 return Response::Error("Script execution is prohibited"); |
| 155 return; | |
| 156 } | |
| 157 | 147 |
| 158 enable(); | 148 enableImpl(); |
| 149 return Response::OK(); |
| 159 } | 150 } |
| 160 | 151 |
| 161 void V8DebuggerAgentImpl::disable(ErrorString*) { | 152 Response V8DebuggerAgentImpl::disable() { |
| 162 if (!enabled()) return; | 153 if (!enabled()) return Response::OK(); |
| 163 | 154 |
| 164 m_state->setObject(DebuggerAgentState::javaScriptBreakpoints, | 155 m_state->setObject(DebuggerAgentState::javaScriptBreakpoints, |
| 165 protocol::DictionaryValue::create()); | 156 protocol::DictionaryValue::create()); |
| 166 m_state->setInteger(DebuggerAgentState::pauseOnExceptionsState, | 157 m_state->setInteger(DebuggerAgentState::pauseOnExceptionsState, |
| 167 v8::DebugInterface::NoBreakOnException); | 158 v8::DebugInterface::NoBreakOnException); |
| 168 m_state->setInteger(DebuggerAgentState::asyncCallStackDepth, 0); | 159 m_state->setInteger(DebuggerAgentState::asyncCallStackDepth, 0); |
| 169 | 160 |
| 170 if (!m_pausedContext.IsEmpty()) m_debugger->continueProgram(); | 161 if (!m_pausedContext.IsEmpty()) m_debugger->continueProgram(); |
| 171 m_debugger->disable(); | 162 m_debugger->disable(); |
| 172 m_pausedContext.Reset(); | 163 m_pausedContext.Reset(); |
| (...skipping 10 matching lines...) Expand all Loading... |
| 183 m_javaScriptPauseScheduled = false; | 174 m_javaScriptPauseScheduled = false; |
| 184 m_steppingFromFramework = false; | 175 m_steppingFromFramework = false; |
| 185 m_pausingOnNativeEvent = false; | 176 m_pausingOnNativeEvent = false; |
| 186 m_skippedStepFrameCount = 0; | 177 m_skippedStepFrameCount = 0; |
| 187 m_recursionLevelForStepFrame = 0; | 178 m_recursionLevelForStepFrame = 0; |
| 188 m_skipAllPauses = false; | 179 m_skipAllPauses = false; |
| 189 m_blackboxPattern = nullptr; | 180 m_blackboxPattern = nullptr; |
| 190 m_state->remove(DebuggerAgentState::blackboxPattern); | 181 m_state->remove(DebuggerAgentState::blackboxPattern); |
| 191 m_enabled = false; | 182 m_enabled = false; |
| 192 m_state->setBoolean(DebuggerAgentState::debuggerEnabled, false); | 183 m_state->setBoolean(DebuggerAgentState::debuggerEnabled, false); |
| 184 return Response::OK(); |
| 193 } | 185 } |
| 194 | 186 |
| 195 void V8DebuggerAgentImpl::restore() { | 187 void V8DebuggerAgentImpl::restore() { |
| 196 DCHECK(!m_enabled); | 188 DCHECK(!m_enabled); |
| 197 if (!m_state->booleanProperty(DebuggerAgentState::debuggerEnabled, false)) | 189 if (!m_state->booleanProperty(DebuggerAgentState::debuggerEnabled, false)) |
| 198 return; | 190 return; |
| 199 if (!m_inspector->client()->canExecuteScripts(m_session->contextGroupId())) | 191 if (!m_inspector->client()->canExecuteScripts(m_session->contextGroupId())) |
| 200 return; | 192 return; |
| 201 | 193 |
| 202 enable(); | 194 enableImpl(); |
| 203 | 195 |
| 204 int pauseState = v8::DebugInterface::NoBreakOnException; | 196 int pauseState = v8::DebugInterface::NoBreakOnException; |
| 205 m_state->getInteger(DebuggerAgentState::pauseOnExceptionsState, &pauseState); | 197 m_state->getInteger(DebuggerAgentState::pauseOnExceptionsState, &pauseState); |
| 206 setPauseOnExceptionsImpl(pauseState); | 198 setPauseOnExceptionsImpl(pauseState); |
| 207 | 199 |
| 208 m_skipAllPauses = | 200 m_skipAllPauses = |
| 209 m_state->booleanProperty(DebuggerAgentState::skipAllPauses, false); | 201 m_state->booleanProperty(DebuggerAgentState::skipAllPauses, false); |
| 210 | 202 |
| 211 int asyncCallStackDepth = 0; | 203 int asyncCallStackDepth = 0; |
| 212 m_state->getInteger(DebuggerAgentState::asyncCallStackDepth, | 204 m_state->getInteger(DebuggerAgentState::asyncCallStackDepth, |
| 213 &asyncCallStackDepth); | 205 &asyncCallStackDepth); |
| 214 m_debugger->setAsyncCallStackDepth(this, asyncCallStackDepth); | 206 m_debugger->setAsyncCallStackDepth(this, asyncCallStackDepth); |
| 215 | 207 |
| 216 String16 blackboxPattern; | 208 String16 blackboxPattern; |
| 217 if (m_state->getString(DebuggerAgentState::blackboxPattern, | 209 if (m_state->getString(DebuggerAgentState::blackboxPattern, |
| 218 &blackboxPattern)) { | 210 &blackboxPattern)) { |
| 219 ErrorString error; | 211 setBlackboxPattern(blackboxPattern); |
| 220 if (!setBlackboxPattern(&error, blackboxPattern)) UNREACHABLE(); | |
| 221 } | 212 } |
| 222 } | 213 } |
| 223 | 214 |
| 224 void V8DebuggerAgentImpl::setBreakpointsActive(ErrorString* errorString, | 215 Response V8DebuggerAgentImpl::setBreakpointsActive(bool active) { |
| 225 bool active) { | 216 if (!enabled()) return Response::Error(kDebuggerNotEnabled); |
| 226 if (!checkEnabled(errorString)) return; | |
| 227 m_debugger->setBreakpointsActivated(active); | 217 m_debugger->setBreakpointsActivated(active); |
| 218 return Response::OK(); |
| 228 } | 219 } |
| 229 | 220 |
| 230 void V8DebuggerAgentImpl::setSkipAllPauses(ErrorString*, bool skip) { | 221 Response V8DebuggerAgentImpl::setSkipAllPauses(bool skip) { |
| 231 m_skipAllPauses = skip; | 222 m_skipAllPauses = skip; |
| 232 m_state->setBoolean(DebuggerAgentState::skipAllPauses, m_skipAllPauses); | 223 m_state->setBoolean(DebuggerAgentState::skipAllPauses, m_skipAllPauses); |
| 224 return Response::OK(); |
| 233 } | 225 } |
| 234 | 226 |
| 235 static std::unique_ptr<protocol::DictionaryValue> | 227 static std::unique_ptr<protocol::DictionaryValue> |
| 236 buildObjectForBreakpointCookie(const String16& url, int lineNumber, | 228 buildObjectForBreakpointCookie(const String16& url, int lineNumber, |
| 237 int columnNumber, const String16& condition, | 229 int columnNumber, const String16& condition, |
| 238 bool isRegex) { | 230 bool isRegex) { |
| 239 std::unique_ptr<protocol::DictionaryValue> breakpointObject = | 231 std::unique_ptr<protocol::DictionaryValue> breakpointObject = |
| 240 protocol::DictionaryValue::create(); | 232 protocol::DictionaryValue::create(); |
| 241 breakpointObject->setString(DebuggerAgentState::url, url); | 233 breakpointObject->setString(DebuggerAgentState::url, url); |
| 242 breakpointObject->setInteger(DebuggerAgentState::lineNumber, lineNumber); | 234 breakpointObject->setInteger(DebuggerAgentState::lineNumber, lineNumber); |
| 243 breakpointObject->setInteger(DebuggerAgentState::columnNumber, columnNumber); | 235 breakpointObject->setInteger(DebuggerAgentState::columnNumber, columnNumber); |
| 244 breakpointObject->setString(DebuggerAgentState::condition, condition); | 236 breakpointObject->setString(DebuggerAgentState::condition, condition); |
| 245 breakpointObject->setBoolean(DebuggerAgentState::isRegex, isRegex); | 237 breakpointObject->setBoolean(DebuggerAgentState::isRegex, isRegex); |
| 246 return breakpointObject; | 238 return breakpointObject; |
| 247 } | 239 } |
| 248 | 240 |
| 249 static bool matches(V8InspectorImpl* inspector, const String16& url, | 241 static bool matches(V8InspectorImpl* inspector, const String16& url, |
| 250 const String16& pattern, bool isRegex) { | 242 const String16& pattern, bool isRegex) { |
| 251 if (isRegex) { | 243 if (isRegex) { |
| 252 V8Regex regex(inspector, pattern, true); | 244 V8Regex regex(inspector, pattern, true); |
| 253 return regex.match(url) != -1; | 245 return regex.match(url) != -1; |
| 254 } | 246 } |
| 255 return url == pattern; | 247 return url == pattern; |
| 256 } | 248 } |
| 257 | 249 |
| 258 void V8DebuggerAgentImpl::setBreakpointByUrl( | 250 Response V8DebuggerAgentImpl::setBreakpointByUrl( |
| 259 ErrorString* errorString, int lineNumber, | 251 int lineNumber, Maybe<String16> optionalURL, |
| 260 const Maybe<String16>& optionalURL, const Maybe<String16>& optionalURLRegex, | 252 Maybe<String16> optionalURLRegex, Maybe<int> optionalColumnNumber, |
| 261 const Maybe<int>& optionalColumnNumber, | 253 Maybe<String16> optionalCondition, String16* outBreakpointId, |
| 262 const Maybe<String16>& optionalCondition, String16* outBreakpointId, | |
| 263 std::unique_ptr<protocol::Array<protocol::Debugger::Location>>* locations) { | 254 std::unique_ptr<protocol::Array<protocol::Debugger::Location>>* locations) { |
| 264 *locations = Array<protocol::Debugger::Location>::create(); | 255 *locations = Array<protocol::Debugger::Location>::create(); |
| 265 if (optionalURL.isJust() == optionalURLRegex.isJust()) { | 256 if (optionalURL.isJust() == optionalURLRegex.isJust()) |
| 266 *errorString = "Either url or urlRegex must be specified."; | 257 return Response::Error("Either url or urlRegex must be specified."); |
| 267 return; | |
| 268 } | |
| 269 | 258 |
| 270 String16 url = optionalURL.isJust() ? optionalURL.fromJust() | 259 String16 url = optionalURL.isJust() ? optionalURL.fromJust() |
| 271 : optionalURLRegex.fromJust(); | 260 : optionalURLRegex.fromJust(); |
| 272 int columnNumber = 0; | 261 int columnNumber = 0; |
| 273 if (optionalColumnNumber.isJust()) { | 262 if (optionalColumnNumber.isJust()) { |
| 274 columnNumber = optionalColumnNumber.fromJust(); | 263 columnNumber = optionalColumnNumber.fromJust(); |
| 275 if (columnNumber < 0) { | 264 if (columnNumber < 0) return Response::Error("Incorrect column number"); |
| 276 *errorString = "Incorrect column number"; | |
| 277 return; | |
| 278 } | |
| 279 } | 265 } |
| 280 String16 condition = optionalCondition.fromMaybe(""); | 266 String16 condition = optionalCondition.fromMaybe(""); |
| 281 bool isRegex = optionalURLRegex.isJust(); | 267 bool isRegex = optionalURLRegex.isJust(); |
| 282 | 268 |
| 283 String16 breakpointId = (isRegex ? "/" + url + "/" : url) + ":" + | 269 String16 breakpointId = (isRegex ? "/" + url + "/" : url) + ":" + |
| 284 String16::fromInteger(lineNumber) + ":" + | 270 String16::fromInteger(lineNumber) + ":" + |
| 285 String16::fromInteger(columnNumber); | 271 String16::fromInteger(columnNumber); |
| 286 protocol::DictionaryValue* breakpointsCookie = | 272 protocol::DictionaryValue* breakpointsCookie = |
| 287 m_state->getObject(DebuggerAgentState::javaScriptBreakpoints); | 273 m_state->getObject(DebuggerAgentState::javaScriptBreakpoints); |
| 288 if (!breakpointsCookie) { | 274 if (!breakpointsCookie) { |
| 289 std::unique_ptr<protocol::DictionaryValue> newValue = | 275 std::unique_ptr<protocol::DictionaryValue> newValue = |
| 290 protocol::DictionaryValue::create(); | 276 protocol::DictionaryValue::create(); |
| 291 breakpointsCookie = newValue.get(); | 277 breakpointsCookie = newValue.get(); |
| 292 m_state->setObject(DebuggerAgentState::javaScriptBreakpoints, | 278 m_state->setObject(DebuggerAgentState::javaScriptBreakpoints, |
| 293 std::move(newValue)); | 279 std::move(newValue)); |
| 294 } | 280 } |
| 295 if (breakpointsCookie->get(breakpointId)) { | 281 if (breakpointsCookie->get(breakpointId)) |
| 296 *errorString = "Breakpoint at specified location already exists."; | 282 return Response::Error("Breakpoint at specified location already exists."); |
| 297 return; | |
| 298 } | |
| 299 | 283 |
| 300 breakpointsCookie->setObject( | 284 breakpointsCookie->setObject( |
| 301 breakpointId, buildObjectForBreakpointCookie( | 285 breakpointId, buildObjectForBreakpointCookie( |
| 302 url, lineNumber, columnNumber, condition, isRegex)); | 286 url, lineNumber, columnNumber, condition, isRegex)); |
| 303 | 287 |
| 304 ScriptBreakpoint breakpoint(lineNumber, columnNumber, condition); | 288 ScriptBreakpoint breakpoint(lineNumber, columnNumber, condition); |
| 305 for (const auto& script : m_scripts) { | 289 for (const auto& script : m_scripts) { |
| 306 if (!matches(m_inspector, script.second->sourceURL(), url, isRegex)) | 290 if (!matches(m_inspector, script.second->sourceURL(), url, isRegex)) |
| 307 continue; | 291 continue; |
| 308 std::unique_ptr<protocol::Debugger::Location> location = resolveBreakpoint( | 292 std::unique_ptr<protocol::Debugger::Location> location = resolveBreakpoint( |
| 309 breakpointId, script.first, breakpoint, UserBreakpointSource); | 293 breakpointId, script.first, breakpoint, UserBreakpointSource); |
| 310 if (location) (*locations)->addItem(std::move(location)); | 294 if (location) (*locations)->addItem(std::move(location)); |
| 311 } | 295 } |
| 312 | 296 |
| 313 *outBreakpointId = breakpointId; | 297 *outBreakpointId = breakpointId; |
| 298 return Response::OK(); |
| 314 } | 299 } |
| 315 | 300 |
| 316 static bool parseLocation( | 301 Response V8DebuggerAgentImpl::setBreakpoint( |
| 317 ErrorString* errorString, | |
| 318 std::unique_ptr<protocol::Debugger::Location> location, String16* scriptId, | |
| 319 int* lineNumber, int* columnNumber) { | |
| 320 *scriptId = location->getScriptId(); | |
| 321 *lineNumber = location->getLineNumber(); | |
| 322 *columnNumber = location->getColumnNumber(0); | |
| 323 return true; | |
| 324 } | |
| 325 | |
| 326 void V8DebuggerAgentImpl::setBreakpoint( | |
| 327 ErrorString* errorString, | |
| 328 std::unique_ptr<protocol::Debugger::Location> location, | 302 std::unique_ptr<protocol::Debugger::Location> location, |
| 329 const Maybe<String16>& optionalCondition, String16* outBreakpointId, | 303 Maybe<String16> optionalCondition, String16* outBreakpointId, |
| 330 std::unique_ptr<protocol::Debugger::Location>* actualLocation) { | 304 std::unique_ptr<protocol::Debugger::Location>* actualLocation) { |
| 331 String16 scriptId; | 305 String16 scriptId = location->getScriptId(); |
| 332 int lineNumber; | 306 int lineNumber = location->getLineNumber(); |
| 333 int columnNumber; | 307 int columnNumber = location->getColumnNumber(0); |
| 334 | |
| 335 if (!parseLocation(errorString, std::move(location), &scriptId, &lineNumber, | |
| 336 &columnNumber)) | |
| 337 return; | |
| 338 | 308 |
| 339 String16 condition = optionalCondition.fromMaybe(""); | 309 String16 condition = optionalCondition.fromMaybe(""); |
| 340 | 310 |
| 341 String16 breakpointId = generateBreakpointId( | 311 String16 breakpointId = generateBreakpointId( |
| 342 scriptId, lineNumber, columnNumber, UserBreakpointSource); | 312 scriptId, lineNumber, columnNumber, UserBreakpointSource); |
| 343 if (m_breakpointIdToDebuggerBreakpointIds.find(breakpointId) != | 313 if (m_breakpointIdToDebuggerBreakpointIds.find(breakpointId) != |
| 344 m_breakpointIdToDebuggerBreakpointIds.end()) { | 314 m_breakpointIdToDebuggerBreakpointIds.end()) { |
| 345 *errorString = "Breakpoint at specified location already exists."; | 315 return Response::Error("Breakpoint at specified location already exists."); |
| 346 return; | |
| 347 } | 316 } |
| 348 ScriptBreakpoint breakpoint(lineNumber, columnNumber, condition); | 317 ScriptBreakpoint breakpoint(lineNumber, columnNumber, condition); |
| 349 *actualLocation = resolveBreakpoint(breakpointId, scriptId, breakpoint, | 318 *actualLocation = resolveBreakpoint(breakpointId, scriptId, breakpoint, |
| 350 UserBreakpointSource); | 319 UserBreakpointSource); |
| 351 if (*actualLocation) | 320 if (!*actualLocation) return Response::Error("Could not resolve breakpoint"); |
| 352 *outBreakpointId = breakpointId; | 321 *outBreakpointId = breakpointId; |
| 353 else | 322 return Response::OK(); |
| 354 *errorString = "Could not resolve breakpoint"; | |
| 355 } | 323 } |
| 356 | 324 |
| 357 void V8DebuggerAgentImpl::removeBreakpoint(ErrorString* errorString, | 325 Response V8DebuggerAgentImpl::removeBreakpoint(const String16& breakpointId) { |
| 358 const String16& breakpointId) { | 326 if (!enabled()) return Response::Error(kDebuggerNotEnabled); |
| 359 if (!checkEnabled(errorString)) return; | |
| 360 protocol::DictionaryValue* breakpointsCookie = | 327 protocol::DictionaryValue* breakpointsCookie = |
| 361 m_state->getObject(DebuggerAgentState::javaScriptBreakpoints); | 328 m_state->getObject(DebuggerAgentState::javaScriptBreakpoints); |
| 362 if (breakpointsCookie) breakpointsCookie->remove(breakpointId); | 329 if (breakpointsCookie) breakpointsCookie->remove(breakpointId); |
| 363 removeBreakpoint(breakpointId); | 330 removeBreakpointImpl(breakpointId); |
| 331 return Response::OK(); |
| 364 } | 332 } |
| 365 | 333 |
| 366 void V8DebuggerAgentImpl::removeBreakpoint(const String16& breakpointId) { | 334 void V8DebuggerAgentImpl::removeBreakpointImpl(const String16& breakpointId) { |
| 367 DCHECK(enabled()); | 335 DCHECK(enabled()); |
| 368 BreakpointIdToDebuggerBreakpointIdsMap::iterator | 336 BreakpointIdToDebuggerBreakpointIdsMap::iterator |
| 369 debuggerBreakpointIdsIterator = | 337 debuggerBreakpointIdsIterator = |
| 370 m_breakpointIdToDebuggerBreakpointIds.find(breakpointId); | 338 m_breakpointIdToDebuggerBreakpointIds.find(breakpointId); |
| 371 if (debuggerBreakpointIdsIterator == | 339 if (debuggerBreakpointIdsIterator == |
| 372 m_breakpointIdToDebuggerBreakpointIds.end()) | 340 m_breakpointIdToDebuggerBreakpointIds.end()) |
| 373 return; | 341 return; |
| 374 const std::vector<String16>& ids = debuggerBreakpointIdsIterator->second; | 342 const std::vector<String16>& ids = debuggerBreakpointIdsIterator->second; |
| 375 for (size_t i = 0; i < ids.size(); ++i) { | 343 for (size_t i = 0; i < ids.size(); ++i) { |
| 376 const String16& debuggerBreakpointId = ids[i]; | 344 const String16& debuggerBreakpointId = ids[i]; |
| 377 | 345 |
| 378 m_debugger->removeBreakpoint(debuggerBreakpointId); | 346 m_debugger->removeBreakpoint(debuggerBreakpointId); |
| 379 m_serverBreakpoints.erase(debuggerBreakpointId); | 347 m_serverBreakpoints.erase(debuggerBreakpointId); |
| 380 } | 348 } |
| 381 m_breakpointIdToDebuggerBreakpointIds.erase(breakpointId); | 349 m_breakpointIdToDebuggerBreakpointIds.erase(breakpointId); |
| 382 } | 350 } |
| 383 | 351 |
| 384 void V8DebuggerAgentImpl::continueToLocation( | 352 Response V8DebuggerAgentImpl::continueToLocation( |
| 385 ErrorString* errorString, | |
| 386 std::unique_ptr<protocol::Debugger::Location> location) { | 353 std::unique_ptr<protocol::Debugger::Location> location) { |
| 387 if (!checkEnabled(errorString)) return; | 354 if (!enabled()) return Response::Error(kDebuggerNotEnabled); |
| 388 if (!m_continueToLocationBreakpointId.isEmpty()) { | 355 if (!m_continueToLocationBreakpointId.isEmpty()) { |
| 389 m_debugger->removeBreakpoint(m_continueToLocationBreakpointId); | 356 m_debugger->removeBreakpoint(m_continueToLocationBreakpointId); |
| 390 m_continueToLocationBreakpointId = ""; | 357 m_continueToLocationBreakpointId = ""; |
| 391 } | 358 } |
| 392 | 359 |
| 393 String16 scriptId; | 360 String16 scriptId = location->getScriptId(); |
| 394 int lineNumber; | 361 int lineNumber = location->getLineNumber(); |
| 395 int columnNumber; | 362 int columnNumber = location->getColumnNumber(0); |
| 396 | |
| 397 if (!parseLocation(errorString, std::move(location), &scriptId, &lineNumber, | |
| 398 &columnNumber)) | |
| 399 return; | |
| 400 | 363 |
| 401 ScriptBreakpoint breakpoint(lineNumber, columnNumber, ""); | 364 ScriptBreakpoint breakpoint(lineNumber, columnNumber, ""); |
| 402 m_continueToLocationBreakpointId = m_debugger->setBreakpoint( | 365 m_continueToLocationBreakpointId = m_debugger->setBreakpoint( |
| 403 scriptId, breakpoint, &lineNumber, &columnNumber); | 366 scriptId, breakpoint, &lineNumber, &columnNumber); |
| 404 resume(errorString); | 367 return resume(); |
| 405 } | 368 } |
| 406 | 369 |
| 407 bool V8DebuggerAgentImpl::isCurrentCallStackEmptyOrBlackboxed() { | 370 bool V8DebuggerAgentImpl::isCurrentCallStackEmptyOrBlackboxed() { |
| 408 DCHECK(enabled()); | 371 DCHECK(enabled()); |
| 409 JavaScriptCallFrames callFrames = m_debugger->currentCallFrames(); | 372 JavaScriptCallFrames callFrames = m_debugger->currentCallFrames(); |
| 410 for (size_t index = 0; index < callFrames.size(); ++index) { | 373 for (size_t index = 0; index < callFrames.size(); ++index) { |
| 411 if (!isCallFrameWithUnknownScriptOrBlackboxed(callFrames[index].get())) | 374 if (!isCallFrameWithUnknownScriptOrBlackboxed(callFrames[index].get())) |
| 412 return false; | 375 return false; |
| 413 } | 376 } |
| 414 return true; | 377 return true; |
| (...skipping 50 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 465 if (m_steppingFromFramework) return RequestNoSkip; | 428 if (m_steppingFromFramework) return RequestNoSkip; |
| 466 | 429 |
| 467 if (m_skipNextDebuggerStepOut) { | 430 if (m_skipNextDebuggerStepOut) { |
| 468 m_skipNextDebuggerStepOut = false; | 431 m_skipNextDebuggerStepOut = false; |
| 469 if (m_scheduledDebuggerStep == StepOut) return RequestStepOut; | 432 if (m_scheduledDebuggerStep == StepOut) return RequestStepOut; |
| 470 } | 433 } |
| 471 | 434 |
| 472 if (!isCallFrameWithUnknownScriptOrBlackboxed(topCallFrame)) | 435 if (!isCallFrameWithUnknownScriptOrBlackboxed(topCallFrame)) |
| 473 return RequestNoSkip; | 436 return RequestNoSkip; |
| 474 | 437 |
| 475 if (m_skippedStepFrameCount >= maxSkipStepFrameCount) return RequestStepOut; | 438 if (m_skippedStepFrameCount >= kMaxSkipStepFrameCount) return RequestStepOut; |
| 476 | 439 |
| 477 if (!m_skippedStepFrameCount) m_recursionLevelForStepFrame = 1; | 440 if (!m_skippedStepFrameCount) m_recursionLevelForStepFrame = 1; |
| 478 | 441 |
| 479 ++m_skippedStepFrameCount; | 442 ++m_skippedStepFrameCount; |
| 480 return RequestStepFrame; | 443 return RequestStepFrame; |
| 481 } | 444 } |
| 482 | 445 |
| 483 std::unique_ptr<protocol::Debugger::Location> | 446 std::unique_ptr<protocol::Debugger::Location> |
| 484 V8DebuggerAgentImpl::resolveBreakpoint(const String16& breakpointId, | 447 V8DebuggerAgentImpl::resolveBreakpoint(const String16& breakpointId, |
| 485 const String16& scriptId, | 448 const String16& scriptId, |
| (...skipping 17 matching lines...) Expand all Loading... |
| 503 | 466 |
| 504 m_serverBreakpoints[debuggerBreakpointId] = | 467 m_serverBreakpoints[debuggerBreakpointId] = |
| 505 std::make_pair(breakpointId, source); | 468 std::make_pair(breakpointId, source); |
| 506 CHECK(!breakpointId.isEmpty()); | 469 CHECK(!breakpointId.isEmpty()); |
| 507 | 470 |
| 508 m_breakpointIdToDebuggerBreakpointIds[breakpointId].push_back( | 471 m_breakpointIdToDebuggerBreakpointIds[breakpointId].push_back( |
| 509 debuggerBreakpointId); | 472 debuggerBreakpointId); |
| 510 return buildProtocolLocation(scriptId, actualLineNumber, actualColumnNumber); | 473 return buildProtocolLocation(scriptId, actualLineNumber, actualColumnNumber); |
| 511 } | 474 } |
| 512 | 475 |
| 513 void V8DebuggerAgentImpl::searchInContent( | 476 Response V8DebuggerAgentImpl::searchInContent( |
| 514 ErrorString* error, const String16& scriptId, const String16& query, | 477 const String16& scriptId, const String16& query, |
| 515 const Maybe<bool>& optionalCaseSensitive, | 478 Maybe<bool> optionalCaseSensitive, Maybe<bool> optionalIsRegex, |
| 516 const Maybe<bool>& optionalIsRegex, | |
| 517 std::unique_ptr<Array<protocol::Debugger::SearchMatch>>* results) { | 479 std::unique_ptr<Array<protocol::Debugger::SearchMatch>>* results) { |
| 518 v8::HandleScope handles(m_isolate); | 480 v8::HandleScope handles(m_isolate); |
| 519 ScriptsMap::iterator it = m_scripts.find(scriptId); | 481 ScriptsMap::iterator it = m_scripts.find(scriptId); |
| 520 if (it == m_scripts.end()) { | 482 if (it == m_scripts.end()) |
| 521 *error = String16("No script for id: " + scriptId); | 483 return Response::Error("No script for id: " + scriptId); |
| 522 return; | |
| 523 } | |
| 524 | 484 |
| 525 std::vector<std::unique_ptr<protocol::Debugger::SearchMatch>> matches = | 485 std::vector<std::unique_ptr<protocol::Debugger::SearchMatch>> matches = |
| 526 searchInTextByLinesImpl(m_session, | 486 searchInTextByLinesImpl(m_session, |
| 527 toProtocolString(it->second->source(m_isolate)), | 487 toProtocolString(it->second->source(m_isolate)), |
| 528 query, optionalCaseSensitive.fromMaybe(false), | 488 query, optionalCaseSensitive.fromMaybe(false), |
| 529 optionalIsRegex.fromMaybe(false)); | 489 optionalIsRegex.fromMaybe(false)); |
| 530 *results = protocol::Array<protocol::Debugger::SearchMatch>::create(); | 490 *results = protocol::Array<protocol::Debugger::SearchMatch>::create(); |
| 531 for (size_t i = 0; i < matches.size(); ++i) | 491 for (size_t i = 0; i < matches.size(); ++i) |
| 532 (*results)->addItem(std::move(matches[i])); | 492 (*results)->addItem(std::move(matches[i])); |
| 493 return Response::OK(); |
| 533 } | 494 } |
| 534 | 495 |
| 535 void V8DebuggerAgentImpl::setScriptSource( | 496 Response V8DebuggerAgentImpl::setScriptSource( |
| 536 ErrorString* errorString, const String16& scriptId, | 497 const String16& scriptId, const String16& newContent, Maybe<bool> dryRun, |
| 537 const String16& newContent, const Maybe<bool>& dryRun, | |
| 538 Maybe<protocol::Array<protocol::Debugger::CallFrame>>* newCallFrames, | 498 Maybe<protocol::Array<protocol::Debugger::CallFrame>>* newCallFrames, |
| 539 Maybe<bool>* stackChanged, Maybe<StackTrace>* asyncStackTrace, | 499 Maybe<bool>* stackChanged, Maybe<StackTrace>* asyncStackTrace, |
| 540 Maybe<protocol::Runtime::ExceptionDetails>* optOutCompileError) { | 500 Maybe<protocol::Runtime::ExceptionDetails>* optOutCompileError) { |
| 541 if (!checkEnabled(errorString)) return; | 501 if (!enabled()) return Response::Error(kDebuggerNotEnabled); |
| 542 | 502 |
| 543 v8::HandleScope handles(m_isolate); | 503 v8::HandleScope handles(m_isolate); |
| 544 v8::Local<v8::String> newSource = toV8String(m_isolate, newContent); | 504 v8::Local<v8::String> newSource = toV8String(m_isolate, newContent); |
| 545 if (!m_debugger->setScriptSource(scriptId, newSource, dryRun.fromMaybe(false), | 505 bool compileError = false; |
| 546 errorString, optOutCompileError, | 506 Response response = m_debugger->setScriptSource( |
| 547 &m_pausedCallFrames, stackChanged)) | 507 scriptId, newSource, dryRun.fromMaybe(false), optOutCompileError, |
| 548 return; | 508 &m_pausedCallFrames, stackChanged, &compileError); |
| 509 if (!response.isSuccess() || compileError) return response; |
| 549 | 510 |
| 550 ScriptsMap::iterator it = m_scripts.find(scriptId); | 511 ScriptsMap::iterator it = m_scripts.find(scriptId); |
| 551 if (it != m_scripts.end()) it->second->setSource(m_isolate, newSource); | 512 if (it != m_scripts.end()) it->second->setSource(m_isolate, newSource); |
| 552 | 513 |
| 553 std::unique_ptr<Array<CallFrame>> callFrames = currentCallFrames(errorString); | 514 std::unique_ptr<Array<CallFrame>> callFrames; |
| 554 if (!callFrames) return; | 515 response = currentCallFrames(&callFrames); |
| 516 if (!response.isSuccess()) return response; |
| 555 *newCallFrames = std::move(callFrames); | 517 *newCallFrames = std::move(callFrames); |
| 556 *asyncStackTrace = currentAsyncStackTrace(); | 518 *asyncStackTrace = currentAsyncStackTrace(); |
| 519 return Response::OK(); |
| 557 } | 520 } |
| 558 | 521 |
| 559 void V8DebuggerAgentImpl::restartFrame( | 522 Response V8DebuggerAgentImpl::restartFrame( |
| 560 ErrorString* errorString, const String16& callFrameId, | 523 const String16& callFrameId, |
| 561 std::unique_ptr<Array<CallFrame>>* newCallFrames, | 524 std::unique_ptr<Array<CallFrame>>* newCallFrames, |
| 562 Maybe<StackTrace>* asyncStackTrace) { | 525 Maybe<StackTrace>* asyncStackTrace) { |
| 563 if (!assertPaused(errorString)) return; | 526 if (m_pausedContext.IsEmpty()) return Response::Error(kDebuggerNotPaused); |
| 564 InjectedScript::CallFrameScope scope(m_inspector, m_session->contextGroupId(), | 527 InjectedScript::CallFrameScope scope(m_inspector, m_session->contextGroupId(), |
| 565 callFrameId); | 528 callFrameId); |
| 566 Response response = scope.initialize(); | 529 Response response = scope.initialize(); |
| 567 if (!response.isSuccess()) { | 530 if (!response.isSuccess()) return response; |
| 568 *errorString = response.errorMessage(); | 531 if (scope.frameOrdinal() >= m_pausedCallFrames.size()) |
| 569 return; | 532 return Response::Error("Could not find call frame with given id"); |
| 570 } | |
| 571 if (scope.frameOrdinal() >= m_pausedCallFrames.size()) { | |
| 572 *errorString = "Could not find call frame with given id"; | |
| 573 return; | |
| 574 } | |
| 575 | 533 |
| 576 v8::Local<v8::Value> resultValue; | 534 v8::Local<v8::Value> resultValue; |
| 577 v8::Local<v8::Boolean> result; | 535 v8::Local<v8::Boolean> result; |
| 578 if (!m_pausedCallFrames[scope.frameOrdinal()]->restart().ToLocal( | 536 if (!m_pausedCallFrames[scope.frameOrdinal()]->restart().ToLocal( |
| 579 &resultValue) || | 537 &resultValue) || |
| 580 scope.tryCatch().HasCaught() || | 538 scope.tryCatch().HasCaught() || |
| 581 !resultValue->ToBoolean(scope.context()).ToLocal(&result) || | 539 !resultValue->ToBoolean(scope.context()).ToLocal(&result) || |
| 582 !result->Value()) { | 540 !result->Value()) { |
| 583 *errorString = "Internal error"; | 541 return Response::InternalError(); |
| 584 return; | |
| 585 } | 542 } |
| 586 JavaScriptCallFrames frames = m_debugger->currentCallFrames(); | 543 JavaScriptCallFrames frames = m_debugger->currentCallFrames(); |
| 587 m_pausedCallFrames.swap(frames); | 544 m_pausedCallFrames.swap(frames); |
| 588 | 545 |
| 589 *newCallFrames = currentCallFrames(errorString); | 546 response = currentCallFrames(newCallFrames); |
| 590 if (!*newCallFrames) return; | 547 if (!response.isSuccess()) return response; |
| 591 *asyncStackTrace = currentAsyncStackTrace(); | 548 *asyncStackTrace = currentAsyncStackTrace(); |
| 549 return Response::OK(); |
| 592 } | 550 } |
| 593 | 551 |
| 594 void V8DebuggerAgentImpl::getScriptSource(ErrorString* error, | 552 Response V8DebuggerAgentImpl::getScriptSource(const String16& scriptId, |
| 595 const String16& scriptId, | 553 String16* scriptSource) { |
| 596 String16* scriptSource) { | 554 if (!enabled()) return Response::Error(kDebuggerNotEnabled); |
| 597 if (!checkEnabled(error)) return; | |
| 598 ScriptsMap::iterator it = m_scripts.find(scriptId); | 555 ScriptsMap::iterator it = m_scripts.find(scriptId); |
| 599 if (it == m_scripts.end()) { | 556 if (it == m_scripts.end()) |
| 600 *error = "No script for id: " + scriptId; | 557 return Response::Error("No script for id: " + scriptId); |
| 601 return; | |
| 602 } | |
| 603 v8::HandleScope handles(m_isolate); | 558 v8::HandleScope handles(m_isolate); |
| 604 *scriptSource = toProtocolString(it->second->source(m_isolate)); | 559 *scriptSource = toProtocolString(it->second->source(m_isolate)); |
| 560 return Response::OK(); |
| 605 } | 561 } |
| 606 | 562 |
| 607 void V8DebuggerAgentImpl::schedulePauseOnNextStatement( | 563 void V8DebuggerAgentImpl::schedulePauseOnNextStatement( |
| 608 const String16& breakReason, | 564 const String16& breakReason, |
| 609 std::unique_ptr<protocol::DictionaryValue> data) { | 565 std::unique_ptr<protocol::DictionaryValue> data) { |
| 610 if (!enabled() || m_scheduledDebuggerStep == StepInto || | 566 if (!enabled() || m_scheduledDebuggerStep == StepInto || |
| 611 m_javaScriptPauseScheduled || m_debugger->isPaused() || | 567 m_javaScriptPauseScheduled || m_debugger->isPaused() || |
| 612 !m_debugger->breakpointsActivated()) | 568 !m_debugger->breakpointsActivated()) |
| 613 return; | 569 return; |
| 614 m_breakReason = breakReason; | 570 m_breakReason = breakReason; |
| (...skipping 15 matching lines...) Expand all Loading... |
| 630 m_debugger->setPauseOnNextStatement(true); | 586 m_debugger->setPauseOnNextStatement(true); |
| 631 } | 587 } |
| 632 | 588 |
| 633 void V8DebuggerAgentImpl::cancelPauseOnNextStatement() { | 589 void V8DebuggerAgentImpl::cancelPauseOnNextStatement() { |
| 634 if (m_javaScriptPauseScheduled || m_debugger->isPaused()) return; | 590 if (m_javaScriptPauseScheduled || m_debugger->isPaused()) return; |
| 635 clearBreakDetails(); | 591 clearBreakDetails(); |
| 636 m_pausingOnNativeEvent = false; | 592 m_pausingOnNativeEvent = false; |
| 637 m_debugger->setPauseOnNextStatement(false); | 593 m_debugger->setPauseOnNextStatement(false); |
| 638 } | 594 } |
| 639 | 595 |
| 640 void V8DebuggerAgentImpl::pause(ErrorString* errorString) { | 596 Response V8DebuggerAgentImpl::pause() { |
| 641 if (!checkEnabled(errorString)) return; | 597 if (!enabled()) return Response::Error(kDebuggerNotEnabled); |
| 642 if (m_javaScriptPauseScheduled || m_debugger->isPaused()) return; | 598 if (m_javaScriptPauseScheduled || m_debugger->isPaused()) |
| 599 return Response::OK(); |
| 643 clearBreakDetails(); | 600 clearBreakDetails(); |
| 644 m_javaScriptPauseScheduled = true; | 601 m_javaScriptPauseScheduled = true; |
| 645 m_scheduledDebuggerStep = NoStep; | 602 m_scheduledDebuggerStep = NoStep; |
| 646 m_skippedStepFrameCount = 0; | 603 m_skippedStepFrameCount = 0; |
| 647 m_steppingFromFramework = false; | 604 m_steppingFromFramework = false; |
| 648 m_debugger->setPauseOnNextStatement(true); | 605 m_debugger->setPauseOnNextStatement(true); |
| 606 return Response::OK(); |
| 649 } | 607 } |
| 650 | 608 |
| 651 void V8DebuggerAgentImpl::resume(ErrorString* errorString) { | 609 Response V8DebuggerAgentImpl::resume() { |
| 652 if (!assertPaused(errorString)) return; | 610 if (m_pausedContext.IsEmpty()) return Response::Error(kDebuggerNotPaused); |
| 653 m_scheduledDebuggerStep = NoStep; | 611 m_scheduledDebuggerStep = NoStep; |
| 654 m_steppingFromFramework = false; | 612 m_steppingFromFramework = false; |
| 655 m_session->releaseObjectGroup(backtraceObjectGroup); | 613 m_session->releaseObjectGroup(kBacktraceObjectGroup); |
| 656 m_debugger->continueProgram(); | 614 m_debugger->continueProgram(); |
| 615 return Response::OK(); |
| 657 } | 616 } |
| 658 | 617 |
| 659 void V8DebuggerAgentImpl::stepOver(ErrorString* errorString) { | 618 Response V8DebuggerAgentImpl::stepOver() { |
| 660 if (!assertPaused(errorString)) return; | 619 if (m_pausedContext.IsEmpty()) return Response::Error(kDebuggerNotPaused); |
| 661 // StepOver at function return point should fallback to StepInto. | 620 // StepOver at function return point should fallback to StepInto. |
| 662 JavaScriptCallFrame* frame = | 621 JavaScriptCallFrame* frame = |
| 663 !m_pausedCallFrames.empty() ? m_pausedCallFrames[0].get() : nullptr; | 622 !m_pausedCallFrames.empty() ? m_pausedCallFrames[0].get() : nullptr; |
| 664 if (frame && frame->isAtReturn()) { | 623 if (frame && frame->isAtReturn()) return stepInto(); |
| 665 stepInto(errorString); | |
| 666 return; | |
| 667 } | |
| 668 m_scheduledDebuggerStep = StepOver; | 624 m_scheduledDebuggerStep = StepOver; |
| 669 m_steppingFromFramework = isTopPausedCallFrameBlackboxed(); | 625 m_steppingFromFramework = isTopPausedCallFrameBlackboxed(); |
| 670 m_session->releaseObjectGroup(backtraceObjectGroup); | 626 m_session->releaseObjectGroup(kBacktraceObjectGroup); |
| 671 m_debugger->stepOverStatement(); | 627 m_debugger->stepOverStatement(); |
| 628 return Response::OK(); |
| 672 } | 629 } |
| 673 | 630 |
| 674 void V8DebuggerAgentImpl::stepInto(ErrorString* errorString) { | 631 Response V8DebuggerAgentImpl::stepInto() { |
| 675 if (!assertPaused(errorString)) return; | 632 if (m_pausedContext.IsEmpty()) return Response::Error(kDebuggerNotPaused); |
| 676 m_scheduledDebuggerStep = StepInto; | 633 m_scheduledDebuggerStep = StepInto; |
| 677 m_steppingFromFramework = isTopPausedCallFrameBlackboxed(); | 634 m_steppingFromFramework = isTopPausedCallFrameBlackboxed(); |
| 678 m_session->releaseObjectGroup(backtraceObjectGroup); | 635 m_session->releaseObjectGroup(kBacktraceObjectGroup); |
| 679 m_debugger->stepIntoStatement(); | 636 m_debugger->stepIntoStatement(); |
| 637 return Response::OK(); |
| 680 } | 638 } |
| 681 | 639 |
| 682 void V8DebuggerAgentImpl::stepOut(ErrorString* errorString) { | 640 Response V8DebuggerAgentImpl::stepOut() { |
| 683 if (!assertPaused(errorString)) return; | 641 if (m_pausedContext.IsEmpty()) return Response::Error(kDebuggerNotPaused); |
| 684 m_scheduledDebuggerStep = StepOut; | 642 m_scheduledDebuggerStep = StepOut; |
| 685 m_skipNextDebuggerStepOut = false; | 643 m_skipNextDebuggerStepOut = false; |
| 686 m_recursionLevelForStepOut = 1; | 644 m_recursionLevelForStepOut = 1; |
| 687 m_steppingFromFramework = isTopPausedCallFrameBlackboxed(); | 645 m_steppingFromFramework = isTopPausedCallFrameBlackboxed(); |
| 688 m_session->releaseObjectGroup(backtraceObjectGroup); | 646 m_session->releaseObjectGroup(kBacktraceObjectGroup); |
| 689 m_debugger->stepOutOfFunction(); | 647 m_debugger->stepOutOfFunction(); |
| 648 return Response::OK(); |
| 690 } | 649 } |
| 691 | 650 |
| 692 void V8DebuggerAgentImpl::setPauseOnExceptions( | 651 Response V8DebuggerAgentImpl::setPauseOnExceptions( |
| 693 ErrorString* errorString, const String16& stringPauseState) { | 652 const String16& stringPauseState) { |
| 694 if (!checkEnabled(errorString)) return; | 653 if (!enabled()) return Response::Error(kDebuggerNotEnabled); |
| 695 v8::DebugInterface::ExceptionBreakState pauseState; | 654 v8::DebugInterface::ExceptionBreakState pauseState; |
| 696 if (stringPauseState == "none") { | 655 if (stringPauseState == "none") { |
| 697 pauseState = v8::DebugInterface::NoBreakOnException; | 656 pauseState = v8::DebugInterface::NoBreakOnException; |
| 698 } else if (stringPauseState == "all") { | 657 } else if (stringPauseState == "all") { |
| 699 pauseState = v8::DebugInterface::BreakOnAnyException; | 658 pauseState = v8::DebugInterface::BreakOnAnyException; |
| 700 } else if (stringPauseState == "uncaught") { | 659 } else if (stringPauseState == "uncaught") { |
| 701 pauseState = v8::DebugInterface::BreakOnUncaughtException; | 660 pauseState = v8::DebugInterface::BreakOnUncaughtException; |
| 702 } else { | 661 } else { |
| 703 *errorString = "Unknown pause on exceptions mode: " + stringPauseState; | 662 return Response::Error("Unknown pause on exceptions mode: " + |
| 704 return; | 663 stringPauseState); |
| 705 } | 664 } |
| 706 setPauseOnExceptionsImpl(pauseState); | 665 setPauseOnExceptionsImpl(pauseState); |
| 666 return Response::OK(); |
| 707 } | 667 } |
| 708 | 668 |
| 709 void V8DebuggerAgentImpl::setPauseOnExceptionsImpl(int pauseState) { | 669 void V8DebuggerAgentImpl::setPauseOnExceptionsImpl(int pauseState) { |
| 710 m_debugger->setPauseOnExceptionsState( | 670 m_debugger->setPauseOnExceptionsState( |
| 711 static_cast<v8::DebugInterface::ExceptionBreakState>(pauseState)); | 671 static_cast<v8::DebugInterface::ExceptionBreakState>(pauseState)); |
| 712 m_state->setInteger(DebuggerAgentState::pauseOnExceptionsState, pauseState); | 672 m_state->setInteger(DebuggerAgentState::pauseOnExceptionsState, pauseState); |
| 713 } | 673 } |
| 714 | 674 |
| 715 void V8DebuggerAgentImpl::evaluateOnCallFrame( | 675 Response V8DebuggerAgentImpl::evaluateOnCallFrame( |
| 716 ErrorString* errorString, const String16& callFrameId, | 676 const String16& callFrameId, const String16& expression, |
| 717 const String16& expression, const Maybe<String16>& objectGroup, | 677 Maybe<String16> objectGroup, Maybe<bool> includeCommandLineAPI, |
| 718 const Maybe<bool>& includeCommandLineAPI, const Maybe<bool>& silent, | 678 Maybe<bool> silent, Maybe<bool> returnByValue, Maybe<bool> generatePreview, |
| 719 const Maybe<bool>& returnByValue, const Maybe<bool>& generatePreview, | |
| 720 std::unique_ptr<RemoteObject>* result, | 679 std::unique_ptr<RemoteObject>* result, |
| 721 Maybe<protocol::Runtime::ExceptionDetails>* exceptionDetails) { | 680 Maybe<protocol::Runtime::ExceptionDetails>* exceptionDetails) { |
| 722 if (!assertPaused(errorString)) return; | 681 if (m_pausedContext.IsEmpty()) return Response::Error(kDebuggerNotPaused); |
| 723 InjectedScript::CallFrameScope scope(m_inspector, m_session->contextGroupId(), | 682 InjectedScript::CallFrameScope scope(m_inspector, m_session->contextGroupId(), |
| 724 callFrameId); | 683 callFrameId); |
| 725 Response response = scope.initialize(); | 684 Response response = scope.initialize(); |
| 726 if (!response.isSuccess()) { | 685 if (!response.isSuccess()) return response; |
| 727 *errorString = response.errorMessage(); | 686 if (scope.frameOrdinal() >= m_pausedCallFrames.size()) |
| 728 return; | 687 return Response::Error("Could not find call frame with given id"); |
| 729 } | |
| 730 if (scope.frameOrdinal() >= m_pausedCallFrames.size()) { | |
| 731 *errorString = "Could not find call frame with given id"; | |
| 732 return; | |
| 733 } | |
| 734 | 688 |
| 735 if (includeCommandLineAPI.fromMaybe(false)) scope.installCommandLineAPI(); | 689 if (includeCommandLineAPI.fromMaybe(false)) scope.installCommandLineAPI(); |
| 736 if (silent.fromMaybe(false)) scope.ignoreExceptionsAndMuteConsole(); | 690 if (silent.fromMaybe(false)) scope.ignoreExceptionsAndMuteConsole(); |
| 737 | 691 |
| 738 v8::MaybeLocal<v8::Value> maybeResultValue = | 692 v8::MaybeLocal<v8::Value> maybeResultValue = |
| 739 m_pausedCallFrames[scope.frameOrdinal()]->evaluate( | 693 m_pausedCallFrames[scope.frameOrdinal()]->evaluate( |
| 740 toV8String(m_isolate, expression)); | 694 toV8String(m_isolate, expression)); |
| 741 | 695 |
| 742 // Re-initialize after running client's code, as it could have destroyed | 696 // Re-initialize after running client's code, as it could have destroyed |
| 743 // context or session. | 697 // context or session. |
| 744 response = scope.initialize(); | 698 response = scope.initialize(); |
| 745 if (!response.isSuccess()) { | 699 if (!response.isSuccess()) return response; |
| 746 *errorString = response.errorMessage(); | 700 return scope.injectedScript()->wrapEvaluateResult( |
| 747 return; | |
| 748 } | |
| 749 response = scope.injectedScript()->wrapEvaluateResult( | |
| 750 maybeResultValue, scope.tryCatch(), objectGroup.fromMaybe(""), | 701 maybeResultValue, scope.tryCatch(), objectGroup.fromMaybe(""), |
| 751 returnByValue.fromMaybe(false), generatePreview.fromMaybe(false), result, | 702 returnByValue.fromMaybe(false), generatePreview.fromMaybe(false), result, |
| 752 exceptionDetails); | 703 exceptionDetails); |
| 753 if (!response.isSuccess()) *errorString = response.errorMessage(); | |
| 754 } | 704 } |
| 755 | 705 |
| 756 void V8DebuggerAgentImpl::setVariableValue( | 706 Response V8DebuggerAgentImpl::setVariableValue( |
| 757 ErrorString* errorString, int scopeNumber, const String16& variableName, | 707 int scopeNumber, const String16& variableName, |
| 758 std::unique_ptr<protocol::Runtime::CallArgument> newValueArgument, | 708 std::unique_ptr<protocol::Runtime::CallArgument> newValueArgument, |
| 759 const String16& callFrameId) { | 709 const String16& callFrameId) { |
| 760 if (!checkEnabled(errorString)) return; | 710 if (!enabled()) return Response::Error(kDebuggerNotEnabled); |
| 761 if (!assertPaused(errorString)) return; | 711 if (m_pausedContext.IsEmpty()) return Response::Error(kDebuggerNotPaused); |
| 762 InjectedScript::CallFrameScope scope(m_inspector, m_session->contextGroupId(), | 712 InjectedScript::CallFrameScope scope(m_inspector, m_session->contextGroupId(), |
| 763 callFrameId); | 713 callFrameId); |
| 764 Response response = scope.initialize(); | 714 Response response = scope.initialize(); |
| 765 if (!response.isSuccess()) { | 715 if (!response.isSuccess()) return response; |
| 766 *errorString = response.errorMessage(); | |
| 767 return; | |
| 768 } | |
| 769 v8::Local<v8::Value> newValue; | 716 v8::Local<v8::Value> newValue; |
| 770 response = scope.injectedScript()->resolveCallArgument(newValueArgument.get(), | 717 response = scope.injectedScript()->resolveCallArgument(newValueArgument.get(), |
| 771 &newValue); | 718 &newValue); |
| 772 if (!response.isSuccess()) { | 719 if (!response.isSuccess()) return response; |
| 773 *errorString = response.errorMessage(); | |
| 774 return; | |
| 775 } | |
| 776 | 720 |
| 777 if (scope.frameOrdinal() >= m_pausedCallFrames.size()) { | 721 if (scope.frameOrdinal() >= m_pausedCallFrames.size()) |
| 778 *errorString = "Could not find call frame with given id"; | 722 return Response::Error("Could not find call frame with given id"); |
| 779 return; | |
| 780 } | |
| 781 v8::MaybeLocal<v8::Value> result = | 723 v8::MaybeLocal<v8::Value> result = |
| 782 m_pausedCallFrames[scope.frameOrdinal()]->setVariableValue( | 724 m_pausedCallFrames[scope.frameOrdinal()]->setVariableValue( |
| 783 scopeNumber, toV8String(m_isolate, variableName), newValue); | 725 scopeNumber, toV8String(m_isolate, variableName), newValue); |
| 784 if (scope.tryCatch().HasCaught() || result.IsEmpty()) { | 726 if (scope.tryCatch().HasCaught() || result.IsEmpty()) |
| 785 *errorString = "Internal error"; | 727 return Response::InternalError(); |
| 786 return; | 728 return Response::OK(); |
| 787 } | |
| 788 } | 729 } |
| 789 | 730 |
| 790 void V8DebuggerAgentImpl::setAsyncCallStackDepth(ErrorString* errorString, | 731 Response V8DebuggerAgentImpl::setAsyncCallStackDepth(int depth) { |
| 791 int depth) { | 732 if (!enabled()) return Response::Error(kDebuggerNotEnabled); |
| 792 if (!checkEnabled(errorString)) return; | |
| 793 m_state->setInteger(DebuggerAgentState::asyncCallStackDepth, depth); | 733 m_state->setInteger(DebuggerAgentState::asyncCallStackDepth, depth); |
| 794 m_debugger->setAsyncCallStackDepth(this, depth); | 734 m_debugger->setAsyncCallStackDepth(this, depth); |
| 735 return Response::OK(); |
| 795 } | 736 } |
| 796 | 737 |
| 797 void V8DebuggerAgentImpl::setBlackboxPatterns( | 738 Response V8DebuggerAgentImpl::setBlackboxPatterns( |
| 798 ErrorString* errorString, | |
| 799 std::unique_ptr<protocol::Array<String16>> patterns) { | 739 std::unique_ptr<protocol::Array<String16>> patterns) { |
| 800 if (!patterns->length()) { | 740 if (!patterns->length()) { |
| 801 m_blackboxPattern = nullptr; | 741 m_blackboxPattern = nullptr; |
| 802 m_state->remove(DebuggerAgentState::blackboxPattern); | 742 m_state->remove(DebuggerAgentState::blackboxPattern); |
| 803 return; | 743 return Response::OK(); |
| 804 } | 744 } |
| 805 | 745 |
| 806 String16Builder patternBuilder; | 746 String16Builder patternBuilder; |
| 807 patternBuilder.append('('); | 747 patternBuilder.append('('); |
| 808 for (size_t i = 0; i < patterns->length() - 1; ++i) { | 748 for (size_t i = 0; i < patterns->length() - 1; ++i) { |
| 809 patternBuilder.append(patterns->get(i)); | 749 patternBuilder.append(patterns->get(i)); |
| 810 patternBuilder.append("|"); | 750 patternBuilder.append("|"); |
| 811 } | 751 } |
| 812 patternBuilder.append(patterns->get(patterns->length() - 1)); | 752 patternBuilder.append(patterns->get(patterns->length() - 1)); |
| 813 patternBuilder.append(')'); | 753 patternBuilder.append(')'); |
| 814 String16 pattern = patternBuilder.toString(); | 754 String16 pattern = patternBuilder.toString(); |
| 815 if (!setBlackboxPattern(errorString, pattern)) return; | 755 Response response = setBlackboxPattern(pattern); |
| 756 if (!response.isSuccess()) return response; |
| 816 m_state->setString(DebuggerAgentState::blackboxPattern, pattern); | 757 m_state->setString(DebuggerAgentState::blackboxPattern, pattern); |
| 758 return Response::OK(); |
| 817 } | 759 } |
| 818 | 760 |
| 819 bool V8DebuggerAgentImpl::setBlackboxPattern(ErrorString* errorString, | 761 Response V8DebuggerAgentImpl::setBlackboxPattern(const String16& pattern) { |
| 820 const String16& pattern) { | |
| 821 std::unique_ptr<V8Regex> regex(new V8Regex( | 762 std::unique_ptr<V8Regex> regex(new V8Regex( |
| 822 m_inspector, pattern, true /** caseSensitive */, false /** multiline */)); | 763 m_inspector, pattern, true /** caseSensitive */, false /** multiline */)); |
| 823 if (!regex->isValid()) { | 764 if (!regex->isValid()) |
| 824 *errorString = "Pattern parser error: " + regex->errorMessage(); | 765 return Response::Error("Pattern parser error: " + regex->errorMessage()); |
| 825 return false; | |
| 826 } | |
| 827 m_blackboxPattern = std::move(regex); | 766 m_blackboxPattern = std::move(regex); |
| 828 return true; | 767 return Response::OK(); |
| 829 } | 768 } |
| 830 | 769 |
| 831 void V8DebuggerAgentImpl::setBlackboxedRanges( | 770 Response V8DebuggerAgentImpl::setBlackboxedRanges( |
| 832 ErrorString* error, const String16& scriptId, | 771 const String16& scriptId, |
| 833 std::unique_ptr<protocol::Array<protocol::Debugger::ScriptPosition>> | 772 std::unique_ptr<protocol::Array<protocol::Debugger::ScriptPosition>> |
| 834 inPositions) { | 773 inPositions) { |
| 835 if (m_scripts.find(scriptId) == m_scripts.end()) { | 774 if (m_scripts.find(scriptId) == m_scripts.end()) |
| 836 *error = "No script with passed id."; | 775 return Response::Error("No script with passed id."); |
| 837 return; | |
| 838 } | |
| 839 | 776 |
| 840 if (!inPositions->length()) { | 777 if (!inPositions->length()) { |
| 841 m_blackboxedPositions.erase(scriptId); | 778 m_blackboxedPositions.erase(scriptId); |
| 842 return; | 779 return Response::OK(); |
| 843 } | 780 } |
| 844 | 781 |
| 845 std::vector<std::pair<int, int>> positions; | 782 std::vector<std::pair<int, int>> positions; |
| 846 positions.reserve(inPositions->length()); | 783 positions.reserve(inPositions->length()); |
| 847 for (size_t i = 0; i < inPositions->length(); ++i) { | 784 for (size_t i = 0; i < inPositions->length(); ++i) { |
| 848 protocol::Debugger::ScriptPosition* position = inPositions->get(i); | 785 protocol::Debugger::ScriptPosition* position = inPositions->get(i); |
| 849 if (position->getLineNumber() < 0) { | 786 if (position->getLineNumber() < 0) |
| 850 *error = "Position missing 'line' or 'line' < 0."; | 787 return Response::Error("Position missing 'line' or 'line' < 0."); |
| 851 return; | 788 if (position->getColumnNumber() < 0) |
| 852 } | 789 return Response::Error("Position missing 'column' or 'column' < 0."); |
| 853 if (position->getColumnNumber() < 0) { | |
| 854 *error = "Position missing 'column' or 'column' < 0."; | |
| 855 return; | |
| 856 } | |
| 857 positions.push_back( | 790 positions.push_back( |
| 858 std::make_pair(position->getLineNumber(), position->getColumnNumber())); | 791 std::make_pair(position->getLineNumber(), position->getColumnNumber())); |
| 859 } | 792 } |
| 860 | 793 |
| 861 for (size_t i = 1; i < positions.size(); ++i) { | 794 for (size_t i = 1; i < positions.size(); ++i) { |
| 862 if (positions[i - 1].first < positions[i].first) continue; | 795 if (positions[i - 1].first < positions[i].first) continue; |
| 863 if (positions[i - 1].first == positions[i].first && | 796 if (positions[i - 1].first == positions[i].first && |
| 864 positions[i - 1].second < positions[i].second) | 797 positions[i - 1].second < positions[i].second) |
| 865 continue; | 798 continue; |
| 866 *error = | 799 return Response::Error( |
| 867 "Input positions array is not sorted or contains duplicate values."; | 800 "Input positions array is not sorted or contains duplicate values."); |
| 868 return; | |
| 869 } | 801 } |
| 870 | 802 |
| 871 m_blackboxedPositions[scriptId] = positions; | 803 m_blackboxedPositions[scriptId] = positions; |
| 804 return Response::OK(); |
| 872 } | 805 } |
| 873 | 806 |
| 874 void V8DebuggerAgentImpl::willExecuteScript(int scriptId) { | 807 void V8DebuggerAgentImpl::willExecuteScript(int scriptId) { |
| 875 changeJavaScriptRecursionLevel(+1); | 808 changeJavaScriptRecursionLevel(+1); |
| 876 // Fast return. | 809 // Fast return. |
| 877 if (m_scheduledDebuggerStep != StepInto) return; | 810 if (m_scheduledDebuggerStep != StepInto) return; |
| 878 schedulePauseOnNextStatementIfSteppingInto(); | 811 schedulePauseOnNextStatementIfSteppingInto(); |
| 879 } | 812 } |
| 880 | 813 |
| 881 void V8DebuggerAgentImpl::didExecuteScript() { | 814 void V8DebuggerAgentImpl::didExecuteScript() { |
| (...skipping 32 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 914 // from the old StepFrame. | 847 // from the old StepFrame. |
| 915 m_skippedStepFrameCount = 0; | 848 m_skippedStepFrameCount = 0; |
| 916 if (m_scheduledDebuggerStep == NoStep) | 849 if (m_scheduledDebuggerStep == NoStep) |
| 917 m_debugger->clearStepping(); | 850 m_debugger->clearStepping(); |
| 918 else if (m_scheduledDebuggerStep == StepOut) | 851 else if (m_scheduledDebuggerStep == StepOut) |
| 919 m_skipNextDebuggerStepOut = true; | 852 m_skipNextDebuggerStepOut = true; |
| 920 } | 853 } |
| 921 } | 854 } |
| 922 } | 855 } |
| 923 | 856 |
| 924 std::unique_ptr<Array<CallFrame>> V8DebuggerAgentImpl::currentCallFrames( | 857 Response V8DebuggerAgentImpl::currentCallFrames( |
| 925 ErrorString* errorString) { | 858 std::unique_ptr<Array<CallFrame>>* result) { |
| 926 if (m_pausedContext.IsEmpty() || !m_pausedCallFrames.size()) | 859 if (m_pausedContext.IsEmpty() || !m_pausedCallFrames.size()) { |
| 927 return Array<CallFrame>::create(); | 860 *result = Array<CallFrame>::create(); |
| 861 return Response::OK(); |
| 862 } |
| 928 v8::HandleScope handles(m_isolate); | 863 v8::HandleScope handles(m_isolate); |
| 929 v8::Local<v8::Context> debuggerContext = | 864 v8::Local<v8::Context> debuggerContext = |
| 930 v8::DebugInterface::GetDebugContext(m_isolate); | 865 v8::DebugInterface::GetDebugContext(m_isolate); |
| 931 v8::Context::Scope contextScope(debuggerContext); | 866 v8::Context::Scope contextScope(debuggerContext); |
| 932 | 867 |
| 933 v8::Local<v8::Array> objects = v8::Array::New(m_isolate); | 868 v8::Local<v8::Array> objects = v8::Array::New(m_isolate); |
| 934 | 869 |
| 935 for (size_t frameOrdinal = 0; frameOrdinal < m_pausedCallFrames.size(); | 870 for (size_t frameOrdinal = 0; frameOrdinal < m_pausedCallFrames.size(); |
| 936 ++frameOrdinal) { | 871 ++frameOrdinal) { |
| 937 const std::unique_ptr<JavaScriptCallFrame>& currentCallFrame = | 872 const std::unique_ptr<JavaScriptCallFrame>& currentCallFrame = |
| 938 m_pausedCallFrames[frameOrdinal]; | 873 m_pausedCallFrames[frameOrdinal]; |
| 939 | 874 |
| 940 v8::Local<v8::Object> details = currentCallFrame->details(); | 875 v8::Local<v8::Object> details = currentCallFrame->details(); |
| 941 if (hasInternalError(errorString, details.IsEmpty())) | 876 if (details.IsEmpty()) return Response::InternalError(); |
| 942 return Array<CallFrame>::create(); | |
| 943 | 877 |
| 944 int contextId = currentCallFrame->contextId(); | 878 int contextId = currentCallFrame->contextId(); |
| 945 | 879 |
| 946 InjectedScript* injectedScript = nullptr; | 880 InjectedScript* injectedScript = nullptr; |
| 947 if (contextId) m_session->findInjectedScript(contextId, injectedScript); | 881 if (contextId) m_session->findInjectedScript(contextId, injectedScript); |
| 948 | 882 |
| 949 String16 callFrameId = | 883 String16 callFrameId = |
| 950 RemoteCallFrameId::serialize(contextId, static_cast<int>(frameOrdinal)); | 884 RemoteCallFrameId::serialize(contextId, static_cast<int>(frameOrdinal)); |
| 951 if (hasInternalError( | 885 if (!details |
| 952 errorString, | 886 ->Set(debuggerContext, |
| 953 !details | 887 toV8StringInternalized(m_isolate, "callFrameId"), |
| 954 ->Set(debuggerContext, | 888 toV8String(m_isolate, callFrameId)) |
| 955 toV8StringInternalized(m_isolate, "callFrameId"), | 889 .FromMaybe(false)) { |
| 956 toV8String(m_isolate, callFrameId)) | 890 return Response::InternalError(); |
| 957 .FromMaybe(false))) | 891 } |
| 958 return Array<CallFrame>::create(); | |
| 959 | 892 |
| 960 if (injectedScript) { | 893 if (injectedScript) { |
| 961 v8::Local<v8::Value> scopeChain; | 894 v8::Local<v8::Value> scopeChain; |
| 962 if (hasInternalError( | 895 if (!details |
| 963 errorString, | 896 ->Get(debuggerContext, |
| 964 !details->Get(debuggerContext, | 897 toV8StringInternalized(m_isolate, "scopeChain")) |
| 965 toV8StringInternalized(m_isolate, "scopeChain")) | 898 .ToLocal(&scopeChain) || |
| 966 .ToLocal(&scopeChain) || | 899 !scopeChain->IsArray()) { |
| 967 !scopeChain->IsArray())) | 900 return Response::InternalError(); |
| 968 return Array<CallFrame>::create(); | 901 } |
| 969 v8::Local<v8::Array> scopeChainArray = scopeChain.As<v8::Array>(); | 902 v8::Local<v8::Array> scopeChainArray = scopeChain.As<v8::Array>(); |
| 970 Response response = injectedScript->wrapPropertyInArray( | 903 Response response = injectedScript->wrapPropertyInArray( |
| 971 scopeChainArray, toV8StringInternalized(m_isolate, "object"), | 904 scopeChainArray, toV8StringInternalized(m_isolate, "object"), |
| 972 backtraceObjectGroup); | 905 kBacktraceObjectGroup); |
| 973 if (!response.isSuccess()) { | 906 if (!response.isSuccess()) return response; |
| 974 *errorString = response.errorMessage(); | |
| 975 return Array<CallFrame>::create(); | |
| 976 } | |
| 977 response = injectedScript->wrapObjectProperty( | 907 response = injectedScript->wrapObjectProperty( |
| 978 details, toV8StringInternalized(m_isolate, "this"), | 908 details, toV8StringInternalized(m_isolate, "this"), |
| 979 backtraceObjectGroup); | 909 kBacktraceObjectGroup); |
| 980 if (!response.isSuccess()) { | 910 if (!response.isSuccess()) return response; |
| 981 *errorString = response.errorMessage(); | |
| 982 return Array<CallFrame>::create(); | |
| 983 } | |
| 984 if (details | 911 if (details |
| 985 ->Has(debuggerContext, | 912 ->Has(debuggerContext, |
| 986 toV8StringInternalized(m_isolate, "returnValue")) | 913 toV8StringInternalized(m_isolate, "returnValue")) |
| 987 .FromMaybe(false)) { | 914 .FromMaybe(false)) { |
| 988 response = injectedScript->wrapObjectProperty( | 915 response = injectedScript->wrapObjectProperty( |
| 989 details, toV8StringInternalized(m_isolate, "returnValue"), | 916 details, toV8StringInternalized(m_isolate, "returnValue"), |
| 990 backtraceObjectGroup); | 917 kBacktraceObjectGroup); |
| 991 if (!response.isSuccess()) { | 918 if (!response.isSuccess()) return response; |
| 992 *errorString = response.errorMessage(); | |
| 993 return Array<CallFrame>::create(); | |
| 994 } | |
| 995 } | 919 } |
| 996 } else { | 920 } else { |
| 997 if (hasInternalError(errorString, !details | 921 if (!details |
| 998 ->Set(debuggerContext, | 922 ->Set(debuggerContext, |
| 999 toV8StringInternalized( | 923 toV8StringInternalized(m_isolate, "scopeChain"), |
| 1000 m_isolate, "scopeChain"), | 924 v8::Array::New(m_isolate, 0)) |
| 1001 v8::Array::New(m_isolate, 0)) | 925 .FromMaybe(false)) { |
| 1002 .FromMaybe(false))) | 926 return Response::InternalError(); |
| 1003 return Array<CallFrame>::create(); | 927 } |
| 1004 v8::Local<v8::Object> remoteObject = v8::Object::New(m_isolate); | 928 v8::Local<v8::Object> remoteObject = v8::Object::New(m_isolate); |
| 1005 if (hasInternalError( | 929 if (!remoteObject |
| 1006 errorString, | 930 ->Set(debuggerContext, toV8StringInternalized(m_isolate, "type"), |
| 1007 !remoteObject | 931 toV8StringInternalized(m_isolate, "undefined")) |
| 1008 ->Set(debuggerContext, | 932 .FromMaybe(false)) { |
| 1009 toV8StringInternalized(m_isolate, "type"), | 933 return Response::InternalError(); |
| 1010 toV8StringInternalized(m_isolate, "undefined")) | 934 } |
| 1011 .FromMaybe(false))) | 935 if (!details |
| 1012 return Array<CallFrame>::create(); | 936 ->Set(debuggerContext, toV8StringInternalized(m_isolate, "this"), |
| 1013 if (hasInternalError(errorString, | 937 remoteObject) |
| 1014 !details | 938 .FromMaybe(false)) { |
| 1015 ->Set(debuggerContext, | 939 return Response::InternalError(); |
| 1016 toV8StringInternalized(m_isolate, "this"), | 940 } |
| 1017 remoteObject) | 941 if (!details |
| 1018 .FromMaybe(false))) | 942 ->Delete(debuggerContext, |
| 1019 return Array<CallFrame>::create(); | 943 toV8StringInternalized(m_isolate, "returnValue")) |
| 1020 if (hasInternalError( | 944 .FromMaybe(false)) { |
| 1021 errorString, | 945 return Response::InternalError(); |
| 1022 !details | 946 } |
| 1023 ->Delete(debuggerContext, | |
| 1024 toV8StringInternalized(m_isolate, "returnValue")) | |
| 1025 .FromMaybe(false))) | |
| 1026 return Array<CallFrame>::create(); | |
| 1027 } | 947 } |
| 1028 | 948 |
| 1029 if (hasInternalError( | 949 if (!objects->Set(debuggerContext, static_cast<int>(frameOrdinal), details) |
| 1030 errorString, | 950 .FromMaybe(false)) { |
| 1031 !objects | 951 return Response::InternalError(); |
| 1032 ->Set(debuggerContext, static_cast<int>(frameOrdinal), details) | 952 } |
| 1033 .FromMaybe(false))) | |
| 1034 return Array<CallFrame>::create(); | |
| 1035 } | 953 } |
| 1036 | 954 |
| 1037 std::unique_ptr<protocol::Value> protocolValue; | 955 std::unique_ptr<protocol::Value> protocolValue; |
| 1038 Response response = toProtocolValue(debuggerContext, objects, &protocolValue); | 956 Response response = toProtocolValue(debuggerContext, objects, &protocolValue); |
| 1039 if (!response.isSuccess()) return Array<CallFrame>::create(); | 957 if (!response.isSuccess()) return response; |
| 1040 protocol::ErrorSupport errorSupport; | 958 protocol::ErrorSupport errorSupport; |
| 1041 std::unique_ptr<Array<CallFrame>> callFrames = | 959 *result = Array<CallFrame>::parse(protocolValue.get(), &errorSupport); |
| 1042 Array<CallFrame>::parse(protocolValue.get(), &errorSupport); | 960 if (!*result) return Response::Error(errorSupport.errors()); |
| 1043 if (hasInternalError(errorString, !callFrames)) | 961 return Response::OK(); |
| 1044 return Array<CallFrame>::create(); | |
| 1045 return callFrames; | |
| 1046 } | 962 } |
| 1047 | 963 |
| 1048 std::unique_ptr<StackTrace> V8DebuggerAgentImpl::currentAsyncStackTrace() { | 964 std::unique_ptr<StackTrace> V8DebuggerAgentImpl::currentAsyncStackTrace() { |
| 1049 if (m_pausedContext.IsEmpty()) return nullptr; | 965 if (m_pausedContext.IsEmpty()) return nullptr; |
| 1050 V8StackTraceImpl* stackTrace = m_debugger->currentAsyncCallChain(); | 966 V8StackTraceImpl* stackTrace = m_debugger->currentAsyncCallChain(); |
| 1051 return stackTrace ? stackTrace->buildInspectorObjectForTail(m_debugger) | 967 return stackTrace ? stackTrace->buildInspectorObjectForTail(m_debugger) |
| 1052 : nullptr; | 968 : nullptr; |
| 1053 } | 969 } |
| 1054 | 970 |
| 1055 void V8DebuggerAgentImpl::didParseSource( | 971 void V8DebuggerAgentImpl::didParseSource( |
| 1056 std::unique_ptr<V8DebuggerScript> script, bool success) { | 972 std::unique_ptr<V8DebuggerScript> script, bool success) { |
| 1057 v8::HandleScope handles(m_isolate); | 973 v8::HandleScope handles(m_isolate); |
| 1058 String16 scriptSource = toProtocolString(script->source(m_isolate)); | 974 String16 scriptSource = toProtocolString(script->source(m_isolate)); |
| 1059 if (!success) script->setSourceURL(findSourceURL(scriptSource, false)); | 975 if (!success) script->setSourceURL(findSourceURL(scriptSource, false)); |
| 1060 if (!success) | 976 if (!success) |
| 1061 script->setSourceMappingURL(findSourceMapURL(scriptSource, false)); | 977 script->setSourceMappingURL(findSourceMapURL(scriptSource, false)); |
| 1062 | 978 |
| 1063 std::unique_ptr<protocol::DictionaryValue> executionContextAuxData; | 979 std::unique_ptr<protocol::DictionaryValue> executionContextAuxData; |
| 1064 if (!script->executionContextAuxData().isEmpty()) | 980 if (!script->executionContextAuxData().isEmpty()) |
| 1065 executionContextAuxData = protocol::DictionaryValue::cast( | 981 executionContextAuxData = protocol::DictionaryValue::cast( |
| 1066 protocol::parseJSON(script->executionContextAuxData())); | 982 protocol::parseJSON(script->executionContextAuxData())); |
| 1067 bool isLiveEdit = script->isLiveEdit(); | 983 bool isLiveEdit = script->isLiveEdit(); |
| 1068 bool hasSourceURL = script->hasSourceURL(); | 984 bool hasSourceURL = script->hasSourceURL(); |
| 1069 String16 scriptId = script->scriptId(); | 985 String16 scriptId = script->scriptId(); |
| 1070 String16 scriptURL = script->sourceURL(); | 986 String16 scriptURL = script->sourceURL(); |
| 1071 | 987 |
| 1072 const Maybe<String16>& sourceMapURLParam = script->sourceMappingURL(); | 988 Maybe<String16> sourceMapURLParam = script->sourceMappingURL(); |
| 1073 const Maybe<protocol::DictionaryValue>& executionContextAuxDataParam( | 989 Maybe<protocol::DictionaryValue> executionContextAuxDataParam( |
| 1074 std::move(executionContextAuxData)); | 990 std::move(executionContextAuxData)); |
| 1075 const bool* isLiveEditParam = isLiveEdit ? &isLiveEdit : nullptr; | 991 const bool* isLiveEditParam = isLiveEdit ? &isLiveEdit : nullptr; |
| 1076 const bool* hasSourceURLParam = hasSourceURL ? &hasSourceURL : nullptr; | 992 const bool* hasSourceURLParam = hasSourceURL ? &hasSourceURL : nullptr; |
| 1077 if (success) | 993 if (success) |
| 1078 m_frontend.scriptParsed( | 994 m_frontend.scriptParsed( |
| 1079 scriptId, scriptURL, script->startLine(), script->startColumn(), | 995 scriptId, scriptURL, script->startLine(), script->startColumn(), |
| 1080 script->endLine(), script->endColumn(), script->executionContextId(), | 996 script->endLine(), script->endColumn(), script->executionContextId(), |
| 1081 script->hash(), executionContextAuxDataParam, isLiveEditParam, | 997 script->hash(), std::move(executionContextAuxDataParam), |
| 1082 sourceMapURLParam, hasSourceURLParam); | 998 isLiveEditParam, std::move(sourceMapURLParam), hasSourceURLParam); |
| 1083 else | 999 else |
| 1084 m_frontend.scriptFailedToParse( | 1000 m_frontend.scriptFailedToParse( |
| 1085 scriptId, scriptURL, script->startLine(), script->startColumn(), | 1001 scriptId, scriptURL, script->startLine(), script->startColumn(), |
| 1086 script->endLine(), script->endColumn(), script->executionContextId(), | 1002 script->endLine(), script->endColumn(), script->executionContextId(), |
| 1087 script->hash(), executionContextAuxDataParam, sourceMapURLParam, | 1003 script->hash(), std::move(executionContextAuxDataParam), |
| 1088 hasSourceURLParam); | 1004 std::move(sourceMapURLParam), hasSourceURLParam); |
| 1089 | 1005 |
| 1090 m_scripts[scriptId] = std::move(script); | 1006 m_scripts[scriptId] = std::move(script); |
| 1091 | 1007 |
| 1092 if (scriptURL.isEmpty() || !success) return; | 1008 if (scriptURL.isEmpty() || !success) return; |
| 1093 | 1009 |
| 1094 protocol::DictionaryValue* breakpointsCookie = | 1010 protocol::DictionaryValue* breakpointsCookie = |
| 1095 m_state->getObject(DebuggerAgentState::javaScriptBreakpoints); | 1011 m_state->getObject(DebuggerAgentState::javaScriptBreakpoints); |
| 1096 if (!breakpointsCookie) return; | 1012 if (!breakpointsCookie) return; |
| 1097 | 1013 |
| 1098 for (size_t i = 0; i < breakpointsCookie->size(); ++i) { | 1014 for (size_t i = 0; i < breakpointsCookie->size(); ++i) { |
| (...skipping 54 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 1153 if (!exception.IsEmpty()) { | 1069 if (!exception.IsEmpty()) { |
| 1154 InjectedScript* injectedScript = nullptr; | 1070 InjectedScript* injectedScript = nullptr; |
| 1155 m_session->findInjectedScript(V8Debugger::contextId(context), | 1071 m_session->findInjectedScript(V8Debugger::contextId(context), |
| 1156 injectedScript); | 1072 injectedScript); |
| 1157 if (injectedScript) { | 1073 if (injectedScript) { |
| 1158 m_breakReason = | 1074 m_breakReason = |
| 1159 isPromiseRejection | 1075 isPromiseRejection |
| 1160 ? protocol::Debugger::Paused::ReasonEnum::PromiseRejection | 1076 ? protocol::Debugger::Paused::ReasonEnum::PromiseRejection |
| 1161 : protocol::Debugger::Paused::ReasonEnum::Exception; | 1077 : protocol::Debugger::Paused::ReasonEnum::Exception; |
| 1162 std::unique_ptr<protocol::Runtime::RemoteObject> obj; | 1078 std::unique_ptr<protocol::Runtime::RemoteObject> obj; |
| 1163 injectedScript->wrapObject(exception, backtraceObjectGroup, false, false, | 1079 injectedScript->wrapObject(exception, kBacktraceObjectGroup, false, false, |
| 1164 &obj); | 1080 &obj); |
| 1165 m_breakAuxData = obj ? obj->serialize() : nullptr; | 1081 m_breakAuxData = obj ? obj->serialize() : nullptr; |
| 1166 // m_breakAuxData might be null after this. | 1082 // m_breakAuxData might be null after this. |
| 1167 } | 1083 } |
| 1168 } | 1084 } |
| 1169 | 1085 |
| 1170 std::unique_ptr<Array<String16>> hitBreakpointIds = Array<String16>::create(); | 1086 std::unique_ptr<Array<String16>> hitBreakpointIds = Array<String16>::create(); |
| 1171 | 1087 |
| 1172 for (const auto& point : hitBreakpoints) { | 1088 for (const auto& point : hitBreakpoints) { |
| 1173 DebugServerBreakpointToBreakpointIdAndSourceMap::iterator | 1089 DebugServerBreakpointToBreakpointIdAndSourceMap::iterator |
| 1174 breakpointIterator = m_serverBreakpoints.find(point); | 1090 breakpointIterator = m_serverBreakpoints.find(point); |
| 1175 if (breakpointIterator != m_serverBreakpoints.end()) { | 1091 if (breakpointIterator != m_serverBreakpoints.end()) { |
| 1176 const String16& localId = breakpointIterator->second.first; | 1092 const String16& localId = breakpointIterator->second.first; |
| 1177 hitBreakpointIds->addItem(localId); | 1093 hitBreakpointIds->addItem(localId); |
| 1178 | 1094 |
| 1179 BreakpointSource source = breakpointIterator->second.second; | 1095 BreakpointSource source = breakpointIterator->second.second; |
| 1180 if (m_breakReason == protocol::Debugger::Paused::ReasonEnum::Other && | 1096 if (m_breakReason == protocol::Debugger::Paused::ReasonEnum::Other && |
| 1181 source == DebugCommandBreakpointSource) | 1097 source == DebugCommandBreakpointSource) |
| 1182 m_breakReason = protocol::Debugger::Paused::ReasonEnum::DebugCommand; | 1098 m_breakReason = protocol::Debugger::Paused::ReasonEnum::DebugCommand; |
| 1183 } | 1099 } |
| 1184 } | 1100 } |
| 1185 | 1101 |
| 1186 ErrorString errorString; | 1102 std::unique_ptr<Array<CallFrame>> protocolCallFrames; |
| 1187 m_frontend.paused(currentCallFrames(&errorString), m_breakReason, | 1103 Response response = currentCallFrames(&protocolCallFrames); |
| 1104 if (!response.isSuccess()) protocolCallFrames = Array<CallFrame>::create(); |
| 1105 m_frontend.paused(std::move(protocolCallFrames), m_breakReason, |
| 1188 std::move(m_breakAuxData), std::move(hitBreakpointIds), | 1106 std::move(m_breakAuxData), std::move(hitBreakpointIds), |
| 1189 currentAsyncStackTrace()); | 1107 currentAsyncStackTrace()); |
| 1190 m_scheduledDebuggerStep = NoStep; | 1108 m_scheduledDebuggerStep = NoStep; |
| 1191 m_javaScriptPauseScheduled = false; | 1109 m_javaScriptPauseScheduled = false; |
| 1192 m_steppingFromFramework = false; | 1110 m_steppingFromFramework = false; |
| 1193 m_pausingOnNativeEvent = false; | 1111 m_pausingOnNativeEvent = false; |
| 1194 m_skippedStepFrameCount = 0; | 1112 m_skippedStepFrameCount = 0; |
| 1195 m_recursionLevelForStepFrame = 0; | 1113 m_recursionLevelForStepFrame = 0; |
| 1196 | 1114 |
| 1197 if (!m_continueToLocationBreakpointId.isEmpty()) { | 1115 if (!m_continueToLocationBreakpointId.isEmpty()) { |
| (...skipping 29 matching lines...) Expand all Loading... |
| 1227 void V8DebuggerAgentImpl::breakProgramOnException( | 1145 void V8DebuggerAgentImpl::breakProgramOnException( |
| 1228 const String16& breakReason, | 1146 const String16& breakReason, |
| 1229 std::unique_ptr<protocol::DictionaryValue> data) { | 1147 std::unique_ptr<protocol::DictionaryValue> data) { |
| 1230 if (!enabled() || | 1148 if (!enabled() || |
| 1231 m_debugger->getPauseOnExceptionsState() == | 1149 m_debugger->getPauseOnExceptionsState() == |
| 1232 v8::DebugInterface::NoBreakOnException) | 1150 v8::DebugInterface::NoBreakOnException) |
| 1233 return; | 1151 return; |
| 1234 breakProgram(breakReason, std::move(data)); | 1152 breakProgram(breakReason, std::move(data)); |
| 1235 } | 1153 } |
| 1236 | 1154 |
| 1237 bool V8DebuggerAgentImpl::assertPaused(ErrorString* errorString) { | |
| 1238 if (m_pausedContext.IsEmpty()) { | |
| 1239 *errorString = "Can only perform operation while paused."; | |
| 1240 return false; | |
| 1241 } | |
| 1242 return true; | |
| 1243 } | |
| 1244 | |
| 1245 void V8DebuggerAgentImpl::clearBreakDetails() { | 1155 void V8DebuggerAgentImpl::clearBreakDetails() { |
| 1246 m_breakReason = protocol::Debugger::Paused::ReasonEnum::Other; | 1156 m_breakReason = protocol::Debugger::Paused::ReasonEnum::Other; |
| 1247 m_breakAuxData = nullptr; | 1157 m_breakAuxData = nullptr; |
| 1248 } | 1158 } |
| 1249 | 1159 |
| 1250 void V8DebuggerAgentImpl::setBreakpointAt(const String16& scriptId, | 1160 void V8DebuggerAgentImpl::setBreakpointAt(const String16& scriptId, |
| 1251 int lineNumber, int columnNumber, | 1161 int lineNumber, int columnNumber, |
| 1252 BreakpointSource source, | 1162 BreakpointSource source, |
| 1253 const String16& condition) { | 1163 const String16& condition) { |
| 1254 String16 breakpointId = | 1164 String16 breakpointId = |
| 1255 generateBreakpointId(scriptId, lineNumber, columnNumber, source); | 1165 generateBreakpointId(scriptId, lineNumber, columnNumber, source); |
| 1256 ScriptBreakpoint breakpoint(lineNumber, columnNumber, condition); | 1166 ScriptBreakpoint breakpoint(lineNumber, columnNumber, condition); |
| 1257 resolveBreakpoint(breakpointId, scriptId, breakpoint, source); | 1167 resolveBreakpoint(breakpointId, scriptId, breakpoint, source); |
| 1258 } | 1168 } |
| 1259 | 1169 |
| 1260 void V8DebuggerAgentImpl::removeBreakpointAt(const String16& scriptId, | 1170 void V8DebuggerAgentImpl::removeBreakpointAt(const String16& scriptId, |
| 1261 int lineNumber, int columnNumber, | 1171 int lineNumber, int columnNumber, |
| 1262 BreakpointSource source) { | 1172 BreakpointSource source) { |
| 1263 removeBreakpoint( | 1173 removeBreakpointImpl( |
| 1264 generateBreakpointId(scriptId, lineNumber, columnNumber, source)); | 1174 generateBreakpointId(scriptId, lineNumber, columnNumber, source)); |
| 1265 } | 1175 } |
| 1266 | 1176 |
| 1267 void V8DebuggerAgentImpl::reset() { | 1177 void V8DebuggerAgentImpl::reset() { |
| 1268 if (!enabled()) return; | 1178 if (!enabled()) return; |
| 1269 m_scheduledDebuggerStep = NoStep; | 1179 m_scheduledDebuggerStep = NoStep; |
| 1270 m_scripts.clear(); | 1180 m_scripts.clear(); |
| 1271 m_blackboxedPositions.clear(); | 1181 m_blackboxedPositions.clear(); |
| 1272 m_breakpointIdToDebuggerBreakpointIds.clear(); | 1182 m_breakpointIdToDebuggerBreakpointIds.clear(); |
| 1273 } | 1183 } |
| 1274 | 1184 |
| 1275 } // namespace v8_inspector | 1185 } // namespace v8_inspector |
| OLD | NEW |