Skip to content

Commit

Permalink
cherry pick changes from PR nodejs#46319
Browse files Browse the repository at this point in the history
  • Loading branch information
vmoroz committed Feb 3, 2023
1 parent 10d248f commit 7273e06
Show file tree
Hide file tree
Showing 4 changed files with 61 additions and 146 deletions.
2 changes: 1 addition & 1 deletion src/node_api.cc
Expand Up @@ -631,7 +631,7 @@ static void napi_module_register_cb(v8::Local<v8::Object> exports,
module,
context,
napi_mod->nm_register_func,
static_cast<int32_t>(napi_mod->nm_api_version));
NAPI_DEFAULT_MODULE_API_VERSION);
}

void napi_module_register_by_symbol(v8::Local<v8::Object> exports,
Expand Down
157 changes: 14 additions & 143 deletions src/node_api.h
Expand Up @@ -30,190 +30,61 @@ struct uv_loop_s; // Forward declaration.

typedef napi_value(NAPI_CDECL* napi_addon_register_func)(napi_env env,
napi_value exports);

#ifndef NAPI_EXPERIMENTAL

typedef struct napi_module {
int nm_version;
unsigned int nm_flags;
const char* nm_filename;
napi_addon_register_func nm_register_func;
const char* nm_modname;
void* nm_priv;
void* reserved[4];
} napi_module;

#else

typedef int32_t(NAPI_CDECL* napi_addon_get_api_version_func)();

// Used by deprecated registration method napi_module_register.
typedef struct napi_module {
int nm_version;
unsigned int nm_flags;
const char* nm_filename;
napi_addon_register_func nm_register_func;
const char* nm_modname;
void* nm_priv;
uintptr_t nm_api_version;
void* reserved[3];
void* reserved[4];
} napi_module;

#endif // NAPI_EXPERIMENTAL

#define NAPI_MODULE_VERSION 1

#if defined(_MSC_VER)
#if defined(__cplusplus)
#define NAPI_C_CTOR(fn) \
static void NAPI_CDECL fn(void); \
namespace { \
struct fn##_ { \
fn##_() { fn(); } \
} fn##_v_; \
} \
static void NAPI_CDECL fn(void)
#else // !defined(__cplusplus)
#pragma section(".CRT$XCU", read)
// The NAPI_C_CTOR macro defines a function fn that is called during CRT
// initialization.
// C does not support dynamic initialization of static variables and this code
// simulates C++ behavior. Exporting the function pointer prevents it from being
// optimized. See for details:
// https://docs.microsoft.com/en-us/cpp/c-runtime-library/crt-initialization?view=msvc-170
#define NAPI_C_CTOR(fn) \
static void NAPI_CDECL fn(void); \
__declspec(dllexport, allocate(".CRT$XCU")) void(NAPI_CDECL * fn##_)(void) = \
fn; \
static void NAPI_CDECL fn(void)
#endif // defined(__cplusplus)
#else
#define NAPI_C_CTOR(fn) \
static void fn(void) __attribute__((constructor)); \
static void fn(void)
#endif

#ifndef NAPI_EXPERIMENTAL

#define NAPI_MODULE_X(modname, regfunc, priv, flags) \
EXTERN_C_START \
static napi_module _module = { \
NAPI_MODULE_VERSION, \
flags, \
__FILE__, \
regfunc, \
#modname, \
priv, \
{0}, \
}; \
NAPI_C_CTOR(_register_##modname) { napi_module_register(&_module); } \
EXTERN_C_END

#define NAPI_MODULE_INITIALIZER_X(base, version) \
NAPI_MODULE_INITIALIZER_X_HELPER(base, version)
#define NAPI_MODULE_INITIALIZER_X_HELPER(base, version) base##version

#ifdef __wasm32__
#define NAPI_WASM_INITIALIZER \
NAPI_MODULE_INITIALIZER_X(napi_register_wasm_v, NAPI_MODULE_VERSION)
#define NAPI_MODULE(modname, regfunc) \
EXTERN_C_START \
NAPI_MODULE_EXPORT napi_value NAPI_WASM_INITIALIZER(napi_env env, \
napi_value exports) { \
return regfunc(env, exports); \
} \
EXTERN_C_END
#define NAPI_MODULE_INITIALIZER_BASE napi_register_wasm_v
#else
#define NAPI_MODULE(modname, regfunc) \
NAPI_MODULE_X(modname, regfunc, NULL, 0) // NOLINT (readability/null_usage)
#endif

#define NAPI_MODULE_INITIALIZER_BASE napi_register_module_v
#endif

#define NAPI_MODULE_INITIALIZER \
NAPI_MODULE_INITIALIZER_X(NAPI_MODULE_INITIALIZER_BASE, NAPI_MODULE_VERSION)

#define NAPI_MODULE_INIT() \
EXTERN_C_START \
NAPI_MODULE_EXPORT napi_value NAPI_MODULE_INITIALIZER(napi_env env, \
napi_value exports); \
EXTERN_C_END \
NAPI_MODULE(NODE_GYP_MODULE_NAME, NAPI_MODULE_INITIALIZER) \
napi_value NAPI_MODULE_INITIALIZER(napi_env env, napi_value exports)

#else

#define NAPI_MODULE_XV(modname, regfunc, api_version, priv, flags) \
EXTERN_C_START \
static napi_module _module = { \
NAPI_MODULE_VERSION, \
flags, \
__FILE__, \
regfunc, \
#modname, \
priv, \
(uintptr_t)api_version, \
{0}, \
}; \
NAPI_C_CTOR(_register_##modname) { napi_module_register(&_module); } \
EXTERN_C_END

#define NAPI_MODULE_X(modname, regfunc, priv, flags) \
NAPI_MODULE_XV(modname, regfunc, NAPI_VERSION, priv, flags)

// Not used. For backward compatibility only.
#define NAPI_MODULE_INITIALIZER_X(base, version) \
NAPI_MODULE_INITIALIZER_X_HELPER(base, version)
#define NAPI_MODULE_INITIALIZER_X_HELPER(base, version) base##version

#define NAPI_CONCAT_HELPER(text1, text2) text1##text2
#define NAPI_CONCAT(text1, text2) NAPI_CONCAT_HELPER(text1, text2)

#define NAPI_MODULE_INITIALIZER_BASE napi_register_module_v
#define NAPI_MODULE_GET_API_VERSION_BASE napi_module_get_api_version_v

#define NAPI_MODULE_INITIALIZER \
NAPI_CONCAT(NAPI_MODULE_INITIALIZER_BASE, NAPI_MODULE_VERSION)
NAPI_MODULE_INITIALIZER_X(NAPI_MODULE_INITIALIZER_BASE, NAPI_MODULE_VERSION)

#define NAPI_MODULE_GET_API_VERSION \
NAPI_CONCAT(NAPI_MODULE_GET_API_VERSION_BASE, NAPI_MODULE_VERSION)
NAPI_MODULE_INITIALIZER_X(NAPI_MODULE_GET_API_VERSION_BASE, \
NAPI_MODULE_VERSION)

#define NAPI_MODULE_INIT() \
EXTERN_C_START \
NAPI_MODULE_EXPORT napi_value NAPI_MODULE_INITIALIZER(napi_env env, \
napi_value exports); \
NAPI_MODULE_EXPORT int32_t NAPI_MODULE_GET_API_VERSION() { \
return NAPI_VERSION; \
} \
NAPI_MODULE_EXPORT napi_value NAPI_MODULE_INITIALIZER(napi_env env, \
napi_value exports); \
EXTERN_C_END \
napi_value NAPI_MODULE_INITIALIZER(napi_env env, napi_value exports)

#ifdef __wasm32__

#define NAPI_WASM_INITIALIZER \
NAPI_CONCAT(napi_register_wasm_v, NAPI_MODULE_VERSION)
#define NAPI_WASM_GET_API_VERSION \
NAPI_CONCAT(napi_wasm_get_api_version_v, NAPI_MODULE_VERSION)
#define NAPI_MODULE(modname, regfunc) \
EXTERN_C_START \
NAPI_MODULE_EXPORT napi_value NAPI_WASM_INITIALIZER(napi_env env, \
napi_value exports) { \
return regfunc(env, exports); \
} \
NAPI_MODULE_EXPORT int32_t NAPI_WASM_GET_API_VERSION() { \
return NAPI_VERSION; \
} \
EXTERN_C_END
#else

#define NAPI_MODULE(modname, regfunc) \
NAPI_MODULE_INIT() { return regfunc(env, exports); }

#endif // __wasm32__

#endif // NAPI_EXPERIMENTAL
// Deprecated. Use NAPI_MODULE.
#define NAPI_MODULE_X(modname, regfunc, priv, flags) \
NAPI_MODULE(modname, regfunc)

EXTERN_C_START

// Deprecated. Replaced by symbol-based registration defined by NAPI_MODULE
// and NAPI_MODULE_INIT macros.
NAPI_EXTERN void NAPI_CDECL napi_module_register(napi_module* mod);

NAPI_EXTERN NAPI_NO_RETURN void NAPI_CDECL
Expand Down
46 changes: 45 additions & 1 deletion test/node-api/test_null_init/test_null_init.c
@@ -1,3 +1,47 @@
#include <node_api.h>

NAPI_MODULE(NODE_GYP_MODULE_NAME, NULL)
#if defined(_MSC_VER)
#if defined(__cplusplus)
#define NAPI_C_CTOR(fn) \
static void NAPI_CDECL fn(void); \
namespace { \
struct fn##_ { \
fn##_() { fn(); } \
} fn##_v_; \
} \
static void NAPI_CDECL fn(void)
#else // !defined(__cplusplus)
#pragma section(".CRT$XCU", read)
// The NAPI_C_CTOR macro defines a function fn that is called during CRT
// initialization.
// C does not support dynamic initialization of static variables and this code
// simulates C++ behavior. Exporting the function pointer prevents it from being
// optimized. See for details:
// https://docs.microsoft.com/en-us/cpp/c-runtime-library/crt-initialization?view=msvc-170
#define NAPI_C_CTOR(fn) \
static void NAPI_CDECL fn(void); \
__declspec(dllexport, allocate(".CRT$XCU")) void(NAPI_CDECL * fn##_)(void) = \
fn; \
static void NAPI_CDECL fn(void)
#endif // defined(__cplusplus)
#else
#define NAPI_C_CTOR(fn) \
static void fn(void) __attribute__((constructor)); \
static void fn(void)
#endif

#define NAPI_MODULE_TEST(modname, regfunc) \
EXTERN_C_START \
static napi_module _module = { \
NAPI_MODULE_VERSION, \
0, \
__FILE__, \
regfunc, \
#modname, \
NULL, \
{0}, \
}; \
NAPI_C_CTOR(_register_##modname) { napi_module_register(&_module); } \
EXTERN_C_END

NAPI_MODULE_TEST(NODE_GYP_MODULE_NAME, NULL)
2 changes: 1 addition & 1 deletion test/node-api/test_reference_obj_only/test.js
Expand Up @@ -53,7 +53,7 @@ async function runTests() {
assert.throws(() => { addon.createRef(entry.value); },
{
name: 'Error',
message: 'Invalid argument'
message: 'Invalid argument',
});
}
}
Expand Down

0 comments on commit 7273e06

Please sign in to comment.