Skip to content

Navigation Menu

Sign in
Appearance settings

Search code, repositories, users, issues, pull requests...

Provide feedback

We read every piece of feedback, and take your input very seriously.

Saved searches

Use saved searches to filter your results more quickly

Appearance settings

Commit 3117ea6

Browse filesBrowse files
addaleaxMylesBorins
authored andcommitted
src: allow adding linked bindings to Environment
This allows manually adding linked bindings to an `Environment` instance, without having to register modules at program load in a global namespace. PR-URL: #30274 Reviewed-By: Gireesh Punathil <gpunathi@in.ibm.com> Reviewed-By: Ben Noordhuis <info@bnoordhuis.nl>
1 parent 0beb8a6 commit 3117ea6
Copy full SHA for 3117ea6

File tree

Expand file treeCollapse file tree

7 files changed

+120
-12
lines changed
Open diff view settings
Filter options
Expand file treeCollapse file tree

7 files changed

+120
-12
lines changed
Open diff view settings
Collapse file

‎src/api/environment.cc‎

Copy file name to clipboardExpand all lines: src/api/environment.cc
+28Lines changed: 28 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -498,4 +498,32 @@ uv_loop_t* GetCurrentEventLoop(Isolate* isolate) {
498498
return env->event_loop();
499499
}
500500

501+
void AddLinkedBinding(Environment* env, const node_module& mod) {
502+
CHECK_NOT_NULL(env);
503+
Mutex::ScopedLock lock(env->extra_linked_bindings_mutex());
504+
505+
node_module* prev_head = env->extra_linked_bindings_head();
506+
env->extra_linked_bindings()->push_back(mod);
507+
if (prev_head != nullptr)
508+
prev_head->nm_link = &env->extra_linked_bindings()->back();
509+
}
510+
511+
void AddLinkedBinding(Environment* env,
512+
const char* name,
513+
addon_context_register_func fn,
514+
void* priv) {
515+
node_module mod = {
516+
NODE_MODULE_VERSION,
517+
NM_F_LINKED,
518+
nullptr, // nm_dso_handle
519+
nullptr, // nm_filename
520+
nullptr, // nm_register_func
521+
fn,
522+
name,
523+
priv,
524+
nullptr // nm_link
525+
};
526+
AddLinkedBinding(env, mod);
527+
}
528+
501529
} // namespace node
Collapse file

‎src/env-inl.h‎

Copy file name to clipboardExpand all lines: src/env-inl.h
+13Lines changed: 13 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -868,6 +868,19 @@ inline bool Environment::is_stopping() const {
868868
return thread_stopper_.is_stopped();
869869
}
870870

871+
inline std::list<node_module>* Environment::extra_linked_bindings() {
872+
return &extra_linked_bindings_;
873+
}
874+
875+
inline node_module* Environment::extra_linked_bindings_head() {
876+
return extra_linked_bindings_.size() > 0 ?
877+
&extra_linked_bindings_.front() : nullptr;
878+
}
879+
880+
inline const Mutex& Environment::extra_linked_bindings_mutex() const {
881+
return extra_linked_bindings_mutex_;
882+
}
883+
871884
inline performance::performance_state* Environment::performance_state() {
872885
return performance_state_.get();
873886
}
Collapse file

‎src/env.cc‎

Copy file name to clipboardExpand all lines: src/env.cc
+4-3Lines changed: 4 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -934,9 +934,10 @@ void Environment::stop_sub_worker_contexts() {
934934
}
935935
}
936936

937-
#if HAVE_INSPECTOR
938-
939-
#endif // HAVE_INSPECTOR
937+
Environment* Environment::worker_parent_env() const {
938+
if (worker_context_ == nullptr) return nullptr;
939+
return worker_context_->env();
940+
}
940941

