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