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