/*
* Copyright (c) Facebook, Inc. and its affiliates.
*
* This source code is licensed under the MIT license found in the
* LICENSE file in the root directory of this source tree.
*/
#ifdef HERMES_ENABLE_DEBUGGER
#include "DebuggerAPI.h"
#include "hermes.h"
#include "hermes/VM/Debugger/DebugCommand.h"
#include "hermes/VM/Debugger/Debugger.h"
#include "hermes/VM/HermesValue.h"
#include
#include
using namespace ::facebook::hermes::debugger;
using ::hermes::vm::DebugCommand;
using ::hermes::vm::HermesValue;
using ::hermes::vm::InterpreterState;
EventObserver::~EventObserver() {}
::hermes::vm::Debugger *ProgramState::impl() const {
return dbg_->impl_;
}
LexicalInfo ProgramState::getLexicalInfo(uint32_t frameIndex) const {
return impl()->getLexicalInfoInFrame(frameIndex);
}
VariableInfo ProgramState::getVariableInfo(
uint32_t frameIndex,
uint32_t scopeDepth,
uint32_t variableIndexInScope) const {
VariableInfo info{};
HermesValue hermesValue = impl()->getVariableInFrame(
frameIndex, scopeDepth, variableIndexInScope, &info.name);
info.value = dbg_->jsiValueFromHermesValue(hermesValue);
return info;
}
VariableInfo ProgramState::getVariableInfoForThis(uint32_t frameIndex) const {
VariableInfo info{};
info.name = "this";
HermesValue hermesValue = impl()->getThisValue(frameIndex);
info.value = dbg_->jsiValueFromHermesValue(hermesValue);
return info;
}
EvalResult ProgramState::getEvalResult() const {
assert(
pauseReason_ == PauseReason::EvalComplete &&
"No EvalResult because pause is not due to EvalComplete");
::facebook::jsi::Value copiedValue(*dbg_->runtime_, evalResult_.value);
return debugger::EvalResult{
std::move(copiedValue),
evalResult_.isException,
evalResult_.exceptionDetails};
}
Command::~Command() = default;
Command::Command(Command &&) = default;
Command &Command::operator=(Command &&) = default;
Debugger::Debugger(
::facebook::hermes::HermesRuntime *runtime,
::hermes::vm::Debugger *impl)
: runtime_(runtime), impl_(impl), state_(this) {
using EvalResultMetadata = ::hermes::vm::Debugger::EvalResultMetadata;
impl->setDidPauseCallback(
[this](
InterpreterState state,
PauseReason reason,
HermesValue evalResult,
const EvalResultMetadata &evalResultMd,
BreakpointID breakpoint) -> DebugCommand {
if (!eventObserver_)
return DebugCommand::makeContinue();
state_.pauseReason_ = reason;
state_.stackTrace_ = impl_->getStackTrace(state);
state_.evalResult_.value = jsiValueFromHermesValue(evalResult);
state_.evalResult_.isException = evalResultMd.isException;
state_.evalResult_.exceptionDetails = evalResultMd.exceptionDetails;
state_.breakpoint_ = breakpoint;
Command command = eventObserver_->didPause(*this);
return std::move(*command.debugCommand_);
});
impl->setBreakpointResolvedCallback([this](BreakpointID breakpoint) -> void {
if (!eventObserver_) {
return;
}
eventObserver_->breakpointResolved(*this, breakpoint);
});
}
String Debugger::getSourceMappingUrl(uint32_t fileId) const {
return impl_->getSourceMappingUrl(fileId);
}
uint64_t Debugger::setBreakpoint(SourceLocation loc) {
return impl_->createBreakpoint(loc);
}
void Debugger::setBreakpointCondition(
BreakpointID breakpoint,
const String &condition) {
return impl_->setBreakpointCondition(breakpoint, condition);
}
void Debugger::deleteBreakpoint(BreakpointID id) {
impl_->deleteBreakpoint(id);
}
void Debugger::deleteAllBreakpoints() {
impl_->deleteAllBreakpoints();
}
void Debugger::setBreakpointEnabled(BreakpointID id, bool enable) {
impl_->setBreakpointEnabled(id, enable);
}
BreakpointInfo Debugger::getBreakpointInfo(BreakpointID breakpoint) {
return impl_->getBreakpointInfo(breakpoint);
}
std::vector Debugger::getBreakpoints() {
return impl_->getBreakpoints();
}
void Debugger::setShouldPauseOnScriptLoad(bool flag) {
return impl_->setShouldPauseOnScriptLoad(flag);
}
bool Debugger::getShouldPauseOnScriptLoad() const {
return impl_->getShouldPauseOnScriptLoad();
}
void Debugger::setPauseOnThrowMode(PauseOnThrowMode mode) {
impl_->setPauseOnThrowMode(mode);
}
PauseOnThrowMode Debugger::getPauseOnThrowMode() const {
return impl_->getPauseOnThrowMode();
}
void Debugger::triggerAsyncPause(AsyncPauseKind kind) {
return impl_->triggerAsyncPause(kind);
}
void Debugger::setIsDebuggerAttached(bool isAttached) {
return impl_->setIsDebuggerAttached(isAttached);
}
void Debugger::setEventObserver(EventObserver *observer) {
eventObserver_ = observer;
}
Command::Command(::hermes::vm::DebugCommand &&debugCommand)
: debugCommand_(new DebugCommand(std::move(debugCommand))) {}
Command Command::step(StepMode mode) {
return Command(DebugCommand::makeStep(mode));
}
Command Command::continueExecution() {
return Command(DebugCommand::makeContinue());
}
Command Command::eval(const String &src, uint32_t frameIndex) {
return Command(DebugCommand::makeEval(frameIndex, src));
}
#endif // HERMES_ENABLE_DEBUGGER