diff options
author | Ben Noordhuis <info@bnoordhuis.nl> | 2018-02-22 13:35:26 +0100 |
---|---|---|
committer | Ben Noordhuis <info@bnoordhuis.nl> | 2018-03-01 13:45:57 +0100 |
commit | 3828fc6289783a632b00270d6b72b5c5bdd6437d (patch) | |
tree | 6ebbfb99f150d9c81ff04365a578e42da0ad95e6 /src | |
parent | 66315220aebf69573c682fea7f21531f58dd8c2a (diff) | |
download | android-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.cc | 29 | ||||
-rw-r--r-- | src/node.h | 3 |
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) |