• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 /*
2  * Copyright (c) 2023 Huawei Device Co., Ltd.
3  * Licensed under the Apache License, Version 2.0 (the "License");
4  * you may not use this file except in compliance with the License.
5  * You may obtain a copy of the License at
6  *
7  *     http://www.apache.org/licenses/LICENSE-2.0
8  *
9  * Unless required by applicable law or agreed to in writing, software
10  * distributed under the License is distributed on an "AS IS" BASIS,
11  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12  * See the License for the specific language governing permissions and
13  * limitations under the License.
14  */
15 
16 #include "js_component_snapshot.h"
17 
18 #include "interfaces/napi/kits/utils/napi_utils.h"
19 #include "js_native_api.h"
20 #include "js_native_api_types.h"
21 #include "napi/native_common.h"
22 #include "node_api_types.h"
23 #include "base/utils/utils.h"
24 #ifdef PIXEL_MAP_SUPPORTED
25 #include "pixel_map.h"
26 #include "pixel_map_napi.h"
27 #endif
28 
29 #include "node_api.h"
30 
31 #include "bridge/common/utils/utils.h"
32 #include "core/common/ace_engine.h"
33 
34 #include "frameworks/bridge/common/utils/engine_helper.h"
35 
36 namespace OHOS::Ace::Napi {
37 namespace {
38 
39 struct SnapshotAsyncCtx {
40     napi_env env = nullptr;
41     napi_deferred deferred = nullptr;
42     napi_ref callbackRef = nullptr;
43     std::shared_ptr<Media::PixelMap> pixmap = nullptr;
44     int32_t errCode = -1;
45     int32_t instanceId = -1;
46 };
47 
OnComplete(SnapshotAsyncCtx * asyncCtx,std::function<void ()> finishCallback)48 void OnComplete(SnapshotAsyncCtx* asyncCtx, std::function<void()> finishCallback)
49 {
50     auto container = AceEngine::Get().GetContainer(asyncCtx->instanceId);
51     if (!container) {
52         LOGW("container is null. %{public}d", asyncCtx->instanceId);
53         return;
54     }
55 
56     auto taskExecutor = container->GetTaskExecutor();
57     if (!taskExecutor) {
58         LOGW("taskExecutor is null.");
59         return;
60     }
61     taskExecutor->PostTask(
62         [asyncCtx, finishCallback]() {
63             std::unique_ptr<SnapshotAsyncCtx> ctx(asyncCtx);
64             napi_handle_scope scope = nullptr;
65             napi_open_handle_scope(ctx->env, &scope);
66 
67             // callback result format: [Error, PixelMap]
68             napi_value result[2] = { nullptr };
69             napi_get_undefined(ctx->env, &result[0]);
70             napi_get_undefined(ctx->env, &result[1]);
71 
72             if (ctx->errCode == ERROR_CODE_NO_ERROR) {
73 #ifdef PIXEL_MAP_SUPPORTED
74                 // convert pixelMap to napi value
75                 result[1] = Media::PixelMapNapi::CreatePixelMap(ctx->env, ctx->pixmap);
76 #endif
77             }
78             napi_create_int32(ctx->env, ctx->errCode, &result[0]);
79 
80             if (ctx->deferred) {
81                 // promise
82                 if (ctx->errCode == ERROR_CODE_NO_ERROR) {
83                     napi_resolve_deferred(ctx->env, ctx->deferred, result[1]);
84                 } else {
85                     napi_reject_deferred(ctx->env, ctx->deferred, result[0]);
86                 }
87             } else {
88                 // callback
89                 napi_value ret = nullptr;
90                 napi_value napiCallback = nullptr;
91                 napi_get_reference_value(ctx->env, ctx->callbackRef, &napiCallback);
92                 napi_call_function(ctx->env, nullptr, napiCallback, 2, result, &ret);
93                 napi_delete_reference(ctx->env, ctx->callbackRef);
94             }
95 
96             napi_close_handle_scope(ctx->env, scope);
97             if (finishCallback) {
98                 finishCallback();
99             }
100         },
101         TaskExecutor::TaskType::JS, "ArkUIComponentSnapshotComplete");
102 }
103 } // namespace
104 
JsComponentSnapshot(napi_env env,napi_callback_info info)105 JsComponentSnapshot::JsComponentSnapshot(napi_env env, napi_callback_info info) : env_(env), argc_(ARGC_MAX)
106 {
107     napi_value thisVar = nullptr;
108     void* data = nullptr;
109 
110     // get arguments from JS
111     napi_get_cb_info(env, info, &argc_, argv_, &thisVar, &data);
112 }
113 
CheckArgs(napi_valuetype firstArgType)114 bool JsComponentSnapshot::CheckArgs(napi_valuetype firstArgType)
115 
116 {
117     size_t minArgc = 1;
118     std::string errorMsg;
119     if (argc_ < minArgc) {
120         errorMsg = "The number of parameters must be greater than or equal to 1.";
121         LOGE("%{public}s", errorMsg.c_str());
122         NapiThrow(env_, errorMsg, ERROR_CODE_PARAM_INVALID);
123 
124         return false;
125     }
126     if (argc_ > ARGC_MAX) {
127         errorMsg = "The largest number of parameters is 2.";
128         LOGE("%{public}s", errorMsg.c_str());
129         NapiThrow(env_, errorMsg, ERROR_CODE_PARAM_INVALID);
130         return false;
131     }
132     napi_valuetype type = napi_undefined;
133     napi_typeof(env_, argv_[0], &type);
134     if (type != firstArgType) {
135         errorMsg = "parameter id is not of type string";
136         LOGE("%{public}s", errorMsg.c_str());
137         NapiThrow(env_, errorMsg, ERROR_CODE_PARAM_INVALID);
138         return false;
139     }
140     return true;
141 }
142 
CreateCallback(napi_value * result)143 auto JsComponentSnapshot::CreateCallback(napi_value* result)
144 {
145     auto* asyncCtx = new SnapshotAsyncCtx;
146     napi_valuetype type = napi_undefined;
147     // parse JsCallback
148     if (argc_ >= 2) {
149         napi_typeof(env_, argv_[1], &type);
150         if (type == napi_function) {
151             napi_create_reference(env_, argv_[1], 1, &asyncCtx->callbackRef);
152         }
153     }
154     // init promise
155     if (!asyncCtx->callbackRef) {
156         napi_create_promise(env_, &asyncCtx->deferred, result);
157     } else {
158         napi_get_undefined(env_, result);
159     }
160 
161     asyncCtx->env = env_;
162     asyncCtx->instanceId = Container::CurrentIdSafely();
163 
164     return [asyncCtx](std::shared_ptr<Media::PixelMap> pixmap, int32_t errCode, std::function<void()> finishCallback) {
165         asyncCtx->pixmap = std::move(pixmap);
166         asyncCtx->errCode = errCode;
167         OnComplete(asyncCtx, finishCallback);
168     };
169 }
170 
GetArgv(int32_t idx)171 napi_value JsComponentSnapshot::GetArgv(int32_t idx)
172 {
173     if (idx >= ARGC_MAX) {
174         return nullptr;
175     }
176     return argv_[idx];
177 }
178 
ParseParamForBuilder(NG::SnapshotParam & param)179 void JsComponentSnapshot::ParseParamForBuilder(NG::SnapshotParam& param)
180 {
181     // parse second param for builder interface
182     if (argc_ >= 2) {
183         napi_valuetype type = napi_undefined;
184         napi_typeof(env_, argv_[1], &type);
185         if (type != napi_function) {
186             ParseParam(1, param);
187         }
188     }
189     // parse third param for builder interface
190     if (argc_ >= 3) {
191         ParseParam(2, param);
192     }
193     // parse fourth param for builder interface
194     if (argc_ >= 4) {
195         ParseParam(3, param);
196     }
197     // parse fifth param for builder interface
198     if (argc_ == 5) {
199         ParseParam(4, param);
200     }
201 }
202 
ParseParamForGet(NG::SnapshotOptions & options)203 void JsComponentSnapshot::ParseParamForGet(NG::SnapshotOptions& options)
204 {
205     // parse options param for Promise
206     if (argc_ >= 2) {
207         napi_valuetype type = napi_undefined;
208         napi_typeof(env_, argv_[1], &type);
209         if (type != napi_function) {
210             ParseOptions(1, options);
211         }
212     }
213     // parse options param for Callback
214     if (argc_ == 3) {
215         ParseOptions(2, options);
216     }
217 }
218 
ParseParam(int32_t idx,NG::SnapshotParam & param)219 void JsComponentSnapshot::ParseParam(int32_t idx, NG::SnapshotParam& param)
220 {
221     if (static_cast<int32_t>(argc_) <= idx) {
222         return;
223     }
224     napi_valuetype type = napi_undefined;
225     napi_typeof(env_, argv_[idx], &type);
226     // parse delay param
227     if (type == napi_number) {
228         int32_t delayTime = 0;
229         napi_get_value_int32(env_, argv_[idx], &delayTime);
230         if (delayTime >= 0) {
231             param.delay = delayTime;
232         }
233     }
234     // parse checkImageStatus param
235     if (type == napi_boolean) {
236         bool checkImageStatus = 0;
237         napi_get_value_bool(env_, argv_[idx], &checkImageStatus);
238         param.checkImageStatus = checkImageStatus;
239     }
240     // parse SnapshotOptions param
241     if (type == napi_object) {
242         NG::SnapshotOptions options;
243         ParseOptions(idx, options);
244         param.options = options;
245     }
246 }
247 
ParseOptions(int32_t idx,NG::SnapshotOptions & options)248 void JsComponentSnapshot::ParseOptions(int32_t idx, NG::SnapshotOptions& options)
249 {
250     if (static_cast<int32_t>(argc_) <= idx) {
251         return;
252     }
253     napi_valuetype type = napi_undefined;
254     napi_typeof(env_, argv_[idx], &type);
255     if (type != napi_object) {
256         return;
257     }
258 
259     bool result = false;
260     napi_has_named_property(env_, argv_[idx], "scale", &result);
261     if (result) {
262         napi_value scaleNapi = nullptr;
263         napi_get_named_property(env_, argv_[idx], "scale", &scaleNapi);
264         double scale = 0.0;
265         napi_get_value_double(env_, scaleNapi, &scale);
266         if (GreatNotEqual(scale, 0.0)) {
267             options.scale = static_cast<float>(scale);
268         }
269     }
270 
271     result = false;
272     napi_has_named_property(env_, argv_[idx], "waitUntilRenderFinished", &result);
273     if (result) {
274         napi_value waitUntilRenderFinishedNapi = nullptr;
275         napi_get_named_property(env_, argv_[idx], "waitUntilRenderFinished", &waitUntilRenderFinishedNapi);
276         bool waitUntilRenderFinished = false;
277         napi_get_value_bool(env_, waitUntilRenderFinishedNapi, &waitUntilRenderFinished);
278         options.waitUntilRenderFinished = waitUntilRenderFinished;
279     }
280 
281     result = false;
282     napi_has_named_property(env_, argv_[idx], "region", &result);
283     if (!result) {
284         options.regionMode = NG::SnapshotRegionMode::NO_REGION;
285         return;
286     }
287     napi_value regionObject = nullptr;
288     napi_get_named_property(env_, argv_[idx], "region", &regionObject);
289     if (!regionObject) {
290         options.regionMode = NG::SnapshotRegionMode::NO_REGION;
291         return;
292     }
293 
294     options.regionMode = NG::SnapshotRegionMode::COMMON;
295     if (ParseLocalizedRegion(&regionObject, options)) {
296         options.regionMode = NG::SnapshotRegionMode::LOCALIZED;
297     } else {
298         ParseRegion(&regionObject, options);
299     }
300 }
301 
ParseRegion(napi_value * regionObject,NG::SnapshotOptions & options)302 bool JsComponentSnapshot::ParseRegion(napi_value* regionObject, NG::SnapshotOptions& options)
303 {
304     bool getReigonResult = false;
305     options.snapshotRegion = NG::LocalizedSnapshotRegion {};
306     napi_has_named_property(env_, *regionObject, "left", &getReigonResult);
307     if (!getReigonResult) {
308         LOGE("The \"left\" attribute cannot be obtained from the parameter.");
309         return false;
310     }
311     napi_value leftPxNapi;
312     napi_get_named_property(env_, *regionObject, "left", &leftPxNapi);
313     napi_get_value_double(env_, leftPxNapi, &options.snapshotRegion.start);
314 
315     napi_has_named_property(env_, *regionObject, "right", &getReigonResult);
316     if (!getReigonResult) {
317         LOGE("The \"right\" attribute cannot be obtained from the parameter.");
318         return false;
319     }
320     napi_value rightPxNapi;
321     napi_get_named_property(env_, *regionObject, "right", &rightPxNapi);
322     napi_get_value_double(env_, rightPxNapi, &options.snapshotRegion.end);
323 
324     napi_has_named_property(env_, *regionObject, "top", &getReigonResult);
325     if (!getReigonResult) {
326         LOGE("The \"top\" attribute cannot be obtained from the parameter.");
327         return false;
328     }
329     napi_value topPxNapi;
330     napi_get_named_property(env_, *regionObject, "top", &topPxNapi);
331     napi_get_value_double(env_, topPxNapi, &options.snapshotRegion.top);
332 
333     napi_has_named_property(env_, *regionObject, "bottom", &getReigonResult);
334     if (!getReigonResult) {
335         LOGE("The \"bottom\" attribute cannot be obtained from the parameter.");
336         return false;
337     }
338     napi_value bottomPxNapi;
339     napi_get_named_property(env_, *regionObject, "bottom", &bottomPxNapi);
340     napi_get_value_double(env_, bottomPxNapi, &options.snapshotRegion.bottom);
341     return true;
342 }
343 
ParseLocalizedRegion(napi_value * regionObject,NG::SnapshotOptions & options)344 bool JsComponentSnapshot::ParseLocalizedRegion(napi_value* regionObject, NG::SnapshotOptions& options)
345 {
346     options.snapshotRegion = NG::LocalizedSnapshotRegion {};
347     bool getReigonResult = false;
348     napi_has_named_property(env_, *regionObject, "start", &getReigonResult);
349     if (!getReigonResult) {
350         LOGE("The \"start\" attribute cannot be obtained from the parameter.");
351         return false;
352     }
353     napi_value startPxNapi;
354     napi_get_named_property(env_, *regionObject, "start", &startPxNapi);
355     napi_get_value_double(env_, startPxNapi, &options.snapshotRegion.start);
356 
357     napi_has_named_property(env_, *regionObject, "end", &getReigonResult);
358     if (!getReigonResult) {
359         LOGE("The \"end\" attribute cannot be obtained from the parameter.");
360         return false;
361     }
362     napi_value endPxNapi;
363     napi_get_named_property(env_, *regionObject, "end", &endPxNapi);
364     napi_get_value_double(env_, endPxNapi, &options.snapshotRegion.end);
365 
366     napi_has_named_property(env_, *regionObject, "top", &getReigonResult);
367     if (!getReigonResult) {
368         LOGE("The \"top\" attribute cannot be obtained from the parameter.");
369         return false;
370     }
371     napi_value topPxNapi;
372     napi_get_named_property(env_, *regionObject, "top", &topPxNapi);
373     napi_get_value_double(env_, topPxNapi, &options.snapshotRegion.top);
374 
375     napi_has_named_property(env_, *regionObject, "bottom", &getReigonResult);
376     if (!getReigonResult) {
377         LOGE("The \"bottom\" attribute cannot be obtained from the parameter.");
378         return false;
379     }
380     napi_value bottomPxNapi;
381     napi_get_named_property(env_, *regionObject, "bottom", &bottomPxNapi);
382     napi_get_value_double(env_, bottomPxNapi, &options.snapshotRegion.bottom);
383     return true;
384 }
385 
JSSnapshotGet(napi_env env,napi_callback_info info)386 static napi_value JSSnapshotGet(napi_env env, napi_callback_info info)
387 {
388     napi_escapable_handle_scope scope = nullptr;
389     napi_open_escapable_handle_scope(env, &scope);
390 
391     JsComponentSnapshot helper(env, info);
392 
393     napi_value result = nullptr;
394 
395     if (!helper.CheckArgs(napi_valuetype::napi_string)) {
396         TAG_LOGW(AceLogTag::ACE_COMPONENT_SNAPSHOT, "Parsing the first argument failed, not of string type.");
397         napi_close_escapable_handle_scope(env, scope);
398         return result;
399     }
400 
401     // parse id
402     std::string componentId;
403     napi_valuetype valueType = napi_null;
404     GetNapiString(env, helper.GetArgv(0), componentId, valueType);
405 
406     auto delegate = EngineHelper::GetCurrentDelegateSafely();
407     if (!delegate) {
408         TAG_LOGW(AceLogTag::ACE_COMPONENT_SNAPSHOT,
409             "Can't get delegate of ace_engine. param: " SEC_PLD(%{public}s),
410             SEC_PARAM(componentId.c_str()));
411         auto callback = helper.CreateCallback(&result);
412         callback(nullptr, ERROR_CODE_INTERNAL_ERROR, nullptr);
413         return result;
414     }
415 
416     NG::SnapshotOptions options;
417     helper.ParseParamForGet(options);
418 
419     delegate->GetSnapshot(componentId, helper.CreateCallback(&result), options);
420 
421     napi_escape_handle(env, scope, result, &result);
422     napi_close_escapable_handle_scope(env, scope);
423     return result;
424 }
425 
JSSnapshotFromBuilder(napi_env env,napi_callback_info info)426 static napi_value JSSnapshotFromBuilder(napi_env env, napi_callback_info info)
427 {
428     napi_escapable_handle_scope scope = nullptr;
429     napi_open_escapable_handle_scope(env, &scope);
430 
431     JsComponentSnapshot helper(env, info);
432     if (!helper.CheckArgs(napi_valuetype::napi_function)) {
433         TAG_LOGW(AceLogTag::ACE_COMPONENT_SNAPSHOT, "Parsing the first argument failed, not of function type.");
434         napi_close_escapable_handle_scope(env, scope);
435         return nullptr;
436     }
437 
438     napi_value result = nullptr;
439     auto delegate = EngineHelper::GetCurrentDelegateSafely();
440     if (!delegate) {
441         TAG_LOGW(AceLogTag::ACE_COMPONENT_SNAPSHOT, "Can't get delegate of ace_engine. ");
442         auto callback = helper.CreateCallback(&result);
443         callback(nullptr, ERROR_CODE_INTERNAL_ERROR, nullptr);
444         return nullptr;
445     }
446 
447     // create builder closure
448     auto builder = [build = helper.GetArgv(0), env] { napi_call_function(env, nullptr, build, 0, nullptr, nullptr); };
449 
450     NG::SnapshotParam param;
451     helper.ParseParamForBuilder(param);
452 
453     delegate->CreateSnapshot(builder, helper.CreateCallback(&result), true, param);
454 
455     napi_escape_handle(env, scope, result, &result);
456     napi_close_escapable_handle_scope(env, scope);
457     return result;
458 }
459 
JSSnapshotGetSync(napi_env env,napi_callback_info info)460 static napi_value JSSnapshotGetSync(napi_env env, napi_callback_info info)
461 {
462     napi_escapable_handle_scope scope = nullptr;
463     napi_open_escapable_handle_scope(env, &scope);
464 
465     JsComponentSnapshot helper(env, info);
466 
467     napi_value result = nullptr;
468 
469     if (!helper.CheckArgs(napi_valuetype::napi_string)) {
470         TAG_LOGW(AceLogTag::ACE_COMPONENT_SNAPSHOT, "Parsing the first argument failed, not of string type.");
471         napi_close_escapable_handle_scope(env, scope);
472         return result;
473     }
474 
475     // parse id
476     std::string componentId;
477     napi_valuetype valueType = napi_null;
478     GetNapiString(env, helper.GetArgv(0), componentId, valueType);
479 
480     auto delegate = EngineHelper::GetCurrentDelegateSafely();
481     if (!delegate) {
482         TAG_LOGW(AceLogTag::ACE_COMPONENT_SNAPSHOT,
483             "Can't get delegate of ace_engine. param: " SEC_PLD(%{public}s),
484             SEC_PARAM(componentId.c_str()));
485         NapiThrow(env, "Delegate is null", ERROR_CODE_INTERNAL_ERROR);
486         napi_close_escapable_handle_scope(env, scope);
487         return result;
488     }
489 
490     NG::SnapshotOptions options;
491     helper.ParseParamForGet(options);
492 
493     auto pair = delegate->GetSyncSnapshot(componentId,  options);
494 
495     switch (pair.first) {
496         case ERROR_CODE_NO_ERROR :
497 #ifdef PIXEL_MAP_SUPPORTED
498             result = Media::PixelMapNapi::CreatePixelMap(env, pair.second);
499 #endif
500             break;
501         case ERROR_CODE_INTERNAL_ERROR :
502             napi_get_null(env, &result);
503             NapiThrow(env, "Internal error!", ERROR_CODE_INTERNAL_ERROR);
504             break;
505         case ERROR_CODE_COMPONENT_SNAPSHOT_TIMEOUT :
506             napi_get_null(env, &result);
507             NapiThrow(env, "ComponentSnapshot timeout!", ERROR_CODE_COMPONENT_SNAPSHOT_TIMEOUT);
508             break;
509     }
510     napi_escape_handle(env, scope, result, &result);
511     napi_close_escapable_handle_scope(env, scope);
512     return result;
513 }
514 
JSSnapshotGetWithUniqueId(napi_env env,napi_callback_info info)515 static napi_value JSSnapshotGetWithUniqueId(napi_env env, napi_callback_info info)
516 {
517     napi_escapable_handle_scope scope = nullptr;
518     napi_open_escapable_handle_scope(env, &scope);
519 
520     JsComponentSnapshot helper(env, info);
521 
522     napi_value result = nullptr;
523 
524     napi_valuetype type = napi_undefined;
525     napi_typeof(env, helper.GetArgv(0), &type);
526     if (type != napi_valuetype::napi_number) {
527         TAG_LOGW(AceLogTag::ACE_COMPONENT_SNAPSHOT, "Parsing the first argument failed, not of number type.");
528         NapiThrow(env, "parameter uniqueId is not of type number", ERROR_CODE_PARAM_INVALID);
529         napi_close_escapable_handle_scope(env, scope);
530         return result;
531     }
532     // parse uniqueId
533     int32_t uniqueId;
534     napi_get_value_int32(env, helper.GetArgv(0), &uniqueId);
535 
536     auto delegate = EngineHelper::GetCurrentDelegateSafely();
537     if (!delegate) {
538         TAG_LOGW(AceLogTag::ACE_COMPONENT_SNAPSHOT,
539             "Can't get delegate of ace_engine. param: %{public}d",
540             uniqueId);
541         auto callback = helper.CreateCallback(&result);
542         callback(nullptr, ERROR_CODE_INTERNAL_ERROR, nullptr);
543         napi_close_escapable_handle_scope(env, scope);
544         return result;
545     }
546 
547     NG::SnapshotOptions options;
548     helper.ParseParamForGet(options);
549 
550     delegate->GetSnapshotByUniqueId(uniqueId, helper.CreateCallback(&result), options);
551 
552     napi_escape_handle(env, scope, result, &result);
553     napi_close_escapable_handle_scope(env, scope);
554     return result;
555 }
556 
JSSnapshotGetSyncWithUniqueId(napi_env env,napi_callback_info info)557 static napi_value JSSnapshotGetSyncWithUniqueId(napi_env env, napi_callback_info info)
558 {
559     napi_escapable_handle_scope scope = nullptr;
560     napi_open_escapable_handle_scope(env, &scope);
561 
562     JsComponentSnapshot helper(env, info);
563 
564     napi_value result = nullptr;
565 
566     napi_valuetype type = napi_undefined;
567     napi_typeof(env, helper.GetArgv(0), &type);
568     if (type != napi_valuetype::napi_number) {
569         TAG_LOGW(AceLogTag::ACE_COMPONENT_SNAPSHOT, "Parsing the first argument failed, not of number type.");
570         NapiThrow(env, "parameter uniqueId is not of type number", ERROR_CODE_PARAM_INVALID);
571         napi_close_escapable_handle_scope(env, scope);
572         return result;
573     }
574     // parse uniqueId
575     int32_t uniqueId;
576     napi_get_value_int32(env, helper.GetArgv(0), &uniqueId);
577 
578     auto delegate = EngineHelper::GetCurrentDelegateSafely();
579     if (!delegate) {
580         TAG_LOGW(AceLogTag::ACE_COMPONENT_SNAPSHOT,
581             "Can't get delegate of ace_engine. param: %{public}d", uniqueId);
582         NapiThrow(env, "Delegate is null", ERROR_CODE_INTERNAL_ERROR);
583         napi_close_escapable_handle_scope(env, scope);
584         return result;
585     }
586 
587     NG::SnapshotOptions options;
588     helper.ParseParamForGet(options);
589 
590     auto pair = delegate->GetSyncSnapshotByUniqueId(uniqueId,  options);
591 
592     switch (pair.first) {
593         case ERROR_CODE_NO_ERROR :
594 #ifdef PIXEL_MAP_SUPPORTED
595             result = Media::PixelMapNapi::CreatePixelMap(env, pair.second);
596 #endif
597             break;
598         case ERROR_CODE_INTERNAL_ERROR :
599             napi_get_null(env, &result);
600             NapiThrow(env, "Internal error!", ERROR_CODE_INTERNAL_ERROR);
601             break;
602         case ERROR_CODE_COMPONENT_SNAPSHOT_TIMEOUT :
603             napi_get_null(env, &result);
604             NapiThrow(env, "ComponentSnapshot timeout!", ERROR_CODE_COMPONENT_SNAPSHOT_TIMEOUT);
605             break;
606     }
607     napi_escape_handle(env, scope, result, &result);
608     napi_close_escapable_handle_scope(env, scope);
609     return result;
610 }
611 
ComponentSnapshotExport(napi_env env,napi_value exports)612 static napi_value ComponentSnapshotExport(napi_env env, napi_value exports)
613 {
614     napi_property_descriptor snapshotDesc[] = {
615         DECLARE_NAPI_FUNCTION("get", JSSnapshotGet),
616         DECLARE_NAPI_FUNCTION("createFromBuilder", JSSnapshotFromBuilder),
617         DECLARE_NAPI_FUNCTION("getSync", JSSnapshotGetSync),
618         DECLARE_NAPI_FUNCTION("getWithUniqueId", JSSnapshotGetWithUniqueId),
619         DECLARE_NAPI_FUNCTION("getSyncWithUniqueId", JSSnapshotGetSyncWithUniqueId),
620     };
621     NAPI_CALL(env, napi_define_properties(env, exports, sizeof(snapshotDesc) / sizeof(snapshotDesc[0]), snapshotDesc));
622 
623     return exports;
624 }
625 
626 static napi_module snapshotModule = {
627     .nm_version = 1,
628     .nm_flags = 0,
629     .nm_filename = nullptr,
630     .nm_register_func = ComponentSnapshotExport,
631     .nm_modname = "arkui.componentSnapshot",
632     .nm_priv = ((void*)0),
633     .reserved = { 0 },
634 };
635 
ComponentSnapshotRegister()636 extern "C" __attribute__((constructor)) void ComponentSnapshotRegister()
637 {
638     napi_module_register(&snapshotModule);
639 }
640 } // namespace OHOS::Ace::Napi
641