Skip to content

Commit 62eafd0

Browse files
author
Mariusz Pasinski
committed
feat: support modules that register via napi_module_register()
This change solves #3 and #70
1 parent a703626 commit 62eafd0

File tree

3 files changed

+42
-9
lines changed

3 files changed

+42
-9
lines changed

packages/react-native-node-api-modules/cpp/AddonRegistry.cpp

Lines changed: 33 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -76,18 +76,31 @@ AddonRegistry::NodeAddon& AddonRegistry::loadAddon(std::string packageName,
7676
}
7777

7878
bool AddonRegistry::tryLoadAddonAsDynamicLib(NodeAddon &addon, const std::string &path) {
79+
{
80+
// There can be only a SINGLE pending module (the same limitation
81+
// has Node.js since Jan 28, 2014 commit 76b9846, see link below).
82+
// We MUST clear it before attempting to load next addon.
83+
// https://github.com/nodejs/node/blob/76b98462e589a69d9fd48ccb9fb5f6e96b539715/src/node.cc#L1949)
84+
assert(nullptr == pendingRegistration_);
85+
}
86+
7987
// Load addon as dynamic library
8088
typename LoaderPolicy::Module library = LoaderPolicy::loadLibrary(path.c_str());
8189
if (nullptr != library) {
82-
// pending addon remains empty, we should look for the symbols...
83-
typename LoaderPolicy::Symbol initFn = LoaderPolicy::getSymbol(library, "napi_register_module_v1");
84-
if (nullptr != initFn) {
85-
addon.initFun_ = (napi_addon_register_func)initFn;
86-
addon.moduleApiVersion_ = NODE_API_DEFAULT_MODULE_API_VERSION;
87-
// This solves https://github.com/callstackincubator/react-native-node-api-modules/issues/4
88-
typename LoaderPolicy::Symbol getVersionFn = LoaderPolicy::getSymbol(library, "node_api_module_get_api_version_v1");
89-
if (nullptr != getVersionFn) {
90-
addon.moduleApiVersion_ = ((node_api_addon_get_api_version_func)getVersionFn)();
90+
if (nullptr != pendingRegistration_) {
91+
// there is a pending addon that used the deprecated `napi_register_module()`
92+
addon.initFun_ = pendingRegistration_;
93+
} else {
94+
// pending addon remains empty, we should look for the symbols...
95+
typename LoaderPolicy::Symbol initFn = LoaderPolicy::getSymbol(library, "napi_register_module_v1");
96+
if (nullptr != initFn) {
97+
addon.initFun_ = (napi_addon_register_func)initFn;
98+
addon.moduleApiVersion_ = NODE_API_DEFAULT_MODULE_API_VERSION;
99+
// This solves https://github.com/callstackincubator/react-native-node-api-modules/issues/4
100+
typename LoaderPolicy::Symbol getVersionFn = LoaderPolicy::getSymbol(library, "node_api_module_get_api_version_v1");
101+
if (nullptr != getVersionFn) {
102+
addon.moduleApiVersion_ = ((node_api_addon_get_api_version_func)getVersionFn)();
103+
}
91104
}
92105
}
93106

@@ -96,6 +109,11 @@ bool AddonRegistry::tryLoadAddonAsDynamicLib(NodeAddon &addon, const std::string
96109
addon.loadedFilePath_ = path;
97110
}
98111
}
112+
113+
// We MUST clear the `pendingAddon_`, even when the module failed to load!
114+
// See: https://github.com/nodejs/node/commit/a60056df3cad2867d337fc1d7adeebe66f89031a
115+
pendingRegistration_ = nullptr;
116+
return addon.isLoaded();
99117
}
100118

101119
jsi::Value AddonRegistry::instantiateAddonInRuntime(jsi::Runtime &rt, NodeAddon &addon) {
@@ -135,6 +153,12 @@ jsi::Value AddonRegistry::instantiateAddonInRuntime(jsi::Runtime &rt, NodeAddon
135153
return lookupAddonByFullPath(rt, fqap);
136154
}
137155

156+
bool AddonRegistry::handleOldNapiModuleRegister(napi_addon_register_func addonInitFunc) {
157+
assert(nullptr == pendingRegistration_);
158+
pendingRegistration_ = addonInitFunc;
159+
return true;
160+
}
161+
138162
napi_status AddonRegistry::createAddonDescriptor(napi_env env, napi_value exports, napi_value *outDescriptor) {
139163
// Create the descriptor object
140164
assert(nullptr != outDescriptor);

packages/react-native-node-api-modules/cpp/AddonRegistry.hpp

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -30,6 +30,7 @@ class AddonRegistry {
3030

3131
NodeAddon& loadAddon(std::string packageName, std::string subpath);
3232
facebook::jsi::Value instantiateAddonInRuntime(facebook::jsi::Runtime &rt, NodeAddon &addon);
33+
bool handleOldNapiModuleRegister(napi_addon_register_func addonInitFunc);
3334

3435
using LoaderPolicy = PosixLoader; // FIXME: HACK: This is temporary workaround
3536
// for my lazyness (works on iOS and Android)
@@ -41,6 +42,7 @@ class AddonRegistry {
4142

4243
static constexpr const char *kInternalRegistryKey = "$NodeApiHost";
4344
std::unordered_map<std::string, NodeAddon> trackedAddons_;
45+
napi_addon_register_func pendingRegistration_;
4446
};
4547

4648
} // namespace callstack::nodeapihost

packages/react-native-node-api-modules/cpp/CxxNodeApiHostModule.cpp

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -248,4 +248,11 @@ void CxxNodeApiHostModule::updateRequireCache(jsi::Runtime &rt,
248248
// TODO: Implement me
249249
}
250250

251+
extern "C" {
252+
NAPI_EXTERN void NAPI_CDECL napi_module_register(napi_module *mod) {
253+
assert(NULL != mod && NULL != mod->nm_register_func);
254+
g_platformAddonRegistry.handleOldNapiModuleRegister(mod->nm_register_func);
255+
}
256+
} // extern "C"
257+
251258
} // namespace callstack::nodeapihost

0 commit comments

Comments
 (0)