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