Skip to content

Commit 7019d48

Browse files
vmorozdanielleadams
authored andcommittedJul 6, 2023
node-api: deprecate napi_module_register
PR-URL: #46319 Reviewed-By: Chengzhong Wu <legendecas@gmail.com> Reviewed-By: Michael Dawson <midawson@redhat.com>
1 parent ab6588e commit 7019d48

File tree

5 files changed

+254
-155
lines changed

5 files changed

+254
-155
lines changed
 

‎src/api/environment.cc

+29-1
Original file line numberDiff line numberDiff line change
@@ -780,7 +780,9 @@ void AddLinkedBinding(Environment* env, const node_module& mod) {
780780
}
781781

782782
void AddLinkedBinding(Environment* env, const napi_module& mod) {
783-
AddLinkedBinding(env, napi_module_to_node_module(&mod));
783+
node_module node_mod = napi_module_to_node_module(&mod);
784+
node_mod.nm_flags = NM_F_LINKED;
785+
AddLinkedBinding(env, node_mod);
784786
}
785787

786788
void AddLinkedBinding(Environment* env,
@@ -801,6 +803,32 @@ void AddLinkedBinding(Environment* env,
801803
AddLinkedBinding(env, mod);
802804
}
803805

806+
void AddLinkedBinding(Environment* env,
807+
const char* name,
808+
napi_addon_register_func fn) {
809+
node_module mod = {
810+
-1,
811+
NM_F_LINKED,
812+
nullptr, // nm_dso_handle
813+
nullptr, // nm_filename
814+
nullptr, // nm_register_func
815+
[](v8::Local<v8::Object> exports,
816+
v8::Local<v8::Value> module,
817+
v8::Local<v8::Context> context,
818+
void* priv) {
819+
napi_module_register_by_symbol(
820+
exports,
821+
module,
822+
context,
823+
reinterpret_cast<napi_addon_register_func>(priv));
824+
},
825+
name,
826+
reinterpret_cast<void*>(fn),
827+
nullptr // nm_link
828+
};
829+
AddLinkedBinding(env, mod);
830+
}
831+
804832
static std::atomic<uint64_t> next_thread_id{0};
805833

806834
ThreadId AllocateEnvironmentThreadId() {

‎src/node.h

+6-2
Original file line numberDiff line numberDiff line change
@@ -75,6 +75,9 @@
7575
#include "v8-platform.h" // NOLINT(build/include_order)
7676
#include "node_version.h" // NODE_MODULE_VERSION
7777

78+
#define NAPI_EXPERIMENTAL
79+
#include "node_api.h"
80+
7881
#include <functional>
7982
#include <memory>
8083
#include <ostream>
@@ -121,8 +124,6 @@
121124
// Forward-declare libuv loop
122125
struct uv_loop_s;
123126

124-
struct napi_module;
125-
126127
// Forward-declare these functions now to stop MSVS from becoming
127128
// terminally confused when it's done in node_internals.h
128129
namespace node {
@@ -1096,6 +1097,9 @@ NODE_EXTERN void AddLinkedBinding(Environment* env,
10961097
const char* name,
10971098
addon_context_register_func fn,
10981099
void* priv);
1100+
NODE_EXTERN void AddLinkedBinding(Environment* env,
1101+
const char* name,
1102+
napi_addon_register_func fn);
10991103

11001104
/* Registers a callback with the passed-in Environment instance. The callback
11011105
* is called after the event loop exits, but before the VM is disposed.

‎src/node_api.h

+17-59
Original file line numberDiff line numberDiff line change
@@ -31,6 +31,7 @@ struct uv_loop_s; // Forward declaration.
3131
typedef napi_value(NAPI_CDECL* napi_addon_register_func)(napi_env env,
3232
napi_value exports);
3333

34+
// Used by deprecated registration method napi_module_register.
3435
typedef struct napi_module {
3536
int nm_version;
3637
unsigned int nm_flags;
@@ -43,70 +44,15 @@ typedef struct napi_module {
4344

4445
#define NAPI_MODULE_VERSION 1
4546

46-
#if defined(_MSC_VER)
47-
#if defined(__cplusplus)
48-
#define NAPI_C_CTOR(fn) \
49-
static void NAPI_CDECL fn(void); \
50-
namespace { \
51-
struct fn##_ { \
52-
fn##_() { fn(); } \
53-
} fn##_v_; \
54-
} \
55-
static void NAPI_CDECL fn(void)
56-
#else // !defined(__cplusplus)
57-
#pragma section(".CRT$XCU", read)
58-
// The NAPI_C_CTOR macro defines a function fn that is called during CRT
59-
// initialization.
60-
// C does not support dynamic initialization of static variables and this code
61-
// simulates C++ behavior. Exporting the function pointer prevents it from being
62-
// optimized. See for details:
63-
// https://docs.microsoft.com/en-us/cpp/c-runtime-library/crt-initialization?view=msvc-170
64-
#define NAPI_C_CTOR(fn) \
65-
static void NAPI_CDECL fn(void); \
66-
__declspec(dllexport, allocate(".CRT$XCU")) void(NAPI_CDECL * fn##_)(void) = \
67-
fn; \
68-
static void NAPI_CDECL fn(void)
69-
#endif // defined(__cplusplus)
70-
#else
71-
#define NAPI_C_CTOR(fn) \
72-
static void fn(void) __attribute__((constructor)); \
73-
static void fn(void)
74-
#endif
75-
76-
#define NAPI_MODULE_X(modname, regfunc, priv, flags) \
77-
EXTERN_C_START \
78-
static napi_module _module = { \
79-
NAPI_MODULE_VERSION, \
80-
flags, \
81-
__FILE__, \
82-
regfunc, \
83-
#modname, \
84-
priv, \
85-
{0}, \
86-
}; \
87-
NAPI_C_CTOR(_register_##modname) { napi_module_register(&_module); } \
88-
EXTERN_C_END
89-
9047
#define NAPI_MODULE_INITIALIZER_X(base, version) \
9148
NAPI_MODULE_INITIALIZER_X_HELPER(base, version)
9249
#define NAPI_MODULE_INITIALIZER_X_HELPER(base, version) base##version
9350

9451
#ifdef __wasm32__
95-
#define NAPI_WASM_INITIALIZER \
96-
NAPI_MODULE_INITIALIZER_X(napi_register_wasm_v, NAPI_MODULE_VERSION)
97-
#define NAPI_MODULE(modname, regfunc) \
98-
EXTERN_C_START \
99-
NAPI_MODULE_EXPORT napi_value NAPI_WASM_INITIALIZER(napi_env env, \
100-
napi_value exports) { \
101-
return regfunc(env, exports); \
102-
} \
103-
EXTERN_C_END
52+
#define NAPI_MODULE_INITIALIZER_BASE napi_register_wasm_v
10453
#else
105-
#define NAPI_MODULE(modname, regfunc) \
106-
NAPI_MODULE_X(modname, regfunc, NULL, 0) // NOLINT (readability/null_usage)
107-
#endif
108-
10954
#define NAPI_MODULE_INITIALIZER_BASE napi_register_module_v
55+
#endif
11056

11157
#define NAPI_MODULE_INITIALIZER \
11258
NAPI_MODULE_INITIALIZER_X(NAPI_MODULE_INITIALIZER_BASE, NAPI_MODULE_VERSION)
@@ -116,12 +62,24 @@ typedef struct napi_module {
11662
NAPI_MODULE_EXPORT napi_value NAPI_MODULE_INITIALIZER(napi_env env, \
11763
napi_value exports); \
11864
EXTERN_C_END \
119-
NAPI_MODULE(NODE_GYP_MODULE_NAME, NAPI_MODULE_INITIALIZER) \
12065
napi_value NAPI_MODULE_INITIALIZER(napi_env env, napi_value exports)
12166

67+
#define NAPI_MODULE(modname, regfunc) \
68+
NAPI_MODULE_INIT() { return regfunc(env, exports); }
69+
70+
// Deprecated. Use NAPI_MODULE.
71+
#define NAPI_MODULE_X(modname, regfunc, priv, flags) \
72+
NAPI_MODULE(modname, regfunc)
73+
12274
EXTERN_C_START
12375

124-
NAPI_EXTERN void NAPI_CDECL napi_module_register(napi_module* mod);
76+
// Deprecated. Replaced by symbol-based registration defined by NAPI_MODULE
77+
// and NAPI_MODULE_INIT macros.
78+
#if defined(__cplusplus) && __cplusplus >= 201402L
79+
[[deprecated]]
80+
#endif
81+
NAPI_EXTERN void NAPI_CDECL
82+
napi_module_register(napi_module* mod);
12583

12684
NAPI_EXTERN NAPI_NO_RETURN void NAPI_CDECL
12785
napi_fatal_error(const char* location,

‎test/cctest/test_linked_binding.cc

+151-92
Original file line numberDiff line numberDiff line change
@@ -1,19 +1,19 @@
1-
#include "node_test_fixture.h"
21
#include "node_api.h"
2+
#include "node_test_fixture.h"
33

44
void InitializeBinding(v8::Local<v8::Object> exports,
55
v8::Local<v8::Value> module,
66
v8::Local<v8::Context> context,
77
void* priv) {
88
v8::Isolate* isolate = context->GetIsolate();
9-
exports->Set(
10-
context,
11-
v8::String::NewFromOneByte(isolate,
12-
reinterpret_cast<const uint8_t*>("key"))
13-
.ToLocalChecked(),
14-
v8::String::NewFromOneByte(isolate,
15-
reinterpret_cast<const uint8_t*>("value"))
16-
.ToLocalChecked())
9+
exports
10+
->Set(context,
11+
v8::String::NewFromOneByte(isolate,
12+
reinterpret_cast<const uint8_t*>("key"))
13+
.ToLocalChecked(),
14+
v8::String::NewFromOneByte(
15+
isolate, reinterpret_cast<const uint8_t*>("value"))
16+
.ToLocalChecked())
1717
.FromJust();
1818
}
1919

@@ -24,18 +24,18 @@ class LinkedBindingTest : public EnvironmentTestFixture {};
2424
TEST_F(LinkedBindingTest, SimpleTest) {
2525
const v8::HandleScope handle_scope(isolate_);
2626
const Argv argv;
27-
Env test_env {handle_scope, argv};
27+
Env test_env{handle_scope, argv};
2828

2929
v8::Local<v8::Context> context = isolate_->GetCurrentContext();
3030

31-
const char* run_script =
32-
"process._linkedBinding('cctest_linkedbinding').key";
33-
v8::Local<v8::Script> script = v8::Script::Compile(
34-
context,
35-
v8::String::NewFromOneByte(isolate_,
36-
reinterpret_cast<const uint8_t*>(run_script))
37-
.ToLocalChecked())
38-
.ToLocalChecked();
31+
const char* run_script = "process._linkedBinding('cctest_linkedbinding').key";
32+
v8::Local<v8::Script> script =
33+
v8::Script::Compile(
34+
context,
35+
v8::String::NewFromOneByte(
36+
isolate_, reinterpret_cast<const uint8_t*>(run_script))
37+
.ToLocalChecked())
38+
.ToLocalChecked();
3939
v8::Local<v8::Value> completion_value = script->Run(context).ToLocalChecked();
4040
v8::String::Utf8Value utf8val(isolate_, completion_value);
4141
CHECK_NOT_NULL(*utf8val);
@@ -48,35 +48,35 @@ void InitializeLocalBinding(v8::Local<v8::Object> exports,
4848
void* priv) {
4949
++*static_cast<int*>(priv);
5050
v8::Isolate* isolate = context->GetIsolate();
51-
exports->Set(
52-
context,
53-
v8::String::NewFromOneByte(isolate,
54-
reinterpret_cast<const uint8_t*>("key"))
55-
.ToLocalChecked(),
56-
v8::String::NewFromOneByte(isolate,
57-
reinterpret_cast<const uint8_t*>("value"))
58-
.ToLocalChecked())
51+
exports
52+
->Set(context,
53+
v8::String::NewFromOneByte(isolate,
54+
reinterpret_cast<const uint8_t*>("key"))
55+
.ToLocalChecked(),
56+
v8::String::NewFromOneByte(
57+
isolate, reinterpret_cast<const uint8_t*>("value"))
58+
.ToLocalChecked())
5959
.FromJust();
6060
}
6161

6262
TEST_F(LinkedBindingTest, LocallyDefinedLinkedBindingTest) {
6363
const v8::HandleScope handle_scope(isolate_);
6464
const Argv argv;
65-
Env test_env {handle_scope, argv};
65+
Env test_env{handle_scope, argv};
6666

6767
int calls = 0;
6868
AddLinkedBinding(*test_env, "local_linked", InitializeLocalBinding, &calls);
6969

7070
v8::Local<v8::Context> context = isolate_->GetCurrentContext();
7171

72-
const char* run_script =
73-
"process._linkedBinding('local_linked').key";
74-
v8::Local<v8::Script> script = v8::Script::Compile(
75-
context,
76-
v8::String::NewFromOneByte(isolate_,
77-
reinterpret_cast<const uint8_t*>(run_script))
78-
.ToLocalChecked())
79-
.ToLocalChecked();
72+
const char* run_script = "process._linkedBinding('local_linked').key";
73+
v8::Local<v8::Script> script =
74+
v8::Script::Compile(
75+
context,
76+
v8::String::NewFromOneByte(
77+
isolate_, reinterpret_cast<const uint8_t*>(run_script))
78+
.ToLocalChecked())
79+
.ToLocalChecked();
8080
v8::Local<v8::Value> completion_value = script->Run(context).ToLocalChecked();
8181
v8::String::Utf8Value utf8val(isolate_, completion_value);
8282
CHECK_NOT_NULL(*utf8val);
@@ -86,41 +86,64 @@ TEST_F(LinkedBindingTest, LocallyDefinedLinkedBindingTest) {
8686

8787
napi_value InitializeLocalNapiBinding(napi_env env, napi_value exports) {
8888
napi_value key, value;
89-
CHECK_EQ(
90-
napi_create_string_utf8(env, "hello", NAPI_AUTO_LENGTH, &key), napi_ok);
91-
CHECK_EQ(
92-
napi_create_string_utf8(env, "world", NAPI_AUTO_LENGTH, &value), napi_ok);
89+
CHECK_EQ(napi_create_string_utf8(env, "hello", NAPI_AUTO_LENGTH, &key),
90+
napi_ok);
91+
CHECK_EQ(napi_create_string_utf8(env, "world", NAPI_AUTO_LENGTH, &value),
92+
napi_ok);
9393
CHECK_EQ(napi_set_property(env, exports, key, value), napi_ok);
9494
return nullptr;
9595
}
9696

9797
static napi_module local_linked_napi = {
98-
NAPI_MODULE_VERSION,
99-
node::ModuleFlags::kLinked,
100-
nullptr,
101-
InitializeLocalNapiBinding,
102-
"local_linked_napi",
103-
nullptr,
104-
{0},
98+
NAPI_MODULE_VERSION,
99+
node::ModuleFlags::kLinked,
100+
nullptr,
101+
InitializeLocalNapiBinding,
102+
"local_linked_napi",
103+
nullptr,
104+
{0},
105105
};
106106

107107
TEST_F(LinkedBindingTest, LocallyDefinedLinkedBindingNapiTest) {
108108
const v8::HandleScope handle_scope(isolate_);
109109
const Argv argv;
110-
Env test_env {handle_scope, argv};
110+
Env test_env{handle_scope, argv};
111111

112112
AddLinkedBinding(*test_env, local_linked_napi);
113113

114114
v8::Local<v8::Context> context = isolate_->GetCurrentContext();
115115

116-
const char* run_script =
117-
"process._linkedBinding('local_linked_napi').hello";
118-
v8::Local<v8::Script> script = v8::Script::Compile(
119-
context,
120-
v8::String::NewFromOneByte(isolate_,
121-
reinterpret_cast<const uint8_t*>(run_script))
122-
.ToLocalChecked())
123-
.ToLocalChecked();
116+
const char* run_script = "process._linkedBinding('local_linked_napi').hello";
117+
v8::Local<v8::Script> script =
118+
v8::Script::Compile(
119+
context,
120+
v8::String::NewFromOneByte(
121+
isolate_, reinterpret_cast<const uint8_t*>(run_script))
122+
.ToLocalChecked())
123+
.ToLocalChecked();
124+
v8::Local<v8::Value> completion_value = script->Run(context).ToLocalChecked();
125+
v8::String::Utf8Value utf8val(isolate_, completion_value);
126+
CHECK_NOT_NULL(*utf8val);
127+
CHECK_EQ(strcmp(*utf8val, "world"), 0);
128+
}
129+
130+
TEST_F(LinkedBindingTest, LocallyDefinedLinkedBindingNapiCallbackTest) {
131+
const v8::HandleScope handle_scope(isolate_);
132+
const Argv argv;
133+
Env test_env{handle_scope, argv};
134+
135+
AddLinkedBinding(*test_env, "local_linked_napi", InitializeLocalNapiBinding);
136+
137+
v8::Local<v8::Context> context = isolate_->GetCurrentContext();
138+
139+
const char* run_script = "process._linkedBinding('local_linked_napi').hello";
140+
v8::Local<v8::Script> script =
141+
v8::Script::Compile(
142+
context,
143+
v8::String::NewFromOneByte(
144+
isolate_, reinterpret_cast<const uint8_t*>(run_script))
145+
.ToLocalChecked())
146+
.ToLocalChecked();
124147
v8::Local<v8::Value> completion_value = script->Run(context).ToLocalChecked();
125148
v8::String::Utf8Value utf8val(isolate_, completion_value);
126149
CHECK_NOT_NULL(*utf8val);
@@ -129,33 +152,32 @@ TEST_F(LinkedBindingTest, LocallyDefinedLinkedBindingNapiTest) {
129152

130153
napi_value NapiLinkedWithInstanceData(napi_env env, napi_value exports) {
131154
int* instance_data = new int(0);
132-
CHECK_EQ(
133-
napi_set_instance_data(
134-
env,
135-
instance_data,
136-
[](napi_env env, void* data, void* hint) {
137-
++*static_cast<int*>(data);
138-
}, nullptr),
139-
napi_ok);
155+
CHECK_EQ(napi_set_instance_data(
156+
env,
157+
instance_data,
158+
[](napi_env env, void* data, void* hint) {
159+
++*static_cast<int*>(data);
160+
},
161+
nullptr),
162+
napi_ok);
140163

141164
napi_value key, value;
142-
CHECK_EQ(
143-
napi_create_string_utf8(env, "hello", NAPI_AUTO_LENGTH, &key), napi_ok);
144-
CHECK_EQ(
145-
napi_create_external(env, instance_data, nullptr, nullptr, &value),
146-
napi_ok);
165+
CHECK_EQ(napi_create_string_utf8(env, "hello", NAPI_AUTO_LENGTH, &key),
166+
napi_ok);
167+
CHECK_EQ(napi_create_external(env, instance_data, nullptr, nullptr, &value),
168+
napi_ok);
147169
CHECK_EQ(napi_set_property(env, exports, key, value), napi_ok);
148170
return nullptr;
149171
}
150172

151173
static napi_module local_linked_napi_id = {
152-
NAPI_MODULE_VERSION,
153-
node::ModuleFlags::kLinked,
154-
nullptr,
155-
NapiLinkedWithInstanceData,
156-
"local_linked_napi_id",
157-
nullptr,
158-
{0},
174+
NAPI_MODULE_VERSION,
175+
node::ModuleFlags::kLinked,
176+
nullptr,
177+
NapiLinkedWithInstanceData,
178+
"local_linked_napi_id",
179+
nullptr,
180+
{0},
159181
};
160182

161183
TEST_F(LinkedBindingTest, LocallyDefinedLinkedBindingNapiInstanceDataTest) {
@@ -164,25 +186,62 @@ TEST_F(LinkedBindingTest, LocallyDefinedLinkedBindingNapiInstanceDataTest) {
164186

165187
{
166188
const Argv argv;
167-
Env test_env {handle_scope, argv};
189+
Env test_env{handle_scope, argv};
168190

169191
AddLinkedBinding(*test_env, local_linked_napi_id);
170192

171193
v8::Local<v8::Context> context = isolate_->GetCurrentContext();
172194

173195
const char* run_script =
174196
"process._linkedBinding('local_linked_napi_id').hello";
175-
v8::Local<v8::Script> script = v8::Script::Compile(
176-
context,
177-
v8::String::NewFromOneByte(isolate_,
178-
reinterpret_cast<const uint8_t*>(run_script))
179-
.ToLocalChecked())
180-
.ToLocalChecked();
197+
v8::Local<v8::Script> script =
198+
v8::Script::Compile(
199+
context,
200+
v8::String::NewFromOneByte(
201+
isolate_, reinterpret_cast<const uint8_t*>(run_script))
202+
.ToLocalChecked())
203+
.ToLocalChecked();
181204
v8::Local<v8::Value> completion_value =
182205
script->Run(context).ToLocalChecked();
183206
CHECK(completion_value->IsExternal());
184-
instance_data = static_cast<int*>(
185-
completion_value.As<v8::External>()->Value());
207+
instance_data =
208+
static_cast<int*>(completion_value.As<v8::External>()->Value());
209+
CHECK_NE(instance_data, nullptr);
210+
CHECK_EQ(*instance_data, 0);
211+
}
212+
213+
CHECK_EQ(*instance_data, 1);
214+
delete instance_data;
215+
}
216+
217+
TEST_F(LinkedBindingTest,
218+
LocallyDefinedLinkedBindingNapiCallbackInstanceDataTest) {
219+
const v8::HandleScope handle_scope(isolate_);
220+
int* instance_data = nullptr;
221+
222+
{
223+
const Argv argv;
224+
Env test_env{handle_scope, argv};
225+
226+
AddLinkedBinding(
227+
*test_env, "local_linked_napi_id", NapiLinkedWithInstanceData);
228+
229+
v8::Local<v8::Context> context = isolate_->GetCurrentContext();
230+
231+
const char* run_script =
232+
"process._linkedBinding('local_linked_napi_id').hello";
233+
v8::Local<v8::Script> script =
234+
v8::Script::Compile(
235+
context,
236+
v8::String::NewFromOneByte(
237+
isolate_, reinterpret_cast<const uint8_t*>(run_script))
238+
.ToLocalChecked())
239+
.ToLocalChecked();
240+
v8::Local<v8::Value> completion_value =
241+
script->Run(context).ToLocalChecked();
242+
CHECK(completion_value->IsExternal());
243+
instance_data =
244+
static_cast<int*>(completion_value.As<v8::External>()->Value());
186245
CHECK_NE(instance_data, nullptr);
187246
CHECK_EQ(*instance_data, 0);
188247
}
@@ -194,7 +253,7 @@ TEST_F(LinkedBindingTest, LocallyDefinedLinkedBindingNapiInstanceDataTest) {
194253
TEST_F(LinkedBindingTest, ManyBindingsTest) {
195254
const v8::HandleScope handle_scope(isolate_);
196255
const Argv argv;
197-
Env test_env {handle_scope, argv};
256+
Env test_env{handle_scope, argv};
198257

199258
int calls = 0;
200259
AddLinkedBinding(*test_env, "local_linked1", InitializeLocalBinding, &calls);
@@ -209,16 +268,16 @@ TEST_F(LinkedBindingTest, ManyBindingsTest) {
209268
const char* run_script =
210269
"for (let i = 1; i <= 5; i++)process._linkedBinding(`local_linked${i}`);"
211270
"process._linkedBinding('local_linked_napi').hello";
212-
v8::Local<v8::Script> script = v8::Script::Compile(
213-
context,
214-
v8::String::NewFromOneByte(isolate_,
215-
reinterpret_cast<const uint8_t*>(run_script))
216-
.ToLocalChecked())
217-
.ToLocalChecked();
271+
v8::Local<v8::Script> script =
272+
v8::Script::Compile(
273+
context,
274+
v8::String::NewFromOneByte(
275+
isolate_, reinterpret_cast<const uint8_t*>(run_script))
276+
.ToLocalChecked())
277+
.ToLocalChecked();
218278
v8::Local<v8::Value> completion_value = script->Run(context).ToLocalChecked();
219279
v8::String::Utf8Value utf8val(isolate_, completion_value);
220280
CHECK_NOT_NULL(*utf8val);
221281
CHECK_EQ(strcmp(*utf8val, "world"), 0);
222282
CHECK_EQ(calls, 5);
223283
}
224-
+51-1
Original file line numberDiff line numberDiff line change
@@ -1,3 +1,53 @@
11
#include <node_api.h>
22

3-
NAPI_MODULE(NODE_GYP_MODULE_NAME, NULL)
3+
// This test uses old module initialization style deprecated in current code.
4+
// The goal is to see that all previously compiled code continues to work the
5+
// same way as before.
6+
// The test has a copy of previous macro definitions which are removed from
7+
// the node_api.h file.
8+
9+
#if defined(_MSC_VER)
10+
#if defined(__cplusplus)
11+
#define NAPI_C_CTOR(fn) \
12+
static void NAPI_CDECL fn(void); \
13+
namespace { \
14+
struct fn##_ { \
15+
fn##_() { fn(); } \
16+
} fn##_v_; \
17+
} \
18+
static void NAPI_CDECL fn(void)
19+
#else // !defined(__cplusplus)
20+
#pragma section(".CRT$XCU", read)
21+
// The NAPI_C_CTOR macro defines a function fn that is called during CRT
22+
// initialization.
23+
// C does not support dynamic initialization of static variables and this code
24+
// simulates C++ behavior. Exporting the function pointer prevents it from being
25+
// optimized. See for details:
26+
// https://docs.microsoft.com/en-us/cpp/c-runtime-library/crt-initialization?view=msvc-170
27+
#define NAPI_C_CTOR(fn) \
28+
static void NAPI_CDECL fn(void); \
29+
__declspec(dllexport, allocate(".CRT$XCU")) void(NAPI_CDECL * fn##_)(void) = \
30+
fn; \
31+
static void NAPI_CDECL fn(void)
32+
#endif // defined(__cplusplus)
33+
#else
34+
#define NAPI_C_CTOR(fn) \
35+
static void fn(void) __attribute__((constructor)); \
36+
static void fn(void)
37+
#endif
38+
39+
#define NAPI_MODULE_TEST(modname, regfunc) \
40+
EXTERN_C_START \
41+
static napi_module _module = { \
42+
NAPI_MODULE_VERSION, \
43+
0, \
44+
__FILE__, \
45+
regfunc, \
46+
#modname, \
47+
NULL, \
48+
{0}, \
49+
}; \
50+
NAPI_C_CTOR(_register_##modname) { napi_module_register(&_module); } \
51+
EXTERN_C_END
52+
53+
NAPI_MODULE_TEST(NODE_GYP_MODULE_NAME, NULL)

0 commit comments

Comments
 (0)
Please sign in to comment.