• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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, &paramLen);
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, &paramLen);
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", &paramsNApi);
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, &paramCount);
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, &param);
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", &paramsNApi) != 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, &paramCount);
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", &paramsNApi);
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