• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 /**
2  * Copyright (c) 2021-2024 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 "plugins/ets/runtime/napi/ets_napi_native_interface.h"
17 
18 #include "libpandabase/macros.h"
19 #include "libpandafile/shorty_iterator.h"
20 #include "libpandabase/utils/logger.h"
21 #include "libpandabase/utils/bit_utils.h"
22 #include "libpandabase/utils/string_helpers.h"
23 #include "runtime/include/mem/panda_containers.h"
24 #include "runtime/include/value.h"
25 
26 #include "plugins/ets/runtime/types/ets_primitives.h"
27 #include "plugins/ets/runtime/napi/ets_napi_macros.h"
28 #include "plugins/ets/runtime/napi/ets_scoped_objects_fix.h"
29 #include "plugins/ets/runtime/types/ets_method.h"
30 #include "plugins/ets/runtime/types/ets_value.h"
31 #include "plugins/ets/runtime/ets_class_linker_extension.h"
32 #include "plugins/ets/runtime/ets_exceptions.h"
33 #include "plugins/ets/runtime/types/ets_string.h"
34 #include "plugins/ets/runtime/types/ets_promise.h"
35 #include "plugins/ets/runtime/napi/ets_napi_helpers.h"
36 
37 // NOLINTBEGIN(cppcoreguidelines-pro-type-vararg)
38 
39 #define ETS_NAPI_DEBUG_TRACE(env)
40 // NOLINTBEGIN(cppcoreguidelines-macro-usage)
41 #define CHECK_ENV(env)                                                                                    \
42     do {                                                                                                  \
43         ets_env *e = env;                                                                                 \
44         ETS_NAPI_RETURN_IF_EQ(::ark::ets::PandaEtsNapiEnv::ToPandaEtsEnv(e)->HasPendingException(), true, \
45                               ETS_PENDING_EXCEPTION);                                                     \
46         ETS_NAPI_RETURN_IF_EQ(e, nullptr, ETS_INVALID_ARG);                                               \
47     } while (false)
48 
49 #define CHECK_ARG(env, arg) ETS_NAPI_RETURN_IF_EQ(arg, nullptr, ETS_INVALID_ARG)
50 // NOLINTEND(cppcoreguidelines-macro-usage)
51 
52 namespace ark::ets::napi {
53 template <typename T>
54 using ArgVector = PandaSmallVector<T>;
55 
56 using TypeId = panda_file::Type::TypeId;
57 
58 // ETS NAPI allocator
EtsAlloc(size_t n)59 void *EtsAlloc(size_t n)
60 {
61     size_t sz = (n + 7) >> 3;  // NOLINT(hicpp-signed-bitwise)
62     return new uint64_t[sz];
63 }
64 
EtsFree(void * obj)65 void EtsFree(void *obj)
66 {
67     delete[] reinterpret_cast<uint64_t *>(obj);
68 }
69 
70 template <typename T>
EtsFree(const T * obj)71 void EtsFree(const T *obj)
72 {
73     EtsFree(reinterpret_cast<void *>(const_cast<T *>(obj)));
74 }
75 
ConstructValueFromFloatingPoint(float val)76 static Value ConstructValueFromFloatingPoint(float val)
77 {
78     return Value(bit_cast<int32_t>(val));
79 }
80 
ConstructValueFromFloatingPoint(double val)81 static Value ConstructValueFromFloatingPoint(double val)
82 {
83     return Value(bit_cast<int64_t>(val));
84 }
85 
GetArgValues(ScopedManagedCodeFix * s,EtsMethod * method,va_list args,ets_object object)86 static ArgVector<Value> GetArgValues(ScopedManagedCodeFix *s, EtsMethod *method, va_list args, ets_object object)
87 {
88     ArgVector<Value> parsedArgs;
89     parsedArgs.reserve(method->GetNumArgs());
90     if (object != nullptr) {
91         parsedArgs.emplace_back(s->ToInternalType(object)->GetCoreType());
92     }
93 
94     panda_file::ShortyIterator it(method->GetPandaMethod()->GetShorty());
95     panda_file::ShortyIterator end;
96     ++it;  // skip the return value
97     while (it != end) {
98         panda_file::Type type = *it;
99         ++it;
100         switch (type.GetId()) {
101             case TypeId::U1:
102             case TypeId::U16:
103                 parsedArgs.emplace_back(va_arg(args, uint32_t));
104                 break;
105             case TypeId::I8:
106             case TypeId::I16:
107             case TypeId::I32:
108                 parsedArgs.emplace_back(va_arg(args, int32_t));
109                 break;
110             case TypeId::I64:
111                 parsedArgs.emplace_back(va_arg(args, int64_t));
112                 break;
113             case TypeId::F32:
114                 parsedArgs.push_back(ConstructValueFromFloatingPoint(static_cast<float>(va_arg(args, double))));
115                 break;
116             case TypeId::F64:
117                 parsedArgs.push_back(ConstructValueFromFloatingPoint(va_arg(args, double)));
118                 break;
119             case TypeId::REFERENCE: {
120                 auto param = va_arg(args, ets_object);
121                 parsedArgs.emplace_back(param != nullptr ? s->ToInternalType(param)->GetCoreType() : nullptr);
122                 break;
123             }
124             default:
125                 LOG(FATAL, ETS_NAPI) << "Unexpected argument type";
126                 break;
127         }
128     }
129     return parsedArgs;
130 }
131 
GetArgValues(ScopedManagedCodeFix * s,EtsMethod * method,const ets_value * args,ets_object object)132 static ArgVector<Value> GetArgValues(ScopedManagedCodeFix *s, EtsMethod *method, const ets_value *args,
133                                      ets_object object)
134 {
135     ArgVector<Value> parsedArgs;
136     parsedArgs.reserve(method->GetNumArgs());
137     if (object != nullptr) {
138         parsedArgs.emplace_back(s->ToInternalType(object)->GetCoreType());
139     }
140 
141     panda_file::ShortyIterator it(method->GetPandaMethod()->GetShorty());
142     panda_file::ShortyIterator end;
143     ++it;  // skip the return value
144     auto *arg = args;
145     while (it != end) {
146         panda_file::Type type = *it;
147         ++it;
148         switch (type.GetId()) {
149             case TypeId::U1:
150                 parsedArgs.emplace_back(arg->z);
151                 break;
152             case TypeId::U16:
153                 parsedArgs.emplace_back(arg->c);
154                 break;
155             case TypeId::I8:
156                 parsedArgs.emplace_back(arg->b);
157                 break;
158             case TypeId::I16:
159                 parsedArgs.emplace_back(arg->s);
160                 break;
161             case TypeId::I32:
162                 parsedArgs.emplace_back(arg->i);
163                 break;
164             case TypeId::I64:
165                 parsedArgs.emplace_back(arg->j);
166                 break;
167             case TypeId::F32:
168                 parsedArgs.push_back(ConstructValueFromFloatingPoint(arg->f));
169                 break;
170             case TypeId::F64:
171                 parsedArgs.push_back(ConstructValueFromFloatingPoint(arg->d));
172                 break;
173             case TypeId::REFERENCE: {
174                 parsedArgs.emplace_back(s->ToInternalType(arg->l)->GetCoreType());
175                 break;
176             }
177             default:
178                 LOG(FATAL, ETS_NAPI) << "Unexpected argument type";
179                 break;
180         }
181         ++arg;  // NOLINT(cppcoreguidelines-pro-bounds-pointer-arithmetic)
182     }
183     return parsedArgs;
184 }
185 
ToInternalType(ets_method methodId)186 EtsMethod *ToInternalType(ets_method methodId)
187 {
188     return reinterpret_cast<EtsMethod *>(methodId);
189 }
190 
ToEtsNapiType(EtsMethod * methodId)191 ets_method ToEtsNapiType(EtsMethod *methodId)
192 {
193     return reinterpret_cast<ets_method>(methodId);
194 }
195 
ToInternalType(ets_field fieldId)196 EtsField *ToInternalType(ets_field fieldId)
197 {
198     return reinterpret_cast<EtsField *>(fieldId);
199 }
200 
ToEtsNapiType(EtsField * fieldId)201 ets_field ToEtsNapiType(EtsField *fieldId)
202 {
203     return reinterpret_cast<ets_field>(fieldId);
204 }
205 
ResolveVirtualMethod(ScopedManagedCodeFix * s,ets_object object,ets_method methodId)206 static EtsMethod *ResolveVirtualMethod(ScopedManagedCodeFix *s, ets_object object, ets_method methodId)
207 {
208     EtsMethod *method = ToInternalType(methodId);
209 
210     if (UNLIKELY(method->IsStatic())) {
211         LOG(ERROR, ETS_NAPI) << "Called ResolveVirtualMethod of static method, invalid ETS NAPI usage";
212         return method;
213     }
214 
215     EtsObject *obj = s->ToInternalType(object);
216     return obj->GetClass()->ResolveVirtualMethod(method);
217 }
218 
219 template <bool IS_VIRTUAL, typename NapiType, typename EtsValueType, typename Args>
GeneralMethodCall(EtsEnv * env,ets_object obj,ets_method methodId,Args args)220 static NapiType GeneralMethodCall(EtsEnv *env, ets_object obj, ets_method methodId, Args args)
221 {
222     EtsMethod *method = nullptr;
223     ScopedManagedCodeFix s(PandaEtsNapiEnv::ToPandaEtsEnv(env));
224     if constexpr (IS_VIRTUAL) {
225         method = ResolveVirtualMethod(&s, obj, methodId);
226     } else {
227         method = ToInternalType(methodId);
228     }
229     ASSERT(method != nullptr);
230 
231     ArgVector<Value> values = GetArgValues(&s, method, args, obj);
232     EtsValue res = method->Invoke(&s, const_cast<Value *>(values.data()));
233 
234     // Now NapiType and EtsValueType are the same, but later it could be changed
235     static_assert(std::is_same_v<NapiType, EtsValueType>);
236     return res.GetAs<EtsValueType>();
237 }
238 
CheckMethodReturnType(ets_method methodId,EtsType type)239 static void CheckMethodReturnType(ets_method methodId, EtsType type)
240 {
241     EtsMethod *method = ToInternalType(methodId);
242     if (method->GetReturnValueType() != type) {
243         LOG(FATAL, ETS_NAPI) << "Return type mismatch";
244     }
245 }
246 
247 template <typename EtsNapiType, typename InternalType>
GetPrimitiveTypeField(EtsEnv * env,ets_object obj,ets_field fieldId)248 static inline EtsNapiType GetPrimitiveTypeField(EtsEnv *env, ets_object obj, ets_field fieldId)
249 {
250     ETS_NAPI_ABORT_IF_NULL(obj);
251     ETS_NAPI_ABORT_IF_NULL(fieldId);
252 
253     EtsField *internalFieldId = ToInternalType(fieldId);
254     ScopedManagedCodeFix s(PandaEtsNapiEnv::ToPandaEtsEnv(env));
255     EtsObject *internalObject = s.ToInternalType(obj);
256 
257     return static_cast<EtsNapiType>(internalObject->GetFieldPrimitive<InternalType>(internalFieldId));
258 }
259 
260 template <typename EtsNapiType>
SetPrimitiveTypeField(EtsEnv * env,ets_object obj,ets_field fieldId,EtsNapiType value)261 static inline void SetPrimitiveTypeField(EtsEnv *env, ets_object obj, ets_field fieldId, EtsNapiType value)
262 {
263     ETS_NAPI_ABORT_IF_NULL(obj);
264     ETS_NAPI_ABORT_IF_NULL(fieldId);
265 
266     EtsField *internalFieldId = ToInternalType(fieldId);
267     ScopedManagedCodeFix s(PandaEtsNapiEnv::ToPandaEtsEnv(env));
268     EtsObject *internalObject = s.ToInternalType(obj);
269 
270     internalObject->SetFieldPrimitive(internalFieldId, value);
271 }
272 
273 template <typename EtsNapiType, typename InternalType>
GetPrimitiveTypeStaticField(EtsEnv * env,ets_field fieldId)274 static inline EtsNapiType GetPrimitiveTypeStaticField(EtsEnv *env, ets_field fieldId)
275 {
276     ETS_NAPI_ABORT_IF_NULL(fieldId);
277 
278     EtsField *internalFieldId = ToInternalType(fieldId);
279     ScopedManagedCodeFix s(PandaEtsNapiEnv::ToPandaEtsEnv(env));
280     EtsClass *internalClass = internalFieldId->GetDeclaringClass();
281 
282     return static_cast<EtsNapiType>(internalClass->GetStaticFieldPrimitive<InternalType>(internalFieldId));
283 }
284 
285 template <typename EtsNapiType>
SetPrimitiveTypeStaticField(EtsEnv * env,ets_field fieldId,EtsNapiType value)286 static inline void SetPrimitiveTypeStaticField(EtsEnv *env, ets_field fieldId, EtsNapiType value)
287 {
288     ETS_NAPI_ABORT_IF_NULL(fieldId);
289 
290     EtsField *internalFieldId = ToInternalType(fieldId);
291     ScopedManagedCodeFix s(PandaEtsNapiEnv::ToPandaEtsEnv(env));
292     EtsClass *internalClass = internalFieldId->GetDeclaringClass();
293 
294     internalClass->SetStaticFieldPrimitive(internalFieldId, value);
295 }
296 
ToClassDescriptor(const char * className)297 inline PandaString ToClassDescriptor(const char *className)
298 {
299     if (className[0] == '[') {  // NOLINT(cppcoreguidelines-pro-bounds-pointer-arithmetic)
300         return className;
301     }
302     return PandaString("L") + className + ';';
303 }
304 
GetClassLinkerContext(ScopedManagedCodeFix * soa)305 ClassLinkerContext *GetClassLinkerContext(ScopedManagedCodeFix *soa)
306 {
307     auto stack = StackWalker::Create(soa->Coroutine());
308     if (!stack.HasFrame()) {
309         return nullptr;
310     }
311 
312     auto *method = EtsMethod::FromRuntimeMethod(stack.GetMethod());
313 
314     if (method != nullptr) {
315         return method->GetClass()->GetLoadContext();
316     }
317 
318     return nullptr;
319 }
320 
GetInternalClass(EtsEnv * env,ets_class cls,ScopedManagedCodeFix * s)321 static EtsClass *GetInternalClass(EtsEnv *env, ets_class cls, ScopedManagedCodeFix *s)
322 {
323     EtsClass *klass = s->ToInternalType(cls);
324 
325     if (klass->IsInitialized()) {
326         return klass;
327     }
328 
329     // Initialize class
330     EtsCoroutine *corutine = PandaEtsNapiEnv::ToPandaEtsEnv(env)->GetEtsCoroutine();
331     EtsClassLinker *classLinker = corutine->GetPandaVM()->GetClassLinker();
332     bool isInitialized = classLinker->InitializeClass(corutine, klass);
333     if (!isInitialized) {
334         LOG(ERROR, ETS_NAPI) << "Cannot initialize class: " << klass->GetDescriptor();
335         return nullptr;
336     }
337 
338     return klass;
339 }
340 
341 template <typename EtsType, typename InternalType>
NewPrimitiveTypeArray(EtsEnv * env,ets_size length)342 static EtsType NewPrimitiveTypeArray(EtsEnv *env, ets_size length)
343 {
344     ETS_NAPI_ABORT_IF_LZ(length);
345 
346     ScopedManagedCodeFix s(PandaEtsNapiEnv::ToPandaEtsEnv(env));
347     auto *array = InternalType::Create(static_cast<uint32_t>(length));
348     if (UNLIKELY(array == nullptr)) {
349         return nullptr;
350     }
351     ets_object ret = s.AddLocalRef(reinterpret_cast<EtsObject *>(array));
352     return reinterpret_cast<EtsType>(ret);
353 }
354 
PinRawDataOfPrimitiveArray(EtsEnv * env,ets_array array)355 static void *PinRawDataOfPrimitiveArray(EtsEnv *env, ets_array array)
356 {
357     ETS_NAPI_ABORT_IF_NULL(array);
358 
359     auto pandaEnv = PandaEtsNapiEnv::ToPandaEtsEnv(env);
360     ScopedManagedCodeFix s(pandaEnv);
361 
362     auto vm = pandaEnv->GetEtsVM();
363     if (!vm->GetGC()->IsPinningSupported()) {
364         LOG(FATAL, ETS_NAPI) << "Pinning is not supported with " << mem::GCStringFromType(vm->GetGC()->GetType());
365         return nullptr;
366     }
367 
368     auto coreArray = s.ToInternalType(array)->GetCoreType();
369     vm->GetHeapManager()->PinObject(coreArray);
370 
371     return coreArray->GetData();
372 }
373 
374 template <typename T>
PinPrimitiveTypeArray(EtsEnv * env,ets_array array)375 static T *PinPrimitiveTypeArray(EtsEnv *env, ets_array array)
376 {
377     return reinterpret_cast<T *>(PinRawDataOfPrimitiveArray(env, array));
378 }
379 
UnpinPrimitiveTypeArray(EtsEnv * env,ets_array array)380 static void UnpinPrimitiveTypeArray(EtsEnv *env, ets_array array)
381 {
382     ETS_NAPI_ABORT_IF_NULL(array);
383 
384     auto pandaEnv = PandaEtsNapiEnv::ToPandaEtsEnv(env);
385     ScopedManagedCodeFix s(pandaEnv);
386 
387     auto coreArray = s.ToInternalType(array)->GetCoreType();
388     auto vm = pandaEnv->GetEtsVM();
389     vm->GetHeapManager()->UnpinObject(coreArray);
390 }
391 
392 template <typename T>
GetPrimitiveTypeArrayRegion(EtsEnv * env,ets_array array,ets_size start,ets_size len,T * buf)393 static void GetPrimitiveTypeArrayRegion(EtsEnv *env, ets_array array, ets_size start, ets_size len, T *buf)
394 {
395     ETS_NAPI_ABORT_IF_NULL(array);
396     ETS_NAPI_ABORT_IF(len != 0 && buf == nullptr);
397 
398     ScopedManagedCodeFix s(PandaEtsNapiEnv::ToPandaEtsEnv(env));
399     EtsArray *internalArray = s.ToInternalType(array);
400     // NOLINTNEXTLINE(bugprone-misplaced-widening-cast)
401     if (start < 0 || len < 0 || static_cast<size_t>(start + len) > internalArray->GetLength()) {
402         PandaStringStream ss;
403         ss << "Array index out of bounds: start = " << start << ", len = " << len
404            << ", array size = " << internalArray->GetLength();
405         s.ThrowNewException(EtsNapiException::ARRAY_INDEX_OUT_OF_BOUNDS, ss.str().c_str());
406         return;
407     }
408     // NOLINTNEXTLINE(cppcoreguidelines-pro-bounds-pointer-arithmetic)
409     auto res = memcpy_s(buf, len * sizeof(T), internalArray->GetData<T>() + start, len * sizeof(T));
410     if (res != 0) {
411         UNREACHABLE();
412     }
413 }
414 
415 template <typename T>
SetPrimitiveTypeArrayRegion(EtsEnv * env,ets_array array,ets_size start,ets_size len,T * buf)416 static void SetPrimitiveTypeArrayRegion(EtsEnv *env, ets_array array, ets_size start, ets_size len, T *buf)
417 {
418     ETS_NAPI_ABORT_IF_NULL(array);
419     ETS_NAPI_ABORT_IF(len != 0 && buf == nullptr);
420 
421     ScopedManagedCodeFix s(PandaEtsNapiEnv::ToPandaEtsEnv(env));
422     EtsArray *internalArray = s.ToInternalType(array);
423     // NOLINTNEXTLINE(bugprone-misplaced-widening-cast)
424     if (start < 0 || len < 0 || static_cast<size_t>(start + len) > internalArray->GetLength()) {
425         PandaStringStream ss;
426         ss << "Array index out of bounds: start = " << start << ", len = " << len
427            << ", array size = " << internalArray->GetLength();
428         s.ThrowNewException(EtsNapiException::ARRAY_INDEX_OUT_OF_BOUNDS, ss.str().c_str());
429         return;
430     }
431     // NOLINTBEGIN(cppcoreguidelines-pro-bounds-pointer-arithmetic)
432     auto res =
433         memcpy_s(internalArray->GetData<std::remove_const_t<T>>() + start, len * sizeof(T), buf, len * sizeof(T));
434     // NOLINTEND(cppcoreguidelines-pro-bounds-pointer-arithmetic)
435     if (res != 0) {
436         UNREACHABLE();
437     }
438 }
439 
440 // ETS NAPI implementation
441 
GetVersion(EtsEnv * env)442 NO_UB_SANITIZE static ets_int GetVersion([[maybe_unused]] EtsEnv *env)
443 {
444     ETS_NAPI_DEBUG_TRACE(env);
445     return ETS_NAPI_VERSION_1_0;
446 }
447 // DefineClass,
FindClass(EtsEnv * env,const char * name)448 NO_UB_SANITIZE static ets_class FindClass(EtsEnv *env, const char *name)
449 {
450     ETS_NAPI_DEBUG_TRACE(env);
451 
452     auto etsEnv = PandaEtsNapiEnv::ToPandaEtsEnv(env);
453     ScopedManagedCodeFix s(etsEnv);
454 
455     if (name == nullptr) {
456         s.ThrowNewException(EtsNapiException::NO_CLASS_DEF_FOUND, "Null pointer passed as a class name");
457         return nullptr;
458     }
459 
460     PandaString classDescriptor = ToClassDescriptor(name);
461     EtsClassLinker *classLinker = etsEnv->GetEtsVM()->GetClassLinker();
462     EtsClass *klass = classLinker->GetClass(classDescriptor.c_str(), true, GetClassLinkerContext(&s));
463 
464     if (etsEnv->HasPendingException()) {
465         EtsThrowable *currentException = etsEnv->GetThrowable();
466         std::string_view exceptionString = currentException->GetClass()->GetDescriptor();
467         if (exceptionString == panda_file_items::class_descriptors::CLASS_NOT_FOUND_EXCEPTION) {
468             etsEnv->ClearException();
469 
470             PandaStringStream ss;
471             ss << "Class '" << name << "' is not found";
472 
473             s.ThrowNewException(EtsNapiException::NO_CLASS_DEF_FOUND, ss.str().c_str());
474 
475             return nullptr;
476         }
477     }
478     ETS_NAPI_RETURN_IF_EQ(klass, nullptr, nullptr);
479     ASSERT_MANAGED_CODE();
480     return reinterpret_cast<ets_class>(s.AddLocalRef(reinterpret_cast<EtsObject *>(klass)));
481 }
482 // FromReflectedMethod,
483 // FromReflectedField,
484 // ToReflectedMethod,
GetSuperclass(EtsEnv * env,ets_class cls)485 NO_UB_SANITIZE static ets_class GetSuperclass(EtsEnv *env, ets_class cls)
486 {
487     ETS_NAPI_DEBUG_TRACE(env);
488     ETS_NAPI_ABORT_IF_NULL(cls);
489 
490     ScopedManagedCodeFix s(PandaEtsNapiEnv::ToPandaEtsEnv(env));
491     auto baseCls = s.ToInternalType(cls)->GetBase();
492     ETS_NAPI_RETURN_IF_EQ(baseCls, nullptr, nullptr);
493     ASSERT_MANAGED_CODE();
494     return reinterpret_cast<ets_class>(s.AddLocalRef(reinterpret_cast<EtsObject *>(baseCls)));
495 }
496 
IsAssignableFrom(EtsEnv * env,ets_class cls1,ets_class cls2)497 NO_UB_SANITIZE static ets_boolean IsAssignableFrom(EtsEnv *env, ets_class cls1, ets_class cls2)
498 {
499     ETS_NAPI_DEBUG_TRACE(env);
500     ETS_NAPI_ABORT_IF_NULL(cls1);
501     ETS_NAPI_ABORT_IF_NULL(cls2);
502 
503     ScopedManagedCodeFix s(PandaEtsNapiEnv::ToPandaEtsEnv(env));
504     EtsClass *klass1 = s.ToInternalType(cls1);
505     EtsClass *klass2 = s.ToInternalType(cls2);
506 
507     return klass2->IsAssignableFrom(klass1) ? ETS_TRUE : ETS_FALSE;
508 }
509 // ToReflectedField,
ErrorCheck(EtsEnv * env)510 NO_UB_SANITIZE static ets_boolean ErrorCheck(EtsEnv *env)
511 {
512     ETS_NAPI_DEBUG_TRACE(env);
513 
514     ScopedManagedCodeFix s(PandaEtsNapiEnv::ToPandaEtsEnv(env));
515     return static_cast<ets_boolean>(PandaEtsNapiEnv::ToPandaEtsEnv(env)->HasPendingException());
516 }
517 
ThrowError(EtsEnv * env,ets_error obj)518 NO_UB_SANITIZE static ets_int ThrowError(EtsEnv *env, ets_error obj)
519 {
520     ETS_NAPI_DEBUG_TRACE(env);
521     if (obj == nullptr) {
522         return ETS_ERR;
523     }
524 
525     ScopedManagedCodeFix s(PandaEtsNapiEnv::ToPandaEtsEnv(env));
526     EtsThrowable *exception = s.ToInternalType(obj);
527     PandaEtsNapiEnv::ToPandaEtsEnv(env)->SetException(exception);
528     return ETS_OK;
529 }
530 
ThrowErrorNew(EtsEnv * env,ets_class cls,const char * message)531 NO_UB_SANITIZE static ets_int ThrowErrorNew(EtsEnv *env, ets_class cls, const char *message)
532 {
533     ETS_NAPI_DEBUG_TRACE(env);
534     ETS_NAPI_ABORT_IF_NULL(cls);
535 
536     PandaEtsNapiEnv *pandaEtsEnv = PandaEtsNapiEnv::ToPandaEtsEnv(env);
537 
538     ScopedManagedCodeFix s(pandaEtsEnv);
539     EtsClass *exceptionClass = s.ToInternalType(cls);
540     EtsCoroutine *coroutine = pandaEtsEnv->GetEtsCoroutine();
541     ThrowEtsException(coroutine, exceptionClass->GetDescriptor(), message);
542     return ETS_OK;
543 }
544 
ErrorOccurred(EtsEnv * env)545 NO_UB_SANITIZE static ets_error ErrorOccurred(EtsEnv *env)
546 {
547     ETS_NAPI_DEBUG_TRACE(env);
548 
549     ScopedManagedCodeFix s(PandaEtsNapiEnv::ToPandaEtsEnv(env));
550     EtsThrowable *error = PandaEtsNapiEnv::ToPandaEtsEnv(env)->GetThrowable();
551     if (error == nullptr) {
552         return nullptr;
553     }
554     return reinterpret_cast<ets_error>(s.AddLocalRef(error));
555 }
556 
ErrorDescribe(EtsEnv * env)557 NO_UB_SANITIZE static void ErrorDescribe(EtsEnv *env)
558 {
559     ETS_NAPI_DEBUG_TRACE(env);
560 
561     auto error = env->ErrorOccurred();
562     if (error == nullptr) {
563         return;
564     }
565 
566     env->ErrorClear();
567 
568     auto errorKlass = env->GetObjectClass(error);
569     auto toStringMethod = env->Getp_method(errorKlass, "toString", ":Lstd/core/String;");
570     auto errorString = env->CallObjectMethod(error, toStringMethod);
571 
572     auto consoleKlass = env->FindClass("std/core/Console");
573 
574     auto coreGlobalClass = env->FindClass("std/core/ETSGLOBAL");
575     ETS_NAPI_ABORT_IF_NULL(coreGlobalClass);
576     auto consoleField = env->GetStaticp_field(coreGlobalClass, "console", "Lstd/core/Console;");
577     ETS_NAPI_ABORT_IF_NULL(consoleField);
578     auto consoleObj = env->GetStaticObjectField(coreGlobalClass, consoleField);
579 
580     auto printlnMethod = env->Getp_method(consoleKlass, "println", "Lstd/core/String;:V");
581     env->CallVoidMethod(consoleObj, printlnMethod, errorString);
582     env->ThrowError(error);
583 }
584 
ErrorClear(EtsEnv * env)585 NO_UB_SANITIZE static void ErrorClear(EtsEnv *env)
586 {
587     ETS_NAPI_DEBUG_TRACE(env);
588     ScopedManagedCodeFix s(PandaEtsNapiEnv::ToPandaEtsEnv(env));
589     PandaEtsNapiEnv::ToPandaEtsEnv(env)->ClearException();
590 }
591 
FatalError(EtsEnv * env,const char * message)592 NO_UB_SANITIZE static void FatalError([[maybe_unused]] EtsEnv *env, const char *message)
593 {
594     ETS_NAPI_DEBUG_TRACE(env);
595     LOG(FATAL, ETS_NAPI) << "EtsNapiFatalError: " << message;
596 }
597 
PushLocalFrame(EtsEnv * env,ets_int capacity)598 NO_UB_SANITIZE static ets_int PushLocalFrame(EtsEnv *env, ets_int capacity)
599 {
600     ETS_NAPI_DEBUG_TRACE(env);
601 
602     if (capacity <= 0) {
603         return ETS_ERR_INVAL;
604     }
605 
606     ScopedManagedCodeFix s(PandaEtsNapiEnv::ToPandaEtsEnv(env));
607     bool ret = PandaEtsNapiEnv::ToPandaEtsEnv(env)->GetEtsReferenceStorage()->PushLocalEtsFrame(
608         static_cast<uint32_t>(capacity));
609     if (!ret) {
610         PandaStringStream ss;
611         ss << "Could not allocate " << capacity << "bytes";
612         s.ThrowNewException(EtsNapiException::OUT_OF_MEMORY, ss.str().c_str());
613         return ETS_ERR;
614     }
615     return ETS_OK;
616 }
617 
PopLocalFrame(EtsEnv * env,ets_object result)618 NO_UB_SANITIZE static ets_object PopLocalFrame(EtsEnv *env, ets_object result)
619 {
620     ETS_NAPI_DEBUG_TRACE(env);
621 
622     ScopedManagedCodeFix s(PandaEtsNapiEnv::ToPandaEtsEnv(env));
623     EtsReference *resultEtsRef = EtsObjectToEtsRef(result);
624     EtsReference *etsRef =
625         PandaEtsNapiEnv::ToPandaEtsEnv(env)->GetEtsReferenceStorage()->PopLocalEtsFrame(resultEtsRef);
626     return EtsRefToEtsObject(etsRef);
627 }
628 
NewGlobalRef(EtsEnv * env,ets_object obj)629 NO_UB_SANITIZE static ets_object NewGlobalRef(EtsEnv *env, ets_object obj)
630 {
631     ETS_NAPI_DEBUG_TRACE(env);
632     ETS_NAPI_RETURN_IF_EQ(obj, nullptr, nullptr);
633 
634     ScopedManagedCodeFix s(PandaEtsNapiEnv::ToPandaEtsEnv(env));
635     EtsObject *internalObject = s.ToInternalType(obj);
636     return s.AddGlobalRef(internalObject);
637 }
638 
DeleteGlobalRef(EtsEnv * env,ets_object globalRef)639 NO_UB_SANITIZE static void DeleteGlobalRef([[maybe_unused]] EtsEnv *env, ets_object globalRef)
640 {
641     ETS_NAPI_DEBUG_TRACE(env);
642     ETS_NAPI_RETURN_VOID_IF_NULL(globalRef);
643 
644     PandaEtsVM *etsVm = PandaEtsVM::GetCurrent();
645     etsVm->DeleteGlobalRef(globalRef);
646 }
647 
DeleteLocalRef(EtsEnv * env,ets_object localRef)648 NO_UB_SANITIZE static void DeleteLocalRef(EtsEnv *env, ets_object localRef)
649 {
650     ETS_NAPI_DEBUG_TRACE(env);
651     ETS_NAPI_RETURN_VOID_IF_NULL(localRef);
652     ScopedManagedCodeFix s(PandaEtsNapiEnv::ToPandaEtsEnv(env));
653     s.DelLocalRef(localRef);
654 }
655 
IsSameObject(EtsEnv * env,ets_object ref1,ets_object ref2)656 NO_UB_SANITIZE static ets_boolean IsSameObject(EtsEnv *env, ets_object ref1, ets_object ref2)
657 {
658     ETS_NAPI_DEBUG_TRACE(env);
659 
660     if (ref1 == ref2) {
661         return ETS_TRUE;
662     }
663     ScopedManagedCodeFix s(PandaEtsNapiEnv::ToPandaEtsEnv(env));
664     return s.ToInternalType(ref1) == s.ToInternalType(ref2) ? ETS_TRUE : ETS_FALSE;
665 }
666 
NewLocalRef(EtsEnv * env,ets_object ref)667 NO_UB_SANITIZE static ets_object NewLocalRef(EtsEnv *env, ets_object ref)
668 {
669     ETS_NAPI_DEBUG_TRACE(env);
670     ETS_NAPI_RETURN_IF_EQ(ref, nullptr, nullptr);
671 
672     ScopedManagedCodeFix s(PandaEtsNapiEnv::ToPandaEtsEnv(env));
673     EtsObject *internalObject = s.ToInternalType(ref);
674     return s.AddLocalRef(internalObject);
675 }
676 
EnsureLocalCapacity(EtsEnv * env,ets_int capacity)677 NO_UB_SANITIZE static ets_int EnsureLocalCapacity(EtsEnv *env, ets_int capacity)
678 {
679     ETS_NAPI_DEBUG_TRACE(env);
680     if (capacity < 0) {
681         return ETS_ERR_INVAL;
682     }
683 
684     ScopedManagedCodeFix s(PandaEtsNapiEnv::ToPandaEtsEnv(env));
685     bool ret =
686         PandaEtsNapiEnv::ToPandaEtsEnv(env)->GetEtsReferenceStorage()->GetAsReferenceStorage()->EnsureLocalCapacity(
687             static_cast<size_t>(capacity));
688     if (!ret) {
689         PandaStringStream ss;
690         ss << "Could not ensure " << capacity << "bytes";
691         s.ThrowNewException(EtsNapiException::OUT_OF_MEMORY, ss.str().c_str());
692         return ETS_ERR;
693     }
694     return ETS_OK;
695 }
696 
697 // NOLINTNEXTLINE(readability-identifier-naming)
Getp_method(EtsEnv * env,ets_class cls,const char * name,const char * sig)698 NO_UB_SANITIZE static ets_method Getp_method(EtsEnv *env, ets_class cls, const char *name, const char *sig)
699 {
700     ETS_NAPI_DEBUG_TRACE(env);
701     ETS_NAPI_ABORT_IF_NULL(cls);
702     ETS_NAPI_ABORT_IF_NULL(name);
703 
704     ScopedManagedCodeFix s(PandaEtsNapiEnv::ToPandaEtsEnv(env));
705     EtsClass *klass = GetInternalClass(env, cls, &s);
706     if (klass == nullptr) {
707         return nullptr;
708     }
709 
710     EtsMethod *method = (sig == nullptr ? klass->GetMethod(name) : klass->GetMethod(name, sig));
711     if (method == nullptr || method->IsStatic()) {
712         PandaStringStream ss;
713         ss << "Method " << klass->GetRuntimeClass()->GetName() << "::" << name
714            << " sig = " << (sig == nullptr ? "nullptr" : sig) << " is not found";
715         s.ThrowNewException(EtsNapiException::NO_SUCH_METHOD, ss.str().c_str());
716         return nullptr;
717     }
718 
719     return ToEtsNapiType(method);
720 }
721 
CallObjectMethodList(EtsEnv * env,ets_object obj,ets_method methodId,va_list args)722 NO_UB_SANITIZE static ets_object CallObjectMethodList(EtsEnv *env, ets_object obj, ets_method methodId, va_list args)
723 {
724     ETS_NAPI_DEBUG_TRACE(env);
725     ETS_NAPI_ABORT_IF_NULL(obj);
726     ETS_NAPI_ABORT_IF_NULL(methodId);
727     CheckMethodReturnType(methodId, EtsType::OBJECT);
728     return GeneralMethodCall<true, ets_object, ets_object>(env, obj, methodId, args);
729 }
730 
CallObjectMethod(EtsEnv * env,ets_object obj,ets_method methodId,...)731 NO_UB_SANITIZE static ets_object CallObjectMethod(EtsEnv *env, ets_object obj, ets_method methodId, ...)
732 {
733     ETS_NAPI_DEBUG_TRACE(env);
734     va_list args;
735     va_start(args, methodId);
736     ets_object res = CallObjectMethodList(env, obj, methodId, args);
737     va_end(args);
738     return res;
739 }
740 
CallObjectMethodArray(EtsEnv * env,ets_object obj,ets_method methodId,const ets_value * args)741 NO_UB_SANITIZE static ets_object CallObjectMethodArray(EtsEnv *env, ets_object obj, ets_method methodId,
742                                                        const ets_value *args)
743 {
744     ETS_NAPI_DEBUG_TRACE(env);
745     ETS_NAPI_ABORT_IF_NULL(obj);
746     ETS_NAPI_ABORT_IF_NULL(methodId);
747     CheckMethodReturnType(methodId, EtsType::OBJECT);
748     return GeneralMethodCall<true, ets_object, ets_object>(env, obj, methodId, args);
749 }
750 
CallBooleanMethodList(EtsEnv * env,ets_object obj,ets_method methodId,va_list args)751 NO_UB_SANITIZE static ets_boolean CallBooleanMethodList(EtsEnv *env, ets_object obj, ets_method methodId, va_list args)
752 {
753     ETS_NAPI_DEBUG_TRACE(env);
754     ETS_NAPI_ABORT_IF_NULL(obj);
755     ETS_NAPI_ABORT_IF_NULL(methodId);
756     CheckMethodReturnType(methodId, EtsType::BOOLEAN);
757     return GeneralMethodCall<true, ets_boolean, EtsBoolean>(env, obj, methodId, args);
758 }
759 
CallBooleanMethod(EtsEnv * env,ets_object obj,ets_method methodId,...)760 NO_UB_SANITIZE static ets_boolean CallBooleanMethod(EtsEnv *env, ets_object obj, ets_method methodId, ...)
761 {
762     ETS_NAPI_DEBUG_TRACE(env);
763     va_list args;
764     va_start(args, methodId);
765     ets_boolean res = CallBooleanMethodList(env, obj, methodId, args);
766     va_end(args);
767     return res;
768 }
769 
CallBooleanMethodArray(EtsEnv * env,ets_object obj,ets_method methodId,const ets_value * args)770 NO_UB_SANITIZE static ets_boolean CallBooleanMethodArray(EtsEnv *env, ets_object obj, ets_method methodId,
771                                                          const ets_value *args)
772 {
773     ETS_NAPI_DEBUG_TRACE(env);
774     ETS_NAPI_ABORT_IF_NULL(obj);
775     ETS_NAPI_ABORT_IF_NULL(methodId);
776     CheckMethodReturnType(methodId, EtsType::BOOLEAN);
777     return GeneralMethodCall<true, ets_boolean, EtsBoolean>(env, obj, methodId, args);
778 }
779 
CallByteMethodList(EtsEnv * env,ets_object obj,ets_method methodId,va_list args)780 NO_UB_SANITIZE static ets_byte CallByteMethodList(EtsEnv *env, ets_object obj, ets_method methodId, va_list args)
781 {
782     ETS_NAPI_DEBUG_TRACE(env);
783     ETS_NAPI_ABORT_IF_NULL(obj);
784     ETS_NAPI_ABORT_IF_NULL(methodId);
785     CheckMethodReturnType(methodId, EtsType::BYTE);
786     return GeneralMethodCall<true, ets_byte, EtsByte>(env, obj, methodId, args);
787 }
788 
CallByteMethod(EtsEnv * env,ets_object obj,ets_method methodId,...)789 NO_UB_SANITIZE static ets_byte CallByteMethod(EtsEnv *env, ets_object obj, ets_method methodId, ...)
790 {
791     ETS_NAPI_DEBUG_TRACE(env);
792     va_list args;
793     va_start(args, methodId);
794     ets_byte res = CallByteMethodList(env, obj, methodId, args);
795     va_end(args);
796     return res;
797 }
798 
CallByteMethodArray(EtsEnv * env,ets_object obj,ets_method methodId,const ets_value * args)799 NO_UB_SANITIZE static ets_byte CallByteMethodArray(EtsEnv *env, ets_object obj, ets_method methodId,
800                                                    const ets_value *args)
801 {
802     ETS_NAPI_DEBUG_TRACE(env);
803     ETS_NAPI_ABORT_IF_NULL(obj);
804     ETS_NAPI_ABORT_IF_NULL(methodId);
805     CheckMethodReturnType(methodId, EtsType::BYTE);
806     return GeneralMethodCall<true, ets_byte, EtsByte>(env, obj, methodId, args);
807 }
808 
CallCharMethodList(EtsEnv * env,ets_object obj,ets_method methodId,va_list args)809 NO_UB_SANITIZE static ets_char CallCharMethodList(EtsEnv *env, ets_object obj, ets_method methodId, va_list args)
810 {
811     ETS_NAPI_DEBUG_TRACE(env);
812     ETS_NAPI_ABORT_IF_NULL(obj);
813     ETS_NAPI_ABORT_IF_NULL(methodId);
814     CheckMethodReturnType(methodId, EtsType::CHAR);
815     return GeneralMethodCall<true, ets_char, EtsChar>(env, obj, methodId, args);
816 }
817 
CallCharMethod(EtsEnv * env,ets_object obj,ets_method methodId,...)818 NO_UB_SANITIZE static ets_char CallCharMethod(EtsEnv *env, ets_object obj, ets_method methodId, ...)
819 {
820     ETS_NAPI_DEBUG_TRACE(env);
821     va_list args;
822     va_start(args, methodId);
823     ets_char res = CallCharMethodList(env, obj, methodId, args);
824     va_end(args);
825     return res;
826 }
827 
CallCharMethodArray(EtsEnv * env,ets_object obj,ets_method methodId,const ets_value * args)828 NO_UB_SANITIZE static ets_char CallCharMethodArray(EtsEnv *env, ets_object obj, ets_method methodId,
829                                                    const ets_value *args)
830 {
831     ETS_NAPI_DEBUG_TRACE(env);
832     ETS_NAPI_ABORT_IF_NULL(obj);
833     ETS_NAPI_ABORT_IF_NULL(methodId);
834     CheckMethodReturnType(methodId, EtsType::CHAR);
835     return GeneralMethodCall<true, ets_char, EtsChar>(env, obj, methodId, args);
836 }
837 
CallShortMethodList(EtsEnv * env,ets_object obj,ets_method methodId,va_list args)838 NO_UB_SANITIZE static ets_short CallShortMethodList(EtsEnv *env, ets_object obj, ets_method methodId, va_list args)
839 {
840     ETS_NAPI_DEBUG_TRACE(env);
841     ETS_NAPI_ABORT_IF_NULL(obj);
842     ETS_NAPI_ABORT_IF_NULL(methodId);
843     CheckMethodReturnType(methodId, EtsType::SHORT);
844     return GeneralMethodCall<true, ets_short, EtsShort>(env, obj, methodId, args);
845 }
846 
CallShortMethod(EtsEnv * env,ets_object obj,ets_method methodId,...)847 NO_UB_SANITIZE static ets_short CallShortMethod(EtsEnv *env, ets_object obj, ets_method methodId, ...)
848 {
849     ETS_NAPI_DEBUG_TRACE(env);
850     va_list args;
851     va_start(args, methodId);
852     ets_short res = CallShortMethodList(env, obj, methodId, args);
853     va_end(args);
854     return res;
855 }
856 
CallShortMethodArray(EtsEnv * env,ets_object obj,ets_method methodId,const ets_value * args)857 NO_UB_SANITIZE static ets_short CallShortMethodArray(EtsEnv *env, ets_object obj, ets_method methodId,
858                                                      const ets_value *args)
859 {
860     ETS_NAPI_DEBUG_TRACE(env);
861     ETS_NAPI_ABORT_IF_NULL(obj);
862     ETS_NAPI_ABORT_IF_NULL(methodId);
863     CheckMethodReturnType(methodId, EtsType::SHORT);
864     return GeneralMethodCall<true, ets_short, EtsShort>(env, obj, methodId, args);
865 }
866 
CallIntMethodList(EtsEnv * env,ets_object obj,ets_method methodId,va_list args)867 NO_UB_SANITIZE static ets_int CallIntMethodList(EtsEnv *env, ets_object obj, ets_method methodId, va_list args)
868 {
869     ETS_NAPI_DEBUG_TRACE(env);
870     ETS_NAPI_ABORT_IF_NULL(obj);
871     ETS_NAPI_ABORT_IF_NULL(methodId);
872     CheckMethodReturnType(methodId, EtsType::INT);
873     return GeneralMethodCall<true, ets_int, EtsInt>(env, obj, methodId, args);
874 }
875 
CallIntMethod(EtsEnv * env,ets_object obj,ets_method methodId,...)876 NO_UB_SANITIZE static ets_int CallIntMethod(EtsEnv *env, ets_object obj, ets_method methodId, ...)
877 {
878     ETS_NAPI_DEBUG_TRACE(env);
879     va_list args;
880     va_start(args, methodId);
881     ets_int res = CallIntMethodList(env, obj, methodId, args);
882     va_end(args);
883     return res;
884 }
885 
CallIntMethodArray(EtsEnv * env,ets_object obj,ets_method methodId,const ets_value * args)886 NO_UB_SANITIZE static ets_int CallIntMethodArray(EtsEnv *env, ets_object obj, ets_method methodId,
887                                                  const ets_value *args)
888 {
889     ETS_NAPI_DEBUG_TRACE(env);
890     ETS_NAPI_ABORT_IF_NULL(obj);
891     ETS_NAPI_ABORT_IF_NULL(methodId);
892     CheckMethodReturnType(methodId, EtsType::INT);
893     return GeneralMethodCall<true, ets_int, EtsInt>(env, obj, methodId, args);
894 }
895 
CallLongMethodList(EtsEnv * env,ets_object obj,ets_method methodId,va_list args)896 NO_UB_SANITIZE static ets_long CallLongMethodList(EtsEnv *env, ets_object obj, ets_method methodId, va_list args)
897 {
898     ETS_NAPI_DEBUG_TRACE(env);
899     ETS_NAPI_ABORT_IF_NULL(obj);
900     ETS_NAPI_ABORT_IF_NULL(methodId);
901     CheckMethodReturnType(methodId, EtsType::LONG);
902     return GeneralMethodCall<true, ets_long, EtsLong>(env, obj, methodId, args);
903 }
904 
CallLongMethod(EtsEnv * env,ets_object obj,ets_method methodId,...)905 NO_UB_SANITIZE static ets_long CallLongMethod(EtsEnv *env, ets_object obj, ets_method methodId, ...)
906 {
907     ETS_NAPI_DEBUG_TRACE(env);
908     va_list args;
909     va_start(args, methodId);
910     ets_long res = CallLongMethodList(env, obj, methodId, args);
911     va_end(args);
912     return res;
913 }
914 
CallLongMethodArray(EtsEnv * env,ets_object obj,ets_method methodId,const ets_value * args)915 NO_UB_SANITIZE static ets_long CallLongMethodArray(EtsEnv *env, ets_object obj, ets_method methodId,
916                                                    const ets_value *args)
917 {
918     ETS_NAPI_DEBUG_TRACE(env);
919     ETS_NAPI_ABORT_IF_NULL(obj);
920     ETS_NAPI_ABORT_IF_NULL(methodId);
921     CheckMethodReturnType(methodId, EtsType::LONG);
922     return GeneralMethodCall<true, ets_long, EtsLong>(env, obj, methodId, args);
923 }
924 
CallFloatMethodList(EtsEnv * env,ets_object obj,ets_method methodId,va_list args)925 NO_UB_SANITIZE static ets_float CallFloatMethodList(EtsEnv *env, ets_object obj, ets_method methodId, va_list args)
926 {
927     ETS_NAPI_DEBUG_TRACE(env);
928     ETS_NAPI_ABORT_IF_NULL(obj);
929     ETS_NAPI_ABORT_IF_NULL(methodId);
930     CheckMethodReturnType(methodId, EtsType::FLOAT);
931     return GeneralMethodCall<true, ets_float, EtsFloat>(env, obj, methodId, args);
932 }
933 
CallFloatMethod(EtsEnv * env,ets_object obj,ets_method methodId,...)934 NO_UB_SANITIZE static ets_float CallFloatMethod(EtsEnv *env, ets_object obj, ets_method methodId, ...)
935 {
936     ETS_NAPI_DEBUG_TRACE(env);
937     va_list args;
938     va_start(args, methodId);
939     ets_float res = CallFloatMethodList(env, obj, methodId, args);
940     va_end(args);
941     return res;
942 }
943 
CallFloatMethodArray(EtsEnv * env,ets_object obj,ets_method methodId,const ets_value * args)944 NO_UB_SANITIZE static ets_float CallFloatMethodArray(EtsEnv *env, ets_object obj, ets_method methodId,
945                                                      const ets_value *args)
946 {
947     ETS_NAPI_DEBUG_TRACE(env);
948     ETS_NAPI_ABORT_IF_NULL(obj);
949     ETS_NAPI_ABORT_IF_NULL(methodId);
950     CheckMethodReturnType(methodId, EtsType::FLOAT);
951     return GeneralMethodCall<true, ets_float, EtsFloat>(env, obj, methodId, args);
952 }
953 
CallDoubleMethodList(EtsEnv * env,ets_object obj,ets_method methodId,va_list args)954 NO_UB_SANITIZE static ets_double CallDoubleMethodList(EtsEnv *env, ets_object obj, ets_method methodId, va_list args)
955 {
956     ETS_NAPI_DEBUG_TRACE(env);
957     ETS_NAPI_ABORT_IF_NULL(obj);
958     ETS_NAPI_ABORT_IF_NULL(methodId);
959     CheckMethodReturnType(methodId, EtsType::DOUBLE);
960     return GeneralMethodCall<true, ets_double, EtsDouble>(env, obj, methodId, args);
961 }
962 
CallDoubleMethod(EtsEnv * env,ets_object obj,ets_method methodId,...)963 NO_UB_SANITIZE static ets_double CallDoubleMethod(EtsEnv *env, ets_object obj, ets_method methodId, ...)
964 {
965     ETS_NAPI_DEBUG_TRACE(env);
966     va_list args;
967     va_start(args, methodId);
968     ets_double res = CallDoubleMethodList(env, obj, methodId, args);
969     va_end(args);
970     return res;
971 }
972 
CallDoubleMethodArray(EtsEnv * env,ets_object obj,ets_method methodId,const ets_value * args)973 NO_UB_SANITIZE static ets_double CallDoubleMethodArray(EtsEnv *env, ets_object obj, ets_method methodId,
974                                                        const ets_value *args)
975 {
976     ETS_NAPI_DEBUG_TRACE(env);
977     ETS_NAPI_ABORT_IF_NULL(obj);
978     ETS_NAPI_ABORT_IF_NULL(methodId);
979     CheckMethodReturnType(methodId, EtsType::DOUBLE);
980     return GeneralMethodCall<true, ets_double, EtsDouble>(env, obj, methodId, args);
981 }
982 
CallVoidMethodList(EtsEnv * env,ets_object obj,ets_method methodId,va_list args)983 NO_UB_SANITIZE static void CallVoidMethodList(EtsEnv *env, ets_object obj, ets_method methodId, va_list args)
984 {
985     ETS_NAPI_DEBUG_TRACE(env);
986     ETS_NAPI_ABORT_IF_NULL(obj);
987     ETS_NAPI_ABORT_IF_NULL(methodId);
988     CheckMethodReturnType(methodId, EtsType::VOID);
989     // Use any primitive type as template parameter and jist ignore the result
990     GeneralMethodCall<true, ets_boolean, EtsBoolean>(env, obj, methodId, args);
991 }
992 
CallVoidMethod(EtsEnv * env,ets_object obj,ets_method methodId,...)993 NO_UB_SANITIZE static void CallVoidMethod(EtsEnv *env, ets_object obj, ets_method methodId, ...)
994 {
995     ETS_NAPI_DEBUG_TRACE(env);
996     va_list args;
997     va_start(args, methodId);
998     CallVoidMethodList(env, obj, methodId, args);
999     va_end(args);
1000 }
1001 
CallVoidMethodArray(EtsEnv * env,ets_object obj,ets_method methodId,const ets_value * args)1002 NO_UB_SANITIZE static void CallVoidMethodArray(EtsEnv *env, ets_object obj, ets_method methodId, const ets_value *args)
1003 {
1004     ETS_NAPI_DEBUG_TRACE(env);
1005     ETS_NAPI_ABORT_IF_NULL(obj);
1006     ETS_NAPI_ABORT_IF_NULL(methodId);
1007     CheckMethodReturnType(methodId, EtsType::VOID);
1008     // Use any primitive type as template parameter and jist ignore the result
1009     GeneralMethodCall<true, ets_boolean, EtsBoolean>(env, obj, methodId, args);
1010 }
1011 
CallNonvirtualObjectMethodList(EtsEnv * env,ets_object obj,ets_class cls,ets_method methodId,va_list args)1012 NO_UB_SANITIZE static ets_object CallNonvirtualObjectMethodList(EtsEnv *env, ets_object obj,
1013                                                                 [[maybe_unused]] ets_class cls, ets_method methodId,
1014                                                                 va_list args)
1015 {
1016     ETS_NAPI_DEBUG_TRACE(env);
1017     ETS_NAPI_ABORT_IF_NULL(obj);
1018     ETS_NAPI_ABORT_IF_NULL(methodId);
1019     CheckMethodReturnType(methodId, EtsType::OBJECT);
1020     return GeneralMethodCall<false, ets_object, ets_object>(env, obj, methodId, args);
1021 }
1022 
CallNonvirtualObjectMethod(EtsEnv * env,ets_object obj,ets_class cls,ets_method methodId,...)1023 NO_UB_SANITIZE static ets_object CallNonvirtualObjectMethod(EtsEnv *env, ets_object obj, ets_class cls,
1024                                                             ets_method methodId, ...)
1025 {
1026     ETS_NAPI_DEBUG_TRACE(env);
1027     va_list args;
1028     va_start(args, methodId);
1029     ets_object res = CallNonvirtualObjectMethodList(env, obj, cls, methodId, args);
1030     va_end(args);
1031     return res;
1032 }
1033 
CallNonvirtualObjectMethodArray(EtsEnv * env,ets_object obj,ets_class cls,ets_method methodId,const ets_value * args)1034 NO_UB_SANITIZE static ets_object CallNonvirtualObjectMethodArray(EtsEnv *env, ets_object obj,
1035                                                                  [[maybe_unused]] ets_class cls, ets_method methodId,
1036                                                                  const ets_value *args)
1037 {
1038     ETS_NAPI_DEBUG_TRACE(env);
1039     ETS_NAPI_ABORT_IF_NULL(obj);
1040     ETS_NAPI_ABORT_IF_NULL(methodId);
1041     CheckMethodReturnType(methodId, EtsType::OBJECT);
1042     return GeneralMethodCall<false, ets_object, ets_object>(env, obj, methodId, args);
1043 }
1044 
CallNonvirtualBooleanMethodList(EtsEnv * env,ets_object obj,ets_class cls,ets_method methodId,va_list args)1045 NO_UB_SANITIZE static ets_boolean CallNonvirtualBooleanMethodList(EtsEnv *env, ets_object obj,
1046                                                                   [[maybe_unused]] ets_class cls, ets_method methodId,
1047                                                                   va_list args)
1048 {
1049     ETS_NAPI_DEBUG_TRACE(env);
1050     ETS_NAPI_ABORT_IF_NULL(obj);
1051     ETS_NAPI_ABORT_IF_NULL(methodId);
1052     CheckMethodReturnType(methodId, EtsType::BOOLEAN);
1053     return GeneralMethodCall<false, ets_boolean, EtsBoolean>(env, obj, methodId, args);
1054 }
1055 
CallNonvirtualBooleanMethod(EtsEnv * env,ets_object obj,ets_class cls,ets_method methodId,...)1056 NO_UB_SANITIZE static ets_boolean CallNonvirtualBooleanMethod(EtsEnv *env, ets_object obj, ets_class cls,
1057                                                               ets_method methodId, ...)
1058 {
1059     ETS_NAPI_DEBUG_TRACE(env);
1060     va_list args;
1061     va_start(args, methodId);
1062     ets_boolean res = CallNonvirtualBooleanMethodList(env, obj, cls, methodId, args);
1063     va_end(args);
1064     return res;
1065 }
1066 
CallNonvirtualBooleanMethodArray(EtsEnv * env,ets_object obj,ets_class cls,ets_method methodId,const ets_value * args)1067 NO_UB_SANITIZE static ets_boolean CallNonvirtualBooleanMethodArray(EtsEnv *env, ets_object obj,
1068                                                                    [[maybe_unused]] ets_class cls, ets_method methodId,
1069                                                                    const ets_value *args)
1070 {
1071     ETS_NAPI_DEBUG_TRACE(env);
1072     ETS_NAPI_ABORT_IF_NULL(obj);
1073     ETS_NAPI_ABORT_IF_NULL(methodId);
1074     CheckMethodReturnType(methodId, EtsType::BOOLEAN);
1075     return GeneralMethodCall<false, ets_boolean, EtsBoolean>(env, obj, methodId, args);
1076 }
1077 
CallNonvirtualByteMethodList(EtsEnv * env,ets_object obj,ets_class cls,ets_method methodId,va_list args)1078 NO_UB_SANITIZE static ets_byte CallNonvirtualByteMethodList(EtsEnv *env, ets_object obj, [[maybe_unused]] ets_class cls,
1079                                                             ets_method methodId, va_list args)
1080 {
1081     ETS_NAPI_DEBUG_TRACE(env);
1082     ETS_NAPI_ABORT_IF_NULL(obj);
1083     ETS_NAPI_ABORT_IF_NULL(methodId);
1084     CheckMethodReturnType(methodId, EtsType::BYTE);
1085     return GeneralMethodCall<false, ets_byte, EtsByte>(env, obj, methodId, args);
1086 }
1087 
CallNonvirtualByteMethod(EtsEnv * env,ets_object obj,ets_class cls,ets_method methodId,...)1088 NO_UB_SANITIZE static ets_byte CallNonvirtualByteMethod(EtsEnv *env, ets_object obj, ets_class cls, ets_method methodId,
1089                                                         ...)
1090 {
1091     ETS_NAPI_DEBUG_TRACE(env);
1092     va_list args;
1093     va_start(args, methodId);
1094     ets_byte res = CallNonvirtualByteMethodList(env, obj, cls, methodId, args);
1095     va_end(args);
1096     return res;
1097 }
1098 
CallNonvirtualByteMethodArray(EtsEnv * env,ets_object obj,ets_class cls,ets_method methodId,const ets_value * args)1099 NO_UB_SANITIZE static ets_byte CallNonvirtualByteMethodArray(EtsEnv *env, ets_object obj,
1100                                                              [[maybe_unused]] ets_class cls, ets_method methodId,
1101                                                              const ets_value *args)
1102 {
1103     ETS_NAPI_DEBUG_TRACE(env);
1104     ETS_NAPI_ABORT_IF_NULL(obj);
1105     ETS_NAPI_ABORT_IF_NULL(methodId);
1106     CheckMethodReturnType(methodId, EtsType::BYTE);
1107     return GeneralMethodCall<false, ets_byte, EtsByte>(env, obj, methodId, args);
1108 }
1109 
CallNonvirtualCharMethodList(EtsEnv * env,ets_object obj,ets_class cls,ets_method methodId,va_list args)1110 NO_UB_SANITIZE static ets_char CallNonvirtualCharMethodList(EtsEnv *env, ets_object obj, [[maybe_unused]] ets_class cls,
1111                                                             ets_method methodId, va_list args)
1112 {
1113     ETS_NAPI_DEBUG_TRACE(env);
1114     ETS_NAPI_ABORT_IF_NULL(obj);
1115     ETS_NAPI_ABORT_IF_NULL(methodId);
1116     CheckMethodReturnType(methodId, EtsType::CHAR);
1117     return GeneralMethodCall<false, ets_char, EtsChar>(env, obj, methodId, args);
1118 }
1119 
CallNonvirtualCharMethod(EtsEnv * env,ets_object obj,ets_class cls,ets_method methodId,...)1120 NO_UB_SANITIZE static ets_char CallNonvirtualCharMethod(EtsEnv *env, ets_object obj, ets_class cls, ets_method methodId,
1121                                                         ...)
1122 {
1123     ETS_NAPI_DEBUG_TRACE(env);
1124     va_list args;
1125     va_start(args, methodId);
1126     ets_char res = CallNonvirtualCharMethodList(env, obj, cls, methodId, args);
1127     va_end(args);
1128     return res;
1129 }
1130 
CallNonvirtualCharMethodArray(EtsEnv * env,ets_object obj,ets_class cls,ets_method methodId,const ets_value * args)1131 NO_UB_SANITIZE static ets_char CallNonvirtualCharMethodArray(EtsEnv *env, ets_object obj,
1132                                                              [[maybe_unused]] ets_class cls, ets_method methodId,
1133                                                              const ets_value *args)
1134 {
1135     ETS_NAPI_DEBUG_TRACE(env);
1136     ETS_NAPI_ABORT_IF_NULL(obj);
1137     ETS_NAPI_ABORT_IF_NULL(methodId);
1138     CheckMethodReturnType(methodId, EtsType::CHAR);
1139     return GeneralMethodCall<false, ets_char, EtsChar>(env, obj, methodId, args);
1140 }
1141 
CallNonvirtualShortMethodList(EtsEnv * env,ets_object obj,ets_class cls,ets_method methodId,va_list args)1142 NO_UB_SANITIZE static ets_short CallNonvirtualShortMethodList(EtsEnv *env, ets_object obj,
1143                                                               [[maybe_unused]] ets_class cls, ets_method methodId,
1144                                                               va_list args)
1145 {
1146     ETS_NAPI_DEBUG_TRACE(env);
1147     ETS_NAPI_ABORT_IF_NULL(obj);
1148     ETS_NAPI_ABORT_IF_NULL(methodId);
1149     CheckMethodReturnType(methodId, EtsType::SHORT);
1150     return GeneralMethodCall<false, ets_short, EtsShort>(env, obj, methodId, args);
1151 }
1152 
CallNonvirtualShortMethod(EtsEnv * env,ets_object obj,ets_class cls,ets_method methodId,...)1153 NO_UB_SANITIZE static ets_short CallNonvirtualShortMethod(EtsEnv *env, ets_object obj, ets_class cls,
1154                                                           ets_method methodId, ...)
1155 {
1156     ETS_NAPI_DEBUG_TRACE(env);
1157     va_list args;
1158     va_start(args, methodId);
1159     ets_short res = CallNonvirtualShortMethodList(env, obj, cls, methodId, args);
1160     va_end(args);
1161     return res;
1162 }
1163 
CallNonvirtualShortMethodArray(EtsEnv * env,ets_object obj,ets_class cls,ets_method methodId,const ets_value * args)1164 NO_UB_SANITIZE static ets_short CallNonvirtualShortMethodArray(EtsEnv *env, ets_object obj,
1165                                                                [[maybe_unused]] ets_class cls, ets_method methodId,
1166                                                                const ets_value *args)
1167 {
1168     ETS_NAPI_DEBUG_TRACE(env);
1169     ETS_NAPI_ABORT_IF_NULL(obj);
1170     ETS_NAPI_ABORT_IF_NULL(methodId);
1171     CheckMethodReturnType(methodId, EtsType::SHORT);
1172     return GeneralMethodCall<false, ets_short, EtsShort>(env, obj, methodId, args);
1173 }
1174 
CallNonvirtualIntMethodList(EtsEnv * env,ets_object obj,ets_class cls,ets_method methodId,va_list args)1175 NO_UB_SANITIZE static ets_int CallNonvirtualIntMethodList(EtsEnv *env, ets_object obj, [[maybe_unused]] ets_class cls,
1176                                                           ets_method methodId, va_list args)
1177 {
1178     ETS_NAPI_DEBUG_TRACE(env);
1179     ETS_NAPI_ABORT_IF_NULL(obj);
1180     ETS_NAPI_ABORT_IF_NULL(methodId);
1181     CheckMethodReturnType(methodId, EtsType::INT);
1182     return GeneralMethodCall<false, ets_int, EtsInt>(env, obj, methodId, args);
1183 }
1184 
CallNonvirtualIntMethod(EtsEnv * env,ets_object obj,ets_class cls,ets_method methodId,...)1185 NO_UB_SANITIZE static ets_int CallNonvirtualIntMethod(EtsEnv *env, ets_object obj, ets_class cls, ets_method methodId,
1186                                                       ...)
1187 {
1188     ETS_NAPI_DEBUG_TRACE(env);
1189     va_list args;
1190     va_start(args, methodId);
1191     ets_int res = CallNonvirtualIntMethodList(env, obj, cls, methodId, args);
1192     va_end(args);
1193     return res;
1194 }
1195 
CallNonvirtualIntMethodArray(EtsEnv * env,ets_object obj,ets_class cls,ets_method methodId,const ets_value * args)1196 NO_UB_SANITIZE static ets_int CallNonvirtualIntMethodArray(EtsEnv *env, ets_object obj, [[maybe_unused]] ets_class cls,
1197                                                            ets_method methodId, const ets_value *args)
1198 {
1199     ETS_NAPI_DEBUG_TRACE(env);
1200     ETS_NAPI_ABORT_IF_NULL(obj);
1201     ETS_NAPI_ABORT_IF_NULL(methodId);
1202     CheckMethodReturnType(methodId, EtsType::INT);
1203     return GeneralMethodCall<false, ets_int, EtsInt>(env, obj, methodId, args);
1204 }
1205 
CallNonvirtualLongMethodList(EtsEnv * env,ets_object obj,ets_class cls,ets_method methodId,va_list args)1206 NO_UB_SANITIZE static ets_long CallNonvirtualLongMethodList(EtsEnv *env, ets_object obj, [[maybe_unused]] ets_class cls,
1207                                                             ets_method methodId, va_list args)
1208 {
1209     ETS_NAPI_DEBUG_TRACE(env);
1210     ETS_NAPI_ABORT_IF_NULL(obj);
1211     ETS_NAPI_ABORT_IF_NULL(methodId);
1212     CheckMethodReturnType(methodId, EtsType::LONG);
1213     return GeneralMethodCall<false, ets_long, EtsLong>(env, obj, methodId, args);
1214 }
1215 
CallNonvirtualLongMethod(EtsEnv * env,ets_object obj,ets_class cls,ets_method methodId,...)1216 NO_UB_SANITIZE static ets_long CallNonvirtualLongMethod(EtsEnv *env, ets_object obj, ets_class cls, ets_method methodId,
1217                                                         ...)
1218 {
1219     ETS_NAPI_DEBUG_TRACE(env);
1220     va_list args;
1221     va_start(args, methodId);
1222     ets_long res = CallNonvirtualLongMethodList(env, obj, cls, methodId, args);
1223     va_end(args);
1224     return res;
1225 }
1226 
CallNonvirtualLongMethodArray(EtsEnv * env,ets_object obj,ets_class cls,ets_method methodId,const ets_value * args)1227 NO_UB_SANITIZE static ets_long CallNonvirtualLongMethodArray(EtsEnv *env, ets_object obj,
1228                                                              [[maybe_unused]] ets_class cls, ets_method methodId,
1229                                                              const ets_value *args)
1230 {
1231     ETS_NAPI_DEBUG_TRACE(env);
1232     ETS_NAPI_ABORT_IF_NULL(obj);
1233     ETS_NAPI_ABORT_IF_NULL(methodId);
1234     CheckMethodReturnType(methodId, EtsType::LONG);
1235     return GeneralMethodCall<false, ets_long, EtsLong>(env, obj, methodId, args);
1236 }
1237 
CallNonvirtualFloatMethodList(EtsEnv * env,ets_object obj,ets_class cls,ets_method methodId,va_list args)1238 NO_UB_SANITIZE static ets_float CallNonvirtualFloatMethodList(EtsEnv *env, ets_object obj,
1239                                                               [[maybe_unused]] ets_class cls, ets_method methodId,
1240                                                               va_list args)
1241 {
1242     ETS_NAPI_DEBUG_TRACE(env);
1243     ETS_NAPI_ABORT_IF_NULL(obj);
1244     ETS_NAPI_ABORT_IF_NULL(methodId);
1245     CheckMethodReturnType(methodId, EtsType::FLOAT);
1246     return GeneralMethodCall<false, ets_float, EtsFloat>(env, obj, methodId, args);
1247 }
1248 
CallNonvirtualFloatMethod(EtsEnv * env,ets_object obj,ets_class cls,ets_method methodId,...)1249 NO_UB_SANITIZE static ets_float CallNonvirtualFloatMethod(EtsEnv *env, ets_object obj, ets_class cls,
1250                                                           ets_method methodId, ...)
1251 {
1252     ETS_NAPI_DEBUG_TRACE(env);
1253     va_list args;
1254     va_start(args, methodId);
1255     ets_float res = CallNonvirtualFloatMethodList(env, obj, cls, methodId, args);
1256     va_end(args);
1257     return res;
1258 }
1259 
CallNonvirtualFloatMethodArray(EtsEnv * env,ets_object obj,ets_class cls,ets_method methodId,const ets_value * args)1260 NO_UB_SANITIZE static ets_float CallNonvirtualFloatMethodArray(EtsEnv *env, ets_object obj,
1261                                                                [[maybe_unused]] ets_class cls, ets_method methodId,
1262                                                                const ets_value *args)
1263 {
1264     ETS_NAPI_DEBUG_TRACE(env);
1265     ETS_NAPI_ABORT_IF_NULL(obj);
1266     ETS_NAPI_ABORT_IF_NULL(methodId);
1267     CheckMethodReturnType(methodId, EtsType::FLOAT);
1268     return GeneralMethodCall<false, ets_float, EtsFloat>(env, obj, methodId, args);
1269 }
1270 
CallNonvirtualDoubleMethodList(EtsEnv * env,ets_object obj,ets_class cls,ets_method methodId,va_list args)1271 NO_UB_SANITIZE static ets_double CallNonvirtualDoubleMethodList(EtsEnv *env, ets_object obj,
1272                                                                 [[maybe_unused]] ets_class cls, ets_method methodId,
1273                                                                 va_list args)
1274 {
1275     ETS_NAPI_DEBUG_TRACE(env);
1276     ETS_NAPI_ABORT_IF_NULL(obj);
1277     ETS_NAPI_ABORT_IF_NULL(methodId);
1278     CheckMethodReturnType(methodId, EtsType::DOUBLE);
1279     return GeneralMethodCall<false, ets_double, EtsDouble>(env, obj, methodId, args);
1280 }
1281 
CallNonvirtualDoubleMethod(EtsEnv * env,ets_object obj,ets_class cls,ets_method methodId,...)1282 NO_UB_SANITIZE static ets_double CallNonvirtualDoubleMethod(EtsEnv *env, ets_object obj, ets_class cls,
1283                                                             ets_method methodId, ...)
1284 {
1285     ETS_NAPI_DEBUG_TRACE(env);
1286     va_list args;
1287     va_start(args, methodId);
1288     ets_double res = CallNonvirtualDoubleMethodList(env, obj, cls, methodId, args);
1289     va_end(args);
1290     return res;
1291 }
1292 
CallNonvirtualDoubleMethodArray(EtsEnv * env,ets_object obj,ets_class cls,ets_method methodId,const ets_value * args)1293 NO_UB_SANITIZE static ets_double CallNonvirtualDoubleMethodArray(EtsEnv *env, ets_object obj,
1294                                                                  [[maybe_unused]] ets_class cls, ets_method methodId,
1295                                                                  const ets_value *args)
1296 {
1297     ETS_NAPI_DEBUG_TRACE(env);
1298     ETS_NAPI_ABORT_IF_NULL(obj);
1299     ETS_NAPI_ABORT_IF_NULL(methodId);
1300     CheckMethodReturnType(methodId, EtsType::DOUBLE);
1301     return GeneralMethodCall<false, ets_double, EtsDouble>(env, obj, methodId, args);
1302 }
1303 
CallNonvirtualVoidMethodList(EtsEnv * env,ets_object obj,ets_class cls,ets_method methodId,va_list args)1304 NO_UB_SANITIZE static void CallNonvirtualVoidMethodList(EtsEnv *env, ets_object obj, [[maybe_unused]] ets_class cls,
1305                                                         ets_method methodId, va_list args)
1306 {
1307     ETS_NAPI_DEBUG_TRACE(env);
1308     ETS_NAPI_ABORT_IF_NULL(obj);
1309     ETS_NAPI_ABORT_IF_NULL(methodId);
1310     CheckMethodReturnType(methodId, EtsType::VOID);
1311     // Use any primitive type as template parameter and jist ignore the result
1312     GeneralMethodCall<false, ets_boolean, EtsBoolean>(env, obj, methodId, args);
1313 }
1314 
CallNonvirtualVoidMethod(EtsEnv * env,ets_object obj,ets_class cls,ets_method methodId,...)1315 NO_UB_SANITIZE static void CallNonvirtualVoidMethod(EtsEnv *env, ets_object obj, ets_class cls, ets_method methodId,
1316                                                     ...)
1317 {
1318     ETS_NAPI_DEBUG_TRACE(env);
1319     va_list args;
1320     va_start(args, methodId);
1321     CallNonvirtualVoidMethodList(env, obj, cls, methodId, args);
1322     va_end(args);
1323 }
1324 
CallNonvirtualVoidMethodArray(EtsEnv * env,ets_object obj,ets_class cls,ets_method methodId,const ets_value * args)1325 NO_UB_SANITIZE static void CallNonvirtualVoidMethodArray(EtsEnv *env, ets_object obj, [[maybe_unused]] ets_class cls,
1326                                                          ets_method methodId, const ets_value *args)
1327 {
1328     ETS_NAPI_DEBUG_TRACE(env);
1329     ETS_NAPI_ABORT_IF_NULL(obj);
1330     ETS_NAPI_ABORT_IF_NULL(methodId);
1331     CheckMethodReturnType(methodId, EtsType::VOID);
1332     // Use any primitive type as template parameter and jist ignore the result
1333     GeneralMethodCall<false, ets_boolean, EtsBoolean>(env, obj, methodId, args);
1334 }
1335 
1336 // NOLINTNEXTLINE(readability-identifier-naming)
Getp_field(EtsEnv * env,ets_class cls,const char * name,const char * sig)1337 NO_UB_SANITIZE static ets_field Getp_field(EtsEnv *env, ets_class cls, const char *name, const char *sig)
1338 {
1339     ETS_NAPI_DEBUG_TRACE(env);
1340     ETS_NAPI_ABORT_IF_NULL(cls);
1341     ETS_NAPI_ABORT_IF_NULL(name);
1342     ETS_NAPI_ABORT_IF_NULL(sig);
1343 
1344     ScopedManagedCodeFix s(PandaEtsNapiEnv::ToPandaEtsEnv(env));
1345     EtsClass *internalClass = GetInternalClass(env, cls, &s);
1346     if (internalClass == nullptr) {
1347         return nullptr;
1348     }
1349 
1350     EtsField *internalFieldId = internalClass->GetFieldIDByName(name, sig);
1351     if (internalFieldId == nullptr) {
1352         PandaStringStream ss;
1353         ss << "Field " << internalClass->GetRuntimeClass()->GetName() << "::" << name << " sig = " << sig
1354            << " is not found";
1355         s.ThrowNewException(EtsNapiException::NO_SUCH_FIELD, ss.str().c_str());
1356         return nullptr;
1357     }
1358 
1359     return ToEtsNapiType(internalFieldId);
1360 }
1361 
GetObjectField(EtsEnv * env,ets_object obj,ets_field pField)1362 NO_UB_SANITIZE static ets_object GetObjectField(EtsEnv *env, ets_object obj, ets_field pField)
1363 {
1364     ETS_NAPI_DEBUG_TRACE(env);
1365     ETS_NAPI_ABORT_IF_NULL(obj);
1366     ETS_NAPI_ABORT_IF_NULL(pField);
1367 
1368     EtsField *internalFieldId = ToInternalType(pField);
1369     ScopedManagedCodeFix s(PandaEtsNapiEnv::ToPandaEtsEnv(env));
1370     EtsObject *internalObject = s.ToInternalType(obj);
1371     EtsObject *retObj = internalObject->GetFieldObject(internalFieldId);
1372     if (retObj == nullptr) {
1373         return nullptr;
1374     }
1375     return reinterpret_cast<ets_object>(s.AddLocalRef(retObj));
1376 }
1377 
GetBooleanField(EtsEnv * env,ets_object obj,ets_field pField)1378 NO_UB_SANITIZE static ets_boolean GetBooleanField(EtsEnv *env, ets_object obj, ets_field pField)
1379 {
1380     ETS_NAPI_DEBUG_TRACE(env);
1381     return GetPrimitiveTypeField<ets_boolean, EtsBoolean>(env, obj, pField);
1382 }
1383 
GetByteField(EtsEnv * env,ets_object obj,ets_field pField)1384 NO_UB_SANITIZE static ets_byte GetByteField(EtsEnv *env, ets_object obj, ets_field pField)
1385 {
1386     ETS_NAPI_DEBUG_TRACE(env);
1387     return GetPrimitiveTypeField<ets_byte, EtsByte>(env, obj, pField);
1388 }
1389 
GetCharField(EtsEnv * env,ets_object obj,ets_field pField)1390 NO_UB_SANITIZE static ets_char GetCharField(EtsEnv *env, ets_object obj, ets_field pField)
1391 {
1392     ETS_NAPI_DEBUG_TRACE(env);
1393     return GetPrimitiveTypeField<ets_char, EtsChar>(env, obj, pField);
1394 }
1395 
GetShortField(EtsEnv * env,ets_object obj,ets_field pField)1396 NO_UB_SANITIZE static ets_short GetShortField(EtsEnv *env, ets_object obj, ets_field pField)
1397 {
1398     ETS_NAPI_DEBUG_TRACE(env);
1399     return GetPrimitiveTypeField<ets_short, EtsShort>(env, obj, pField);
1400 }
1401 
GetIntField(EtsEnv * env,ets_object obj,ets_field pField)1402 NO_UB_SANITIZE static ets_int GetIntField(EtsEnv *env, ets_object obj, ets_field pField)
1403 {
1404     ETS_NAPI_DEBUG_TRACE(env);
1405     return GetPrimitiveTypeField<ets_int, EtsInt>(env, obj, pField);
1406 }
1407 
GetLongField(EtsEnv * env,ets_object obj,ets_field pField)1408 NO_UB_SANITIZE static ets_long GetLongField(EtsEnv *env, ets_object obj, ets_field pField)
1409 {
1410     ETS_NAPI_DEBUG_TRACE(env);
1411     return GetPrimitiveTypeField<ets_long, EtsLong>(env, obj, pField);
1412 }
1413 
GetFloatField(EtsEnv * env,ets_object obj,ets_field pField)1414 NO_UB_SANITIZE static ets_float GetFloatField(EtsEnv *env, ets_object obj, ets_field pField)
1415 {
1416     ETS_NAPI_DEBUG_TRACE(env);
1417     return GetPrimitiveTypeField<ets_float, EtsFloat>(env, obj, pField);
1418 }
1419 
GetDoubleField(EtsEnv * env,ets_object obj,ets_field pField)1420 NO_UB_SANITIZE static ets_double GetDoubleField(EtsEnv *env, ets_object obj, ets_field pField)
1421 {
1422     ETS_NAPI_DEBUG_TRACE(env);
1423     return GetPrimitiveTypeField<ets_double, EtsDouble>(env, obj, pField);
1424 }
1425 
SetObjectField(EtsEnv * env,ets_object obj,ets_field pField,ets_object value)1426 NO_UB_SANITIZE static void SetObjectField(EtsEnv *env, ets_object obj, ets_field pField, ets_object value)
1427 {
1428     ETS_NAPI_DEBUG_TRACE(env);
1429     ETS_NAPI_ABORT_IF_NULL(obj);
1430     ETS_NAPI_ABORT_IF_NULL(pField);
1431 
1432     EtsField *internalFieldId = ToInternalType(pField);
1433     ScopedManagedCodeFix s(PandaEtsNapiEnv::ToPandaEtsEnv(env));
1434     EtsObject *internalValue = s.ToInternalType(value);
1435 
1436     s.ToInternalType(obj)->SetFieldObject(internalFieldId, internalValue);
1437 }
1438 
SetBooleanField(EtsEnv * env,ets_object obj,ets_field pField,ets_boolean value)1439 NO_UB_SANITIZE static void SetBooleanField(EtsEnv *env, ets_object obj, ets_field pField, ets_boolean value)
1440 {
1441     ETS_NAPI_DEBUG_TRACE(env);
1442     SetPrimitiveTypeField(env, obj, pField, value);
1443 }
1444 
SetByteField(EtsEnv * env,ets_object obj,ets_field pField,ets_byte value)1445 NO_UB_SANITIZE static void SetByteField(EtsEnv *env, ets_object obj, ets_field pField, ets_byte value)
1446 {
1447     ETS_NAPI_DEBUG_TRACE(env);
1448     SetPrimitiveTypeField(env, obj, pField, value);
1449 }
1450 
SetCharField(EtsEnv * env,ets_object obj,ets_field pField,ets_char value)1451 NO_UB_SANITIZE static void SetCharField(EtsEnv *env, ets_object obj, ets_field pField, ets_char value)
1452 {
1453     ETS_NAPI_DEBUG_TRACE(env);
1454     SetPrimitiveTypeField(env, obj, pField, value);
1455 }
1456 
SetShortField(EtsEnv * env,ets_object obj,ets_field pField,ets_short value)1457 NO_UB_SANITIZE static void SetShortField(EtsEnv *env, ets_object obj, ets_field pField, ets_short value)
1458 {
1459     ETS_NAPI_DEBUG_TRACE(env);
1460     SetPrimitiveTypeField(env, obj, pField, value);
1461 }
1462 
SetIntField(EtsEnv * env,ets_object obj,ets_field pField,ets_int value)1463 NO_UB_SANITIZE static void SetIntField(EtsEnv *env, ets_object obj, ets_field pField, ets_int value)
1464 {
1465     ETS_NAPI_DEBUG_TRACE(env);
1466     SetPrimitiveTypeField(env, obj, pField, value);
1467 }
1468 
SetLongField(EtsEnv * env,ets_object obj,ets_field pField,ets_long value)1469 NO_UB_SANITIZE static void SetLongField(EtsEnv *env, ets_object obj, ets_field pField, ets_long value)
1470 {
1471     ETS_NAPI_DEBUG_TRACE(env);
1472     SetPrimitiveTypeField(env, obj, pField, value);
1473 }
1474 
SetFloatField(EtsEnv * env,ets_object obj,ets_field pField,ets_float value)1475 NO_UB_SANITIZE static void SetFloatField(EtsEnv *env, ets_object obj, ets_field pField, ets_float value)
1476 {
1477     ETS_NAPI_DEBUG_TRACE(env);
1478     SetPrimitiveTypeField(env, obj, pField, value);
1479 }
1480 
SetDoubleField(EtsEnv * env,ets_object obj,ets_field pField,ets_double value)1481 NO_UB_SANITIZE static void SetDoubleField(EtsEnv *env, ets_object obj, ets_field pField, ets_double value)
1482 {
1483     ETS_NAPI_DEBUG_TRACE(env);
1484     SetPrimitiveTypeField(env, obj, pField, value);
1485 }
1486 
1487 // NOLINTNEXTLINE(readability-identifier-naming)
GetStaticp_method(EtsEnv * env,ets_class cls,const char * name,const char * sig)1488 NO_UB_SANITIZE static ets_method GetStaticp_method(EtsEnv *env, ets_class cls, const char *name, const char *sig)
1489 {
1490     ETS_NAPI_DEBUG_TRACE(env);
1491     ETS_NAPI_ABORT_IF_NULL(cls);
1492     ETS_NAPI_ABORT_IF_NULL(name);
1493 
1494     ScopedManagedCodeFix s(PandaEtsNapiEnv::ToPandaEtsEnv(env));
1495     EtsClass *klass = GetInternalClass(env, cls, &s);
1496     if (klass == nullptr) {
1497         return nullptr;
1498     }
1499 
1500     EtsMethod *method = (sig == nullptr ? klass->GetMethod(name) : klass->GetMethod(name, sig));
1501     if (method == nullptr || !method->IsStatic()) {
1502         PandaStringStream ss;
1503         ss << "Static method " << klass->GetRuntimeClass()->GetName() << "::" << name
1504            << " sig = " << (sig == nullptr ? "nullptr" : sig) << " is not found";
1505         s.ThrowNewException(EtsNapiException::NO_SUCH_METHOD, ss.str().c_str());
1506         return nullptr;
1507     }
1508 
1509     return ToEtsNapiType(method);
1510 }
1511 
CallStaticObjectMethodList(EtsEnv * env,ets_class cls,ets_method methodId,va_list args)1512 NO_UB_SANITIZE static ets_object CallStaticObjectMethodList(EtsEnv *env, [[maybe_unused]] ets_class cls,
1513                                                             ets_method methodId, va_list args)
1514 {
1515     ETS_NAPI_DEBUG_TRACE(env);
1516     ETS_NAPI_ABORT_IF_NULL(methodId);
1517     CheckMethodReturnType(methodId, EtsType::OBJECT);
1518     return GeneralMethodCall<false, ets_object, ets_object>(env, nullptr, methodId, args);
1519 }
1520 
CallStaticObjectMethod(EtsEnv * env,ets_class cls,ets_method methodId,...)1521 NO_UB_SANITIZE static ets_object CallStaticObjectMethod(EtsEnv *env, ets_class cls, ets_method methodId, ...)
1522 {
1523     ETS_NAPI_DEBUG_TRACE(env);
1524     va_list args;
1525     va_start(args, methodId);
1526     ets_object res = CallStaticObjectMethodList(env, cls, methodId, args);
1527     va_end(args);
1528     return res;
1529 }
1530 
CallStaticObjectMethodArray(EtsEnv * env,ets_class cls,ets_method methodId,ets_value * args)1531 NO_UB_SANITIZE static ets_object CallStaticObjectMethodArray(EtsEnv *env, [[maybe_unused]] ets_class cls,
1532                                                              ets_method methodId, ets_value *args)
1533 {
1534     ETS_NAPI_DEBUG_TRACE(env);
1535     ETS_NAPI_ABORT_IF_NULL(methodId);
1536     CheckMethodReturnType(methodId, EtsType::OBJECT);
1537     return GeneralMethodCall<false, ets_object, ets_object>(env, nullptr, methodId, args);
1538 }
1539 
CallStaticBooleanMethodList(EtsEnv * env,ets_class cls,ets_method methodId,va_list args)1540 NO_UB_SANITIZE static ets_boolean CallStaticBooleanMethodList(EtsEnv *env, [[maybe_unused]] ets_class cls,
1541                                                               ets_method methodId, va_list args)
1542 {
1543     ETS_NAPI_DEBUG_TRACE(env);
1544     ETS_NAPI_ABORT_IF_NULL(methodId);
1545     CheckMethodReturnType(methodId, EtsType::BOOLEAN);
1546     return GeneralMethodCall<false, ets_boolean, EtsBoolean>(env, nullptr, methodId, args);
1547 }
1548 
CallStaticBooleanMethod(EtsEnv * env,ets_class cls,ets_method methodId,...)1549 NO_UB_SANITIZE static ets_boolean CallStaticBooleanMethod(EtsEnv *env, ets_class cls, ets_method methodId, ...)
1550 {
1551     ETS_NAPI_DEBUG_TRACE(env);
1552     va_list args;
1553     va_start(args, methodId);
1554     ets_boolean res = CallStaticBooleanMethodList(env, cls, methodId, args);
1555     va_end(args);
1556     return res;
1557 }
1558 
CallStaticBooleanMethodArray(EtsEnv * env,ets_class cls,ets_method methodId,ets_value * args)1559 NO_UB_SANITIZE static ets_boolean CallStaticBooleanMethodArray(EtsEnv *env, [[maybe_unused]] ets_class cls,
1560                                                                ets_method methodId, ets_value *args)
1561 {
1562     ETS_NAPI_DEBUG_TRACE(env);
1563     ETS_NAPI_ABORT_IF_NULL(methodId);
1564     CheckMethodReturnType(methodId, EtsType::BOOLEAN);
1565     return GeneralMethodCall<false, ets_boolean, EtsBoolean>(env, nullptr, methodId, args);
1566 }
1567 
CallStaticByteMethodList(EtsEnv * env,ets_class cls,ets_method methodId,va_list args)1568 NO_UB_SANITIZE static ets_byte CallStaticByteMethodList(EtsEnv *env, [[maybe_unused]] ets_class cls,
1569                                                         ets_method methodId, va_list args)
1570 {
1571     ETS_NAPI_DEBUG_TRACE(env);
1572     ETS_NAPI_ABORT_IF_NULL(methodId);
1573     CheckMethodReturnType(methodId, EtsType::BYTE);
1574     return GeneralMethodCall<false, ets_byte, EtsByte>(env, nullptr, methodId, args);
1575 }
1576 
CallStaticByteMethod(EtsEnv * env,ets_class cls,ets_method methodId,...)1577 NO_UB_SANITIZE static ets_byte CallStaticByteMethod(EtsEnv *env, ets_class cls, ets_method methodId, ...)
1578 {
1579     ETS_NAPI_DEBUG_TRACE(env);
1580     va_list args;
1581     va_start(args, methodId);
1582     ets_byte res = CallStaticByteMethodList(env, cls, methodId, args);
1583     va_end(args);
1584     return res;
1585 }
1586 
CallStaticByteMethodArray(EtsEnv * env,ets_class cls,ets_method methodId,ets_value * args)1587 NO_UB_SANITIZE static ets_byte CallStaticByteMethodArray(EtsEnv *env, [[maybe_unused]] ets_class cls,
1588                                                          ets_method methodId, ets_value *args)
1589 {
1590     ETS_NAPI_DEBUG_TRACE(env);
1591     ETS_NAPI_ABORT_IF_NULL(methodId);
1592     CheckMethodReturnType(methodId, EtsType::BYTE);
1593     return GeneralMethodCall<false, ets_byte, EtsByte>(env, nullptr, methodId, args);
1594 }
1595 
CallStaticCharMethodList(EtsEnv * env,ets_class cls,ets_method methodId,va_list args)1596 NO_UB_SANITIZE static ets_char CallStaticCharMethodList(EtsEnv *env, [[maybe_unused]] ets_class cls,
1597                                                         ets_method methodId, va_list args)
1598 {
1599     ETS_NAPI_DEBUG_TRACE(env);
1600     ETS_NAPI_ABORT_IF_NULL(methodId);
1601     CheckMethodReturnType(methodId, EtsType::CHAR);
1602     return GeneralMethodCall<false, ets_char, EtsChar>(env, nullptr, methodId, args);
1603 }
1604 
CallStaticCharMethod(EtsEnv * env,ets_class cls,ets_method methodId,...)1605 NO_UB_SANITIZE static ets_char CallStaticCharMethod(EtsEnv *env, ets_class cls, ets_method methodId, ...)
1606 {
1607     ETS_NAPI_DEBUG_TRACE(env);
1608     va_list args;
1609     va_start(args, methodId);
1610     ets_char res = CallStaticCharMethodList(env, cls, methodId, args);
1611     va_end(args);
1612     return res;
1613 }
1614 
CallStaticCharMethodArray(EtsEnv * env,ets_class cls,ets_method methodId,ets_value * args)1615 NO_UB_SANITIZE static ets_char CallStaticCharMethodArray(EtsEnv *env, [[maybe_unused]] ets_class cls,
1616                                                          ets_method methodId, ets_value *args)
1617 {
1618     ETS_NAPI_DEBUG_TRACE(env);
1619     ETS_NAPI_ABORT_IF_NULL(methodId);
1620     CheckMethodReturnType(methodId, EtsType::CHAR);
1621     return GeneralMethodCall<false, ets_char, EtsChar>(env, nullptr, methodId, args);
1622 }
1623 
CallStaticShortMethodList(EtsEnv * env,ets_class cls,ets_method methodId,va_list args)1624 NO_UB_SANITIZE static ets_short CallStaticShortMethodList(EtsEnv *env, [[maybe_unused]] ets_class cls,
1625                                                           ets_method methodId, va_list args)
1626 {
1627     ETS_NAPI_DEBUG_TRACE(env);
1628     ETS_NAPI_ABORT_IF_NULL(methodId);
1629     CheckMethodReturnType(methodId, EtsType::SHORT);
1630     return GeneralMethodCall<false, ets_short, EtsShort>(env, nullptr, methodId, args);
1631 }
1632 
CallStaticShortMethod(EtsEnv * env,ets_class cls,ets_method methodId,...)1633 NO_UB_SANITIZE static ets_short CallStaticShortMethod(EtsEnv *env, ets_class cls, ets_method methodId, ...)
1634 {
1635     ETS_NAPI_DEBUG_TRACE(env);
1636     va_list args;
1637     va_start(args, methodId);
1638     ets_short res = CallStaticShortMethodList(env, cls, methodId, args);
1639     va_end(args);
1640     return res;
1641 }
1642 
CallStaticShortMethodArray(EtsEnv * env,ets_class cls,ets_method methodId,ets_value * args)1643 NO_UB_SANITIZE static ets_short CallStaticShortMethodArray(EtsEnv *env, [[maybe_unused]] ets_class cls,
1644                                                            ets_method methodId, ets_value *args)
1645 {
1646     ETS_NAPI_DEBUG_TRACE(env);
1647     ETS_NAPI_ABORT_IF_NULL(methodId);
1648     CheckMethodReturnType(methodId, EtsType::SHORT);
1649     return GeneralMethodCall<false, ets_short, EtsShort>(env, nullptr, methodId, args);
1650 }
1651 
CallStaticIntMethodList(EtsEnv * env,ets_class cls,ets_method methodId,va_list args)1652 NO_UB_SANITIZE static ets_int CallStaticIntMethodList(EtsEnv *env, [[maybe_unused]] ets_class cls, ets_method methodId,
1653                                                       va_list args)
1654 {
1655     ETS_NAPI_DEBUG_TRACE(env);
1656     ETS_NAPI_ABORT_IF_NULL(methodId);
1657     CheckMethodReturnType(methodId, EtsType::INT);
1658     return GeneralMethodCall<false, ets_int, EtsInt>(env, nullptr, methodId, args);
1659 }
1660 
CallStaticIntMethod(EtsEnv * env,ets_class cls,ets_method methodId,...)1661 NO_UB_SANITIZE static ets_int CallStaticIntMethod(EtsEnv *env, ets_class cls, ets_method methodId, ...)
1662 {
1663     ETS_NAPI_DEBUG_TRACE(env);
1664     va_list args;
1665     va_start(args, methodId);
1666     ets_int res = CallStaticIntMethodList(env, cls, methodId, args);
1667     va_end(args);
1668     return res;
1669 }
1670 
CallStaticIntMethodArray(EtsEnv * env,ets_class cls,ets_method methodId,ets_value * args)1671 NO_UB_SANITIZE static ets_int CallStaticIntMethodArray(EtsEnv *env, [[maybe_unused]] ets_class cls, ets_method methodId,
1672                                                        ets_value *args)
1673 {
1674     ETS_NAPI_DEBUG_TRACE(env);
1675     ETS_NAPI_ABORT_IF_NULL(methodId);
1676     CheckMethodReturnType(methodId, EtsType::INT);
1677     return GeneralMethodCall<false, ets_int, EtsInt>(env, nullptr, methodId, args);
1678 }
1679 
CallStaticLongMethodList(EtsEnv * env,ets_class cls,ets_method methodId,va_list args)1680 NO_UB_SANITIZE static ets_long CallStaticLongMethodList(EtsEnv *env, [[maybe_unused]] ets_class cls,
1681                                                         ets_method methodId, va_list args)
1682 {
1683     ETS_NAPI_DEBUG_TRACE(env);
1684     ETS_NAPI_ABORT_IF_NULL(methodId);
1685     CheckMethodReturnType(methodId, EtsType::LONG);
1686     return GeneralMethodCall<false, ets_long, EtsLong>(env, nullptr, methodId, args);
1687 }
1688 
CallStaticLongMethod(EtsEnv * env,ets_class cls,ets_method methodId,...)1689 NO_UB_SANITIZE static ets_long CallStaticLongMethod(EtsEnv *env, ets_class cls, ets_method methodId, ...)
1690 {
1691     ETS_NAPI_DEBUG_TRACE(env);
1692     va_list args;
1693     va_start(args, methodId);
1694     ets_long res = CallStaticLongMethodList(env, cls, methodId, args);
1695     va_end(args);
1696     return res;
1697 }
1698 
CallStaticLongMethodArray(EtsEnv * env,ets_class cls,ets_method methodId,ets_value * args)1699 NO_UB_SANITIZE static ets_long CallStaticLongMethodArray(EtsEnv *env, [[maybe_unused]] ets_class cls,
1700                                                          ets_method methodId, ets_value *args)
1701 {
1702     ETS_NAPI_DEBUG_TRACE(env);
1703     ETS_NAPI_ABORT_IF_NULL(methodId);
1704     CheckMethodReturnType(methodId, EtsType::LONG);
1705     return GeneralMethodCall<false, ets_long, EtsLong>(env, nullptr, methodId, args);
1706 }
1707 
CallStaticFloatMethodList(EtsEnv * env,ets_class cls,ets_method methodId,va_list args)1708 NO_UB_SANITIZE static ets_float CallStaticFloatMethodList(EtsEnv *env, [[maybe_unused]] ets_class cls,
1709                                                           ets_method methodId, va_list args)
1710 {
1711     ETS_NAPI_DEBUG_TRACE(env);
1712     ETS_NAPI_ABORT_IF_NULL(methodId);
1713     CheckMethodReturnType(methodId, EtsType::FLOAT);
1714     return GeneralMethodCall<false, ets_float, EtsFloat>(env, nullptr, methodId, args);
1715 }
1716 
CallStaticFloatMethod(EtsEnv * env,ets_class cls,ets_method methodId,...)1717 NO_UB_SANITIZE static ets_float CallStaticFloatMethod(EtsEnv *env, ets_class cls, ets_method methodId, ...)
1718 {
1719     ETS_NAPI_DEBUG_TRACE(env);
1720     va_list args;
1721     va_start(args, methodId);
1722     ets_float res = CallStaticFloatMethodList(env, cls, methodId, args);
1723     va_end(args);
1724     return res;
1725 }
1726 
CallStaticFloatMethodArray(EtsEnv * env,ets_class cls,ets_method methodId,ets_value * args)1727 NO_UB_SANITIZE static ets_float CallStaticFloatMethodArray(EtsEnv *env, [[maybe_unused]] ets_class cls,
1728                                                            ets_method methodId, ets_value *args)
1729 {
1730     ETS_NAPI_DEBUG_TRACE(env);
1731     ETS_NAPI_ABORT_IF_NULL(methodId);
1732     CheckMethodReturnType(methodId, EtsType::FLOAT);
1733     return GeneralMethodCall<false, ets_float, EtsFloat>(env, nullptr, methodId, args);
1734 }
1735 
CallStaticDoubleMethodList(EtsEnv * env,ets_class cls,ets_method methodId,va_list args)1736 NO_UB_SANITIZE static ets_double CallStaticDoubleMethodList(EtsEnv *env, [[maybe_unused]] ets_class cls,
1737                                                             ets_method methodId, va_list args)
1738 {
1739     ETS_NAPI_DEBUG_TRACE(env);
1740     ETS_NAPI_ABORT_IF_NULL(methodId);
1741     CheckMethodReturnType(methodId, EtsType::DOUBLE);
1742     return GeneralMethodCall<false, ets_double, EtsDouble>(env, nullptr, methodId, args);
1743 }
1744 
CallStaticDoubleMethod(EtsEnv * env,ets_class cls,ets_method methodId,...)1745 NO_UB_SANITIZE static ets_double CallStaticDoubleMethod(EtsEnv *env, ets_class cls, ets_method methodId, ...)
1746 {
1747     ETS_NAPI_DEBUG_TRACE(env);
1748     va_list args;
1749     va_start(args, methodId);
1750     ets_double res = CallStaticDoubleMethodList(env, cls, methodId, args);
1751     va_end(args);
1752     return res;
1753 }
1754 
CallStaticDoubleMethodArray(EtsEnv * env,ets_class cls,ets_method methodId,ets_value * args)1755 NO_UB_SANITIZE static ets_double CallStaticDoubleMethodArray(EtsEnv *env, [[maybe_unused]] ets_class cls,
1756                                                              ets_method methodId, ets_value *args)
1757 {
1758     ETS_NAPI_DEBUG_TRACE(env);
1759     ETS_NAPI_ABORT_IF_NULL(methodId);
1760     CheckMethodReturnType(methodId, EtsType::DOUBLE);
1761     return GeneralMethodCall<false, ets_double, EtsDouble>(env, nullptr, methodId, args);
1762 }
1763 
CallStaticVoidMethodList(EtsEnv * env,ets_class cls,ets_method methodId,va_list args)1764 NO_UB_SANITIZE static void CallStaticVoidMethodList(EtsEnv *env, [[maybe_unused]] ets_class cls, ets_method methodId,
1765                                                     va_list args)
1766 {
1767     ETS_NAPI_DEBUG_TRACE(env);
1768     ETS_NAPI_ABORT_IF_NULL(methodId);
1769     CheckMethodReturnType(methodId, EtsType::VOID);
1770     // Use any primitive type as template parameter and just ignore the result
1771     GeneralMethodCall<false, ets_boolean, EtsBoolean>(env, nullptr, methodId, args);
1772 }
1773 
CallStaticVoidMethod(EtsEnv * env,ets_class cls,ets_method methodId,...)1774 NO_UB_SANITIZE static void CallStaticVoidMethod(EtsEnv *env, ets_class cls, ets_method methodId, ...)
1775 {
1776     ETS_NAPI_DEBUG_TRACE(env);
1777     va_list args;
1778     va_start(args, methodId);
1779     CallStaticVoidMethodList(env, cls, methodId, args);
1780     va_end(args);
1781 }
1782 
CallStaticVoidMethodArray(EtsEnv * env,ets_class cls,ets_method methodId,ets_value * args)1783 NO_UB_SANITIZE static void CallStaticVoidMethodArray(EtsEnv *env, [[maybe_unused]] ets_class cls, ets_method methodId,
1784                                                      ets_value *args)
1785 {
1786     ETS_NAPI_DEBUG_TRACE(env);
1787     ETS_NAPI_ABORT_IF_NULL(methodId);
1788     CheckMethodReturnType(methodId, EtsType::VOID);
1789     // Use any primitive type as template parameter and just ignore the result
1790     GeneralMethodCall<false, ets_boolean, EtsBoolean>(env, nullptr, methodId, args);
1791 }
1792 
1793 // NOLINTNEXTLINE(readability-identifier-naming)
GetStaticp_field(EtsEnv * env,ets_class cls,const char * name,const char * sig)1794 NO_UB_SANITIZE static ets_field GetStaticp_field(EtsEnv *env, ets_class cls, const char *name, const char *sig)
1795 {
1796     ETS_NAPI_DEBUG_TRACE(env);
1797     ETS_NAPI_ABORT_IF_NULL(cls);
1798     ETS_NAPI_ABORT_IF_NULL(name);
1799     ETS_NAPI_ABORT_IF_NULL(sig);
1800 
1801     ScopedManagedCodeFix s(PandaEtsNapiEnv::ToPandaEtsEnv(env));
1802     EtsClass *internalClass = GetInternalClass(env, cls, &s);
1803     if (internalClass == nullptr) {
1804         return nullptr;
1805     }
1806 
1807     EtsField *internalFieldId = internalClass->GetStaticFieldIDByName(name, sig);
1808     if (internalFieldId == nullptr) {
1809         PandaStringStream ss;
1810         ss << "Static field " << internalClass->GetRuntimeClass()->GetName() << "::" << name << " sig = " << sig
1811            << " is not found";
1812         s.ThrowNewException(EtsNapiException::NO_SUCH_FIELD, ss.str().c_str());
1813         return nullptr;
1814     }
1815 
1816     return ToEtsNapiType(internalFieldId);
1817 }
1818 
GetStaticObjectField(EtsEnv * env,ets_class unusedCls,ets_field pField)1819 NO_UB_SANITIZE static ets_object GetStaticObjectField(EtsEnv *env, [[maybe_unused]] ets_class unusedCls,
1820                                                       ets_field pField)
1821 {
1822     ETS_NAPI_DEBUG_TRACE(env);
1823     ETS_NAPI_ABORT_IF_NULL(pField);
1824 
1825     EtsField *internalFieldId = ToInternalType(pField);
1826     ScopedManagedCodeFix s(PandaEtsNapiEnv::ToPandaEtsEnv(env));
1827     EtsClass *internalClass = internalFieldId->GetDeclaringClass();
1828     EtsObject *retObj = internalClass->GetStaticFieldObject(internalFieldId);
1829     if (retObj == nullptr) {
1830         return nullptr;
1831     }
1832     return reinterpret_cast<ets_object>(s.AddLocalRef(retObj));
1833 }
1834 
GetStaticBooleanField(EtsEnv * env,ets_class unusedCls,ets_field pField)1835 NO_UB_SANITIZE static ets_boolean GetStaticBooleanField(EtsEnv *env, [[maybe_unused]] ets_class unusedCls,
1836                                                         ets_field pField)
1837 {
1838     ETS_NAPI_DEBUG_TRACE(env);
1839     return GetPrimitiveTypeStaticField<ets_boolean, EtsBoolean>(env, pField);
1840 }
1841 
GetStaticByteField(EtsEnv * env,ets_class unusedCls,ets_field pField)1842 NO_UB_SANITIZE static ets_byte GetStaticByteField(EtsEnv *env, [[maybe_unused]] ets_class unusedCls, ets_field pField)
1843 {
1844     ETS_NAPI_DEBUG_TRACE(env);
1845     return GetPrimitiveTypeStaticField<ets_byte, EtsByte>(env, pField);
1846 }
1847 
GetStaticCharField(EtsEnv * env,ets_class unusedCls,ets_field pField)1848 NO_UB_SANITIZE static ets_char GetStaticCharField(EtsEnv *env, [[maybe_unused]] ets_class unusedCls, ets_field pField)
1849 {
1850     ETS_NAPI_DEBUG_TRACE(env);
1851     return GetPrimitiveTypeStaticField<ets_char, EtsChar>(env, pField);
1852 }
1853 
GetStaticShortField(EtsEnv * env,ets_class unusedCls,ets_field pField)1854 NO_UB_SANITIZE static ets_short GetStaticShortField(EtsEnv *env, [[maybe_unused]] ets_class unusedCls, ets_field pField)
1855 {
1856     ETS_NAPI_DEBUG_TRACE(env);
1857     return GetPrimitiveTypeStaticField<ets_short, EtsShort>(env, pField);
1858 }
1859 
GetStaticIntField(EtsEnv * env,ets_class unusedCls,ets_field pField)1860 NO_UB_SANITIZE static ets_int GetStaticIntField(EtsEnv *env, [[maybe_unused]] ets_class unusedCls, ets_field pField)
1861 {
1862     ETS_NAPI_DEBUG_TRACE(env);
1863     return GetPrimitiveTypeStaticField<ets_int, EtsInt>(env, pField);
1864 }
1865 
GetStaticLongField(EtsEnv * env,ets_class unusedCls,ets_field pField)1866 NO_UB_SANITIZE static ets_long GetStaticLongField(EtsEnv *env, [[maybe_unused]] ets_class unusedCls, ets_field pField)
1867 {
1868     ETS_NAPI_DEBUG_TRACE(env);
1869     return GetPrimitiveTypeStaticField<ets_long, EtsLong>(env, pField);
1870 }
1871 
GetStaticFloatField(EtsEnv * env,ets_class unusedCls,ets_field pField)1872 NO_UB_SANITIZE static ets_float GetStaticFloatField(EtsEnv *env, [[maybe_unused]] ets_class unusedCls, ets_field pField)
1873 {
1874     ETS_NAPI_DEBUG_TRACE(env);
1875     return GetPrimitiveTypeStaticField<ets_float, EtsFloat>(env, pField);
1876 }
1877 
GetStaticDoubleField(EtsEnv * env,ets_class unusedCls,ets_field pField)1878 NO_UB_SANITIZE static ets_double GetStaticDoubleField(EtsEnv *env, [[maybe_unused]] ets_class unusedCls,
1879                                                       ets_field pField)
1880 {
1881     ETS_NAPI_DEBUG_TRACE(env);
1882     return GetPrimitiveTypeStaticField<ets_double, EtsDouble>(env, pField);
1883 }
1884 
SetStaticObjectField(EtsEnv * env,ets_class unusedCls,ets_field pField,ets_object value)1885 NO_UB_SANITIZE static void SetStaticObjectField(EtsEnv *env, [[maybe_unused]] ets_class unusedCls, ets_field pField,
1886                                                 ets_object value)
1887 {
1888     ETS_NAPI_DEBUG_TRACE(env);
1889     ETS_NAPI_ABORT_IF_NULL(pField);
1890 
1891     EtsField *internalFieldId = ToInternalType(pField);
1892     ScopedManagedCodeFix s(PandaEtsNapiEnv::ToPandaEtsEnv(env));
1893     EtsObject *internalValue = s.ToInternalType(value);
1894 
1895     internalFieldId->GetDeclaringClass()->SetStaticFieldObject(internalFieldId, internalValue);
1896 }
1897 
SetStaticBooleanField(EtsEnv * env,ets_class unusedCls,ets_field pField,ets_boolean value)1898 NO_UB_SANITIZE static void SetStaticBooleanField(EtsEnv *env, [[maybe_unused]] ets_class unusedCls, ets_field pField,
1899                                                  ets_boolean value)
1900 {
1901     ETS_NAPI_DEBUG_TRACE(env);
1902     SetPrimitiveTypeStaticField(env, pField, value);
1903 }
1904 
SetStaticByteField(EtsEnv * env,ets_class unusedCls,ets_field pField,ets_byte value)1905 NO_UB_SANITIZE static void SetStaticByteField(EtsEnv *env, [[maybe_unused]] ets_class unusedCls, ets_field pField,
1906                                               ets_byte value)
1907 {
1908     ETS_NAPI_DEBUG_TRACE(env);
1909     SetPrimitiveTypeStaticField(env, pField, value);
1910 }
1911 
SetStaticCharField(EtsEnv * env,ets_class unusedCls,ets_field pField,ets_char value)1912 NO_UB_SANITIZE static void SetStaticCharField(EtsEnv *env, [[maybe_unused]] ets_class unusedCls, ets_field pField,
1913                                               ets_char value)
1914 {
1915     ETS_NAPI_DEBUG_TRACE(env);
1916     SetPrimitiveTypeStaticField(env, pField, value);
1917 }
1918 
SetStaticShortField(EtsEnv * env,ets_class unusedCls,ets_field pField,ets_short value)1919 NO_UB_SANITIZE static void SetStaticShortField(EtsEnv *env, [[maybe_unused]] ets_class unusedCls, ets_field pField,
1920                                                ets_short value)
1921 {
1922     ETS_NAPI_DEBUG_TRACE(env);
1923     SetPrimitiveTypeStaticField(env, pField, value);
1924 }
1925 
SetStaticIntField(EtsEnv * env,ets_class unusedCls,ets_field pField,ets_int value)1926 NO_UB_SANITIZE static void SetStaticIntField(EtsEnv *env, [[maybe_unused]] ets_class unusedCls, ets_field pField,
1927                                              ets_int value)
1928 {
1929     ETS_NAPI_DEBUG_TRACE(env);
1930     SetPrimitiveTypeStaticField(env, pField, value);
1931 }
1932 
SetStaticLongField(EtsEnv * env,ets_class unusedCls,ets_field pField,ets_long value)1933 NO_UB_SANITIZE static void SetStaticLongField(EtsEnv *env, [[maybe_unused]] ets_class unusedCls, ets_field pField,
1934                                               ets_long value)
1935 {
1936     ETS_NAPI_DEBUG_TRACE(env);
1937     SetPrimitiveTypeStaticField(env, pField, value);
1938 }
1939 
SetStaticFloatField(EtsEnv * env,ets_class unusedCls,ets_field pField,ets_float value)1940 NO_UB_SANITIZE static void SetStaticFloatField(EtsEnv *env, [[maybe_unused]] ets_class unusedCls, ets_field pField,
1941                                                ets_float value)
1942 {
1943     ETS_NAPI_DEBUG_TRACE(env);
1944     SetPrimitiveTypeStaticField(env, pField, value);
1945 }
1946 
SetStaticDoubleField(EtsEnv * env,ets_class unusedCls,ets_field pField,ets_double value)1947 NO_UB_SANITIZE static void SetStaticDoubleField(EtsEnv *env, [[maybe_unused]] ets_class unusedCls, ets_field pField,
1948                                                 ets_double value)
1949 {
1950     ETS_NAPI_DEBUG_TRACE(env);
1951     SetPrimitiveTypeStaticField(env, pField, value);
1952 }
1953 
NewString(EtsEnv * env,const ets_char * unicodeChars,ets_size len)1954 NO_UB_SANITIZE static ets_string NewString(EtsEnv *env, const ets_char *unicodeChars, ets_size len)
1955 {
1956     ETS_NAPI_DEBUG_TRACE(env);
1957     if (unicodeChars == nullptr) {
1958         ETS_NAPI_ABORT_IF_NE(len, 0);
1959     }
1960     ETS_NAPI_ABORT_IF_LZ(len);
1961 
1962     ScopedManagedCodeFix s(PandaEtsNapiEnv::ToPandaEtsEnv(env));
1963     auto internalString = EtsString::CreateFromUtf16(unicodeChars, len);
1964     if (internalString == nullptr) {
1965         return nullptr;
1966     }
1967     return reinterpret_cast<ets_string>(s.AddLocalRef(reinterpret_cast<EtsObject *>(internalString)));
1968 }
1969 
GetStringLength(EtsEnv * env,ets_string string)1970 NO_UB_SANITIZE static ets_size GetStringLength(EtsEnv *env, ets_string string)
1971 {
1972     ETS_NAPI_DEBUG_TRACE(env);
1973     ETS_NAPI_ABORT_IF_NULL(string);
1974     ScopedManagedCodeFix s(PandaEtsNapiEnv::ToPandaEtsEnv(env));
1975     auto internalString = s.ToInternalType(string);
1976     return static_cast<ets_size>(internalString->GetLength());
1977 }
1978 
GetStringChars(EtsEnv * env,ets_string string,ets_boolean * isCopy)1979 NO_UB_SANITIZE static const ets_char *GetStringChars(EtsEnv *env, ets_string string, ets_boolean *isCopy)
1980 {
1981     ETS_NAPI_DEBUG_TRACE(env);
1982     ETS_NAPI_ABORT_IF_NULL(string);
1983     if (isCopy != nullptr) {
1984         *isCopy = ETS_TRUE;
1985     }
1986     ScopedManagedCodeFix s(PandaEtsNapiEnv::ToPandaEtsEnv(env));
1987     auto internalString = s.ToInternalType(string);
1988     size_t len = internalString->GetUtf16Length();
1989     void *buf = EtsAlloc(len * sizeof(uint16_t));
1990     if (buf == nullptr) {
1991         LOG(ERROR, ETS_NAPI) << __func__ << ": cannot copy string";
1992         return nullptr;
1993     }
1994     internalString->CopyDataUtf16(buf, len);
1995     return static_cast<ets_char *>(buf);
1996 }
1997 
ReleaseStringChars(EtsEnv * env,ets_string string,const ets_char * chars)1998 NO_UB_SANITIZE static void ReleaseStringChars([[maybe_unused]] EtsEnv *env, ets_string string, const ets_char *chars)
1999 {
2000     ETS_NAPI_DEBUG_TRACE(env);
2001     ETS_NAPI_ABORT_IF_NULL(string);
2002     EtsFree(chars);
2003 }
2004 
NewStringUTF(EtsEnv * env,const char * bytes)2005 NO_UB_SANITIZE static ets_string NewStringUTF(EtsEnv *env, const char *bytes)
2006 {
2007     ETS_NAPI_DEBUG_TRACE(env);
2008 
2009     // NOTE(m.morozov): check if this right solution
2010     if (bytes == nullptr) {
2011         return nullptr;
2012     }
2013 
2014     ScopedManagedCodeFix s(PandaEtsNapiEnv::ToPandaEtsEnv(env));
2015     // NOTE(m.morozov): check after mutf8 vs utf8 decision
2016     auto internalString = EtsString::CreateFromMUtf8(bytes);
2017     if (internalString == nullptr) {
2018         s.ThrowNewException(EtsNapiException::OUT_OF_MEMORY, "Could not allocate memory for string");
2019         return nullptr;
2020     }
2021     return reinterpret_cast<ets_string>(s.AddLocalRef(reinterpret_cast<EtsObject *>(internalString)));
2022 }
2023 
GetStringUTFLength(EtsEnv * env,ets_string string)2024 NO_UB_SANITIZE static ets_size GetStringUTFLength(EtsEnv *env, ets_string string)
2025 {
2026     ETS_NAPI_DEBUG_TRACE(env);
2027     ETS_NAPI_ABORT_IF_NULL(string);
2028     ScopedManagedCodeFix s(PandaEtsNapiEnv::ToPandaEtsEnv(env));
2029     auto internalString = s.ToInternalType(string);
2030     // NOTE(m.morozov): ensure that place for \0 is included
2031     // NOTE(m.morozov): check after mutf8 vs utf8 decision
2032     return internalString->GetMUtf8Length() - 1;
2033 }
2034 
GetStringUTFChars(EtsEnv * env,ets_string string,ets_boolean * isCopy)2035 NO_UB_SANITIZE static const char *GetStringUTFChars(EtsEnv *env, ets_string string, ets_boolean *isCopy)
2036 {
2037     ETS_NAPI_DEBUG_TRACE(env);
2038     ETS_NAPI_ABORT_IF_NULL(string);
2039     if (isCopy != nullptr) {
2040         *isCopy = ETS_TRUE;
2041     }
2042     ScopedManagedCodeFix s(PandaEtsNapiEnv::ToPandaEtsEnv(env));
2043     auto internalString = s.ToInternalType(string);
2044     // NOTE(m.morozov): check after mutf8 vs utf8 decision
2045     size_t len = internalString->GetMUtf8Length();
2046     void *buf = EtsAlloc(len);
2047     if (buf == nullptr) {
2048         LOG(ERROR, ETS_NAPI) << __func__ << ": cannot copy string";
2049         return nullptr;
2050     }
2051     // NOTE(m.morozov): check after mutf8 vs utf8 decision
2052     internalString->CopyDataMUtf8(buf, len, true);
2053     return static_cast<char *>(buf);
2054 }
2055 
ReleaseStringUTFChars(EtsEnv * env,ets_string string,const char * chars)2056 NO_UB_SANITIZE static void ReleaseStringUTFChars([[maybe_unused]] EtsEnv *env, [[maybe_unused]] ets_string string,
2057                                                  const char *chars)
2058 {
2059     ETS_NAPI_DEBUG_TRACE(env);
2060     EtsFree(chars);
2061 }
2062 
GetArrayLength(EtsEnv * env,ets_array array)2063 NO_UB_SANITIZE static ets_size GetArrayLength(EtsEnv *env, ets_array array)
2064 {
2065     ETS_NAPI_DEBUG_TRACE(env);
2066     ETS_NAPI_ABORT_IF_NULL(array);
2067 
2068     ScopedManagedCodeFix s(PandaEtsNapiEnv::ToPandaEtsEnv(env));
2069     EtsArray *internalArray = s.ToInternalType(array);
2070     return static_cast<ets_size>(internalArray->GetLength());
2071 }
2072 
2073 // NOTE(kropacheva): change name after conflicts resolved
NewObjectsArray(EtsEnv * env,ets_size length,ets_class elementClass,ets_object initialElement)2074 NO_UB_SANITIZE static ets_objectArray NewObjectsArray(EtsEnv *env, ets_size length, ets_class elementClass,
2075                                                       ets_object initialElement)
2076 {
2077     ETS_NAPI_DEBUG_TRACE(env);
2078     ETS_NAPI_ABORT_IF_LZ(length);
2079     ETS_NAPI_ABORT_IF_NULL(elementClass);
2080 
2081     ScopedManagedCodeFix s(PandaEtsNapiEnv::ToPandaEtsEnv(env));
2082     EtsClass *internalClass = s.ToInternalType(elementClass);
2083     EtsObjectArray *array = EtsObjectArray::Create(internalClass, static_cast<uint32_t>(length));
2084     if (array == nullptr) {
2085         PandaStringStream ss;
2086         ss << "Could not allocate array of " << internalClass->GetRuntimeClass()->GetName() << " of " << length
2087            << " elements";
2088         s.ThrowNewException(EtsNapiException::OUT_OF_MEMORY, ss.str().c_str());
2089         return nullptr;
2090     }
2091     if (initialElement != nullptr) {
2092         for (decltype(length) i = 0; i < length; ++i) {
2093             array->Set(static_cast<uint32_t>(i), s.ToInternalType(initialElement));
2094         }
2095     }
2096     return reinterpret_cast<ets_objectArray>(s.AddLocalRef(reinterpret_cast<EtsObject *>(array)));
2097 }
2098 
GetObjectArrayElement(EtsEnv * env,ets_objectArray array,ets_size index)2099 NO_UB_SANITIZE static ets_object GetObjectArrayElement(EtsEnv *env, ets_objectArray array, ets_size index)
2100 {
2101     ETS_NAPI_DEBUG_TRACE(env);
2102     ETS_NAPI_ABORT_IF_NULL(array);
2103 
2104     ScopedManagedCodeFix s(PandaEtsNapiEnv::ToPandaEtsEnv(env));
2105     EtsObjectArray *internalArray = s.ToInternalType(array);
2106     if (index < 0 || index >= static_cast<ets_size>(internalArray->GetLength())) {
2107         PandaStringStream ss;
2108         ss << "Could not access " << index << " element, array length = " << internalArray->GetLength();
2109         s.ThrowNewException(EtsNapiException::ARRAY_INDEX_OUT_OF_BOUNDS, ss.str().c_str());
2110         return nullptr;
2111     }
2112 
2113     return s.AddLocalRef(internalArray->Get(static_cast<uint32_t>(index)));
2114 }
2115 
SetObjectArrayElement(EtsEnv * env,ets_objectArray array,ets_size index,ets_object value)2116 NO_UB_SANITIZE static void SetObjectArrayElement(EtsEnv *env, ets_objectArray array, ets_size index, ets_object value)
2117 {
2118     ETS_NAPI_DEBUG_TRACE(env);
2119     ETS_NAPI_ABORT_IF_NULL(array);
2120 
2121     ScopedManagedCodeFix s(PandaEtsNapiEnv::ToPandaEtsEnv(env));
2122     EtsObjectArray *internalArray = s.ToInternalType(array);
2123     if (index < 0 || index >= static_cast<ets_size>(internalArray->GetLength())) {
2124         PandaStringStream ss;
2125         ss << "Could not access " << index << " element, array length = " << internalArray->GetLength();
2126         s.ThrowNewException(EtsNapiException::ARRAY_INDEX_OUT_OF_BOUNDS, ss.str().c_str());
2127         return;
2128     }
2129     EtsObject *internalValue = s.ToInternalType(value);
2130     if (internalValue != nullptr) {
2131         auto *componentClass = internalArray->GetClass()->GetComponentType();
2132         if (!internalValue->IsInstanceOf(componentClass)) {
2133             PandaStringStream ss;
2134             ss << internalValue->GetClass()->GetRuntimeClass()->GetName();
2135             ss << "cannot be stored in an array of type ";
2136             ss << componentClass->GetRuntimeClass()->GetName();
2137             s.ThrowNewException(EtsNapiException::ARRAY_STORE, ss.str().c_str());
2138             return;
2139         }
2140     }
2141     internalArray->Set(static_cast<uint32_t>(index), internalValue);
2142 }
2143 
NewBooleanArray(EtsEnv * env,ets_size length)2144 NO_UB_SANITIZE static ets_booleanArray NewBooleanArray(EtsEnv *env, ets_size length)
2145 {
2146     ETS_NAPI_DEBUG_TRACE(env);
2147     return NewPrimitiveTypeArray<ets_booleanArray, EtsBooleanArray>(env, length);
2148 }
2149 
NewByteArray(EtsEnv * env,ets_size length)2150 NO_UB_SANITIZE static ets_byteArray NewByteArray(EtsEnv *env, ets_size length)
2151 {
2152     ETS_NAPI_DEBUG_TRACE(env);
2153     return NewPrimitiveTypeArray<ets_byteArray, EtsByteArray>(env, length);
2154 }
2155 
NewCharArray(EtsEnv * env,ets_size length)2156 NO_UB_SANITIZE static ets_charArray NewCharArray(EtsEnv *env, ets_size length)
2157 {
2158     ETS_NAPI_DEBUG_TRACE(env);
2159     return NewPrimitiveTypeArray<ets_charArray, EtsCharArray>(env, length);
2160 }
2161 
NewShortArray(EtsEnv * env,ets_size length)2162 NO_UB_SANITIZE static ets_shortArray NewShortArray(EtsEnv *env, ets_size length)
2163 {
2164     ETS_NAPI_DEBUG_TRACE(env);
2165     return NewPrimitiveTypeArray<ets_shortArray, EtsShortArray>(env, length);
2166 }
2167 
NewIntArray(EtsEnv * env,ets_size length)2168 NO_UB_SANITIZE static ets_intArray NewIntArray(EtsEnv *env, ets_size length)
2169 {
2170     ETS_NAPI_DEBUG_TRACE(env);
2171     return NewPrimitiveTypeArray<ets_intArray, EtsIntArray>(env, length);
2172 }
2173 
NewLongArray(EtsEnv * env,ets_size length)2174 NO_UB_SANITIZE static ets_longArray NewLongArray(EtsEnv *env, ets_size length)
2175 {
2176     ETS_NAPI_DEBUG_TRACE(env);
2177     return NewPrimitiveTypeArray<ets_longArray, EtsLongArray>(env, length);
2178 }
2179 
NewFloatArray(EtsEnv * env,ets_size length)2180 NO_UB_SANITIZE static ets_floatArray NewFloatArray(EtsEnv *env, ets_size length)
2181 {
2182     ETS_NAPI_DEBUG_TRACE(env);
2183     return NewPrimitiveTypeArray<ets_floatArray, EtsFloatArray>(env, length);
2184 }
2185 
NewDoubleArray(EtsEnv * env,ets_size length)2186 NO_UB_SANITIZE static ets_doubleArray NewDoubleArray(EtsEnv *env, ets_size length)
2187 {
2188     ETS_NAPI_DEBUG_TRACE(env);
2189     return NewPrimitiveTypeArray<ets_doubleArray, EtsDoubleArray>(env, length);
2190 }
2191 
PinBooleanArray(EtsEnv * env,ets_booleanArray array)2192 NO_UB_SANITIZE static ets_boolean *PinBooleanArray(EtsEnv *env, ets_booleanArray array)
2193 {
2194     ETS_NAPI_DEBUG_TRACE(env);
2195     return PinPrimitiveTypeArray<ets_boolean>(env, array);
2196 }
2197 
PinByteArray(EtsEnv * env,ets_byteArray array)2198 NO_UB_SANITIZE static ets_byte *PinByteArray(EtsEnv *env, ets_byteArray array)
2199 {
2200     ETS_NAPI_DEBUG_TRACE(env);
2201     return PinPrimitiveTypeArray<ets_byte>(env, array);
2202 }
2203 
PinCharArray(EtsEnv * env,ets_charArray array)2204 NO_UB_SANITIZE static ets_char *PinCharArray(EtsEnv *env, ets_charArray array)
2205 {
2206     ETS_NAPI_DEBUG_TRACE(env);
2207     return PinPrimitiveTypeArray<ets_char>(env, array);
2208 }
2209 
PinShortArray(EtsEnv * env,ets_shortArray array)2210 NO_UB_SANITIZE static ets_short *PinShortArray(EtsEnv *env, ets_shortArray array)
2211 {
2212     ETS_NAPI_DEBUG_TRACE(env);
2213     return PinPrimitiveTypeArray<ets_short>(env, array);
2214 }
2215 
PinIntArray(EtsEnv * env,ets_intArray array)2216 NO_UB_SANITIZE static ets_int *PinIntArray(EtsEnv *env, ets_intArray array)
2217 {
2218     ETS_NAPI_DEBUG_TRACE(env);
2219     return PinPrimitiveTypeArray<ets_int>(env, array);
2220 }
2221 
PinLongArray(EtsEnv * env,ets_longArray array)2222 NO_UB_SANITIZE static ets_long *PinLongArray(EtsEnv *env, ets_longArray array)
2223 {
2224     ETS_NAPI_DEBUG_TRACE(env);
2225     return PinPrimitiveTypeArray<ets_long>(env, array);
2226 }
2227 
PinFloatArray(EtsEnv * env,ets_floatArray array)2228 NO_UB_SANITIZE static ets_float *PinFloatArray(EtsEnv *env, ets_floatArray array)
2229 {
2230     ETS_NAPI_DEBUG_TRACE(env);
2231     return PinPrimitiveTypeArray<ets_float>(env, array);
2232 }
2233 
PinDoubleArray(EtsEnv * env,ets_doubleArray array)2234 NO_UB_SANITIZE static ets_double *PinDoubleArray(EtsEnv *env, ets_doubleArray array)
2235 {
2236     ETS_NAPI_DEBUG_TRACE(env);
2237     return PinPrimitiveTypeArray<ets_double>(env, array);
2238 }
2239 
UnpinBooleanArray(EtsEnv * env,ets_booleanArray array)2240 NO_UB_SANITIZE static void UnpinBooleanArray(EtsEnv *env, ets_booleanArray array)
2241 {
2242     ETS_NAPI_DEBUG_TRACE(env);
2243     UnpinPrimitiveTypeArray(env, array);
2244 }
2245 
UnpinByteArray(EtsEnv * env,ets_byteArray array)2246 NO_UB_SANITIZE static void UnpinByteArray(EtsEnv *env, ets_byteArray array)
2247 {
2248     ETS_NAPI_DEBUG_TRACE(env);
2249     UnpinPrimitiveTypeArray(env, array);
2250 }
2251 
UnpinCharArray(EtsEnv * env,ets_charArray array)2252 NO_UB_SANITIZE static void UnpinCharArray(EtsEnv *env, ets_charArray array)
2253 {
2254     ETS_NAPI_DEBUG_TRACE(env);
2255     UnpinPrimitiveTypeArray(env, array);
2256 }
2257 
UnpinShortArray(EtsEnv * env,ets_shortArray array)2258 NO_UB_SANITIZE static void UnpinShortArray(EtsEnv *env, ets_shortArray array)
2259 {
2260     ETS_NAPI_DEBUG_TRACE(env);
2261     UnpinPrimitiveTypeArray(env, array);
2262 }
2263 
UnpinIntArray(EtsEnv * env,ets_intArray array)2264 NO_UB_SANITIZE static void UnpinIntArray(EtsEnv *env, ets_intArray array)
2265 {
2266     ETS_NAPI_DEBUG_TRACE(env);
2267     UnpinPrimitiveTypeArray(env, array);
2268 }
2269 
UnpinLongArray(EtsEnv * env,ets_longArray array)2270 NO_UB_SANITIZE static void UnpinLongArray(EtsEnv *env, ets_longArray array)
2271 {
2272     ETS_NAPI_DEBUG_TRACE(env);
2273     UnpinPrimitiveTypeArray(env, array);
2274 }
2275 
UnpinFloatArray(EtsEnv * env,ets_floatArray array)2276 NO_UB_SANITIZE static void UnpinFloatArray(EtsEnv *env, ets_floatArray array)
2277 {
2278     ETS_NAPI_DEBUG_TRACE(env);
2279     UnpinPrimitiveTypeArray(env, array);
2280 }
2281 
UnpinDoubleArray(EtsEnv * env,ets_doubleArray array)2282 NO_UB_SANITIZE static void UnpinDoubleArray(EtsEnv *env, ets_doubleArray array)
2283 {
2284     ETS_NAPI_DEBUG_TRACE(env);
2285     UnpinPrimitiveTypeArray(env, array);
2286 }
2287 
GetBooleanArrayRegion(EtsEnv * env,ets_booleanArray array,ets_size start,ets_size len,ets_boolean * buf)2288 NO_UB_SANITIZE static void GetBooleanArrayRegion(EtsEnv *env, ets_booleanArray array, ets_size start, ets_size len,
2289                                                  ets_boolean *buf)
2290 {
2291     ETS_NAPI_DEBUG_TRACE(env);
2292     GetPrimitiveTypeArrayRegion(env, array, start, len, buf);
2293 }
2294 
GetByteArrayRegion(EtsEnv * env,ets_byteArray array,ets_size start,ets_size len,ets_byte * buf)2295 NO_UB_SANITIZE static void GetByteArrayRegion(EtsEnv *env, ets_byteArray array, ets_size start, ets_size len,
2296                                               ets_byte *buf)
2297 {
2298     ETS_NAPI_DEBUG_TRACE(env);
2299     GetPrimitiveTypeArrayRegion(env, array, start, len, buf);
2300 }
2301 
GetCharArrayRegion(EtsEnv * env,ets_charArray array,ets_size start,ets_size len,ets_char * buf)2302 NO_UB_SANITIZE static void GetCharArrayRegion(EtsEnv *env, ets_charArray array, ets_size start, ets_size len,
2303                                               ets_char *buf)
2304 {
2305     ETS_NAPI_DEBUG_TRACE(env);
2306     GetPrimitiveTypeArrayRegion(env, array, start, len, buf);
2307 }
2308 
GetShortArrayRegion(EtsEnv * env,ets_shortArray array,ets_size start,ets_size len,ets_short * buf)2309 NO_UB_SANITIZE static void GetShortArrayRegion(EtsEnv *env, ets_shortArray array, ets_size start, ets_size len,
2310                                                ets_short *buf)
2311 {
2312     ETS_NAPI_DEBUG_TRACE(env);
2313     GetPrimitiveTypeArrayRegion(env, array, start, len, buf);
2314 }
2315 
GetIntArrayRegion(EtsEnv * env,ets_intArray array,ets_size start,ets_size len,ets_int * buf)2316 NO_UB_SANITIZE static void GetIntArrayRegion(EtsEnv *env, ets_intArray array, ets_size start, ets_size len,
2317                                              ets_int *buf)
2318 {
2319     ETS_NAPI_DEBUG_TRACE(env);
2320     GetPrimitiveTypeArrayRegion(env, array, start, len, buf);
2321 }
2322 
GetLongArrayRegion(EtsEnv * env,ets_longArray array,ets_size start,ets_size len,ets_long * buf)2323 NO_UB_SANITIZE static void GetLongArrayRegion(EtsEnv *env, ets_longArray array, ets_size start, ets_size len,
2324                                               ets_long *buf)
2325 {
2326     ETS_NAPI_DEBUG_TRACE(env);
2327     GetPrimitiveTypeArrayRegion(env, array, start, len, buf);
2328 }
2329 
GetFloatArrayRegion(EtsEnv * env,ets_floatArray array,ets_size start,ets_size len,ets_float * buf)2330 NO_UB_SANITIZE static void GetFloatArrayRegion(EtsEnv *env, ets_floatArray array, ets_size start, ets_size len,
2331                                                ets_float *buf)
2332 {
2333     ETS_NAPI_DEBUG_TRACE(env);
2334     GetPrimitiveTypeArrayRegion(env, array, start, len, buf);
2335 }
2336 
GetDoubleArrayRegion(EtsEnv * env,ets_doubleArray array,ets_size start,ets_size len,ets_double * buf)2337 NO_UB_SANITIZE static void GetDoubleArrayRegion(EtsEnv *env, ets_doubleArray array, ets_size start, ets_size len,
2338                                                 ets_double *buf)
2339 {
2340     ETS_NAPI_DEBUG_TRACE(env);
2341     GetPrimitiveTypeArrayRegion(env, array, start, len, buf);
2342 }
2343 
SetBooleanArrayRegion(EtsEnv * env,ets_booleanArray array,ets_size start,ets_size length,const ets_boolean * buf)2344 NO_UB_SANITIZE static void SetBooleanArrayRegion(EtsEnv *env, ets_booleanArray array, ets_size start, ets_size length,
2345                                                  const ets_boolean *buf)
2346 {
2347     ETS_NAPI_DEBUG_TRACE(env);
2348     SetPrimitiveTypeArrayRegion(env, array, start, length, buf);
2349 }
2350 
SetByteArrayRegion(EtsEnv * env,ets_byteArray array,ets_size start,ets_size length,const ets_byte * buf)2351 NO_UB_SANITIZE static void SetByteArrayRegion(EtsEnv *env, ets_byteArray array, ets_size start, ets_size length,
2352                                               const ets_byte *buf)
2353 {
2354     ETS_NAPI_DEBUG_TRACE(env);
2355     SetPrimitiveTypeArrayRegion(env, array, start, length, buf);
2356 }
2357 
SetCharArrayRegion(EtsEnv * env,ets_charArray array,ets_size start,ets_size length,const ets_char * buf)2358 NO_UB_SANITIZE static void SetCharArrayRegion(EtsEnv *env, ets_charArray array, ets_size start, ets_size length,
2359                                               const ets_char *buf)
2360 {
2361     ETS_NAPI_DEBUG_TRACE(env);
2362     SetPrimitiveTypeArrayRegion(env, array, start, length, buf);
2363 }
2364 
SetShortArrayRegion(EtsEnv * env,ets_shortArray array,ets_size start,ets_size length,const ets_short * buf)2365 NO_UB_SANITIZE static void SetShortArrayRegion(EtsEnv *env, ets_shortArray array, ets_size start, ets_size length,
2366                                                const ets_short *buf)
2367 {
2368     ETS_NAPI_DEBUG_TRACE(env);
2369     SetPrimitiveTypeArrayRegion(env, array, start, length, buf);
2370 }
2371 
SetIntArrayRegion(EtsEnv * env,ets_intArray array,ets_size start,ets_size length,const ets_int * buf)2372 NO_UB_SANITIZE static void SetIntArrayRegion(EtsEnv *env, ets_intArray array, ets_size start, ets_size length,
2373                                              const ets_int *buf)
2374 {
2375     ETS_NAPI_DEBUG_TRACE(env);
2376     SetPrimitiveTypeArrayRegion(env, array, start, length, buf);
2377 }
2378 
SetLongArrayRegion(EtsEnv * env,ets_longArray array,ets_size start,ets_size length,const ets_long * buf)2379 NO_UB_SANITIZE static void SetLongArrayRegion(EtsEnv *env, ets_longArray array, ets_size start, ets_size length,
2380                                               const ets_long *buf)
2381 {
2382     ETS_NAPI_DEBUG_TRACE(env);
2383     SetPrimitiveTypeArrayRegion(env, array, start, length, buf);
2384 }
2385 
SetFloatArrayRegion(EtsEnv * env,ets_floatArray array,ets_size start,ets_size length,const ets_float * buf)2386 NO_UB_SANITIZE static void SetFloatArrayRegion(EtsEnv *env, ets_floatArray array, ets_size start, ets_size length,
2387                                                const ets_float *buf)
2388 {
2389     ETS_NAPI_DEBUG_TRACE(env);
2390     SetPrimitiveTypeArrayRegion(env, array, start, length, buf);
2391 }
2392 
SetDoubleArrayRegion(EtsEnv * env,ets_doubleArray array,ets_size start,ets_size length,const ets_double * buf)2393 NO_UB_SANITIZE static void SetDoubleArrayRegion(EtsEnv *env, ets_doubleArray array, ets_size start, ets_size length,
2394                                                 const ets_double *buf)
2395 {
2396     ETS_NAPI_DEBUG_TRACE(env);
2397     SetPrimitiveTypeArrayRegion(env, array, start, length, buf);
2398 }
2399 
2400 // NOTE(#18101): this workaround should be removed after the annotations are implemented.
ExtractNativeMethodInfo(const char * signature,uint32_t * outNativeFlag,const char ** outSignature)2401 static bool ExtractNativeMethodInfo(const char *signature, uint32_t *outNativeFlag, const char **outSignature)
2402 {
2403     ASSERT(outSignature);
2404 
2405     *outNativeFlag = 0;
2406     *outSignature = signature;
2407 
2408     if (signature == nullptr) {
2409         return true;
2410     }
2411     // NOLINTBEGIN(cppcoreguidelines-pro-bounds-pointer-arithmetic)
2412     if (signature[0U] == '#') {
2413         if (signature[1U] == '\0' || signature[2U] != '$') {
2414             return false;
2415         }
2416 
2417         if (signature[1U] == 'F') {
2418             *outNativeFlag |= ACC_FAST_NATIVE;
2419         } else if (signature[1U] == 'C') {
2420             *outNativeFlag |= ACC_CRITICAL_NATIVE;
2421         } else {
2422             return false;
2423         }
2424 
2425         *outSignature = signature + 3U;
2426         if (**outSignature == '\0') {
2427             *outSignature = nullptr;
2428         }
2429     }
2430     // NOLINTEND(cppcoreguidelines-pro-bounds-pointer-arithmetic)
2431     return true;
2432 }
2433 
2434 // NOTE(#18101): this workaround should be removed after the annotations are implemented.
SetNativeCallType(EtsMethod * method,uint32_t nativeFlag)2435 static void SetNativeCallType(EtsMethod *method, uint32_t nativeFlag)
2436 {
2437     ASSERT(method);
2438 
2439     method->GetPandaMethod()->SetAccessFlags(method->GetAccessFlags() | nativeFlag);
2440 
2441     if (method->IsCriticalNative()) {
2442         EtsMethod::ToRuntimeMethod(method)->SetCompiledEntryPoint(GetEtsNapiCriticalEntryPoint());
2443     }  // EtsNapiEntryPoint is set by default.
2444 }
2445 
RegisterNatives(EtsEnv * env,ets_class cls,const EtsNativeMethod * methods,ets_int nMethods)2446 NO_UB_SANITIZE static ets_int RegisterNatives(EtsEnv *env, ets_class cls, const EtsNativeMethod *methods,
2447                                               ets_int nMethods)
2448 {
2449     ETS_NAPI_DEBUG_TRACE(env);
2450     ETS_NAPI_ABORT_IF_NULL(cls);
2451     ETS_NAPI_ABORT_IF_LZ(nMethods);
2452     if (nMethods == 0) {
2453         return ETS_OK;
2454     }
2455     ETS_NAPI_ABORT_IF_NULL(methods);
2456 
2457     ScopedManagedCodeFix s(PandaEtsNapiEnv::ToPandaEtsEnv(env));
2458     EtsClass *klass = s.ToInternalType(cls);
2459     for (ets_int i = 0; i < nMethods; ++i) {
2460         const char *signature = nullptr;
2461         uint32_t nativeFlag = 0;
2462 
2463         // NOLINTBEGIN(cppcoreguidelines-pro-bounds-pointer-arithmetic)
2464         if (!ExtractNativeMethodInfo(methods[i].signature, &nativeFlag, &signature)) {
2465             PandaStringStream ss;
2466             ss << "Method " << klass->GetRuntimeClass()->GetName() << "::" << methods[i].name
2467                << " sig = " << (signature == nullptr ? "nullptr" : signature)
2468                << " has an invalid signature. Signature prefix for fast native: #F$, for critical native: #C$";
2469             s.ThrowNewException(EtsNapiException::NO_SUCH_METHOD, ss.str().c_str());
2470             return ETS_ERR_INVAL;
2471         }
2472 
2473         EtsMethod *method =
2474             (signature == nullptr ? klass->GetMethod(methods[i].name) : klass->GetMethod(methods[i].name, signature));
2475 
2476         if (method == nullptr || !method->IsNative()) {
2477             PandaStringStream ss;
2478             ss << "Method " << klass->GetRuntimeClass()->GetName() << "::" << methods[i].name
2479                << " sig = " << (signature == nullptr ? "nullptr" : signature) << " not found or not native";
2480             s.ThrowNewException(EtsNapiException::NO_SUCH_METHOD, ss.str().c_str());
2481             return ETS_ERR_INVAL;
2482         }
2483 
2484         SetNativeCallType(method, nativeFlag);
2485         method->RegisterNativeImpl(methods[i].func);
2486         // NOLINTEND(cppcoreguidelines-pro-bounds-pointer-arithmetic)
2487     }
2488     return ETS_OK;
2489 }
2490 
UnregisterNatives(EtsEnv * env,ets_class cls)2491 NO_UB_SANITIZE static ets_int UnregisterNatives(EtsEnv *env, ets_class cls)
2492 {
2493     ETS_NAPI_DEBUG_TRACE(env);
2494     ETS_NAPI_ABORT_IF_NULL(cls);
2495 
2496     ScopedManagedCodeFix s(PandaEtsNapiEnv::ToPandaEtsEnv(env));
2497     EtsClass *klass = s.ToInternalType(cls);
2498     klass->EnumerateMethods([](EtsMethod *method) {
2499         if (method->IsNative()) {
2500             method->UnregisterNativeImpl();
2501         }
2502         return false;
2503     });
2504     return ETS_OK;
2505 }
2506 
GetEtsVM(EtsEnv * env,EtsVM ** vm)2507 NO_UB_SANITIZE static ets_int GetEtsVM([[maybe_unused]] EtsEnv *env, EtsVM **vm)
2508 {
2509     ETS_NAPI_DEBUG_TRACE(env);
2510     ETS_NAPI_ABORT_IF_NULL(vm);
2511 
2512     if (Runtime::GetCurrent() == nullptr) {
2513         *vm = nullptr;
2514         return ETS_ERR;
2515     }
2516     *vm = PandaEtsVM::GetCurrent();
2517     if (*vm == nullptr) {
2518         return ETS_ERR;
2519     }
2520     return ETS_OK;
2521 }
2522 
GetStringRegion(EtsEnv * env,ets_string str,ets_size start,ets_size len,ets_char * buf)2523 NO_UB_SANITIZE static void GetStringRegion(EtsEnv *env, ets_string str, ets_size start, ets_size len, ets_char *buf)
2524 {
2525     ETS_NAPI_DEBUG_TRACE(env);
2526     ETS_NAPI_ABORT_IF_NULL(str);
2527     ETS_NAPI_ABORT_IF_NULL(buf);
2528 
2529     ScopedManagedCodeFix s(PandaEtsNapiEnv::ToPandaEtsEnv(env));
2530     EtsString *internalString = s.ToInternalType(str);
2531     // NOLINTNEXTLINE(bugprone-misplaced-widening-cast)
2532     if (start < 0 || len < 0 || static_cast<size_t>(start + len) > internalString->GetUtf16Length()) {
2533         PandaStringStream ss;
2534         ss << "String index out of bounds: start = " << start << ", len = " << len
2535            << ", string size = " << internalString->GetUtf16Length();
2536         s.ThrowNewException(EtsNapiException::STRING_INDEX_OUT_OF_BOUNDS, ss.str().c_str());
2537         return;
2538     }
2539     internalString->CopyDataRegionUtf16(buf, start, len, len);
2540 }
2541 
GetStringUTFRegion(EtsEnv * env,ets_string str,ets_size start,ets_size len,char * buf)2542 NO_UB_SANITIZE static void GetStringUTFRegion(EtsEnv *env, ets_string str, ets_size start, ets_size len, char *buf)
2543 {
2544     ETS_NAPI_DEBUG_TRACE(env);
2545     ETS_NAPI_ABORT_IF_NULL(str);
2546     ETS_NAPI_ABORT_IF_NULL(buf);
2547 
2548     ScopedManagedCodeFix s(PandaEtsNapiEnv::ToPandaEtsEnv(env));
2549     EtsString *internalString = s.ToInternalType(str);
2550     // NOLINTNEXTLINE(bugprone-misplaced-widening-cast)
2551     if (start < 0 || len < 0 || static_cast<size_t>(start + len) > internalString->GetUtf16Length()) {
2552         PandaStringStream ss;
2553         ss << "String index out of bounds: start = " << start << ", len = " << len
2554            << ", string size = " << internalString->GetUtf16Length();
2555         s.ThrowNewException(EtsNapiException::STRING_INDEX_OUT_OF_BOUNDS, ss.str().c_str());
2556         return;
2557     }
2558     // NOTE(m.morozov): check after mutf8 vs utf8 decision
2559     internalString->CopyDataRegionMUtf8(buf, start, len, internalString->GetMUtf8Length());
2560 }
2561 
AllocObject(EtsEnv * env,ets_class cls)2562 NO_UB_SANITIZE static ets_object AllocObject(EtsEnv *env, ets_class cls)
2563 {
2564     ETS_NAPI_DEBUG_TRACE(env);
2565     ETS_NAPI_ABORT_IF_NULL(cls);
2566 
2567     ScopedManagedCodeFix s(PandaEtsNapiEnv::ToPandaEtsEnv(env));
2568     EtsClass *internalClass = GetInternalClass(env, cls, &s);
2569     if (internalClass == nullptr) {
2570         return nullptr;
2571     }
2572 
2573     if (internalClass->IsAbstract() || internalClass->IsInterface()) {
2574         PandaStringStream ss;
2575         ss << "Class " << internalClass->GetRuntimeClass()->GetName() << " is interface or abstract";
2576         s.ThrowNewException(EtsNapiException::INSTANTIATION, ss.str().c_str());
2577         return nullptr;
2578     }
2579     if (internalClass->GetRuntimeClass()->IsStringClass()) {
2580         EtsString *str = EtsString::CreateNewEmptyString();
2581         if (UNLIKELY(str == nullptr)) {
2582             return nullptr;
2583         }
2584         return s.AddLocalRef(reinterpret_cast<EtsObject *>(str));
2585     }
2586 
2587     EtsObject *obj = EtsObject::Create(internalClass);
2588     if (UNLIKELY(obj == nullptr)) {
2589         return nullptr;
2590     }
2591     return s.AddLocalRef(reinterpret_cast<EtsObject *>(obj));
2592 }
2593 
NewObjectList(EtsEnv * env,ets_class cls,ets_method pMethod,va_list args)2594 NO_UB_SANITIZE static ets_object NewObjectList(EtsEnv *env, ets_class cls, ets_method pMethod, va_list args)
2595 {
2596     ETS_NAPI_DEBUG_TRACE(env);
2597     ETS_NAPI_ABORT_IF_NULL(cls);
2598     ETS_NAPI_ABORT_IF_NULL(pMethod);
2599 
2600     ets_object newObject = AllocObject(env, cls);
2601     if (newObject == nullptr) {
2602         return nullptr;
2603     }
2604     CallNonvirtualVoidMethodList(env, newObject, cls, pMethod, args);
2605 
2606     ScopedManagedCodeFix s(PandaEtsNapiEnv::ToPandaEtsEnv(env));
2607     if (PandaEtsNapiEnv::ToPandaEtsEnv(env)->HasPendingException()) {
2608         return nullptr;
2609     }
2610     return newObject;
2611 }
2612 
NewObject(EtsEnv * env,ets_class cls,ets_method pMethod,...)2613 NO_UB_SANITIZE static ets_object NewObject(EtsEnv *env, ets_class cls, ets_method pMethod, ...)
2614 {
2615     ETS_NAPI_DEBUG_TRACE(env);
2616     ETS_NAPI_ABORT_IF_NULL(cls);
2617     ETS_NAPI_ABORT_IF_NULL(pMethod);
2618 
2619     va_list args;
2620     va_start(args, pMethod);
2621     ets_object res = NewObjectList(env, cls, pMethod, args);
2622     va_end(args);
2623     return res;
2624 }
2625 
NewObjectArray(EtsEnv * env,ets_class cls,ets_method pMethod,const ets_value * args)2626 NO_UB_SANITIZE static ets_object NewObjectArray(EtsEnv *env, ets_class cls, ets_method pMethod, const ets_value *args)
2627 {
2628     ETS_NAPI_DEBUG_TRACE(env);
2629     ETS_NAPI_ABORT_IF_NULL(cls);
2630     ETS_NAPI_ABORT_IF_NULL(pMethod);
2631 
2632     ets_object newObject = AllocObject(env, cls);
2633     if (newObject == nullptr) {
2634         return nullptr;
2635     }
2636     CallNonvirtualVoidMethodArray(env, newObject, cls, pMethod, args);
2637 
2638     ScopedManagedCodeFix s(PandaEtsNapiEnv::ToPandaEtsEnv(env));
2639     if (PandaEtsNapiEnv::ToPandaEtsEnv(env)->HasPendingException()) {
2640         return nullptr;
2641     }
2642     return newObject;
2643 }
2644 
GetObjectClass(EtsEnv * env,ets_object obj)2645 NO_UB_SANITIZE static ets_class GetObjectClass(EtsEnv *env, ets_object obj)
2646 {
2647     ETS_NAPI_DEBUG_TRACE(env);
2648     ETS_NAPI_ABORT_IF_NULL(obj);
2649     ScopedManagedCodeFix s(PandaEtsNapiEnv::ToPandaEtsEnv(env));
2650     EtsObject *internalObject = s.ToInternalType(obj);
2651 
2652     return reinterpret_cast<ets_class>(s.AddLocalRef(reinterpret_cast<EtsObject *>(internalObject->GetClass())));
2653 }
2654 
IsInstanceOf(EtsEnv * env,ets_object obj,ets_class cls)2655 NO_UB_SANITIZE static ets_boolean IsInstanceOf(EtsEnv *env, ets_object obj, ets_class cls)
2656 {
2657     ETS_NAPI_DEBUG_TRACE(env);
2658     ETS_NAPI_ABORT_IF_NULL(cls);
2659     if (obj == nullptr) {
2660         return ETS_TRUE;
2661     }
2662 
2663     ScopedManagedCodeFix s(PandaEtsNapiEnv::ToPandaEtsEnv(env));
2664     EtsClass *internalClass = s.ToInternalType(cls);
2665     EtsObject *internalObject = s.ToInternalType(obj);
2666 
2667     return internalObject->IsInstanceOf(internalClass) ? ETS_TRUE : ETS_FALSE;
2668 }
2669 
GetObjectRefType(EtsEnv * env,ets_object obj)2670 NO_UB_SANITIZE static ets_objectRefType GetObjectRefType(EtsEnv *env, ets_object obj)
2671 {
2672     ETS_NAPI_DEBUG_TRACE(env);
2673     ScopedManagedCodeFix s(PandaEtsNapiEnv::ToPandaEtsEnv(env));
2674     if (UNLIKELY(obj == nullptr || !s.IsValidRef(obj))) {
2675         return ETS_INVALID_REF_TYPE;
2676     }
2677 
2678     switch (mem::ReferenceStorage::GetObjectType(reinterpret_cast<ark::mem::Reference *>(obj))) {
2679         case ark::mem::Reference::ObjectType::GLOBAL:
2680             return ETS_GLOBAL_REF_TYPE;
2681         case ark::mem::Reference::ObjectType::WEAK:
2682             return ETS_WEAK_GLOBAL_REF_TYPE;
2683         case ark::mem::Reference::ObjectType::LOCAL:
2684         case ark::mem::Reference::ObjectType::STACK:
2685             return ETS_LOCAL_REF_TYPE;
2686         default:
2687             UNREACHABLE();
2688     }
2689     UNREACHABLE();
2690 }
2691 
NewWeakGlobalRef(EtsEnv * env,ets_object obj)2692 NO_UB_SANITIZE static ets_weak NewWeakGlobalRef(EtsEnv *env, ets_object obj)
2693 {
2694     ETS_NAPI_DEBUG_TRACE(env);
2695     ETS_NAPI_RETURN_IF_EQ(obj, nullptr, nullptr);
2696 
2697     ScopedManagedCodeFix s(PandaEtsNapiEnv::ToPandaEtsEnv(env));
2698     EtsObject *internalObject = s.ToInternalType(obj);
2699     ets_weak ret = s.AddWeakGlobalRef(internalObject);
2700     if (ret == nullptr) {
2701         s.ThrowNewException(EtsNapiException::OUT_OF_MEMORY, "Could not allocate object");
2702         return nullptr;
2703     }
2704     return ret;
2705 }
2706 
DeleteWeakGlobalRef(EtsEnv * env,ets_weak obj)2707 NO_UB_SANITIZE static void DeleteWeakGlobalRef([[maybe_unused]] EtsEnv *env, ets_weak obj)
2708 {
2709     ETS_NAPI_DEBUG_TRACE(env);
2710     ETS_NAPI_RETURN_VOID_IF_NULL(obj);
2711 
2712     PandaEtsVM *etsVm = PandaEtsVM::GetCurrent();
2713     etsVm->DeleteWeakGlobalRef(obj);
2714 }
2715 
PromiseCreate(EtsEnv * env,ets_deferred * deferred,ets_object * promise)2716 NO_UB_SANITIZE static ets_status PromiseCreate(EtsEnv *env, ets_deferred *deferred, ets_object *promise)
2717 {
2718     ETS_NAPI_DEBUG_TRACE(env);
2719     CHECK_ENV(env);
2720     CHECK_ARG(env, deferred);
2721     CHECK_ARG(env, promise);
2722 
2723     ScopedManagedCodeFix s(PandaEtsNapiEnv::ToPandaEtsEnv(env));
2724     EtsPromise *internalPromise = EtsPromise::Create(s.Coroutine());
2725     if (UNLIKELY(internalPromise == nullptr)) {
2726         return ETS_GENERIC_FAILURE;
2727     }
2728 
2729     auto *promiseObj = reinterpret_cast<EtsObject *>(internalPromise);
2730     *promise = s.AddLocalRef(promiseObj);
2731     *deferred = reinterpret_cast<ets_deferred>(s.AddGlobalRef(promiseObj));
2732     return ETS_OKAY;
2733 }
2734 
DeferredResolve(EtsEnv * env,ets_deferred deferred,ets_object resolution)2735 NO_UB_SANITIZE static ets_status DeferredResolve(EtsEnv *env, ets_deferred deferred, ets_object resolution)
2736 {
2737     ETS_NAPI_DEBUG_TRACE(env);
2738     CHECK_ENV(env);
2739     CHECK_ARG(env, deferred);
2740     CHECK_ARG(env, resolution);
2741 
2742     ScopedManagedCodeFix s(PandaEtsNapiEnv::ToPandaEtsEnv(env));
2743     EtsPromise *promise = s.ToInternalType(deferred);
2744     EtsObject *value = s.ToInternalType(resolution);
2745     EtsCoroutine *coro = PandaEtsNapiEnv::ToPandaEtsEnv(env)->GetEtsCoroutine();
2746 
2747     promise->Resolve(coro, value);
2748     DeleteGlobalRef(env, reinterpret_cast<ets_object>(deferred));
2749     return ETS_OKAY;
2750 }
2751 
DeferredReject(EtsEnv * env,ets_deferred deferred,ets_object rejection)2752 NO_UB_SANITIZE static ets_status DeferredReject(EtsEnv *env, ets_deferred deferred, ets_object rejection)
2753 {
2754     ETS_NAPI_DEBUG_TRACE(env);
2755     CHECK_ENV(env);
2756     CHECK_ARG(env, deferred);
2757     CHECK_ARG(env, rejection);
2758 
2759     ScopedManagedCodeFix s(PandaEtsNapiEnv::ToPandaEtsEnv(env));
2760     EtsPromise *promise = s.ToInternalType(deferred);
2761     EtsObject *error = s.ToInternalType(rejection);
2762     EtsCoroutine *coro = PandaEtsNapiEnv::ToPandaEtsEnv(env)->GetEtsCoroutine();
2763 
2764     promise->Reject(coro, error);
2765     DeleteGlobalRef(env, reinterpret_cast<ets_object>(deferred));
2766     return ETS_OKAY;
2767 }
2768 // NewDirectByteBuffer,
2769 // GetDirectBufferAddress,
2770 // GetDirectBufferCapacity,
2771 
2772 // clang-format off
2773 const ETS_NativeInterface NATIVE_INTERFACE = {
2774     GetVersion,
2775     // DefineClass,
2776     FindClass,
2777     // FromReflectedMethod,
2778     // FromReflectedField,
2779     // ToReflectedMethod,
2780     GetSuperclass,
2781     IsAssignableFrom,
2782     // ToReflectedField,
2783     ThrowError,
2784     ThrowErrorNew,
2785     ErrorOccurred,
2786     ErrorDescribe,
2787     ErrorClear,
2788     FatalError,
2789     PushLocalFrame,
2790     PopLocalFrame,
2791     NewGlobalRef,
2792     DeleteGlobalRef,
2793     DeleteLocalRef,
2794     IsSameObject,
2795     NewLocalRef,
2796     EnsureLocalCapacity,
2797     AllocObject,
2798     NewObject,
2799     NewObjectList,
2800     NewObjectArray,
2801     GetObjectClass,
2802     IsInstanceOf,
2803     Getp_method,
2804     CallObjectMethod,
2805     CallObjectMethodList,
2806     CallObjectMethodArray,
2807     CallBooleanMethod,
2808     CallBooleanMethodList,
2809     CallBooleanMethodArray,
2810     CallByteMethod,
2811     CallByteMethodList,
2812     CallByteMethodArray,
2813     CallCharMethod,
2814     CallCharMethodList,
2815     CallCharMethodArray,
2816     CallShortMethod,
2817     CallShortMethodList,
2818     CallShortMethodArray,
2819     CallIntMethod,
2820     CallIntMethodList,
2821     CallIntMethodArray,
2822     CallLongMethod,
2823     CallLongMethodList,
2824     CallLongMethodArray,
2825     CallFloatMethod,
2826     CallFloatMethodList,
2827     CallFloatMethodArray,
2828     CallDoubleMethod,
2829     CallDoubleMethodList,
2830     CallDoubleMethodArray,
2831     CallVoidMethod,
2832     CallVoidMethodList,
2833     CallVoidMethodArray,
2834     CallNonvirtualObjectMethod,
2835     CallNonvirtualObjectMethodList,
2836     CallNonvirtualObjectMethodArray,
2837     CallNonvirtualBooleanMethod,
2838     CallNonvirtualBooleanMethodList,
2839     CallNonvirtualBooleanMethodArray,
2840     CallNonvirtualByteMethod,
2841     CallNonvirtualByteMethodList,
2842     CallNonvirtualByteMethodArray,
2843     CallNonvirtualCharMethod,
2844     CallNonvirtualCharMethodList,
2845     CallNonvirtualCharMethodArray,
2846     CallNonvirtualShortMethod,
2847     CallNonvirtualShortMethodList,
2848     CallNonvirtualShortMethodArray,
2849     CallNonvirtualIntMethod,
2850     CallNonvirtualIntMethodList,
2851     CallNonvirtualIntMethodArray,
2852     CallNonvirtualLongMethod,
2853     CallNonvirtualLongMethodList,
2854     CallNonvirtualLongMethodArray,
2855     CallNonvirtualFloatMethod,
2856     CallNonvirtualFloatMethodList,
2857     CallNonvirtualFloatMethodArray,
2858     CallNonvirtualDoubleMethod,
2859     CallNonvirtualDoubleMethodList,
2860     CallNonvirtualDoubleMethodArray,
2861     CallNonvirtualVoidMethod,
2862     CallNonvirtualVoidMethodList,
2863     CallNonvirtualVoidMethodArray,
2864     Getp_field,
2865     GetObjectField,
2866     GetBooleanField,
2867     GetByteField,
2868     GetCharField,
2869     GetShortField,
2870     GetIntField,
2871     GetLongField,
2872     GetFloatField,
2873     GetDoubleField,
2874     SetObjectField,
2875     SetBooleanField,
2876     SetByteField,
2877     SetCharField,
2878     SetShortField,
2879     SetIntField,
2880     SetLongField,
2881     SetFloatField,
2882     SetDoubleField,
2883     GetStaticp_method,
2884     CallStaticObjectMethod,
2885     CallStaticObjectMethodList,
2886     CallStaticObjectMethodArray,
2887     CallStaticBooleanMethod,
2888     CallStaticBooleanMethodList,
2889     CallStaticBooleanMethodArray,
2890     CallStaticByteMethod,
2891     CallStaticByteMethodList,
2892     CallStaticByteMethodArray,
2893     CallStaticCharMethod,
2894     CallStaticCharMethodList,
2895     CallStaticCharMethodArray,
2896     CallStaticShortMethod,
2897     CallStaticShortMethodList,
2898     CallStaticShortMethodArray,
2899     CallStaticIntMethod,
2900     CallStaticIntMethodList,
2901     CallStaticIntMethodArray,
2902     CallStaticLongMethod,
2903     CallStaticLongMethodList,
2904     CallStaticLongMethodArray,
2905     CallStaticFloatMethod,
2906     CallStaticFloatMethodList,
2907     CallStaticFloatMethodArray,
2908     CallStaticDoubleMethod,
2909     CallStaticDoubleMethodList,
2910     CallStaticDoubleMethodArray,
2911     CallStaticVoidMethod,
2912     CallStaticVoidMethodList,
2913     CallStaticVoidMethodArray,
2914     GetStaticp_field,
2915     GetStaticObjectField,
2916     GetStaticBooleanField,
2917     GetStaticByteField,
2918     GetStaticCharField,
2919     GetStaticShortField,
2920     GetStaticIntField,
2921     GetStaticLongField,
2922     GetStaticFloatField,
2923     GetStaticDoubleField,
2924     SetStaticObjectField,
2925     SetStaticBooleanField,
2926     SetStaticByteField,
2927     SetStaticCharField,
2928     SetStaticShortField,
2929     SetStaticIntField,
2930     SetStaticLongField,
2931     SetStaticFloatField,
2932     SetStaticDoubleField,
2933     NewString,
2934     GetStringLength,
2935     GetStringChars,
2936     ReleaseStringChars,
2937     NewStringUTF,
2938     GetStringUTFLength,
2939     GetStringUTFChars,
2940     ReleaseStringUTFChars,
2941     GetArrayLength,
2942     NewObjectsArray,
2943     GetObjectArrayElement,
2944     SetObjectArrayElement,
2945     NewBooleanArray,
2946     NewByteArray,
2947     NewCharArray,
2948     NewShortArray,
2949     NewIntArray,
2950     NewLongArray,
2951     NewFloatArray,
2952     NewDoubleArray,
2953     PinBooleanArray,
2954     PinByteArray,
2955     PinCharArray,
2956     PinShortArray,
2957     PinIntArray,
2958     PinLongArray,
2959     PinFloatArray,
2960     PinDoubleArray,
2961     UnpinBooleanArray,
2962     UnpinByteArray,
2963     UnpinCharArray,
2964     UnpinShortArray,
2965     UnpinIntArray,
2966     UnpinLongArray,
2967     UnpinFloatArray,
2968     UnpinDoubleArray,
2969     GetBooleanArrayRegion,
2970     GetByteArrayRegion,
2971     GetCharArrayRegion,
2972     GetShortArrayRegion,
2973     GetIntArrayRegion,
2974     GetLongArrayRegion,
2975     GetFloatArrayRegion,
2976     GetDoubleArrayRegion,
2977     SetBooleanArrayRegion,
2978     SetByteArrayRegion,
2979     SetCharArrayRegion,
2980     SetShortArrayRegion,
2981     SetIntArrayRegion,
2982     SetLongArrayRegion,
2983     SetFloatArrayRegion,
2984     SetDoubleArrayRegion,
2985     RegisterNatives,
2986     UnregisterNatives,
2987     GetEtsVM,
2988     GetStringRegion,
2989     GetStringUTFRegion,
2990     NewWeakGlobalRef,
2991     DeleteWeakGlobalRef,
2992     ErrorCheck,
2993     // NewDirectByteBuffer,
2994     // GetDirectBufferAddress,
2995     // GetDirectBufferCapacity,
2996     GetObjectRefType,
2997     PromiseCreate,
2998     DeferredResolve,
2999     DeferredReject,
3000 };
3001 // clang-format on
3002 
GetNativeInterface()3003 const ETS_NativeInterface *GetNativeInterface()
3004 {
3005     return &NATIVE_INTERFACE;
3006 }
3007 }  // namespace ark::ets::napi
3008 
3009 // NOLINTEND(cppcoreguidelines-pro-type-vararg)
3010