Skip to content

Commit

Permalink
feat(napi-derive): catch_unwind attribute
Browse files Browse the repository at this point in the history
  • Loading branch information
Brooooooklyn committed Aug 19, 2022
1 parent bc69e15 commit 97659e4
Show file tree
Hide file tree
Showing 12 changed files with 55 additions and 5 deletions.
1 change: 1 addition & 0 deletions crates/backend/src/ast.rs
Expand Up @@ -26,6 +26,7 @@ pub struct NapiFn {
pub writable: bool,
pub enumerable: bool,
pub configurable: bool,
pub catch_unwind: bool,
}

#[derive(Debug, Clone)]
Expand Down
14 changes: 14 additions & 0 deletions crates/backend/src/codegen/fn.rs
Expand Up @@ -69,6 +69,20 @@ impl TryToTokens for NapiFn {
}
};

let function_call = if self.catch_unwind {
quote! {
{
std::panic::catch_unwind(|| { #function_call })
.map_err(|e| napi::Error::new(napi::Status::GenericFailure, format!("{:?}", e)))
.and_then(|r| r)
}
}
} else {
quote! {
#function_call
}
};

(quote! {
#(#attrs)*
#[doc(hidden)]
Expand Down
1 change: 1 addition & 0 deletions crates/macro/src/parser/attrs.rs
Expand Up @@ -42,6 +42,7 @@ pub struct BindgenAttrs {
macro_rules! attrgen {
($mac:ident) => {
$mac! {
(catch_unwind, CatchUnwind(Span)),
(js_name, JsName(Span, String, Span)),
(constructor, Constructor(Span)),
(factory, Factory(Span)),
Expand Down
25 changes: 25 additions & 0 deletions crates/macro/src/parser/mod.rs
Expand Up @@ -695,6 +695,7 @@ fn napi_fn_from_decl(
writable: opts.writable(),
enumerable: opts.enumerable(),
configurable: opts.configurable(),
catch_unwind: opts.catch_unwind().is_some(),
}
})
}
Expand Down Expand Up @@ -747,6 +748,12 @@ impl ParseNapi for syn::ItemStruct {
"#[napi(return_if_invalid)] can only be applied to a function or method."
);
}
if opts.catch_unwind().is_some() {
bail_span!(
self,
"#[napi(catch_unwind)] can only be applied to a function or method."
);
}
if opts.object().is_some() && opts.custom_finalize().is_some() {
bail_span!(self, "Custom finalize is not supported for #[napi(object)]");
}
Expand Down Expand Up @@ -776,6 +783,12 @@ impl ParseNapi for syn::ItemImpl {
"#[napi(return_if_invalid)] can only be applied to a function or method."
);
}
if opts.catch_unwind().is_some() {
bail_span!(
self,
"#[napi(catch_unwind)] can only be applied to a function or method."
);
}
// #[napi] macro will be remove from impl items after converted to ast
let napi = self.convert_to_ast(opts);
self.to_tokens(tokens);
Expand All @@ -802,6 +815,12 @@ impl ParseNapi for syn::ItemEnum {
"#[napi(return_if_invalid)] can only be applied to a function or method."
);
}
if opts.catch_unwind().is_some() {
bail_span!(
self,
"#[napi(catch_unwind)] can only be applied to a function or method."
);
}
let napi = self.convert_to_ast(opts);
self.to_tokens(tokens);

Expand All @@ -826,6 +845,12 @@ impl ParseNapi for syn::ItemConst {
"#[napi(return_if_invalid)] can only be applied to a function or method."
);
}
if opts.catch_unwind().is_some() {
bail_span!(
self,
"#[napi(catch_unwind)] can only be applied to a function or method."
);
}
let napi = self.convert_to_ast(opts);
self.to_tokens(tokens);
napi
Expand Down
2 changes: 1 addition & 1 deletion crates/napi/src/bindgen_runtime/module_register.rs
Expand Up @@ -38,7 +38,7 @@ impl<T> PersistedSingleThreadVec<T> {
.inner
.lock()
.expect("Acquire persisted thread vec lock failed");
f(&mut *locked);
f(&mut locked);
}

fn push(&self, item: T) {
Expand Down
2 changes: 1 addition & 1 deletion crates/napi/src/env.rs
Expand Up @@ -854,7 +854,7 @@ impl Env {
))?;
let type_id = unknown_tagged_object as *const TypeId;
if *type_id == TypeId::of::<T>() {
Box::from_raw(unknown_tagged_object as *mut TaggedObject<T>);
drop(Box::from_raw(unknown_tagged_object as *mut TaggedObject<T>));
Ok(())
} else {
Err(Error::new(
Expand Down
1 change: 1 addition & 0 deletions examples/napi/__test__/typegen.spec.ts.md
Expand Up @@ -103,6 +103,7 @@ Generated by [AVA](https://avajs.dev).
}␊
export function enumToI32(e: CustomNumEnum): number␊
export function throwError(): void␊
export function panic(): void␊
export function createExternal(size: number): ExternalObject<number>␊
export function createExternalString(content: string): ExternalObject<string>␊
export function getExternal(external: ExternalObject<number>): number␊
Expand Down
Binary file modified examples/napi/__test__/typegen.spec.ts.snap
Binary file not shown.
4 changes: 3 additions & 1 deletion examples/napi/__test__/values.spec.ts
Expand Up @@ -31,6 +31,7 @@ import {
mapOption,
readFile,
throwError,
panic,
readPackageJson,
getPackageJsonName,
getBuffer,
Expand Down Expand Up @@ -163,7 +164,7 @@ test('enum', (t) => {
t.is(enumToI32(CustomNumEnum.Eight), 8)
})

test.only('class', (t) => {
test('class', (t) => {
const dog = new Animal(Kind.Dog, '旺财')

t.is(dog.name, '旺财')
Expand Down Expand Up @@ -371,6 +372,7 @@ test('Option', (t) => {

test('Result', (t) => {
t.throws(() => throwError(), void 0, 'Manual Error')
t.throws(() => panic(), void 0, `Don't panic`)
})

test('function ts type override', (t) => {
Expand Down
1 change: 1 addition & 0 deletions examples/napi/index.d.ts
Expand Up @@ -93,6 +93,7 @@ export const enum CustomNumEnum {
}
export function enumToI32(e: CustomNumEnum): number
export function throwError(): void
export function panic(): void
export function createExternal(size: number): ExternalObject<number>
export function createExternalString(content: string): ExternalObject<string>
export function getExternal(external: ExternalObject<number>): number
Expand Down
7 changes: 6 additions & 1 deletion examples/napi/src/error.rs
@@ -1,6 +1,11 @@
use napi::bindgen_prelude::*;

#[napi]
fn throw_error() -> Result<()> {
pub fn throw_error() -> Result<()> {
Err(Error::new(Status::InvalidArg, "Manual Error".to_owned()))
}

#[napi(catch_unwind)]
pub fn panic() {
panic!("Don't panic");
}
2 changes: 1 addition & 1 deletion examples/napi/src/lib.rs
@@ -1,6 +1,6 @@
#![allow(dead_code)]
#![allow(unreachable_code)]
#![allow(clippy::blacklisted_name)]
#![allow(clippy::disallowed_names)]

#[macro_use]
extern crate napi_derive;
Expand Down

1 comment on commit 97659e4

@github-actions
Copy link

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Benchmark

Benchmark suite Current: 97659e4 Previous: bc69e15 Ratio
noop#napi-rs 60426621 ops/sec (±0.36%) 59795184 ops/sec (±0.26%) 0.99
noop#JavaScript 595940093 ops/sec (±0.11%) 591426599 ops/sec (±0.85%) 0.99
Plus number#napi-rs 20560698 ops/sec (±0.69%) 20721781 ops/sec (±0.51%) 1.01
Plus number#JavaScript 594437491 ops/sec (±0.22%) 594960595 ops/sec (±0.08%) 1.00
Create buffer#napi-rs 427054 ops/sec (±7.03%) 436176 ops/sec (±7.38%) 1.02
Create buffer#JavaScript 1869852 ops/sec (±4.36%) 1582612 ops/sec (±49.38%) 0.85
createArray#createArrayJson 43096 ops/sec (±0.14%) 43174 ops/sec (±0.1%) 1.00
createArray#create array for loop 8067 ops/sec (±0.12%) 8070 ops/sec (±0.11%) 1.00
createArray#create array with serde trait 8016 ops/sec (±0.1%) 8018 ops/sec (±0.1%) 1.00
getArrayFromJs#get array from json string 17680 ops/sec (±0.15%) 17665 ops/sec (±0.14%) 1.00
getArrayFromJs#get array from serde 10767 ops/sec (±0.05%) 10792 ops/sec (±0.05%) 1.00
getArrayFromJs#get array with for loop 12611 ops/sec (±0.2%) 13157 ops/sec (±0.05%) 1.04
Get Set property#Get Set from native#u32 374182 ops/sec (±4.8%) 389557 ops/sec (±4.34%) 1.04
Get Set property#Get Set from JavaScript#u32 332581 ops/sec (±4.43%) 334551 ops/sec (±4.49%) 1.01
Get Set property#Get Set from native#string 351176 ops/sec (±4.7%) 361064 ops/sec (±4.31%) 1.03
Get Set property#Get Set from JavaScript#string 311788 ops/sec (±4.7%) 324569 ops/sec (±4.26%) 1.04
Async task#spawn task 36447 ops/sec (±0.82%) 36267 ops/sec (±0.98%) 1.00
Async task#ThreadSafeFunction 2445 ops/sec (±7.68%) 1992 ops/sec (±2.86%) 0.81
Async task#Tokio future to Promise 31065 ops/sec (±0.53%) 32020 ops/sec (±0.61%) 1.03
Query#query * 100 2194 ops/sec (±1.69%) 2196 ops/sec (±2.09%) 1.00
Query#query * 1 31988 ops/sec (±1.65%) 32783 ops/sec (±0.52%) 1.02

This comment was automatically generated by workflow using github-action-benchmark.

Please sign in to comment.