From 711372e175115acb2eda08c36a32fcd381f28ef5 Mon Sep 17 00:00:00 2001 From: LongYinan Date: Wed, 17 Aug 2022 15:11:32 +0800 Subject: [PATCH] feat(napi-derive): implement instance_of for Class --- crates/backend/src/codegen/struct.rs | 32 ++++++++++++++++++-- examples/napi/__test__/typegen.spec.ts.md | 1 + examples/napi/__test__/typegen.spec.ts.snap | Bin 3515 -> 3531 bytes examples/napi/__test__/values.spec.ts | 1 + examples/napi/index.d.ts | 1 + examples/napi/src/class.rs | 7 ++++- 6 files changed, 39 insertions(+), 3 deletions(-) diff --git a/crates/backend/src/codegen/struct.rs b/crates/backend/src/codegen/struct.rs index 411825db19..4971558cd4 100644 --- a/crates/backend/src/codegen/struct.rs +++ b/crates/backend/src/codegen/struct.rs @@ -283,6 +283,7 @@ impl NapiStruct { } else { quote! { impl napi::bindgen_prelude::ObjectFinalize for #name {} } }; + let instance_of_impl = self.gen_instance_of_impl(name, &js_name_str); quote! { impl napi::bindgen_prelude::ToNapiValue for #name { unsafe fn to_napi_value( @@ -303,7 +304,7 @@ impl NapiStruct { } #finalize_trait - + #instance_of_impl impl #name { pub fn into_reference(val: #name, env: napi::Env) -> napi::Result> { if let Some(ctor_ref) = napi::bindgen_prelude::get_class_constructor(#js_name_str) { @@ -394,6 +395,7 @@ impl NapiStruct { let name = &self.name; let js_name_without_null = &self.js_name; let js_name_str = format!("{}\0", &self.js_name); + let instance_of_impl = self.gen_instance_of_impl(name, &js_name_str); let mut field_conversions = vec![]; let mut field_destructions = vec![]; @@ -466,7 +468,7 @@ impl NapiStruct { } } } - + #instance_of_impl #finalize_trait } } @@ -750,6 +752,32 @@ impl NapiStruct { } } } + + fn gen_instance_of_impl(&self, name: &Ident, js_name: &str) -> TokenStream { + quote! { + impl #name { + pub fn instance_of(env: napi::Env, value: V) -> napi::Result { + if let Some(ctor_ref) = napi::bindgen_prelude::get_class_constructor(#js_name) { + let mut ctor = std::ptr::null_mut(); + napi::check_status!( + unsafe { napi::sys::napi_get_reference_value(env.raw(), ctor_ref, &mut ctor) }, + "Failed to get constructor reference of class `{}`", + #js_name + )?; + let mut is_instance_of = false; + napi::check_status!( + unsafe { napi::sys::napi_instanceof(env.raw(), value.raw(), ctor, &mut is_instance_of) }, + "Failed to run instanceof for class `{}`", + #js_name + )?; + Ok(is_instance_of) + } else { + Err(napi::Error::new(napi::Status::GenericFailure, format!("Failed to get constructor of class `{}`", #js_name))) + } + } + } + } + } } impl TryToTokens for NapiImpl { diff --git a/examples/napi/__test__/typegen.spec.ts.md b/examples/napi/__test__/typegen.spec.ts.md index 335a908ad3..00c6ddf5d2 100644 --- a/examples/napi/__test__/typegen.spec.ts.md +++ b/examples/napi/__test__/typegen.spec.ts.md @@ -267,6 +267,7 @@ Generated by [AVA](https://avajs.dev). }␊ export class NinjaTurtle {␊ name: string␊ + static isInstanceOf(value: unknown): boolean␊ /** Create your ninja turtle! 🐢 */␊ static newRaph(): NinjaTurtle␊ getMaskColor(): string␊ diff --git a/examples/napi/__test__/typegen.spec.ts.snap b/examples/napi/__test__/typegen.spec.ts.snap index 77b9d6a1502dad84611b3c2805597b7e8c05a00e..17f9c8a756eae3f6d8fd16a88aa44954a667c46c 100644 GIT binary patch literal 3531 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 F005?W@rVEb literal 3515 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 { t.is(assets.get(1)?.filePath, 1) const turtle = NinjaTurtle.newRaph() t.is(turtle.returnThis(), turtle) + t.is(NinjaTurtle.isInstanceOf(turtle), true) }) test('class factory', (t) => { diff --git a/examples/napi/index.d.ts b/examples/napi/index.d.ts index ca259111bf..0ea1ca8ebd 100644 --- a/examples/napi/index.d.ts +++ b/examples/napi/index.d.ts @@ -257,6 +257,7 @@ export class AnimalWithDefaultConstructor { } export class NinjaTurtle { name: string + static isInstanceOf(value: unknown): boolean /** Create your ninja turtle! 🐢 */ static newRaph(): NinjaTurtle getMaskColor(): string diff --git a/examples/napi/src/class.rs b/examples/napi/src/class.rs index 01ed6b6d33..b0c3a54500 100644 --- a/examples/napi/src/class.rs +++ b/examples/napi/src/class.rs @@ -1,5 +1,5 @@ use napi::{ - bindgen_prelude::{Buffer, ClassInstance, ObjectFinalize, This, Uint8Array}, + bindgen_prelude::{Buffer, ClassInstance, ObjectFinalize, This, Uint8Array, Unknown}, Env, Result, }; @@ -214,6 +214,11 @@ pub struct NinjaTurtle { #[napi] impl NinjaTurtle { + #[napi] + pub fn is_instance_of(env: Env, value: Unknown) -> Result { + Self::instance_of(env, value) + } + /// Create your ninja turtle! 🐢 #[napi(factory)] pub fn new_raph() -> Self {