1 /* 2 * Copyright (c) 2021 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 FRAMEWORKS_BRIDGE_DECLARATIVE_FRONTEND_ENGINE_JSI_JSI_REF_H 17 #define FRAMEWORKS_BRIDGE_DECLARATIVE_FRONTEND_ENGINE_JSI_JSI_REF_H 18 19 #include "frameworks/bridge/declarative_frontend/engine/jsi/jsi_types.h" 20 21 namespace OHOS::Ace::Framework { 22 23 template<typename T> 24 class JsiWeak; 25 26 /** 27 * \brief A class template that holds a strong reference to a javascript value. 28 * Further in the text, when we talk about "javascript value" we refer to its representation within C++. 29 * Such are Value, Object, Array, Function, etc. 30 * 31 * A strong reference will increase the reference count of the holding javascript value when constructed, 32 * copied or assigned, and will decrease the reference count when destroyed. 33 * 34 * A strong reference to a javascript value should only be held when sharing it among owners that outlive 35 * said value. All other cases should use \p JSWeak. For example a row containing several buttons should 36 * hold a strong reference, but those buttons should hold a weak reference to the parent row if that is 37 * what the application requires, otherwise a circular dependency is established and objects do not get 38 * collected by the garbage collector. 39 * 40 * \code{.cpp} 41 * \endcode 42 * 43 * 3. \p FunctionCallback and \p MemberFunctionCallback corresponding to ESI callback signatures: 44 * \code{.cpp} 45 * \endcode 46 * 47 * 48 * \tparam A javascript value (Value, Object, Array, Function, etc.) 49 * \example 50 * \code{.cpp} 51 * \endcode 52 * 53 * \class JsiRef 54 * \alias JSRef 55 */ 56 template<typename T> 57 class JsiRef { 58 public: 59 using wrappedT = panda::Local<panda::ObjectRef>; 60 JsiRef()61 JsiRef() {} JsiRef(const T & val)62 explicit JsiRef(const T& val) : value_(val) {} ~JsiRef()63 ~JsiRef() 64 { 65 value_.Reset(); 66 } 67 68 template<typename S> JsiRef(const JsiRef<S> & that)69 JsiRef(const JsiRef<S>& that) : value_(T::Cast(that.Get())) 70 {} 71 72 // We do not want implicit conversions from weak to strong reference JsiRef(const JsiWeak<T> & rhs)73 explicit JsiRef(const JsiWeak<T>& rhs) 74 { 75 *this = rhs.Lock(); 76 } 77 78 template<typename... Args> Make(Args &&...args)79 static JsiRef<T> Make(Args&&... args) 80 { 81 auto obj = T { args... }; 82 return JsiRef<T>(obj); 83 } 84 Claim(T && val)85 static JsiRef<T> Claim(T&& val) 86 { 87 return JsiRef<T>(std::forward<T>(val)); 88 } 89 90 template<typename S> Cast(const JsiRef<S> & that)91 static JsiRef<T> Cast(const JsiRef<S>& that) 92 { 93 return JsiRef<T>::Make(T::Cast(that.Get())); 94 } 95 96 template<class... Args> New(Args &&...args)97 static JsiRef<T> New(Args&&... args) 98 { 99 return JsiRef<T>::Make(T::New(std::forward<Args>(args)...)); 100 } 101 JsiRef(const JsiRef<T> & rhs)102 JsiRef(const JsiRef<T>& rhs) : value_(rhs.value_) {} 103 JsiRef(JsiRef<T> && rhs)104 JsiRef(JsiRef<T>&& rhs) : value_(std::move(rhs.value_)) 105 { 106 rhs.value_.Reset(); 107 } 108 109 JsiRef<T>& operator=(const JsiRef<T>& rhs) 110 { 111 value_.Reset(); 112 value_ = rhs.value_; 113 return *this; 114 } 115 116 JsiRef<T>& operator=(JsiRef<T>&& rhs) 117 { 118 value_.Reset(); 119 value_ = std::move(rhs.value_); 120 rhs.value_.Reset(); 121 return *this; 122 } 123 IsEmpty()124 bool IsEmpty() const 125 { 126 return value_.IsEmpty(); 127 } 128 Reset()129 void Reset() 130 { 131 value_.Reset(); 132 } 133 134 template<typename U> Unwrap()135 typename std::enable_if_t<std::is_same_v<T, JsiObject>, U*> Unwrap() const 136 { 137 return value_.template Unwrap<U>(); 138 } 139 140 const T& operator->() const 141 { 142 return value_; 143 } 144 Get()145 T Get() const 146 { 147 return value_; 148 } 149 150 private: 151 T value_; 152 }; 153 154 template<typename T> 155 class JsiWeak { 156 public: 157 using wrappedT = panda::Local<panda::ObjectRef>; 158 JsiWeak()159 JsiWeak() {} ~JsiWeak()160 ~JsiWeak() 161 { 162 value_.Reset(); 163 } 164 JsiWeak(const JsiWeak<T> & rhs)165 JsiWeak(const JsiWeak<T>& rhs) : value_(rhs.value_) 166 { 167 value_.SetWeakCallback(this, Reset); 168 } 169 JsiWeak(JsiWeak<T> && rhs)170 JsiWeak(JsiWeak<T>&& rhs) : value_(std::move(rhs.value_)) 171 { 172 value_.SetWeakCallback(this, Reset); 173 rhs.value_.Reset(); 174 } 175 JsiWeak(const JsiRef<T> & rhs)176 explicit JsiWeak(const JsiRef<T>& rhs) : value_(rhs.Get()) 177 { 178 value_.SetWeakCallback(this, Reset); 179 } 180 181 JsiWeak<T>& operator=(const JsiWeak<T>& rhs) 182 { 183 value_.Reset(); 184 value_ = rhs.value_; 185 value_.SetWeakCallback(this, Reset); 186 return *this; 187 } 188 189 JsiWeak<T>& operator=(const JsiRef<T>& rhs) 190 { 191 value_ = rhs.Get(); 192 value_.SetWeakCallback(this, Reset); 193 return *this; 194 } 195 196 JsiWeak<T>& operator=(JsiWeak<T>&& rhs) 197 { 198 value_.Reset(); 199 value_ = std::move(rhs.value_); 200 value_.SetWeakCallback(this, Reset); 201 202 rhs.value_.Reset(); 203 return *this; 204 } 205 IsEmpty()206 bool IsEmpty() const 207 { 208 return value_.IsEmpty(); 209 } 210 Reset()211 void Reset() 212 { 213 value_.Reset(); 214 } 215 Lock()216 JsiRef<T> Lock() const 217 { 218 return JsiRef<T>(value_); 219 } 220 Reset(void * ref)221 static void Reset(void *ref) 222 { 223 auto that = reinterpret_cast<JsiWeak<T>*>(ref); 224 that->Reset(); 225 } 226 227 private: 228 T value_; 229 }; 230 231 } // namespace OHOS::Ace::Framework 232 #endif 233