1 /*
2  * Copyright (C) 2024 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 #define MLOG_TAG "FetchResultNapi"
16 
17 #include "sendable_fetch_file_result_napi.h"
18 
19 #include "album_napi.h"
20 #include "hitrace_meter.h"
21 #include "medialibrary_client_errno.h"
22 #include "medialibrary_napi_log.h"
23 #include "medialibrary_napi_utils.h"
24 #include "medialibrary_tracer.h"
25 #include "sendable_photo_album_napi.h"
26 #include "sendable_medialibrary_napi_utils.h"
27 #include "smart_album_napi.h"
28 #include "media_file_utils.h"
29 
30 using OHOS::HiviewDFX::HiLog;
31 using OHOS::HiviewDFX::HiLogLabel;
32 using namespace std;
33 
34 namespace OHOS {
35 namespace Media {
36 thread_local napi_ref SendableFetchFileResultNapi::photoAccessHelperConstructor_ = nullptr;
37 
SendableFetchFileResultNapi()38 SendableFetchFileResultNapi::SendableFetchFileResultNapi()
39     : env_(nullptr) {}
40 
~SendableFetchFileResultNapi()41 SendableFetchFileResultNapi::~SendableFetchFileResultNapi()
42 {
43     propertyPtr = nullptr;
44 }
45 
FetchFileResultNapiDestructor(napi_env env,void * nativeObject,void * finalize_hint)46 void SendableFetchFileResultNapi::FetchFileResultNapiDestructor(napi_env env, void *nativeObject, void *finalize_hint)
47 {
48     SendableFetchFileResultNapi *fetchFileResultObj = reinterpret_cast<SendableFetchFileResultNapi*>(nativeObject);
49     if (fetchFileResultObj != nullptr) {
50         delete fetchFileResultObj;
51         fetchFileResultObj = nullptr;
52     }
53 }
54 
GetFetchResult(unique_ptr<SendableFetchFileResultNapi> & obj)55 void SendableFetchFileResultNapi::GetFetchResult(unique_ptr<SendableFetchFileResultNapi> &obj)
56 {
57     switch (sFetchResType_) {
58         case FetchResType::TYPE_FILE: {
59             auto fileResult = make_shared<FetchResult<FileAsset>>(move(sFetchFileResult_->GetDataShareResultSet()));
60             obj->propertyPtr->fetchFileResult_ = fileResult;
61             obj->propertyPtr->fetchFileResult_->SetInfo(sFetchFileResult_);
62             break;
63         }
64         case FetchResType::TYPE_ALBUM: {
65             auto albumResult = make_shared<FetchResult<AlbumAsset>>(move(sFetchAlbumResult_->GetDataShareResultSet()));
66             obj->propertyPtr->fetchAlbumResult_ = albumResult;
67             obj->propertyPtr->fetchAlbumResult_->SetInfo(sFetchAlbumResult_);
68             break;
69         }
70         case FetchResType::TYPE_PHOTOALBUM: {
71             auto photoAlbumResult =
72                 make_shared<FetchResult<PhotoAlbum>>(move(sFetchPhotoAlbumResult_->GetDataShareResultSet()));
73             obj->propertyPtr->fetchPhotoAlbumResult_ = photoAlbumResult;
74             obj->propertyPtr->fetchPhotoAlbumResult_->SetInfo(sFetchPhotoAlbumResult_);
75             break;
76         }
77         case FetchResType::TYPE_SMARTALBUM: {
78             auto smartResult =
79                 make_shared<FetchResult<SmartAlbumAsset>>(move(sFetchSmartAlbumResult_->GetDataShareResultSet()));
80             obj->propertyPtr->fetchSmartAlbumResult_ = smartResult;
81             obj->propertyPtr->fetchSmartAlbumResult_->SetInfo(sFetchSmartAlbumResult_);
82             break;
83         }
84         default:
85             NAPI_ERR_LOG("unsupported FetchResType");
86             break;
87     }
88 }
89 
90 // Constructor callback
FetchFileResultNapiConstructor(napi_env env,napi_callback_info info)91 napi_value SendableFetchFileResultNapi::FetchFileResultNapiConstructor(napi_env env, napi_callback_info info)
92 {
93     MediaLibraryTracer tracer;
94     tracer.Start("FetchFileResultNapiConstructor");
95 
96     napi_status status;
97     napi_value result = nullptr;
98     napi_value thisVar = nullptr;
99 
100     napi_get_undefined(env, &result);
101     GET_JS_OBJ_WITH_ZERO_ARGS(env, info, status, thisVar);
102     if (status != napi_ok || thisVar == nullptr) {
103         NAPI_ERR_LOG("Get Js obj failed, status: %{public}d, (thisVar == nullptr) = %{public}d",
104             status, (thisVar == nullptr));
105         return result;
106     }
107 
108     unique_ptr<SendableFetchFileResultNapi> obj = make_unique<SendableFetchFileResultNapi>();
109     if (obj == nullptr) {
110         NAPI_ERR_LOG("Get SendableFetchFileResultNapi failed");
111         return result;
112     }
113     obj->env_ = env;
114     obj->propertyPtr = make_shared<SendableFetchResultProperty>();
115     GetFetchResult(obj);
116     obj->propertyPtr->fetchResType_ = sFetchResType_;
117     status = napi_wrap_sendable(env, thisVar, reinterpret_cast<void *>(obj.get()),
118         SendableFetchFileResultNapi::FetchFileResultNapiDestructor, nullptr);
119     if (status == napi_ok) {
120         obj.release();
121         return thisVar;
122     } else {
123         NAPI_ERR_LOG("Failure wrapping js to native napi, status: %{public}d", status);
124     }
125     return result;
126 }
127 
GetFetchResType()128 FetchResType SendableFetchFileResultNapi::GetFetchResType()
129 {
130     return propertyPtr->fetchResType_;
131 }
132 
SolveConstructorRef(unique_ptr<FetchResult<FileAsset>> & fileResult,napi_ref & constructorRef)133 void SendableFetchFileResultNapi::SolveConstructorRef(unique_ptr<FetchResult<FileAsset>> &fileResult,
134     napi_ref &constructorRef)
135 {
136     switch (fileResult->GetResultNapiType()) {
137         case ResultNapiType::TYPE_PHOTOACCESS_HELPER: {
138             constructorRef = photoAccessHelperConstructor_;
139             break;
140         }
141         default:
142             NAPI_ERR_LOG("Invalid result napi type: %{public}d", static_cast<int>(fileResult->GetResultNapiType()));
143             constructorRef = nullptr;
144             break;
145     }
146 }
147 
SolveConstructorRef(unique_ptr<FetchResult<AlbumAsset>> & fileResult,napi_ref & constructorRef)148 void SendableFetchFileResultNapi::SolveConstructorRef(unique_ptr<FetchResult<AlbumAsset>> &fileResult,
149     napi_ref &constructorRef)
150 {
151     switch (fileResult->GetResultNapiType()) {
152         case ResultNapiType::TYPE_PHOTOACCESS_HELPER: {
153             constructorRef = photoAccessHelperConstructor_;
154             break;
155         }
156         default:
157             NAPI_ERR_LOG("Invalid result napi type: %{public}d", static_cast<int>(fileResult->GetResultNapiType()));
158             constructorRef = nullptr;
159             break;
160     }
161 }
162 
SolveConstructorRef(unique_ptr<FetchResult<SmartAlbumAsset>> & fileResult,napi_ref & constructorRef)163 void SendableFetchFileResultNapi::SolveConstructorRef(unique_ptr<FetchResult<SmartAlbumAsset>> &fileResult,
164     napi_ref &constructorRef)
165 {
166     switch (fileResult->GetResultNapiType()) {
167         case ResultNapiType::TYPE_PHOTOACCESS_HELPER: {
168             constructorRef = photoAccessHelperConstructor_;
169             break;
170         }
171         default:
172             NAPI_ERR_LOG("Invalid result napi type: %{public}d", static_cast<int>(fileResult->GetResultNapiType()));
173             constructorRef = nullptr;
174             break;
175     }
176 }
177 
SolveConstructorRef(unique_ptr<FetchResult<PhotoAlbum>> & fileResult,napi_ref & constructorRef)178 void SendableFetchFileResultNapi::SolveConstructorRef(unique_ptr<FetchResult<PhotoAlbum>> &fileResult,
179     napi_ref &constructorRef)
180 {
181     switch (fileResult->GetResultNapiType()) {
182         case ResultNapiType::TYPE_PHOTOACCESS_HELPER: {
183             constructorRef = photoAccessHelperConstructor_;
184             break;
185         }
186         default:
187             NAPI_ERR_LOG("Invalid result napi type: %{public}d", static_cast<int>(fileResult->GetResultNapiType()));
188             constructorRef = nullptr;
189             break;
190     }
191 }
192 
CreateFetchFileResult(napi_env env,unique_ptr<FetchResult<FileAsset>> fileResult)193 napi_value SendableFetchFileResultNapi::CreateFetchFileResult(napi_env env,
194     unique_ptr<FetchResult<FileAsset>> fileResult)
195 {
196     if (photoAccessHelperConstructor_ == nullptr) {
197         napi_value exports = nullptr;
198         napi_create_object(env, &exports);
199         SendableFetchFileResultNapi::PhotoAccessHelperInit(env, exports);
200     }
201 
202     MediaLibraryTracer tracer;
203     tracer.Start("CreateFetchFileResult");
204     napi_value constructor;
205     napi_ref constructorRef;
206 
207     SendableFetchFileResultNapi::SolveConstructorRef(fileResult, constructorRef);
208     NAPI_CALL(env, napi_get_reference_value(env, constructorRef, &constructor));
209     sFetchResType_ = fileResult->GetFetchResType();
210     sFetchFileResult_ = move(fileResult);
211     napi_value result = nullptr;
212     NAPI_CALL(env, napi_new_instance(env, constructor, 0, nullptr, &result));
213     sFetchFileResult_ = nullptr;
214     return result;
215 }
216 
CreateFetchFileResult(napi_env env,unique_ptr<FetchResult<AlbumAsset>> fileResult)217 napi_value SendableFetchFileResultNapi::CreateFetchFileResult(napi_env env,
218     unique_ptr<FetchResult<AlbumAsset>> fileResult)
219 {
220     if (photoAccessHelperConstructor_ == nullptr) {
221         napi_value exports = nullptr;
222         napi_create_object(env, &exports);
223         SendableFetchFileResultNapi::PhotoAccessHelperInit(env, exports);
224     }
225 
226     MediaLibraryTracer tracer;
227     tracer.Start("CreateFetchFileResult");
228     napi_value constructor;
229     napi_ref constructorRef;
230     SendableFetchFileResultNapi::SolveConstructorRef(fileResult, constructorRef);
231     NAPI_CALL(env, napi_get_reference_value(env, constructorRef, &constructor));
232     sFetchResType_ = fileResult->GetFetchResType();
233     sFetchAlbumResult_ = move(fileResult);
234     napi_value result = nullptr;
235     NAPI_CALL(env, napi_new_instance(env, constructor, 0, nullptr, &result));
236     sFetchAlbumResult_ = nullptr;
237     return result;
238 }
239 
CreateFetchFileResult(napi_env env,unique_ptr<FetchResult<PhotoAlbum>> fileResult)240 napi_value SendableFetchFileResultNapi::CreateFetchFileResult(napi_env env,
241     unique_ptr<FetchResult<PhotoAlbum>> fileResult)
242 {
243     if (photoAccessHelperConstructor_ == nullptr) {
244         napi_value exports = nullptr;
245         napi_create_object(env, &exports);
246         SendableFetchFileResultNapi::PhotoAccessHelperInit(env, exports);
247     }
248 
249     MediaLibraryTracer tracer;
250     tracer.Start("CreateFetchFileResult");
251     napi_value constructor;
252     napi_ref constructorRef;
253     SendableFetchFileResultNapi::SolveConstructorRef(fileResult, constructorRef);
254     NAPI_CALL(env, napi_get_reference_value(env, constructorRef, &constructor));
255     sFetchResType_ = fileResult->GetFetchResType();
256     sFetchPhotoAlbumResult_ = move(fileResult);
257     napi_value result = nullptr;
258     NAPI_CALL(env, napi_new_instance(env, constructor, 0, nullptr, &result));
259     sFetchPhotoAlbumResult_ = nullptr;
260     return result;
261 }
262 
CreateFetchFileResult(napi_env env,unique_ptr<FetchResult<SmartAlbumAsset>> fileResult)263 napi_value SendableFetchFileResultNapi::CreateFetchFileResult(napi_env env,
264     unique_ptr<FetchResult<SmartAlbumAsset>> fileResult)
265 {
266     if (photoAccessHelperConstructor_ == nullptr) {
267         napi_value exports = nullptr;
268         napi_create_object(env, &exports);
269         SendableFetchFileResultNapi::PhotoAccessHelperInit(env, exports);
270     }
271 
272     MediaLibraryTracer tracer;
273     tracer.Start("CreateFetchFileResult");
274     napi_value constructor;
275     napi_ref constructorRef;
276     SendableFetchFileResultNapi::SolveConstructorRef(fileResult, constructorRef);
277     NAPI_CALL(env, napi_get_reference_value(env, constructorRef, &constructor));
278     sFetchResType_ = fileResult->GetFetchResType();
279     sFetchSmartAlbumResult_ = move(fileResult);
280     napi_value result = nullptr;
281     NAPI_CALL(env, napi_new_instance(env, constructor, 0, nullptr, &result));
282     sFetchSmartAlbumResult_ = nullptr;
283     return result;
284 }
285 
GetFetchFileResult() const286 std::shared_ptr<FetchResult<FileAsset>> SendableFetchFileResultNapi::GetFetchFileResult() const
287 {
288     return propertyPtr->fetchFileResult_;
289 }
290 
PhotoAccessHelperInit(napi_env env,napi_value exports)291 napi_value SendableFetchFileResultNapi::PhotoAccessHelperInit(napi_env env, napi_value exports)
292 {
293     napi_value ctorObj;
294     napi_property_descriptor props[] = {
295         DECLARE_NAPI_FUNCTION("getCount", JSGetCount),
296         DECLARE_NAPI_FUNCTION("isAfterLast", JSIsAfterLast),
297         DECLARE_NAPI_FUNCTION("getFirstObject", JSGetFirstObject),
298         DECLARE_NAPI_FUNCTION("getNextObject", JSGetNextObject),
299         DECLARE_NAPI_FUNCTION("getAllObjects", JSGetAllObject),
300         DECLARE_NAPI_FUNCTION("getLastObject", JSGetLastObject),
301         DECLARE_NAPI_FUNCTION("getObjectByPosition", JSGetPositionObject),
302         DECLARE_NAPI_FUNCTION("close", JSClose)
303     };
304     napi_define_sendable_class(env, PAH_FETCH_FILE_RESULT_SENDABLE_CLASS_NAME.c_str(), NAPI_AUTO_LENGTH,
305                                FetchFileResultNapiConstructor, nullptr,
306                                sizeof(props) / sizeof(props[0]), props, nullptr, &ctorObj);
307     NAPI_CALL(env, napi_create_reference(env, ctorObj, NAPI_INIT_REF_COUNT, &photoAccessHelperConstructor_));
308     NAPI_CALL(env, napi_set_named_property(env, exports, PAH_FETCH_FILE_RESULT_SENDABLE_CLASS_NAME.c_str(), ctorObj));
309     return exports;
310 }
311 
CheckIfFFRNapiNotEmpty(SendableFetchFileResultNapi * obj)312 static bool CheckIfFFRNapiNotEmpty(SendableFetchFileResultNapi* obj)
313 {
314     if (obj == nullptr) {
315         NAPI_INFO_LOG("SendableFetchFileResultNapi is nullptr");
316         return false;
317     }
318     if (obj->CheckIfPropertyPtrNull()) {
319         NAPI_INFO_LOG("PropertyPtr in SendableFetchFileResultNapi is nullptr");
320         return false;
321     }
322     return true;
323 }
324 
JSGetCount(napi_env env,napi_callback_info info)325 napi_value SendableFetchFileResultNapi::JSGetCount(napi_env env, napi_callback_info info)
326 {
327     napi_status status;
328     napi_value jsResult = nullptr;
329     SendableFetchFileResultNapi* obj = nullptr;
330     int32_t count = 0;
331     napi_value thisVar = nullptr;
332 
333     MediaLibraryTracer tracer;
334     tracer.Start("JSGetCount");
335 
336     napi_get_undefined(env, &jsResult);
337     GET_JS_OBJ_WITH_ZERO_ARGS(env, info, status, thisVar);
338     if (status != napi_ok || thisVar == nullptr) {
339         NAPI_ERR_LOG("JSGetCount Invalid arguments!, status: %{public}d", status);
340         NAPI_ASSERT(env, false, "JSGetCount thisVar == nullptr");
341     }
342 
343     status = napi_unwrap_sendable(env, thisVar, reinterpret_cast<void **>(&obj));
344     if ((status == napi_ok) && CheckIfFFRNapiNotEmpty(obj)) {
345         switch (obj->GetFetchResType()) {
346             case FetchResType::TYPE_FILE:
347                 count = obj->GetFetchFileResultObject()->GetCount();
348                 break;
349             case FetchResType::TYPE_ALBUM:
350                 count = obj->GetFetchAlbumResultObject()->GetCount();
351                 break;
352             case FetchResType::TYPE_PHOTOALBUM:
353                 count = obj->GetFetchPhotoAlbumResultObject()->GetCount();
354                 break;
355             case FetchResType::TYPE_SMARTALBUM:
356                 count = obj->GetFetchSmartAlbumResultObject()->GetCount();
357                 break;
358             default:
359                 NAPI_ERR_LOG("unsupported FetchResType");
360                 break;
361         }
362         if (count < 0) {
363             NapiError::ThrowError(env, JS_INNER_FAIL, "Failed to get count");
364             return nullptr;
365         }
366         napi_create_int32(env, count, &jsResult);
367     } else {
368         NapiError::ThrowError(env, JS_ERR_PARAMETER_INVALID, "Failed to get native obj");
369         return nullptr;
370     }
371 
372     return jsResult;
373 }
374 
GetNapiResFromAsset(napi_env env,FetchFileResultSendableAsyncContext * context,unique_ptr<SendableJSAsyncContextOutput> & jsContext)375 static void GetNapiResFromAsset(napi_env env, FetchFileResultSendableAsyncContext *context,
376     unique_ptr<SendableJSAsyncContextOutput> &jsContext)
377 {
378     napi_value jsAsset;
379     switch (context->objectPtr->fetchResType_) {
380         case FetchResType::TYPE_FILE:
381             jsAsset = SendableFileAssetNapi::CreateFileAsset(env, context->fileAsset);
382             break;
383         case FetchResType::TYPE_ALBUM:
384             jsAsset = AlbumNapi::CreateAlbumNapi(env, context->albumAsset);
385             break;
386         case FetchResType::TYPE_PHOTOALBUM:
387             jsAsset = SendablePhotoAlbumNapi::CreatePhotoAlbumNapi(env, context->photoAlbum);
388             break;
389         case FetchResType::TYPE_SMARTALBUM:
390             jsAsset = SmartAlbumNapi::CreateSmartAlbumNapi(env, context->smartAlbumAsset);
391             break;
392         default:
393             NAPI_ERR_LOG("unsupported FetchResType");
394             break;
395     }
396 
397     if (jsAsset == nullptr) {
398         NAPI_ERR_LOG("Failed to get file asset napi object");
399         napi_get_undefined(env, &jsContext->data);
400         SendableMediaLibraryNapiUtils::CreateNapiErrorObject(env, jsContext->error, JS_INNER_FAIL,
401             "System inner fail");
402     } else {
403         jsContext->data = jsAsset;
404         napi_get_undefined(env, &jsContext->error);
405         jsContext->status = true;
406     }
407 }
408 
GetPositionObjectCompleteCallback(napi_env env,napi_status status,FetchFileResultSendableAsyncContext * context)409 static void GetPositionObjectCompleteCallback(napi_env env, napi_status status,
410     FetchFileResultSendableAsyncContext* context)
411 {
412     MediaLibraryTracer tracer;
413     tracer.Start("GetPositionObjectCompleteCallback");
414 
415     CHECK_NULL_PTR_RETURN_VOID(context, "Async context is null");
416 
417     unique_ptr<SendableJSAsyncContextOutput> jsContext = make_unique<SendableJSAsyncContextOutput>();
418     jsContext->status = false;
419 
420     GetNapiResFromAsset(env, context, jsContext);
421 
422     if (context->work != nullptr) {
423         SendableMediaLibraryNapiUtils::InvokeJSAsyncMethod(env, context->deferred, context->callbackRef,
424             context->work, *jsContext);
425     }
426 
427     delete context;
428 }
429 
JSGetFirstObject(napi_env env,napi_callback_info info)430 napi_value SendableFetchFileResultNapi::JSGetFirstObject(napi_env env, napi_callback_info info)
431 {
432     napi_status status;
433     napi_value result = nullptr;
434     const int32_t refCount = 1;
435     napi_value resource = nullptr;
436     size_t argc = ARGS_ONE;
437     napi_value argv[ARGS_ONE] = {0};
438     napi_value thisVar = nullptr;
439 
440     GET_JS_ARGS(env, info, argc, argv, thisVar);
441     NAPI_ASSERT(env, argc <= ARGS_ONE, "requires 1 parameter");
442     napi_get_undefined(env, &result);
443 
444     unique_ptr<FetchFileResultSendableAsyncContext> asyncContext = make_unique<FetchFileResultSendableAsyncContext>();
445     status = napi_unwrap_sendable(env, thisVar, reinterpret_cast<void **>(&asyncContext->objectInfo));
446     if (status == napi_ok && CheckIfFFRNapiNotEmpty(asyncContext->objectInfo)) {
447         if (argc == ARGS_ONE) {
448             GET_JS_ASYNC_CB_REF(env, argv[PARAM0], refCount, asyncContext->callbackRef);
449         }
450 
451         NAPI_CREATE_PROMISE(env, asyncContext->callbackRef, asyncContext->deferred, result);
452         NAPI_CREATE_RESOURCE_NAME(env, resource, "JSGetFirstObject", asyncContext);
453 
454         asyncContext->objectPtr = asyncContext->objectInfo->propertyPtr;
455         CHECK_NULL_PTR_RETURN_UNDEFINED(env, asyncContext->objectPtr, result, "propertyPtr is nullptr");
456 
457         status = napi_create_async_work(
458             env, nullptr, resource, [](napi_env env, void *data) {
459                 auto context = static_cast<FetchFileResultSendableAsyncContext*>(data);
460                 context->GetFirstAsset();
461             },
462             reinterpret_cast<napi_async_complete_callback>(GetPositionObjectCompleteCallback),
463             static_cast<void *>(asyncContext.get()), &asyncContext->work);
464         if (status != napi_ok) {
465             napi_get_undefined(env, &result);
466         } else {
467             napi_queue_async_work_with_qos(env, asyncContext->work, napi_qos_user_initiated);
468             asyncContext.release();
469         }
470     } else {
471         NAPI_ERR_LOG("JSGetFirstObject obj == nullptr, status: %{public}d", status);
472         NAPI_ASSERT(env, false, "JSGetFirstObject obj == nullptr");
473     }
474 
475     return result;
476 }
477 
JSGetNextObject(napi_env env,napi_callback_info info)478 napi_value SendableFetchFileResultNapi::JSGetNextObject(napi_env env, napi_callback_info info)
479 {
480     napi_status status;
481     napi_value result = nullptr;
482     const int32_t refCount = 1;
483     napi_value resource = nullptr;
484     size_t argc = ARGS_ONE;
485     napi_value argv[ARGS_ONE] = {0};
486     napi_value thisVar = nullptr;
487 
488     GET_JS_ARGS(env, info, argc, argv, thisVar);
489     NAPI_ASSERT(env, argc <= ARGS_ONE, "requires 1 parameter");
490 
491     napi_get_undefined(env, &result);
492     unique_ptr<FetchFileResultSendableAsyncContext> asyncContext = make_unique<FetchFileResultSendableAsyncContext>();
493     status = napi_unwrap_sendable(env, thisVar, reinterpret_cast<void **>(&asyncContext->objectInfo));
494     if (status == napi_ok && CheckIfFFRNapiNotEmpty(asyncContext->objectInfo)) {
495         if (argc == ARGS_ONE) {
496             GET_JS_ASYNC_CB_REF(env, argv[PARAM0], refCount, asyncContext->callbackRef);
497         }
498 
499         NAPI_CREATE_PROMISE(env, asyncContext->callbackRef, asyncContext->deferred, result);
500         NAPI_CREATE_RESOURCE_NAME(env, resource, "JSGetNextObject", asyncContext);
501 
502         asyncContext->objectPtr = asyncContext->objectInfo->propertyPtr;
503         CHECK_NULL_PTR_RETURN_UNDEFINED(env, asyncContext->objectPtr, result, "propertyPtr is nullptr");
504 
505         status = napi_create_async_work(
506             env, nullptr, resource, [](napi_env env, void *data) {
507                 auto context = static_cast<FetchFileResultSendableAsyncContext*>(data);
508                 context->GetNextObject();
509             },
510             reinterpret_cast<napi_async_complete_callback>(GetPositionObjectCompleteCallback),
511             static_cast<void *>(asyncContext.get()), &asyncContext->work);
512         if (status != napi_ok) {
513             napi_get_undefined(env, &result);
514         } else {
515             napi_queue_async_work_with_qos(env, asyncContext->work, napi_qos_user_initiated);
516             asyncContext.release();
517         }
518     } else {
519         NAPI_ERR_LOG("JSGetNextObject obj == nullptr, status: %{public}d", status);
520         NAPI_ASSERT(env, false, "JSGetNextObject obj == nullptr");
521     }
522 
523     return result;
524 }
525 
GetAsset(napi_env env,vector<std::unique_ptr<FileAsset>> & array,int index)526 static napi_value GetAsset(napi_env env, vector<std::unique_ptr<FileAsset>> &array, int index)
527 {
528     return SendableFileAssetNapi::CreateFileAsset(env, array[index]);
529 }
530 
GetAsset(napi_env env,vector<std::unique_ptr<AlbumAsset>> & array,int index)531 static napi_value GetAsset(napi_env env, vector<std::unique_ptr<AlbumAsset>> &array, int index)
532 {
533     return AlbumNapi::CreateAlbumNapi(env, array[index]);
534 }
535 
GetAsset(napi_env env,vector<std::unique_ptr<PhotoAlbum>> & array,int index)536 static napi_value GetAsset(napi_env env, vector<std::unique_ptr<PhotoAlbum>> &array, int index)
537 {
538     return SendablePhotoAlbumNapi::CreatePhotoAlbumNapi(env, array[index]);
539 }
540 
GetAsset(napi_env env,vector<std::unique_ptr<SmartAlbumAsset>> & array,int index)541 static napi_value GetAsset(napi_env env, vector<std::unique_ptr<SmartAlbumAsset>> &array, int index)
542 {
543     return SmartAlbumNapi::CreateSmartAlbumNapi(env, array[index]);
544 }
545 
546 template<class T>
GetAssetFromArray(napi_env env,FetchFileResultSendableAsyncContext * context,T & array,unique_ptr<SendableJSAsyncContextOutput> & jsContext)547 static void GetAssetFromArray(napi_env env, FetchFileResultSendableAsyncContext* context, T& array,
548     unique_ptr<SendableJSAsyncContextOutput> &jsContext)
549 {
550     napi_value jsFileArray = nullptr;
551     napi_create_array_with_length(env, array.size(), &jsFileArray);
552     napi_value jsFileAsset = nullptr;
553     size_t i = 0;
554     for (i = 0; i < array.size(); i++) {
555         jsFileAsset = GetAsset(env, array, i);
556         if ((jsFileAsset == nullptr) || (napi_set_element(env, jsFileArray, i, jsFileAsset) != napi_ok)) {
557             NAPI_ERR_LOG("Failed to get file asset napi object");
558             napi_get_undefined(env, &jsContext->data);
559             SendableMediaLibraryNapiUtils::CreateNapiErrorObject(env, jsContext->error, ERR_MEM_ALLOCATION,
560                 "Failed to create js object");
561             break;
562         }
563     }
564     if (i == array.size()) {
565         jsContext->data = jsFileArray;
566         napi_get_undefined(env, &jsContext->error);
567         jsContext->status = true;
568     }
569 }
570 
GetAllObjectCompleteCallback(napi_env env,napi_status status,FetchFileResultSendableAsyncContext * context)571 static void GetAllObjectCompleteCallback(napi_env env, napi_status status, FetchFileResultSendableAsyncContext* context)
572 {
573     MediaLibraryTracer tracer;
574     tracer.Start("GetAllObjectCompleteCallback");
575     CHECK_NULL_PTR_RETURN_VOID(context, "Async context is null");
576     unique_ptr<SendableJSAsyncContextOutput> jsContext = make_unique<SendableJSAsyncContextOutput>();
577     jsContext->status = false;
578 
579     switch (context->objectPtr->fetchResType_) {
580         case FetchResType::TYPE_FILE:
581             GetAssetFromArray(env, context, context->fileAssetArray, jsContext);
582             break;
583         case FetchResType::TYPE_ALBUM:
584             GetAssetFromArray(env, context, context->fileAlbumArray, jsContext);
585             break;
586         case FetchResType::TYPE_PHOTOALBUM:
587             GetAssetFromArray(env, context, context->filePhotoAlbumArray, jsContext);
588             break;
589         case FetchResType::TYPE_SMARTALBUM:
590             GetAssetFromArray(env, context, context->fileSmartAlbumArray, jsContext);
591             break;
592         default:
593             NAPI_ERR_LOG("unsupported FetchResType");
594             napi_get_undefined(env, &jsContext->data);
595             SendableMediaLibraryNapiUtils::CreateNapiErrorObject(env, jsContext->error, ERR_INVALID_OUTPUT,
596                 "Failed to obtain fileAsset array from DB");
597     }
598 
599     if (context->work != nullptr) {
600         int64_t start = MediaFileUtils::UTCTimeMilliSeconds();
601         SendableMediaLibraryNapiUtils::InvokeJSAsyncMethod(env, context->deferred, context->callbackRef,
602             context->work, *jsContext);
603         int64_t end = MediaFileUtils::UTCTimeMilliSeconds();
604         int64_t normalTime = 500;
605         if ((long)(end - start) >= normalTime) {
606             NAPI_INFO_LOG("InvokeJSAsync dir cost: %{public}ld", (long)(end - start));
607         }
608     }
609 
610     delete context;
611 }
612 
GetFetchFileResultObject()613 std::shared_ptr<FetchResult<FileAsset>> SendableFetchFileResultNapi::GetFetchFileResultObject()
614 {
615     return propertyPtr->fetchFileResult_;
616 }
617 
GetFetchAlbumResultObject()618 std::shared_ptr<FetchResult<AlbumAsset>> SendableFetchFileResultNapi::GetFetchAlbumResultObject()
619 {
620     return propertyPtr->fetchAlbumResult_;
621 }
622 
GetFetchPhotoAlbumResultObject()623 std::shared_ptr<FetchResult<PhotoAlbum>> SendableFetchFileResultNapi::GetFetchPhotoAlbumResultObject()
624 {
625     return propertyPtr->fetchPhotoAlbumResult_;
626 }
627 
GetFetchSmartAlbumResultObject()628 std::shared_ptr<FetchResult<SmartAlbumAsset>> SendableFetchFileResultNapi::GetFetchSmartAlbumResultObject()
629 {
630     return propertyPtr->fetchSmartAlbumResult_;
631 }
632 
GetAllObjectFromFetchResult(const FetchFileResultSendableAsyncContext & asyncContext)633 void GetAllObjectFromFetchResult(const FetchFileResultSendableAsyncContext &asyncContext)
634 {
635     MediaLibraryTracer tracer;
636     tracer.Start("GetAllObjectFromFetchResult");
637 
638     FetchFileResultSendableAsyncContext *context = const_cast<FetchFileResultSendableAsyncContext *>(&asyncContext);
639     context->GetAllObjectFromFetchResult();
640 }
641 
JSGetAllObject(napi_env env,napi_callback_info info)642 napi_value SendableFetchFileResultNapi::JSGetAllObject(napi_env env, napi_callback_info info)
643 {
644     napi_status status;
645     napi_value result = nullptr;
646     const int32_t refCount = 1;
647     napi_value resource = nullptr;
648     size_t argc = ARGS_ONE;
649     napi_value argv[ARGS_ONE] = {0};
650     napi_value thisVar = nullptr;
651 
652     MediaLibraryTracer tracer;
653     tracer.Start("JSGetAllObject");
654 
655     GET_JS_ARGS(env, info, argc, argv, thisVar);
656     NAPI_ASSERT(env, argc <= ARGS_ONE, "requires 1 parameter maximum");
657 
658     napi_get_undefined(env, &result);
659     unique_ptr<FetchFileResultSendableAsyncContext> asyncContext = make_unique<FetchFileResultSendableAsyncContext>();
660     status = napi_unwrap_sendable(env, thisVar, reinterpret_cast<void **>(&asyncContext->objectInfo));
661     if (status == napi_ok && CheckIfFFRNapiNotEmpty(asyncContext->objectInfo)) {
662         if (argc == ARGS_ONE) {
663             GET_JS_ASYNC_CB_REF(env, argv[PARAM0], refCount, asyncContext->callbackRef);
664         }
665 
666         NAPI_CREATE_PROMISE(env, asyncContext->callbackRef, asyncContext->deferred, result);
667         NAPI_CREATE_RESOURCE_NAME(env, resource, "JSGetAllObject", asyncContext);
668 
669         asyncContext->objectPtr = asyncContext->objectInfo->propertyPtr;
670         CHECK_NULL_PTR_RETURN_UNDEFINED(env, asyncContext->objectPtr, result, "propertyPtr is nullptr");
671 
672         status = napi_create_async_work(
673             env, nullptr, resource, [](napi_env env, void *data) {
674                 auto context = static_cast<FetchFileResultSendableAsyncContext*>(data);
675                 GetAllObjectFromFetchResult(*context);
676             },
677             reinterpret_cast<napi_async_complete_callback>(GetAllObjectCompleteCallback),
678             static_cast<void *>(asyncContext.get()), &asyncContext->work);
679         if (status != napi_ok) {
680             napi_get_undefined(env, &result);
681         } else {
682             napi_queue_async_work_with_qos(env, asyncContext->work, napi_qos_user_initiated);
683             asyncContext.release();
684         }
685     } else {
686         NAPI_ERR_LOG("JSGetAllObject obj == nullptr, status: %{public}d", status);
687         NAPI_ASSERT(env, false, "JSGetAllObject obj == nullptr");
688     }
689 
690     return result;
691 }
692 
JSClose(napi_env env,napi_callback_info info)693 napi_value SendableFetchFileResultNapi::JSClose(napi_env env, napi_callback_info info)
694 {
695     napi_status status;
696     napi_value jsResult = nullptr;
697     SendableFetchFileResultNapi* obj = nullptr;
698     napi_value thisVar = nullptr;
699 
700     MediaLibraryTracer tracer;
701     tracer.Start("JSClose");
702 
703     napi_get_undefined(env, &jsResult);
704     GET_JS_OBJ_WITH_ZERO_ARGS(env, info, status, thisVar);
705     if (status != napi_ok || thisVar == nullptr) {
706         NAPI_ERR_LOG("Invalid arguments!, status: %{public}d", status);
707         return jsResult;
708     }
709     status = napi_unwrap_sendable(env, thisVar, reinterpret_cast<void **>(&obj));
710     if ((status == napi_ok) && (obj != nullptr)) {
711         obj->propertyPtr = nullptr;
712     }
713     status = napi_remove_wrap_sendable(env, thisVar, reinterpret_cast<void **>(&obj));
714     if ((status == napi_ok) && (obj != nullptr)) {
715         napi_create_int32(env, E_SUCCESS, &jsResult);
716     } else {
717         NAPI_INFO_LOG("JSClose obj == nullptr");
718     }
719 
720     NAPI_DEBUG_LOG("JSClose OUT!");
721     return jsResult;
722 }
723 
GetFirstAsset()724 void FetchFileResultSendableAsyncContext::GetFirstAsset()
725 {
726     switch (objectPtr->fetchResType_) {
727         case FetchResType::TYPE_FILE: {
728             fileAsset = objectPtr->fetchFileResult_->GetFirstObject();
729             break;
730         }
731         case FetchResType::TYPE_ALBUM: {
732             albumAsset = objectPtr->fetchAlbumResult_->GetFirstObject();
733             break;
734         }
735         case FetchResType::TYPE_PHOTOALBUM: {
736             photoAlbum = objectPtr->fetchPhotoAlbumResult_->GetFirstObject();
737             break;
738         }
739         case FetchResType::TYPE_SMARTALBUM: {
740             smartAlbumAsset = objectPtr->fetchSmartAlbumResult_->GetFirstObject();
741             break;
742         }
743         default:
744             NAPI_ERR_LOG("unsupported FetchResType");
745             break;
746     }
747 }
748 
GetObjectAtPosition()749 void FetchFileResultSendableAsyncContext::GetObjectAtPosition()
750 {
751     switch (objectPtr->fetchResType_) {
752         case FetchResType::TYPE_FILE: {
753             fileAsset = objectPtr->fetchFileResult_->GetObjectAtPosition(position);
754             break;
755         }
756         case FetchResType::TYPE_ALBUM: {
757             albumAsset = objectPtr->fetchAlbumResult_->GetObjectAtPosition(position);
758             break;
759         }
760         case FetchResType::TYPE_PHOTOALBUM: {
761             photoAlbum = objectPtr->fetchPhotoAlbumResult_->GetObjectAtPosition(position);
762             break;
763         }
764         case FetchResType::TYPE_SMARTALBUM: {
765             smartAlbumAsset = objectPtr->fetchSmartAlbumResult_->GetObjectAtPosition(position);
766             break;
767         }
768         default:
769             NAPI_ERR_LOG("unsupported FetchResType");
770             break;
771     }
772 }
773 
GetLastObject()774 void FetchFileResultSendableAsyncContext::GetLastObject()
775 {
776     switch (objectPtr->fetchResType_) {
777         case FetchResType::TYPE_FILE: {
778             fileAsset = objectPtr->fetchFileResult_->GetLastObject();
779             break;
780         }
781         case FetchResType::TYPE_ALBUM: {
782             albumAsset = objectPtr->fetchAlbumResult_->GetLastObject();
783             break;
784         }
785         case FetchResType::TYPE_PHOTOALBUM: {
786             photoAlbum = objectPtr->fetchPhotoAlbumResult_->GetLastObject();
787             break;
788         }
789         case FetchResType::TYPE_SMARTALBUM: {
790             smartAlbumAsset = objectPtr->fetchSmartAlbumResult_->GetLastObject();
791             break;
792         }
793         default:
794             NAPI_ERR_LOG("unsupported FetchResType");
795             break;
796     }
797 }
798 
GetNextObject()799 void FetchFileResultSendableAsyncContext::GetNextObject()
800 {
801     switch (objectPtr->fetchResType_) {
802         case FetchResType::TYPE_FILE: {
803             fileAsset = objectPtr->fetchFileResult_->GetNextObject();
804             break;
805         }
806         case FetchResType::TYPE_ALBUM: {
807             albumAsset = objectPtr->fetchAlbumResult_->GetNextObject();
808             break;
809         }
810         case FetchResType::TYPE_PHOTOALBUM: {
811             photoAlbum = objectPtr->fetchPhotoAlbumResult_->GetNextObject();
812             break;
813         }
814         case FetchResType::TYPE_SMARTALBUM: {
815             smartAlbumAsset = objectPtr->fetchSmartAlbumResult_->GetNextObject();
816             break;
817         }
818         default:
819             NAPI_ERR_LOG("unsupported FetchResType");
820             break;
821     }
822 }
823 
GetAllObjectFromFetchResult()824 void FetchFileResultSendableAsyncContext::GetAllObjectFromFetchResult()
825 {
826     switch (objectPtr->fetchResType_) {
827         case FetchResType::TYPE_FILE: {
828             auto fetchResult = objectPtr->fetchFileResult_;
829             auto file = fetchResult->GetFirstObject();
830             while (file != nullptr) {
831                 fileAssetArray.push_back(move(file));
832                 file = fetchResult->GetNextObject();
833             }
834             break;
835         }
836         case FetchResType::TYPE_ALBUM: {
837             auto fetchResult = objectPtr->fetchAlbumResult_;
838             auto album = fetchResult->GetFirstObject();
839             while (album != nullptr) {
840                 fileAlbumArray.push_back(move(album));
841                 album = fetchResult->GetNextObject();
842             }
843             break;
844         }
845         case FetchResType::TYPE_PHOTOALBUM: {
846             auto fetchResult = objectPtr->fetchPhotoAlbumResult_;
847             auto photoAlbum = fetchResult->GetFirstObject();
848             while (photoAlbum != nullptr) {
849                 filePhotoAlbumArray.push_back(move(photoAlbum));
850                 photoAlbum = fetchResult->GetNextObject();
851             }
852             break;
853         }
854         case FetchResType::TYPE_SMARTALBUM: {
855             auto fetchResult = objectPtr->fetchSmartAlbumResult_;
856             auto smartAlbum = fetchResult->GetFirstObject();
857             while (smartAlbum != nullptr) {
858                 fileSmartAlbumArray.push_back(move(smartAlbum));
859                 smartAlbum = fetchResult->GetNextObject();
860             }
861             break;
862         }
863         default:
864             NAPI_ERR_LOG("unsupported FetchResType");
865             break;
866     }
867 }
868 
CheckIfPropertyPtrNull()869 bool SendableFetchFileResultNapi::CheckIfPropertyPtrNull()
870 {
871     return propertyPtr == nullptr;
872 }
873 
JSIsAfterLast(napi_env env,napi_callback_info info)874 napi_value SendableFetchFileResultNapi::JSIsAfterLast(napi_env env, napi_callback_info info)
875 {
876     napi_status status;
877     napi_value jsResult = nullptr;
878     SendableFetchFileResultNapi* obj = nullptr;
879     bool isAfterLast = false;
880     napi_value thisVar = nullptr;
881 
882     MediaLibraryTracer tracer;
883     tracer.Start("JSIsAfterLast");
884 
885     napi_get_undefined(env, &jsResult);
886     GET_JS_OBJ_WITH_ZERO_ARGS(env, info, status, thisVar);
887     if (status != napi_ok || thisVar == nullptr) {
888         NAPI_ERR_LOG("JSIsAfterLast Invalid arguments!, status: %{public}d", status);
889         NAPI_ASSERT(env, false, "JSIsAfterLast thisVar == nullptr");
890     }
891 
892     status = napi_unwrap_sendable(env, thisVar, reinterpret_cast<void **>(&obj));
893     if ((status == napi_ok) && CheckIfFFRNapiNotEmpty(obj)) {
894         switch (obj->GetFetchResType()) {
895             case FetchResType::TYPE_FILE:
896                 isAfterLast = obj->GetFetchFileResultObject()->IsAtLastRow();
897                 break;
898             case FetchResType::TYPE_ALBUM:
899                 isAfterLast = obj->GetFetchAlbumResultObject()->IsAtLastRow();
900                 break;
901             case FetchResType::TYPE_PHOTOALBUM:
902                 isAfterLast = obj->GetFetchPhotoAlbumResultObject()->IsAtLastRow();
903                 break;
904             case FetchResType::TYPE_SMARTALBUM:
905                 isAfterLast = obj->GetFetchSmartAlbumResultObject()->IsAtLastRow();
906                 break;
907             default:
908                 NAPI_ERR_LOG("unsupported FetchResType");
909                 break;
910         }
911         napi_get_boolean(env, isAfterLast, &jsResult);
912     } else {
913         NAPI_ERR_LOG("JSIsAfterLast obj == nullptr, status: %{public}d", status);
914         NAPI_ASSERT(env, false, "JSIsAfterLast obj == nullptr");
915     }
916 
917     return jsResult;
918 }
919 
JSGetLastObject(napi_env env,napi_callback_info info)920 napi_value SendableFetchFileResultNapi::JSGetLastObject(napi_env env, napi_callback_info info)
921 {
922     napi_status status;
923     napi_value result = nullptr;
924     const int32_t refCount = 1;
925     napi_value resource = nullptr;
926     size_t argc = ARGS_ONE;
927     napi_value argv[ARGS_ONE] = {0};
928     napi_value thisVar = nullptr;
929 
930     GET_JS_ARGS(env, info, argc, argv, thisVar);
931     NAPI_ASSERT(env, argc <= ARGS_ONE, "requires 1 parameter");
932 
933     napi_get_undefined(env, &result);
934     unique_ptr<FetchFileResultSendableAsyncContext> asyncContext = make_unique<FetchFileResultSendableAsyncContext>();
935     status = napi_unwrap_sendable(env, thisVar, reinterpret_cast<void **>(&asyncContext->objectInfo));
936     if (status == napi_ok && CheckIfFFRNapiNotEmpty(asyncContext->objectInfo)) {
937         if (argc == ARGS_ONE) {
938             GET_JS_ASYNC_CB_REF(env, argv[PARAM0], refCount, asyncContext->callbackRef);
939         }
940 
941         NAPI_CREATE_PROMISE(env, asyncContext->callbackRef, asyncContext->deferred, result);
942         NAPI_CREATE_RESOURCE_NAME(env, resource, "JSGetLastObject", asyncContext);
943 
944         asyncContext->objectPtr = asyncContext->objectInfo->propertyPtr;
945         CHECK_NULL_PTR_RETURN_UNDEFINED(env, asyncContext->objectPtr, result, "propertyPtr is nullptr");
946 
947         status = napi_create_async_work(
948             env, nullptr, resource, [](napi_env env, void *data) {
949                 auto context = static_cast<FetchFileResultSendableAsyncContext*>(data);
950                 context->GetLastObject();
951             },
952             reinterpret_cast<napi_async_complete_callback>(GetPositionObjectCompleteCallback),
953             static_cast<void *>(asyncContext.get()), &asyncContext->work);
954         if (status != napi_ok) {
955             napi_get_undefined(env, &result);
956         } else {
957             napi_queue_async_work_with_qos(env, asyncContext->work, napi_qos_user_initiated);
958             asyncContext.release();
959         }
960     } else {
961         NAPI_ERR_LOG("JSGetLastObject obj == nullptr, status: %{public}d", status);
962         NAPI_ASSERT(env, false, "JSGetLastObject obj == nullptr");
963     }
964 
965     return result;
966 }
967 
JSGetPositionObject(napi_env env,napi_callback_info info)968 napi_value SendableFetchFileResultNapi::JSGetPositionObject(napi_env env, napi_callback_info info)
969 {
970     napi_status status;
971     napi_value result = nullptr;
972     const int32_t refCount = 1;
973     napi_valuetype type = napi_undefined;
974     napi_value resource = nullptr;
975     size_t argc = ARGS_TWO;
976     napi_value argv[ARGS_TWO] = {0};
977     napi_value thisVar = nullptr;
978 
979     MediaLibraryTracer tracer;
980     tracer.Start("JSGetPositionObject");
981 
982     GET_JS_ARGS(env, info, argc, argv, thisVar);
983     NAPI_ASSERT(env, (argc == ARGS_ONE || argc == ARGS_TWO), "requires 2 parameter maximum");
984 
985     napi_get_undefined(env, &result);
986     unique_ptr<FetchFileResultSendableAsyncContext> asyncContext = make_unique<FetchFileResultSendableAsyncContext>();
987     status = napi_unwrap_sendable(env, thisVar, reinterpret_cast<void **>(&asyncContext->objectInfo));
988     if (status == napi_ok && CheckIfFFRNapiNotEmpty(asyncContext->objectInfo)) {
989         // Check the arguments and their types
990         napi_typeof(env, argv[PARAM0], &type);
991         if (type == napi_number) {
992             napi_get_value_int32(env, argv[PARAM0], &(asyncContext->position));
993         } else {
994             NAPI_ERR_LOG("Argument mismatch, type: %{public}d", type);
995             return result;
996         }
997 
998         if (argc == ARGS_TWO) {
999             GET_JS_ASYNC_CB_REF(env, argv[PARAM1], refCount, asyncContext->callbackRef);
1000         }
1001 
1002         NAPI_CREATE_PROMISE(env, asyncContext->callbackRef, asyncContext->deferred, result);
1003         NAPI_CREATE_RESOURCE_NAME(env, resource, "JSGetPositionObject", asyncContext);
1004 
1005         asyncContext->objectPtr = asyncContext->objectInfo->propertyPtr;
1006         CHECK_NULL_PTR_RETURN_UNDEFINED(env, asyncContext->objectPtr, result, "propertyPtr is nullptr");
1007 
1008         status = napi_create_async_work(
1009             env, nullptr, resource, [](napi_env env, void *data) {
1010                 auto context = static_cast<FetchFileResultSendableAsyncContext*>(data);
1011                 context->GetObjectAtPosition();
1012             },
1013             reinterpret_cast<napi_async_complete_callback>(GetPositionObjectCompleteCallback),
1014             static_cast<void *>(asyncContext.get()), &asyncContext->work);
1015         if (status != napi_ok) {
1016             napi_get_undefined(env, &result);
1017         } else {
1018             napi_queue_async_work_with_qos(env, asyncContext->work, napi_qos_user_initiated);
1019             asyncContext.release();
1020         }
1021     } else {
1022         NAPI_ERR_LOG("JSGetPositionObject obj == nullptr, status: %{public}d", status);
1023         NAPI_ASSERT(env, false, "JSGetPositionObject obj == nullptr");
1024     }
1025 
1026     return result;
1027 }
1028 } // namespace Media
1029 } // namespace OHOS