debug-interface.h 15.9 KB
Newer Older
1 2 3 4 5 6 7
// Copyright 2016 the V8 project authors. All rights reserved.
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.

#ifndef V8_DEBUG_DEBUG_INTERFACE_H_
#define V8_DEBUG_DEBUG_INTERFACE_H_

8
#include "include/v8-inspector.h"
9
#include "include/v8-util.h"
10 11
#include "include/v8.h"

12
#include "src/debug/interface-types.h"
13
#include "src/globals.h"
14

15
namespace v8 {
16 17

namespace internal {
18
struct CoverageBlock;
19 20
struct CoverageFunction;
struct CoverageScript;
21 22
struct TypeProfileEntry;
struct TypeProfileScript;
23
class Coverage;
24
class PostponeInterruptsScope;
25
class Script;
26 27
class TypeProfile;
}  // namespace internal
28

29
namespace debug {
30

31 32 33
void SetContextId(Local<Context> context, int id);
int GetContextId(Local<Context> context);

34 35 36
void SetInspector(Isolate* isolate, v8_inspector::V8Inspector*);
v8_inspector::V8Inspector* GetInspector(Isolate* isolate);

37 38 39
// Schedule a debugger break to happen when function is called inside given
// isolate.
void SetBreakOnNextFunctionCall(Isolate* isolate);
40 41 42

// Remove scheduled debugger break in given isolate if it has not
// happened yet.
43
void ClearBreakOnNextFunctionCall(Isolate* isolate);
44 45 46 47 48 49 50 51 52 53 54 55 56

/**
 * Returns array of internal properties specific to the value type. Result has
 * the following format: [<name>, <value>,...,<name>, <value>]. Result array
 * will be allocated in the current context.
 */
MaybeLocal<Array> GetInternalProperties(Isolate* isolate, Local<Value> value);

enum ExceptionBreakState {
  NoBreakOnException = 0,
  BreakOnUncaughtException = 1,
  BreakOnAnyException = 2
};
57

58 59 60 61 62 63 64 65
/**
 * Defines if VM will pause on exceptions or not.
 * If BreakOnAnyExceptions is set then VM will pause on caught and uncaught
 * exception, if BreakOnUncaughtException is set then VM will pause only on
 * uncaught exception, otherwise VM won't stop on any exception.
 */
void ChangeBreakOnException(Isolate* isolate, ExceptionBreakState state);

66
void RemoveBreakpoint(Isolate* isolate, BreakpointId id);
67 68
void SetBreakPointsActive(Isolate* isolate, bool is_active);

69 70 71
enum StepAction {
  StepOut = 0,   // Step out of the current function.
  StepNext = 1,  // Step to the next statement in the current function.
72
  StepIn = 2     // Step into new functions invoked or the next statement
73 74
                 // in the current function.
};
75

76
void PrepareStep(Isolate* isolate, StepAction action);
77
void ClearStepping(Isolate* isolate);
78
void BreakRightNow(Isolate* isolate);
79

80
bool AllFramesOnStackAreBlackboxed(Isolate* isolate);
81

82 83
class Script;

84 85 86 87 88 89 90 91 92 93 94 95 96
struct LiveEditResult {
  enum Status {
    OK,
    COMPILE_ERROR,
    BLOCKED_BY_RUNNING_GENERATOR,
    BLOCKED_BY_FUNCTION_ABOVE_BREAK_FRAME,
    BLOCKED_BY_FUNCTION_BELOW_NON_DROPPABLE_FRAME,
    BLOCKED_BY_ACTIVE_FUNCTION,
    BLOCKED_BY_NEW_TARGET_IN_RESTART_FRAME,
    FRAME_RESTART_IS_NOT_SUPPORTED
  };
  Status status = OK;
  bool stack_changed = false;
97 98
  // Available only for OK.
  v8::Local<v8::debug::Script> script;
99 100 101 102 103 104
  // Fields below are available only for COMPILE_ERROR.
  v8::Local<v8::String> message;
  int line_number = -1;
  int column_number = -1;
};

105 106 107
/**
 * Native wrapper around v8::internal::Script object.
 */
108
class V8_EXPORT_PRIVATE Script {
109 110 111 112 113
 public:
  v8::Isolate* GetIsolate() const;

