diff --git a/ext/napi/lib.rs b/ext/napi/lib.rs index a304a88187..b4f38fd0af 100644 --- a/ext/napi/lib.rs +++ b/ext/napi/lib.rs @@ -678,7 +678,7 @@ where let nm = unsafe { &*nm }; assert_eq!(nm.nm_version, 1); // SAFETY: we are going blind, calling the register function on the other side. - let exports = unsafe { + let maybe_exports = unsafe { (nm.nm_register_func)( env_ptr, std::mem::transmute::, napi_value>( @@ -687,11 +687,20 @@ where ) }; - // SAFETY: v8::Local is a pointer to a value and napi_value is also a pointer - // to a value, they have the same layout - let exports = unsafe { - std::mem::transmute::>(exports) - }; + let exports = maybe_exports + .as_ref() + .map(|_| unsafe { + // SAFETY: v8::Local is a pointer to a value and napi_value is also a pointer + // to a value, they have the same layout + std::mem::transmute::>( + maybe_exports, + ) + }) + .unwrap_or_else(|| { + // If the module didn't return anything, we use the exports object. + exports.into() + }); + Ok(serde_v8::Value { v8_value: exports }) } None => { @@ -704,17 +713,29 @@ where exports: napi_value, ) -> napi_value>(b"napi_register_module_v1") .expect("napi_register_module_v1 not found"); - init( + let maybe_exports = init( env_ptr, std::mem::transmute::, napi_value>( exports.into(), ), - ) - }; + ); - Ok(serde_v8::Value { - v8_value: exports.into(), - }) + let exports = maybe_exports + .as_ref() + .map(|_| { + // SAFETY: v8::Local is a pointer to a value and napi_value is also a pointer + // to a value, they have the same layout + std::mem::transmute::>( + maybe_exports, + ) + }) + .unwrap_or_else(|| { + // If the module didn't return anything, we use the exports object. + exports.into() + }); + + Ok(serde_v8::Value { v8_value: exports }) + } } }; // NAPI addons can't be unloaded, so we're going to "forget" the library diff --git a/test_napi/src/lib.rs b/test_napi/src/lib.rs index c02e53da46..78a8248dcf 100644 --- a/test_napi/src/lib.rs +++ b/test_napi/src/lib.rs @@ -123,13 +123,20 @@ pub fn init_cleanup_hook(env: napi_env, exports: napi_value) { #[no_mangle] unsafe extern "C" fn napi_register_module_v1( env: napi_env, - exports: napi_value, + _: napi_value, ) -> napi_value { #[cfg(windows)] { napi_sys::setup(); } + // We create a fresh exports object and leave the passed + // exports object empty. + // + // https://github.com/denoland/deno/issues/17349 + let mut exports = std::ptr::null_mut(); + assert_napi_ok!(napi_create_object(env, &mut exports)); + strings::init(env, exports); numbers::init(env, exports); typedarray::init(env, exports);