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