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 3 // found in the LICENSE file. 4 5 #ifndef V8_INSPECTOR_V8_DEBUGGER_AGENT_IMPL_H_ 6 #define V8_INSPECTOR_V8_DEBUGGER_AGENT_IMPL_H_ 7 8 #include <deque> 9 #include <memory> 10 #include <unordered_map> 11 #include <vector> 12 13 #include "src/base/macros.h" 14 #include "src/debug/debug-interface.h" 15 #include "src/debug/interface-types.h" 16 #include "src/inspector/protocol/Debugger.h" 17 #include "src/inspector/protocol/Forward.h" 18 19 namespace v8_inspector { 20 21 struct ScriptBreakpoint; 22 class V8Debugger; 23 class V8DebuggerScript; 24 class V8InspectorImpl; 25 class V8InspectorSessionImpl; 26 class V8Regex; 27 28 using protocol::Maybe; 29 using protocol::Response; 30 31 class V8DebuggerAgentImpl : public protocol::Debugger::Backend { 32 public: 33 enum BreakpointSource { 34 UserBreakpointSource, 35 DebugCommandBreakpointSource, 36 MonitorCommandBreakpointSource 37 }; 38 39 V8DebuggerAgentImpl(V8InspectorSessionImpl*, protocol::FrontendChannel*, 40 protocol::DictionaryValue* state); 41 ~V8DebuggerAgentImpl() override; 42 void restore(); 43 44 // Part of the protocol. 45 Response enable(Maybe<double> maxScriptsCacheSize, 46 String16* outDebuggerId) override; 47 Response disable() override; 48 Response setBreakpointsActive(bool active) override; 49 Response setSkipAllPauses(bool skip) override; 50 Response setBreakpointByUrl( 51 int lineNumber, Maybe<String16> optionalURL, 52 Maybe<String16> optionalURLRegex, Maybe<String16> optionalScriptHash, 53 Maybe<int> optionalColumnNumber, Maybe<String16> optionalCondition, 54 String16*, 55 std::unique_ptr<protocol::Array<protocol::Debugger::Location>>* locations) 56 override; 57 Response setBreakpoint( 58 std::unique_ptr<protocol::Debugger::Location>, 59 Maybe<String16> optionalCondition, String16*, 60 std::unique_ptr<protocol::Debugger::Location>* actualLocation) override; 61 Response setBreakpointOnFunctionCall(const String16& functionObjectId, 62 Maybe<String16> optionalCondition, 63 String16* outBreakpointId) override; 64 Response setInstrumentationBreakpoint(const String16& instrumentation, 65 String16* outBreakpointId) override; 66 Response removeBreakpoint(const String16& breakpointId) override; 67 Response continueToLocation(std::unique_ptr<protocol::Debugger::Location>, 68 Maybe<String16> targetCallFrames) override; 69 Response getStackTrace( 70 std::unique_ptr<protocol::Runtime::StackTraceId> inStackTraceId, 71 std::unique_ptr<protocol::Runtime::StackTrace>* outStackTrace) override; 72 Response searchInContent( 73 const String16& scriptId, const String16& query, 74 Maybe<bool> optionalCaseSensitive, Maybe<bool> optionalIsRegex, 75 std::unique_ptr<protocol::Array<protocol::Debugger::SearchMatch>>*) 76 override; 77 Response getPossibleBreakpoints( 78 std::unique_ptr<protocol::Debugger::Location> start, 79 Maybe<protocol::Debugger::Location> end, Maybe<bool> restrictToFunction, 80 std::unique_ptr<protocol::Array<protocol::Debugger::BreakLocation>>* 81 locations) override; 82 Response setScriptSource( 83 const String16& inScriptId, const String16& inScriptSource, 84 Maybe<bool> dryRun, 85 Maybe<protocol::Array<protocol::Debugger::CallFrame>>* optOutCallFrames, 86 Maybe<bool>* optOutStackChanged, 87 Maybe<protocol::Runtime::StackTrace>* optOutAsyncStackTrace, 88 Maybe<protocol::Runtime::StackTraceId>* optOutAsyncStackTraceId, 89 Maybe<protocol::Runtime::ExceptionDetails>* optOutCompileError) override; 90 Response restartFrame( 91 const String16& callFrameId, 92 std::unique_ptr<protocol::Array<protocol::Debugger::CallFrame>>* 93 newCallFrames, 94 Maybe<protocol::Runtime::StackTrace>* asyncStackTrace, 95 Maybe<protocol::Runtime::StackTraceId>* asyncStackTraceId) override; 96 Response getScriptSource(const String16& scriptId, String16* scriptSource, 97 Maybe<protocol::Binary>* bytecode) override; 98 Response getWasmBytecode(const String16& scriptId, 99 protocol::Binary* bytecode) override; 100 Response pause() override; 101 Response resume(Maybe<bool> terminateOnResume) override; 102 Response stepOver(Maybe<protocol::Array<protocol::Debugger::LocationRange>> 103 inSkipList) override; 104 Response stepInto(Maybe<bool> inBreakOnAsyncCall, 105 Maybe<protocol::Array<protocol::Debugger::LocationRange>> 106 inSkipList) override; 107 Response stepOut() override; 108 Response pauseOnAsyncCall(std::unique_ptr<protocol::Runtime::StackTraceId> 109 inParentStackTraceId) override; 110 Response setPauseOnExceptions(const String16& pauseState) override; 111 Response evaluateOnCallFrame( 112 const String16& callFrameId, const String16& expression, 113 Maybe<String16> objectGroup, Maybe<bool> includeCommandLineAPI, 114 Maybe<bool> silent, Maybe<bool> returnByValue, 115 Maybe<bool> generatePreview, Maybe<bool> throwOnSideEffect, 116 Maybe<double> timeout, 117 std::unique_ptr<protocol::Runtime::RemoteObject>* result, 118 Maybe<protocol::Runtime::ExceptionDetails>*) override; 119 Response executeWasmEvaluator( 120 const String16& callFrameId, const protocol::Binary& evaluator, 121 Maybe<double> timeout, 122 std::unique_ptr<protocol::Runtime::RemoteObject>* result, 123 Maybe<protocol::Runtime::ExceptionDetails>* exceptionDetails) override; 124 Response setVariableValue( 125 int scopeNumber, const String16& variableName, 126 std::unique_ptr<protocol::Runtime::CallArgument> newValue, 127 const String16& callFrame) override; 128 Response setReturnValue( 129 std::unique_ptr<protocol::Runtime::CallArgument> newValue) override; 130 Response setAsyncCallStackDepth(int depth) override; 131 Response setBlackboxPatterns( 132 std::unique_ptr<protocol::Array<String16>> patterns) override; 133 Response setBlackboxedRanges( 134 const String16& scriptId, 135 std::unique_ptr<protocol::Array<protocol::Debugger::ScriptPosition>> 136 positions) override; 137 enabled()138 bool enabled() const { return m_enabled; } 139 140 void setBreakpointFor(v8::Local<v8::Function> function, 141 v8::Local<v8::String> condition, 142 BreakpointSource source); 143 void removeBreakpointFor(v8::Local<v8::Function> function, 144 BreakpointSource source); 145 void schedulePauseOnNextStatement( 146 const String16& breakReason, 147 std::unique_ptr<protocol::DictionaryValue> data); 148 void cancelPauseOnNextStatement(); 149 void breakProgram(const String16& breakReason, 150 std::unique_ptr<protocol::DictionaryValue> data); 151 152 void reset(); 153 154 // Interface for V8InspectorImpl 155 void didPause(int contextId, v8::Local<v8::Value> exception, 156 const std::vector<v8::debug::BreakpointId>& hitBreakpoints, 157 v8::debug::ExceptionType exceptionType, bool isUncaught, 158 bool isOOMBreak, bool isAssert); 159 void didContinue(); 160 void didParseSource(std::unique_ptr<V8DebuggerScript>, bool success); 161 162 bool isFunctionBlackboxed(const String16& scriptId, 163 const v8::debug::Location& start, 164 const v8::debug::Location& end); 165 bool shouldBeSkipped(const String16& scriptId, int line, int column); 166 167 bool acceptsPause(bool isOOMBreak) const; 168 169 void ScriptCollected(const V8DebuggerScript* script); 170 isolate()171 v8::Isolate* isolate() { return m_isolate; } 172 173 private: 174 void enableImpl(); 175 176 Response currentCallFrames( 177 std::unique_ptr<protocol::Array<protocol::Debugger::CallFrame>>*); 178 std::unique_ptr<protocol::Runtime::StackTrace> currentAsyncStackTrace(); 179 std::unique_ptr<protocol::Runtime::StackTraceId> currentExternalStackTrace(); 180 181 void setPauseOnExceptionsImpl(int); 182 183 std::unique_ptr<protocol::Debugger::Location> setBreakpointImpl( 184 const String16& breakpointId, const String16& scriptId, 185 const String16& condition, int lineNumber, int columnNumber); 186 void setBreakpointImpl(const String16& breakpointId, 187 v8::Local<v8::Function> function, 188 v8::Local<v8::String> condition); 189 void removeBreakpointImpl(const String16& breakpointId, 190 const std::vector<V8DebuggerScript*>& scripts); 191 void clearBreakDetails(); 192 193 void internalSetAsyncCallStackDepth(int); 194 void increaseCachedSkipStackGeneration(); 195 196 Response setBlackboxPattern(const String16& pattern); 197 void resetBlackboxedStateCache(); 198 199 bool isPaused() const; 200 201 void setScriptInstrumentationBreakpointIfNeeded(V8DebuggerScript* script); 202 203 Response processSkipList( 204 protocol::Array<protocol::Debugger::LocationRange>* skipList); 205 206 using ScriptsMap = 207 std::unordered_map<String16, std::unique_ptr<V8DebuggerScript>>; 208 using BreakpointIdToDebuggerBreakpointIdsMap = 209 std::unordered_map<String16, std::vector<v8::debug::BreakpointId>>; 210 using DebuggerBreakpointIdToBreakpointIdMap = 211 std::unordered_map<v8::debug::BreakpointId, String16>; 212 213 V8InspectorImpl* m_inspector; 214 V8Debugger* m_debugger; 215 V8InspectorSessionImpl* m_session; 216 bool m_enabled; 217 protocol::DictionaryValue* m_state; 218 protocol::Debugger::Frontend m_frontend; 219 v8::Isolate* m_isolate; 220 ScriptsMap m_scripts; 221 BreakpointIdToDebuggerBreakpointIdsMap m_breakpointIdToDebuggerBreakpointIds; 222 DebuggerBreakpointIdToBreakpointIdMap m_debuggerBreakpointIdToBreakpointId; 223 std::unordered_map<v8::debug::BreakpointId, 224 std::unique_ptr<protocol::DictionaryValue>> 225 m_breakpointsOnScriptRun; 226 227 size_t m_maxScriptCacheSize = 0; 228 size_t m_cachedScriptSize = 0; 229 std::deque<String16> m_cachedScriptIds; 230 231 using BreakReason = 232 std::pair<String16, std::unique_ptr<protocol::DictionaryValue>>; 233 std::vector<BreakReason> m_breakReason; 234 235 void pushBreakDetails( 236 const String16& breakReason, 237 std::unique_ptr<protocol::DictionaryValue> breakAuxData); 238 void popBreakDetails(); 239 240 bool m_skipAllPauses = false; 241 bool m_breakpointsActive = false; 242 243 std::unique_ptr<V8Regex> m_blackboxPattern; 244 std::unordered_map<String16, std::vector<std::pair<int, int>>> 245 m_blackboxedPositions; 246 std::unordered_map<String16, std::vector<std::pair<int, int>>> m_skipList; 247 248 DISALLOW_COPY_AND_ASSIGN(V8DebuggerAgentImpl); 249 }; 250 251 } // namespace v8_inspector 252 253 #endif // V8_INSPECTOR_V8_DEBUGGER_AGENT_IMPL_H_ 254