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 102 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
113 m_isolate(m_inspector->isolate()), | 113 m_isolate(m_inspector->isolate()), |
114 m_breakReason(protocol::Debugger::Paused::ReasonEnum::Other), | 114 m_breakReason(protocol::Debugger::Paused::ReasonEnum::Other), |
115 m_scheduledDebuggerStep(NoStep), | 115 m_scheduledDebuggerStep(NoStep), |
116 m_skipNextDebuggerStepOut(false), | 116 m_skipNextDebuggerStepOut(false), |
117 m_javaScriptPauseScheduled(false), | 117 m_javaScriptPauseScheduled(false), |
118 m_steppingFromFramework(false), | 118 m_steppingFromFramework(false), |
119 m_pausingOnNativeEvent(false), | 119 m_pausingOnNativeEvent(false), |
120 m_skippedStepFrameCount(0), | 120 m_skippedStepFrameCount(0), |
121 m_recursionLevelForStepOut(0), | 121 m_recursionLevelForStepOut(0), |
122 m_recursionLevelForStepFrame(0), | 122 m_recursionLevelForStepFrame(0), |
123 m_skipAllPauses(false) { | 123 m_skipAllPauses(false), |
| 124 m_wasmTranslation(m_isolate, this) { |
124 clearBreakDetails(); | 125 clearBreakDetails(); |
125 } | 126 } |
126 | 127 |
127 V8DebuggerAgentImpl::~V8DebuggerAgentImpl() {} | 128 V8DebuggerAgentImpl::~V8DebuggerAgentImpl() {} |
128 | 129 |
129 void V8DebuggerAgentImpl::enableImpl() { | 130 void V8DebuggerAgentImpl::enableImpl() { |
130 // m_inspector->addListener may result in reporting all parsed scripts to | 131 // m_inspector->addListener may result in reporting all parsed scripts to |
131 // the agent so it should already be in enabled state by then. | 132 // the agent so it should already be in enabled state by then. |
132 m_enabled = true; | 133 m_enabled = true; |
133 m_state->setBoolean(DebuggerAgentState::debuggerEnabled, true); | 134 m_state->setBoolean(DebuggerAgentState::debuggerEnabled, true); |
(...skipping 46 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
180 m_javaScriptPauseScheduled = false; | 181 m_javaScriptPauseScheduled = false; |
181 m_steppingFromFramework = false; | 182 m_steppingFromFramework = false; |
182 m_pausingOnNativeEvent = false; | 183 m_pausingOnNativeEvent = false; |
183 m_skippedStepFrameCount = 0; | 184 m_skippedStepFrameCount = 0; |
184 m_recursionLevelForStepFrame = 0; | 185 m_recursionLevelForStepFrame = 0; |
185 m_skipAllPauses = false; | 186 m_skipAllPauses = false; |
186 m_blackboxPattern = nullptr; | 187 m_blackboxPattern = nullptr; |
187 m_state->remove(DebuggerAgentState::blackboxPattern); | 188 m_state->remove(DebuggerAgentState::blackboxPattern); |
188 m_enabled = false; | 189 m_enabled = false; |
189 m_state->setBoolean(DebuggerAgentState::debuggerEnabled, false); | 190 m_state->setBoolean(DebuggerAgentState::debuggerEnabled, false); |
| 191 m_wasmTranslation.Clear(); |
190 return Response::OK(); | 192 return Response::OK(); |
191 } | 193 } |
192 | 194 |
193 void V8DebuggerAgentImpl::restore() { | 195 void V8DebuggerAgentImpl::restore() { |
194 DCHECK(!m_enabled); | 196 DCHECK(!m_enabled); |
195 if (!m_state->booleanProperty(DebuggerAgentState::debuggerEnabled, false)) | 197 if (!m_state->booleanProperty(DebuggerAgentState::debuggerEnabled, false)) |
196 return; | 198 return; |
197 if (!m_inspector->client()->canExecuteScripts(m_session->contextGroupId())) | 199 if (!m_inspector->client()->canExecuteScripts(m_session->contextGroupId())) |
198 return; | 200 return; |
199 | 201 |
(...skipping 296 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
496 DCHECK(enabled()); | 498 DCHECK(enabled()); |
497 // FIXME: remove these checks once crbug.com/520702 is resolved. | 499 // FIXME: remove these checks once crbug.com/520702 is resolved. |
498 CHECK(!breakpointId.isEmpty()); | 500 CHECK(!breakpointId.isEmpty()); |
499 CHECK(!breakpoint.script_id.isEmpty()); | 501 CHECK(!breakpoint.script_id.isEmpty()); |
500 ScriptsMap::iterator scriptIterator = m_scripts.find(breakpoint.script_id); | 502 ScriptsMap::iterator scriptIterator = m_scripts.find(breakpoint.script_id); |
501 if (scriptIterator == m_scripts.end()) return nullptr; | 503 if (scriptIterator == m_scripts.end()) return nullptr; |
502 if (breakpoint.line_number < scriptIterator->second->startLine() || | 504 if (breakpoint.line_number < scriptIterator->second->startLine() || |
503 scriptIterator->second->endLine() < breakpoint.line_number) | 505 scriptIterator->second->endLine() < breakpoint.line_number) |
504 return nullptr; | 506 return nullptr; |
505 | 507 |
| 508 ScriptBreakpoint translatedBreakpoint(breakpoint); |
| 509 m_wasmTranslation.TranslateBack(&translatedBreakpoint); |
| 510 |
506 int actualLineNumber; | 511 int actualLineNumber; |
507 int actualColumnNumber; | 512 int actualColumnNumber; |
508 String16 debuggerBreakpointId = m_debugger->setBreakpoint( | 513 String16 debuggerBreakpointId = m_debugger->setBreakpoint( |
509 breakpoint, &actualLineNumber, &actualColumnNumber); | 514 translatedBreakpoint, &actualLineNumber, &actualColumnNumber); |
510 if (debuggerBreakpointId.isEmpty()) return nullptr; | 515 if (debuggerBreakpointId.isEmpty()) return nullptr; |
511 | 516 |
512 m_serverBreakpoints[debuggerBreakpointId] = | 517 m_serverBreakpoints[debuggerBreakpointId] = |
513 std::make_pair(breakpointId, source); | 518 std::make_pair(breakpointId, source); |
514 CHECK(!breakpointId.isEmpty()); | 519 CHECK(!breakpointId.isEmpty()); |
515 | 520 |
516 m_breakpointIdToDebuggerBreakpointIds[breakpointId].push_back( | 521 m_breakpointIdToDebuggerBreakpointIds[breakpointId].push_back( |
517 debuggerBreakpointId); | 522 debuggerBreakpointId); |
518 return buildProtocolLocation(breakpoint.script_id, actualLineNumber, | 523 return buildProtocolLocation(translatedBreakpoint.script_id, actualLineNumber, |
519 actualColumnNumber); | 524 actualColumnNumber); |
520 } | 525 } |
521 | 526 |
522 Response V8DebuggerAgentImpl::searchInContent( | 527 Response V8DebuggerAgentImpl::searchInContent( |
523 const String16& scriptId, const String16& query, | 528 const String16& scriptId, const String16& query, |
524 Maybe<bool> optionalCaseSensitive, Maybe<bool> optionalIsRegex, | 529 Maybe<bool> optionalCaseSensitive, Maybe<bool> optionalIsRegex, |
525 std::unique_ptr<Array<protocol::Debugger::SearchMatch>>* results) { | 530 std::unique_ptr<Array<protocol::Debugger::SearchMatch>>* results) { |
526 v8::HandleScope handles(m_isolate); | 531 v8::HandleScope handles(m_isolate); |
527 ScriptsMap::iterator it = m_scripts.find(scriptId); | 532 ScriptsMap::iterator it = m_scripts.find(scriptId); |
528 if (it == m_scripts.end()) | 533 if (it == m_scripts.end()) |
529 return Response::Error("No script for id: " + scriptId); | 534 return Response::Error("No script for id: " + scriptId); |
530 | 535 |
531 std::vector<std::unique_ptr<protocol::Debugger::SearchMatch>> matches = | 536 std::vector<std::unique_ptr<protocol::Debugger::SearchMatch>> matches = |
532 searchInTextByLinesImpl(m_session, | 537 searchInTextByLinesImpl(m_session, it->second->source(m_isolate), query, |
533 toProtocolString(it->second->source(m_isolate)), | 538 optionalCaseSensitive.fromMaybe(false), |
534 query, optionalCaseSensitive.fromMaybe(false), | |
535 optionalIsRegex.fromMaybe(false)); | 539 optionalIsRegex.fromMaybe(false)); |
536 *results = protocol::Array<protocol::Debugger::SearchMatch>::create(); | 540 *results = protocol::Array<protocol::Debugger::SearchMatch>::create(); |
537 for (size_t i = 0; i < matches.size(); ++i) | 541 for (size_t i = 0; i < matches.size(); ++i) |
538 (*results)->addItem(std::move(matches[i])); | 542 (*results)->addItem(std::move(matches[i])); |
539 return Response::OK(); | 543 return Response::OK(); |
540 } | 544 } |
541 | 545 |
542 Response V8DebuggerAgentImpl::setScriptSource( | 546 Response V8DebuggerAgentImpl::setScriptSource( |
543 const String16& scriptId, const String16& newContent, Maybe<bool> dryRun, | 547 const String16& scriptId, const String16& newContent, Maybe<bool> dryRun, |
544 Maybe<protocol::Array<protocol::Debugger::CallFrame>>* newCallFrames, | 548 Maybe<protocol::Array<protocol::Debugger::CallFrame>>* newCallFrames, |
(...skipping 50 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
595 return Response::OK(); | 599 return Response::OK(); |
596 } | 600 } |
597 | 601 |
598 Response V8DebuggerAgentImpl::getScriptSource(const String16& scriptId, | 602 Response V8DebuggerAgentImpl::getScriptSource(const String16& scriptId, |
599 String16* scriptSource) { | 603 String16* scriptSource) { |
600 if (!enabled()) return Response::Error(kDebuggerNotEnabled); | 604 if (!enabled()) return Response::Error(kDebuggerNotEnabled); |
601 ScriptsMap::iterator it = m_scripts.find(scriptId); | 605 ScriptsMap::iterator it = m_scripts.find(scriptId); |
602 if (it == m_scripts.end()) | 606 if (it == m_scripts.end()) |
603 return Response::Error("No script for id: " + scriptId); | 607 return Response::Error("No script for id: " + scriptId); |
604 v8::HandleScope handles(m_isolate); | 608 v8::HandleScope handles(m_isolate); |
605 *scriptSource = toProtocolString(it->second->source(m_isolate)); | 609 *scriptSource = it->second->source(m_isolate); |
606 return Response::OK(); | 610 return Response::OK(); |
607 } | 611 } |
608 | 612 |
609 void V8DebuggerAgentImpl::schedulePauseOnNextStatement( | 613 void V8DebuggerAgentImpl::schedulePauseOnNextStatement( |
610 const String16& breakReason, | 614 const String16& breakReason, |
611 std::unique_ptr<protocol::DictionaryValue> data) { | 615 std::unique_ptr<protocol::DictionaryValue> data) { |
612 if (!enabled() || m_scheduledDebuggerStep == StepInto || | 616 if (!enabled() || m_scheduledDebuggerStep == StepInto || |
613 m_javaScriptPauseScheduled || m_debugger->isPaused() || | 617 m_javaScriptPauseScheduled || m_debugger->isPaused() || |
614 !m_debugger->breakpointsActivated()) | 618 !m_debugger->breakpointsActivated()) |
615 return; | 619 return; |
(...skipping 238 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
854 changeJavaScriptRecursionLevel(+1); | 858 changeJavaScriptRecursionLevel(+1); |
855 // Fast return. | 859 // Fast return. |
856 if (m_scheduledDebuggerStep != StepInto) return; | 860 if (m_scheduledDebuggerStep != StepInto) return; |
857 schedulePauseOnNextStatementIfSteppingInto(); | 861 schedulePauseOnNextStatementIfSteppingInto(); |
858 } | 862 } |
859 | 863 |
860 void V8DebuggerAgentImpl::didExecuteScript() { | 864 void V8DebuggerAgentImpl::didExecuteScript() { |
861 changeJavaScriptRecursionLevel(-1); | 865 changeJavaScriptRecursionLevel(-1); |
862 } | 866 } |
863 | 867 |
| 868 void V8DebuggerAgentImpl::newWasmScript(v8::Local<v8::Object> scriptWrapper) { |
| 869 m_wasmTranslation.AddScript(scriptWrapper); |
| 870 } |
| 871 |
864 void V8DebuggerAgentImpl::changeJavaScriptRecursionLevel(int step) { | 872 void V8DebuggerAgentImpl::changeJavaScriptRecursionLevel(int step) { |
865 if (m_javaScriptPauseScheduled && !m_skipAllPauses && | 873 if (m_javaScriptPauseScheduled && !m_skipAllPauses && |
866 !m_debugger->isPaused()) { | 874 !m_debugger->isPaused()) { |
867 // Do not ever loose user's pause request until we have actually paused. | 875 // Do not ever loose user's pause request until we have actually paused. |
868 m_debugger->setPauseOnNextStatement(true); | 876 m_debugger->setPauseOnNextStatement(true); |
869 } | 877 } |
870 if (m_scheduledDebuggerStep == StepOut) { | 878 if (m_scheduledDebuggerStep == StepOut) { |
871 m_recursionLevelForStepOut += step; | 879 m_recursionLevelForStepOut += step; |
872 if (!m_recursionLevelForStepOut) { | 880 if (!m_recursionLevelForStepOut) { |
873 // When StepOut crosses a task boundary (i.e. js -> c++) from where it was | 881 // When StepOut crosses a task boundary (i.e. js -> c++) from where it was |
(...skipping 123 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
997 return Response::InternalError(); | 1005 return Response::InternalError(); |
998 } | 1006 } |
999 } | 1007 } |
1000 | 1008 |
1001 std::unique_ptr<protocol::Value> protocolValue; | 1009 std::unique_ptr<protocol::Value> protocolValue; |
1002 Response response = toProtocolValue(debuggerContext, objects, &protocolValue); | 1010 Response response = toProtocolValue(debuggerContext, objects, &protocolValue); |
1003 if (!response.isSuccess()) return response; | 1011 if (!response.isSuccess()) return response; |
1004 protocol::ErrorSupport errorSupport; | 1012 protocol::ErrorSupport errorSupport; |
1005 *result = Array<CallFrame>::parse(protocolValue.get(), &errorSupport); | 1013 *result = Array<CallFrame>::parse(protocolValue.get(), &errorSupport); |
1006 if (!*result) return Response::Error(errorSupport.errors()); | 1014 if (!*result) return Response::Error(errorSupport.errors()); |
| 1015 for (size_t i = 0, e = (*result)->length(); i != e; ++i) |
| 1016 m_wasmTranslation.Translate((*result)->get(i)->getLocation()); |
1007 return Response::OK(); | 1017 return Response::OK(); |
1008 } | 1018 } |
1009 | 1019 |
1010 std::unique_ptr<StackTrace> V8DebuggerAgentImpl::currentAsyncStackTrace() { | 1020 std::unique_ptr<StackTrace> V8DebuggerAgentImpl::currentAsyncStackTrace() { |
1011 if (m_pausedContext.IsEmpty()) return nullptr; | 1021 if (m_pausedContext.IsEmpty()) return nullptr; |
1012 V8StackTraceImpl* stackTrace = m_debugger->currentAsyncCallChain(); | 1022 V8StackTraceImpl* stackTrace = m_debugger->currentAsyncCallChain(); |
1013 return stackTrace ? stackTrace->buildInspectorObjectForTail(m_debugger) | 1023 return stackTrace ? stackTrace->buildInspectorObjectForTail(m_debugger) |
1014 : nullptr; | 1024 : nullptr; |
1015 } | 1025 } |
1016 | 1026 |
1017 void V8DebuggerAgentImpl::didParseSource( | 1027 void V8DebuggerAgentImpl::didParseSource( |
1018 std::unique_ptr<V8DebuggerScript> script, bool success) { | 1028 std::unique_ptr<V8DebuggerScript> script, bool success) { |
1019 v8::HandleScope handles(m_isolate); | 1029 v8::HandleScope handles(m_isolate); |
1020 String16 scriptSource = toProtocolString(script->source(m_isolate)); | 1030 String16 scriptSource = script->source(m_isolate); |
1021 if (!success) script->setSourceURL(findSourceURL(scriptSource, false)); | 1031 if (!success) script->setSourceURL(findSourceURL(scriptSource, false)); |
1022 if (!success) | 1032 if (!success) |
1023 script->setSourceMappingURL(findSourceMapURL(scriptSource, false)); | 1033 script->setSourceMappingURL(findSourceMapURL(scriptSource, false)); |
1024 | 1034 |
1025 std::unique_ptr<protocol::DictionaryValue> executionContextAuxData; | 1035 std::unique_ptr<protocol::DictionaryValue> executionContextAuxData; |
1026 if (!script->executionContextAuxData().isEmpty()) | 1036 if (!script->executionContextAuxData().isEmpty()) |
1027 executionContextAuxData = protocol::DictionaryValue::cast( | 1037 executionContextAuxData = protocol::DictionaryValue::cast( |
1028 protocol::parseJSON(script->executionContextAuxData())); | 1038 protocol::parseJSON(script->executionContextAuxData())); |
1029 bool isLiveEdit = script->isLiveEdit(); | 1039 bool isLiveEdit = script->isLiveEdit(); |
1030 bool hasSourceURL = script->hasSourceURL(); | 1040 bool hasSourceURL = script->hasSourceURL(); |
1031 String16 scriptId = script->scriptId(); | 1041 String16 scriptId = script->scriptId(); |
1032 String16 scriptURL = script->sourceURL(); | 1042 String16 scriptURL = script->sourceURL(); |
1033 | 1043 |
1034 m_scripts[scriptId] = std::move(script); | 1044 m_scripts[scriptId] = std::move(script); |
1035 | 1045 |
1036 ScriptsMap::iterator scriptIterator = m_scripts.find(scriptId); | 1046 ScriptsMap::iterator scriptIterator = m_scripts.find(scriptId); |
1037 DCHECK(scriptIterator != m_scripts.end()); | 1047 DCHECK(scriptIterator != m_scripts.end()); |
1038 V8DebuggerScript* scriptRef = scriptIterator->second.get(); | 1048 V8DebuggerScript* scriptRef = scriptIterator->second.get(); |
1039 | 1049 |
1040 Maybe<String16> sourceMapURLParam = scriptRef->sourceMappingURL(); | 1050 Maybe<String16> sourceMapURLParam = scriptRef->sourceMappingURL(); |
1041 Maybe<protocol::DictionaryValue> executionContextAuxDataParam( | 1051 Maybe<protocol::DictionaryValue> executionContextAuxDataParam( |
1042 std::move(executionContextAuxData)); | 1052 std::move(executionContextAuxData)); |
1043 const bool* isLiveEditParam = isLiveEdit ? &isLiveEdit : nullptr; | 1053 const bool* isLiveEditParam = isLiveEdit ? &isLiveEdit : nullptr; |
1044 const bool* hasSourceURLParam = hasSourceURL ? &hasSourceURL : nullptr; | 1054 const bool* hasSourceURLParam = hasSourceURL ? &hasSourceURL : nullptr; |
1045 if (success) | 1055 if (success) |
1046 m_frontend.scriptParsed( | 1056 m_frontend.scriptParsed( |
1047 scriptId, scriptURL, scriptRef->startLine(), scriptRef->startColumn(), | 1057 scriptId, scriptURL, scriptRef->startLine(), scriptRef->startColumn(), |
1048 scriptRef->endLine(), scriptRef->endColumn(), | 1058 scriptRef->endLine(), scriptRef->endColumn(), |
1049 scriptRef->executionContextId(), scriptRef->hash(), | 1059 scriptRef->executionContextId(), scriptRef->hash(m_isolate), |
1050 std::move(executionContextAuxDataParam), isLiveEditParam, | 1060 std::move(executionContextAuxDataParam), isLiveEditParam, |
1051 std::move(sourceMapURLParam), hasSourceURLParam); | 1061 std::move(sourceMapURLParam), hasSourceURLParam); |
1052 else | 1062 else |
1053 m_frontend.scriptFailedToParse( | 1063 m_frontend.scriptFailedToParse( |
1054 scriptId, scriptURL, scriptRef->startLine(), scriptRef->startColumn(), | 1064 scriptId, scriptURL, scriptRef->startLine(), scriptRef->startColumn(), |
1055 scriptRef->endLine(), scriptRef->endColumn(), | 1065 scriptRef->endLine(), scriptRef->endColumn(), |
1056 scriptRef->executionContextId(), scriptRef->hash(), | 1066 scriptRef->executionContextId(), scriptRef->hash(m_isolate), |
1057 std::move(executionContextAuxDataParam), std::move(sourceMapURLParam), | 1067 std::move(executionContextAuxDataParam), std::move(sourceMapURLParam), |
1058 hasSourceURLParam); | 1068 hasSourceURLParam); |
1059 | 1069 |
1060 if (scriptURL.isEmpty() || !success) return; | 1070 if (scriptURL.isEmpty() || !success) return; |
1061 | 1071 |
1062 protocol::DictionaryValue* breakpointsCookie = | 1072 protocol::DictionaryValue* breakpointsCookie = |
1063 m_state->getObject(DebuggerAgentState::javaScriptBreakpoints); | 1073 m_state->getObject(DebuggerAgentState::javaScriptBreakpoints); |
1064 if (!breakpointsCookie) return; | 1074 if (!breakpointsCookie) return; |
1065 | 1075 |
1066 for (size_t i = 0; i < breakpointsCookie->size(); ++i) { | 1076 for (size_t i = 0; i < breakpointsCookie->size(); ++i) { |
(...skipping 167 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
1234 } | 1244 } |
1235 | 1245 |
1236 void V8DebuggerAgentImpl::reset() { | 1246 void V8DebuggerAgentImpl::reset() { |
1237 if (!enabled()) return; | 1247 if (!enabled()) return; |
1238 m_scheduledDebuggerStep = NoStep; | 1248 m_scheduledDebuggerStep = NoStep; |
1239 m_scripts.clear(); | 1249 m_scripts.clear(); |
1240 m_blackboxedPositions.clear(); | 1250 m_blackboxedPositions.clear(); |
1241 m_breakpointIdToDebuggerBreakpointIds.clear(); | 1251 m_breakpointIdToDebuggerBreakpointIds.clear(); |
1242 } | 1252 } |
1243 | 1253 |
| 1254 void V8DebuggerAgentImpl::translateLocation(String16* scriptId, int* lineNumber, |
| 1255 int* columnNumber) { |
| 1256 m_wasmTranslation.Translate(scriptId, lineNumber, columnNumber); |
| 1257 } |
| 1258 |
1244 } // namespace v8_inspector | 1259 } // namespace v8_inspector |
OLD | NEW |