refactor(napi): split NapiRaw trait from NapiValue
This commit is contained in:
parent
ba1d16759f
commit
d4331e05df
9 changed files with 120 additions and 31 deletions
|
@ -96,7 +96,7 @@ pub fn js_function(attr: TokenStream, input: TokenStream) -> TokenStream {
|
|||
use std::ptr;
|
||||
use std::panic::{self, AssertUnwindSafe};
|
||||
use std::ffi::CString;
|
||||
use napi::{Env, Error, Status, NapiValue, CallContext};
|
||||
use napi::{Env, Error, Status, NapiValue, NapiRaw, CallContext};
|
||||
let mut argc = #arg_len_span as usize;
|
||||
let mut raw_args: [napi::sys::napi_value; #arg_len_span] = [ptr::null_mut(); #arg_len_span];
|
||||
let mut raw_this = ptr::null_mut();
|
||||
|
@ -145,7 +145,7 @@ pub fn contextless_function(_attr: TokenStream, input: TokenStream) -> TokenStre
|
|||
use std::ptr;
|
||||
use std::panic::{self, AssertUnwindSafe};
|
||||
use std::ffi::CString;
|
||||
use napi::{Env, NapiValue, Error, Status};
|
||||
use napi::{Env, NapiValue, NapiRaw, Error, Status};
|
||||
|
||||
let ctx = unsafe { Env::from_raw(raw_env) };
|
||||
#execute_js_function
|
||||
|
@ -227,7 +227,7 @@ pub fn module_exports(_attr: TokenStream, input: TokenStream) -> TokenStream {
|
|||
) -> napi::sys::napi_value {
|
||||
use std::ffi::CString;
|
||||
use std::ptr;
|
||||
use napi::{Env, JsObject, NapiValue};
|
||||
use napi::{Env, JsObject, NapiValue, NapiRaw};
|
||||
|
||||
#[cfg(all(feature = "tokio_rt", feature = "napi4"))]
|
||||
use napi::shutdown_tokio_rt;
|
||||
|
|
|
@ -2,7 +2,11 @@ use std::mem;
|
|||
use std::os::raw::{c_char, c_void};
|
||||
use std::ptr;
|
||||
|
||||
use crate::{check_status, js_values::NapiValue, sys, Env, JsError, JsObject, Result, Task};
|
||||
use crate::{
|
||||
check_status,
|
||||
js_values::{NapiRaw, NapiValue},
|
||||
sys, Env, JsError, JsObject, Result, Task,
|
||||
};
|
||||
|
||||
struct AsyncWork<T: Task> {
|
||||
inner_task: T,
|
||||
|
|
|
@ -123,11 +123,19 @@ impl JsBigint {
|
|||
}
|
||||
}
|
||||
|
||||
impl NapiValue for JsBigint {
|
||||
impl NapiRaw for JsBigint {
|
||||
unsafe fn raw(&self) -> sys::napi_value {
|
||||
self.raw.value
|
||||
}
|
||||
}
|
||||
|
||||
impl<'env> NapiRaw for &'env JsBigint {
|
||||
unsafe fn raw(&self) -> sys::napi_value {
|
||||
self.raw.value
|
||||
}
|
||||
}
|
||||
|
||||
impl NapiValue for JsBigint {
|
||||
unsafe fn from_raw(env: sys::napi_env, value: sys::napi_value) -> Result<Self> {
|
||||
let mut word_count = 0usize;
|
||||
check_status!(sys::napi_get_value_bigint_words(
|
||||
|
|
|
@ -1,4 +1,4 @@
|
|||
use crate::{sys, JsUndefined, NapiValue, Result};
|
||||
use crate::{sys, JsUndefined, NapiRaw, NapiValue, Result};
|
||||
|
||||
#[derive(Debug, Clone, Copy)]
|
||||
pub enum Either<A: NapiValue, B: NapiValue> {
|
||||
|
@ -25,7 +25,9 @@ impl<A: NapiValue, B: NapiValue> NapiValue for Either<A, B> {
|
|||
unsafe fn from_raw_unchecked(env: sys::napi_env, value: sys::napi_value) -> Either<A, B> {
|
||||
Self::from_raw(env, value).unwrap()
|
||||
}
|
||||
}
|
||||
|
||||
impl<A: NapiValue, B: NapiValue> NapiRaw for Either<A, B> {
|
||||
unsafe fn raw(&self) -> sys::napi_value {
|
||||
match self {
|
||||
Either::A(v) => v.raw(),
|
||||
|
|
|
@ -2,7 +2,7 @@ use std::ops::Deref;
|
|||
use std::ptr;
|
||||
|
||||
use crate::check_status;
|
||||
use crate::{sys, Env, NapiValue, Result};
|
||||
use crate::{sys, Env, NapiRaw, NapiValue, Result};
|
||||
|
||||
pub struct EscapableHandleScope<T: NapiValue> {
|
||||
handle_scope: sys::napi_escapable_handle_scope,
|
||||
|
@ -16,7 +16,7 @@ impl<T: NapiValue> EscapableHandleScope<T> {
|
|||
check_status!(unsafe { sys::napi_open_escapable_handle_scope(env, &mut handle_scope) })?;
|
||||
let mut result = ptr::null_mut();
|
||||
check_status!(unsafe {
|
||||
sys::napi_escape_handle(env, handle_scope, NapiValue::raw(&value), &mut result)
|
||||
sys::napi_escape_handle(env, handle_scope, NapiRaw::raw(&value), &mut result)
|
||||
})?;
|
||||
Ok(Self {
|
||||
value,
|
||||
|
|
|
@ -2,7 +2,7 @@ use std::ptr;
|
|||
|
||||
use super::Value;
|
||||
use crate::check_status;
|
||||
use crate::{sys, Env, Error, JsObject, JsUnknown, NapiValue, Result, Status};
|
||||
use crate::{sys, Env, Error, JsObject, JsUnknown, NapiRaw, NapiValue, Result, Status};
|
||||
|
||||
pub struct JsFunction(pub(crate) Value);
|
||||
|
||||
|
@ -23,7 +23,10 @@ pub struct JsFunction(pub(crate) Value);
|
|||
impl JsFunction {
|
||||
/// [napi_call_function](https://nodejs.org/api/n-api.html#n_api_napi_call_function)
|
||||
#[inline]
|
||||
pub fn call(&self, this: Option<&JsObject>, args: &[JsUnknown]) -> Result<JsUnknown> {
|
||||
pub fn call<V>(&self, this: Option<&JsObject>, args: &[V]) -> Result<JsUnknown>
|
||||
where
|
||||
V: NapiRaw,
|
||||
{
|
||||
let raw_this = this
|
||||
.map(|v| unsafe { v.raw() })
|
||||
.or_else(|| {
|
||||
|
@ -35,7 +38,7 @@ impl JsFunction {
|
|||
.ok_or_else(|| Error::new(Status::GenericFailure, "Get raw this failed".to_owned()))?;
|
||||
let raw_args = args
|
||||
.iter()
|
||||
.map(|arg| arg.0.value)
|
||||
.map(|arg| unsafe { arg.raw() })
|
||||
.collect::<Vec<sys::napi_value>>();
|
||||
let mut return_value = ptr::null_mut();
|
||||
check_status!(unsafe {
|
||||
|
@ -52,6 +55,34 @@ impl JsFunction {
|
|||
unsafe { JsUnknown::from_raw(self.0.env, return_value) }
|
||||
}
|
||||
|
||||
/// [napi_call_function](https://nodejs.org/api/n-api.html#n_api_napi_call_function)
|
||||
/// The same with `call`, but without arguments
|
||||
#[inline]
|
||||
pub fn call_without_args(&self, this: Option<&JsObject>) -> Result<JsUnknown> {
|
||||
let raw_this = this
|
||||
.map(|v| unsafe { v.raw() })
|
||||
.or_else(|| {
|
||||
unsafe { Env::from_raw(self.0.env) }
|
||||
.get_undefined()
|
||||
.ok()
|
||||
.map(|u| unsafe { u.raw() })
|
||||
})
|
||||
.ok_or_else(|| Error::new(Status::GenericFailure, "Get raw this failed".to_owned()))?;
|
||||
let mut return_value = ptr::null_mut();
|
||||
check_status!(unsafe {
|
||||
sys::napi_call_function(
|
||||
self.0.env,
|
||||
raw_this,
|
||||
self.0.value,
|
||||
0,
|
||||
ptr::null_mut(),
|
||||
&mut return_value,
|
||||
)
|
||||
})?;
|
||||
|
||||
unsafe { JsUnknown::from_raw(self.0.env, return_value) }
|
||||
}
|
||||
|
||||
/// https://nodejs.org/api/n-api.html#n_api_napi_new_instance
|
||||
///
|
||||
/// This method is used to instantiate a new `JavaScript` value using a given `JsFunction` that represents the constructor for the object.
|
||||
|
|
|
@ -101,10 +101,6 @@ macro_rules! impl_napi_value_trait {
|
|||
}
|
||||
}
|
||||
|
||||
unsafe fn raw(&self) -> sys::napi_value {
|
||||
self.0.value
|
||||
}
|
||||
|
||||
unsafe fn from_raw_unchecked(env: sys::napi_env, value: sys::napi_value) -> $js_value {
|
||||
$js_value(Value {
|
||||
env,
|
||||
|
@ -114,6 +110,18 @@ macro_rules! impl_napi_value_trait {
|
|||
}
|
||||
}
|
||||
|
||||
impl NapiRaw for $js_value {
|
||||
unsafe fn raw(&self) -> sys::napi_value {
|
||||
self.0.value
|
||||
}
|
||||
}
|
||||
|
||||
impl<'env> NapiRaw for &'env $js_value {
|
||||
unsafe fn raw(&self) -> sys::napi_value {
|
||||
self.0.value
|
||||
}
|
||||
}
|
||||
|
||||
impl TryFrom<JsUnknown> for $js_value {
|
||||
type Error = Error;
|
||||
fn try_from(value: JsUnknown) -> Result<$js_value> {
|
||||
|
@ -221,7 +229,10 @@ macro_rules! impl_js_value_methods {
|
|||
}
|
||||
|
||||
#[inline]
|
||||
pub fn instanceof<Constructor: NapiValue>(&self, constructor: Constructor) -> Result<bool> {
|
||||
pub fn instanceof<Constructor>(&self, constructor: Constructor) -> Result<bool>
|
||||
where
|
||||
Constructor: NapiRaw,
|
||||
{
|
||||
let mut result = false;
|
||||
check_status!(unsafe {
|
||||
sys::napi_instanceof(self.0.env, self.0.value, constructor.raw(), &mut result)
|
||||
|
@ -238,7 +249,7 @@ macro_rules! impl_object_methods {
|
|||
#[inline]
|
||||
pub fn set_property<V>(&mut self, key: JsString, value: V) -> Result<()>
|
||||
where
|
||||
V: NapiValue,
|
||||
V: NapiRaw,
|
||||
{
|
||||
check_status!(unsafe {
|
||||
sys::napi_set_property(self.0.env, self.0.value, key.0.value, value.raw())
|
||||
|
@ -246,9 +257,9 @@ macro_rules! impl_object_methods {
|
|||
}
|
||||
|
||||
#[inline]
|
||||
pub fn get_property<K, T>(&self, key: &K) -> Result<T>
|
||||
pub fn get_property<K, T>(&self, key: K) -> Result<T>
|
||||
where
|
||||
K: NapiValue,
|
||||
K: NapiRaw,
|
||||
T: NapiValue,
|
||||
{
|
||||
let mut raw_value = ptr::null_mut();
|
||||
|
@ -259,9 +270,9 @@ macro_rules! impl_object_methods {
|
|||
}
|
||||
|
||||
#[inline]
|
||||
pub fn get_property_unchecked<K, T>(&self, key: &K) -> Result<T>
|
||||
pub fn get_property_unchecked<K, T>(&self, key: K) -> Result<T>
|
||||
where
|
||||
K: NapiValue,
|
||||
K: NapiRaw,
|
||||
T: NapiValue,
|
||||
{
|
||||
let mut raw_value = ptr::null_mut();
|
||||
|
@ -274,7 +285,7 @@ macro_rules! impl_object_methods {
|
|||
#[inline]
|
||||
pub fn set_named_property<T>(&mut self, name: &str, value: T) -> Result<()>
|
||||
where
|
||||
T: NapiValue,
|
||||
T: NapiRaw,
|
||||
{
|
||||
let key = CString::new(name)?;
|
||||
check_status!(unsafe {
|
||||
|
@ -341,7 +352,7 @@ macro_rules! impl_object_methods {
|
|||
#[inline]
|
||||
pub fn delete_property<S>(&mut self, name: S) -> Result<bool>
|
||||
where
|
||||
S: NapiValue,
|
||||
S: NapiRaw,
|
||||
{
|
||||
let mut result = false;
|
||||
check_status!(unsafe {
|
||||
|
@ -381,7 +392,7 @@ macro_rules! impl_object_methods {
|
|||
#[inline]
|
||||
pub fn has_own_property_js<K>(&self, key: K) -> Result<bool>
|
||||
where
|
||||
K: NapiValue,
|
||||
K: NapiRaw,
|
||||
{
|
||||
let mut result = false;
|
||||
check_status!(unsafe {
|
||||
|
@ -407,7 +418,7 @@ macro_rules! impl_object_methods {
|
|||
#[inline]
|
||||
pub fn has_property_js<K>(&self, name: K) -> Result<bool>
|
||||
where
|
||||
K: NapiValue,
|
||||
K: NapiRaw,
|
||||
{
|
||||
let mut result = false;
|
||||
check_status!(unsafe {
|
||||
|
@ -473,7 +484,7 @@ macro_rules! impl_object_methods {
|
|||
#[inline]
|
||||
pub fn set_element<T>(&mut self, index: u32, value: T) -> Result<()>
|
||||
where
|
||||
T: NapiValue,
|
||||
T: NapiRaw,
|
||||
{
|
||||
check_status!(unsafe {
|
||||
sys::napi_set_element(self.0.env, self.0.value, index, value.raw())
|
||||
|
@ -565,15 +576,17 @@ macro_rules! impl_object_methods {
|
|||
};
|
||||
}
|
||||
|
||||
pub trait NapiValue: Sized {
|
||||
pub trait NapiRaw {
|
||||
#[allow(clippy::missing_safety_doc)]
|
||||
unsafe fn raw(&self) -> sys::napi_value;
|
||||
}
|
||||
|
||||
pub trait NapiValue: Sized + NapiRaw {
|
||||
#[allow(clippy::missing_safety_doc)]
|
||||
unsafe fn from_raw(env: sys::napi_env, value: sys::napi_value) -> Result<Self>;
|
||||
|
||||
#[allow(clippy::missing_safety_doc)]
|
||||
unsafe fn from_raw_unchecked(env: sys::napi_env, value: sys::napi_value) -> Self;
|
||||
|
||||
#[allow(clippy::missing_safety_doc)]
|
||||
unsafe fn raw(&self) -> sys::napi_value;
|
||||
}
|
||||
|
||||
impl_js_value_methods!(JsUnknown);
|
||||
|
@ -640,7 +653,17 @@ impl NapiValue for JsUnknown {
|
|||
value_type: Unknown,
|
||||
})
|
||||
}
|
||||
}
|
||||
|
||||
impl NapiRaw for JsUnknown {
|
||||
/// get raw js value ptr
|
||||
#[inline]
|
||||
unsafe fn raw(&self) -> sys::napi_value {
|
||||
self.0.value
|
||||
}
|
||||
}
|
||||
|
||||
impl<'env> NapiRaw for &'env JsUnknown {
|
||||
/// get raw js value ptr
|
||||
#[inline]
|
||||
unsafe fn raw(&self) -> sys::napi_value {
|
||||
|
|
|
@ -8,6 +8,12 @@ test('should call the function', (t) => {
|
|||
})
|
||||
})
|
||||
|
||||
test('should call function with ref args', (t) => {
|
||||
bindings.testCallFunctionWithRefArguments((arg1: string, arg2: string) => {
|
||||
t.is(`${arg1} ${arg2}`, 'hello world')
|
||||
})
|
||||
})
|
||||
|
||||
test('should set "this" properly', (t) => {
|
||||
const obj = {}
|
||||
bindings.testCallFunctionWithThis.call(obj, function (this: typeof obj) {
|
||||
|
|
|
@ -11,18 +11,33 @@ pub fn call_function(ctx: CallContext) -> Result<JsNull> {
|
|||
ctx.env.get_null()
|
||||
}
|
||||
|
||||
#[js_function(1)]
|
||||
pub fn call_function_with_ref_arguments(ctx: CallContext) -> Result<JsNull> {
|
||||
let js_func = ctx.get::<JsFunction>(0)?;
|
||||
let js_string_hello = ctx.env.create_string("hello".as_ref())?;
|
||||
let js_string_world = ctx.env.create_string("world".as_ref())?;
|
||||
|
||||
js_func.call(None, &[&js_string_hello, &js_string_world])?;
|
||||
|
||||
ctx.env.get_null()
|
||||
}
|
||||
|
||||
#[js_function(1)]
|
||||
pub fn call_function_with_this(ctx: CallContext) -> Result<JsNull> {
|
||||
let js_this: JsObject = ctx.this_unchecked();
|
||||
let js_func = ctx.get::<JsFunction>(0)?;
|
||||
|
||||
js_func.call(Some(&js_this), &[])?;
|
||||
js_func.call_without_args(Some(&js_this))?;
|
||||
|
||||
ctx.env.get_null()
|
||||
}
|
||||
|
||||
pub fn register_js(exports: &mut JsObject) -> Result<()> {
|
||||
exports.create_named_method("testCallFunction", call_function)?;
|
||||
exports.create_named_method(
|
||||
"testCallFunctionWithRefArguments",
|
||||
call_function_with_ref_arguments,
|
||||
)?;
|
||||
exports.create_named_method("testCallFunctionWithThis", call_function_with_this)?;
|
||||
Ok(())
|
||||
}
|
||||
|
|
Loading…
Reference in a new issue