summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorDivy Srivastava <dj.srivastava23@gmail.com>2023-01-23 05:29:46 -0800
committerGitHub <noreply@github.com>2023-01-23 18:59:46 +0530
commitc3e0b12c72673badece8ef5d789a942637d893ba (patch)
treee46e85e98b1ec9b7649e936b3794f348e408ca74
parentb96bbc32c8a0828f997f6148111a31ec27ec08b1 (diff)
fix(napi): handle return value from initializer (#17502)
Fixes https://github.com/denoland/deno/issues/17349
-rw-r--r--ext/napi/lib.rs47
-rw-r--r--test_napi/src/lib.rs9
2 files changed, 42 insertions, 14 deletions
diff --git a/ext/napi/lib.rs b/ext/napi/lib.rs
index a304a8818..b4f38fd0a 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::<v8::Local<v8::Value>, 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::<napi_value, v8::Local<v8::Value>>(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::<napi_value, v8::Local<v8::Value>>(
+ 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::<v8::Local<v8::Value>, 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::<napi_value, v8::Local<v8::Value>>(
+ 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 c02e53da4..78a8248dc 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);