summaryrefslogtreecommitdiff
path: root/ext/napi
diff options
context:
space:
mode:
Diffstat (limited to 'ext/napi')
-rw-r--r--ext/napi/lib.rs31
-rw-r--r--ext/napi/value.rs58
2 files changed, 77 insertions, 12 deletions
diff --git a/ext/napi/lib.rs b/ext/napi/lib.rs
index 5bcb29643..5fd3085ca 100644
--- a/ext/napi/lib.rs
+++ b/ext/napi/lib.rs
@@ -12,18 +12,12 @@ use deno_core::futures::channel::mpsc;
use deno_core::futures::StreamExt;
use deno_core::op;
use deno_core::serde_v8;
-pub use deno_core::v8;
use deno_core::Extension;
use deno_core::OpState;
use std::cell::RefCell;
-pub use std::ffi::CStr;
use std::ffi::CString;
-pub use std::mem::transmute;
-pub use std::os::raw::c_char;
-pub use std::os::raw::c_void;
use std::path::Path;
use std::path::PathBuf;
-pub use std::ptr;
use std::task::Poll;
use std::thread_local;
@@ -33,11 +27,21 @@ use libloading::os::unix::*;
#[cfg(windows)]
use libloading::os::windows::*;
+// Expose common stuff for ease of use.
+// `use deno_napi::*`
+pub use deno_core::v8;
+pub use std::ffi::CStr;
+pub use std::mem::transmute;
+pub use std::os::raw::c_char;
+pub use std::os::raw::c_void;
+pub use std::ptr;
+pub use value::napi_value;
+
pub mod function;
+mod value;
pub type napi_status = i32;
pub type napi_env = *mut c_void;
-pub type napi_value = *mut c_void;
pub type napi_callback_info = *mut c_void;
pub type napi_deferred = *mut c_void;
pub type napi_ref = *mut c_void;
@@ -81,7 +85,7 @@ type napi_addon_register_func =
extern "C" fn(env: napi_env, exports: napi_value) -> napi_value;
#[repr(C)]
-#[derive(Debug, Clone)]
+#[derive(Clone)]
pub struct NapiModule {
pub nm_version: i32,
pub nm_flags: u32,
@@ -211,7 +215,10 @@ pub struct napi_type_tag {
}
pub type napi_callback = Option<
- unsafe extern "C" fn(env: napi_env, info: napi_callback_info) -> napi_value,
+ unsafe extern "C" fn(
+ env: napi_env,
+ info: napi_callback_info,
+ ) -> napi_value<'static>,
>;
pub type napi_finalize = unsafe extern "C" fn(
@@ -250,13 +257,13 @@ pub const napi_default_jsproperty: napi_property_attributes =
#[repr(C)]
#[derive(Copy, Clone, Debug)]
-pub struct napi_property_descriptor {
+pub struct napi_property_descriptor<'a> {
pub utf8name: *const c_char,
- pub name: napi_value,
+ pub name: napi_value<'a>,
pub method: napi_callback,
pub getter: napi_callback,
pub setter: napi_callback,
- pub value: napi_value,
+ pub value: napi_value<'a>,
pub attributes: napi_property_attributes,
pub data: *mut c_void,
}
diff --git a/ext/napi/value.rs b/ext/napi/value.rs
new file mode 100644
index 000000000..bb3966593
--- /dev/null
+++ b/ext/napi/value.rs
@@ -0,0 +1,58 @@
+// Copyright 2018-2022 the Deno authors. All rights reserved. MIT license.
+
+use deno_core::v8;
+use std::mem::transmute;
+use std::ops::Deref;
+use std::os::raw::c_void;
+use std::ptr::NonNull;
+
+/// An FFI-opaque, nullable wrapper around v8::Local<v8::Value>.
+/// rusty_v8 Local handle cannot be empty but napi_value can be.
+#[repr(transparent)]
+#[derive(Clone, Copy, Debug)]
+pub struct NapiValue<'s>(
+ Option<NonNull<v8::Value>>,
+ std::marker::PhantomData<&'s ()>,
+);
+
+pub type napi_value<'s> = NapiValue<'s>;
+
+impl<'s> Deref for napi_value<'s> {
+ type Target = Option<v8::Local<'s, v8::Value>>;
+ fn deref(&self) -> &Self::Target {
+ // SAFETY: It is safe to transmute `Option<NonNull<T>>` to `Option<*const T>`.
+ // v8::Local guarantees that *const T is not null but napi_value *can* be null.
+ unsafe { transmute::<&Self, &Self::Target>(self) }
+ }
+}
+
+impl<'s, T> From<v8::Local<'s, T>> for napi_value<'s>
+where
+ v8::Local<'s, T>: Into<v8::Local<'s, v8::Value>>,
+{
+ fn from(v: v8::Local<'s, T>) -> Self {
+ // SAFETY: It is safe to cast v8::Local<T> that implements Into<v8::Local<v8::Value>>.
+ // `fn into(self)` transmutes anyways.
+ Self(unsafe { transmute(v) }, std::marker::PhantomData)
+ }
+}
+
+const _: () = {
+ assert!(
+ std::mem::size_of::<napi_value>() == std::mem::size_of::<*mut c_void>()
+ );
+ // Assert "nullable pointer optimization" on napi_value
+ unsafe {
+ type Src<'a> = napi_value<'a>;
+ type Dst = usize;
+ assert!(std::mem::size_of::<Src>() == std::mem::size_of::<Dst>());
+ union Transmute<'a> {
+ src: Src<'a>,
+ dst: Dst,
+ }
+ Transmute {
+ src: NapiValue(None, std::marker::PhantomData),
+ }
+ .dst
+ };
+};