1 // Copyright 2016 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_V8_INSPECTOR_H_ 6 #define V8_V8_INSPECTOR_H_ 7 8 #include <stdint.h> 9 #include <cctype> 10 11 #include <memory> 12 #include <unordered_map> 13 14 #include "v8.h" // NOLINT(build/include_directory) 15 16 namespace v8_inspector { 17 18 namespace protocol { 19 namespace Debugger { 20 namespace API { 21 class SearchMatch; 22 } 23 } 24 namespace Runtime { 25 namespace API { 26 class RemoteObject; 27 class StackTrace; 28 class StackTraceId; 29 } 30 } 31 namespace Schema { 32 namespace API { 33 class Domain; 34 } 35 } 36 } // namespace protocol 37 38 class V8_EXPORT StringView { 39 public: StringView()40 StringView() : m_is8Bit(true), m_length(0), m_characters8(nullptr) {} 41 StringView(const uint8_t * characters,size_t length)42 StringView(const uint8_t* characters, size_t length) 43 : m_is8Bit(true), m_length(length), m_characters8(characters) {} 44 StringView(const uint16_t * characters,size_t length)45 StringView(const uint16_t* characters, size_t length) 46 : m_is8Bit(false), m_length(length), m_characters16(characters) {} 47 is8Bit()48 bool is8Bit() const { return m_is8Bit; } length()49 size_t length() const { return m_length; } 50 51 // TODO(dgozman): add DCHECK(m_is8Bit) to accessors once platform can be used 52 // here. characters8()53 const uint8_t* characters8() const { return m_characters8; } characters16()54 const uint16_t* characters16() const { return m_characters16; } 55 56 private: 57 bool m_is8Bit; 58 size_t m_length; 59 union { 60 const uint8_t* m_characters8; 61 const uint16_t* m_characters16; 62 }; 63 }; 64 65 class V8_EXPORT StringBuffer { 66 public: 67 virtual ~StringBuffer() = default; 68 virtual StringView string() const = 0; 69 // This method copies contents. 70 static std::unique_ptr<StringBuffer> create(StringView); 71 }; 72 73 class V8_EXPORT V8ContextInfo { 74 public: V8ContextInfo(v8::Local<v8::Context> context,int contextGroupId,StringView humanReadableName)75 V8ContextInfo(v8::Local<v8::Context> context, int contextGroupId, 76 StringView humanReadableName) 77 : context(context), 78 contextGroupId(contextGroupId), 79 humanReadableName(humanReadableName), 80 hasMemoryOnConsole(false) {} 81 82 v8::Local<v8::Context> context; 83 // Each v8::Context is a part of a group. The group id must be non-zero. 84 int contextGroupId; 85 StringView humanReadableName; 86 StringView origin; 87 StringView auxData; 88 bool hasMemoryOnConsole; 89 90 static int executionContextId(v8::Local<v8::Context> context); 91 92 // Disallow copying and allocating this one. 93 enum NotNullTagEnum { NotNullLiteral }; 94 void* operator new(size_t) = delete; 95 void* operator new(size_t, NotNullTagEnum, void*) = delete; 96 void* operator new(size_t, void*) = delete; 97 V8ContextInfo(const V8ContextInfo&) = delete; 98 V8ContextInfo& operator=(const V8ContextInfo&) = delete; 99 }; 100 101 class V8_EXPORT V8StackTrace { 102 public: 103 virtual StringView firstNonEmptySourceURL() const = 0; 104 virtual bool isEmpty() const = 0; 105 virtual StringView topSourceURL() const = 0; 106 virtual int topLineNumber() const = 0; 107 virtual int topColumnNumber() const = 0; 108 virtual StringView topScriptId() const = 0; 109 virtual StringView topFunctionName() const = 0; 110 111 virtual ~V8StackTrace() = default; 112 virtual std::unique_ptr<protocol::Runtime::API::StackTrace> 113 buildInspectorObject() const = 0; 114 virtual std::unique_ptr<protocol::Runtime::API::StackTrace> 115 buildInspectorObject(int maxAsyncDepth) const = 0; 116 virtual std::unique_ptr<StringBuffer> toString() const = 0; 117 118 // Safe to pass between threads, drops async chain. 119 virtual std::unique_ptr<V8StackTrace> clone() = 0; 120 }; 121 122 class V8_EXPORT V8InspectorSession { 123 public: 124 virtual ~V8InspectorSession() = default; 125 126 // Cross-context inspectable values (DOM nodes in different worlds, etc.). 127 class V8_EXPORT Inspectable { 128 public: 129 virtual v8::Local<v8::Value> get(v8::Local<v8::Context>) = 0; 130 virtual ~Inspectable() = default; 131 }; 132 virtual void addInspectedObject(std::unique_ptr<Inspectable>) = 0; 133 134 // Dispatching protocol messages. 135 static bool canDispatchMethod(StringView method); 136 virtual void dispatchProtocolMessage(StringView message) = 0; 137 virtual std::vector<uint8_t> state() = 0; 138 virtual std::vector<std::unique_ptr<protocol::Schema::API::Domain>> 139 supportedDomains() = 0; 140 141 // Debugger actions. 142 virtual void schedulePauseOnNextStatement(StringView breakReason, 143 StringView breakDetails) = 0; 144 virtual void cancelPauseOnNextStatement() = 0; 145 virtual void breakProgram(StringView breakReason, 146 StringView breakDetails) = 0; 147 virtual void setSkipAllPauses(bool) = 0; 148 virtual void resume(bool setTerminateOnResume = false) = 0; 149 virtual void stepOver() = 0; 150 virtual std::vector<std::unique_ptr<protocol::Debugger::API::SearchMatch>> 151 searchInTextByLines(StringView text, StringView query, bool caseSensitive, 152 bool isRegex) = 0; 153 154 // Remote objects. 155 virtual std::unique_ptr<protocol::Runtime::API::RemoteObject> wrapObject( 156 v8::Local<v8::Context>, v8::Local<v8::Value>, StringView groupName, 157 bool generatePreview) = 0; 158 159 virtual bool unwrapObject(std::unique_ptr<StringBuffer>* error, 160 StringView objectId, v8::Local<v8::Value>*, 161 v8::Local<v8::Context>*, 162 std::unique_ptr<StringBuffer>* objectGroup) = 0; 163 virtual void releaseObjectGroup(StringView) = 0; 164 virtual void triggerPreciseCoverageDeltaUpdate(StringView occassion) = 0; 165 }; 166 167 class V8_EXPORT V8InspectorClient { 168 public: 169 virtual ~V8InspectorClient() = default; 170 runMessageLoopOnPause(int contextGroupId)171 virtual void runMessageLoopOnPause(int contextGroupId) {} quitMessageLoopOnPause()172 virtual void quitMessageLoopOnPause() {} runIfWaitingForDebugger(int contextGroupId)173 virtual void runIfWaitingForDebugger(int contextGroupId) {} 174 muteMetrics(int contextGroupId)175 virtual void muteMetrics(int contextGroupId) {} unmuteMetrics(int contextGroupId)176 virtual void unmuteMetrics(int contextGroupId) {} 177 beginUserGesture()178 virtual void beginUserGesture() {} endUserGesture()179 virtual void endUserGesture() {} 180 valueSubtype(v8::Local<v8::Value>)181 virtual std::unique_ptr<StringBuffer> valueSubtype(v8::Local<v8::Value>) { 182 return nullptr; 183 } descriptionForValueSubtype(v8::Local<v8::Context>,v8::Local<v8::Value>)184 virtual std::unique_ptr<StringBuffer> descriptionForValueSubtype( 185 v8::Local<v8::Context>, v8::Local<v8::Value>) { 186 return nullptr; 187 } formatAccessorsAsProperties(v8::Local<v8::Value>)188 virtual bool formatAccessorsAsProperties(v8::Local<v8::Value>) { 189 return false; 190 } isInspectableHeapObject(v8::Local<v8::Object>)191 virtual bool isInspectableHeapObject(v8::Local<v8::Object>) { return true; } 192 ensureDefaultContextInGroup(int contextGroupId)193 virtual v8::Local<v8::Context> ensureDefaultContextInGroup( 194 int contextGroupId) { 195 return v8::Local<v8::Context>(); 196 } beginEnsureAllContextsInGroup(int contextGroupId)197 virtual void beginEnsureAllContextsInGroup(int contextGroupId) {} endEnsureAllContextsInGroup(int contextGroupId)198 virtual void endEnsureAllContextsInGroup(int contextGroupId) {} 199 installAdditionalCommandLineAPI(v8::Local<v8::Context>,v8::Local<v8::Object>)200 virtual void installAdditionalCommandLineAPI(v8::Local<v8::Context>, 201 v8::Local<v8::Object>) {} consoleAPIMessage(int contextGroupId,v8::Isolate::MessageErrorLevel level,const StringView & message,const StringView & url,unsigned lineNumber,unsigned columnNumber,V8StackTrace *)202 virtual void consoleAPIMessage(int contextGroupId, 203 v8::Isolate::MessageErrorLevel level, 204 const StringView& message, 205 const StringView& url, unsigned lineNumber, 206 unsigned columnNumber, V8StackTrace*) {} memoryInfo(v8::Isolate *,v8::Local<v8::Context>)207 virtual v8::MaybeLocal<v8::Value> memoryInfo(v8::Isolate*, 208 v8::Local<v8::Context>) { 209 return v8::MaybeLocal<v8::Value>(); 210 } 211 consoleTime(const StringView & title)212 virtual void consoleTime(const StringView& title) {} consoleTimeEnd(const StringView & title)213 virtual void consoleTimeEnd(const StringView& title) {} consoleTimeStamp(const StringView & title)214 virtual void consoleTimeStamp(const StringView& title) {} consoleClear(int contextGroupId)215 virtual void consoleClear(int contextGroupId) {} currentTimeMS()216 virtual double currentTimeMS() { return 0; } 217 typedef void (*TimerCallback)(void*); startRepeatingTimer(double,TimerCallback,void * data)218 virtual void startRepeatingTimer(double, TimerCallback, void* data) {} cancelTimer(void * data)219 virtual void cancelTimer(void* data) {} 220 221 // TODO(dgozman): this was added to support service worker shadow page. We 222 // should not connect at all. canExecuteScripts(int contextGroupId)223 virtual bool canExecuteScripts(int contextGroupId) { return true; } 224 maxAsyncCallStackDepthChanged(int depth)225 virtual void maxAsyncCallStackDepthChanged(int depth) {} 226 resourceNameToUrl(const StringView & resourceName)227 virtual std::unique_ptr<StringBuffer> resourceNameToUrl( 228 const StringView& resourceName) { 229 return nullptr; 230 } 231 }; 232 233 // These stack trace ids are intended to be passed between debuggers and be 234 // resolved later. This allows to track cross-debugger calls and step between 235 // them if a single client connects to multiple debuggers. 236 struct V8_EXPORT V8StackTraceId { 237 uintptr_t id; 238 std::pair<int64_t, int64_t> debugger_id; 239 bool should_pause = false; 240 241 V8StackTraceId(); 242 V8StackTraceId(const V8StackTraceId&) = default; 243 V8StackTraceId(uintptr_t id, const std::pair<int64_t, int64_t> debugger_id); 244 V8StackTraceId(uintptr_t id, const std::pair<int64_t, int64_t> debugger_id, 245 bool should_pause); 246 explicit V8StackTraceId(StringView); 247 V8StackTraceId& operator=(const V8StackTraceId&) = default; 248 V8StackTraceId& operator=(V8StackTraceId&&) noexcept = default; 249 ~V8StackTraceId() = default; 250 251 bool IsInvalid() const; 252 std::unique_ptr<StringBuffer> ToString(); 253 }; 254 255 class V8_EXPORT V8Inspector { 256 public: 257 static std::unique_ptr<V8Inspector> create(v8::Isolate*, V8InspectorClient*); 258 virtual ~V8Inspector() = default; 259 260 // Contexts instrumentation. 261 virtual void contextCreated(const V8ContextInfo&) = 0; 262 virtual void contextDestroyed(v8::Local<v8::Context>) = 0; 263 virtual void resetContextGroup(int contextGroupId) = 0; 264 virtual v8::MaybeLocal<v8::Context> contextById(int contextId) = 0; 265 266 // Various instrumentation. 267 virtual void idleStarted() = 0; 268 virtual void idleFinished() = 0; 269 270 // Async stack traces instrumentation. 271 virtual void asyncTaskScheduled(StringView taskName, void* task, 272 bool recurring) = 0; 273 virtual void asyncTaskCanceled(void* task) = 0; 274 virtual void asyncTaskStarted(void* task) = 0; 275 virtual void asyncTaskFinished(void* task) = 0; 276 virtual void allAsyncTasksCanceled() = 0; 277 278 virtual V8StackTraceId storeCurrentStackTrace(StringView description) = 0; 279 virtual void externalAsyncTaskStarted(const V8StackTraceId& parent) = 0; 280 virtual void externalAsyncTaskFinished(const V8StackTraceId& parent) = 0; 281 282 // Exceptions instrumentation. 283 virtual unsigned exceptionThrown(v8::Local<v8::Context>, StringView message, 284 v8::Local<v8::Value> exception, 285 StringView detailedMessage, StringView url, 286 unsigned lineNumber, unsigned columnNumber, 287 std::unique_ptr<V8StackTrace>, 288 int scriptId) = 0; 289 virtual void exceptionRevoked(v8::Local<v8::Context>, unsigned exceptionId, 290 StringView message) = 0; 291 292 // Connection. 293 class V8_EXPORT Channel { 294 public: 295 virtual ~Channel() = default; 296 virtual void sendResponse(int callId, 297 std::unique_ptr<StringBuffer> message) = 0; 298 virtual void sendNotification(std::unique_ptr<StringBuffer> message) = 0; 299 virtual void flushProtocolNotifications() = 0; 300 }; 301 virtual std::unique_ptr<V8InspectorSession> connect(int contextGroupId, 302 Channel*, 303 StringView state) = 0; 304 305 // API methods. 306 virtual std::unique_ptr<V8StackTrace> createStackTrace( 307 v8::Local<v8::StackTrace>) = 0; 308 virtual std::unique_ptr<V8StackTrace> captureStackTrace(bool fullStack) = 0; 309 310 // Performance counters. 311 class V8_EXPORT Counters : public std::enable_shared_from_this<Counters> { 312 public: 313 explicit Counters(v8::Isolate* isolate); 314 ~Counters(); getCountersMap()315 const std::unordered_map<std::string, int>& getCountersMap() const { 316 return m_countersMap; 317 } 318 319 private: 320 static int* getCounterPtr(const char* name); 321 322 v8::Isolate* m_isolate; 323 std::unordered_map<std::string, int> m_countersMap; 324 }; 325 326 virtual std::shared_ptr<Counters> enableCounters() = 0; 327 }; 328 329 } // namespace v8_inspector 330 331 #endif // V8_V8_INSPECTOR_H_ 332