Skip to content
Closed
Show file tree
Hide file tree
Changes from 1 commit
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Prev Previous commit
Next Next commit
Address PR feedback
  • Loading branch information
vmoroz committed Mar 10, 2023
commit d0af42d9509c2904f08f82c6863392e020d6e38c
30 changes: 29 additions & 1 deletion src/api/environment.cc
Original file line number Diff line number Diff line change
Expand Up @@ -833,7 +833,9 @@ void AddLinkedBinding(Environment* env, const node_module& mod) {
}

void AddLinkedBinding(Environment* env, const napi_module& mod) {
AddLinkedBinding(env, napi_module_to_node_module(&mod));
node_module node_mod = napi_module_to_node_module(&mod);
node_mod.nm_flags = NM_F_LINKED;
AddLinkedBinding(env, node_mod);
}

void AddLinkedBinding(Environment* env,
Expand All @@ -854,6 +856,32 @@ void AddLinkedBinding(Environment* env,
AddLinkedBinding(env, mod);
}

void AddLinkedBinding(Environment* env,
const char* name,
napi_addon_register_func fn) {
node_module mod = {
-1,
NM_F_LINKED,
nullptr, // nm_dso_handle
nullptr, // nm_filename
nullptr, // nm_register_func
[](v8::Local<v8::Object> exports,
v8::Local<v8::Value> module,
v8::Local<v8::Context> context,
void* priv) {
napi_module_register_by_symbol(
exports,
module,
context,
reinterpret_cast<napi_addon_register_func>(priv));
},
name,
fn,
nullptr // nm_link
};
AddLinkedBinding(env, mod);
}

static std::atomic<uint64_t> next_thread_id{0};

ThreadId AllocateEnvironmentThreadId() {
Expand Down
8 changes: 6 additions & 2 deletions src/node.h
Original file line number Diff line number Diff line change
Expand Up @@ -75,6 +75,9 @@
#include "v8-platform.h" // NOLINT(build/include_order)
#include "node_version.h" // NODE_MODULE_VERSION

#define NAPI_EXPERIMENTAL
#include "node_api.h"

#include <functional>
#include <memory>
#include <ostream>
Expand Down Expand Up @@ -121,8 +124,6 @@
// Forward-declare libuv loop
struct uv_loop_s;

struct napi_module;

// Forward-declare these functions now to stop MSVS from becoming
// terminally confused when it's done in node_internals.h
namespace node {
Expand Down Expand Up @@ -1235,6 +1236,9 @@ NODE_EXTERN void AddLinkedBinding(Environment* env,
const char* name,
addon_context_register_func fn,
void* priv);
NODE_EXTERN void AddLinkedBinding(Environment* env,
const char* name,
napi_addon_register_func fn);

/* Registers a callback with the passed-in Environment instance. The callback
* is called after the event loop exits, but before the VM is disposed.
Expand Down
3 changes: 3 additions & 0 deletions src/node_api.h
Original file line number Diff line number Diff line change
Expand Up @@ -75,6 +75,9 @@ EXTERN_C_START

// Deprecated. Replaced by symbol-based registration defined by NAPI_MODULE
// and NAPI_MODULE_INIT macros.
#if defined(__cplusplus) && __cplusplus >= 201402L
[[deprecated]]
#endif
NAPI_EXTERN void NAPI_CDECL napi_module_register(napi_module* mod);

NAPI_EXTERN NAPI_NO_RETURN void NAPI_CDECL
Expand Down
56 changes: 56 additions & 0 deletions test/cctest/test_linked_binding.cc
Original file line number Diff line number Diff line change
Expand Up @@ -127,6 +127,29 @@ TEST_F(LinkedBindingTest, LocallyDefinedLinkedBindingNapiTest) {
CHECK_EQ(strcmp(*utf8val, "world"), 0);
}

TEST_F(LinkedBindingTest, LocallyDefinedLinkedBindingNapiCallbackTest) {
const v8::HandleScope handle_scope(isolate_);
const Argv argv;
Env test_env {handle_scope, argv};

AddLinkedBinding(*test_env, "local_linked_napi", InitializeLocalNapiBinding);

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

const char* run_script =
"process._linkedBinding('local_linked_napi').hello";
v8::Local<v8::Script> script = v8::Script::Compile(
context,
v8::String::NewFromOneByte(isolate_,
reinterpret_cast<const uint8_t*>(run_script))
.ToLocalChecked())
.ToLocalChecked();
v8::Local<v8::Value> completion_value = script->Run(context).ToLocalChecked();
v8::String::Utf8Value utf8val(isolate_, completion_value);
CHECK_NOT_NULL(*utf8val);
CHECK_EQ(strcmp(*utf8val, "world"), 0);
}

napi_value NapiLinkedWithInstanceData(napi_env env, napi_value exports) {
int* instance_data = new int(0);
CHECK_EQ(
Expand Down Expand Up @@ -191,6 +214,39 @@ TEST_F(LinkedBindingTest, LocallyDefinedLinkedBindingNapiInstanceDataTest) {
delete instance_data;
}

TEST_F(LinkedBindingTest, LocallyDefinedLinkedBindingNapiCallbackInstanceDataTest) {
const v8::HandleScope handle_scope(isolate_);
int* instance_data = nullptr;

{
const Argv argv;
Env test_env {handle_scope, argv};

AddLinkedBinding(*test_env, "local_linked_napi_id", NapiLinkedWithInstanceData);

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

const char* run_script =
"process._linkedBinding('local_linked_napi_id').hello";
v8::Local<v8::Script> script = v8::Script::Compile(
context,
v8::String::NewFromOneByte(isolate_,
reinterpret_cast<const uint8_t*>(run_script))
.ToLocalChecked())
.ToLocalChecked();
v8::Local<v8::Value> completion_value =
script->Run(context).ToLocalChecked();
CHECK(completion_value->IsExternal());
instance_data = static_cast<int*>(
completion_value.As<v8::External>()->Value());
CHECK_NE(instance_data, nullptr);
CHECK_EQ(*instance_data, 0);
}

CHECK_EQ(*instance_data, 1);
delete instance_data;
}

TEST_F(LinkedBindingTest, ManyBindingsTest) {
const v8::HandleScope handle_scope(isolate_);
const Argv argv;
Expand Down
6 changes: 6 additions & 0 deletions test/node-api/test_null_init/test_null_init.c
Original file line number Diff line number Diff line change
@@ -1,5 +1,11 @@
#include <node_api.h>

// This test uses old module initialization style deprecated in current code.
// The goal is to see that all previously compiled code continues to work the
// same way as before.
// The test has a copy of previous macro definitions which are removed from
// the node_api.h file.

#if defined(_MSC_VER)
#if defined(__cplusplus)
#define NAPI_C_CTOR(fn) \
Expand Down