• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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 
ScheduleHighQos(const std::string & name,NativeEngine & engine,std::unique_ptr<AsyncTask> && task)178 void AsyncTask::ScheduleHighQos(const std::string &name, NativeEngine& engine, std::unique_ptr<AsyncTask>&& task)
179 {
180     if (task && task->StartHighQos(name, engine)) {
181         task.release();
182     }
183 }
184 
ScheduleLowQos(const std::string & name,NativeEngine & engine,std::unique_ptr<AsyncTask> && task)185 void AsyncTask::ScheduleLowQos(const std::string &name, NativeEngine& engine, std::unique_ptr<AsyncTask>&& task)
186 {
187     if (task && task->StartLowQos(name, engine)) {
188         task.release();
189     }
190 }
191 
ScheduleWithDefaultQos(const std::string & name,NativeEngine & engine,std::unique_ptr<AsyncTask> && task)192 void AsyncTask::ScheduleWithDefaultQos(const std::string &name,
193     NativeEngine& engine, std::unique_ptr<AsyncTask>&& task)
194 {
195     if (task && task->StartWithDefaultQos(name, engine)) {
196         task.release();
197     }
198 }
199 
StartWithDefaultQos(const std::string & name,NativeEngine & engine)200 bool AsyncTask::StartWithDefaultQos(const std::string &name, NativeEngine& engine)
201 {
202     work_.reset(engine.CreateAsyncWork(name, Execute, Complete, this));
203     return work_->QueueWithQos(napi_qos_default);
204 }
205 
Resolve(NativeEngine & engine,NativeValue * value)206 void AsyncTask::Resolve(NativeEngine& engine, NativeValue* value)
207 {
208     HILOG_DEBUG("AsyncTask::Resolve is called");
209     if (deferred_) {
210         deferred_->Resolve(value);
211         deferred_.reset();
212     }
213     if (callbackRef_) {
214         NativeValue* argv[] = {
215             CreateJsError(engine, 0),
216             value,
217         };
218         engine.CallFunction(engine.CreateUndefined(), callbackRef_->Get(), argv, ArraySize(argv));
219         callbackRef_.reset();
220     }
221     HILOG_DEBUG("AsyncTask::Resolve is called end.");
222 }
223 
ResolveWithNoError(NativeEngine & engine,NativeValue * value)224 void AsyncTask::ResolveWithNoError(NativeEngine& engine, NativeValue* value)
225 {
226     HILOG_DEBUG("AsyncTask::Resolve is called");
227     if (deferred_) {
228         deferred_->Resolve(value);
229         deferred_.reset();
230     }
231     if (callbackRef_) {
232         NativeValue* argv[] = {
233             engine.CreateNull(),
234             value,
235         };
236         engine.CallFunction(engine.CreateUndefined(), callbackRef_->Get(), argv, ArraySize(argv));
237         callbackRef_.reset();
238     }
239     HILOG_DEBUG("AsyncTask::Resolve is called end.");
240 }
241 
Reject(NativeEngine & engine,NativeValue * error)242 void AsyncTask::Reject(NativeEngine& engine, NativeValue* error)
243 {
244     if (deferred_) {
245         deferred_->Reject(error);
246         deferred_.reset();
247     }
248     if (callbackRef_) {
249         NativeValue* argv[] = {
250             error,
251             engine.CreateUndefined(),
252         };
253         engine.CallFunction(engine.CreateUndefined(), callbackRef_->Get(), argv, ArraySize(argv));
254         callbackRef_.reset();
255     }
256 }
257 
ResolveWithCustomize(NativeEngine & engine,NativeValue * error,NativeValue * value)258 void AsyncTask::ResolveWithCustomize(NativeEngine& engine, NativeValue* error, NativeValue* value)
259 {
260     HILOG_DEBUG("AsyncTask::ResolveWithCustomize is called");
261     if (deferred_) {
262         deferred_->Resolve(value);
263         deferred_.reset();
264     }
265     if (callbackRef_) {
266         NativeValue* argv[] = {
267             error,
268             value,
269         };
270         engine.CallFunction(engine.CreateUndefined(), callbackRef_->Get(), argv, ArraySize(argv));
271         callbackRef_.reset();
272     }
273     HILOG_DEBUG("AsyncTask::ResolveWithCustomize is called end.");
274 }
275 
RejectWithCustomize(NativeEngine & engine,NativeValue * error,NativeValue * value)276 void AsyncTask::RejectWithCustomize(NativeEngine& engine, NativeValue* error, NativeValue* value)
277 {
278     HILOG_DEBUG("AsyncTask::RejectWithCustomize is called");
279     if (deferred_) {
280         deferred_->Reject(error);
281         deferred_.reset();
282     }
283     if (callbackRef_) {
284         NativeValue* argv[] = {
285             error,
286             value,
287         };
288         engine.CallFunction(engine.CreateUndefined(), callbackRef_->Get(), argv, ArraySize(argv));
289         callbackRef_.reset();
290     }
291     HILOG_DEBUG("AsyncTask::RejectWithCustomize is called end.");
292 }
293 
Execute(NativeEngine * engine,void * data)294 void AsyncTask::Execute(NativeEngine* engine, void* data)
295 {
296     if (engine == nullptr || data == nullptr) {
297         return;
298     }
299     auto me = static_cast<AsyncTask*>(data);
300     if (me->execute_ && *(me->execute_)) {
301         (*me->execute_)();
302     }
303 }
304 
Complete(NativeEngine * engine,int32_t status,void * data)305 void AsyncTask::Complete(NativeEngine* engine, int32_t status, void* data)
306 {
307     if (engine == nullptr || data == nullptr) {
308         return;
309     }
310     std::unique_ptr<AsyncTask> me(static_cast<AsyncTask*>(data));
311     if (me->complete_ && *(me->complete_)) {
312         HandleScope handleScope(*engine);
313         (*me->complete_)(*engine, *me, status);
314     }
315 }
316 
Start(const std::string & name,NativeEngine & engine)317 bool AsyncTask::Start(const std::string &name, NativeEngine& engine)
318 {
319     work_.reset(engine.CreateAsyncWork(name, Execute, Complete, this));
320     return work_->Queue();
321 }
322 
StartHighQos(const std::string & name,NativeEngine & engine)323 bool AsyncTask::StartHighQos(const std::string &name, NativeEngine& engine)
324 {
325     work_.reset(engine.CreateAsyncWork(name, Execute, Complete, this));
326     return work_->QueueWithQos(napi_qos_user_initiated);
327 }
328 
StartLowQos(const std::string & name,NativeEngine & engine)329 bool AsyncTask::StartLowQos(const std::string &name, NativeEngine& engine)
330 {
331     work_.reset(engine.CreateAsyncWork(name, Execute, Complete, this));
332     return work_->QueueWithQos(napi_qos_utility);
333 }
334 
CreateAsyncTaskWithLastParam(NativeEngine & engine,NativeValue * lastParam,AsyncTask::ExecuteCallback && execute,AsyncTask::CompleteCallback && complete,NativeValue ** result)335 std::unique_ptr<AsyncTask> CreateAsyncTaskWithLastParam(NativeEngine& engine, NativeValue* lastParam,
336     AsyncTask::ExecuteCallback&& execute, AsyncTask::CompleteCallback&& complete, NativeValue** result)
337 {
338     return CreateAsyncTaskWithLastParam(engine, lastParam,
339         std::make_unique<AsyncTask::ExecuteCallback>(std::move(execute)),
340         std::make_unique<AsyncTask::CompleteCallback>(std::move(complete)), result);
341 }
342 
CreateAsyncTaskWithLastParam(NativeEngine & engine,NativeValue * lastParam,AsyncTask::ExecuteCallback && execute,nullptr_t,NativeValue ** result)343 std::unique_ptr<AsyncTask> CreateAsyncTaskWithLastParam(NativeEngine& engine, NativeValue* lastParam,
344     AsyncTask::ExecuteCallback&& execute, nullptr_t, NativeValue** result)
345 {
346     return CreateAsyncTaskWithLastParam(
347         engine, lastParam, std::make_unique<AsyncTask::ExecuteCallback>(std::move(execute)), nullptr, result);
348 }
349 
CreateAsyncTaskWithLastParam(NativeEngine & engine,NativeValue * lastParam,nullptr_t,AsyncTask::CompleteCallback && complete,NativeValue ** result)350 std::unique_ptr<AsyncTask> CreateAsyncTaskWithLastParam(NativeEngine& engine, NativeValue* lastParam,
351     nullptr_t, AsyncTask::CompleteCallback&& complete, NativeValue** result)
352 {
353     return CreateAsyncTaskWithLastParam(
354         engine, lastParam, nullptr, std::make_unique<AsyncTask::CompleteCallback>(std::move(complete)), result);
355 }
356 
CreateAsyncTaskWithLastParam(NativeEngine & engine,NativeValue * lastParam,nullptr_t,nullptr_t,NativeValue ** result)357 std::unique_ptr<AsyncTask> CreateAsyncTaskWithLastParam(NativeEngine& engine, NativeValue* lastParam,
358     nullptr_t, nullptr_t, NativeValue** result)
359 {
360     return CreateAsyncTaskWithLastParam(engine, lastParam, std::unique_ptr<AsyncTask::ExecuteCallback>(),
361         std::unique_ptr<AsyncTask::CompleteCallback>(), result);
362 }
363 }  // namespace AbilityRuntime
364 }  // namespace OHOS
365