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