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