chore(napi): enhance the error messages while converting types failed (#1473)
This commit is contained in:
parent
f1838a7b32
commit
7613d669fb
12 changed files with 161 additions and 15 deletions
crates/napi/src
|
@ -39,7 +39,7 @@ impl FromNapiValue for String {
|
|||
unsafe { sys::napi_get_value_string_utf8(env, napi_val, ptr::null_mut(), 0, &mut len) },
|
||||
env,
|
||||
napi_val,
|
||||
"Failed to convert napi `{}` into rust type `String`"
|
||||
"Failed to convert JavaScript value `{}` into rust type `String`"
|
||||
)?;
|
||||
|
||||
// end char len in C
|
||||
|
@ -106,7 +106,7 @@ impl FromNapiValue for &str {
|
|||
},
|
||||
env,
|
||||
napi_val,
|
||||
"Failed to convert napi `{}` into rust type `String`"
|
||||
"Failed to convert JavaScript value `{}` into rust type `String`"
|
||||
)?;
|
||||
|
||||
// The `&str` should only be accepted from function arguments.
|
||||
|
|
|
@ -369,11 +369,49 @@ macro_rules! check_status_and_type {
|
|||
match c {
|
||||
$crate::sys::Status::napi_ok => Ok(()),
|
||||
_ => {
|
||||
use $crate::js_values::NapiValue;
|
||||
let value_type = $crate::type_of!($env, $val)?;
|
||||
Err($crate::Error::new(
|
||||
$crate::Status::from(c),
|
||||
format!($msg, value_type),
|
||||
))
|
||||
let error_msg = match value_type {
|
||||
ValueType::Function => {
|
||||
let function_name = unsafe { JsFunction::from_raw_unchecked($env, $val).name()? };
|
||||
format!(
|
||||
$msg,
|
||||
format!(
|
||||
"function {}(..) ",
|
||||
if function_name.len() == 0 {
|
||||
"anonymous".to_owned()
|
||||
} else {
|
||||
function_name
|
||||
}
|
||||
)
|
||||
)
|
||||
}
|
||||
ValueType::Object => {
|
||||
let env_ = $crate::Env::from($env);
|
||||
let json: $crate::JSON = env_.get_global()?.get_named_property_unchecked("JSON")?;
|
||||
let object = json.stringify($crate::JsObject($crate::Value {
|
||||
value: $val,
|
||||
env: $env,
|
||||
value_type: ValueType::Object,
|
||||
}))?;
|
||||
format!($msg, format!("Object {}", object))
|
||||
}
|
||||
ValueType::Boolean | ValueType::Number => {
|
||||
let value =
|
||||
unsafe { $crate::JsUnknown::from_raw_unchecked($env, $val).coerce_to_string()? }
|
||||
.into_utf8()?;
|
||||
format!($msg, format!("{} {} ", value_type, value.as_str()?))
|
||||
}
|
||||
#[cfg(feature = "napi6")]
|
||||
ValueType::BigInt => {
|
||||
let value =
|
||||
unsafe { $crate::JsUnknown::from_raw_unchecked($env, $val).coerce_to_string()? }
|
||||
.into_utf8()?;
|
||||
format!($msg, format!("{} {} ", value_type, value.as_str()?))
|
||||
}
|
||||
_ => format!($msg, value_type),
|
||||
};
|
||||
Err($crate::Error::new($crate::Status::from(c), error_msg))
|
||||
}
|
||||
}
|
||||
}};
|
||||
|
|
|
@ -1,12 +1,12 @@
|
|||
use std::ptr;
|
||||
|
||||
use super::Value;
|
||||
use crate::bindgen_runtime::TypeName;
|
||||
#[cfg(feature = "napi4")]
|
||||
use crate::{
|
||||
bindgen_runtime::ToNapiValue,
|
||||
threadsafe_function::{ThreadSafeCallContext, ThreadsafeFunction},
|
||||
};
|
||||
use crate::{bindgen_runtime::TypeName, JsString};
|
||||
use crate::{check_pending_exception, ValueType};
|
||||
use crate::{sys, Env, Error, JsObject, JsUnknown, NapiRaw, NapiValue, Result, Status};
|
||||
|
||||
|
@ -122,6 +122,21 @@ impl JsFunction {
|
|||
Ok(unsafe { JsObject::from_raw_unchecked(self.0.env, js_instance) })
|
||||
}
|
||||
|
||||
/// function name
|
||||
pub fn name(&self) -> Result<String> {
|
||||
let mut name = ptr::null_mut();
|
||||
check_pending_exception!(self.0.env, unsafe {
|
||||
sys::napi_get_named_property(
|
||||
self.0.env,
|
||||
self.0.value,
|
||||
"name\0".as_ptr().cast(),
|
||||
&mut name,
|
||||
)
|
||||
})?;
|
||||
let name_value = unsafe { JsString::from_raw_unchecked(self.0.env, name) };
|
||||
Ok(name_value.into_utf8()?.as_str()?.to_owned())
|
||||
}
|
||||
|
||||
#[cfg(feature = "napi4")]
|
||||
pub fn create_threadsafe_function<T, V, F, ES>(
|
||||
&self,
|
||||
|
|
|
@ -1,12 +1,34 @@
|
|||
use std::convert::TryInto;
|
||||
|
||||
use super::*;
|
||||
use crate::Env;
|
||||
use crate::{bindgen_runtime::FromNapiValue, Env};
|
||||
|
||||
pub struct JsGlobal(pub(crate) Value);
|
||||
|
||||
pub struct JsTimeout(pub(crate) Value);
|
||||
|
||||
pub struct JSON(pub(crate) Value);
|
||||
|
||||
impl FromNapiValue for JSON {
|
||||
unsafe fn from_napi_value(env: sys::napi_env, napi_val: sys::napi_value) -> Result<Self> {
|
||||
Ok(JSON(Value {
|
||||
env,
|
||||
value: napi_val,
|
||||
value_type: ValueType::Object,
|
||||
}))
|
||||
}
|
||||
}
|
||||
|
||||
impl JSON {
|
||||
pub fn stringify<V: NapiRaw>(&self, value: V) -> Result<std::string::String> {
|
||||
let func: JsFunction = self.get_named_property_unchecked("stringify")?;
|
||||
let result = func
|
||||
.call(None, &[value])
|
||||
.map(|ret| unsafe { ret.cast::<JsString>() })?;
|
||||
result.into_utf8()?.as_str().map(|s| s.to_owned())
|
||||
}
|
||||
}
|
||||
|
||||
impl JsGlobal {
|
||||
pub fn set_interval(&self, handler: JsFunction, interval: f64) -> Result<JsTimeout> {
|
||||
let func: JsFunction = self.get_named_property_unchecked("setInterval")?;
|
||||
|
|
|
@ -3,7 +3,7 @@ use std::ffi::CString;
|
|||
use std::ptr;
|
||||
|
||||
use crate::{
|
||||
bindgen_runtime::{TypeName, ValidateNapiValue},
|
||||
bindgen_runtime::{FromNapiValue, TypeName, ValidateNapiValue},
|
||||
check_status, sys, type_of, Callback, Error, Result, Status, ValueType,
|
||||
};
|
||||
|
||||
|
@ -337,26 +337,26 @@ macro_rules! impl_object_methods {
|
|||
|
||||
pub fn get_named_property<T>(&self, name: &str) -> Result<T>
|
||||
where
|
||||
T: NapiValue,
|
||||
T: FromNapiValue,
|
||||
{
|
||||
let key = CString::new(name)?;
|
||||
let mut raw_value = ptr::null_mut();
|
||||
check_status!(unsafe {
|
||||
sys::napi_get_named_property(self.0.env, self.0.value, key.as_ptr(), &mut raw_value)
|
||||
})?;
|
||||
unsafe { T::from_raw(self.0.env, raw_value) }
|
||||
unsafe { <T as FromNapiValue>::from_napi_value(self.0.env, raw_value) }
|
||||
}
|
||||
|
||||
pub fn get_named_property_unchecked<T>(&self, name: &str) -> Result<T>
|
||||
where
|
||||
T: NapiValue,
|
||||
T: FromNapiValue,
|
||||
{
|
||||
let key = CString::new(name)?;
|
||||
let mut raw_value = ptr::null_mut();
|
||||
check_status!(unsafe {
|
||||
sys::napi_get_named_property(self.0.env, self.0.value, key.as_ptr(), &mut raw_value)
|
||||
})?;
|
||||
Ok(unsafe { T::from_raw_unchecked(self.0.env, raw_value) })
|
||||
unsafe { <T as FromNapiValue>::from_napi_value(self.0.env, raw_value) }
|
||||
}
|
||||
|
||||
pub fn has_named_property(&self, name: &str) -> Result<bool> {
|
||||
|
@ -618,6 +618,7 @@ impl_js_value_methods!(JsFunction);
|
|||
impl_js_value_methods!(JsExternal);
|
||||
impl_js_value_methods!(JsSymbol);
|
||||
impl_js_value_methods!(JsTimeout);
|
||||
impl_js_value_methods!(JSON);
|
||||
|
||||
impl_object_methods!(JsObject);
|
||||
impl_object_methods!(JsBuffer);
|
||||
|
@ -625,6 +626,7 @@ impl_object_methods!(JsArrayBuffer);
|
|||
impl_object_methods!(JsTypedArray);
|
||||
impl_object_methods!(JsDataView);
|
||||
impl_object_methods!(JsGlobal);
|
||||
impl_object_methods!(JSON);
|
||||
|
||||
use ValueType::*;
|
||||
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue