1 /*
2 * Copyright (c) 2025 Huawei Device Co., Ltd.
3 * Licensed under the Apache License, Version 2.0 (the "License");
4 * you may not use this file except in compliance with the License.
5 * You may obtain a copy of the License at
6 *
7 * http://www.apache.org/licenses/LICENSE-2.0
8 *
9 * Unless required by applicable law or agreed to in writing, software
10 * distributed under the License is distributed on an "AS IS" BASIS,
11 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12 * See the License for the specific language governing permissions and
13 * limitations under the License.
14 */
15
16 #ifndef CONVERTORS_NAPI_H_
17 #define CONVERTORS_NAPI_H_
18
19 #include <unordered_map>
20 #include <vector>
21 #include <string>
22
23 #ifndef TS_NAPI_OHOS
24 #include <node_api.h>
25 #else
26 #include <native_api.h>
27 #include <native_node_api.h>
28 #endif
29 #include "panda_types.h"
30
31 // NOLINTBEGIN
32 template <class T>
33 struct InteropTypeConverter {
34 using InteropType = T;
convertFromInteropTypeConverter35 static T convertFrom([[maybe_unused]] napi_env env, InteropType value)
36 {
37 return value;
38 }
convertToInteropTypeConverter39 static InteropType convertTo([[maybe_unused]] napi_env env, T value)
40 {
41 return value;
42 }
releaseInteropTypeConverter43 static void release([[maybe_unused]] napi_env env, [[maybe_unused]] InteropType value, [[maybe_unused]] T converted)
44 {
45 }
46 };
47
48 template <typename Type>
makeResult(napi_env env,Type value)49 inline typename InteropTypeConverter<Type>::InteropType makeResult(napi_env env, Type value)
50 {
51 return InteropTypeConverter<Type>::convertTo(env, value);
52 }
53
54 template <typename Type>
getArgument(napi_env env,typename InteropTypeConverter<Type>::InteropType arg)55 inline Type getArgument(napi_env env, typename InteropTypeConverter<Type>::InteropType arg)
56 {
57 return InteropTypeConverter<Type>::convertFrom(env, arg);
58 }
59
60 template <typename Type>
releaseArgument(napi_env env,typename InteropTypeConverter<Type>::InteropType arg,Type data)61 inline void releaseArgument(napi_env env, typename InteropTypeConverter<Type>::InteropType arg, Type data)
62 {
63 InteropTypeConverter<Type>::release(env, arg, data);
64 }
65
66 template <>
67 struct InteropTypeConverter<KInteropBuffer> {
68 using InteropType = napi_value;
69 static KInteropBuffer convertFrom(napi_env env, InteropType value)
70 {
71 auto placeholder = 0;
72 KInteropBuffer result = {placeholder, nullptr, 0, nullptr};
73 bool isArrayBuffer = false;
74 napi_is_arraybuffer(env, value, &isArrayBuffer);
75 if (isArrayBuffer) {
76 napi_get_arraybuffer_info(env, value, &result.data, (size_t *)&result.length);
77 } else {
78 bool isDataView = false;
79 napi_is_dataview(env, value, &isDataView);
80 if (isDataView) {
81 napi_get_dataview_info(env, value, (size_t *)&result.length, &result.data, nullptr, nullptr);
82 }
83 }
84 return result;
85 }
86 static InteropType convertTo(napi_env env, KInteropBuffer value)
87 {
88 KInteropBuffer *copy = new KInteropBuffer(value);
89 napi_value result;
90 napi_status status = napi_create_external_arraybuffer(
91 env, value.data, value.length,
92 []([[maybe_unused]] napi_env env_, [[maybe_unused]] void *finalize_data, void *finalize_hint) {
93 KInteropBuffer *buffer = reinterpret_cast<KInteropBuffer *>(finalize_hint);
94 buffer->dispose(buffer->resourceId);
95 delete buffer;
96 },
97 (void *)copy, &result);
98 if (status != napi_ok) {
99 // do smth here
100 }
101 return result;
102 };
103 static void release([[maybe_unused]] napi_env env, [[maybe_unused]] InteropType value,
104 [[maybe_unused]] KInteropBuffer converted)
105 {
106 }
107 };
108
109 template <>
110 struct InteropTypeConverter<KStringPtr> {
111 using InteropType = napi_value;
112 static KStringPtr convertFrom(napi_env env, InteropType value)
113 {
114 if (value == nullptr)
115 return KStringPtr();
116 KStringPtr result;
117 size_t length = 0;
118 napi_status status = napi_get_value_string_utf8(env, value, nullptr, 0, &length);
119 if (status != 0)
120 return result;
121 result.resize(length);
122 napi_get_value_string_utf8(env, value, result.data(), length + 1, nullptr);
123 return result;
124 }
125 static InteropType convertTo(napi_env env, const KStringPtr &value)
126 {
127 napi_value result;
128 napi_create_string_utf8(env, value.c_str(), value.length(), &result);
129 return result;
130 }
131 static void release([[maybe_unused]] napi_env env, [[maybe_unused]] InteropType value,
132 [[maybe_unused]] const KStringPtr &converted)
133 {
134 }
135 };
136
137 template <>
138 struct InteropTypeConverter<KInteropNumber> {
139 using InteropType = napi_value;
140 static KInteropNumber convertFrom(napi_env env, InteropType interopValue)
141 {
142 double value = 0.0;
143 napi_get_value_double(env, interopValue, &value);
144 return KInteropNumber::fromDouble(value);
145 }
146 static InteropType convertTo(napi_env env, KInteropNumber value)
147 {
148 napi_value result;
149 napi_create_double(env, value.asDouble(), &result);
150 return result;
151 }
152 static void release([[maybe_unused]] napi_env env, [[maybe_unused]] InteropType value,
153 [[maybe_unused]] KInteropNumber converted)
154 {
155 }
156 };
157
158 template <>
159 struct InteropTypeConverter<KVMObjectHandle> {
160 using InteropType = napi_value;
161 static inline KVMObjectHandle convertFrom([[maybe_unused]] napi_env env, InteropType value)
162 {
163 return reinterpret_cast<KVMObjectHandle>(value);
164 }
165 static InteropType convertTo([[maybe_unused]] napi_env env, KVMObjectHandle value)
166 {
167 return reinterpret_cast<napi_value>(value);
168 }
169 static inline void release([[maybe_unused]] napi_env env, [[maybe_unused]] InteropType value,
170 [[maybe_unused]] KVMObjectHandle converted)
171 {
172 }
173 };
174
175 template <>
176 struct InteropTypeConverter<KInteropReturnBuffer> {
177 using InteropType = napi_value;
178 static inline KInteropReturnBuffer convertFrom(napi_env env, InteropType value) = delete;
179 static void disposer([[maybe_unused]] napi_env env, [[maybe_unused]] void *data, void *hint)
180 {
181 KInteropReturnBuffer *bufferCopy = (KInteropReturnBuffer *)hint;
182 bufferCopy->dispose(bufferCopy->data, bufferCopy->length);
183 delete bufferCopy;
184 }
185 static InteropType convertTo(napi_env env, KInteropReturnBuffer value)
186 {
187 napi_value result = nullptr;
188 napi_value arrayBuffer = nullptr;
189 auto clone = new KInteropReturnBuffer();
190 *clone = value;
191 napi_create_external_arraybuffer(env, value.data, value.length, disposer, clone, &arrayBuffer);
192 napi_create_typedarray(env, napi_uint8_array, value.length, arrayBuffer, 0, &result);
193 return result;
194 }
195 static inline void release(napi_env env, InteropType value, const KInteropReturnBuffer &converted) = delete;
196 };
197
198 #define TS_INTEROP_THROW(vmcontext, object, ...) \
199 do { \
200 napi_env env = (napi_env)vmcontext; \
201 napi_handle_scope scope = nullptr; \
202 [[maybe_unused]] napi_status status = napi_open_handle_scope(env, &scope); \
203 napi_throw((napi_env)vmcontext, object); \
204 napi_close_handle_scope(env, scope); \
205 /* CC-OFFNXT(G.PRE.05) function gen */ \
206 return __VA_ARGS__; \
207 } while (0)
208
209 #define TS_INTEROP_THROW_STRING(vmContext, message, ...) \
210 do { \
211 napi_value value; \
212 napi_create_string_utf8((napi_env)vmContext, message, strlen(message), &value); \
213 TS_INTEROP_THROW(vmContext, value, __VA_ARGS__); \
214 } while (0)
215
216 // CC-OFFNXT(G.PRE.02-CPP) code generation
217 #define NAPI_ASSERT_INDEX(info, index, result) \
218 do { \
219 /* CC-OFFNXT(G.PRE.02) name part*/ \
220 if (static_cast<size_t>(index) >= info.Length()) { \
221 /* CC-OFFNXT(G.PRE.02) name part*/ \
222 napi_throw_error(info.Env(), nullptr, "No such element"); \
223 /* CC-OFFNXT(G.PRE.05) function gen */ \
224 return result; \
225 } \
226 } while (0)
227
228 // Helpers from node-addon-api
229 // CC-OFFNXT(G.PRE.02-CPP) code generation
230 #define TS_NAPI_THROW_IF_FAILED(env, status, ...) \
231 if ((status) != napi_ok) { \
232 const napi_extended_error_info *errorInfo; \
233 napi_get_last_error_info(env, &errorInfo); \
234 napi_throw_error(env, nullptr, errorInfo->error_message); \
235 /* CC-OFFNXT(G.PRE.05) function gen */ \
236 return __VA_ARGS__; \
237 }
238 // CC-OFFNXT(G.PRE.02-CPP) code generation
239 #define TS_NAPI_THROW_IF_FAILED_VOID(env, status) \
240 if ((status) != napi_ok) { \
241 const napi_extended_error_info *errorInfo; \
242 napi_get_last_error_info(env, &errorInfo); \
243 napi_throw_error(env, nullptr, errorInfo->error_message); \
244 /* CC-OFFNXT(G.PRE.05) function gen */ \
245 return; \
246 }
247
248 class CallbackInfo {
249 public:
250 CallbackInfo(napi_env env, napi_callback_info info) : _env(env)
251 {
252 size_t size = 0;
253 napi_status status = napi_get_cb_info(env, info, &size, nullptr, nullptr, nullptr);
254 TS_NAPI_THROW_IF_FAILED_VOID(env, status);
255 if (size > 0) {
256 args.resize(size); // NOTE(khil): statically allocate small array for common case with few arguments passed
257 status = napi_get_cb_info(env, info, &size, args.data(), nullptr, nullptr);
258 TS_NAPI_THROW_IF_FAILED_VOID(env, status);
259 }
260 }
261
262 napi_value operator[](size_t idx) const
263 {
264 if (idx >= Length()) {
265 napi_value result;
266 napi_get_undefined(_env, &result);
267 return result;
268 }
269 return args[idx];
270 }
271
272 napi_env Env() const
273 {
274 return _env;
275 }
276
277 size_t Length() const
278 {
279 return args.size();
280 }
281
282 private:
283 napi_env _env;
284 // napi_callback_info _info;
285 std::vector<napi_value> args;
286 };
287
288 template <typename ElemType>
289 inline napi_typedarray_type getNapiType() = delete;
290
291 template <>
292 inline napi_typedarray_type getNapiType<float>()
293 {
294 return napi_float32_array;
295 }
296
297 template <>
298 inline napi_typedarray_type getNapiType<int8_t>()
299 {
300 return napi_int8_array;
301 }
302
303 template <>
304 inline napi_typedarray_type getNapiType<uint8_t>()
305 {
306 return napi_uint8_array;
307 }
308
309 template <>
310 inline napi_typedarray_type getNapiType<int16_t>()
311 {
312 return napi_int16_array;
313 }
314
315 template <>
316 inline napi_typedarray_type getNapiType<uint16_t>()
317 {
318 return napi_uint16_array;
319 }
320
321 template <>
322 inline napi_typedarray_type getNapiType<int32_t>()
323 {
324 return napi_int32_array;
325 }
326
327 template <>
328 inline napi_typedarray_type getNapiType<uint32_t>()
329 {
330 return napi_uint32_array;
331 }
332
333 template <>
334 inline napi_typedarray_type getNapiType<KNativePointer>()
335 {
336 return napi_biguint64_array;
337 }
338
339 napi_valuetype getValueTypeChecked(napi_env env, napi_value value);
340 bool isTypedArray(napi_env env, napi_value value);
341
342 template <typename ElemType>
343 // CC-OFFNXT(G.FUD.06) solid logic, ODR
344 inline ElemType *getTypedElements(napi_env env, napi_value value)
345 {
346 napi_valuetype valueType = getValueTypeChecked(env, value);
347 if (valueType == napi_null) {
348 return nullptr;
349 }
350 if (!isTypedArray(env, value)) {
351 napi_throw_error(env, nullptr, "Expected TypedArray");
352 return nullptr;
353 }
354 napi_value arrayBuffer;
355 void *data = nullptr;
356 size_t byteLength;
357 size_t byteOffset;
358 napi_typedarray_type type;
359 napi_status status = napi_get_typedarray_info(env, value, &type, &byteLength, &data, &arrayBuffer, &byteOffset);
360 TS_NAPI_THROW_IF_FAILED(env, status, nullptr);
361 if (type != getNapiType<ElemType>()) {
362 printf("Array type mismatch. Expected %d got %d\n", getNapiType<ElemType>(), type);
363 napi_throw_error(env, nullptr, "Array type mismatch");
364 return nullptr;
365 }
366 return reinterpret_cast<ElemType *>(data);
367 }
368
369 template <typename ElemType>
370 inline ElemType *getTypedElements(const CallbackInfo &info, int index)
371 {
372 NAPI_ASSERT_INDEX(info, index, nullptr);
373 return getTypedElements<ElemType>(info.Env(), info[index]);
374 }
375
376 inline uint8_t *getUInt8Elements(const CallbackInfo &info, int index)
377 {
378 return getTypedElements<uint8_t>(info, index);
379 }
380
381 inline int8_t *getInt8Elements(const CallbackInfo &info, int index)
382 {
383 return getTypedElements<int8_t>(info, index);
384 }
385
386 inline uint16_t *getUInt16Elements(const CallbackInfo &info, int index)
387 {
388 return getTypedElements<uint16_t>(info, index);
389 }
390
391 inline int16_t *getInt16Elements(const CallbackInfo &info, int index)
392 {
393 return getTypedElements<int16_t>(info, index);
394 }
395
396 inline uint32_t *getUInt32Elements(const CallbackInfo &info, int index)
397 {
398 return getTypedElements<uint32_t>(info, index);
399 }
400
401 inline uint32_t *getUInt32Elements(napi_env env, napi_value value)
402 {
403 return getTypedElements<uint32_t>(env, value);
404 }
405
406 inline int32_t *getInt32Elements(const CallbackInfo &info, int index)
407 {
408 return getTypedElements<int32_t>(info, index);
409 }
410
411 inline float *getFloat32Elements(const CallbackInfo &info, int index)
412 {
413 return getTypedElements<float>(info, index);
414 }
415
416 inline KNativePointer *getPointerElements(const CallbackInfo &info, int index)
417 {
418 return getTypedElements<KNativePointer>(info, index);
419 }
420
421 KInt getInt32(napi_env env, napi_value value);
422 inline int32_t getInt32(const CallbackInfo &info, int index)
423 {
424 NAPI_ASSERT_INDEX(info, index, 0);
425 return getInt32(info.Env(), info[index]);
426 }
427 KUInt getUInt32(napi_env env, napi_value value);
428 inline uint32_t getUInt32(const CallbackInfo &info, int index)
429 {
430 NAPI_ASSERT_INDEX(info, index, 0);
431 return getUInt32(info.Env(), info[index]);
432 }
433 KFloat getFloat32(napi_env env, napi_value value);
434 inline float getFloat32(const CallbackInfo &info, int index)
435 {
436 NAPI_ASSERT_INDEX(info, index, 0.0f);
437 return getFloat32(info.Env(), info[index]);
438 }
439 KDouble getFloat64(napi_env env, napi_value value);
440 inline KDouble getFloat64(const CallbackInfo &info, int index)
441 {
442 NAPI_ASSERT_INDEX(info, index, 0.0);
443 return getFloat64(info.Env(), info[index]);
444 }
445 KStringPtr getString(napi_env env, napi_value value);
446 inline KStringPtr getString(const CallbackInfo &info, int index)
447 {
448 NAPI_ASSERT_INDEX(info, index, KStringPtr());
449 return getString(info.Env(), info[index]);
450 }
451 void *getPointer(napi_env env, napi_value value);
452 inline void *getPointer(const CallbackInfo &info, int index)
453 {
454 NAPI_ASSERT_INDEX(info, index, nullptr);
455 return getPointer(info.Env(), info[index]);
456 }
457 KLong getInt64(napi_env env, napi_value value);
458 inline KLong getInt64(const CallbackInfo &info, int index)
459 {
460 NAPI_ASSERT_INDEX(info, index, 0);
461 return getInt64(info.Env(), info[index]);
462 }
463 KBoolean getBoolean(napi_env env, napi_value value);
464 inline KBoolean getBoolean(const CallbackInfo &info, int index)
465 {
466 NAPI_ASSERT_INDEX(info, index, false);
467 return getBoolean(info.Env(), info[index]);
468 }
469
470 template <typename Type>
471 inline Type getArgument(const CallbackInfo &info, int index) = delete;
472
473 template <>
474 inline KBoolean getArgument<KBoolean>(const CallbackInfo &info, int index)
475 {
476 return getBoolean(info, index);
477 }
478
479 template <>
480 inline KUInt getArgument<uint32_t>(const CallbackInfo &info, int index)
481 {
482 return getUInt32(info, index);
483 }
484
485 template <>
486 inline KInt getArgument<int32_t>(const CallbackInfo &info, int index)
487 {
488 return getInt32(info, index);
489 }
490
491 template <>
492 inline KInteropNumber getArgument<KInteropNumber>(const CallbackInfo &info, int index)
493 {
494 KInteropNumber res = {0, {0}};
495 NAPI_ASSERT_INDEX(info, index, res);
496 return getArgument<KInteropNumber>(info.Env(), info[index]);
497 }
498
499 template <>
500 // CC-OFFNXT(G.FUD.06) solid logic, ODR
501 inline KLength getArgument<KLength>(const CallbackInfo &info, int index)
502 {
503 KLength result = {0, 0.0f, 0, 0};
504 NAPI_ASSERT_INDEX(info, index, result);
505 auto value = info[index];
506 napi_valuetype type;
507 auto type_status = napi_typeof(info.Env(), value, &type);
508 if (type_status != 0)
509 return result;
510 switch (type) {
511 case napi_number: {
512 result.value = getFloat32(info.Env(), value);
513 result.unit = 1;
514 result.type = 0;
515 break;
516 }
517 case napi_string: {
518 KStringPtr string = getString(info.Env(), value);
519 ParseKLength(string, &result);
520 result.type = 1;
521 result.resource = 0;
522 break;
523 }
524 case napi_object: {
525 result.value = 0;
526 result.unit = 1;
527 result.type = 2U;
528 napi_value field;
529 napi_status status = napi_get_named_property(info.Env(), value, "id", &field);
530 if (status == 0) {
531 status = napi_get_value_int32(info.Env(), field, &result.resource);
532 if (status != 0)
533 result.resource = 0;
534 } else {
535 result.resource = 0;
536 }
537 break;
538 }
539 default:
540 throw "Error, unexpected KLength type";
541 }
542 return result;
543 }
544
545 template <>
546 inline KInteropBuffer getArgument<KInteropBuffer>(const CallbackInfo &info, int index)
547 {
548 KInteropBuffer res = {0, nullptr, 0, nullptr};
549 NAPI_ASSERT_INDEX(info, index, res);
550 return getArgument<KInteropBuffer>((napi_env)info.Env(), (napi_value)info[index]);
551 }
552
553 template <>
554 inline KFloat getArgument<KFloat>(const CallbackInfo &info, int index)
555 {
556 return getFloat32(info, index);
557 }
558
559 template <>
560 inline KDouble getArgument<KDouble>(const CallbackInfo &info, int index)
561 {
562 return getFloat64(info, index);
563 }
564
565 template <>
566 inline KNativePointer getArgument<KNativePointer>(const CallbackInfo &info, int index)
567 {
568 return getPointer(info, index);
569 }
570
571 template <>
572 inline KLong getArgument<KLong>(const CallbackInfo &info, int index)
573 {
574 return getInt64(info, index);
575 }
576
577 template <>
578 inline KNativePointerArray getArgument<KNativePointerArray>(const CallbackInfo &info, int index)
579 {
580 return getPointerElements(info, index);
581 }
582
583 template <>
584 inline uint8_t *getArgument<uint8_t *>(const CallbackInfo &info, int index)
585 {
586 return getUInt8Elements(info, index);
587 }
588
589 template <>
590 inline const uint8_t *getArgument<const uint8_t *>(const CallbackInfo &info, int index)
591 {
592 return getUInt8Elements(info, index);
593 }
594
595 template <>
596 inline int8_t *getArgument<int8_t *>(const CallbackInfo &info, int index)
597 {
598 return getInt8Elements(info, index);
599 }
600
601 template <>
602 inline int16_t *getArgument<int16_t *>(const CallbackInfo &info, int index)
603 {
604 return getInt16Elements(info, index);
605 }
606
607 template <>
608 inline uint16_t *getArgument<uint16_t *>(const CallbackInfo &info, int index)
609 {
610 return getUInt16Elements(info, index);
611 }
612
613 template <>
614 inline int32_t *getArgument<int32_t *>(const CallbackInfo &info, int index)
615 {
616 return getInt32Elements(info, index);
617 }
618
619 template <>
620 inline uint32_t *getArgument<uint32_t *>(const CallbackInfo &info, int index)
621 {
622 return getUInt32Elements(info, index);
623 }
624
625 template <>
626 inline float *getArgument<float *>(const CallbackInfo &info, int index)
627 {
628 return getFloat32Elements(info, index);
629 }
630
631 template <>
632 inline KStringPtr getArgument<KStringPtr>(const CallbackInfo &info, int index)
633 {
634 return getString(info, index);
635 }
636
637 napi_value makeString(napi_env env, KStringPtr value);
638 napi_value makeString(napi_env env, const std::string &value);
639 napi_value makeBoolean(napi_env env, KBoolean value);
640 napi_value makeInt32(napi_env env, int32_t value);
641 napi_value makeUInt32(napi_env env, uint32_t value);
642 napi_value makeFloat32(napi_env env, float value);
643 napi_value makePointer(napi_env env, void *value);
644 napi_value makeVoid(napi_env env);
645
646 inline napi_value makeVoid(const CallbackInfo &info)
647 {
648 return makeVoid(info.Env());
649 }
650
651 template <typename Type>
652 inline napi_value makeResult(const CallbackInfo &info, Type value) = delete;
653
654 template <>
655 inline napi_value makeResult<KBoolean>(const CallbackInfo &info, KBoolean value)
656 {
657 return makeBoolean(info.Env(), value);
658 }
659
660 template <>
661 inline napi_value makeResult<int32_t>(const CallbackInfo &info, int32_t value)
662 {
663 return makeInt32(info.Env(), value);
664 }
665
666 template <>
667 inline napi_value makeResult<uint32_t>(const CallbackInfo &info, uint32_t value)
668 {
669 return makeUInt32(info.Env(), value);
670 }
671
672 template <>
673 inline napi_value makeResult<float>(const CallbackInfo &info, float value)
674 {
675 return makeFloat32(info.Env(), value);
676 }
677
678 template <>
679 inline napi_value makeResult<KNativePointer>(const CallbackInfo &info, KNativePointer value)
680 {
681 return makePointer(info.Env(), value);
682 }
683
684 template <>
685 inline napi_value makeResult<KVMObjectHandle>(const CallbackInfo &info, KVMObjectHandle value)
686 {
687 return InteropTypeConverter<KVMObjectHandle>::convertTo(info.Env(), value);
688 }
689
690 template <>
691 inline napi_value makeResult<KStringPtr>(const CallbackInfo &info, KStringPtr value)
692 {
693 return InteropTypeConverter<KStringPtr>::convertTo(info.Env(), value);
694 }
695
696 template <>
697 inline napi_value makeResult<KInteropBuffer>(const CallbackInfo &info, KInteropBuffer value)
698 {
699 return InteropTypeConverter<KInteropBuffer>::convertTo(info.Env(), value);
700 }
701
702 template <>
703 inline napi_value makeResult<KInteropReturnBuffer>(const CallbackInfo &info, KInteropReturnBuffer value)
704 {
705 return InteropTypeConverter<KInteropReturnBuffer>::convertTo(info.Env(), value);
706 }
707
708 template <>
709 inline napi_value makeResult<KInteropNumber>(const CallbackInfo &info, KInteropNumber value)
710 {
711 return InteropTypeConverter<KInteropNumber>::convertTo(info.Env(), value);
712 }
713
714 typedef napi_value (*napi_type_t)(napi_env, napi_callback_info);
715
716 class Exports {
717 std::unordered_map<std::string, std::vector<std::pair<std::string, napi_type_t>>> implementations;
718
719 public:
720 static Exports *getInstance();
721
722 std::vector<std::string> getModules();
723 void addMethod(const char *module, const char *name, napi_type_t impl);
724 const std::vector<std::pair<std::string, napi_type_t>> &getMethods(const std::string &module);
725 };
726
727 // CC-OFFNXT(G.DCL.01) false positive
728 // CC-OFFNXT(G.NAM.01) false positive
729 #define __QUOTE(x) #x
730 #define QUOTE(x) __QUOTE(x)
731
732 #define MAKE_NODE_EXPORT(module, name) \
733 __attribute__((constructor)) static void __init_##name() \
734 { \
735 Exports::getInstance()->addMethod(QUOTE(module), "_" #name, Node_##name); \
736 }
737
738 #ifndef TS_INTEROP_MODULE
739 #error TS_INTEROP_MODULE is undefined
740 #endif
741
742 #define MAKE_INTEROP_NODE_EXPORT(name) MAKE_NODE_EXPORT(TS_INTEROP_MODULE, name)
743
744 #define TS_INTEROP_0(name, Ret) \
745 napi_value Node_##name(napi_env env, napi_callback_info cbinfo) \
746 { \
747 TS_MAYBE_LOG(name) \
748 CallbackInfo info(env, cbinfo); \
749 /* CC-OFFNXT(G.PRE.05) function gen */ \
750 return makeResult<Ret>(info, impl_##name()); \
751 } \
752 MAKE_NODE_EXPORT(TS_INTEROP_MODULE, name)
753
754 #define TS_INTEROP_1(name, Ret, P0) \
755 napi_value Node_##name(napi_env env, napi_callback_info cbinfo) \
756 { \
757 TS_MAYBE_LOG(name) \
758 CallbackInfo info(env, cbinfo); \
759 P0 p0 = getArgument<P0>(info, 0); \
760 /* CC-OFFNXT(G.PRE.05) function gen */ \
761 return makeResult<Ret>(info, impl_##name(p0)); \
762 } \
763 MAKE_NODE_EXPORT(TS_INTEROP_MODULE, name)
764
765 #define TS_INTEROP_2(name, Ret, P0, P1) \
766 napi_value Node_##name(napi_env env, napi_callback_info cbinfo) \
767 { \
768 TS_MAYBE_LOG(name) \
769 CallbackInfo info(env, cbinfo); \
770 P0 p0 = getArgument<P0>(info, 0); \
771 P1 p1 = getArgument<P1>(info, 1); \
772 /* CC-OFFNXT(G.PRE.05) function gen */ \
773 return makeResult<Ret>(info, impl_##name(p0, p1)); \
774 } \
775 MAKE_NODE_EXPORT(TS_INTEROP_MODULE, name)
776
777 // CC-OFFNXT(G.PRE.06) solid logic
778 #define TS_INTEROP_3(name, Ret, P0, P1, P2) \
779 napi_value Node_##name(napi_env env, napi_callback_info cbinfo) \
780 { \
781 TS_MAYBE_LOG(name) \
782 CallbackInfo info(env, cbinfo); \
783 P0 p0 = getArgument<P0>(info, 0); \
784 P1 p1 = getArgument<P1>(info, 1); \
785 P2 p2 = getArgument<P2>(info, 2); \
786 /* CC-OFFNXT(G.PRE.05) function gen */ \
787 return makeResult<Ret>(info, impl_##name(p0, p1, p2)); \
788 } \
789 MAKE_NODE_EXPORT(TS_INTEROP_MODULE, name)
790
791 // CC-OFFNXT(G.PRE.06) solid logic
792 #define TS_INTEROP_4(name, Ret, P0, P1, P2, P3) \
793 napi_value Node_##name(napi_env env, napi_callback_info cbinfo) \
794 { \
795 TS_MAYBE_LOG(name) \
796 CallbackInfo info(env, cbinfo); \
797 P0 p0 = getArgument<P0>(info, 0); \
798 P1 p1 = getArgument<P1>(info, 1); \
799 P2 p2 = getArgument<P2>(info, 2); \
800 P3 p3 = getArgument<P3>(info, 3); \
801 /* CC-OFFNXT(G.PRE.05) function gen */ \
802 return makeResult<Ret>(info, impl_##name(p0, p1, p2, p3)); \
803 } \
804 MAKE_NODE_EXPORT(TS_INTEROP_MODULE, name)
805
806 // CC-OFFNXT(G.PRE.06) solid logic
807 #define TS_INTEROP_5(name, Ret, P0, P1, P2, P3, P4) \
808 napi_value Node_##name(napi_env env, napi_callback_info cbinfo) \
809 { \
810 TS_MAYBE_LOG(name) \
811 CallbackInfo info(env, cbinfo); \
812 P0 p0 = getArgument<P0>(info, 0); \
813 P1 p1 = getArgument<P1>(info, 1); \
814 P2 p2 = getArgument<P2>(info, 2); \
815 P3 p3 = getArgument<P3>(info, 3); \
816 P4 p4 = getArgument<P4>(info, 4); \
817 /* CC-OFFNXT(G.PRE.05) function gen */ \
818 return makeResult<Ret>(info, impl_##name(p0, p1, p2, p3, p4)); \
819 } \
820 MAKE_NODE_EXPORT(TS_INTEROP_MODULE, name)
821
822 // CC-OFFNXT(G.PRE.06) solid logic
823 #define TS_INTEROP_6(name, Ret, P0, P1, P2, P3, P4, P5) \
824 napi_value Node_##name(napi_env env, napi_callback_info cbinfo) \
825 { \
826 TS_MAYBE_LOG(name) \
827 CallbackInfo info(env, cbinfo); \
828 P0 p0 = getArgument<P0>(info, 0); \
829 P1 p1 = getArgument<P1>(info, 1); \
830 P2 p2 = getArgument<P2>(info, 2); \
831 P3 p3 = getArgument<P3>(info, 3); \
832 P4 p4 = getArgument<P4>(info, 4); \
833 P5 p5 = getArgument<P5>(info, 5); \
834 /* CC-OFFNXT(G.PRE.05) function gen */ \
835 return makeResult<Ret>(info, impl_##name(p0, p1, p2, p3, p4, p5)); \
836 } \
837 MAKE_NODE_EXPORT(TS_INTEROP_MODULE, name)
838
839 // CC-OFFNXT(G.PRE.06) solid logic
840 #define TS_INTEROP_7(name, Ret, P0, P1, P2, P3, P4, P5, P6) \
841 napi_value Node_##name(napi_env env, napi_callback_info cbinfo) \
842 { \
843 TS_MAYBE_LOG(name) \
844 CallbackInfo info(env, cbinfo); \
845 P0 p0 = getArgument<P0>(info, 0); \
846 P1 p1 = getArgument<P1>(info, 1); \
847 P2 p2 = getArgument<P2>(info, 2); \
848 P3 p3 = getArgument<P3>(info, 3); \
849 P4 p4 = getArgument<P4>(info, 4); \
850 P5 p5 = getArgument<P5>(info, 5); \
851 P6 p6 = getArgument<P6>(info, 6); \
852 /* CC-OFFNXT(G.PRE.05) function gen */ \
853 return makeResult<Ret>(info, impl_##name(p0, p1, p2, p3, p4, p5, p6)); \
854 } \
855 MAKE_NODE_EXPORT(TS_INTEROP_MODULE, name)
856
857 // CC-OFFNXT(G.PRE.06) solid logic
858 #define TS_INTEROP_8(name, Ret, P0, P1, P2, P3, P4, P5, P6, P7) \
859 napi_value Node_##name(napi_env env, napi_callback_info cbinfo) \
860 { \
861 TS_MAYBE_LOG(name) \
862 CallbackInfo info(env, cbinfo); \
863 P0 p0 = getArgument<P0>(info, 0); \
864 P1 p1 = getArgument<P1>(info, 1); \
865 P2 p2 = getArgument<P2>(info, 2); \
866 P3 p3 = getArgument<P3>(info, 3); \
867 P4 p4 = getArgument<P4>(info, 4); \
868 P5 p5 = getArgument<P5>(info, 5); \
869 P6 p6 = getArgument<P6>(info, 6); \
870 P7 p7 = getArgument<P7>(info, 7); \
871 /* CC-OFFNXT(G.PRE.05) function gen */ \
872 return makeResult<Ret>(info, impl_##name(p0, p1, p2, p3, p4, p5, p6, p7)); \
873 } \
874 MAKE_NODE_EXPORT(TS_INTEROP_MODULE, name)
875
876 // CC-OFFNXT(G.PRE.06) solid logic
877 #define TS_INTEROP_9(name, Ret, P0, P1, P2, P3, P4, P5, P6, P7, P8) \
878 napi_value Node_##name(napi_env env, napi_callback_info cbinfo) \
879 { \
880 TS_MAYBE_LOG(name) \
881 CallbackInfo info(env, cbinfo); \
882 P0 p0 = getArgument<P0>(info, 0); \
883 P1 p1 = getArgument<P1>(info, 1); \
884 P2 p2 = getArgument<P2>(info, 2); \
885 P3 p3 = getArgument<P3>(info, 3); \
886 P4 p4 = getArgument<P4>(info, 4); \
887 P5 p5 = getArgument<P5>(info, 5); \
888 P6 p6 = getArgument<P6>(info, 6); \
889 P7 p7 = getArgument<P7>(info, 7); \
890 P8 p8 = getArgument<P8>(info, 8); \
891 /* CC-OFFNXT(G.PRE.05) function gen */ \
892 return makeResult<Ret>(info, impl_##name(p0, p1, p2, p3, p4, p5, p6, p7, p8)); \
893 } \
894 MAKE_NODE_EXPORT(TS_INTEROP_MODULE, name)
895
896 // CC-OFFNXT(G.PRE.06) solid logic
897 #define TS_INTEROP_10(name, Ret, P0, P1, P2, P3, P4, P5, P6, P7, P8, P9) \
898 napi_value Node_##name(napi_env env, napi_callback_info cbinfo) \
899 { \
900 TS_MAYBE_LOG(name) \
901 CallbackInfo info(env, cbinfo); \
902 P0 p0 = getArgument<P0>(info, 0); \
903 P1 p1 = getArgument<P1>(info, 1); \
904 P2 p2 = getArgument<P2>(info, 2); \
905 P3 p3 = getArgument<P3>(info, 3); \
906 P4 p4 = getArgument<P4>(info, 4); \
907 P5 p5 = getArgument<P5>(info, 5); \
908 P6 p6 = getArgument<P6>(info, 6); \
909 P7 p7 = getArgument<P7>(info, 7); \
910 P8 p8 = getArgument<P8>(info, 8); \
911 P9 p9 = getArgument<P9>(info, 9); \
912 /* CC-OFFNXT(G.PRE.05) function gen */ \
913 return makeResult<Ret>(info, impl_##name(p0, p1, p2, p3, p4, p5, p6, p7, p8, p9)); \
914 } \
915 MAKE_NODE_EXPORT(TS_INTEROP_MODULE, name)
916
917 // CC-OFFNXT(G.PRE.06) solid logic
918 #define TS_INTEROP_11(name, Ret, P0, P1, P2, P3, P4, P5, P6, P7, P8, P9, P10) \
919 napi_value Node_##name(napi_env env, napi_callback_info cbinfo) \
920 { \
921 TS_MAYBE_LOG(name) \
922 CallbackInfo info(env, cbinfo); \
923 P0 p0 = getArgument<P0>(info, 0); \
924 P1 p1 = getArgument<P1>(info, 1); \
925 P2 p2 = getArgument<P2>(info, 2); \
926 P3 p3 = getArgument<P3>(info, 3); \
927 P4 p4 = getArgument<P4>(info, 4); \
928 P5 p5 = getArgument<P5>(info, 5); \
929 P6 p6 = getArgument<P6>(info, 6); \
930 P7 p7 = getArgument<P7>(info, 7); \
931 P8 p8 = getArgument<P8>(info, 8); \
932 P9 p9 = getArgument<P9>(info, 9); \
933 P10 p10 = getArgument<P10>(info, 10); \
934 /* CC-OFFNXT(G.PRE.05) function gen */ \
935 return makeResult<Ret>(info, impl_##name(p0, p1, p2, p3, p4, p5, p6, p7, p8, p9, p10)); \
936 } \
937 MAKE_NODE_EXPORT(TS_INTEROP_MODULE, name)
938
939 // CC-OFFNXT(G.PRE.06) solid logic
940 #define TS_INTEROP_12(name, Ret, P0, P1, P2, P3, P4, P5, P6, P7, P8, P9, P10, P11) \
941 napi_value Node_##name(napi_env env, napi_callback_info cbinfo) \
942 { \
943 TS_MAYBE_LOG(name) \
944 CallbackInfo info(env, cbinfo); \
945 P0 p0 = getArgument<P0>(info, 0); \
946 P1 p1 = getArgument<P1>(info, 1); \
947 P2 p2 = getArgument<P2>(info, 2); \
948 P3 p3 = getArgument<P3>(info, 3); \
949 P4 p4 = getArgument<P4>(info, 4); \
950 P5 p5 = getArgument<P5>(info, 5); \
951 P6 p6 = getArgument<P6>(info, 6); \
952 P7 p7 = getArgument<P7>(info, 7); \
953 P8 p8 = getArgument<P8>(info, 8); \
954 P9 p9 = getArgument<P9>(info, 9); \
955 P10 p10 = getArgument<P10>(info, 10); \
956 P11 p11 = getArgument<P11>(info, 11); \
957 /* CC-OFFNXT(G.PRE.05) function gen */ \
958 return makeResult<Ret>(info, impl_##name(p0, p1, p2, p3, p4, p5, p6, p7, p8, p9, p10, p11)); \
959 } \
960 MAKE_NODE_EXPORT(TS_INTEROP_MODULE, name)
961
962 // CC-OFFNXT(G.PRE.06) solid logic
963 #define TS_INTEROP_13(name, Ret, P0, P1, P2, P3, P4, P5, P6, P7, P8, P9, P10, P11, P12) \
964 napi_value Node_##name(napi_env env, napi_callback_info cbinfo) \
965 { \
966 TS_MAYBE_LOG(name) \
967 CallbackInfo info(env, cbinfo); \
968 P0 p0 = getArgument<P0>(info, 0); \
969 P1 p1 = getArgument<P1>(info, 1); \
970 P2 p2 = getArgument<P2>(info, 2); \
971 P3 p3 = getArgument<P3>(info, 3); \
972 P4 p4 = getArgument<P4>(info, 4); \
973 P5 p5 = getArgument<P5>(info, 5); \
974 P6 p6 = getArgument<P6>(info, 6); \
975 P7 p7 = getArgument<P7>(info, 7); \
976 P8 p8 = getArgument<P8>(info, 8); \
977 P9 p9 = getArgument<P9>(info, 9); \
978 P10 p10 = getArgument<P10>(info, 10); \
979 P11 p11 = getArgument<P11>(info, 11); \
980 P12 p12 = getArgument<P12>(info, 12); \
981 /* CC-OFFNXT(G.PRE.05) function gen */ \
982 return makeResult<Ret>(info, impl_##name(p0, p1, p2, p3, p4, p5, p6, p7, p8, p9, p10, p11, p12)); \
983 } \
984 MAKE_NODE_EXPORT(TS_INTEROP_MODULE, name)
985
986 // CC-OFFNXT(G.PRE.06) solid logic
987 #define TS_INTEROP_14(name, Ret, P0, P1, P2, P3, P4, P5, P6, P7, P8, P9, P10, P11, P12, P13) \
988 napi_value Node_##name(napi_env env, napi_callback_info cbinfo) \
989 { \
990 TS_MAYBE_LOG(name) \
991 CallbackInfo info(env, cbinfo); \
992 P0 p0 = getArgument<P0>(info, 0); \
993 P1 p1 = getArgument<P1>(info, 1); \
994 P2 p2 = getArgument<P2>(info, 2); \
995 P3 p3 = getArgument<P3>(info, 3); \
996 P4 p4 = getArgument<P4>(info, 4); \
997 P5 p5 = getArgument<P5>(info, 5); \
998 P6 p6 = getArgument<P6>(info, 6); \
999 P7 p7 = getArgument<P7>(info, 7); \
1000 P8 p8 = getArgument<P8>(info, 8); \
1001 P9 p9 = getArgument<P9>(info, 9); \
1002 P10 p10 = getArgument<P10>(info, 10); \
1003 P11 p11 = getArgument<P11>(info, 11); \
1004 P12 p12 = getArgument<P12>(info, 12); \
1005 P13 p13 = getArgument<P13>(info, 13); \
1006 /* CC-OFFNXT(G.PRE.05) function gen */ \
1007 return makeResult<Ret>(info, impl_##name(p0, p1, p2, p3, p4, p5, p6, p7, p8, p9, p10, p11, p12, p13)); \
1008 } \
1009 MAKE_NODE_EXPORT(TS_INTEROP_MODULE, name)
1010
1011 #define TS_INTEROP_V0(name) \
1012 napi_value Node_##name(napi_env env, napi_callback_info cbinfo) \
1013 { \
1014 TS_MAYBE_LOG(name) \
1015 CallbackInfo info(env, cbinfo); \
1016 impl_##name(); \
1017 /* CC-OFFNXT(G.PRE.05) function gen */ \
1018 return makeVoid(info); \
1019 } \
1020 MAKE_NODE_EXPORT(TS_INTEROP_MODULE, name)
1021
1022 #define TS_INTEROP_V1(name, P0) \
1023 napi_value Node_##name(napi_env env, napi_callback_info cbinfo) \
1024 { \
1025 TS_MAYBE_LOG(name) \
1026 CallbackInfo info(env, cbinfo); \
1027 P0 p0 = getArgument<P0>(info, 0); \
1028 impl_##name(p0); \
1029 /* CC-OFFNXT(G.PRE.05) function gen */ \
1030 return makeVoid(info); \
1031 } \
1032 MAKE_NODE_EXPORT(TS_INTEROP_MODULE, name)
1033
1034 // CC-OFFNXT(G.PRE.06) solid logic
1035 #define TS_INTEROP_V2(name, P0, P1) \
1036 napi_value Node_##name(napi_env env, napi_callback_info cbinfo) \
1037 { \
1038 TS_MAYBE_LOG(name) \
1039 CallbackInfo info(env, cbinfo); \
1040 P0 p0 = getArgument<P0>(info, 0); \
1041 P1 p1 = getArgument<P1>(info, 1); \
1042 impl_##name(p0, p1); \
1043 /* CC-OFFNXT(G.PRE.05) function gen */ \
1044 return makeVoid(info); \
1045 } \
1046 MAKE_NODE_EXPORT(TS_INTEROP_MODULE, name)
1047
1048 // CC-OFFNXT(G.PRE.06) solid logic
1049 #define TS_INTEROP_V3(name, P0, P1, P2) \
1050 napi_value Node_##name(napi_env env, napi_callback_info cbinfo) \
1051 { \
1052 TS_MAYBE_LOG(name) \
1053 CallbackInfo info(env, cbinfo); \
1054 P0 p0 = getArgument<P0>(info, 0); \
1055 P1 p1 = getArgument<P1>(info, 1); \
1056 P2 p2 = getArgument<P2>(info, 2); \
1057 impl_##name(p0, p1, p2); \
1058 /* CC-OFFNXT(G.PRE.05) function gen */ \
1059 return makeVoid(info); \
1060 } \
1061 MAKE_NODE_EXPORT(TS_INTEROP_MODULE, name)
1062
1063 // CC-OFFNXT(G.PRE.06) solid logic
1064 #define TS_INTEROP_V4(name, P0, P1, P2, P3) \
1065 napi_value Node_##name(napi_env env, napi_callback_info cbinfo) \
1066 { \
1067 TS_MAYBE_LOG(name) \
1068 CallbackInfo info(env, cbinfo); \
1069 P0 p0 = getArgument<P0>(info, 0); \
1070 P1 p1 = getArgument<P1>(info, 1); \
1071 P2 p2 = getArgument<P2>(info, 2); \
1072 P3 p3 = getArgument<P3>(info, 3); \
1073 impl_##name(p0, p1, p2, p3); \
1074 /* CC-OFFNXT(G.PRE.05) function gen */ \
1075 return makeVoid(info); \
1076 } \
1077 MAKE_NODE_EXPORT(TS_INTEROP_MODULE, name)
1078
1079 // CC-OFFNXT(G.PRE.06) solid logic
1080 #define TS_INTEROP_V5(name, P0, P1, P2, P3, P4) \
1081 napi_value Node_##name(napi_env env, napi_callback_info cbinfo) \
1082 { \
1083 TS_MAYBE_LOG(name) \
1084 CallbackInfo info(env, cbinfo); \
1085 P0 p0 = getArgument<P0>(info, 0); \
1086 P1 p1 = getArgument<P1>(info, 1); \
1087 P2 p2 = getArgument<P2>(info, 2); \
1088 P3 p3 = getArgument<P3>(info, 3); \
1089 P4 p4 = getArgument<P4>(info, 4); \
1090 impl_##name(p0, p1, p2, p3, p4); \
1091 /* CC-OFFNXT(G.PRE.05) function gen */ \
1092 return makeVoid(info); \
1093 } \
1094 MAKE_NODE_EXPORT(TS_INTEROP_MODULE, name)
1095
1096 // CC-OFFNXT(G.PRE.06) solid logic
1097 #define TS_INTEROP_V6(name, P0, P1, P2, P3, P4, P5) \
1098 napi_value Node_##name(napi_env env, napi_callback_info cbinfo) \
1099 { \
1100 TS_MAYBE_LOG(name) \
1101 CallbackInfo info(env, cbinfo); \
1102 P0 p0 = getArgument<P0>(info, 0); \
1103 P1 p1 = getArgument<P1>(info, 1); \
1104 P2 p2 = getArgument<P2>(info, 2); \
1105 P3 p3 = getArgument<P3>(info, 3); \
1106 P4 p4 = getArgument<P4>(info, 4); \
1107 P5 p5 = getArgument<P5>(info, 5); \
1108 impl_##name(p0, p1, p2, p3, p4, p5); \
1109 /* CC-OFFNXT(G.PRE.05) function gen */ \
1110 return makeVoid(info); \
1111 } \
1112 MAKE_NODE_EXPORT(TS_INTEROP_MODULE, name)
1113
1114 // CC-OFFNXT(G.PRE.06) solid logic
1115 #define TS_INTEROP_V7(name, P0, P1, P2, P3, P4, P5, P6) \
1116 napi_value Node_##name(napi_env env, napi_callback_info cbinfo) \
1117 { \
1118 TS_MAYBE_LOG(name) \
1119 CallbackInfo info(env, cbinfo); \
1120 P0 p0 = getArgument<P0>(info, 0); \
1121 P1 p1 = getArgument<P1>(info, 1); \
1122 P2 p2 = getArgument<P2>(info, 2); \
1123 P3 p3 = getArgument<P3>(info, 3); \
1124 P4 p4 = getArgument<P4>(info, 4); \
1125 P5 p5 = getArgument<P5>(info, 5); \
1126 P6 p6 = getArgument<P6>(info, 6); \
1127 impl_##name(p0, p1, p2, p3, p4, p5, p6); \
1128 /* CC-OFFNXT(G.PRE.05) function gen */ \
1129 return makeVoid(info); \
1130 } \
1131 MAKE_NODE_EXPORT(TS_INTEROP_MODULE, name)
1132
1133 // CC-OFFNXT(G.PRE.06) solid logic
1134 #define TS_INTEROP_V8(name, P0, P1, P2, P3, P4, P5, P6, P7) \
1135 napi_value Node_##name(napi_env env, napi_callback_info cbinfo) \
1136 { \
1137 TS_MAYBE_LOG(name) \
1138 CallbackInfo info(env, cbinfo); \
1139 P0 p0 = getArgument<P0>(info, 0); \
1140 P1 p1 = getArgument<P1>(info, 1); \
1141 P2 p2 = getArgument<P2>(info, 2); \
1142 P3 p3 = getArgument<P3>(info, 3); \
1143 P4 p4 = getArgument<P4>(info, 4); \
1144 P5 p5 = getArgument<P5>(info, 5); \
1145 P6 p6 = getArgument<P6>(info, 6); \
1146 P7 p7 = getArgument<P7>(info, 7); \
1147 impl_##name(p0, p1, p2, p3, p4, p5, p6, p7); \
1148 /* CC-OFFNXT(G.PRE.05) function gen */ \
1149 return makeVoid(info); \
1150 } \
1151 MAKE_NODE_EXPORT(TS_INTEROP_MODULE, name)
1152
1153 // CC-OFFNXT(G.PRE.06) solid logic
1154 #define TS_INTEROP_V9(name, P0, P1, P2, P3, P4, P5, P6, P7, P8) \
1155 napi_value Node_##name(napi_env env, napi_callback_info cbinfo) \
1156 { \
1157 TS_MAYBE_LOG(impl_##name) \
1158 CallbackInfo info(env, cbinfo); \
1159 P0 p0 = getArgument<P0>(info, 0); \
1160 P1 p1 = getArgument<P1>(info, 1); \
1161 P2 p2 = getArgument<P2>(info, 2); \
1162 P3 p3 = getArgument<P3>(info, 3); \
1163 P4 p4 = getArgument<P4>(info, 4); \
1164 P5 p5 = getArgument<P5>(info, 5); \
1165 P6 p6 = getArgument<P6>(info, 6); \
1166 P7 p7 = getArgument<P7>(info, 7); \
1167 P8 p8 = getArgument<P8>(info, 8); \
1168 impl_##name(p0, p1, p2, p3, p4, p5, p6, p7, p8); \
1169 /* CC-OFFNXT(G.PRE.05) function gen */ \
1170 return makeVoid(info); \
1171 } \
1172 MAKE_NODE_EXPORT(TS_INTEROP_MODULE, name)
1173
1174 // CC-OFFNXT(G.PRE.06) solid logic
1175 #define TS_INTEROP_V10(name, P0, P1, P2, P3, P4, P5, P6, P7, P8, P9) \
1176 napi_value Node_##name(napi_env env, napi_callback_info cbinfo) \
1177 { \
1178 TS_MAYBE_LOG(name) \
1179 CallbackInfo info(env, cbinfo); \
1180 P0 p0 = getArgument<P0>(info, 0); \
1181 P1 p1 = getArgument<P1>(info, 1); \
1182 P2 p2 = getArgument<P2>(info, 2); \
1183 P3 p3 = getArgument<P3>(info, 3); \
1184 P4 p4 = getArgument<P4>(info, 4); \
1185 P5 p5 = getArgument<P5>(info, 5); \
1186 P6 p6 = getArgument<P6>(info, 6); \
1187 P7 p7 = getArgument<P7>(info, 7); \
1188 P8 p8 = getArgument<P8>(info, 8); \
1189 P9 p9 = getArgument<P9>(info, 9); \
1190 impl_##name(p0, p1, p2, p3, p4, p5, p6, p7, p8, p9); \
1191 /* CC-OFFNXT(G.PRE.05) function gen */ \
1192 return makeVoid(info); \
1193 } \
1194 MAKE_NODE_EXPORT(TS_INTEROP_MODULE, name)
1195
1196 // CC-OFFNXT(G.PRE.06) solid logic
1197 #define TS_INTEROP_V11(name, P0, P1, P2, P3, P4, P5, P6, P7, P8, P9, P10) \
1198 napi_value Node_##name(napi_env env, napi_callback_info cbinfo) \
1199 { \
1200 TS_MAYBE_LOG(impl_##name) \
1201 CallbackInfo info(env, cbinfo); \
1202 P0 p0 = getArgument<P0>(info, 0); \
1203 P1 p1 = getArgument<P1>(info, 1); \
1204 P2 p2 = getArgument<P2>(info, 2); \
1205 P3 p3 = getArgument<P3>(info, 3); \
1206 P4 p4 = getArgument<P4>(info, 4); \
1207 P5 p5 = getArgument<P5>(info, 5); \
1208 P6 p6 = getArgument<P6>(info, 6); \
1209 P7 p7 = getArgument<P7>(info, 7); \
1210 P8 p8 = getArgument<P8>(info, 8); \
1211 P9 p9 = getArgument<P9>(info, 9); \
1212 P10 p10 = getArgument<P10>(info, 10); \
1213 impl_##name(p0, p1, p2, p3, p4, p5, p6, p7, p8, p9, p10); \
1214 /* CC-OFFNXT(G.PRE.05) function gen */ \
1215 return makeVoid(info); \
1216 } \
1217 MAKE_NODE_EXPORT(TS_INTEROP_MODULE, name)
1218
1219 // CC-OFFNXT(G.PRE.06) solid logic
1220 #define TS_INTEROP_V12(name, P0, P1, P2, P3, P4, P5, P6, P7, P8, P9, P10, P11) \
1221 napi_value Node_##name(napi_env env, napi_callback_info cbinfo) \
1222 { \
1223 TS_MAYBE_LOG(impl_##name) \
1224 CallbackInfo info(env, cbinfo); \
1225 P0 p0 = getArgument<P0>(info, 0); \
1226 P1 p1 = getArgument<P1>(info, 1); \
1227 P2 p2 = getArgument<P2>(info, 2); \
1228 P3 p3 = getArgument<P3>(info, 3); \
1229 P4 p4 = getArgument<P4>(info, 4); \
1230 P5 p5 = getArgument<P5>(info, 5); \
1231 P6 p6 = getArgument<P6>(info, 6); \
1232 P7 p7 = getArgument<P7>(info, 7); \
1233 P8 p8 = getArgument<P8>(info, 8); \
1234 P9 p9 = getArgument<P9>(info, 9); \
1235 P10 p10 = getArgument<P10>(info, 10); \
1236 P11 p11 = getArgument<P11>(info, 11); \
1237 impl_##name(p0, p1, p2, p3, p4, p5, p6, p7, p8, p9, p10, p11); \
1238 /* CC-OFFNXT(G.PRE.05) function gen */ \
1239 return makeVoid(info); \
1240 } \
1241 MAKE_NODE_EXPORT(TS_INTEROP_MODULE, name)
1242
1243 // CC-OFFNXT(G.PRE.06) solid logic
1244 #define TS_INTEROP_V13(name, P0, P1, P2, P3, P4, P5, P6, P7, P8, P9, P10, P11, P12) \
1245 napi_value Node_##name(napi_env env, napi_callback_info cbinfo) \
1246 { \
1247 TS_MAYBE_LOG(impl_##name) \
1248 CallbackInfo info(env, cbinfo); \
1249 P0 p0 = getArgument<P0>(info, 0); \
1250 P1 p1 = getArgument<P1>(info, 1); \
1251 P2 p2 = getArgument<P2>(info, 2); \
1252 P3 p3 = getArgument<P3>(info, 3); \
1253 P4 p4 = getArgument<P4>(info, 4); \
1254 P5 p5 = getArgument<P5>(info, 5); \
1255 P6 p6 = getArgument<P6>(info, 6); \
1256 P7 p7 = getArgument<P7>(info, 7); \
1257 P8 p8 = getArgument<P8>(info, 8); \
1258 P9 p9 = getArgument<P9>(info, 9); \
1259 P10 p10 = getArgument<P10>(info, 10); \
1260 P11 p11 = getArgument<P11>(info, 11); \
1261 P12 p12 = getArgument<P12>(info, 12); \
1262 impl_##name(p0, p1, p2, p3, p4, p5, p6, p7, p8, p9, p10, p11, p12); \
1263 /* CC-OFFNXT(G.PRE.05) function gen */ \
1264 return makeVoid(info); \
1265 } \
1266 MAKE_NODE_EXPORT(TS_INTEROP_MODULE, name)
1267
1268 // CC-OFFNXT(G.PRE.06) solid logic
1269 #define TS_INTEROP_V14(name, P0, P1, P2, P3, P4, P5, P6, P7, P8, P9, P10, P11, P12, P13) \
1270 napi_value Node_##name(napi_env env, napi_callback_info cbinfo) \
1271 { \
1272 TS_MAYBE_LOG(name) \
1273 CallbackInfo info(env, cbinfo); \
1274 P0 p0 = getArgument<P0>(info, 0); \
1275 P1 p1 = getArgument<P1>(info, 1); \
1276 P2 p2 = getArgument<P2>(info, 2); \
1277 P3 p3 = getArgument<P3>(info, 3); \
1278 P4 p4 = getArgument<P4>(info, 4); \
1279 P5 p5 = getArgument<P5>(info, 5); \
1280 P6 p6 = getArgument<P6>(info, 6); \
1281 P7 p7 = getArgument<P7>(info, 7); \
1282 P8 p8 = getArgument<P8>(info, 8); \
1283 P9 p9 = getArgument<P9>(info, 9); \
1284 P10 p10 = getArgument<P10>(info, 10); \
1285 P11 p11 = getArgument<P11>(info, 11); \
1286 P12 p12 = getArgument<P12>(info, 12); \
1287 P13 p13 = getArgument<P13>(info, 13); \
1288 impl_##name(p0, p1, p2, p3, p4, p5, p6, p7, p8, p9, p10, p11, p12, p13); \
1289 /* CC-OFFNXT(G.PRE.05) function gen */ \
1290 return makeVoid(info); \
1291 } \
1292 MAKE_NODE_EXPORT(TS_INTEROP_MODULE, name)
1293
1294 // CC-OFFNXT(G.PRE.06) solid logic
1295 #define TS_INTEROP_V15(name, P0, P1, P2, P3, P4, P5, P6, P7, P8, P9, P10, P11, P12, P13, P14) \
1296 napi_value Node_##name(napi_env env, napi_callback_info cbinfo) \
1297 { \
1298 TS_MAYBE_LOG(name) \
1299 CallbackInfo info(env, cbinfo); \
1300 P0 p0 = getArgument<P0>(info, 0); \
1301 P1 p1 = getArgument<P1>(info, 1); \
1302 P2 p2 = getArgument<P2>(info, 2); \
1303 P3 p3 = getArgument<P3>(info, 3); \
1304 P4 p4 = getArgument<P4>(info, 4); \
1305 P5 p5 = getArgument<P5>(info, 5); \
1306 P6 p6 = getArgument<P6>(info, 6); \
1307 P7 p7 = getArgument<P7>(info, 7); \
1308 P8 p8 = getArgument<P8>(info, 8); \
1309 P9 p9 = getArgument<P9>(info, 9); \
1310 P10 p10 = getArgument<P10>(info, 10); \
1311 P11 p11 = getArgument<P11>(info, 11); \
1312 P12 p12 = getArgument<P12>(info, 12); \
1313 P13 p13 = getArgument<P13>(info, 13); \
1314 P14 p14 = getArgument<P14>(info, 14); \
1315 impl_##name(p0, p1, p2, p3, p4, p5, p6, p7, p8, p9, p10, p11, p12, p13, p14); \
1316 /* CC-OFFNXT(G.PRE.05) function gen */ \
1317 return makeVoid(info); \
1318 } \
1319 MAKE_NODE_EXPORT(TS_INTEROP_MODULE, name)
1320
1321 // CC-OFFNXT(G.PRE.06) solid logic
1322 #define TS_INTEROP_CTX_0(name, Ret) \
1323 napi_value Node_##name(napi_env env, napi_callback_info cbinfo) \
1324 { \
1325 TS_MAYBE_LOG(impl_##name) \
1326 CallbackInfo info(env, cbinfo); \
1327 KVMContext ctx = reinterpret_cast<KVMContext>((napi_env)info.Env()); \
1328 /* CC-OFFNXT(G.PRE.05) function gen */ \
1329 return makeResult<Ret>(info, impl_##name(ctx)); \
1330 } \
1331 MAKE_NODE_EXPORT(TS_INTEROP_MODULE, name)
1332
1333 // CC-OFFNXT(G.PRE.06) solid logic
1334 #define TS_INTEROP_CTX_1(name, Ret, P0) \
1335 napi_value Node_##name(napi_env env, napi_callback_info cbinfo) \
1336 { \
1337 TS_MAYBE_LOG(impl_##name) \
1338 CallbackInfo info(env, cbinfo); \
1339 KVMContext ctx = reinterpret_cast<KVMContext>((napi_env)info.Env()); \
1340 P0 p0 = getArgument<P0>(info, 0); \
1341 /* CC-OFFNXT(G.PRE.05) function gen */ \
1342 return makeResult<Ret>(info, impl_##name(ctx, p0)); \
1343 } \
1344 MAKE_NODE_EXPORT(TS_INTEROP_MODULE, name)
1345
1346 // CC-OFFNXT(G.PRE.06) solid logic
1347 #define TS_INTEROP_CTX_2(name, Ret, P0, P1) \
1348 napi_value Node_##name(napi_env env, napi_callback_info cbinfo) \
1349 { \
1350 TS_MAYBE_LOG(name) \
1351 CallbackInfo info(env, cbinfo); \
1352 KVMContext ctx = reinterpret_cast<KVMContext>((napi_env)info.Env()); \
1353 P0 p0 = getArgument<P0>(info, 0); \
1354 P1 p1 = getArgument<P1>(info, 1); \
1355 /* CC-OFFNXT(G.PRE.05) function gen */ \
1356 return makeResult<Ret>(info, impl_##name(ctx, p0, p1)); \
1357 } \
1358 MAKE_NODE_EXPORT(TS_INTEROP_MODULE, name)
1359
1360 // CC-OFFNXT(G.PRE.06) solid logic
1361 #define TS_INTEROP_CTX_3(name, Ret, P0, P1, P2) \
1362 napi_value Node_##name(napi_env env, napi_callback_info cbinfo) \
1363 { \
1364 TS_MAYBE_LOG(name) \
1365 CallbackInfo info(env, cbinfo); \
1366 KVMContext ctx = reinterpret_cast<KVMContext>((napi_env)info.Env()); \
1367 P0 p0 = getArgument<P0>(info, 0); \
1368 P1 p1 = getArgument<P1>(info, 1); \
1369 P2 p2 = getArgument<P2>(info, 2); \
1370 /* CC-OFFNXT(G.PRE.05) function gen */ \
1371 return makeResult<Ret>(info, impl_##name(ctx, p0, p1, p2)); \
1372 } \
1373 MAKE_NODE_EXPORT(TS_INTEROP_MODULE, name)
1374
1375 // CC-OFFNXT(G.PRE.06) solid logic
1376 #define TS_INTEROP_CTX_4(name, Ret, P0, P1, P2, P3) \
1377 napi_value Node_##name(napi_env env, napi_callback_info cbinfo) \
1378 { \
1379 TS_MAYBE_LOG(name) \
1380 CallbackInfo info(env, cbinfo); \
1381 KVMContext ctx = reinterpret_cast<KVMContext>((napi_env)info.Env()); \
1382 P0 p0 = getArgument<P0>(info, 0); \
1383 P1 p1 = getArgument<P1>(info, 1); \
1384 P2 p2 = getArgument<P2>(info, 2); \
1385 P3 p3 = getArgument<P3>(info, 3); \
1386 /* CC-OFFNXT(G.PRE.05) function gen */ \
1387 return makeResult<Ret>(info, impl_##name(ctx, p0, p1, p2, p3)); \
1388 } \
1389 MAKE_NODE_EXPORT(TS_INTEROP_MODULE, name)
1390
1391 // CC-OFFNXT(G.PRE.06) solid logic
1392 #define TS_INTEROP_CTX_V0(name) \
1393 napi_value Node_##name(napi_env env, napi_callback_info cbinfo) \
1394 { \
1395 TS_MAYBE_LOG(name) \
1396 CallbackInfo info(env, cbinfo); \
1397 KVMContext ctx = reinterpret_cast<KVMContext>((napi_env)info.Env()); \
1398 impl_##name(ctx); \
1399 /* CC-OFFNXT(G.PRE.05) function gen */ \
1400 return makeVoid(info); \
1401 } \
1402 MAKE_NODE_EXPORT(TS_INTEROP_MODULE, name)
1403
1404 // CC-OFFNXT(G.PRE.06) solid logic
1405 #define TS_INTEROP_CTX_V1(name, P0) \
1406 napi_value Node_##name(napi_env env, napi_callback_info cbinfo) \
1407 { \
1408 TS_MAYBE_LOG(name) \
1409 CallbackInfo info(env, cbinfo); \
1410 KVMContext ctx = reinterpret_cast<KVMContext>((napi_env)info.Env()); \
1411 P0 p0 = getArgument<P0>(info, 0); \
1412 impl_##name(ctx, p0); \
1413 /* CC-OFFNXT(G.PRE.05) function gen */ \
1414 return makeVoid(info); \
1415 } \
1416 MAKE_NODE_EXPORT(TS_INTEROP_MODULE, name)
1417
1418 // CC-OFFNXT(G.PRE.06) solid logic
1419 #define TS_INTEROP_CTX_V2(name, P0, P1) \
1420 napi_value Node_##name(napi_env env, napi_callback_info cbinfo) \
1421 { \
1422 TS_MAYBE_LOG(name) \
1423 CallbackInfo info(env, cbinfo); \
1424 KVMContext ctx = reinterpret_cast<KVMContext>((napi_env)info.Env()); \
1425 P0 p0 = getArgument<P0>(info, 0); \
1426 P1 p1 = getArgument<P1>(info, 1); \
1427 impl_##name(ctx, p0, p1); \
1428 /* CC-OFFNXT(G.PRE.05) function gen */ \
1429 return makeVoid(info); \
1430 } \
1431 MAKE_NODE_EXPORT(TS_INTEROP_MODULE, name)
1432
1433 // CC-OFFNXT(G.PRE.06) solid logic
1434 #define TS_INTEROP_CTX_V3(name, P0, P1, P2) \
1435 napi_value Node_##name(napi_env env, napi_callback_info cbinfo) \
1436 { \
1437 TS_MAYBE_LOG(name) \
1438 CallbackInfo info(env, cbinfo); \
1439 KVMContext ctx = reinterpret_cast<KVMContext>((napi_env)info.Env()); \
1440 P0 p0 = getArgument<P0>(info, 0); \
1441 P1 p1 = getArgument<P1>(info, 1); \
1442 P2 p2 = getArgument<P2>(info, 2); \
1443 impl_##name(ctx, p0, p1, p2); \
1444 /* CC-OFFNXT(G.PRE.05) function gen */ \
1445 return makeVoid(info); \
1446 } \
1447 MAKE_NODE_EXPORT(TS_INTEROP_MODULE, name)
1448
1449 // CC-OFFNXT(G.PRE.06) solid logic
1450 #define NODEJS_GET_AND_THROW_LAST_ERROR(env) \
1451 do { \
1452 const napi_extended_error_info *error_info; \
1453 napi_get_last_error_info((env), &error_info); \
1454 bool is_pending; \
1455 napi_is_exception_pending((env), &is_pending); \
1456 /* If an exception is already pending, don't rethrow it */ \
1457 if (!is_pending) { \
1458 const char *error_message = \
1459 error_info->error_message != NULL ? error_info->error_message : "empty error message"; \
1460 napi_throw_error((env), NULL, error_message); \
1461 } \
1462 } while (0)
1463
1464 napi_value getKoalaNapiCallbackDispatcher(napi_env env);
1465
1466 // CC-OFFNXT(G.PRE.06) solid logic
1467 #define TS_INTEROP_CALL_VOID(venv, id, length, args) \
1468 { \
1469 napi_env env = reinterpret_cast<napi_env>(venv); \
1470 napi_value bridge = getKoalaNapiCallbackDispatcher(env), global = nullptr, return_val = nullptr; \
1471 napi_handle_scope scope = nullptr; \
1472 napi_open_handle_scope(env, &scope); \
1473 napi_status status = napi_get_global(env, &global); \
1474 napi_value node_args[3]; \
1475 napi_create_int32(env, id, &node_args[0]); \
1476 napi_value buffer = nullptr; \
1477 napi_create_external_arraybuffer( \
1478 env, args, length, [](napi_env, void *data, void *hint) {}, nullptr, &buffer); \
1479 napi_create_typedarray(env, napi_uint8_array, length, buffer, 0, &node_args[1]); \
1480 napi_create_int32(env, length, &node_args[2]); \
1481 status = napi_call_function(env, global, bridge, 3, node_args, &return_val); \
1482 if (status != napi_ok) \
1483 NODEJS_GET_AND_THROW_LAST_ERROR((env)); \
1484 napi_close_handle_scope(env, scope); \
1485 }
1486
1487 // CC-OFFNXT(G.PRE.06) solid logic
1488 #define TS_INTEROP_CALL_INT(venv, id, length, args) \
1489 { \
1490 napi_env env = reinterpret_cast<napi_env>(venv); \
1491 napi_value bridge = getKoalaNapiCallbackDispatcher(env), global = nullptr, return_val = nullptr; \
1492 napi_handle_scope scope = nullptr; \
1493 napi_open_handle_scope(env, &scope); \
1494 napi_status status = napi_get_global(env, &global); \
1495 napi_value node_args[3]; \
1496 napi_create_int32(env, id, &node_args[0]); \
1497 napi_value buffer = nullptr; \
1498 napi_create_external_arraybuffer( \
1499 env, args, length, [](napi_env, [[maybe_unused]] void *data, [[maybe_unused]] void *hint) {}, nullptr, \
1500 &buffer); \
1501 napi_create_typedarray(env, napi_uint8_array, length, buffer, 0, &node_args[1]); \
1502 napi_create_int32(env, length, &node_args[2]); \
1503 status = napi_call_function(env, global, bridge, 3, node_args, &return_val); \
1504 if (status != napi_ok) \
1505 NODEJS_GET_AND_THROW_LAST_ERROR((env)); \
1506 int result; \
1507 status = napi_get_value_int32(env, return_val, &result); \
1508 napi_close_handle_scope(env, scope); \
1509 /* CC-OFFNXT(G.PRE.05) function gen */ \
1510 return result; \
1511 }
1512
1513 #define TS_INTEROP_CALL_VOID_INTS32(venv, id, argc, args) TS_INTEROP_CALL_VOID(venv, id, (argc) * sizeof(int32_t), args)
1514 #define TS_INTEROP_CALL_INT_INTS32(venv, id, argc, args) TS_INTEROP_CALL_INT(venv, id, (argc) * sizeof(int32_t), args)
1515
1516 // NOLINTEND
1517
1518 #endif // CONVERTORS_NAPI_H_
1519