From efa9ba5892dd2ddc4953d456fa258bbb9aaab384 Mon Sep 17 00:00:00 2001 From: messense Date: Sun, 19 Jul 2020 16:54:10 +0800 Subject: [PATCH 1/2] Throw exception when Rust code panics --- napi-derive/src/lib.rs | 21 +++++++++++++++++++-- test_module/__test__/throw.spec.js | 4 ++++ test_module/src/lib.rs | 5 +++++ 3 files changed, 28 insertions(+), 2 deletions(-) diff --git a/napi-derive/src/lib.rs b/napi-derive/src/lib.rs index 69b7d475..963f92bc 100644 --- a/napi-derive/src/lib.rs +++ b/napi-derive/src/lib.rs @@ -89,8 +89,9 @@ pub fn js_function(attr: TokenStream, input: TokenStream) -> TokenStream { use std::mem; use std::os::raw::c_char; use std::ptr; + use std::panic::{self, AssertUnwindSafe}; use std::ffi::CString; - use napi::{JsUnknown, Env, Status, NapiValue, CallContext}; + use napi::{JsUnknown, Env, Error, Status, NapiValue, CallContext}; let mut argc = #arg_len_span as usize; let mut raw_args = unsafe { mem::MaybeUninit::<[napi::sys::napi_value; #arg_len_span as usize]>::uninit().assume_init() }; @@ -112,7 +113,23 @@ pub fn js_function(attr: TokenStream, input: TokenStream) -> TokenStream { let mut env = Env::from_raw(raw_env); let call_ctx = CallContext::new(&mut env, raw_this, &raw_args, #arg_len_span, argc as usize); - let result = call_ctx.and_then(|ctx| #new_fn_name(ctx)); + let result = call_ctx.and_then(|ctx| { + match panic::catch_unwind(AssertUnwindSafe(move || #new_fn_name(ctx))) { + Ok(result) => result, + Err(e) => { + let message = { + if let Some(string) = e.downcast_ref::() { + string.clone() + } else if let Some(string) = e.downcast_ref::<&str>() { + string.to_string() + } else { + format!("panic from Rust code: {:?}", e) + } + }; + Err(Error { status: Status::GenericFailure, reason: message }) + } + } + }); has_error = has_error && result.is_err(); match result { diff --git a/test_module/__test__/throw.spec.js b/test_module/__test__/throw.spec.js index 76a03546..461fbed4 100644 --- a/test_module/__test__/throw.spec.js +++ b/test_module/__test__/throw.spec.js @@ -14,3 +14,7 @@ test('should be able to throw error from native with reason', (t) => { test('should throw if argument type is not match', (t) => { t.throws(() => bindings.testThrowWithReason(2)) }) + +test('should throw if Rust code panic', (t) => { + t.throws(() => bindings.testThrowWithPanic()) +}) diff --git a/test_module/src/lib.rs b/test_module/src/lib.rs index 88297dd5..88c9a900 100644 --- a/test_module/src/lib.rs +++ b/test_module/src/lib.rs @@ -86,3 +86,8 @@ fn test_throw_with_reason(ctx: CallContext) -> Result { reason.as_str()?.to_owned(), )) } + +#[js_function] +pub fn test_throw_with_panic(_ctx: CallContext) -> Result { + panic!("don't panic."); +} From e7a8cbf26bf0a384f0701c9ee7bb377da084473e Mon Sep 17 00:00:00 2001 From: messense Date: Sun, 19 Jul 2020 17:29:47 +0800 Subject: [PATCH 2/2] Rename napi_rs to napi --- napi-derive/README.md | 4 ++-- napi/src/threadsafe_function.rs | 6 +++--- 2 files changed, 5 insertions(+), 5 deletions(-) diff --git a/napi-derive/README.md b/napi-derive/README.md index 6e663dfd..63ae9338 100644 --- a/napi-derive/README.md +++ b/napi-derive/README.md @@ -4,9 +4,9 @@ ```rust #[macro_use] -extern crate napi_rs as napi; +extern crate napi; #[macro_use] -extern crate napi_rs_derive; +extern crate napi_derive; use napi::{CallContext, Error, JsNumber, JsUnknown, Module, Result, Status}; use std::convert::TryInto; diff --git a/napi/src/threadsafe_function.rs b/napi/src/threadsafe_function.rs index 4a84dae4..2083eee2 100644 --- a/napi/src/threadsafe_function.rs +++ b/napi/src/threadsafe_function.rs @@ -20,10 +20,10 @@ pub trait ToJs: Copy + Clone { /// /// ``` /// #[macro_use] -/// extern crate napi_rs_derive; +/// extern crate napi_derive; /// /// use std::thread; -/// use napi_rs::{ +/// use napi::{ /// Number, Result, Env, CallContext, JsUndefined, JsFunction, /// sys::{ /// napi_threadsafe_function_call_mode::{ @@ -34,7 +34,7 @@ pub trait ToJs: Copy + Clone { /// } /// } /// }; -/// use napi_rs::threadsafe_function::{ +/// use napi::threadsafe_function::{ /// ToJs, ThreadsafeFunction, /// }; ///