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