Skip to content

Commit a703626

Browse files
author
Mariusz Pasinski
committed
refactor: swap old TM addon loader with AddonRegistry
1 parent 0aaf8d7 commit a703626

File tree

2 files changed

+11
-108
lines changed

2 files changed

+11
-108
lines changed

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

Lines changed: 11 additions & 97 deletions
Original file line numberDiff line numberDiff line change
@@ -4,6 +4,7 @@
44
#include <algorithm> // std::equal, std::all_of
55
#include <cctype> // std::isalnum
66
#include "CxxNodeApiHostModule.hpp"
7+
#include "AddonRegistry.hpp"
78
#include "Logger.hpp"
89

910
using namespace facebook;
@@ -124,6 +125,8 @@ rpartition(const std::string_view &input, char delimiter) {
124125

125126
namespace callstack::nodeapihost {
126127

128+
AddonRegistry g_platformAddonRegistry;
129+
127130
CxxNodeApiHostModule::CxxNodeApiHostModule(
128131
std::shared_ptr<react::CallInvoker> jsInvoker)
129132
: TurboModule(CxxNodeApiHostModule::kModuleName, jsInvoker) {
@@ -216,109 +219,20 @@ CxxNodeApiHostModule::resolveRelativePath(facebook::jsi::Runtime &rt,
216219
mergedSubpath);
217220

218221
if (!isCached) {
219-
const std::string libraryNameStr(requiredPath);
220-
auto [it, inserted] = nodeAddons_.emplace(libraryNameStr, NodeAddon());
221-
NodeAddon &addon = it->second;
222-
223-
// Check if this module has been loaded already, if not then load it...
224-
if (inserted) {
225-
if (!loadNodeAddon(addon, libraryNameStr)) {
226-
return jsi::Value::undefined();
227-
}
228-
}
229-
230-
// Initialize the addon if it has not already been initialized
231-
if (!rt.global().hasProperty(rt, addon.generatedName.data())) {
232-
initializeNodeModule(rt, addon);
233-
}
234-
235-
// Look up the exports (using JSI), add to cache and return
236-
exports = rt.global().getProperty(rt, addon.generatedName.data());
222+
// Ask the global addon registry to load given Node-API addon.
223+
// If other runtime loaded it already, the OS will return the same pointer.
224+
// NOTE: This method might try multiple platform-specific paths.
225+
const std::string packageNameCopy(requiredPackageName);
226+
auto &addon = g_platformAddonRegistry.loadAddon(packageNameCopy, mergedSubpath);
227+
228+
// Create a `napi_env` and initialize the addon
229+
exports = g_platformAddonRegistry.instantiateAddonInRuntime(rt, addon);
237230
updateRequireCache(rt, requiredPackageName, mergedSubpath, exports);
238231
}
239232

240233
return std::move(exports);
241234
}
242235

243-
bool CxxNodeApiHostModule::loadNodeAddon(NodeAddon &addon,
244-
const std::string &libraryName) const {
245-
#if defined(__APPLE__)
246-
std::string libraryPath =
247-
"@rpath/" + libraryName + ".framework/" + libraryName;
248-
#elif defined(__ANDROID__)
249-
std::string libraryPath = "lib" + libraryName + ".so";
250-
#else
251-
abort()
252-
#endif
253-
254-
log_debug("[%s] Loading addon by '%s'", libraryName.c_str(),
255-
libraryPath.c_str());
256-
257-
typename LoaderPolicy::Symbol initFn = NULL;
258-
typename LoaderPolicy::Module library =
259-
LoaderPolicy::loadLibrary(libraryPath.c_str());
260-
if (NULL != library) {
261-
log_debug("[%s] Loaded addon", libraryName.c_str());
262-
addon.moduleHandle = library;
263-
264-
// Generate a name allowing us to reference the exports object from JSI
265-
// later Instead of using random numbers to avoid name clashes, we just use
266-
// the pointer address of the loaded module
267-
addon.generatedName.resize(32, '\0');
268-
snprintf(addon.generatedName.data(), addon.generatedName.size(),
269-
"RN$NodeAddon_%p", addon.moduleHandle);
270-
271-
initFn = LoaderPolicy::getSymbol(library, "napi_register_module_v1");
272-
if (NULL != initFn) {
273-
log_debug("[%s] Found napi_register_module_v1 (%p)", libraryName.c_str(),
274-
initFn);
275-
addon.init = (napi_addon_register_func)initFn;
276-
} else {
277-
log_debug("[%s] Failed to find napi_register_module_v1. Expecting the "
278-
"addon to call napi_module_register to register itself.",
279-
libraryName.c_str());
280-
}
281-
// TODO: Read "node_api_module_get_api_version_v1" to support the addon
282-
// declaring its Node-API version
283-
// @see
284-
// https://github.com/callstackincubator/react-native-node-api-modules/issues/4
285-
} else {
286-
log_debug("[%s] Failed to load library", libraryName.c_str());
287-
}
288-
return NULL != initFn;
289-
}
290-
291-
bool CxxNodeApiHostModule::initializeNodeModule(jsi::Runtime &rt,
292-
NodeAddon &addon) {
293-
// We should check if the module has already been initialized
294-
assert(NULL != addon.moduleHandle);
295-
assert(NULL != addon.init);
296-
napi_status status = napi_ok;
297-
// TODO: Read the version from the addon
298-
// @see
299-
// https://github.com/callstackincubator/react-native-node-api-modules/issues/4
300-
napi_env env = reinterpret_cast<napi_env>(rt.createNodeApiEnv(8));
301-
302-
// Create the "exports" object
303-
napi_value exports;
304-
status = napi_create_object(env, &exports);
305-
assert(status == napi_ok);
306-
307-
// Call the addon init function to populate the "exports" object
308-
// Allowing it to replace the value entirely by its return value
309-
exports = addon.init(env, exports);
310-
311-
napi_value global;
312-
napi_get_global(env, &global);
313-
assert(status == napi_ok);
314-
315-
status =
316-
napi_set_named_property(env, global, addon.generatedName.data(), exports);
317-
assert(status == napi_ok);
318-
319-
return true;
320-
}
321-
322236
std::pair<jsi::Value, bool>
323237
CxxNodeApiHostModule::lookupRequireCache(::jsi::Runtime &rt,
324238
const std::string_view &packageName,

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

Lines changed: 0 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -50,19 +50,8 @@ class JSI_EXPORT CxxNodeApiHostModule : public facebook::react::TurboModule {
5050
facebook::jsi::Value &value);
5151

5252
protected:
53-
struct NodeAddon {
54-
void *moduleHandle;
55-
napi_addon_register_func init;
56-
std::string generatedName;
57-
};
58-
std::unordered_map<std::string, NodeAddon> nodeAddons_;
5953
std::unordered_map<std::string, ResolverFunc> prefixResolvers_;
6054
std::unordered_map<std::string, ResolverFunc> packageOverrides_;
61-
using LoaderPolicy = PosixLoader; // FIXME: HACK: This is temporary workaround
62-
// for my lazyness (work on iOS and Android)
63-
64-
bool loadNodeAddon(NodeAddon &addon, const std::string &path) const;
65-
bool initializeNodeModule(facebook::jsi::Runtime &rt, NodeAddon &addon);
6655
};
6756

6857
} // namespace callstack::nodeapihost

0 commit comments

Comments
 (0)