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 |