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