941942
void MemoryTracker::TrackField(const char* edge_name,
942943
const CleanupHookCallback& value,
Collapse file

‎src/env.h‎

Copy file name to clipboardExpand all lines: src/env.h
+7Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1074,11 +1074,15 @@ class Environment : public MemoryRetainer {
10741074
inline bool owns_inspector() const;
10751075
inline uint64_t thread_id() const;
10761076
inline worker::Worker* worker_context() const;
1077+
Environment* worker_parent_env() const;
10771078
inline void set_worker_context(worker::Worker* context);
10781079
inline void add_sub_worker_context(worker::Worker* context);
10791080
inline void remove_sub_worker_context(worker::Worker* context);
10801081
void stop_sub_worker_contexts();
10811082
inline bool is_stopping() const;
1083+
inline std::list<node_module>* extra_linked_bindings();
1084+
inline node_module* extra_linked_bindings_head();
1085+
inline const Mutex& extra_linked_bindings_mutex() const;
10821086

10831087
inline void ThrowError(const char* errmsg);
10841088
inline void ThrowTypeError(const char* errmsg);
@@ -1374,6 +1378,9 @@ class Environment : public MemoryRetainer {
13741378

13751379
worker::Worker* worker_context_ = nullptr;
13761380

1381+
std::list<node_module> extra_linked_bindings_;
1382+
Mutex extra_linked_bindings_mutex_;
1383+
13771384
static void RunTimers(uv_timer_t* handle);
13781385

13791386
struct ExitCallback {
Collapse file

‎src/node.h‎

Copy file name to clipboardExpand all lines: src/node.h
+11Lines changed: 11 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -662,6 +662,17 @@ extern "C" NODE_EXTERN void node_module_register(void* mod);
662662
v8::Local<v8::Value> module, \
663663
v8::Local<v8::Context> context)
664664

665+
// Allows embedders to add a binding to the current Environment* that can be
666+
// accessed through process._linkedBinding() in the target Environment and all
667+
// Worker threads that it creates.
668+
// In each variant, the registration function needs to be usable at least for
669+
// the time during which the Environment exists.
670+
NODE_EXTERN void AddLinkedBinding(Environment* env, const node_module& mod);
671+
NODE_EXTERN void AddLinkedBinding(Environment* env,
672+
const char* name,
673+
addon_context_register_func fn,
674+
void* priv);
675+
665676
/* Called after the event loop exits but before the VM is disposed.
666677
* Callbacks are run in reverse order of registration, i.e. newest first.
667678
*
Collapse file

‎src/node_binding.cc‎

Copy file name to clipboardExpand all lines: src/node_binding.cc
+15-9Lines changed: 15 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -558,13 +558,6 @@ inline struct node_module* FindModule(struct node_module* list,
558558
return mp;
559559
}
560560

561-
node_module* get_internal_module(const char* name) {
562-
return FindModule(modlist_internal, name, NM_F_INTERNAL);
563-
}
564-
node_module* get_linked_module(const char* name) {
565-
return FindModule(modlist_linked, name, NM_F_LINKED);
566-
}
567-
568561
static Local<Object> InitModule(Environment* env,
569562
node_module* mod,
570563
Local<String> module) {
@@ -592,7 +585,7 @@ void GetInternalBinding(const FunctionCallbackInfo<Value>& args) {
592585
node::Utf8Value module_v(env->isolate(), module);
593586
Local<Object> exports;
594587

595-
node_module* mod = get_internal_module(*module_v);
588+
node_module* mod = FindModule(modlist_internal, *module_v, NM_F_INTERNAL);
596589
if (mod != nullptr) {
597590
exports = InitModule(env, mod, module);
598591
} else if (!strcmp(*module_v, "constants")) {
@@ -625,7 +618,20 @@ void GetLinkedBinding(const FunctionCallbackInfo<Value>& args) {
625618
Local<String> module_name = args[0].As<String>();
626619

627620
node::Utf8Value module_name_v(env->isolate(), module_name);
628-
node_module* mod = get_linked_module(*module_name_v);
621+
const char* name = *module_name_v;
622+
node_module* mod = nullptr;
623+
624+
// Iterate from here to the nearest non-Worker Environment to see if there's
625+
// a linked binding defined locally rather than through the global list.
626+
Environment* cur_env = env;
627+
while (mod == nullptr && cur_env != nullptr) {
628+
Mutex::ScopedLock lock(cur_env->extra_linked_bindings_mutex());
629+
mod = FindModule(cur_env->extra_linked_bindings_head(), name, NM_F_LINKED);
630+
cur_env = cur_env->worker_parent_env();
631+
}
632+
633+
if (mod == nullptr)
634+
mod = FindModule(modlist_linked, name, NM_F_LINKED);
629635

630636
if (mod == nullptr) {
631637
char errmsg[1024];
Collapse file

‎test/cctest/test_linked_binding.cc‎

Copy file name to clipboardExpand all lines: test/cctest/test_linked_binding.cc
+42Lines changed: 42 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -41,3 +41,45 @@ TEST_F(LinkedBindingTest, SimpleTest) {
4141
CHECK_NOT_NULL(*utf8val);
4242
CHECK_EQ(strcmp(*utf8val, "value"), 0);
4343
}
44+
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+
v8::NewStringType::kNormal).ToLocalChecked(),
56+
v8::String::NewFromOneByte(isolate,
57+
reinterpret_cast<const uint8_t*>("value"),
58+
v8::NewStringType::kNormal).ToLocalChecked())
59+
.FromJust();
60+
}
61+
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+
v8::NewStringType::kNormal).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+
}

0 commit comments

Comments
0 (0)
Morty Proxy This is a proxified and sanitized view of the page, visit original site.