• 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 "frameworks/bridge/declarative_frontend/engine/jsi/nativeModule/arkts_utils.h"
17 
18 #include "ecmascript/napi/include/jsnapi.h"
19 #include "jsnapi_expo.h"
20 
21 #include "base/utils/utils.h"
22 #include "bridge/declarative_frontend/engine/js_converter.h"
23 #include "frameworks/base/image/pixel_map.h"
24 #include "frameworks/base/utils/system_properties.h"
25 #include "frameworks/bridge/common/utils/engine_helper.h"
26 #include "frameworks/bridge/declarative_frontend/engine/jsi/js_ui_index.h"
27 #include "frameworks/bridge/declarative_frontend/jsview/js_utils.h"
28 #include "frameworks/core/common/card_scope.h"
29 #include "frameworks/core/common/resource/resource_configuration.h"
30 
31 namespace OHOS::Ace::NG {
32 namespace {
GetBundleNameFromContainer()33 std::string GetBundleNameFromContainer()
34 {
35     auto container = Container::Current();
36     CHECK_NULL_RETURN(container, "");
37     return container->GetBundleName();
38 }
39 
GetModuleNameFromContainer()40 std::string GetModuleNameFromContainer()
41 {
42     auto container = Container::Current();
43     CHECK_NULL_RETURN(container, "");
44     return container->GetModuleName();
45 }
46 }
47 constexpr int NUM_0 = 0;
48 constexpr int NUM_1 = 1;
49 constexpr int NUM_2 = 2;
50 constexpr int NUM_3 = 3;
51 constexpr int NUM_4 = 4;
52 constexpr int PARAM_ARR_LENGTH_1 = 1;
53 constexpr int PARAM_ARR_LENGTH_2 = 2;
54 const std::regex RESOURCE_APP_STRING_PLACEHOLDER(R"(\%((\d+)(\$)){0,1}([dsf]))", std::regex::icase);
55 const std::regex FLOAT_PATTERN(R"(-?(0|[1-9]\d*)(\.\d+))", std::regex::icase);
56 const std::string RESOURCE_TOKEN_PATTERN = "(app|sys|\\[.+?\\])\\.(\\S+?)\\.(\\S+)";
57 const std::string RESOURCE_NAME_PATTERN = "\\[(.+?)\\]";
58 constexpr uint32_t COLOR_ALPHA_OFFSET = 24;
59 constexpr uint32_t COLOR_ALPHA_VALUE = 0xFF000000;
60 constexpr uint32_t RES_TYPE_INDEX = 2;
61 constexpr int32_t UNKNOWN_RESOURCE_ID = -1;
62 constexpr int32_t UNKNOWN_RESOURCE_TYPE = -1;
63 const std::string DEFAULT_STR = "-1";
64 constexpr  int32_t REPLACEHOLDER_INDEX = 2;
65 const Color DEFAULT_TEXT_SHADOW_COLOR = Color::BLACK;
66 constexpr bool DEFAULT_TEXT_SHADOW_FILL = false;
67 constexpr ShadowType DEFAULT_TEXT_SHADOW_TYPE = ShadowType::COLOR;
68 constexpr char JS_TEXT_MENU_ID_CLASS_NAME[] = "TextMenuItemId";
69 const std::string CUSTOM_SYMBOL_SUFFIX = "_CustomSymbol";
70 
ColorAlphaAdapt(uint32_t origin)71 uint32_t ArkTSUtils::ColorAlphaAdapt(uint32_t origin)
72 {
73     uint32_t result = origin;
74     if ((origin >> COLOR_ALPHA_OFFSET) == 0) {
75         result = origin | COLOR_ALPHA_VALUE;
76     }
77     return result;
78 }
79 
ParseJsColor(const EcmaVM * vm,const Local<JSValueRef> & value,Color & result)80 bool ArkTSUtils::ParseJsColor(const EcmaVM* vm, const Local<JSValueRef>& value, Color& result)
81 {
82     if (value->IsNumber()) {
83         result = Color(value->Uint32Value(vm));
84         return true;
85     }
86     if (value->IsString(vm)) {
87         return Color::ParseColorString(value->ToString(vm)->ToString(vm), result);
88     }
89     if (value->IsObject(vm)) {
90         auto obj = value->ToObject(vm);
91         auto resId = obj->Get(vm, panda::StringRef::NewFromUtf8(vm, "id"));
92         if (!resId->IsNumber()) {
93             return false;
94         }
95         return ParseJsColorFromResource(vm, value, result);
96     }
97     return false;
98 }
99 
ParseJsSymbolColorAlpha(const EcmaVM * vm,const Local<JSValueRef> & value,Color & result)100 bool ArkTSUtils::ParseJsSymbolColorAlpha(const EcmaVM* vm, const Local<JSValueRef>& value, Color& result)
101 {
102     if (!value->IsNumber() && !value->IsString(vm) && !value->IsObject(vm)) {
103         return false;
104     }
105     if (value->IsNumber()) {
106         result = Color(ColorAlphaAdapt(value->Uint32Value(vm)));
107     } else if (value->IsString(vm)) {
108         Color::ParseColorString(value->ToString(vm)->ToString(vm), result);
109     } else if (value->IsObject(vm)) {
110         ParseJsColorFromResource(vm, value, result);
111     }
112     return true;
113 }
114 
ParseJsColorAlpha(const EcmaVM * vm,const Local<JSValueRef> & value,Color & result)115 bool ArkTSUtils::ParseJsColorAlpha(const EcmaVM* vm, const Local<JSValueRef>& value, Color& result)
116 {
117     if (value->IsNumber()) {
118         result = Color(ColorAlphaAdapt(value->Uint32Value(vm)));
119         return true;
120     }
121     if (value->IsString(vm)) {
122         return Color::ParseColorString(value->ToString(vm)->ToString(vm), result);
123     }
124     if (value->IsObject(vm)) {
125         return ParseJsColorFromResource(vm, value, result);
126     }
127     return false;
128 }
129 
ParseJsColorContent(const EcmaVM * vm,const Local<JSValueRef> & value)130 bool ArkTSUtils::ParseJsColorContent(const EcmaVM* vm, const Local<JSValueRef>& value)
131 {
132     if (!value->IsObject(vm)) {
133         return false;
134     }
135     auto obj = value->ToObject(vm);
136     auto colorContentValue = obj->Get(vm, panda::StringRef::NewFromUtf8(vm, "colorContent_"));
137     return !colorContentValue.IsEmpty() && colorContentValue->IsString(vm) &&
138            colorContentValue->ToString(vm)->ToString(vm) == "ORIGIN";
139 }
140 
ParseJsColorAlpha(const EcmaVM * vm,const Local<JSValueRef> & value,Color & result,const Color & defaultColor)141 bool ArkTSUtils::ParseJsColorAlpha(
142     const EcmaVM* vm, const Local<JSValueRef>& value, Color& result, const Color& defaultColor)
143 {
144     if (!value->IsNumber() && !value->IsString(vm) && !value->IsObject(vm)) {
145         return false;
146     }
147     if (value->IsNumber()) {
148         result = Color(ColorAlphaAdapt(value->Uint32Value(vm)));
149         return true;
150     }
151     if (value->IsString(vm)) {
152         return Color::ParseColorString(value->ToString(vm)->ToString(vm), result, defaultColor);
153     }
154     return ParseJsColorFromResource(vm, value, result);
155 }
156 
ToString(const EcmaVM * vm,Local<JSValueRef> & jsVal)157 std::string ToString(const EcmaVM* vm,  Local<JSValueRef>& jsVal)
158 {
159     panda::LocalScope scope(vm);
160     if (jsVal->IsObject(vm)) {
161         return panda::JSON::Stringify(vm, jsVal)->ToString(vm)->ToString(vm);
162     }
163     return jsVal->ToString(vm)->ToString(vm);
164 }
165 
GetResourceObject(const EcmaVM * vm,const Local<JSValueRef> & jsObj)166 RefPtr<ResourceObject> GetResourceObject(const EcmaVM* vm, const Local<JSValueRef>& jsObj)
167 {
168     auto obj = jsObj->ToObject(vm);
169     auto id = obj->Get(vm, panda::ExternalStringCache::GetCachedString(vm,
170         static_cast<int32_t>(Framework::ArkUIIndex::ID)))->Int32Value(vm);
171     auto type = obj->Get(vm, panda::ExternalStringCache::GetCachedString(vm,
172         static_cast<int32_t>(Framework::ArkUIIndex::TYPE)))->Int32Value(vm);
173     auto args = obj->Get(vm, panda::ExternalStringCache::GetCachedString(vm,
174         static_cast<int32_t>(Framework::ArkUIIndex::PARAMS)));
175 
176     std::string bundleName;
177     std::string moduleName;
178     auto bundle = obj->Get(vm, panda::ExternalStringCache::GetCachedString(vm,
179         static_cast<int32_t>(Framework::ArkUIIndex::BUNDLE_NAME)));
180     auto module = obj->Get(vm, panda::ExternalStringCache::GetCachedString(vm,
181         static_cast<int32_t>(Framework::ArkUIIndex::MODULE_NAME)));
182     if (bundle->IsString(vm) && module->IsString(vm)) {
183         bundleName = bundle->ToString(vm)->ToString(vm);
184         moduleName = module->ToString(vm)->ToString(vm);
185     }
186 
187     Local<panda::ArrayRef> params = static_cast<Local<panda::ArrayRef>>(args);
188     std::vector<ResourceObjectParams> resObjParamsList;
189     auto size = static_cast<int32_t>(params->Length(vm));
190     for (int32_t i = 0; i < size; i++) {
191         auto item = panda::ArrayRef::GetValueAt(vm, params, i);
192 
193         std::string valueString = ToString(vm, item).c_str();
194 
195         ResourceObjectParams resObjParams { .value = valueString };
196         if (item->IsString(vm)) {
197             resObjParams.type = ResourceObjectParamType::STRING;
198         } else if (item->IsNumber()) {
199             if (std::regex_match(item->ToString(vm)->ToString(vm), FLOAT_PATTERN)) {
200                 resObjParams.type = OHOS::Ace::ResourceObjectParamType::FLOAT;
201             } else {
202                 resObjParams.type = OHOS::Ace::ResourceObjectParamType::INT;
203             }
204         }
205         resObjParamsList.emplace_back(resObjParams);
206     }
207     auto resourceObject = AceType::MakeRefPtr<ResourceObject>(
208         id, type, resObjParamsList, bundleName, moduleName, Container::CurrentIdSafely());
209     return resourceObject;
210 }
211 
GetThemeConstants(const EcmaVM * vm,const Local<JSValueRef> & jsObj)212 RefPtr<OHOS::Ace::ThemeConstants> GetThemeConstants(const EcmaVM* vm, const Local<JSValueRef>& jsObj)
213 {
214     std::string bundleName;
215     std::string moduleName;
216     if (!jsObj->IsUndefined()) {
217         auto obj = jsObj->ToObject(vm);
218         auto bundle = obj->Get(vm, panda::StringRef::NewFromUtf8(vm, "bundleName"));
219         auto module = obj->Get(vm, panda::StringRef::NewFromUtf8(vm, "moduleName"));
220         if (bundle->IsString(vm) && module->IsString(vm)) {
221             bundleName = bundle->ToString(vm)->ToString(vm);
222             moduleName = module->ToString(vm)->ToString(vm);
223         }
224     }
225 
226     auto cardId = CardScope::CurrentId();
227     if (cardId != OHOS::Ace::INVALID_CARD_ID) {
228         auto container = Container::Current();
229         auto weak = container->GetCardPipeline(cardId);
230         auto cardPipelineContext = weak.Upgrade();
231         CHECK_NULL_RETURN(cardPipelineContext, nullptr);
232         auto cardThemeManager = cardPipelineContext->GetThemeManager();
233         CHECK_NULL_RETURN(cardThemeManager, nullptr);
234         return cardThemeManager->GetThemeConstants(bundleName, moduleName);
235     }
236 
237     auto container = Container::Current();
238     CHECK_NULL_RETURN(container, nullptr);
239     auto pipelineContext = container->GetPipelineContext();
240     CHECK_NULL_RETURN(pipelineContext, nullptr);
241     auto themeManager = pipelineContext->GetThemeManager();
242     CHECK_NULL_RETURN(themeManager, nullptr);
243     return themeManager->GetThemeConstants(bundleName, moduleName);
244 }
245 
CreateResourceWrapper(const EcmaVM * vm,const Local<JSValueRef> & jsObj,RefPtr<ResourceObject> & resourceObject)246 RefPtr<ResourceWrapper> CreateResourceWrapper(const EcmaVM* vm, const Local<JSValueRef>& jsObj,
247     RefPtr<ResourceObject>& resourceObject)
248 {
249     RefPtr<ResourceAdapter> resourceAdapter = nullptr;
250     RefPtr<ThemeConstants> themeConstants = nullptr;
251     if (SystemProperties::GetResourceDecoupling()) {
252         resourceAdapter = ResourceManager::GetInstance().GetOrCreateResourceAdapter(resourceObject);
253         if (!resourceAdapter) {
254             return nullptr;
255         }
256     } else {
257         themeConstants = GetThemeConstants(vm, jsObj);
258         if (!themeConstants) {
259             return nullptr;
260         }
261     }
262     auto resourceWrapper = AceType::MakeRefPtr<ResourceWrapper>(themeConstants, resourceAdapter);
263     return resourceWrapper;
264 }
265 
IsGetResourceByName(const EcmaVM * vm,const Local<JSValueRef> & jsObj)266 bool IsGetResourceByName(const EcmaVM* vm, const Local<JSValueRef>& jsObj)
267 {
268     auto obj = jsObj->ToObject(vm);
269     auto args = obj->Get(vm, panda::StringRef::NewFromUtf8(vm, "params"));
270     if (!args->IsArray(vm)) {
271         return false;
272     }
273     auto bundleName = obj->Get(vm, panda::StringRef::NewFromUtf8(vm, "bundleName"));
274     auto moduleName = obj->Get(vm, panda::StringRef::NewFromUtf8(vm, "moduleName"));
275     if (!bundleName->IsString(vm) || !moduleName->IsString(vm)) {
276         return false;
277     }
278     Local<panda::ArrayRef> params = static_cast<Local<panda::ArrayRef>>(args);
279     if (params->Length(vm) == 0) {
280         return false;
281     }
282     return true;
283 }
284 
ConvertResourceType(const std::string & typeName,ResourceType & resType)285 bool ConvertResourceType(const std::string& typeName, ResourceType& resType)
286 {
287     static const std::unordered_map<std::string, ResourceType> resTypeMap {
288         { "color", ResourceType::COLOR },
289         { "media", ResourceType::MEDIA },
290         { "float", ResourceType::FLOAT },
291         { "string", ResourceType::STRING },
292         { "plural", ResourceType::PLURAL },
293         { "pattern", ResourceType::PATTERN },
294         { "boolean", ResourceType::BOOLEAN },
295         { "integer", ResourceType::INTEGER },
296         { "strarray", ResourceType::STRARRAY },
297         { "intarray", ResourceType::INTARRAY },
298     };
299     auto it = resTypeMap.find(typeName);
300     if (it == resTypeMap.end()) {
301         return false;
302     }
303     resType = it->second;
304     return true;
305 }
306 
ParseDollarResource(std::string & targetModule,ResourceType & resType,std::string & resName,bool isParseType)307 bool ParseDollarResource(std::string& targetModule, ResourceType& resType,
308     std::string& resName, bool isParseType)
309 {
310     std::smatch results;
311     std::regex tokenRegex(RESOURCE_TOKEN_PATTERN);
312     if (!std::regex_match(resName, results, tokenRegex)) {
313         return false;
314     }
315     targetModule = results[1];
316     if (isParseType && !ConvertResourceType(results[RES_TYPE_INDEX], resType)) {
317         return false;
318     }
319     return true;
320 }
321 
CompleteResourceObjectFromParams(const EcmaVM * vm,Local<panda::ObjectRef> & jsObj,std::string & targetModule,ResourceType & resType,std::string & resName)322 void CompleteResourceObjectFromParams(const EcmaVM* vm, Local<panda::ObjectRef>& jsObj,
323     std::string& targetModule, ResourceType& resType, std::string& resName)
324 {
325     auto type = jsObj->Get(vm,
326         panda::ExternalStringCache::GetCachedString(vm, static_cast<int32_t>(Framework::ArkUIIndex::TYPE)));
327     int32_t typeNum = -1;
328     if (type->IsNumber()) {
329         typeNum = type->Int32Value(vm);
330     }
331     auto resId = jsObj->Get(vm,
332         panda::ExternalStringCache::GetCachedString(vm, static_cast<int32_t>(Framework::ArkUIIndex::ID)));
333     int32_t resIdValue = resId->Int32Value(vm);
334     if (resIdValue != UNKNOWN_RESOURCE_ID) {
335         return;
336     }
337     auto args = jsObj->Get(vm,
338         panda::ExternalStringCache::GetCachedString(vm, static_cast<int32_t>(Framework::ArkUIIndex::PARAMS)));
339     Local<panda::ArrayRef> params = static_cast<Local<panda::ArrayRef>>(args);
340     auto identity = panda::ArrayRef::GetValueAt(vm, params, 0);
341     if (!identity->IsString(vm)) {
342         return;
343     }
344     resName = identity->ToString(vm)->ToString(vm);
345     bool isParseDollarResourceSuccess =
346         ParseDollarResource(targetModule, resType, resName, typeNum == UNKNOWN_RESOURCE_TYPE);
347     if (!isParseDollarResourceSuccess) {
348         return;
349     }
350 
351     auto moduleName = jsObj->Get(vm,
352         panda::ExternalStringCache::GetCachedString(vm,
353             static_cast<int32_t>(Framework::ArkUIIndex::MODULE_NAME)));
354     if (moduleName->IsString(vm) && moduleName->ToString(vm)->ToString(vm).empty()) {
355         std::regex resNameRegex(RESOURCE_NAME_PATTERN);
356         std::smatch resNameResults;
357         if (std::regex_match(targetModule, resNameResults, resNameRegex)) {
358             jsObj->Set(vm,
359                 panda::ExternalStringCache::GetCachedString(vm,
360                     static_cast<int32_t>(Framework::ArkUIIndex::MODULE_NAME)),
361                 panda::StringRef::NewFromUtf8(vm, resNameResults.str(1).c_str()));
362         } else {
363             jsObj->Set(vm,
364                 panda::ExternalStringCache::GetCachedString(vm,
365                     static_cast<int32_t>(Framework::ArkUIIndex::MODULE_NAME)),
366                 panda::StringRef::NewFromUtf8(vm, ""));
367         }
368     }
369     if (typeNum == UNKNOWN_RESOURCE_TYPE) {
370         jsObj->Set(vm, panda::ExternalStringCache::GetCachedString(vm,
371             static_cast<int32_t>(Framework::ArkUIIndex::TYPE)),
372             panda::NumberRef::New(vm, static_cast<int32_t>(resType)));
373     }
374 }
375 
CompleteResourceObjectFromId(const EcmaVM * vm,const Local<JSValueRef> & type,Local<panda::ObjectRef> & jsObj,ResourceType & resType,const std::string & resName)376 void CompleteResourceObjectFromId(const EcmaVM* vm, const Local<JSValueRef>& type, Local<panda::ObjectRef>& jsObj,
377     ResourceType& resType, const std::string& resName)
378 {
379     auto args = jsObj->Get(vm,
380         panda::ExternalStringCache::GetCachedString(vm, static_cast<int32_t>(Framework::ArkUIIndex::PARAMS)));
381     if (!args->IsArray(vm)) {
382         return;
383     }
384     Local<panda::ArrayRef> params = static_cast<Local<panda::ArrayRef>>(args);
385     auto paramCount = params->Length(vm);
386     auto name = panda::StringRef::NewFromUtf8(vm, resName.c_str());
387     if (resType == ResourceType::PLURAL || resType == ResourceType::STRING) {
388         std::vector<Local<JSValueRef>> tmpParams;
389         for (uint32_t i = 0; i < paramCount; i++) {
390             auto param = panda::ArrayRef::GetValueAt(vm, params, i);
391             tmpParams.insert(tmpParams.end(), param);
392         }
393         panda::ArrayRef::SetValueAt(vm, params, 0, name);
394         uint32_t paramIndex = 1;
395         auto firstParam = jsObj->Get(vm,
396             panda::ExternalStringCache::GetCachedString(vm, static_cast<int32_t>(Framework::ArkUIIndex::TYPE)));
397         if (!firstParam->IsNull()) {
398             panda::ArrayRef::SetValueAt(vm, params, paramIndex, firstParam);
399             paramIndex++;
400         }
401         for (auto tmpParam : tmpParams) {
402             panda::ArrayRef::SetValueAt(vm, params, paramIndex, tmpParam);
403             paramIndex++;
404         }
405     } else {
406         panda::ArrayRef::SetValueAt(vm, params, 0, name);
407     }
408     jsObj->Set(vm, panda::ExternalStringCache::GetCachedString(vm, static_cast<int32_t>(Framework::ArkUIIndex::ID)),
409                 panda::NumberRef::New(vm, UNKNOWN_RESOURCE_ID));
410     jsObj->Set(vm, panda::ExternalStringCache::GetCachedString(vm, static_cast<int32_t>(Framework::ArkUIIndex::TYPE)),
411             panda::ExternalStringCache::GetCachedString(vm, static_cast<int32_t>(resType)));
412     if (!jsObj->Has(vm,
413         panda::ExternalStringCache::GetCachedString(vm, static_cast<int32_t>(Framework::ArkUIIndex::BUNDLE_NAME)))) {
414         jsObj->Set(vm,
415             panda::ExternalStringCache::GetCachedString(vm, static_cast<int32_t>(Framework::ArkUIIndex::BUNDLE_NAME)),
416             panda::StringRef::NewFromUtf8(vm, ""));
417     }
418     if (!jsObj->Has(vm,
419         panda::ExternalStringCache::GetCachedString(vm, static_cast<int32_t>(Framework::ArkUIIndex::MODULE_NAME)))) {
420         jsObj->Set(vm,
421             panda::ExternalStringCache::GetCachedString(vm, static_cast<int32_t>(Framework::ArkUIIndex::MODULE_NAME)),
422             panda::StringRef::NewFromUtf8(vm, ""));
423     }
424 }
425 
CompleteResourceObject(const EcmaVM * vm,Local<panda::ObjectRef> & jsObj)426 void ArkTSUtils::CompleteResourceObject(const EcmaVM* vm, Local<panda::ObjectRef>& jsObj)
427 {
428     // dynamic $r raw input format is
429     // {"id":"app.xxx.xxx", "params":[], "bundleName":"xxx", "moduleName":"xxx"}
430     auto resId = jsObj->Get(vm,
431         panda::ExternalStringCache::GetCachedString(vm, static_cast<int32_t>(Framework::ArkUIIndex::ID)));
432     ResourceType resType = ResourceType::NONE;
433     std::string targetModule;
434     std::string resName;
435     if (resId->IsString(vm)) {
436         auto type = jsObj->Get(vm,
437             panda::ExternalStringCache::GetCachedString(vm, static_cast<int32_t>(Framework::ArkUIIndex::TYPE)));
438         int32_t typeNum = -1;
439         if (type->IsNumber()) {
440             typeNum = type->Int32Value(vm);
441         }
442         resName = resId->ToString(vm)->ToString(vm);
443         if (!ParseDollarResource(targetModule, resType, resName, typeNum == UNKNOWN_RESOURCE_TYPE)) {
444             return;
445         }
446         CompleteResourceObjectFromId(vm, type, jsObj, resType, resName);
447     } else if (resId->IsNumber()) {
448         int32_t resIdValue = resId->Int32Value(vm);
449         if (resIdValue == -1) {
450             CompleteResourceObjectFromParams(vm, jsObj, targetModule, resType, resName);
451         }
452     }
453 
454     std::string bundleName;
455     std::string moduleName;
456     ArkTSUtils::GetJsMediaBundleInfo(vm, jsObj, bundleName, moduleName);
457     if ((bundleName.empty() && !moduleName.empty()) || bundleName == DEFAULT_HAR_BUNDLE_NAME) {
458         bundleName = GetBundleNameFromContainer();
459         jsObj->Set(vm,
460             panda::ExternalStringCache::GetCachedString(vm, static_cast<int32_t>(Framework::ArkUIIndex::BUNDLE_NAME)),
461             panda::StringRef::NewFromUtf8(vm, bundleName.c_str()));
462     }
463     if (moduleName == DEFAULT_HAR_MODULE_NAME) {
464         moduleName = GetModuleNameFromContainer();
465         jsObj->Set(vm,
466             panda::ExternalStringCache::GetCachedString(vm, static_cast<int32_t>(Framework::ArkUIIndex::MODULE_NAME)),
467             panda::StringRef::NewFromUtf8(vm, moduleName.c_str()));
468     }
469 }
470 
471 
ParseJsColorFromResource(const EcmaVM * vm,const Local<JSValueRef> & jsObj,Color & result)472 bool ArkTSUtils::ParseJsColorFromResource(const EcmaVM* vm, const Local<JSValueRef>& jsObj, Color& result)
473 {
474     auto obj = jsObj ->ToObject(vm);
475     auto resId = obj->Get(vm, panda::StringRef::NewFromUtf8(vm, "id"));
476     if (!resId->IsNumber()) {
477         return false;
478     }
479 
480     CompleteResourceObject(vm, obj);
481     auto resourceObject = GetResourceObject(vm, jsObj);
482     auto resourceWrapper = CreateResourceWrapper(vm, jsObj, resourceObject);
483     if (!resourceWrapper) {
484         return false;
485     }
486 
487     auto resIdNum = resId->Int32Value(vm);
488     if (resIdNum == -1) {
489         if (!IsGetResourceByName(vm, jsObj)) {
490             return false;
491         }
492         auto args = obj->Get(vm, panda::StringRef::NewFromUtf8(vm, "params"));
493         if (!args->IsArray(vm)) {
494             return false;
495         }
496         Local<panda::ArrayRef> params = static_cast<Local<panda::ArrayRef>>(args);
497         auto param = panda::ArrayRef::GetValueAt(vm, params, 0);
498         result = resourceWrapper->GetColorByName(param->ToString(vm)->ToString(vm));
499         return true;
500     }
501     auto type = obj->Get(vm, panda::StringRef::NewFromUtf8(vm, "type"));
502     if (type->IsNull() || !type->IsNumber()) {
503         return false;
504     }
505     if (resourceObject->GetType() == static_cast<int32_t>(ResourceType::STRING)) {
506         auto value = resourceWrapper->GetString(resId->Int32Value(vm));
507         return Color::ParseColorString(value, result);
508     }
509     if (resourceObject->GetType() == static_cast<int32_t>(ResourceType::INTEGER)) {
510         auto value = resourceWrapper->GetInt(resId->Int32Value(vm));
511         result = Color(ColorAlphaAdapt(value));
512         return true;
513     }
514     if (resourceObject->GetType() == static_cast<int32_t>(ResourceType::COLOR)) {
515         result = resourceWrapper->GetColor(resId->ToNumber(vm)->Value());
516         result.SetResourceId(resId->Int32Value(vm));
517         return true;
518     }
519     return false;
520 }
521 
ParseJsDimensionFromResource(const EcmaVM * vm,const Local<JSValueRef> & jsObj,DimensionUnit dimensionUnit,CalcDimension & result)522 bool ArkTSUtils::ParseJsDimensionFromResource(const EcmaVM* vm, const Local<JSValueRef>& jsObj,
523     DimensionUnit dimensionUnit, CalcDimension& result)
524 {
525     auto obj = jsObj->ToObject(vm);
526     auto resId = obj->Get(vm, panda::StringRef::NewFromUtf8(vm, "id"));
527     if (!resId->IsNumber()) {
528         return false;
529     }
530 
531     CompleteResourceObject(vm, obj);
532     auto resourceObject = GetResourceObject(vm, jsObj);
533 
534     auto resourceWrapper = CreateResourceWrapper(vm, jsObj, resourceObject);
535     if (!resourceWrapper) {
536         return false;
537     }
538     auto resIdNum = resId->Int32Value(vm);
539     if (resIdNum == -1) {
540         if (!IsGetResourceByName(vm, jsObj)) {
541             return false;
542         }
543         auto args = obj->Get(vm, panda::StringRef::NewFromUtf8(vm, "params"));
544         if (!args->IsArray(vm)) {
545             return false;
546         }
547         Local<panda::ArrayRef> params = static_cast<Local<panda::ArrayRef>>(args);
548         auto param = panda::ArrayRef::GetValueAt(vm, params, 0);
549         result = resourceWrapper->GetDimensionByName(param->ToString(vm)->ToString(vm));
550         return true;
551     }
552     auto type = obj->Get(vm, panda::StringRef::NewFromUtf8(vm, "type"));
553     if (type->IsNull() || !type->IsNumber()) {
554         return false;
555     }
556     if (resourceObject->GetType() == static_cast<int32_t>(ResourceType::STRING)) {
557         auto value = resourceWrapper->GetString(resId->Int32Value(vm));
558         result = StringUtils::StringToCalcDimension(value, false, dimensionUnit);
559         return true;
560     }
561     if (resourceObject->GetType() == static_cast<int32_t>(ResourceType::INTEGER)) {
562         auto value = std::to_string(resourceWrapper->GetInt(resId->Int32Value(vm)));
563         result = StringUtils::StringToDimensionWithUnit(value, dimensionUnit);
564         return true;
565     }
566     result = resourceWrapper->GetDimension(resId->Int32Value(vm));
567     return true;
568 }
569 
ParseJsDimensionFromResourceNG(const EcmaVM * vm,const Local<JSValueRef> & jsObj,DimensionUnit dimensionUnit,CalcDimension & result)570 bool ArkTSUtils::ParseJsDimensionFromResourceNG(const EcmaVM* vm, const Local<JSValueRef>& jsObj,
571     DimensionUnit dimensionUnit, CalcDimension& result)
572 {
573     auto obj = jsObj->ToObject(vm);
574     auto resId = obj->Get(vm, panda::StringRef::NewFromUtf8(vm, "id"));
575     if (!resId->IsNumber()) {
576         return false;
577     }
578 
579     CompleteResourceObject(vm, obj);
580     auto resourceObject = GetResourceObject(vm, jsObj);
581 
582     auto resourceWrapper = CreateResourceWrapper(vm, jsObj, resourceObject);
583     if (!resourceWrapper) {
584         return false;
585     }
586     auto resIdNum = resId->Int32Value(vm);
587     if (resIdNum == -1) {
588         if (!IsGetResourceByName(vm, jsObj)) {
589             return false;
590         }
591         auto args = obj->Get(vm, panda::StringRef::NewFromUtf8(vm, "params"));
592         if (!args->IsArray(vm)) {
593             return false;
594         }
595         Local<panda::ArrayRef> params = static_cast<Local<panda::ArrayRef>>(args);
596         auto param = panda::ArrayRef::GetValueAt(vm, params, 0);
597         result = resourceWrapper->GetDimensionByName(param->ToString(vm)->ToString(vm));
598         return true;
599     }
600     auto type = obj->Get(vm, panda::StringRef::NewFromUtf8(vm, "type"));
601     if (type->IsNull() || !type->IsNumber()) {
602         return false;
603     }
604     if (resourceObject->GetType() == static_cast<int32_t>(ResourceType::STRING)) {
605         auto value = resourceWrapper->GetString(resId->Int32Value(vm));
606         return StringUtils::StringToCalcDimensionNG(value, result, false, dimensionUnit);
607     }
608     if (resourceObject->GetType() == static_cast<int32_t>(ResourceType::INTEGER)) {
609         auto value = std::to_string(resourceWrapper->GetInt(resId->Int32Value(vm)));
610         StringUtils::StringToDimensionWithUnitNG(value, result, dimensionUnit);
611         return true;
612     }
613     if (resourceObject->GetType() == static_cast<int32_t>(ResourceType::FLOAT)) {
614         result = resourceWrapper->GetDimension(resId->Int32Value(vm));
615         return true;
616     }
617 
618     return false;
619 }
620 
ParseStringArray(const EcmaVM * vm,const Local<JSValueRef> & arg,std::string * array,int32_t defaultLength)621 bool ArkTSUtils::ParseStringArray(const EcmaVM* vm, const Local<JSValueRef>& arg,
622     std::string* array, int32_t defaultLength)
623 {
624     CHECK_NULL_RETURN(vm, false);
625     CHECK_NULL_RETURN(array, false);
626     if (defaultLength <= 0) {
627         return false;
628     }
629     auto handle = panda::CopyableGlobal<panda::ArrayRef>(vm, arg);
630     if (handle.IsEmpty() || handle->IsUndefined() || handle->IsNull()) {
631         return false;
632     }
633     int32_t length = static_cast<int32_t>(handle->Length(vm));
634     if (length != defaultLength) {
635         return false;
636     }
637     for (int32_t i = 0; i < length; i++) {
638         auto value = handle->GetValueAt(vm, arg, i);
639         if (!ParseJsMedia(vm, value, *(array + i))) {
640             *(array + i) = "";
641         }
642     }
643     return true;
644 }
645 
ParseJsDimensionVp(const EcmaVM * vm,const Local<JSValueRef> & value,CalcDimension & result,bool enableCheckInvalidvalue)646 bool ArkTSUtils::ParseJsDimensionVp(
647     const EcmaVM* vm, const Local<JSValueRef>& value, CalcDimension& result, bool enableCheckInvalidvalue)
648 {
649     return ArkTSUtils::ParseJsDimension(vm, value, result, DimensionUnit::VP, true, enableCheckInvalidvalue);
650 }
651 
ParseJsInteger(const EcmaVM * vm,const Local<JSValueRef> & value,int32_t & result)652 bool ArkTSUtils::ParseJsInteger(const EcmaVM *vm, const Local<JSValueRef> &value, int32_t &result)
653 {
654     if (value->IsNumber()) {
655         result = value->Int32Value(vm);
656         return true;
657     }
658     return false;
659 }
660 
ParseJsInteger(const EcmaVM * vm,const Local<JSValueRef> & value,uint32_t & result)661 bool ArkTSUtils::ParseJsInteger(const EcmaVM *vm, const Local<JSValueRef> &value, uint32_t &result)
662 {
663     if (value->IsNumber()) {
664         result = value->Uint32Value(vm);
665         return true;
666     }
667     // resource ignore by design
668     return false;
669 }
670 
ParseJsIntegerWithResource(const EcmaVM * vm,const Local<JSValueRef> & jsValue,int32_t & result)671 bool ArkTSUtils::ParseJsIntegerWithResource(const EcmaVM* vm, const Local<JSValueRef>& jsValue, int32_t& result)
672 {
673     if (!jsValue->IsNumber() && !jsValue->IsObject(vm)) {
674         return false;
675     }
676 
677     if (jsValue->IsNumber()) {
678         result = jsValue->Int32Value(vm);
679         return true;
680     }
681 
682     auto jsObj = jsValue->ToObject(vm);
683     auto type = jsObj->Get(vm, panda::StringRef::NewFromUtf8(vm, "type"));
684     auto id = jsObj->Get(vm, panda::StringRef::NewFromUtf8(vm, "id"));
685     int32_t resourceType = 0;
686     if (!type->IsNumber() || !id->IsNumber()) {
687         return false;
688     }
689     resourceType = type->Int32Value(vm);
690     auto resIdNum = id->Int32Value(vm);
691 
692     CompleteResourceObject(vm, jsObj);
693     auto resourceObject = GetResourceObject(vm, jsValue);
694     auto resourceWrapper = CreateResourceWrapper(vm, jsValue, resourceObject);
695     CHECK_NULL_RETURN(resourceWrapper, false);
696 
697     if (resIdNum == -1) {
698         if (!IsGetResourceByName(vm, jsObj)) {
699             return false;
700         }
701         auto args = jsObj->Get(vm, panda::StringRef::NewFromUtf8(vm, "params"));
702         Local<panda::ArrayRef> params = static_cast<Local<panda::ArrayRef>>(args);
703         auto param = panda::ArrayRef::GetValueAt(vm, params, 0);
704         if (resourceType == static_cast<int32_t>(ResourceType::INTEGER)) {
705             result = resourceWrapper->GetIntByName(param->ToString(vm)->ToString(vm));
706             return true;
707         }
708         return false;
709     }
710 
711     if (resourceType == static_cast<int32_t>(ResourceType::INTEGER)) {
712         result = resourceWrapper->GetInt(resIdNum);
713         return true;
714     }
715 
716     return false;
717 }
718 
GetResourceIdAndType(const EcmaVM * vm,const Local<panda::ObjectRef> & jsObj,int32_t & resId,int32_t & resType)719 bool GetResourceIdAndType(const EcmaVM* vm, const Local<panda::ObjectRef>& jsObj, int32_t& resId, int32_t& resType)
720 {
721     auto id = jsObj->Get(vm, panda::StringRef::NewFromUtf8(vm, "id"));
722     auto type = jsObj->Get(vm, panda::StringRef::NewFromUtf8(vm, "type"));
723     if (!id->IsNumber() || !type->IsNumber()) {
724         return false;
725     }
726 
727     resId = id->Int32Value(vm);
728     resType = type->Int32Value(vm);
729     return true;
730 }
731 
ParseResourceToDouble(const EcmaVM * vm,const Local<JSValueRef> & jsValue,double & result)732 bool ArkTSUtils::ParseResourceToDouble(const EcmaVM* vm, const Local<JSValueRef>& jsValue, double& result)
733 {
734     auto jsObj = jsValue->ToObject(vm);
735     int32_t resId;
736     int32_t resType;
737     if (jsObj->IsNull() || !GetResourceIdAndType(vm, jsObj, resId, resType)) {
738         return false;
739     }
740     CompleteResourceObject(vm, jsObj);
741     auto resourceObject = GetResourceObject(vm, jsObj);
742     auto resourceWrapper = CreateResourceWrapper(vm, jsObj, resourceObject);
743     CHECK_NULL_RETURN(resourceWrapper, false);
744     if (resId == -1) {
745         if (!IsGetResourceByName(vm, jsObj)) {
746             return false;
747         }
748         auto args = jsObj->Get(vm, panda::StringRef::NewFromUtf8(vm, "params"));
749         if (!args->IsArray(vm)) {
750             return false;
751         }
752         Local<panda::ArrayRef> params = static_cast<Local<panda::ArrayRef>>(args);
753         auto param = panda::ArrayRef::GetValueAt(vm, params, 0);
754         if (resType == static_cast<int32_t>(ResourceType::STRING)) {
755             auto numberString = resourceWrapper->GetStringByName(param->ToString(vm)->ToString(vm));
756             return StringUtils::StringToDouble(numberString, result);
757         }
758         if (resType == static_cast<int32_t>(ResourceType::INTEGER)) {
759             result = resourceWrapper->GetIntByName(param->ToString(vm)->ToString(vm));
760             return true;
761         }
762         if (resType == static_cast<int32_t>(ResourceType::FLOAT)) {
763             result = resourceWrapper->GetDoubleByName(param->ToString(vm)->ToString(vm));
764             return true;
765         }
766         return false;
767     }
768     if (resourceObject->GetType() == static_cast<int32_t>(ResourceType::STRING)) {
769         auto numberString = resourceWrapper->GetString(resId);
770         return StringUtils::StringToDouble(numberString, result);
771     }
772     if (resourceObject->GetType() == static_cast<int32_t>(ResourceType::INTEGER)) {
773         result = resourceWrapper->GetInt(resId);
774         return true;
775     }
776     if (resourceObject->GetType() == static_cast<int32_t>(ResourceType::FLOAT)) {
777         result = resourceWrapper->GetDouble(resId);
778         return true;
779     }
780     return false;
781 }
782 
ParseJsDouble(const EcmaVM * vm,const Local<JSValueRef> & value,double & result)783 bool ArkTSUtils::ParseJsDouble(const EcmaVM *vm, const Local<JSValueRef> &value, double &result)
784 {
785     if (value->IsNumber()) {
786         result = value->ToNumber(vm)->Value();
787         return true;
788     }
789     if (value->IsString(vm)) {
790         return StringUtils::StringToDouble(value->ToString(vm)->ToString(vm), result);
791     }
792     if (value->IsObject(vm)) {
793         return ParseResourceToDouble(vm, value, result);
794     }
795     return false;
796 }
797 
ParseAllBorder(const EcmaVM * vm,const Local<JSValueRef> & args,CalcDimension & result)798 bool ArkTSUtils::ParseAllBorder(const EcmaVM* vm, const Local<JSValueRef>& args, CalcDimension& result)
799 {
800     if (ParseJsDimensionVp(vm, args, result)) {
801         if (result.IsNegative()) {
802             result.Reset();
803         }
804         return true;
805     } else {
806         return false;
807     }
808 }
809 
ParseAllRadius(const EcmaVM * vm,const Local<JSValueRef> & args,CalcDimension & result)810 bool ArkTSUtils::ParseAllRadius(const EcmaVM* vm, const Local<JSValueRef>& args, CalcDimension& result)
811 {
812     if (ParseJsDimensionVp(vm, args, result)) {
813         if (result.IsNegative()) {
814             result.Reset();
815         }
816         return true;
817     } else {
818         return false;
819     }
820 }
821 
ParseJsDimensionNG(const EcmaVM * vm,const Local<JSValueRef> & jsValue,CalcDimension & result,DimensionUnit defaultUnit,bool isSupportPercent)822 bool ArkTSUtils::ParseJsDimensionNG(const EcmaVM *vm, const Local<JSValueRef> &jsValue, CalcDimension &result,
823     DimensionUnit defaultUnit, bool isSupportPercent)
824 {
825     if (!jsValue->IsNumber() && !jsValue->IsString(vm) && !jsValue->IsObject(vm)) {
826         return false;
827     }
828     if (jsValue->IsNumber()) {
829         result = CalcDimension(jsValue->ToNumber(vm)->Value(), defaultUnit);
830         return true;
831     }
832     if (jsValue->IsString(vm)) {
833         auto value = jsValue->ToString(vm)->ToString(vm);
834         if (value.back() == '%' && !isSupportPercent) {
835             return false;
836         }
837         return StringUtils::StringToCalcDimensionNG(jsValue->ToString(vm)->ToString(vm), result, false, defaultUnit);
838     }
839     if (jsValue->IsObject(vm)) {
840         return ParseJsDimensionFromResourceNG(vm, jsValue, defaultUnit, result);
841     }
842     return false;
843 }
844 
ParseJsDimensionVpNG(const EcmaVM * vm,const Local<JSValueRef> & jsValue,CalcDimension & result,bool isSupportPercent)845 bool ArkTSUtils::ParseJsDimensionVpNG(const EcmaVM *vm, const Local<JSValueRef> &jsValue, CalcDimension &result,
846     bool isSupportPercent)
847 {
848     return ArkTSUtils::ParseJsDimensionNG(vm, jsValue, result, DimensionUnit::VP, isSupportPercent);
849 }
850 
ParseJsDimension(const EcmaVM * vm,const Local<JSValueRef> & jsValue,CalcDimension & result,DimensionUnit defaultUnit,bool isSupportPercent,bool enableCheckInvalidvalue)851 bool ArkTSUtils::ParseJsDimension(const EcmaVM *vm, const Local<JSValueRef> &jsValue, CalcDimension &result,
852     DimensionUnit defaultUnit, bool isSupportPercent, bool enableCheckInvalidvalue)
853 {
854     if (!jsValue->IsNumber() && !jsValue->IsString(vm) && !jsValue->IsObject(vm)) {
855         return false;
856     }
857 
858     if (jsValue->IsNumber()) {
859         result = CalcDimension(jsValue->ToNumber(vm)->Value(), defaultUnit);
860         return true;
861     }
862     if (jsValue->IsString(vm)) {
863         auto stringValue = jsValue->ToString(vm)->ToString(vm);
864         if (stringValue.back() == '%' && !isSupportPercent) {
865             return false;
866         }
867         if (enableCheckInvalidvalue && stringValue.find("calc") == std::string::npos) {
868             errno = 0;
869             char* pEnd = nullptr;
870             std::string str = jsValue->ToString(vm)->ToString(vm);
871             std::strtod(str.c_str(), &pEnd);
872             if (pEnd == str.c_str() || errno == ERANGE) {
873                 return false;
874             }
875         }
876         result = StringUtils::StringToCalcDimension(jsValue->ToString(vm)->ToString(vm), false, defaultUnit);
877         return true;
878     }
879     if (jsValue->IsObject(vm)) {
880         return ParseJsDimensionFromResource(vm, jsValue, defaultUnit, result);
881     }
882     return false;
883 }
884 
ParseJsDimensionFp(const EcmaVM * vm,const Local<JSValueRef> & jsValue,CalcDimension & result,bool isSupportPercent,bool enableCheckInvalidvalue)885 bool ArkTSUtils::ParseJsDimensionFp(const EcmaVM* vm, const Local<JSValueRef>& jsValue, CalcDimension& result,
886     bool isSupportPercent, bool enableCheckInvalidvalue)
887 {
888     return ArkTSUtils::ParseJsDimension(
889         vm, jsValue, result, DimensionUnit::FP, isSupportPercent, enableCheckInvalidvalue);
890 }
891 
ParseJsDimensionFpNG(const EcmaVM * vm,const Local<JSValueRef> & jsValue,CalcDimension & result,bool isSupportPercent)892 bool ArkTSUtils::ParseJsDimensionFpNG(const EcmaVM *vm, const Local<JSValueRef> &jsValue, CalcDimension &result,
893     bool isSupportPercent)
894 {
895     return ArkTSUtils::ParseJsDimensionNG(vm, jsValue, result, DimensionUnit::FP, isSupportPercent);
896 }
897 
ParseJsFontFamiliesToString(const EcmaVM * vm,const Local<JSValueRef> & jsValue,std::string & result)898 bool ArkTSUtils::ParseJsFontFamiliesToString(const EcmaVM* vm, const Local<JSValueRef>& jsValue, std::string& result)
899 {
900     if (jsValue->IsNull() || jsValue->IsUndefined()) {
901         return false;
902     }
903 
904     if (jsValue->IsString(vm) && jsValue->ToString(vm)->ToString(vm).empty()) {
905         return false;
906     }
907 
908     std::vector<std::string> fontFamilies;
909     if (!ParseJsFontFamilies(vm, jsValue, fontFamilies)) {
910         return false;
911     }
912     if (fontFamilies.size() > 0) {
913         result = "";
914         for (uint32_t i = 0; i < fontFamilies.size(); i++) {
915             result += fontFamilies.at(i);
916             if (&fontFamilies.at(i) != &fontFamilies.back()) {
917                 result += ",";
918             }
919         }
920         return true;
921     }
922 
923     return true;
924 }
925 
ParseJsFontFamilies(const EcmaVM * vm,const Local<JSValueRef> & jsValue,std::vector<std::string> & result)926 bool ArkTSUtils::ParseJsFontFamilies(
927     const EcmaVM *vm, const Local<JSValueRef> &jsValue, std::vector<std::string> &result)
928 {
929     result.clear();
930     if (!jsValue->IsString(vm) && !jsValue->IsObject(vm)) {
931         return false;
932     }
933     if (jsValue->IsString(vm)) {
934         result = Framework::ConvertStrToFontFamilies(jsValue->ToString(vm)->ToString(vm));
935         return true;
936     }
937     if (jsValue->IsObject(vm)) {
938         auto obj = jsValue->ToObject(vm);
939         auto resId = obj->Get(vm, panda::StringRef::NewFromUtf8(vm, "id"));
940         if (!resId->IsNumber()) {
941             return false;
942         }
943         return ParseJsFontFamiliesFromResource(vm, jsValue, result);
944     }
945     return true;
946 }
947 
ParseJsFontFamiliesFromResource(const EcmaVM * vm,const Local<JSValueRef> & jsValue,std::vector<std::string> & result)948 bool ArkTSUtils::ParseJsFontFamiliesFromResource(
949     const EcmaVM *vm, const Local<JSValueRef> &jsValue, std::vector<std::string> &result)
950 {
951     auto jsObj = jsValue->ToObject(vm);
952     auto resId = jsObj->Get(vm, panda::StringRef::NewFromUtf8(vm, "id"));
953     if (!resId->IsNumber()) {
954         return false;
955     }
956 
957     CompleteResourceObject(vm, jsObj);
958     auto resourceObject = GetResourceObject(vm, jsValue);
959     auto resourceWrapper = CreateResourceWrapper(vm, jsValue, resourceObject);
960     if (!resourceWrapper) {
961         return false;
962     }
963 
964     auto resIdNum = resId->Int32Value(vm);
965     if (resIdNum == -1) {
966         if (!IsGetResourceByName(vm, jsValue)) {
967             return false;
968         }
969         auto args = jsObj->Get(vm, panda::StringRef::NewFromUtf8(vm, "params"));
970         if (!args->IsArray(vm)) {
971             return false;
972         }
973         Local<panda::ArrayRef> params = static_cast<Local<panda::ArrayRef>>(args);
974         auto param = panda::ArrayRef::GetValueAt(vm, params, 0);
975         result.emplace_back(resourceWrapper->GetStringByName(param->ToString(vm)->ToString(vm)));
976         return true;
977     }
978     result.emplace_back(resourceWrapper->GetString(resId->Uint32Value(vm)));
979     return true;
980 }
981 
ParseJsLengthMetrics(const EcmaVM * vm,const Local<JSValueRef> & jsValue,CalcDimension & result)982 bool ArkTSUtils::ParseJsLengthMetrics(const EcmaVM* vm, const Local<JSValueRef>& jsValue, CalcDimension& result)
983 {
984     if (!jsValue->IsObject(vm)) {
985         return false;
986     }
987     auto jsObj = jsValue->ToObject(vm);
988     auto value = jsObj->Get(vm, panda::StringRef::NewFromUtf8(vm, "value"));
989     if (!value->IsNumber()) {
990         return false;
991     }
992     auto unit = DimensionUnit::VP;
993     auto jsUnit = jsObj->Get(vm, panda::StringRef::NewFromUtf8(vm, "unit"));
994     if (jsUnit->IsNumber()) {
995         unit = static_cast<DimensionUnit>(jsUnit->ToNumber(vm)->Value());
996     }
997     CalcDimension dimension(value->ToNumber(vm)->Value(), unit);
998     result = dimension;
999     return true;
1000 }
1001 
ParseJsMedia(const EcmaVM * vm,const Local<JSValueRef> & jsValue,std::string & result)1002 bool ArkTSUtils::ParseJsMedia(const EcmaVM *vm, const Local<JSValueRef> &jsValue, std::string& result)
1003 {
1004     if (!jsValue->IsObject(vm) && !jsValue->IsString(vm)) {
1005         return false;
1006     }
1007     if (jsValue->IsString(vm)) {
1008         result = jsValue->ToString(vm)->ToString(vm);
1009         return true;
1010     }
1011     if (jsValue->IsObject(vm)) {
1012         auto obj = jsValue->ToObject(vm);
1013         CompleteResourceObject(vm, obj);
1014         auto resId = obj->Get(vm,
1015             panda::ExternalStringCache::GetCachedString(vm, static_cast<int32_t>(Framework::ArkUIIndex::ID)));
1016         if (!resId->IsNumber()) {
1017             return false;
1018         }
1019         return ParseJsMediaFromResource(vm, jsValue, result);
1020     }
1021     return false;
1022 }
1023 
ParseJsMediaFromResource(const EcmaVM * vm,const Local<JSValueRef> & jsValue,std::string & result)1024 bool ArkTSUtils::ParseJsMediaFromResource(const EcmaVM *vm, const Local<JSValueRef> &jsValue, std::string& result)
1025 {
1026     auto jsObj = jsValue->ToObject(vm);
1027     auto type = jsObj->Get(vm,
1028         panda::ExternalStringCache::GetCachedString(vm, static_cast<int32_t>(Framework::ArkUIIndex::TYPE)));
1029     auto resId = jsObj->Get(vm,
1030         panda::ExternalStringCache::GetCachedString(vm, static_cast<int32_t>(Framework::ArkUIIndex::ID)));
1031     if (!resId->IsNull() && !type->IsNull() && type->IsNumber() && resId->IsNumber()) {
1032         auto resourceObject = GetResourceObject(vm, jsValue);
1033         auto resourceWrapper = CreateResourceWrapper(vm, jsValue, resourceObject);
1034         if (!resourceWrapper) {
1035             return false;
1036         }
1037 
1038         if (resourceObject->GetType() == static_cast<int32_t>(ResourceType::RAWFILE)) {
1039             auto args = jsObj->Get(vm, panda::ExternalStringCache::GetCachedString(vm,
1040                 static_cast<int32_t>(Framework::ArkUIIndex::PARAMS)));
1041             if (!args->IsArray(vm)) {
1042                 return false;
1043             }
1044             Local<panda::ArrayRef> params = static_cast<Local<panda::ArrayRef>>(args);
1045             auto fileName = panda::ArrayRef::GetValueAt(vm, params, 0);
1046             if (!fileName->IsString(vm)) {
1047                 return false;
1048             }
1049             result = resourceWrapper->GetRawfile(fileName->ToString(vm)->ToString(vm));
1050             return true;
1051         }
1052         auto resIdNum = resId->Int32Value(vm);
1053         if (resIdNum == -1) {
1054             if (!IsGetResourceByName(vm, jsValue)) {
1055                 return false;
1056             }
1057             auto args = jsObj->Get(vm, panda::ExternalStringCache::GetCachedString(vm,
1058                 static_cast<int32_t>(Framework::ArkUIIndex::PARAMS)));
1059             if (!args->IsArray(vm)) {
1060                 return false;
1061             }
1062             Local<panda::ArrayRef> params = static_cast<Local<panda::ArrayRef>>(args);
1063             auto param = panda::ArrayRef::GetValueAt(vm, params, 0);
1064             if (resourceObject->GetType() == static_cast<int32_t>(ResourceType::MEDIA)) {
1065                 result = resourceWrapper->GetMediaPathByName(param->ToString(vm)->ToString(vm));
1066                 return true;
1067             }
1068             return false;
1069         }
1070         if (resourceObject->GetType() == static_cast<int32_t>(ResourceType::MEDIA)) {
1071             result = resourceWrapper->GetMediaPath(resId->Uint32Value(vm));
1072             return true;
1073         }
1074         return false;
1075     }
1076     return false;
1077 }
1078 
GetStringFromJS(const EcmaVM * vm,const Local<JSValueRef> & value,std::string & result)1079 void ArkTSUtils::GetStringFromJS(const EcmaVM *vm, const Local<JSValueRef> &value, std::string& result)
1080 {
1081     result = DEFAULT_STR;
1082     if (!value->IsNull() && value->IsString(vm)) {
1083         result = value->ToString(vm)->ToString(vm);
1084     }
1085     if (value->IsObject(vm)) {
1086         ParseJsStringFromResource(vm, value, result);
1087     }
1088 }
1089 
ParseJsIntegerArray(const EcmaVM * vm,Local<JSValueRef> values,std::vector<uint32_t> & result)1090 bool ArkTSUtils::ParseJsIntegerArray(const EcmaVM* vm, Local<JSValueRef> values, std::vector<uint32_t>& result)
1091 {
1092     if (!values->IsArray(vm) && !values->IsObject(vm)) {
1093         return false;
1094     }
1095 
1096     Local<panda::ArrayRef> valueArray = static_cast<Local<panda::ArrayRef>>(values);
1097     for (size_t i = 0; i < valueArray->Length(vm); i++) {
1098         Local<JSValueRef> value = valueArray->GetValueAt(vm, values, i);
1099         if (value->IsNumber()) {
1100             result.emplace_back(value->Uint32Value(vm));
1101         } else if (value->IsObject(vm)) {
1102             uint32_t singleResInt;
1103             if (ParseJsInteger(vm, value, singleResInt)) {
1104                 result.emplace_back(singleResInt);
1105             } else {
1106                 return false;
1107             }
1108         } else {
1109             return false;
1110         }
1111     }
1112     return true;
1113 }
1114 
ParseJsString(const EcmaVM * vm,const Local<JSValueRef> & jsValue,std::string & result)1115 bool ArkTSUtils::ParseJsString(const EcmaVM* vm, const Local<JSValueRef>& jsValue, std::string& result)
1116 {
1117     if (!jsValue->IsString(vm) && !jsValue->IsObject(vm)) {
1118         return false;
1119     }
1120     if (jsValue->IsString(vm)) {
1121         result = jsValue->ToString(vm)->ToString(vm);
1122         return true;
1123     }
1124     if (jsValue->IsObject(vm)) {
1125         return ArkTSUtils::ParseJsStringFromResource(vm, jsValue, result);
1126     }
1127     return false;
1128 }
1129 
GetReplaceContentStr(const EcmaVM * vm,int32_t pos,const std::string & type,Local<panda::ArrayRef> params,int32_t containCount)1130 std::string GetReplaceContentStr(
1131     const EcmaVM* vm, int32_t pos, const std::string& type, Local<panda::ArrayRef> params, int32_t containCount)
1132 {
1133     int32_t index = pos + containCount;
1134     if (index < 0) {
1135         return std::string();
1136     }
1137     auto item = panda::ArrayRef::GetValueAt(vm, params, static_cast<uint32_t>(index));
1138     if (type == "d") {
1139         if (item->IsNumber()) {
1140             return std::to_string(item->Int32Value(vm));
1141         }
1142     } else if (type == "s") {
1143         if (item->IsString(vm)) {
1144             return item->ToString(vm)->ToString(vm);
1145         }
1146     } else if (type == "f") {
1147         if (item->IsNumber()) {
1148             return std::to_string(item->ToNumber(vm)->Value());
1149         }
1150     }
1151     return std::string();
1152 }
1153 
ReplaceHolder(const EcmaVM * vm,std::string & originStr,const Local<panda::ArrayRef> & params,int32_t containCount)1154 void ReplaceHolder(const EcmaVM* vm, std::string& originStr, const Local<panda::ArrayRef>& params, int32_t containCount)
1155 {
1156     auto size = static_cast<int32_t>(params->Length(vm));
1157     if (containCount == size) {
1158         return;
1159     }
1160     std::string::const_iterator start = originStr.begin();
1161     std::string::const_iterator end = originStr.end();
1162     std::smatch matches;
1163     bool shortHolderType = false;
1164     bool firstMatch = true;
1165     int searchTime = 0;
1166     while (std::regex_search(start, end, matches, RESOURCE_APP_STRING_PLACEHOLDER)) {
1167         std::string pos = matches[2];
1168         std::string type = matches[4];
1169         if (firstMatch) {
1170             firstMatch = false;
1171             shortHolderType = pos.length() == 0;
1172         } else {
1173             if (static_cast<uint32_t>(shortHolderType) ^ static_cast<uint32_t>(pos.length() == 0)) {
1174                 return;
1175             }
1176         }
1177 
1178         std::string replaceContentStr;
1179         if (shortHolderType) {
1180             replaceContentStr = GetReplaceContentStr(vm, searchTime, type, params, containCount);
1181         } else {
1182             replaceContentStr = GetReplaceContentStr(vm, StringUtils::StringToInt(pos) - 1, type, params, containCount);
1183         }
1184 
1185         originStr.replace(matches[0].first - originStr.begin(), matches[0].length(), replaceContentStr);
1186         start = originStr.begin() + matches.prefix().length() + replaceContentStr.length();
1187         end = originStr.end();
1188         searchTime++;
1189     }
1190 }
1191 
FillResultForResIdNumIsNegative(const EcmaVM * vm,const Local<JSValueRef> & type,const Local<JSValueRef> & params,std::string & result,const RefPtr<ResourceWrapper> & resourceWrapper)1192 bool FillResultForResIdNumIsNegative(const EcmaVM* vm, const Local<JSValueRef>& type, const Local<JSValueRef>& params,
1193     std::string& result, const RefPtr<ResourceWrapper>& resourceWrapper)
1194 {
1195     auto param = panda::ArrayRef::GetValueAt(vm, params, 0);
1196     if (type->Uint32Value(vm) == static_cast<uint32_t>(ResourceType::STRING)) {
1197         auto originStr = resourceWrapper->GetStringByName(param->ToString(vm)->ToString(vm));
1198         ReplaceHolder(vm, originStr, params, 1);
1199         result = originStr;
1200     } else if (type->Uint32Value(vm) == static_cast<uint32_t>(ResourceType::PLURAL)) {
1201         auto countJsVal = panda::ArrayRef::GetValueAt(vm, params, 1);
1202         int count = 0;
1203         if (!countJsVal->IsNumber()) {
1204             return false;
1205         }
1206         count = countJsVal->ToNumber(vm)->Value();
1207         auto pluralStr = resourceWrapper->GetPluralStringByName(param->ToString(vm)->ToString(vm), count);
1208         ReplaceHolder(vm, pluralStr, params, REPLACEHOLDER_INDEX);
1209         result = pluralStr;
1210     } else {
1211         return false;
1212     }
1213     return true;
1214 }
1215 
ParseJsStringFromResource(const EcmaVM * vm,const Local<JSValueRef> & jsValue,std::string & result)1216 bool ArkTSUtils::ParseJsStringFromResource(const EcmaVM* vm, const Local<JSValueRef>& jsValue, std::string& result)
1217 {
1218     auto obj = jsValue->ToObject(vm);
1219     auto type = obj->Get(vm, panda::StringRef::NewFromUtf8(vm, "type"));
1220     auto resId = obj->Get(vm, panda::StringRef::NewFromUtf8(vm, "id"));
1221     auto args = obj->Get(vm, panda::StringRef::NewFromUtf8(vm, "params"));
1222     if (!type->IsNumber() || !resId->IsNumber() || !args->IsArray(vm)) {
1223         return false;
1224     }
1225 
1226     CompleteResourceObject(vm, obj);
1227     auto resourceObject = GetResourceObject(vm, obj);
1228     auto resourceWrapper = CreateResourceWrapper(vm, obj, resourceObject);
1229     if (!resourceWrapper) {
1230         return false;
1231     }
1232 
1233     Local<panda::ArrayRef> params = static_cast<Local<panda::ArrayRef>>(args);
1234     auto resIdNum = resourceObject->GetId();
1235     if (resIdNum == -1) {
1236         if (!IsGetResourceByName(vm, obj)) {
1237             return false;
1238         }
1239         return FillResultForResIdNumIsNegative(vm, type, params, result, resourceWrapper);
1240     }
1241     if (resourceObject->GetType() == static_cast<int32_t>(ResourceType::STRING)) {
1242         auto originStr = resourceWrapper->GetString(resId->Uint32Value(vm));
1243         ReplaceHolder(vm, originStr, params, 0);
1244         result = originStr;
1245     } else if (resourceObject->GetType() == static_cast<int32_t>(ResourceType::PLURAL)) {
1246         auto countJsVal = panda::ArrayRef::GetValueAt(vm, params, 0);
1247         int count = 0;
1248         if (!countJsVal->IsNumber()) {
1249             return false;
1250         }
1251         count = countJsVal->ToNumber(vm)->Value();
1252         auto pluralStr = resourceWrapper->GetPluralString(resId->ToNumber(vm)->Value(), count);
1253         ReplaceHolder(vm, pluralStr, params, 1);
1254         result = pluralStr;
1255     } else if (resourceObject->GetType() == static_cast<int32_t>(ResourceType::FLOAT)) {
1256         result = std::to_string(resourceWrapper->GetDouble(resId->Uint32Value(vm)));
1257     } else if (resourceObject->GetType() == static_cast<int32_t>(ResourceType::INTEGER)) {
1258         result = std::to_string(resourceWrapper->GetInt(resId->Uint32Value(vm)));
1259     } else {
1260         return false;
1261     }
1262     return true;
1263 }
1264 
ParseJsResource(const EcmaVM * vm,const Local<JSValueRef> & jsValue,CalcDimension & result)1265 bool ArkTSUtils::ParseJsResource(const EcmaVM *vm, const Local<JSValueRef> &jsValue, CalcDimension &result)
1266 {
1267     if (!jsValue->IsObject(vm)) {
1268         return false;
1269     }
1270     auto jsObj = jsValue->ToObject(vm);
1271     CompleteResourceObject(vm, jsObj);
1272     auto resourceObject = GetResourceObject(vm, jsValue);
1273     auto resourceWrapper = CreateResourceWrapper(vm, jsValue, resourceObject);
1274     CHECK_NULL_RETURN(resourceWrapper, false);
1275 
1276     auto type = jsObj->Get(vm, panda::StringRef::NewFromUtf8(vm, "type"));
1277     auto id = jsObj->Get(vm, panda::StringRef::NewFromUtf8(vm, "id"));
1278     uint32_t resourceType = 0;
1279     if (type->IsNull() || !type->IsNumber() || id->IsNull() || !id->IsNumber()) {
1280         return false;
1281     } else {
1282         resourceType = type->Uint32Value(vm);
1283     }
1284     if (resourceType == static_cast<uint32_t>(ResourceType::STRING)) {
1285         auto value = resourceWrapper->GetString(id->Uint32Value(vm));
1286         return StringUtils::StringToCalcDimensionNG(value, result, false);
1287     }
1288     if (resourceType == static_cast<uint32_t>(ResourceType::INTEGER)) {
1289         auto value = std::to_string(resourceWrapper->GetInt(id->Uint32Value(vm)));
1290         StringUtils::StringToDimensionWithUnitNG(value, result);
1291         return true;
1292     }
1293 
1294     if (resourceType == static_cast<uint32_t>(ResourceType::FLOAT)) {
1295         result = resourceWrapper->GetDimension(id->Uint32Value(vm));
1296         return true;
1297     }
1298     return false;
1299 }
1300 
GetJsMediaBundleInfo(const EcmaVM * vm,const Local<JSValueRef> & jsValue,std::string & bundleName,std::string & moduleName)1301 void ArkTSUtils::GetJsMediaBundleInfo(
1302     const EcmaVM* vm, const Local<JSValueRef>& jsValue, std::string& bundleName, std::string& moduleName)
1303 {
1304     if (!jsValue->IsObject(vm) || jsValue->IsString(vm)) {
1305         return;
1306     }
1307     auto jsObj = jsValue->ToObject(vm);
1308     if (!jsObj->IsUndefined()) {
1309         auto bundle = jsObj->Get(vm, panda::ExternalStringCache::GetCachedString(vm,
1310             static_cast<int32_t>(Framework::ArkUIIndex::BUNDLE_NAME)));
1311         auto module = jsObj->Get(vm, panda::ExternalStringCache::GetCachedString(vm,
1312             static_cast<int32_t>(Framework::ArkUIIndex::MODULE_NAME)));
1313         if (bundle->IsString(vm) && module->IsString(vm)) {
1314             bundleName = bundle->ToString(vm)->ToString(vm);
1315             moduleName = module->ToString(vm)->ToString(vm);
1316         }
1317     }
1318 }
1319 
ParseJsColorStrategy(const EcmaVM * vm,const Local<JSValueRef> & value,ForegroundColorStrategy & strategy)1320 bool ArkTSUtils::ParseJsColorStrategy(
1321     const EcmaVM* vm, const Local<JSValueRef>& value, ForegroundColorStrategy& strategy)
1322 {
1323     if (value->IsString(vm)) {
1324         std::string colorStr = value->ToString(vm)->ToString(vm);
1325         if (colorStr.compare("invert") == 0) {
1326             strategy = ForegroundColorStrategy::INVERT;
1327             return true;
1328         }
1329     }
1330     return false;
1331 }
1332 
GetJsPasswordIcon(const EcmaVM * vm,const Local<JSValueRef> & jsOnIconSrc,const Local<JSValueRef> & jsOffIconSrc,PasswordIcon & result)1333 bool ArkTSUtils::GetJsPasswordIcon(const EcmaVM *vm, const Local<JSValueRef> &jsOnIconSrc,
1334     const Local<JSValueRef> &jsOffIconSrc, PasswordIcon& result)
1335 {
1336     result.showResult = "";
1337     result.hideResult = "";
1338     result.showBundleName = "";
1339     result.hideBundleName = "";
1340     result.showModuleName = "";
1341     result.hideModuleName = "";
1342 
1343     if (!jsOnIconSrc->IsString(vm) && !jsOnIconSrc->IsObject(vm)
1344         && !jsOffIconSrc->IsString(vm) && !jsOffIconSrc->IsObject(vm)) {
1345         return false;
1346     }
1347 
1348     if (jsOnIconSrc->IsString(vm)) {
1349         result.showResult = jsOnIconSrc->ToString(vm)->ToString(vm);
1350     }
1351 
1352     if (jsOnIconSrc->IsObject(vm)) {
1353         auto obj = jsOnIconSrc->ToObject(vm);
1354         std::string bundleName;
1355         std::string moduleName;
1356         auto bundle = obj->Get(vm, panda::StringRef::NewFromUtf8(vm, "bundleName"));
1357         auto module = obj->Get(vm, panda::StringRef::NewFromUtf8(vm, "moduleName"));
1358         if (bundle->IsString(vm) && module->IsString(vm)) {
1359             result.showBundleName = bundle->ToString(vm)->ToString(vm);
1360             result.showModuleName = module->ToString(vm)->ToString(vm);
1361         }
1362         ParseJsMedia(vm, jsOnIconSrc, result.showResult);
1363     }
1364 
1365     if (jsOffIconSrc->IsString(vm)) {
1366         result.hideResult = jsOffIconSrc->ToString(vm)->ToString(vm);
1367     }
1368 
1369     if (jsOffIconSrc->IsObject(vm)) {
1370         auto obj = jsOffIconSrc->ToObject(vm);
1371         std::string bundleName;
1372         std::string moduleName;
1373         auto bundle = obj->Get(vm, panda::StringRef::NewFromUtf8(vm, "bundleName"));
1374         auto module = obj->Get(vm, panda::StringRef::NewFromUtf8(vm, "moduleName"));
1375         if (bundle->IsString(vm) && module->IsString(vm)) {
1376             result.hideBundleName = bundle->ToString(vm)->ToString(vm);
1377             result.hideModuleName = module->ToString(vm)->ToString(vm);
1378         }
1379         ParseJsMedia(vm, jsOffIconSrc, result.hideResult);
1380     }
1381     return true;
1382 }
1383 
ParsePadding(const EcmaVM * vm,const Local<JSValueRef> & value,CalcDimension & dimen,ArkUISizeType & result)1384 void ArkTSUtils::ParsePadding(
1385     const EcmaVM* vm, const Local<JSValueRef>& value, CalcDimension& dimen, ArkUISizeType& result)
1386 {
1387     if (ArkTSUtils::ParseJsDimensionVp(vm, value, dimen)) {
1388         if (LessOrEqual(dimen.Value(), 0.0)) {
1389             dimen.SetValue(0.0);
1390             dimen.SetUnit(DimensionUnit::VP);
1391         }
1392         result.unit = static_cast<int8_t>(dimen.Unit());
1393         if (dimen.CalcValue() != "") {
1394             result.string = dimen.CalcValue().c_str();
1395         } else {
1396             result.value = dimen.Value();
1397         }
1398     }
1399 }
1400 
GetContext(EcmaVM * vm)1401 panda::Local<panda::ObjectRef> ArkTSUtils::GetContext(EcmaVM* vm)
1402 {
1403     auto container = Container::Current();
1404     CHECK_NULL_RETURN(container, panda::JSValueRef::Undefined(vm));
1405     auto frontend = container->GetFrontend();
1406     CHECK_NULL_RETURN(frontend, panda::JSValueRef::Undefined(vm));
1407     return NapiValueToLocalValue(frontend->GetContextValue());
1408 }
1409 
ParseResponseRegion(const EcmaVM * vm,const Local<JSValueRef> & jsValue,ArkUI_Float32 * regionValues,int32_t * regionUnits,uint32_t length)1410 bool ArkTSUtils::ParseResponseRegion(
1411     const EcmaVM* vm, const Local<JSValueRef>& jsValue, ArkUI_Float32* regionValues,
1412     int32_t* regionUnits, uint32_t length)
1413 {
1414     if (jsValue->IsUndefined() || !jsValue->IsArray(vm)) {
1415         return false;
1416     }
1417 
1418     Local<panda::ArrayRef> transArray = static_cast<Local<panda::ArrayRef>>(jsValue);
1419     for (uint32_t i = 0; i < length; i = i + 4) { // 4: dimension length
1420         Local<JSValueRef> x = transArray->GetValueAt(vm, jsValue, i);
1421         Local<JSValueRef> y = transArray->GetValueAt(vm, jsValue, i + 1);
1422         Local<JSValueRef> width = transArray->GetValueAt(vm, jsValue, i + 2); // 2: width value
1423         Local<JSValueRef> height = transArray->GetValueAt(vm, jsValue, i + 3); // 3: height value
1424         CalcDimension xDimen = CalcDimension(0.0, DimensionUnit::VP);
1425         CalcDimension yDimen = CalcDimension(0.0, DimensionUnit::VP);
1426         CalcDimension widthDimen = CalcDimension(1, DimensionUnit::PERCENT);
1427         CalcDimension heightDimen = CalcDimension(1, DimensionUnit::PERCENT);
1428         auto s1 = width->ToString(vm)->ToString(vm);
1429         auto s2 = height->ToString(vm)->ToString(vm);
1430         if (s1.find('-') != std::string::npos) {
1431             width = OHOS::Ace::Framework::ToJSValue("100%");
1432         }
1433         if (s2.find('-') != std::string::npos) {
1434             height = OHOS::Ace::Framework::ToJSValue("100%");
1435         }
1436         if (!ArkTSUtils::ParseJsDimensionNG(vm, x, xDimen, DimensionUnit::VP)) {
1437             xDimen = CalcDimension(0.0, DimensionUnit::VP);
1438         }
1439         if (!ArkTSUtils::ParseJsDimensionNG(vm, y, yDimen, DimensionUnit::VP)) {
1440             yDimen = CalcDimension(0.0, DimensionUnit::VP);
1441         }
1442         if (!ArkTSUtils::ParseJsDimensionNG(vm, width, widthDimen, DimensionUnit::VP)) {
1443             widthDimen = CalcDimension(1, DimensionUnit::PERCENT);
1444         }
1445         if (!ArkTSUtils::ParseJsDimensionNG(vm, height, heightDimen, DimensionUnit::VP)) {
1446             heightDimen = CalcDimension(1, DimensionUnit::PERCENT);
1447         }
1448         regionValues[i] = static_cast<ArkUI_Float32>(xDimen.Value());
1449         regionUnits[i] = static_cast<int32_t>(xDimen.Unit());
1450         regionValues[i + 1] = static_cast<ArkUI_Float32>(yDimen.Value());
1451         regionUnits[i + 1] = static_cast<int32_t>(yDimen.Unit());
1452         regionValues[i + 2] = static_cast<ArkUI_Float32>(widthDimen.Value()); // 2: width value
1453         regionUnits[i + 2] = static_cast<int32_t>(widthDimen.Unit()); // 2: width Unit
1454         regionValues[i + 3] = static_cast<ArkUI_Float32>(heightDimen.Value()); // 3: height value
1455         regionUnits[i + 3] = static_cast<int32_t>(heightDimen.Unit()); // 3: height Unit
1456     }
1457     return true;
1458 }
1459 
parseShadowColor(const EcmaVM * vm,const Local<JSValueRef> & jsValue)1460 uint32_t ArkTSUtils::parseShadowColor(const EcmaVM* vm, const Local<JSValueRef>& jsValue)
1461 {
1462     Color color = DEFAULT_TEXT_SHADOW_COLOR;
1463     if (!ParseJsColorAlpha(vm, jsValue, color)) {
1464         color = DEFAULT_TEXT_SHADOW_COLOR;
1465     }
1466     return color.GetValue();
1467 };
1468 
parseShadowFill(const EcmaVM * vm,const Local<JSValueRef> & jsValue)1469 uint32_t ArkTSUtils::parseShadowFill(const EcmaVM* vm, const Local<JSValueRef>& jsValue)
1470 {
1471     if (jsValue->IsBoolean()) {
1472         return static_cast<uint32_t>(jsValue->ToBoolean(vm)->Value());
1473     }
1474     return static_cast<uint32_t>(DEFAULT_TEXT_SHADOW_FILL);
1475 };
1476 
parseShadowType(const EcmaVM * vm,const Local<JSValueRef> & jsValue)1477 uint32_t ArkTSUtils::parseShadowType(const EcmaVM* vm, const Local<JSValueRef>& jsValue)
1478 {
1479     if (jsValue->IsInt()) {
1480         return jsValue->Uint32Value(vm);
1481     }
1482     return static_cast<uint32_t>(DEFAULT_TEXT_SHADOW_TYPE);
1483 };
1484 
parseShadowRadius(const EcmaVM * vm,const Local<JSValueRef> & jsValue)1485 double ArkTSUtils::parseShadowRadius(const EcmaVM* vm, const Local<JSValueRef>& jsValue)
1486 {
1487     double radius = 0.0;
1488     ArkTSUtils::ParseJsDouble(vm, jsValue, radius);
1489     if (LessNotEqual(radius, 0.0)) {
1490         radius = 0.0;
1491     }
1492     return radius;
1493 };
1494 
parseShadowOffset(const EcmaVM * vm,const Local<JSValueRef> & jsValue)1495 double ArkTSUtils::parseShadowOffset(const EcmaVM* vm, const Local<JSValueRef>& jsValue)
1496 {
1497     CalcDimension offset;
1498     if (ArkTSUtils::ParseJsResource(vm, jsValue, offset)) {
1499         return offset.Value();
1500     } else if (ArkTSUtils::ParseJsDimensionVp(vm, jsValue, offset)) {
1501         return offset.Value();
1502     }
1503     return 0.0;
1504 };
1505 
ParseOuterBorder(EcmaVM * vm,const Local<JSValueRef> & args,std::optional<CalcDimension> & optionalDimension)1506 void ArkTSUtils::ParseOuterBorder(
1507     EcmaVM* vm, const Local<JSValueRef>& args, std::optional<CalcDimension>& optionalDimension)
1508 {
1509     CalcDimension valueDim;
1510     if (!args->IsUndefined() && ArkTSUtils::ParseJsDimensionVp(vm, args, valueDim, false)) {
1511         if (valueDim.IsNegative() || valueDim.Unit() == DimensionUnit::PERCENT) {
1512             valueDim.Reset();
1513         }
1514         optionalDimension = valueDim;
1515     }
1516 }
1517 
ParseOuterBorderForDashParams(EcmaVM * vm,const Local<JSValueRef> & args,std::optional<CalcDimension> & optionalDimension)1518 void ArkTSUtils::ParseOuterBorderForDashParams(
1519     EcmaVM* vm, const Local<JSValueRef>& args, std::optional<CalcDimension>& optionalDimension)
1520 {
1521     CalcDimension valueDim;
1522     if (!args->IsUndefined()) {
1523         if (ArkTSUtils::ParseJsLengthMetrics(vm, args, valueDim)) {
1524             if (valueDim.Unit() == DimensionUnit::PERCENT) {
1525                 valueDim.Reset();
1526             }
1527             optionalDimension = valueDim;
1528         } else if (ArkTSUtils::ParseJsDimensionVpNG(vm, args, valueDim, false)) {
1529             if (valueDim.IsNegative() || valueDim.Unit() == DimensionUnit::PERCENT) {
1530                 valueDim.Reset();
1531             }
1532             optionalDimension = valueDim;
1533         }
1534     }
1535 }
1536 
PushOuterBorderDimensionVector(const std::optional<CalcDimension> & valueDim,std::vector<ArkUI_Float32> & values,std::vector<ArkUI_Int32> & units)1537 void ArkTSUtils::PushOuterBorderDimensionVector(
1538     const std::optional<CalcDimension>& valueDim, std::vector<ArkUI_Float32>& values, std::vector<ArkUI_Int32>& units)
1539 {
1540     if (valueDim.has_value()) {
1541         values.emplace_back(static_cast<ArkUI_Float32>(valueDim.value().Value()));
1542         units.emplace_back(static_cast<ArkUI_Float32>(valueDim.value().Unit()));
1543     } else {
1544         values.emplace_back(0);
1545         units.emplace_back(0);
1546     }
1547 }
1548 
ParseJsSymbolFontFamilyName(const EcmaVM * vm,const Local<JSValueRef> & jsValue,std::string & customFamilyName)1549 void ArkTSUtils::ParseJsSymbolFontFamilyName(const EcmaVM *vm, const Local<JSValueRef> &jsValue,
1550     std::string& customFamilyName)
1551 {
1552     if (jsValue->IsNull() || jsValue->IsUndefined()) {
1553         return;
1554     }
1555     auto jsObj = jsValue->ToObject(vm);
1556     CompleteResourceObject(vm, jsObj);
1557     auto resId = jsObj->Get(vm, panda::StringRef::NewFromUtf8(vm, "id"));
1558     if (resId->IsNull() || !resId->IsNumber()) {
1559         return;
1560     }
1561     auto resourceObject = GetResourceObject(vm, jsValue);
1562     if (!resourceObject) {
1563         return;
1564     }
1565     std::string bundleName = resourceObject->GetBundleName();
1566     std::string moduleName = resourceObject->GetModuleName();
1567     customFamilyName = bundleName + "_" + moduleName + CUSTOM_SYMBOL_SUFFIX;
1568     std::replace(customFamilyName.begin(), customFamilyName.end(), '.', '_');
1569 }
1570 
ParseJsSymbolId(const EcmaVM * vm,const Local<JSValueRef> & jsValue,std::uint32_t & symbolId)1571 bool ArkTSUtils::ParseJsSymbolId(const EcmaVM *vm, const Local<JSValueRef> &jsValue, std::uint32_t& symbolId)
1572 {
1573     if (jsValue->IsNull() || jsValue->IsUndefined()) {
1574         symbolId = 0;
1575         return false;
1576     }
1577     auto jsObj = jsValue->ToObject(vm);
1578     CompleteResourceObject(vm, jsObj);
1579     auto resId = jsObj->Get(vm, panda::StringRef::NewFromUtf8(vm, "id"));
1580     if (resId->IsNull() || !resId->IsNumber()) {
1581         return false;
1582     }
1583     auto resourceObject = GetResourceObject(vm, jsValue);
1584     if (!resourceObject) {
1585         return false;
1586     }
1587     auto resourceWrapper = CreateResourceWrapper(vm, jsValue, resourceObject);
1588     if (!resourceWrapper) {
1589         return false;
1590     }
1591     auto strValue = resourceWrapper->GetString(resId->Uint32Value(vm));
1592     if (!strValue.empty()) {
1593         auto customSymbolId = static_cast<uint32_t>(strtol(strValue.c_str(), nullptr, 16));
1594         symbolId = customSymbolId;
1595         return true;
1596     }
1597     auto resIdNum = resId->Int32Value(vm);
1598     if (resIdNum == -1) {
1599         if (!IsGetResourceByName(vm, jsObj)) {
1600             return false;
1601         }
1602         auto args = jsObj->Get(vm, panda::StringRef::NewFromUtf8(vm, "params"));
1603         if (!args->IsArray(vm)) {
1604             return false;
1605         }
1606         Local<panda::ArrayRef> params = static_cast<Local<panda::ArrayRef>>(args);
1607         auto param = panda::ArrayRef::GetValueAt(vm, params, 0);
1608         auto symbol = resourceWrapper->GetSymbolByName(param->ToString(vm)->ToString(vm).c_str());
1609         if (!symbol) {
1610             return false;
1611         }
1612         symbolId = symbol;
1613         return true;
1614     }
1615 
1616     auto symbol = resourceWrapper->GetSymbolById(resId->Uint32Value(vm));
1617     if (!symbol) {
1618         return false;
1619     }
1620     symbolId = symbol;
1621     return true;
1622 }
1623 
ConvertBorderStyle(int32_t value)1624 BorderStyle ArkTSUtils::ConvertBorderStyle(int32_t value)
1625 {
1626     auto style = static_cast<BorderStyle>(value);
1627     if (style < BorderStyle::SOLID || style > BorderStyle::NONE) {
1628         style = BorderStyle::SOLID;
1629     }
1630     return style;
1631 }
1632 
PushOuterBorderDimensionVector(const std::optional<CalcDimension> & valueDim,std::vector<ArkUI_Float32> & options)1633 void ArkTSUtils::PushOuterBorderDimensionVector(const std::optional<CalcDimension>& valueDim,
1634     std::vector<ArkUI_Float32> &options)
1635 {
1636     options.push_back(static_cast<ArkUI_Float32>(valueDim.has_value()));
1637     if (valueDim.has_value()) {
1638         options.push_back(static_cast<ArkUI_Float32>(valueDim.value().Value()));
1639         options.push_back(static_cast<ArkUI_Float32>(valueDim.value().Unit()));
1640     } else {
1641         options.push_back(0);
1642         options.push_back(0);
1643     }
1644 }
1645 
ParseOuterBorderWidth(ArkUIRuntimeCallInfo * runtimeCallInfo,EcmaVM * vm,std::vector<ArkUI_Float32> & values)1646 void ArkTSUtils::ParseOuterBorderWidth(
1647     ArkUIRuntimeCallInfo *runtimeCallInfo, EcmaVM *vm, std::vector<ArkUI_Float32> &values)
1648 {
1649     Local<JSValueRef> leftArgs = runtimeCallInfo->GetCallArgRef(NUM_1);
1650     Local<JSValueRef> rightArgs = runtimeCallInfo->GetCallArgRef(NUM_2);
1651     Local<JSValueRef> topArgs = runtimeCallInfo->GetCallArgRef(NUM_3);
1652     Local<JSValueRef> bottomArgs = runtimeCallInfo->GetCallArgRef(NUM_4);
1653     std::optional<CalcDimension> leftDim;
1654     std::optional<CalcDimension> rightDim;
1655     std::optional<CalcDimension> topDim;
1656     std::optional<CalcDimension> bottomDim;
1657 
1658     ParseOuterBorder(vm, leftArgs, leftDim);
1659     ParseOuterBorder(vm, rightArgs, rightDim);
1660     ParseOuterBorder(vm, topArgs, topDim);
1661     ParseOuterBorder(vm, bottomArgs, bottomDim);
1662 
1663     PushOuterBorderDimensionVector(leftDim, values);
1664     PushOuterBorderDimensionVector(rightDim, values);
1665     PushOuterBorderDimensionVector(topDim, values);
1666     PushOuterBorderDimensionVector(bottomDim, values);
1667 }
1668 
PushOuterBorderColorVector(const std::optional<Color> & valueColor,std::vector<uint32_t> & options)1669 void ArkTSUtils::PushOuterBorderColorVector(const std::optional<Color>& valueColor, std::vector<uint32_t> &options)
1670 {
1671     options.push_back(static_cast<uint32_t>(valueColor.has_value()));
1672     if (valueColor.has_value()) {
1673         options.push_back(static_cast<uint32_t>(valueColor.value().GetValue()));
1674     } else {
1675         options.push_back(0);
1676     }
1677 }
1678 
ParseOuterBorderColor(ArkUIRuntimeCallInfo * runtimeCallInfo,EcmaVM * vm,std::vector<uint32_t> & values,int32_t argsIndex)1679 void ArkTSUtils::ParseOuterBorderColor(
1680     ArkUIRuntimeCallInfo* runtimeCallInfo, EcmaVM* vm, std::vector<uint32_t>& values, int32_t argsIndex)
1681 {
1682     Local<JSValueRef> leftArg = runtimeCallInfo->GetCallArgRef(argsIndex);
1683     Local<JSValueRef> rightArg = runtimeCallInfo->GetCallArgRef(argsIndex + NUM_1);
1684     Local<JSValueRef> topArg = runtimeCallInfo->GetCallArgRef(argsIndex + NUM_2);
1685     Local<JSValueRef> bottomArg = runtimeCallInfo->GetCallArgRef(argsIndex + NUM_3);
1686 
1687     std::optional<Color> leftColor;
1688     std::optional<Color> rightColor;
1689     std::optional<Color> topColor;
1690     std::optional<Color> bottomColor;
1691 
1692     Color left;
1693     if (!leftArg->IsUndefined() && ArkTSUtils::ParseJsColorAlpha(vm, leftArg, left)) {
1694         leftColor = left;
1695     }
1696     Color right;
1697     if (!rightArg->IsUndefined() && ArkTSUtils::ParseJsColorAlpha(vm, rightArg, right)) {
1698         rightColor = right;
1699     }
1700     Color top;
1701     if (!topArg->IsUndefined() && ArkTSUtils::ParseJsColorAlpha(vm, topArg, top)) {
1702         topColor = top;
1703     }
1704     Color bottom;
1705     if (!bottomArg->IsUndefined() && ArkTSUtils::ParseJsColorAlpha(vm, bottomArg, bottom)) {
1706         bottomColor = bottom;
1707     }
1708 
1709     PushOuterBorderColorVector(leftColor, values);
1710     PushOuterBorderColorVector(rightColor, values);
1711     PushOuterBorderColorVector(topColor, values);
1712     PushOuterBorderColorVector(bottomColor, values);
1713 }
1714 
ParseOuterBorderRadius(ArkUIRuntimeCallInfo * runtimeCallInfo,EcmaVM * vm,std::vector<ArkUI_Float32> & values,int32_t argsIndex)1715 void ArkTSUtils::ParseOuterBorderRadius(
1716     ArkUIRuntimeCallInfo* runtimeCallInfo, EcmaVM* vm, std::vector<ArkUI_Float32>& values, int32_t argsIndex)
1717 {
1718     Local<JSValueRef> topLeftArgs = runtimeCallInfo->GetCallArgRef(argsIndex);
1719     Local<JSValueRef> topRightArgs = runtimeCallInfo->GetCallArgRef(argsIndex + NUM_1);
1720     Local<JSValueRef> bottomLeftArgs = runtimeCallInfo->GetCallArgRef(argsIndex + NUM_2);
1721     Local<JSValueRef> bottomRightArgs = runtimeCallInfo->GetCallArgRef(argsIndex + NUM_3);
1722 
1723     std::optional<CalcDimension> topLeftOptional;
1724     std::optional<CalcDimension> topRightOptional;
1725     std::optional<CalcDimension> bottomLeftOptional;
1726     std::optional<CalcDimension> bottomRightOptional;
1727 
1728     ParseOuterBorder(vm, topLeftArgs, topLeftOptional);
1729     ParseOuterBorder(vm, topRightArgs, topRightOptional);
1730     ParseOuterBorder(vm, bottomLeftArgs, bottomLeftOptional);
1731     ParseOuterBorder(vm, bottomRightArgs, bottomRightOptional);
1732 
1733     PushOuterBorderDimensionVector(topLeftOptional, values);
1734     PushOuterBorderDimensionVector(topRightOptional, values);
1735     PushOuterBorderDimensionVector(bottomLeftOptional, values);
1736     PushOuterBorderDimensionVector(bottomRightOptional, values);
1737 }
1738 
ParseOuterBorderRadius(ArkUIRuntimeCallInfo * runtimeCallInfo,EcmaVM * vm,std::vector<ArkUI_Float32> & values,std::vector<ArkUI_Int32> & units,int32_t argsIndex)1739 void ArkTSUtils::ParseOuterBorderRadius(ArkUIRuntimeCallInfo* runtimeCallInfo,
1740     EcmaVM* vm, std::vector<ArkUI_Float32>& values, std::vector<ArkUI_Int32>& units, int32_t argsIndex)
1741 {
1742     Local<JSValueRef> topLeftArgs = runtimeCallInfo->GetCallArgRef(argsIndex);
1743     Local<JSValueRef> topRightArgs = runtimeCallInfo->GetCallArgRef(argsIndex + NUM_1);
1744     Local<JSValueRef> bottomLeftArgs = runtimeCallInfo->GetCallArgRef(argsIndex + NUM_2);
1745     Local<JSValueRef> bottomRightArgs = runtimeCallInfo->GetCallArgRef(argsIndex + NUM_3);
1746 
1747     std::optional<CalcDimension> topLeftOptional;
1748     std::optional<CalcDimension> topRightOptional;
1749     std::optional<CalcDimension> bottomLeftOptional;
1750     std::optional<CalcDimension> bottomRightOptional;
1751 
1752     ParseOuterBorder(vm, topLeftArgs, topLeftOptional);
1753     ParseOuterBorder(vm, topRightArgs, topRightOptional);
1754     ParseOuterBorder(vm, bottomLeftArgs, bottomLeftOptional);
1755     ParseOuterBorder(vm, bottomRightArgs, bottomRightOptional);
1756 
1757     PushOuterBorderDimensionVector(topLeftOptional, values, units);
1758     PushOuterBorderDimensionVector(topRightOptional, values, units);
1759     PushOuterBorderDimensionVector(bottomLeftOptional, values, units);
1760     PushOuterBorderDimensionVector(bottomRightOptional, values, units);
1761 }
1762 
PushOuterBorderStyleVector(const std::optional<BorderStyle> & value,std::vector<uint32_t> & options)1763 void ArkTSUtils::PushOuterBorderStyleVector(const std::optional<BorderStyle>& value, std::vector<uint32_t> &options)
1764 {
1765     options.push_back(static_cast<uint32_t>(value.has_value()));
1766     if (value.has_value()) {
1767         options.push_back(static_cast<uint32_t>(value.value()));
1768     } else {
1769         options.push_back(NUM_0);
1770     }
1771 }
1772 
ParseOuterBorderStyle(ArkUIRuntimeCallInfo * runtimeCallInfo,EcmaVM * vm,std::vector<uint32_t> & values,int32_t argsIndex)1773 void ArkTSUtils::ParseOuterBorderStyle(
1774     ArkUIRuntimeCallInfo* runtimeCallInfo, EcmaVM* vm, std::vector<uint32_t>& values, int32_t argsIndex)
1775 {
1776     std::optional<BorderStyle> styleLeft;
1777     std::optional<BorderStyle> styleRight;
1778     std::optional<BorderStyle> styleTop;
1779     std::optional<BorderStyle> styleBottom;
1780 
1781     auto topArg = runtimeCallInfo->GetCallArgRef(argsIndex);
1782     auto rightArg = runtimeCallInfo->GetCallArgRef(argsIndex + NUM_1);
1783     auto bottomArg = runtimeCallInfo->GetCallArgRef(argsIndex + NUM_2);
1784     auto leftArg = runtimeCallInfo->GetCallArgRef(argsIndex + NUM_3);
1785 
1786     if (!topArg->IsUndefined() && topArg->IsNumber()) {
1787         styleTop = ConvertBorderStyle(topArg->Int32Value(vm));
1788     }
1789     if (!rightArg->IsUndefined() && rightArg->IsNumber()) {
1790         styleRight = ConvertBorderStyle(rightArg->Int32Value(vm));
1791     }
1792     if (!bottomArg->IsUndefined() && bottomArg->IsNumber()) {
1793         styleBottom = ConvertBorderStyle(bottomArg->Int32Value(vm));
1794     }
1795     if (!leftArg->IsUndefined() && leftArg->IsNumber()) {
1796         styleLeft = ConvertBorderStyle(leftArg->Int32Value(vm));
1797     }
1798 
1799     PushOuterBorderStyleVector(styleLeft, values);
1800     PushOuterBorderStyleVector(styleRight, values);
1801     PushOuterBorderStyleVector(styleTop, values);
1802     PushOuterBorderStyleVector(styleBottom, values);
1803 }
1804 
SetBorderWidthArray(const EcmaVM * vm,const Local<JSValueRef> & args,ArkUI_Float32 values[],int units[],int index)1805 void ArkTSUtils::SetBorderWidthArray(const EcmaVM* vm, const Local<JSValueRef>& args, ArkUI_Float32 values[],
1806     int units[], int index)
1807 {
1808     CalcDimension borderDimension;
1809     if (!args->IsUndefined()) {
1810         if (ArkTSUtils::ParseAllBorder(vm, args, borderDimension)) {
1811             values[index] = borderDimension.Value();
1812             units[index] = static_cast<int>(borderDimension.Unit());
1813         } else {
1814             values[index] = 0;
1815             units[index] = static_cast<int>(DimensionUnit::VP);
1816         }
1817     } else {
1818         values[index] = -1;
1819         units[index] = static_cast<int>(DimensionUnit::INVALID);
1820     }
1821 }
1822 
ParseJsToArkUISize(const EcmaVM * vm,const Local<JSValueRef> & arg)1823 ArkUISizeType ArkTSUtils::ParseJsToArkUISize(const EcmaVM *vm, const Local<JSValueRef> &arg)
1824 {
1825     ArkUISizeType size = { 0.0, static_cast<int8_t>(DimensionUnit::VP), nullptr };
1826     CalcDimension dimen(0, DimensionUnit::VP);
1827     if (ArkTSUtils::ParseJsDimensionVp(vm, arg, dimen)) {
1828         size.unit = static_cast<int8_t>(dimen.Unit());
1829         if (dimen.CalcValue() != "") {
1830             size.string = dimen.CalcValue().c_str();
1831         } else {
1832             size.value = dimen.Value();
1833         }
1834     }
1835     return size;
1836 }
1837 
CheckKeysPressed(const EcmaVM * vm,const std::vector<KeyCode> & pressedKeyCodes,std::vector<std::string> & checkKeyCodes)1838 bool ArkTSUtils::CheckKeysPressed(
1839     const EcmaVM* vm, const std::vector<KeyCode>& pressedKeyCodes, std::vector<std::string>& checkKeyCodes)
1840 {
1841     auto hasKeyCode = [pressedKeyCodes](const KeyCode& keyCode) -> bool {
1842         auto it = std::find(pressedKeyCodes.begin(), pressedKeyCodes.end(), keyCode);
1843         return it != pressedKeyCodes.end();
1844     };
1845     for (auto& checkKeyCode : checkKeyCodes) {
1846         if (checkKeyCode == "ctrl") {
1847             if (!hasKeyCode(KeyCode::KEY_CTRL_LEFT) && !hasKeyCode(KeyCode::KEY_CTRL_RIGHT)) {
1848                 return false;
1849             }
1850         } else if (checkKeyCode == "shift") {
1851             if (!hasKeyCode(KeyCode::KEY_SHIFT_LEFT) && !hasKeyCode(KeyCode::KEY_SHIFT_RIGHT)) {
1852                 return false;
1853             }
1854         } else if (checkKeyCode == "alt") {
1855             if (!hasKeyCode(KeyCode::KEY_ALT_LEFT) && !hasKeyCode(KeyCode::KEY_ALT_RIGHT)) {
1856                 return false;
1857             }
1858         } else if (checkKeyCode == "fn") {
1859             if (!hasKeyCode(KeyCode::KEY_FN)) {
1860                 return false;
1861             }
1862         } else {
1863             ThrowError(vm, "indicate the keys are illegal", ERROR_CODE_PARAM_INVALID);
1864             return false;
1865         }
1866     }
1867     return true;
1868 }
1869 
ThrowError(const EcmaVM * vm,const std::string & msg,int32_t code)1870 void ArkTSUtils::ThrowError(const EcmaVM* vm, const std::string& msg, int32_t code)
1871 {
1872     auto errorVal = panda::Exception::Error(vm, panda::StringRef::NewFromUtf8(vm, msg.c_str()));
1873     auto codeVal = panda::Exception::Error(vm, panda::StringRef::NewFromUtf8(vm, std::to_string(code).c_str()));
1874     Local<panda::StringRef> codeKey = panda::StringRef::NewFromUtf8(vm, "code");
1875     Local<panda::ObjectRef> errorObj(errorVal);
1876     errorObj->Set(vm, codeKey, codeVal);
1877     panda::JSNApi::ThrowException(vm, errorObj);
1878 }
1879 
GetModifierKeyState(ArkUIRuntimeCallInfo * info,const std::vector<KeyCode> & pressedKeyCodes)1880 Local<JSValueRef> ArkTSUtils::GetModifierKeyState(
1881     ArkUIRuntimeCallInfo* info, const std::vector<KeyCode>& pressedKeyCodes)
1882 {
1883     auto vm = info->GetVM();
1884     auto param = info->GetCallArgRef(0);
1885     if (!param->IsArray(vm)) {
1886         ThrowError(vm, "indicate the keys are illegal", ERROR_CODE_PARAM_INVALID);
1887         return JSValueRef::Undefined(vm);
1888     }
1889     std::vector<std::string> checkKeyCodes;
1890     std::vector<std::string> validKeyCodes = { "ctrl", "shift", "alt", "fn" };
1891     auto paramArray = panda::Local<panda::ArrayRef>(param);
1892     auto length = paramArray->Length(vm);
1893     for (size_t i = 0; i < length; i++) {
1894         auto value = panda::ArrayRef::GetValueAt(vm, paramArray, i);
1895         auto code = value->ToString(vm)->ToString(vm);
1896         std::transform(code.begin(), code.end(), code.begin(), [](char& c) { return std::tolower(c); });
1897         auto it = std::find(validKeyCodes.begin(), validKeyCodes.end(), code.c_str());
1898         if (it == validKeyCodes.end()) {
1899             ThrowError(vm, "indicate the keys are illegal", ERROR_CODE_PARAM_INVALID);
1900             return JSValueRef::Undefined(info->GetVM());
1901         } else {
1902             checkKeyCodes.emplace_back(code);
1903         }
1904     }
1905     if (checkKeyCodes.empty()) {
1906         ThrowError(vm, "indicate the keys are illegal", ERROR_CODE_PARAM_INVALID);
1907         return JSValueRef::Undefined(vm);
1908     }
1909     if (ArkTSUtils::CheckKeysPressed(vm, pressedKeyCodes, checkKeyCodes)) {
1910         return panda::BooleanRef::New(vm, true);
1911     } else {
1912         return panda::BooleanRef::New(vm, false);
1913     }
1914 }
1915 
JsGetModifierKeyState(ArkUIRuntimeCallInfo * info)1916 Local<JSValueRef> ArkTSUtils::JsGetModifierKeyState(ArkUIRuntimeCallInfo* info)
1917 {
1918     Local<JSValueRef> thisObj = info->GetThisRef();
1919     auto eventInfo = static_cast<BaseEventInfo*>(panda::Local<panda::ObjectRef>(thisObj)->GetNativePointerField(
1920         info->GetVM(), 0));
1921     if (!eventInfo) {
1922         return JSValueRef::Undefined(info->GetVM());
1923     }
1924     auto pressedKeyCodes = eventInfo->GetPressedKeyCodes();
1925     return ArkTSUtils::GetModifierKeyState(info, pressedKeyCodes);
1926 }
1927 
JsGetHorizontalAxisValue(ArkUIRuntimeCallInfo * info)1928 Local<JSValueRef> ArkTSUtils::JsGetHorizontalAxisValue(ArkUIRuntimeCallInfo* info)
1929 {
1930     Local<JSValueRef> thisObj = info->GetThisRef();
1931     auto eventInfo =
1932         static_cast<AxisInfo*>(panda::Local<panda::ObjectRef>(thisObj)->GetNativePointerField(info->GetVM(), 0));
1933     if (!eventInfo) {
1934         return JSValueRef::Undefined(info->GetVM());
1935     }
1936     return panda::NumberRef::New(info->GetVM(), eventInfo->GetHorizontalAxis());
1937 }
1938 
JsGetVerticalAxisValue(ArkUIRuntimeCallInfo * info)1939 Local<JSValueRef> ArkTSUtils::JsGetVerticalAxisValue(ArkUIRuntimeCallInfo* info)
1940 {
1941     Local<JSValueRef> thisObj = info->GetThisRef();
1942     auto eventInfo =
1943         static_cast<AxisInfo*>(panda::Local<panda::ObjectRef>(thisObj)->GetNativePointerField(info->GetVM(), 0));
1944     if (!eventInfo) {
1945         return JSValueRef::Undefined(info->GetVM());
1946     }
1947     return panda::NumberRef::New(info->GetVM(), eventInfo->GetVerticalAxis());
1948 }
1949 
IsDrawable(const EcmaVM * vm,const Local<JSValueRef> & jsValue)1950 bool ArkTSUtils::IsDrawable(const EcmaVM* vm, const Local<JSValueRef>& jsValue)
1951 {
1952     if (!jsValue->IsObject(vm)) {
1953         return false;
1954     }
1955     auto jsObj = jsValue->ToObject(vm);
1956     if (jsObj->IsUndefined()) {
1957         return false;
1958     }
1959 
1960     // if jsObject has function getPixelMap, it's a DrawableDescriptor object
1961     auto func = jsObj->Get(vm, panda::StringRef::NewFromUtf8(vm, "getPixelMap"));
1962     return (!func->IsNull() && func->IsFunction(vm));
1963 }
1964 
GetDrawablePixmap(const EcmaVM * vm,Local<JSValueRef> obj)1965 RefPtr<PixelMap> ArkTSUtils::GetDrawablePixmap(const EcmaVM* vm, Local<JSValueRef> obj)
1966 {
1967     return PixelMap::GetFromDrawable(UnwrapNapiValue(vm, obj));
1968 }
1969 
CreateRSBrightnessBlenderFromNapiValue(const EcmaVM * vm,Local<JSValueRef> obj)1970 Rosen::BrightnessBlender* ArkTSUtils::CreateRSBrightnessBlenderFromNapiValue(const EcmaVM* vm, Local<JSValueRef> obj)
1971 {
1972     auto blenderPtr = static_cast<Rosen::BrightnessBlender*>(UnwrapNapiValue(vm, obj));
1973     return blenderPtr;
1974 }
1975 
UnwrapNapiValue(const EcmaVM * vm,const Local<JSValueRef> & obj)1976 void* ArkTSUtils::UnwrapNapiValue(const EcmaVM* vm, const Local<JSValueRef>& obj)
1977 {
1978     if (!obj->IsObject(vm)) {
1979         LOGE("info is not an object when try CreateFromNapiValue");
1980         return nullptr;
1981     }
1982     auto engine = EngineHelper::GetCurrentEngine();
1983     CHECK_NULL_RETURN(engine, nullptr);
1984     auto nativeEngine = engine->GetNativeEngine();
1985     CHECK_NULL_RETURN(nativeEngine, nullptr);
1986     JSValueWrapper valueWrapper = obj;
1987 
1988     Framework::ScopeRAII scope(reinterpret_cast<napi_env>(nativeEngine));
1989     napi_value napiValue = nativeEngine->ValueToNapiValue(valueWrapper);
1990     auto env = reinterpret_cast<napi_env>(nativeEngine);
1991     napi_valuetype valueType = napi_undefined;
1992     napi_typeof(env, napiValue, &valueType);
1993     if (valueType != napi_object) {
1994         LOGE("napiValue is not napi_object");
1995         return nullptr;
1996     }
1997     void* objectNapi = nullptr;
1998     napi_unwrap(env, napiValue, &objectNapi);
1999     return objectNapi;
2000 }
2001 
2002 #if !defined(PREVIEW)
CreatePixelMapFromNapiValue(const EcmaVM * vm,Local<JSValueRef> obj)2003 RefPtr<PixelMap> ArkTSUtils::CreatePixelMapFromNapiValue(const EcmaVM* vm, Local<JSValueRef> obj)
2004 {
2005     if (!obj->IsObject(vm)) {
2006         return nullptr;
2007     }
2008     auto engine = EngineHelper::GetCurrentEngine();
2009     if (!engine) {
2010         return nullptr;
2011     }
2012     auto* nativeEngine = engine->GetNativeEngine();
2013     if (nativeEngine == nullptr) {
2014         return nullptr;
2015     }
2016     JSValueWrapper valueWrapper = obj;
2017 
2018     Framework::ScopeRAII scope(reinterpret_cast<napi_env>(nativeEngine));
2019     napi_value napiValue = nativeEngine->ValueToNapiValue(valueWrapper);
2020 
2021     Framework::PixelMapNapiEntry pixelMapNapiEntry = Framework::JsEngine::GetPixelMapNapiEntry();
2022     if (!pixelMapNapiEntry) {
2023         return nullptr;
2024     }
2025 
2026     void* pixmapPtrAddr = pixelMapNapiEntry(reinterpret_cast<napi_env>(nativeEngine), napiValue);
2027     if (pixmapPtrAddr == nullptr) {
2028         return nullptr;
2029     }
2030     return PixelMap::CreatePixelMap(pixmapPtrAddr);
2031 }
2032 #endif
2033 
ParseSelectionMenuOptions(ArkUIRuntimeCallInfo * info,const EcmaVM * vm,NG::OnCreateMenuCallback & onCreateMenuCallback,NG::OnMenuItemClickCallback & onMenuItemClickCallback)2034 bool ArkTSUtils::ParseSelectionMenuOptions(ArkUIRuntimeCallInfo* info, const EcmaVM* vm,
2035     NG::OnCreateMenuCallback& onCreateMenuCallback, NG::OnMenuItemClickCallback& onMenuItemClickCallback)
2036 {
2037     Local<JSValueRef> firstArg = info->GetCallArgRef(NUM_0);
2038     Local<JSValueRef> secondArg = info->GetCallArgRef(NUM_1);
2039     if (!secondArg->IsObject(vm) || secondArg->IsUndefined()) {
2040         return false;
2041     }
2042     auto* nativeNode = nodePtr(firstArg->ToNativePointer(vm)->Value());
2043     auto* frameNode = reinterpret_cast<FrameNode*>(nativeNode);
2044     CHECK_NULL_RETURN(frameNode, false);
2045     auto menuOptionsObject = secondArg->ToObject(vm);
2046     auto jsValueOnCreateMenu = menuOptionsObject->Get(vm, panda::StringRef::NewFromUtf8(vm, "onCreateMenu"));
2047     ParseOnCreateMenu(vm, frameNode, jsValueOnCreateMenu, onCreateMenuCallback);
2048     auto jsValueOnMenuItemClick = menuOptionsObject->Get(vm, panda::StringRef::NewFromUtf8(vm, "onMenuItemClick"));
2049     ParseOnMenuItemClick(vm, frameNode, jsValueOnMenuItemClick, onMenuItemClickCallback);
2050     return true;
2051 }
2052 
CreateJsSystemMenuItems(const EcmaVM * vm,const std::vector<NG::MenuItemParam> & systemMenuItems)2053 Local<panda::ArrayRef> ArkTSUtils::CreateJsSystemMenuItems(
2054     const EcmaVM* vm, const std::vector<NG::MenuItemParam>& systemMenuItems)
2055 {
2056     Local<panda::ArrayRef> systemMenuItemsArray = panda::ArrayRef::New(vm);
2057     uint32_t idx = 0;
2058     for (const auto& item : systemMenuItems) {
2059         systemMenuItemsArray->SetValueAt(vm, systemMenuItemsArray, idx++, CreateJsTextMenuItem(vm, item));
2060     }
2061     return systemMenuItemsArray;
2062 }
2063 
CreateJsTextMenuItem(const EcmaVM * vm,const NG::MenuItemParam & menuItemParam)2064 Local<panda::ObjectRef> ArkTSUtils::CreateJsTextMenuItem(const EcmaVM* vm, const NG::MenuItemParam& menuItemParam)
2065 {
2066     Local<panda::ObjectRef> obj = CreateJsTextMenuId(vm, menuItemParam.menuOptionsParam.id);
2067     const char* keys[] = { "content", "id" };
2068     Local<JSValueRef> values[] = {
2069         panda::StringRef::NewFromUtf8(vm, menuItemParam.menuOptionsParam.content.value_or("").c_str()), obj
2070     };
2071     return panda::ObjectRef::NewWithNamedProperties(vm, ArraySize(keys), keys, values);
2072 }
2073 
CreateJsTextMenuId(const EcmaVM * vm,const std::string & id)2074 Local<panda::ObjectRef> ArkTSUtils::CreateJsTextMenuId(const EcmaVM* vm, const std::string& id)
2075 {
2076     Local<panda::ObjectRef> empty = panda::ObjectRef::New(vm);
2077     auto engine = EngineHelper::GetCurrentEngine();
2078     CHECK_NULL_RETURN(engine, empty);
2079     NativeEngine* nativeEngine = engine->GetNativeEngine();
2080     CHECK_NULL_RETURN(nativeEngine, empty);
2081     auto env = reinterpret_cast<napi_env>(nativeEngine);
2082 
2083     napi_value global = nullptr;
2084     napi_status ret = napi_get_global(env, &global);
2085     if (ret != napi_ok) {
2086         return empty;
2087     }
2088     napi_value constructor = nullptr;
2089     ret = napi_get_named_property(env, global, JS_TEXT_MENU_ID_CLASS_NAME, &constructor);
2090     if (ret != napi_ok) {
2091         return empty;
2092     }
2093 
2094     napi_value obj = nullptr;
2095     napi_value menuId = nullptr;
2096 
2097     ret = napi_create_string_utf8(env, id.c_str(), id.length(), &menuId);
2098     if (ret != napi_ok) {
2099         return empty;
2100     }
2101     ret = napi_new_instance(env, constructor, NUM_1, &menuId, &obj);
2102     if (ret != napi_ok) {
2103         return empty;
2104     }
2105 
2106     auto value = Framework::JsConverter::ConvertNapiValueToJsVal(obj);
2107     if (!value->IsObject()) {
2108         return empty;
2109     }
2110 
2111     return value->GetLocalHandle();
2112 }
2113 
ParseOnCreateMenu(const EcmaVM * vm,FrameNode * frameNode,const Local<JSValueRef> & jsValueOnCreateMenu,NG::OnCreateMenuCallback & onCreateMenuCallback)2114 void ArkTSUtils::ParseOnCreateMenu(const EcmaVM* vm, FrameNode* frameNode, const Local<JSValueRef>& jsValueOnCreateMenu,
2115     NG::OnCreateMenuCallback& onCreateMenuCallback)
2116 {
2117     if (jsValueOnCreateMenu.IsEmpty() || !jsValueOnCreateMenu->IsFunction(vm)) {
2118         return;
2119     }
2120     panda::Local<panda::FunctionRef> func = jsValueOnCreateMenu->ToObject(vm);
2121     auto containerId = Container::CurrentId();
2122     auto jsCallback = [vm, node = AceType::WeakClaim(frameNode), func = panda::CopyableGlobal(vm, func), containerId](
2123                           const std::vector<NG::MenuItemParam>& systemMenuItems) -> std::vector<NG::MenuOptionsParam> {
2124         ContainerScope scope(containerId);
2125         panda::LocalScope pandaScope(vm);
2126         panda::TryCatch trycatch(vm);
2127         PipelineContext::SetCallBackNode(node);
2128         std::vector<NG::MenuOptionsParam> menuParams;
2129         auto textMenuItemArrayObj = CreateJsSystemMenuItems(vm, systemMenuItems);
2130         panda::Local<panda::JSValueRef> params[PARAM_ARR_LENGTH_1] = { textMenuItemArrayObj };
2131         auto menuItems = func->Call(vm, func.ToLocal(), params, PARAM_ARR_LENGTH_1);
2132         if (!menuItems->IsArray(vm)) {
2133             return menuParams;
2134         }
2135         WrapMenuParams(vm, menuParams, menuItems);
2136         return menuParams;
2137     };
2138     onCreateMenuCallback = jsCallback;
2139 }
2140 
WrapMenuParams(const EcmaVM * vm,std::vector<NG::MenuOptionsParam> & menuParams,const Local<JSValueRef> & menuItems)2141 void ArkTSUtils::WrapMenuParams(
2142     const EcmaVM* vm, std::vector<NG::MenuOptionsParam>& menuParams, const Local<JSValueRef>& menuItems)
2143 {
2144     auto menuItemsArray = Local<panda::ArrayRef>(menuItems);
2145     auto length = menuItemsArray->Length(vm);
2146     for (uint32_t index = 0; index < length; index++) {
2147         Local<JSValueRef> menuItem = panda::ArrayRef::GetValueAt(vm, menuItemsArray, index);
2148         if (!menuItem->IsObject(vm)) {
2149             continue;
2150         }
2151         auto menuItemObject = menuItem->ToObject(vm);
2152         NG::MenuOptionsParam menuOptionsParam;
2153         auto jsContent = menuItemObject->Get(vm, panda::StringRef::NewFromUtf8(vm, "content"));
2154         std::string content;
2155         ParseJsString(vm, jsContent, content);
2156         menuOptionsParam.content = content;
2157         auto jsStartIcon = menuItemObject->Get(vm, panda::StringRef::NewFromUtf8(vm, "icon"));
2158         std::string icon;
2159         ParseJsMedia(vm, jsStartIcon, icon);
2160         menuOptionsParam.icon = icon;
2161         auto jsTextMenuId = menuItemObject->Get(vm, panda::StringRef::NewFromUtf8(vm, "id"));
2162         std::string id;
2163         if (jsTextMenuId->IsObject(vm)) {
2164             auto textMenuIdObject = jsTextMenuId->ToObject(vm);
2165             auto jsId = textMenuIdObject->Get(vm, panda::StringRef::NewFromUtf8(vm, "id_"));
2166             ParseJsString(vm, jsId, id);
2167         }
2168         menuOptionsParam.id = id;
2169         menuParams.emplace_back(menuOptionsParam);
2170     }
2171 }
2172 
ParseOnMenuItemClick(const EcmaVM * vm,FrameNode * frameNode,const Local<JSValueRef> & jsValueOnMenuItemClick,NG::OnMenuItemClickCallback & onMenuItemClickCallback)2173 void ArkTSUtils::ParseOnMenuItemClick(const EcmaVM* vm, FrameNode* frameNode,
2174     const Local<JSValueRef>& jsValueOnMenuItemClick, NG::OnMenuItemClickCallback& onMenuItemClickCallback)
2175 {
2176     if (jsValueOnMenuItemClick.IsEmpty() || !jsValueOnMenuItemClick->IsFunction(vm)) {
2177         return;
2178     }
2179     panda::Local<panda::FunctionRef> func = jsValueOnMenuItemClick->ToObject(vm);
2180     auto containerId = Container::CurrentId();
2181     auto jsCallback = [vm, node = AceType::WeakClaim(frameNode), func = panda::CopyableGlobal(vm, func), containerId](
2182                           const NG::MenuItemParam& menuOptionsParam) -> bool {
2183         ContainerScope scope(containerId);
2184         panda::LocalScope pandaScope(vm);
2185         panda::TryCatch trycatch(vm);
2186         PipelineContext::SetCallBackNode(node);
2187         auto paramArrayObj = CreateJsOnMenuItemClick(vm, menuOptionsParam);
2188         if (paramArrayObj->Length(vm) != PARAM_ARR_LENGTH_2) {
2189             return false;
2190         }
2191         panda::Local<panda::JSValueRef> params[PARAM_ARR_LENGTH_2] = {
2192             panda::ArrayRef::GetValueAt(vm, paramArrayObj, 0), panda::ArrayRef::GetValueAt(vm, paramArrayObj, 1)
2193         };
2194         auto ret = func->Call(vm, func.ToLocal(), params, PARAM_ARR_LENGTH_2);
2195         if (ret->IsBoolean()) {
2196             return ret->ToBoolean(vm)->Value();
2197         }
2198         return false;
2199     };
2200     onMenuItemClickCallback = jsCallback;
2201 }
2202 
CreateJsOnMenuItemClick(const EcmaVM * vm,const NG::MenuItemParam & menuItemParam)2203 Local<panda::ArrayRef> ArkTSUtils::CreateJsOnMenuItemClick(const EcmaVM* vm, const NG::MenuItemParam& menuItemParam)
2204 {
2205     Local<panda::ArrayRef> paramsArray = panda::ArrayRef::New(vm);
2206     paramsArray->SetValueAt(vm, paramsArray, 0, CreateJsTextMenuItem(vm, menuItemParam));
2207     paramsArray->SetValueAt(vm, paramsArray, 1, CreateJsTextRange(vm, menuItemParam));
2208     return paramsArray;
2209 }
2210 
CreateJsTextRange(const EcmaVM * vm,const NG::MenuItemParam & menuItemParam)2211 Local<panda::ObjectRef> ArkTSUtils::CreateJsTextRange(const EcmaVM* vm, const NG::MenuItemParam& menuItemParam)
2212 {
2213     const char* keys[] = { "start", "end" };
2214     Local<JSValueRef> values[] = { panda::NumberRef::New(vm, menuItemParam.start),
2215         panda::NumberRef::New(vm, menuItemParam.end) };
2216     return panda::ObjectRef::NewWithNamedProperties(vm, ArraySize(keys), keys, values);
2217 }
2218 
ChoosePointToJSValue(const EcmaVM * vm,std::vector<int> input)2219 Local<panda::ArrayRef> ArkTSUtils::ChoosePointToJSValue(const EcmaVM* vm, std::vector<int> input)
2220 {
2221     Local<panda::ArrayRef> arr = panda::ArrayRef::New(vm);
2222     for (size_t i = 0; i < input.size(); i++) {
2223         arr->SetValueAt(vm, arr, i, ToJSValueWithVM(vm, input[i]));
2224     }
2225     return arr;
2226 }
2227 } // namespace OHOS::Ace::NG
2228