22
33using namespace facebook ;
44
5- extern napi_status
6- hermes_create_napi_env (::hermes::vm::Runtime &runtime, bool isInspectable,
7- std::shared_ptr<jsi::PreparedScriptStore> scriptCache,
8- const ::hermes::vm::RuntimeConfig &runtimeConfig,
9- napi_env *env);
10-
115namespace callstack ::nodeapihost {
126
137CxxNodeApiHostModule::CxxNodeApiHostModule (
@@ -43,10 +37,10 @@ jsi::Value CxxNodeApiHostModule::requireNodeAddon(jsi::Runtime &rt,
4337 // Library has been loaded, make sure that the "exports" was populated.
4438 // If not, then just call the "napi_register_module_v1" function...
4539 NodeAddon &addon = nodeAddons_[pathStr];
46- if ( NULL == addon. cachedExports ) {
47- if (! initializeNodeModule (napiEnv_, addon)) {
48- return jsi::Value::undefined ();
49- }
40+
41+ // Initialize the addon if it has not already been initialized
42+ if (!rt. global (). hasProperty (rt, addon. generatedName . data ())) {
43+ initializeNodeModule (rt, addon);
5044 }
5145
5246 // Look the exports up (using JSI) and return it...
@@ -55,46 +49,59 @@ jsi::Value CxxNodeApiHostModule::requireNodeAddon(jsi::Runtime &rt,
5549
5650bool CxxNodeApiHostModule::loadNodeAddon (NodeAddon &addon,
5751 const std::string &path) const {
58- typename LoaderPolicy::Symbol registratorFn = NULL ;
52+ typename LoaderPolicy::Symbol initFn = NULL ;
5953 typename LoaderPolicy::Module library =
6054 LoaderPolicy::loadLibrary (path.c_str ());
6155 if (NULL != library) {
6256 addon.moduleHandle = library;
63- registratorFn = LoaderPolicy::getSymbol (library, " napi_register_module_v1" );
64- if (NULL != registratorFn) {
65- addon.registerFn = (napi_addon_register_func)registratorFn;
57+
58+ // Generate a name allowing us to reference the exports object from JSI
59+ // later Instead of using random numbers to avoid name clashes, we just use
60+ // the pointer address of the loaded module
61+ addon.generatedName .resize (32 , ' \0 ' );
62+ snprintf (addon.generatedName .data (), addon.generatedName .size (),
63+ " RN$NodeAddon_%lX" , (uintptr_t )addon.moduleHandle );
64+
65+ initFn = LoaderPolicy::getSymbol (library, " napi_register_module_v1" );
66+ if (NULL != initFn) {
67+ addon.init = (napi_addon_register_func)initFn;
6668 }
69+ // TODO: Read "node_api_module_get_api_version_v1" to support the addon
70+ // declaring its Node-API version
71+ // @see
72+ // https://github.com/callstackincubator/react-native-node-api-modules/issues/4
6773 }
68- return NULL != registratorFn ;
74+ return NULL != initFn ;
6975}
7076
7177bool CxxNodeApiHostModule::initializeNodeModule (jsi::Runtime &rt,
7278 NodeAddon &addon) {
73- // We should check if the module has already been registered
79+ // We should check if the module has already been initialized
7480 assert (NULL != addon.moduleHandle );
75- assert (NULL != addon.registerFn );
81+ assert (NULL != addon.init );
7682 napi_status status = napi_ok;
77- napi_value &exports = addon.cachedExports ;
83+ // TODO: Read the version from the addon
84+ // @see
85+ // https://github.com/callstackincubator/react-native-node-api-modules/issues/4
86+ napi_env env = reinterpret_cast <napi_env>(rt.createNodeApiEnv (8 ));
7887
7988 // Create the "exports" object
80- status = napi_create_object (napiEnv_, &exports);
81- if (napi_ok != status) {
82- return false ;
83- }
84-
85- // Call the addon registration function to populate the "exports" object
86- addon.registerFn (napiEnv_, exports);
89+ napi_value exports;
90+ status = napi_create_object (env, &exports);
91+ assert (status == napi_ok);
8792
88- // Instead of using random numbers to avoid name clashes, we just use the
89- // pointer address of the loaded module
90- addon.generatedName .resize (32 , ' \0 ' );
91- snprintf (addon.generatedName .data (), addon.generatedName .size (),
92- " RN$NodeAddon_%lX" , (uintptr_t )addon.moduleHandle );
93+ // Call the addon init function to populate the "exports" object
94+ // Allowing it to replace the value entirely by its return value
95+ exports = addon.init (env, exports);
9396
9497 napi_value global;
95- napi_get_global (napiEnv_, &global);
96- napi_set_named_property (napiEnv_, global, addon.generatedName .data (),
97- addon.cachedExports );
98+ napi_get_global (env, &global);
99+ assert (status == napi_ok);
100+
101+ status =
102+ napi_set_named_property (env, global, addon.generatedName .data (), exports);
103+ assert (status == napi_ok);
104+
98105 return true ;
99106}
100107
0 commit comments