From db2a5b05dfb3634e8fdb965ef5d4c75f73094e9e Mon Sep 17 00:00:00 2001 From: Anna Henningsen Date: Tue, 5 Mar 2019 20:09:43 +0100 Subject: [PATCH] src: add public API for linked bindings (Re-?)add a public API for creating linked bindings (access to `NM_F_LINKED` as a constant was previously removed in d6ac8a4db0c0a588258f594dc21fbd8018bef7c2), and add a test for the functionality. PR-URL: https://github.com/nodejs/node/pull/26457 Reviewed-By: Ben Noordhuis Reviewed-By: Joyee Cheung Reviewed-By: Shelley Vohr Reviewed-By: James M Snell --- node.gyp | 1 + src/node.h | 12 +++++++++ src/node_binding.h | 5 ++++ test/cctest/test_linked_binding.cc | 42 ++++++++++++++++++++++++++++++ 4 files changed, 60 insertions(+) create mode 100644 test/cctest/test_linked_binding.cc diff --git a/node.gyp b/node.gyp index 64d0721d249705..96e9805a3620d6 100644 --- a/node.gyp +++ b/node.gyp @@ -1038,6 +1038,7 @@ 'test/cctest/test_base64.cc', 'test/cctest/test_node_postmortem_metadata.cc', 'test/cctest/test_environment.cc', + 'test/cctest/test_linked_binding.cc', 'test/cctest/test_platform.cc', 'test/cctest/test_report_util.cc', 'test/cctest/test_traced_value.cc', diff --git a/src/node.h b/src/node.h index 3ba5cf92f349d2..dffeb2b9cd7fc7 100644 --- a/src/node.h +++ b/src/node.h @@ -445,6 +445,10 @@ typedef void (*addon_context_register_func)( v8::Local context, void* priv); +enum ModuleFlags { + kLinked = 0x02 +}; + struct node_module { int nm_version; unsigned int nm_flags; @@ -532,6 +536,14 @@ extern "C" NODE_EXTERN void node_module_register(void* mod); /* NOLINTNEXTLINE (readability/null_usage) */ \ NODE_MODULE_CONTEXT_AWARE_X(modname, regfunc, NULL, 0) +// Embedders can use this type of binding for statically linked native bindings. +// It is used the same way addon bindings are used, except that linked bindings +// can be accessed through `process._linkedBinding(modname)`. +#define NODE_MODULE_LINKED(modname, regfunc) \ + /* NOLINTNEXTLINE (readability/null_usage) */ \ + NODE_MODULE_CONTEXT_AWARE_X(modname, regfunc, NULL, \ + node::ModuleFlags::kLinked) + /* * For backward compatibility in add-on modules. */ diff --git a/src/node_binding.h b/src/node_binding.h index fcd7f34ac6a57a..e2f4d320c8031d 100644 --- a/src/node_binding.h +++ b/src/node_binding.h @@ -21,6 +21,11 @@ enum { NM_F_DELETEME = 1 << 3, }; +// Make sure our internal values match the public API's values. +static_assert(static_cast(NM_F_LINKED) == + static_cast(node::ModuleFlags::kLinked), + "NM_F_LINKED != node::ModuleFlags::kLinked"); + #define NODE_MODULE_CONTEXT_AWARE_CPP(modname, regfunc, priv, flags) \ static node::node_module _module = { \ NODE_MODULE_VERSION, \ diff --git a/test/cctest/test_linked_binding.cc b/test/cctest/test_linked_binding.cc new file mode 100644 index 00000000000000..e0b46d3822754b --- /dev/null +++ b/test/cctest/test_linked_binding.cc @@ -0,0 +1,42 @@ +#include "node_test_fixture.h" +#include "node_internals.h" // RunBootstrapping() + +void InitializeBinding(v8::Local exports, + v8::Local module, + v8::Local context) { + v8::Isolate* isolate = context->GetIsolate(); + exports->Set( + context, + v8::String::NewFromOneByte(isolate, + reinterpret_cast("key"), + v8::NewStringType::kNormal).ToLocalChecked(), + v8::String::NewFromOneByte(isolate, + reinterpret_cast("value"), + v8::NewStringType::kNormal).ToLocalChecked()) + .FromJust(); +} + +NODE_MODULE_LINKED(cctest_linkedbinding, InitializeBinding); + +class LinkedBindingTest : public EnvironmentTestFixture {}; + +TEST_F(LinkedBindingTest, SimpleTest) { + const v8::HandleScope handle_scope(isolate_); + const Argv argv; + Env test_env {handle_scope, argv}; + + v8::Local context = isolate_->GetCurrentContext(); + + const char* run_script = + "process._linkedBinding('cctest_linkedbinding').key"; + v8::Local script = v8::Script::Compile( + context, + v8::String::NewFromOneByte(isolate_, + reinterpret_cast(run_script), + v8::NewStringType::kNormal).ToLocalChecked()) + .ToLocalChecked(); + v8::Local completion_value = script->Run(context).ToLocalChecked(); + v8::String::Utf8Value utf8val(isolate_, completion_value); + CHECK_NOT_NULL(*utf8val); + CHECK_EQ(strcmp(*utf8val, "value"), 0); +}