feat(napi-derive): implement instance_of for Class

This commit is contained in:
LongYinan 2022-08-17 15:11:32 +08:00
parent 8d0045f5b6
commit 711372e175
No known key found for this signature in database
GPG key ID: C3666B7FC82ADAD7
6 changed files with 39 additions and 3 deletions

View file

@ -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<napi::bindgen_prelude::Reference<#name>> {
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<V: napi::NapiRaw>(env: napi::Env, value: V) -> napi::Result<bool> {
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 {

View file

@ -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␊

View file

@ -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) => {

View file

@ -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

View file

@ -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<bool> {
Self::instance_of(env, value)
}
/// Create your ninja turtle! 🐢
#[napi(factory)]
pub fn new_raph() -> Self {