/src/node/deps/v8/include/v8-inspector.h
Line | Count | Source (jump to first uncovered line) |
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 | 271k | 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 | 407k | : 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 | 135k | : context(context), |
90 | 135k | contextGroupId(contextGroupId), |
91 | 135k | humanReadableName(humanReadableName), |
92 | 135k | 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 | | }; |
143 | | |
144 | | class V8_EXPORT V8StackTrace { |
145 | | public: |
146 | | virtual StringView firstNonEmptySourceURL() const = 0; |
147 | | virtual bool isEmpty() const = 0; |
148 | | virtual StringView topSourceURL() const = 0; |
149 | | virtual int topLineNumber() const = 0; |
150 | | virtual int topColumnNumber() const = 0; |
151 | | virtual int topScriptId() const = 0; |
152 | | virtual StringView topFunctionName() const = 0; |
153 | | |
154 | | virtual ~V8StackTrace() = default; |
155 | | virtual std::unique_ptr<protocol::Runtime::API::StackTrace> |
156 | | buildInspectorObject(int maxAsyncDepth) const = 0; |
157 | | virtual std::unique_ptr<StringBuffer> toString() const = 0; |
158 | | |
159 | | // Safe to pass between threads, drops async chain. |
160 | | virtual std::unique_ptr<V8StackTrace> clone() = 0; |
161 | | |
162 | | virtual std::vector<V8StackFrame> frames() const = 0; |
163 | | }; |
164 | | |
165 | | class V8_EXPORT V8InspectorSession { |
166 | | public: |
167 | | virtual ~V8InspectorSession() = default; |
168 | | |
169 | | // Cross-context inspectable values (DOM nodes in different worlds, etc.). |
170 | | class V8_EXPORT Inspectable { |
171 | | public: |
172 | | virtual v8::Local<v8::Value> get(v8::Local<v8::Context>) = 0; |
173 | | virtual ~Inspectable() = default; |
174 | | }; |
175 | | virtual void addInspectedObject(std::unique_ptr<Inspectable>) = 0; |
176 | | |
177 | | // Dispatching protocol messages. |
178 | | static bool canDispatchMethod(StringView method); |
179 | | virtual void dispatchProtocolMessage(StringView message) = 0; |
180 | | virtual std::vector<uint8_t> state() = 0; |
181 | | virtual std::vector<std::unique_ptr<protocol::Schema::API::Domain>> |
182 | | supportedDomains() = 0; |
183 | | |
184 | | // Debugger actions. |
185 | | virtual void schedulePauseOnNextStatement(StringView breakReason, |
186 | | StringView breakDetails) = 0; |
187 | | virtual void cancelPauseOnNextStatement() = 0; |
188 | | virtual void breakProgram(StringView breakReason, |
189 | | StringView breakDetails) = 0; |
190 | | virtual void setSkipAllPauses(bool) = 0; |
191 | | virtual void resume(bool setTerminateOnResume = false) = 0; |
192 | | virtual void stepOver() = 0; |
193 | | virtual std::vector<std::unique_ptr<protocol::Debugger::API::SearchMatch>> |
194 | | searchInTextByLines(StringView text, StringView query, bool caseSensitive, |
195 | | bool isRegex) = 0; |
196 | | |
197 | | // Remote objects. |
198 | | virtual std::unique_ptr<protocol::Runtime::API::RemoteObject> wrapObject( |
199 | | v8::Local<v8::Context>, v8::Local<v8::Value>, StringView groupName, |
200 | | bool generatePreview) = 0; |
201 | | |
202 | | virtual bool unwrapObject(std::unique_ptr<StringBuffer>* error, |
203 | | StringView objectId, v8::Local<v8::Value>*, |
204 | | v8::Local<v8::Context>*, |
205 | | std::unique_ptr<StringBuffer>* objectGroup) = 0; |
206 | | virtual void releaseObjectGroup(StringView) = 0; |
207 | | virtual void triggerPreciseCoverageDeltaUpdate(StringView occasion) = 0; |
208 | | |
209 | | struct V8_EXPORT EvaluateResult { |
210 | | enum class ResultType { |
211 | | kNotRun, |
212 | | kSuccess, |
213 | | kException, |
214 | | }; |
215 | | |
216 | | ResultType type; |
217 | | v8::Local<v8::Value> value; |
218 | | }; |
219 | | // Evalaute 'expression' in the provided context. Does the same as |
220 | | // Runtime#evaluate under-the-hood but exposed on the C++ side. |
221 | | virtual EvaluateResult evaluate(v8::Local<v8::Context> context, |
222 | | StringView expression, |
223 | | bool includeCommandLineAPI = false) = 0; |
224 | | |
225 | | // Prepare for shutdown (disables debugger pausing, etc.). |
226 | | virtual void stop() = 0; |
227 | | }; |
228 | | |
229 | | struct V8_EXPORT DeepSerializedValue { |
230 | | explicit DeepSerializedValue(std::unique_ptr<StringBuffer> type, |
231 | | v8::MaybeLocal<v8::Value> value = {}) |
232 | 0 | : type(std::move(type)), value(value) {} |
233 | | std::unique_ptr<StringBuffer> type; |
234 | | v8::MaybeLocal<v8::Value> value; |
235 | | }; |
236 | | |
237 | | struct V8_EXPORT DeepSerializationResult { |
238 | | explicit DeepSerializationResult( |
239 | | std::unique_ptr<DeepSerializedValue> serializedValue) |
240 | 0 | : serializedValue(std::move(serializedValue)), isSuccess(true) {} |
241 | | explicit DeepSerializationResult(std::unique_ptr<StringBuffer> errorMessage) |
242 | 0 | : errorMessage(std::move(errorMessage)), isSuccess(false) {} |
243 | | |
244 | | // Use std::variant when available. |
245 | | std::unique_ptr<DeepSerializedValue> serializedValue; |
246 | | std::unique_ptr<StringBuffer> errorMessage; |
247 | | bool isSuccess; |
248 | | }; |
249 | | |
250 | | class V8_EXPORT V8InspectorClient { |
251 | | public: |
252 | 134k | virtual ~V8InspectorClient() = default; |
253 | | |
254 | 0 | virtual void runMessageLoopOnPause(int contextGroupId) {} |
255 | 0 | virtual void runMessageLoopOnInstrumentationPause(int contextGroupId) { |
256 | 0 | runMessageLoopOnPause(contextGroupId); |
257 | 0 | } |
258 | 0 | virtual void quitMessageLoopOnPause() {} |
259 | 0 | virtual void runIfWaitingForDebugger(int contextGroupId) {} |
260 | | |
261 | 0 | virtual void muteMetrics(int contextGroupId) {} |
262 | 0 | virtual void unmuteMetrics(int contextGroupId) {} |
263 | | |
264 | 0 | virtual void beginUserGesture() {} |
265 | 0 | virtual void endUserGesture() {} |
266 | | |
267 | | virtual std::unique_ptr<DeepSerializationResult> deepSerialize( |
268 | | v8::Local<v8::Value> v8Value, int maxDepth, |
269 | 0 | v8::Local<v8::Object> additionalParameters) { |
270 | 0 | return nullptr; |
271 | 0 | } |
272 | 0 | virtual std::unique_ptr<StringBuffer> valueSubtype(v8::Local<v8::Value>) { |
273 | 0 | return nullptr; |
274 | 0 | } |
275 | | virtual std::unique_ptr<StringBuffer> descriptionForValueSubtype( |
276 | 0 | v8::Local<v8::Context>, v8::Local<v8::Value>) { |
277 | 0 | return nullptr; |
278 | 0 | } |
279 | 0 | virtual bool isInspectableHeapObject(v8::Local<v8::Object>) { return true; } |
280 | | |
281 | | virtual v8::Local<v8::Context> ensureDefaultContextInGroup( |
282 | 0 | int contextGroupId) { |
283 | 0 | return v8::Local<v8::Context>(); |
284 | 0 | } |
285 | 0 | virtual void beginEnsureAllContextsInGroup(int contextGroupId) {} |
286 | 0 | virtual void endEnsureAllContextsInGroup(int contextGroupId) {} |
287 | | |
288 | | virtual void installAdditionalCommandLineAPI(v8::Local<v8::Context>, |
289 | 0 | v8::Local<v8::Object>) {} |
290 | | virtual void consoleAPIMessage(int contextGroupId, |
291 | | v8::Isolate::MessageErrorLevel level, |
292 | | const StringView& message, |
293 | | const StringView& url, unsigned lineNumber, |
294 | 0 | unsigned columnNumber, V8StackTrace*) {} |
295 | | virtual v8::MaybeLocal<v8::Value> memoryInfo(v8::Isolate*, |
296 | 0 | v8::Local<v8::Context>) { |
297 | 0 | return v8::MaybeLocal<v8::Value>(); |
298 | 0 | } |
299 | | |
300 | 0 | virtual void consoleTime(const StringView& title) {} |
301 | 0 | virtual void consoleTimeEnd(const StringView& title) {} |
302 | 0 | virtual void consoleTimeStamp(const StringView& title) {} |
303 | 0 | virtual void consoleClear(int contextGroupId) {} |
304 | 0 | virtual double currentTimeMS() { return 0; } |
305 | | typedef void (*TimerCallback)(void*); |
306 | 0 | virtual void startRepeatingTimer(double, TimerCallback, void* data) {} |
307 | 0 | virtual void cancelTimer(void* data) {} |
308 | | |
309 | | // TODO(dgozman): this was added to support service worker shadow page. We |
310 | | // should not connect at all. |
311 | 0 | virtual bool canExecuteScripts(int contextGroupId) { return true; } |
312 | | |
313 | 0 | virtual void maxAsyncCallStackDepthChanged(int depth) {} |
314 | | |
315 | | virtual std::unique_ptr<StringBuffer> resourceNameToUrl( |
316 | 0 | const StringView& resourceName) { |
317 | 0 | return nullptr; |
318 | 0 | } |
319 | | |
320 | | // The caller would defer to generating a random 64 bit integer if |
321 | | // this method returns 0. |
322 | 406k | virtual int64_t generateUniqueId() { return 0; } |
323 | | |
324 | | virtual void dispatchError(v8::Local<v8::Context>, v8::Local<v8::Message>, |
325 | 0 | v8::Local<v8::Value>) {} |
326 | | }; |
327 | | |
328 | | // These stack trace ids are intended to be passed between debuggers and be |
329 | | // resolved later. This allows to track cross-debugger calls and step between |
330 | | // them if a single client connects to multiple debuggers. |
331 | | struct V8_EXPORT V8StackTraceId { |
332 | | uintptr_t id; |
333 | | std::pair<int64_t, int64_t> debugger_id; |
334 | | bool should_pause = false; |
335 | | |
336 | | V8StackTraceId(); |
337 | | V8StackTraceId(const V8StackTraceId&) = default; |
338 | | V8StackTraceId(uintptr_t id, const std::pair<int64_t, int64_t> debugger_id); |
339 | | V8StackTraceId(uintptr_t id, const std::pair<int64_t, int64_t> debugger_id, |
340 | | bool should_pause); |
341 | | explicit V8StackTraceId(StringView); |
342 | | V8StackTraceId& operator=(const V8StackTraceId&) = default; |
343 | | V8StackTraceId& operator=(V8StackTraceId&&) noexcept = default; |
344 | | ~V8StackTraceId() = default; |
345 | | |
346 | | bool IsInvalid() const; |
347 | | std::unique_ptr<StringBuffer> ToString(); |
348 | | }; |
349 | | |
350 | | class V8_EXPORT V8Inspector { |
351 | | public: |
352 | | static std::unique_ptr<V8Inspector> create(v8::Isolate*, V8InspectorClient*); |
353 | | virtual ~V8Inspector() = default; |
354 | | |
355 | | // Contexts instrumentation. |
356 | | virtual void contextCreated(const V8ContextInfo&) = 0; |
357 | | virtual void contextDestroyed(v8::Local<v8::Context>) = 0; |
358 | | virtual void resetContextGroup(int contextGroupId) = 0; |
359 | | virtual v8::MaybeLocal<v8::Context> contextById(int contextId) = 0; |
360 | | virtual V8DebuggerId uniqueDebuggerId(int contextId) = 0; |
361 | | |
362 | | // Various instrumentation. |
363 | | virtual void idleStarted() = 0; |
364 | | virtual void idleFinished() = 0; |
365 | | |
366 | | // Async stack traces instrumentation. |
367 | | virtual void asyncTaskScheduled(StringView taskName, void* task, |
368 | | bool recurring) = 0; |
369 | | virtual void asyncTaskCanceled(void* task) = 0; |
370 | | virtual void asyncTaskStarted(void* task) = 0; |
371 | | virtual void asyncTaskFinished(void* task) = 0; |
372 | | virtual void allAsyncTasksCanceled() = 0; |
373 | | |
374 | | virtual V8StackTraceId storeCurrentStackTrace(StringView description) = 0; |
375 | | virtual void externalAsyncTaskStarted(const V8StackTraceId& parent) = 0; |
376 | | virtual void externalAsyncTaskFinished(const V8StackTraceId& parent) = 0; |
377 | | |
378 | | // Exceptions instrumentation. |
379 | | virtual unsigned exceptionThrown(v8::Local<v8::Context>, StringView message, |
380 | | v8::Local<v8::Value> exception, |
381 | | StringView detailedMessage, StringView url, |
382 | | unsigned lineNumber, unsigned columnNumber, |
383 | | std::unique_ptr<V8StackTrace>, |
384 | | int scriptId) = 0; |
385 | | virtual void exceptionRevoked(v8::Local<v8::Context>, unsigned exceptionId, |
386 | | StringView message) = 0; |
387 | | virtual bool associateExceptionData(v8::Local<v8::Context>, |
388 | | v8::Local<v8::Value> exception, |
389 | | v8::Local<v8::Name> key, |
390 | | v8::Local<v8::Value> value) = 0; |
391 | | |
392 | | // Connection. |
393 | | class V8_EXPORT Channel { |
394 | | public: |
395 | 0 | virtual ~Channel() = default; |
396 | | virtual void sendResponse(int callId, |
397 | | std::unique_ptr<StringBuffer> message) = 0; |
398 | | virtual void sendNotification(std::unique_ptr<StringBuffer> message) = 0; |
399 | | virtual void flushProtocolNotifications() = 0; |
400 | | }; |
401 | | enum ClientTrustLevel { kUntrusted, kFullyTrusted }; |
402 | | enum SessionPauseState { kWaitingForDebugger, kNotWaitingForDebugger }; |
403 | | // TODO(chromium:1352175): remove default value once downstream change lands. |
404 | | virtual std::unique_ptr<V8InspectorSession> connect( |
405 | | int contextGroupId, Channel*, StringView state, |
406 | | ClientTrustLevel client_trust_level, |
407 | 0 | SessionPauseState = kNotWaitingForDebugger) { |
408 | 0 | return nullptr; |
409 | 0 | } |
410 | | |
411 | | // API methods. |
412 | | virtual std::unique_ptr<V8StackTrace> createStackTrace( |
413 | | v8::Local<v8::StackTrace>) = 0; |
414 | | virtual std::unique_ptr<V8StackTrace> captureStackTrace(bool fullStack) = 0; |
415 | | }; |
416 | | |
417 | | } // namespace v8_inspector |
418 | | |
419 | | #endif // V8_V8_INSPECTOR_H_ |