diff --git a/cli/src/__test__/parse-triple.spec.ts b/cli/src/__test__/parse-triple.spec.ts index bedae3ca..cb72b515 100644 --- a/cli/src/__test__/parse-triple.spec.ts +++ b/cli/src/__test__/parse-triple.spec.ts @@ -1,3 +1,5 @@ +import { platform } from 'os' + import test from 'ava' import { parseTriple, getDefaultTargetTriple } from '../parse-triple' @@ -121,7 +123,10 @@ for (const triple of triples) { }) } -test('should parse default triple from rustup show active', (t) => { +const MaybeTest = + process.arch !== 'x64' && platform() === 'linux' ? test.skip : test + +MaybeTest('should parse default triple from rustup show active', (t) => { t.deepEqual( getDefaultTargetTriple( `x86_64-unknown-linux-gnu (directory override for '/home/runner/work/fast-escape/fast-escape')`, diff --git a/crates/backend/src/codegen/struct.rs b/crates/backend/src/codegen/struct.rs index 70c9a316..79df9c9e 100644 --- a/crates/backend/src/codegen/struct.rs +++ b/crates/backend/src/codegen/struct.rs @@ -153,7 +153,10 @@ impl NapiStruct { fn gen_napi_value_map_impl(&self) -> TokenStream { match self.kind { - NapiStructKind::None => gen_napi_value_map_impl(&self.name, quote! {}), + NapiStructKind::None => gen_napi_value_map_impl( + &self.name, + self.gen_to_napi_value_ctor_impl_for_non_default_constructor_struct(), + ), NapiStructKind::Constructor => { gen_napi_value_map_impl(&self.name, self.gen_to_napi_value_ctor_impl()) } @@ -161,6 +164,42 @@ impl NapiStruct { } } + fn gen_to_napi_value_ctor_impl_for_non_default_constructor_struct(&self) -> TokenStream { + let name = &self.name; + let js_name_str = format!("{}\0", &self.js_name); + quote! { + impl napi::bindgen_prelude::ToNapiValue for #name { + unsafe fn to_napi_value( + env: napi::bindgen_prelude::sys::napi_env, val: #name + ) -> napi::bindgen_prelude::Result { + if let Some(ctor_ref) = napi::bindgen_prelude::get_class_constructor(#js_name_str) { + let mut ctor = std::ptr::null_mut(); + + napi::bindgen_prelude::check_status!( + napi::bindgen_prelude::sys::napi_get_reference_value(env, ctor_ref, &mut ctor), + "Failed to get constructor of class `{}`", + #js_name_str + )?; + + let mut result = std::ptr::null_mut(); + napi::bindgen_prelude::___CALL_FROM_FACTORY.store(true, std::sync::atomic::Ordering::Relaxed); + napi::bindgen_prelude::check_status!( + napi::bindgen_prelude::sys::napi_new_instance(env, ctor, 0, std::ptr::null_mut(), &mut result), + "Failed to construct class `{}`", + #js_name_str + )?; + napi::bindgen_prelude::___CALL_FROM_FACTORY.store(false, std::sync::atomic::Ordering::Relaxed); + Ok(result) + } else { + Err(napi::bindgen_prelude::Error::new( + napi::bindgen_prelude::Status::InvalidArg, format!("Failed to get constructor of class `{}`", #js_name_str)) + ) + } + } + } + } + } + fn gen_to_napi_value_ctor_impl(&self) -> TokenStream { let name = &self.name; let js_name_str = format!("{}\0", &self.js_name); diff --git a/examples/napi/__test__/typegen.spec.ts.md b/examples/napi/__test__/typegen.spec.ts.md index f00894e4..68cb4c58 100644 --- a/examples/napi/__test__/typegen.spec.ts.md +++ b/examples/napi/__test__/typegen.spec.ts.md @@ -145,11 +145,16 @@ Generated by [AVA](https://avajs.dev). /** This is static... */␊ static getDogKind(): Kind␊ returnOtherClass(): Dog␊ + returnOtherClassWithCustomConstructor(): Bird␊ }␊ export class Dog {␊ name: string␊ constructor(name: string)␊ }␊ + export class Bird {␊ + name: string␊ + constructor(name: string)␊ + }␊ /** Smoking test for type generation */␊ export class Blake2BHasher {␊ static withKey(key: Blake2bKey): Blake2BHasher␊ diff --git a/examples/napi/__test__/typegen.spec.ts.snap b/examples/napi/__test__/typegen.spec.ts.snap index 4abe403e..870adc52 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 83eccc11..d1c9ae5c 100644 --- a/examples/napi/__test__/values.spec.ts +++ b/examples/napi/__test__/values.spec.ts @@ -70,6 +70,7 @@ import { returnNull, returnUndefined, Dog, + Bird, } from '../' test('export const', (t) => { @@ -127,6 +128,7 @@ test('class', (t) => { dog.name = '可乐' t.is(dog.name, '可乐') t.deepEqual(dog.returnOtherClass(), new Dog('Doge')) + t.deepEqual(dog.returnOtherClassWithCustomConstructor(), new Bird('parrot')) }) test('class factory', (t) => { diff --git a/examples/napi/index.d.ts b/examples/napi/index.d.ts index da828cfa..5224aef8 100644 --- a/examples/napi/index.d.ts +++ b/examples/napi/index.d.ts @@ -135,11 +135,16 @@ export class Animal { /** This is static... */ static getDogKind(): Kind returnOtherClass(): Dog + returnOtherClassWithCustomConstructor(): Bird } export class Dog { name: string constructor(name: string) } +export class Bird { + name: string + constructor(name: string) +} /** Smoking test for type generation */ export class Blake2BHasher { static withKey(key: Blake2bKey): Blake2BHasher diff --git a/examples/napi/src/class.rs b/examples/napi/src/class.rs index bb8e5dd0..4c1a7562 100644 --- a/examples/napi/src/class.rs +++ b/examples/napi/src/class.rs @@ -67,6 +67,11 @@ impl Animal { name: "Doge".to_owned(), } } + + #[napi] + pub fn return_other_class_with_custom_constructor(&self) -> Bird { + Bird::new("parrot".to_owned()) + } } #[napi(constructor)] @@ -74,6 +79,19 @@ pub struct Dog { pub name: String, } +#[napi] +pub struct Bird { + pub name: String, +} + +#[napi] +impl Bird { + #[napi(constructor)] + pub fn new(name: String) -> Self { + Bird { name } + } +} + /// Smoking test for type generation #[napi] #[repr(transparent)]