• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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