// Copyright 2016 the V8 project authors. All rights reserved.
|
// Use of this source code is governed by a BSD-style license that can be
|
// found in the LICENSE file.
|
|
#ifndef V8_DEBUG_DEBUG_INTERFACE_H_
|
#define V8_DEBUG_DEBUG_INTERFACE_H_
|
|
#include "include/v8-inspector.h"
|
#include "include/v8-util.h"
|
#include "include/v8.h"
|
|
#include "src/debug/interface-types.h"
|
#include "src/globals.h"
|
|
namespace v8 {
|
|
namespace internal {
|
struct CoverageBlock;
|
struct CoverageFunction;
|
struct CoverageScript;
|
struct TypeProfileEntry;
|
struct TypeProfileScript;
|
class Coverage;
|
class PostponeInterruptsScope;
|
class Script;
|
class TypeProfile;
|
} // namespace internal
|
|
namespace debug {
|
|
void SetContextId(Local<Context> context, int id);
|
int GetContextId(Local<Context> context);
|
|
void SetInspector(Isolate* isolate, v8_inspector::V8Inspector*);
|
v8_inspector::V8Inspector* GetInspector(Isolate* isolate);
|
|
// Schedule a debugger break to happen when function is called inside given
|
// isolate.
|
void SetBreakOnNextFunctionCall(Isolate* isolate);
|
|
// Remove scheduled debugger break in given isolate if it has not
|
// happened yet.
|
void ClearBreakOnNextFunctionCall(Isolate* isolate);
|
|
/**
|
* Returns array of internal properties specific to the value type. Result has
|
* the following format: [<name>, <value>,...,<name>, <value>]. Result array
|
* will be allocated in the current context.
|
*/
|
MaybeLocal<Array> GetInternalProperties(Isolate* isolate, Local<Value> value);
|
|
enum ExceptionBreakState {
|
NoBreakOnException = 0,
|
BreakOnUncaughtException = 1,
|
BreakOnAnyException = 2
|
};
|
|
/**
|
* Defines if VM will pause on exceptions or not.
|
* If BreakOnAnyExceptions is set then VM will pause on caught and uncaught
|
* exception, if BreakOnUncaughtException is set then VM will pause only on
|
* uncaught exception, otherwise VM won't stop on any exception.
|
*/
|
void ChangeBreakOnException(Isolate* isolate, ExceptionBreakState state);
|
|
void RemoveBreakpoint(Isolate* isolate, BreakpointId id);
|
void SetBreakPointsActive(Isolate* isolate, bool is_active);
|
|
enum StepAction {
|
StepOut = 0, // Step out of the current function.
|
StepNext = 1, // Step to the next statement in the current function.
|
StepIn = 2 // Step into new functions invoked or the next statement
|
// in the current function.
|
};
|
|
void PrepareStep(Isolate* isolate, StepAction action);
|
void ClearStepping(Isolate* isolate);
|
void BreakRightNow(Isolate* isolate);
|
|
bool AllFramesOnStackAreBlackboxed(Isolate* isolate);
|
|
class Script;
|
|
struct LiveEditResult {
|
enum Status {
|
OK,
|
COMPILE_ERROR,
|
BLOCKED_BY_RUNNING_GENERATOR,
|
BLOCKED_BY_FUNCTION_ABOVE_BREAK_FRAME,
|
BLOCKED_BY_FUNCTION_BELOW_NON_DROPPABLE_FRAME,
|
BLOCKED_BY_ACTIVE_FUNCTION,
|
BLOCKED_BY_NEW_TARGET_IN_RESTART_FRAME,
|
FRAME_RESTART_IS_NOT_SUPPORTED
|
};
|
Status status = OK;
|
bool stack_changed = false;
|
// Available only for OK.
|
v8::Local<v8::debug::Script> script;
|
// Fields below are available only for COMPILE_ERROR.
|
v8::Local<v8::String> message;
|
int line_number = -1;
|
int column_number = -1;
|
};
|
|
/**
|
* Native wrapper around v8::internal::Script object.
|
*/
|
class V8_EXPORT_PRIVATE Script {
|
public:
|
v8::Isolate* GetIsolate() const;
|
|
ScriptOriginOptions OriginOptions() const;
|
bool WasCompiled() const;
|
bool IsEmbedded() const;
|
int Id() const;
|
int LineOffset() const;
|
int ColumnOffset() const;
|
std::vector<int> LineEnds() const;
|
MaybeLocal<String> Name() const;
|
MaybeLocal<String> SourceURL() const;
|
MaybeLocal<String> SourceMappingURL() const;
|
Maybe<int> ContextId() const;
|
MaybeLocal<String> Source() const;
|
bool IsWasm() const;
|
bool IsModule() const;
|
bool GetPossibleBreakpoints(
|
const debug::Location& start, const debug::Location& end,
|
bool restrict_to_function,
|
std::vector<debug::BreakLocation>* locations) const;
|
int GetSourceOffset(const debug::Location& location) const;
|
v8::debug::Location GetSourceLocation(int offset) const;
|
bool SetScriptSource(v8::Local<v8::String> newSource, bool preview,
|
LiveEditResult* result) const;
|
bool SetBreakpoint(v8::Local<v8::String> condition, debug::Location* location,
|
BreakpointId* id) const;
|
};
|
|
// Specialization for wasm Scripts.
|
class WasmScript : public Script {
|
public:
|
static WasmScript* Cast(Script* script);
|
|
int NumFunctions() const;
|
int NumImportedFunctions() const;
|
|
std::pair<int, int> GetFunctionRange(int function_index) const;
|
|
debug::WasmDisassembly DisassembleFunction(int function_index) const;
|
uint32_t GetFunctionHash(int function_index);
|
};
|
|
void GetLoadedScripts(Isolate* isolate, PersistentValueVector<Script>& scripts);
|
|
MaybeLocal<UnboundScript> CompileInspectorScript(Isolate* isolate,
|
Local<String> source);
|
|
class DebugDelegate {
|
public:
|
virtual ~DebugDelegate() {}
|
virtual void ScriptCompiled(v8::Local<Script> script, bool is_live_edited,
|
bool has_compile_error) {}
|
// |inspector_break_points_hit| contains id of breakpoints installed with
|
// debug::Script::SetBreakpoint API.
|
virtual void BreakProgramRequested(
|
v8::Local<v8::Context> paused_context,
|
const std::vector<debug::BreakpointId>& inspector_break_points_hit) {}
|
virtual void ExceptionThrown(v8::Local<v8::Context> paused_context,
|
v8::Local<v8::Value> exception,
|
v8::Local<v8::Value> promise, bool is_uncaught) {
|
}
|
virtual bool IsFunctionBlackboxed(v8::Local<debug::Script> script,
|
const debug::Location& start,
|
const debug::Location& end) {
|
return false;
|
}
|
};
|
|
void SetDebugDelegate(Isolate* isolate, DebugDelegate* listener);
|
|
class AsyncEventDelegate {
|
public:
|
virtual ~AsyncEventDelegate() {}
|
virtual void AsyncEventOccurred(debug::DebugAsyncActionType type, int id,
|
bool is_blackboxed) = 0;
|
};
|
|
void SetAsyncEventDelegate(Isolate* isolate, AsyncEventDelegate* delegate);
|
|
void ResetBlackboxedStateCache(Isolate* isolate,
|
v8::Local<debug::Script> script);
|
|
int EstimatedValueSize(Isolate* isolate, v8::Local<v8::Value> value);
|
|
enum Builtin {
|
kObjectKeys,
|
kObjectGetPrototypeOf,
|
kObjectGetOwnPropertyDescriptor,
|
kObjectGetOwnPropertyNames,
|
kObjectGetOwnPropertySymbols,
|
};
|
|
Local<Function> GetBuiltin(Isolate* isolate, Builtin builtin);
|
|
V8_EXPORT_PRIVATE void SetConsoleDelegate(Isolate* isolate,
|
ConsoleDelegate* delegate);
|
|
int GetStackFrameId(v8::Local<v8::StackFrame> frame);
|
|
v8::Local<v8::StackTrace> GetDetailedStackTrace(Isolate* isolate,
|
v8::Local<v8::Object> error);
|
|
/**
|
* Native wrapper around v8::internal::JSGeneratorObject object.
|
*/
|
class GeneratorObject {
|
public:
|
v8::MaybeLocal<debug::Script> Script();
|
v8::Local<v8::Function> Function();
|
debug::Location SuspendedLocation();
|
bool IsSuspended();
|
|
static v8::Local<debug::GeneratorObject> Cast(v8::Local<v8::Value> value);
|
};
|
|
/*
|
* Provide API layer between inspector and code coverage.
|
*/
|
class V8_EXPORT_PRIVATE Coverage {
|
public:
|
MOVE_ONLY_NO_DEFAULT_CONSTRUCTOR(Coverage);
|
|
enum Mode {
|
// Make use of existing information in feedback vectors on the heap.
|
// Only return a yes/no result. Optimization and GC are not affected.
|
// Collecting best effort coverage does not reset counters.
|
kBestEffort,
|
// Disable optimization and prevent feedback vectors from being garbage
|
// collected in order to preserve precise invocation counts. Collecting
|
// precise count coverage resets counters to get incremental updates.
|
kPreciseCount,
|
// We are only interested in a yes/no result for the function. Optimization
|
// and GC can be allowed once a function has been invoked. Collecting
|
// precise binary coverage resets counters for incremental updates.
|
kPreciseBinary,
|
// Similar to the precise coverage modes but provides coverage at a
|
// lower granularity. Design doc: goo.gl/lA2swZ.
|
kBlockCount,
|
kBlockBinary,
|
};
|
|
// Forward declarations.
|
class ScriptData;
|
class FunctionData;
|
|
class V8_EXPORT_PRIVATE BlockData {
|
public:
|
MOVE_ONLY_NO_DEFAULT_CONSTRUCTOR(BlockData);
|
|
int StartOffset() const;
|
int EndOffset() const;
|
uint32_t Count() const;
|
|
private:
|
explicit BlockData(i::CoverageBlock* block,
|
std::shared_ptr<i::Coverage> coverage)
|
: block_(block), coverage_(std::move(coverage)) {}
|
|
i::CoverageBlock* block_;
|
std::shared_ptr<i::Coverage> coverage_;
|
|
friend class v8::debug::Coverage::FunctionData;
|
};
|
|
class V8_EXPORT_PRIVATE FunctionData {
|
public:
|
MOVE_ONLY_NO_DEFAULT_CONSTRUCTOR(FunctionData);
|
|
int StartOffset() const;
|
int EndOffset() const;
|
uint32_t Count() const;
|
MaybeLocal<String> Name() const;
|
size_t BlockCount() const;
|
bool HasBlockCoverage() const;
|
BlockData GetBlockData(size_t i) const;
|
|
private:
|
explicit FunctionData(i::CoverageFunction* function,
|
std::shared_ptr<i::Coverage> coverage)
|
: function_(function), coverage_(std::move(coverage)) {}
|
|
i::CoverageFunction* function_;
|
std::shared_ptr<i::Coverage> coverage_;
|
|
friend class v8::debug::Coverage::ScriptData;
|
};
|
|
class V8_EXPORT_PRIVATE ScriptData {
|
public:
|
MOVE_ONLY_NO_DEFAULT_CONSTRUCTOR(ScriptData);
|
|
Local<debug::Script> GetScript() const;
|
size_t FunctionCount() const;
|
FunctionData GetFunctionData(size_t i) const;
|
|
private:
|
explicit ScriptData(size_t index, std::shared_ptr<i::Coverage> c);
|
|
i::CoverageScript* script_;
|
std::shared_ptr<i::Coverage> coverage_;
|
|
friend class v8::debug::Coverage;
|
};
|
|
static Coverage CollectPrecise(Isolate* isolate);
|
static Coverage CollectBestEffort(Isolate* isolate);
|
|
static void SelectMode(Isolate* isolate, Mode mode);
|
|
size_t ScriptCount() const;
|
ScriptData GetScriptData(size_t i) const;
|
bool IsEmpty() const { return coverage_ == nullptr; }
|
|
private:
|
explicit Coverage(std::shared_ptr<i::Coverage> coverage)
|
: coverage_(std::move(coverage)) {}
|
std::shared_ptr<i::Coverage> coverage_;
|
};
|
|
/*
|
* Provide API layer between inspector and type profile.
|
*/
|
class V8_EXPORT_PRIVATE TypeProfile {
|
public:
|
MOVE_ONLY_NO_DEFAULT_CONSTRUCTOR(TypeProfile);
|
|
enum Mode {
|
kNone,
|
kCollect,
|
};
|
class ScriptData; // Forward declaration.
|
|
class V8_EXPORT_PRIVATE Entry {
|
public:
|
MOVE_ONLY_NO_DEFAULT_CONSTRUCTOR(Entry);
|
|
int SourcePosition() const;
|
std::vector<MaybeLocal<String>> Types() const;
|
|
private:
|
explicit Entry(const i::TypeProfileEntry* entry,
|
std::shared_ptr<i::TypeProfile> type_profile)
|
: entry_(entry), type_profile_(std::move(type_profile)) {}
|
|
const i::TypeProfileEntry* entry_;
|
std::shared_ptr<i::TypeProfile> type_profile_;
|
|
friend class v8::debug::TypeProfile::ScriptData;
|
};
|
|
class V8_EXPORT_PRIVATE ScriptData {
|
public:
|
MOVE_ONLY_NO_DEFAULT_CONSTRUCTOR(ScriptData);
|
|
Local<debug::Script> GetScript() const;
|
std::vector<Entry> Entries() const;
|
|
private:
|
explicit ScriptData(size_t index,
|
std::shared_ptr<i::TypeProfile> type_profile);
|
|
i::TypeProfileScript* script_;
|
std::shared_ptr<i::TypeProfile> type_profile_;
|
|
friend class v8::debug::TypeProfile;
|
};
|
|
static TypeProfile Collect(Isolate* isolate);
|
|
static void SelectMode(Isolate* isolate, Mode mode);
|
|
size_t ScriptCount() const;
|
ScriptData GetScriptData(size_t i) const;
|
|
private:
|
explicit TypeProfile(std::shared_ptr<i::TypeProfile> type_profile)
|
: type_profile_(std::move(type_profile)) {}
|
|
std::shared_ptr<i::TypeProfile> type_profile_;
|
};
|
|
class ScopeIterator {
|
public:
|
static std::unique_ptr<ScopeIterator> CreateForFunction(
|
v8::Isolate* isolate, v8::Local<v8::Function> func);
|
static std::unique_ptr<ScopeIterator> CreateForGeneratorObject(
|
v8::Isolate* isolate, v8::Local<v8::Object> generator);
|
|
ScopeIterator() = default;
|
virtual ~ScopeIterator() = default;
|
|
enum ScopeType {
|
ScopeTypeGlobal = 0,
|
ScopeTypeLocal,
|
ScopeTypeWith,
|
ScopeTypeClosure,
|
ScopeTypeCatch,
|
ScopeTypeBlock,
|
ScopeTypeScript,
|
ScopeTypeEval,
|
ScopeTypeModule
|
};
|
|
virtual bool Done() = 0;
|
virtual void Advance() = 0;
|
virtual ScopeType GetType() = 0;
|
virtual v8::Local<v8::Object> GetObject() = 0;
|
virtual v8::Local<v8::Value> GetFunctionDebugName() = 0;
|
virtual int GetScriptId() = 0;
|
virtual bool HasLocationInfo() = 0;
|
virtual debug::Location GetStartLocation() = 0;
|
virtual debug::Location GetEndLocation() = 0;
|
|
virtual bool SetVariableValue(v8::Local<v8::String> name,
|
v8::Local<v8::Value> value) = 0;
|
|
private:
|
DISALLOW_COPY_AND_ASSIGN(ScopeIterator);
|
};
|
|
class StackTraceIterator {
|
public:
|
static std::unique_ptr<StackTraceIterator> Create(Isolate* isolate,
|
int index = 0);
|
StackTraceIterator() = default;
|
virtual ~StackTraceIterator() = default;
|
|
virtual bool Done() const = 0;
|
virtual void Advance() = 0;
|
|
virtual int GetContextId() const = 0;
|
virtual v8::MaybeLocal<v8::Value> GetReceiver() const = 0;
|
virtual v8::Local<v8::Value> GetReturnValue() const = 0;
|
virtual v8::Local<v8::String> GetFunctionDebugName() const = 0;
|
virtual v8::Local<v8::debug::Script> GetScript() const = 0;
|
virtual debug::Location GetSourceLocation() const = 0;
|
virtual v8::Local<v8::Function> GetFunction() const = 0;
|
virtual std::unique_ptr<ScopeIterator> GetScopeIterator() const = 0;
|
|
virtual bool Restart() = 0;
|
virtual v8::MaybeLocal<v8::Value> Evaluate(v8::Local<v8::String> source,
|
bool throw_on_side_effect) = 0;
|
|
private:
|
DISALLOW_COPY_AND_ASSIGN(StackTraceIterator);
|
};
|
|
class QueryObjectPredicate {
|
public:
|
virtual ~QueryObjectPredicate() = default;
|
virtual bool Filter(v8::Local<v8::Object> object) = 0;
|
};
|
|
void QueryObjects(v8::Local<v8::Context> context,
|
QueryObjectPredicate* predicate,
|
v8::PersistentValueVector<v8::Object>* objects);
|
|
void GlobalLexicalScopeNames(v8::Local<v8::Context> context,
|
v8::PersistentValueVector<v8::String>* names);
|
|
void SetReturnValue(v8::Isolate* isolate, v8::Local<v8::Value> value);
|
|
enum class NativeAccessorType {
|
None = 0,
|
HasGetter = 1 << 0,
|
HasSetter = 1 << 1,
|
IsBuiltin = 1 << 2
|
};
|
|
int GetNativeAccessorDescriptor(v8::Local<v8::Context> context,
|
v8::Local<v8::Object> object,
|
v8::Local<v8::Name> name);
|
|
int64_t GetNextRandomInt64(v8::Isolate* isolate);
|
|
v8::MaybeLocal<v8::Value> EvaluateGlobal(v8::Isolate* isolate,
|
v8::Local<v8::String> source,
|
bool throw_on_side_effect);
|
|
int GetDebuggingId(v8::Local<v8::Function> function);
|
|
bool SetFunctionBreakpoint(v8::Local<v8::Function> function,
|
v8::Local<v8::String> condition, BreakpointId* id);
|
|
v8::Platform* GetCurrentPlatform();
|
|
class PostponeInterruptsScope {
|
public:
|
explicit PostponeInterruptsScope(v8::Isolate* isolate);
|
~PostponeInterruptsScope();
|
|
private:
|
std::unique_ptr<i::PostponeInterruptsScope> scope_;
|
};
|
|
} // namespace debug
|
} // namespace v8
|
|
#endif // V8_DEBUG_DEBUG_INTERFACE_H_
|