1 /*
2 * Copyright (c) 2021-2022 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 #include "js_runtime_utils.h"
17
18 #include "hilog_wrapper.h"
19 #include "js_runtime.h"
20 namespace OHOS {
21 namespace AbilityRuntime {
22 namespace {
CreateAsyncTaskWithLastParam(NativeEngine & engine,NativeValue * lastParam,std::unique_ptr<AsyncTask::ExecuteCallback> && execute,std::unique_ptr<AsyncTask::CompleteCallback> && complete,NativeValue ** result)23 std::unique_ptr<AsyncTask> CreateAsyncTaskWithLastParam(NativeEngine& engine, NativeValue* lastParam,
24 std::unique_ptr<AsyncTask::ExecuteCallback>&& execute, std::unique_ptr<AsyncTask::CompleteCallback>&& complete,
25 NativeValue** result)
26 {
27 if (lastParam == nullptr || lastParam->TypeOf() != NATIVE_FUNCTION) {
28 NativeDeferred* nativeDeferred = nullptr;
29 *result = engine.CreatePromise(&nativeDeferred);
30 return std::make_unique<AsyncTask>(nativeDeferred, std::move(execute), std::move(complete));
31 } else {
32 *result = engine.CreateUndefined();
33 NativeReference* callbackRef = engine.CreateReference(lastParam, 1);
34 return std::make_unique<AsyncTask>(callbackRef, std::move(execute), std::move(complete));
35 }
36 }
37 } // namespace
38
39 // Help Functions
CreateJsError(NativeEngine & engine,int32_t errCode,const std::string & message)40 NativeValue* CreateJsError(NativeEngine& engine, int32_t errCode, const std::string& message)
41 {
42 return engine.CreateError(CreateJsValue(engine, errCode), CreateJsValue(engine, message));
43 }
44
BindNativeFunction(NativeEngine & engine,NativeObject & object,const char * name,const char * moduleName,NativeCallback func)45 void BindNativeFunction(NativeEngine& engine, NativeObject& object, const char* name,
46 const char* moduleName, NativeCallback func)
47 {
48 std::string fullName(moduleName);
49 fullName += ".";
50 fullName += name;
51 object.SetProperty(name, engine.CreateFunction(fullName.c_str(), fullName.length(), func, nullptr));
52 }
53
BindNativeProperty(NativeObject & object,const char * name,NativeCallback getter)54 void BindNativeProperty(NativeObject& object, const char* name, NativeCallback getter)
55 {
56 NativePropertyDescriptor property;
57 property.utf8name = name;
58 property.name = nullptr;
59 property.method = nullptr;
60 property.getter = getter;
61 property.setter = nullptr;
62 property.value = nullptr;
63 property.attributes = napi_default;
64 property.data = nullptr;
65 object.DefineProperty(property);
66 }
67
GetNativePointerFromCallbackInfo(const NativeEngine * engine,NativeCallbackInfo * info,const char * name)68 void* GetNativePointerFromCallbackInfo(const NativeEngine* engine, NativeCallbackInfo* info, const char* name)
69 {
70 if (engine == nullptr || info == nullptr) {
71 return nullptr;
72 }
73
74 NativeObject* object = ConvertNativeValueTo<NativeObject>(info->thisVar);
75 if (object != nullptr && name != nullptr) {
76 object = ConvertNativeValueTo<NativeObject>(object->GetProperty(name));
77 }
78 return (object != nullptr) ? object->GetNativePointer() : nullptr;
79 }
80
SetNamedNativePointer(NativeEngine & engine,NativeObject & object,const char * name,void * ptr,NativeFinalize func)81 void SetNamedNativePointer(NativeEngine& engine, NativeObject& object, const char* name, void* ptr, NativeFinalize func)
82 {
83 NativeValue* value = engine.CreateObject();
84 NativeObject* newObject = ConvertNativeValueTo<NativeObject>(value);
85 if (newObject == nullptr) {
86 return;
87 }
88 newObject->SetNativePointer(ptr, func, nullptr);
89 object.SetProperty(name, value);
90 }
91
GetNamedNativePointer(NativeEngine & engine,NativeObject & object,const char * name)92 void* GetNamedNativePointer(NativeEngine& engine, NativeObject& object, const char* name)
93 {
94 NativeObject* namedObj = ConvertNativeValueTo<NativeObject>(object.GetProperty(name));
95 return (namedObj != nullptr) ? namedObj->GetNativePointer() : nullptr;
96 }
97
98 // Handle Scope
HandleScope(JsRuntime & jsRuntime)99 HandleScope::HandleScope(JsRuntime& jsRuntime)
100 {
101 scopeManager_ = jsRuntime.GetNativeEngine().GetScopeManager();
102 if (scopeManager_ != nullptr) {
103 nativeScope_ = scopeManager_->Open();
104 }
105 }
106
HandleScope(NativeEngine & engine)107 HandleScope::HandleScope(NativeEngine& engine)
108 {
109 scopeManager_ = engine.GetScopeManager();
110 if (scopeManager_ != nullptr) {
111 nativeScope_ = scopeManager_->Open();
112 }
113 }
114
~HandleScope()115 HandleScope::~HandleScope()
116 {
117 if (nativeScope_ != nullptr) {
118 scopeManager_->Close(nativeScope_);
119 nativeScope_ = nullptr;
120 }
121 scopeManager_ = nullptr;
122 }
123
124 // Handle Escape
HandleEscape(JsRuntime & jsRuntime)125 HandleEscape::HandleEscape(JsRuntime& jsRuntime)
126 {
127 scopeManager_ = jsRuntime.GetNativeEngine().GetScopeManager();
128 if (scopeManager_ != nullptr) {
129 nativeScope_ = scopeManager_->OpenEscape();
130 }
131 }
132
HandleEscape(NativeEngine & engine)133 HandleEscape::HandleEscape(NativeEngine& engine)
134 {
135 scopeManager_ = engine.GetScopeManager();
136 if (scopeManager_ != nullptr) {
137 nativeScope_ = scopeManager_->OpenEscape();
138 }
139 }
140
~HandleEscape()141 HandleEscape::~HandleEscape()
142 {
143 if (nativeScope_ != nullptr) {
144 scopeManager_->CloseEscape(nativeScope_);
145 nativeScope_ = nullptr;
146 }
147 scopeManager_ = nullptr;
148 }
149
Escape(NativeValue * value)150 NativeValue* HandleEscape::Escape(NativeValue* value)
151 {
152 if (nativeScope_ != nullptr) {
153 scopeManager_->Escape(nativeScope_, value);
154 }
155 return value;
156 }
157
158 // Async Task
AsyncTask(NativeDeferred * deferred,std::unique_ptr<AsyncTask::ExecuteCallback> && execute,std::unique_ptr<AsyncTask::CompleteCallback> && complete)159 AsyncTask::AsyncTask(NativeDeferred* deferred, std::unique_ptr<AsyncTask::ExecuteCallback>&& execute,
160 std::unique_ptr<AsyncTask::CompleteCallback>&& complete)
161 : deferred_(deferred), execute_(std::move(execute)), complete_(std::move(complete))
162 {}
163
AsyncTask(NativeReference * callbackRef,std::unique_ptr<AsyncTask::ExecuteCallback> && execute,std::unique_ptr<AsyncTask::CompleteCallback> && complete)164 AsyncTask::AsyncTask(NativeReference* callbackRef, std::unique_ptr<AsyncTask::ExecuteCallback>&& execute,
165 std::unique_ptr<AsyncTask::CompleteCallback>&& complete)
166 : callbackRef_(callbackRef), execute_(std::move(execute)), complete_(std::move(complete))
167 {}
168
169 AsyncTask::~AsyncTask() = default;
170
Schedule(const std::string & name,NativeEngine & engine,std::unique_ptr<AsyncTask> && task)171 void AsyncTask::Schedule(const std::string &name, NativeEngine& engine, std::unique_ptr<AsyncTask>&& task)
172 {
173 if (task && task->Start(name, engine)) {
174 task.release();
175 }
176 }
177
Resolve(NativeEngine & engine,NativeValue * value)178 void AsyncTask::Resolve(NativeEngine& engine, NativeValue* value)
179 {
180 HILOG_DEBUG("AsyncTask::Resolve is called");
181 if (deferred_) {
182 deferred_->Resolve(value);
183 deferred_.reset();
184 }
185 if (callbackRef_) {
186 NativeValue* argv[] = {
187 CreateJsError(engine, 0),
188 value,
189 };
190 engine.CallFunction(engine.CreateUndefined(), callbackRef_->Get(), argv, ArraySize(argv));
191 callbackRef_.reset();
192 }
193 HILOG_DEBUG("AsyncTask::Resolve is called end.");
194 }
195
ResolveWithNoError(NativeEngine & engine,NativeValue * value)196 void AsyncTask::ResolveWithNoError(NativeEngine& engine, NativeValue* value)
197 {
198 HILOG_DEBUG("AsyncTask::Resolve is called");
199 if (deferred_) {
200 deferred_->Resolve(value);
201 deferred_.reset();
202 }
203 if (callbackRef_) {
204 NativeValue* argv[] = {
205 engine.CreateNull(),
206 value,
207 };
208 engine.CallFunction(engine.CreateUndefined(), callbackRef_->Get(), argv, ArraySize(argv));
209 callbackRef_.reset();
210 }
211 HILOG_DEBUG("AsyncTask::Resolve is called end.");
212 }
213
Reject(NativeEngine & engine,NativeValue * error)214 void AsyncTask::Reject(NativeEngine& engine, NativeValue* error)
215 {
216 if (deferred_) {
217 deferred_->Reject(error);
218 deferred_.reset();
219 }
220 if (callbackRef_) {
221 NativeValue* argv[] = {
222 error,
223 engine.CreateUndefined(),
224 };
225 engine.CallFunction(engine.CreateUndefined(), callbackRef_->Get(), argv, ArraySize(argv));
226 callbackRef_.reset();
227 }
228 }
229
Execute(NativeEngine * engine,void * data)230 void AsyncTask::Execute(NativeEngine* engine, void* data)
231 {
232 if (engine == nullptr || data == nullptr) {
233 return;
234 }
235 auto me = static_cast<AsyncTask*>(data);
236 if (me->execute_ && *(me->execute_)) {
237 (*me->execute_)();
238 }
239 }
240
Complete(NativeEngine * engine,int32_t status,void * data)241 void AsyncTask::Complete(NativeEngine* engine, int32_t status, void* data)
242 {
243 if (engine == nullptr || data == nullptr) {
244 return;
245 }
246 std::unique_ptr<AsyncTask> me(static_cast<AsyncTask*>(data));
247 if (me->complete_ && *(me->complete_)) {
248 HandleScope handleScope(*engine);
249 (*me->complete_)(*engine, *me, status);
250 }
251 }
252
Start(const std::string & name,NativeEngine & engine)253 bool AsyncTask::Start(const std::string &name, NativeEngine& engine)
254 {
255 work_.reset(engine.CreateAsyncWork(name, Execute, Complete, this));
256 return work_->Queue();
257 }
258
CreateAsyncTaskWithLastParam(NativeEngine & engine,NativeValue * lastParam,AsyncTask::ExecuteCallback && execute,AsyncTask::CompleteCallback && complete,NativeValue ** result)259 std::unique_ptr<AsyncTask> CreateAsyncTaskWithLastParam(NativeEngine& engine, NativeValue* lastParam,
260 AsyncTask::ExecuteCallback&& execute, AsyncTask::CompleteCallback&& complete, NativeValue** result)
261 {
262 return CreateAsyncTaskWithLastParam(engine, lastParam,
263 std::make_unique<AsyncTask::ExecuteCallback>(std::move(execute)),
264 std::make_unique<AsyncTask::CompleteCallback>(std::move(complete)), result);
265 }
266
CreateAsyncTaskWithLastParam(NativeEngine & engine,NativeValue * lastParam,AsyncTask::ExecuteCallback && execute,nullptr_t,NativeValue ** result)267 std::unique_ptr<AsyncTask> CreateAsyncTaskWithLastParam(NativeEngine& engine, NativeValue* lastParam,
268 AsyncTask::ExecuteCallback&& execute, nullptr_t, NativeValue** result)
269 {
270 return CreateAsyncTaskWithLastParam(
271 engine, lastParam, std::make_unique<AsyncTask::ExecuteCallback>(std::move(execute)), nullptr, result);
272 }
273
CreateAsyncTaskWithLastParam(NativeEngine & engine,NativeValue * lastParam,nullptr_t,AsyncTask::CompleteCallback && complete,NativeValue ** result)274 std::unique_ptr<AsyncTask> CreateAsyncTaskWithLastParam(NativeEngine& engine, NativeValue* lastParam,
275 nullptr_t, AsyncTask::CompleteCallback&& complete, NativeValue** result)
276 {
277 return CreateAsyncTaskWithLastParam(
278 engine, lastParam, nullptr, std::make_unique<AsyncTask::CompleteCallback>(std::move(complete)), result);
279 }
280
CreateAsyncTaskWithLastParam(NativeEngine & engine,NativeValue * lastParam,nullptr_t,nullptr_t,NativeValue ** result)281 std::unique_ptr<AsyncTask> CreateAsyncTaskWithLastParam(NativeEngine& engine, NativeValue* lastParam,
282 nullptr_t, nullptr_t, NativeValue** result)
283 {
284 return CreateAsyncTaskWithLastParam(engine, lastParam, std::unique_ptr<AsyncTask::ExecuteCallback>(),
285 std::unique_ptr<AsyncTask::CompleteCallback>(), result);
286 }
287 } // namespace AbilityRuntime
288 } // namespace OHOS
289