/src/node/deps/v8/include/v8-inspector.h
Line | Count | Source |
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 internal { |
27 | | class V8DebuggerId; |
28 | | } // namespace internal |
29 | | |
30 | | namespace protocol { |
31 | | namespace Debugger { |
32 | | namespace API { |
33 | | class SearchMatch; |
34 | | } |
35 | | } // namespace Debugger |
36 | | namespace Runtime { |
37 | | namespace API { |
38 | | class RemoteObject; |
39 | | class StackTrace; |
40 | | class StackTraceId; |
41 | | } // namespace API |
42 | | } // namespace Runtime |
43 | | namespace Schema { |
44 | | namespace API { |
45 | | class Domain; |
46 | | } |
47 | | } // namespace Schema |
48 | | } // namespace protocol |
49 | | |
50 | | class V8_EXPORT StringView { |
51 | | public: |
52 | 70 | StringView() : m_is8Bit(true), m_length(0), m_characters8(nullptr) {} |
53 | | |
54 | | StringView(const uint8_t* characters, size_t length) |
55 | 0 | : m_is8Bit(true), m_length(length), m_characters8(characters) {} |
56 | | |
57 | | StringView(const uint16_t* characters, size_t length) |
58 | 105 | : m_is8Bit(false), m_length(length), m_characters16(characters) {} |
59 | | |
60 | 0 | bool is8Bit() const { return m_is8Bit; } |
61 | 0 | size_t length() const { return m_length; } |
62 | | |
63 | | // TODO(dgozman): add DCHECK(m_is8Bit) to accessors once platform can be used |
64 | | // here. |
65 | 0 | const uint8_t* characters8() const { return m_characters8; } |
66 | 0 | const uint16_t* characters16() const { return m_characters16; } |
67 | | |
68 | | private: |
69 | | bool m_is8Bit; |
70 | | size_t m_length; |
71 | | union { |
72 | | const uint8_t* m_characters8; |
73 | | const uint16_t* m_characters16; |
74 | | }; |
75 | | }; |
76 | | |
77 | | class V8_EXPORT StringBuffer { |
78 | | public: |
79 | | virtual ~StringBuffer() = default; |
80 | | virtual StringView string() const = 0; |
81 | | // This method copies contents. |
82 | | static std::unique_ptr<StringBuffer> create(StringView); |
83 | | }; |
84 | | |
85 | | class V8_EXPORT V8ContextInfo { |
86 | | public: |
87 | | V8ContextInfo(v8::Local<v8::Context> context, int contextGroupId, |
88 | | StringView humanReadableName) |
89 | 35 | : context(context), |
90 | 35 | contextGroupId(contextGroupId), |
91 | 35 | humanReadableName(humanReadableName), |
92 | 35 | hasMemoryOnConsole(false) {} |
93 | | |
94 | | v8::Local<v8::Context> context; |
95 | | // Each v8::Context is a part of a group. The group id must be non-zero. |
96 | | int contextGroupId; |
97 | | StringView humanReadableName; |
98 | | StringView origin; |
99 | | StringView auxData; |
100 | | bool hasMemoryOnConsole; |
101 | | |
102 | | static int executionContextId(v8::Local<v8::Context> context); |
103 | | |
104 | | // Disallow copying and allocating this one. |
105 | | enum NotNullTagEnum { NotNullLiteral }; |
106 | | void* operator new(size_t) = delete; |
107 | | void* operator new(size_t, NotNullTagEnum, void*) = delete; |
108 | | void* operator new(size_t, void*) = delete; |
109 | | V8ContextInfo(const V8ContextInfo&) = delete; |
110 | | V8ContextInfo& operator=(const V8ContextInfo&) = delete; |
111 | | }; |
112 | | |
113 | | // This debugger id tries to be unique by generating two random |
114 | | // numbers, which should most likely avoid collisions. |
115 | | // Debugger id has a 1:1 mapping to context group. It is used to |
116 | | // attribute stack traces to a particular debugging, when doing any |
117 | | // cross-debugger operations (e.g. async step in). |
118 | | // See also Runtime.UniqueDebuggerId in the protocol. |
119 | | class V8_EXPORT V8DebuggerId { |
120 | | public: |
121 | | V8DebuggerId() = default; |
122 | | V8DebuggerId(const V8DebuggerId&) = default; |
123 | | V8DebuggerId& operator=(const V8DebuggerId&) = default; |
124 | | |
125 | | std::unique_ptr<StringBuffer> toString() const; |
126 | | bool isValid() const; |
127 | | std::pair<int64_t, int64_t> pair() const; |
128 | | |
129 | | private: |
130 | | friend class internal::V8DebuggerId; |
131 | | explicit V8DebuggerId(std::pair<int64_t, int64_t>); |
132 | | |
133 | | int64_t m_first = 0; |
134 | | int64_t m_second = 0; |
135 | | }; |
136 | | |
137 | | struct V8_EXPORT V8StackFrame { |
138 | | StringView sourceURL; |
139 | | StringView functionName; |
140 | | int lineNumber; |
141 | | int columnNumber; |
142 | | int scriptId; |
143 | | }; |
144 | | |
145 | | class V8_EXPORT V8StackTrace { |
146 | | public: |
147 | | virtual StringView firstNonEmptySourceURL() const = 0; |
148 | | virtual bool isEmpty() const = 0; |
149 | | virtual StringView topSourceURL() const = 0; |
150 | | virtual int topLineNumber() const = 0; |
151 | | virtual int topColumnNumber() const = 0; |
152 | | virtual int topScriptId() const = 0; |
153 | | virtual StringView topFunctionName() const = 0; |
154 | | |
155 | | virtual ~V8StackTrace() = default; |
156 | | virtual std::unique_ptr<protocol::Runtime::API::StackTrace> |
157 | | buildInspectorObject(int maxAsyncDepth) const = 0; |
158 | | virtual std::unique_ptr<StringBuffer> toString() const = 0; |
159 | | |
160 | | // Safe to pass between threads, drops async chain. |
161 | | virtual std::unique_ptr<V8StackTrace> clone() = 0; |
162 | | |
163 | | virtual std::vector<V8StackFrame> frames() const = 0; |
164 | | }; |
165 | | |
166 | | class V8_EXPORT V8InspectorSession { |
167 | | public: |
168 | | virtual ~V8InspectorSession() = default; |
169 | | |
170 | | // Cross-context inspectable values (DOM nodes in different worlds, etc.). |
171 | | class V8_EXPORT Inspectable { |
172 | | public: |
173 | | virtual v8::Local<v8::Value> get(v8::Local<v8::Context>) = 0; |
174 | | virtual ~Inspectable() = default; |
175 | | }; |
176 | | virtual void addInspectedObject(std::unique_ptr<Inspectable>) = 0; |
177 | | |
178 | | // Dispatching protocol messages. |
179 | | static bool canDispatchMethod(StringView method); |
180 | | virtual void dispatchProtocolMessage(StringView message) = 0; |
181 | | virtual std::vector<uint8_t> state() = 0; |
182 | | virtual std::vector<std::unique_ptr<protocol::Schema::API::Domain>> |
183 | | supportedDomains() = 0; |
184 | | |
185 | | // Debugger actions. |
186 | | virtual void schedulePauseOnNextStatement(StringView breakReason, |
187 | | StringView breakDetails) = 0; |
188 | | virtual void cancelPauseOnNextStatement() = 0; |
189 | | virtual void breakProgram(StringView breakReason, |
190 | | StringView breakDetails) = 0; |
191 | | virtual void setSkipAllPauses(bool) = 0; |
192 | | virtual void resume(bool setTerminateOnResume = false) = 0; |
193 | | virtual void stepOver() = 0; |
194 | | virtual std::vector<std::unique_ptr<protocol::Debugger::API::SearchMatch>> |
195 | | searchInTextByLines(StringView text, StringView query, bool caseSensitive, |
196 | | bool isRegex) = 0; |
197 | | |
198 | | // Remote objects. |
199 | | virtual std::unique_ptr<protocol::Runtime::API::RemoteObject> wrapObject( |
200 | | v8::Local<v8::Context>, v8::Local<v8::Value>, StringView groupName, |
201 | | bool generatePreview) = 0; |
202 | | |
203 | | virtual bool unwrapObject(std::unique_ptr<StringBuffer>* error, |
204 | | StringView objectId, v8::Local<v8::Value>*, |
205 | | v8::Local<v8::Context>*, |
206 | | std::unique_ptr<StringBuffer>* objectGroup) = 0; |
207 | | virtual void releaseObjectGroup(StringView) = 0; |
208 | | virtual void triggerPreciseCoverageDeltaUpdate(StringView occasion) = 0; |
209 | | |
210 | | struct V8_EXPORT EvaluateResult { |
211 | | enum class ResultType { |
212 | | kNotRun, |
213 | | kSuccess, |
214 | | kException, |
215 | | }; |
216 | | |
217 | | ResultType type; |
218 | | v8::Local<v8::Value> value; |
219 | | }; |
220 | | // Evalaute 'expression' in the provided context. Does the same as |
221 | | // Runtime#evaluate under-the-hood but exposed on the C++ side. |
222 | | virtual EvaluateResult evaluate(v8::Local<v8::Context> context, |
223 | | StringView expression, |
224 | | bool includeCommandLineAPI = false) = 0; |
225 | | |
226 | | // Prepare for shutdown (disables debugger pausing, etc.). |
227 | | virtual void stop() = 0; |
228 | | }; |
229 | | |
230 | | struct V8_EXPORT DeepSerializedValue { |
231 | | explicit DeepSerializedValue(std::unique_ptr<StringBuffer> type, |
232 | | v8::MaybeLocal<v8::Value> value = {}) |
233 | 0 | : type(std::move(type)), value(value) {} |
234 | | std::unique_ptr<StringBuffer> type; |
235 | | v8::MaybeLocal<v8::Value> value; |
236 | | }; |
237 | | |
238 | | struct V8_EXPORT DeepSerializationResult { |
239 | | explicit DeepSerializationResult( |
240 | | std::unique_ptr<DeepSerializedValue> serializedValue) |
241 | 0 | : serializedValue(std::move(serializedValue)), isSuccess(true) {} |
242 | | explicit DeepSerializationResult(std::unique_ptr<StringBuffer> errorMessage) |
243 | 0 | : errorMessage(std::move(errorMessage)), isSuccess(false) {} |
244 | | |
245 | | // Use std::variant when available. |
246 | | std::unique_ptr<DeepSerializedValue> serializedValue; |
247 | | std::unique_ptr<StringBuffer> errorMessage; |
248 | | bool isSuccess; |
249 | | }; |
250 | | |
251 | | class V8_EXPORT V8InspectorClient { |
252 | | public: |
253 | 35 | virtual ~V8InspectorClient() = default; |
254 | | |
255 | 0 | virtual void runMessageLoopOnPause(int contextGroupId) {} |
256 | 0 | virtual void runMessageLoopOnInstrumentationPause(int contextGroupId) { |
257 | 0 | runMessageLoopOnPause(contextGroupId); |
258 | 0 | } |
259 | 0 | virtual void quitMessageLoopOnPause() {} |
260 | 0 | virtual void runIfWaitingForDebugger(int contextGroupId) {} |
261 | | |
262 | 0 | virtual void muteMetrics(int contextGroupId) {} |
263 | 0 | virtual void unmuteMetrics(int contextGroupId) {} |
264 | | |
265 | 0 | virtual void beginUserGesture() {} |
266 | 0 | virtual void endUserGesture() {} |
267 | | |
268 | | virtual std::unique_ptr<DeepSerializationResult> deepSerialize( |
269 | | v8::Local<v8::Value> v8Value, int maxDepth, |
270 | 0 | v8::Local<v8::Object> additionalParameters) { |
271 | 0 | return nullptr; |
272 | 0 | } |
273 | 0 | virtual std::unique_ptr<StringBuffer> valueSubtype(v8::Local<v8::Value>) { |
274 | 0 | return nullptr; |
275 | 0 | } |
276 | | virtual std::unique_ptr<StringBuffer> descriptionForValueSubtype( |
277 | 0 | v8::Local<v8::Context>, v8::Local<v8::Value>) { |
278 | 0 | return nullptr; |
279 | 0 | } |
280 | 0 | virtual bool isInspectableHeapObject(v8::Local<v8::Object>) { return true; } |
281 | | |
282 | | virtual v8::Local<v8::Context> ensureDefaultContextInGroup( |
283 | 0 | int contextGroupId) { |
284 | 0 | return v8::Local<v8::Context>(); |
285 | 0 | } |
286 | 0 | virtual void beginEnsureAllContextsInGroup(int contextGroupId) {} |
287 | 0 | virtual void endEnsureAllContextsInGroup(int contextGroupId) {} |
288 | | |
289 | | virtual void installAdditionalCommandLineAPI(v8::Local<v8::Context>, |
290 | 0 | v8::Local<v8::Object>) {} |
291 | | // Deprecated. Use version with contextId. |
292 | | virtual void consoleAPIMessage(int contextGroupId, |
293 | | v8::Isolate::MessageErrorLevel level, |
294 | | const StringView& message, |
295 | | const StringView& url, unsigned lineNumber, |
296 | 0 | unsigned columnNumber, V8StackTrace*) {} |
297 | | virtual void consoleAPIMessage(int contextGroupId, int contextId, |
298 | | v8::Isolate::MessageErrorLevel level, |
299 | | const StringView& message, |
300 | | const StringView& url, unsigned lineNumber, |
301 | | unsigned columnNumber, |
302 | 0 | V8StackTrace* stackTrace) { |
303 | 0 | consoleAPIMessage(contextGroupId, level, message, url, lineNumber, |
304 | 0 | columnNumber, stackTrace); |
305 | 0 | } |
306 | | virtual v8::MaybeLocal<v8::Value> memoryInfo(v8::Isolate*, |
307 | 0 | v8::Local<v8::Context>) { |
308 | 0 | return v8::MaybeLocal<v8::Value>(); |
309 | 0 | } |
310 | | |
311 | 0 | virtual void consoleTime(v8::Isolate* isolate, v8::Local<v8::String> label) {} |
312 | | virtual void consoleTimeEnd(v8::Isolate* isolate, |
313 | 0 | v8::Local<v8::String> label) {} |
314 | | virtual void consoleTimeStamp(v8::Isolate* isolate, |
315 | 0 | v8::Local<v8::String> label) {} |
316 | | virtual void consoleTimeStampWithArgs( |
317 | | v8::Isolate* isolate, v8::Local<v8::String> label, |
318 | 0 | const v8::LocalVector<v8::Value>& args) {} |
319 | 0 | virtual void consoleClear(int contextGroupId) {} |
320 | 0 | virtual double currentTimeMS() { return 0; } |
321 | | typedef void (*TimerCallback)(void*); |
322 | 0 | virtual void startRepeatingTimer(double, TimerCallback, void* data) {} |
323 | 0 | virtual void cancelTimer(void* data) {} |
324 | | |
325 | | // TODO(dgozman): this was added to support service worker shadow page. We |
326 | | // should not connect at all. |
327 | 0 | virtual bool canExecuteScripts(int contextGroupId) { return true; } |
328 | | |
329 | 0 | virtual void maxAsyncCallStackDepthChanged(int depth) {} |
330 | | |
331 | | virtual std::unique_ptr<StringBuffer> resourceNameToUrl( |
332 | 0 | const StringView& resourceName) { |
333 | 0 | return nullptr; |
334 | 0 | } |
335 | | |
336 | | // The caller would defer to generating a random 64 bit integer if |
337 | | // this method returns 0. |
338 | 105 | virtual int64_t generateUniqueId() { return 0; } |
339 | | |
340 | | virtual void dispatchError(v8::Local<v8::Context>, v8::Local<v8::Message>, |
341 | 0 | v8::Local<v8::Value>) {} |
342 | | }; |
343 | | |
344 | | // These stack trace ids are intended to be passed between debuggers and be |
345 | | // resolved later. This allows to track cross-debugger calls and step between |
346 | | // them if a single client connects to multiple debuggers. |
347 | | struct V8_EXPORT V8StackTraceId { |
348 | | uintptr_t id; |
349 | | std::pair<int64_t, int64_t> debugger_id; |
350 | | bool should_pause = false; |
351 | | |
352 | | V8StackTraceId(); |
353 | | V8StackTraceId(const V8StackTraceId&) = default; |
354 | | V8StackTraceId(uintptr_t id, const std::pair<int64_t, int64_t> debugger_id); |
355 | | V8StackTraceId(uintptr_t id, const std::pair<int64_t, int64_t> debugger_id, |
356 | | bool should_pause); |
357 | | explicit V8StackTraceId(StringView); |
358 | | V8StackTraceId& operator=(const V8StackTraceId&) = default; |
359 | | V8StackTraceId& operator=(V8StackTraceId&&) noexcept = default; |
360 | | ~V8StackTraceId() = default; |
361 | | |
362 | | bool IsInvalid() const; |
363 | | std::unique_ptr<StringBuffer> ToString(); |
364 | | }; |
365 | | |
366 | | class V8_EXPORT V8Inspector { |
367 | | public: |
368 | | static std::unique_ptr<V8Inspector> create(v8::Isolate*, V8InspectorClient*); |
369 | | virtual ~V8Inspector() = default; |
370 | | |
371 | | // Contexts instrumentation. |
372 | | virtual void contextCreated(const V8ContextInfo&) = 0; |
373 | | virtual void contextDestroyed(v8::Local<v8::Context>) = 0; |
374 | | virtual void resetContextGroup(int contextGroupId) = 0; |
375 | | virtual v8::MaybeLocal<v8::Context> contextById(int contextId) = 0; |
376 | | virtual V8DebuggerId uniqueDebuggerId(int contextId) = 0; |
377 | | virtual uint64_t isolateId() = 0; |
378 | | |
379 | | // Various instrumentation. |
380 | | virtual void idleStarted() = 0; |
381 | | virtual void idleFinished() = 0; |
382 | | |
383 | | // Async stack traces instrumentation. |
384 | | virtual void asyncTaskScheduled(StringView taskName, void* task, |
385 | | bool recurring) = 0; |
386 | | virtual void asyncTaskCanceled(void* task) = 0; |
387 | | virtual void asyncTaskStarted(void* task) = 0; |
388 | | virtual void asyncTaskFinished(void* task) = 0; |
389 | | virtual void allAsyncTasksCanceled() = 0; |
390 | | |
391 | | virtual V8StackTraceId storeCurrentStackTrace(StringView description) = 0; |
392 | | virtual void externalAsyncTaskStarted(const V8StackTraceId& parent) = 0; |
393 | | virtual void externalAsyncTaskFinished(const V8StackTraceId& parent) = 0; |
394 | | |
395 | | // Exceptions instrumentation. |
396 | | virtual unsigned exceptionThrown(v8::Local<v8::Context>, StringView message, |
397 | | v8::Local<v8::Value> exception, |
398 | | StringView detailedMessage, StringView url, |
399 | | unsigned lineNumber, unsigned columnNumber, |
400 | | std::unique_ptr<V8StackTrace>, |
401 | | int scriptId) = 0; |
402 | | virtual void exceptionRevoked(v8::Local<v8::Context>, unsigned exceptionId, |
403 | | StringView message) = 0; |
404 | | virtual bool associateExceptionData(v8::Local<v8::Context>, |
405 | | v8::Local<v8::Value> exception, |
406 | | v8::Local<v8::Name> key, |
407 | | v8::Local<v8::Value> value) = 0; |
408 | | |
409 | | // Connection. |
410 | | class V8_EXPORT Channel { |
411 | | public: |
412 | 0 | virtual ~Channel() = default; |
413 | | virtual void sendResponse(int callId, |
414 | | std::unique_ptr<StringBuffer> message) = 0; |
415 | | virtual void sendNotification(std::unique_ptr<StringBuffer> message) = 0; |
416 | | virtual void flushProtocolNotifications() = 0; |
417 | | }; |
418 | | enum ClientTrustLevel { kUntrusted, kFullyTrusted }; |
419 | | enum SessionPauseState { kWaitingForDebugger, kNotWaitingForDebugger }; |
420 | | // TODO(chromium:1352175): remove default value once downstream change lands. |
421 | | // Deprecated: Use `connectShared` instead. |
422 | | virtual std::unique_ptr<V8InspectorSession> connect( |
423 | | int contextGroupId, Channel*, StringView state, |
424 | | ClientTrustLevel client_trust_level, |
425 | | SessionPauseState = kNotWaitingForDebugger) = 0; |
426 | | |
427 | | // Same as `connect` but returns a std::shared_ptr instead. |
428 | | // Embedders should not deconstruct V8 sessions while the nested run loop |
429 | | // (V8InspectorClient::runMessageLoopOnPause) is running. To partially ensure |
430 | | // this, we defer session deconstruction until no "dispatchProtocolMessages" |
431 | | // remains on the stack. |
432 | | virtual std::shared_ptr<V8InspectorSession> connectShared( |
433 | | int contextGroupId, Channel* channel, StringView state, |
434 | | ClientTrustLevel clientTrustLevel, SessionPauseState pauseState) = 0; |
435 | | |
436 | | // API methods. |
437 | | virtual std::unique_ptr<V8StackTrace> createStackTrace( |
438 | | v8::Local<v8::StackTrace>) = 0; |
439 | | virtual std::unique_ptr<V8StackTrace> captureStackTrace(bool fullStack) = 0; |
440 | | }; |
441 | | |
442 | | } // namespace v8_inspector |
443 | | |
444 | | #endif // V8_V8_INSPECTOR_H_ |