• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 /*
2  * Copyright (c) 2021-2023 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 // Async Task
AsyncTask(NativeDeferred * deferred,std::unique_ptr<AsyncTask::ExecuteCallback> && execute,std::unique_ptr<AsyncTask::CompleteCallback> && complete)99 AsyncTask::AsyncTask(NativeDeferred *deferred, std::unique_ptr<AsyncTask::ExecuteCallback> &&execute,
100     std::unique_ptr<AsyncTask::CompleteCallback> &&complete)
101     : deferred_(deferred), execute_(std::move(execute)), complete_(std::move(complete))
102 {}
103 
AsyncTask(NativeReference * callbackRef,std::unique_ptr<AsyncTask::ExecuteCallback> && execute,std::unique_ptr<AsyncTask::CompleteCallback> && complete)104 AsyncTask::AsyncTask(NativeReference *callbackRef, std::unique_ptr<AsyncTask::ExecuteCallback> &&execute,
105     std::unique_ptr<AsyncTask::CompleteCallback> &&complete)
106     : callbackRef_(callbackRef), execute_(std::move(execute)), complete_(std::move(complete))
107 {}
108 
109 AsyncTask::~AsyncTask() = default;
110 
Schedule(const std::string & name,NativeEngine & engine,std::unique_ptr<AsyncTask> && task)111 void AsyncTask::Schedule(const std::string &name, NativeEngine &engine, std::unique_ptr<AsyncTask> &&task)
112 {
113     if (task && task->Start(name, engine)) {
114         task.release();
115     }
116 }
117 
Resolve(NativeEngine & engine,NativeValue * value)118 void AsyncTask::Resolve(NativeEngine &engine, NativeValue *value)
119 {
120     HILOG_DEBUG("AsyncTask::Resolve is called");
121     if (deferred_) {
122         deferred_->Resolve(value);
123         deferred_.reset();
124     }
125     if (callbackRef_) {
126         NativeValue *argv[] = {
127             CreateJsError(engine, 0),
128             value,
129         };
130         engine.CallFunction(engine.CreateUndefined(), callbackRef_->Get(), argv, ArraySize(argv));
131         callbackRef_.reset();
132     }
133     HILOG_DEBUG("AsyncTask::Resolve is called end.");
134 }
135 
ResolveWithNoError(NativeEngine & engine,NativeValue * value)136 void AsyncTask::ResolveWithNoError(NativeEngine &engine, NativeValue *value)
137 {
138     HILOG_DEBUG("AsyncTask::Resolve is called");
139     if (deferred_) {
140         deferred_->Resolve(value);
141         deferred_.reset();
142     }
143     if (callbackRef_) {
144         NativeValue *argv[] = {
145             engine.CreateNull(),
146             value,
147         };
148         engine.CallFunction(engine.CreateUndefined(), callbackRef_->Get(), argv, ArraySize(argv));
149         callbackRef_.reset();
150     }
151     HILOG_DEBUG("AsyncTask::Resolve is called end.");
152 }
153 
Reject(NativeEngine & engine,NativeValue * error)154 void AsyncTask::Reject(NativeEngine &engine, NativeValue *error)
155 {
156     if (deferred_) {
157         deferred_->Reject(error);
158         deferred_.reset();
159     }
160     if (callbackRef_) {
161         NativeValue *argv[] = {
162             error,
163             engine.CreateUndefined(),
164         };
165         engine.CallFunction(engine.CreateUndefined(), callbackRef_->Get(), argv, ArraySize(argv));
166         callbackRef_.reset();
167     }
168 }
169 
ResolveWithCustomize(NativeEngine & engine,NativeValue * error,NativeValue * value)170 void AsyncTask::ResolveWithCustomize(NativeEngine &engine, NativeValue *error, NativeValue *value)
171 {
172     HILOG_DEBUG("AsyncTask::ResolveWithCustomize is called");
173     if (deferred_) {
174         deferred_->Resolve(value);
175         deferred_.reset();
176     }
177     if (callbackRef_) {
178         NativeValue *argv[] = {
179             error,
180             value,
181         };
182         engine.CallFunction(engine.CreateUndefined(), callbackRef_->Get(), argv, ArraySize(argv));
183         callbackRef_.reset();
184     }
185     HILOG_DEBUG("AsyncTask::ResolveWithCustomize is called end.");
186 }
187 
RejectWithCustomize(NativeEngine & engine,NativeValue * error,NativeValue * value)188 void AsyncTask::RejectWithCustomize(NativeEngine &engine, NativeValue *error, NativeValue *value)
189 {
190     HILOG_DEBUG("AsyncTask::RejectWithCustomize is called");
191     if (deferred_) {
192         deferred_->Reject(error);
193         deferred_.reset();
194     }
195     if (callbackRef_) {
196         NativeValue *argv[] = {
197             error,
198             value,
199         };
200         engine.CallFunction(engine.CreateUndefined(), callbackRef_->Get(), argv, ArraySize(argv));
201         callbackRef_.reset();
202     }
203     HILOG_DEBUG("AsyncTask::RejectWithCustomize is called end.");
204 }
205 
Execute(NativeEngine * engine,void * data)206 void AsyncTask::Execute(NativeEngine *engine, void *data)
207 {
208     if (engine == nullptr || data == nullptr) {
209         return;
210     }
211     auto me = static_cast<AsyncTask*>(data);
212     if (me->execute_ && *(me->execute_)) {
213         (*me->execute_)();
214     }
215 }
216 
Complete(NativeEngine * engine,int32_t status,void * data)217 void AsyncTask::Complete(NativeEngine *engine, int32_t status, void *data)
218 {
219     if (engine == nullptr || data == nullptr) {
220         return;
221     }
222     std::unique_ptr<AsyncTask> me(static_cast<AsyncTask*>(data));
223     if (me->complete_ && *(me->complete_)) {
224         (*me->complete_)(*engine, *me, status);
225     }
226 }
227 
Start(const std::string & name,NativeEngine & engine)228 bool AsyncTask::Start(const std::string &name, NativeEngine &engine)
229 {
230     work_.reset(engine.CreateAsyncWork(name, Execute, Complete, this));
231     return work_->Queue();
232 }
233 
CreateAsyncTaskWithLastParam(NativeEngine & engine,NativeValue * lastParam,AsyncTask::ExecuteCallback && execute,AsyncTask::CompleteCallback && complete,NativeValue ** result)234 std::unique_ptr<AsyncTask> CreateAsyncTaskWithLastParam(NativeEngine &engine, NativeValue *lastParam,
235     AsyncTask::ExecuteCallback &&execute, AsyncTask::CompleteCallback &&complete, NativeValue **result)
236 {
237     return CreateAsyncTaskWithLastParam(engine, lastParam,
238         std::make_unique<AsyncTask::ExecuteCallback>(std::move(execute)),
239         std::make_unique<AsyncTask::CompleteCallback>(std::move(complete)), result);
240 }
241 
CreateAsyncTaskWithLastParam(NativeEngine & engine,NativeValue * lastParam,AsyncTask::ExecuteCallback && execute,nullptr_t,NativeValue ** result)242 std::unique_ptr<AsyncTask> CreateAsyncTaskWithLastParam(NativeEngine &engine, NativeValue *lastParam,
243     AsyncTask::ExecuteCallback &&execute, nullptr_t, NativeValue **result)
244 {
245     return CreateAsyncTaskWithLastParam(
246         engine, lastParam, std::make_unique<AsyncTask::ExecuteCallback>(std::move(execute)), nullptr, result);
247 }
248 
CreateAsyncTaskWithLastParam(NativeEngine & engine,NativeValue * lastParam,nullptr_t,AsyncTask::CompleteCallback && complete,NativeValue ** result)249 std::unique_ptr<AsyncTask> CreateAsyncTaskWithLastParam(NativeEngine &engine, NativeValue *lastParam,
250     nullptr_t, AsyncTask::CompleteCallback &&complete, NativeValue **result)
251 {
252     return CreateAsyncTaskWithLastParam(
253         engine, lastParam, nullptr, std::make_unique<AsyncTask::CompleteCallback>(std::move(complete)), result);
254 }
255 
CreateAsyncTaskWithLastParam(NativeEngine & engine,NativeValue * lastParam,nullptr_t,nullptr_t,NativeValue ** result)256 std::unique_ptr<AsyncTask> CreateAsyncTaskWithLastParam(NativeEngine &engine, NativeValue *lastParam,
257     nullptr_t, nullptr_t, NativeValue **result)
258 {
259     return CreateAsyncTaskWithLastParam(engine, lastParam, std::unique_ptr<AsyncTask::ExecuteCallback>(),
260         std::unique_ptr<AsyncTask::CompleteCallback>(), result);
261 }
262 
LoadSystemModuleByEngine(NativeEngine * engine,const std::string & moduleName,NativeValue * const * argv,size_t argc)263 std::unique_ptr<NativeReference> JsRuntime::LoadSystemModuleByEngine(NativeEngine *engine,
264     const std::string &moduleName, NativeValue *const *argv, size_t argc)
265 {
266     HILOG_DEBUG("JsRuntime::LoadSystemModule(%{public}s)", moduleName.c_str());
267     if (engine == nullptr) {
268         HILOG_DEBUG("JsRuntime::LoadSystemModule: invalid engine.");
269         return std::unique_ptr<NativeReference>();
270     }
271 
272     NativeObject *globalObj = ConvertNativeValueTo<NativeObject>(engine->GetGlobal());
273     std::unique_ptr<NativeReference> methodRequireNapiRef_;
274     methodRequireNapiRef_.reset(engine->CreateReference(globalObj->GetProperty("requireNapi"), 1));
275     if (!methodRequireNapiRef_) {
276         HILOG_ERROR("Failed to create reference for global.requireNapi");
277         return nullptr;
278     }
279     NativeValue *className = engine->CreateString(moduleName.c_str(), moduleName.length());
280     NativeValue *classValue =
281         engine->CallFunction(engine->GetGlobal(), methodRequireNapiRef_->Get(), &className, 1);
282     NativeValue *instanceValue = engine->CreateInstance(classValue, argv, argc);
283     if (instanceValue == nullptr) {
284         HILOG_ERROR("Failed to create object instance");
285         return std::unique_ptr<NativeReference>();
286     }
287 
288     return std::unique_ptr<NativeReference>(engine->CreateReference(instanceValue, 1));
289 }
290 } // namespace AbilityRuntime
291 } // namespace OHOS