diff --git a/crates/backend/src/codegen/struct.rs b/crates/backend/src/codegen/struct.rs index 4e1ef477..a3c431c4 100644 --- a/crates/backend/src/codegen/struct.rs +++ b/crates/backend/src/codegen/struct.rs @@ -25,6 +25,26 @@ fn gen_napi_value_map_impl(name: &Ident, to_napi_val_impl: TokenStream) -> Token } } + impl napi::bindgen_prelude::TypeName for &#name { + fn type_name() -> &'static str { + #name_str + } + + fn value_type() -> napi::ValueType { + napi::ValueType::Object + } + } + + impl napi::bindgen_prelude::TypeName for &mut #name { + fn type_name() -> &'static str { + #name_str + } + + fn value_type() -> napi::ValueType { + napi::ValueType::Object + } + } + #to_napi_val_impl impl napi::bindgen_prelude::FromNapiRef for #name { @@ -60,6 +80,36 @@ fn gen_napi_value_map_impl(name: &Ident, to_napi_val_impl: TokenStream) -> Token Ok(&mut *(wrapped_val as *mut #name)) } } + + impl napi::bindgen_prelude::FromNapiValue for &#name { + unsafe fn from_napi_value( + env: napi::bindgen_prelude::sys::napi_env, + napi_val: napi::bindgen_prelude::sys::napi_value + ) -> napi::bindgen_prelude::Result { + napi::bindgen_prelude::FromNapiRef::from_napi_ref(env, napi_val) + } + } + + impl napi::bindgen_prelude::FromNapiValue for &mut #name { + unsafe fn from_napi_value( + env: napi::bindgen_prelude::sys::napi_env, + napi_val: napi::bindgen_prelude::sys::napi_value + ) -> napi::bindgen_prelude::Result { + napi::bindgen_prelude::FromNapiMutRef::from_napi_mut_ref(env, napi_val) + } + } + + impl napi::NapiRaw for &#name { + unsafe fn raw(&self) -> napi::sys::napi_value { + unreachable!() + } + } + + impl napi::NapiRaw for &mut #name { + unsafe fn raw(&self) -> napi::sys::napi_value { + unreachable!() + } + } } } diff --git a/examples/napi/__test__/typegen.spec.ts.md b/examples/napi/__test__/typegen.spec.ts.md index 55b92aca..25d3615b 100644 --- a/examples/napi/__test__/typegen.spec.ts.md +++ b/examples/napi/__test__/typegen.spec.ts.md @@ -40,6 +40,8 @@ Generated by [AVA](https://avajs.dev). v: string | number␊ }␊ export function either4(input: string | number | boolean | Obj): number␊ + export function receiveClassOrNumber(either: number | JsClassForEither): number␊ + export function receiveMutClassOrNumber(either: number | JsClassForEither): number␊ /** default enum values are continuos i32s start from 0 */␊ export const enum Kind {␊ /** Barks */␊ @@ -200,6 +202,9 @@ Generated by [AVA](https://avajs.dev). static withName(name: string): ClassWithFactory␊ setName(name: string): this␊ }␊ + export class JsClassForEither {␊ + constructor()␊ + }␊ export namespace xxh3 {␊ export const ALIGNMENT: number␊ export function xxh3_64(input: Buffer): BigInt␊ diff --git a/examples/napi/__test__/typegen.spec.ts.snap b/examples/napi/__test__/typegen.spec.ts.snap index 36b7e036..a929b2b0 100644 Binary files a/examples/napi/__test__/typegen.spec.ts.snap and b/examples/napi/__test__/typegen.spec.ts.snap differ diff --git a/examples/napi/__test__/values.spec.ts b/examples/napi/__test__/values.spec.ts index 395f0719..6e065d42 100644 --- a/examples/napi/__test__/values.spec.ts +++ b/examples/napi/__test__/values.spec.ts @@ -73,6 +73,9 @@ import { Bird, Assets, receiveStrictObject, + receiveClassOrNumber, + JsClassForEither, + receiveMutClassOrNumber, } from '../' test('export const', (t) => { @@ -320,6 +323,13 @@ test('return either', (t) => { t.is(returnEither(42), '42') }) +test('receive class reference in either', (t) => { + const c = new JsClassForEither() + t.is(receiveClassOrNumber(1), 2) + t.is(receiveClassOrNumber(c), 100) + t.is(receiveMutClassOrNumber(c), 100) +}) + test('either3', (t) => { t.is(either3(2), 2) t.is(either3('hello'), 'hello'.length) diff --git a/examples/napi/index.d.ts b/examples/napi/index.d.ts index cd2e9b02..31d68233 100644 --- a/examples/napi/index.d.ts +++ b/examples/napi/index.d.ts @@ -30,6 +30,8 @@ export interface Obj { v: string | number } export function either4(input: string | number | boolean | Obj): number +export function receiveClassOrNumber(either: number | JsClassForEither): number +export function receiveMutClassOrNumber(either: number | JsClassForEither): number /** default enum values are continuos i32s start from 0 */ export const enum Kind { /** Barks */ @@ -190,6 +192,9 @@ export class ClassWithFactory { static withName(name: string): ClassWithFactory setName(name: string): this } +export class JsClassForEither { + constructor() +} export namespace xxh3 { export const ALIGNMENT: number export function xxh3_64(input: Buffer): BigInt diff --git a/examples/napi/src/either.rs b/examples/napi/src/either.rs index 12ddccdc..175de708 100644 --- a/examples/napi/src/either.rs +++ b/examples/napi/src/either.rs @@ -55,3 +55,30 @@ fn either4(input: Either4) -> u32 { }, } } + +#[napi] +struct JsClassForEither {} + +#[napi] +impl JsClassForEither { + #[napi(constructor)] + pub fn new() -> Self { + JsClassForEither {} + } +} + +#[napi] +fn receive_class_or_number(either: Either) -> u32 { + match either { + Either::A(n) => n + 1, + Either::B(_) => 100, + } +} + +#[napi] +fn receive_mut_class_or_number(either: Either) -> u32 { + match either { + Either::A(n) => n + 1, + Either::B(_) => 100, + } +}