* Copyright (c) 2025 Huawei Device Co., Ltd.
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
#ifndef CONVERTORS_NAPI_H_
#define CONVERTORS_NAPI_H_
#include <array>
#include <unordered_map>
#include <vector>
#include <string>
#include <iostream>
#include <stdexcept>
#ifndef TS_NAPI_OHOS
#include <node_api.h>
#else
#include <native_api.h>
#include <native_node_api.h>
#endif
#include "panda_types.h"
template <class T>
struct InteropTypeConverter {
using InteropType = T;
static T ConvertFrom([[maybe_unused]] napi_env env, InteropType value)
{
return value;
}
static InteropType ConvertTo([[maybe_unused]] napi_env env, T value)
{
return value;
}
static void Release([[maybe_unused]] napi_env env, [[maybe_unused]] InteropType value, [[maybe_unused]] T converted)
{
}
};
template <typename Type>
inline typename InteropTypeConverter<Type>::InteropType MakeResult(napi_env env, Type value)
{
return InteropTypeConverter<Type>::ConvertTo(env, value);
}
template <typename Type>
inline Type GetArgument(napi_env env, typename InteropTypeConverter<Type>::InteropType arg)
{
return InteropTypeConverter<Type>::ConvertFrom(env, arg);
}
template <typename Type>
inline void ReleaseArgument(napi_env env, typename InteropTypeConverter<Type>::InteropType arg, Type data)
{
InteropTypeConverter<Type>::Release(env, arg, data);
}
template <>
struct InteropTypeConverter<KInteropBuffer> {
using InteropType = napi_value;
static KInteropBuffer ConvertFrom(napi_env env, InteropType value)
{
auto placeholder = 0;
KInteropBuffer result = {placeholder, nullptr, 0, nullptr};
bool isArrayBuffer = false;
napi_is_arraybuffer(env, value, &isArrayBuffer);
if (isArrayBuffer) {
napi_get_arraybuffer_info(env, value, &result.data, reinterpret_cast<size_t *>(&result.length));
} else {
bool isDataView = false;
napi_is_dataview(env, value, &isDataView);
if (isDataView) {
napi_get_dataview_info(env, value, reinterpret_cast<size_t *>(&result.length), &result.data, nullptr,
nullptr);
}
}
return result;
}
static InteropType ConvertTo(napi_env env, KInteropBuffer value)
{
auto *copy = new KInteropBuffer(value);
napi_value result;
napi_status status = napi_create_external_arraybuffer(
env, value.data, value.length,
[]([[maybe_unused]] napi_env envArg, [[maybe_unused]] void *finalizeData, void *finalizeHint) {
auto *buffer = reinterpret_cast<KInteropBuffer *>(finalizeHint);
buffer->dispose(buffer->resourceId);
delete buffer;
},
(void *)copy, &result);
if (status != napi_ok) {
}
return result;
};
static void Release([[maybe_unused]] napi_env env, [[maybe_unused]] InteropType value,
[[maybe_unused]] KInteropBuffer converted)
{
}
};
template <>
struct InteropTypeConverter<KStringPtr> {
using InteropType = napi_value;
static KStringPtr ConvertFrom(napi_env env, InteropType value)
{
if (value == nullptr) {
return KStringPtr();
}
KStringPtr result;
size_t length = 0;
napi_status status = napi_get_value_string_utf8(env, value, nullptr, 0, &length);
if (status != 0) {
return result;
}
result.Resize(length);
napi_get_value_string_utf8(env, value, result.Data(), length + 1, nullptr);
return result;
}
static InteropType ConvertTo(napi_env env, const KStringPtr &value)
{
napi_value result;
napi_create_string_utf8(env, value.CStr(), value.Length(), &result);
return result;
}
static void Release([[maybe_unused]] napi_env env, [[maybe_unused]] InteropType value,
[[maybe_unused]] const KStringPtr &converted)
{
}
};
template <>
struct InteropTypeConverter<KInteropNumber> {
using InteropType = napi_value;
static KInteropNumber ConvertFrom(napi_env env, InteropType interopValue)
{
double value = 0.0;
napi_get_value_double(env, interopValue, &value);
return KInteropNumber::FromDouble(value);
}
static InteropType ConvertTo(napi_env env, KInteropNumber value)
{
napi_value result;
napi_create_double(env, value.AsDouble(), &result);
return result;
}
static void Release([[maybe_unused]] napi_env env, [[maybe_unused]] InteropType value,
[[maybe_unused]] KInteropNumber converted)
{
}
};
template <>
struct InteropTypeConverter<KVMObjectHandle> {
using InteropType = napi_value;
static inline KVMObjectHandle ConvertFrom([[maybe_unused]] napi_env env, InteropType value)
{
return reinterpret_cast<KVMObjectHandle>(value);
}
static InteropType ConvertTo([[maybe_unused]] napi_env env, KVMObjectHandle value)
{
return reinterpret_cast<napi_value>(value);
}
static inline void Release([[maybe_unused]] napi_env env, [[maybe_unused]] InteropType value,
[[maybe_unused]] KVMObjectHandle converted)
{
}
};
template <>
struct InteropTypeConverter<KInteropReturnBuffer> {
using InteropType = napi_value;
static inline KInteropReturnBuffer ConvertFrom(napi_env env, InteropType value) = delete;
static void Disposer([[maybe_unused]] napi_env env, [[maybe_unused]] void *data, void *hint)
{
auto *bufferCopy = static_cast<KInteropReturnBuffer *>(hint);
bufferCopy->dispose(bufferCopy->data, bufferCopy->length);
delete bufferCopy;
}
static InteropType ConvertTo(napi_env env, KInteropReturnBuffer value)
{
napi_value result = nullptr;
napi_value arrayBuffer = nullptr;
auto clone = new KInteropReturnBuffer();
*clone = value;
napi_create_external_arraybuffer(env, value.data, value.length, Disposer, clone, &arrayBuffer);
napi_create_typedarray(env, napi_uint8_array, value.length, arrayBuffer, 0, &result);
return result;
}
static inline void Release(napi_env env, InteropType value, const KInteropReturnBuffer &converted) = delete;
};
#define TS_INTEROP_THROW(vmcontext, object, ...) \
do { \
napi_env env = (napi_env)vmcontext; \
napi_handle_scope scope = nullptr; \
[[maybe_unused]] napi_status status = napi_open_handle_scope(env, &scope); \
napi_throw((napi_env)vmcontext, object); \
napi_close_handle_scope(env, scope); \
\
return __VA_ARGS__; \
} while (0)
#define TS_INTEROP_THROW_STRING(vmContext, message, ...) \
do { \
napi_value value; \
napi_create_string_utf8((napi_env)vmContext, message, strlen(message), &value); \
TS_INTEROP_THROW(vmContext, value, __VA_ARGS__); \
} while (0)
#define NAPI_ASSERT_INDEX(info, index, result) \
do { \
\
if ((static_cast<size_t>(index)) >= (info).Length()) { \
\
napi_throw_error((info).Env(), nullptr, "No such element"); \
\
return result; \
} \
} while (0)
#define TS_NAPI_THROW_IF_FAILED(env, status, ...) \
if ((status) != napi_ok) { \
const napi_extended_error_info *errorInfo; \
napi_get_last_error_info(env, &errorInfo); \
napi_throw_error(env, nullptr, errorInfo->error_message); \
\
return __VA_ARGS__; \
}
#define TS_NAPI_THROW_IF_FAILED_VOID(env, status) \
if ((status) != napi_ok) { \
const napi_extended_error_info *errorInfo; \
napi_get_last_error_info(env, &errorInfo); \
napi_throw_error(env, nullptr, errorInfo->error_message); \
\
return; \
}
class CallbackInfo {
public:
CallbackInfo(napi_env env, napi_callback_info info) : env_(env)
{
size_t size = 0;
napi_status status = napi_get_cb_info(env, info, &size, nullptr, nullptr, nullptr);
TS_NAPI_THROW_IF_FAILED_VOID(env, status);
if (size > 0) {
args_.resize(
size);
status = napi_get_cb_info(env, info, &size, args_.data(), nullptr, nullptr);
TS_NAPI_THROW_IF_FAILED_VOID(env, status);
}
}
napi_value operator[](size_t idx) const
{
if (idx >= Length()) {
napi_value result;
napi_get_undefined(env_, &result);
return result;
}
return args_[idx];
}
napi_env Env() const
{
return env_;
}
size_t Length() const
{
return args_.size();
}
private:
napi_env env_;
std::vector<napi_value> args_;
};
template <typename ElemType>
inline napi_typedarray_type GetNapiType() = delete;
template <>
inline napi_typedarray_type GetNapiType<float>()
{
return napi_float32_array;
}
template <>
inline napi_typedarray_type GetNapiType<int8_t>()
{
return napi_int8_array;
}
template <>
inline napi_typedarray_type GetNapiType<uint8_t>()
{
return napi_uint8_array;
}
template <>
inline napi_typedarray_type GetNapiType<int16_t>()
{
return napi_int16_array;
}
template <>
inline napi_typedarray_type GetNapiType<uint16_t>()
{
return napi_uint16_array;
}
template <>
inline napi_typedarray_type GetNapiType<int32_t>()
{
return napi_int32_array;
}
template <>
inline napi_typedarray_type GetNapiType<uint32_t>()
{
return napi_uint32_array;
}
template <>
inline napi_typedarray_type GetNapiType<KNativePointer>()
{
return napi_biguint64_array;
}
napi_valuetype GetValueTypeChecked(napi_env env, napi_value value);
bool IsTypedArray(napi_env env, napi_value value);
template <typename ElemType>
inline ElemType *GetTypedElements(napi_env env, napi_value value)
{
napi_valuetype valueType = GetValueTypeChecked(env, value);
if (valueType == napi_null) {
return nullptr;
}
if (!IsTypedArray(env, value)) {
napi_throw_error(env, nullptr, "Expected TypedArray");
return nullptr;
}
napi_value arrayBuffer;
void *data = nullptr;
size_t byteLength;
size_t byteOffset;
napi_typedarray_type type;
napi_status status = napi_get_typedarray_info(env, value, &type, &byteLength, &data, &arrayBuffer, &byteOffset);
TS_NAPI_THROW_IF_FAILED(env, status, nullptr);
if (type != GetNapiType<ElemType>()) {
std::cout << "Array type mismatch. Expected " << GetNapiType<ElemType>() << " got " << type << std::endl;
napi_throw_error(env, nullptr, "Array type mismatch");
return nullptr;
}
return reinterpret_cast<ElemType *>(data);
}
template <typename ElemType>
inline ElemType *GetTypedElements(const CallbackInfo &info, int index)
{
NAPI_ASSERT_INDEX(info, index, nullptr);
return GetTypedElements<ElemType>(info.Env(), info[index]);
}
inline uint8_t *GetUInt8Elements(const CallbackInfo &info, int index)
{
return GetTypedElements<uint8_t>(info, index);
}
inline int8_t *GetInt8Elements(const CallbackInfo &info, int index)
{
return GetTypedElements<int8_t>(info, index);
}
inline uint16_t *GetUInt16Elements(const CallbackInfo &info, int index)
{
return GetTypedElements<uint16_t>(info, index);
}
inline int16_t *GetInt16Elements(const CallbackInfo &info, int index)
{
return GetTypedElements<int16_t>(info, index);
}
inline uint32_t *GetUInt32Elements(const CallbackInfo &info, int index)
{
return GetTypedElements<uint32_t>(info, index);
}
inline uint32_t *GetUInt32Elements(napi_env env, napi_value value)
{
return GetTypedElements<uint32_t>(env, value);
}
inline int32_t *GetInt32Elements(const CallbackInfo &info, int index)
{
return GetTypedElements<int32_t>(info, index);
}
inline float *GetFloat32Elements(const CallbackInfo &info, int index)
{
return GetTypedElements<float>(info, index);
}
inline KNativePointer *GetPointerElements(const CallbackInfo &info, int index)
{
return GetTypedElements<KNativePointer>(info, index);
}
KInt GetInt32(napi_env env, napi_value value);
inline int32_t GetInt32(const CallbackInfo &info, int index)
{
NAPI_ASSERT_INDEX(info, index, 0);
return GetInt32(info.Env(), info[index]);
}
KUInt GetUInt32(napi_env env, napi_value value);
inline uint32_t GetUInt32(const CallbackInfo &info, int index)
{
NAPI_ASSERT_INDEX(info, index, 0);
return GetUInt32(info.Env(), info[index]);
}
KFloat GetFloat32(napi_env env, napi_value value);
inline float GetFloat32(const CallbackInfo &info, int index)
{
NAPI_ASSERT_INDEX(info, index, 0.0F);
return GetFloat32(info.Env(), info[index]);
}
KDouble GetFloat64(napi_env env, napi_value value);
inline KDouble GetFloat64(const CallbackInfo &info, int index)
{
NAPI_ASSERT_INDEX(info, index, 0.0);
return GetFloat64(info.Env(), info[index]);
}
KStringPtr GetString(napi_env env, napi_value value);
inline KStringPtr GetString(const CallbackInfo &info, int index)
{
NAPI_ASSERT_INDEX(info, index, KStringPtr());
return GetString(info.Env(), info[index]);
}
void *GetPointer(napi_env env, napi_value value);
inline void *GetPointer(const CallbackInfo &info, int index)
{
NAPI_ASSERT_INDEX(info, index, nullptr);
return GetPointer(info.Env(), info[index]);
}
KLong GetInt64(napi_env env, napi_value value);
inline KLong GetInt64(const CallbackInfo &info, int index)
{
NAPI_ASSERT_INDEX(info, index, 0);
return GetInt64(info.Env(), info[index]);
}
KBoolean GetBoolean(napi_env env, napi_value value);
inline KBoolean GetBoolean(const CallbackInfo &info, int index)
{
NAPI_ASSERT_INDEX(info, index, false);
return GetBoolean(info.Env(), info[index]);
}
template <typename Type>
inline Type GetArgument(const CallbackInfo &info, int index) = delete;
template <>
inline KBoolean GetArgument<KBoolean>(const CallbackInfo &info, int index)
{
return GetBoolean(info, index);
}
template <>
inline KUInt GetArgument<uint32_t>(const CallbackInfo &info, int index)
{
return GetUInt32(info, index);
}
template <>
inline KInt GetArgument<int32_t>(const CallbackInfo &info, int index)
{
return GetInt32(info, index);
}
template <>
inline KInteropNumber GetArgument<KInteropNumber>(const CallbackInfo &info, int index)
{
KInteropNumber res {};
NAPI_ASSERT_INDEX(info, index, res);
return GetArgument<KInteropNumber>(info.Env(), info[index]);
}
template <>
inline KLength GetArgument<KLength>(const CallbackInfo &info, int index)
{
KLength result = {0, 0.0F, 0, 0};
NAPI_ASSERT_INDEX(info, index, result);
auto value = info[index];
napi_valuetype type;
auto typeStatus = napi_typeof(info.Env(), value, &type);
if (typeStatus != 0) {
return result;
}
switch (type) {
case napi_number: {
result.value = GetFloat32(info.Env(), value);
result.unit = 1;
result.type = 0;
break;
}
case napi_string: {
KStringPtr string = GetString(info.Env(), value);
ParseKLength(string, &result);
result.type = 1;
result.resource = 0;
break;
}
case napi_object: {
result.value = 0;
result.unit = 1;
result.type = 2U;
napi_value field;
napi_status status = napi_get_named_property(info.Env(), value, "id", &field);
if (status == 0) {
status = napi_get_value_int32(info.Env(), field, &result.resource);
if (status != 0) {
result.resource = 0;
}
} else {
result.resource = 0;
}
break;
}
default:
throw std::runtime_error("Error, unexpected KLength type");
}
return result;
}
template <>
inline KInteropBuffer GetArgument<KInteropBuffer>(const CallbackInfo &info, int index)
{
KInteropBuffer res = {0, nullptr, 0, nullptr};
NAPI_ASSERT_INDEX(info, index, res);
return GetArgument<KInteropBuffer>((napi_env)info.Env(), (napi_value)info[index]);
}
template <>
inline KFloat GetArgument<KFloat>(const CallbackInfo &info, int index)
{
return GetFloat32(info, index);
}
template <>
inline KDouble GetArgument<KDouble>(const CallbackInfo &info, int index)
{
return GetFloat64(info, index);
}
template <>
inline KNativePointer GetArgument<KNativePointer>(const CallbackInfo &info, int index)
{
return GetPointer(info, index);
}
template <>
inline KLong GetArgument<KLong>(const CallbackInfo &info, int index)
{
return GetInt64(info, index);
}
template <>
inline KNativePointerArray GetArgument<KNativePointerArray>(const CallbackInfo &info, int index)
{
return GetPointerElements(info, index);
}
template <>
inline uint8_t *GetArgument<uint8_t *>(const CallbackInfo &info, int index)
{
return GetUInt8Elements(info, index);
}
template <>
inline const uint8_t *GetArgument<const uint8_t *>(const CallbackInfo &info, int index)
{
return GetUInt8Elements(info, index);
}
template <>
inline int8_t *GetArgument<int8_t *>(const CallbackInfo &info, int index)
{
return GetInt8Elements(info, index);
}
template <>
inline int16_t *GetArgument<int16_t *>(const CallbackInfo &info, int index)
{
return GetInt16Elements(info, index);
}
template <>
inline uint16_t *GetArgument<uint16_t *>(const CallbackInfo &info, int index)
{
return GetUInt16Elements(info, index);
}
template <>
inline int32_t *GetArgument<int32_t *>(const CallbackInfo &info, int index)
{
return GetInt32Elements(info, index);
}
template <>
inline uint32_t *GetArgument<uint32_t *>(const CallbackInfo &info, int index)
{
return GetUInt32Elements(info, index);
}
template <>
inline float *GetArgument<float *>(const CallbackInfo &info, int index)
{
return GetFloat32Elements(info, index);
}
template <>
inline KStringPtr GetArgument<KStringPtr>(const CallbackInfo &info, int index)
{
return GetString(info, index);
}
napi_value MakeString(napi_env env, KStringPtr value);
napi_value MakeString(napi_env env, const std::string &value);
napi_value MakeBoolean(napi_env env, KBoolean value);
napi_value MakeInt32(napi_env env, int32_t value);
napi_value MakeUInt32(napi_env env, uint32_t value);
napi_value MakeFloat32(napi_env env, float value);
napi_value MakePointer(napi_env env, void *value);
napi_value MakeVoid(napi_env env);
inline napi_value MakeVoid(const CallbackInfo &info)
{
return MakeVoid(info.Env());
}
template <typename Type>
inline napi_value MakeResult(const CallbackInfo &info, Type value) = delete;
template <>
inline napi_value MakeResult<KBoolean>(const CallbackInfo &info, KBoolean value)
{
return MakeBoolean(info.Env(), value);
}
template <>
inline napi_value MakeResult<int32_t>(const CallbackInfo &info, int32_t value)
{
return MakeInt32(info.Env(), value);
}
template <>
inline napi_value MakeResult<uint32_t>(const CallbackInfo &info, uint32_t value)
{
return MakeUInt32(info.Env(), value);
}
template <>
inline napi_value MakeResult<float>(const CallbackInfo &info, float value)
{
return MakeFloat32(info.Env(), value);
}
template <>
inline napi_value MakeResult<KNativePointer>(const CallbackInfo &info, KNativePointer value)
{
return MakePointer(info.Env(), value);
}
template <>
inline napi_value MakeResult<KVMObjectHandle>(const CallbackInfo &info, KVMObjectHandle value)
{
return InteropTypeConverter<KVMObjectHandle>::ConvertTo(info.Env(), value);
}
template <>
inline napi_value MakeResult<KStringPtr>(const CallbackInfo &info, KStringPtr value)
{
return InteropTypeConverter<KStringPtr>::ConvertTo(info.Env(), value);
}
template <>
inline napi_value MakeResult<KInteropBuffer>(const CallbackInfo &info, KInteropBuffer value)
{
return InteropTypeConverter<KInteropBuffer>::ConvertTo(info.Env(), value);
}
template <>
inline napi_value MakeResult<KInteropReturnBuffer>(const CallbackInfo &info, KInteropReturnBuffer value)
{
return InteropTypeConverter<KInteropReturnBuffer>::ConvertTo(info.Env(), value);
}
template <>
inline napi_value MakeResult<KInteropNumber>(const CallbackInfo &info, KInteropNumber value)
{
return InteropTypeConverter<KInteropNumber>::ConvertTo(info.Env(), value);
}
using NapiTypeT = napi_value (*)(napi_env, napi_callback_info);
class Exports {
std::unordered_map<std::string, std::vector<std::pair<std::string, NapiTypeT>>> implementations_;
public:
static Exports *GetInstance();
std::vector<std::string> GetModules();
void addMethod(const char *module, const char *name, NapiTypeT impl);
const std::vector<std::pair<std::string, NapiTypeT>> &GetMethods(const std::string &module);
};
#define __QUOTE(x) #x
#define QUOTE(x) __QUOTE(x)
#define MAKE_NODE_EXPORT(module, name) \
__attribute__((constructor)) static void __init_##name() \
{ \
Exports::GetInstance()->addMethod(QUOTE(module), "_" #name, Node_##name); \
}
#ifndef TS_INTEROP_MODULE
#error TS_INTEROP_MODULE is undefined
#endif
#define MAKE_INTEROP_NODE_EXPORT(name) MAKE_NODE_EXPORT(TS_INTEROP_MODULE, name)
#define TS_INTEROP_0(name, Ret) \
napi_value Node_##name(napi_env env, napi_callback_info cbinfo) \
{ \
TS_MAYBE_LOG(name) \
CallbackInfo info(env, cbinfo); \
\
return MakeResult<Ret>(info, impl_##name()); \
} \
MAKE_NODE_EXPORT(TS_INTEROP_MODULE, name)
#define TS_INTEROP_1(name, Ret, P0) \
napi_value Node_##name(napi_env env, napi_callback_info cbinfo) \
{ \
TS_MAYBE_LOG(name) \
CallbackInfo info(env, cbinfo); \
P0 p0 = GetArgument<P0>(info, 0); \
\
return MakeResult<Ret>(info, impl_##name(p0)); \
} \
MAKE_NODE_EXPORT(TS_INTEROP_MODULE, name)
#define TS_INTEROP_2(name, Ret, P0, P1) \
napi_value Node_##name(napi_env env, napi_callback_info cbinfo) \
{ \
TS_MAYBE_LOG(name) \
CallbackInfo info(env, cbinfo); \
P0 p0 = GetArgument<P0>(info, 0); \
P1 p1 = GetArgument<P1>(info, 1); \
\
return MakeResult<Ret>(info, impl_##name(p0, p1)); \
} \
MAKE_NODE_EXPORT(TS_INTEROP_MODULE, name)
#define TS_INTEROP_3(name, Ret, P0, P1, P2) \
napi_value Node_##name(napi_env env, napi_callback_info cbinfo) \
{ \
TS_MAYBE_LOG(name) \
CallbackInfo info(env, cbinfo); \
P0 p0 = GetArgument<P0>(info, 0); \
P1 p1 = GetArgument<P1>(info, 1); \
P2 p2 = GetArgument<P2>(info, 2); \
\
return MakeResult<Ret>(info, impl_##name(p0, p1, p2)); \
} \
MAKE_NODE_EXPORT(TS_INTEROP_MODULE, name)
#define TS_INTEROP_4(name, Ret, P0, P1, P2, P3) \
napi_value Node_##name(napi_env env, napi_callback_info cbinfo) \
{ \
TS_MAYBE_LOG(name) \
CallbackInfo info(env, cbinfo); \
P0 p0 = GetArgument<P0>(info, 0); \
P1 p1 = GetArgument<P1>(info, 1); \
P2 p2 = GetArgument<P2>(info, 2); \
P3 p3 = GetArgument<P3>(info, 3); \
\
return MakeResult<Ret>(info, impl_##name(p0, p1, p2, p3)); \
} \
MAKE_NODE_EXPORT(TS_INTEROP_MODULE, name)
#define TS_INTEROP_5(name, Ret, P0, P1, P2, P3, P4) \
napi_value Node_##name(napi_env env, napi_callback_info cbinfo) \
{ \
TS_MAYBE_LOG(name) \
CallbackInfo info(env, cbinfo); \
P0 p0 = GetArgument<P0>(info, 0); \
P1 p1 = GetArgument<P1>(info, 1); \
P2 p2 = GetArgument<P2>(info, 2); \
P3 p3 = GetArgument<P3>(info, 3); \
P4 p4 = GetArgument<P4>(info, 4); \
\
return MakeResult<Ret>(info, impl_##name(p0, p1, p2, p3, p4)); \
} \
MAKE_NODE_EXPORT(TS_INTEROP_MODULE, name)
#define TS_INTEROP_6(name, Ret, P0, P1, P2, P3, P4, P5) \
napi_value Node_##name(napi_env env, napi_callback_info cbinfo) \
{ \
TS_MAYBE_LOG(name) \
CallbackInfo info(env, cbinfo); \
P0 p0 = GetArgument<P0>(info, 0); \
P1 p1 = GetArgument<P1>(info, 1); \
P2 p2 = GetArgument<P2>(info, 2); \
P3 p3 = GetArgument<P3>(info, 3); \
P4 p4 = GetArgument<P4>(info, 4); \
P5 p5 = GetArgument<P5>(info, 5); \
\
return MakeResult<Ret>(info, impl_##name(p0, p1, p2, p3, p4, p5)); \
} \
MAKE_NODE_EXPORT(TS_INTEROP_MODULE, name)
#define TS_INTEROP_7(name, Ret, P0, P1, P2, P3, P4, P5, P6) \
napi_value Node_##name(napi_env env, napi_callback_info cbinfo) \
{ \
TS_MAYBE_LOG(name) \
CallbackInfo info(env, cbinfo); \
P0 p0 = GetArgument<P0>(info, 0); \
P1 p1 = GetArgument<P1>(info, 1); \
P2 p2 = GetArgument<P2>(info, 2); \
P3 p3 = GetArgument<P3>(info, 3); \
P4 p4 = GetArgument<P4>(info, 4); \
P5 p5 = GetArgument<P5>(info, 5); \
P6 p6 = GetArgument<P6>(info, 6); \
\
return MakeResult<Ret>(info, impl_##name(p0, p1, p2, p3, p4, p5, p6)); \
} \
MAKE_NODE_EXPORT(TS_INTEROP_MODULE, name)
#define TS_INTEROP_8(name, Ret, P0, P1, P2, P3, P4, P5, P6, P7) \
napi_value Node_##name(napi_env env, napi_callback_info cbinfo) \
{ \
TS_MAYBE_LOG(name) \
CallbackInfo info(env, cbinfo); \
P0 p0 = GetArgument<P0>(info, 0); \
P1 p1 = GetArgument<P1>(info, 1); \
P2 p2 = GetArgument<P2>(info, 2); \
P3 p3 = GetArgument<P3>(info, 3); \
P4 p4 = GetArgument<P4>(info, 4); \
P5 p5 = GetArgument<P5>(info, 5); \
P6 p6 = GetArgument<P6>(info, 6); \
P7 p7 = GetArgument<P7>(info, 7); \
\
return MakeResult<Ret>(info, impl_##name(p0, p1, p2, p3, p4, p5, p6, p7)); \
} \
MAKE_NODE_EXPORT(TS_INTEROP_MODULE, name)
#define TS_INTEROP_9(name, Ret, P0, P1, P2, P3, P4, P5, P6, P7, P8) \
napi_value Node_##name(napi_env env, napi_callback_info cbinfo) \
{ \
TS_MAYBE_LOG(name) \
CallbackInfo info(env, cbinfo); \
P0 p0 = GetArgument<P0>(info, 0); \
P1 p1 = GetArgument<P1>(info, 1); \
P2 p2 = GetArgument<P2>(info, 2); \
P3 p3 = GetArgument<P3>(info, 3); \
P4 p4 = GetArgument<P4>(info, 4); \
P5 p5 = GetArgument<P5>(info, 5); \
P6 p6 = GetArgument<P6>(info, 6); \
P7 p7 = GetArgument<P7>(info, 7); \
P8 p8 = GetArgument<P8>(info, 8); \
\
return MakeResult<Ret>(info, impl_##name(p0, p1, p2, p3, p4, p5, p6, p7, p8)); \
} \
MAKE_NODE_EXPORT(TS_INTEROP_MODULE, name)
#define TS_INTEROP_10(name, Ret, P0, P1, P2, P3, P4, P5, P6, P7, P8, P9) \
napi_value Node_##name(napi_env env, napi_callback_info cbinfo) \
{ \
TS_MAYBE_LOG(name) \
CallbackInfo info(env, cbinfo); \
P0 p0 = GetArgument<P0>(info, 0); \
P1 p1 = GetArgument<P1>(info, 1); \
P2 p2 = GetArgument<P2>(info, 2); \
P3 p3 = GetArgument<P3>(info, 3); \
P4 p4 = GetArgument<P4>(info, 4); \
P5 p5 = GetArgument<P5>(info, 5); \
P6 p6 = GetArgument<P6>(info, 6); \
P7 p7 = GetArgument<P7>(info, 7); \
P8 p8 = GetArgument<P8>(info, 8); \
P9 p9 = GetArgument<P9>(info, 9); \
\
return MakeResult<Ret>(info, impl_##name(p0, p1, p2, p3, p4, p5, p6, p7, p8, p9)); \
} \
MAKE_NODE_EXPORT(TS_INTEROP_MODULE, name)
#define TS_INTEROP_11(name, Ret, P0, P1, P2, P3, P4, P5, P6, P7, P8, P9, P10) \
napi_value Node_##name(napi_env env, napi_callback_info cbinfo) \
{ \
TS_MAYBE_LOG(name) \
CallbackInfo info(env, cbinfo); \
P0 p0 = GetArgument<P0>(info, 0); \
P1 p1 = GetArgument<P1>(info, 1); \
P2 p2 = GetArgument<P2>(info, 2); \
P3 p3 = GetArgument<P3>(info, 3); \
P4 p4 = GetArgument<P4>(info, 4); \
P5 p5 = GetArgument<P5>(info, 5); \
P6 p6 = GetArgument<P6>(info, 6); \
P7 p7 = GetArgument<P7>(info, 7); \
P8 p8 = GetArgument<P8>(info, 8); \
P9 p9 = GetArgument<P9>(info, 9); \
P10 p10 = GetArgument<P10>(info, 10); \
\
return MakeResult<Ret>(info, impl_##name(p0, p1, p2, p3, p4, p5, p6, p7, p8, p9, p10)); \
} \
MAKE_NODE_EXPORT(TS_INTEROP_MODULE, name)
#define TS_INTEROP_12(name, Ret, P0, P1, P2, P3, P4, P5, P6, P7, P8, P9, P10, P11) \
napi_value Node_##name(napi_env env, napi_callback_info cbinfo) \
{ \
TS_MAYBE_LOG(name) \
CallbackInfo info(env, cbinfo); \
P0 p0 = GetArgument<P0>(info, 0); \
P1 p1 = GetArgument<P1>(info, 1); \
P2 p2 = GetArgument<P2>(info, 2); \
P3 p3 = GetArgument<P3>(info, 3); \
P4 p4 = GetArgument<P4>(info, 4); \
P5 p5 = GetArgument<P5>(info, 5); \
P6 p6 = GetArgument<P6>(info, 6); \
P7 p7 = GetArgument<P7>(info, 7); \
P8 p8 = GetArgument<P8>(info, 8); \
P9 p9 = GetArgument<P9>(info, 9); \
P10 p10 = GetArgument<P10>(info, 10); \
P11 p11 = GetArgument<P11>(info, 11); \
\
return MakeResult<Ret>(info, impl_##name(p0, p1, p2, p3, p4, p5, p6, p7, p8, p9, p10, p11)); \
} \
MAKE_NODE_EXPORT(TS_INTEROP_MODULE, name)
#define TS_INTEROP_13(name, Ret, P0, P1, P2, P3, P4, P5, P6, P7, P8, P9, P10, P11, P12) \
napi_value Node_##name(napi_env env, napi_callback_info cbinfo) \
{ \
TS_MAYBE_LOG(name) \
CallbackInfo info(env, cbinfo); \
P0 p0 = GetArgument<P0>(info, 0); \
P1 p1 = GetArgument<P1>(info, 1); \
P2 p2 = GetArgument<P2>(info, 2); \
P3 p3 = GetArgument<P3>(info, 3); \
P4 p4 = GetArgument<P4>(info, 4); \
P5 p5 = GetArgument<P5>(info, 5); \
P6 p6 = GetArgument<P6>(info, 6); \
P7 p7 = GetArgument<P7>(info, 7); \
P8 p8 = GetArgument<P8>(info, 8); \
P9 p9 = GetArgument<P9>(info, 9); \
P10 p10 = GetArgument<P10>(info, 10); \
P11 p11 = GetArgument<P11>(info, 11); \
P12 p12 = GetArgument<P12>(info, 12); \
\
return MakeResult<Ret>(info, impl_##name(p0, p1, p2, p3, p4, p5, p6, p7, p8, p9, p10, p11, p12)); \
} \
MAKE_NODE_EXPORT(TS_INTEROP_MODULE, name)
#define TS_INTEROP_14(name, Ret, P0, P1, P2, P3, P4, P5, P6, P7, P8, P9, P10, P11, P12, P13) \
napi_value Node_##name(napi_env env, napi_callback_info cbinfo) \
{ \
TS_MAYBE_LOG(name) \
CallbackInfo info(env, cbinfo); \
P0 p0 = GetArgument<P0>(info, 0); \
P1 p1 = GetArgument<P1>(info, 1); \
P2 p2 = GetArgument<P2>(info, 2); \
P3 p3 = GetArgument<P3>(info, 3); \
P4 p4 = GetArgument<P4>(info, 4); \
P5 p5 = GetArgument<P5>(info, 5); \
P6 p6 = GetArgument<P6>(info, 6); \
P7 p7 = GetArgument<P7>(info, 7); \
P8 p8 = GetArgument<P8>(info, 8); \
P9 p9 = GetArgument<P9>(info, 9); \
P10 p10 = GetArgument<P10>(info, 10); \
P11 p11 = GetArgument<P11>(info, 11); \
P12 p12 = GetArgument<P12>(info, 12); \
P13 p13 = GetArgument<P13>(info, 13); \
\
return MakeResult<Ret>(info, impl_##name(p0, p1, p2, p3, p4, p5, p6, p7, p8, p9, p10, p11, p12, p13)); \
} \
MAKE_NODE_EXPORT(TS_INTEROP_MODULE, name)
#define TS_INTEROP_V0(name) \
napi_value Node_##name(napi_env env, napi_callback_info cbinfo) \
{ \
TS_MAYBE_LOG(name) \
CallbackInfo info(env, cbinfo); \
impl_##name(); \
\
return MakeVoid(info); \
} \
MAKE_NODE_EXPORT(TS_INTEROP_MODULE, name)
#define TS_INTEROP_V1(name, P0) \
napi_value Node_##name(napi_env env, napi_callback_info cbinfo) \
{ \
TS_MAYBE_LOG(name) \
CallbackInfo info(env, cbinfo); \
P0 p0 = GetArgument<P0>(info, 0); \
impl_##name(p0); \
\
return MakeVoid(info); \
} \
MAKE_NODE_EXPORT(TS_INTEROP_MODULE, name)
#define TS_INTEROP_V2(name, P0, P1) \
napi_value Node_##name(napi_env env, napi_callback_info cbinfo) \
{ \
TS_MAYBE_LOG(name) \
CallbackInfo info(env, cbinfo); \
P0 p0 = GetArgument<P0>(info, 0); \
P1 p1 = GetArgument<P1>(info, 1); \
impl_##name(p0, p1); \
\
return MakeVoid(info); \
} \
MAKE_NODE_EXPORT(TS_INTEROP_MODULE, name)
#define TS_INTEROP_V3(name, P0, P1, P2) \
napi_value Node_##name(napi_env env, napi_callback_info cbinfo) \
{ \
TS_MAYBE_LOG(name) \
CallbackInfo info(env, cbinfo); \
P0 p0 = GetArgument<P0>(info, 0); \
P1 p1 = GetArgument<P1>(info, 1); \
P2 p2 = GetArgument<P2>(info, 2); \
impl_##name(p0, p1, p2); \
\
return MakeVoid(info); \
} \
MAKE_NODE_EXPORT(TS_INTEROP_MODULE, name)
#define TS_INTEROP_V4(name, P0, P1, P2, P3) \
napi_value Node_##name(napi_env env, napi_callback_info cbinfo) \
{ \
TS_MAYBE_LOG(name) \
CallbackInfo info(env, cbinfo); \
P0 p0 = GetArgument<P0>(info, 0); \
P1 p1 = GetArgument<P1>(info, 1); \
P2 p2 = GetArgument<P2>(info, 2); \
P3 p3 = GetArgument<P3>(info, 3); \
impl_##name(p0, p1, p2, p3); \
\
return MakeVoid(info); \
} \
MAKE_NODE_EXPORT(TS_INTEROP_MODULE, name)
#define TS_INTEROP_V5(name, P0, P1, P2, P3, P4) \
napi_value Node_##name(napi_env env, napi_callback_info cbinfo) \
{ \
TS_MAYBE_LOG(name) \
CallbackInfo info(env, cbinfo); \
P0 p0 = GetArgument<P0>(info, 0); \
P1 p1 = GetArgument<P1>(info, 1); \
P2 p2 = GetArgument<P2>(info, 2); \
P3 p3 = GetArgument<P3>(info, 3); \
P4 p4 = GetArgument<P4>(info, 4); \
impl_##name(p0, p1, p2, p3, p4); \
\
return MakeVoid(info); \
} \
MAKE_NODE_EXPORT(TS_INTEROP_MODULE, name)
#define TS_INTEROP_V6(name, P0, P1, P2, P3, P4, P5) \
napi_value Node_##name(napi_env env, napi_callback_info cbinfo) \
{ \
TS_MAYBE_LOG(name) \
CallbackInfo info(env, cbinfo); \
P0 p0 = GetArgument<P0>(info, 0); \
P1 p1 = GetArgument<P1>(info, 1); \
P2 p2 = GetArgument<P2>(info, 2); \
P3 p3 = GetArgument<P3>(info, 3); \
P4 p4 = GetArgument<P4>(info, 4); \
P5 p5 = GetArgument<P5>(info, 5); \
impl_##name(p0, p1, p2, p3, p4, p5); \
\
return MakeVoid(info); \
} \
MAKE_NODE_EXPORT(TS_INTEROP_MODULE, name)
#define TS_INTEROP_V7(name, P0, P1, P2, P3, P4, P5, P6) \
napi_value Node_##name(napi_env env, napi_callback_info cbinfo) \
{ \
TS_MAYBE_LOG(name) \
CallbackInfo info(env, cbinfo); \
P0 p0 = GetArgument<P0>(info, 0); \
P1 p1 = GetArgument<P1>(info, 1); \
P2 p2 = GetArgument<P2>(info, 2); \
P3 p3 = GetArgument<P3>(info, 3); \
P4 p4 = GetArgument<P4>(info, 4); \
P5 p5 = GetArgument<P5>(info, 5); \
P6 p6 = GetArgument<P6>(info, 6); \
impl_##name(p0, p1, p2, p3, p4, p5, p6); \
\
return MakeVoid(info); \
} \
MAKE_NODE_EXPORT(TS_INTEROP_MODULE, name)
#define TS_INTEROP_V8(name, P0, P1, P2, P3, P4, P5, P6, P7) \
napi_value Node_##name(napi_env env, napi_callback_info cbinfo) \
{ \
TS_MAYBE_LOG(name) \
CallbackInfo info(env, cbinfo); \
P0 p0 = GetArgument<P0>(info, 0); \
P1 p1 = GetArgument<P1>(info, 1); \
P2 p2 = GetArgument<P2>(info, 2); \
P3 p3 = GetArgument<P3>(info, 3); \
P4 p4 = GetArgument<P4>(info, 4); \
P5 p5 = GetArgument<P5>(info, 5); \
P6 p6 = GetArgument<P6>(info, 6); \
P7 p7 = GetArgument<P7>(info, 7); \
impl_##name(p0, p1, p2, p3, p4, p5, p6, p7); \
\
return MakeVoid(info); \
} \
MAKE_NODE_EXPORT(TS_INTEROP_MODULE, name)
#define TS_INTEROP_V9(name, P0, P1, P2, P3, P4, P5, P6, P7, P8) \
napi_value Node_##name(napi_env env, napi_callback_info cbinfo) \
{ \
TS_MAYBE_LOG(impl_##name) \
CallbackInfo info(env, cbinfo); \
P0 p0 = GetArgument<P0>(info, 0); \
P1 p1 = GetArgument<P1>(info, 1); \
P2 p2 = GetArgument<P2>(info, 2); \
P3 p3 = GetArgument<P3>(info, 3); \
P4 p4 = GetArgument<P4>(info, 4); \
P5 p5 = GetArgument<P5>(info, 5); \
P6 p6 = GetArgument<P6>(info, 6); \
P7 p7 = GetArgument<P7>(info, 7); \
P8 p8 = GetArgument<P8>(info, 8); \
impl_##name(p0, p1, p2, p3, p4, p5, p6, p7, p8); \
\
return MakeVoid(info); \
} \
MAKE_NODE_EXPORT(TS_INTEROP_MODULE, name)
#define TS_INTEROP_V10(name, P0, P1, P2, P3, P4, P5, P6, P7, P8, P9) \
napi_value Node_##name(napi_env env, napi_callback_info cbinfo) \
{ \
TS_MAYBE_LOG(name) \
CallbackInfo info(env, cbinfo); \
P0 p0 = GetArgument<P0>(info, 0); \
P1 p1 = GetArgument<P1>(info, 1); \
P2 p2 = GetArgument<P2>(info, 2); \
P3 p3 = GetArgument<P3>(info, 3); \
P4 p4 = GetArgument<P4>(info, 4); \
P5 p5 = GetArgument<P5>(info, 5); \
P6 p6 = GetArgument<P6>(info, 6); \
P7 p7 = GetArgument<P7>(info, 7); \
P8 p8 = GetArgument<P8>(info, 8); \
P9 p9 = GetArgument<P9>(info, 9); \
impl_##name(p0, p1, p2, p3, p4, p5, p6, p7, p8, p9); \
\
return MakeVoid(info); \
} \
MAKE_NODE_EXPORT(TS_INTEROP_MODULE, name)
#define TS_INTEROP_V11(name, P0, P1, P2, P3, P4, P5, P6, P7, P8, P9, P10) \
napi_value Node_##name(napi_env env, napi_callback_info cbinfo) \
{ \
TS_MAYBE_LOG(impl_##name) \
CallbackInfo info(env, cbinfo); \
P0 p0 = GetArgument<P0>(info, 0); \
P1 p1 = GetArgument<P1>(info, 1); \
P2 p2 = GetArgument<P2>(info, 2); \
P3 p3 = GetArgument<P3>(info, 3); \
P4 p4 = GetArgument<P4>(info, 4); \
P5 p5 = GetArgument<P5>(info, 5); \
P6 p6 = GetArgument<P6>(info, 6); \
P7 p7 = GetArgument<P7>(info, 7); \
P8 p8 = GetArgument<P8>(info, 8); \
P9 p9 = GetArgument<P9>(info, 9); \
P10 p10 = GetArgument<P10>(info, 10); \
impl_##name(p0, p1, p2, p3, p4, p5, p6, p7, p8, p9, p10); \
\
return MakeVoid(info); \
} \
MAKE_NODE_EXPORT(TS_INTEROP_MODULE, name)
#define TS_INTEROP_V12(name, P0, P1, P2, P3, P4, P5, P6, P7, P8, P9, P10, P11) \
napi_value Node_##name(napi_env env, napi_callback_info cbinfo) \
{ \
TS_MAYBE_LOG(impl_##name) \
CallbackInfo info(env, cbinfo); \
P0 p0 = GetArgument<P0>(info, 0); \
P1 p1 = GetArgument<P1>(info, 1); \
P2 p2 = GetArgument<P2>(info, 2); \
P3 p3 = GetArgument<P3>(info, 3); \
P4 p4 = GetArgument<P4>(info, 4); \
P5 p5 = GetArgument<P5>(info, 5); \
P6 p6 = GetArgument<P6>(info, 6); \
P7 p7 = GetArgument<P7>(info, 7); \
P8 p8 = GetArgument<P8>(info, 8); \
P9 p9 = GetArgument<P9>(info, 9); \
P10 p10 = GetArgument<P10>(info, 10); \
P11 p11 = GetArgument<P11>(info, 11); \
impl_##name(p0, p1, p2, p3, p4, p5, p6, p7, p8, p9, p10, p11); \
\
return MakeVoid(info); \
} \
MAKE_NODE_EXPORT(TS_INTEROP_MODULE, name)
#define TS_INTEROP_V13(name, P0, P1, P2, P3, P4, P5, P6, P7, P8, P9, P10, P11, P12) \
napi_value Node_##name(napi_env env, napi_callback_info cbinfo) \
{ \
TS_MAYBE_LOG(impl_##name) \
CallbackInfo info(env, cbinfo); \
P0 p0 = GetArgument<P0>(info, 0); \
P1 p1 = GetArgument<P1>(info, 1); \
P2 p2 = GetArgument<P2>(info, 2); \
P3 p3 = GetArgument<P3>(info, 3); \
P4 p4 = GetArgument<P4>(info, 4); \
P5 p5 = GetArgument<P5>(info, 5); \
P6 p6 = GetArgument<P6>(info, 6); \
P7 p7 = GetArgument<P7>(info, 7); \
P8 p8 = GetArgument<P8>(info, 8); \
P9 p9 = GetArgument<P9>(info, 9); \
P10 p10 = GetArgument<P10>(info, 10); \
P11 p11 = GetArgument<P11>(info, 11); \
P12 p12 = GetArgument<P12>(info, 12); \
impl_##name(p0, p1, p2, p3, p4, p5, p6, p7, p8, p9, p10, p11, p12); \
\
return MakeVoid(info); \
} \
MAKE_NODE_EXPORT(TS_INTEROP_MODULE, name)
#define TS_INTEROP_V14(name, P0, P1, P2, P3, P4, P5, P6, P7, P8, P9, P10, P11, P12, P13) \
napi_value Node_##name(napi_env env, napi_callback_info cbinfo) \
{ \
TS_MAYBE_LOG(name) \
CallbackInfo info(env, cbinfo); \
P0 p0 = GetArgument<P0>(info, 0); \
P1 p1 = GetArgument<P1>(info, 1); \
P2 p2 = GetArgument<P2>(info, 2); \
P3 p3 = GetArgument<P3>(info, 3); \
P4 p4 = GetArgument<P4>(info, 4); \
P5 p5 = GetArgument<P5>(info, 5); \
P6 p6 = GetArgument<P6>(info, 6); \
P7 p7 = GetArgument<P7>(info, 7); \
P8 p8 = GetArgument<P8>(info, 8); \
P9 p9 = GetArgument<P9>(info, 9); \
P10 p10 = GetArgument<P10>(info, 10); \
P11 p11 = GetArgument<P11>(info, 11); \
P12 p12 = GetArgument<P12>(info, 12); \
P13 p13 = GetArgument<P13>(info, 13); \
impl_##name(p0, p1, p2, p3, p4, p5, p6, p7, p8, p9, p10, p11, p12, p13); \
\
return MakeVoid(info); \
} \
MAKE_NODE_EXPORT(TS_INTEROP_MODULE, name)
#define TS_INTEROP_V15(name, P0, P1, P2, P3, P4, P5, P6, P7, P8, P9, P10, P11, P12, P13, P14) \
napi_value Node_##name(napi_env env, napi_callback_info cbinfo) \
{ \
TS_MAYBE_LOG(name) \
CallbackInfo info(env, cbinfo); \
P0 p0 = GetArgument<P0>(info, 0); \
P1 p1 = GetArgument<P1>(info, 1); \
P2 p2 = GetArgument<P2>(info, 2); \
P3 p3 = GetArgument<P3>(info, 3); \
P4 p4 = GetArgument<P4>(info, 4); \
P5 p5 = GetArgument<P5>(info, 5); \
P6 p6 = GetArgument<P6>(info, 6); \
P7 p7 = GetArgument<P7>(info, 7); \
P8 p8 = GetArgument<P8>(info, 8); \
P9 p9 = GetArgument<P9>(info, 9); \
P10 p10 = GetArgument<P10>(info, 10); \
P11 p11 = GetArgument<P11>(info, 11); \
P12 p12 = GetArgument<P12>(info, 12); \
P13 p13 = GetArgument<P13>(info, 13); \
P14 p14 = GetArgument<P14>(info, 14); \
impl_##name(p0, p1, p2, p3, p4, p5, p6, p7, p8, p9, p10, p11, p12, p13, p14); \
\
return MakeVoid(info); \
} \
MAKE_NODE_EXPORT(TS_INTEROP_MODULE, name)
#define TS_INTEROP_CTX_0(name, Ret) \
napi_value Node_##name(napi_env env, napi_callback_info cbinfo) \
{ \
TS_MAYBE_LOG(impl_##name) \
CallbackInfo info(env, cbinfo); \
KVMContext ctx = reinterpret_cast<KVMContext>((napi_env)info.Env()); \
\
return MakeResult<Ret>(info, impl_##name(ctx)); \
} \
MAKE_NODE_EXPORT(TS_INTEROP_MODULE, name)
#define TS_INTEROP_CTX_1(name, Ret, P0) \
napi_value Node_##name(napi_env env, napi_callback_info cbinfo) \
{ \
TS_MAYBE_LOG(impl_##name) \
CallbackInfo info(env, cbinfo); \
KVMContext ctx = reinterpret_cast<KVMContext>((napi_env)info.Env()); \
P0 p0 = GetArgument<P0>(info, 0); \
\
return MakeResult<Ret>(info, impl_##name(ctx, p0)); \
} \
MAKE_NODE_EXPORT(TS_INTEROP_MODULE, name)
#define TS_INTEROP_CTX_2(name, Ret, P0, P1) \
napi_value Node_##name(napi_env env, napi_callback_info cbinfo) \
{ \
TS_MAYBE_LOG(name) \
CallbackInfo info(env, cbinfo); \
KVMContext ctx = reinterpret_cast<KVMContext>((napi_env)info.Env()); \
P0 p0 = GetArgument<P0>(info, 0); \
P1 p1 = GetArgument<P1>(info, 1); \
\
return MakeResult<Ret>(info, impl_##name(ctx, p0, p1)); \
} \
MAKE_NODE_EXPORT(TS_INTEROP_MODULE, name)
#define TS_INTEROP_CTX_3(name, Ret, P0, P1, P2) \
napi_value Node_##name(napi_env env, napi_callback_info cbinfo) \
{ \
TS_MAYBE_LOG(name) \
CallbackInfo info(env, cbinfo); \
KVMContext ctx = reinterpret_cast<KVMContext>((napi_env)info.Env()); \
P0 p0 = GetArgument<P0>(info, 0); \
P1 p1 = GetArgument<P1>(info, 1); \
P2 p2 = GetArgument<P2>(info, 2); \
\
return MakeResult<Ret>(info, impl_##name(ctx, p0, p1, p2)); \
} \
MAKE_NODE_EXPORT(TS_INTEROP_MODULE, name)
#define TS_INTEROP_CTX_4(name, Ret, P0, P1, P2, P3) \
napi_value Node_##name(napi_env env, napi_callback_info cbinfo) \
{ \
TS_MAYBE_LOG(name) \
CallbackInfo info(env, cbinfo); \
KVMContext ctx = reinterpret_cast<KVMContext>((napi_env)info.Env()); \
P0 p0 = GetArgument<P0>(info, 0); \
P1 p1 = GetArgument<P1>(info, 1); \
P2 p2 = GetArgument<P2>(info, 2); \
P3 p3 = GetArgument<P3>(info, 3); \
\
return MakeResult<Ret>(info, impl_##name(ctx, p0, p1, p2, p3)); \
} \
MAKE_NODE_EXPORT(TS_INTEROP_MODULE, name)
#define TS_INTEROP_CTX_V0(name) \
napi_value Node_##name(napi_env env, napi_callback_info cbinfo) \
{ \
TS_MAYBE_LOG(name) \
CallbackInfo info(env, cbinfo); \
KVMContext ctx = reinterpret_cast<KVMContext>((napi_env)info.Env()); \
impl_##name(ctx); \
\
return MakeVoid(info); \
} \
MAKE_NODE_EXPORT(TS_INTEROP_MODULE, name)
#define TS_INTEROP_CTX_V1(name, P0) \
napi_value Node_##name(napi_env env, napi_callback_info cbinfo) \
{ \
TS_MAYBE_LOG(name) \
CallbackInfo info(env, cbinfo); \
KVMContext ctx = reinterpret_cast<KVMContext>((napi_env)info.Env()); \
P0 p0 = GetArgument<P0>(info, 0); \
impl_##name(ctx, p0); \
\
return MakeVoid(info); \
} \
MAKE_NODE_EXPORT(TS_INTEROP_MODULE, name)
#define TS_INTEROP_CTX_V2(name, P0, P1) \
napi_value Node_##name(napi_env env, napi_callback_info cbinfo) \
{ \
TS_MAYBE_LOG(name) \
CallbackInfo info(env, cbinfo); \
KVMContext ctx = reinterpret_cast<KVMContext>((napi_env)info.Env()); \
P0 p0 = GetArgument<P0>(info, 0); \
P1 p1 = GetArgument<P1>(info, 1); \
impl_##name(ctx, p0, p1); \
\
return MakeVoid(info); \
} \
MAKE_NODE_EXPORT(TS_INTEROP_MODULE, name)
#define TS_INTEROP_CTX_V3(name, P0, P1, P2) \
napi_value Node_##name(napi_env env, napi_callback_info cbinfo) \
{ \
TS_MAYBE_LOG(name) \
CallbackInfo info(env, cbinfo); \
KVMContext ctx = reinterpret_cast<KVMContext>((napi_env)info.Env()); \
P0 p0 = GetArgument<P0>(info, 0); \
P1 p1 = GetArgument<P1>(info, 1); \
P2 p2 = GetArgument<P2>(info, 2); \
impl_##name(ctx, p0, p1, p2); \
\
return MakeVoid(info); \
} \
MAKE_NODE_EXPORT(TS_INTEROP_MODULE, name)
#define NODEJS_GET_AND_THROW_LAST_ERROR(env) \
do { \
const napi_extended_error_info *error_info; \
napi_get_last_error_info((env), &error_info); \
bool is_pending; \
napi_is_exception_pending((env), &is_pending); \
\
if (!is_pending) { \
const char *error_message = \
error_info->error_message != NULL ? error_info->error_message : "empty error message"; \
napi_throw_error((env), NULL, error_message); \
} \
} while (0)
napi_value GetKoalaNapiCallbackDispatcher(napi_env env);
#define TS_INTEROP_CALL_VOID(venv, id, length, args) \
{ \
napi_env env = reinterpret_cast<napi_env>(venv); \
napi_value bridge = GetKoalaNapiCallbackDispatcher(env), global = nullptr, return_val = nullptr; \
napi_handle_scope scope = nullptr; \
napi_open_handle_scope(env, &scope); \
napi_status status = napi_get_global(env, &global); \
std::array<napi_value, 3> node_args; \
napi_create_int32(env, id, &node_args[0]); \
napi_value buffer = nullptr; \
napi_create_external_arraybuffer( \
env, args, length, [](napi_env, void *data, void *hint) {}, nullptr, &buffer); \
napi_create_typedarray(env, napi_uint8_array, length, buffer, 0, &node_args[1]); \
napi_create_int32(env, length, &node_args[2]); \
status = napi_call_function(env, global, bridge, 3, node_args.data(), &return_val); \
if (status != napi_ok) { \
NODEJS_GET_AND_THROW_LAST_ERROR((env)); \
} \
napi_close_handle_scope(env, scope); \
}
#define TS_INTEROP_CALL_INT(venv, id, length, args) \
{ \
napi_env env = reinterpret_cast<napi_env>(venv); \
napi_value bridge = GetKoalaNapiCallbackDispatcher(env); \
napi_value global = nullptr; \
napi_value return_val = nullptr; \
napi_handle_scope scope = nullptr; \
napi_open_handle_scope(env, &scope); \
napi_status status = napi_get_global(env, &global); \
std::array<napi_value, 3> node_args {}; \
napi_create_int32(env, id, &node_args[0]); \
napi_value buffer = nullptr; \
napi_create_external_arraybuffer( \
env, args, length, [](napi_env, [[maybe_unused]] void *data, [[maybe_unused]] void *hint) {}, nullptr, \
&buffer); \
napi_create_typedarray(env, napi_uint8_array, length, buffer, 0, &node_args[1]); \
napi_create_int32(env, length, &node_args[2]); \
status = napi_call_function(env, global, bridge, 3, node_args.data(), &return_val); \
if (status != napi_ok) { \
NODEJS_GET_AND_THROW_LAST_ERROR((env)); \
} \
int result; \
status = napi_get_value_int32(env, return_val, &result); \
napi_close_handle_scope(env, scope); \
\
return result; \
}
#define TS_INTEROP_CALL_VOID_INTS32(venv, id, argc, args) TS_INTEROP_CALL_VOID(venv, id, (argc) * sizeof(int32_t), args)
#define TS_INTEROP_CALL_INT_INTS32(venv, id, argc, args) TS_INTEROP_CALL_INT(venv, id, (argc) * sizeof(int32_t), args)
#endif