14514f5e3Sopenharmony_ci/* 24514f5e3Sopenharmony_ci * Copyright (c) 2021-2022 Huawei Device Co., Ltd. 34514f5e3Sopenharmony_ci * Licensed under the Apache License, Version 2.0 (the "License"); 44514f5e3Sopenharmony_ci * you may not use this file except in compliance with the License. 54514f5e3Sopenharmony_ci * You may obtain a copy of the License at 64514f5e3Sopenharmony_ci * 74514f5e3Sopenharmony_ci * http://www.apache.org/licenses/LICENSE-2.0 84514f5e3Sopenharmony_ci * 94514f5e3Sopenharmony_ci * Unless required by applicable law or agreed to in writing, software 104514f5e3Sopenharmony_ci * distributed under the License is distributed on an "AS IS" BASIS, 114514f5e3Sopenharmony_ci * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 124514f5e3Sopenharmony_ci * See the License for the specific language governing permissions and 134514f5e3Sopenharmony_ci * limitations under the License. 144514f5e3Sopenharmony_ci */ 154514f5e3Sopenharmony_ci 164514f5e3Sopenharmony_ci#include "ecmascript/debugger/js_debugger.h" 174514f5e3Sopenharmony_ci#include <memory> 184514f5e3Sopenharmony_ci 194514f5e3Sopenharmony_ci#include "ecmascript/interpreter/interpreter-inl.h" 204514f5e3Sopenharmony_ci 214514f5e3Sopenharmony_cinamespace panda::ecmascript::tooling { 224514f5e3Sopenharmony_ciusing panda::ecmascript::base::BuiltinsBase; 234514f5e3Sopenharmony_ci 244514f5e3Sopenharmony_cibool JSDebugger::SetBreakpoint(const JSPtLocation &location, Local<FunctionRef> condFuncRef) 254514f5e3Sopenharmony_ci{ 264514f5e3Sopenharmony_ci std::unique_ptr<PtMethod> ptMethod = FindMethod(location); 274514f5e3Sopenharmony_ci if (ptMethod == nullptr) { 284514f5e3Sopenharmony_ci LOG_DEBUGGER(ERROR) << "SetBreakpoint: Cannot find MethodLiteral"; 294514f5e3Sopenharmony_ci return false; 304514f5e3Sopenharmony_ci } 314514f5e3Sopenharmony_ci 324514f5e3Sopenharmony_ci if (location.GetBytecodeOffset() >= ptMethod->GetCodeSize()) { 334514f5e3Sopenharmony_ci LOG_DEBUGGER(ERROR) << "SetBreakpoint: Invalid breakpoint location"; 344514f5e3Sopenharmony_ci return false; 354514f5e3Sopenharmony_ci } 364514f5e3Sopenharmony_ci 374514f5e3Sopenharmony_ci auto [_, success] = breakpoints_.emplace(location.GetSourceFile(), ptMethod.release(), 384514f5e3Sopenharmony_ci location.GetBytecodeOffset(), Global<FunctionRef>(ecmaVm_, condFuncRef)); 394514f5e3Sopenharmony_ci if (!success) { 404514f5e3Sopenharmony_ci // also return true 414514f5e3Sopenharmony_ci LOG_DEBUGGER(WARN) << "SetBreakpoint: Breakpoint already exists"; 424514f5e3Sopenharmony_ci } 434514f5e3Sopenharmony_ci 444514f5e3Sopenharmony_ci DumpBreakpoints(); 454514f5e3Sopenharmony_ci return true; 464514f5e3Sopenharmony_ci} 474514f5e3Sopenharmony_ci 484514f5e3Sopenharmony_cibool JSDebugger::SetSmartBreakpoint(const JSPtLocation &location) 494514f5e3Sopenharmony_ci{ 504514f5e3Sopenharmony_ci std::unique_ptr<PtMethod> ptMethod = FindMethod(location); 514514f5e3Sopenharmony_ci if (ptMethod == nullptr) { 524514f5e3Sopenharmony_ci LOG_DEBUGGER(ERROR) << "SetSmartBreakpoint: Cannot find MethodLiteral"; 534514f5e3Sopenharmony_ci return false; 544514f5e3Sopenharmony_ci } 554514f5e3Sopenharmony_ci 564514f5e3Sopenharmony_ci if (location.GetBytecodeOffset() >= ptMethod->GetCodeSize()) { 574514f5e3Sopenharmony_ci LOG_DEBUGGER(ERROR) << "SetSmartBreakpoint: Invalid breakpoint location"; 584514f5e3Sopenharmony_ci return false; 594514f5e3Sopenharmony_ci } 604514f5e3Sopenharmony_ci 614514f5e3Sopenharmony_ci auto [_, success] = smartBreakpoints_.emplace(location.GetSourceFile(), ptMethod.release(), 624514f5e3Sopenharmony_ci location.GetBytecodeOffset(), Global<FunctionRef>(ecmaVm_, FunctionRef::Undefined(ecmaVm_))); 634514f5e3Sopenharmony_ci if (!success) { 644514f5e3Sopenharmony_ci // also return true 654514f5e3Sopenharmony_ci LOG_DEBUGGER(WARN) << "SetSmartBreakpoint: Breakpoint already exists"; 664514f5e3Sopenharmony_ci } 674514f5e3Sopenharmony_ci 684514f5e3Sopenharmony_ci DumpBreakpoints(); 694514f5e3Sopenharmony_ci return true; 704514f5e3Sopenharmony_ci} 714514f5e3Sopenharmony_ci 724514f5e3Sopenharmony_cibool JSDebugger::RemoveBreakpoint(const JSPtLocation &location) 734514f5e3Sopenharmony_ci{ 744514f5e3Sopenharmony_ci std::unique_ptr<PtMethod> ptMethod = FindMethod(location); 754514f5e3Sopenharmony_ci if (ptMethod == nullptr) { 764514f5e3Sopenharmony_ci LOG_DEBUGGER(ERROR) << "RemoveBreakpoint: Cannot find MethodLiteral"; 774514f5e3Sopenharmony_ci return false; 784514f5e3Sopenharmony_ci } 794514f5e3Sopenharmony_ci 804514f5e3Sopenharmony_ci if (!RemoveBreakpoint(ptMethod, location.GetBytecodeOffset())) { 814514f5e3Sopenharmony_ci LOG_DEBUGGER(ERROR) << "RemoveBreakpoint: Breakpoint not found"; 824514f5e3Sopenharmony_ci return false; 834514f5e3Sopenharmony_ci } 844514f5e3Sopenharmony_ci 854514f5e3Sopenharmony_ci DumpBreakpoints(); 864514f5e3Sopenharmony_ci return true; 874514f5e3Sopenharmony_ci} 884514f5e3Sopenharmony_ci 894514f5e3Sopenharmony_civoid JSDebugger::RemoveAllBreakpoints() 904514f5e3Sopenharmony_ci{ 914514f5e3Sopenharmony_ci breakpoints_.clear(); 924514f5e3Sopenharmony_ci} 934514f5e3Sopenharmony_ci 944514f5e3Sopenharmony_cibool JSDebugger::RemoveBreakpointsByUrl(const std::string &url) 954514f5e3Sopenharmony_ci{ 964514f5e3Sopenharmony_ci for (auto it = breakpoints_.begin(); it != breakpoints_.end();) { 974514f5e3Sopenharmony_ci const auto &bp = *it; 984514f5e3Sopenharmony_ci if (bp.GetSourceFile() == url) { 994514f5e3Sopenharmony_ci it = breakpoints_.erase(it); 1004514f5e3Sopenharmony_ci } else { 1014514f5e3Sopenharmony_ci it++; 1024514f5e3Sopenharmony_ci } 1034514f5e3Sopenharmony_ci } 1044514f5e3Sopenharmony_ci 1054514f5e3Sopenharmony_ci DumpBreakpoints(); 1064514f5e3Sopenharmony_ci return true; 1074514f5e3Sopenharmony_ci} 1084514f5e3Sopenharmony_ci 1094514f5e3Sopenharmony_civoid JSDebugger::BytecodePcChanged(JSThread *thread, JSHandle<Method> method, uint32_t bcOffset) 1104514f5e3Sopenharmony_ci{ 1114514f5e3Sopenharmony_ci ASSERT(bcOffset < method->GetCodeSize() && "code size of current Method less then bcOffset"); 1124514f5e3Sopenharmony_ci HandleExceptionThrowEvent(thread, method, bcOffset); 1134514f5e3Sopenharmony_ci // clear singlestep flag 1144514f5e3Sopenharmony_ci singleStepOnDebuggerStmt_ = false; 1154514f5e3Sopenharmony_ci if (ecmaVm_->GetJsDebuggerManager()->IsMixedStackEnabled()) { 1164514f5e3Sopenharmony_ci if (!HandleBreakpoint(method, bcOffset)) { 1174514f5e3Sopenharmony_ci HandleNativeOut(); 1184514f5e3Sopenharmony_ci HandleStep(method, bcOffset); 1194514f5e3Sopenharmony_ci } 1204514f5e3Sopenharmony_ci } else { 1214514f5e3Sopenharmony_ci if (!HandleStep(method, bcOffset)) { 1224514f5e3Sopenharmony_ci HandleBreakpoint(method, bcOffset); 1234514f5e3Sopenharmony_ci } 1244514f5e3Sopenharmony_ci } 1254514f5e3Sopenharmony_ci} 1264514f5e3Sopenharmony_ci 1274514f5e3Sopenharmony_cibool JSDebugger::HandleNativeOut() 1284514f5e3Sopenharmony_ci{ 1294514f5e3Sopenharmony_ci if (hooks_ == nullptr) { 1304514f5e3Sopenharmony_ci return false; 1314514f5e3Sopenharmony_ci } 1324514f5e3Sopenharmony_ci 1334514f5e3Sopenharmony_ci return hooks_->NativeOut(); 1344514f5e3Sopenharmony_ci} 1354514f5e3Sopenharmony_ci 1364514f5e3Sopenharmony_cibool JSDebugger::HandleBreakpoint(JSHandle<Method> method, uint32_t bcOffset) 1374514f5e3Sopenharmony_ci{ 1384514f5e3Sopenharmony_ci if (hooks_ == nullptr) { 1394514f5e3Sopenharmony_ci return false; 1404514f5e3Sopenharmony_ci } 1414514f5e3Sopenharmony_ci 1424514f5e3Sopenharmony_ci auto smartBreakpoint = FindSmartBreakpoint(method, bcOffset); 1434514f5e3Sopenharmony_ci if (smartBreakpoint.has_value()) { 1444514f5e3Sopenharmony_ci JSPtLocation smartLocation {method->GetJSPandaFile(), method->GetMethodId(), bcOffset, 1454514f5e3Sopenharmony_ci smartBreakpoint.value().GetSourceFile()}; 1464514f5e3Sopenharmony_ci std::unique_ptr<PtMethod> ptMethod = FindMethod(smartLocation); 1474514f5e3Sopenharmony_ci RemoveSmartBreakpoint(ptMethod, bcOffset); 1484514f5e3Sopenharmony_ci hooks_->Breakpoint(smartLocation); 1494514f5e3Sopenharmony_ci return true; 1504514f5e3Sopenharmony_ci } 1514514f5e3Sopenharmony_ci 1524514f5e3Sopenharmony_ci auto breakpoint = FindBreakpoint(method, bcOffset); 1534514f5e3Sopenharmony_ci if (!breakpoint.has_value() || !IsBreakpointCondSatisfied(breakpoint)) { 1544514f5e3Sopenharmony_ci return false; 1554514f5e3Sopenharmony_ci } 1564514f5e3Sopenharmony_ci JSPtLocation location {method->GetJSPandaFile(), method->GetMethodId(), bcOffset, 1574514f5e3Sopenharmony_ci breakpoint.value().GetSourceFile()}; 1584514f5e3Sopenharmony_ci 1594514f5e3Sopenharmony_ci hooks_->Breakpoint(location); 1604514f5e3Sopenharmony_ci return true; 1614514f5e3Sopenharmony_ci} 1624514f5e3Sopenharmony_ci 1634514f5e3Sopenharmony_cibool JSDebugger::HandleDebuggerStmt(JSHandle<Method> method, uint32_t bcOffset) 1644514f5e3Sopenharmony_ci{ 1654514f5e3Sopenharmony_ci if (hooks_ == nullptr || !ecmaVm_->GetJsDebuggerManager()->IsDebugMode()) { 1664514f5e3Sopenharmony_ci return false; 1674514f5e3Sopenharmony_ci } 1684514f5e3Sopenharmony_ci // if debugger stmt is met by single stepping, disable debugger 1694514f5e3Sopenharmony_ci // stmt to prevent pausing on this line twice 1704514f5e3Sopenharmony_ci if (singleStepOnDebuggerStmt_) { 1714514f5e3Sopenharmony_ci return false; 1724514f5e3Sopenharmony_ci } 1734514f5e3Sopenharmony_ci auto breakpointAtDebugger = FindBreakpoint(method, bcOffset); 1744514f5e3Sopenharmony_ci // if a breakpoint is set on the same line as debugger stmt, 1754514f5e3Sopenharmony_ci // the debugger stmt is ineffective 1764514f5e3Sopenharmony_ci if (breakpointAtDebugger.has_value()) { 1774514f5e3Sopenharmony_ci return false; 1784514f5e3Sopenharmony_ci } 1794514f5e3Sopenharmony_ci JSPtLocation location {method->GetJSPandaFile(), method->GetMethodId(), bcOffset}; 1804514f5e3Sopenharmony_ci hooks_->DebuggerStmt(location); 1814514f5e3Sopenharmony_ci 1824514f5e3Sopenharmony_ci return true; 1834514f5e3Sopenharmony_ci} 1844514f5e3Sopenharmony_ci 1854514f5e3Sopenharmony_civoid JSDebugger::HandleExceptionThrowEvent(const JSThread *thread, JSHandle<Method> method, uint32_t bcOffset) 1864514f5e3Sopenharmony_ci{ 1874514f5e3Sopenharmony_ci if (hooks_ == nullptr || !thread->HasPendingException()) { 1884514f5e3Sopenharmony_ci return; 1894514f5e3Sopenharmony_ci } 1904514f5e3Sopenharmony_ci 1914514f5e3Sopenharmony_ci JSPtLocation throwLocation {method->GetJSPandaFile(), method->GetMethodId(), bcOffset}; 1924514f5e3Sopenharmony_ci 1934514f5e3Sopenharmony_ci hooks_->Exception(throwLocation); 1944514f5e3Sopenharmony_ci} 1954514f5e3Sopenharmony_ci 1964514f5e3Sopenharmony_cibool JSDebugger::HandleStep(JSHandle<Method> method, uint32_t bcOffset) 1974514f5e3Sopenharmony_ci{ 1984514f5e3Sopenharmony_ci if (hooks_ == nullptr) { 1994514f5e3Sopenharmony_ci return false; 2004514f5e3Sopenharmony_ci } 2014514f5e3Sopenharmony_ci 2024514f5e3Sopenharmony_ci JSPtLocation location {method->GetJSPandaFile(), method->GetMethodId(), bcOffset}; 2034514f5e3Sopenharmony_ci 2044514f5e3Sopenharmony_ci return hooks_->SingleStep(location); 2054514f5e3Sopenharmony_ci} 2064514f5e3Sopenharmony_ci 2074514f5e3Sopenharmony_cistd::optional<JSBreakpoint> JSDebugger::FindBreakpoint(JSHandle<Method> method, uint32_t bcOffset) const 2084514f5e3Sopenharmony_ci{ 2094514f5e3Sopenharmony_ci for (const auto &bp : breakpoints_) { 2104514f5e3Sopenharmony_ci if ((bp.GetBytecodeOffset() == bcOffset) && 2114514f5e3Sopenharmony_ci (bp.GetPtMethod()->GetJSPandaFile() == method->GetJSPandaFile()) && 2124514f5e3Sopenharmony_ci (bp.GetPtMethod()->GetMethodId() == method->GetMethodId())) { 2134514f5e3Sopenharmony_ci return bp; 2144514f5e3Sopenharmony_ci } 2154514f5e3Sopenharmony_ci } 2164514f5e3Sopenharmony_ci return {}; 2174514f5e3Sopenharmony_ci} 2184514f5e3Sopenharmony_ci 2194514f5e3Sopenharmony_cistd::optional<JSBreakpoint> JSDebugger::FindSmartBreakpoint(JSHandle<Method> method, uint32_t bcOffset) const 2204514f5e3Sopenharmony_ci{ 2214514f5e3Sopenharmony_ci for (const auto &bp : smartBreakpoints_) { 2224514f5e3Sopenharmony_ci if ((bp.GetBytecodeOffset() == bcOffset) && 2234514f5e3Sopenharmony_ci (bp.GetPtMethod()->GetJSPandaFile() == method->GetJSPandaFile()) && 2244514f5e3Sopenharmony_ci (bp.GetPtMethod()->GetMethodId() == method->GetMethodId())) { 2254514f5e3Sopenharmony_ci return bp; 2264514f5e3Sopenharmony_ci } 2274514f5e3Sopenharmony_ci } 2284514f5e3Sopenharmony_ci return {}; 2294514f5e3Sopenharmony_ci} 2304514f5e3Sopenharmony_ci 2314514f5e3Sopenharmony_cibool JSDebugger::RemoveBreakpoint(const std::unique_ptr<PtMethod> &ptMethod, uint32_t bcOffset) 2324514f5e3Sopenharmony_ci{ 2334514f5e3Sopenharmony_ci for (auto it = breakpoints_.begin(); it != breakpoints_.end(); ++it) { 2344514f5e3Sopenharmony_ci const auto &bp = *it; 2354514f5e3Sopenharmony_ci if ((bp.GetBytecodeOffset() == bcOffset) && 2364514f5e3Sopenharmony_ci (bp.GetPtMethod()->GetJSPandaFile() == ptMethod->GetJSPandaFile()) && 2374514f5e3Sopenharmony_ci (bp.GetPtMethod()->GetMethodId() == ptMethod->GetMethodId())) { 2384514f5e3Sopenharmony_ci it = breakpoints_.erase(it); 2394514f5e3Sopenharmony_ci return true; 2404514f5e3Sopenharmony_ci } 2414514f5e3Sopenharmony_ci } 2424514f5e3Sopenharmony_ci 2434514f5e3Sopenharmony_ci return false; 2444514f5e3Sopenharmony_ci} 2454514f5e3Sopenharmony_ci 2464514f5e3Sopenharmony_cibool JSDebugger::RemoveSmartBreakpoint(const std::unique_ptr<PtMethod> &ptMethod, uint32_t bcOffset) 2474514f5e3Sopenharmony_ci{ 2484514f5e3Sopenharmony_ci for (auto it = smartBreakpoints_.begin(); it != smartBreakpoints_.end(); ++it) { 2494514f5e3Sopenharmony_ci const auto &bp = *it; 2504514f5e3Sopenharmony_ci if ((bp.GetBytecodeOffset() == bcOffset) && 2514514f5e3Sopenharmony_ci (bp.GetPtMethod()->GetJSPandaFile() == ptMethod->GetJSPandaFile()) && 2524514f5e3Sopenharmony_ci (bp.GetPtMethod()->GetMethodId() == ptMethod->GetMethodId())) { 2534514f5e3Sopenharmony_ci it = smartBreakpoints_.erase(it); 2544514f5e3Sopenharmony_ci return true; 2554514f5e3Sopenharmony_ci } 2564514f5e3Sopenharmony_ci } 2574514f5e3Sopenharmony_ci 2584514f5e3Sopenharmony_ci return false; 2594514f5e3Sopenharmony_ci} 2604514f5e3Sopenharmony_ci 2614514f5e3Sopenharmony_cistd::unique_ptr<PtMethod> JSDebugger::FindMethod(const JSPtLocation &location) const 2624514f5e3Sopenharmony_ci{ 2634514f5e3Sopenharmony_ci std::unique_ptr<PtMethod> ptMethod {nullptr}; 2644514f5e3Sopenharmony_ci ::panda::ecmascript::JSPandaFileManager::GetInstance()->EnumerateJSPandaFiles([&ptMethod, location]( 2654514f5e3Sopenharmony_ci const std::shared_ptr<JSPandaFile> &file) { 2664514f5e3Sopenharmony_ci if (file->GetJSPandaFileDesc() == location.GetJsPandaFile()->GetJSPandaFileDesc()) { 2674514f5e3Sopenharmony_ci MethodLiteral *methodsData = file->GetMethodLiterals(); 2684514f5e3Sopenharmony_ci uint32_t numberMethods = file->GetNumMethods(); 2694514f5e3Sopenharmony_ci for (uint32_t i = 0; i < numberMethods; ++i) { 2704514f5e3Sopenharmony_ci if (methodsData[i].GetMethodId() == location.GetMethodId()) { 2714514f5e3Sopenharmony_ci MethodLiteral *methodLiteral = methodsData + i; 2724514f5e3Sopenharmony_ci ptMethod = std::make_unique<PtMethod>(file.get(), 2734514f5e3Sopenharmony_ci methodLiteral->GetMethodId(), methodLiteral->IsNativeWithCallField()); 2744514f5e3Sopenharmony_ci return false; 2754514f5e3Sopenharmony_ci } 2764514f5e3Sopenharmony_ci } 2774514f5e3Sopenharmony_ci } 2784514f5e3Sopenharmony_ci return true; 2794514f5e3Sopenharmony_ci }); 2804514f5e3Sopenharmony_ci return ptMethod; 2814514f5e3Sopenharmony_ci} 2824514f5e3Sopenharmony_ci 2834514f5e3Sopenharmony_civoid JSDebugger::DumpBreakpoints() 2844514f5e3Sopenharmony_ci{ 2854514f5e3Sopenharmony_ci LOG_DEBUGGER(INFO) << "dump breakpoints with size " << breakpoints_.size(); 2864514f5e3Sopenharmony_ci for (const auto &bp : breakpoints_) { 2874514f5e3Sopenharmony_ci LOG_DEBUGGER(DEBUG) << bp.ToString(); 2884514f5e3Sopenharmony_ci } 2894514f5e3Sopenharmony_ci} 2904514f5e3Sopenharmony_ci 2914514f5e3Sopenharmony_cibool JSDebugger::IsBreakpointCondSatisfied(std::optional<JSBreakpoint> breakpoint) const 2924514f5e3Sopenharmony_ci{ 2934514f5e3Sopenharmony_ci if (!breakpoint.has_value()) { 2944514f5e3Sopenharmony_ci return false; 2954514f5e3Sopenharmony_ci } 2964514f5e3Sopenharmony_ci JSThread *thread = ecmaVm_->GetJSThread(); 2974514f5e3Sopenharmony_ci auto condFuncRef = breakpoint.value().GetConditionFunction(); 2984514f5e3Sopenharmony_ci if (condFuncRef->IsFunction(ecmaVm_)) { 2994514f5e3Sopenharmony_ci LOG_DEBUGGER(INFO) << "BreakpointCondition: evaluating condition"; 3004514f5e3Sopenharmony_ci auto handlerPtr = std::make_shared<FrameHandler>(ecmaVm_->GetJSThread()); 3014514f5e3Sopenharmony_ci auto evalResult = DebuggerApi::EvaluateViaFuncCall(const_cast<EcmaVM *>(ecmaVm_), 3024514f5e3Sopenharmony_ci condFuncRef.ToLocal(ecmaVm_), handlerPtr); 3034514f5e3Sopenharmony_ci if (thread->HasPendingException()) { 3044514f5e3Sopenharmony_ci LOG_DEBUGGER(ERROR) << "BreakpointCondition: has pending exception"; 3054514f5e3Sopenharmony_ci thread->ClearException(); 3064514f5e3Sopenharmony_ci return false; 3074514f5e3Sopenharmony_ci } 3084514f5e3Sopenharmony_ci bool satisfied = evalResult->ToBoolean(ecmaVm_)->Value(); 3094514f5e3Sopenharmony_ci if (!satisfied) { 3104514f5e3Sopenharmony_ci LOG_DEBUGGER(INFO) << "BreakpointCondition: condition not meet"; 3114514f5e3Sopenharmony_ci return false; 3124514f5e3Sopenharmony_ci } 3134514f5e3Sopenharmony_ci } 3144514f5e3Sopenharmony_ci return true; 3154514f5e3Sopenharmony_ci} 3164514f5e3Sopenharmony_ci 3174514f5e3Sopenharmony_civoid JSDebugger::MethodEntry(JSHandle<Method> method, JSHandle<JSTaggedValue> envHandle) 3184514f5e3Sopenharmony_ci{ 3194514f5e3Sopenharmony_ci if (hooks_ == nullptr || !ecmaVm_->GetJsDebuggerManager()->IsDebugMode()) { 3204514f5e3Sopenharmony_ci return; 3214514f5e3Sopenharmony_ci } 3224514f5e3Sopenharmony_ci FrameHandler frameHandler(ecmaVm_->GetJSThread()); 3234514f5e3Sopenharmony_ci if (frameHandler.IsEntryFrame() || frameHandler.IsBuiltinFrame()) { 3244514f5e3Sopenharmony_ci return; 3254514f5e3Sopenharmony_ci } 3264514f5e3Sopenharmony_ci auto *debuggerMgr = ecmaVm_->GetJsDebuggerManager(); 3274514f5e3Sopenharmony_ci debuggerMgr->MethodEntry(method, envHandle); 3284514f5e3Sopenharmony_ci 3294514f5e3Sopenharmony_ci // scriptParsed for sendable object 3304514f5e3Sopenharmony_ci if (method->IsSendableMethod()) { 3314514f5e3Sopenharmony_ci hooks_->SendableMethodEntry(method); 3324514f5e3Sopenharmony_ci } 3334514f5e3Sopenharmony_ci} 3344514f5e3Sopenharmony_ci 3354514f5e3Sopenharmony_civoid JSDebugger::MethodExit([[maybe_unused]] JSHandle<Method> method) 3364514f5e3Sopenharmony_ci{ 3374514f5e3Sopenharmony_ci if (hooks_ == nullptr || !ecmaVm_->GetJsDebuggerManager()->IsDebugMode()) { 3384514f5e3Sopenharmony_ci return; 3394514f5e3Sopenharmony_ci } 3404514f5e3Sopenharmony_ci FrameHandler frameHandler(ecmaVm_->GetJSThread()); 3414514f5e3Sopenharmony_ci if (frameHandler.IsEntryFrame() || frameHandler.IsBuiltinFrame()) { 3424514f5e3Sopenharmony_ci return; 3434514f5e3Sopenharmony_ci } 3444514f5e3Sopenharmony_ci auto *debuggerMgr = ecmaVm_->GetJsDebuggerManager(); 3454514f5e3Sopenharmony_ci debuggerMgr->MethodExit(method); 3464514f5e3Sopenharmony_ci} 3474514f5e3Sopenharmony_ci} // namespace panda::tooling::ecmascript 348