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