1 /*
2 * Copyright (c) 2022-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 #ifdef KOALA_NAPI
20
21 #include <unordered_map>
22 #include <vector>
23 #include <string>
24
25 #ifndef KOALA_NAPI_OHOS
26 #include <node_api.h>
27 #else
28 #include <native_api.h>
29 #include <native_node_api.h>
30 #endif
31 #include "koala-types.h"
32 #include "interop-types.h"
33
34 template<class T>
35 struct InteropTypeConverter {
36 using InteropType = T;
convertFromInteropTypeConverter37 static T convertFrom(napi_env env, InteropType value) { return value; }
convertToInteropTypeConverter38 static InteropType convertTo(napi_env env, T value) { return value; }
releaseInteropTypeConverter39 static void release(napi_env env, InteropType value, T converted) {}
40 };
41
42 template <typename Type>
makeResult(napi_env env,Type value)43 inline typename InteropTypeConverter<Type>::InteropType makeResult(napi_env env, Type value) {
44 return InteropTypeConverter<Type>::convertTo(env, value);
45 }
46
47 template <typename Type>
getArgument(napi_env env,typename InteropTypeConverter<Type>::InteropType arg)48 inline Type getArgument(napi_env env, typename InteropTypeConverter<Type>::InteropType arg) {
49 return InteropTypeConverter<Type>::convertFrom(env, arg);
50 }
51
52 template <typename Type>
releaseArgument(napi_env env,typename InteropTypeConverter<Type>::InteropType arg,Type data)53 inline void releaseArgument(napi_env env, typename InteropTypeConverter<Type>::InteropType arg, Type data) {
54 InteropTypeConverter<Type>::release(env, arg, data);
55 }
56
57 template<>
58 struct InteropTypeConverter<KInteropBuffer> {
59 using InteropType = napi_value;
60 static KInteropBuffer convertFrom(napi_env env, InteropType value) {
61 KInteropBuffer result = { 0 };
62 bool isArrayBuffer = false;
63 napi_is_arraybuffer(env, value, &isArrayBuffer);
64 if (isArrayBuffer) {
65 napi_get_arraybuffer_info(env, value, &result.data, (size_t*)&result.length);
66 } else {
67 bool isDataView = false;
68 napi_is_dataview(env, value, &isDataView);
69 if (isDataView) {
70 napi_get_dataview_info(env, value, (size_t*)&result.length, &result.data, nullptr, nullptr);
71 }
72 }
73 return result;
74 }
75 static InteropType convertTo(napi_env env, KInteropBuffer value) {
76 KInteropBuffer* copy = new KInteropBuffer(value);
77 napi_value result;
78 napi_status status = napi_create_external_arraybuffer(
79 env,
80 value.data,
81 value.length,
82 [](napi_env env, void* finalize_data, void* finalize_hint) {
83 KInteropBuffer* buffer = reinterpret_cast<KInteropBuffer*>(finalize_hint);
84 buffer->dispose(buffer->resourceId);
85 delete buffer;
86 },
87 (void*)copy,
88 &result
89 );
90 return result;
91 };
92 static void release(napi_env env, InteropType value, KInteropBuffer converted) {}
93 };
94
95 template<>
96 struct InteropTypeConverter<KStringPtr> {
97 using InteropType = napi_value;
98 static KStringPtr convertFrom(napi_env env, InteropType value) {
99 if (value == nullptr) return KStringPtr();
100 KStringPtr result;
101 size_t length = 0;
102 napi_status status = napi_get_value_string_utf8(env, value, nullptr, 0, &length);
103 if (status != 0) return result;
104 result.resize(length);
105 status = napi_get_value_string_utf8(env, value, result.data(), length + 1, nullptr);
106 return result;
107 }
108 static InteropType convertTo(napi_env env, const KStringPtr& value) {
109 napi_value result;
110 napi_create_string_utf8(env, value.c_str(), value.length(), &result);
111 return result;
112 }
113 static void release(napi_env env, InteropType value, const KStringPtr& converted) {}
114 };
115
116 template<>
117 struct InteropTypeConverter<KInteropNumber> {
118 using InteropType = napi_value;
119 static KInteropNumber convertFrom(napi_env env, InteropType interopValue) {
120 double value = 0.0;
121 napi_get_value_double(env, interopValue, &value);
122 return KInteropNumber::fromDouble(value);
123 }
124 static InteropType convertTo(napi_env env, KInteropNumber value) {
125 napi_value result;
126 napi_create_double(env, value.asDouble(), &result);
127 return result;
128 }
129 static void release(napi_env env, InteropType value, KInteropNumber converted) {}
130 };
131
132 template<>
133 struct InteropTypeConverter<KVMObjectHandle> {
134 using InteropType = napi_value;
135 static inline KVMObjectHandle convertFrom(napi_env env, InteropType value) {
136 return reinterpret_cast<KVMObjectHandle>(value);
137 }
138 static InteropType convertTo(napi_env env, KVMObjectHandle value) {
139 return reinterpret_cast<napi_value>(value);
140 }
141 static inline void release(napi_env env, InteropType value, KVMObjectHandle converted) {
142 }
143 };
144
145 template<>
146 struct InteropTypeConverter<KInteropReturnBuffer> {
147 using InteropType = napi_value;
148 static inline KInteropReturnBuffer convertFrom(napi_env env, InteropType value) = delete;
149 static void disposer(napi_env env, void* data, void* hint) {
150 KInteropReturnBuffer* bufferCopy = (KInteropReturnBuffer*)hint;
151 bufferCopy->dispose(bufferCopy->data, bufferCopy->length);
152 delete bufferCopy;
153 }
154 static InteropType convertTo(napi_env env, KInteropReturnBuffer value) {
155 napi_value result = nullptr;
156 napi_value arrayBuffer = nullptr;
157 auto clone = new KInteropReturnBuffer();
158 *clone = value;
159 napi_create_external_arraybuffer(env, value.data, value.length, disposer, clone, &arrayBuffer);
160 napi_create_typedarray(env, napi_uint8_array, value.length, arrayBuffer, 0, &result);
161 return result;
162 }
163 static inline void release(napi_env env, InteropType value, const KInteropReturnBuffer& converted) = delete;
164 };
165
166
167 #define KOALA_INTEROP_THROW(vmcontext, object, ...) \
168 do { \
169 napi_env env = (napi_env)vmcontext; \
170 napi_handle_scope scope = nullptr; \
171 napi_open_handle_scope(env, &scope); \
172 napi_throw((napi_env)vmcontext, object); \
173 napi_close_handle_scope(env, scope); \
174 return __VA_ARGS__; \
175 } while (0)
176
177 #define KOALA_INTEROP_THROW_STRING(vmContext, message, ...) \
178 do { \
179 napi_value value; \
180 napi_create_string_utf8((napi_env)vmContext, message, strlen(message), &value); \
181 KOALA_INTEROP_THROW(vmContext, value, __VA_ARGS__); \
182 } while (0)
183
184 #define NAPI_ASSERT_INDEX(info, index, result) \
185 do { \
186 if (static_cast<size_t>(index) >= info.Length()) { \
187 napi_throw_error(info.Env(), nullptr, "No such element");\
188 return result; \
189 } \
190 } while (0)
191
192 // Helpers from node-addon-api
193 #define KOALA_NAPI_THROW_IF_FAILED(env, status, ...) \
194 if ((status) != napi_ok) { \
195 const napi_extended_error_info* errorInfo; \
196 napi_get_last_error_info(env, &errorInfo); \
197 napi_throw_error(env, nullptr, errorInfo->error_message); \
198 return __VA_ARGS__; \
199 }
200 #define KOALA_NAPI_THROW_IF_FAILED_VOID(env, status) \
201 if ((status) != napi_ok) { \
202 const napi_extended_error_info* errorInfo; \
203 napi_get_last_error_info(env, &errorInfo); \
204 napi_throw_error(env, nullptr, errorInfo->error_message); \
205 return; \
206 }
207
208 class CallbackInfo {
209 public:
210 CallbackInfo(napi_env env, napi_callback_info info) : _env(env) {
211 size_t size = 0;
212 napi_status status;
213 status = napi_get_cb_info(env, info, &size, nullptr, nullptr, nullptr);
214 KOALA_NAPI_THROW_IF_FAILED_VOID(env, status);
215 if (size > 0) {
216 args.resize(size); // TODO statically allocate small array for common case with few arguments passed
217 status = napi_get_cb_info(env, info, &size, args.data(), nullptr, nullptr);
218 KOALA_NAPI_THROW_IF_FAILED_VOID(env, status);
219 }
220 }
221
222 napi_value operator[](size_t idx) const {
223 if (idx >= Length()) {
224 napi_value result;
225 napi_get_undefined(_env, &result);
226 return result;
227 }
228 return args[idx];
229 }
230
231 napi_env Env() const {
232 return _env;
233 }
234
235 size_t Length() const {
236 return args.size();
237 }
238 private:
239 napi_env _env;
240 std::vector<napi_value> args;
241 };
242
243 template <typename ElemType>
244 inline napi_typedarray_type getNapiType() = delete;
245
246 template <>
247 inline napi_typedarray_type getNapiType<float>() {
248 return napi_float32_array;
249 }
250
251 template <>
252 inline napi_typedarray_type getNapiType<int8_t>() {
253 return napi_int8_array;
254 }
255
256 template <>
257 inline napi_typedarray_type getNapiType<uint8_t>() {
258 return napi_uint8_array;
259 }
260
261 template <>
262 inline napi_typedarray_type getNapiType<int16_t>() {
263 return napi_int16_array;
264 }
265
266 template <>
267 inline napi_typedarray_type getNapiType<uint16_t>() {
268 return napi_uint16_array;
269 }
270
271 template <>
272 inline napi_typedarray_type getNapiType<int32_t>() {
273 return napi_int32_array;
274 }
275
276 template <>
277 inline napi_typedarray_type getNapiType<uint32_t>() {
278 return napi_uint32_array;
279 }
280
281 template <>
282 inline napi_typedarray_type getNapiType<KNativePointer>() {
283 return napi_biguint64_array;
284 }
285
286 napi_valuetype getValueTypeChecked(napi_env env, napi_value value);
287 bool isTypedArray(napi_env env, napi_value value);
288
289 template <typename ElemType>
290 inline ElemType* getTypedElements(napi_env env, napi_value value) {
291 napi_valuetype valueType = getValueTypeChecked(env, value);
292 if (valueType == napi_null) {
293 return nullptr;
294 }
295 if (!isTypedArray(env, value)) {
296 napi_throw_error(env, nullptr, "Expected TypedArray");
297 return nullptr;
298 }
299 napi_value arrayBuffer;
300 void* data = nullptr;
301 size_t byteLength;
302 size_t byteOffset;
303 napi_typedarray_type type;
304 napi_status status = napi_get_typedarray_info(env,
305 value,
306 &type,
307 &byteLength,
308 &data,
309 &arrayBuffer,
310 &byteOffset);
311 KOALA_NAPI_THROW_IF_FAILED(env, status, nullptr);
312 if (type != getNapiType<ElemType>()) {
313 printf("Array type mismatch. Expected %d got %d\n", getNapiType<ElemType>(), type);
314 napi_throw_error(env, nullptr, "Array type mismatch");
315 return nullptr;
316 }
317 return reinterpret_cast<ElemType*>(data);
318 }
319
320 template <typename ElemType>
321 inline ElemType* getTypedElements(const CallbackInfo& info, int index) {
322 NAPI_ASSERT_INDEX(info, index, nullptr);
323 return getTypedElements<ElemType>(info.Env(), info[index]);
324 }
325
326 inline uint8_t* getUInt8Elements(const CallbackInfo& info, int index) {
327 return getTypedElements<uint8_t>(info, index);
328 }
329
330 inline int8_t* getInt8Elements(const CallbackInfo& info, int index) {
331 return getTypedElements<int8_t>(info, index);
332 }
333
334 inline uint16_t* getUInt16Elements(const CallbackInfo& info, int index) {
335 return getTypedElements<uint16_t>(info, index);
336 }
337
338 inline int16_t* getInt16Elements(const CallbackInfo& info, int index) {
339 return getTypedElements<int16_t>(info, index);
340 }
341
342 inline uint32_t* getUInt32Elements(const CallbackInfo& info, int index) {
343 return getTypedElements<uint32_t>(info, index);
344 }
345
346 inline uint32_t* getUInt32Elements(napi_env env, napi_value value) {
347 return getTypedElements<uint32_t>(env, value);
348 }
349
350 inline int32_t* getInt32Elements(const CallbackInfo& info, int index) {
351 return getTypedElements<int32_t>(info, index);
352 }
353
354 inline float* getFloat32Elements(const CallbackInfo& info, int index) {
355 return getTypedElements<float>(info, index);
356 }
357
358 inline KNativePointer* getPointerElements(const CallbackInfo& info, int index) {
359 return getTypedElements<KNativePointer>(info, index);
360 }
361
362 KInt getInt32(napi_env env, napi_value value);
363 inline int32_t getInt32(const CallbackInfo& info, int index) {
364 NAPI_ASSERT_INDEX(info, index, 0);
365 return getInt32(info.Env(), info[index]);
366 }
367 KUInt getUInt32(napi_env env, napi_value value);
368 inline uint32_t getUInt32(const CallbackInfo& info, int index) {
369 NAPI_ASSERT_INDEX(info, index, 0);
370 return getUInt32(info.Env(), info[index]);
371 }
372 KFloat getFloat32(napi_env env, napi_value value);
373 inline float getFloat32(const CallbackInfo& info, int index) {
374 NAPI_ASSERT_INDEX(info, index, 0.0f);
375 return getFloat32(info.Env(), info[index]);
376 }
377 KDouble getFloat64(napi_env env, napi_value value);
378 inline KDouble getFloat64(const CallbackInfo& info, int index) {
379 NAPI_ASSERT_INDEX(info, index, 0.0);
380 return getFloat64(info.Env(), info[index]);
381 }
382 KStringPtr getString(napi_env env, napi_value value);
383 inline KStringPtr getString(const CallbackInfo& info, int index) {
384 NAPI_ASSERT_INDEX(info, index, KStringPtr());
385 return getString(info.Env(), info[index]);
386 }
387 void* getPointer(napi_env env, napi_value value);
388 inline void* getPointer(const CallbackInfo& info, int index) {
389 NAPI_ASSERT_INDEX(info, index, nullptr);
390 return getPointer(info.Env(), info[index]);
391 }
392 KULong getUInt64(napi_env env, napi_value value);
393 inline KULong getUInt64(const CallbackInfo& info, int index) {
394 NAPI_ASSERT_INDEX(info, index, 0);
395 return getUInt64(info.Env(), info[index]);
396 }
397 KLong getInt64(napi_env env, napi_value value);
398 inline KLong getInt64(const CallbackInfo& info, int index) {
399 NAPI_ASSERT_INDEX(info, index, 0);
400 return getInt64(info.Env(), info[index]);
401 }
402 KBoolean getBoolean(napi_env env, napi_value value);
403 inline KBoolean getBoolean(const CallbackInfo& info, int index) {
404 NAPI_ASSERT_INDEX(info, index, false);
405 return getBoolean(info.Env(), info[index]);
406 }
407
408 template <typename Type>
409 inline Type getArgument(const CallbackInfo& info, int index) = delete;
410
411 template <>
412 inline KBoolean getArgument<KBoolean>(const CallbackInfo& info, int index) {
413 return getBoolean(info, index);
414 }
415
416 template <>
417 inline KUInt getArgument<uint32_t>(const CallbackInfo& info, int index) {
418 return getUInt32(info, index);
419 }
420
421 template <>
422 inline KInt getArgument<int32_t>(const CallbackInfo& info, int index) {
423 return getInt32(info, index);
424 }
425
426 template <>
427 inline KInteropNumber getArgument<KInteropNumber>(const CallbackInfo& info, int index) {
428 NAPI_ASSERT_INDEX(info, index, { 0 });
429 return getArgument<KInteropNumber>(info.Env(), info[index]);
430 }
431
432 template <>
433 inline KLength getArgument<KLength>(const CallbackInfo& info, int index) {
434 KLength result = { 0 };
435 NAPI_ASSERT_INDEX(info, index, result);
436 auto value = info[index];
437 napi_valuetype type;
438 auto status = napi_typeof(info.Env(), value, &type);
439 if (status != 0) return result;
440 switch (type) {
441 case napi_number: {
442 result.value = getFloat32(info.Env(), value);
443 result.unit = 1;
444 result.type = 0;
445 break;
446 }
447 case napi_string: {
448 KStringPtr string = getString(info.Env(), value);
449 parseKLength(string, &result);
450 result.type = 1;
451 result.resource = 0;
452 break;
453 }
454 case napi_object: {
455 result.value = 0;
456 result.unit = 1;
457 result.type = 2;
458 napi_value field;
459 napi_status status = napi_get_named_property(info.Env(), value, "id", &field);
460 if (status == 0) {
461 status = napi_get_value_int32(info.Env(), field, &result.resource);
462 if (status != 0) result.resource = 0;
463 } else {
464 result.resource = 0;
465 }
466 break;
467 }
468 default:
469 INTEROP_FATAL("Error, unexpected KLength type");
470 }
471 return result;
472 }
473
474
475 template <>
476 inline KInteropBuffer getArgument<KInteropBuffer>(const CallbackInfo& info, int index) {
477 NAPI_ASSERT_INDEX(info, index, { 0 });
478 return getArgument<KInteropBuffer>((napi_env)info.Env(), (napi_value)info[index]);
479 }
480
481 template <>
482 inline KFloat getArgument<KFloat>(const CallbackInfo& info, int index) {
483 return getFloat32(info, index);
484 }
485
486 template <>
487 inline KDouble getArgument<KDouble>(const CallbackInfo& info, int index) {
488 return getFloat64(info, index);
489 }
490
491 template <>
492 inline KNativePointer getArgument<KNativePointer>(const CallbackInfo& info, int index) {
493 return getPointer(info, index);
494 }
495
496 template <>
497 inline KLong getArgument<KLong>(const CallbackInfo& info, int index) {
498 return getInt64(info, index);
499 }
500
501 template <>
502 inline KULong getArgument<KULong>(const CallbackInfo& info, int index) {
503 return getUInt64(info, index);
504 }
505
506 template <>
507 inline KNativePointerArray getArgument<KNativePointerArray>(const CallbackInfo& info, int index) {
508 return getPointerElements(info, index);
509 }
510
511 template <>
512 inline uint8_t* getArgument<uint8_t*>(const CallbackInfo& info, int index) {
513 return getUInt8Elements(info, index);
514 }
515
516 template <>
517 inline const uint8_t* getArgument<const uint8_t*>(const CallbackInfo& info, int index) {
518 return getUInt8Elements(info, index);
519 }
520
521 template <>
522 inline int8_t* getArgument<int8_t*>(const CallbackInfo& info, int index) {
523 return getInt8Elements(info, index);
524 }
525
526 template <>
527 inline int16_t* getArgument<int16_t*>(const CallbackInfo& info, int index) {
528 return getInt16Elements(info, index);
529 }
530
531 template <>
532 inline uint16_t* getArgument<uint16_t*>(const CallbackInfo& info, int index) {
533 return getUInt16Elements(info, index);
534 }
535
536 template <>
537 inline int32_t* getArgument<int32_t*>(const CallbackInfo& info, int index) {
538 return getInt32Elements(info, index);
539 }
540
541 template <>
542 inline uint32_t* getArgument<uint32_t*>(const CallbackInfo& info, int index) {
543 return getUInt32Elements(info, index);
544 }
545
546 template <>
547 inline float* getArgument<float*>(const CallbackInfo& info, int index) {
548 return getFloat32Elements(info, index);
549 }
550
551 template <>
552 inline KStringPtr getArgument<KStringPtr>(const CallbackInfo& info, int index) {
553 return getString(info, index);
554 }
555
556 napi_value makeString(napi_env env, KStringPtr value);
557 napi_value makeString(napi_env env, const std::string& value);
558 napi_value makeBoolean(napi_env env, KBoolean value);
559 napi_value makeInt32(napi_env env, int32_t value);
560 napi_value makeUInt32(napi_env env, uint32_t value);
561 napi_value makeInt64(napi_env env, int32_t value);
562 napi_value makeUInt64(napi_env env, uint32_t value);
563 napi_value makeFloat32(napi_env env, float value);
564 napi_value makePointer(napi_env env, void* value);
565 napi_value makeVoid(napi_env env);
566
567 inline napi_value makeVoid(const CallbackInfo& info) {
568 return makeVoid(info.Env());
569 }
570
571 template <typename Type>
572 inline napi_value makeResult(const CallbackInfo& info, Type value) = delete;
573
574 template <>
575 inline napi_value makeResult<KBoolean>(const CallbackInfo& info, KBoolean value) {
576 return makeBoolean(info.Env(), value);
577 }
578
579 template <>
580 inline napi_value makeResult<int32_t>(const CallbackInfo& info, int32_t value) {
581 return makeInt32(info.Env(), value);
582 }
583
584 template <>
585 inline napi_value makeResult<uint32_t>(const CallbackInfo& info, uint32_t value) {
586 return makeUInt32(info.Env(), value);
587 }
588
589 template <>
590 inline napi_value makeResult<KLong>(const CallbackInfo& info, int64_t value) {
591 return makeInt64(info.Env(), value);
592 }
593
594 template <>
595 inline napi_value makeResult<KULong>(const CallbackInfo& info, uint64_t value) {
596 return makeUInt64(info.Env(), value);
597 }
598
599 template <>
600 inline napi_value makeResult<float>(const CallbackInfo& info, float value) {
601 return makeFloat32(info.Env(), value);
602 }
603
604 template <>
605 inline napi_value makeResult<KNativePointer>(const CallbackInfo& info, KNativePointer value) {
606 return makePointer(info.Env(), value);
607 }
608
609 template <>
610 inline napi_value makeResult<KVMObjectHandle>(const CallbackInfo& info, KVMObjectHandle value) {
611 return InteropTypeConverter<KVMObjectHandle>::convertTo(info.Env(), value);
612 }
613
614 template <>
615 inline napi_value makeResult<KStringPtr>(const CallbackInfo& info, KStringPtr value) {
616 return InteropTypeConverter<KStringPtr>::convertTo(info.Env(), value);
617 }
618
619 template <>
620 inline napi_value makeResult<KInteropBuffer>(const CallbackInfo& info, KInteropBuffer value) {
621 return InteropTypeConverter<KInteropBuffer>::convertTo(info.Env(), value);
622 }
623
624 template <>
625 inline napi_value makeResult<KInteropReturnBuffer>(const CallbackInfo& info, KInteropReturnBuffer value) {
626 return InteropTypeConverter<KInteropReturnBuffer>::convertTo(info.Env(), value);
627 }
628
629 template <>
630 inline napi_value makeResult<KInteropNumber>(const CallbackInfo& info, KInteropNumber value) {
631 return InteropTypeConverter<KInteropNumber>::convertTo(info.Env(), value);
632 }
633
634 typedef napi_value (*napi_type_t)(napi_env, napi_callback_info);
635
636 class Exports {
637 std::unordered_map<std::string,
638 std::vector<std::pair<std::string, napi_type_t>>> implementations;
639
640 public:
641 static Exports* getInstance();
642
643 std::vector<std::string> getModules();
644 void addMethod(const char* module, const char* name, napi_type_t impl);
645 const std::vector<std::pair<std::string, napi_type_t>>& getMethods(const std::string& module);
646 };
647
648 #define QUOTE(x) #x
649
650 #ifdef _MSC_VER
651 #define MAKE_NODE_EXPORT(module, name) \
652 static void __init_##name() { \
653 Exports::getInstance()->addMethod(QUOTE(module), "_"#name, Node_##name); \
654 } \
655 namespace { \
656 struct __Init_##name { \
657 __Init_##name() { __init_##name(); } \
658 } __Init_##name##_v; \
659 }
660 #else
661 #define MAKE_NODE_EXPORT(module, name) \
662 __attribute__((constructor)) \
663 static void __init_##name() { \
664 Exports::getInstance()->addMethod(QUOTE(module), "_"#name, Node_##name); \
665 }
666 #endif
667
668 #ifndef KOALA_INTEROP_MODULE
669 #error KOALA_INTEROP_MODULE is undefined
670 #endif
671
672 #define MAKE_INTEROP_NODE_EXPORT(name) MAKE_NODE_EXPORT(KOALA_INTEROP_MODULE, name)
673
674 #define KOALA_INTEROP_0(name, Ret) \
675 napi_value Node_##name(napi_env env, napi_callback_info cbinfo) { \
676 KOALA_MAYBE_LOG(name) \
677 CallbackInfo info(env, cbinfo); \
678 return makeResult<Ret>(info, impl_##name()); \
679 } \
680 MAKE_NODE_EXPORT(KOALA_INTEROP_MODULE, name)
681
682 #define KOALA_INTEROP_1(name, Ret, P0) \
683 napi_value Node_##name(napi_env env, napi_callback_info cbinfo) { \
684 KOALA_MAYBE_LOG(name) \
685 CallbackInfo info(env, cbinfo); \
686 P0 p0 = getArgument<P0>(info, 0); \
687 return makeResult<Ret>(info, impl_##name(p0)); \
688 } \
689 MAKE_NODE_EXPORT(KOALA_INTEROP_MODULE, name)
690
691 #define KOALA_INTEROP_2(name, Ret, P0, P1) \
692 napi_value Node_##name(napi_env env, napi_callback_info cbinfo) { \
693 KOALA_MAYBE_LOG(name) \
694 CallbackInfo info(env, cbinfo); \
695 P0 p0 = getArgument<P0>(info, 0); \
696 P1 p1 = getArgument<P1>(info, 1); \
697 return makeResult<Ret>(info, impl_##name(p0, p1)); \
698 } \
699 MAKE_NODE_EXPORT(KOALA_INTEROP_MODULE, name)
700
701 #define KOALA_INTEROP_3(name, Ret, P0, P1, P2) \
702 napi_value Node_##name(napi_env env, napi_callback_info cbinfo) { \
703 KOALA_MAYBE_LOG(name) \
704 CallbackInfo info(env, cbinfo); \
705 P0 p0 = getArgument<P0>(info, 0); \
706 P1 p1 = getArgument<P1>(info, 1); \
707 P2 p2 = getArgument<P2>(info, 2); \
708 return makeResult<Ret>(info, impl_##name(p0, p1, p2)); \
709 } \
710 MAKE_NODE_EXPORT(KOALA_INTEROP_MODULE, name)
711
712 #define KOALA_INTEROP_4(name, Ret, P0, P1, P2, P3) \
713 napi_value Node_##name(napi_env env, napi_callback_info cbinfo) { \
714 KOALA_MAYBE_LOG(name) \
715 CallbackInfo info(env, cbinfo); \
716 P0 p0 = getArgument<P0>(info, 0); \
717 P1 p1 = getArgument<P1>(info, 1); \
718 P2 p2 = getArgument<P2>(info, 2); \
719 P3 p3 = getArgument<P3>(info, 3); \
720 return makeResult<Ret>(info, impl_##name(p0, p1, p2, p3)); \
721 } \
722 MAKE_NODE_EXPORT(KOALA_INTEROP_MODULE, name)
723
724 #define KOALA_INTEROP_5(name, Ret, P0, P1, P2, P3, P4) \
725 napi_value Node_##name(napi_env env, napi_callback_info cbinfo) { \
726 KOALA_MAYBE_LOG(name) \
727 CallbackInfo info(env, cbinfo); \
728 P0 p0 = getArgument<P0>(info, 0); \
729 P1 p1 = getArgument<P1>(info, 1); \
730 P2 p2 = getArgument<P2>(info, 2); \
731 P3 p3 = getArgument<P3>(info, 3); \
732 P4 p4 = getArgument<P4>(info, 4); \
733 return makeResult<Ret>(info, impl_##name(p0, p1, p2, p3, p4)); \
734 } \
735 MAKE_NODE_EXPORT(KOALA_INTEROP_MODULE, name)
736
737 #define KOALA_INTEROP_6(name, Ret, P0, P1, P2, P3, P4, P5) \
738 napi_value Node_##name(napi_env env, napi_callback_info cbinfo) { \
739 KOALA_MAYBE_LOG(name) \
740 CallbackInfo info(env, cbinfo); \
741 P0 p0 = getArgument<P0>(info, 0); \
742 P1 p1 = getArgument<P1>(info, 1); \
743 P2 p2 = getArgument<P2>(info, 2); \
744 P3 p3 = getArgument<P3>(info, 3); \
745 P4 p4 = getArgument<P4>(info, 4); \
746 P5 p5 = getArgument<P5>(info, 5); \
747 return makeResult<Ret>(info, impl_##name(p0, p1, p2, p3, p4, p5)); \
748 } \
749 MAKE_NODE_EXPORT(KOALA_INTEROP_MODULE, name)
750
751 #define KOALA_INTEROP_7(name, Ret, P0, P1, P2, P3, P4, P5, P6) \
752 napi_value Node_##name(napi_env env, napi_callback_info cbinfo) { \
753 KOALA_MAYBE_LOG(name) \
754 CallbackInfo info(env, cbinfo); \
755 P0 p0 = getArgument<P0>(info, 0); \
756 P1 p1 = getArgument<P1>(info, 1); \
757 P2 p2 = getArgument<P2>(info, 2); \
758 P3 p3 = getArgument<P3>(info, 3); \
759 P4 p4 = getArgument<P4>(info, 4); \
760 P5 p5 = getArgument<P5>(info, 5); \
761 P6 p6 = getArgument<P6>(info, 6); \
762 return makeResult<Ret>(info, impl_##name(p0, p1, p2, p3, p4, p5, p6)); \
763 } \
764 MAKE_NODE_EXPORT(KOALA_INTEROP_MODULE, name)
765
766 #define KOALA_INTEROP_8(name, Ret, P0, P1, P2, P3, P4, P5, P6, P7) \
767 napi_value Node_##name(napi_env env, napi_callback_info cbinfo) { \
768 KOALA_MAYBE_LOG(name) \
769 CallbackInfo info(env, cbinfo); \
770 P0 p0 = getArgument<P0>(info, 0); \
771 P1 p1 = getArgument<P1>(info, 1); \
772 P2 p2 = getArgument<P2>(info, 2); \
773 P3 p3 = getArgument<P3>(info, 3); \
774 P4 p4 = getArgument<P4>(info, 4); \
775 P5 p5 = getArgument<P5>(info, 5); \
776 P6 p6 = getArgument<P6>(info, 6); \
777 P7 p7 = getArgument<P7>(info, 7); \
778 return makeResult<Ret>(info, impl_##name(p0, p1, p2, p3, p4, p5, p6, p7)); \
779 } \
780 MAKE_NODE_EXPORT(KOALA_INTEROP_MODULE, name)
781
782 #define KOALA_INTEROP_9(name, Ret, P0, P1, P2, P3, P4, P5, P6, P7, P8) \
783 napi_value Node_##name(napi_env env, napi_callback_info cbinfo) { \
784 KOALA_MAYBE_LOG(name) \
785 CallbackInfo info(env, cbinfo); \
786 P0 p0 = getArgument<P0>(info, 0); \
787 P1 p1 = getArgument<P1>(info, 1); \
788 P2 p2 = getArgument<P2>(info, 2); \
789 P3 p3 = getArgument<P3>(info, 3); \
790 P4 p4 = getArgument<P4>(info, 4); \
791 P5 p5 = getArgument<P5>(info, 5); \
792 P6 p6 = getArgument<P6>(info, 6); \
793 P7 p7 = getArgument<P7>(info, 7); \
794 P8 p8 = getArgument<P8>(info, 8); \
795 return makeResult<Ret>(info, impl_##name(p0, p1, p2, p3, p4, p5, p6, p7, p8)); \
796 } \
797 MAKE_NODE_EXPORT(KOALA_INTEROP_MODULE, name)
798
799 #define KOALA_INTEROP_10(name, Ret, P0, P1, P2, P3, P4, P5, P6, P7, P8, P9) \
800 napi_value Node_##name(napi_env env, napi_callback_info cbinfo) { \
801 KOALA_MAYBE_LOG(name) \
802 CallbackInfo info(env, cbinfo); \
803 P0 p0 = getArgument<P0>(info, 0); \
804 P1 p1 = getArgument<P1>(info, 1); \
805 P2 p2 = getArgument<P2>(info, 2); \
806 P3 p3 = getArgument<P3>(info, 3); \
807 P4 p4 = getArgument<P4>(info, 4); \
808 P5 p5 = getArgument<P5>(info, 5); \
809 P6 p6 = getArgument<P6>(info, 6); \
810 P7 p7 = getArgument<P7>(info, 7); \
811 P8 p8 = getArgument<P8>(info, 8); \
812 P9 p9 = getArgument<P9>(info, 9); \
813 return makeResult<Ret>(info, impl_##name(p0, p1, p2, p3, p4, p5, p6, p7, p8, p9)); \
814 } \
815 MAKE_NODE_EXPORT(KOALA_INTEROP_MODULE, name)
816
817 #define KOALA_INTEROP_11(name, Ret, P0, P1, P2, P3, P4, P5, P6, P7, P8, P9, P10) \
818 napi_value Node_##name(napi_env env, napi_callback_info cbinfo) { \
819 KOALA_MAYBE_LOG(name) \
820 CallbackInfo info(env, cbinfo); \
821 P0 p0 = getArgument<P0>(info, 0); \
822 P1 p1 = getArgument<P1>(info, 1); \
823 P2 p2 = getArgument<P2>(info, 2); \
824 P3 p3 = getArgument<P3>(info, 3); \
825 P4 p4 = getArgument<P4>(info, 4); \
826 P5 p5 = getArgument<P5>(info, 5); \
827 P6 p6 = getArgument<P6>(info, 6); \
828 P7 p7 = getArgument<P7>(info, 7); \
829 P8 p8 = getArgument<P8>(info, 8); \
830 P9 p9 = getArgument<P9>(info, 9); \
831 P10 p10 = getArgument<P10>(info, 10); \
832 return makeResult<Ret>(info, impl_##name(p0, p1, p2, p3, p4, p5, p6, p7, p8, p9, p10)); \
833 } \
834 MAKE_NODE_EXPORT(KOALA_INTEROP_MODULE, name)
835
836 #define KOALA_INTEROP_12(name, Ret, P0, P1, P2, P3, P4, P5, P6, P7, P8, P9, P10, P11) \
837 napi_value Node_##name(napi_env env, napi_callback_info cbinfo) { \
838 KOALA_MAYBE_LOG(name) \
839 CallbackInfo info(env, cbinfo); \
840 P0 p0 = getArgument<P0>(info, 0); \
841 P1 p1 = getArgument<P1>(info, 1); \
842 P2 p2 = getArgument<P2>(info, 2); \
843 P3 p3 = getArgument<P3>(info, 3); \
844 P4 p4 = getArgument<P4>(info, 4); \
845 P5 p5 = getArgument<P5>(info, 5); \
846 P6 p6 = getArgument<P6>(info, 6); \
847 P7 p7 = getArgument<P7>(info, 7); \
848 P8 p8 = getArgument<P8>(info, 8); \
849 P9 p9 = getArgument<P9>(info, 9); \
850 P10 p10 = getArgument<P10>(info, 10); \
851 P11 p11 = getArgument<P11>(info, 11); \
852 return makeResult<Ret>(info, impl_##name(p0, p1, p2, p3, p4, p5, p6, p7, p8, p9, p10, p11)); \
853 } \
854 MAKE_NODE_EXPORT(KOALA_INTEROP_MODULE, name)
855
856 #define KOALA_INTEROP_13(name, Ret, P0, P1, P2, P3, P4, P5, P6, P7, P8, P9, P10, P11, P12) \
857 napi_value Node_##name(napi_env env, napi_callback_info cbinfo) { \
858 KOALA_MAYBE_LOG(name) \
859 CallbackInfo info(env, cbinfo); \
860 P0 p0 = getArgument<P0>(info, 0); \
861 P1 p1 = getArgument<P1>(info, 1); \
862 P2 p2 = getArgument<P2>(info, 2); \
863 P3 p3 = getArgument<P3>(info, 3); \
864 P4 p4 = getArgument<P4>(info, 4); \
865 P5 p5 = getArgument<P5>(info, 5); \
866 P6 p6 = getArgument<P6>(info, 6); \
867 P7 p7 = getArgument<P7>(info, 7); \
868 P8 p8 = getArgument<P8>(info, 8); \
869 P9 p9 = getArgument<P9>(info, 9); \
870 P10 p10 = getArgument<P10>(info, 10); \
871 P11 p11 = getArgument<P11>(info, 11); \
872 P12 p12 = getArgument<P12>(info, 12); \
873 return makeResult<Ret>(info, impl_##name(p0, p1, p2, p3, p4, p5, p6, p7, p8, p9, p10, p11, p12)); \
874 } \
875 MAKE_NODE_EXPORT(KOALA_INTEROP_MODULE, name)
876
877 #define KOALA_INTEROP_14(name, Ret, P0, P1, P2, P3, P4, P5, P6, P7, P8, P9, P10, P11, P12, P13) \
878 napi_value Node_##name(napi_env env, napi_callback_info cbinfo) { \
879 KOALA_MAYBE_LOG(name) \
880 CallbackInfo info(env, cbinfo); \
881 P0 p0 = getArgument<P0>(info, 0); \
882 P1 p1 = getArgument<P1>(info, 1); \
883 P2 p2 = getArgument<P2>(info, 2); \
884 P3 p3 = getArgument<P3>(info, 3); \
885 P4 p4 = getArgument<P4>(info, 4); \
886 P5 p5 = getArgument<P5>(info, 5); \
887 P6 p6 = getArgument<P6>(info, 6); \
888 P7 p7 = getArgument<P7>(info, 7); \
889 P8 p8 = getArgument<P8>(info, 8); \
890 P9 p9 = getArgument<P9>(info, 9); \
891 P10 p10 = getArgument<P10>(info, 10); \
892 P11 p11 = getArgument<P11>(info, 11); \
893 P12 p12 = getArgument<P12>(info, 12); \
894 P13 p13 = getArgument<P13>(info, 13); \
895 return makeResult<Ret>(info, impl_##name(p0, p1, p2, p3, p4, p5, p6, p7, p8, p9, p10, p11, p12, p13)); \
896 } \
897 MAKE_NODE_EXPORT(KOALA_INTEROP_MODULE, name)
898
899 #define KOALA_INTEROP_V0(name) \
900 napi_value Node_##name(napi_env env, napi_callback_info cbinfo) { \
901 KOALA_MAYBE_LOG(name) \
902 CallbackInfo info(env, cbinfo); \
903 impl_##name(); \
904 return makeVoid(info); \
905 } \
906 MAKE_NODE_EXPORT(KOALA_INTEROP_MODULE, name)
907
908 #define KOALA_INTEROP_V1(name, P0) \
909 napi_value Node_##name(napi_env env, napi_callback_info cbinfo) { \
910 KOALA_MAYBE_LOG(name) \
911 CallbackInfo info(env, cbinfo); \
912 P0 p0 = getArgument<P0>(info, 0); \
913 impl_##name(p0); \
914 return makeVoid(info); \
915 } \
916 MAKE_NODE_EXPORT(KOALA_INTEROP_MODULE, name)
917
918 #define KOALA_INTEROP_V2(name, P0, P1) \
919 napi_value Node_##name(napi_env env, napi_callback_info cbinfo) { \
920 KOALA_MAYBE_LOG(name) \
921 CallbackInfo info(env, cbinfo); \
922 P0 p0 = getArgument<P0>(info, 0); \
923 P1 p1 = getArgument<P1>(info, 1); \
924 impl_##name(p0, p1); \
925 return makeVoid(info); \
926 } \
927 MAKE_NODE_EXPORT(KOALA_INTEROP_MODULE, name)
928
929 #define KOALA_INTEROP_V3(name, P0, P1, P2) \
930 napi_value Node_##name(napi_env env, napi_callback_info cbinfo) { \
931 KOALA_MAYBE_LOG(name) \
932 CallbackInfo info(env, cbinfo); \
933 P0 p0 = getArgument<P0>(info, 0); \
934 P1 p1 = getArgument<P1>(info, 1); \
935 P2 p2 = getArgument<P2>(info, 2); \
936 impl_##name(p0, p1, p2); \
937 return makeVoid(info); \
938 } \
939 MAKE_NODE_EXPORT(KOALA_INTEROP_MODULE, name)
940
941 #define KOALA_INTEROP_V4(name, P0, P1, P2, P3) \
942 napi_value Node_##name(napi_env env, napi_callback_info cbinfo) { \
943 KOALA_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 impl_##name(p0, p1, p2, p3); \
950 return makeVoid(info); \
951 } \
952 MAKE_NODE_EXPORT(KOALA_INTEROP_MODULE, name)
953
954 #define KOALA_INTEROP_V5(name, P0, P1, P2, P3, P4) \
955 napi_value Node_##name(napi_env env, napi_callback_info cbinfo) { \
956 KOALA_MAYBE_LOG(name) \
957 CallbackInfo info(env, cbinfo); \
958 P0 p0 = getArgument<P0>(info, 0); \
959 P1 p1 = getArgument<P1>(info, 1); \
960 P2 p2 = getArgument<P2>(info, 2); \
961 P3 p3 = getArgument<P3>(info, 3); \
962 P4 p4 = getArgument<P4>(info, 4); \
963 impl_##name(p0, p1, p2, p3, p4); \
964 return makeVoid(info); \
965 } \
966 MAKE_NODE_EXPORT(KOALA_INTEROP_MODULE, name)
967
968 #define KOALA_INTEROP_V6(name, P0, P1, P2, P3, P4, P5) \
969 napi_value Node_##name(napi_env env, napi_callback_info cbinfo) { \
970 KOALA_MAYBE_LOG(name) \
971 CallbackInfo info(env, cbinfo); \
972 P0 p0 = getArgument<P0>(info, 0); \
973 P1 p1 = getArgument<P1>(info, 1); \
974 P2 p2 = getArgument<P2>(info, 2); \
975 P3 p3 = getArgument<P3>(info, 3); \
976 P4 p4 = getArgument<P4>(info, 4); \
977 P5 p5 = getArgument<P5>(info, 5); \
978 impl_##name(p0, p1, p2, p3, p4, p5); \
979 return makeVoid(info); \
980 } \
981 MAKE_NODE_EXPORT(KOALA_INTEROP_MODULE, name)
982
983 #define KOALA_INTEROP_V7(name, P0, P1, P2, P3, P4, P5, P6) \
984 napi_value Node_##name(napi_env env, napi_callback_info cbinfo) { \
985 KOALA_MAYBE_LOG(name) \
986 CallbackInfo info(env, cbinfo); \
987 P0 p0 = getArgument<P0>(info, 0); \
988 P1 p1 = getArgument<P1>(info, 1); \
989 P2 p2 = getArgument<P2>(info, 2); \
990 P3 p3 = getArgument<P3>(info, 3); \
991 P4 p4 = getArgument<P4>(info, 4); \
992 P5 p5 = getArgument<P5>(info, 5); \
993 P6 p6 = getArgument<P6>(info, 6); \
994 impl_##name(p0, p1, p2, p3, p4, p5, p6); \
995 return makeVoid(info); \
996 } \
997 MAKE_NODE_EXPORT(KOALA_INTEROP_MODULE, name)
998
999 #define KOALA_INTEROP_V8(name, P0, P1, P2, P3, P4, P5, P6, P7) \
1000 napi_value Node_##name(napi_env env, napi_callback_info cbinfo) { \
1001 KOALA_MAYBE_LOG(name) \
1002 CallbackInfo info(env, cbinfo); \
1003 P0 p0 = getArgument<P0>(info, 0); \
1004 P1 p1 = getArgument<P1>(info, 1); \
1005 P2 p2 = getArgument<P2>(info, 2); \
1006 P3 p3 = getArgument<P3>(info, 3); \
1007 P4 p4 = getArgument<P4>(info, 4); \
1008 P5 p5 = getArgument<P5>(info, 5); \
1009 P6 p6 = getArgument<P6>(info, 6); \
1010 P7 p7 = getArgument<P7>(info, 7); \
1011 impl_##name(p0, p1, p2, p3, p4, p5, p6, p7); \
1012 return makeVoid(info); \
1013 } \
1014 MAKE_NODE_EXPORT(KOALA_INTEROP_MODULE, name)
1015
1016 #define KOALA_INTEROP_V9(name, P0, P1, P2, P3, P4, P5, P6, P7, P8) \
1017 napi_value Node_##name(napi_env env, napi_callback_info cbinfo) { \
1018 KOALA_MAYBE_LOG(impl_##name) \
1019 CallbackInfo info(env, cbinfo); \
1020 P0 p0 = getArgument<P0>(info, 0); \
1021 P1 p1 = getArgument<P1>(info, 1); \
1022 P2 p2 = getArgument<P2>(info, 2); \
1023 P3 p3 = getArgument<P3>(info, 3); \
1024 P4 p4 = getArgument<P4>(info, 4); \
1025 P5 p5 = getArgument<P5>(info, 5); \
1026 P6 p6 = getArgument<P6>(info, 6); \
1027 P7 p7 = getArgument<P7>(info, 7); \
1028 P8 p8 = getArgument<P8>(info, 8); \
1029 impl_##name(p0, p1, p2, p3, p4, p5, p6, p7, p8); \
1030 return makeVoid(info); \
1031 } \
1032 MAKE_NODE_EXPORT(KOALA_INTEROP_MODULE, name)
1033
1034 #define KOALA_INTEROP_V10(name, P0, P1, P2, P3, P4, P5, P6, P7, P8, P9) \
1035 napi_value Node_##name(napi_env env, napi_callback_info cbinfo) { \
1036 KOALA_MAYBE_LOG(name) \
1037 CallbackInfo info(env, cbinfo); \
1038 P0 p0 = getArgument<P0>(info, 0); \
1039 P1 p1 = getArgument<P1>(info, 1); \
1040 P2 p2 = getArgument<P2>(info, 2); \
1041 P3 p3 = getArgument<P3>(info, 3); \
1042 P4 p4 = getArgument<P4>(info, 4); \
1043 P5 p5 = getArgument<P5>(info, 5); \
1044 P6 p6 = getArgument<P6>(info, 6); \
1045 P7 p7 = getArgument<P7>(info, 7); \
1046 P8 p8 = getArgument<P8>(info, 8); \
1047 P9 p9 = getArgument<P9>(info, 9); \
1048 impl_##name(p0, p1, p2, p3, p4, p5, p6, p7, p8, p9); \
1049 return makeVoid(info); \
1050 } \
1051 MAKE_NODE_EXPORT(KOALA_INTEROP_MODULE, name)
1052
1053 #define KOALA_INTEROP_V11(name, P0, P1, P2, P3, P4, P5, P6, P7, P8, P9, P10) \
1054 napi_value Node_##name(napi_env env, napi_callback_info cbinfo) { \
1055 KOALA_MAYBE_LOG(impl_##name) \
1056 CallbackInfo info(env, cbinfo); \
1057 P0 p0 = getArgument<P0>(info, 0); \
1058 P1 p1 = getArgument<P1>(info, 1); \
1059 P2 p2 = getArgument<P2>(info, 2); \
1060 P3 p3 = getArgument<P3>(info, 3); \
1061 P4 p4 = getArgument<P4>(info, 4); \
1062 P5 p5 = getArgument<P5>(info, 5); \
1063 P6 p6 = getArgument<P6>(info, 6); \
1064 P7 p7 = getArgument<P7>(info, 7); \
1065 P8 p8 = getArgument<P8>(info, 8); \
1066 P9 p9 = getArgument<P9>(info, 9); \
1067 P10 p10 = getArgument<P10>(info, 10); \
1068 impl_##name(p0, p1, p2, p3, p4, p5, p6, p7, p8, p9, p10); \
1069 return makeVoid(info); \
1070 } \
1071 MAKE_NODE_EXPORT(KOALA_INTEROP_MODULE, name)
1072
1073 #define KOALA_INTEROP_V12(name, P0, P1, P2, P3, P4, P5, P6, P7, P8, P9, P10, P11) \
1074 napi_value Node_##name(napi_env env, napi_callback_info cbinfo) { \
1075 KOALA_MAYBE_LOG(impl_##name) \
1076 CallbackInfo info(env, cbinfo); \
1077 P0 p0 = getArgument<P0>(info, 0); \
1078 P1 p1 = getArgument<P1>(info, 1); \
1079 P2 p2 = getArgument<P2>(info, 2); \
1080 P3 p3 = getArgument<P3>(info, 3); \
1081 P4 p4 = getArgument<P4>(info, 4); \
1082 P5 p5 = getArgument<P5>(info, 5); \
1083 P6 p6 = getArgument<P6>(info, 6); \
1084 P7 p7 = getArgument<P7>(info, 7); \
1085 P8 p8 = getArgument<P8>(info, 8); \
1086 P9 p9 = getArgument<P9>(info, 9); \
1087 P10 p10 = getArgument<P10>(info, 10); \
1088 P11 p11 = getArgument<P11>(info, 11); \
1089 impl_##name(p0, p1, p2, p3, p4, p5, p6, p7, p8, p9, p10, p11); \
1090 return makeVoid(info); \
1091 } \
1092 MAKE_NODE_EXPORT(KOALA_INTEROP_MODULE, name)
1093
1094 #define KOALA_INTEROP_V13(name, P0, P1, P2, P3, P4, P5, P6, P7, P8, P9, P10, P11, P12) \
1095 napi_value Node_##name(napi_env env, napi_callback_info cbinfo) { \
1096 KOALA_MAYBE_LOG(impl_##name) \
1097 CallbackInfo info(env, cbinfo); \
1098 P0 p0 = getArgument<P0>(info, 0); \
1099 P1 p1 = getArgument<P1>(info, 1); \
1100 P2 p2 = getArgument<P2>(info, 2); \
1101 P3 p3 = getArgument<P3>(info, 3); \
1102 P4 p4 = getArgument<P4>(info, 4); \
1103 P5 p5 = getArgument<P5>(info, 5); \
1104 P6 p6 = getArgument<P6>(info, 6); \
1105 P7 p7 = getArgument<P7>(info, 7); \
1106 P8 p8 = getArgument<P8>(info, 8); \
1107 P9 p9 = getArgument<P9>(info, 9); \
1108 P10 p10 = getArgument<P10>(info, 10); \
1109 P11 p11 = getArgument<P11>(info, 11); \
1110 P12 p12 = getArgument<P12>(info, 12); \
1111 impl_##name(p0, p1, p2, p3, p4, p5, p6, p7, p8, p9, p10, p11, p12); \
1112 return makeVoid(info); \
1113 } \
1114 MAKE_NODE_EXPORT(KOALA_INTEROP_MODULE, name)
1115
1116 #define KOALA_INTEROP_V14(name, P0, P1, P2, P3, P4, P5, P6, P7, P8, P9, P10, P11, P12, P13) \
1117 napi_value Node_##name(napi_env env, napi_callback_info cbinfo) { \
1118 KOALA_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 P7 p7 = getArgument<P7>(info, 7); \
1128 P8 p8 = getArgument<P8>(info, 8); \
1129 P9 p9 = getArgument<P9>(info, 9); \
1130 P10 p10 = getArgument<P10>(info, 10); \
1131 P11 p11 = getArgument<P11>(info, 11); \
1132 P12 p12 = getArgument<P12>(info, 12); \
1133 P13 p13 = getArgument<P13>(info, 13); \
1134 impl_##name(p0, p1, p2, p3, p4, p5, p6, p7, p8, p9, p10, p11, p12, p13); \
1135 return makeVoid(info); \
1136 } \
1137 MAKE_NODE_EXPORT(KOALA_INTEROP_MODULE, name)
1138
1139 #define KOALA_INTEROP_V15(name, P0, P1, P2, P3, P4, P5, P6, P7, P8, P9, P10, P11, P12, P13, P14) \
1140 napi_value Node_##name(napi_env env, napi_callback_info cbinfo) { \
1141 KOALA_MAYBE_LOG(name) \
1142 CallbackInfo info(env, cbinfo); \
1143 P0 p0 = getArgument<P0>(info, 0); \
1144 P1 p1 = getArgument<P1>(info, 1); \
1145 P2 p2 = getArgument<P2>(info, 2); \
1146 P3 p3 = getArgument<P3>(info, 3); \
1147 P4 p4 = getArgument<P4>(info, 4); \
1148 P5 p5 = getArgument<P5>(info, 5); \
1149 P6 p6 = getArgument<P6>(info, 6); \
1150 P7 p7 = getArgument<P7>(info, 7); \
1151 P8 p8 = getArgument<P8>(info, 8); \
1152 P9 p9 = getArgument<P9>(info, 9); \
1153 P10 p10 = getArgument<P10>(info, 10); \
1154 P11 p11 = getArgument<P11>(info, 11); \
1155 P12 p12 = getArgument<P12>(info, 12); \
1156 P13 p13 = getArgument<P13>(info, 13); \
1157 P14 p14 = getArgument<P14>(info, 14); \
1158 impl_##name(p0, p1, p2, p3, p4, p5, p6, p7, p8, p9, p10, p11, p12, p13, p14); \
1159 return makeVoid(info); \
1160 } \
1161 MAKE_NODE_EXPORT(KOALA_INTEROP_MODULE, name)
1162
1163 #define KOALA_INTEROP_CTX_0(name, Ret) \
1164 napi_value Node_##name(napi_env env, napi_callback_info cbinfo) { \
1165 KOALA_MAYBE_LOG(impl_##name) \
1166 CallbackInfo info(env, cbinfo); \
1167 KVMContext ctx = reinterpret_cast<KVMContext>((napi_env)info.Env()); \
1168 return makeResult<Ret>(info, impl_##name(ctx)); \
1169 } \
1170 MAKE_NODE_EXPORT(KOALA_INTEROP_MODULE, name)
1171
1172 #define KOALA_INTEROP_CTX_1(name, Ret, P0) \
1173 napi_value Node_##name(napi_env env, napi_callback_info cbinfo) { \
1174 KOALA_MAYBE_LOG(impl_##name) \
1175 CallbackInfo info(env, cbinfo); \
1176 KVMContext ctx = reinterpret_cast<KVMContext>((napi_env)info.Env()); \
1177 P0 p0 = getArgument<P0>(info, 0); \
1178 return makeResult<Ret>(info, impl_##name(ctx, p0)); \
1179 } \
1180 MAKE_NODE_EXPORT(KOALA_INTEROP_MODULE, name)
1181
1182 #define KOALA_INTEROP_CTX_2(name, Ret, P0, P1) \
1183 napi_value Node_##name(napi_env env, napi_callback_info cbinfo) { \
1184 KOALA_MAYBE_LOG(name) \
1185 CallbackInfo info(env, cbinfo); \
1186 KVMContext ctx = reinterpret_cast<KVMContext>((napi_env)info.Env()); \
1187 P0 p0 = getArgument<P0>(info, 0); \
1188 P1 p1 = getArgument<P1>(info, 1); \
1189 return makeResult<Ret>(info, impl_##name(ctx, p0, p1)); \
1190 } \
1191 MAKE_NODE_EXPORT(KOALA_INTEROP_MODULE, name)
1192
1193 #define KOALA_INTEROP_CTX_3(name, Ret, P0, P1, P2) \
1194 napi_value Node_##name(napi_env env, napi_callback_info cbinfo) { \
1195 KOALA_MAYBE_LOG(name) \
1196 CallbackInfo info(env, cbinfo); \
1197 KVMContext ctx = reinterpret_cast<KVMContext>((napi_env)info.Env()); \
1198 P0 p0 = getArgument<P0>(info, 0); \
1199 P1 p1 = getArgument<P1>(info, 1); \
1200 P2 p2 = getArgument<P2>(info, 2); \
1201 return makeResult<Ret>(info, impl_##name(ctx, p0, p1, p2)); \
1202 } \
1203 MAKE_NODE_EXPORT(KOALA_INTEROP_MODULE, name)
1204
1205 #define KOALA_INTEROP_CTX_4(name, Ret, P0, P1, P2, P3) \
1206 napi_value Node_##name(napi_env env, napi_callback_info cbinfo) { \
1207 KOALA_MAYBE_LOG(name) \
1208 CallbackInfo info(env, cbinfo); \
1209 KVMContext ctx = reinterpret_cast<KVMContext>((napi_env)info.Env()); \
1210 P0 p0 = getArgument<P0>(info, 0); \
1211 P1 p1 = getArgument<P1>(info, 1); \
1212 P2 p2 = getArgument<P2>(info, 2); \
1213 P3 p3 = getArgument<P3>(info, 3); \
1214 return makeResult<Ret>(info, impl_##name(ctx, p0, p1, p2, p3)); \
1215 } \
1216 MAKE_NODE_EXPORT(KOALA_INTEROP_MODULE, name)
1217
1218 #define KOALA_INTEROP_CTX_V0(name) \
1219 napi_value Node_##name(napi_env env, napi_callback_info cbinfo) { \
1220 KOALA_MAYBE_LOG(name) \
1221 CallbackInfo info(env, cbinfo); \
1222 KVMContext ctx = reinterpret_cast<KVMContext>((napi_env)info.Env()); \
1223 impl_##name(ctx); \
1224 return makeVoid(info); \
1225 } \
1226 MAKE_NODE_EXPORT(KOALA_INTEROP_MODULE, name)
1227
1228
1229 #define KOALA_INTEROP_CTX_V1(name, P0) \
1230 napi_value Node_##name(napi_env env, napi_callback_info cbinfo) { \
1231 KOALA_MAYBE_LOG(name) \
1232 CallbackInfo info(env, cbinfo); \
1233 KVMContext ctx = reinterpret_cast<KVMContext>((napi_env)info.Env()); \
1234 P0 p0 = getArgument<P0>(info, 0); \
1235 impl_##name(ctx, p0); \
1236 return makeVoid(info); \
1237 } \
1238 MAKE_NODE_EXPORT(KOALA_INTEROP_MODULE, name)
1239
1240 #define KOALA_INTEROP_CTX_V2(name, P0, P1) \
1241 napi_value Node_##name(napi_env env, napi_callback_info cbinfo) { \
1242 KOALA_MAYBE_LOG(name) \
1243 CallbackInfo info(env, cbinfo); \
1244 KVMContext ctx = reinterpret_cast<KVMContext>((napi_env)info.Env()); \
1245 P0 p0 = getArgument<P0>(info, 0); \
1246 P1 p1 = getArgument<P1>(info, 1); \
1247 impl_##name(ctx, p0, p1); \
1248 return makeVoid(info); \
1249 } \
1250 MAKE_NODE_EXPORT(KOALA_INTEROP_MODULE, name)
1251
1252 #define KOALA_INTEROP_CTX_V3(name, P0, P1, P2) \
1253 napi_value Node_##name(napi_env env, napi_callback_info cbinfo) { \
1254 KOALA_MAYBE_LOG(name) \
1255 CallbackInfo info(env, cbinfo); \
1256 KVMContext ctx = reinterpret_cast<KVMContext>((napi_env)info.Env()); \
1257 P0 p0 = getArgument<P0>(info, 0); \
1258 P1 p1 = getArgument<P1>(info, 1); \
1259 P2 p2 = getArgument<P2>(info, 2); \
1260 impl_##name(ctx, p0, p1, p2); \
1261 return makeVoid(info); \
1262 } \
1263 MAKE_NODE_EXPORT(KOALA_INTEROP_MODULE, name)
1264
1265 #define KOALA_INTEROP_CTX_V4(name, P0, P1, P2, P3) \
1266 napi_value Node_##name(napi_env env, napi_callback_info cbinfo) { \
1267 KOALA_MAYBE_LOG(name) \
1268 CallbackInfo info(env, cbinfo); \
1269 KVMContext ctx = reinterpret_cast<KVMContext>((napi_env)info.Env()); \
1270 P0 p0 = getArgument<P0>(info, 0); \
1271 P1 p1 = getArgument<P1>(info, 1); \
1272 P2 p2 = getArgument<P2>(info, 2); \
1273 P3 p3 = getArgument<P3>(info, 3); \
1274 impl_##name(ctx, p0, p1, p2, p3); \
1275 return makeVoid(info); \
1276 } \
1277 MAKE_NODE_EXPORT(KOALA_INTEROP_MODULE, name)
1278
1279 #define KOALA_INTEROP_CTX_V5(name, P0, P1, P2, P3, P4) \
1280 napi_value Node_##name(napi_env env, napi_callback_info cbinfo) { \
1281 KOALA_MAYBE_LOG(name) \
1282 CallbackInfo info(env, cbinfo); \
1283 KVMContext ctx = reinterpret_cast<KVMContext>((napi_env)info.Env()); \
1284 P0 p0 = getArgument<P0>(info, 0); \
1285 P1 p1 = getArgument<P1>(info, 1); \
1286 P2 p2 = getArgument<P2>(info, 2); \
1287 P3 p3 = getArgument<P3>(info, 3); \
1288 P4 p4 = getArgument<P4>(info, 4); \
1289 impl_##name(ctx, p0, p1, p2, p3, p4); \
1290 return makeVoid(info); \
1291 } \
1292 MAKE_NODE_EXPORT(KOALA_INTEROP_MODULE, name)
1293
1294 #define NODEJS_GET_AND_THROW_LAST_ERROR(env) \
1295 do { \
1296 const napi_extended_error_info *error_info; \
1297 napi_get_last_error_info((env), &error_info); \
1298 bool is_pending; \
1299 napi_is_exception_pending((env), &is_pending); \
1300 /* If an exception is already pending, don't rethrow it */ \
1301 if (!is_pending) { \
1302 const char* error_message = error_info->error_message != NULL ? \
1303 error_info->error_message : \
1304 "empty error message"; \
1305 napi_throw_error((env), NULL, error_message); \
1306 } \
1307 } while (0)
1308
1309 napi_value getKoalaNapiCallbackDispatcher(napi_env env);
1310 // TODO: can/shall we cache bridge reference?
1311
1312 #define KOALA_INTEROP_CALL_VOID(venv, id, length, args) \
1313 { \
1314 napi_env env = reinterpret_cast<napi_env>(venv); \
1315 napi_value bridge = getKoalaNapiCallbackDispatcher(env), \
1316 global = nullptr, return_val = nullptr; \
1317 napi_handle_scope scope = nullptr; \
1318 napi_open_handle_scope(env, &scope); \
1319 napi_status status = napi_get_global(env, &global); \
1320 napi_value node_args[3]; \
1321 napi_create_int32(env, id, &node_args[0]); \
1322 napi_value buffer = nullptr; \
1323 napi_create_external_arraybuffer(env, \
1324 args, length, \
1325 [](napi_env, void* data, void* hint) {}, nullptr, &buffer); \
1326 napi_create_typedarray(env, napi_uint8_array, length, buffer, 0, &node_args[1]); \
1327 napi_create_int32(env, length, &node_args[2]); \
1328 status = napi_call_function(env, global, bridge, 3, node_args, &return_val); \
1329 if (status != napi_ok) NODEJS_GET_AND_THROW_LAST_ERROR((env)); \
1330 napi_close_handle_scope(env, scope); \
1331 }
1332
1333 #define KOALA_INTEROP_CALL_INT(venv, id, length, args) \
1334 { \
1335 napi_env env = reinterpret_cast<napi_env>(venv); \
1336 napi_value bridge = getKoalaNapiCallbackDispatcher(env), \
1337 global = nullptr, return_val = nullptr; \
1338 napi_handle_scope scope = nullptr; \
1339 napi_open_handle_scope(env, &scope); \
1340 napi_status status = napi_get_global(env, &global); \
1341 napi_value node_args[3]; \
1342 napi_create_int32(env, id, &node_args[0]); \
1343 napi_value buffer = nullptr; \
1344 napi_create_external_arraybuffer(env, \
1345 args, length, \
1346 [](napi_env, void* data, void* hint) {}, nullptr, &buffer); \
1347 napi_create_typedarray(env, napi_uint8_array, length, buffer, 0, &node_args[1]); \
1348 napi_create_int32(env, length, &node_args[2]); \
1349 status = napi_call_function(env, global, bridge, 3, node_args, &return_val); \
1350 if (status != napi_ok) NODEJS_GET_AND_THROW_LAST_ERROR((env)); \
1351 int result; \
1352 status = napi_get_value_int32(env, return_val, &result); \
1353 napi_close_handle_scope(env, scope); \
1354 return result; \
1355 }
1356
1357 #define KOALA_INTEROP_CALL_VOID_INTS32(venv, id, argc, args) KOALA_INTEROP_CALL_VOID(venv, id, (argc) * sizeof(int32_t), args)
1358 #define KOALA_INTEROP_CALL_INT_INTS32(venv, id, argc, args) KOALA_INTEROP_CALL_INT(venv, id, (argc) * sizeof(int32_t), args)
1359
1360 #endif // KOALA_NAPI
1361
1362 #endif // _CONVERTORS_NAPI_H_