Files
ark_js_runtime/ecmascript/tooling/interface/debugger_api.cpp
T
y00576111 9eeef5be33 js pandafile refactor, support actor function
When the worker thread is started
the part shared by the virtual machine is not recreated
only the part that cannot be shared is created

issue:https://gitee.com/openharmony/js_worker_module/issues/I4SMW8

Signed-off-by: y00576111 <yaojian16@huawei.com>
Change-Id: I3c01588bb8449bd9cd8b410cfd13ff55205f41c1
2022-03-02 15:33:19 +08:00

271 lines
9.3 KiB
C++

/*
* Copyright (c) 2021 Huawei Device Co., Ltd.
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
#include "ecmascript/tooling/interface/debugger_api.h"
#include "ecmascript/base/number_helper.h"
#include "ecmascript/class_linker/program_object-inl.h"
#include "ecmascript/interpreter/frame_handler.h"
#include "ecmascript/js_handle.h"
#include "ecmascript/js_method.h"
#include "ecmascript/mem/c_string.h"
#include "ecmascript/napi/jsnapi_helper-inl.h"
#include "ecmascript/tooling/interface/js_debugger.h"
#include "ecmascript/jspandafile/js_pandafile.h"
namespace panda::tooling::ecmascript {
using panda::ecmascript::JSHandle;
using panda::ecmascript::JSTaggedValue;
using panda::ecmascript::JSNativePointer;
using panda::ecmascript::LexicalEnv;
using panda::ecmascript::ScopeDebugInfo;
using panda::ecmascript::Program;
using panda::ecmascript::base::ALLOW_BINARY;
using panda::ecmascript::base::ALLOW_HEX;
using panda::ecmascript::base::ALLOW_OCTAL;
using panda::ecmascript::base::NumberHelper;
// CString
uint64_t DebuggerApi::CStringToULL(const CString &str)
{
return panda::ecmascript::CStringToULL(str);
}
CString DebuggerApi::ToCString(int32_t number)
{
return panda::ecmascript::ToCString(number);
}
CString DebuggerApi::ConvertToString(const std::string &str)
{
return panda::ecmascript::ConvertToString(str);
}
// InterpretedFrameHandler
uint32_t DebuggerApi::GetStackDepth(const EcmaVM *ecmaVm)
{
uint32_t count = 0;
InterpretedFrameHandler frameHandler(ecmaVm->GetJSThread());
for (; frameHandler.HasFrame(); frameHandler.PrevInterpretedFrame()) {
if (frameHandler.IsBreakFrame()) {
continue;
}
++count;
}
return count;
}
bool DebuggerApi::StackWalker(const EcmaVM *ecmaVm, std::function<StackState(const InterpretedFrameHandler *)> func)
{
InterpretedFrameHandler frameHandler(ecmaVm->GetJSThread());
for (; frameHandler.HasFrame(); frameHandler.PrevInterpretedFrame()) {
if (frameHandler.IsBreakFrame()) {
continue;
}
StackState state = func(&frameHandler);
if (state == StackState::CONTINUE) {
continue;
}
if (state == StackState::FAILED) {
return false;
}
return true;
}
return true;
}
uint32_t DebuggerApi::GetBytecodeOffset(const EcmaVM *ecmaVm)
{
return InterpretedFrameHandler(ecmaVm->GetJSThread()).GetBytecodeOffset();
}
JSMethod *DebuggerApi::GetMethod(const EcmaVM *ecmaVm)
{
return InterpretedFrameHandler(ecmaVm->GetJSThread()).GetMethod();
}
Local<JSValueRef> DebuggerApi::GetVRegValue(const EcmaVM *ecmaVm, size_t index)
{
auto value = InterpretedFrameHandler(ecmaVm->GetJSThread()).GetVRegValue(index);
JSHandle<JSTaggedValue> handledValue(ecmaVm->GetJSThread(), value);
return JSNApiHelper::ToLocal<JSValueRef>(handledValue);
}
void DebuggerApi::SetVRegValue(const EcmaVM *ecmaVm, size_t index, Local<JSValueRef> value)
{
return InterpretedFrameHandler(ecmaVm->GetJSThread()).SetVRegValue(index, JSNApiHelper::ToJSTaggedValue(*value));
}
uint32_t DebuggerApi::GetBytecodeOffset(const InterpretedFrameHandler *frameHandler)
{
return frameHandler->GetBytecodeOffset();
}
JSMethod *DebuggerApi::GetMethod(const InterpretedFrameHandler *frameHandler)
{
return frameHandler->GetMethod();
}
Local<JSValueRef> DebuggerApi::GetVRegValue(const EcmaVM *ecmaVm,
const InterpretedFrameHandler *frameHandler, size_t index)
{
auto value = frameHandler->GetVRegValue(index);
JSHandle<JSTaggedValue> handledValue(ecmaVm->GetJSThread(), value);
return JSNApiHelper::ToLocal<JSValueRef>(handledValue);
}
// JSThread
Local<JSValueRef> DebuggerApi::GetException(const EcmaVM *ecmaVm)
{
auto exception = ecmaVm->GetJSThread()->GetException();
JSHandle<JSTaggedValue> handledException(ecmaVm->GetJSThread(), exception);
return JSNApiHelper::ToLocal<JSValueRef>(handledException);
}
void DebuggerApi::SetException(const EcmaVM *ecmaVm, Local<JSValueRef> exception)
{
ecmaVm->GetJSThread()->SetException(JSNApiHelper::ToJSTaggedValue(*exception));
}
void DebuggerApi::ClearException(const EcmaVM *ecmaVm)
{
return ecmaVm->GetJSThread()->ClearException();
}
// EcmaVM
const panda_file::File *DebuggerApi::FindPandaFile(const EcmaVM *ecmaVm, const CString &fileName)
{
const panda_file::File *pfs = nullptr;
ecmaVm->EnumerateJSPandaFiles([&pfs, fileName](const panda::ecmascript::JSPandaFile *jsPandaFile) {
if (ConvertToString(jsPandaFile->GetJSPandaFileDesc()) == fileName) {
pfs = jsPandaFile->GetPandaFile();
return false;
}
return true;
});
return pfs;
}
// NumberHelper
double DebuggerApi::StringToDouble(const uint8_t *start, const uint8_t *end, uint8_t radix)
{
return NumberHelper::StringToDouble(start, end, radix, ALLOW_BINARY | ALLOW_HEX | ALLOW_OCTAL);
}
// JSDebugger
JSDebugger *DebuggerApi::CreateJSDebugger(const EcmaVM *ecmaVm)
{
return new JSDebugger(ecmaVm);
}
void DebuggerApi::DestroyJSDebugger(JSDebugger *debugger)
{
delete debugger;
}
std::optional<Error> DebuggerApi::RegisterHooks(JSDebugger *debugger, PtHooks *hooks)
{
return debugger->RegisterHooks(hooks);
}
std::optional<Error> DebuggerApi::SetBreakpoint(JSDebugger *debugger, const PtLocation &location)
{
return debugger->SetBreakpoint(location);
}
std::optional<Error> DebuggerApi::RemoveBreakpoint(JSDebugger *debugger, const PtLocation &location)
{
return debugger->RemoveBreakpoint(location);
}
// JSMethod
CString DebuggerApi::ParseFunctionName(const JSMethod *method)
{
return method->ParseFunctionName();
}
// ScopeInfo
Local<JSValueRef> DebuggerApi::GetProperties(const EcmaVM *ecmaVm, int32_t level, uint32_t slot)
{
JSTaggedValue env = ecmaVm->GetJSThread()->GetCurrentLexenv();
for (int i = 0; i < level; i++) {
JSTaggedValue taggedParentEnv = LexicalEnv::Cast(env.GetTaggedObject())->GetParentEnv();
ASSERT(!taggedParentEnv.IsUndefined());
env= taggedParentEnv;
}
JSTaggedValue value = LexicalEnv::Cast(env.GetTaggedObject())->GetProperties(slot);
JSHandle<JSTaggedValue> handledValue(ecmaVm->GetJSThread(), value);
return JSNApiHelper::ToLocal<JSValueRef>(handledValue);
}
void DebuggerApi::SetProperties(const EcmaVM *ecmaVm, int32_t level, uint32_t slot, Local<JSValueRef> value)
{
JSTaggedValue target = JSNApiHelper::ToJSHandle(value).GetTaggedValue();
JSTaggedValue env = ecmaVm->GetJSThread()->GetCurrentLexenv();
for (int i = 0; i < level; i++) {
JSTaggedValue taggedParentEnv = LexicalEnv::Cast(env.GetTaggedObject())->GetParentEnv();
ASSERT(!taggedParentEnv.IsUndefined());
env= taggedParentEnv;
}
LexicalEnv::Cast(env.GetTaggedObject())->SetProperties(ecmaVm->GetJSThread(), slot, target);
}
bool DebuggerApi::EvaluateLexicalValue(const EcmaVM *ecmaVm, const CString &name, int32_t &level, uint32_t &slot)
{
JSTaggedValue curEnv = ecmaVm->GetJSThread()->GetCurrentLexenv();
for (; curEnv.IsTaggedArray(); curEnv = LexicalEnv::Cast(curEnv.GetTaggedObject())->GetParentEnv()) {
level++;
LexicalEnv *lexicalEnv = LexicalEnv::Cast(curEnv.GetTaggedObject());
if (lexicalEnv->GetScopeInfo().IsHole()) {
continue;
}
auto result = JSNativePointer::Cast(lexicalEnv->GetScopeInfo().GetTaggedObject())->GetExternalPointer();
ScopeDebugInfo *scopeDebugInfo = reinterpret_cast<ScopeDebugInfo *>(result);
for (const auto &info : scopeDebugInfo->scopeInfo) {
if (info.name == name) {
slot = info.slot;
return true;
}
}
}
return false;
}
Local<JSValueRef> DebuggerApi::GetLexicalValueInfo(const EcmaVM *ecmaVm, const CString &name)
{
JSThread *thread = ecmaVm->GetJSThread();
JSTaggedValue curEnv = thread->GetCurrentLexenv();
for (; curEnv.IsTaggedArray(); curEnv = LexicalEnv::Cast(curEnv.GetTaggedObject())->GetParentEnv()) {
LexicalEnv *lexicalEnv = LexicalEnv::Cast(curEnv.GetTaggedObject());
if (lexicalEnv->GetScopeInfo().IsHole()) {
continue;
}
void *pointer = JSNativePointer::Cast(lexicalEnv->GetScopeInfo().GetTaggedObject())->GetExternalPointer();
ScopeDebugInfo *scopeDebugInfo = static_cast<ScopeDebugInfo *>(pointer);
for (const auto &info : scopeDebugInfo->scopeInfo) {
if (info.name == name) {
uint16_t slot = info.slot;
JSTaggedValue value = lexicalEnv->GetProperties(slot);
JSHandle<JSTaggedValue> handledValue(thread, value);
return JSNApiHelper::ToLocal<JSValueRef>(handledValue);
}
}
}
JSHandle<JSTaggedValue> handledValue(thread, JSTaggedValue::Hole());
return JSNApiHelper::ToLocal<JSValueRef>(handledValue);
}
} // namespace panda::tooling::ecmascript