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", ®ionObject);
289 if (!regionObject) {
290 options.regionMode = NG::SnapshotRegionMode::NO_REGION;
291 return;
292 }
293
294 options.regionMode = NG::SnapshotRegionMode::COMMON;
295 if (ParseLocalizedRegion(®ionObject, options)) {
296 options.regionMode = NG::SnapshotRegionMode::LOCALIZED;
297 } else {
298 ParseRegion(®ionObject, 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