From 02dd4c3fd375f1f0879d72b822d7d22d47849cd2 Mon Sep 17 00:00:00 2001 From: LongYinan Date: Wed, 27 Dec 2023 12:49:10 +0800 Subject: [PATCH] fix(napi-derive): catch_unwind on constructor (#1869) - Close https://github.com/napi-rs/napi-rs/issues/1852 --- .github/workflows/zig.yaml | 5 ++-- crates/backend/src/codegen/fn.rs | 7 +++++- .../__snapshots__/typegen.spec.ts.md | 8 +++++++ .../__snapshots__/typegen.spec.ts.snap | Bin 4138 -> 4162 bytes examples/napi/__tests__/values.spec.ts | 20 ++++++++++++++++ examples/napi/index.d.ts | 8 +++++++ examples/napi/src/class.rs | 22 ++++++++++++++++++ 7 files changed, 67 insertions(+), 3 deletions(-) diff --git a/.github/workflows/zig.yaml b/.github/workflows/zig.yaml index b1b025ec..b67bfb89 100644 --- a/.github/workflows/zig.yaml +++ b/.github/workflows/zig.yaml @@ -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: | diff --git a/crates/backend/src/codegen/fn.rs b/crates/backend/src/codegen/fn.rs index d09a4716..5fb803a3 100644 --- a/crates/backend/src/codegen/fn.rs +++ b/crates/backend/src/codegen/fn.rs @@ -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 } diff --git a/examples/napi/__tests__/__snapshots__/typegen.spec.ts.md b/examples/napi/__tests__/__snapshots__/typegen.spec.ts.md index 4bb95143..4fb8710f 100644 --- a/examples/napi/__tests__/__snapshots__/typegen.spec.ts.md +++ b/examples/napi/__tests__/__snapshots__/typegen.spec.ts.md @@ -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␊ diff --git a/examples/napi/__tests__/__snapshots__/typegen.spec.ts.snap b/examples/napi/__tests__/__snapshots__/typegen.spec.ts.snap index 30c3aa3fd81e568d3d2082f56315a1b9a10e69fe..339b96f04122a7b3d5ec51de5ff791736a74adf8 100644 GIT binary patch literal 4162 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 obnFR~-r9ax4&PPQofEty*fJOXIsD { // @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) => { diff --git a/examples/napi/index.d.ts b/examples/napi/index.d.ts index 340c29e2..aeaafcc3 100644 --- a/examples/napi/index.d.ts +++ b/examples/napi/index.d.ts @@ -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 diff --git a/examples/napi/src/class.rs b/examples/napi/src/class.rs index 8045dd12..a0956262 100644 --- a/examples/napi/src/class.rs +++ b/examples/napi/src/class.rs @@ -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"); + } +}