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 42 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
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 kMaxSkipStepFrameCount = 128; | 57 static const int kMaxSkipStepFrameCount = 128; |
58 static const char kBacktraceObjectGroup[] = "backtrace"; | 58 static const char kBacktraceObjectGroup[] = "backtrace"; |
59 static const char kDebuggerNotEnabled[] = "Debugger agent is not enabled"; | 59 static const char kDebuggerNotEnabled[] = "Debugger agent is not enabled"; |
60 static const char kDebuggerNotPaused[] = | 60 static const char kDebuggerNotPaused[] = |
61 "Can only perform operation while paused."; | 61 "Can only perform operation while paused."; |
62 | 62 |
63 static String16 breakpointIdSuffix( | 63 namespace { |
64 V8DebuggerAgentImpl::BreakpointSource source) { | 64 |
| 65 void TranslateWasmStackTraceLocations(Array<CallFrame>* stackTrace, |
| 66 WasmTranslation* wasmTranslation, |
| 67 int context_group_id) { |
| 68 for (size_t i = 0, e = stackTrace->length(); i != e; ++i) { |
| 69 protocol::Debugger::Location* location = stackTrace->get(i)->getLocation(); |
| 70 String16 scriptId = location->getScriptId(); |
| 71 int lineNumber = location->getLineNumber(); |
| 72 int columnNumber = location->getColumnNumber(-1); |
| 73 |
| 74 if (!wasmTranslation->TranslateWasmScriptLocationToProtocolLocation( |
| 75 &scriptId, &lineNumber, &columnNumber, context_group_id)) { |
| 76 continue; |
| 77 } |
| 78 |
| 79 location->setScriptId(std::move(scriptId)); |
| 80 location->setLineNumber(lineNumber); |
| 81 location->setColumnNumber(columnNumber); |
| 82 } |
| 83 } |
| 84 |
| 85 String16 breakpointIdSuffix(V8DebuggerAgentImpl::BreakpointSource source) { |
65 switch (source) { | 86 switch (source) { |
66 case V8DebuggerAgentImpl::UserBreakpointSource: | 87 case V8DebuggerAgentImpl::UserBreakpointSource: |
67 break; | 88 break; |
68 case V8DebuggerAgentImpl::DebugCommandBreakpointSource: | 89 case V8DebuggerAgentImpl::DebugCommandBreakpointSource: |
69 return ":debug"; | 90 return ":debug"; |
70 case V8DebuggerAgentImpl::MonitorCommandBreakpointSource: | 91 case V8DebuggerAgentImpl::MonitorCommandBreakpointSource: |
71 return ":monitor"; | 92 return ":monitor"; |
72 } | 93 } |
73 return String16(); | 94 return String16(); |
74 } | 95 } |
75 | 96 |
76 static String16 generateBreakpointId( | 97 String16 generateBreakpointId(const ScriptBreakpoint& breakpoint, |
77 const ScriptBreakpoint& breakpoint, | 98 V8DebuggerAgentImpl::BreakpointSource source) { |
78 V8DebuggerAgentImpl::BreakpointSource source) { | |
79 String16Builder builder; | 99 String16Builder builder; |
80 builder.append(breakpoint.script_id); | 100 builder.append(breakpoint.script_id); |
81 builder.append(':'); | 101 builder.append(':'); |
82 builder.appendNumber(breakpoint.line_number); | 102 builder.appendNumber(breakpoint.line_number); |
83 builder.append(':'); | 103 builder.append(':'); |
84 builder.appendNumber(breakpoint.column_number); | 104 builder.appendNumber(breakpoint.column_number); |
85 builder.append(breakpointIdSuffix(source)); | 105 builder.append(breakpointIdSuffix(source)); |
86 return builder.toString(); | 106 return builder.toString(); |
87 } | 107 } |
88 | 108 |
89 static bool positionComparator(const std::pair<int, int>& a, | 109 bool positionComparator(const std::pair<int, int>& a, |
90 const std::pair<int, int>& b) { | 110 const std::pair<int, int>& b) { |
91 if (a.first != b.first) return a.first < b.first; | 111 if (a.first != b.first) return a.first < b.first; |
92 return a.second < b.second; | 112 return a.second < b.second; |
93 } | 113 } |
94 | 114 |
95 static std::unique_ptr<protocol::Debugger::Location> buildProtocolLocation( | 115 std::unique_ptr<protocol::Debugger::Location> buildProtocolLocation( |
96 const String16& scriptId, int lineNumber, int columnNumber) { | 116 const String16& scriptId, int lineNumber, int columnNumber) { |
97 return protocol::Debugger::Location::create() | 117 return protocol::Debugger::Location::create() |
98 .setScriptId(scriptId) | 118 .setScriptId(scriptId) |
99 .setLineNumber(lineNumber) | 119 .setLineNumber(lineNumber) |
100 .setColumnNumber(columnNumber) | 120 .setColumnNumber(columnNumber) |
101 .build(); | 121 .build(); |
102 } | 122 } |
103 | 123 |
| 124 } // namespace |
| 125 |
104 V8DebuggerAgentImpl::V8DebuggerAgentImpl( | 126 V8DebuggerAgentImpl::V8DebuggerAgentImpl( |
105 V8InspectorSessionImpl* session, protocol::FrontendChannel* frontendChannel, | 127 V8InspectorSessionImpl* session, protocol::FrontendChannel* frontendChannel, |
106 protocol::DictionaryValue* state) | 128 protocol::DictionaryValue* state) |
107 : m_inspector(session->inspector()), | 129 : m_inspector(session->inspector()), |
108 m_debugger(m_inspector->debugger()), | 130 m_debugger(m_inspector->debugger()), |
109 m_session(session), | 131 m_session(session), |
110 m_enabled(false), | 132 m_enabled(false), |
111 m_state(state), | 133 m_state(state), |
112 m_frontend(frontendChannel), | 134 m_frontend(frontendChannel), |
113 m_isolate(m_inspector->isolate()), | 135 m_isolate(m_inspector->isolate()), |
(...skipping 382 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
496 DCHECK(enabled()); | 518 DCHECK(enabled()); |
497 // FIXME: remove these checks once crbug.com/520702 is resolved. | 519 // FIXME: remove these checks once crbug.com/520702 is resolved. |
498 CHECK(!breakpointId.isEmpty()); | 520 CHECK(!breakpointId.isEmpty()); |
499 CHECK(!breakpoint.script_id.isEmpty()); | 521 CHECK(!breakpoint.script_id.isEmpty()); |
500 ScriptsMap::iterator scriptIterator = m_scripts.find(breakpoint.script_id); | 522 ScriptsMap::iterator scriptIterator = m_scripts.find(breakpoint.script_id); |
501 if (scriptIterator == m_scripts.end()) return nullptr; | 523 if (scriptIterator == m_scripts.end()) return nullptr; |
502 if (breakpoint.line_number < scriptIterator->second->startLine() || | 524 if (breakpoint.line_number < scriptIterator->second->startLine() || |
503 scriptIterator->second->endLine() < breakpoint.line_number) | 525 scriptIterator->second->endLine() < breakpoint.line_number) |
504 return nullptr; | 526 return nullptr; |
505 | 527 |
| 528 ScriptBreakpoint translatedBreakpoint = breakpoint; |
| 529 if (m_scripts.count(breakpoint.script_id) == 0) { |
| 530 m_debugger->wasmTranslation() |
| 531 ->TranslateProtocolLocationToWasmScriptLocation( |
| 532 &translatedBreakpoint.script_id, &translatedBreakpoint.line_number, |
| 533 &translatedBreakpoint.column_number); |
| 534 } |
| 535 |
506 int actualLineNumber; | 536 int actualLineNumber; |
507 int actualColumnNumber; | 537 int actualColumnNumber; |
508 String16 debuggerBreakpointId = m_debugger->setBreakpoint( | 538 String16 debuggerBreakpointId = m_debugger->setBreakpoint( |
509 breakpoint, &actualLineNumber, &actualColumnNumber); | 539 translatedBreakpoint, &actualLineNumber, &actualColumnNumber); |
510 if (debuggerBreakpointId.isEmpty()) return nullptr; | 540 if (debuggerBreakpointId.isEmpty()) return nullptr; |
511 | 541 |
512 m_serverBreakpoints[debuggerBreakpointId] = | 542 m_serverBreakpoints[debuggerBreakpointId] = |
513 std::make_pair(breakpointId, source); | 543 std::make_pair(breakpointId, source); |
514 CHECK(!breakpointId.isEmpty()); | 544 CHECK(!breakpointId.isEmpty()); |
515 | 545 |
516 m_breakpointIdToDebuggerBreakpointIds[breakpointId].push_back( | 546 m_breakpointIdToDebuggerBreakpointIds[breakpointId].push_back( |
517 debuggerBreakpointId); | 547 debuggerBreakpointId); |
518 return buildProtocolLocation(breakpoint.script_id, actualLineNumber, | 548 return buildProtocolLocation(translatedBreakpoint.script_id, actualLineNumber, |
519 actualColumnNumber); | 549 actualColumnNumber); |
520 } | 550 } |
521 | 551 |
522 Response V8DebuggerAgentImpl::searchInContent( | 552 Response V8DebuggerAgentImpl::searchInContent( |
523 const String16& scriptId, const String16& query, | 553 const String16& scriptId, const String16& query, |
524 Maybe<bool> optionalCaseSensitive, Maybe<bool> optionalIsRegex, | 554 Maybe<bool> optionalCaseSensitive, Maybe<bool> optionalIsRegex, |
525 std::unique_ptr<Array<protocol::Debugger::SearchMatch>>* results) { | 555 std::unique_ptr<Array<protocol::Debugger::SearchMatch>>* results) { |
526 v8::HandleScope handles(m_isolate); | 556 v8::HandleScope handles(m_isolate); |
527 ScriptsMap::iterator it = m_scripts.find(scriptId); | 557 ScriptsMap::iterator it = m_scripts.find(scriptId); |
528 if (it == m_scripts.end()) | 558 if (it == m_scripts.end()) |
529 return Response::Error("No script for id: " + scriptId); | 559 return Response::Error("No script for id: " + scriptId); |
530 | 560 |
531 std::vector<std::unique_ptr<protocol::Debugger::SearchMatch>> matches = | 561 std::vector<std::unique_ptr<protocol::Debugger::SearchMatch>> matches = |
532 searchInTextByLinesImpl(m_session, | 562 searchInTextByLinesImpl(m_session, it->second->source(m_isolate), query, |
533 toProtocolString(it->second->source(m_isolate)), | 563 optionalCaseSensitive.fromMaybe(false), |
534 query, optionalCaseSensitive.fromMaybe(false), | |
535 optionalIsRegex.fromMaybe(false)); | 564 optionalIsRegex.fromMaybe(false)); |
536 *results = protocol::Array<protocol::Debugger::SearchMatch>::create(); | 565 *results = protocol::Array<protocol::Debugger::SearchMatch>::create(); |
537 for (size_t i = 0; i < matches.size(); ++i) | 566 for (size_t i = 0; i < matches.size(); ++i) |
538 (*results)->addItem(std::move(matches[i])); | 567 (*results)->addItem(std::move(matches[i])); |
539 return Response::OK(); | 568 return Response::OK(); |
540 } | 569 } |
541 | 570 |
542 Response V8DebuggerAgentImpl::setScriptSource( | 571 Response V8DebuggerAgentImpl::setScriptSource( |
543 const String16& scriptId, const String16& newContent, Maybe<bool> dryRun, | 572 const String16& scriptId, const String16& newContent, Maybe<bool> dryRun, |
544 Maybe<protocol::Array<protocol::Debugger::CallFrame>>* newCallFrames, | 573 Maybe<protocol::Array<protocol::Debugger::CallFrame>>* newCallFrames, |
(...skipping 50 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
595 return Response::OK(); | 624 return Response::OK(); |
596 } | 625 } |
597 | 626 |
598 Response V8DebuggerAgentImpl::getScriptSource(const String16& scriptId, | 627 Response V8DebuggerAgentImpl::getScriptSource(const String16& scriptId, |
599 String16* scriptSource) { | 628 String16* scriptSource) { |
600 if (!enabled()) return Response::Error(kDebuggerNotEnabled); | 629 if (!enabled()) return Response::Error(kDebuggerNotEnabled); |
601 ScriptsMap::iterator it = m_scripts.find(scriptId); | 630 ScriptsMap::iterator it = m_scripts.find(scriptId); |
602 if (it == m_scripts.end()) | 631 if (it == m_scripts.end()) |
603 return Response::Error("No script for id: " + scriptId); | 632 return Response::Error("No script for id: " + scriptId); |
604 v8::HandleScope handles(m_isolate); | 633 v8::HandleScope handles(m_isolate); |
605 *scriptSource = toProtocolString(it->second->source(m_isolate)); | 634 *scriptSource = it->second->source(m_isolate); |
606 return Response::OK(); | 635 return Response::OK(); |
607 } | 636 } |
608 | 637 |
609 void V8DebuggerAgentImpl::schedulePauseOnNextStatement( | 638 void V8DebuggerAgentImpl::schedulePauseOnNextStatement( |
610 const String16& breakReason, | 639 const String16& breakReason, |
611 std::unique_ptr<protocol::DictionaryValue> data) { | 640 std::unique_ptr<protocol::DictionaryValue> data) { |
612 if (!enabled() || m_scheduledDebuggerStep == StepInto || | 641 if (!enabled() || m_scheduledDebuggerStep == StepInto || |
613 m_javaScriptPauseScheduled || m_debugger->isPaused() || | 642 m_javaScriptPauseScheduled || m_debugger->isPaused() || |
614 !m_debugger->breakpointsActivated()) | 643 !m_debugger->breakpointsActivated()) |
615 return; | 644 return; |
(...skipping 381 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
997 return Response::InternalError(); | 1026 return Response::InternalError(); |
998 } | 1027 } |
999 } | 1028 } |
1000 | 1029 |
1001 std::unique_ptr<protocol::Value> protocolValue; | 1030 std::unique_ptr<protocol::Value> protocolValue; |
1002 Response response = toProtocolValue(debuggerContext, objects, &protocolValue); | 1031 Response response = toProtocolValue(debuggerContext, objects, &protocolValue); |
1003 if (!response.isSuccess()) return response; | 1032 if (!response.isSuccess()) return response; |
1004 protocol::ErrorSupport errorSupport; | 1033 protocol::ErrorSupport errorSupport; |
1005 *result = Array<CallFrame>::parse(protocolValue.get(), &errorSupport); | 1034 *result = Array<CallFrame>::parse(protocolValue.get(), &errorSupport); |
1006 if (!*result) return Response::Error(errorSupport.errors()); | 1035 if (!*result) return Response::Error(errorSupport.errors()); |
| 1036 TranslateWasmStackTraceLocations(result->get(), m_debugger->wasmTranslation(), |
| 1037 m_session->contextGroupId()); |
1007 return Response::OK(); | 1038 return Response::OK(); |
1008 } | 1039 } |
1009 | 1040 |
1010 std::unique_ptr<StackTrace> V8DebuggerAgentImpl::currentAsyncStackTrace() { | 1041 std::unique_ptr<StackTrace> V8DebuggerAgentImpl::currentAsyncStackTrace() { |
1011 if (m_pausedContext.IsEmpty()) return nullptr; | 1042 if (m_pausedContext.IsEmpty()) return nullptr; |
1012 V8StackTraceImpl* stackTrace = m_debugger->currentAsyncCallChain(); | 1043 V8StackTraceImpl* stackTrace = m_debugger->currentAsyncCallChain(); |
1013 return stackTrace ? stackTrace->buildInspectorObjectForTail(m_debugger) | 1044 return stackTrace ? stackTrace->buildInspectorObjectForTail(m_debugger) |
1014 : nullptr; | 1045 : nullptr; |
1015 } | 1046 } |
1016 | 1047 |
1017 void V8DebuggerAgentImpl::didParseSource( | 1048 void V8DebuggerAgentImpl::didParseSource( |
1018 std::unique_ptr<V8DebuggerScript> script, bool success) { | 1049 std::unique_ptr<V8DebuggerScript> script, bool success) { |
1019 v8::HandleScope handles(m_isolate); | 1050 v8::HandleScope handles(m_isolate); |
1020 String16 scriptSource = toProtocolString(script->source(m_isolate)); | 1051 String16 scriptSource = script->source(m_isolate); |
1021 if (!success) script->setSourceURL(findSourceURL(scriptSource, false)); | 1052 if (!success) script->setSourceURL(findSourceURL(scriptSource, false)); |
1022 if (!success) | 1053 if (!success) |
1023 script->setSourceMappingURL(findSourceMapURL(scriptSource, false)); | 1054 script->setSourceMappingURL(findSourceMapURL(scriptSource, false)); |
1024 | 1055 |
1025 std::unique_ptr<protocol::DictionaryValue> executionContextAuxData; | 1056 std::unique_ptr<protocol::DictionaryValue> executionContextAuxData; |
1026 if (!script->executionContextAuxData().isEmpty()) | 1057 if (!script->executionContextAuxData().isEmpty()) |
1027 executionContextAuxData = protocol::DictionaryValue::cast( | 1058 executionContextAuxData = protocol::DictionaryValue::cast( |
1028 protocol::parseJSON(script->executionContextAuxData())); | 1059 protocol::parseJSON(script->executionContextAuxData())); |
1029 bool isLiveEdit = script->isLiveEdit(); | 1060 bool isLiveEdit = script->isLiveEdit(); |
1030 bool hasSourceURL = script->hasSourceURL(); | 1061 bool hasSourceURL = script->hasSourceURL(); |
1031 String16 scriptId = script->scriptId(); | 1062 String16 scriptId = script->scriptId(); |
1032 String16 scriptURL = script->sourceURL(); | 1063 String16 scriptURL = script->sourceURL(); |
1033 | 1064 |
1034 m_scripts[scriptId] = std::move(script); | 1065 m_scripts[scriptId] = std::move(script); |
1035 | 1066 |
1036 ScriptsMap::iterator scriptIterator = m_scripts.find(scriptId); | 1067 ScriptsMap::iterator scriptIterator = m_scripts.find(scriptId); |
1037 DCHECK(scriptIterator != m_scripts.end()); | 1068 DCHECK(scriptIterator != m_scripts.end()); |
1038 V8DebuggerScript* scriptRef = scriptIterator->second.get(); | 1069 V8DebuggerScript* scriptRef = scriptIterator->second.get(); |
1039 | 1070 |
1040 Maybe<String16> sourceMapURLParam = scriptRef->sourceMappingURL(); | 1071 Maybe<String16> sourceMapURLParam = scriptRef->sourceMappingURL(); |
1041 Maybe<protocol::DictionaryValue> executionContextAuxDataParam( | 1072 Maybe<protocol::DictionaryValue> executionContextAuxDataParam( |
1042 std::move(executionContextAuxData)); | 1073 std::move(executionContextAuxData)); |
1043 const bool* isLiveEditParam = isLiveEdit ? &isLiveEdit : nullptr; | 1074 const bool* isLiveEditParam = isLiveEdit ? &isLiveEdit : nullptr; |
1044 const bool* hasSourceURLParam = hasSourceURL ? &hasSourceURL : nullptr; | 1075 const bool* hasSourceURLParam = hasSourceURL ? &hasSourceURL : nullptr; |
1045 if (success) | 1076 if (success) |
1046 m_frontend.scriptParsed( | 1077 m_frontend.scriptParsed( |
1047 scriptId, scriptURL, scriptRef->startLine(), scriptRef->startColumn(), | 1078 scriptId, scriptURL, scriptRef->startLine(), scriptRef->startColumn(), |
1048 scriptRef->endLine(), scriptRef->endColumn(), | 1079 scriptRef->endLine(), scriptRef->endColumn(), |
1049 scriptRef->executionContextId(), scriptRef->hash(), | 1080 scriptRef->executionContextId(), scriptRef->hash(m_isolate), |
1050 std::move(executionContextAuxDataParam), isLiveEditParam, | 1081 std::move(executionContextAuxDataParam), isLiveEditParam, |
1051 std::move(sourceMapURLParam), hasSourceURLParam); | 1082 std::move(sourceMapURLParam), hasSourceURLParam); |
1052 else | 1083 else |
1053 m_frontend.scriptFailedToParse( | 1084 m_frontend.scriptFailedToParse( |
1054 scriptId, scriptURL, scriptRef->startLine(), scriptRef->startColumn(), | 1085 scriptId, scriptURL, scriptRef->startLine(), scriptRef->startColumn(), |
1055 scriptRef->endLine(), scriptRef->endColumn(), | 1086 scriptRef->endLine(), scriptRef->endColumn(), |
1056 scriptRef->executionContextId(), scriptRef->hash(), | 1087 scriptRef->executionContextId(), scriptRef->hash(m_isolate), |
1057 std::move(executionContextAuxDataParam), std::move(sourceMapURLParam), | 1088 std::move(executionContextAuxDataParam), std::move(sourceMapURLParam), |
1058 hasSourceURLParam); | 1089 hasSourceURLParam); |
1059 | 1090 |
1060 if (scriptURL.isEmpty() || !success) return; | 1091 if (scriptURL.isEmpty() || !success) return; |
1061 | 1092 |
1062 protocol::DictionaryValue* breakpointsCookie = | 1093 protocol::DictionaryValue* breakpointsCookie = |
1063 m_state->getObject(DebuggerAgentState::javaScriptBreakpoints); | 1094 m_state->getObject(DebuggerAgentState::javaScriptBreakpoints); |
1064 if (!breakpointsCookie) return; | 1095 if (!breakpointsCookie) return; |
1065 | 1096 |
1066 for (size_t i = 0; i < breakpointsCookie->size(); ++i) { | 1097 for (size_t i = 0; i < breakpointsCookie->size(); ++i) { |
(...skipping 168 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
1235 | 1266 |
1236 void V8DebuggerAgentImpl::reset() { | 1267 void V8DebuggerAgentImpl::reset() { |
1237 if (!enabled()) return; | 1268 if (!enabled()) return; |
1238 m_scheduledDebuggerStep = NoStep; | 1269 m_scheduledDebuggerStep = NoStep; |
1239 m_scripts.clear(); | 1270 m_scripts.clear(); |
1240 m_blackboxedPositions.clear(); | 1271 m_blackboxedPositions.clear(); |
1241 m_breakpointIdToDebuggerBreakpointIds.clear(); | 1272 m_breakpointIdToDebuggerBreakpointIds.clear(); |
1242 } | 1273 } |
1243 | 1274 |
1244 } // namespace v8_inspector | 1275 } // namespace v8_inspector |
OLD | NEW |