| FazBrowse GitHub Viewer | Trending | | Home |
| Tools: [Download Repo ZIP] [Original HTTPS Page] |
1 parent 0beb8a6 commit 3117ea6
7 files changed
| Original file line number | Diff line number | Diff line change | |
|---|---|---|---|
@@ -498,4 +498,32 @@ uv_loop_t* GetCurrentEventLoop(Isolate* isolate) { | |||
| 498 | 498 | return env->event_loop(); | |
| 499 | 499 | } | |
| 500 | 500 | ||
| 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 | + | ||
| 501 | 529 | } // namespace node | |
| Original file line number | Diff line number | Diff line change | |
|---|---|---|---|
@@ -868,6 +868,19 @@ inline bool Environment::is_stopping() const { | |||
| 868 | 868 | return thread_stopper_.is_stopped(); | |
| 869 | 869 | } | |
| 870 | 870 | ||
| 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 | + | ||
| 871 | 884 | inline performance::performance_state* Environment::performance_state() { | |
| 872 | 885 | return performance_state_.get(); | |
| 873 | 886 | } | |
| Original file line number | Diff line number | Diff line change | |
|---|---|---|---|
@@ -934,9 +934,10 @@ void Environment::stop_sub_worker_contexts() { | |||
| 934 | 934 | } | |
| 935 | 935 | } | |
| 936 | 936 | ||
| 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 | + } | ||
| 940 | 941 | ||
| 941 | 942 | void MemoryTracker::TrackField(const char* edge_name, | |
| 942 | 943 | const CleanupHookCallback& value, | |
| Original file line number | Diff line number | Diff line change | |
|---|---|---|---|
@@ -1074,11 +1074,15 @@ class Environment : public MemoryRetainer { | |||
| 1074 | 1074 | inline bool owns_inspector() const; | |
| 1075 | 1075 | inline uint64_t thread_id() const; | |
| 1076 | 1076 | inline worker::Worker* worker_context() const; | |
| 1077 | + Environment* worker_parent_env() const; | ||
| 1077 | 1078 | inline void set_worker_context(worker::Worker* context); | |
| 1078 | 1079 | inline void add_sub_worker_context(worker::Worker* context); | |
| 1079 | 1080 | inline void remove_sub_worker_context(worker::Worker* context); | |
| 1080 | 1081 | void stop_sub_worker_contexts(); | |
| 1081 | 1082 | 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; | ||
| 1082 | 1086 | ||
| 1083 | 1087 | inline void ThrowError(const char* errmsg); | |
| 1084 | 1088 | inline void ThrowTypeError(const char* errmsg); | |
@@ -1374,6 +1378,9 @@ class Environment : public MemoryRetainer { | |||
| 1374 | 1378 | ||
| 1375 | 1379 | worker::Worker* worker_context_ = nullptr; | |
| 1376 | 1380 | ||
| 1381 | + std::list<node_module> extra_linked_bindings_; | ||
| 1382 | + Mutex extra_linked_bindings_mutex_; | ||
| 1383 | + | ||
| 1377 | 1384 | static void RunTimers(uv_timer_t* handle); | |
| 1378 | 1385 | ||
| 1379 | 1386 | struct ExitCallback { | |
| Original file line number | Diff line number | Diff line change | |
|---|---|---|---|
@@ -662,6 +662,17 @@ extern "C" NODE_EXTERN void node_module_register(void* mod); | |||
| 662 | 662 | v8::Local<v8::Value> module, \ | |
| 663 | 663 | v8::Local<v8::Context> context) | |
| 664 | 664 | ||
| 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 | + | ||
| 665 | 676 | /* Called after the event loop exits but before the VM is disposed. | |
| 666 | 677 | * Callbacks are run in reverse order of registration, i.e. newest first. | |
| 667 | 678 | * | |
| Original file line number | Diff line number | Diff line change | |
|---|---|---|---|
@@ -558,13 +558,6 @@ inline struct node_module* FindModule(struct node_module* list, | |||
| 558 | 558 | return mp; | |
| 559 | 559 | } | |
| 560 | 560 | ||
| 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 | - | ||
| 568 | 561 | static Local<Object> InitModule(Environment* env, | |
| 569 | 562 | node_module* mod, | |
| 570 | 563 | Local<String> module) { | |
@@ -592,7 +585,7 @@ void GetInternalBinding(const FunctionCallbackInfo<Value>& args) { | |||
| 592 | 585 | node::Utf8Value module_v(env->isolate(), module); | |
| 593 | 586 | Local<Object> exports; | |
| 594 | 587 | ||
| 595 | - node_module* mod = get_internal_module(*module_v); | ||
| 588 | + node_module* mod = FindModule(modlist_internal, *module_v, NM_F_INTERNAL); | ||
| 596 | 589 | if (mod != nullptr) { | |
| 597 | 590 | exports = InitModule(env, mod, module); | |
| 598 | 591 | } else if (!strcmp(*module_v, "constants")) { | |
@@ -625,7 +618,20 @@ void GetLinkedBinding(const FunctionCallbackInfo<Value>& args) { | |||
| 625 | 618 | Local<String> module_name = args[0].As<String>(); | |
| 626 | 619 | ||
| 627 | 620 | 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); | ||
| 629 | 635 | ||
| 630 | 636 | if (mod == nullptr) { | |
| 631 | 637 | char errmsg[1024]; | |
| Original file line number | Diff line number | Diff line change | |
|---|---|---|---|
@@ -41,3 +41,45 @@ TEST_F(LinkedBindingTest, SimpleTest) { | |||
| 41 | 41 | CHECK_NOT_NULL(*utf8val); | |
| 42 | 42 | CHECK_EQ(strcmp(*utf8val, "value"), 0); | |
| 43 | 43 | } | |
| 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 | + } | ||
| Back | FazBrowse Home | New Git URL |
0 commit comments