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