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: ~DebugDelegate()159 virtual ~DebugDelegate() {} ScriptCompiled(v8::Local<Script> script,bool is_live_edited,bool has_compile_error)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. BreakProgramRequested(v8::Local<v8::Context> paused_context,const std::vector<debug::BreakpointId> & inspector_break_points_hit)164 virtual void BreakProgramRequested( 165 v8::Local<v8::Context> paused_context, 166 const std::vector<debug::BreakpointId>& inspector_break_points_hit) {} ExceptionThrown(v8::Local<v8::Context> paused_context,v8::Local<v8::Value> exception,v8::Local<v8::Value> promise,bool is_uncaught)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 } IsFunctionBlackboxed(v8::Local<debug::Script> script,const debug::Location & start,const debug::Location & end)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: ~AsyncEventDelegate()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: BlockData(i::CoverageBlock * block,std::shared_ptr<i::Coverage> coverage)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: FunctionData(i::CoverageFunction * function,std::shared_ptr<i::Coverage> coverage)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; IsEmpty()321 bool IsEmpty() const { return coverage_ == nullptr; } 322 323 private: Coverage(std::shared_ptr<i::Coverage> coverage)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: Entry(const i::TypeProfileEntry * entry,std::shared_ptr<i::TypeProfile> type_profile)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: TypeProfile(std::shared_ptr<i::TypeProfile> type_profile)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