  ScriptOriginOptions OriginOptions() const;
  bool WasCompiled() const;
114
  bool IsEmbedded() const;
115 116 117 118 119 120 121
  int Id() const;
  int LineOffset() const;
  int ColumnOffset() const;
  std::vector<int> LineEnds() const;
  MaybeLocal<String> Name() const;
  MaybeLocal<String> SourceURL() const;
  MaybeLocal<String> SourceMappingURL() const;
122
  Maybe<int> ContextId() const;
123 124
  MaybeLocal<String> Source() const;
  bool IsWasm() const;
125
  bool IsModule() const;
126 127 128 129
  bool GetPossibleBreakpoints(
      const debug::Location& start, const debug::Location& end,
      bool restrict_to_function,
      std::vector<debug::BreakLocation>* locations) const;
130 131
  int GetSourceOffset(const debug::Location& location) const;
  v8::debug::Location GetSourceLocation(int offset) const;
132
  bool SetScriptSource(v8::Local<v8::String> newSource, bool preview,
133
                       LiveEditResult* result) const;
134 135
  bool SetBreakpoint(v8::Local<v8::String> condition, debug::Location* location,
                     BreakpointId* id) const;
136
};
137

138 139 140 141
// Specialization for wasm Scripts.
class WasmScript : public Script {
 public:
  static WasmScript* Cast(Script* script);
142

143 144 145
  int NumFunctions() const;
  int NumImportedFunctions() const;

146 147
  std::pair<int, int> GetFunctionRange(int function_index) const;

148
  debug::WasmDisassembly DisassembleFunction(int function_index) const;
149
  uint32_t GetFunctionHash(int function_index);
150 151 152
};

void GetLoadedScripts(Isolate* isolate, PersistentValueVector<Script>& scripts);
153

154 155
MaybeLocal<UnboundScript> CompileInspectorScript(Isolate* isolate,
                                                 Local<String> source);
156

157 158
enum ExceptionType { kException, kPromiseRejection };

159
class DebugDelegate {
160
 public:
161
  virtual ~DebugDelegate() = default;
162
  virtual void ScriptCompiled(v8::Local<Script> script, bool is_live_edited,
163
                              bool has_compile_error) {}
164 165 166
  // |inspector_break_points_hit| contains id of breakpoints installed with
  // debug::Script::SetBreakpoint API.
  virtual void BreakProgramRequested(
167
      v8::Local<v8::Context> paused_context,
168
      const std::vector<debug::BreakpointId>& inspector_break_points_hit) {}
169 170
  virtual void ExceptionThrown(v8::Local<v8::Context> paused_context,
                               v8::Local<v8::Value> exception,
171 172
                               v8::Local<v8::Value> promise, bool is_uncaught,
                               ExceptionType exception_type) {}
173 174 175 176 177
  virtual bool IsFunctionBlackboxed(v8::Local<debug::Script> script,
                                    const debug::Location& start,
                                    const debug::Location& end) {
    return false;
  }
178 179
};

180 181
void SetDebugDelegate(Isolate* isolate, DebugDelegate* listener);

182 183
class AsyncEventDelegate {
 public:
184
  virtual ~AsyncEventDelegate() = default;
185 186 187 188 189 190
  virtual void AsyncEventOccurred(debug::DebugAsyncActionType type, int id,
                                  bool is_blackboxed) = 0;
};

void SetAsyncEventDelegate(Isolate* isolate, AsyncEventDelegate* delegate);

191 192
void ResetBlackboxedStateCache(Isolate* isolate,
                               v8::Local<debug::Script> script);
193

194 195
int EstimatedValueSize(Isolate* isolate, v8::Local<v8::Value> value);

196 197 198 199 200 201 202 203 204 205
enum Builtin {
  kObjectKeys,
  kObjectGetPrototypeOf,
  kObjectGetOwnPropertyDescriptor,
  kObjectGetOwnPropertyNames,
  kObjectGetOwnPropertySymbols,
};

Local<Function> GetBuiltin(Isolate* isolate, Builtin builtin);

206 207
V8_EXPORT_PRIVATE void SetConsoleDelegate(Isolate* isolate,
                                          ConsoleDelegate* delegate);
208

209 210
int GetStackFrameId(v8::Local<v8::StackFrame> frame);

211 212 213
v8::Local<v8::StackTrace> GetDetailedStackTrace(Isolate* isolate,
                                                v8::Local<v8::Object> error);

214 215 216 217 218 219 220 221 222 223 224 225 226
/**
 * Native wrapper around v8::internal::JSGeneratorObject object.
 */
class GeneratorObject {
 public:
  v8::MaybeLocal<debug::Script> Script();
  v8::Local<v8::Function> Function();
  debug::Location SuspendedLocation();
  bool IsSuspended();

