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