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_TYPES_H
17 #define FRAMEWORKS_BRIDGE_DECLARATIVE_FRONTEND_ENGINE_JSI_JSI_TYPES_H
18 
19 #include <string>
20 
21 #include "ecmascript/napi/include/jsnapi.h"
22 
23 #include "frameworks/bridge/declarative_frontend/engine/jsi/jsi_declarative_engine.h"
24 #include "frameworks/bridge/declarative_frontend/engine/jsi/jsi_fwd.h"
25 #include "frameworks/bridge/declarative_frontend/engine/jsi/jsi_value_conversions.h"
26 
27 #define FAKE_PTR_FOR_FUNCTION_ACCESS(klass) \
28     const klass* operator->() const         \
29     {                                       \
30         return this;                        \
31     }
32 
33 namespace OHOS::Ace::Framework {
34 
35 using JsiFunctionCallback = panda::Local<panda::JSValueRef> (*)(panda::JsiRuntimeCallInfo*);
36 using EcmaVM = panda::ecmascript::EcmaVM;
37 
38 template<typename T>
39 class JsiType {
40 public:
41     JsiType() = default;
42     JsiType(const JsiType& rhs);
43     JsiType(JsiType&& rhs);
44     virtual ~JsiType() = default;
45 
46     explicit JsiType(panda::Local<T> val);
47     explicit JsiType(const panda::CopyableGlobal<T>& other);
48     explicit JsiType(const EcmaVM *vm, panda::Local<T> val);
49 
50     template<typename S>
51     explicit JsiType(panda::Local<S> val);
52 
53     JsiType& operator=(const JsiType& rhs);
54     JsiType& operator=(JsiType&& rhs);
55 
56     template<typename S>
Cast(const JsiType<S> & that)57     static JsiType<T> Cast(const JsiType<S>& that)
58     {
59         return JsiType<T>(that.GetHandle());
60     }
61 
62     template<class... Args>
63     static JsiType<T> New(Args &&... args);
64 
65     void SetWeakCallback(void *ref, panda::WeakRefClearCallBack callback);
66     const panda::CopyableGlobal<T>& GetHandle() const;
67     const panda::CopyableGlobal<T>& operator->() const;
68     Local<T> GetLocalHandle() const;
69     bool IsEmpty() const;
70     bool IsWeak() const;
71     void Reset();
72     operator panda::CopyableGlobal<T>() const;
73 
74     const EcmaVM* GetEcmaVM() const;
75 
76 private:
77     panda::CopyableGlobal<T> handle_;
78 };
79 
80 class JsiValue : public JsiType<panda::JSValueRef> {
81 public:
82     JsiValue() = default;
83     explicit JsiValue(const panda::CopyableGlobal<panda::JSValueRef>& val);
84     explicit JsiValue(panda::Local<panda::JSValueRef> val);
85     explicit JsiValue(const EcmaVM *vm, panda::Local<panda::JSValueRef> val);
86     ~JsiValue() override = default;
87 
88     bool IsEmpty() const;
89     bool IsFunction() const;
90     bool IsNumber() const;
91     bool IsString() const;
92     bool IsBoolean() const;
93     bool IsObject() const;
94     bool IsArray() const;
95     bool IsArrayBuffer() const;
96     bool IsUint8ClampedArray() const;
97     bool IsUndefined() const;
98     bool IsNull() const;
99     std::string ToString() const;
100     bool ToBoolean() const;
101 
102     template<typename T>
103     T ToNumber() const;
104 
105     static JsiRef<JsiValue> Undefined();
106     static JsiRef<JsiValue> Null();
107     static JsiRef<JsiValue> True();
108     static JsiRef<JsiValue> False();
109 
110     FAKE_PTR_FOR_FUNCTION_ACCESS(JsiValue)
111 };
112 
113 /**
114  * @brief A wrapper around a panda::StringRef
115  *
116  */
117 class JsiString : public JsiType<panda::StringRef> {
118 public:
119     JsiString() = default;
120     explicit JsiString(panda::Local<panda::StringRef> val);
121     explicit JsiString(const panda::CopyableGlobal<panda::StringRef>& val);
122     ~JsiString() override = default;
123 
124     static panda::Local<panda::StringRef> New(const char* str);
125     static panda::Local<panda::StringRef> New(const std::string& str);
126     FAKE_PTR_FOR_FUNCTION_ACCESS(JsiString)
127 };
128 
129 /**
130  * @brief A wrapper around a panda::ArrayRef
131  *
132  */
133 class JsiArray : public JsiType<panda::ArrayRef> {
134 public:
135     JsiArray();
136     explicit JsiArray(panda::Local<panda::ArrayRef> val);
137     explicit JsiArray(const EcmaVM *vm, panda::Local<panda::ArrayRef> val);
138     explicit JsiArray(const panda::CopyableGlobal<panda::ArrayRef>& val);
139     ~JsiArray() override = default;
140     JsiRef<JsiValue> GetValueAt(size_t index) const;
141     void SetValueAt(size_t index, JsiRef<JsiValue> value) const;
142     JsiRef<JsiValue> GetProperty(const char* prop) const;
143     JsiRef<JsiValue> GetProperty(int32_t propertyIndex) const;
144     size_t Length() const;
145     void SetLength(size_t length) const;
146     bool IsArray() const;
147     FAKE_PTR_FOR_FUNCTION_ACCESS(JsiArray)
148 };
149 
150 /**
151  * @brief A wrapper around a panda::ArrayBufferRef
152  *
153  */
154 class JsiArrayBuffer : public JsiType<panda::ArrayBufferRef> {
155 public:
156     JsiArrayBuffer() = default;
157     explicit JsiArrayBuffer(panda::Local<panda::ArrayBufferRef> val);
158     explicit JsiArrayBuffer(const panda::CopyableGlobal<panda::ArrayBufferRef>& val);
159     int32_t ByteLength() const;
160     void* GetBuffer() const;
161     void Detach() const;
162     bool IsDetach() const;
163     ~JsiArrayBuffer() override = default;
164     FAKE_PTR_FOR_FUNCTION_ACCESS(JsiArrayBuffer)
165 };
166 
167 /**
168  * @brief A wrapper around a panda::Uint8ClampedArrayRef
169  *
170  */
171 class JsiUint8ClampedArray : public JsiType<panda::Uint8ClampedArrayRef> {
172 public:
173     JsiUint8ClampedArray() = default;
174     explicit JsiUint8ClampedArray(panda::Local<panda::Uint8ClampedArrayRef> val);
175     explicit JsiUint8ClampedArray(const panda::CopyableGlobal<panda::Uint8ClampedArrayRef>& val);
176     ~JsiUint8ClampedArray() override = default;
177     JsiRef<JsiArrayBuffer> GetArrayBuffer() const;
178     FAKE_PTR_FOR_FUNCTION_ACCESS(JsiUint8ClampedArray)
179 };
180 
181 /**
182  * @brief A wrapper around panda::ObjectRef
183  *
184  */
185 class JsiObject : public JsiType<panda::ObjectRef> {
186 public:
187     JsiObject();
188     explicit JsiObject(panda::Local<panda::ObjectRef> val);
189     explicit JsiObject(const EcmaVM *vm, panda::Local<panda::ObjectRef> val);
190     explicit JsiObject(const panda::CopyableGlobal<panda::ObjectRef>& val);
191     bool IsUndefined() const;
192     ~JsiObject() override = default;
193     enum InternalFieldIndex { INSTANCE = 0 };
194 
195     template<typename T>
196     T* Unwrap() const;
197 
198     template<typename T>
199     void Wrap(T* data) const;
200 
201     JsiRef<JsiArray> GetPropertyNames() const;
202     JsiRef<JsiValue> GetProperty(const char* prop) const;
203     JsiRef<JsiValue> GetProperty(int32_t propertyIndex) const;
204     bool HasProperty(int32_t propertyIndex) const;
205     bool HasProperty(const char* prop) const;
206     JsiRef<JsiValue> ToJsonObject(const char* value) const;
207 
208     template<typename T>
209     T GetPropertyValue(int32_t propertyIndex, T defaultValue) const;
210 
211     template<typename T>
212     T GetPropertyValue(const char* prop, T defaultValue) const;
213 
214     template<typename T>
215     void SetProperty(int32_t propertyIndex, const T value) const;
216 
217     template<typename T>
218     void SetProperty(const char* prop, const T value) const;
219     void SetPropertyJsonObject(const char* prop, const char* value) const;
220     void SetPropertyObject(const char* prop, JsiRef<JsiValue> value) const;
221 
222     FAKE_PTR_FOR_FUNCTION_ACCESS(JsiObject)
223 };
224 
225 /**
226  * @brief A wrapper around panda::FunctionRef
227  *
228  */
229 class JsiFunction : public JsiType<panda::FunctionRef> {
230 public:
231     JsiFunction();
232     explicit JsiFunction(panda::Local<panda::FunctionRef> val);
233     explicit JsiFunction(const EcmaVM *vm, panda::Local<panda::FunctionRef> val);
234     explicit JsiFunction(const panda::CopyableGlobal<panda::FunctionRef>& val);
235     ~JsiFunction() override = default;
236 
237     JsiRef<JsiValue> Call(JsiRef<JsiValue> thisVal, int argc = 0, JsiRef<JsiValue> argv[] = nullptr) const;
238     static panda::Local<panda::FunctionRef> New(JsiFunctionCallback func);
239 
240     FAKE_PTR_FOR_FUNCTION_ACCESS(JsiFunction)
241 };
242 
243 class JsiObjTemplate : public JsiObject {
244 public:
245     JsiObjTemplate() = default;
246     explicit JsiObjTemplate(panda::Local<panda::ObjectRef> val);
247     explicit JsiObjTemplate(const panda::CopyableGlobal<panda::ObjectRef>& val);
248     ~JsiObjTemplate() override = default;
249 
250     void SetInternalFieldCount(int32_t count) const;
251     JsiRef<JsiObject> NewInstance() const;
252     static panda::Local<panda::JSValueRef> New();
253 
254     FAKE_PTR_FOR_FUNCTION_ACCESS(JsiObjTemplate)
255 };
256 
257 struct JsiExecutionContext {
258     panda::ecmascript::EcmaVM* vm_ = nullptr;
259 };
260 
261 class JsiCallbackInfo {
262 public:
263     JsiCallbackInfo(panda::JsiRuntimeCallInfo* info);
264     ~JsiCallbackInfo() = default;
265     JsiCallbackInfo(const JsiCallbackInfo&) = delete;
266     JsiCallbackInfo& operator=(const JsiCallbackInfo&) = delete;
267 
268     JsiRef<JsiValue> operator[](size_t index) const;
269     JsiRef<JsiObject> This() const;
270     int Length() const;
271 
272     template<typename T>
273     void SetReturnValue(T* instance) const;
274 
275     template<typename T>
276     void SetReturnValue(JsiRef<T> val) const;
277 
278     void ReturnSelf() const;
279 
GetReturnValue()280     std::variant<void*, panda::CopyableGlobal<panda::JSValueRef>> GetReturnValue()
281     {
282         return retVal_;
283     }
284 
GetJsiRuntimeCallInfo()285     panda::JsiRuntimeCallInfo* GetJsiRuntimeCallInfo() const
286     {
287         return info_;
288     }
289 
GetExecutionContext()290     JsiExecutionContext GetExecutionContext() const
291     {
292         return JsiExecutionContext { info_->GetVM() };
293     }
294 
GetVm()295     panda::ecmascript::EcmaVM* GetVm() const
296     {
297         return info_->GetVM();
298     }
299 
SetSize(size_t size)300     void SetSize(size_t size) const
301     {
302         size_ = size;
303     }
304 
GetSize()305     size_t GetSize() const
306     {
307         return size_;
308     }
309 
310     template<typename T>
311     T* UnwrapArg(size_t index) const;
312     bool GetBooleanArg(size_t index, bool& value) const;
313     bool GetInt32Arg(size_t index, int32_t& value) const;
314     bool GetUint32Arg(size_t index, uint32_t& value) const;
315     bool GetDoubleArg(size_t index, double& value) const;
316     bool GetDoubleArrayArg(size_t index, std::vector<double>& valueArr) const;
317     bool GetStringArg(size_t index, std::string& value) const;
318 
319 private:
320     mutable size_t size_ = 0;
321     panda::JsiRuntimeCallInfo* info_ = nullptr;
322     mutable std::variant<void*, panda::CopyableGlobal<panda::JSValueRef>> retVal_;
323 };
324 
325 class JsiGCMarkCallbackInfo {
326 public:
327     template<typename T>
Mark(const JsiRef<T> & val)328     void Mark(const JsiRef<T>& val) const
329     {}
330 };
331 
332 class JsiDate : public JsiType<panda::DateRef> {
333 public:
334     JsiDate() = default;
335     explicit JsiDate(panda::Local<panda::DateRef> val);
336     explicit JsiDate(const panda::CopyableGlobal<panda::DateRef>& val);
337     ~JsiDate() override = default;
338 
339     static JsiRef<JsiValue> New(double value);
340     FAKE_PTR_FOR_FUNCTION_ACCESS(JsiDate)
341 };
342 
343 class JsiException {
344 public:
345     template<typename... Args>
346     static void Throw(const char* format, Args... args);
347     template<typename... Args>
348     static void Throw(int32_t code, const char* format, Args... args);
349     template<typename... Args>
350     static void ThrowRangeError(const char* format, Args... args);
351     template<typename... Args>
352     static void ThrowReferenceError(const char* format, Args... args);
353     template<typename... Args>
354     static void ThrowSyntaxError(const char* format, Args... args);
355     template<typename... Args>
356     static void ThrowTypeError(const char* format, Args... args);
357     template<typename... Args>
358     static void ThrowEvalError(const char* format, Args... args);
359 };
360 
361 } // namespace OHOS::Ace::Framework
362 
363 #include "jsi_types.inl"
364 
365 #endif // FRAMEWORKS_BRIDGE_DECLARATIVE_FRONTEND_ENGINE_JSI_JSI_TYPES_H
366