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 FOUNDATION_OHOS_ABILITYRUNTIME_JS_RUNTIME_UTILS_H
17 #define FOUNDATION_OHOS_ABILITYRUNTIME_JS_RUNTIME_UTILS_H
18
19 #include <cstdint>
20 #include <memory>
21 #include <type_traits>
22
23 #include "native_engine/native_engine.h"
24
25 #include "js_runtime.h"
26
27 namespace OHOS {
28 namespace AbilityRuntime {
29 template<class T>
ConvertNativeValueTo(NativeValue * value)30 inline T* ConvertNativeValueTo(NativeValue* value)
31 {
32 return (value != nullptr) ? static_cast<T*>(value->GetInterface(T::INTERFACE_ID)) : nullptr;
33 }
34
35 template<typename T, size_t N>
ArraySize(T (&)[N])36 inline constexpr size_t ArraySize(T (&)[N]) noexcept
37 {
38 return N;
39 }
40
41 template<class T>
CreateJsValue(NativeEngine & engine,const T & value)42 inline NativeValue* CreateJsValue(NativeEngine& engine, const T& value)
43 {
44 using ValueType = std::remove_cv_t<std::remove_reference_t<T>>;
45 if constexpr (std::is_same_v<ValueType, bool>) {
46 return engine.CreateBoolean(value);
47 } else if constexpr (std::is_arithmetic_v<ValueType>) {
48 return engine.CreateNumber(value);
49 } else if constexpr (std::is_same_v<ValueType, std::string>) {
50 return engine.CreateString(value.c_str(), value.length());
51 } else if constexpr (std::is_enum_v<ValueType>) {
52 return engine.CreateNumber(static_cast<std::make_signed_t<ValueType>>(value));
53 }
54 return engine.CreateUndefined();
55 }
56
57 template<class T>
ConvertFromJsValue(NativeEngine & engine,NativeValue * jsValue,T & value)58 inline bool ConvertFromJsValue(NativeEngine& engine, NativeValue* jsValue, T& value)
59 {
60 if (jsValue == nullptr) {
61 return false;
62 }
63
64 using ValueType = std::remove_cv_t<std::remove_reference_t<T>>;
65 if constexpr (std::is_same_v<ValueType, bool>) {
66 auto boolValue = ConvertNativeValueTo<NativeBoolean>(jsValue);
67 if (boolValue == nullptr) {
68 return false;
69 }
70 value = *boolValue;
71 return true;
72 } else if constexpr (std::is_arithmetic_v<ValueType>) {
73 auto numberValue = ConvertNativeValueTo<NativeNumber>(jsValue);
74 if (numberValue == nullptr) {
75 return false;
76 }
77 value = *numberValue;
78 return true;
79 } else if constexpr (std::is_same_v<ValueType, std::string>) {
80 auto stringValue = ConvertNativeValueTo<NativeString>(jsValue);
81 if (stringValue == nullptr) {
82 return false;
83 }
84 size_t len = stringValue->GetLength() + 1;
85 auto buffer = std::make_unique<char[]>(len);
86 size_t strLength = 0;
87 stringValue->GetCString(buffer.get(), len, &strLength);
88 value = buffer.get();
89 return true;
90 } else if constexpr (std::is_enum_v<ValueType>) {
91 auto numberValue = ConvertNativeValueTo<NativeNumber>(jsValue);
92 if (numberValue == nullptr) {
93 return false;
94 }
95 value = static_cast<ValueType>(static_cast<std::make_signed_t<ValueType>>(*numberValue));
96 return true;
97 }
98 }
99
100 template<class T>
CreateNativeArray(NativeEngine & engine,const std::vector<T> & data)101 NativeValue* CreateNativeArray(NativeEngine& engine, const std::vector<T>& data)
102 {
103 NativeValue* arrayValue = engine.CreateArray(data.size());
104 NativeArray* array = ConvertNativeValueTo<NativeArray>(arrayValue);
105 uint32_t index = 0;
106 for (const T& item : data) {
107 array->SetElement(index++, CreateJsValue(engine, item));
108 }
109 return arrayValue;
110 }
111
112 NativeValue* CreateJsError(NativeEngine& engine, int32_t errCode, const std::string& message = std::string());
113 void BindNativeFunction(NativeEngine& engine, NativeObject& object, const char* name, NativeCallback func);
114 void BindNativeProperty(NativeObject& object, const char* name, NativeCallback getter);
115 void* GetNativePointerFromCallbackInfo(NativeEngine* engine, NativeCallbackInfo* info, const char* name);
116
117 void SetNamedNativePointer(
118 NativeEngine& engine, NativeObject& object, const char* name, void* ptr, NativeFinalize func);
119 void* GetNamedNativePointer(NativeEngine& engine, NativeObject& object, const char* name);
120
121 template<class T>
122 T* CheckParamsAndGetThis(NativeEngine* engine, NativeCallbackInfo* info, const char* name = nullptr)
123 {
124 return static_cast<T*>(GetNativePointerFromCallbackInfo(engine, info, name));
125 }
126
127 class HandleScope final {
128 public:
129 explicit HandleScope(JsRuntime& jsRuntime);
130 explicit HandleScope(NativeEngine& engine);
131 ~HandleScope();
132
133 NativeValue* Escape(NativeValue* value);
134
135 HandleScope(const HandleScope&) = delete;
136 HandleScope(HandleScope&&) = delete;
137 HandleScope& operator=(const HandleScope&) = delete;
138 HandleScope& operator=(HandleScope&&) = delete;
139
140 private:
141 NativeScopeManager* scopeManager_ = nullptr;
142 NativeScope* nativeScope_ = nullptr;
143 };
144
145 class AsyncTask final {
146 public:
147 using ExecuteCallback = std::function<void()>;
148 using CompleteCallback = std::function<void(NativeEngine&, AsyncTask&, int32_t)>;
149
150 static void Schedule(NativeEngine& engine, std::unique_ptr<AsyncTask>&& task);
151
152 AsyncTask(NativeDeferred* deferred, std::unique_ptr<ExecuteCallback>&& execute,
153 std::unique_ptr<CompleteCallback>&& complete);
154 AsyncTask(NativeReference* callbackRef, std::unique_ptr<ExecuteCallback>&& execute,
155 std::unique_ptr<CompleteCallback>&& complete);
156 ~AsyncTask();
157
158 void Resolve(NativeEngine& engine, NativeValue* value);
159 void Reject(NativeEngine& engine, NativeValue* error);
160
161 private:
162 static void Execute(NativeEngine* engine, void* data);
163 static void Complete(NativeEngine* engine, int32_t status, void* data);
164
165 bool Start(NativeEngine& engine);
166
167 std::unique_ptr<NativeDeferred> deferred_;
168 std::unique_ptr<NativeReference> callbackRef_;
169 std::unique_ptr<NativeAsyncWork> work_;
170 std::unique_ptr<ExecuteCallback> execute_;
171 std::unique_ptr<CompleteCallback> complete_;
172 };
173
174 std::unique_ptr<AsyncTask> CreateAsyncTaskWithLastParam(NativeEngine& engine, NativeValue* lastParam,
175 AsyncTask::ExecuteCallback&& execute, AsyncTask::CompleteCallback&& complete, NativeValue** result);
176
177 std::unique_ptr<AsyncTask> CreateAsyncTaskWithLastParam(NativeEngine& engine, NativeValue* lastParam,
178 AsyncTask::ExecuteCallback&& execute, nullptr_t, NativeValue** result);
179
180 std::unique_ptr<AsyncTask> CreateAsyncTaskWithLastParam(NativeEngine& engine, NativeValue* lastParam,
181 nullptr_t, AsyncTask::CompleteCallback&& complete, NativeValue** result);
182
183 std::unique_ptr<AsyncTask> CreateAsyncTaskWithLastParam(NativeEngine& engine, NativeValue* lastParam,
184 nullptr_t, nullptr_t, NativeValue** result);
185 } // namespace AbilityRuntime
186 } // namespace OHOS
187
188 #endif // FOUNDATION_OHOS_ABILITYRUNTIME_JS_RUNTIME_UTILS_H
189