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