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