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 <functional> 9 10 #include "include/v8-debug.h" 11 #include "include/v8-util.h" 12 #include "include/v8.h" 13 14 #include "src/debug/interface-types.h" 15 #include "src/globals.h" 16 17 namespace v8 { 18 19 namespace internal { 20 struct CoverageFunction; 21 struct CoverageScript; 22 class Coverage; 23 class Script; 24 } 25 26 namespace debug { 27 28 /** 29 * Debugger is running in its own context which is entered while debugger 30 * messages are being dispatched. This is an explicit getter for this 31 * debugger context. Note that the content of the debugger context is subject 32 * to change. The Context exists only when the debugger is active, i.e. at 33 * least one DebugEventListener or MessageHandler is set. 34 */ 35 Local<Context> GetDebugContext(Isolate* isolate); 36 37 /** 38 * Run a JavaScript function in the debugger. 39 * \param fun the function to call 40 * \param data passed as second argument to the function 41 * With this call the debugger is entered and the function specified is called 42 * with the execution state as the first argument. This makes it possible to 43 * get access to information otherwise not available during normal JavaScript 44 * execution e.g. details on stack frames. Receiver of the function call will 45 * be the debugger context global object, however this is a subject to change. 46 * The following example shows a JavaScript function which when passed to 47 * v8::Debug::Call will return the current line of JavaScript execution. 48 * 49 * \code 50 * function frame_source_line(exec_state) { 51 * return exec_state.frame(0).sourceLine(); 52 * } 53 * \endcode 54 */ 55 // TODO(dcarney): data arg should be a MaybeLocal 56 MaybeLocal<Value> Call(Local<Context> context, v8::Local<v8::Function> fun, 57 Local<Value> data = Local<Value>()); 58 59 /** 60 * Enable/disable LiveEdit functionality for the given Isolate 61 * (default Isolate if not provided). V8 will abort if LiveEdit is 62 * unexpectedly used. LiveEdit is enabled by default. 63 */ 64 void SetLiveEditEnabled(Isolate* isolate, bool enable); 65 66 // Schedule a debugger break to happen when JavaScript code is run 67 // in the given isolate. 68 void DebugBreak(Isolate* isolate); 69 70 // Remove scheduled debugger break in given isolate if it has not 71 // happened yet. 72 void CancelDebugBreak(Isolate* isolate); 73 74 /** 75 * Returns array of internal properties specific to the value type. Result has 76 * the following format: [<name>, <value>,...,<name>, <value>]. Result array 77 * will be allocated in the current context. 78 */ 79 MaybeLocal<Array> GetInternalProperties(Isolate* isolate, Local<Value> value); 80 81 enum ExceptionBreakState { 82 NoBreakOnException = 0, 83 BreakOnUncaughtException = 1, 84 BreakOnAnyException = 2 85 }; 86 87 /** 88 * Defines if VM will pause on exceptions or not. 89 * If BreakOnAnyExceptions is set then VM will pause on caught and uncaught 90 * exception, if BreakOnUncaughtException is set then VM will pause only on 91 * uncaught exception, otherwise VM won't stop on any exception. 92 */ 93 void ChangeBreakOnException(Isolate* isolate, ExceptionBreakState state); 94 95 void SetBreakPointsActive(Isolate* isolate, bool is_active); 96 97 enum StepAction { 98 StepOut = 0, // Step out of the current function. 99 StepNext = 1, // Step to the next statement in the current function. 100 StepIn = 2 // Step into new functions invoked or the next statement 101 // in the current function. 102 }; 103 104 void PrepareStep(Isolate* isolate, StepAction action); 105 106 bool HasNonBlackboxedFrameOnStack(Isolate* isolate); 107 108 /** 109 * Out-of-memory callback function. 110 * The function is invoked when the heap size is close to the hard limit. 111 * 112 * \param data the parameter provided during callback installation. 113 */ 114 typedef void (*OutOfMemoryCallback)(void* data); 115 void SetOutOfMemoryCallback(Isolate* isolate, OutOfMemoryCallback callback, 116 void* data); 117 118 /** 119 * Native wrapper around v8::internal::Script object. 120 */ 121 class V8_EXPORT_PRIVATE Script { 122 public: 123 v8::Isolate* GetIsolate() const; 124 125 ScriptOriginOptions OriginOptions() const; 126 bool WasCompiled() const; 127 int Id() const; 128 int LineOffset() const; 129 int ColumnOffset() const; 130 std::vector<int> LineEnds() const; 131 MaybeLocal<String> Name() const; 132 MaybeLocal<String> SourceURL() const; 133 MaybeLocal<String> SourceMappingURL() const; 134 MaybeLocal<Value> ContextData() const; 135 MaybeLocal<String> Source() const; 136 bool IsWasm() const; 137 bool IsModule() const; 138 bool GetPossibleBreakpoints(const debug::Location& start, 139 const debug::Location& end, 140 std::vector<debug::Location>* locations) const; 141 142 private: 143 int GetSourcePosition(const debug::Location& location) const; 144 }; 145 146 // Specialization for wasm Scripts. 147 class WasmScript : public Script { 148 public: 149 static WasmScript* Cast(Script* script); 150 151 int NumFunctions() const; 152 int NumImportedFunctions() const; 153 154 std::pair<int, int> GetFunctionRange(int function_index) const; 155 156 debug::WasmDisassembly DisassembleFunction(int function_index) const; 157 }; 158 159 void GetLoadedScripts(Isolate* isolate, PersistentValueVector<Script>& scripts); 160 161 MaybeLocal<UnboundScript> CompileInspectorScript(Isolate* isolate, 162 Local<String> source); 163 164 class DebugDelegate { 165 public: ~DebugDelegate()166 virtual ~DebugDelegate() {} PromiseEventOccurred(debug::PromiseDebugActionType type,int id,int parent_id)167 virtual void PromiseEventOccurred(debug::PromiseDebugActionType type, int id, 168 int parent_id) {} ScriptCompiled(v8::Local<Script> script,bool has_compile_error)169 virtual void ScriptCompiled(v8::Local<Script> script, 170 bool has_compile_error) {} BreakProgramRequested(v8::Local<v8::Context> paused_context,v8::Local<v8::Object> exec_state,v8::Local<v8::Value> break_points_hit)171 virtual void BreakProgramRequested(v8::Local<v8::Context> paused_context, 172 v8::Local<v8::Object> exec_state, 173 v8::Local<v8::Value> break_points_hit) {} ExceptionThrown(v8::Local<v8::Context> paused_context,v8::Local<v8::Object> exec_state,v8::Local<v8::Value> exception,v8::Local<v8::Value> promise,bool is_uncaught)174 virtual void ExceptionThrown(v8::Local<v8::Context> paused_context, 175 v8::Local<v8::Object> exec_state, 176 v8::Local<v8::Value> exception, 177 v8::Local<v8::Value> promise, bool is_uncaught) { 178 } IsFunctionBlackboxed(v8::Local<debug::Script> script,const debug::Location & start,const debug::Location & end)179 virtual bool IsFunctionBlackboxed(v8::Local<debug::Script> script, 180 const debug::Location& start, 181 const debug::Location& end) { 182 return false; 183 } 184 }; 185 186 void SetDebugDelegate(Isolate* isolate, DebugDelegate* listener); 187 188 void ResetBlackboxedStateCache(Isolate* isolate, 189 v8::Local<debug::Script> script); 190 191 int EstimatedValueSize(Isolate* isolate, v8::Local<v8::Value> value); 192 193 v8::MaybeLocal<v8::Array> EntriesPreview(Isolate* isolate, 194 v8::Local<v8::Value> value, 195 bool* is_key_value); 196 197 /** 198 * Native wrapper around v8::internal::JSGeneratorObject object. 199 */ 200 class GeneratorObject { 201 public: 202 v8::MaybeLocal<debug::Script> Script(); 203 v8::Local<v8::Function> Function(); 204 debug::Location SuspendedLocation(); 205 bool IsSuspended(); 206 207 static v8::Local<debug::GeneratorObject> Cast(v8::Local<v8::Value> value); 208 }; 209 210 /* 211 * Provide API layer between inspector and code coverage. 212 */ 213 class V8_EXPORT_PRIVATE Coverage { 214 public: 215 class ScriptData; // Forward declaration. 216 217 class V8_EXPORT_PRIVATE FunctionData { 218 public: 219 // 0-based line and colum numbers. Start()220 Location Start() { return start_; } End()221 Location End() { return end_; } 222 uint32_t Count(); 223 MaybeLocal<String> Name(); 224 225 private: 226 FunctionData(i::CoverageFunction* function, Local<debug::Script> script); 227 i::CoverageFunction* function_; 228 Location start_; 229 Location end_; 230 231 friend class v8::debug::Coverage::ScriptData; 232 }; 233 234 class V8_EXPORT_PRIVATE ScriptData { 235 public: 236 Local<debug::Script> GetScript(); 237 size_t FunctionCount(); 238 FunctionData GetFunctionData(size_t i); 239 240 private: ScriptData(i::CoverageScript * script)241 explicit ScriptData(i::CoverageScript* script) : script_(script) {} 242 i::CoverageScript* script_; 243 244 friend class v8::debug::Coverage; 245 }; 246 247 static Coverage Collect(Isolate* isolate, bool reset_count); 248 249 static void TogglePrecise(Isolate* isolate, bool enable); 250 251 size_t ScriptCount(); 252 ScriptData GetScriptData(size_t i); IsEmpty()253 bool IsEmpty() { return coverage_ == nullptr; } 254 255 ~Coverage(); 256 257 private: Coverage(i::Coverage * coverage)258 explicit Coverage(i::Coverage* coverage) : coverage_(coverage) {} 259 i::Coverage* coverage_; 260 }; 261 } // namespace debug 262 } // namespace v8 263 264 #endif // V8_DEBUG_DEBUG_INTERFACE_H_ 265