feat(napi-derive): allow injecting this in class method
This commit is contained in:
parent
c3b59c8a12
commit
87fd74cbb6
8 changed files with 51 additions and 24 deletions
|
@ -12,7 +12,7 @@ impl TryToTokens for NapiFn {
|
||||||
let intermediate_ident = get_intermediate_ident(&name_str);
|
let intermediate_ident = get_intermediate_ident(&name_str);
|
||||||
let args_len = self.args.len();
|
let args_len = self.args.len();
|
||||||
|
|
||||||
let (arg_conversions, arg_names) = self.gen_arg_conversions();
|
let (arg_conversions, arg_names) = self.gen_arg_conversions()?;
|
||||||
let receiver = self.gen_fn_receiver();
|
let receiver = self.gen_fn_receiver();
|
||||||
let receiver_ret_name = Ident::new("_ret", Span::call_site());
|
let receiver_ret_name = Ident::new("_ret", Span::call_site());
|
||||||
let ret = self.gen_fn_return(&receiver_ret_name);
|
let ret = self.gen_fn_return(&receiver_ret_name);
|
||||||
|
@ -93,7 +93,7 @@ impl TryToTokens for NapiFn {
|
||||||
}
|
}
|
||||||
|
|
||||||
impl NapiFn {
|
impl NapiFn {
|
||||||
fn gen_arg_conversions(&self) -> (Vec<TokenStream>, Vec<TokenStream>) {
|
fn gen_arg_conversions(&self) -> BindgenResult<(Vec<TokenStream>, Vec<TokenStream>)> {
|
||||||
let mut arg_conversions = vec![];
|
let mut arg_conversions = vec![];
|
||||||
let mut args = vec![];
|
let mut args = vec![];
|
||||||
|
|
||||||
|
@ -117,7 +117,7 @@ impl NapiFn {
|
||||||
}
|
}
|
||||||
|
|
||||||
let mut skipped_arg_count = 0;
|
let mut skipped_arg_count = 0;
|
||||||
self.args.iter().enumerate().for_each(|(i, arg)| {
|
for (i, arg) in self.args.iter().enumerate() {
|
||||||
let i = i - skipped_arg_count;
|
let i = i - skipped_arg_count;
|
||||||
let ident = Ident::new(&format!("arg{}", i), Span::call_site());
|
let ident = Ident::new(&format!("arg{}", i), Span::call_site());
|
||||||
|
|
||||||
|
@ -127,27 +127,41 @@ impl NapiFn {
|
||||||
args.push(quote! { napi::bindgen_prelude::Env::from(env) });
|
args.push(quote! { napi::bindgen_prelude::Env::from(env) });
|
||||||
skipped_arg_count += 1;
|
skipped_arg_count += 1;
|
||||||
} else {
|
} else {
|
||||||
if self.parent.is_some() {
|
let is_in_class = self.parent.is_some();
|
||||||
if let syn::Type::Path(path) = path.ty.as_ref() {
|
if let syn::Type::Path(path) = path.ty.as_ref() {
|
||||||
if let Some(p) = path.path.segments.last() {
|
if let Some(p) = path.path.segments.last() {
|
||||||
if p.ident == "Reference" {
|
if p.ident == "Reference" {
|
||||||
if let syn::PathArguments::AngleBracketed(
|
if !is_in_class {
|
||||||
syn::AngleBracketedGenericArguments { args: angle_bracketed_args, .. },
|
bail_span!(p, "`Reference` is only allowed in class methods");
|
||||||
) = &p.arguments
|
}
|
||||||
|
if let syn::PathArguments::AngleBracketed(syn::AngleBracketedGenericArguments {
|
||||||
|
args: angle_bracketed_args,
|
||||||
|
..
|
||||||
|
}) = &p.arguments
|
||||||
|
{
|
||||||
|
if let Some(syn::GenericArgument::Type(syn::Type::Path(path))) =
|
||||||
|
angle_bracketed_args.first()
|
||||||
{
|
{
|
||||||
if let Some(syn::GenericArgument::Type(syn::Type::Path(path))) = angle_bracketed_args.first() {
|
if let Some(p) = path.path.segments.first() {
|
||||||
if let Some(p) = path.path.segments.first() {
|
if p.ident == *self.parent.as_ref().unwrap() {
|
||||||
if p.ident == *self.parent.as_ref().unwrap() {
|
args.push(
|
||||||
args.push(
|
quote! { napi::bindgen_prelude::Reference::from_value_ptr(this_ptr as *mut std::ffi::c_void, env)? },
|
||||||
quote! { napi::bindgen_prelude::Reference::from_value_ptr(this_ptr as *mut std::ffi::c_void, env)? },
|
);
|
||||||
);
|
skipped_arg_count += 1;
|
||||||
skipped_arg_count += 1;
|
continue;
|
||||||
return;
|
}
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
} else if p.ident == "This" {
|
||||||
|
if !is_in_class {
|
||||||
|
bail_span!(p, "`This` is only allowed in class methods");
|
||||||
|
}
|
||||||
|
args.push(
|
||||||
|
quote! { <napi::bindgen_prelude::This as napi::NapiValue>::from_raw_unchecked(env, cb.this) },
|
||||||
|
);
|
||||||
|
skipped_arg_count += 1;
|
||||||
|
continue;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -160,9 +174,9 @@ impl NapiFn {
|
||||||
args.push(quote! { #ident });
|
args.push(quote! { #ident });
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
});
|
}
|
||||||
|
|
||||||
(arg_conversions, args)
|
Ok((arg_conversions, args))
|
||||||
}
|
}
|
||||||
|
|
||||||
fn gen_ty_arg_conversion(
|
fn gen_ty_arg_conversion(
|
||||||
|
|
|
@ -214,6 +214,7 @@ static KNOWN_TYPES: Lazy<HashMap<&'static str, &'static str>> = Lazy::new(|| {
|
||||||
("unknown", "unknown"),
|
("unknown", "unknown"),
|
||||||
("Unknown", "unknown"),
|
("Unknown", "unknown"),
|
||||||
("JsUnknown", "unknown"),
|
("JsUnknown", "unknown"),
|
||||||
|
("This", "this")
|
||||||
]);
|
]);
|
||||||
|
|
||||||
map
|
map
|
||||||
|
|
|
@ -2,7 +2,9 @@ use std::any::type_name;
|
||||||
use std::ops::{Deref, DerefMut};
|
use std::ops::{Deref, DerefMut};
|
||||||
use std::ptr;
|
use std::ptr;
|
||||||
|
|
||||||
use crate::{bindgen_runtime::FromNapiValue, check_status, sys, NapiRaw};
|
use crate::{bindgen_runtime::FromNapiValue, check_status, sys, JsObject, NapiRaw};
|
||||||
|
|
||||||
|
pub type This = JsObject;
|
||||||
|
|
||||||
pub struct ClassInstance<T: 'static> {
|
pub struct ClassInstance<T: 'static> {
|
||||||
pub value: sys::napi_value,
|
pub value: sys::napi_value,
|
||||||
|
|
|
@ -254,6 +254,7 @@ Generated by [AVA](https://avajs.dev).
|
||||||
static newRaph(): NinjaTurtle␊
|
static newRaph(): NinjaTurtle␊
|
||||||
getMaskColor(): string␊
|
getMaskColor(): string␊
|
||||||
getName(): string␊
|
getName(): string␊
|
||||||
|
returnThis(this: this): this␊
|
||||||
}␊
|
}␊
|
||||||
export type JsAssets = Assets␊
|
export type JsAssets = Assets␊
|
||||||
export class Assets {␊
|
export class Assets {␊
|
||||||
|
|
Binary file not shown.
|
@ -21,6 +21,7 @@ import {
|
||||||
getCwd,
|
getCwd,
|
||||||
Animal,
|
Animal,
|
||||||
Kind,
|
Kind,
|
||||||
|
NinjaTurtle,
|
||||||
ClassWithFactory,
|
ClassWithFactory,
|
||||||
CustomNumEnum,
|
CustomNumEnum,
|
||||||
Context,
|
Context,
|
||||||
|
@ -173,6 +174,8 @@ test('class', (t) => {
|
||||||
t.is(dog.type, Kind.Cat)
|
t.is(dog.type, Kind.Cat)
|
||||||
const assets = new Assets()
|
const assets = new Assets()
|
||||||
t.is(assets.get(1)?.filePath, 1)
|
t.is(assets.get(1)?.filePath, 1)
|
||||||
|
const turtle = NinjaTurtle.newRaph()
|
||||||
|
t.is(turtle.returnThis(), turtle)
|
||||||
})
|
})
|
||||||
|
|
||||||
test('class factory', (t) => {
|
test('class factory', (t) => {
|
||||||
|
|
1
examples/napi/index.d.ts
vendored
1
examples/napi/index.d.ts
vendored
|
@ -244,6 +244,7 @@ export class NinjaTurtle {
|
||||||
static newRaph(): NinjaTurtle
|
static newRaph(): NinjaTurtle
|
||||||
getMaskColor(): string
|
getMaskColor(): string
|
||||||
getName(): string
|
getName(): string
|
||||||
|
returnThis(this: this): this
|
||||||
}
|
}
|
||||||
export type JsAssets = Assets
|
export type JsAssets = Assets
|
||||||
export class Assets {
|
export class Assets {
|
||||||
|
|
|
@ -1,5 +1,5 @@
|
||||||
use napi::{
|
use napi::{
|
||||||
bindgen_prelude::{Buffer, ClassInstance},
|
bindgen_prelude::{Buffer, ClassInstance, This},
|
||||||
Env, Result,
|
Env, Result,
|
||||||
};
|
};
|
||||||
|
|
||||||
|
@ -229,6 +229,11 @@ impl NinjaTurtle {
|
||||||
pub fn get_name(&self) -> &str {
|
pub fn get_name(&self) -> &str {
|
||||||
self.name.as_str()
|
self.name.as_str()
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#[napi]
|
||||||
|
pub fn return_this(&self, this: This) -> This {
|
||||||
|
this
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
#[napi(js_name = "Assets")]
|
#[napi(js_name = "Assets")]
|
||||||
|
|
Loading…
Reference in a new issue