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