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