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 | V8_EXPORT_PRIVATE void SetBreakOnNextFunctionCall(Isolate* isolate); |
40 | |
41 | // Remove scheduled debugger break in given isolate if it has not |
42 | // happened yet. |
43 | V8_EXPORT_PRIVATE 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 | /** |
53 | * Returns array of private fields specific to the value type. Result has |
54 | * the following format: [<name>, <value>,...,<name>, <value>]. Result array |
55 | * will be allocated in the current context. |
56 | */ |
57 | V8_EXPORT_PRIVATE MaybeLocal<Array> GetPrivateFields(Local<Context> context, |
58 | Local<Object> value); |
59 | |
60 | enum ExceptionBreakState { |
61 | NoBreakOnException = 0, |
62 | BreakOnUncaughtException = 1, |
63 | BreakOnAnyException = 2 |
64 | }; |
65 | |
66 | /** |
67 | * Defines if VM will pause on exceptions or not. |
68 | * If BreakOnAnyExceptions is set then VM will pause on caught and uncaught |
69 | * exception, if BreakOnUncaughtException is set then VM will pause only on |
70 | * uncaught exception, otherwise VM won't stop on any exception. |
71 | */ |
72 | void ChangeBreakOnException(Isolate* isolate, ExceptionBreakState state); |
73 | |
74 | void RemoveBreakpoint(Isolate* isolate, BreakpointId id); |
75 | void SetBreakPointsActive(Isolate* isolate, bool is_active); |
76 | |
77 | enum StepAction { |
78 | StepOut = 0, // Step out of the current function. |
79 | StepNext = 1, // Step to the next statement in the current function. |
80 | StepIn = 2 // Step into new functions invoked or the next statement |
81 | // in the current function. |
82 | }; |
83 | |
84 | void PrepareStep(Isolate* isolate, StepAction action); |
85 | void ClearStepping(Isolate* isolate); |
86 | V8_EXPORT_PRIVATE void BreakRightNow(Isolate* isolate); |
87 | |
88 | bool AllFramesOnStackAreBlackboxed(Isolate* isolate); |
89 | |
90 | class Script; |
91 | |
92 | struct LiveEditResult { |
93 | enum Status { |
94 | OK, |
95 | COMPILE_ERROR, |
96 | BLOCKED_BY_RUNNING_GENERATOR, |
97 | BLOCKED_BY_FUNCTION_ABOVE_BREAK_FRAME, |
98 | BLOCKED_BY_FUNCTION_BELOW_NON_DROPPABLE_FRAME, |
99 | BLOCKED_BY_ACTIVE_FUNCTION, |
100 | BLOCKED_BY_NEW_TARGET_IN_RESTART_FRAME, |
101 | FRAME_RESTART_IS_NOT_SUPPORTED |
102 | }; |
103 | Status status = OK; |
104 | bool stack_changed = false; |
105 | // Available only for OK. |
106 | v8::Local<v8::debug::Script> script; |
107 | // Fields below are available only for COMPILE_ERROR. |
108 | v8::Local<v8::String> message; |
109 | int line_number = -1; |
110 | int column_number = -1; |
111 | }; |
112 | |
113 | /** |
114 | * Native wrapper around v8::internal::Script object. |
115 | */ |
116 | class V8_EXPORT_PRIVATE Script { |
117 | public: |
118 | v8::Isolate* GetIsolate() const; |
119 | |
120 | ScriptOriginOptions OriginOptions() const; |
121 | bool WasCompiled() const; |
122 | bool IsEmbedded() const; |
123 | int Id() const; |
124 | int LineOffset() const; |
125 | int ColumnOffset() const; |
126 | std::vector<int> LineEnds() const; |
127 | MaybeLocal<String> Name() const; |
128 | MaybeLocal<String> SourceURL() const; |
129 | MaybeLocal<String> SourceMappingURL() const; |
130 | Maybe<int> ContextId() const; |
131 | MaybeLocal<String> Source() const; |
132 | bool IsWasm() const; |
133 | bool IsModule() const; |
134 | bool GetPossibleBreakpoints( |
135 | const debug::Location& start, const debug::Location& end, |
136 | bool restrict_to_function, |
137 | std::vector<debug::BreakLocation>* locations) const; |
138 | int GetSourceOffset(const debug::Location& location) const; |
139 | v8::debug::Location GetSourceLocation(int offset) const; |
140 | bool SetScriptSource(v8::Local<v8::String> newSource, bool preview, |
141 | LiveEditResult* result) const; |
142 | bool SetBreakpoint(v8::Local<v8::String> condition, debug::Location* location, |
143 | BreakpointId* id) 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 | uint32_t GetFunctionHash(int function_index); |
158 | }; |
159 | |
160 | V8_EXPORT_PRIVATE void GetLoadedScripts(Isolate* isolate, |
161 | PersistentValueVector<Script>& scripts); |
162 | |
163 | MaybeLocal<UnboundScript> CompileInspectorScript(Isolate* isolate, |
164 | Local<String> source); |
165 | |
166 | enum ExceptionType { kException, kPromiseRejection }; |
167 | |
168 | class DebugDelegate { |
169 | public: |
170 | virtual ~DebugDelegate() = default; |
171 | virtual void ScriptCompiled(v8::Local<Script> script, bool is_live_edited, |
172 | bool has_compile_error) {} |
173 | // |inspector_break_points_hit| contains id of breakpoints installed with |
174 | // debug::Script::SetBreakpoint API. |
175 | virtual void BreakProgramRequested( |
176 | v8::Local<v8::Context> paused_context, |
177 | const std::vector<debug::BreakpointId>& inspector_break_points_hit) {} |
178 | virtual void ExceptionThrown(v8::Local<v8::Context> paused_context, |
179 | v8::Local<v8::Value> exception, |
180 | v8::Local<v8::Value> promise, bool is_uncaught, |
181 | ExceptionType exception_type) {} |
182 | virtual bool IsFunctionBlackboxed(v8::Local<debug::Script> script, |
183 | const debug::Location& start, |
184 | const debug::Location& end) { |
185 | return false; |
186 | } |
187 | }; |
188 | |
189 | V8_EXPORT_PRIVATE void SetDebugDelegate(Isolate* isolate, |
190 | DebugDelegate* listener); |
191 | |
192 | class AsyncEventDelegate { |
193 | public: |
194 | virtual ~AsyncEventDelegate() = default; |
195 | virtual void AsyncEventOccurred(debug::DebugAsyncActionType type, int id, |
196 | bool is_blackboxed) = 0; |
197 | }; |
198 | |
199 | void SetAsyncEventDelegate(Isolate* isolate, AsyncEventDelegate* delegate); |
200 | |
201 | void ResetBlackboxedStateCache(Isolate* isolate, |
202 | v8::Local<debug::Script> script); |
203 | |
204 | int EstimatedValueSize(Isolate* isolate, v8::Local<v8::Value> value); |
205 | |
206 | enum Builtin { kStringToLowerCase }; |
207 | |
208 | Local<Function> GetBuiltin(Isolate* isolate, Builtin builtin); |
209 | |
210 | V8_EXPORT_PRIVATE void SetConsoleDelegate(Isolate* isolate, |
211 | ConsoleDelegate* delegate); |
212 | |
213 | int GetStackFrameId(v8::Local<v8::StackFrame> frame); |
214 | |
215 | v8::Local<v8::StackTrace> GetDetailedStackTrace(Isolate* isolate, |
216 | v8::Local<v8::Object> error); |
217 | |
218 | /** |
219 | * Native wrapper around v8::internal::JSGeneratorObject object. |
220 | */ |
221 | class GeneratorObject { |
222 | public: |
223 | v8::MaybeLocal<debug::Script> Script(); |
224 | v8::Local<v8::Function> Function(); |
225 | debug::Location SuspendedLocation(); |
226 | bool IsSuspended(); |
227 | |
228 | static v8::Local<debug::GeneratorObject> Cast(v8::Local<v8::Value> value); |
229 | }; |
230 | |
231 | /* |
232 | * Provide API layer between inspector and code coverage. |
233 | */ |
234 | class V8_EXPORT_PRIVATE Coverage { |
235 | public: |
236 | MOVE_ONLY_NO_DEFAULT_CONSTRUCTOR(Coverage); |
237 | |
238 | // Forward declarations. |
239 | class ScriptData; |
240 | class FunctionData; |
241 | |
242 | class V8_EXPORT_PRIVATE BlockData { |
243 | public: |
244 | MOVE_ONLY_NO_DEFAULT_CONSTRUCTOR(BlockData); |
245 | |
246 | int StartOffset() const; |
247 | int EndOffset() const; |
248 | uint32_t Count() const; |
249 | |
250 | private: |
251 | explicit BlockData(i::CoverageBlock* block, |
252 | std::shared_ptr<i::Coverage> coverage) |
253 | : block_(block), coverage_(std::move(coverage)) {} |
254 | |
255 | i::CoverageBlock* block_; |
256 | std::shared_ptr<i::Coverage> coverage_; |
257 | |
258 | friend class v8::debug::Coverage::FunctionData; |
259 | }; |
260 | |
261 | class V8_EXPORT_PRIVATE FunctionData { |
262 | public: |
263 | MOVE_ONLY_NO_DEFAULT_CONSTRUCTOR(FunctionData); |
264 | |
265 | int StartOffset() const; |
266 | int EndOffset() const; |
267 | uint32_t Count() const; |
268 | MaybeLocal<String> Name() const; |
269 | size_t BlockCount() const; |
270 | bool HasBlockCoverage() const; |
271 | BlockData GetBlockData(size_t i) const; |
272 | |
273 | private: |
274 | explicit FunctionData(i::CoverageFunction* function, |
275 | std::shared_ptr<i::Coverage> coverage) |
276 | : function_(function), coverage_(std::move(coverage)) {} |
277 | |
278 | i::CoverageFunction* function_; |
279 | std::shared_ptr<i::Coverage> coverage_; |
280 | |
281 | friend class v8::debug::Coverage::ScriptData; |
282 | }; |
283 | |
284 | class V8_EXPORT_PRIVATE ScriptData { |
285 | public: |
286 | MOVE_ONLY_NO_DEFAULT_CONSTRUCTOR(ScriptData); |
287 | |
288 | Local<debug::Script> GetScript() const; |
289 | size_t FunctionCount() const; |
290 | FunctionData GetFunctionData(size_t i) const; |
291 | |
292 | private: |
293 | explicit ScriptData(size_t index, std::shared_ptr<i::Coverage> c); |
294 | |
295 | i::CoverageScript* script_; |
296 | std::shared_ptr<i::Coverage> coverage_; |
297 | |
298 | friend class v8::debug::Coverage; |
299 | }; |
300 | |
301 | static Coverage CollectPrecise(Isolate* isolate); |
302 | static Coverage CollectBestEffort(Isolate* isolate); |
303 | |
304 | static void SelectMode(Isolate* isolate, CoverageMode mode); |
305 | |
306 | size_t ScriptCount() const; |
307 | ScriptData GetScriptData(size_t i) const; |
308 | bool IsEmpty() const { return coverage_ == nullptr; } |
309 | |
310 | private: |
311 | explicit Coverage(std::shared_ptr<i::Coverage> coverage) |
312 | : coverage_(std::move(coverage)) {} |
313 | std::shared_ptr<i::Coverage> coverage_; |
314 | }; |
315 | |
316 | /* |
317 | * Provide API layer between inspector and type profile. |
318 | */ |
319 | class V8_EXPORT_PRIVATE TypeProfile { |
320 | public: |
321 | MOVE_ONLY_NO_DEFAULT_CONSTRUCTOR(TypeProfile); |
322 | |
323 | class ScriptData; // Forward declaration. |
324 | |
325 | class V8_EXPORT_PRIVATE Entry { |
326 | public: |
327 | MOVE_ONLY_NO_DEFAULT_CONSTRUCTOR(Entry); |
328 | |
329 | int SourcePosition() const; |
330 | std::vector<MaybeLocal<String>> Types() const; |
331 | |
332 | private: |
333 | explicit Entry(const i::TypeProfileEntry* entry, |
334 | std::shared_ptr<i::TypeProfile> type_profile) |
335 | : entry_(entry), type_profile_(std::move(type_profile)) {} |
336 | |
337 | const i::TypeProfileEntry* entry_; |
338 | std::shared_ptr<i::TypeProfile> type_profile_; |
339 | |
340 | friend class v8::debug::TypeProfile::ScriptData; |
341 | }; |
342 | |
343 | class V8_EXPORT_PRIVATE ScriptData { |
344 | public: |
345 | MOVE_ONLY_NO_DEFAULT_CONSTRUCTOR(ScriptData); |
346 | |
347 | Local<debug::Script> GetScript() const; |
348 | std::vector<Entry> Entries() const; |
349 | |
350 | private: |
351 | explicit ScriptData(size_t index, |
352 | std::shared_ptr<i::TypeProfile> type_profile); |
353 | |
354 | i::TypeProfileScript* script_; |
355 | std::shared_ptr<i::TypeProfile> type_profile_; |
356 | |
357 | friend class v8::debug::TypeProfile; |
358 | }; |
359 | |
360 | static TypeProfile Collect(Isolate* isolate); |
361 | |
362 | static void SelectMode(Isolate* isolate, TypeProfileMode mode); |
363 | |
364 | size_t ScriptCount() const; |
365 | ScriptData GetScriptData(size_t i) const; |
366 | |
367 | private: |
368 | explicit TypeProfile(std::shared_ptr<i::TypeProfile> type_profile) |
369 | : type_profile_(std::move(type_profile)) {} |
370 | |
371 | std::shared_ptr<i::TypeProfile> type_profile_; |
372 | }; |
373 | |
374 | class V8_EXPORT_PRIVATE ScopeIterator { |
375 | public: |
376 | static std::unique_ptr<ScopeIterator> CreateForFunction( |
377 | v8::Isolate* isolate, v8::Local<v8::Function> func); |
378 | static std::unique_ptr<ScopeIterator> CreateForGeneratorObject( |
379 | v8::Isolate* isolate, v8::Local<v8::Object> generator); |
380 | |
381 | ScopeIterator() = default; |
382 | virtual ~ScopeIterator() = default; |
383 | |
384 | enum ScopeType { |
385 | ScopeTypeGlobal = 0, |
386 | ScopeTypeLocal, |
387 | ScopeTypeWith, |
388 | ScopeTypeClosure, |
389 | ScopeTypeCatch, |
390 | ScopeTypeBlock, |
391 | ScopeTypeScript, |
392 | ScopeTypeEval, |
393 | ScopeTypeModule |
394 | }; |
395 | |
396 | virtual bool Done() = 0; |
397 | virtual void Advance() = 0; |
398 | virtual ScopeType GetType() = 0; |
399 | virtual v8::Local<v8::Object> GetObject() = 0; |
400 | virtual v8::Local<v8::Value> GetFunctionDebugName() = 0; |
401 | virtual int GetScriptId() = 0; |
402 | virtual bool HasLocationInfo() = 0; |
403 | virtual debug::Location GetStartLocation() = 0; |
404 | virtual debug::Location GetEndLocation() = 0; |
405 | |
406 | virtual bool SetVariableValue(v8::Local<v8::String> name, |
407 | v8::Local<v8::Value> value) = 0; |
408 | |
409 | private: |
410 | DISALLOW_COPY_AND_ASSIGN(ScopeIterator); |
411 | }; |
412 | |
413 | class V8_EXPORT_PRIVATE StackTraceIterator { |
414 | public: |
415 | static std::unique_ptr<StackTraceIterator> Create(Isolate* isolate, |
416 | int index = 0); |
417 | StackTraceIterator() = default; |
418 | virtual ~StackTraceIterator() = default; |
419 | |
420 | virtual bool Done() const = 0; |
421 | virtual void Advance() = 0; |
422 | |
423 | virtual int GetContextId() const = 0; |
424 | virtual v8::MaybeLocal<v8::Value> GetReceiver() const = 0; |
425 | virtual v8::Local<v8::Value> GetReturnValue() const = 0; |
426 | virtual v8::Local<v8::String> GetFunctionDebugName() const = 0; |
427 | virtual v8::Local<v8::debug::Script> GetScript() const = 0; |
428 | virtual debug::Location GetSourceLocation() const = 0; |
429 | virtual v8::Local<v8::Function> GetFunction() const = 0; |
430 | virtual std::unique_ptr<ScopeIterator> GetScopeIterator() const = 0; |
431 | |
432 | virtual bool Restart() = 0; |
433 | virtual v8::MaybeLocal<v8::Value> Evaluate(v8::Local<v8::String> source, |
434 | bool throw_on_side_effect) = 0; |
435 | |
436 | private: |
437 | DISALLOW_COPY_AND_ASSIGN(StackTraceIterator); |
438 | }; |
439 | |
440 | class QueryObjectPredicate { |
441 | public: |
442 | virtual ~QueryObjectPredicate() = default; |
443 | virtual bool Filter(v8::Local<v8::Object> object) = 0; |
444 | }; |
445 | |
446 | void QueryObjects(v8::Local<v8::Context> context, |
447 | QueryObjectPredicate* predicate, |
448 | v8::PersistentValueVector<v8::Object>* objects); |
449 | |
450 | void GlobalLexicalScopeNames(v8::Local<v8::Context> context, |
451 | v8::PersistentValueVector<v8::String>* names); |
452 | |
453 | void SetReturnValue(v8::Isolate* isolate, v8::Local<v8::Value> value); |
454 | |
455 | enum class NativeAccessorType { |
456 | None = 0, |
457 | HasGetter = 1 << 0, |
458 | HasSetter = 1 << 1 |
459 | }; |
460 | |
461 | int64_t GetNextRandomInt64(v8::Isolate* isolate); |
462 | |
463 | V8_EXPORT_PRIVATE v8::MaybeLocal<v8::Value> EvaluateGlobal( |
464 | v8::Isolate* isolate, v8::Local<v8::String> source, |
465 | bool throw_on_side_effect); |
466 | |
467 | int GetDebuggingId(v8::Local<v8::Function> function); |
468 | |
469 | bool SetFunctionBreakpoint(v8::Local<v8::Function> function, |
470 | v8::Local<v8::String> condition, BreakpointId* id); |
471 | |
472 | v8::Platform* GetCurrentPlatform(); |
473 | |
474 | class PostponeInterruptsScope { |
475 | public: |
476 | explicit PostponeInterruptsScope(v8::Isolate* isolate); |
477 | ~PostponeInterruptsScope(); |
478 | |
479 | private: |
480 | std::unique_ptr<i::PostponeInterruptsScope> scope_; |
481 | }; |
482 | |
483 | class WeakMap : public v8::Object { |
484 | public: |
485 | V8_WARN_UNUSED_RESULT v8::MaybeLocal<v8::Value> Get( |
486 | v8::Local<v8::Context> context, v8::Local<v8::Value> key); |
487 | V8_WARN_UNUSED_RESULT v8::MaybeLocal<WeakMap> Set( |
488 | v8::Local<v8::Context> context, v8::Local<v8::Value> key, |
489 | v8::Local<v8::Value> value); |
490 | |
491 | static Local<WeakMap> New(v8::Isolate* isolate); |
492 | V8_INLINE static WeakMap* Cast(Value* obj); |
493 | |
494 | private: |
495 | WeakMap(); |
496 | }; |
497 | |
498 | struct PropertyDescriptor { |
499 | bool enumerable : 1; |
500 | bool has_enumerable : 1; |
501 | bool configurable : 1; |
502 | bool has_configurable : 1; |
503 | bool writable : 1; |
504 | bool has_writable : 1; |
505 | v8::Local<v8::Value> value; |
506 | v8::Local<v8::Value> get; |
507 | v8::Local<v8::Value> set; |
508 | }; |
509 | |
510 | class PropertyIterator { |
511 | public: |
512 | static std::unique_ptr<PropertyIterator> Create(v8::Local<v8::Object> object); |
513 | |
514 | virtual ~PropertyIterator() = default; |
515 | |
516 | virtual bool Done() const = 0; |
517 | virtual void Advance() = 0; |
518 | |
519 | virtual v8::Local<v8::Name> name() const = 0; |
520 | |
521 | virtual bool is_native_accessor() = 0; |
522 | virtual bool has_native_getter() = 0; |
523 | virtual bool has_native_setter() = 0; |
524 | virtual Maybe<PropertyAttribute> attributes() = 0; |
525 | virtual Maybe<PropertyDescriptor> descriptor() = 0; |
526 | |
527 | virtual bool is_own() = 0; |
528 | virtual bool is_array_index() = 0; |
529 | }; |
530 | } // namespace debug |
531 | } // namespace v8 |
532 | |
533 | #endif // V8_DEBUG_DEBUG_INTERFACE_H_ |
534 | |