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-debug.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 Script;
25 : class TypeProfile;
26 : } // namespace internal
27 :
28 : namespace debug {
29 :
30 : void SetContextId(Local<Context> context, int id);
31 : int GetContextId(Local<Context> context);
32 :
33 : /**
34 : * Debugger is running in its own context which is entered while debugger
35 : * messages are being dispatched. This is an explicit getter for this
36 : * debugger context. Note that the content of the debugger context is subject
37 : * to change. The Context exists only when the debugger is active, i.e. at
38 : * least one DebugEventListener or MessageHandler is set.
39 : */
40 : Local<Context> GetDebugContext(Isolate* isolate);
41 :
42 : /**
43 : * Run a JavaScript function in the debugger.
44 : * \param fun the function to call
45 : * \param data passed as second argument to the function
46 : * With this call the debugger is entered and the function specified is called
47 : * with the execution state as the first argument. This makes it possible to
48 : * get access to information otherwise not available during normal JavaScript
49 : * execution e.g. details on stack frames. Receiver of the function call will
50 : * be the debugger context global object, however this is a subject to change.
51 : * The following example shows a JavaScript function which when passed to
52 : * v8::Debug::Call will return the current line of JavaScript execution.
53 : *
54 : * \code
55 : * function frame_source_line(exec_state) {
56 : * return exec_state.frame(0).sourceLine();
57 : * }
58 : * \endcode
59 : */
60 : // TODO(dcarney): data arg should be a MaybeLocal
61 : MaybeLocal<Value> Call(Local<Context> context, v8::Local<v8::Function> fun,
62 : Local<Value> data = Local<Value>());
63 :
64 : /**
65 : * Enable/disable LiveEdit functionality for the given Isolate
66 : * (default Isolate if not provided). V8 will abort if LiveEdit is
67 : * unexpectedly used. LiveEdit is enabled by default.
68 : */
69 : V8_EXPORT_PRIVATE void SetLiveEditEnabled(Isolate* isolate, bool enable);
70 :
71 : // Schedule a debugger break to happen when JavaScript code is run
72 : // in the given isolate.
73 : void DebugBreak(Isolate* isolate);
74 :
75 : // Remove scheduled debugger break in given isolate if it has not
76 : // happened yet.
77 : void CancelDebugBreak(Isolate* isolate);
78 :
79 : /**
80 : * Returns array of internal properties specific to the value type. Result has
81 : * the following format: [<name>, <value>,...,<name>, <value>]. Result array
82 : * will be allocated in the current context.
83 : */
84 : MaybeLocal<Array> GetInternalProperties(Isolate* isolate, Local<Value> value);
85 :
86 : enum ExceptionBreakState {
87 : NoBreakOnException = 0,
88 : BreakOnUncaughtException = 1,
89 : BreakOnAnyException = 2
90 : };
91 :
92 : /**
93 : * Defines if VM will pause on exceptions or not.
94 : * If BreakOnAnyExceptions is set then VM will pause on caught and uncaught
95 : * exception, if BreakOnUncaughtException is set then VM will pause only on
96 : * uncaught exception, otherwise VM won't stop on any exception.
97 : */
98 : void ChangeBreakOnException(Isolate* isolate, ExceptionBreakState state);
99 :
100 : void RemoveBreakpoint(Isolate* isolate, BreakpointId id);
101 : void SetBreakPointsActive(Isolate* isolate, bool is_active);
102 :
103 : enum StepAction {
104 : StepOut = 0, // Step out of the current function.
105 : StepNext = 1, // Step to the next statement in the current function.
106 : StepIn = 2 // Step into new functions invoked or the next statement
107 : // in the current function.
108 : };
109 :
110 : void PrepareStep(Isolate* isolate, StepAction action);
111 : void ClearStepping(Isolate* isolate);
112 : void BreakRightNow(Isolate* isolate);
113 :
114 : bool AllFramesOnStackAreBlackboxed(Isolate* isolate);
115 :
116 : /**
117 : * Out-of-memory callback function.
118 : * The function is invoked when the heap size is close to the hard limit.
119 : *
120 : * \param data the parameter provided during callback installation.
121 : */
122 : typedef void (*OutOfMemoryCallback)(void* data);
123 : void SetOutOfMemoryCallback(Isolate* isolate, OutOfMemoryCallback callback,
124 : void* data);
125 :
126 : /**
127 : * Native wrapper around v8::internal::Script object.
128 : */
129 : class V8_EXPORT_PRIVATE Script {
130 : public:
131 : v8::Isolate* GetIsolate() const;
132 :
133 : ScriptOriginOptions OriginOptions() const;
134 : bool WasCompiled() const;
135 : bool IsEmbedded() const;
136 : int Id() const;
137 : int LineOffset() const;
138 : int ColumnOffset() const;
139 : std::vector<int> LineEnds() const;
140 : MaybeLocal<String> Name() const;
141 : MaybeLocal<String> SourceURL() const;
142 : MaybeLocal<String> SourceMappingURL() const;
143 : Maybe<int> ContextId() const;
144 : MaybeLocal<String> Source() const;
145 : bool IsWasm() const;
146 : bool IsModule() const;
147 : bool GetPossibleBreakpoints(
148 : const debug::Location& start, const debug::Location& end,
149 : bool restrict_to_function,
150 : std::vector<debug::BreakLocation>* locations) const;
151 : int GetSourceOffset(const debug::Location& location) const;
152 : v8::debug::Location GetSourceLocation(int offset) const;
153 : bool SetScriptSource(v8::Local<v8::String> newSource, bool preview,
154 : bool* stack_changed) const;
155 : bool SetBreakpoint(v8::Local<v8::String> condition, debug::Location* location,
156 : BreakpointId* id) const;
157 : };
158 :
159 : // Specialization for wasm Scripts.
160 : class WasmScript : public Script {
161 : public:
162 : static WasmScript* Cast(Script* script);
163 :
164 : int NumFunctions() const;
165 : int NumImportedFunctions() const;
166 :
167 : std::pair<int, int> GetFunctionRange(int function_index) const;
168 :
169 : debug::WasmDisassembly DisassembleFunction(int function_index) const;
170 : };
171 :
172 : void GetLoadedScripts(Isolate* isolate, PersistentValueVector<Script>& scripts);
173 :
174 : MaybeLocal<UnboundScript> CompileInspectorScript(Isolate* isolate,
175 : Local<String> source);
176 :
177 3890 : class DebugDelegate {
178 : public:
179 3869924 : virtual ~DebugDelegate() {}
180 0 : virtual void PromiseEventOccurred(debug::PromiseDebugActionType type, int id,
181 0 : int parent_id, bool created_by_user) {}
182 11 : virtual void ScriptCompiled(v8::Local<Script> script, bool is_live_edited,
183 11 : bool has_compile_error) {}
184 : // |break_points_hit| contains installed by JS debug API breakpoint objects.
185 : // |inspector_break_points_hit| contains id of breakpoints installed with
186 : // debug::Script::SetBreakpoint API.
187 0 : virtual void BreakProgramRequested(
188 : v8::Local<v8::Context> paused_context, v8::Local<v8::Object> exec_state,
189 : v8::Local<v8::Value> break_points_hit,
190 0 : const std::vector<debug::BreakpointId>& inspector_break_points_hit) {}
191 0 : virtual void ExceptionThrown(v8::Local<v8::Context> paused_context,
192 : v8::Local<v8::Object> exec_state,
193 : v8::Local<v8::Value> exception,
194 : v8::Local<v8::Value> promise, bool is_uncaught) {
195 0 : }
196 6 : virtual bool IsFunctionBlackboxed(v8::Local<debug::Script> script,
197 : const debug::Location& start,
198 : const debug::Location& end) {
199 6 : return false;
200 : }
201 : };
202 :
203 : void SetDebugDelegate(Isolate* isolate, DebugDelegate* listener);
204 :
205 : void ResetBlackboxedStateCache(Isolate* isolate,
206 : v8::Local<debug::Script> script);
207 :
208 : int EstimatedValueSize(Isolate* isolate, v8::Local<v8::Value> value);
209 :
210 : v8::MaybeLocal<v8::Array> EntriesPreview(Isolate* isolate,
211 : v8::Local<v8::Value> value,
212 : bool* is_key_value);
213 :
214 : enum Builtin {
215 : kObjectKeys,
216 : kObjectGetPrototypeOf,
217 : kObjectGetOwnPropertyDescriptor,
218 : kObjectGetOwnPropertyNames,
219 : kObjectGetOwnPropertySymbols,
220 : };
221 :
222 : Local<Function> GetBuiltin(Isolate* isolate, Builtin builtin);
223 :
224 : V8_EXPORT_PRIVATE void SetConsoleDelegate(Isolate* isolate,
225 : ConsoleDelegate* delegate);
226 :
227 : int GetStackFrameId(v8::Local<v8::StackFrame> frame);
228 :
229 : v8::Local<v8::StackTrace> GetDetailedStackTrace(Isolate* isolate,
230 : v8::Local<v8::Object> error);
231 :
232 : /**
233 : * Native wrapper around v8::internal::JSGeneratorObject object.
234 : */
235 : class GeneratorObject {
236 : public:
237 : v8::MaybeLocal<debug::Script> Script();
238 : v8::Local<v8::Function> Function();
239 : debug::Location SuspendedLocation();
240 : bool IsSuspended();
241 :
242 : static v8::Local<debug::GeneratorObject> Cast(v8::Local<v8::Value> value);
243 : };
244 :
245 : /*
246 : * Provide API layer between inspector and code coverage.
247 : */
248 : class V8_EXPORT_PRIVATE Coverage {
249 : public:
250 : MOVE_ONLY_NO_DEFAULT_CONSTRUCTOR(Coverage);
251 :
252 : enum Mode {
253 : // Make use of existing information in feedback vectors on the heap.
254 : // Only return a yes/no result. Optimization and GC are not affected.
255 : // Collecting best effort coverage does not reset counters.
256 : kBestEffort,
257 : // Disable optimization and prevent feedback vectors from being garbage
258 : // collected in order to preserve precise invocation counts. Collecting
259 : // precise count coverage resets counters to get incremental updates.
260 : kPreciseCount,
261 : // We are only interested in a yes/no result for the function. Optimization
262 : // and GC can be allowed once a function has been invoked. Collecting
263 : // precise binary coverage resets counters for incremental updates.
264 : kPreciseBinary,
265 : // Similar to the precise coverage modes but provides coverage at a
266 : // lower granularity. Design doc: goo.gl/lA2swZ.
267 : kBlockCount,
268 : kBlockBinary,
269 : };
270 :
271 : // Forward declarations.
272 : class ScriptData;
273 : class FunctionData;
274 :
275 : class V8_EXPORT_PRIVATE BlockData {
276 : public:
277 : MOVE_ONLY_NO_DEFAULT_CONSTRUCTOR(BlockData);
278 :
279 : int StartOffset() const;
280 : int EndOffset() const;
281 : uint32_t Count() const;
282 :
283 : private:
284 : explicit BlockData(i::CoverageBlock* block,
285 : std::shared_ptr<i::Coverage> coverage)
286 110 : : block_(block), coverage_(std::move(coverage)) {}
287 :
288 : i::CoverageBlock* block_;
289 : std::shared_ptr<i::Coverage> coverage_;
290 :
291 : friend class v8::debug::Coverage::FunctionData;
292 : };
293 :
294 20 : class V8_EXPORT_PRIVATE FunctionData {
295 : public:
296 : MOVE_ONLY_NO_DEFAULT_CONSTRUCTOR(FunctionData);
297 :
298 : int StartOffset() const;
299 : int EndOffset() const;
300 : uint32_t Count() const;
301 : MaybeLocal<String> Name() const;
302 : size_t BlockCount() const;
303 : bool HasBlockCoverage() const;
304 : BlockData GetBlockData(size_t i) const;
305 :
306 : private:
307 : explicit FunctionData(i::CoverageFunction* function,
308 : std::shared_ptr<i::Coverage> coverage)
309 500 : : function_(function), coverage_(std::move(coverage)) {}
310 :
311 : i::CoverageFunction* function_;
312 : std::shared_ptr<i::Coverage> coverage_;
313 :
314 : friend class v8::debug::Coverage::ScriptData;
315 : };
316 :
317 : class V8_EXPORT_PRIVATE ScriptData {
318 : public:
319 : MOVE_ONLY_NO_DEFAULT_CONSTRUCTOR(ScriptData);
320 :
321 : Local<debug::Script> GetScript() const;
322 : size_t FunctionCount() const;
323 : FunctionData GetFunctionData(size_t i) const;
324 :
325 : private:
326 : explicit ScriptData(size_t index, std::shared_ptr<i::Coverage> c);
327 :
328 : i::CoverageScript* script_;
329 : std::shared_ptr<i::Coverage> coverage_;
330 :
331 : friend class v8::debug::Coverage;
332 : };
333 :
334 : static Coverage CollectPrecise(Isolate* isolate);
335 : static Coverage CollectBestEffort(Isolate* isolate);
336 :
337 : static void SelectMode(Isolate* isolate, Mode mode);
338 :
339 : size_t ScriptCount() const;
340 : ScriptData GetScriptData(size_t i) const;
341 : bool IsEmpty() const { return coverage_ == nullptr; }
342 :
343 : private:
344 : explicit Coverage(std::shared_ptr<i::Coverage> coverage)
345 : : coverage_(std::move(coverage)) {}
346 : std::shared_ptr<i::Coverage> coverage_;
347 : };
348 :
349 : /*
350 : * Provide API layer between inspector and type profile.
351 : */
352 : class V8_EXPORT_PRIVATE TypeProfile {
353 : public:
354 : MOVE_ONLY_NO_DEFAULT_CONSTRUCTOR(TypeProfile);
355 :
356 : enum Mode {
357 : kNone,
358 : kCollect,
359 : };
360 : class ScriptData; // Forward declaration.
361 :
362 : class V8_EXPORT_PRIVATE Entry {
363 : public:
364 385 : MOVE_ONLY_NO_DEFAULT_CONSTRUCTOR(Entry);
365 :
366 : int SourcePosition() const;
367 : std::vector<MaybeLocal<String>> Types() const;
368 :
369 : private:
370 : explicit Entry(const i::TypeProfileEntry* entry,
371 : std::shared_ptr<i::TypeProfile> type_profile)
372 185 : : entry_(entry), type_profile_(std::move(type_profile)) {}
373 :
374 : const i::TypeProfileEntry* entry_;
375 : std::shared_ptr<i::TypeProfile> type_profile_;
376 :
377 : friend class v8::debug::TypeProfile::ScriptData;
378 : };
379 :
380 : class V8_EXPORT_PRIVATE ScriptData {
381 : public:
382 : MOVE_ONLY_NO_DEFAULT_CONSTRUCTOR(ScriptData);
383 :
384 : Local<debug::Script> GetScript() const;
385 : std::vector<Entry> Entries() const;
386 :
387 : private:
388 : explicit ScriptData(size_t index,
389 : std::shared_ptr<i::TypeProfile> type_profile);
390 :
391 : i::TypeProfileScript* script_;
392 : std::shared_ptr<i::TypeProfile> type_profile_;
393 :
394 : friend class v8::debug::TypeProfile;
395 : };
396 :
397 : static TypeProfile Collect(Isolate* isolate);
398 :
399 : static void SelectMode(Isolate* isolate, Mode mode);
400 :
401 : size_t ScriptCount() const;
402 : ScriptData GetScriptData(size_t i) const;
403 :
404 : private:
405 : explicit TypeProfile(std::shared_ptr<i::TypeProfile> type_profile)
406 : : type_profile_(std::move(type_profile)) {}
407 :
408 : std::shared_ptr<i::TypeProfile> type_profile_;
409 : };
410 :
411 : class ScopeIterator {
412 : public:
413 : static std::unique_ptr<ScopeIterator> CreateForFunction(
414 : v8::Isolate* isolate, v8::Local<v8::Function> func);
415 : static std::unique_ptr<ScopeIterator> CreateForGeneratorObject(
416 : v8::Isolate* isolate, v8::Local<v8::Object> generator);
417 :
418 125447 : ScopeIterator() = default;
419 125447 : virtual ~ScopeIterator() = default;
420 :
421 : enum ScopeType {
422 : ScopeTypeGlobal = 0,
423 : ScopeTypeLocal,
424 : ScopeTypeWith,
425 : ScopeTypeClosure,
426 : ScopeTypeCatch,
427 : ScopeTypeBlock,
428 : ScopeTypeScript,
429 : ScopeTypeEval,
430 : ScopeTypeModule
431 : };
432 :
433 : virtual bool Done() = 0;
434 : virtual void Advance() = 0;
435 : virtual ScopeType GetType() = 0;
436 : virtual v8::Local<v8::Object> GetObject() = 0;
437 : virtual v8::Local<v8::Function> GetFunction() = 0;
438 : virtual debug::Location GetStartLocation() = 0;
439 : virtual debug::Location GetEndLocation() = 0;
440 :
441 : virtual bool SetVariableValue(v8::Local<v8::String> name,
442 : v8::Local<v8::Value> value) = 0;
443 :
444 : private:
445 : DISALLOW_COPY_AND_ASSIGN(ScopeIterator);
446 : };
447 :
448 : class StackTraceIterator {
449 : public:
450 : static std::unique_ptr<StackTraceIterator> Create(Isolate* isolate,
451 : int index = 0);
452 59807 : StackTraceIterator() = default;
453 59807 : virtual ~StackTraceIterator() = default;
454 :
455 : virtual bool Done() const = 0;
456 : virtual void Advance() = 0;
457 :
458 : virtual int GetContextId() const = 0;
459 : virtual v8::Local<v8::Value> GetReceiver() const = 0;
460 : virtual v8::Local<v8::Value> GetReturnValue() const = 0;
461 : virtual v8::Local<v8::String> GetFunctionName() const = 0;
462 : virtual v8::Local<v8::debug::Script> GetScript() const = 0;
463 : virtual debug::Location GetSourceLocation() const = 0;
464 : virtual v8::Local<v8::Function> GetFunction() const = 0;
465 : virtual std::unique_ptr<ScopeIterator> GetScopeIterator() const = 0;
466 :
467 : virtual bool Restart() = 0;
468 : virtual v8::MaybeLocal<v8::Value> Evaluate(v8::Local<v8::String> source,
469 : bool throw_on_side_effect) = 0;
470 :
471 : private:
472 : DISALLOW_COPY_AND_ASSIGN(StackTraceIterator);
473 : };
474 :
475 65 : class QueryObjectPredicate {
476 : public:
477 65 : virtual ~QueryObjectPredicate() = default;
478 : virtual bool Filter(v8::Local<v8::Object> object) = 0;
479 : };
480 :
481 : void QueryObjects(v8::Local<v8::Context> context,
482 : QueryObjectPredicate* predicate,
483 : v8::PersistentValueVector<v8::Object>* objects);
484 :
485 : void GlobalLexicalScopeNames(v8::Local<v8::Context> context,
486 : v8::PersistentValueVector<v8::String>* names);
487 :
488 : } // namespace debug
489 : } // namespace v8
490 :
491 : #endif // V8_DEBUG_DEBUG_INTERFACE_H_
|