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 77b9d6a150..17f9c8a756 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 e688c6f7e7..999a77ac0a 100644 --- a/examples/napi/__test__/values.spec.ts +++ b/examples/napi/__test__/values.spec.ts @@ -191,6 +191,7 @@ test('class', (t) => { 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 {