From 966b23a2a03cfdbbec4c4da00b474cef5ac948f9 Mon Sep 17 00:00:00 2001 From: Kamil Paradowski Date: Wed, 23 Jul 2025 12:07:34 +0200 Subject: [PATCH 1/3] feat: Implement logging functions and add Node API version retrieval --- .changeset/kind-forks-talk.md | 5 ++ packages/host/cpp/Logger.cpp | 68 ++++++++++++++++--- packages/host/cpp/Logger.hpp | 6 +- packages/host/cpp/RuntimeNodeApi.cpp | 38 +++++++++++ packages/host/cpp/RuntimeNodeApi.hpp | 10 +++ packages/host/cpp/Versions.hpp | 7 ++ .../generate-weak-node-api-injector.ts | 3 + 7 files changed, 126 insertions(+), 11 deletions(-) create mode 100644 .changeset/kind-forks-talk.md create mode 100644 packages/host/cpp/Versions.hpp diff --git a/.changeset/kind-forks-talk.md b/.changeset/kind-forks-talk.md new file mode 100644 index 00000000..019e9ea5 --- /dev/null +++ b/.changeset/kind-forks-talk.md @@ -0,0 +1,5 @@ +--- +"react-native-node-api": patch +--- + +Added implementation of napi_fatal_error, napi_get_node_version and napi_get_version. Improved the Logger functionalities diff --git a/packages/host/cpp/Logger.cpp b/packages/host/cpp/Logger.cpp index d160ac3f..0d2a9c9f 100644 --- a/packages/host/cpp/Logger.cpp +++ b/packages/host/cpp/Logger.cpp @@ -9,27 +9,77 @@ #include #endif -namespace callstack::nodeapihost { -void log_debug(const char *format, ...) { - // TODO: Disable logging in release builds +namespace { +constexpr auto LineFormat = "[%s] [NodeApiHost] "; - va_list args; - va_start(args, format); +enum class LogLevel { Debug, Warning, Error }; + +constexpr std::string_view levelToString(LogLevel level) { + switch (level) { + case LogLevel::Debug: + return "DEBUG"; + case LogLevel::Warning: + return "WARNING"; + case LogLevel::Error: + return "ERROR"; + default: + return "UNKNOWN"; + } +} #if defined(__ANDROID__) - __android_log_vprint(ANDROID_LOG_DEBUG, LOG_TAG, format, args); +constexpr int androidLogLevel(LogLevel level) { + switch (level) { + case LogLevel::Debug: + return ANDROID_LOG_DEBUG; + case LogLevel::Warning: + return ANDROID_LOG_WARN; + case LogLevel::Error: + return ANDROID_LOG_ERROR; + default: + return ANDROID_LOG_UNKNOWN; + } +} +#endif + +void log_message_internal(LogLevel level, const char* format, va_list args) { +#if defined(__ANDROID__) + __android_log_vprint(androidLogLevel(level), LOG_TAG, format, args); #elif defined(__APPLE__) // iOS or macOS - fprintf(stderr, "[NodeApiHost] "); + const auto level_str = levelToString(level); + fprintf(stderr, LineFormat, level_str.data()); vfprintf(stderr, format, args); fprintf(stderr, "\n"); #else // Fallback for other platforms - fprintf(stdout, "[NodeApiHost] "); + const auto level_str = levelToString(level); + fprintf(stdout, LineFormat, level_str.data()); vfprintf(stdout, format, args); fprintf(stdout, "\n"); #endif +} +} // anonymous namespace + +namespace callstack::nodeapihost { +void log_debug(const char* format, ...) { + // TODO: Disable logging in release builds + va_list args; + va_start(args, format); + log_message_internal(LogLevel::Debug, format, args); + va_end(args); +} +void log_warning(const char* format, ...) { + va_list args; + va_start(args, format); + log_message_internal(LogLevel::Warning, format, args); + va_end(args); +} +void log_error(const char* format, ...) { + va_list args; + va_start(args, format); + log_message_internal(LogLevel::Error, format, args); va_end(args); } -} // namespace callstack::nodeapihost +} // namespace callstack::nodeapihost diff --git a/packages/host/cpp/Logger.hpp b/packages/host/cpp/Logger.hpp index af373f31..350e3f21 100644 --- a/packages/host/cpp/Logger.hpp +++ b/packages/host/cpp/Logger.hpp @@ -3,5 +3,7 @@ #include namespace callstack::nodeapihost { -void log_debug(const char *format, ...); -} +void log_debug(const char* format, ...); +void log_warning(const char* format, ...); +void log_error(const char* format, ...); +} // namespace callstack::nodeapihost diff --git a/packages/host/cpp/RuntimeNodeApi.cpp b/packages/host/cpp/RuntimeNodeApi.cpp index 1644240e..5afbdad2 100644 --- a/packages/host/cpp/RuntimeNodeApi.cpp +++ b/packages/host/cpp/RuntimeNodeApi.cpp @@ -1,5 +1,7 @@ #include "RuntimeNodeApi.hpp" #include +#include "Logger.hpp" +#include "Versions.hpp" auto ArrayType = napi_uint8_array; @@ -121,4 +123,40 @@ napi_status napi_create_external_buffer(napi_env env, return napi_create_typedarray(env, ArrayType, length, buffer, 0, result); } +void napi_fatal_error(const char* location, + size_t location_len, + const char* message, + size_t message_len) { + log_error("Fatal error in Node-API: %.*s: %.*s", + static_cast(location_len), + location, + static_cast(message_len), + message); + abort(); +} + +napi_status napi_get_node_version( + node_api_basic_env env, const napi_node_version** result) { + if (!result) { + return napi_invalid_arg; + } + + static napi_node_version version = { + .major = NODE_MAJOR_VERSION, + .minor = NODE_MINOR_VERSION, + .patch = NODE_PATCH_VERSION, + }; + *result = &version; + return napi_ok; +} + +napi_status napi_get_version(node_api_basic_env env, uint32_t* result) { + if (!result) { + return napi_invalid_arg; + } + + *result = NAPI_VERSION; + return napi_ok; +} + } // namespace callstack::nodeapihost diff --git a/packages/host/cpp/RuntimeNodeApi.hpp b/packages/host/cpp/RuntimeNodeApi.hpp index 5b7d9b86..67da7856 100644 --- a/packages/host/cpp/RuntimeNodeApi.hpp +++ b/packages/host/cpp/RuntimeNodeApi.hpp @@ -23,4 +23,14 @@ napi_status napi_create_external_buffer(napi_env env, node_api_basic_finalize basic_finalize_cb, void* finalize_hint, napi_value* result); + +void __attribute__((noreturn)) napi_fatal_error(const char* location, + size_t location_len, + const char* message, + size_t message_len); + +napi_status napi_get_node_version( + node_api_basic_env env, const napi_node_version** result); + +napi_status napi_get_version(node_api_basic_env env, uint32_t* result); } // namespace callstack::nodeapihost diff --git a/packages/host/cpp/Versions.hpp b/packages/host/cpp/Versions.hpp new file mode 100644 index 00000000..37b3a0c2 --- /dev/null +++ b/packages/host/cpp/Versions.hpp @@ -0,0 +1,7 @@ +#pragma once + +#define NODE_MAJOR_VERSION 8 +#define NODE_MINOR_VERSION 6 +#define NODE_PATCH_VERSION 0 + +#define NAPI_VERSION 1 diff --git a/packages/host/scripts/generate-weak-node-api-injector.ts b/packages/host/scripts/generate-weak-node-api-injector.ts index 129d2fc0..010288a0 100644 --- a/packages/host/scripts/generate-weak-node-api-injector.ts +++ b/packages/host/scripts/generate-weak-node-api-injector.ts @@ -17,6 +17,9 @@ const IMPLEMENTED_RUNTIME_FUNCTIONS = [ "napi_queue_async_work", "napi_delete_async_work", "napi_cancel_async_work", + "napi_fatal_error", + "napi_get_node_version", + "napi_get_version", ]; /** From fc3a35b0f47849e96cc006bd9f6667b045deefd1 Mon Sep 17 00:00:00 2001 From: Kamil Paradowski Date: Thu, 24 Jul 2025 12:46:46 +0200 Subject: [PATCH 2/3] chore: Improve error logging format in napi_fatal_error function --- packages/host/cpp/RuntimeNodeApi.cpp | 15 ++++++++++----- 1 file changed, 10 insertions(+), 5 deletions(-) diff --git a/packages/host/cpp/RuntimeNodeApi.cpp b/packages/host/cpp/RuntimeNodeApi.cpp index 5afbdad2..07e0516c 100644 --- a/packages/host/cpp/RuntimeNodeApi.cpp +++ b/packages/host/cpp/RuntimeNodeApi.cpp @@ -127,11 +127,16 @@ void napi_fatal_error(const char* location, size_t location_len, const char* message, size_t message_len) { - log_error("Fatal error in Node-API: %.*s: %.*s", - static_cast(location_len), - location, - static_cast(message_len), - message); + if (location && location_len) { + log_error("Fatal Node-API error: %.*s %.*s", + static_cast(location_len), + location, + static_cast(message_len), + message); + } else { + log_error( + "Fatal Node-API error: %.*s", static_cast(message_len), message); + } abort(); } From f523909cc94b786b964b1b57911f18f43dfeabcd Mon Sep 17 00:00:00 2001 From: Kamil Paradowski Date: Thu, 24 Jul 2025 16:19:03 +0200 Subject: [PATCH 3/3] refactor: bumped NAPI_VERSION + removed node --- packages/host/cpp/RuntimeNodeApi.cpp | 9 ++------- packages/host/cpp/Versions.hpp | 6 +----- 2 files changed, 3 insertions(+), 12 deletions(-) diff --git a/packages/host/cpp/RuntimeNodeApi.cpp b/packages/host/cpp/RuntimeNodeApi.cpp index 07e0516c..58309ed6 100644 --- a/packages/host/cpp/RuntimeNodeApi.cpp +++ b/packages/host/cpp/RuntimeNodeApi.cpp @@ -146,13 +146,8 @@ napi_status napi_get_node_version( return napi_invalid_arg; } - static napi_node_version version = { - .major = NODE_MAJOR_VERSION, - .minor = NODE_MINOR_VERSION, - .patch = NODE_PATCH_VERSION, - }; - *result = &version; - return napi_ok; + *result = nullptr; + return napi_generic_failure; } napi_status napi_get_version(node_api_basic_env env, uint32_t* result) { diff --git a/packages/host/cpp/Versions.hpp b/packages/host/cpp/Versions.hpp index 37b3a0c2..2cc106ef 100644 --- a/packages/host/cpp/Versions.hpp +++ b/packages/host/cpp/Versions.hpp @@ -1,7 +1,3 @@ #pragma once -#define NODE_MAJOR_VERSION 8 -#define NODE_MINOR_VERSION 6 -#define NODE_PATCH_VERSION 0 - -#define NAPI_VERSION 1 +#define NAPI_VERSION 8