Home | History | Annotate | Download | only in debug
      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_DEBUG_DEBUG_INTERFACE_H_
      6 #define V8_DEBUG_DEBUG_INTERFACE_H_
      7 
      8 #include "include/v8-inspector.h"
      9 #include "include/v8-util.h"
     10 #include "include/v8.h"
     11 
     12 #include "src/debug/interface-types.h"
     13 #include "src/globals.h"
     14 
     15 namespace v8 {
     16 
     17 namespace internal {
     18 struct CoverageBlock;
     19 struct CoverageFunction;
     20 struct CoverageScript;
     21 struct TypeProfileEntry;
     22 struct TypeProfileScript;
     23 class Coverage;
     24 class PostponeInterruptsScope;
     25 class Script;
     26 class TypeProfile;
     27 }  // namespace internal
     28 
     29 namespace debug {
     30 
     31 void SetContextId(Local<Context> context, int id);
     32 int GetContextId(Local<Context> context);
     33 
     34 void SetInspector(Isolate* isolate, v8_inspector::V8Inspector*);
     35 v8_inspector::V8Inspector* GetInspector(Isolate* isolate);
     36 
     37 // Schedule a debugger break to happen when function is called inside given
     38 // isolate.
     39 void SetBreakOnNextFunctionCall(Isolate* isolate);
     40 
     41 // Remove scheduled debugger break in given isolate if it has not
     42 // happened yet.
     43 void ClearBreakOnNextFunctionCall(Isolate* isolate);
     44 
     45 /**
     46  * Returns array of internal properties specific to the value type. Result has
     47  * the following format: [<name>, <value>,...,<name>, <value>]. Result array
     48  * will be allocated in the current context.
     49  */
     50 MaybeLocal<Array> GetInternalProperties(Isolate* isolate, Local<Value> value);
     51 
     52 enum ExceptionBreakState {
     53   NoBreakOnException = 0,
     54   BreakOnUncaughtException = 1,
     55   BreakOnAnyException = 2
     56 };
     57 
     58 /**
     59  * Defines if VM will pause on exceptions or not.
     60  * If BreakOnAnyExceptions is set then VM will pause on caught and uncaught
     61  * exception, if BreakOnUncaughtException is set then VM will pause only on
     62  * uncaught exception, otherwise VM won't stop on any exception.
     63  */
     64 void ChangeBreakOnException(Isolate* isolate, ExceptionBreakState state);
     65 
     66 void RemoveBreakpoint(Isolate* isolate, BreakpointId id);
     67 void SetBreakPointsActive(Isolate* isolate, bool is_active);
     68 
     69 enum StepAction {
     70   StepOut = 0,   // Step out of the current function.
     71   StepNext = 1,  // Step to the next statement in the current function.
     72   StepIn = 2     // Step into new functions invoked or the next statement
     73                  // in the current function.
     74 };
     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 class Script;
     83 
     84 struct LiveEditResult {
     85   enum Status {
     86     OK,
     87     COMPILE_ERROR,
     88     BLOCKED_BY_RUNNING_GENERATOR,
     89     BLOCKED_BY_FUNCTION_ABOVE_BREAK_FRAME,
     90     BLOCKED_BY_FUNCTION_BELOW_NON_DROPPABLE_FRAME,
     91     BLOCKED_BY_ACTIVE_FUNCTION,
     92     BLOCKED_BY_NEW_TARGET_IN_RESTART_FRAME,
     93     FRAME_RESTART_IS_NOT_SUPPORTED
     94   };
     95   Status status = OK;
     96   bool stack_changed = false;
     97   // Available only for OK.
     98   v8::Local<v8::debug::Script> script;
     99   // Fields below are available only for COMPILE_ERROR.
    100   v8::Local<v8::String> message;
    101   int line_number = -1;
    102   int column_number = -1;
    103 };
    104 
    105 /**
    106  * Native wrapper around v8::internal::Script object.
    107  */
    108 class V8_EXPORT_PRIVATE Script {
    109  public:
    110   v8::Isolate* GetIsolate() const;
    111 
    112   ScriptOriginOptions OriginOptions() const;
    113   bool WasCompiled() const;
    114   bool IsEmbedded() const;
    115   int Id() const;
    116   int LineOffset() const;
    117   int ColumnOffset() const;
    118   std::vector<int> LineEnds() const;
    119   MaybeLocal<String> Name() const;
    120   MaybeLocal<String> SourceURL() const;
    121   MaybeLocal<String> SourceMappingURL() const;
    122   Maybe<int> ContextId() const;
    123   MaybeLocal<String> Source() const;
    124   bool IsWasm() const;
    125   bool IsModule() const;
    126   bool GetPossibleBreakpoints(
    127       const debug::Location& start, const debug::Location& end,
    128       bool restrict_to_function,
    129       std::vector<debug::BreakLocation>* locations) const;
    130   int GetSourceOffset(const debug::Location& location) const;
    131   v8::debug::Location GetSourceLocation(int offset) const;
    132   bool SetScriptSource(v8::Local<v8::String> newSource, bool preview,
    133                        LiveEditResult* result) const;
    134   bool SetBreakpoint(v8::Local<v8::String> condition, debug::Location* location,
    135                      BreakpointId* id) const;
    136 };
    137 
    138 // Specialization for wasm Scripts.
    139 class WasmScript : public Script {
    140  public:
    141   static WasmScript* Cast(Script* script);
    142 
    143   int NumFunctions() const;
    144   int NumImportedFunctions() const;
    145 
    146   std::pair<int, int> GetFunctionRange(int function_index) const;
    147 
    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 MaybeLocal<UnboundScript> CompileInspectorScript(Isolate* isolate,
    155                                                  Local<String> source);
    156 
    157 class DebugDelegate {
    158  public:
    159   virtual ~DebugDelegate() {}
    160   virtual void ScriptCompiled(v8::Local<Script> script, bool is_live_edited,
    161                               bool has_compile_error) {}
    162   // |inspector_break_points_hit| contains id of breakpoints installed with
    163   // debug::Script::SetBreakpoint API.
    164   virtual void BreakProgramRequested(
    165       v8::Local<v8::Context> paused_context,
    166       const std::vector<debug::BreakpointId>& inspector_break_points_hit) {}
    167   virtual void ExceptionThrown(v8::Local<v8::Context> paused_context,
    168                                v8::Local<v8::Value> exception,
    169                                v8::Local<v8::Value> promise, bool is_uncaught) {
    170   }
    171   virtual bool IsFunctionBlackboxed(v8::Local<debug::Script> script,
    172                                     const debug::Location& start,
    173                                     const debug::Location& end) {
    174     return false;
    175   }
    176 };
    177 
    178 void SetDebugDelegate(Isolate* isolate, DebugDelegate* listener);
    179 
    180 class AsyncEventDelegate {
    181  public:
    182   virtual ~AsyncEventDelegate() {}
    183   virtual void AsyncEventOccurred(debug::DebugAsyncActionType type, int id,
    184                                   bool is_blackboxed) = 0;
    185 };
    186 
    187 void SetAsyncEventDelegate(Isolate* isolate, AsyncEventDelegate* delegate);
    188 
    189 void ResetBlackboxedStateCache(Isolate* isolate,
    190                                v8::Local<debug::Script> script);
    191 
    192 int EstimatedValueSize(Isolate* isolate, v8::Local<v8::Value> value);
    193 
    194 enum Builtin {
    195   kObjectKeys,
    196   kObjectGetPrototypeOf,
    197   kObjectGetOwnPropertyDescriptor,
    198   kObjectGetOwnPropertyNames,
    199   kObjectGetOwnPropertySymbols,
    200 };
    201 
    202 Local<Function> GetBuiltin(Isolate* isolate, Builtin builtin);
    203 
    204 V8_EXPORT_PRIVATE void SetConsoleDelegate(Isolate* isolate,
    205                                           ConsoleDelegate* delegate);
    206 
    207 int GetStackFrameId(v8::Local<v8::StackFrame> frame);
    208 
    209 v8::Local<v8::StackTrace> GetDetailedStackTrace(Isolate* isolate,
    210                                                 v8::Local<v8::Object> error);
    211 
    212 /**
    213  * Native wrapper around v8::internal::JSGeneratorObject object.
    214  */
    215 class GeneratorObject {
    216  public:
    217   v8::MaybeLocal<debug::Script> Script();
    218   v8::Local<v8::Function> Function();
    219   debug::Location SuspendedLocation();
    220   bool IsSuspended();
    221 
    222   static v8::Local<debug::GeneratorObject> Cast(v8::Local<v8::Value> value);
    223 };
    224 
    225 /*
    226  * Provide API layer between inspector and code coverage.
    227  */
    228 class V8_EXPORT_PRIVATE Coverage {
    229  public:
    230   MOVE_ONLY_NO_DEFAULT_CONSTRUCTOR(Coverage);
    231 
    232   enum Mode {
    233     // Make use of existing information in feedback vectors on the heap.
    234     // Only return a yes/no result. Optimization and GC are not affected.
    235     // Collecting best effort coverage does not reset counters.
    236     kBestEffort,
    237     // Disable optimization and prevent feedback vectors from being garbage
    238     // collected in order to preserve precise invocation counts. Collecting
    239     // precise count coverage resets counters to get incremental updates.
    240     kPreciseCount,
    241     // We are only interested in a yes/no result for the function. Optimization
    242     // and GC can be allowed once a function has been invoked. Collecting
    243     // precise binary coverage resets counters for incremental updates.
    244     kPreciseBinary,
    245     // Similar to the precise coverage modes but provides coverage at a
    246     // lower granularity. Design doc: goo.gl/lA2swZ.
    247     kBlockCount,
    248     kBlockBinary,
    249   };
    250 
    251   // Forward declarations.
    252   class ScriptData;
    253   class FunctionData;
    254 
    255   class V8_EXPORT_PRIVATE BlockData {
    256    public:
    257     MOVE_ONLY_NO_DEFAULT_CONSTRUCTOR(BlockData);
    258 
    259     int StartOffset() const;
    260     int EndOffset() const;
    261     uint32_t Count() const;
    262 
    263    private:
    264     explicit BlockData(i::CoverageBlock* block,
    265                        std::shared_ptr<i::Coverage> coverage)
    266         : block_(block), coverage_(std::move(coverage)) {}
    267 
    268     i::CoverageBlock* block_;
    269     std::shared_ptr<i::Coverage> coverage_;
    270 
    271     friend class v8::debug::Coverage::FunctionData;
    272   };
    273 
    274   class V8_EXPORT_PRIVATE FunctionData {
    275    public:
    276     MOVE_ONLY_NO_DEFAULT_CONSTRUCTOR(FunctionData);
    277 
    278     int StartOffset() const;
    279     int EndOffset() const;
    280     uint32_t Count() const;
    281     MaybeLocal<String> Name() const;
    282     size_t BlockCount() const;
    283     bool HasBlockCoverage() const;
    284     BlockData GetBlockData(size_t i) const;
    285 
    286    private:
    287     explicit FunctionData(i::CoverageFunction* function,
    288                           std::shared_ptr<i::Coverage> coverage)
    289         : function_(function), coverage_(std::move(coverage)) {}
    290 
    291     i::CoverageFunction* function_;
    292     std::shared_ptr<i::Coverage> coverage_;
    293 
    294     friend class v8::debug::Coverage::ScriptData;
    295   };
    296 
    297   class V8_EXPORT_PRIVATE ScriptData {
    298    public:
    299     MOVE_ONLY_NO_DEFAULT_CONSTRUCTOR(ScriptData);
    300 
    301     Local<debug::Script> GetScript() const;
    302     size_t FunctionCount() const;
    303     FunctionData GetFunctionData(size_t i) const;
    304 
    305    private:
    306     explicit ScriptData(size_t index, std::shared_ptr<i::Coverage> c);
    307 
    308     i::CoverageScript* script_;
    309     std::shared_ptr<i::Coverage> coverage_;
    310 
    311     friend class v8::debug::Coverage;
    312   };
    313 
    314   static Coverage CollectPrecise(Isolate* isolate);
    315   static Coverage CollectBestEffort(Isolate* isolate);
    316 
    317   static void SelectMode(Isolate* isolate, Mode mode);
    318 
    319   size_t ScriptCount() const;
    320   ScriptData GetScriptData(size_t i) const;
    321   bool IsEmpty() const { return coverage_ == nullptr; }
    322 
    323  private:
    324   explicit Coverage(std::shared_ptr<i::Coverage> coverage)
    325       : coverage_(std::move(coverage)) {}
    326   std::shared_ptr<i::Coverage> coverage_;
    327 };
    328 
    329 /*
    330  * Provide API layer between inspector and type profile.
    331  */
    332 class V8_EXPORT_PRIVATE TypeProfile {
    333  public:
    334   MOVE_ONLY_NO_DEFAULT_CONSTRUCTOR(TypeProfile);
    335 
    336   enum Mode {
    337     kNone,
    338     kCollect,
    339   };
    340   class ScriptData;  // Forward declaration.
    341 
    342   class V8_EXPORT_PRIVATE Entry {
    343    public:
    344     MOVE_ONLY_NO_DEFAULT_CONSTRUCTOR(Entry);
    345 
    346     int SourcePosition() const;
    347     std::vector<MaybeLocal<String>> Types() const;
    348 
    349    private:
    350     explicit Entry(const i::TypeProfileEntry* entry,
    351                    std::shared_ptr<i::TypeProfile> type_profile)
    352         : entry_(entry), type_profile_(std::move(type_profile)) {}
    353 
    354     const i::TypeProfileEntry* entry_;
    355     std::shared_ptr<i::TypeProfile> type_profile_;
    356 
    357     friend class v8::debug::TypeProfile::ScriptData;
    358   };
    359 
    360   class V8_EXPORT_PRIVATE ScriptData {
    361    public:
    362     MOVE_ONLY_NO_DEFAULT_CONSTRUCTOR(ScriptData);
    363 
    364     Local<debug::Script> GetScript() const;
    365     std::vector<Entry> Entries() const;
    366 
    367    private:
    368     explicit ScriptData(size_t index,
    369                         std::shared_ptr<i::TypeProfile> type_profile);
    370 
    371     i::TypeProfileScript* script_;
    372     std::shared_ptr<i::TypeProfile> type_profile_;
    373 
    374     friend class v8::debug::TypeProfile;
    375   };
    376 
    377   static TypeProfile Collect(Isolate* isolate);
    378 
    379   static void SelectMode(Isolate* isolate, Mode mode);
    380 
    381   size_t ScriptCount() const;
    382   ScriptData GetScriptData(size_t i) const;
    383 
    384  private:
    385   explicit TypeProfile(std::shared_ptr<i::TypeProfile> type_profile)
    386       : type_profile_(std::move(type_profile)) {}
    387 
    388   std::shared_ptr<i::TypeProfile> type_profile_;
    389 };
    390 
    391 class ScopeIterator {
    392  public:
    393   static std::unique_ptr<ScopeIterator> CreateForFunction(
    394       v8::Isolate* isolate, v8::Local<v8::Function> func);
    395   static std::unique_ptr<ScopeIterator> CreateForGeneratorObject(
    396       v8::Isolate* isolate, v8::Local<v8::Object> generator);
    397 
    398   ScopeIterator() = default;
    399   virtual ~ScopeIterator() = default;
    400 
    401   enum ScopeType {
    402     ScopeTypeGlobal = 0,
    403     ScopeTypeLocal,
    404     ScopeTypeWith,
    405     ScopeTypeClosure,
    406     ScopeTypeCatch,
    407     ScopeTypeBlock,
    408     ScopeTypeScript,
    409     ScopeTypeEval,
    410     ScopeTypeModule
    411   };
    412 
    413   virtual bool Done() = 0;
    414   virtual void Advance() = 0;
    415   virtual ScopeType GetType() = 0;
    416   virtual v8::Local<v8::Object> GetObject() = 0;
    417   virtual v8::Local<v8::Value> GetFunctionDebugName() = 0;
    418   virtual int GetScriptId() = 0;
    419   virtual bool HasLocationInfo() = 0;
    420   virtual debug::Location GetStartLocation() = 0;
    421   virtual debug::Location GetEndLocation() = 0;
    422 
    423   virtual bool SetVariableValue(v8::Local<v8::String> name,
    424                                 v8::Local<v8::Value> value) = 0;
    425 
    426  private:
    427   DISALLOW_COPY_AND_ASSIGN(ScopeIterator);
    428 };
    429 
    430 class StackTraceIterator {
    431  public:
    432   static std::unique_ptr<StackTraceIterator> Create(Isolate* isolate,
    433                                                     int index = 0);
    434   StackTraceIterator() = default;
    435   virtual ~StackTraceIterator() = default;
    436 
    437   virtual bool Done() const = 0;
    438   virtual void Advance() = 0;
    439 
    440   virtual int GetContextId() const = 0;
    441   virtual v8::MaybeLocal<v8::Value> GetReceiver() const = 0;
    442   virtual v8::Local<v8::Value> GetReturnValue() const = 0;
    443   virtual v8::Local<v8::String> GetFunctionDebugName() const = 0;
    444   virtual v8::Local<v8::debug::Script> GetScript() const = 0;
    445   virtual debug::Location GetSourceLocation() const = 0;
    446   virtual v8::Local<v8::Function> GetFunction() const = 0;
    447   virtual std::unique_ptr<ScopeIterator> GetScopeIterator() const = 0;
    448 
    449   virtual bool Restart() = 0;
    450   virtual v8::MaybeLocal<v8::Value> Evaluate(v8::Local<v8::String> source,
    451                                              bool throw_on_side_effect) = 0;
    452 
    453  private:
    454   DISALLOW_COPY_AND_ASSIGN(StackTraceIterator);
    455 };
    456 
    457 class QueryObjectPredicate {
    458  public:
    459   virtual ~QueryObjectPredicate() = default;
    460   virtual bool Filter(v8::Local<v8::Object> object) = 0;
    461 };
    462 
    463 void QueryObjects(v8::Local<v8::Context> context,
    464                   QueryObjectPredicate* predicate,
    465                   v8::PersistentValueVector<v8::Object>* objects);
    466 
    467 void GlobalLexicalScopeNames(v8::Local<v8::Context> context,
    468                              v8::PersistentValueVector<v8::String>* names);
    469 
    470 void SetReturnValue(v8::Isolate* isolate, v8::Local<v8::Value> value);
    471 
    472 enum class NativeAccessorType {
    473   None = 0,
    474   HasGetter = 1 << 0,
    475   HasSetter = 1 << 1,
    476   IsBuiltin = 1 << 2
    477 };
    478 
    479 int GetNativeAccessorDescriptor(v8::Local<v8::Context> context,
    480                                 v8::Local<v8::Object> object,
    481                                 v8::Local<v8::Name> name);
    482 
    483 int64_t GetNextRandomInt64(v8::Isolate* isolate);
    484 
    485 v8::MaybeLocal<v8::Value> EvaluateGlobal(v8::Isolate* isolate,
    486                                          v8::Local<v8::String> source,
    487                                          bool throw_on_side_effect);
    488 
    489 int GetDebuggingId(v8::Local<v8::Function> function);
    490 
    491 bool SetFunctionBreakpoint(v8::Local<v8::Function> function,
    492                            v8::Local<v8::String> condition, BreakpointId* id);
    493 
    494 v8::Platform* GetCurrentPlatform();
    495 
    496 class PostponeInterruptsScope {
    497  public:
    498   explicit PostponeInterruptsScope(v8::Isolate* isolate);
    499   ~PostponeInterruptsScope();
    500 
    501  private:
    502   std::unique_ptr<i::PostponeInterruptsScope> scope_;
    503 };
    504 
    505 }  // namespace debug
    506 }  // namespace v8
    507 
    508 #endif  // V8_DEBUG_DEBUG_INTERFACE_H_
    509