fix(napi-derive): return instance from non-default constructor class
Fix https://github.com/napi-rs/napi-rs/issues/933
This commit is contained in:
parent
c25cfc5773
commit
e6a30ffcca
7 changed files with 76 additions and 2 deletions
|
@ -1,3 +1,5 @@
|
|||
import { platform } from 'os'
|
||||
|
||||
import test from 'ava'
|
||||
|
||||
import { parseTriple, getDefaultTargetTriple } from '../parse-triple'
|
||||
|
@ -121,7 +123,10 @@ for (const triple of triples) {
|
|||
})
|
||||
}
|
||||
|
||||
test('should parse default triple from rustup show active', (t) => {
|
||||
const MaybeTest =
|
||||
process.arch !== 'x64' && platform() === 'linux' ? test.skip : test
|
||||
|
||||
MaybeTest('should parse default triple from rustup show active', (t) => {
|
||||
t.deepEqual(
|
||||
getDefaultTargetTriple(
|
||||
`x86_64-unknown-linux-gnu (directory override for '/home/runner/work/fast-escape/fast-escape')`,
|
||||
|
|
|
@ -153,7 +153,10 @@ impl NapiStruct {
|
|||
|
||||
fn gen_napi_value_map_impl(&self) -> TokenStream {
|
||||
match self.kind {
|
||||
NapiStructKind::None => gen_napi_value_map_impl(&self.name, quote! {}),
|
||||
NapiStructKind::None => gen_napi_value_map_impl(
|
||||
&self.name,
|
||||
self.gen_to_napi_value_ctor_impl_for_non_default_constructor_struct(),
|
||||
),
|
||||
NapiStructKind::Constructor => {
|
||||
gen_napi_value_map_impl(&self.name, self.gen_to_napi_value_ctor_impl())
|
||||
}
|
||||
|
@ -161,6 +164,42 @@ impl NapiStruct {
|
|||
}
|
||||
}
|
||||
|
||||
fn gen_to_napi_value_ctor_impl_for_non_default_constructor_struct(&self) -> TokenStream {
|
||||
let name = &self.name;
|
||||
let js_name_str = format!("{}\0", &self.js_name);
|
||||
quote! {
|
||||
impl napi::bindgen_prelude::ToNapiValue for #name {
|
||||
unsafe fn to_napi_value(
|
||||
env: napi::bindgen_prelude::sys::napi_env, val: #name
|
||||
) -> napi::bindgen_prelude::Result<napi::bindgen_prelude::sys::napi_value> {
|
||||
if let Some(ctor_ref) = napi::bindgen_prelude::get_class_constructor(#js_name_str) {
|
||||
let mut ctor = std::ptr::null_mut();
|
||||
|
||||
napi::bindgen_prelude::check_status!(
|
||||
napi::bindgen_prelude::sys::napi_get_reference_value(env, ctor_ref, &mut ctor),
|
||||
"Failed to get constructor of class `{}`",
|
||||
#js_name_str
|
||||
)?;
|
||||
|
||||
let mut result = std::ptr::null_mut();
|
||||
napi::bindgen_prelude::___CALL_FROM_FACTORY.store(true, std::sync::atomic::Ordering::Relaxed);
|
||||
napi::bindgen_prelude::check_status!(
|
||||
napi::bindgen_prelude::sys::napi_new_instance(env, ctor, 0, std::ptr::null_mut(), &mut result),
|
||||
"Failed to construct class `{}`",
|
||||
#js_name_str
|
||||
)?;
|
||||
napi::bindgen_prelude::___CALL_FROM_FACTORY.store(false, std::sync::atomic::Ordering::Relaxed);
|
||||
Ok(result)
|
||||
} else {
|
||||
Err(napi::bindgen_prelude::Error::new(
|
||||
napi::bindgen_prelude::Status::InvalidArg, format!("Failed to get constructor of class `{}`", #js_name_str))
|
||||
)
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
fn gen_to_napi_value_ctor_impl(&self) -> TokenStream {
|
||||
let name = &self.name;
|
||||
let js_name_str = format!("{}\0", &self.js_name);
|
||||
|
|
|
@ -145,11 +145,16 @@ Generated by [AVA](https://avajs.dev).
|
|||
/** This is static... */␊
|
||||
static getDogKind(): Kind␊
|
||||
returnOtherClass(): Dog␊
|
||||
returnOtherClassWithCustomConstructor(): Bird␊
|
||||
}␊
|
||||
export class Dog {␊
|
||||
name: string␊
|
||||
constructor(name: string)␊
|
||||
}␊
|
||||
export class Bird {␊
|
||||
name: string␊
|
||||
constructor(name: string)␊
|
||||
}␊
|
||||
/** Smoking test for type generation */␊
|
||||
export class Blake2BHasher {␊
|
||||
static withKey(key: Blake2bKey): Blake2BHasher␊
|
||||
|
|
Binary file not shown.
|
@ -70,6 +70,7 @@ import {
|
|||
returnNull,
|
||||
returnUndefined,
|
||||
Dog,
|
||||
Bird,
|
||||
} from '../'
|
||||
|
||||
test('export const', (t) => {
|
||||
|
@ -127,6 +128,7 @@ test('class', (t) => {
|
|||
dog.name = '可乐'
|
||||
t.is(dog.name, '可乐')
|
||||
t.deepEqual(dog.returnOtherClass(), new Dog('Doge'))
|
||||
t.deepEqual(dog.returnOtherClassWithCustomConstructor(), new Bird('parrot'))
|
||||
})
|
||||
|
||||
test('class factory', (t) => {
|
||||
|
|
5
examples/napi/index.d.ts
vendored
5
examples/napi/index.d.ts
vendored
|
@ -135,11 +135,16 @@ export class Animal {
|
|||
/** This is static... */
|
||||
static getDogKind(): Kind
|
||||
returnOtherClass(): Dog
|
||||
returnOtherClassWithCustomConstructor(): Bird
|
||||
}
|
||||
export class Dog {
|
||||
name: string
|
||||
constructor(name: string)
|
||||
}
|
||||
export class Bird {
|
||||
name: string
|
||||
constructor(name: string)
|
||||
}
|
||||
/** Smoking test for type generation */
|
||||
export class Blake2BHasher {
|
||||
static withKey(key: Blake2bKey): Blake2BHasher
|
||||
|
|
|
@ -67,6 +67,11 @@ impl Animal {
|
|||
name: "Doge".to_owned(),
|
||||
}
|
||||
}
|
||||
|
||||
#[napi]
|
||||
pub fn return_other_class_with_custom_constructor(&self) -> Bird {
|
||||
Bird::new("parrot".to_owned())
|
||||
}
|
||||
}
|
||||
|
||||
#[napi(constructor)]
|
||||
|
@ -74,6 +79,19 @@ pub struct Dog {
|
|||
pub name: String,
|
||||
}
|
||||
|
||||
#[napi]
|
||||
pub struct Bird {
|
||||
pub name: String,
|
||||
}
|
||||
|
||||
#[napi]
|
||||
impl Bird {
|
||||
#[napi(constructor)]
|
||||
pub fn new(name: String) -> Self {
|
||||
Bird { name }
|
||||
}
|
||||
}
|
||||
|
||||
/// Smoking test for type generation
|
||||
#[napi]
|
||||
#[repr(transparent)]
|
||||
|
|
Loading…
Reference in a new issue