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