  static v8::Local<debug::GeneratorObject> Cast(v8::Local<v8::Value> value);
};

227 228 229 230 231
/*
 * Provide API layer between inspector and code coverage.
 */
class V8_EXPORT_PRIVATE Coverage {
 public:
232 233
  MOVE_ONLY_NO_DEFAULT_CONSTRUCTOR(Coverage);

234 235
  enum Mode {
    // Make use of existing information in feedback vectors on the heap.
236 237
    // Only return a yes/no result. Optimization and GC are not affected.
    // Collecting best effort coverage does not reset counters.
238 239
    kBestEffort,
    // Disable optimization and prevent feedback vectors from being garbage
240 241
    // collected in order to preserve precise invocation counts. Collecting
    // precise count coverage resets counters to get incremental updates.
242
    kPreciseCount,
243 244 245
    // We are only interested in a yes/no result for the function. Optimization
    // and GC can be allowed once a function has been invoked. Collecting
    // precise binary coverage resets counters for incremental updates.
246 247 248 249
    kPreciseBinary,
    // Similar to the precise coverage modes but provides coverage at a
    // lower granularity. Design doc: goo.gl/lA2swZ.
    kBlockCount,
250
    kBlockBinary,
251 252
  };

253 254 255 256 257 258
  // Forward declarations.
  class ScriptData;
  class FunctionData;

  class V8_EXPORT_PRIVATE BlockData {
   public:
259 260
    MOVE_ONLY_NO_DEFAULT_CONSTRUCTOR(BlockData);

261 262 263 264 265
    int StartOffset() const;
    int EndOffset() const;
    uint32_t Count() const;

   private:
266 267 268 269
    explicit BlockData(i::CoverageBlock* block,
                       std::shared_ptr<i::Coverage> coverage)
        : block_(block), coverage_(std::move(coverage)) {}

270
    i::CoverageBlock* block_;
271
    std::shared_ptr<i::Coverage> coverage_;
272 273 274

    friend class v8::debug::Coverage::FunctionData;
  };
275 276

  class V8_EXPORT_PRIVATE FunctionData {
277
   public:
278 279
    MOVE_ONLY_NO_DEFAULT_CONSTRUCTOR(FunctionData);

280 281 282 283
    int StartOffset() const;
    int EndOffset() const;
    uint32_t Count() const;
    MaybeLocal<String> Name() const;
284
    size_t BlockCount() const;
285
    bool HasBlockCoverage() const;
286
    BlockData GetBlockData(size_t i) const;
287 288

   private:
289 290 291 292
    explicit FunctionData(i::CoverageFunction* function,
                          std::shared_ptr<i::Coverage> coverage)
        : function_(function), coverage_(std::move(coverage)) {}

293
    i::CoverageFunction* function_;
294
    std::shared_ptr<i::Coverage> coverage_;
295

296 297 298 299 300
    friend class v8::debug::Coverage::ScriptData;
  };

  class V8_EXPORT_PRIVATE ScriptData {
   public:
301 302
    MOVE_ONLY_NO_DEFAULT_CONSTRUCTOR(ScriptData);

303 304 305
    Local<debug::Script> GetScript() const;
    size_t FunctionCount() const;
    FunctionData GetFunctionData(size_t i) const;
306 307

   private:
308 309
    explicit ScriptData(size_t index, std::shared_ptr<i::Coverage> c);

310
    i::CoverageScript* script_;
311
    std::shared_ptr<i::Coverage> coverage_;
312 313

