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/js_handle.h" 22 #include "ecmascript/js_thread.h" 23 #include "ecmascript/method.h" 24 25 namespace panda::ecmascript::tooling { 26 class RuntimeListener { 27 public: 28 RuntimeListener() = default; 29 virtual ~RuntimeListener() = default; 30 DEFAULT_COPY_SEMANTIC(RuntimeListener); 31 DEFAULT_MOVE_SEMANTIC(RuntimeListener); 32 33 virtual void LoadModule(std::string_view name, std::string_view) = 0; 34 35 virtual void BytecodePcChanged(JSThread *thread, JSHandle<Method> method, 36 uint32_t bcOffset) = 0; 37 38 virtual bool HandleDebuggerStmt(JSHandle<Method> method, uint32_t bcOffset) = 0; 39 virtual void VmStart() = 0; 40 virtual void VmDeath() = 0; 41 virtual void NativeCalling(const void *nativeAddress) = 0; 42 virtual void NativeReturn(const void *nativeAddress) = 0; 43 virtual void MethodEntry(JSHandle<Method> method, JSHandle<JSTaggedValue> envHandle) = 0; 44 virtual void MethodExit(JSHandle<Method> method) = 0; 45 }; 46 47 class NotificationManager { 48 public: 49 NotificationManager() = default; 50 ~NotificationManager() = default; 51 NO_COPY_SEMANTIC(NotificationManager); 52 NO_MOVE_SEMANTIC(NotificationManager); 53 AddListener(RuntimeListener * listener)54 void AddListener(RuntimeListener *listener) 55 { 56 if (listener != nullptr) { 57 listeners_.emplace_back(listener); 58 } 59 } RemoveListener(RuntimeListener * listener)60 void RemoveListener(RuntimeListener *listener) 61 { 62 for (auto it = listeners_.begin(); it != listeners_.end(); ++it) { 63 if (*it == listener) { 64 listeners_.erase(it); 65 return; 66 } 67 } 68 } 69 LoadModuleEvent(std::string_view name,std::string_view entryPoint)70 void LoadModuleEvent(std::string_view name, std::string_view entryPoint) const 71 { 72 for (auto it: listeners_) { 73 it->LoadModule(name, entryPoint); 74 } 75 } 76 BytecodePcChangedEvent(JSThread * thread,Method * method,uint32_t bcOffset)77 void BytecodePcChangedEvent(JSThread *thread, Method *method, uint32_t bcOffset) const 78 { 79 [[maybe_unused]] EcmaHandleScope handleScope(thread); 80 JSHandle<Method> methodHandle(thread, method); 81 for (auto it: listeners_) { 82 it->BytecodePcChanged(thread, methodHandle, bcOffset); 83 } 84 } 85 DebuggerStmtEvent(JSThread * thread,Method * method,uint32_t bcOffset)86 void DebuggerStmtEvent(JSThread *thread, Method *method, uint32_t bcOffset) const 87 { 88 JSHandle<Method> methodHandle(thread, method); 89 for (auto it: listeners_) { 90 it->HandleDebuggerStmt(methodHandle, bcOffset); 91 } 92 } 93 NativeCallingEvent(const void * nativeAddress)94 void NativeCallingEvent(const void *nativeAddress) const 95 { 96 for (auto it: listeners_) { 97 it->NativeCalling(nativeAddress); 98 } 99 } 100 NativeReturnEvent(const void * nativeAddress)101 void NativeReturnEvent(const void *nativeAddress) const 102 { 103 for (auto it: listeners_) { 104 it->NativeReturn(nativeAddress); 105 } 106 } 107 VmStartEvent()108 void VmStartEvent() const 109 { 110 for (auto it: listeners_) { 111 it->VmStart(); 112 } 113 } VmDeathEvent()114 void VmDeathEvent() const 115 { 116 for (auto it: listeners_) { 117 it->VmDeath(); 118 } 119 } 120 MethodEntryEvent(JSThread * thread,Method * method,JSTaggedValue env)121 void MethodEntryEvent(JSThread *thread, Method *method, JSTaggedValue env) const 122 { 123 JSHandle<Method> methodHandle(thread, method); 124 JSHandle<JSTaggedValue> envHandle(thread, env); 125 for (auto it: listeners_) { 126 it->MethodEntry(methodHandle, envHandle); 127 } 128 } MethodExitEvent(JSThread * thread,Method * method)129 void MethodExitEvent(JSThread *thread, Method *method) const 130 { 131 JSHandle<Method> methodHandle(thread, method); 132 for (auto it: listeners_) { 133 it->MethodExit(methodHandle); 134 } 135 } 136 private: 137 std::vector<RuntimeListener*> listeners_; 138 }; 139 } // panda::ecmascript::tooling 140 141 #endif // ECMASCRIPT_DEBUGGER_NOTIFICATION_MANAGER_H