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 using EcmaVM = panda::ecmascript::EcmaVM; 61 JsiRef()62 JsiRef() {} JsiRef(const T & val)63 explicit JsiRef(const T& val) : value_(val) {} ~JsiRef()64 ~JsiRef() 65 { 66 value_.Reset(); 67 } 68 69 template<typename S> JsiRef(const JsiRef<S> & that)70 JsiRef(const JsiRef<S>& that) : value_(T::Cast(that.Get())) 71 {} 72 73 // We do not want implicit conversions from weak to strong reference JsiRef(const JsiWeak<T> & rhs)74 explicit JsiRef(const JsiWeak<T>& rhs) 75 { 76 *this = rhs.Lock(); 77 } 78 79 template<typename... Args> Make(Args &&...args)80 static JsiRef<T> Make(Args&&... args) 81 { 82 auto obj = T { args... }; 83 return JsiRef<T>(obj); 84 } 85 86 template<typename... Args> FastMake(const EcmaVM * vm,Args &&...args)87 static JsiRef<T> FastMake(const EcmaVM *vm, Args&&... args) 88 { 89 auto obj = T { vm, args... }; 90 return JsiRef<T>(obj); 91 } 92 Claim(T && val)93 static JsiRef<T> Claim(T&& val) 94 { 95 return JsiRef<T>(std::forward<T>(val)); 96 } 97 98 template<typename S> Cast(const JsiRef<S> & that)99 static JsiRef<T> Cast(const JsiRef<S>& that) 100 { 101 return JsiRef<T>::Make(T::Cast(that.Get())); 102 } 103 104 template<class... Args> New(Args &&...args)105 static JsiRef<T> New(Args&&... args) 106 { 107 return JsiRef<T>::Make(T::New(std::forward<Args>(args)...)); 108 } 109 JsiRef(const JsiRef<T> & rhs)110 JsiRef(const JsiRef<T>& rhs) : value_(rhs.value_) {} 111 JsiRef(JsiRef<T> && rhs)112 JsiRef(JsiRef<T>&& rhs) : value_(std::move(rhs.value_)) 113 { 114 rhs.value_.Reset(); 115 } 116 117 JsiRef<T>& operator=(const JsiRef<T>& rhs) 118 { 119 value_.Reset(); 120 value_ = rhs.value_; 121 return *this; 122 } 123 124 JsiRef<T>& operator=(JsiRef<T>&& rhs) 125 { 126 value_.Reset(); 127 value_ = std::move(rhs.value_); 128 rhs.value_.Reset(); 129 return *this; 130 } 131 IsEmpty()132 bool IsEmpty() const 133 { 134 return value_.IsEmpty(); 135 } 136 Reset()137 void Reset() 138 { 139 value_.Reset(); 140 } 141 142 template<typename U> Unwrap()143 typename std::enable_if_t<std::is_same_v<T, JsiObject>, U*> Unwrap() const 144 { 145 return value_.template Unwrap<U>(); 146 } 147 148 const T& operator->() const 149 { 150 return value_; 151 } 152 Get()153 T Get() const 154 { 155 return value_; 156 } 157 158 private: 159 T value_; 160 }; 161 162 template<typename T> 163 class JsiWeak { 164 public: 165 using wrappedT = panda::Local<panda::ObjectRef>; 166 JsiWeak()167 JsiWeak() {} ~JsiWeak()168 ~JsiWeak() 169 { 170 value_.Reset(); 171 } 172 JsiWeak(const JsiWeak<T> & rhs)173 JsiWeak(const JsiWeak<T>& rhs) : value_(rhs.value_) 174 { 175 value_.SetWeakCallback(this, Reset); 176 } 177 JsiWeak(JsiWeak<T> && rhs)178 JsiWeak(JsiWeak<T>&& rhs) : value_(std::move(rhs.value_)) 179 { 180 value_.SetWeakCallback(this, Reset); 181 rhs.value_.Reset(); 182 } 183 JsiWeak(const JsiRef<T> & rhs)184 explicit JsiWeak(const JsiRef<T>& rhs) : value_(rhs.Get()) 185 { 186 value_.SetWeakCallback(this, Reset); 187 } 188 189 JsiWeak<T>& operator=(const JsiWeak<T>& rhs) 190 { 191 value_.Reset(); 192 value_ = rhs.value_; 193 value_.SetWeakCallback(this, Reset); 194 return *this; 195 } 196 197 JsiWeak<T>& operator=(const JsiRef<T>& rhs) 198 { 199 value_ = rhs.Get(); 200 value_.SetWeakCallback(this, Reset); 201 return *this; 202 } 203 204 JsiWeak<T>& operator=(JsiWeak<T>&& rhs) 205 { 206 value_.Reset(); 207 value_ = std::move(rhs.value_); 208 value_.SetWeakCallback(this, Reset); 209 210 rhs.value_.Reset(); 211 return *this; 212 } 213 IsEmpty()214 bool IsEmpty() const 215 { 216 return value_.IsEmpty(); 217 } 218 Reset()219 void Reset() 220 { 221 value_.Reset(); 222 } 223 Lock()224 JsiRef<T> Lock() const 225 { 226 return JsiRef<T>(value_); 227 } 228 Reset(void * ref)229 static void Reset(void *ref) 230 { 231 auto that = reinterpret_cast<JsiWeak<T>*>(ref); 232 that->Reset(); 233 } 234 235 private: 236 T value_; 237 }; 238 239 } // namespace OHOS::Ace::Framework 240 #endif 241