1 /* 2 * Copyright (c) 2021-2024 Huawei Device Co., Ltd. 3 * Licensed under the Apache License, Version 2.0 (the "License"); 4 * you may not use this file except in compliance with the License. 5 * You may obtain a copy of the License at 6 * 7 * http://www.apache.org/licenses/LICENSE-2.0 8 * 9 * Unless required by applicable law or agreed to in writing, software 10 * distributed under the License is distributed on an "AS IS" BASIS, 11 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 12 * See the License for the specific language governing permissions and 13 * limitations under the License. 14 */ 15 16 #ifndef ECMASCRIPT_DEBUGGER_NOTIFICATION_MANAGER_H 17 #define ECMASCRIPT_DEBUGGER_NOTIFICATION_MANAGER_H 18 19 #include <string_view> 20 21 #include "ecmascript/dfx/stackinfo/async_stack_trace.h" 22 #include "ecmascript/js_handle.h" 23 #include "ecmascript/js_thread.h" 24 #include "ecmascript/method.h" 25 26 namespace panda::ecmascript::tooling { 27 class RuntimeListener { 28 public: 29 RuntimeListener() = default; 30 virtual ~RuntimeListener() = default; 31 DEFAULT_COPY_SEMANTIC(RuntimeListener); 32 DEFAULT_MOVE_SEMANTIC(RuntimeListener); 33 34 virtual void LoadModule(std::string_view name, std::string_view) = 0; 35 36 virtual void BytecodePcChanged(JSThread *thread, JSHandle<Method> method, 37 uint32_t bcOffset) = 0; 38 39 virtual bool HandleDebuggerStmt(JSHandle<Method> method, uint32_t bcOffset) = 0; 40 virtual void VmStart() = 0; 41 virtual void VmDeath() = 0; 42 virtual void NativeCalling(const void *nativeAddress) = 0; 43 virtual void NativeReturn(const void *nativeAddress) = 0; 44 virtual void MethodEntry(JSHandle<Method> method, JSHandle<JSTaggedValue> envHandle) = 0; 45 virtual void MethodExit(JSHandle<Method> method) = 0; 46 virtual void GenerateAsyncFrames(std::shared_ptr<AsyncStack> asyncStack, bool skipTopFrame) = 0; 47 }; 48 49 class NotificationManager { 50 public: 51 NotificationManager() = default; 52 ~NotificationManager() = default; 53 NO_COPY_SEMANTIC(NotificationManager); 54 NO_MOVE_SEMANTIC(NotificationManager); 55 AddListener(RuntimeListener * listener)56 void AddListener(RuntimeListener *listener) 57 { 58 if (listener != nullptr) { 59 listeners_.emplace_back(listener); 60 } 61 } RemoveListener(RuntimeListener * listener)62 void RemoveListener(RuntimeListener *listener) 63 { 64 for (auto it = listeners_.begin(); it != listeners_.end(); ++it) { 65 if (*it == listener) { 66 listeners_.erase(it); 67 return; 68 } 69 } 70 } 71 GenerateAsyncFramesEvent(std::shared_ptr<AsyncStack> asyncStack,bool skipTopFrame)72 void GenerateAsyncFramesEvent(std::shared_ptr<AsyncStack> asyncStack, bool skipTopFrame) const 73 { 74 for (auto it: listeners_) { 75 it->GenerateAsyncFrames(asyncStack, skipTopFrame); 76 } 77 } 78 LoadModuleEvent(std::string_view name,std::string_view entryPoint)79 void LoadModuleEvent(std::string_view name, std::string_view entryPoint) const 80 { 81 for (auto it: listeners_) { 82 it->LoadModule(name, entryPoint); 83 } 84 } 85 BytecodePcChangedEvent(JSThread * thread,Method * method,uint32_t bcOffset)86 void BytecodePcChangedEvent(JSThread *thread, Method *method, uint32_t bcOffset) const 87 { 88 [[maybe_unused]] EcmaHandleScope handleScope(thread); 89 JSHandle<Method> methodHandle(thread, method); 90 for (auto it: listeners_) { 91 it->BytecodePcChanged(thread, methodHandle, bcOffset); 92 } 93 } 94 DebuggerStmtEvent(JSThread * thread,Method * method,uint32_t bcOffset)95 void DebuggerStmtEvent(JSThread *thread, Method *method, uint32_t bcOffset) const 96 { 97 JSHandle<Method> methodHandle(thread, method); 98 for (auto it: listeners_) { 99 it->HandleDebuggerStmt(methodHandle, bcOffset); 100 } 101 } 102 NativeCallingEvent(const void * nativeAddress)103 void NativeCallingEvent(const void *nativeAddress) const 104 { 105 for (auto it: listeners_) { 106 it->NativeCalling(nativeAddress); 107 } 108 } 109 NativeReturnEvent(const void * nativeAddress)110 void NativeReturnEvent(const void *nativeAddress) const 111 { 112 for (auto it: listeners_) { 113 it->NativeReturn(nativeAddress); 114 } 115 } 116 VmStartEvent()117 void VmStartEvent() const 118 { 119 for (auto it: listeners_) { 120 it->VmStart(); 121 } 122 } VmDeathEvent()123 void VmDeathEvent() const 124 { 125 for (auto it: listeners_) { 126 it->VmDeath(); 127 } 128 } 129 MethodEntryEvent(JSThread * thread,Method * method,JSTaggedValue env)130 void MethodEntryEvent(JSThread *thread, Method *method, JSTaggedValue env) const 131 { 132 JSHandle<Method> methodHandle(thread, method); 133 JSHandle<JSTaggedValue> envHandle(thread, env); 134 for (auto it: listeners_) { 135 it->MethodEntry(methodHandle, envHandle); 136 } 137 } MethodExitEvent(JSThread * thread,Method * method)138 void MethodExitEvent(JSThread *thread, Method *method) const 139 { 140 JSHandle<Method> methodHandle(thread, method); 141 for (auto it: listeners_) { 142 it->MethodExit(methodHandle); 143 } 144 } 145 private: 146 std::vector<RuntimeListener*> listeners_; 147 }; 148 } // panda::ecmascript::tooling 149 150 #endif // ECMASCRIPT_DEBUGGER_NOTIFICATION_MANAGER_H