Coverage Report

Created: 2025-07-04 09:33

/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_