diff options
author | Anna Henningsen <anna@addaleax.net> | 2021-06-12 00:43:48 +0300 |
---|---|---|
committer | Michaël Zasso <targos@protonmail.com> | 2021-06-14 14:34:10 +0300 |
commit | 163fcecb697de53fc166d429d8cfffb3da980985 (patch) | |
tree | edd1e4d23b6040d3a7cadeecdb6d8519e288894a | |
parent | eb8f7ee634065b24888e4c5f28fb32d530eb7036 (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.cc | 6 | ||||
-rw-r--r-- | src/env-inl.h | 5 | ||||
-rw-r--r-- | src/env.h | 1 | ||||
-rw-r--r-- | test/cctest/test_linked_binding.cc | 32 |
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); +} + |