    friend class v8::debug::Coverage;
314 315
  };

316 317
  static Coverage CollectPrecise(Isolate* isolate);
  static Coverage CollectBestEffort(Isolate* isolate);
318

319
  static void SelectMode(Isolate* isolate, Mode mode);
320

321 322 323
  size_t ScriptCount() const;
  ScriptData GetScriptData(size_t i) const;
  bool IsEmpty() const { return coverage_ == nullptr; }
324 325

 private:
326 327
  explicit Coverage(std::shared_ptr<i::Coverage> coverage)
      : coverage_(std::move(coverage)) {}
328
  std::shared_ptr<i::Coverage> coverage_;
329
};
330

331 332 333 334 335 336 337 338 339 340 341 342 343 344 345 346 347 348 349 350 351
/*
 * Provide API layer between inspector and type profile.
 */
class V8_EXPORT_PRIVATE TypeProfile {
 public:
  MOVE_ONLY_NO_DEFAULT_CONSTRUCTOR(TypeProfile);

  enum Mode {
    kNone,
    kCollect,
  };
  class ScriptData;  // Forward declaration.

  class V8_EXPORT_PRIVATE Entry {
   public:
    MOVE_ONLY_NO_DEFAULT_CONSTRUCTOR(Entry);

    int SourcePosition() const;
    std::vector<MaybeLocal<String>> Types() const;

   private:
352 353 354 355
    explicit Entry(const i::TypeProfileEntry* entry,
                   std::shared_ptr<i::TypeProfile> type_profile)
        : entry_(entry), type_profile_(std::move(type_profile)) {}

356
    const i::TypeProfileEntry* entry_;
357
    std::shared_ptr<i::TypeProfile> type_profile_;
358 359 360 361 362 363 364 365 366 367 368 369

    friend class v8::debug::TypeProfile::ScriptData;
  };

  class V8_EXPORT_PRIVATE ScriptData {
   public:
    MOVE_ONLY_NO_DEFAULT_CONSTRUCTOR(ScriptData);

    Local<debug::Script> GetScript() const;
    std::vector<Entry> Entries() const;

   private:
370 371 372
    explicit ScriptData(size_t index,
                        std::shared_ptr<i::TypeProfile> type_profile);

373
    i::TypeProfileScript* script_;
374
    std::shared_ptr<i::TypeProfile> type_profile_;
375 376 377 378 379 380 381 382 383 384 385 386

    friend class v8::debug::TypeProfile;
  };

  static TypeProfile Collect(Isolate* isolate);

  static void SelectMode(Isolate* isolate, Mode mode);

  size_t ScriptCount() const;
  ScriptData GetScriptData(size_t i) const;

 private:
387 388 389 390
  explicit TypeProfile(std::shared_ptr<i::TypeProfile> type_profile)
      : type_profile_(std::move(type_profile)) {}

  std::shared_ptr<i::TypeProfile> type_profile_;
391 392
};

393 394 395 396 397 398 399 400 401 402 403 404 405 406 407 408 409 410 411 412 413 414 415 416 417 418
class ScopeIterator {
 public:
  static std::unique_ptr<ScopeIterator> CreateForFunction(
      v8::Isolate* isolate, v8::Local<v8::Function> func);
  static std::unique_ptr<ScopeIterator> CreateForGeneratorObject(
      v8::Isolate* isolate, v8::Local<v8::Object> generator);

  ScopeIterator() = default;
  virtual ~ScopeIterator() = default;

  enum ScopeType {
    ScopeTypeGlobal = 0,
    ScopeTypeLocal,
    ScopeTypeWith,
    ScopeTypeClosure,
    ScopeTypeCatch,
    ScopeTypeBlock,
    ScopeTypeScript,
    ScopeTypeEval,
    ScopeTypeModule
  };

  virtual bool Done() = 0;
  virtual void Advance() = 0;
  virtual ScopeType GetType() = 0;
  virtual v8::Local<v8::Object> GetObject() = 0;
419 420 421
  virtual v8::Local<v8::Value> GetFunctionDebugName() = 0;
  virtual int GetScriptId() = 0;
  virtual bool HasLocationInfo() = 0;
422 423 424 425 426 427 428 429 430 431 432 433 434 435 436 437 438 439 440 441 442
  virtual debug::Location GetStartLocation() = 0;
  virtual debug::Location GetEndLocation() = 0;

