Line data Source code
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 1522 : 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 : enum ExceptionType { kException, kPromiseRejection };
158 :
159 3700 : class DebugDelegate {
160 : public:
161 4713410 : virtual ~DebugDelegate() = default;
162 3239 : virtual void ScriptCompiled(v8::Local<Script> script, bool is_live_edited,
163 3239 : bool has_compile_error) {}
164 : // |inspector_break_points_hit| contains id of breakpoints installed with
165 : // debug::Script::SetBreakpoint API.
166 10 : virtual void BreakProgramRequested(
167 : v8::Local<v8::Context> paused_context,
168 10 : const std::vector<debug::BreakpointId>& inspector_break_points_hit) {}
169 10 : virtual void ExceptionThrown(v8::Local<v8::Context> paused_context,
170 : v8::Local<v8::Value> exception,
171 : v8::Local<v8::Value> promise, bool is_uncaught,
172 10 : ExceptionType exception_type) {}
173 1284 : virtual bool IsFunctionBlackboxed(v8::Local<debug::Script> script,
174 : const debug::Location& start,
175 : const debug::Location& end) {
176 1284 : return false;
177 : }
178 : };
179 :
180 : void SetDebugDelegate(Isolate* isolate, DebugDelegate* listener);
181 :
182 3638 : class AsyncEventDelegate {
183 : public:
184 3638 : virtual ~AsyncEventDelegate() = default;
185 : virtual void AsyncEventOccurred(debug::DebugAsyncActionType type, int id,
186 : bool is_blackboxed) = 0;
187 : };
188 :
189 : void SetAsyncEventDelegate(Isolate* isolate, AsyncEventDelegate* delegate);
190 :
191 : void ResetBlackboxedStateCache(Isolate* isolate,
192 : v8::Local<debug::Script> script);
193 :
194 : int EstimatedValueSize(Isolate* isolate, v8::Local<v8::Value> value);
195 :
196 : enum Builtin { kStringToLowerCase };
197 :
198 : Local<Function> GetBuiltin(Isolate* isolate, Builtin builtin);
199 :
200 : V8_EXPORT_PRIVATE void SetConsoleDelegate(Isolate* isolate,
201 : ConsoleDelegate* delegate);
202 :
203 : int GetStackFrameId(v8::Local<v8::StackFrame> frame);
204 :
205 : v8::Local<v8::StackTrace> GetDetailedStackTrace(Isolate* isolate,
206 : v8::Local<v8::Object> error);
207 :
208 : /**
209 : * Native wrapper around v8::internal::JSGeneratorObject object.
210 : */
211 : class GeneratorObject {
212 : public:
213 : v8::MaybeLocal<debug::Script> Script();
214 : v8::Local<v8::Function> Function();
215 : debug::Location SuspendedLocation();
216 : bool IsSuspended();
217 :
218 : static v8::Local<debug::GeneratorObject> Cast(v8::Local<v8::Value> value);
219 : };
220 :
221 : /*
222 : * Provide API layer between inspector and code coverage.
223 : */
224 : class V8_EXPORT_PRIVATE Coverage {
225 : public:
226 : MOVE_ONLY_NO_DEFAULT_CONSTRUCTOR(Coverage);
227 :
228 : enum Mode {
229 : // Make use of existing information in feedback vectors on the heap.
230 : // Only return a yes/no result. Optimization and GC are not affected.
231 : // Collecting best effort coverage does not reset counters.
232 : kBestEffort,
233 : // Disable optimization and prevent feedback vectors from being garbage
234 : // collected in order to preserve precise invocation counts. Collecting
235 : // precise count coverage resets counters to get incremental updates.
236 : kPreciseCount,
237 : // We are only interested in a yes/no result for the function. Optimization
238 : // and GC can be allowed once a function has been invoked. Collecting
239 : // precise binary coverage resets counters for incremental updates.
240 : kPreciseBinary,
241 : // Similar to the precise coverage modes but provides coverage at a
242 : // lower granularity. Design doc: goo.gl/lA2swZ.
243 : kBlockCount,
244 : kBlockBinary,
245 : };
246 :
247 : // Forward declarations.
248 : class ScriptData;
249 : class FunctionData;
250 :
251 : class V8_EXPORT_PRIVATE BlockData {
252 : public:
253 : MOVE_ONLY_NO_DEFAULT_CONSTRUCTOR(BlockData);
254 :
255 : int StartOffset() const;
256 : int EndOffset() const;
257 : uint32_t Count() const;
258 :
259 : private:
260 : explicit BlockData(i::CoverageBlock* block,
261 : std::shared_ptr<i::Coverage> coverage)
262 32 : : block_(block), coverage_(std::move(coverage)) {}
263 :
264 : i::CoverageBlock* block_;
265 : std::shared_ptr<i::Coverage> coverage_;
266 :
267 : friend class v8::debug::Coverage::FunctionData;
268 : };
269 :
270 20 : class V8_EXPORT_PRIVATE FunctionData {
271 : public:
272 : MOVE_ONLY_NO_DEFAULT_CONSTRUCTOR(FunctionData);
273 :
274 : int StartOffset() const;
275 : int EndOffset() const;
276 : uint32_t Count() const;
277 : MaybeLocal<String> Name() const;
278 : size_t BlockCount() const;
279 : bool HasBlockCoverage() const;
280 : BlockData GetBlockData(size_t i) const;
281 :
282 : private:
283 : explicit FunctionData(i::CoverageFunction* function,
284 : std::shared_ptr<i::Coverage> coverage)
285 405 : : function_(function), coverage_(std::move(coverage)) {}
286 :
287 : i::CoverageFunction* function_;
288 : std::shared_ptr<i::Coverage> coverage_;
289 :
290 : friend class v8::debug::Coverage::ScriptData;
291 : };
292 :
293 : class V8_EXPORT_PRIVATE ScriptData {
294 : public:
295 : MOVE_ONLY_NO_DEFAULT_CONSTRUCTOR(ScriptData);
296 :
297 : Local<debug::Script> GetScript() const;
298 : size_t FunctionCount() const;
299 : FunctionData GetFunctionData(size_t i) const;
300 :
301 : private:
302 : explicit ScriptData(size_t index, std::shared_ptr<i::Coverage> c);
303 :
304 : i::CoverageScript* script_;
305 : std::shared_ptr<i::Coverage> coverage_;
306 :
307 : friend class v8::debug::Coverage;
308 : };
309 :
310 : static Coverage CollectPrecise(Isolate* isolate);
311 : static Coverage CollectBestEffort(Isolate* isolate);
312 :
313 : static void SelectMode(Isolate* isolate, Mode mode);
314 :
315 : size_t ScriptCount() const;
316 : ScriptData GetScriptData(size_t i) const;
317 : bool IsEmpty() const { return coverage_ == nullptr; }
318 :
319 : private:
320 : explicit Coverage(std::shared_ptr<i::Coverage> coverage)
321 : : coverage_(std::move(coverage)) {}
322 : std::shared_ptr<i::Coverage> coverage_;
323 : };
324 :
325 : /*
326 : * Provide API layer between inspector and type profile.
327 : */
328 : class V8_EXPORT_PRIVATE TypeProfile {
329 : public:
330 : MOVE_ONLY_NO_DEFAULT_CONSTRUCTOR(TypeProfile);
331 :
332 : enum Mode {
333 : kNone,
334 : kCollect,
335 : };
336 : class ScriptData; // Forward declaration.
337 :
338 : class V8_EXPORT_PRIVATE Entry {
339 : public:
340 308 : MOVE_ONLY_NO_DEFAULT_CONSTRUCTOR(Entry);
341 :
342 : int SourcePosition() const;
343 : std::vector<MaybeLocal<String>> Types() const;
344 :
345 : private:
346 : explicit Entry(const i::TypeProfileEntry* entry,
347 : std::shared_ptr<i::TypeProfile> type_profile)
348 148 : : entry_(entry), type_profile_(std::move(type_profile)) {}
349 :
350 : const i::TypeProfileEntry* entry_;
351 : std::shared_ptr<i::TypeProfile> type_profile_;
352 :
353 : friend class v8::debug::TypeProfile::ScriptData;
354 : };
355 :
356 : class V8_EXPORT_PRIVATE ScriptData {
357 : public:
358 : MOVE_ONLY_NO_DEFAULT_CONSTRUCTOR(ScriptData);
359 :
360 : Local<debug::Script> GetScript() const;
361 : std::vector<Entry> Entries() const;
362 :
363 : private:
364 : explicit ScriptData(size_t index,
365 : std::shared_ptr<i::TypeProfile> type_profile);
366 :
367 : i::TypeProfileScript* script_;
368 : std::shared_ptr<i::TypeProfile> type_profile_;
369 :
370 : friend class v8::debug::TypeProfile;
371 : };
372 :
373 : static TypeProfile Collect(Isolate* isolate);
374 :
375 : static void SelectMode(Isolate* isolate, Mode mode);
376 :
377 : size_t ScriptCount() const;
378 : ScriptData GetScriptData(size_t i) const;
379 :
380 : private:
381 : explicit TypeProfile(std::shared_ptr<i::TypeProfile> type_profile)
382 : : type_profile_(std::move(type_profile)) {}
383 :
384 : std::shared_ptr<i::TypeProfile> type_profile_;
385 : };
386 :
387 : class ScopeIterator {
388 : public:
389 : static std::unique_ptr<ScopeIterator> CreateForFunction(
390 : v8::Isolate* isolate, v8::Local<v8::Function> func);
391 : static std::unique_ptr<ScopeIterator> CreateForGeneratorObject(
392 : v8::Isolate* isolate, v8::Local<v8::Object> generator);
393 :
394 146917 : ScopeIterator() = default;
395 146917 : virtual ~ScopeIterator() = default;
396 :
397 : enum ScopeType {
398 : ScopeTypeGlobal = 0,
399 : ScopeTypeLocal,
400 : ScopeTypeWith,
401 : ScopeTypeClosure,
402 : ScopeTypeCatch,
403 : ScopeTypeBlock,
404 : ScopeTypeScript,
405 : ScopeTypeEval,
406 : ScopeTypeModule
407 : };
408 :
409 : virtual bool Done() = 0;
410 : virtual void Advance() = 0;
411 : virtual ScopeType GetType() = 0;
412 : virtual v8::Local<v8::Object> GetObject() = 0;
413 : virtual v8::Local<v8::Value> GetFunctionDebugName() = 0;
414 : virtual int GetScriptId() = 0;
415 : virtual bool HasLocationInfo() = 0;
416 : virtual debug::Location GetStartLocation() = 0;
417 : virtual debug::Location GetEndLocation() = 0;
418 :
419 : virtual bool SetVariableValue(v8::Local<v8::String> name,
420 : v8::Local<v8::Value> value) = 0;
421 :
422 : private:
423 : DISALLOW_COPY_AND_ASSIGN(ScopeIterator);
424 : };
425 :
426 : class StackTraceIterator {
427 : public:
428 : static std::unique_ptr<StackTraceIterator> Create(Isolate* isolate,
429 : int index = 0);
430 111405 : StackTraceIterator() = default;
431 111405 : virtual ~StackTraceIterator() = default;
432 :
433 : virtual bool Done() const = 0;
434 : virtual void Advance() = 0;
435 :
436 : virtual int GetContextId() const = 0;
437 : virtual v8::MaybeLocal<v8::Value> GetReceiver() const = 0;
438 : virtual v8::Local<v8::Value> GetReturnValue() const = 0;
439 : virtual v8::Local<v8::String> GetFunctionDebugName() const = 0;
440 : virtual v8::Local<v8::debug::Script> GetScript() const = 0;
441 : virtual debug::Location GetSourceLocation() const = 0;
442 : virtual v8::Local<v8::Function> GetFunction() const = 0;
443 : virtual std::unique_ptr<ScopeIterator> GetScopeIterator() const = 0;
444 :
445 : virtual bool Restart() = 0;
446 : virtual v8::MaybeLocal<v8::Value> Evaluate(v8::Local<v8::String> source,
447 : bool throw_on_side_effect) = 0;
448 :
449 : private:
450 : DISALLOW_COPY_AND_ASSIGN(StackTraceIterator);
451 : };
452 :
453 85 : class QueryObjectPredicate {
454 : public:
455 85 : virtual ~QueryObjectPredicate() = default;
456 : virtual bool Filter(v8::Local<v8::Object> object) = 0;
457 : };
458 :
459 : void QueryObjects(v8::Local<v8::Context> context,
460 : QueryObjectPredicate* predicate,
461 : v8::PersistentValueVector<v8::Object>* objects);
462 :
463 : void GlobalLexicalScopeNames(v8::Local<v8::Context> context,
464 : v8::PersistentValueVector<v8::String>* names);
465 :
466 : void SetReturnValue(v8::Isolate* isolate, v8::Local<v8::Value> value);
467 :
468 : enum class NativeAccessorType {
469 : None = 0,
470 : HasGetter = 1 << 0,
471 : HasSetter = 1 << 1
472 : };
473 :
474 : int64_t GetNextRandomInt64(v8::Isolate* isolate);
475 :
476 : v8::MaybeLocal<v8::Value> EvaluateGlobal(v8::Isolate* isolate,
477 : v8::Local<v8::String> source,
478 : bool throw_on_side_effect);
479 :
480 : int GetDebuggingId(v8::Local<v8::Function> function);
481 :
482 : bool SetFunctionBreakpoint(v8::Local<v8::Function> function,
483 : v8::Local<v8::String> condition, BreakpointId* id);
484 :
485 : v8::Platform* GetCurrentPlatform();
486 :
487 0 : class PostponeInterruptsScope {
488 : public:
489 : explicit PostponeInterruptsScope(v8::Isolate* isolate);
490 : ~PostponeInterruptsScope();
491 :
492 : private:
493 : std::unique_ptr<i::PostponeInterruptsScope> scope_;
494 : };
495 :
496 : class WeakMap : public v8::Object {
497 : public:
498 : V8_WARN_UNUSED_RESULT v8::MaybeLocal<v8::Value> Get(
499 : v8::Local<v8::Context> context, v8::Local<v8::Value> key);
500 : V8_WARN_UNUSED_RESULT v8::MaybeLocal<WeakMap> Set(
501 : v8::Local<v8::Context> context, v8::Local<v8::Value> key,
502 : v8::Local<v8::Value> value);
503 :
504 : static Local<WeakMap> New(v8::Isolate* isolate);
505 : V8_INLINE static WeakMap* Cast(Value* obj);
506 :
507 : private:
508 : WeakMap();
509 : };
510 :
511 : struct PropertyDescriptor {
512 : bool enumerable : 1;
513 : bool has_enumerable : 1;
514 : bool configurable : 1;
515 : bool has_configurable : 1;
516 : bool writable : 1;
517 : bool has_writable : 1;
518 : v8::Local<v8::Value> value;
519 : v8::Local<v8::Value> get;
520 : v8::Local<v8::Value> set;
521 : };
522 :
523 79158 : class PropertyIterator {
524 : public:
525 : static std::unique_ptr<PropertyIterator> Create(v8::Local<v8::Object> object);
526 :
527 79158 : virtual ~PropertyIterator() = default;
528 :
529 : virtual bool Done() const = 0;
530 : virtual void Advance() = 0;
531 :
532 : virtual v8::Local<v8::Name> name() const = 0;
533 :
534 : virtual bool is_native_accessor() = 0;
535 : virtual bool has_native_getter() = 0;
536 : virtual bool has_native_setter() = 0;
537 : virtual Maybe<PropertyAttribute> attributes() = 0;
538 : virtual Maybe<PropertyDescriptor> descriptor() = 0;
539 :
540 : virtual bool is_own() = 0;
541 : virtual bool is_array_index() = 0;
542 : };
543 : } // namespace debug
544 : } // namespace v8
545 :
546 : #endif // V8_DEBUG_DEBUG_INTERFACE_H_
|