• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 #include "node_test_fixture.h"
2 #include "node_api.h"
3 
InitializeBinding(v8::Local<v8::Object> exports,v8::Local<v8::Value> module,v8::Local<v8::Context> context,void * priv)4 void InitializeBinding(v8::Local<v8::Object> exports,
5                        v8::Local<v8::Value> module,
6                        v8::Local<v8::Context> context,
7                        void* priv) {
8   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())
17       .FromJust();
18 }
19 
20 NODE_MODULE_LINKED(cctest_linkedbinding, InitializeBinding)
21 
22 class LinkedBindingTest : public EnvironmentTestFixture {};
23 
TEST_F(LinkedBindingTest,SimpleTest)24 TEST_F(LinkedBindingTest, SimpleTest) {
25   const v8::HandleScope handle_scope(isolate_);
26   const Argv argv;
27   Env test_env {handle_scope, argv};
28 
29   v8::Local<v8::Context> context = isolate_->GetCurrentContext();
30 
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();
39   v8::Local<v8::Value> completion_value = script->Run(context).ToLocalChecked();
40   v8::String::Utf8Value utf8val(isolate_, completion_value);
41   CHECK_NOT_NULL(*utf8val);
42   CHECK_EQ(strcmp(*utf8val, "value"), 0);
43 }
44 
InitializeLocalBinding(v8::Local<v8::Object> exports,v8::Local<v8::Value> module,v8::Local<v8::Context> context,void * priv)45 void InitializeLocalBinding(v8::Local<v8::Object> exports,
46                             v8::Local<v8::Value> module,
47                             v8::Local<v8::Context> context,
48                             void* priv) {
49   ++*static_cast<int*>(priv);
50   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())
59       .FromJust();
60 }
61 
TEST_F(LinkedBindingTest,LocallyDefinedLinkedBindingTest)62 TEST_F(LinkedBindingTest, LocallyDefinedLinkedBindingTest) {
63   const v8::HandleScope handle_scope(isolate_);
64   const Argv argv;
65   Env test_env {handle_scope, argv};
66 
67   int calls = 0;
68   AddLinkedBinding(*test_env, "local_linked", InitializeLocalBinding, &calls);
69 
70   v8::Local<v8::Context> context = isolate_->GetCurrentContext();
71 
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();
80   v8::Local<v8::Value> completion_value = script->Run(context).ToLocalChecked();
81   v8::String::Utf8Value utf8val(isolate_, completion_value);
82   CHECK_NOT_NULL(*utf8val);
83   CHECK_EQ(strcmp(*utf8val, "value"), 0);
84   CHECK_EQ(calls, 1);
85 }
86 
InitializeLocalNapiBinding(napi_env env,napi_value exports)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 
TEST_F(LinkedBindingTest,LocallyDefinedLinkedBindingNapiTest)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 
NapiLinkedWithInstanceData(napi_env env,napi_value exports)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 
TEST_F(LinkedBindingTest,LocallyDefinedLinkedBindingNapiInstanceDataTest)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 }
193 
TEST_F(LinkedBindingTest,ManyBindingsTest)194 TEST_F(LinkedBindingTest, ManyBindingsTest) {
195   const v8::HandleScope handle_scope(isolate_);
196   const Argv argv;
197   Env test_env {handle_scope, argv};
198 
199   int calls = 0;
200   AddLinkedBinding(*test_env, "local_linked1", InitializeLocalBinding, &calls);
201   AddLinkedBinding(*test_env, "local_linked2", InitializeLocalBinding, &calls);
202   AddLinkedBinding(*test_env, "local_linked3", InitializeLocalBinding, &calls);
203   AddLinkedBinding(*test_env, local_linked_napi);  // Add a N-API addon as well.
204   AddLinkedBinding(*test_env, "local_linked4", InitializeLocalBinding, &calls);
205   AddLinkedBinding(*test_env, "local_linked5", InitializeLocalBinding, &calls);
206 
207   v8::Local<v8::Context> context = isolate_->GetCurrentContext();
208 
209   const char* run_script =
210       "for (let i = 1; i <= 5; i++)process._linkedBinding(`local_linked${i}`);"
211       "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();
218   v8::Local<v8::Value> completion_value = script->Run(context).ToLocalChecked();
219   v8::String::Utf8Value utf8val(isolate_, completion_value);
220   CHECK_NOT_NULL(*utf8val);
221   CHECK_EQ(strcmp(*utf8val, "world"), 0);
222   CHECK_EQ(calls, 5);
223 }
224 
225