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