summaryrefslogtreecommitdiff
path: root/src
diff options
context:
space:
mode:
authorBen Noordhuis <info@bnoordhuis.nl>2018-02-22 13:35:26 +0100
committerBen Noordhuis <info@bnoordhuis.nl>2018-03-01 13:45:57 +0100
commit3828fc6289783a632b00270d6b72b5c5bdd6437d (patch)
tree6ebbfb99f150d9c81ff04365a578e42da0ad95e6 /src
parent66315220aebf69573c682fea7f21531f58dd8c2a (diff)
downloadandroid-node-v8-3828fc6289783a632b00270d6b72b5c5bdd6437d.tar.gz
android-node-v8-3828fc6289783a632b00270d6b72b5c5bdd6437d.tar.bz2
android-node-v8-3828fc6289783a632b00270d6b72b5c5bdd6437d.zip
src: make process.dlopen() load well-known symbol
Look for symbol `node_register_module_v${NODE_MODULE_VERSION}` if the add-on didn't self-register. This can be used to create add-ons that support multiple Node.js versions from a single shared object. PR-URL: https://github.com/nodejs/node/pull/18934 Reviewed-By: Colin Ihrig <cjihrig@gmail.com> Reviewed-By: Daniel Bevenius <daniel.bevenius@gmail.com> Reviewed-By: Franziska Hinkelmann <franziska.hinkelmann@gmail.com> Reviewed-By: James M Snell <jasnell@gmail.com> Reviewed-By: Joyee Cheung <joyeec9h3@gmail.com> Reviewed-By: Matheus Marchini <matheus@sthima.com> Reviewed-By: Tobias Nießen <tniessen@tnie.de>
Diffstat (limited to 'src')
-rw-r--r--src/node.cc29
-rw-r--r--src/node.h3
2 files changed, 30 insertions, 2 deletions
diff --git a/src/node.cc b/src/node.cc
index 6d082caacf..dbf9314273 100644
--- a/src/node.cc
+++ b/src/node.cc
@@ -2158,6 +2158,7 @@ struct DLib {
inline bool Open();
inline void Close();
+ inline void* GetSymbolAddress(const char* name);
const std::string filename_;
const int flags_;
@@ -2185,6 +2186,10 @@ void DLib::Close() {
dlclose(handle_);
handle_ = nullptr;
}
+
+void* DLib::GetSymbolAddress(const char* name) {
+ return dlsym(handle_, name);
+}
#else // !__POSIX__
bool DLib::Open() {
int ret = uv_dlopen(filename_.c_str(), &lib_);
@@ -2202,8 +2207,23 @@ void DLib::Close() {
uv_dlclose(&lib_);
handle_ = nullptr;
}
+
+void* DLib::GetSymbolAddress(const char* name) {
+ void* address;
+ if (0 == uv_dlsym(&lib_, name, &address)) return address;
+ return nullptr;
+}
#endif // !__POSIX__
+using InitializerCallback = void (*)(Local<Object> exports,
+ Local<Value> module,
+ Local<Context> context);
+
+inline InitializerCallback GetInitializerCallback(DLib* dlib) {
+ const char* name = "node_register_module_v" STRINGIFY(NODE_MODULE_VERSION);
+ return reinterpret_cast<InitializerCallback>(dlib->GetSymbolAddress(name));
+}
+
// DLOpen is process.dlopen(module, filename, flags).
// Used to load 'module.node' dynamically shared objects.
//
@@ -2258,10 +2278,15 @@ static void DLOpen(const FunctionCallbackInfo<Value>& args) {
}
if (mp == nullptr) {
- dlib.Close();
- env->ThrowError("Module did not self-register.");
+ if (auto callback = GetInitializerCallback(&dlib)) {
+ callback(exports, module, context);
+ } else {
+ dlib.Close();
+ env->ThrowError("Module did not self-register.");
+ }
return;
}
+
if (mp->nm_version == -1) {
if (env->EmitNapiWarning()) {
if (ProcessEmitWarning(env, "N-API is an experimental feature and could "
diff --git a/src/node.h b/src/node.h
index cb43468930..ab5d1c120f 100644
--- a/src/node.h
+++ b/src/node.h
@@ -535,6 +535,9 @@ extern "C" NODE_EXTERN void node_module_register(void* mod);
} \
}
+// Usage: `NODE_MODULE(NODE_GYP_MODULE_NAME, InitializerFunction)`
+// If no NODE_MODULE is declared, Node.js looks for the well-known
+// symbol `node_register_module_v${NODE_MODULE_VERSION}`.
#define NODE_MODULE(modname, regfunc) \
NODE_MODULE_X(modname, regfunc, NULL, 0) // NOLINT (readability/null_usage)