1 /*
2 * Copyright (c) 2025 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 "napi/napi_parser.h"
17
18 #include <optional>
19 #include <regex>
20
21 #include "core/common/container.h"
22 #include "core/common/resource/resource_manager.h"
23 #include "core/components/theme/resource_adapter.h"
24 #ifdef PREVIEW
25 #include "native_engine/native_engine.h"
26 #ifdef WINDOWS_PLATFORM
27 #undef TRANSPARENT
28 #undef ERROR
29 #undef ALTERNATE
30 #endif
31 #endif
32 #include "bridge/declarative_frontend/jsview/js_scroller.h"
33 #include "interfaces/inner_api/ace_kit/src/view/scroller_impl.h"
34
35 namespace OHOS::Ace::Kit {
36
37 namespace {
38 const std::regex RESOURCE_APP_STRING_PLACEHOLDER(R"(\%((\d+)(\$)){0,1}([dsf]))", std::regex::icase);
39 constexpr int32_t UNKNOWN_RESOURCE_ID = -1;
40 constexpr char BUNDLE_NAME[] = "bundleName";
41 std::vector<std::string> RESOURCE_HEADS = { "app", "sys" };
42 } // namespace
43
44 struct ResourceInfo {
45 int32_t resId = 0;
46 int32_t type = 0;
47 std::vector<std::string> params;
48 std::optional<std::string> bundleName = std::nullopt;
49 std::optional<std::string> moduleName = std::nullopt;
50 };
51
52 enum class ResourceType : uint32_t {
53 COLOR = 10001,
54 FLOAT,
55 STRING,
56 PLURAL,
57 BOOLEAN,
58 INTARRAY,
59 INTEGER,
60 PATTERN,
61 STRARRAY,
62 MEDIA = 20000,
63 RAWFILE = 30000
64 };
65
66 enum class ResourceStruct { CONSTANT, DYNAMIC_V1, DYNAMIC_V2 };
67
68 bool GetNapiString(napi_env env, napi_value value, std::string& retStr, napi_valuetype& valueType);
69
70 bool ParseResourceParam(napi_env env, napi_value value, ResourceInfo& info);
71
GetValueType(napi_env env,napi_value value)72 napi_valuetype GetValueType(napi_env env, napi_value value)
73 {
74 if (value == nullptr) {
75 return napi_undefined;
76 }
77
78 napi_valuetype valueType = napi_undefined;
79 NAPI_CALL_BASE(env, napi_typeof(env, value, &valueType), napi_undefined);
80 return valueType;
81 }
82
ReplaceHolder(std::string & originStr,const std::vector<std::string> & params,uint32_t containCount)83 void ReplaceHolder(std::string& originStr, const std::vector<std::string>& params, uint32_t containCount)
84 {
85 auto size = static_cast<uint32_t>(params.size());
86 if (containCount == size) {
87 return;
88 }
89 std::string::const_iterator start = originStr.begin();
90 std::string::const_iterator end = originStr.end();
91 std::smatch matches;
92 bool shortHolderType = false;
93 bool firstMatch = true;
94 uint32_t searchTime = 0;
95 while (std::regex_search(start, end, matches, RESOURCE_APP_STRING_PLACEHOLDER)) {
96 std::string pos = matches[2];
97 std::string type = matches[4];
98 if (firstMatch) {
99 firstMatch = false;
100 shortHolderType = pos.length() == 0;
101 } else {
102 if (static_cast<uint32_t>(shortHolderType) ^ static_cast<uint32_t>(pos.length() == 0)) {
103 LOGE("wrong place holder,stop parse string");
104 return;
105 }
106 }
107
108 std::string replaceContentStr;
109 std::string::size_type index = 0;
110 if (shortHolderType) {
111 index = static_cast<std::string::size_type>(searchTime + containCount);
112 } else {
113 int32_t indexTmp = StringUtils::StringToInt(pos) + static_cast<int32_t>(containCount) - 1;
114 if (indexTmp >= 0) {
115 index = static_cast<std::string::size_type>(indexTmp);
116 } else {
117 LOGE("indexTmp err:%{public}d", indexTmp);
118 }
119 }
120 if (static_cast<uint32_t>(index) < size) {
121 replaceContentStr = params[index];
122 } else {
123 LOGE("index = %{public}d size = %{public}d", static_cast<uint32_t>(index), size);
124 }
125 originStr.replace(matches[0].first - originStr.begin(), matches[0].length(), replaceContentStr);
126 start = originStr.begin() + matches.prefix().length() + replaceContentStr.length();
127 end = originStr.end();
128 searchTime++;
129 }
130 }
131
GetParamLen(napi_env env,napi_value param)132 size_t GetParamLen(napi_env env, napi_value param)
133 {
134 size_t buffSize = 0;
135 napi_status status = napi_get_value_string_utf8(env, param, nullptr, 0, &buffSize);
136 if (status != napi_ok || buffSize == 0) {
137 return 0;
138 }
139 return buffSize;
140 }
141
NapiStringToString(napi_env env,napi_value value,std::string & retStr)142 bool NapiStringToString(napi_env env, napi_value value, std::string& retStr)
143 {
144 size_t ret = 0;
145 napi_valuetype valueType = napi_undefined;
146 napi_typeof(env, value, &valueType);
147 if (valueType != napi_string) {
148 return false;
149 }
150 if (GetParamLen(env, value) == 0) {
151 return false;
152 }
153 size_t valueLen = GetParamLen(env, value) + 1;
154 std::unique_ptr<char[]> buffer = std::make_unique<char[]>(valueLen);
155 napi_get_value_string_utf8(env, value, buffer.get(), valueLen, &ret);
156 retStr = buffer.get();
157 return true;
158 }
159
CompleteColorAlphaIfIncomplete(uint32_t origin)160 static uint32_t CompleteColorAlphaIfIncomplete(uint32_t origin)
161 {
162 constexpr uint32_t colorAlphaOffset = 24;
163 constexpr uint32_t colorAlphaDefaultValue = 0xFF000000;
164 uint32_t result = origin;
165 if ((origin >> colorAlphaOffset) == 0) {
166 result = origin | colorAlphaDefaultValue;
167 }
168 return result;
169 }
170
CreateNapiString(napi_env env,const std::string & rawStr)171 napi_value CreateNapiString(napi_env env, const std::string& rawStr)
172 {
173 napi_value retVal = nullptr;
174 napi_create_string_utf8(env, rawStr.c_str(), rawStr.length(), &retVal);
175 return retVal;
176 }
177
CreateResourceWrapper(const ResourceInfo & info)178 RefPtr<ResourceAdapter> CreateResourceWrapper(const ResourceInfo& info)
179 {
180 auto bundleName = info.bundleName;
181 auto moduleName = info.moduleName;
182
183 RefPtr<ResourceAdapter> resourceAdapter = nullptr;
184 if (bundleName.has_value() && moduleName.has_value()) {
185 auto resourceObject = AceType::MakeRefPtr<ResourceObject>(
186 bundleName.value_or(""), moduleName.value_or(""), Container::CurrentIdSafely());
187 resourceAdapter = ResourceManager::GetInstance().GetOrCreateResourceAdapter(resourceObject);
188 } else {
189 resourceAdapter = ResourceManager::GetInstance().GetResourceAdapter(Container::CurrentIdSafely());
190 }
191 return resourceAdapter;
192 }
193
ParseIntegerToString(const ResourceInfo & info,std::string & result)194 bool ParseIntegerToString(const ResourceInfo& info, std::string& result)
195 {
196 auto resourceWrapper = CreateResourceWrapper(info);
197 if (resourceWrapper == nullptr) {
198 return false;
199 }
200 if (info.type == static_cast<int>(ResourceType::INTEGER)) {
201 if (info.resId == UNKNOWN_RESOURCE_ID) {
202 result = std::to_string(resourceWrapper->GetIntByName(info.params[0]));
203 } else {
204 result = std::to_string(resourceWrapper->GetInt(info.resId));
205 }
206 return true;
207 }
208 return true;
209 }
210
DimensionToString(Dimension dimension)211 std::string DimensionToString(Dimension dimension)
212 {
213 static const int32_t unitsNum = 6;
214 static const int32_t percentIndex = 3;
215 static const int32_t percentUnit = 100;
216 static std::array<std::string, unitsNum> units = { "px", "vp", "fp", "%", "lpx", "auto" };
217 auto unit = dimension.Unit();
218 auto value = dimension.Value();
219 if (unit == DimensionUnit::NONE) {
220 return StringUtils::DoubleToString(value).append("none");
221 }
222 if (units[static_cast<int>(unit)] == units[percentIndex]) {
223 return StringUtils::DoubleToString(value * percentUnit).append(units[static_cast<int>(unit)]);
224 }
225 return StringUtils::DoubleToString(value).append(units[static_cast<int>(unit)]);
226 }
227
ParseString(const ResourceInfo & info,std::string & result)228 bool ParseString(const ResourceInfo& info, std::string& result)
229 {
230 auto resourceWrapper = CreateResourceWrapper(info);
231 if (resourceWrapper == nullptr) {
232 return false;
233 }
234 if (info.type == static_cast<int>(ResourceType::PLURAL)) {
235 std::string pluralResults;
236 if (info.resId == UNKNOWN_RESOURCE_ID) {
237 auto count = StringUtils::StringToInt(info.params[1]);
238 pluralResults = resourceWrapper->GetPluralStringByName(info.params[0], count);
239 ReplaceHolder(pluralResults, info.params, 2); // plural holder in index 2
240 } else {
241 pluralResults = resourceWrapper->GetPluralString(info.resId, StringUtils::StringToInt(info.params[0]));
242 ReplaceHolder(pluralResults, info.params, 1);
243 }
244 result = pluralResults;
245 return true;
246 }
247 if (info.type == static_cast<int>(ResourceType::RAWFILE)) {
248 result = resourceWrapper->GetRawfile(info.params[0]);
249 return true;
250 }
251 if (info.type == static_cast<int>(ResourceType::FLOAT)) {
252 if (info.resId == UNKNOWN_RESOURCE_ID) {
253 result = DimensionToString(resourceWrapper->GetDimensionByName(info.params[0]));
254 } else {
255 result = DimensionToString(resourceWrapper->GetDimension(info.resId));
256 }
257 return true;
258 }
259 if (info.type == static_cast<int>(ResourceType::STRING)) {
260 std::string originStr;
261 if (info.resId == UNKNOWN_RESOURCE_ID) {
262 originStr = resourceWrapper->GetStringByName(info.params[0]);
263 ReplaceHolder(originStr, info.params, 1);
264 } else {
265 originStr = resourceWrapper->GetString(info.resId);
266 ReplaceHolder(originStr, info.params, 0);
267 }
268 result = originStr;
269 return true;
270 }
271 if (info.type == static_cast<int>(ResourceType::COLOR)) {
272 result = resourceWrapper->GetColor(info.resId).ColorToString();
273 return true;
274 }
275 if (info.type == static_cast<int>(ResourceType::INTEGER)) {
276 result = std::to_string(resourceWrapper->GetInt(info.resId));
277 return true;
278 }
279 return true;
280 }
281
ConvertResourceType(const std::string & typeName,ResourceType & resType)282 bool ConvertResourceType(const std::string& typeName, ResourceType& resType)
283 {
284 static const std::unordered_map<std::string, ResourceType> resTypeMap {
285 { "color", ResourceType::COLOR },
286 { "media", ResourceType::MEDIA },
287 { "float", ResourceType::FLOAT },
288 { "string", ResourceType::STRING },
289 { "plural", ResourceType::PLURAL },
290 { "pattern", ResourceType::PATTERN },
291 { "boolean", ResourceType::BOOLEAN },
292 { "integer", ResourceType::INTEGER },
293 { "strarray", ResourceType::STRARRAY },
294 { "intarray", ResourceType::INTARRAY },
295 };
296 auto it = resTypeMap.find(typeName);
297 if (it == resTypeMap.end()) {
298 return false;
299 }
300 resType = it->second;
301 return true;
302 }
303
ParseDollarResource(napi_env env,napi_value value,ResourceType & resType,std::string & resName,std::string & moduleName)304 bool ParseDollarResource(
305 napi_env env, napi_value value, ResourceType& resType, std::string& resName, std::string& moduleName)
306 {
307 napi_valuetype valueType = napi_undefined;
308 napi_typeof(env, value, &valueType);
309 if (valueType != napi_string) {
310 return false;
311 }
312 std::string resPath;
313 if (!GetNapiString(env, value, resPath, valueType)) {
314 return false;
315 }
316 std::vector<std::string> tokens;
317 StringUtils::StringSplitter(resPath, '.', tokens);
318 // $r format like app.xxx.xxx, has 3 paragraph
319 if (static_cast<int32_t>(tokens.size()) != 3) {
320 return false;
321 }
322 std::string maybeModuleName = tokens[0];
323 // [*] or app/hsp at least has 3 chars
324 if (maybeModuleName.size() < 3) {
325 return false;
326 }
327 char begin = *maybeModuleName.begin();
328 char end = maybeModuleName.at(maybeModuleName.size() - 1);
329 bool headCheckPass = false;
330 if (begin == '[' && end == ']') {
331 // moduleName not include 2 brackets
332 moduleName = maybeModuleName.substr(1, maybeModuleName.size() - 2);
333 headCheckPass = true;
334 }
335 if (std::find(RESOURCE_HEADS.begin(), RESOURCE_HEADS.end(), tokens[0]) == RESOURCE_HEADS.end() && !headCheckPass) {
336 return false;
337 }
338 if (!ConvertResourceType(tokens[1], resType)) {
339 return false;
340 }
341 resName = resPath;
342 return true;
343 }
344
PreFixEmptyBundleName(napi_env env,napi_value value)345 void PreFixEmptyBundleName(napi_env env, napi_value value)
346 {
347 napi_value bundleNameNApi = nullptr;
348 if (napi_get_named_property(env, value, BUNDLE_NAME, &bundleNameNApi) != napi_ok) {
349 return;
350 }
351 std::string bundleName;
352 NapiStringToString(env, bundleNameNApi, bundleName);
353 if (bundleName.empty()) {
354 auto container = Container::CurrentSafely();
355 CHECK_NULL_VOID(container);
356 bundleName = container->GetBundleName();
357 bundleNameNApi = CreateNapiString(env, bundleName);
358 napi_set_named_property(env, value, BUNDLE_NAME, bundleNameNApi);
359 }
360 }
361
CheckResourceStruct(napi_env env,napi_value value)362 ResourceStruct CheckResourceStruct(napi_env env, napi_value value)
363 {
364 napi_value idNApi = nullptr;
365 napi_valuetype valueType = napi_undefined;
366 napi_typeof(env, value, &valueType);
367 if (valueType != napi_object) {
368 return ResourceStruct::CONSTANT;
369 }
370 if (napi_get_named_property(env, value, "id", &idNApi) != napi_ok) {
371 return ResourceStruct::CONSTANT;
372 }
373 napi_typeof(env, idNApi, &valueType);
374 if (valueType == napi_string) {
375 return ResourceStruct::DYNAMIC_V1;
376 }
377 if (valueType == napi_number) {
378 int32_t id = 0;
379 napi_get_value_int32(env, idNApi, &id);
380 if (id == UNKNOWN_RESOURCE_ID) {
381 return ResourceStruct::DYNAMIC_V2;
382 }
383 }
384 return ResourceStruct::CONSTANT;
385 }
386
GetStringFromValueUtf8(napi_env env,napi_value value)387 std::optional<std::string> GetStringFromValueUtf8(napi_env env, napi_value value)
388 {
389 if (GetValueType(env, value) != napi_string) {
390 return std::nullopt;
391 }
392
393 size_t paramLen = 0;
394 napi_status status = napi_get_value_string_utf8(env, value, nullptr, 0, ¶mLen);
395 if (paramLen == 0 || status != napi_ok) {
396 return std::nullopt;
397 }
398 std::unique_ptr<char[]> params = std::make_unique<char[]>(paramLen + 1);
399 status = napi_get_value_string_utf8(env, value, params.get(), paramLen + 1, ¶mLen);
400 if (status != napi_ok) {
401 return std::nullopt;
402 }
403 return std::optional<std::string>(params.get());
404 }
405
GetNapiString(napi_env env,napi_value value,std::string & retStr,napi_valuetype & valueType)406 bool GetNapiString(napi_env env, napi_value value, std::string& retStr, napi_valuetype& valueType)
407 {
408 if (NapiStringToString(env, value, retStr)) {
409 return true;
410 }
411 napi_typeof(env, value, &valueType);
412 if (valueType == napi_object) {
413 ResourceInfo recv;
414 if (ParseResourceParam(env, value, recv)) {
415 ParseString(recv, retStr);
416 return true;
417 }
418 }
419 return false;
420 }
421
ModifyResourceParam(napi_env env,napi_value value,const ResourceType & resType,const std::string & resName)422 void ModifyResourceParam(napi_env env, napi_value value, const ResourceType& resType, const std::string& resName)
423 {
424 // raw input : {"id":"app.xxx.xxx","params":[],"moduleName":"xxx","bundleName":"xxx"}
425 // modified output : {"id":-1, "params":["app.xxx.xxx"],"type":xxxx,"moduleName":"xxx","bundleName":"xxx"}
426 napi_value paramsNApi = nullptr;
427 napi_get_named_property(env, value, "params", ¶msNApi);
428 bool isArray = false;
429 if (napi_is_array(env, paramsNApi, &isArray) != napi_ok) {
430 return;
431 }
432 if (!isArray) {
433 return;
434 }
435 uint32_t paramCount = 0;
436 bool hasProperty = false;
437 napi_get_array_length(env, paramsNApi, ¶mCount);
438 napi_value typeKeyNApi = CreateNapiString(env, "type");
439 napi_value resNameNApi = CreateNapiString(env, resName);
440 if (resType == ResourceType::PLURAL || resType == ResourceType::STRING) {
441 std::vector<napi_value> tmpParams;
442 for (uint32_t i = 0; i < paramCount; i++) {
443 napi_value param = nullptr;
444 napi_get_element(env, paramsNApi, i, ¶m);
445 tmpParams.insert(tmpParams.end(), param);
446 }
447 napi_set_element(env, paramsNApi, 0, resNameNApi);
448 uint32_t paramIndex = 1;
449 napi_has_property(env, value, typeKeyNApi, &hasProperty);
450 if (hasProperty) {
451 napi_value firstParam = nullptr;
452 napi_get_property(env, value, typeKeyNApi, &firstParam);
453 napi_set_element(env, paramsNApi, paramIndex, firstParam);
454 paramIndex++;
455 }
456 for (auto tmpParam : tmpParams) {
457 napi_set_element(env, paramsNApi, paramIndex, tmpParam);
458 paramIndex++;
459 }
460 } else {
461 napi_set_element(env, paramsNApi, 0, resNameNApi);
462 }
463 }
464
CompleteResourceParamV1(napi_env env,napi_value value)465 void CompleteResourceParamV1(napi_env env, napi_value value)
466 {
467 napi_value idNApi = nullptr;
468 napi_valuetype valueType = napi_undefined;
469 napi_typeof(env, value, &valueType);
470 if (valueType != napi_object) {
471 return;
472 }
473 if (napi_get_named_property(env, value, "id", &idNApi) != napi_ok) {
474 return;
475 }
476 std::string resName;
477 std::string moduleName;
478 ResourceType resType;
479 if (!ParseDollarResource(env, idNApi, resType, resName, moduleName)) {
480 return;
481 }
482 bool hasProperty = false;
483 napi_value typeIdNApi = nullptr;
484 napi_value resourceIdNApi = nullptr;
485 napi_value typeKeyNApi = CreateNapiString(env, "type");
486 napi_value defaultNameNApi = CreateNapiString(env, "");
487 napi_value bundleNameKeyNApi = CreateNapiString(env, "bundleName");
488 napi_value moduleNameKeyNApi = CreateNapiString(env, "moduleName");
489 napi_create_int32(env, UNKNOWN_RESOURCE_ID, &resourceIdNApi);
490 napi_create_int32(env, static_cast<uint32_t>(resType), &typeIdNApi);
491 ModifyResourceParam(env, value, resType, resName);
492 napi_set_property(env, value, typeKeyNApi, typeIdNApi);
493 napi_set_property(env, value, CreateNapiString(env, "id"), resourceIdNApi);
494 napi_has_property(env, value, bundleNameKeyNApi, &hasProperty);
495 if (!hasProperty) {
496 napi_set_property(env, value, bundleNameKeyNApi, defaultNameNApi);
497 }
498 napi_has_property(env, value, moduleNameKeyNApi, &hasProperty);
499 if (!hasProperty) {
500 napi_set_property(env, value, moduleNameKeyNApi, defaultNameNApi);
501 }
502 }
503
CompleteResourceParamV2(napi_env env,napi_value value)504 void CompleteResourceParamV2(napi_env env, napi_value value)
505 {
506 napi_value paramsNApi = nullptr;
507 if (napi_get_named_property(env, value, "params", ¶msNApi) != napi_ok) {
508 return;
509 }
510 bool isArray = false;
511 napi_is_array(env, paramsNApi, &isArray);
512 if (!isArray) {
513 return;
514 }
515 uint32_t paramCount = 0;
516 napi_get_array_length(env, paramsNApi, ¶mCount);
517 if (paramCount <= 0) {
518 return;
519 }
520 napi_value resNameNApi = nullptr;
521 napi_get_element(env, paramsNApi, 0, &resNameNApi);
522 std::string resName;
523 std::string moduleName;
524 ResourceType resType;
525 if (!ParseDollarResource(env, resNameNApi, resType, resName, moduleName)) {
526 return;
527 }
528 napi_value typeIdNApi = nullptr;
529 napi_value typeKeyNApi = CreateNapiString(env, "type");
530 napi_create_int32(env, static_cast<uint32_t>(resType), &typeIdNApi);
531 napi_set_property(env, value, typeKeyNApi, typeIdNApi);
532 if (!moduleName.empty()) {
533 napi_value moduleNameNApi = CreateNapiString(env, moduleName);
534 napi_value moduleNameKeyNApi = CreateNapiString(env, "moduleName");
535 napi_set_property(env, value, moduleNameKeyNApi, moduleNameNApi);
536 }
537 }
538
CompleteResourceParam(napi_env env,napi_value value)539 void CompleteResourceParam(napi_env env, napi_value value)
540 {
541 PreFixEmptyBundleName(env, value);
542 ResourceStruct resourceStruct = CheckResourceStruct(env, value);
543 switch (resourceStruct) {
544 case ResourceStruct::CONSTANT:
545 return;
546 case ResourceStruct::DYNAMIC_V1:
547 CompleteResourceParamV1(env, value);
548 return;
549 case ResourceStruct::DYNAMIC_V2:
550 CompleteResourceParamV2(env, value);
551 return;
552 default:
553 return;
554 }
555 }
556
ParseResourceParam(napi_env env,napi_value value,ResourceInfo & info)557 bool ParseResourceParam(napi_env env, napi_value value, ResourceInfo& info)
558 {
559 CompleteResourceParam(env, value);
560 napi_value idNApi = nullptr;
561 napi_value typeNApi = nullptr;
562 napi_value paramsNApi = nullptr;
563 napi_value bundleNameNApi = nullptr;
564 napi_value moduleNameNApi = nullptr;
565 napi_valuetype valueType = napi_undefined;
566 napi_typeof(env, value, &valueType);
567 if (valueType == napi_object) {
568 napi_get_named_property(env, value, "id", &idNApi);
569 napi_get_named_property(env, value, "type", &typeNApi);
570 napi_get_named_property(env, value, "params", ¶msNApi);
571 napi_get_named_property(env, value, "bundleName", &bundleNameNApi);
572 napi_get_named_property(env, value, "moduleName", &moduleNameNApi);
573 } else {
574 return false;
575 }
576
577 napi_typeof(env, idNApi, &valueType);
578 if (valueType == napi_number) {
579 napi_get_value_int32(env, idNApi, &info.resId);
580 }
581
582 napi_typeof(env, typeNApi, &valueType);
583 if (valueType == napi_number) {
584 napi_get_value_int32(env, typeNApi, &info.type);
585 }
586
587 bool isArray = false;
588 if (napi_is_array(env, paramsNApi, &isArray) != napi_ok) {
589 return false;
590 }
591
592 if (!isArray) {
593 return false;
594 }
595
596 uint32_t arrayLength = 0;
597 napi_get_array_length(env, paramsNApi, &arrayLength);
598
599 for (uint32_t i = 0; i < arrayLength; i++) {
600 size_t ret = 0;
601 napi_value indexValue = nullptr;
602 napi_get_element(env, paramsNApi, i, &indexValue);
603 napi_typeof(env, indexValue, &valueType);
604 if (valueType == napi_string) {
605 size_t strLen = GetParamLen(env, indexValue) + 1;
606 std::unique_ptr<char[]> indexStr = std::make_unique<char[]>(strLen);
607 napi_get_value_string_utf8(env, indexValue, indexStr.get(), strLen, &ret);
608 info.params.emplace_back(indexStr.get());
609 } else if (valueType == napi_number) {
610 int32_t num;
611 napi_get_value_int32(env, indexValue, &num);
612 info.params.emplace_back(std::to_string(num));
613 }
614 }
615
616 napi_typeof(env, bundleNameNApi, &valueType);
617 if (valueType == napi_string) {
618 size_t ret = 0;
619 size_t strLen = GetParamLen(env, bundleNameNApi) + 1;
620 std::unique_ptr<char[]> bundleNameStr = std::make_unique<char[]>(strLen);
621 napi_get_value_string_utf8(env, bundleNameNApi, bundleNameStr.get(), strLen, &ret);
622 info.bundleName = bundleNameStr.get();
623 }
624
625 napi_typeof(env, moduleNameNApi, &valueType);
626 if (valueType == napi_string) {
627 size_t ret = 0;
628 size_t strLen = GetParamLen(env, moduleNameNApi) + 1;
629 std::unique_ptr<char[]> moduleNameStr = std::make_unique<char[]>(strLen);
630 napi_get_value_string_utf8(env, moduleNameNApi, moduleNameStr.get(), strLen, &ret);
631 info.moduleName = moduleNameStr.get();
632 }
633
634 return true;
635 }
636
ParseColorFromResourceObject(napi_env env,napi_value value,Color & colorResult)637 bool ParseColorFromResourceObject(napi_env env, napi_value value, Color& colorResult)
638 {
639 ResourceInfo resourceInfo;
640 if (!ParseResourceParam(env, value, resourceInfo)) {
641 return false;
642 }
643 auto resourceWrapper = CreateResourceWrapper(resourceInfo);
644 if (resourceWrapper == nullptr) {
645 return false;
646 }
647 if (resourceInfo.type == static_cast<int32_t>(ResourceType::STRING)) {
648 auto colorString = resourceWrapper->GetString(resourceInfo.type);
649 return Color::ParseColorString(colorString, colorResult);
650 }
651 if (resourceInfo.type == static_cast<int32_t>(ResourceType::INTEGER)) {
652 auto colorInt = resourceWrapper->GetInt(resourceInfo.type);
653 colorResult = Color(CompleteColorAlphaIfIncomplete(colorInt));
654 return true;
655 }
656 colorResult = resourceWrapper->GetColor(resourceInfo.resId);
657 return true;
658 }
659
ParseColor(napi_env env,napi_value value,Color & result)660 bool ParseColor(napi_env env, napi_value value, Color& result)
661 {
662 napi_valuetype valueType = GetValueType(env, value);
663 if (valueType != napi_number && valueType != napi_string && valueType != napi_object) {
664 return false;
665 }
666 if (valueType == napi_number) {
667 int32_t colorId = 0;
668 napi_get_value_int32(env, value, &colorId);
669 result = Color(CompleteColorAlphaIfIncomplete(static_cast<uint32_t>(colorId)));
670 return true;
671 }
672 if (valueType == napi_string) {
673 std::optional<std::string> colorString = GetStringFromValueUtf8(env, value);
674 if (!colorString.has_value()) {
675 return false;
676 }
677 return Color::ParseColorString(colorString.value(), result);
678 }
679
680 return ParseColorFromResourceObject(env, value, result);
681 }
682
ParseDimension(napi_env env,CalcDimension & result,napi_value napiValue,DimensionUnit defaultUnit,bool isSupportPercent)683 bool ACE_FORCE_EXPORT ParseDimension(
684 napi_env env, CalcDimension& result, napi_value napiValue, DimensionUnit defaultUnit, bool isSupportPercent)
685 {
686 napi_valuetype valueType = napi_undefined;
687 napi_typeof(env, napiValue, &valueType);
688 if (valueType == napi_number) {
689 double value = 0;
690 napi_get_value_double(env, napiValue, &value);
691
692 result.SetUnit(defaultUnit);
693 result.SetValue(value);
694 return true;
695 } else if (valueType == napi_string) {
696 std::string valueString;
697 if (!GetNapiString(env, napiValue, valueString, valueType)) {
698 return false;
699 }
700 if (valueString.back() == '%' && !isSupportPercent) {
701 return false;
702 }
703 return StringUtils::StringToCalcDimensionNG(valueString, result, false, defaultUnit);
704 } else if (valueType == napi_object) {
705 ResourceInfo recv;
706 std::string parameterStr;
707 if (!ParseResourceParam(env, napiValue, recv)) {
708 return false;
709 }
710 if (!ParseString(recv, parameterStr)) {
711 return false;
712 }
713 if (!ParseIntegerToString(recv, parameterStr)) {
714 return false;
715 }
716 result = StringUtils::StringToDimensionWithUnit(parameterStr, defaultUnit);
717 return true;
718 }
719 return false;
720 }
721
ParseScroller(napi_env env,napi_value value)722 RefPtr<Scroller> ACE_FORCE_EXPORT ParseScroller(napi_env env, napi_value value)
723 {
724 napi_valuetype valueType = napi_undefined;
725 napi_typeof(env, value, &valueType);
726 if (valueType != napi_object) {
727 return nullptr;
728 }
729 auto vm = reinterpret_cast<NativeEngine*>(env)->GetEcmaVm();
730 panda::Local<panda::ObjectRef> scrollerObject((uintptr_t)value);
731 if (scrollerObject->GetNativePointerFieldCount(vm) == 0) {
732 return nullptr;
733 }
734 Framework::JSScroller* scroller = (Framework::JSScroller*)scrollerObject->GetNativePointerField(vm, 0);
735 return AceType::MakeRefPtr<ScrollerImpl>(AceType::Claim(scroller));
736 }
737
738 } // namespace OHOS::Ace::Kit
739