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 25 matching lines...) Expand all Loading... |
36 using protocol::Runtime::ScriptId; | 36 using protocol::Runtime::ScriptId; |
37 using protocol::Runtime::StackTrace; | 37 using protocol::Runtime::StackTrace; |
38 using protocol::Runtime::RemoteObject; | 38 using protocol::Runtime::RemoteObject; |
39 | 39 |
40 namespace DebuggerAgentState { | 40 namespace DebuggerAgentState { |
41 static const char javaScriptBreakpoints[] = "javaScriptBreakopints"; | 41 static const char javaScriptBreakpoints[] = "javaScriptBreakopints"; |
42 static const char pauseOnExceptionsState[] = "pauseOnExceptionsState"; | 42 static const char pauseOnExceptionsState[] = "pauseOnExceptionsState"; |
43 static const char asyncCallStackDepth[] = "asyncCallStackDepth"; | 43 static const char asyncCallStackDepth[] = "asyncCallStackDepth"; |
44 static const char blackboxPattern[] = "blackboxPattern"; | 44 static const char blackboxPattern[] = "blackboxPattern"; |
45 static const char debuggerEnabled[] = "debuggerEnabled"; | 45 static const char debuggerEnabled[] = "debuggerEnabled"; |
| 46 static const char skipAllPauses[] = "skipAllPauses"; |
46 | 47 |
47 // Breakpoint properties. | 48 // Breakpoint properties. |
48 static const char url[] = "url"; | 49 static const char url[] = "url"; |
49 static const char isRegex[] = "isRegex"; | 50 static const char isRegex[] = "isRegex"; |
50 static const char lineNumber[] = "lineNumber"; | 51 static const char lineNumber[] = "lineNumber"; |
51 static const char columnNumber[] = "columnNumber"; | 52 static const char columnNumber[] = "columnNumber"; |
52 static const char condition[] = "condition"; | 53 static const char condition[] = "condition"; |
53 static const char skipAllPauses[] = "skipAllPauses"; | 54 static const char hint[] = "hint"; |
54 | 55 |
55 } // namespace DebuggerAgentState | 56 } // namespace DebuggerAgentState |
56 | 57 |
57 static const char kBacktraceObjectGroup[] = "backtrace"; | 58 static const char kBacktraceObjectGroup[] = "backtrace"; |
58 static const char kDebuggerNotEnabled[] = "Debugger agent is not enabled"; | 59 static const char kDebuggerNotEnabled[] = "Debugger agent is not enabled"; |
59 static const char kDebuggerNotPaused[] = | 60 static const char kDebuggerNotPaused[] = |
60 "Can only perform operation while paused."; | 61 "Can only perform operation while paused."; |
61 | 62 |
| 63 static const size_t kBreakpointHintMaxLength = 128; |
| 64 static const size_t kBreakpointHintMaxSearchOffset = 80 * 10; |
| 65 |
62 namespace { | 66 namespace { |
63 | 67 |
64 void TranslateWasmStackTraceLocations(Array<CallFrame>* stackTrace, | 68 void TranslateWasmStackTraceLocations(Array<CallFrame>* stackTrace, |
65 WasmTranslation* wasmTranslation) { | 69 WasmTranslation* wasmTranslation) { |
66 for (size_t i = 0, e = stackTrace->length(); i != e; ++i) { | 70 for (size_t i = 0, e = stackTrace->length(); i != e; ++i) { |
67 protocol::Debugger::Location* location = stackTrace->get(i)->getLocation(); | 71 protocol::Debugger::Location* location = stackTrace->get(i)->getLocation(); |
68 String16 scriptId = location->getScriptId(); | 72 String16 scriptId = location->getScriptId(); |
69 int lineNumber = location->getLineNumber(); | 73 int lineNumber = location->getLineNumber(); |
70 int columnNumber = location->getColumnNumber(-1); | 74 int columnNumber = location->getColumnNumber(-1); |
71 | 75 |
(...skipping 40 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
112 | 116 |
113 std::unique_ptr<protocol::Debugger::Location> buildProtocolLocation( | 117 std::unique_ptr<protocol::Debugger::Location> buildProtocolLocation( |
114 const String16& scriptId, int lineNumber, int columnNumber) { | 118 const String16& scriptId, int lineNumber, int columnNumber) { |
115 return protocol::Debugger::Location::create() | 119 return protocol::Debugger::Location::create() |
116 .setScriptId(scriptId) | 120 .setScriptId(scriptId) |
117 .setLineNumber(lineNumber) | 121 .setLineNumber(lineNumber) |
118 .setColumnNumber(columnNumber) | 122 .setColumnNumber(columnNumber) |
119 .build(); | 123 .build(); |
120 } | 124 } |
121 | 125 |
| 126 String16 breakpointHint(const V8DebuggerScript& script, |
| 127 const ScriptBreakpoint& breakpoint) { |
| 128 int offset = script.offset(breakpoint.line_number, breakpoint.column_number); |
| 129 if (offset == V8DebuggerScript::kNoOffset) return String16(); |
| 130 const String16& source = script.source(); |
| 131 String16 hint = source.substring(offset, offset + kBreakpointHintMaxLength) |
| 132 .stripWhiteSpace(); |
| 133 for (size_t i = 0; i < hint.length(); ++i) { |
| 134 if (hint[i] == '\r' || hint[i] == '\n' || hint[i] == ';') { |
| 135 return hint.substring(0, i); |
| 136 } |
| 137 } |
| 138 return hint; |
| 139 } |
| 140 |
| 141 void adjustBreakpointLocation(const V8DebuggerScript& script, |
| 142 const String16& hint, |
| 143 ScriptBreakpoint* breakpoint) { |
| 144 if (hint.isEmpty()) return; |
| 145 size_t offset = static_cast<size_t>( |
| 146 script.offset(breakpoint->line_number, breakpoint->column_number)); |
| 147 if (offset == static_cast<size_t>(V8DebuggerScript::kNoOffset)) return; |
| 148 size_t searchAreaOffset = 0; |
| 149 if (offset > kBreakpointHintMaxSearchOffset) |
| 150 searchAreaOffset = offset - kBreakpointHintMaxSearchOffset; |
| 151 String16 searchArea = |
| 152 script.source() |
| 153 .substring(searchAreaOffset, offset + kBreakpointHintMaxSearchOffset) |
| 154 .stripWhiteSpace(); |
| 155 size_t hintOffset = searchArea.find(hint); |
| 156 if (hintOffset == String16::kNotFound) return; |
| 157 size_t bestMatch = hintOffset + searchAreaOffset; |
| 158 size_t bestDistance = |
| 159 bestMatch > offset ? bestMatch - offset : offset - bestMatch; |
| 160 while (hintOffset != String16::kNotFound) { |
| 161 hintOffset = searchArea.find(hint, hintOffset + 1); |
| 162 if (hintOffset == String16::kNotFound) break; |
| 163 size_t hintDistance = hintOffset + searchAreaOffset > offset |
| 164 ? hintOffset + searchAreaOffset - offset |
| 165 : offset - (hintOffset + searchAreaOffset); |
| 166 if (hintDistance < bestDistance) { |
| 167 bestMatch = hintOffset + searchAreaOffset; |
| 168 bestDistance = hintDistance; |
| 169 } else { |
| 170 break; |
| 171 } |
| 172 } |
| 173 if (bestMatch == String16::kNotFound) return; |
| 174 v8::debug::Location hintPosition = script.position(bestMatch); |
| 175 if (hintPosition.IsEmpty()) return; |
| 176 breakpoint->line_number = hintPosition.GetLineNumber(); |
| 177 breakpoint->column_number = hintPosition.GetColumnNumber(); |
| 178 } |
122 } // namespace | 179 } // namespace |
123 | 180 |
124 V8DebuggerAgentImpl::V8DebuggerAgentImpl( | 181 V8DebuggerAgentImpl::V8DebuggerAgentImpl( |
125 V8InspectorSessionImpl* session, protocol::FrontendChannel* frontendChannel, | 182 V8InspectorSessionImpl* session, protocol::FrontendChannel* frontendChannel, |
126 protocol::DictionaryValue* state) | 183 protocol::DictionaryValue* state) |
127 : m_inspector(session->inspector()), | 184 : m_inspector(session->inspector()), |
128 m_debugger(m_inspector->debugger()), | 185 m_debugger(m_inspector->debugger()), |
129 m_session(session), | 186 m_session(session), |
130 m_enabled(false), | 187 m_enabled(false), |
131 m_state(state), | 188 m_state(state), |
(...skipping 100 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
232 | 289 |
233 Response V8DebuggerAgentImpl::setSkipAllPauses(bool skip) { | 290 Response V8DebuggerAgentImpl::setSkipAllPauses(bool skip) { |
234 m_state->setBoolean(DebuggerAgentState::skipAllPauses, skip); | 291 m_state->setBoolean(DebuggerAgentState::skipAllPauses, skip); |
235 m_skipAllPauses = skip; | 292 m_skipAllPauses = skip; |
236 return Response::OK(); | 293 return Response::OK(); |
237 } | 294 } |
238 | 295 |
239 static std::unique_ptr<protocol::DictionaryValue> | 296 static std::unique_ptr<protocol::DictionaryValue> |
240 buildObjectForBreakpointCookie(const String16& url, int lineNumber, | 297 buildObjectForBreakpointCookie(const String16& url, int lineNumber, |
241 int columnNumber, const String16& condition, | 298 int columnNumber, const String16& condition, |
242 bool isRegex) { | 299 bool isRegex, const String16& hint) { |
243 std::unique_ptr<protocol::DictionaryValue> breakpointObject = | 300 std::unique_ptr<protocol::DictionaryValue> breakpointObject = |
244 protocol::DictionaryValue::create(); | 301 protocol::DictionaryValue::create(); |
245 breakpointObject->setString(DebuggerAgentState::url, url); | 302 breakpointObject->setString(DebuggerAgentState::url, url); |
246 breakpointObject->setInteger(DebuggerAgentState::lineNumber, lineNumber); | 303 breakpointObject->setInteger(DebuggerAgentState::lineNumber, lineNumber); |
247 breakpointObject->setInteger(DebuggerAgentState::columnNumber, columnNumber); | 304 breakpointObject->setInteger(DebuggerAgentState::columnNumber, columnNumber); |
248 breakpointObject->setString(DebuggerAgentState::condition, condition); | 305 breakpointObject->setString(DebuggerAgentState::condition, condition); |
249 breakpointObject->setBoolean(DebuggerAgentState::isRegex, isRegex); | 306 breakpointObject->setBoolean(DebuggerAgentState::isRegex, isRegex); |
| 307 if (!hint.isEmpty()) { |
| 308 breakpointObject->setString(DebuggerAgentState::hint, hint); |
| 309 } |
250 return breakpointObject; | 310 return breakpointObject; |
251 } | 311 } |
252 | 312 |
253 static bool matches(V8InspectorImpl* inspector, const String16& url, | 313 static bool matches(V8InspectorImpl* inspector, const String16& url, |
254 const String16& pattern, bool isRegex) { | 314 const String16& pattern, bool isRegex) { |
255 if (isRegex) { | 315 if (isRegex) { |
256 V8Regex regex(inspector, pattern, true); | 316 V8Regex regex(inspector, pattern, true); |
257 return regex.match(url) != -1; | 317 return regex.match(url) != -1; |
258 } | 318 } |
259 return url == pattern; | 319 return url == pattern; |
(...skipping 26 matching lines...) Expand all Loading... |
286 if (!breakpointsCookie) { | 346 if (!breakpointsCookie) { |
287 std::unique_ptr<protocol::DictionaryValue> newValue = | 347 std::unique_ptr<protocol::DictionaryValue> newValue = |
288 protocol::DictionaryValue::create(); | 348 protocol::DictionaryValue::create(); |
289 breakpointsCookie = newValue.get(); | 349 breakpointsCookie = newValue.get(); |
290 m_state->setObject(DebuggerAgentState::javaScriptBreakpoints, | 350 m_state->setObject(DebuggerAgentState::javaScriptBreakpoints, |
291 std::move(newValue)); | 351 std::move(newValue)); |
292 } | 352 } |
293 if (breakpointsCookie->get(breakpointId)) | 353 if (breakpointsCookie->get(breakpointId)) |
294 return Response::Error("Breakpoint at specified location already exists."); | 354 return Response::Error("Breakpoint at specified location already exists."); |
295 | 355 |
296 breakpointsCookie->setObject( | 356 String16 hint; |
297 breakpointId, buildObjectForBreakpointCookie( | |
298 url, lineNumber, columnNumber, condition, isRegex)); | |
299 | |
300 ScriptBreakpoint breakpoint(String16(), lineNumber, columnNumber, condition); | 357 ScriptBreakpoint breakpoint(String16(), lineNumber, columnNumber, condition); |
301 for (const auto& script : m_scripts) { | 358 for (const auto& script : m_scripts) { |
302 if (!matches(m_inspector, script.second->sourceURL(), url, isRegex)) | 359 if (!matches(m_inspector, script.second->sourceURL(), url, isRegex)) |
303 continue; | 360 continue; |
304 breakpoint.script_id = script.first; | 361 breakpoint.script_id = script.first; |
305 std::unique_ptr<protocol::Debugger::Location> location = | 362 std::unique_ptr<protocol::Debugger::Location> location = |
306 resolveBreakpoint(breakpointId, breakpoint, UserBreakpointSource); | 363 resolveBreakpoint(breakpointId, breakpoint, UserBreakpointSource, hint); |
| 364 if (!isRegex) hint = breakpointHint(*script.second, breakpoint); |
307 if (location) (*locations)->addItem(std::move(location)); | 365 if (location) (*locations)->addItem(std::move(location)); |
308 } | 366 } |
309 | 367 |
| 368 breakpointsCookie->setObject( |
| 369 breakpointId, |
| 370 buildObjectForBreakpointCookie(url, lineNumber, columnNumber, condition, |
| 371 isRegex, hint)); |
| 372 |
310 *outBreakpointId = breakpointId; | 373 *outBreakpointId = breakpointId; |
311 return Response::OK(); | 374 return Response::OK(); |
312 } | 375 } |
313 | 376 |
314 Response V8DebuggerAgentImpl::setBreakpoint( | 377 Response V8DebuggerAgentImpl::setBreakpoint( |
315 std::unique_ptr<protocol::Debugger::Location> location, | 378 std::unique_ptr<protocol::Debugger::Location> location, |
316 Maybe<String16> optionalCondition, String16* outBreakpointId, | 379 Maybe<String16> optionalCondition, String16* outBreakpointId, |
317 std::unique_ptr<protocol::Debugger::Location>* actualLocation) { | 380 std::unique_ptr<protocol::Debugger::Location>* actualLocation) { |
318 ScriptBreakpoint breakpoint( | 381 ScriptBreakpoint breakpoint( |
319 location->getScriptId(), location->getLineNumber(), | 382 location->getScriptId(), location->getLineNumber(), |
320 location->getColumnNumber(0), optionalCondition.fromMaybe(String16())); | 383 location->getColumnNumber(0), optionalCondition.fromMaybe(String16())); |
321 | 384 |
322 String16 breakpointId = | 385 String16 breakpointId = |
323 generateBreakpointId(breakpoint, UserBreakpointSource); | 386 generateBreakpointId(breakpoint, UserBreakpointSource); |
324 if (m_breakpointIdToDebuggerBreakpointIds.find(breakpointId) != | 387 if (m_breakpointIdToDebuggerBreakpointIds.find(breakpointId) != |
325 m_breakpointIdToDebuggerBreakpointIds.end()) { | 388 m_breakpointIdToDebuggerBreakpointIds.end()) { |
326 return Response::Error("Breakpoint at specified location already exists."); | 389 return Response::Error("Breakpoint at specified location already exists."); |
327 } | 390 } |
328 *actualLocation = | 391 *actualLocation = resolveBreakpoint( |
329 resolveBreakpoint(breakpointId, breakpoint, UserBreakpointSource); | 392 breakpointId, breakpoint, UserBreakpointSource, /* hint */ String16()); |
330 if (!*actualLocation) return Response::Error("Could not resolve breakpoint"); | 393 if (!*actualLocation) return Response::Error("Could not resolve breakpoint"); |
331 *outBreakpointId = breakpointId; | 394 *outBreakpointId = breakpointId; |
332 return Response::OK(); | 395 return Response::OK(); |
333 } | 396 } |
334 | 397 |
335 Response V8DebuggerAgentImpl::removeBreakpoint(const String16& breakpointId) { | 398 Response V8DebuggerAgentImpl::removeBreakpoint(const String16& breakpointId) { |
336 if (!enabled()) return Response::Error(kDebuggerNotEnabled); | 399 if (!enabled()) return Response::Error(kDebuggerNotEnabled); |
337 protocol::DictionaryValue* breakpointsCookie = | 400 protocol::DictionaryValue* breakpointsCookie = |
338 m_state->getObject(DebuggerAgentState::javaScriptBreakpoints); | 401 m_state->getObject(DebuggerAgentState::javaScriptBreakpoints); |
339 if (breakpointsCookie) breakpointsCookie->remove(breakpointId); | 402 if (breakpointsCookie) breakpointsCookie->remove(breakpointId); |
(...skipping 109 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
449 // Ranges array contains positions in script where blackbox state is changed. | 512 // Ranges array contains positions in script where blackbox state is changed. |
450 // [(0,0) ... ranges[0]) isn't blackboxed, [ranges[0] ... ranges[1]) is | 513 // [(0,0) ... ranges[0]) isn't blackboxed, [ranges[0] ... ranges[1]) is |
451 // blackboxed... | 514 // blackboxed... |
452 return itStartRange == itEndRange && | 515 return itStartRange == itEndRange && |
453 std::distance(ranges.begin(), itStartRange) % 2; | 516 std::distance(ranges.begin(), itStartRange) % 2; |
454 } | 517 } |
455 | 518 |
456 std::unique_ptr<protocol::Debugger::Location> | 519 std::unique_ptr<protocol::Debugger::Location> |
457 V8DebuggerAgentImpl::resolveBreakpoint(const String16& breakpointId, | 520 V8DebuggerAgentImpl::resolveBreakpoint(const String16& breakpointId, |
458 const ScriptBreakpoint& breakpoint, | 521 const ScriptBreakpoint& breakpoint, |
459 BreakpointSource source) { | 522 BreakpointSource source, |
| 523 const String16& hint) { |
460 v8::HandleScope handles(m_isolate); | 524 v8::HandleScope handles(m_isolate); |
461 DCHECK(enabled()); | 525 DCHECK(enabled()); |
462 // FIXME: remove these checks once crbug.com/520702 is resolved. | 526 // FIXME: remove these checks once crbug.com/520702 is resolved. |
463 CHECK(!breakpointId.isEmpty()); | 527 CHECK(!breakpointId.isEmpty()); |
464 CHECK(!breakpoint.script_id.isEmpty()); | 528 CHECK(!breakpoint.script_id.isEmpty()); |
465 ScriptsMap::iterator scriptIterator = m_scripts.find(breakpoint.script_id); | 529 ScriptsMap::iterator scriptIterator = m_scripts.find(breakpoint.script_id); |
466 if (scriptIterator == m_scripts.end()) return nullptr; | 530 if (scriptIterator == m_scripts.end()) return nullptr; |
467 if (breakpoint.line_number < scriptIterator->second->startLine() || | 531 if (breakpoint.line_number < scriptIterator->second->startLine() || |
468 scriptIterator->second->endLine() < breakpoint.line_number) | 532 scriptIterator->second->endLine() < breakpoint.line_number) |
469 return nullptr; | 533 return nullptr; |
470 | 534 |
471 // Translate from protocol location to v8 location for the debugger. | 535 // Translate from protocol location to v8 location for the debugger. |
472 ScriptBreakpoint translatedBreakpoint = breakpoint; | 536 ScriptBreakpoint translatedBreakpoint = breakpoint; |
| 537 adjustBreakpointLocation(*scriptIterator->second, hint, |
| 538 &translatedBreakpoint); |
473 m_debugger->wasmTranslation()->TranslateProtocolLocationToWasmScriptLocation( | 539 m_debugger->wasmTranslation()->TranslateProtocolLocationToWasmScriptLocation( |
474 &translatedBreakpoint.script_id, &translatedBreakpoint.line_number, | 540 &translatedBreakpoint.script_id, &translatedBreakpoint.line_number, |
475 &translatedBreakpoint.column_number); | 541 &translatedBreakpoint.column_number); |
476 | 542 |
477 int actualLineNumber; | 543 int actualLineNumber; |
478 int actualColumnNumber; | 544 int actualColumnNumber; |
479 String16 debuggerBreakpointId = m_debugger->setBreakpoint( | 545 String16 debuggerBreakpointId = m_debugger->setBreakpoint( |
480 translatedBreakpoint, &actualLineNumber, &actualColumnNumber); | 546 translatedBreakpoint, &actualLineNumber, &actualColumnNumber); |
481 if (debuggerBreakpointId.isEmpty()) return nullptr; | 547 if (debuggerBreakpointId.isEmpty()) return nullptr; |
482 | 548 |
(...skipping 14 matching lines...) Expand all Loading... |
497 Response V8DebuggerAgentImpl::searchInContent( | 563 Response V8DebuggerAgentImpl::searchInContent( |
498 const String16& scriptId, const String16& query, | 564 const String16& scriptId, const String16& query, |
499 Maybe<bool> optionalCaseSensitive, Maybe<bool> optionalIsRegex, | 565 Maybe<bool> optionalCaseSensitive, Maybe<bool> optionalIsRegex, |
500 std::unique_ptr<Array<protocol::Debugger::SearchMatch>>* results) { | 566 std::unique_ptr<Array<protocol::Debugger::SearchMatch>>* results) { |
501 v8::HandleScope handles(m_isolate); | 567 v8::HandleScope handles(m_isolate); |
502 ScriptsMap::iterator it = m_scripts.find(scriptId); | 568 ScriptsMap::iterator it = m_scripts.find(scriptId); |
503 if (it == m_scripts.end()) | 569 if (it == m_scripts.end()) |
504 return Response::Error("No script for id: " + scriptId); | 570 return Response::Error("No script for id: " + scriptId); |
505 | 571 |
506 std::vector<std::unique_ptr<protocol::Debugger::SearchMatch>> matches = | 572 std::vector<std::unique_ptr<protocol::Debugger::SearchMatch>> matches = |
507 searchInTextByLinesImpl(m_session, it->second->source(m_isolate), query, | 573 searchInTextByLinesImpl(m_session, it->second->source(), query, |
508 optionalCaseSensitive.fromMaybe(false), | 574 optionalCaseSensitive.fromMaybe(false), |
509 optionalIsRegex.fromMaybe(false)); | 575 optionalIsRegex.fromMaybe(false)); |
510 *results = protocol::Array<protocol::Debugger::SearchMatch>::create(); | 576 *results = protocol::Array<protocol::Debugger::SearchMatch>::create(); |
511 for (size_t i = 0; i < matches.size(); ++i) | 577 for (size_t i = 0; i < matches.size(); ++i) |
512 (*results)->addItem(std::move(matches[i])); | 578 (*results)->addItem(std::move(matches[i])); |
513 return Response::OK(); | 579 return Response::OK(); |
514 } | 580 } |
515 | 581 |
516 Response V8DebuggerAgentImpl::setScriptSource( | 582 Response V8DebuggerAgentImpl::setScriptSource( |
517 const String16& scriptId, const String16& newContent, Maybe<bool> dryRun, | 583 const String16& scriptId, const String16& newContent, Maybe<bool> dryRun, |
(...skipping 12 matching lines...) Expand all Loading... |
530 } | 596 } |
531 | 597 |
532 v8::HandleScope handles(m_isolate); | 598 v8::HandleScope handles(m_isolate); |
533 v8::Local<v8::String> newSource = toV8String(m_isolate, newContent); | 599 v8::Local<v8::String> newSource = toV8String(m_isolate, newContent); |
534 bool compileError = false; | 600 bool compileError = false; |
535 Response response = m_debugger->setScriptSource( | 601 Response response = m_debugger->setScriptSource( |
536 scriptId, newSource, dryRun.fromMaybe(false), optOutCompileError, | 602 scriptId, newSource, dryRun.fromMaybe(false), optOutCompileError, |
537 &m_pausedCallFrames, stackChanged, &compileError); | 603 &m_pausedCallFrames, stackChanged, &compileError); |
538 if (!response.isSuccess() || compileError) return response; | 604 if (!response.isSuccess() || compileError) return response; |
539 | 605 |
540 it->second->setSource(newSource); | 606 it->second->setSource(newContent); |
541 std::unique_ptr<Array<CallFrame>> callFrames; | 607 std::unique_ptr<Array<CallFrame>> callFrames; |
542 response = currentCallFrames(&callFrames); | 608 response = currentCallFrames(&callFrames); |
543 if (!response.isSuccess()) return response; | 609 if (!response.isSuccess()) return response; |
544 *newCallFrames = std::move(callFrames); | 610 *newCallFrames = std::move(callFrames); |
545 *asyncStackTrace = currentAsyncStackTrace(); | 611 *asyncStackTrace = currentAsyncStackTrace(); |
546 return Response::OK(); | 612 return Response::OK(); |
547 } | 613 } |
548 | 614 |
549 Response V8DebuggerAgentImpl::restartFrame( | 615 Response V8DebuggerAgentImpl::restartFrame( |
550 const String16& callFrameId, | 616 const String16& callFrameId, |
(...skipping 24 matching lines...) Expand all Loading... |
575 *asyncStackTrace = currentAsyncStackTrace(); | 641 *asyncStackTrace = currentAsyncStackTrace(); |
576 return Response::OK(); | 642 return Response::OK(); |
577 } | 643 } |
578 | 644 |
579 Response V8DebuggerAgentImpl::getScriptSource(const String16& scriptId, | 645 Response V8DebuggerAgentImpl::getScriptSource(const String16& scriptId, |
580 String16* scriptSource) { | 646 String16* scriptSource) { |
581 if (!enabled()) return Response::Error(kDebuggerNotEnabled); | 647 if (!enabled()) return Response::Error(kDebuggerNotEnabled); |
582 ScriptsMap::iterator it = m_scripts.find(scriptId); | 648 ScriptsMap::iterator it = m_scripts.find(scriptId); |
583 if (it == m_scripts.end()) | 649 if (it == m_scripts.end()) |
584 return Response::Error("No script for id: " + scriptId); | 650 return Response::Error("No script for id: " + scriptId); |
585 v8::HandleScope handles(m_isolate); | 651 *scriptSource = it->second->source(); |
586 *scriptSource = it->second->source(m_isolate); | |
587 return Response::OK(); | 652 return Response::OK(); |
588 } | 653 } |
589 | 654 |
590 void V8DebuggerAgentImpl::pushBreakDetails( | 655 void V8DebuggerAgentImpl::pushBreakDetails( |
591 const String16& breakReason, | 656 const String16& breakReason, |
592 std::unique_ptr<protocol::DictionaryValue> breakAuxData) { | 657 std::unique_ptr<protocol::DictionaryValue> breakAuxData) { |
593 m_breakReason.push_back(std::make_pair(breakReason, std::move(breakAuxData))); | 658 m_breakReason.push_back(std::make_pair(breakReason, std::move(breakAuxData))); |
594 } | 659 } |
595 | 660 |
596 void V8DebuggerAgentImpl::popBreakDetails() { | 661 void V8DebuggerAgentImpl::popBreakDetails() { |
(...skipping 388 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
985 V8StackTraceImpl* stackTrace = m_debugger->currentAsyncCallChain(); | 1050 V8StackTraceImpl* stackTrace = m_debugger->currentAsyncCallChain(); |
986 return stackTrace ? stackTrace->buildInspectorObjectForTail(m_debugger) | 1051 return stackTrace ? stackTrace->buildInspectorObjectForTail(m_debugger) |
987 : nullptr; | 1052 : nullptr; |
988 } | 1053 } |
989 | 1054 |
990 bool V8DebuggerAgentImpl::isPaused() const { return m_debugger->isPaused(); } | 1055 bool V8DebuggerAgentImpl::isPaused() const { return m_debugger->isPaused(); } |
991 | 1056 |
992 void V8DebuggerAgentImpl::didParseSource( | 1057 void V8DebuggerAgentImpl::didParseSource( |
993 std::unique_ptr<V8DebuggerScript> script, bool success) { | 1058 std::unique_ptr<V8DebuggerScript> script, bool success) { |
994 v8::HandleScope handles(m_isolate); | 1059 v8::HandleScope handles(m_isolate); |
995 String16 scriptSource = script->source(m_isolate); | 1060 String16 scriptSource = script->source(); |
996 if (!success) script->setSourceURL(findSourceURL(scriptSource, false)); | 1061 if (!success) script->setSourceURL(findSourceURL(scriptSource, false)); |
997 if (!success) | 1062 if (!success) |
998 script->setSourceMappingURL(findSourceMapURL(scriptSource, false)); | 1063 script->setSourceMappingURL(findSourceMapURL(scriptSource, false)); |
999 | 1064 |
1000 int contextId = script->executionContextId(); | 1065 int contextId = script->executionContextId(); |
1001 int contextGroupId = m_inspector->contextGroupId(contextId); | 1066 int contextGroupId = m_inspector->contextGroupId(contextId); |
1002 InspectedContext* inspected = | 1067 InspectedContext* inspected = |
1003 m_inspector->getContext(contextGroupId, contextId); | 1068 m_inspector->getContext(contextGroupId, contextId); |
1004 std::unique_ptr<protocol::DictionaryValue> executionContextAuxData; | 1069 std::unique_ptr<protocol::DictionaryValue> executionContextAuxData; |
1005 if (inspected) { | 1070 if (inspected) { |
(...skipping 22 matching lines...) Expand all Loading... |
1028 Maybe<String16> sourceMapURLParam = scriptRef->sourceMappingURL(); | 1093 Maybe<String16> sourceMapURLParam = scriptRef->sourceMappingURL(); |
1029 Maybe<protocol::DictionaryValue> executionContextAuxDataParam( | 1094 Maybe<protocol::DictionaryValue> executionContextAuxDataParam( |
1030 std::move(executionContextAuxData)); | 1095 std::move(executionContextAuxData)); |
1031 const bool* isLiveEditParam = isLiveEdit ? &isLiveEdit : nullptr; | 1096 const bool* isLiveEditParam = isLiveEdit ? &isLiveEdit : nullptr; |
1032 const bool* hasSourceURLParam = hasSourceURL ? &hasSourceURL : nullptr; | 1097 const bool* hasSourceURLParam = hasSourceURL ? &hasSourceURL : nullptr; |
1033 const bool* isModuleParam = isModule ? &isModule : nullptr; | 1098 const bool* isModuleParam = isModule ? &isModule : nullptr; |
1034 if (success) | 1099 if (success) |
1035 m_frontend.scriptParsed( | 1100 m_frontend.scriptParsed( |
1036 scriptId, scriptURL, scriptRef->startLine(), scriptRef->startColumn(), | 1101 scriptId, scriptURL, scriptRef->startLine(), scriptRef->startColumn(), |
1037 scriptRef->endLine(), scriptRef->endColumn(), contextId, | 1102 scriptRef->endLine(), scriptRef->endColumn(), contextId, |
1038 scriptRef->hash(m_isolate), std::move(executionContextAuxDataParam), | 1103 scriptRef->hash(), std::move(executionContextAuxDataParam), |
1039 isLiveEditParam, std::move(sourceMapURLParam), hasSourceURLParam, | 1104 isLiveEditParam, std::move(sourceMapURLParam), hasSourceURLParam, |
1040 isModuleParam); | 1105 isModuleParam); |
1041 else | 1106 else |
1042 m_frontend.scriptFailedToParse( | 1107 m_frontend.scriptFailedToParse( |
1043 scriptId, scriptURL, scriptRef->startLine(), scriptRef->startColumn(), | 1108 scriptId, scriptURL, scriptRef->startLine(), scriptRef->startColumn(), |
1044 scriptRef->endLine(), scriptRef->endColumn(), contextId, | 1109 scriptRef->endLine(), scriptRef->endColumn(), contextId, |
1045 scriptRef->hash(m_isolate), std::move(executionContextAuxDataParam), | 1110 scriptRef->hash(), std::move(executionContextAuxDataParam), |
1046 std::move(sourceMapURLParam), hasSourceURLParam, isModuleParam); | 1111 std::move(sourceMapURLParam), hasSourceURLParam, isModuleParam); |
1047 | 1112 |
1048 if (scriptURL.isEmpty() || !success) return; | 1113 if (scriptURL.isEmpty() || !success) return; |
1049 | 1114 |
1050 protocol::DictionaryValue* breakpointsCookie = | 1115 protocol::DictionaryValue* breakpointsCookie = |
1051 m_state->getObject(DebuggerAgentState::javaScriptBreakpoints); | 1116 m_state->getObject(DebuggerAgentState::javaScriptBreakpoints); |
1052 if (!breakpointsCookie) return; | 1117 if (!breakpointsCookie) return; |
1053 | 1118 |
1054 for (size_t i = 0; i < breakpointsCookie->size(); ++i) { | 1119 for (size_t i = 0; i < breakpointsCookie->size(); ++i) { |
1055 auto cookie = breakpointsCookie->at(i); | 1120 auto cookie = breakpointsCookie->at(i); |
1056 protocol::DictionaryValue* breakpointObject = | 1121 protocol::DictionaryValue* breakpointObject = |
1057 protocol::DictionaryValue::cast(cookie.second); | 1122 protocol::DictionaryValue::cast(cookie.second); |
1058 bool isRegex; | 1123 bool isRegex; |
1059 breakpointObject->getBoolean(DebuggerAgentState::isRegex, &isRegex); | 1124 breakpointObject->getBoolean(DebuggerAgentState::isRegex, &isRegex); |
1060 String16 url; | 1125 String16 url; |
1061 breakpointObject->getString(DebuggerAgentState::url, &url); | 1126 breakpointObject->getString(DebuggerAgentState::url, &url); |
1062 if (!matches(m_inspector, scriptURL, url, isRegex)) continue; | 1127 if (!matches(m_inspector, scriptURL, url, isRegex)) continue; |
1063 ScriptBreakpoint breakpoint; | 1128 ScriptBreakpoint breakpoint; |
1064 breakpoint.script_id = scriptId; | 1129 breakpoint.script_id = scriptId; |
1065 breakpointObject->getInteger(DebuggerAgentState::lineNumber, | 1130 breakpointObject->getInteger(DebuggerAgentState::lineNumber, |
1066 &breakpoint.line_number); | 1131 &breakpoint.line_number); |
1067 breakpointObject->getInteger(DebuggerAgentState::columnNumber, | 1132 breakpointObject->getInteger(DebuggerAgentState::columnNumber, |
1068 &breakpoint.column_number); | 1133 &breakpoint.column_number); |
1069 breakpointObject->getString(DebuggerAgentState::condition, | 1134 breakpointObject->getString(DebuggerAgentState::condition, |
1070 &breakpoint.condition); | 1135 &breakpoint.condition); |
| 1136 String16 hint; |
| 1137 bool hasHint = breakpointObject->getString(DebuggerAgentState::hint, &hint); |
1071 std::unique_ptr<protocol::Debugger::Location> location = | 1138 std::unique_ptr<protocol::Debugger::Location> location = |
1072 resolveBreakpoint(cookie.first, breakpoint, UserBreakpointSource); | 1139 resolveBreakpoint(cookie.first, breakpoint, UserBreakpointSource, hint); |
| 1140 if (!hasHint) { |
| 1141 hint = breakpointHint(*scriptRef, breakpoint); |
| 1142 if (!hint.isEmpty()) |
| 1143 breakpointObject->setString(DebuggerAgentState::hint, hint); |
| 1144 } |
1073 if (location) | 1145 if (location) |
1074 m_frontend.breakpointResolved(cookie.first, std::move(location)); | 1146 m_frontend.breakpointResolved(cookie.first, std::move(location)); |
1075 } | 1147 } |
1076 } | 1148 } |
1077 | 1149 |
1078 void V8DebuggerAgentImpl::didPause(int contextId, | 1150 void V8DebuggerAgentImpl::didPause(int contextId, |
1079 v8::Local<v8::Value> exception, | 1151 v8::Local<v8::Value> exception, |
1080 const std::vector<String16>& hitBreakpoints, | 1152 const std::vector<String16>& hitBreakpoints, |
1081 bool isPromiseRejection, bool isUncaught, | 1153 bool isPromiseRejection, bool isUncaught, |
1082 bool isOOMBreak) { | 1154 bool isOOMBreak) { |
(...skipping 118 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
1201 return; | 1273 return; |
1202 breakProgram(breakReason, std::move(data)); | 1274 breakProgram(breakReason, std::move(data)); |
1203 } | 1275 } |
1204 | 1276 |
1205 void V8DebuggerAgentImpl::setBreakpointAt(const String16& scriptId, | 1277 void V8DebuggerAgentImpl::setBreakpointAt(const String16& scriptId, |
1206 int lineNumber, int columnNumber, | 1278 int lineNumber, int columnNumber, |
1207 BreakpointSource source, | 1279 BreakpointSource source, |
1208 const String16& condition) { | 1280 const String16& condition) { |
1209 ScriptBreakpoint breakpoint(scriptId, lineNumber, columnNumber, condition); | 1281 ScriptBreakpoint breakpoint(scriptId, lineNumber, columnNumber, condition); |
1210 String16 breakpointId = generateBreakpointId(breakpoint, source); | 1282 String16 breakpointId = generateBreakpointId(breakpoint, source); |
1211 resolveBreakpoint(breakpointId, breakpoint, source); | 1283 resolveBreakpoint(breakpointId, breakpoint, source, /* hint */ String16()); |
1212 } | 1284 } |
1213 | 1285 |
1214 void V8DebuggerAgentImpl::removeBreakpointAt(const String16& scriptId, | 1286 void V8DebuggerAgentImpl::removeBreakpointAt(const String16& scriptId, |
1215 int lineNumber, int columnNumber, | 1287 int lineNumber, int columnNumber, |
1216 BreakpointSource source) { | 1288 BreakpointSource source) { |
1217 removeBreakpointImpl(generateBreakpointId( | 1289 removeBreakpointImpl(generateBreakpointId( |
1218 ScriptBreakpoint(scriptId, lineNumber, columnNumber, String16()), | 1290 ScriptBreakpoint(scriptId, lineNumber, columnNumber, String16()), |
1219 source)); | 1291 source)); |
1220 } | 1292 } |
1221 | 1293 |
1222 void V8DebuggerAgentImpl::reset() { | 1294 void V8DebuggerAgentImpl::reset() { |
1223 if (!enabled()) return; | 1295 if (!enabled()) return; |
1224 m_scheduledDebuggerStep = NoStep; | 1296 m_scheduledDebuggerStep = NoStep; |
1225 m_blackboxedPositions.clear(); | 1297 m_blackboxedPositions.clear(); |
1226 resetBlackboxedStateCache(); | 1298 resetBlackboxedStateCache(); |
1227 m_scripts.clear(); | 1299 m_scripts.clear(); |
1228 m_breakpointIdToDebuggerBreakpointIds.clear(); | 1300 m_breakpointIdToDebuggerBreakpointIds.clear(); |
1229 } | 1301 } |
1230 | 1302 |
1231 } // namespace v8_inspector | 1303 } // namespace v8_inspector |
OLD | NEW |