From 3f004ad3782de8d1ac9d415686f52201635ab97d Mon Sep 17 00:00:00 2001 From: Anna Henningsen Date: Tue, 5 Mar 2019 20:14:44 +0100 Subject: [PATCH 1/3] test: make cctest full Node.js environment MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Make sure `node::Init()` is called once, and execute `RunBootstrapping()` so that Node’s internals are ready when the cctests run. --- test/cctest/node_test_fixture.cc | 1 + test/cctest/node_test_fixture.h | 14 ++++++++++++++ 2 files changed, 15 insertions(+) diff --git a/test/cctest/node_test_fixture.cc b/test/cctest/node_test_fixture.cc index f13481824734fb..1a50e58dd9e8fa 100644 --- a/test/cctest/node_test_fixture.cc +++ b/test/cctest/node_test_fixture.cc @@ -4,3 +4,4 @@ ArrayBufferUniquePtr NodeTestFixture::allocator{nullptr, nullptr}; uv_loop_t NodeTestFixture::current_loop; NodePlatformUniquePtr NodeTestFixture::platform; TracingAgentUniquePtr NodeTestFixture::tracing_agent; +bool NodeTestFixture::node_initialized = false; diff --git a/test/cctest/node_test_fixture.h b/test/cctest/node_test_fixture.h index f7ecb9cdea744e..02c1164691b138 100644 --- a/test/cctest/node_test_fixture.h +++ b/test/cctest/node_test_fixture.h @@ -64,9 +64,19 @@ class NodeTestFixture : public ::testing::Test { static TracingAgentUniquePtr tracing_agent; static NodePlatformUniquePtr platform; static uv_loop_t current_loop; + static bool node_initialized; v8::Isolate* isolate_; static void SetUpTestCase() { + if (!node_initialized) { + node_initialized = true; + int argc = 1; + const char* argv0 = "cctest"; + int exec_argc; + const char** exec_argv; + node::Init(&argc, &argv0, &exec_argc, &exec_argv); + } + tracing_agent.reset(new node::tracing::Agent()); node::tracing::TraceEventHelper::SetAgent(tracing_agent.get()); CHECK_EQ(0, uv_loop_init(¤t_loop)); @@ -89,9 +99,11 @@ class NodeTestFixture : public ::testing::Test { &node::FreeArrayBufferAllocator); isolate_ = NewIsolate(allocator.get(), ¤t_loop); CHECK_NE(isolate_, nullptr); + isolate_->Enter(); } void TearDown() override { + isolate_->Exit(); isolate_->Dispose(); platform->UnregisterIsolate(isolate_); isolate_ = nullptr; @@ -118,6 +130,8 @@ class EnvironmentTestFixture : public NodeTestFixture { 1, *argv, argv.nr_args(), *argv); CHECK_NE(nullptr, environment_); + // TODO(addaleax): Make this a public API. + CHECK(!RunBootstrapping(environment_).IsEmpty()); } ~Env() { From 7b193952cf4992a9374aa4cb574e7b1ada7b72e8 Mon Sep 17 00:00:00 2001 From: Anna Henningsen Date: Tue, 5 Mar 2019 20:09:43 +0100 Subject: [PATCH 2/3] 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. --- node.gyp | 1 + src/node.h | 12 +++++++++ src/node_binding.h | 4 +++ test/cctest/test_linked_binding.cc | 42 ++++++++++++++++++++++++++++++ 4 files changed, 59 insertions(+) create mode 100644 test/cctest/test_linked_binding.cc diff --git a/node.gyp b/node.gyp index c005470cef1e23..978ad890f768f9 100644 --- a/node.gyp +++ b/node.gyp @@ -1037,6 +1037,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..7fbe76537a9443 100644 --- a/src/node_binding.h +++ b/src/node_binding.h @@ -21,6 +21,10 @@ 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)); + #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); +} From 211c33722202b49249445adf1babcc6b4fc9347c Mon Sep 17 00:00:00 2001 From: Anna Henningsen Date: Tue, 5 Mar 2019 21:03:23 +0100 Subject: [PATCH 3/3] fixup! src: add public API for linked bindings --- src/node_binding.h | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/src/node_binding.h b/src/node_binding.h index 7fbe76537a9443..e2f4d320c8031d 100644 --- a/src/node_binding.h +++ b/src/node_binding.h @@ -23,7 +23,8 @@ enum { // Make sure our internal values match the public API's values. static_assert(static_cast(NM_F_LINKED) == - static_cast(node::ModuleFlags::kLinked)); + 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 = { \