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
15namespace v8 {
16
17namespace internal {
18struct CoverageBlock;
19struct CoverageFunction;
20struct CoverageScript;
21struct TypeProfileEntry;
22struct TypeProfileScript;
23class Coverage;
24class PostponeInterruptsScope;
25class Script;
26class TypeProfile;
27} // namespace internal
28
29namespace debug {
30
31void SetContextId(Local<Context> context, int id);
32int GetContextId(Local<Context> context);
33
34void SetInspector(Isolate* isolate, v8_inspector::V8Inspector*);
35v8_inspector::V8Inspector* GetInspector(Isolate* isolate);
36
37// Schedule a debugger break to happen when function is called inside given
38// isolate.
39V8_EXPORT_PRIVATE void SetBreakOnNextFunctionCall(Isolate* isolate);
40
41// Remove scheduled debugger break in given isolate if it has not
42// happened yet.
43V8_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 */
50MaybeLocal<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 */
57V8_EXPORT_PRIVATE MaybeLocal<Array> GetPrivateFields(Local<Context> context,
58 Local<Object> value);
59
60enum 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 */
72void ChangeBreakOnException(Isolate* isolate, ExceptionBreakState state);
73
74void RemoveBreakpoint(Isolate* isolate, BreakpointId id);
75void SetBreakPointsActive(Isolate* isolate, bool is_active);
76
77enum 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
84void PrepareStep(Isolate* isolate, StepAction action);
85void ClearStepping(Isolate* isolate);
86V8_EXPORT_PRIVATE void BreakRightNow(Isolate* isolate);
87
88bool AllFramesOnStackAreBlackboxed(Isolate* isolate);
89
90class Script;
91
92struct 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 */
116class 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.
147class 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
160V8_EXPORT_PRIVATE void GetLoadedScripts(Isolate* isolate,
161 PersistentValueVector<Script>& scripts);
162
163MaybeLocal<UnboundScript> CompileInspectorScript(Isolate* isolate,
164 Local<String> source);
165
166enum ExceptionType { kException, kPromiseRejection };
167
168class 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
189V8_EXPORT_PRIVATE void SetDebugDelegate(Isolate* isolate,
190 DebugDelegate* listener);
191
192class AsyncEventDelegate {
193 public:
194 virtual ~AsyncEventDelegate() = default;
195 virtual void AsyncEventOccurred(debug::DebugAsyncActionType type, int id,
196 bool is_blackboxed) = 0;
197};
198
199void SetAsyncEventDelegate(Isolate* isolate, AsyncEventDelegate* delegate);
200
201void ResetBlackboxedStateCache(Isolate* isolate,
202 v8::Local<debug::Script> script);
203
204int EstimatedValueSize(Isolate* isolate, v8::Local<v8::Value> value);
205
206enum Builtin { kStringToLowerCase };
207
208Local<Function> GetBuiltin(Isolate* isolate, Builtin builtin);
209
210V8_EXPORT_PRIVATE void SetConsoleDelegate(Isolate* isolate,
211 ConsoleDelegate* delegate);
212
213int GetStackFrameId(v8::Local<v8::StackFrame> frame);
214
215v8::Local<v8::StackTrace> GetDetailedStackTrace(Isolate* isolate,
216 v8::Local<v8::Object> error);
217
218/**
219 * Native wrapper around v8::internal::JSGeneratorObject object.
220 */
221class 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 */
234class 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 */
319class 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
374class 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
413class 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
440class QueryObjectPredicate {
441 public:
442 virtual ~QueryObjectPredicate() = default;
443 virtual bool Filter(v8::Local<v8::Object> object) = 0;
444};
445
446void QueryObjects(v8::Local<v8::Context> context,
447 QueryObjectPredicate* predicate,
448 v8::PersistentValueVector<v8::Object>* objects);
449
450void GlobalLexicalScopeNames(v8::Local<v8::Context> context,
451 v8::PersistentValueVector<v8::String>* names);
452
453void SetReturnValue(v8::Isolate* isolate, v8::Local<v8::Value> value);
454
455enum class NativeAccessorType {
456 None = 0,
457 HasGetter = 1 << 0,
458 HasSetter = 1 << 1
459};
460
461int64_t GetNextRandomInt64(v8::Isolate* isolate);
462
463V8_EXPORT_PRIVATE v8::MaybeLocal<v8::Value> EvaluateGlobal(
464 v8::Isolate* isolate, v8::Local<v8::String> source,
465 bool throw_on_side_effect);
466
467int GetDebuggingId(v8::Local<v8::Function> function);
468
469bool SetFunctionBreakpoint(v8::Local<v8::Function> function,
470 v8::Local<v8::String> condition, BreakpointId* id);
471
472v8::Platform* GetCurrentPlatform();
473
474class PostponeInterruptsScope {
475 public:
476 explicit PostponeInterruptsScope(v8::Isolate* isolate);
477 ~PostponeInterruptsScope();
478
479 private:
480 std::unique_ptr<i::PostponeInterruptsScope> scope_;
481};
482
483class 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
498struct 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
510class 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