Skip to content

Commit 0304c23

Browse files
committed
handle panic in rust fn
1 parent dbe4a50 commit 0304c23

File tree

3 files changed

+33
-7
lines changed

3 files changed

+33
-7
lines changed

duk-derive/Cargo.toml

+3-3
Original file line numberDiff line numberDiff line change
@@ -14,6 +14,6 @@ repository = "https://github.com/dflemstr/duk"
1414
proc-macro = true
1515

1616
[dependencies]
17-
proc-macro2 = "1.0.18"
18-
quote = "1.0.6"
19-
syn = { version = "1.0.30", features = ["full", "extra-traits"] }
17+
proc-macro2 = "1.0.36"
18+
quote = "1.0.15"
19+
syn = { version = "1.0.86", features = ["full", "extra-traits"] }

duk-derive/src/lib.rs

+22-4
Original file line numberDiff line numberDiff line change
@@ -30,7 +30,7 @@ pub fn duktape_fn(_attr: TokenStream, mut item: TokenStream) -> TokenStream {
3030
duk::duk_sys::duk_push_error_object(
3131
ctx,
3232
duk::duk_sys::DUK_ERR_TYPE_ERROR as i32,
33-
std::ffi::CString::new(format!("{}", e)).into_raw(),
33+
std::ffi::CString::new(format!("{}", e)).unwrap_or_default().into_raw(),
3434
);
3535
duk::duk_sys::duk_throw_raw(ctx);
3636
return 0;
@@ -49,7 +49,7 @@ pub fn duktape_fn(_attr: TokenStream, mut item: TokenStream) -> TokenStream {
4949
duk::duk_sys::duk_push_error_object(
5050
ctx,
5151
duk::duk_sys::DUK_ERR_TYPE_ERROR as i32,
52-
std::ffi::CString::new(format!("{}", e)).into_raw(),
52+
std::ffi::CString::new(format!("{}", e)).unwrap_or_default().into_raw(),
5353
);
5454
duk::duk_sys::duk_throw_raw(ctx);
5555
0
@@ -74,9 +74,27 @@ pub fn duktape_fn(_attr: TokenStream, mut item: TokenStream) -> TokenStream {
7474
#(
7575
#args
7676
)*
77-
let res = fn_impl(#(
77+
let res = match std::panic::catch_unwind(|| fn_impl(#(
7878
#arg_names,
79-
)*);
79+
)*)) {
80+
Ok(res) => res,
81+
Err(e) => {
82+
let error = if let Some(msg) = e.downcast_ref::<&str>() {
83+
format!("panic: {}", *msg)
84+
} else if let Some(msg) = e.downcast_ref::<String>() {
85+
format!("panic: {}", msg)
86+
} else {
87+
"panic: unknown error".into()
88+
};
89+
duk::duk_sys::duk_push_error_object(
90+
ctx,
91+
duk::duk_sys::DUK_ERR_ERROR as i32,
92+
std::ffi::CString::new(error).unwrap_or_default().into_raw(),
93+
);
94+
duk::duk_sys::duk_throw_raw(ctx);
95+
return 0;
96+
}
97+
};
8098
#ret
8199
}
82100
}

src/lib.rs

+8
Original file line numberDiff line numberDiff line change
@@ -1468,6 +1468,11 @@ mod tests {
14681468
input
14691469
}
14701470

1471+
#[cfg_attr(feature = "derive", duktape_fn)]
1472+
fn test_rust_panic_fn() {
1473+
panic!("panicked successfully")
1474+
}
1475+
14711476
#[derive(Debug, serde::Deserialize, serde::Serialize, PartialEq)]
14721477
enum TestEnum {
14731478
A,
@@ -1497,6 +1502,7 @@ mod tests {
14971502

14981503
add_global_fn!(ctx, test_rust_fn);
14991504
add_global_fn!(ctx, test_rust_complex_fn);
1505+
add_global_fn!(ctx, test_rust_panic_fn);
15001506

15011507
let val = ctx.eval_string(r#"test_rust_fn(5.5)"#).unwrap().to_value();
15021508
assert_eq!(Value::String("test 5".to_owned()), val);
@@ -1534,5 +1540,7 @@ mod tests {
15341540
},
15351541
val
15361542
);
1543+
1544+
assert!(ctx.eval_string(r"test_rust_panic_fn()").is_err());
15371545
}
15381546
}

0 commit comments

Comments
 (0)