From 3dde26bcef162cc1e29305aef4803f9a34fbc748 Mon Sep 17 00:00:00 2001 From: LongYinan Date: Mon, 24 Oct 2022 00:16:30 +0800 Subject: [PATCH] chore(napi): including type message in error message (#1350) --- .../src/bindgen_runtime/js_values/string.rs | 26 ++++++++++++------- crates/napi/src/error.rs | 26 +++++++++++++++++++ examples/napi/__test__/values.spec.ts | 2 +- 3 files changed, 44 insertions(+), 10 deletions(-) diff --git a/crates/napi/src/bindgen_runtime/js_values/string.rs b/crates/napi/src/bindgen_runtime/js_values/string.rs index 9fb4635a..0bf6cd5b 100644 --- a/crates/napi/src/bindgen_runtime/js_values/string.rs +++ b/crates/napi/src/bindgen_runtime/js_values/string.rs @@ -1,4 +1,4 @@ -use crate::{bindgen_prelude::*, check_status, sys, Error, Result, Status}; +use crate::{bindgen_prelude::*, check_status, check_status_and_type, sys, Error, Result, Status}; use std::ffi::{c_void, CStr}; use std::fmt::Display; @@ -35,9 +35,11 @@ impl FromNapiValue for String { unsafe fn from_napi_value(env: sys::napi_env, napi_val: sys::napi_value) -> Result { let mut len = 0; - check_status!( + check_status_and_type!( unsafe { sys::napi_get_value_string_utf8(env, napi_val, ptr::null_mut(), 0, &mut len) }, - "Failed to convert napi `string` into rust type `String`", + env, + napi_val, + "Failed to convert napi `{}` into rust type `String`" )?; // end char len in C @@ -47,11 +49,13 @@ impl FromNapiValue for String { let mut written_char_count = 0; - check_status!( + check_status_and_type!( unsafe { sys::napi_get_value_string_utf8(env, napi_val, buf_ptr, len, &mut written_char_count) }, - "Failed to convert napi `string` into rust type `String`" + env, + napi_val, + "Failed to convert napi `{}` into rust type `String`" )?; let mut ret = mem::ManuallyDrop::new(ret); @@ -83,9 +87,11 @@ impl FromNapiValue for &str { unsafe fn from_napi_value(env: sys::napi_env, napi_val: sys::napi_value) -> Result { let mut len = 0; - check_status!( + check_status_and_type!( unsafe { sys::napi_get_value_string_utf8(env, napi_val, ptr::null_mut(), 0, &mut len) }, - "Failed to convert napi `string` into rust type `String`", + env, + napi_val, + "Failed to convert napi `{}` into rust type `String`" )?; // end char len in C @@ -94,11 +100,13 @@ impl FromNapiValue for &str { let buf_ptr = ret.as_mut_ptr(); let mut written_char_count = 0; - check_status!( + check_status_and_type!( unsafe { sys::napi_get_value_string_utf8(env, napi_val, buf_ptr, len, &mut written_char_count) }, - "Failed to convert napi `string` into rust type `String`" + env, + napi_val, + "Failed to convert napi `{}` into rust type `String`" )?; // The `&str` should only be accepted from function arguments. diff --git a/crates/napi/src/error.rs b/crates/napi/src/error.rs index 019e3822..98a4cd4b 100644 --- a/crates/napi/src/error.rs +++ b/crates/napi/src/error.rs @@ -351,6 +351,32 @@ macro_rules! check_status { _ => Err($crate::Error::new($crate::Status::from(c), format!($($msg)*))), } }}; + + ($code:expr, $msg:expr, $env:expr, $val:expr) => {{ + let c = $code; + match c { + $crate::sys::Status::napi_ok => Ok(()), + _ => Err($crate::Error::new($crate::Status::from(c), format!($msg, $crate::type_of!($env, $val)?))), + } + }}; +} + +#[doc(hidden)] +#[macro_export] +macro_rules! check_status_and_type { + ($code:expr, $env:ident, $val:ident, $msg:expr) => {{ + let c = $code; + match c { + $crate::sys::Status::napi_ok => Ok(()), + _ => { + let value_type = $crate::type_of!($env, $val)?; + Err($crate::Error::new( + $crate::Status::from(c), + format!($msg, value_type), + )) + } + } + }}; } #[doc(hidden)] diff --git a/examples/napi/__test__/values.spec.ts b/examples/napi/__test__/values.spec.ts index d4f7fe51..6dcbedf3 100644 --- a/examples/napi/__test__/values.spec.ts +++ b/examples/napi/__test__/values.spec.ts @@ -414,7 +414,7 @@ test('option object', (t) => { test('should throw if object type is not matched', (t) => { // @ts-expect-error const err1 = t.throws(() => receiveStrictObject({ name: 1 })) - t.is(err1!.message, 'Failed to convert napi `string` into rust type `String`') + t.is(err1!.message, 'Failed to convert napi `Number` into rust type `String`') // @ts-expect-error const err2 = t.throws(() => receiveStrictObject({ bar: 1 })) t.is(err2!.message, 'Missing field `name`')