/* * Copyright (c) 2022-2024 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. */ #ifndef ECMASCRIPT_DEBUGGER_JS_DEBUGGER_MANAGER_H #define ECMASCRIPT_DEBUGGER_JS_DEBUGGER_MANAGER_H #include #include #include "ecmascript/debugger/hot_reload_manager.h" #include "ecmascript/debugger/notification_manager.h" #include "ecmascript/debugger/dropframe_manager.h" #include "ecmascript/ecma_vm.h" #include "ecmascript/interpreter/frame_handler.h" #include "ecmascript/js_thread.h" #include "ecmascript/lexical_env.h" #include "ecmascript/napi/include/jsnapi.h" #include "ecmascript/global_handle_collection.h" #include "libpandabase/os/library_loader.h" namespace panda::ecmascript::tooling { class ProtocolHandler; class JsDebuggerManager { public: using LibraryHandle = os::library_loader::LibraryHandle; using ObjectUpdaterFunc = std::function, const std::string&)>; using SingleStepperFunc = std::function; using ReturnNativeFunc = std::function; explicit JsDebuggerManager(const EcmaVM *vm) : hotReloadManager_(vm) { jsThread_ = vm->GetJSThread(); } ~JsDebuggerManager() = default; NO_COPY_SEMANTIC(JsDebuggerManager); NO_MOVE_SEMANTIC(JsDebuggerManager); NotificationManager *GetNotificationManager() const { return const_cast(¬ificationManager_); } HotReloadManager *GetHotReloadManager() const { return const_cast(&hotReloadManager_); } void SetDebugMode(bool isDebugMode) { if (isDebugMode_ == isDebugMode) { return; } isDebugMode_ = isDebugMode; if (isDebugMode) { jsThread_->SetDebugModeState(); } else { jsThread_->ResetDebugModeState(); } } bool IsDebugMode() const { return isDebugMode_; } void SetIsDebugApp(bool isDebugApp) { isDebugApp_ = isDebugApp; } bool IsDebugApp() const { return isDebugApp_; } void SetFaApp(bool isFaApp) { isFaApp_ = isFaApp; } bool GetFaApp() const { return isFaApp_; } void SetMixedStackEnabled(bool mixedStackEnabled) { isMixedStackEnabled_ = mixedStackEnabled; } bool IsMixedStackEnabled() const { return isMixedStackEnabled_; } void SetMixedDebugEnabled(bool enabled) { isMixedDebugEnabled_ = enabled; } bool IsMixedDebugEnabled() const { return isMixedDebugEnabled_; } void SetDebuggerHandler(ProtocolHandler *debuggerHandler) { debuggerHandler_ = debuggerHandler; } ProtocolHandler *GetDebuggerHandler() const { return debuggerHandler_; } void SetDebugLibraryHandle(LibraryHandle handle) { debuggerLibraryHandle_ = std::move(handle); } const LibraryHandle &GetDebugLibraryHandle() const { return debuggerLibraryHandle_; } bool GetSignalState() const { return isSignalInterrupt_; } void SetSignalState(bool isSignalInterrupt) { isSignalInterrupt_ = isSignalInterrupt; } void SetEvalFrameHandler(std::shared_ptr frameHandler) { frameHandler_ = frameHandler; } const std::shared_ptr &GetEvalFrameHandler() const { return frameHandler_; } void SetLocalScopeUpdater(ObjectUpdaterFunc *updaterFunc) { updaterFunc_ = updaterFunc; } void NotifyScopeUpdated(std::string_view varName, Local value, const std::string& scope) { if (updaterFunc_ != nullptr) { (*updaterFunc_)(frameHandler_.get(), varName, value, scope); } } void SetJSReturnNativeFunc(ReturnNativeFunc *returnNative) { returnNative_ = returnNative; } void NotifyReturnNative() { if (returnNative_ != nullptr) { (*returnNative_)(); } } void SetStepperFunc(SingleStepperFunc *stepperFunc) { stepperFunc_ = stepperFunc; } void ClearSingleStepper() { if (stepperFunc_ != nullptr) { (*stepperFunc_)(); } } void MethodEntry(JSHandle method, JSHandle envHandle) { dropframeManager_.MethodEntry(jsThread_, method, envHandle); } void MethodExit(JSHandle method) { dropframeManager_.MethodExit(jsThread_, method); } void DropLastFrame() { dropframeManager_.DropLastFrame(jsThread_); } uint32_t GetPromiseQueueSizeRecordOfTopFrame() { return dropframeManager_.GetPromiseQueueSizeRecordOfTopFrame(); } bool CheckIsSendableMethod() { return dropframeManager_.CheckIsSendableMethod(); } void EnableObjectHashDisplay() { isObjHashDisplayEnabled_ = true; } void DisableObjectHashDisplay() { isObjHashDisplayEnabled_ = false; } bool IsObjHashDisplayEnabled() { return isObjHashDisplayEnabled_; } void EnableSerializationTimeoutCheck() { isSerializationTimeoutCheckEnabled_ = true; } void DisableSerializationTimeoutCheck() { isSerializationTimeoutCheckEnabled_ = false; } bool IsSerializationTimeoutCheckEnabled() { return isSerializationTimeoutCheckEnabled_; } void SetSerializationCheckThreshold(int threshold) { serializationCheckThreshold_ = threshold; } int32_t GetSerializationCheckThreshold() const { return serializationCheckThreshold_; } static void AddJsDebuggerManager(int tid, JsDebuggerManager *jsDebuggerManager); static JsDebuggerManager* GetJsDebuggerManager(int tid); static void DeleteJsDebuggerManager(int tid); private: bool isDebugMode_ {false}; bool isDebugApp_ {false}; bool isFaApp_ {false}; bool isMixedDebugEnabled_ { false }; bool isMixedStackEnabled_ { false }; bool isSignalInterrupt_ {false}; bool isObjHashDisplayEnabled_ { true }; ProtocolHandler *debuggerHandler_ {nullptr}; LibraryHandle debuggerLibraryHandle_ {nullptr}; ObjectUpdaterFunc *updaterFunc_ {nullptr}; SingleStepperFunc *stepperFunc_ {nullptr}; ReturnNativeFunc *returnNative_ {nullptr}; JSThread *jsThread_ {nullptr}; std::shared_ptr frameHandler_ {nullptr}; DropframeManager dropframeManager_; NotificationManager notificationManager_; HotReloadManager hotReloadManager_; // Serialization / DeSerialization Timeout flag bool isSerializationTimeoutCheckEnabled_ { false }; // in milliseconds static constexpr int32_t DEFAULT_THRESHOLD = 8; int32_t serializationCheckThreshold_ { DEFAULT_THRESHOLD }; static std::unordered_map jsDebuggerManagerMap_; static std::shared_mutex mutex_; }; } // panda::ecmascript::tooling #endif // ECMASCRIPT_DEBUGGER_JS_DEBUGGER_MANAGER_H