  virtual bool SetVariableValue(v8::Local<v8::String> name,
                                v8::Local<v8::Value> value) = 0;

 private:
  DISALLOW_COPY_AND_ASSIGN(ScopeIterator);
};

class StackTraceIterator {
 public:
  static std::unique_ptr<StackTraceIterator> Create(Isolate* isolate,
                                                    int index = 0);
  StackTraceIterator() = default;
  virtual ~StackTraceIterator() = default;

  virtual bool Done() const = 0;
  virtual void Advance() = 0;

  virtual int GetContextId() const = 0;
443
  virtual v8::MaybeLocal<v8::Value> GetReceiver() const = 0;
444
  virtual v8::Local<v8::Value> GetReturnValue() const = 0;
445
  virtual v8::Local<v8::String> GetFunctionDebugName() const = 0;
446 447 448 449 450 451 452 453 454 455 456 457 458
  virtual v8::Local<v8::debug::Script> GetScript() const = 0;
  virtual debug::Location GetSourceLocation() const = 0;
  virtual v8::Local<v8::Function> GetFunction() const = 0;
  virtual std::unique_ptr<ScopeIterator> GetScopeIterator() const = 0;

  virtual bool Restart() = 0;
  virtual v8::MaybeLocal<v8::Value> Evaluate(v8::Local<v8::String> source,
                                             bool throw_on_side_effect) = 0;

 private:
  DISALLOW_COPY_AND_ASSIGN(StackTraceIterator);
};

459 460 461 462 463 464 465 466 467 468
class QueryObjectPredicate {
 public:
  virtual ~QueryObjectPredicate() = default;
  virtual bool Filter(v8::Local<v8::Object> object) = 0;
};

void QueryObjects(v8::Local<v8::Context> context,
                  QueryObjectPredicate* predicate,
                  v8::PersistentValueVector<v8::Object>* objects);

469 470 471
void GlobalLexicalScopeNames(v8::Local<v8::Context> context,
                             v8::PersistentValueVector<v8::String>* names);

472 473
void SetReturnValue(v8::Isolate* isolate, v8::Local<v8::Value> value);

474 475 476 477 478 479 480 481 482 483 484
enum class NativeAccessorType {
  None = 0,
  HasGetter = 1 << 0,
  HasSetter = 1 << 1,
  IsBuiltin = 1 << 2
};

int GetNativeAccessorDescriptor(v8::Local<v8::Context> context,
                                v8::Local<v8::Object> object,
                                v8::Local<v8::Name> name);

485 486
int64_t GetNextRandomInt64(v8::Isolate* isolate);

487
v8::MaybeLocal<v8::Value> EvaluateGlobal(v8::Isolate* isolate,
488 489
                                         v8::Local<v8::String> source,
                                         bool throw_on_side_effect);
490

491 492 493 494 495
int GetDebuggingId(v8::Local<v8::Function> function);

bool SetFunctionBreakpoint(v8::Local<v8::Function> function,
                           v8::Local<v8::String> condition, BreakpointId* id);

496 497
v8::Platform* GetCurrentPlatform();

498 499 500 501 502 503 504 505 506
class PostponeInterruptsScope {
 public:
  explicit PostponeInterruptsScope(v8::Isolate* isolate);
  ~PostponeInterruptsScope();

 private:
  std::unique_ptr<i::PostponeInterruptsScope> scope_;
};

507 508 509 510 511 512 513 514 515 516 517 518 519 520
class WeakMap : public v8::Object {
 public:
  V8_WARN_UNUSED_RESULT v8::MaybeLocal<v8::Value> Get(
      v8::Local<v8::Context> context, v8::Local<v8::Value> key);
  V8_WARN_UNUSED_RESULT v8::MaybeLocal<WeakMap> Set(
      v8::Local<v8::Context> context, v8::Local<v8::Value> key,
      v8::Local<v8::Value> value);

  static Local<WeakMap> New(v8::Isolate* isolate);
  V8_INLINE static WeakMap* Cast(Value* obj);

 private:
  WeakMap();
};
521
}  // namespace debug
522 523 524
}  // namespace v8

#endif  // V8_DEBUG_DEBUG_INTERFACE_H_