• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 /**
2  * Copyright (c) 2025 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 "stdlib_ani_helpers.h"
17 #include "libpandabase/utils/logger.h"
18 
19 namespace ark::ets::stdlib {
20 
StdlibLogFatal(const char * msg)21 void StdlibLogFatal(const char *msg)
22 {
23     LOG(FATAL, STDLIB) << msg;
24     UNREACHABLE();
25 }
26 
StdlibLogFatal(const char * msg,ani_status status)27 void StdlibLogFatal(const char *msg, ani_status status)
28 {
29     LOG(FATAL, STDLIB) << (std::string(msg) + " status = " + StatusToString(status) + "(" + std::to_string(status) +
30                            ")");
31     UNREACHABLE();
32 }
33 
ThrowNewError(ani_env * env,ani_class errorClass,std::string_view msg,const char * ctorSignature)34 ANI_EXPORT void ThrowNewError(ani_env *env, ani_class errorClass, std::string_view msg, const char *ctorSignature)
35 {
36     ASSERT(env != nullptr);
37 
38     ani_method ctor;
39     ANI_FATAL_IF_ERROR(env->Class_FindMethod(errorClass, "<ctor>", ctorSignature, &ctor));
40 
41     ani_string message = CreateUtf8String(env, msg.data(), msg.size());
42     if (message == nullptr) {
43         // Exception occured in CreateUtf8String.
44         return;
45     }
46 
47     ani_object errorObject;
48     // NOLINTNEXTLINE(cppcoreguidelines-pro-type-vararg)
49     ANI_FATAL_IF_ERROR(env->Object_New(errorClass, ctor, &errorObject, message));
50 
51     ANI_FATAL_IF_ERROR(env->ThrowError(reinterpret_cast<ani_error>(errorObject)));
52 }
53 
ThrowNewError(ani_env * env,std::string_view classDescriptor,std::string_view msg,const char * ctorSignature)54 ANI_EXPORT void ThrowNewError(ani_env *env, std::string_view classDescriptor, std::string_view msg,
55                               const char *ctorSignature)
56 {
57     ASSERT(env != nullptr);
58 
59     ani_class errCls;
60     ANI_FATAL_IF_ERROR(env->FindClass(classDescriptor.data(), &errCls));
61     ThrowNewError(env, errCls, msg, ctorSignature);
62 }
63 
ConvertFromAniString(ani_env * env,ani_string aniStr)64 ANI_EXPORT std::string ConvertFromAniString(ani_env *env, ani_string aniStr)
65 {
66     ani_size strSz;
67     ANI_FATAL_IF_ERROR(env->String_GetUTF8Size(aniStr, &strSz));
68 
69     std::string buffer;
70     buffer.resize(strSz + 1U);
71 
72     ani_size nmbCopiedBytes;
73     ANI_FATAL_IF_ERROR(env->String_GetUTF8SubString(aniStr, 0U, strSz, buffer.data(), buffer.size(), &nmbCopiedBytes));
74     ANI_FATAL_IF(nmbCopiedBytes != strSz);
75 
76     buffer.resize(strSz);
77     return buffer;
78 }
79 
StatusToString(ani_status status)80 ANI_EXPORT std::string StatusToString(ani_status status)
81 {
82     constexpr size_t STATUS_NUM = static_cast<size_t>(ANI_INVALID_VERSION) + 1U;
83 
84     static std::array<std::string, STATUS_NUM> statusToStringTable {
85         "ANI_OK",
86         "ANI_ERROR",
87         "ANI_INVALID_ARGS",
88         "ANI_INVALID_TYPE",
89         "ANI_INVALID_DESCRIPTOR",
90         "ANI_INCORRECT_REF",
91         "ANI_PENDING_ERROR",
92         "ANI_NOT_FOUND",
93         "ANI_ALREADY_BINDED",
94         "ANI_OUT_OF_REF",
95         "ANI_OUT_OF_MEMORY",
96         "ANI_OUT_OF_RANGE",
97         "ANI_BUFFER_TO_SMALL",
98         "ANI_INVALID_VERSION",
99     };
100 
101     auto idx = static_cast<size_t>(status);
102     if (idx >= STATUS_NUM) {
103         StdlibLogFatal("Invalid status");
104         UNREACHABLE();
105     }
106     return statusToStringTable[idx];
107 }
108 
CreateUtf8String(ani_env * env,const char * data,ani_size size)109 ANI_EXPORT ani_string CreateUtf8String(ani_env *env, const char *data, ani_size size)
110 {
111     ani_string result;
112 
113     auto status = env->String_NewUTF8(data, size, &result);
114     if (status != ANI_OK) {
115         ani_boolean unhandledExc;
116         ANI_FATAL_IF_ERROR(env->ExistUnhandledError(&unhandledExc));
117         if (unhandledExc == ANI_TRUE) {
118             return nullptr;
119         }
120         UNREACHABLE();
121     }
122     return result;
123 }
124 
CreateUtf16String(ani_env * env,const uint16_t * data,ani_size size)125 ANI_EXPORT ani_string CreateUtf16String(ani_env *env, const uint16_t *data, ani_size size)
126 {
127     ani_string result;
128 
129     auto status = env->String_NewUTF16(data, size, &result);
130     if (status != ANI_OK) {
131         ani_boolean unhandledExc;
132         ANI_FATAL_IF_ERROR(env->ExistUnhandledError(&unhandledExc));
133         if (unhandledExc == ANI_TRUE) {
134             return nullptr;
135         }
136         UNREACHABLE();
137     }
138     return result;
139 }
140 
GetFieldStrUndefined(ani_env * env,ani_object obj,const char * name)141 ANI_EXPORT std::string GetFieldStrUndefined(ani_env *env, ani_object obj, const char *name)
142 {
143     ani_ref ref = nullptr;
144     ANI_FATAL_IF_ERROR(env->Object_GetFieldByName_Ref(obj, name, &ref));
145     ani_boolean isUndefined = ANI_FALSE;
146     ANI_FATAL_IF_ERROR(env->Reference_IsUndefined(ref, &isUndefined));
147     if (isUndefined == ANI_TRUE) {
148         return std::string();
149     }
150     auto aniStr = static_cast<ani_string>(ref);
151     ASSERT(aniStr != nullptr);
152     return ConvertFromAniString(env, aniStr);
153 }
154 
GetFieldStr(ani_env * env,ani_object obj,const char * name)155 ANI_EXPORT std::string GetFieldStr(ani_env *env, ani_object obj, const char *name)
156 {
157     ani_ref ref = nullptr;
158     ANI_FATAL_IF_ERROR(env->Object_GetFieldByName_Ref(obj, name, &ref));
159     auto aniStr = static_cast<ani_string>(ref);
160     ASSERT(aniStr != nullptr);
161     return ConvertFromAniString(env, aniStr);
162 }
163 
164 }  // namespace ark::ets::stdlib
165