Welcome to mirror list, hosted at ThFree Co, Russian Federation.

github.com/nodejs/node.git - Unnamed repository; edit this file 'description' to name the repository.
summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorAnna Henningsen <anna@addaleax.net>2021-06-12 00:43:48 +0300
committerMichaël Zasso <targos@protonmail.com>2021-06-14 14:34:10 +0300
commit163fcecb697de53fc166d429d8cfffb3da980985 (patch)
treeedd1e4d23b6040d3a7cadeecdb6d8519e288894a
parenteb8f7ee634065b24888e4c5f28fb32d530eb7036 (diff)
src: fix multiple AddLinkedBinding() calls
Singly-linked lists are extended at their tail, not their head. This fixes using more than 2 linked addons at a time. PR-URL: https://github.com/nodejs/node/pull/39012 Reviewed-By: Shelley Vohr <codebytere@gmail.com> Reviewed-By: Michaël Zasso <targos@protonmail.com> Reviewed-By: Richard Lau <rlau@redhat.com>
-rw-r--r--src/api/environment.cc6
-rw-r--r--src/env-inl.h5
-rw-r--r--src/env.h1
-rw-r--r--test/cctest/test_linked_binding.cc32
4 files changed, 41 insertions, 3 deletions
diff --git a/src/api/environment.cc b/src/api/environment.cc
index 2c4acbc4fa0..5426d5392a2 100644
--- a/src/api/environment.cc
+++ b/src/api/environment.cc
@@ -671,10 +671,10 @@ void AddLinkedBinding(Environment* env, const node_module& mod) {
CHECK_NOT_NULL(env);
Mutex::ScopedLock lock(env->extra_linked_bindings_mutex());
- node_module* prev_head = env->extra_linked_bindings_head();
+ node_module* prev_tail = env->extra_linked_bindings_tail();
env->extra_linked_bindings()->push_back(mod);
- if (prev_head != nullptr)
- prev_head->nm_link = &env->extra_linked_bindings()->back();
+ if (prev_tail != nullptr)
+ prev_tail->nm_link = &env->extra_linked_bindings()->back();
}
void AddLinkedBinding(Environment* env, const napi_module& mod) {
diff --git a/src/env-inl.h b/src/env-inl.h
index 9b2f82cc00e..e5c9d0eed1b 100644
--- a/src/env-inl.h
+++ b/src/env-inl.h
@@ -892,6 +892,11 @@ inline node_module* Environment::extra_linked_bindings_head() {
&extra_linked_bindings_.front() : nullptr;
}
+inline node_module* Environment::extra_linked_bindings_tail() {
+ return extra_linked_bindings_.size() > 0 ?
+ &extra_linked_bindings_.back() : nullptr;
+}
+
inline const Mutex& Environment::extra_linked_bindings_mutex() const {
return extra_linked_bindings_mutex_;
}
diff --git a/src/env.h b/src/env.h
index ee172017e28..1e930170bce 100644
--- a/src/env.h
+++ b/src/env.h
@@ -1043,6 +1043,7 @@ class Environment : public MemoryRetainer {
inline void set_stopping(bool value);
inline std::list<node_module>* extra_linked_bindings();
inline node_module* extra_linked_bindings_head();
+ inline node_module* extra_linked_bindings_tail();
inline const Mutex& extra_linked_bindings_mutex() const;
inline bool filehandle_close_warning() const;
diff --git a/test/cctest/test_linked_binding.cc b/test/cctest/test_linked_binding.cc
index 17c020429f0..7e40068b5db 100644
--- a/test/cctest/test_linked_binding.cc
+++ b/test/cctest/test_linked_binding.cc
@@ -190,3 +190,35 @@ TEST_F(LinkedBindingTest, LocallyDefinedLinkedBindingNapiInstanceDataTest) {
CHECK_EQ(*instance_data, 1);
delete instance_data;
}
+
+TEST_F(LinkedBindingTest, ManyBindingsTest) {
+ const v8::HandleScope handle_scope(isolate_);
+ const Argv argv;
+ Env test_env {handle_scope, argv};
+
+ int calls = 0;
+ AddLinkedBinding(*test_env, "local_linked1", InitializeLocalBinding, &calls);
+ AddLinkedBinding(*test_env, "local_linked2", InitializeLocalBinding, &calls);
+ AddLinkedBinding(*test_env, "local_linked3", InitializeLocalBinding, &calls);
+ AddLinkedBinding(*test_env, local_linked_napi); // Add a N-API addon as well.
+ AddLinkedBinding(*test_env, "local_linked4", InitializeLocalBinding, &calls);
+ AddLinkedBinding(*test_env, "local_linked5", InitializeLocalBinding, &calls);
+
+ v8::Local<v8::Context> context = isolate_->GetCurrentContext();
+
+ const char* run_script =
+ "for (let i = 1; i <= 5; i++)process._linkedBinding(`local_linked${i}`);"
+ "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);
+ CHECK_EQ(calls, 5);
+}
+