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 |