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