fix(napi-derive): catch_unwind on constructor (#1869)

- Close https://github.com/napi-rs/napi-rs/issues/1852
This commit is contained in:
LongYinan 2023-12-27 12:49:10 +08:00 committed by GitHub
parent b411b87872
commit 02dd4c3fd3
No known key found for this signature in database
GPG key ID: 4AEE18F83AFDEB23
7 changed files with 67 additions and 3 deletions

View file

@ -2,6 +2,7 @@ name: Zig-Cross-Compile
env:
DEBUG: 'napi:*'
TEST_ZIG_CROSS: '1'
concurrency:
group: ${{ github.workflow }}-${{ github.ref }}
@ -33,7 +34,7 @@ jobs:
- name: Setup node
uses: actions/setup-node@v4
with:
node-version: 18
node-version: 20
cache: 'yarn'
- name: Install
uses: dtolnay/rust-toolchain@stable
@ -99,7 +100,7 @@ jobs:
- name: Setup node
uses: actions/setup-node@v4
with:
node-version: 18
node-version: 20
cache: 'yarn'
- name: Install dependencies
run: |

View file

@ -135,11 +135,16 @@ impl TryToTokens for NapiFn {
{
quote! { #native_call }
} else if self.kind == FnKind::Constructor {
let return_from_factory = if self.catch_unwind {
quote! { return Ok(std::ptr::null_mut()); }
} else {
quote! { return std::ptr::null_mut(); }
};
quote! {
// constructor function is called from class `factory`
// so we should skip the original `constructor` logic
if napi::__private::___CALL_FROM_FACTORY.with(|inner| inner.load(std::sync::atomic::Ordering::Relaxed)) {
return std::ptr::null_mut();
#return_from_factory
}
#function_call_inner
}

View file

@ -99,6 +99,14 @@ Generated by [AVA](https://avajs.dev).
}␊
export type Blake2bKey = Blake2BKey␊
export class CatchOnConstructor {␊
constructor()␊
}␊
export class CatchOnConstructor2 {␊
constructor()␊
}␊
export class ClassWithFactory {␊
name: string␊
static withName(name: string): ClassWithFactory␊

View file

@ -108,6 +108,8 @@ const {
arrayBufferPassThrough,
JsRepo,
CssStyleSheet,
CatchOnConstructor,
CatchOnConstructor2,
asyncReduceBuffer,
callbackReturnPromise,
callbackReturnPromiseAndSpawn,
@ -234,6 +236,24 @@ test('class', (t) => {
// @ts-expect-error
plusOne.call('')
})
t.notThrows(() => {
new CatchOnConstructor()
})
if (!process.env.TEST_ZIG_CROSS) {
t.throws(
() => {
new CatchOnConstructor2()
},
(() =>
process.env.WASI_TEST
? undefined
: {
message: 'CatchOnConstructor2 panic',
})(),
)
}
})
test('async self in class', async (t) => {

View file

@ -89,6 +89,14 @@ export class Blake2BKey {
}
export type Blake2bKey = Blake2BKey
export class CatchOnConstructor {
constructor()
}
export class CatchOnConstructor2 {
constructor()
}
export class ClassWithFactory {
name: string
static withName(name: string): ClassWithFactory

View file

@ -432,3 +432,25 @@ impl GetterSetterWithClosures {
Ok(Self {})
}
}
#[napi]
pub struct CatchOnConstructor {}
#[napi]
impl CatchOnConstructor {
#[napi(constructor, catch_unwind)]
pub fn new() -> Self {
Self {}
}
}
#[napi]
pub struct CatchOnConstructor2 {}
#[napi]
impl CatchOnConstructor2 {
#[napi(constructor, catch_unwind)]
pub fn new() -> Self {
panic!("CatchOnConstructor2 panic");
}
}