From e6a30ffcca38f1b6d72211931f32675a53f12dcf Mon Sep 17 00:00:00 2001 From: LongYinan Date: Fri, 24 Dec 2021 18:46:10 +0800 Subject: [PATCH] fix(napi-derive): return instance from non-default constructor class Fix https://github.com/napi-rs/napi-rs/issues/933 --- cli/src/__test__/parse-triple.spec.ts | 7 +++- crates/backend/src/codegen/struct.rs | 41 +++++++++++++++++++- examples/napi/__test__/typegen.spec.ts.md | 5 +++ examples/napi/__test__/typegen.spec.ts.snap | Bin 2116 -> 2131 bytes examples/napi/__test__/values.spec.ts | 2 + examples/napi/index.d.ts | 5 +++ examples/napi/src/class.rs | 18 +++++++++ 7 files changed, 76 insertions(+), 2 deletions(-) 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 4abe403e7c8e0afa31bc1fdd3897cbd9107374e1..870adc528bd485e780403fd6c804d4afffcaca71 100644 GIT binary patch literal 2131 zcmV-Z2(0%(RzV-~Il_|NZ-4|9I5EpC=zR8t*mUH|s~gZhY`7^3jvWM5~Ak-43~;e#FS*Co6Es z%;BnYh^I8ua&^cAOQ~id@h7C$d405cdS(FFZ6Z@mf`}?b4sJC|1&vPpD;DUd{ax~I zg^-ldP>N_mKKZ0=4i=6w!N18EQIpu0k-5Hj+0M6@ZPJIMyOlc-bvCq;1VvvbIb1BG>=`Up(DzDiloiwGBr%I<>40jES z7fdUnWXy7O=VWWAN&yyQ`&AS57D*!wQkaKBO9 z_o>p895V~X=x=$J`buWNFN+{qf0h;pG+t8bQK};VFi~)eQ)ST?k@Trif}SKy4#?0PRDmv6g=v4RO21G&N2#;2(1{{z z&cfYI;zIwuuVexU9kTnZUy+|u7BGIzN*qy*K&mWBrBAsJb&_xA)luin$lfW6!yYEe znH=t$A<9??St!fj3;tpVz;fy@6)zZwQ~QQ6C*fhU=u&GDmXoS=Pwe|%N157KU-yzy zuUFCi%{A1*c?XuL1ezZ(#Ts@?PFb1(y|w^f;C*4*!m>q$gt}LBW8iUE26M8uZ02_k zR>%?trV#;W>Uk-LP%+u9cAAh~@Bb{+DsQ5p^EUKxXIm8t&UFv-b28h{;ZC!3IfkKN zQ7)9HplSzGHMR)!GQhwoWO;v7MIoRXd<8vc3SG|*fY0?{W9Q-EuPF2?8xMh3OrM$I z?MPr+vV&YP(A6g?o5(CCYCWF^7r}0zg_N1@_;A_u9;Y#WeiZLoz0i-N<)qB#fN46`*?W10(uD1ovB z2on-B$Pl5W1k<4AfeCXY;ZQ^K8c6{PT+Gn+noccJ#bE_k{7U7pw%Zs#x~xVxR0T4Q zVFIz|$Q%nSi{%w3Km7GCe>CSP-pxqTn9s3w-(;nSaG84yNDHH?c}{bxQ`^O!pn{5c;g3^Wa~{aSxU=IUcU57CR^7K>NF1|PsosV_ z-iy{-qBRFtGHj2FE85Re9kIIhuWRxnnc$ZQf#5_N_}@Sb{ONCVE)5g#DNRQBNQbbE z%wwv?T^U&)oie}?WIkdSja2yhVV)K$q;zc1D@A&{M8YP8Do70hI}-peRf0`24BuOZ z@!Vhmef*2w@j001UH47mUR literal 2116 zcmV-K2)p+|RzVJh+ao8NFT!HYWaM~~Av+UilsN3HqG+eOyKGn7UDexFox}{0 z_z9dia6#e%H~s+Pf{?g#<}V;loO!RR+pczZ$I)t|D5;P4Rqy*XX|-BUS|9!HNB{cg zf4=(bpMLtY|NZ+PfB*B77XJM0<5ugV)(_13$@g17{N7(a{_H8yD&j(SL$0VFG4k}Y zH8^DEaNRk?Q<`bHK4yZYRI`xyGcxGCJzhUMHvsG|k*Ov@M3o|kcbcVwMyLKY3-q($ zKKZalNXlp^MKmLye%dt$OGlaD-(-xaS?tTmTwlKK=G&_-8N$*1+C7N!lnf_a5%{Gf zkV0vcpb)_9UmhOyF5V2k?w_6yyF_HM&(Z>7l!-udDae@VFJ&4kuiYiRG^Mj=N~c_m z_YI3zOe>;f%yM+)FmXu?ve=b z^EQ<+SM1qAHX7A&q=;EJl`ibl7~P5{~5apnsD-*d>}Vq zGo3zT?@@uIUlB}Ov$goSwlABf`uId7h5k1 zncOQ_i!6#NVlH!ITu)efZtzdjfia55MUrWU>fCsZ&H@hYFOJ`v!iyEBV0+=q|XTfkC+x+?p^rBR4e4z^XK582Oru zOhRJV*@n>76gh&Ylg&zgFu1R|2#v@{^?;^R6XJxtlw)v{%}##vnn#g>kbq2K@B384 z{Z?^5q)N|n%q*CqzvWr#E13bmEP`YS4mBn4W)O=dgaYFcxDh;1u-m!hnX>QMsF$~& zDJ?OL9O4cIKNYNy1cKanIxZ(E!}A^79LX$&^)9Z@`5i3xaCykb6MV(zxEXLm=jR5Q zVZ>~0))@`h4(0LAw#T|CPf~enV#aIoewz)7lHn=-E9Q9aQYmT5SY;wMlswcc z6WU3dOVo;dUz2v`^00i-Buew!<4n5`TScgYzVJ)DpFh4-NRSPdL;rNJ>? zvzhXwf88b0cuA#4sgD4_M8Pdiokd?o(x*lVdX_LbB4cw<2fA7nrv0%h{Xz{Kr7p@s zFN&-=3wJk(3;p+@k_jMm%pS6SO@2yQ!1xWTa6~l%sj4KkKIJ~tNxr=|$GvkSd#@-C z2bd@qa=34XC}SaHp)7wd_=_O`%elYQykI2G>>I+Igon+dORYm#PO8y8vG02uWom14 z(@QG7UQPE`YN&=5W>fPquU^8TofLO?b63VO~Qx|tmSU+B@+-s8dFQ0P^*9s{qK zJ~zYLvB0!s2f1RPYfe%&ky%XCdOi;>gWW<4DKp*k;j|BWOJx*6=i88(S4})f?J=Y} zMDejH;s*NMY#u=$=Lqb}XsGCj9p%UFc(Jju0Y(P3f{R{WnVA7rjZHv>)^O2j1^#zH z?}%y|oyd@V$K<}Xh!6m_V=?ohSyhu?g2A7I`Ps;Aa_TX_sUiL7i=Ay#UW?x70uo$) zv~spD_nt#2tD&XUF41Y|4;}cN_faIN!@QVm*T_@y-c%$k1TuY3WMZoZr0Mte^gX1l zZ!(U9E_fC+9xQ^XMN8sC%FXIWcc}ao+(^*4amGU*usNF!Qo@koC9xx*(ueS_7WjV zpezBxjKmBwL})3&G^lxC!W>CB)X=;}Qh)*%Gqk<7Q;Sq_Si=>+QaP;cHpY)G>k$rB zfsA9AKC9&X#=;j}=UYNe$KbxW zT^8>pq%1FlKTfI3c_0VlU5?4_>!RXIq+>r=^d0Z6QN8uZyftjLM5hGUUgip;{52hB zsg77vH`X`lip=oCfIx7f4g8P6C4c+Jl83=SdPb88KGGp<1LcIOXOC znWA^T-rH>&p{<4iXlwiP1(H!|4J812n9w_v)9THoVNc!_kElAa#m { @@ -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)]