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/enum-set.h" 14 #include "src/base/macros.h" 15 #include "src/debug/debug-interface.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 V8DebuggerAgentImpl(const V8DebuggerAgentImpl&) = delete; 43 V8DebuggerAgentImpl& operator=(const V8DebuggerAgentImpl&) = delete; 44 void restore(); 45 46 // Part of the protocol. 47 Response enable(Maybe<double> maxScriptsCacheSize, 48 String16* outDebuggerId) override; 49 Response disable() override; 50 Response setBreakpointsActive(bool active) override; 51 Response setSkipAllPauses(bool skip) override; 52 Response setBreakpointByUrl( 53 int lineNumber, Maybe<String16> optionalURL, 54 Maybe<String16> optionalURLRegex, Maybe<String16> optionalScriptHash, 55 Maybe<int> optionalColumnNumber, Maybe<String16> optionalCondition, 56 String16*, 57 std::unique_ptr<protocol::Array<protocol::Debugger::Location>>* locations) 58 override; 59 Response setBreakpoint( 60 std::unique_ptr<protocol::Debugger::Location>, 61 Maybe<String16> optionalCondition, String16*, 62 std::unique_ptr<protocol::Debugger::Location>* actualLocation) override; 63 Response setBreakpointOnFunctionCall(const String16& functionObjectId, 64 Maybe<String16> optionalCondition, 65 String16* outBreakpointId) override; 66 Response setInstrumentationBreakpoint(const String16& instrumentation, 67 String16* outBreakpointId) override; 68 Response removeBreakpoint(const String16& breakpointId) override; 69 Response continueToLocation(std::unique_ptr<protocol::Debugger::Location>, 70 Maybe<String16> targetCallFrames) override; 71 Response getStackTrace( 72 std::unique_ptr<protocol::Runtime::StackTraceId> inStackTraceId, 73 std::unique_ptr<protocol::Runtime::StackTrace>* outStackTrace) override; 74 Response searchInContent( 75 const String16& scriptId, const String16& query, 76 Maybe<bool> optionalCaseSensitive, Maybe<bool> optionalIsRegex, 77 std::unique_ptr<protocol::Array<protocol::Debugger::SearchMatch>>*) 78 override; 79 Response getPossibleBreakpoints( 80 std::unique_ptr<protocol::Debugger::Location> start, 81 Maybe<protocol::Debugger::Location> end, Maybe<bool> restrictToFunction, 82 std::unique_ptr<protocol::Array<protocol::Debugger::BreakLocation>>* 83 locations) override; 84 Response setScriptSource( 85 const String16& inScriptId, const String16& inScriptSource, 86 Maybe<bool> dryRun, 87 Maybe<protocol::Array<protocol::Debugger::CallFrame>>* optOutCallFrames, 88 Maybe<bool>* optOutStackChanged, 89 Maybe<protocol::Runtime::StackTrace>* optOutAsyncStackTrace, 90 Maybe<protocol::Runtime::StackTraceId>* optOutAsyncStackTraceId, 91 Maybe<protocol::Runtime::ExceptionDetails>* optOutCompileError) override; 92 Response restartFrame( 93 const String16& callFrameId, 94 std::unique_ptr<protocol::Array<protocol::Debugger::CallFrame>>* 95 newCallFrames, 96 Maybe<protocol::Runtime::StackTrace>* asyncStackTrace, 97 Maybe<protocol::Runtime::StackTraceId>* asyncStackTraceId) override; 98 Response getScriptSource(const String16& scriptId, String16* scriptSource, 99 Maybe<protocol::Binary>* bytecode) override; 100 Response getWasmBytecode(const String16& scriptId, 101 protocol::Binary* bytecode) override; 102 Response pause() override; 103 Response resume(Maybe<bool> terminateOnResume) override; 104 Response stepOver(Maybe<protocol::Array<protocol::Debugger::LocationRange>> 105 inSkipList) override; 106 Response stepInto(Maybe<bool> inBreakOnAsyncCall, 107 Maybe<protocol::Array<protocol::Debugger::LocationRange>> 108 inSkipList) override; 109 Response stepOut() override; 110 Response pauseOnAsyncCall(std::unique_ptr<protocol::Runtime::StackTraceId> 111 inParentStackTraceId) override; 112 Response setPauseOnExceptions(const String16& pauseState) override; 113 Response evaluateOnCallFrame( 114 const String16& callFrameId, const String16& expression, 115 Maybe<String16> objectGroup, Maybe<bool> includeCommandLineAPI, 116 Maybe<bool> silent, Maybe<bool> returnByValue, 117 Maybe<bool> generatePreview, Maybe<bool> throwOnSideEffect, 118 Maybe<double> timeout, 119 std::unique_ptr<protocol::Runtime::RemoteObject>* result, 120 Maybe<protocol::Runtime::ExceptionDetails>*) override; 121 Response setVariableValue( 122 int scopeNumber, const String16& variableName, 123 std::unique_ptr<protocol::Runtime::CallArgument> newValue, 124 const String16& callFrame) override; 125 Response setReturnValue( 126 std::unique_ptr<protocol::Runtime::CallArgument> newValue) override; 127 Response setAsyncCallStackDepth(int depth) override; 128 Response setBlackboxPatterns( 129 std::unique_ptr<protocol::Array<String16>> patterns) override; 130 Response setBlackboxedRanges( 131 const String16& scriptId, 132 std::unique_ptr<protocol::Array<protocol::Debugger::ScriptPosition>> 133 positions) override; 134 enabled() const135 bool enabled() const { return m_enabled; } 136 137 void setBreakpointFor(v8::Local<v8::Function> function, 138 v8::Local<v8::String> condition, 139 BreakpointSource source); 140 void removeBreakpointFor(v8::Local<v8::Function> function, 141 BreakpointSource source); 142 void schedulePauseOnNextStatement( 143 const String16& breakReason, 144 std::unique_ptr<protocol::DictionaryValue> data); 145 void cancelPauseOnNextStatement(); 146 void breakProgram(const String16& breakReason, 147 std::unique_ptr<protocol::DictionaryValue> data); 148 149 void reset(); 150 151 // Interface for V8InspectorImpl 152 void didPauseOnInstrumentation(v8::debug::BreakpointId instrumentationId); 153 154 void didPause(int contextId, v8::Local<v8::Value> exception, 155 const std::vector<v8::debug::BreakpointId>& hitBreakpoints, 156 v8::debug::ExceptionType exceptionType, bool isUncaught, 157 v8::debug::BreakReasons breakReasons); 158 void didContinue(); 159 void didParseSource(std::unique_ptr<V8DebuggerScript>, bool success); 160 161 bool isFunctionBlackboxed(const String16& scriptId, 162 const v8::debug::Location& start, 163 const v8::debug::Location& end); 164 bool shouldBeSkipped(const String16& scriptId, int line, int column); 165 166 bool acceptsPause(bool isOOMBreak) const; 167 168 void ScriptCollected(const V8DebuggerScript* script); 169 isolate()170 v8::Isolate* isolate() { return m_isolate; } 171 172 void clearBreakDetails(); 173 174 private: 175 void enableImpl(); 176 177 Response currentCallFrames( 178 std::unique_ptr<protocol::Array<protocol::Debugger::CallFrame>>*); 179 std::unique_ptr<protocol::Runtime::StackTrace> currentAsyncStackTrace(); 180 std::unique_ptr<protocol::Runtime::StackTraceId> currentExternalStackTrace(); 181 182 void setPauseOnExceptionsImpl(int); 183 184 std::unique_ptr<protocol::Debugger::Location> setBreakpointImpl( 185 const String16& breakpointId, const String16& scriptId, 186 const String16& condition, int lineNumber, int columnNumber); 187 void setBreakpointImpl(const String16& breakpointId, 188 v8::Local<v8::Function> function, 189 v8::Local<v8::String> condition); 190 void removeBreakpointImpl(const String16& breakpointId, 191 const std::vector<V8DebuggerScript*>& scripts); 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 struct CachedScript { 230 String16 scriptId; 231 String16 source; 232 std::vector<uint8_t> bytecode; 233 sizev8_inspector::V8DebuggerAgentImpl::CachedScript234 size_t size() const { 235 return source.length() * sizeof(UChar) + bytecode.size(); 236 } 237 }; 238 std::deque<CachedScript> m_cachedScripts; 239 240 using BreakReason = 241 std::pair<String16, std::unique_ptr<protocol::DictionaryValue>>; 242 std::vector<BreakReason> m_breakReason; 243 244 void pushBreakDetails( 245 const String16& breakReason, 246 std::unique_ptr<protocol::DictionaryValue> breakAuxData); 247 void popBreakDetails(); 248 249 bool m_skipAllPauses = false; 250 bool m_breakpointsActive = false; 251 252 std::unique_ptr<V8Regex> m_blackboxPattern; 253 std::unordered_map<String16, std::vector<std::pair<int, int>>> 254 m_blackboxedPositions; 255 std::unordered_map<String16, std::vector<std::pair<int, int>>> m_skipList; 256 }; 257 258 } // namespace v8_inspector 259 260 #endif // V8_INSPECTOR_V8_DEBUGGER_AGENT_IMPL_H_ 261