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 test from 'ava'
|
||||||
|
|
||||||
import { parseTriple, getDefaultTargetTriple } from '../parse-triple'
|
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(
|
t.deepEqual(
|
||||||
getDefaultTargetTriple(
|
getDefaultTargetTriple(
|
||||||
`x86_64-unknown-linux-gnu (directory override for '/home/runner/work/fast-escape/fast-escape')`,
|
`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 {
|
fn gen_napi_value_map_impl(&self) -> TokenStream {
|
||||||
match self.kind {
|
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 => {
|
NapiStructKind::Constructor => {
|
||||||
gen_napi_value_map_impl(&self.name, self.gen_to_napi_value_ctor_impl())
|
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 {
|
fn gen_to_napi_value_ctor_impl(&self) -> TokenStream {
|
||||||
let name = &self.name;
|
let name = &self.name;
|
||||||
let js_name_str = format!("{}\0", &self.js_name);
|
let js_name_str = format!("{}\0", &self.js_name);
|
||||||
|
|
|
@ -145,11 +145,16 @@ Generated by [AVA](https://avajs.dev).
|
||||||
/** This is static... */␊
|
/** This is static... */␊
|
||||||
static getDogKind(): Kind␊
|
static getDogKind(): Kind␊
|
||||||
returnOtherClass(): Dog␊
|
returnOtherClass(): Dog␊
|
||||||
|
returnOtherClassWithCustomConstructor(): Bird␊
|
||||||
}␊
|
}␊
|
||||||
export class Dog {␊
|
export class Dog {␊
|
||||||
name: string␊
|
name: string␊
|
||||||
constructor(name: string)␊
|
constructor(name: string)␊
|
||||||
}␊
|
}␊
|
||||||
|
export class Bird {␊
|
||||||
|
name: string␊
|
||||||
|
constructor(name: string)␊
|
||||||
|
}␊
|
||||||
/** Smoking test for type generation */␊
|
/** Smoking test for type generation */␊
|
||||||
export class Blake2BHasher {␊
|
export class Blake2BHasher {␊
|
||||||
static withKey(key: Blake2bKey): Blake2BHasher␊
|
static withKey(key: Blake2bKey): Blake2BHasher␊
|
||||||
|
|
Binary file not shown.
|
@ -70,6 +70,7 @@ import {
|
||||||
returnNull,
|
returnNull,
|
||||||
returnUndefined,
|
returnUndefined,
|
||||||
Dog,
|
Dog,
|
||||||
|
Bird,
|
||||||
} from '../'
|
} from '../'
|
||||||
|
|
||||||
test('export const', (t) => {
|
test('export const', (t) => {
|
||||||
|
@ -127,6 +128,7 @@ test('class', (t) => {
|
||||||
dog.name = '可乐'
|
dog.name = '可乐'
|
||||||
t.is(dog.name, '可乐')
|
t.is(dog.name, '可乐')
|
||||||
t.deepEqual(dog.returnOtherClass(), new Dog('Doge'))
|
t.deepEqual(dog.returnOtherClass(), new Dog('Doge'))
|
||||||
|
t.deepEqual(dog.returnOtherClassWithCustomConstructor(), new Bird('parrot'))
|
||||||
})
|
})
|
||||||
|
|
||||||
test('class factory', (t) => {
|
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... */
|
/** This is static... */
|
||||||
static getDogKind(): Kind
|
static getDogKind(): Kind
|
||||||
returnOtherClass(): Dog
|
returnOtherClass(): Dog
|
||||||
|
returnOtherClassWithCustomConstructor(): Bird
|
||||||
}
|
}
|
||||||
export class Dog {
|
export class Dog {
|
||||||
name: string
|
name: string
|
||||||
constructor(name: string)
|
constructor(name: string)
|
||||||
}
|
}
|
||||||
|
export class Bird {
|
||||||
|
name: string
|
||||||
|
constructor(name: string)
|
||||||
|
}
|
||||||
/** Smoking test for type generation */
|
/** Smoking test for type generation */
|
||||||
export class Blake2BHasher {
|
export class Blake2BHasher {
|
||||||
static withKey(key: Blake2bKey): Blake2BHasher
|
static withKey(key: Blake2bKey): Blake2BHasher
|
||||||
|
|
|
@ -67,6 +67,11 @@ impl Animal {
|
||||||
name: "Doge".to_owned(),
|
name: "Doge".to_owned(),
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#[napi]
|
||||||
|
pub fn return_other_class_with_custom_constructor(&self) -> Bird {
|
||||||
|
Bird::new("parrot".to_owned())
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
#[napi(constructor)]
|
#[napi(constructor)]
|
||||||
|
@ -74,6 +79,19 @@ pub struct Dog {
|
||||||
pub name: String,
|
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
|
/// Smoking test for type generation
|
||||||
#[napi]
|
#[napi]
|
||||||
#[repr(transparent)]
|
#[repr(transparent)]
|
||||||
|
|
Loading…
Reference in a new issue