From 0ef482c6ca87390267a6fd1d31f02a390da1f5f2 Mon Sep 17 00:00:00 2001 From: LongYinan <lynweklm@gmail.com> Date: Wed, 17 Aug 2022 17:49:22 +0800 Subject: [PATCH 1/2] feat(napi-derive): support inject This<Value> into raw function --- crates/backend/src/codegen/fn.rs | 59 +++++++++++++++++- crates/backend/src/lib.rs | 37 +++++++++++ crates/backend/src/typegen.rs | 35 +---------- crates/backend/src/typegen/fn.rs | 34 +++++++++- .../src/bindgen_runtime/js_values/class.rs | 5 +- .../src/bindgen_runtime/js_values/number.rs | 2 +- examples/napi/__test__/typegen.spec.ts.md | 5 ++ examples/napi/__test__/typegen.spec.ts.snap | Bin 3531 -> 3557 bytes examples/napi/__test__/values.spec.ts | 11 +++- examples/napi/index.d.ts | 5 ++ examples/napi/src/class.rs | 10 +++ 11 files changed, 160 insertions(+), 43 deletions(-) diff --git a/crates/backend/src/codegen/fn.rs b/crates/backend/src/codegen/fn.rs index 4f7c1604..35e2df94 100644 --- a/crates/backend/src/codegen/fn.rs +++ b/crates/backend/src/codegen/fn.rs @@ -156,8 +156,63 @@ impl NapiFn { } } } else if p.ident == "This" { - if !is_in_class { - bail_span!(p, "`This` is only allowed in class methods"); + if let syn::PathArguments::AngleBracketed(syn::AngleBracketedGenericArguments { + args: angle_bracketed_args, + .. + }) = &p.arguments + { + if let Some(syn::GenericArgument::Type(generic_type)) = + angle_bracketed_args.first() + { + if let syn::Type::Path(syn::TypePath { + path: syn::Path { segments, .. }, + .. + }) = generic_type + { + if let Some(syn::PathSegment { ident, .. }) = segments.first() { + if let Some((primitive_type, _)) = + crate::PRIMITIVE_TYPES.iter().find(|(p, _)| ident == *p) + { + bail_span!( + ident, + "This type must not be {} \nthis in JavaScript function must be `Object` type or `undefined`", + primitive_type + ); + } + args.push( + quote! { + { + <#ident as napi::bindgen_prelude::FromNapiValue>::from_napi_value(env, cb.this)? + } + }, + ); + skipped_arg_count += 1; + continue; + } + } else if let syn::Type::Reference(syn::TypeReference { + elem, + mutability, + .. + }) = generic_type + { + if let syn::Type::Path(syn::TypePath { + path: syn::Path { segments, .. }, + .. + }) = elem.as_ref() + { + if let Some(syn::PathSegment { ident, .. }) = segments.first() { + let token = if mutability.is_some() { + quote! { <#ident as napi::bindgen_prelude::FromNapiMutRef>::from_napi_mut_ref(env, cb.this)? } + } else { + quote! { <#ident as napi::bindgen_prelude::FromNapiRef>::from_napi_ref(env, cb.this)? } + }; + args.push(token); + skipped_arg_count += 1; + continue; + } + } + } + } } args.push( quote! { <napi::bindgen_prelude::This as napi::NapiValue>::from_raw_unchecked(env, cb.this) }, diff --git a/crates/backend/src/lib.rs b/crates/backend/src/lib.rs index 332ab69a..9ea18085 100644 --- a/crates/backend/src/lib.rs +++ b/crates/backend/src/lib.rs @@ -55,3 +55,40 @@ napi_ast_impl! { (Enum, NapiEnum), (Const, NapiConst), } + +pub(crate) static PRIMITIVE_TYPES: &[(&str, &str)] = &[ + ("JsUndefined", "undefined"), + ("()", "undefined"), + ("Undefined", "undefined"), + ("JsNumber", "number"), + ("i8", "number"), + ("i16", "number"), + ("i32", "number"), + ("i64", "number"), + ("f64", "number"), + ("u8", "number"), + ("u16", "number"), + ("u32", "number"), + ("u64", "bigint"), + ("i64n", "bigint"), + ("u128", "bigint"), + ("i128", "bigint"), + ("usize", "bigint"), + ("isize", "bigint"), + ("JsBigInt", "bigint"), + ("BigInt", "bigint"), + ("JsBoolean", "boolean"), + ("bool", "boolean"), + ("JsString", "string"), + ("String", "string"), + ("str", "string"), + ("Latin1String", "string"), + ("Utf16String", "string"), + ("char", "string"), + ("Null", "null"), + ("JsNull", "null"), + ("null", "null"), + ("Symbol", "symbol"), + ("JsSymbol", "symbol"), + ("JsFunction", "(...args: any[]) => any"), +]; diff --git a/crates/backend/src/typegen.rs b/crates/backend/src/typegen.rs index d0a2357c..ead99fac 100644 --- a/crates/backend/src/typegen.rs +++ b/crates/backend/src/typegen.rs @@ -120,35 +120,8 @@ pub trait ToTypeDef { static KNOWN_TYPES: Lazy<HashMap<&'static str, &'static str>> = Lazy::new(|| { let mut map = HashMap::default(); + map.extend(crate::PRIMITIVE_TYPES.iter().cloned()); map.extend([ - ("JsUndefined", "undefined"), - ("()", "undefined"), - ("Undefined", "undefined"), - ("JsNumber", "number"), - ("i8", "number"), - ("i16", "number"), - ("i32", "number"), - ("i64", "number"), - ("f64", "number"), - ("u8", "number"), - ("u16", "number"), - ("u32", "number"), - ("u64", "bigint"), - ("i64n", "bigint"), - ("u128", "bigint"), - ("i128", "bigint"), - ("usize", "bigint"), - ("isize", "bigint"), - ("JsBigInt", "bigint"), - ("BigInt", "bigint"), - ("JsBoolean", "boolean"), - ("bool", "boolean"), - ("JsString", "string"), - ("String", "string"), - ("str", "string"), - ("Latin1String", "string"), - ("Utf16String", "string"), - ("char", "string"), ("JsObject", "object"), ("Object", "object"), ("Array", "unknown[]"), @@ -201,14 +174,8 @@ static KNOWN_TYPES: Lazy<HashMap<&'static str, &'static str>> = Lazy::new(|| { ("Either24", "{} | {} | {} | {} | {} | {} | {} | {} | {} | {} | {} | {} | {} | {} | {} | {} | {} | {} | {} | {} | {} | {} | {} | {}"), ("Either25", "{} | {} | {} | {} | {} | {} | {} | {} | {} | {} | {} | {} | {} | {} | {} | {} | {} | {} | {} | {} | {} | {} | {} | {} | {}"), ("Either26", "{} | {} | {} | {} | {} | {} | {} | {} | {} | {} | {} | {} | {} | {} | {} | {} | {} | {} | {} | {} | {} | {} | {} | {} | {} | {}"), - ("Null", "null"), - ("JsNull", "null"), - ("null", "null"), - ("Symbol", "symbol"), - ("JsSymbol", "symbol"), ("external", "object"), ("AbortSignal", "AbortSignal"), - ("JsFunction", "(...args: any[]) => any"), ("JsGlobal", "typeof global"), ("External", "ExternalObject<{}>"), ("unknown", "unknown"), diff --git a/crates/backend/src/typegen/fn.rs b/crates/backend/src/typegen/fn.rs index a5541c14..e9122006 100644 --- a/crates/backend/src/typegen/fn.rs +++ b/crates/backend/src/typegen/fn.rs @@ -13,14 +13,18 @@ struct FnArg { } struct FnArgList { + this: Option<FnArg>, args: Vec<FnArg>, last_required: Option<usize>, } impl Display for FnArgList { fn fmt(&self, f: &mut Formatter<'_>) -> std::fmt::Result { + if let Some(this) = &self.this { + write!(f, "this: {}", this.ts_type)?; + } for (i, arg) in self.args.iter().enumerate() { - if i != 0 { + if i != 0 || self.this.is_some() { write!(f, ", ")?; } let is_optional = arg.is_optional @@ -39,13 +43,22 @@ impl Display for FnArgList { impl FromIterator<FnArg> for FnArgList { fn from_iter<T: IntoIterator<Item = FnArg>>(iter: T) -> Self { - let args = iter.into_iter().collect::<Vec<_>>(); + let mut args = Vec::new(); + let mut this = None; + for arg in iter.into_iter() { + if arg.arg != "this" { + args.push(arg); + } else { + this = Some(arg); + } + } let last_required = args .iter() .enumerate() .rfind(|(_, arg)| !arg.is_optional) .map(|(i, _)| i); FnArgList { + this, args, last_required, } @@ -128,12 +141,27 @@ impl NapiFn { if let syn::Type::Path(path) = path.ty.as_ref() { if let Some(PathSegment { ident, - arguments: PathArguments::AngleBracketed(_), + arguments: + PathArguments::AngleBracketed(syn::AngleBracketedGenericArguments { + args: angle_bracketed_args, + .. + }), }) = path.path.segments.last() { if ident == "Reference" || ident == "WeakReference" { return None; } + if ident == "This" { + if let Some(syn::GenericArgument::Type(ty)) = angle_bracketed_args.first() { + let (ts_type, _) = ty_to_ts_type(&ty, false, false); + return Some(FnArg { + arg: "this".to_owned(), + ts_type, + is_optional: false, + }); + } + return None; + } } } diff --git a/crates/napi/src/bindgen_runtime/js_values/class.rs b/crates/napi/src/bindgen_runtime/js_values/class.rs index 2b700fed..9005ce33 100644 --- a/crates/napi/src/bindgen_runtime/js_values/class.rs +++ b/crates/napi/src/bindgen_runtime/js_values/class.rs @@ -2,9 +2,10 @@ use std::any::type_name; use std::ops::{Deref, DerefMut}; use std::ptr; -use crate::{bindgen_runtime::FromNapiValue, check_status, sys, JsObject, NapiRaw}; +use super::Object; +use crate::{bindgen_runtime::FromNapiValue, check_status, sys, NapiRaw}; -pub type This = JsObject; +pub type This<T = Object> = T; pub struct ClassInstance<T: 'static> { pub value: sys::napi_value, diff --git a/crates/napi/src/bindgen_runtime/js_values/number.rs b/crates/napi/src/bindgen_runtime/js_values/number.rs index 97296809..80421706 100644 --- a/crates/napi/src/bindgen_runtime/js_values/number.rs +++ b/crates/napi/src/bindgen_runtime/js_values/number.rs @@ -41,7 +41,7 @@ macro_rules! impl_number_conversions { check_status!( unsafe { sys::$get(env, napi_val, &mut ret) }, "Failed to convert napi value {:?} into rust type `{}`", - type_of!(env, napi_val), + type_of!(env, napi_val)?, $name, )?; diff --git a/examples/napi/__test__/typegen.spec.ts.md b/examples/napi/__test__/typegen.spec.ts.md index 00c6ddf5..839b73db 100644 --- a/examples/napi/__test__/typegen.spec.ts.md +++ b/examples/napi/__test__/typegen.spec.ts.md @@ -48,6 +48,7 @@ Generated by [AVA](https://avajs.dev). }␊ export function createObjectWithClassField(): ObjectFieldClassInstance␊ export function receiveObjectWithClassField(object: ObjectFieldClassInstance): Bird␊ + export function plusOne(this: Width): number␊ export function dateToNumber(input: Date): number␊ export function chronoDateToMillis(input: Date): number␊ export function chronoDateAdd1Minute(input: Date): Date␊ @@ -298,6 +299,10 @@ Generated by [AVA](https://avajs.dev). export class CustomFinalize {␊ constructor(width: number, height: number)␊ }␊ + export class Width {␊ + value: number␊ + constructor(value: number)␊ + }␊ export class ClassWithFactory {␊ name: string␊ static withName(name: string): ClassWithFactory␊ diff --git a/examples/napi/__test__/typegen.spec.ts.snap b/examples/napi/__test__/typegen.spec.ts.snap index 17f9c8a756eae3f6d8fd16a88aa44954a667c46c..4b49767a2c08c17091d3f0614cac63df8cd0dc46 100644 GIT binary patch literal 3557 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 literal 3531 zcmV;+4K(sWRzV<BZeeh9Xm4~Nb~6eC0Lj3Db?@|_ygb5KzPBEk|I7@;bF_M^C5?dU zy+omuFCU8t00000000B68ryCg$2DzHwD4R0VCtgC(x4qnG7OjS1r#MEvMtGw=-PoI z#KYYoIo5KA*_oBZC<2;4=yP9+<O}=Sx1KYX-Ps#SCH6(ynLTsnoHOS>`}24di|}0j z^b1p5#q8>Daw@VoA`_OdlqyC-k)|wEL@nlwL~KmPJZ4-bbPkY8{`7McQANMm{PQ0^ z`_pIm=XZbn?DOCMZ{y2*M9G*ZsuyudM=>M!zPtmIOi$kTCUKT#O5AsQMr5=ghy6GE z_m59B0K1xtRFN>IQj*;(#nObvN28BG*VEy1a(#!8l+j2e@q&EuMNdyurm}>8pD`jA zvyq7P>(f^~J3Q-=Axz!exdBq{k>Qj}0{<xRo=AlhI0E!|XLqmv_Vw_)!O_XEN0Mwd zVyS}|XGy5INI-t-ok$}Ybb6$prgZUCs+1>_=X#5;n36<_8MDi!w~3G9Fq?T84D9n7 zpv-0(5Z=oQY^Rk#C0<GpAz~L=k}dlKx**4Lde#WVBpg~D7XQ}Z@l^Ieh5B-lgu$Gu zDI9|q4Xk{ViW!&e>2@|AH*rdF(Loj~KD-nGO($+MZ*7~DMtlN_*N>ur_UxcbM((lW z9%}1CpjfeOKG{!HupZd{<3~#%%`~XM+sBXk@<j6<jJQXMkw=rL2bWP0(l{Q`@VrM* z0uOWXk!R1zh2Rk&z+biHVvfIdlU58}0;7!=Zb*Ivs{xDW30UNhAm}(=bB_~6Q`NRh z16s53Eg8|9Ea7J5K6<qI3D`XXCsU>3R%p>BfJ5cv8M!7G;0_S?GqTwwV^FFrWfDfG zcO^?BcK@Rk$=x$@)8sOoan)tAo2DZ5Y54?)oid;;c`5ho1nPY7;K2hx41S0vi_<fW z1D@*UVhKFfIGpVcp9c<NKbdC=@M#P~AgO@q5|2HWrUiHAkU?JHBEYHp9F$QwdcfXT zI;J5bCY<bX7Doe&GyCA`X#y`Wn2dND^~g5-gc#9m`DXn)uBLjqMuY-s!`mRuknxLV zJjO$}BkNe=syHDuv!OWD9x>oXqB}6x9u~rBDiX1y*B$UU=JK}dz{74F@FY{LvJ!vQ z<&Lvb3t6H;TQEXc61}j4y2u%bho#1K9;Idea(&JtLkr19eRnk~w>V!@!O}v(R?DXF zFcKnWG^uT0(m2icMSZt6jvuYu51s(;GN!ebY3<1+XOQ;_WG|&rK9L&nti*SasZWh^ zhhq-F5`#ELSj7XV`-#A(_3;<yZg5u*zm@2gW7z}0ax`}?uz|wdwbr$uuXSK7M6Y)E z1<<zfLNr|lG_XKF)Pb7l)vhGxy$@7w!~a2%eqdArvMKmdu*PggE@+&At<n^$f<%Fh z3rLi=Hl;CLG6uBdVJ%<QYhUps()1zLZJM6zl$VelF@f0juxsDE0+%DTyS48JRKfcV z_kKvFTG*9Yc#c7`;L_V}cQyw&+|MTU--ry}V`Vb}cYRJk3_vxTLvV^f`YHS-3A@Z0 z%cNoVK{GppOe%p{_b!fbpQD61LLoQR(HkG9DZ}|K9PEiKh37~3e8R8b@i9K`^2rpL ze1d~RuJQa`FJ_npY&>i_N7!~K_O~_z)+-aUB;yAceW@d5&=%26D03B7Ao&l>GmA>) z)s|?Nk=Xne<qEd!<@yzDt~_c;dUJZ1eP|=4o%dO$e8yHG>Y^_E1K;P&H_8iCgky}= zH5X)B>DuL&TWKnt0O}C)w0gx53h~HnXl?f`_<$#RW{v%Hjp0_Vs(tcRCb$Gxq~vkU zKD92w*d0Wx5(gi8$Y-}$QJm)O^}*rDQ`d0ha?Mp~gIoGFmD2+{ccMIIA=LX%U1_m4 z1&5HbqFi;xy;`VmT_nLZd01Ivp-Yl#VXk$B&6b0Ct+rmH+IC2+`Ag66TdLc9h3?7d z75Zrn-c0NTP0(ktw5aJ44TEK0kulXOpY|<H@{pgx{&+vpROA-5(mdKQIB{D<PQVt8 zFLO6l_we$VB@}Fk_MnjTatd;j%e|o`BcS9=dBpaUh+pt1qj5i-93{DJKzem#Kq8hD z)$`a{Os?}j+-5DAzU{uc1{%SXU(G6U>5+iUt}J02$@8ddX@6Z^O&>q%$DHOlQtqK! zyd{Jxa0qkM_fDHbXlmZMMW%muTSqdZbDMjD8olt6*9NW5-{H7LGqpqN^p=4XPN*#~ zQqyKL`{_2@Dz7u<BQW7G<Uz6;7|K!wuKpEUNUV+B8P<BOt)=?%w&z!|7*Q<*?0Sna zndpfo(AA>QZPdC*y$T?XodYxBOXrg%)rK*huop`bds{TsaG`i$U44&6{qPy^vfcjc z{r-ujs_&BZZOlxYst|24ECRouSx!I?Gy*J6mT)jmjtviyMS&rpgsn@MMO7iS*d4=7 zs48O2rPwMqe_0^CL9c{y$q@rsQB_rSp`dRlF?}0MX)<A^9zqSXZi(eOS)O($_acA4 zqzQ#y69UDYrD}n6T$?(^T8439U8ETQ16f7Gp471#5X)H5ZjZVz|0d4l#>0o}<qM^Y zmc)|~)?#z;^`P$$u+{0+Uj@(`1Mm{x*G}11icsLWRw`I9)_WGMDIe`SZ&k$R3``;k zIg>AHewZeU=Njl@XEj`tqS45s8fEDXn*{H@KE#+lFUF;{?eSGHsZOwGd@R7$0cIZH zU7c>tc6!ZiSt!#ePh=pWRt;GZX`#Ren!GHoExiE@Aw_doC+9Q3Z`F9?@%rGeDOBhi z>%gau?={JhV8=S=+)q&7P5$ZSp)C=^*q+T>I}W}Eb_td#GSwf!>;UAPiZ}-QYYCI9 z5^Th_4yrDZe4<NT4Sk{qYv9M63%eIIl636VNkuBw-05%gk*bDkSo9-w_4Qlv?SXE` z2O?sh7~QWXF_Ua4&bfGJ4_@DRE{P$w7tnE;X5G!s(et>LK{obM(v}t2J;7GkO4MLl z;1Si^t<73%!A`BbhA#Jgyf#Irgr}u9Q*UeR#e#a9H%cvHDH|94543<{q^&>?2Qi&F z^zBh>q($?FN{OnOO{NtYue_ZuB5VywsYl}w6_YJj-N!7-Le_ZT4FUBIxko<ev<<T* zk$$lElRBn;FtZ;Z5`CX>yix>9hOC>#kt9lx5yZ!A6!Wl)XmmsU67YlLpAbHq11Qo& zJoE_n*HgT=47}OS*&V-Ssz2H2CwxZZy#1?t!4Q+FnbzSr|5)Q3UiLId9>`6WfDzo= z$1L+Ef?{R2ln`_(h$w*^0v0UDjDcZB29pFO<e_$}h{D5$imxdJD9oF5h28NI2k9oO zyCO6uatLiXl5WbwZ|K91QamEfaE9MH+>fy-9E#bDCCbbrnV2`RnfS=bfB*CEf9iQ; z<Z>$LjF$-Xxi@@*BP+2Dl<tU$X1wD|-|Y4^Seb77>rYm~DNR9u_|*zF&+{Sh_I(Cv z5tC+>no>pV=R}}gOokL}(0x!8FM0;-+tah_n=ilZ-MyQ$V5-cc;(`Wm55=V6jqVZX z_V>Wk1a}=u+FA?;`rv~^q%-tXMVce>1_91q=jq{1r+WQsG#jrk8WK=nEz3$#S&ukx zhd^u901_MJ<>NV4{gu{sOwZZo2pg0PFC5Hx+l+PQeKLc%luUGnsJ(+;XTQJVrKH=^ z>7#JBwYj~pMR3kQUUp*`cY2jw3CZS>ZV2lPG<Rd#t2dGlSPI%<&`1yhU6YDXF(YDE zrv97J#fTj;78MOYtV8wozE`fuyi?|I2Z*+m=Q*U^r3~o1>XOSZppDb<?DM9{S)yX^ zn9Da$vzt`KI1;M}?V8gq0oD}pkS8DMFiTa;nl`a4^8AZ~qj6yC$}Blg#HHWyG!AE= z(*d%;ORog66Q$Ar1>DuYekpmMgk2uf`4na1(P32mfXefMh>ca}^k7q^>V}PPKtC5K z_|YTyvtxc$RP3efONrm$JtO9!as=k(b%RpC#sQDKJl&#lJ+;Pt+%^rnv~8k4vwTC< zw8_fNde;{4&9V5#%ZB;L^KC^Np}k>RKXd<+E{9@igT1=*a-2x3L%VS+yah+gKjLcJ zUVpZAJE2sKMyPiwSNI{Tjz+ij<kD(!X};<ctxwZIZjS@0{0COknoAzxhm@}5n=-sp zZZ-Bibne+isNLexsWs79MbXYp+58LvwNE7KR#5Yb4c~aIUbe?a8tBwi=MT8T2q)4r zG^>3(c<RK4f-gGtt5I+M2HaM@rf3QzW4=>C+ztC}8HTeo)mQ1c&rcw-w1j{PaJK~8 z`IXeyPV<<}MeQ&mp8Cq3LawTq`9S7aKR4mQ`CJ{Ff~5AVgOiivEM~8{MBh4)(v2#5 zUcAsa!LQ=D;iGKhbLSLgb)ptAJDD=3Gc4Gum}sm3nq7Zsogvc0Qzg>_t%|W6#8afd zLcI$aspHKT2!SNsn2x`TmO#UNg$V~z;iYk9qq){NYo#;a82OcR?DAe+O^wEvZY27z z_rE$k*gYJ28sBhtxAooQM{O5(CP4w9jm;;;BAt;mU;?1!h~6WehHoE-nR)M+sE2v8 z+T_J%Wu7Hh_tPN(-$#4`IeXxfaML2YO<#6CLz~#CUvWLxEYtTZ??i9z{2wQ6Q{huG F005?W@rVEb diff --git a/examples/napi/__test__/values.spec.ts b/examples/napi/__test__/values.spec.ts index 999a77ac..2b884642 100644 --- a/examples/napi/__test__/values.spec.ts +++ b/examples/napi/__test__/values.spec.ts @@ -108,6 +108,8 @@ import { getNumArr, getNestedNumArr, CustomFinalize, + plusOne, + Width, } from '../' test('export const', (t) => { @@ -161,7 +163,7 @@ test('enum', (t) => { t.is(enumToI32(CustomNumEnum.Eight), 8) }) -test('class', (t) => { +test.only('class', (t) => { const dog = new Animal(Kind.Dog, '旺财') t.is(dog.name, '旺财') @@ -192,6 +194,13 @@ test('class', (t) => { const turtle = NinjaTurtle.newRaph() t.is(turtle.returnThis(), turtle) t.is(NinjaTurtle.isInstanceOf(turtle), true) + // Inject this to function + const width = new Width(1) + t.is(plusOne.call(width), 2) + t.throws(() => { + // @ts-expect-error + plusOne.call('') + }) }) test('class factory', (t) => { diff --git a/examples/napi/index.d.ts b/examples/napi/index.d.ts index 0ea1ca8e..970ce77a 100644 --- a/examples/napi/index.d.ts +++ b/examples/napi/index.d.ts @@ -38,6 +38,7 @@ export interface ObjectFieldClassInstance { } export function createObjectWithClassField(): ObjectFieldClassInstance export function receiveObjectWithClassField(object: ObjectFieldClassInstance): Bird +export function plusOne(this: Width): number export function dateToNumber(input: Date): number export function chronoDateToMillis(input: Date): number export function chronoDateAdd1Minute(input: Date): Date @@ -288,6 +289,10 @@ export class NotWritableClass { export class CustomFinalize { constructor(width: number, height: number) } +export class Width { + value: number + constructor(value: number) +} 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 b0c3a545..72c3a5ff 100644 --- a/examples/napi/src/class.rs +++ b/examples/napi/src/class.rs @@ -395,3 +395,13 @@ impl ObjectFinalize for CustomFinalize { Ok(()) } } + +#[napi(constructor)] +pub struct Width { + pub value: i32, +} + +#[napi] +pub fn plus_one(this: This<&Width>) -> i32 { + this.value + 1 +} From 528b1d21cb2a4055dbde2992375ff8396876d3c9 Mon Sep 17 00:00:00 2001 From: LongYinan <lynweklm@gmail.com> Date: Wed, 17 Aug 2022 17:53:44 +0800 Subject: [PATCH 2/2] style: clippy fix --- crates/backend/src/ast.rs | 4 ++-- crates/backend/src/typegen/fn.rs | 2 +- examples/napi/src/lib.rs | 1 + 3 files changed, 4 insertions(+), 3 deletions(-) diff --git a/crates/backend/src/ast.rs b/crates/backend/src/ast.rs index 64677f82..101dfc54 100644 --- a/crates/backend/src/ast.rs +++ b/crates/backend/src/ast.rs @@ -54,7 +54,7 @@ pub enum NapiFnArgKind { Callback(Box<CallbackArg>), } -#[derive(Debug, Clone, PartialEq)] +#[derive(Debug, Clone, PartialEq, Eq)] pub enum FnKind { Normal, Constructor, @@ -84,7 +84,7 @@ pub struct NapiStruct { pub use_custom_finalize: bool, } -#[derive(Debug, Clone, PartialEq)] +#[derive(Debug, Clone, PartialEq, Eq)] pub enum NapiStructKind { None, Constructor, diff --git a/crates/backend/src/typegen/fn.rs b/crates/backend/src/typegen/fn.rs index e9122006..b6ae0fd0 100644 --- a/crates/backend/src/typegen/fn.rs +++ b/crates/backend/src/typegen/fn.rs @@ -153,7 +153,7 @@ impl NapiFn { } if ident == "This" { if let Some(syn::GenericArgument::Type(ty)) = angle_bracketed_args.first() { - let (ts_type, _) = ty_to_ts_type(&ty, false, false); + let (ts_type, _) = ty_to_ts_type(ty, false, false); return Some(FnArg { arg: "this".to_owned(), ts_type, diff --git a/examples/napi/src/lib.rs b/examples/napi/src/lib.rs index 189f1eef..1825406c 100644 --- a/examples/napi/src/lib.rs +++ b/examples/napi/src/lib.rs @@ -1,5 +1,6 @@ #![allow(dead_code)] #![allow(unreachable_code)] +#![allow(clippy::blacklisted_name)] #[macro_use] extern crate napi_derive;