Skip to content

Commit 0d8eaa3

Browse files
addaleaxMylesBorins
authored andcommitted
src: allow N-API addon in AddLinkedBinding()
`AddLinkedBinding()` can be used to load old-style Node.js addons, but currently not N-API addons. There’s no good reason not to support N-API addons as well, so add that. PR-URL: #35301 Reviewed-By: Colin Ihrig <cjihrig@gmail.com> Reviewed-By: Michael Dawson <midawson@redhat.com> Reviewed-By: Zeyu Yang <himself65@outlook.com>
1 parent 353a567 commit 0d8eaa3

File tree

6 files changed

+131
-7
lines changed

6 files changed

+131
-7
lines changed

src/api/environment.cc

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -677,6 +677,10 @@ void AddLinkedBinding(Environment* env, const node_module& mod) {
677677
prev_head->nm_link = &env->extra_linked_bindings()->back();
678678
}
679679

680+
void AddLinkedBinding(Environment* env, const napi_module& mod) {
681+
AddLinkedBinding(env, napi_module_to_node_module(&mod));
682+
}
683+
680684
void AddLinkedBinding(Environment* env,
681685
const char* name,
682686
addon_context_register_func fn,

src/node.h

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -117,6 +117,8 @@
117117
// Forward-declare libuv loop
118118
struct uv_loop_s;
119119

120+
struct napi_module;
121+
120122
// Forward-declare these functions now to stop MSVS from becoming
121123
// terminally confused when it's done in node_internals.h
122124
namespace node {
@@ -824,6 +826,8 @@ extern "C" NODE_EXTERN void node_module_register(void* mod);
824826
// In each variant, the registration function needs to be usable at least for
825827
// the time during which the Environment exists.
826828
NODE_EXTERN void AddLinkedBinding(Environment* env, const node_module& mod);
829+
NODE_EXTERN void AddLinkedBinding(Environment* env,
830+
const struct napi_module& mod);
827831
NODE_EXTERN void AddLinkedBinding(Environment* env,
828832
const char* name,
829833
addon_context_register_func fn,

src/node_api.cc

Lines changed: 12 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -447,7 +447,7 @@ static void napi_module_register_cb(v8::Local<v8::Object> exports,
447447
v8::Local<v8::Context> context,
448448
void* priv) {
449449
napi_module_register_by_symbol(exports, module, context,
450-
static_cast<napi_module*>(priv)->nm_register_func);
450+
static_cast<const napi_module*>(priv)->nm_register_func);
451451
}
452452

453453
void napi_module_register_by_symbol(v8::Local<v8::Object> exports,
@@ -480,19 +480,26 @@ void napi_module_register_by_symbol(v8::Local<v8::Object> exports,
480480
}
481481
}
482482

483-
// Registers a NAPI module.
484-
void napi_module_register(napi_module* mod) {
485-
node::node_module* nm = new node::node_module {
483+
namespace node {
484+
node_module napi_module_to_node_module(const napi_module* mod) {
485+
return {
486486
-1,
487487
mod->nm_flags | NM_F_DELETEME,
488488
nullptr,
489489
mod->nm_filename,
490490
nullptr,
491491
napi_module_register_cb,
492492
mod->nm_modname,
493-
mod, // priv
493+
const_cast<napi_module*>(mod), // priv
494494
nullptr,
495495
};
496+
}
497+
} // namespace node
498+
499+
// Registers a NAPI module.
500+
void napi_module_register(napi_module* mod) {
501+
node::node_module* nm = new node::node_module(
502+
node::napi_module_to_node_module(mod));
496503
node::node_module_register(nm);
497504
}
498505

src/node_api.h

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -31,7 +31,7 @@ struct uv_loop_s; // Forward declaration.
3131
typedef napi_value (*napi_addon_register_func)(napi_env env,
3232
napi_value exports);
3333

34-
typedef struct {
34+
typedef struct napi_module {
3535
int nm_version;
3636
unsigned int nm_flags;
3737
const char* nm_filename;

src/node_internals.h

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -398,6 +398,8 @@ namespace fs {
398398
std::string Basename(const std::string& str, const std::string& extension);
399399
} // namespace fs
400400

401+
node_module napi_module_to_node_module(const napi_module* mod);
402+
401403
} // namespace node
402404

403405
#endif // defined(NODE_WANT_INTERNALS) && NODE_WANT_INTERNALS

test/cctest/test_linked_binding.cc

Lines changed: 108 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,5 @@
11
#include "node_test_fixture.h"
2-
#include "node_internals.h" // RunBootstrapping()
2+
#include "node_api.h"
33

44
void InitializeBinding(v8::Local<v8::Object> exports,
55
v8::Local<v8::Value> module,
@@ -83,3 +83,110 @@ TEST_F(LinkedBindingTest, LocallyDefinedLinkedBindingTest) {
8383
CHECK_EQ(strcmp(*utf8val, "value"), 0);
8484
CHECK_EQ(calls, 1);
8585
}
86+
87+
napi_value InitializeLocalNapiBinding(napi_env env, napi_value exports) {
88+
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);
93+
CHECK_EQ(napi_set_property(env, exports, key, value), napi_ok);
94+
return nullptr;
95+
}
96+
97+
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},
105+
};
106+
107+
TEST_F(LinkedBindingTest, LocallyDefinedLinkedBindingNapiTest) {
108+
const v8::HandleScope handle_scope(isolate_);
109+
const Argv argv;
110+
Env test_env {handle_scope, argv};
111+
112+
AddLinkedBinding(*test_env, local_linked_napi);
113+
114+
v8::Local<v8::Context> context = isolate_->GetCurrentContext();
115+
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();
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+
napi_value NapiLinkedWithInstanceData(napi_env env, napi_value exports) {
131+
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);
140+
141+
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);
147+
CHECK_EQ(napi_set_property(env, exports, key, value), napi_ok);
148+
return nullptr;
149+
}
150+
151+
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},
159+
};
160+
161+
TEST_F(LinkedBindingTest, LocallyDefinedLinkedBindingNapiInstanceDataTest) {
162+
const v8::HandleScope handle_scope(isolate_);
163+
int* instance_data = nullptr;
164+
165+
{
166+
const Argv argv;
167+
Env test_env {handle_scope, argv};
168+
169+
AddLinkedBinding(*test_env, local_linked_napi_id);
170+
171+
v8::Local<v8::Context> context = isolate_->GetCurrentContext();
172+
173+
const char* run_script =
174+
"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();
181+
v8::Local<v8::Value> completion_value =
182+
script->Run(context).ToLocalChecked();
183+
CHECK(completion_value->IsExternal());
184+
instance_data = static_cast<int*>(
185+
completion_value.As<v8::External>()->Value());
186+
CHECK_NE(instance_data, nullptr);
187+
CHECK_EQ(*instance_data, 0);
188+
}
189+
190+
CHECK_EQ(*instance_data, 1);
191+
delete instance_data;
192+
}

0 commit comments

Comments
 (0)