feat(napi): new Function/FunctionRef API (#1913)
This is the experimental feature that provides a all new design `Function` API in NAPI-RS. The main motivation to design a new `Function` instead of improving the old `JsFunction` is there are some fundamental problems in the old `JsFunction` API. 1. The old `JsFunction` doesn't contains a lifetime, which means you can send it to a outlive scope and call it later, which would cause a `napi_invalid_arg` error in the underlying `napi_call_function` API. This design issue also happens in the `JsObject`/`JsBuffer` and all other non-primitive types APIs. 2. It's not possible to generate correct TypeScript type definitions for the old `JsFunction` API. 3. The arguments of the old `JsFunction` API must be the same type, which is makes it really unfriendly to use. Expect that, we also have a high level and modern Function exists in the `NAPI-RS` which is the Generic type style `Fn(Args) -> Return`. This API is pretty nice to use, and more importantly, it's sound. But there are some limitations to use it, like create a reference to it to outlive the scope of the JavaScript function under the hood. And you can't use it create a `ThreadsafeFunction`. So there is the new design `Function` API, there are some core features: 1. It's a generic typed API, which means you can get more accurate Rust type information and generate correct TypeScript type definitions. 2. It's sound, which means you can't send it to a outlive scope and call it later, if you want do that, you must create a reference to it or create a `ThreadsafeFunction`. 3. It's friendly to use, you can use different types of arguments and return types, and it can covert the Rust tuple type to JavaScript arguments automatically. Here is some examples to show how to use it: ```rust use napi::bindgen_prelude::*; use napi_derive::napi; #[napi] pub fn callback_javascript_callback(add_one: Function<u32, u32>) -> Result<u32> { add_one.call(100) } ``` ⬇️⬇️⬇️ ```typescript export function callbackJavascriptCallback(add_one: (arg0: number) => number): number; ``` ⬇️⬇️⬇️ ```javascript callbackJavascriptCallback((arg0) => arg0 + 1); // 101 ``` If you define a tuple as the `Function` arguments, it will be converted to JavaScript arguments automatically. ```rust use napi::bindgen_prelude::*; use napi_derive::napi; #[napi] pub fn callback_javascript_callback(add: Function<(u32, u32), u32>) -> Result<u32> { add.call((100, 200)) } ``` ⬇️⬇️⬇️ ```typescript export function callbackJavascriptCallback(add: (arg0: number, arg1: number) => number): number; ``` ⬇️⬇️⬇️ ```javascript callbackJavascriptCallback((arg0, arg1) => arg0 + arg1); // 300 ``` If you are trying to send it into a outlive scope, you will get a compile error. For example, if you are trying to send a callback to `git2-rs` `RemoteCallbacks::credentials` API: ```rust use napi::bindgen_prelude::*; use napi_derive::napi; #[napi] pub fn build_credential(on_credential: Function<(String, Option<String>, CredentialType), ClassInstance<Cred>>) -> Result<()> { let mut callbacks = git2::RemoteCallbacks::new(); callbacks.credentials(move |url, username_from_url, allowed_types| { on_credential.call((url.to_string(), username_from_url.map(|s| s.to_string()), allowed_types.into())) .map(...) .map_error(...) }); } ``` You will get a compile error: ```text error[E0597]: `on_credential` does not live long enough ``` To fix this issue, you can create a reference to it: ```rust use napi::bindgen_prelude::*; use napi_derive::napi; #[napi] pub fn build_credential(env: Env. on_credential: Function<(String, Option<String>, CredentialType), ClassInstance<Cred>>) -> Result<()> { let mut callbacks = git2::RemoteCallbacks::new(); let on_credential_ref = on_credential.create_ref()?; callbacks.credentials(move |url, username_from_url, allowed_types| { let on_credential = on_credential_ref.borrow_back(&env)?; on_credential.call((url.to_string(), username_from_url.map(|s| s.to_string()), allowed_types.into())) .map(...) .map_error(...) }); } ```
This commit is contained in:
commit
baf0db2f19
15 changed files with 836 additions and 313 deletions
|
@ -151,18 +151,6 @@ fn gen_napi_value_map_impl(name: &Ident, to_napi_val_impl: TokenStream) -> Token
|
|||
impl napi::bindgen_prelude::ValidateNapiValue for &mut #name {
|
||||
#validate
|
||||
}
|
||||
|
||||
impl napi::NapiRaw for &#name {
|
||||
unsafe fn raw(&self) -> napi::sys::napi_value {
|
||||
unreachable!()
|
||||
}
|
||||
}
|
||||
|
||||
impl napi::NapiRaw for &mut #name {
|
||||
unsafe fn raw(&self) -> napi::sys::napi_value {
|
||||
unreachable!()
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
@ -173,6 +173,8 @@ static KNOWN_TYPES: Lazy<HashMap<&'static str, (&'static str, bool, bool)>> = La
|
|||
("JsTypeError", ("TypeError", false, false)),
|
||||
("JsRangeError", ("RangeError", false, false)),
|
||||
("ClassInstance", ("{}", false, false)),
|
||||
("Function", ("({}) => {}", true, false)),
|
||||
("FunctionRef", ("({}) => {}", true, false)),
|
||||
("Either", ("{} | {}", false, true)),
|
||||
("Either3", ("{} | {} | {}", false, true)),
|
||||
("Either4", ("{} | {} | {} | {}", false, true)),
|
||||
|
@ -241,9 +243,11 @@ fn is_ts_union_type(rust_ty: &str) -> bool {
|
|||
}
|
||||
|
||||
const TSFN_RUST_TY: &str = "ThreadsafeFunction";
|
||||
const FUNCTION_TY: &str = "Function";
|
||||
const FUNCTION_REF_TY: &str = "FunctionRef";
|
||||
|
||||
fn should_convert_tuple_to_variadic(rust_ty: &str) -> bool {
|
||||
rust_ty == TSFN_RUST_TY
|
||||
fn is_generic_function_type(rust_ty: &str) -> bool {
|
||||
rust_ty == TSFN_RUST_TY || rust_ty == FUNCTION_TY || rust_ty == FUNCTION_REF_TY
|
||||
}
|
||||
|
||||
fn is_ts_function_type_notation(ty: &Type) -> bool {
|
||||
|
@ -253,7 +257,7 @@ fn is_ts_function_type_notation(ty: &Type) -> bool {
|
|||
let rust_ty = ident.to_string();
|
||||
return KNOWN_TYPES
|
||||
.get(&*rust_ty)
|
||||
.map(|&(_, is_ts_fn, _)| is_ts_fn)
|
||||
.map(|&(_, is_fn, _)| is_fn)
|
||||
.unwrap_or(false);
|
||||
}
|
||||
|
||||
|
@ -263,25 +267,33 @@ fn is_ts_function_type_notation(ty: &Type) -> bool {
|
|||
}
|
||||
}
|
||||
|
||||
// return (type, is_optional, is_variadic)
|
||||
// return (type, is_optional)
|
||||
pub fn ty_to_ts_type(
|
||||
ty: &Type,
|
||||
is_return_ty: bool,
|
||||
is_struct_field: bool,
|
||||
convert_tuple_to_variadic: bool,
|
||||
) -> (String, bool, bool) {
|
||||
) -> (String, bool) {
|
||||
match ty {
|
||||
Type::Reference(r) => ty_to_ts_type(&r.elem, is_return_ty, is_struct_field, false),
|
||||
Type::Tuple(tuple) => {
|
||||
if tuple.elems.is_empty() {
|
||||
("undefined".to_owned(), false, false)
|
||||
if convert_tuple_to_variadic {
|
||||
if is_return_ty {
|
||||
("void".to_owned(), false)
|
||||
} else {
|
||||
("".to_owned(), false)
|
||||
}
|
||||
} else {
|
||||
("undefined".to_owned(), false)
|
||||
}
|
||||
} else if convert_tuple_to_variadic {
|
||||
let variadic = &tuple
|
||||
.elems
|
||||
.iter()
|
||||
.enumerate()
|
||||
.map(|(i, arg)| {
|
||||
let (ts_type, is_optional, _) = ty_to_ts_type(arg, false, false, false);
|
||||
let (ts_type, is_optional) = ty_to_ts_type(arg, false, false, false);
|
||||
r#fn::FnArg {
|
||||
arg: format!("arg{}", i),
|
||||
ts_type,
|
||||
|
@ -289,7 +301,7 @@ pub fn ty_to_ts_type(
|
|||
}
|
||||
})
|
||||
.collect::<r#fn::FnArgList>();
|
||||
(format!("{}", variadic), false, true)
|
||||
(format!("{}", variadic), false)
|
||||
} else {
|
||||
(
|
||||
format!(
|
||||
|
@ -302,7 +314,6 @@ pub fn ty_to_ts_type(
|
|||
.join(", ")
|
||||
),
|
||||
false,
|
||||
false,
|
||||
)
|
||||
}
|
||||
}
|
||||
|
@ -316,18 +327,19 @@ pub fn ty_to_ts_type(
|
|||
arguments
|
||||
.args
|
||||
.iter()
|
||||
.filter_map(|arg| match arg {
|
||||
.enumerate()
|
||||
.filter_map(|(index, arg)| match arg {
|
||||
syn::GenericArgument::Type(generic_ty) => Some(ty_to_ts_type(
|
||||
generic_ty,
|
||||
index == 1 && is_generic_function_type(&rust_ty),
|
||||
false,
|
||||
false,
|
||||
should_convert_tuple_to_variadic(&rust_ty),
|
||||
is_generic_function_type(&rust_ty),
|
||||
))
|
||||
.map(|(mut ty, is_optional, is_variadic)| {
|
||||
.map(|(mut ty, is_optional)| {
|
||||
if is_ts_union_type && is_ts_function_type_notation(generic_ty) {
|
||||
ty = format!("({})", ty);
|
||||
}
|
||||
(ty, is_optional, is_variadic)
|
||||
(ty, is_optional)
|
||||
}),
|
||||
_ => None,
|
||||
})
|
||||
|
@ -339,7 +351,7 @@ pub fn ty_to_ts_type(
|
|||
if rust_ty == "Result" && is_return_ty {
|
||||
ts_ty = Some(args.first().unwrap().to_owned());
|
||||
} else if rust_ty == "Option" {
|
||||
ts_ty = args.first().map(|(arg, _, _)| {
|
||||
ts_ty = args.first().map(|(arg, _)| {
|
||||
(
|
||||
if is_struct_field {
|
||||
arg.to_string()
|
||||
|
@ -349,80 +361,57 @@ pub fn ty_to_ts_type(
|
|||
format!("{} | undefined | null", arg)
|
||||
},
|
||||
true,
|
||||
false,
|
||||
)
|
||||
});
|
||||
} else if rust_ty == "AsyncTask" {
|
||||
ts_ty = r#struct::TASK_STRUCTS.with(|t| {
|
||||
let (output_type, _, _) = args.first().unwrap().to_owned();
|
||||
let (output_type, _) = args.first().unwrap().to_owned();
|
||||
if let Some(o) = t.borrow().get(&output_type) {
|
||||
Some((format!("Promise<{}>", o), false, false))
|
||||
Some((format!("Promise<{}>", o), false))
|
||||
} else {
|
||||
Some(("Promise<unknown>".to_owned(), false, false))
|
||||
Some(("Promise<unknown>".to_owned(), false))
|
||||
}
|
||||
});
|
||||
} else if rust_ty == "Reference" || rust_ty == "WeakReference" {
|
||||
ts_ty = r#struct::TASK_STRUCTS.with(|t| {
|
||||
// Reference<T> => T
|
||||
if let Some(arg) = args.first() {
|
||||
let (output_type, _, _) = arg.to_owned();
|
||||
let (output_type, _) = arg.to_owned();
|
||||
if let Some(o) = t.borrow().get(&output_type) {
|
||||
Some((o.to_owned(), false, false))
|
||||
Some((o.to_owned(), false))
|
||||
} else {
|
||||
Some((output_type, false, false))
|
||||
Some((output_type, false))
|
||||
}
|
||||
} else {
|
||||
// Not NAPI-RS `Reference`
|
||||
Some((rust_ty, false, false))
|
||||
Some((rust_ty, false))
|
||||
}
|
||||
});
|
||||
} else if let Some(&(known_ty, _, _)) = KNOWN_TYPES.get(rust_ty.as_str()) {
|
||||
if known_ty.contains("{}") {
|
||||
if rust_ty == "()" && is_return_ty {
|
||||
ts_ty = Some(("void".to_owned(), false));
|
||||
} else if known_ty.contains("{}") {
|
||||
ts_ty = Some((
|
||||
fill_ty(known_ty, args.into_iter().map(|(arg, _, _)| arg).collect()),
|
||||
false,
|
||||
fill_ty(known_ty, args.into_iter().map(|(arg, _)| arg).collect()),
|
||||
false,
|
||||
));
|
||||
} else {
|
||||
ts_ty = Some((known_ty.to_owned(), false, false));
|
||||
ts_ty = Some((known_ty.to_owned(), false));
|
||||
}
|
||||
} else if let Some(t) = crate::typegen::r#struct::CLASS_STRUCTS
|
||||
.with(|c| c.borrow_mut().get(rust_ty.as_str()).cloned())
|
||||
{
|
||||
ts_ty = Some((t, false, false));
|
||||
ts_ty = Some((t, false));
|
||||
} else if rust_ty == TSFN_RUST_TY {
|
||||
let fatal_tsfn = match args.get(1) {
|
||||
Some((arg, _, _)) => arg == "Fatal",
|
||||
Some((arg, _)) => arg == "Fatal",
|
||||
_ => false,
|
||||
};
|
||||
let (args, is_variadic) = args
|
||||
.first()
|
||||
.map(|(arg, _, is_variadic)| (arg, is_variadic))
|
||||
.unwrap();
|
||||
let args = args.first().map(|(arg, _)| arg).unwrap();
|
||||
ts_ty = if fatal_tsfn {
|
||||
Some((
|
||||
{
|
||||
if *is_variadic {
|
||||
format!("({}) => any", args)
|
||||
} else {
|
||||
format!("(value: {}) => any", args)
|
||||
}
|
||||
},
|
||||
false,
|
||||
false,
|
||||
))
|
||||
Some((format!("({}) => any", args), false))
|
||||
} else {
|
||||
Some((
|
||||
{
|
||||
if *is_variadic {
|
||||
format!("(err: Error | null, {}) => any", args)
|
||||
} else {
|
||||
format!("(err: Error | null, value: {}) => any", args)
|
||||
}
|
||||
},
|
||||
false,
|
||||
false,
|
||||
))
|
||||
Some((format!("(err: Error | null, {}) => any", args), false))
|
||||
};
|
||||
} else {
|
||||
// there should be runtime registered type in else
|
||||
|
@ -430,25 +419,31 @@ pub fn ty_to_ts_type(
|
|||
aliases
|
||||
.borrow()
|
||||
.get(rust_ty.as_str())
|
||||
.map(|a| (a.to_owned(), false, false))
|
||||
.map(|a| (a.to_owned(), false))
|
||||
});
|
||||
ts_ty = type_alias.or(Some((rust_ty, false, false)));
|
||||
ts_ty = type_alias.or(Some((rust_ty, false)));
|
||||
}
|
||||
}
|
||||
|
||||
ts_ty.unwrap_or_else(|| ("any".to_owned(), false, false))
|
||||
let (ty, is_optional) = ts_ty.unwrap_or_else(|| ("any".to_owned(), false));
|
||||
(
|
||||
(convert_tuple_to_variadic && !is_return_ty)
|
||||
.then(|| format!("arg: {ty}"))
|
||||
.unwrap_or(ty),
|
||||
is_optional,
|
||||
)
|
||||
}
|
||||
Type::Group(g) => ty_to_ts_type(&g.elem, is_return_ty, is_struct_field, false),
|
||||
Type::Array(a) => {
|
||||
let (element_type, is_optional, _) =
|
||||
let (element_type, is_optional) =
|
||||
ty_to_ts_type(&a.elem, is_return_ty, is_struct_field, false);
|
||||
(format!("{}[]", element_type), is_optional, false)
|
||||
(format!("{}[]", element_type), is_optional)
|
||||
}
|
||||
Type::Paren(p) => {
|
||||
let (element_type, is_optional, _) =
|
||||
let (element_type, is_optional) =
|
||||
ty_to_ts_type(&p.elem, is_return_ty, is_struct_field, false);
|
||||
(element_type, is_optional, false)
|
||||
(element_type, is_optional)
|
||||
}
|
||||
_ => ("any".to_owned(), false, false),
|
||||
_ => ("any".to_owned(), false),
|
||||
}
|
||||
}
|
||||
|
|
|
@ -110,7 +110,7 @@ fn gen_callback_type(callback: &CallbackArg) -> String {
|
|||
.iter()
|
||||
.enumerate()
|
||||
.map(|(i, arg)| {
|
||||
let (ts_type, is_optional, _) = ty_to_ts_type(arg, false, false, false);
|
||||
let (ts_type, is_optional) = ty_to_ts_type(arg, false, false, false);
|
||||
FnArg {
|
||||
arg: format!("arg{}", i),
|
||||
ts_type,
|
||||
|
@ -153,7 +153,7 @@ impl NapiFn {
|
|||
}) = arguments
|
||||
{
|
||||
if let Some(syn::GenericArgument::Type(ty)) = angle_bracketed_args.first() {
|
||||
let (ts_type, _, _) = ty_to_ts_type(ty, false, false, false);
|
||||
let (ts_type, _) = ty_to_ts_type(ty, false, false, false);
|
||||
return Some(FnArg {
|
||||
arg: "this".to_owned(),
|
||||
ts_type,
|
||||
|
@ -178,7 +178,7 @@ impl NapiFn {
|
|||
i.mutability = None;
|
||||
}
|
||||
|
||||
let (ts_type, is_optional, _) = ty_to_ts_type(&path.ty, false, false, false);
|
||||
let (ts_type, is_optional) = ty_to_ts_type(&path.ty, false, false, false);
|
||||
let ts_type = arg.use_overridden_type_or(|| ts_type);
|
||||
let arg = path.pat.to_token_stream().to_string().to_case(Case::Camel);
|
||||
|
||||
|
@ -237,7 +237,7 @@ impl NapiFn {
|
|||
.unwrap_or_else(|| "".to_owned()),
|
||||
_ => {
|
||||
let ret = if let Some(ret) = &self.ret {
|
||||
let (ts_type, _, _) = ty_to_ts_type(ret, true, false, false);
|
||||
let (ts_type, _) = ty_to_ts_type(ret, true, false, false);
|
||||
if ts_type == "undefined" {
|
||||
"void".to_owned()
|
||||
} else if ts_type == "Self" {
|
||||
|
|
|
@ -36,7 +36,7 @@ impl ToTypeDef for NapiImpl {
|
|||
fn to_type_def(&self) -> Option<TypeDef> {
|
||||
if let Some(output_type) = &self.task_output_type {
|
||||
TASK_STRUCTS.with(|t| {
|
||||
let (resolved_type, is_optional, _) = ty_to_ts_type(output_type, false, true, false);
|
||||
let (resolved_type, is_optional) = ty_to_ts_type(output_type, false, true, false);
|
||||
t.borrow_mut().insert(
|
||||
self.name.to_string(),
|
||||
if resolved_type == "undefined" {
|
||||
|
@ -125,7 +125,7 @@ impl NapiStruct {
|
|||
field_str.push_str("readonly ")
|
||||
}
|
||||
|
||||
let (arg, is_optional, _) = ty_to_ts_type(&f.ty, false, true, false);
|
||||
let (arg, is_optional) = ty_to_ts_type(&f.ty, false, true, false);
|
||||
let arg = f.ts_type.as_ref().map(|ty| ty.to_string()).unwrap_or(arg);
|
||||
|
||||
let sep = if is_optional { "?" } else { "" };
|
||||
|
|
|
@ -80,6 +80,12 @@ impl TypeName for JsUnknown {
|
|||
|
||||
impl ValidateNapiValue for JsUnknown {}
|
||||
|
||||
impl ToNapiValue for sys::napi_value {
|
||||
unsafe fn to_napi_value(_env: sys::napi_env, val: Self) -> Result<sys::napi_value> {
|
||||
Ok(val)
|
||||
}
|
||||
}
|
||||
|
||||
impl<T: NapiRaw> ToNapiValue for T {
|
||||
unsafe fn to_napi_value(_env: sys::napi_env, val: Self) -> Result<sys::napi_value> {
|
||||
Ok(unsafe { NapiRaw::raw(&val) })
|
||||
|
|
|
@ -1,5 +1,315 @@
|
|||
use super::ValidateNapiValue;
|
||||
use std::ptr;
|
||||
|
||||
use super::{FromNapiValue, ToNapiValue, TypeName, ValidateNapiValue};
|
||||
|
||||
pub use crate::JsFunction;
|
||||
use crate::{
|
||||
check_pending_exception, check_status, sys, threadsafe_function::JsValuesTupleIntoVec, Env,
|
||||
NapiRaw, Result, ValueType,
|
||||
};
|
||||
|
||||
impl ValidateNapiValue for JsFunction {}
|
||||
|
||||
/// A JavaScript function.
|
||||
/// It can only live in the scope of a function call.
|
||||
/// If you want to use it outside the scope of a function call, you can turn it into a reference.
|
||||
/// By calling the `create_ref` method.
|
||||
pub struct Function<'scope, Args: JsValuesTupleIntoVec, Return: FromNapiValue> {
|
||||
pub(crate) env: sys::napi_env,
|
||||
pub(crate) value: sys::napi_value,
|
||||
pub(crate) _args: std::marker::PhantomData<Args>,
|
||||
pub(crate) _return: std::marker::PhantomData<Return>,
|
||||
_scope: std::marker::PhantomData<&'scope ()>,
|
||||
}
|
||||
|
||||
impl<'scope, Args: JsValuesTupleIntoVec, Return: FromNapiValue> TypeName
|
||||
for Function<'scope, Args, Return>
|
||||
{
|
||||
fn type_name() -> &'static str {
|
||||
"Function"
|
||||
}
|
||||
|
||||
fn value_type() -> crate::ValueType {
|
||||
ValueType::Function
|
||||
}
|
||||
}
|
||||
|
||||
impl<'scope, Args: JsValuesTupleIntoVec, Return: FromNapiValue> NapiRaw
|
||||
for Function<'scope, Args, Return>
|
||||
{
|
||||
unsafe fn raw(&self) -> sys::napi_value {
|
||||
self.value
|
||||
}
|
||||
}
|
||||
|
||||
impl<'scope, Args: JsValuesTupleIntoVec, Return: FromNapiValue> FromNapiValue
|
||||
for Function<'scope, Args, Return>
|
||||
{
|
||||
unsafe fn from_napi_value(env: sys::napi_env, value: sys::napi_value) -> Result<Self> {
|
||||
Ok(Function {
|
||||
env,
|
||||
value,
|
||||
_args: std::marker::PhantomData,
|
||||
_return: std::marker::PhantomData,
|
||||
_scope: std::marker::PhantomData,
|
||||
})
|
||||
}
|
||||
}
|
||||
|
||||
impl<'scope, Args: JsValuesTupleIntoVec, Return: FromNapiValue> ValidateNapiValue
|
||||
for Function<'scope, Args, Return>
|
||||
{
|
||||
}
|
||||
|
||||
impl<'scope, Args: JsValuesTupleIntoVec, Return: FromNapiValue> Function<'scope, Args, Return> {
|
||||
/// Call the JavaScript function.
|
||||
/// `this` in the JavaScript function will be `undefined`.
|
||||
/// If you want to specify `this`, you can use the `apply` method.
|
||||
pub fn call(&self, args: Args) -> Result<Return> {
|
||||
let mut raw_this = ptr::null_mut();
|
||||
check_status!(
|
||||
unsafe { sys::napi_get_undefined(self.env, &mut raw_this) },
|
||||
"Get undefined value failed"
|
||||
)?;
|
||||
let args_ptr = args.into_vec(self.env)?;
|
||||
let mut raw_return = ptr::null_mut();
|
||||
check_pending_exception!(
|
||||
self.env,
|
||||
unsafe {
|
||||
sys::napi_call_function(
|
||||
self.env,
|
||||
raw_this,
|
||||
self.value,
|
||||
args_ptr.len(),
|
||||
args_ptr.as_ptr(),
|
||||
&mut raw_return,
|
||||
)
|
||||
},
|
||||
"Call Function failed"
|
||||
)?;
|
||||
unsafe { Return::from_napi_value(self.env, raw_return) }
|
||||
}
|
||||
|
||||
/// Call the JavaScript function.
|
||||
/// `this` in the JavaScript function will be the provided `this`.
|
||||
pub fn apply<Context: ToNapiValue>(&self, this: Context, args: Args) -> Result<Return> {
|
||||
let raw_this = unsafe { Context::to_napi_value(self.env, this) }?;
|
||||
let args_ptr = args.into_vec(self.env)?;
|
||||
let mut raw_return = ptr::null_mut();
|
||||
check_pending_exception!(
|
||||
self.env,
|
||||
unsafe {
|
||||
sys::napi_call_function(
|
||||
self.env,
|
||||
raw_this,
|
||||
self.value,
|
||||
args_ptr.len(),
|
||||
args_ptr.as_ptr(),
|
||||
&mut raw_return,
|
||||
)
|
||||
},
|
||||
"Call Function failed"
|
||||
)?;
|
||||
unsafe { Return::from_napi_value(self.env, raw_return) }
|
||||
}
|
||||
|
||||
/// Create a reference to the JavaScript function.
|
||||
pub fn create_ref(&self) -> Result<FunctionRef<Args, Return>> {
|
||||
let mut reference = ptr::null_mut();
|
||||
check_status!(
|
||||
unsafe { sys::napi_create_reference(self.env, self.value, 1, &mut reference) },
|
||||
"Create reference failed"
|
||||
)?;
|
||||
Ok(FunctionRef {
|
||||
inner: reference,
|
||||
env: self.env,
|
||||
_args: std::marker::PhantomData,
|
||||
_return: std::marker::PhantomData,
|
||||
})
|
||||
}
|
||||
}
|
||||
|
||||
/// A reference to a JavaScript function.
|
||||
/// It can be used to outlive the scope of the function.
|
||||
pub struct FunctionRef<Args: JsValuesTupleIntoVec, Return: FromNapiValue> {
|
||||
pub(crate) inner: sys::napi_ref,
|
||||
pub(crate) env: sys::napi_env,
|
||||
_args: std::marker::PhantomData<Args>,
|
||||
_return: std::marker::PhantomData<Return>,
|
||||
}
|
||||
|
||||
unsafe impl<Args: JsValuesTupleIntoVec, Return: FromNapiValue> Sync for FunctionRef<Args, Return> {}
|
||||
|
||||
impl<Args: JsValuesTupleIntoVec, Return: FromNapiValue> FunctionRef<Args, Return> {
|
||||
pub fn borrow_back<'scope>(&self, env: &'scope Env) -> Result<Function<'scope, Args, Return>> {
|
||||
let mut value = ptr::null_mut();
|
||||
check_status!(
|
||||
unsafe { sys::napi_get_reference_value(env.0, self.inner, &mut value) },
|
||||
"Get reference value failed"
|
||||
)?;
|
||||
Ok(Function {
|
||||
env: env.0,
|
||||
value,
|
||||
_args: std::marker::PhantomData,
|
||||
_return: std::marker::PhantomData,
|
||||
_scope: std::marker::PhantomData,
|
||||
})
|
||||
}
|
||||
}
|
||||
|
||||
impl<Args: JsValuesTupleIntoVec, Return: FromNapiValue> Drop for FunctionRef<Args, Return> {
|
||||
fn drop(&mut self) {
|
||||
let status = unsafe { sys::napi_delete_reference(self.env, self.inner) };
|
||||
debug_assert_eq!(status, sys::Status::napi_ok, "Drop FunctionRef failed");
|
||||
}
|
||||
}
|
||||
|
||||
impl<Args: JsValuesTupleIntoVec, Return: FromNapiValue> TypeName for FunctionRef<Args, Return> {
|
||||
fn type_name() -> &'static str {
|
||||
"Function"
|
||||
}
|
||||
|
||||
fn value_type() -> crate::ValueType {
|
||||
ValueType::Function
|
||||
}
|
||||
}
|
||||
|
||||
impl<Args: JsValuesTupleIntoVec, Return: FromNapiValue> FromNapiValue
|
||||
for FunctionRef<Args, Return>
|
||||
{
|
||||
unsafe fn from_napi_value(env: sys::napi_env, value: sys::napi_value) -> Result<Self> {
|
||||
let mut reference = ptr::null_mut();
|
||||
check_status!(
|
||||
unsafe { sys::napi_create_reference(env, value, 1, &mut reference) },
|
||||
"Create reference failed"
|
||||
)?;
|
||||
Ok(FunctionRef {
|
||||
inner: reference,
|
||||
env,
|
||||
_args: std::marker::PhantomData,
|
||||
_return: std::marker::PhantomData,
|
||||
})
|
||||
}
|
||||
}
|
||||
|
||||
impl<Args: JsValuesTupleIntoVec, Return: FromNapiValue> ValidateNapiValue
|
||||
for FunctionRef<Args, Return>
|
||||
{
|
||||
}
|
||||
|
||||
macro_rules! impl_call_apply {
|
||||
($fn_call_name:ident, $fn_apply_name:ident, $($ident:ident),*) => {
|
||||
#[allow(non_snake_case, clippy::too_many_arguments)]
|
||||
pub fn $fn_call_name<$($ident: ToNapiValue),*, Return: FromNapiValue>(
|
||||
&self,
|
||||
$($ident: $ident),*
|
||||
) -> Result<Return> {
|
||||
let raw_this = unsafe { Env::from_raw(self.0.env) }
|
||||
.get_undefined()
|
||||
.map(|u| unsafe { u.raw() })?;
|
||||
|
||||
let raw_args = vec![
|
||||
$(
|
||||
unsafe { $ident::to_napi_value(self.0.env, $ident) }?
|
||||
),*
|
||||
];
|
||||
|
||||
let mut return_value = ptr::null_mut();
|
||||
check_pending_exception!(self.0.env, unsafe {
|
||||
sys::napi_call_function(
|
||||
self.0.env,
|
||||
raw_this,
|
||||
self.0.value,
|
||||
raw_args.len(),
|
||||
raw_args.as_ptr(),
|
||||
&mut return_value,
|
||||
)
|
||||
})?;
|
||||
|
||||
unsafe { Return::from_napi_value(self.0.env, return_value) }
|
||||
}
|
||||
|
||||
#[allow(non_snake_case, clippy::too_many_arguments)]
|
||||
pub fn $fn_apply_name<$($ident: ToNapiValue),*, Context: ToNapiValue, Return: FromNapiValue>(
|
||||
&self,
|
||||
this: Context,
|
||||
$($ident: $ident),*
|
||||
) -> Result<Return> {
|
||||
let raw_this = unsafe { Context::to_napi_value(self.0.env, this) }?;
|
||||
|
||||
let raw_args = vec![
|
||||
$(
|
||||
unsafe { $ident::to_napi_value(self.0.env, $ident) }?
|
||||
),*
|
||||
];
|
||||
|
||||
let mut return_value = ptr::null_mut();
|
||||
check_pending_exception!(self.0.env, unsafe {
|
||||
sys::napi_call_function(
|
||||
self.0.env,
|
||||
raw_this,
|
||||
self.0.value,
|
||||
raw_args.len(),
|
||||
raw_args.as_ptr(),
|
||||
&mut return_value,
|
||||
)
|
||||
})?;
|
||||
|
||||
unsafe { Return::from_napi_value(self.0.env, return_value) }
|
||||
}
|
||||
};
|
||||
}
|
||||
|
||||
impl JsFunction {
|
||||
pub fn apply0<Return: FromNapiValue, Context: ToNapiValue>(
|
||||
&self,
|
||||
this: Context,
|
||||
) -> Result<Return> {
|
||||
let raw_this = unsafe { Context::to_napi_value(self.0.env, this) }?;
|
||||
|
||||
let mut return_value = ptr::null_mut();
|
||||
check_pending_exception!(self.0.env, unsafe {
|
||||
sys::napi_call_function(
|
||||
self.0.env,
|
||||
raw_this,
|
||||
self.0.value,
|
||||
0,
|
||||
ptr::null_mut(),
|
||||
&mut return_value,
|
||||
)
|
||||
})?;
|
||||
|
||||
unsafe { Return::from_napi_value(self.0.env, return_value) }
|
||||
}
|
||||
|
||||
pub fn call0<Return: FromNapiValue>(&self) -> Result<Return> {
|
||||
let raw_this = unsafe { Env::from_raw(self.0.env) }
|
||||
.get_undefined()
|
||||
.map(|u| unsafe { u.raw() })?;
|
||||
|
||||
let mut return_value = ptr::null_mut();
|
||||
check_pending_exception!(self.0.env, unsafe {
|
||||
sys::napi_call_function(
|
||||
self.0.env,
|
||||
raw_this,
|
||||
self.0.value,
|
||||
0,
|
||||
ptr::null_mut(),
|
||||
&mut return_value,
|
||||
)
|
||||
})?;
|
||||
|
||||
unsafe { Return::from_napi_value(self.0.env, return_value) }
|
||||
}
|
||||
|
||||
impl_call_apply!(call1, apply1, Arg1);
|
||||
impl_call_apply!(call2, apply2, Arg1, Arg2);
|
||||
impl_call_apply!(call3, apply3, Arg1, Arg2, Arg3);
|
||||
impl_call_apply!(call4, apply4, Arg1, Arg2, Arg3, Arg4);
|
||||
impl_call_apply!(call5, apply5, Arg1, Arg2, Arg3, Arg4, Arg5);
|
||||
impl_call_apply!(call6, apply6, Arg1, Arg2, Arg3, Arg4, Arg5, Arg6);
|
||||
impl_call_apply!(call7, apply7, Arg1, Arg2, Arg3, Arg4, Arg5, Arg6, Arg7);
|
||||
impl_call_apply!(call8, apply8, Arg1, Arg2, Arg3, Arg4, Arg5, Arg6, Arg7, Arg8);
|
||||
impl_call_apply!(call9, apply9, Arg1, Arg2, Arg3, Arg4, Arg5, Arg6, Arg7, Arg8, Arg9);
|
||||
impl_call_apply!(call10, apply10, Arg1, Arg2, Arg3, Arg4, Arg5, Arg6, Arg7, Arg8, Arg9, Arg10);
|
||||
}
|
||||
|
|
|
@ -255,30 +255,26 @@ impl<T: 'static, ES: ErrorStrategy::T> Clone for ThreadsafeFunction<T, ES> {
|
|||
}
|
||||
|
||||
pub trait JsValuesTupleIntoVec {
|
||||
fn into_vec(self, env: &Env) -> Result<Vec<JsUnknown>>;
|
||||
fn into_vec(self, env: sys::napi_env) -> Result<Vec<sys::napi_value>>;
|
||||
}
|
||||
|
||||
impl<T: ToNapiValue> JsValuesTupleIntoVec for T {
|
||||
fn into_vec(self, env: &Env) -> Result<Vec<JsUnknown>> {
|
||||
Ok(vec![JsUnknown(crate::Value {
|
||||
env: env.0,
|
||||
value: unsafe { <T as ToNapiValue>::to_napi_value(env.0, self)? },
|
||||
value_type: crate::ValueType::Unknown,
|
||||
})])
|
||||
#[allow(clippy::not_unsafe_ptr_arg_deref)]
|
||||
fn into_vec(self, env: sys::napi_env) -> Result<Vec<sys::napi_value>> {
|
||||
Ok(vec![unsafe {
|
||||
<T as ToNapiValue>::to_napi_value(env, self)?
|
||||
}])
|
||||
}
|
||||
}
|
||||
|
||||
macro_rules! impl_js_value_tuple_to_vec {
|
||||
($($ident:ident),*) => {
|
||||
impl<$($ident: ToNapiValue),*> JsValuesTupleIntoVec for ($($ident,)*) {
|
||||
fn into_vec(self, env: &Env) -> Result<Vec<JsUnknown>> {
|
||||
#[allow(clippy::not_unsafe_ptr_arg_deref)]
|
||||
fn into_vec(self, env: sys::napi_env) -> Result<Vec<sys::napi_value>> {
|
||||
#[allow(non_snake_case)]
|
||||
let ($($ident,)*) = self;
|
||||
Ok(vec![$(JsUnknown($crate::Value {
|
||||
env: env.0,
|
||||
value: unsafe { <$ident as ToNapiValue>::to_napi_value(env.0, $ident)? },
|
||||
value_type: $crate::ValueType::Unknown,
|
||||
})),*])
|
||||
Ok(vec![$(unsafe { <$ident as ToNapiValue>::to_napi_value(env, $ident)? }),*])
|
||||
}
|
||||
}
|
||||
};
|
||||
|
@ -319,7 +315,7 @@ impl<T: JsValuesTupleIntoVec + 'static, ES: ErrorStrategy::T> FromNapiValue
|
|||
for ThreadsafeFunction<T, ES>
|
||||
{
|
||||
unsafe fn from_napi_value(env: sys::napi_env, napi_val: sys::napi_value) -> Result<Self> {
|
||||
Self::create(env, napi_val, 0, |ctx| ctx.value.into_vec(&ctx.env))
|
||||
Self::create(env, napi_val, 0, |ctx| ctx.value.into_vec(ctx.env.0))
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
@ -221,9 +221,9 @@ Generated by [AVA](https://avajs.dev).
|
|||
foo: number␊
|
||||
}␊
|
||||
␊
|
||||
export function acceptThreadsafeFunction(func: (err: Error | null, value: number) => any): void␊
|
||||
export function acceptThreadsafeFunction(func: (err: Error | null, arg: number) => any): void␊
|
||||
␊
|
||||
export function acceptThreadsafeFunctionFatal(func: (value: number) => any): void␊
|
||||
export function acceptThreadsafeFunctionFatal(func: (arg: number) => any): void␊
|
||||
␊
|
||||
export function acceptThreadsafeFunctionTupleArgs(func: (err: Error | null, arg0: number, arg1: boolean, arg2: string) => any): void␊
|
||||
␊
|
||||
|
@ -246,6 +246,10 @@ Generated by [AVA](https://avajs.dev).
|
|||
␊
|
||||
export function appendBuffer(buf: Buffer): Buffer␊
|
||||
␊
|
||||
export function apply0(ctx: Animal, callback: (...args: any[]) => any): void␊
|
||||
␊
|
||||
export function apply1(ctx: Animal, callback: (...args: any[]) => any, name: string): void␊
|
||||
␊
|
||||
export function arrayBufferPassThrough(buf: Uint8Array): Promise<Uint8Array>␊
|
||||
␊
|
||||
export function asyncMultiTwo(arg: number): Promise<number>␊
|
||||
|
@ -276,10 +280,22 @@ Generated by [AVA](https://avajs.dev).
|
|||
baz: number␊
|
||||
}␊
|
||||
␊
|
||||
export function call0(callback: (...args: any[]) => any): number␊
|
||||
␊
|
||||
export function call1(callback: (...args: any[]) => any, arg: number): number␊
|
||||
␊
|
||||
export function call2(callback: (...args: any[]) => any, arg1: number, arg2: number): number␊
|
||||
␊
|
||||
export function callbackReturnPromise<T>(functionInput: () => T | Promise<T>, callback: (err: Error | null, result: T) => void): T | Promise<T>␊
|
||||
␊
|
||||
export function callbackReturnPromiseAndSpawn(jsFunc: (arg0: string) => Promise<string>): Promise<string>␊
|
||||
␊
|
||||
export function callFunction(cb: () => number): number␊
|
||||
␊
|
||||
export function callFunctionWithArg(cb: (arg0: number, arg1: number) => number, arg0: number, arg1: number): number␊
|
||||
␊
|
||||
export function callFunctionWithArgAndCtx(ctx: Animal, cb: (arg: string) => void, name: string): void␊
|
||||
␊
|
||||
export function callLongThreadsafeFunction(callback: (...args: any[]) => any): void␊
|
||||
␊
|
||||
export function callThreadsafeFunction(callback: (...args: any[]) => any): void␊
|
||||
|
@ -320,6 +336,8 @@ Generated by [AVA](https://avajs.dev).
|
|||
␊
|
||||
export function createObjWithProperty(): { value: ArrayBuffer, get getter(): number }␊
|
||||
␊
|
||||
export function createReferenceOnFunction(cb: () => void): object␊
|
||||
␊
|
||||
export function createSymbol(): symbol␊
|
||||
␊
|
||||
export function createSymbolFor(desc: string): symbol␊
|
||||
|
@ -433,7 +451,7 @@ Generated by [AVA](https://avajs.dev).
|
|||
␊
|
||||
export interface ObjectOnlyFromJs {␊
|
||||
count: number␊
|
||||
callback: (err: Error | null, value: number) => any␊
|
||||
callback: (err: Error | null, arg: number) => any␊
|
||||
}␊
|
||||
␊
|
||||
export function optionEnd(callback: (arg0: string, arg1?: string | undefined | null) => void): void␊
|
||||
|
@ -486,6 +504,8 @@ Generated by [AVA](https://avajs.dev).
|
|||
␊
|
||||
export function receiveString(s: string): string␊
|
||||
␊
|
||||
export function referenceAsCallback(callback: (arg0: number, arg1: number) => number, arg0: number, arg1: number): number␊
|
||||
␊
|
||||
export function returnEither(input: number): string | number␊
|
||||
␊
|
||||
export function returnEitherClass(input: number): number | JsClassForEither␊
|
||||
|
@ -550,11 +570,11 @@ Generated by [AVA](https://avajs.dev).
|
|||
␊
|
||||
export function tsfnCallWithCallback(func: (...args: any[]) => any): void␊
|
||||
␊
|
||||
export function tsfnReturnPromise(func: (err: Error | null, value: number) => any): Promise<number>␊
|
||||
export function tsfnReturnPromise(func: (err: Error | null, arg: number) => any): Promise<number>␊
|
||||
␊
|
||||
export function tsfnReturnPromiseTimeout(func: (err: Error | null, value: number) => any): Promise<number>␊
|
||||
export function tsfnReturnPromiseTimeout(func: (err: Error | null, arg: number) => any): Promise<number>␊
|
||||
␊
|
||||
export function tsfnThrowFromJs(tsfn: (err: Error | null, value: number) => any): Promise<number>␊
|
||||
export function tsfnThrowFromJs(tsfn: (err: Error | null, arg: number) => any): Promise<number>␊
|
||||
␊
|
||||
export function tsRename(a: { foo: number }): string[]␊
|
||||
␊
|
||||
|
|
Binary file not shown.
|
@ -4,7 +4,7 @@ import { fileURLToPath } from 'node:url'
|
|||
|
||||
import { spy } from 'sinon'
|
||||
|
||||
import type { AliasedStruct } from '../index.js'
|
||||
import type { AliasedStruct, Animal as AnimalClass } from '../index.js'
|
||||
|
||||
import { test } from './test.framework.js'
|
||||
|
||||
|
@ -14,6 +14,16 @@ const {
|
|||
DEFAULT_COST,
|
||||
add,
|
||||
fibonacci,
|
||||
call0,
|
||||
call1,
|
||||
call2,
|
||||
apply0,
|
||||
apply1,
|
||||
callFunction,
|
||||
callFunctionWithArg,
|
||||
callFunctionWithArgAndCtx,
|
||||
createReferenceOnFunction,
|
||||
referenceAsCallback,
|
||||
contains,
|
||||
concatLatin1,
|
||||
concatStr,
|
||||
|
@ -198,6 +208,59 @@ test('enum', (t) => {
|
|||
t.is(enumToI32(CustomNumEnum.Eight), 8)
|
||||
})
|
||||
|
||||
test('function call', async (t) => {
|
||||
t.is(
|
||||
call0(() => 42),
|
||||
42,
|
||||
)
|
||||
t.is(
|
||||
call1((a) => a + 10, 42),
|
||||
52,
|
||||
)
|
||||
t.is(
|
||||
call2((a, b) => a + b, 42, 10),
|
||||
52,
|
||||
)
|
||||
const ctx = new Animal(Kind.Dog, '旺财')
|
||||
apply0(ctx, function (this: AnimalClass) {
|
||||
this.name = '可乐'
|
||||
})
|
||||
t.is(ctx.name, '可乐')
|
||||
const ctx2 = new Animal(Kind.Dog, '旺财')
|
||||
apply1(
|
||||
ctx2,
|
||||
function (this: AnimalClass, name: string) {
|
||||
this.name = name
|
||||
},
|
||||
'可乐',
|
||||
)
|
||||
t.is(ctx2.name, '可乐')
|
||||
t.is(
|
||||
callFunction(() => 42),
|
||||
42,
|
||||
)
|
||||
t.is(
|
||||
callFunctionWithArg((a, b) => a + b, 42, 10),
|
||||
52,
|
||||
)
|
||||
const ctx3 = new Animal(Kind.Dog, '旺财')
|
||||
callFunctionWithArgAndCtx(
|
||||
ctx3,
|
||||
function (this: AnimalClass, name: string) {
|
||||
this.name = name
|
||||
},
|
||||
'可乐',
|
||||
)
|
||||
t.is(ctx3.name, '可乐')
|
||||
const cbSpy = spy()
|
||||
await createReferenceOnFunction(cbSpy)
|
||||
t.is(cbSpy.callCount, 1)
|
||||
t.is(
|
||||
referenceAsCallback((a, b) => a + b, 42, 10),
|
||||
52,
|
||||
)
|
||||
})
|
||||
|
||||
test('class', (t) => {
|
||||
const dog = new Animal(Kind.Dog, '旺财')
|
||||
|
||||
|
|
32
examples/napi/index.d.ts
vendored
32
examples/napi/index.d.ts
vendored
|
@ -211,9 +211,9 @@ export interface A {
|
|||
foo: number
|
||||
}
|
||||
|
||||
export function acceptThreadsafeFunction(func: (err: Error | null, value: number) => any): void
|
||||
export function acceptThreadsafeFunction(func: (err: Error | null, arg: number) => any): void
|
||||
|
||||
export function acceptThreadsafeFunctionFatal(func: (value: number) => any): void
|
||||
export function acceptThreadsafeFunctionFatal(func: (arg: number) => any): void
|
||||
|
||||
export function acceptThreadsafeFunctionTupleArgs(func: (err: Error | null, arg0: number, arg1: boolean, arg2: string) => any): void
|
||||
|
||||
|
@ -236,6 +236,10 @@ export interface AllOptionalObject {
|
|||
|
||||
export function appendBuffer(buf: Buffer): Buffer
|
||||
|
||||
export function apply0(ctx: Animal, callback: (...args: any[]) => any): void
|
||||
|
||||
export function apply1(ctx: Animal, callback: (...args: any[]) => any, name: string): void
|
||||
|
||||
export function arrayBufferPassThrough(buf: Uint8Array): Promise<Uint8Array>
|
||||
|
||||
export function asyncMultiTwo(arg: number): Promise<number>
|
||||
|
@ -266,10 +270,22 @@ export interface C {
|
|||
baz: number
|
||||
}
|
||||
|
||||
export function call0(callback: (...args: any[]) => any): number
|
||||
|
||||
export function call1(callback: (...args: any[]) => any, arg: number): number
|
||||
|
||||
export function call2(callback: (...args: any[]) => any, arg1: number, arg2: number): number
|
||||
|
||||
export function callbackReturnPromise<T>(functionInput: () => T | Promise<T>, callback: (err: Error | null, result: T) => void): T | Promise<T>
|
||||
|
||||
export function callbackReturnPromiseAndSpawn(jsFunc: (arg0: string) => Promise<string>): Promise<string>
|
||||
|
||||
export function callFunction(cb: () => number): number
|
||||
|
||||
export function callFunctionWithArg(cb: (arg0: number, arg1: number) => number, arg0: number, arg1: number): number
|
||||
|
||||
export function callFunctionWithArgAndCtx(ctx: Animal, cb: (arg: string) => void, name: string): void
|
||||
|
||||
export function callLongThreadsafeFunction(callback: (...args: any[]) => any): void
|
||||
|
||||
export function callThreadsafeFunction(callback: (...args: any[]) => any): void
|
||||
|
@ -310,6 +326,8 @@ export function createObjectWithClassField(): ObjectFieldClassInstance
|
|||
|
||||
export function createObjWithProperty(): { value: ArrayBuffer, get getter(): number }
|
||||
|
||||
export function createReferenceOnFunction(cb: () => void): object
|
||||
|
||||
export function createSymbol(): symbol
|
||||
|
||||
export function createSymbolFor(desc: string): symbol
|
||||
|
@ -423,7 +441,7 @@ export interface ObjectFieldClassInstance {
|
|||
|
||||
export interface ObjectOnlyFromJs {
|
||||
count: number
|
||||
callback: (err: Error | null, value: number) => any
|
||||
callback: (err: Error | null, arg: number) => any
|
||||
}
|
||||
|
||||
export function optionEnd(callback: (arg0: string, arg1?: string | undefined | null) => void): void
|
||||
|
@ -476,6 +494,8 @@ export function receiveStrictObject(strictObject: StrictObject): void
|
|||
|
||||
export function receiveString(s: string): string
|
||||
|
||||
export function referenceAsCallback(callback: (arg0: number, arg1: number) => number, arg0: number, arg1: number): number
|
||||
|
||||
export function returnEither(input: number): string | number
|
||||
|
||||
export function returnEitherClass(input: number): number | JsClassForEither
|
||||
|
@ -540,11 +560,11 @@ export function tsfnAsyncCall(func: (...args: any[]) => any): Promise<void>
|
|||
|
||||
export function tsfnCallWithCallback(func: (...args: any[]) => any): void
|
||||
|
||||
export function tsfnReturnPromise(func: (err: Error | null, value: number) => any): Promise<number>
|
||||
export function tsfnReturnPromise(func: (err: Error | null, arg: number) => any): Promise<number>
|
||||
|
||||
export function tsfnReturnPromiseTimeout(func: (err: Error | null, value: number) => any): Promise<number>
|
||||
export function tsfnReturnPromiseTimeout(func: (err: Error | null, arg: number) => any): Promise<number>
|
||||
|
||||
export function tsfnThrowFromJs(tsfn: (err: Error | null, value: number) => any): Promise<number>
|
||||
export function tsfnThrowFromJs(tsfn: (err: Error | null, arg: number) => any): Promise<number>
|
||||
|
||||
export function tsRename(a: { foo: number }): string[]
|
||||
|
||||
|
|
|
@ -59,6 +59,7 @@ const {
|
|||
})
|
||||
|
||||
function __napi_rs_initialize_modules(__napiInstance) {
|
||||
__napiInstance.exports['__napi_register__Shared_struct_0']?.()
|
||||
__napiInstance.exports['__napi_register__DEFAULT_COST_0']?.()
|
||||
__napiInstance.exports['__napi_register__TYPE_SKIPPED_CONST_1']?.()
|
||||
__napiInstance.exports['__napi_register__get_words_2']?.()
|
||||
|
@ -213,124 +214,138 @@ function __napi_rs_initialize_modules(__napiInstance) {
|
|||
__napiInstance.exports[
|
||||
'__napi_register__override_individual_arg_on_function_with_cb_arg_174'
|
||||
]?.()
|
||||
__napiInstance.exports['__napi_register__Fib_struct_175']?.()
|
||||
__napiInstance.exports['__napi_register__Fib_impl_176']?.()
|
||||
__napiInstance.exports['__napi_register__Fib_impl_178']?.()
|
||||
__napiInstance.exports['__napi_register__Fib2_struct_179']?.()
|
||||
__napiInstance.exports['__napi_register__Fib2_impl_180']?.()
|
||||
__napiInstance.exports['__napi_register__Fib2_impl_182']?.()
|
||||
__napiInstance.exports['__napi_register__Fib3_struct_183']?.()
|
||||
__napiInstance.exports['__napi_register__Fib3_impl_184']?.()
|
||||
__napiInstance.exports['__napi_register__ALIGNMENT_185']?.()
|
||||
__napiInstance.exports['__napi_register__xxh64_186']?.()
|
||||
__napiInstance.exports['__napi_register__xxh128_187']?.()
|
||||
__napiInstance.exports['__napi_register__Xxh3_struct_188']?.()
|
||||
__napiInstance.exports['__napi_register__Xxh3_impl_192']?.()
|
||||
__napiInstance.exports['__napi_register__xxh2_plus_193']?.()
|
||||
__napiInstance.exports['__napi_register__xxh3_xxh64_alias_194']?.()
|
||||
__napiInstance.exports['__napi_register__xxh64_alias_195']?.()
|
||||
__napiInstance.exports['__napi_register__get_mapping_196']?.()
|
||||
__napiInstance.exports['__napi_register__sum_mapping_197']?.()
|
||||
__napiInstance.exports['__napi_register__map_option_198']?.()
|
||||
__napiInstance.exports['__napi_register__return_null_199']?.()
|
||||
__napiInstance.exports['__napi_register__return_undefined_200']?.()
|
||||
__napiInstance.exports['__napi_register__add_201']?.()
|
||||
__napiInstance.exports['__napi_register__fibonacci_202']?.()
|
||||
__napiInstance.exports['__napi_register__list_obj_keys_203']?.()
|
||||
__napiInstance.exports['__napi_register__create_obj_204']?.()
|
||||
__napiInstance.exports['__napi_register__get_global_205']?.()
|
||||
__napiInstance.exports['__napi_register__get_undefined_206']?.()
|
||||
__napiInstance.exports['__napi_register__get_null_207']?.()
|
||||
__napiInstance.exports['__napi_register__AllOptionalObject_struct_208']?.()
|
||||
__napiInstance.exports['__napi_register__receive_all_optional_object_209']?.()
|
||||
__napiInstance.exports['__napi_register__AliasedEnum_210']?.()
|
||||
__napiInstance.exports['__napi_register__call0_175']?.()
|
||||
__napiInstance.exports['__napi_register__call1_176']?.()
|
||||
__napiInstance.exports['__napi_register__call2_177']?.()
|
||||
__napiInstance.exports['__napi_register__apply0_178']?.()
|
||||
__napiInstance.exports['__napi_register__apply1_179']?.()
|
||||
__napiInstance.exports['__napi_register__call_function_180']?.()
|
||||
__napiInstance.exports['__napi_register__call_function_with_arg_181']?.()
|
||||
__napiInstance.exports[
|
||||
'__napi_register__StructContainsAliasedEnum_struct_211'
|
||||
]?.()
|
||||
__napiInstance.exports['__napi_register__fn_received_aliased_212']?.()
|
||||
__napiInstance.exports['__napi_register__StrictObject_struct_213']?.()
|
||||
__napiInstance.exports['__napi_register__receive_strict_object_214']?.()
|
||||
__napiInstance.exports['__napi_register__get_str_from_object_215']?.()
|
||||
__napiInstance.exports['__napi_register__TsTypeChanged_struct_216']?.()
|
||||
__napiInstance.exports['__napi_register__create_obj_with_property_217']?.()
|
||||
__napiInstance.exports['__napi_register__getter_from_obj_218']?.()
|
||||
__napiInstance.exports['__napi_register__ObjectOnlyFromJs_struct_219']?.()
|
||||
__napiInstance.exports['__napi_register__receive_object_only_from_js_220']?.()
|
||||
__napiInstance.exports['__napi_register__async_plus_100_221']?.()
|
||||
__napiInstance.exports['__napi_register__JsRepo_struct_222']?.()
|
||||
__napiInstance.exports['__napi_register__JsRepo_impl_225']?.()
|
||||
__napiInstance.exports['__napi_register__JsRemote_struct_226']?.()
|
||||
__napiInstance.exports['__napi_register__JsRemote_impl_228']?.()
|
||||
__napiInstance.exports['__napi_register__CSSRuleList_struct_229']?.()
|
||||
__napiInstance.exports['__napi_register__CSSRuleList_impl_233']?.()
|
||||
__napiInstance.exports['__napi_register__CSSStyleSheet_struct_234']?.()
|
||||
__napiInstance.exports['__napi_register__AnotherCSSStyleSheet_struct_235']?.()
|
||||
__napiInstance.exports['__napi_register__AnotherCSSStyleSheet_impl_237']?.()
|
||||
__napiInstance.exports['__napi_register__CSSStyleSheet_impl_241']?.()
|
||||
__napiInstance.exports['__napi_register__PackageJson_struct_242']?.()
|
||||
__napiInstance.exports['__napi_register__read_package_json_243']?.()
|
||||
__napiInstance.exports['__napi_register__get_package_json_name_244']?.()
|
||||
__napiInstance.exports['__napi_register__test_serde_roundtrip_245']?.()
|
||||
__napiInstance.exports[
|
||||
'__napi_register__test_serde_big_number_precision_246'
|
||||
]?.()
|
||||
__napiInstance.exports['__napi_register__return_from_shared_crate_247']?.()
|
||||
__napiInstance.exports['__napi_register__contains_248']?.()
|
||||
__napiInstance.exports['__napi_register__concat_str_249']?.()
|
||||
__napiInstance.exports['__napi_register__concat_utf16_250']?.()
|
||||
__napiInstance.exports['__napi_register__concat_latin1_251']?.()
|
||||
__napiInstance.exports['__napi_register__roundtrip_str_252']?.()
|
||||
__napiInstance.exports['__napi_register__set_symbol_in_obj_253']?.()
|
||||
__napiInstance.exports['__napi_register__create_symbol_254']?.()
|
||||
__napiInstance.exports['__napi_register__create_symbol_for_255']?.()
|
||||
__napiInstance.exports['__napi_register__DelaySum_impl_256']?.()
|
||||
__napiInstance.exports['__napi_register__without_abort_controller_257']?.()
|
||||
__napiInstance.exports['__napi_register__with_abort_controller_258']?.()
|
||||
__napiInstance.exports['__napi_register__AsyncTaskVoidReturn_impl_259']?.()
|
||||
__napiInstance.exports['__napi_register__async_task_void_return_260']?.()
|
||||
__napiInstance.exports[
|
||||
'__napi_register__AsyncTaskOptionalReturn_impl_261'
|
||||
]?.()
|
||||
__napiInstance.exports['__napi_register__async_task_optional_return_262']?.()
|
||||
__napiInstance.exports['__napi_register__call_threadsafe_function_263']?.()
|
||||
__napiInstance.exports[
|
||||
'__napi_register__call_long_threadsafe_function_264'
|
||||
'__napi_register__create_reference_on_function_182'
|
||||
]?.()
|
||||
__napiInstance.exports[
|
||||
'__napi_register__threadsafe_function_throw_error_265'
|
||||
'__napi_register__call_function_with_arg_and_ctx_183'
|
||||
]?.()
|
||||
__napiInstance.exports['__napi_register__reference_as_callback_184']?.()
|
||||
__napiInstance.exports['__napi_register__Fib_struct_185']?.()
|
||||
__napiInstance.exports['__napi_register__Fib_impl_186']?.()
|
||||
__napiInstance.exports['__napi_register__Fib_impl_188']?.()
|
||||
__napiInstance.exports['__napi_register__Fib2_struct_189']?.()
|
||||
__napiInstance.exports['__napi_register__Fib2_impl_190']?.()
|
||||
__napiInstance.exports['__napi_register__Fib2_impl_192']?.()
|
||||
__napiInstance.exports['__napi_register__Fib3_struct_193']?.()
|
||||
__napiInstance.exports['__napi_register__Fib3_impl_194']?.()
|
||||
__napiInstance.exports['__napi_register__ALIGNMENT_195']?.()
|
||||
__napiInstance.exports['__napi_register__xxh64_196']?.()
|
||||
__napiInstance.exports['__napi_register__xxh128_197']?.()
|
||||
__napiInstance.exports['__napi_register__Xxh3_struct_198']?.()
|
||||
__napiInstance.exports['__napi_register__Xxh3_impl_202']?.()
|
||||
__napiInstance.exports['__napi_register__xxh2_plus_203']?.()
|
||||
__napiInstance.exports['__napi_register__xxh3_xxh64_alias_204']?.()
|
||||
__napiInstance.exports['__napi_register__xxh64_alias_205']?.()
|
||||
__napiInstance.exports['__napi_register__get_mapping_206']?.()
|
||||
__napiInstance.exports['__napi_register__sum_mapping_207']?.()
|
||||
__napiInstance.exports['__napi_register__map_option_208']?.()
|
||||
__napiInstance.exports['__napi_register__return_null_209']?.()
|
||||
__napiInstance.exports['__napi_register__return_undefined_210']?.()
|
||||
__napiInstance.exports['__napi_register__add_211']?.()
|
||||
__napiInstance.exports['__napi_register__fibonacci_212']?.()
|
||||
__napiInstance.exports['__napi_register__list_obj_keys_213']?.()
|
||||
__napiInstance.exports['__napi_register__create_obj_214']?.()
|
||||
__napiInstance.exports['__napi_register__get_global_215']?.()
|
||||
__napiInstance.exports['__napi_register__get_undefined_216']?.()
|
||||
__napiInstance.exports['__napi_register__get_null_217']?.()
|
||||
__napiInstance.exports['__napi_register__AllOptionalObject_struct_218']?.()
|
||||
__napiInstance.exports['__napi_register__receive_all_optional_object_219']?.()
|
||||
__napiInstance.exports['__napi_register__AliasedEnum_220']?.()
|
||||
__napiInstance.exports[
|
||||
'__napi_register__StructContainsAliasedEnum_struct_221'
|
||||
]?.()
|
||||
__napiInstance.exports['__napi_register__fn_received_aliased_222']?.()
|
||||
__napiInstance.exports['__napi_register__StrictObject_struct_223']?.()
|
||||
__napiInstance.exports['__napi_register__receive_strict_object_224']?.()
|
||||
__napiInstance.exports['__napi_register__get_str_from_object_225']?.()
|
||||
__napiInstance.exports['__napi_register__TsTypeChanged_struct_226']?.()
|
||||
__napiInstance.exports['__napi_register__create_obj_with_property_227']?.()
|
||||
__napiInstance.exports['__napi_register__getter_from_obj_228']?.()
|
||||
__napiInstance.exports['__napi_register__ObjectOnlyFromJs_struct_229']?.()
|
||||
__napiInstance.exports['__napi_register__receive_object_only_from_js_230']?.()
|
||||
__napiInstance.exports['__napi_register__async_plus_100_231']?.()
|
||||
__napiInstance.exports['__napi_register__JsRepo_struct_232']?.()
|
||||
__napiInstance.exports['__napi_register__JsRepo_impl_235']?.()
|
||||
__napiInstance.exports['__napi_register__JsRemote_struct_236']?.()
|
||||
__napiInstance.exports['__napi_register__JsRemote_impl_238']?.()
|
||||
__napiInstance.exports['__napi_register__CSSRuleList_struct_239']?.()
|
||||
__napiInstance.exports['__napi_register__CSSRuleList_impl_243']?.()
|
||||
__napiInstance.exports['__napi_register__CSSStyleSheet_struct_244']?.()
|
||||
__napiInstance.exports['__napi_register__AnotherCSSStyleSheet_struct_245']?.()
|
||||
__napiInstance.exports['__napi_register__AnotherCSSStyleSheet_impl_247']?.()
|
||||
__napiInstance.exports['__napi_register__CSSStyleSheet_impl_251']?.()
|
||||
__napiInstance.exports['__napi_register__PackageJson_struct_252']?.()
|
||||
__napiInstance.exports['__napi_register__read_package_json_253']?.()
|
||||
__napiInstance.exports['__napi_register__get_package_json_name_254']?.()
|
||||
__napiInstance.exports['__napi_register__test_serde_roundtrip_255']?.()
|
||||
__napiInstance.exports[
|
||||
'__napi_register__test_serde_big_number_precision_256'
|
||||
]?.()
|
||||
__napiInstance.exports['__napi_register__return_from_shared_crate_257']?.()
|
||||
__napiInstance.exports['__napi_register__contains_258']?.()
|
||||
__napiInstance.exports['__napi_register__concat_str_259']?.()
|
||||
__napiInstance.exports['__napi_register__concat_utf16_260']?.()
|
||||
__napiInstance.exports['__napi_register__concat_latin1_261']?.()
|
||||
__napiInstance.exports['__napi_register__roundtrip_str_262']?.()
|
||||
__napiInstance.exports['__napi_register__set_symbol_in_obj_263']?.()
|
||||
__napiInstance.exports['__napi_register__create_symbol_264']?.()
|
||||
__napiInstance.exports['__napi_register__create_symbol_for_265']?.()
|
||||
__napiInstance.exports['__napi_register__DelaySum_impl_266']?.()
|
||||
__napiInstance.exports['__napi_register__without_abort_controller_267']?.()
|
||||
__napiInstance.exports['__napi_register__with_abort_controller_268']?.()
|
||||
__napiInstance.exports['__napi_register__AsyncTaskVoidReturn_impl_269']?.()
|
||||
__napiInstance.exports['__napi_register__async_task_void_return_270']?.()
|
||||
__napiInstance.exports[
|
||||
'__napi_register__AsyncTaskOptionalReturn_impl_271'
|
||||
]?.()
|
||||
__napiInstance.exports['__napi_register__async_task_optional_return_272']?.()
|
||||
__napiInstance.exports['__napi_register__call_threadsafe_function_273']?.()
|
||||
__napiInstance.exports[
|
||||
'__napi_register__call_long_threadsafe_function_274'
|
||||
]?.()
|
||||
__napiInstance.exports[
|
||||
'__napi_register__threadsafe_function_fatal_mode_266'
|
||||
'__napi_register__threadsafe_function_throw_error_275'
|
||||
]?.()
|
||||
__napiInstance.exports[
|
||||
'__napi_register__threadsafe_function_fatal_mode_error_267'
|
||||
'__napi_register__threadsafe_function_fatal_mode_276'
|
||||
]?.()
|
||||
__napiInstance.exports[
|
||||
'__napi_register__threadsafe_function_closure_capture_268'
|
||||
]?.()
|
||||
__napiInstance.exports['__napi_register__tsfn_call_with_callback_269']?.()
|
||||
__napiInstance.exports['__napi_register__tsfn_async_call_270']?.()
|
||||
__napiInstance.exports['__napi_register__accept_threadsafe_function_271']?.()
|
||||
__napiInstance.exports[
|
||||
'__napi_register__accept_threadsafe_function_fatal_272'
|
||||
'__napi_register__threadsafe_function_fatal_mode_error_277'
|
||||
]?.()
|
||||
__napiInstance.exports[
|
||||
'__napi_register__accept_threadsafe_function_tuple_args_273'
|
||||
'__napi_register__threadsafe_function_closure_capture_278'
|
||||
]?.()
|
||||
__napiInstance.exports['__napi_register__tsfn_return_promise_274']?.()
|
||||
__napiInstance.exports['__napi_register__tsfn_return_promise_timeout_275']?.()
|
||||
__napiInstance.exports['__napi_register__tsfn_throw_from_js_276']?.()
|
||||
__napiInstance.exports['__napi_register__get_buffer_277']?.()
|
||||
__napiInstance.exports['__napi_register__append_buffer_278']?.()
|
||||
__napiInstance.exports['__napi_register__get_empty_buffer_279']?.()
|
||||
__napiInstance.exports['__napi_register__convert_u32_array_280']?.()
|
||||
__napiInstance.exports['__napi_register__create_external_typed_array_281']?.()
|
||||
__napiInstance.exports['__napi_register__mutate_typed_array_282']?.()
|
||||
__napiInstance.exports['__napi_register__deref_uint8_array_283']?.()
|
||||
__napiInstance.exports['__napi_register__buffer_pass_through_284']?.()
|
||||
__napiInstance.exports['__napi_register__array_buffer_pass_through_285']?.()
|
||||
__napiInstance.exports['__napi_register__AsyncBuffer_impl_286']?.()
|
||||
__napiInstance.exports['__napi_register__async_reduce_buffer_287']?.()
|
||||
__napiInstance.exports['__napi_register__tsfn_call_with_callback_279']?.()
|
||||
__napiInstance.exports['__napi_register__tsfn_async_call_280']?.()
|
||||
__napiInstance.exports['__napi_register__accept_threadsafe_function_281']?.()
|
||||
__napiInstance.exports[
|
||||
'__napi_register__accept_threadsafe_function_fatal_282'
|
||||
]?.()
|
||||
__napiInstance.exports[
|
||||
'__napi_register__accept_threadsafe_function_tuple_args_283'
|
||||
]?.()
|
||||
__napiInstance.exports['__napi_register__tsfn_return_promise_284']?.()
|
||||
__napiInstance.exports['__napi_register__tsfn_return_promise_timeout_285']?.()
|
||||
__napiInstance.exports['__napi_register__tsfn_throw_from_js_286']?.()
|
||||
__napiInstance.exports['__napi_register__get_buffer_287']?.()
|
||||
__napiInstance.exports['__napi_register__append_buffer_288']?.()
|
||||
__napiInstance.exports['__napi_register__get_empty_buffer_289']?.()
|
||||
__napiInstance.exports['__napi_register__convert_u32_array_290']?.()
|
||||
__napiInstance.exports['__napi_register__create_external_typed_array_291']?.()
|
||||
__napiInstance.exports['__napi_register__mutate_typed_array_292']?.()
|
||||
__napiInstance.exports['__napi_register__deref_uint8_array_293']?.()
|
||||
__napiInstance.exports['__napi_register__buffer_pass_through_294']?.()
|
||||
__napiInstance.exports['__napi_register__array_buffer_pass_through_295']?.()
|
||||
__napiInstance.exports['__napi_register__AsyncBuffer_impl_296']?.()
|
||||
__napiInstance.exports['__napi_register__async_reduce_buffer_297']?.()
|
||||
}
|
||||
export const Animal = __napiModule.exports.Animal
|
||||
export const AnimalWithDefaultConstructor =
|
||||
|
@ -380,6 +395,8 @@ export const add = __napiModule.exports.add
|
|||
export const ALIAS = __napiModule.exports.ALIAS
|
||||
export const AliasedEnum = __napiModule.exports.AliasedEnum
|
||||
export const appendBuffer = __napiModule.exports.appendBuffer
|
||||
export const apply0 = __napiModule.exports.apply0
|
||||
export const apply1 = __napiModule.exports.apply1
|
||||
export const arrayBufferPassThrough =
|
||||
__napiModule.exports.arrayBufferPassThrough
|
||||
export const asyncMultiTwo = __napiModule.exports.asyncMultiTwo
|
||||
|
@ -393,9 +410,16 @@ export const bigintFromI128 = __napiModule.exports.bigintFromI128
|
|||
export const bigintFromI64 = __napiModule.exports.bigintFromI64
|
||||
export const bigintGetU64AsString = __napiModule.exports.bigintGetU64AsString
|
||||
export const bufferPassThrough = __napiModule.exports.bufferPassThrough
|
||||
export const call0 = __napiModule.exports.call0
|
||||
export const call1 = __napiModule.exports.call1
|
||||
export const call2 = __napiModule.exports.call2
|
||||
export const callbackReturnPromise = __napiModule.exports.callbackReturnPromise
|
||||
export const callbackReturnPromiseAndSpawn =
|
||||
__napiModule.exports.callbackReturnPromiseAndSpawn
|
||||
export const callFunction = __napiModule.exports.callFunction
|
||||
export const callFunctionWithArg = __napiModule.exports.callFunctionWithArg
|
||||
export const callFunctionWithArgAndCtx =
|
||||
__napiModule.exports.callFunctionWithArgAndCtx
|
||||
export const callLongThreadsafeFunction =
|
||||
__napiModule.exports.callLongThreadsafeFunction
|
||||
export const callThreadsafeFunction =
|
||||
|
@ -422,6 +446,8 @@ export const createObj = __napiModule.exports.createObj
|
|||
export const createObjectWithClassField =
|
||||
__napiModule.exports.createObjectWithClassField
|
||||
export const createObjWithProperty = __napiModule.exports.createObjWithProperty
|
||||
export const createReferenceOnFunction =
|
||||
__napiModule.exports.createReferenceOnFunction
|
||||
export const createSymbol = __napiModule.exports.createSymbol
|
||||
export const createSymbolFor = __napiModule.exports.createSymbolFor
|
||||
export const CustomNumEnum = __napiModule.exports.CustomNumEnum
|
||||
|
@ -486,6 +512,7 @@ export const receiveObjectWithClassField =
|
|||
__napiModule.exports.receiveObjectWithClassField
|
||||
export const receiveStrictObject = __napiModule.exports.receiveStrictObject
|
||||
export const receiveString = __napiModule.exports.receiveString
|
||||
export const referenceAsCallback = __napiModule.exports.referenceAsCallback
|
||||
export const returnEither = __napiModule.exports.returnEither
|
||||
export const returnEitherClass = __napiModule.exports.returnEitherClass
|
||||
export const returnFromSharedCrate = __napiModule.exports.returnFromSharedCrate
|
||||
|
|
|
@ -72,6 +72,7 @@ const { instance: __napiInstance, module: __wasiModule, napiModule: __napiModule
|
|||
})
|
||||
|
||||
function __napi_rs_initialize_modules(__napiInstance) {
|
||||
__napiInstance.exports['__napi_register__Shared_struct_0']?.()
|
||||
__napiInstance.exports['__napi_register__DEFAULT_COST_0']?.()
|
||||
__napiInstance.exports['__napi_register__TYPE_SKIPPED_CONST_1']?.()
|
||||
__napiInstance.exports['__napi_register__get_words_2']?.()
|
||||
|
@ -202,104 +203,114 @@ function __napi_rs_initialize_modules(__napiInstance) {
|
|||
__napiInstance.exports['__napi_register__ts_rename_172']?.()
|
||||
__napiInstance.exports['__napi_register__override_individual_arg_on_function_173']?.()
|
||||
__napiInstance.exports['__napi_register__override_individual_arg_on_function_with_cb_arg_174']?.()
|
||||
__napiInstance.exports['__napi_register__Fib_struct_175']?.()
|
||||
__napiInstance.exports['__napi_register__Fib_impl_176']?.()
|
||||
__napiInstance.exports['__napi_register__Fib_impl_178']?.()
|
||||
__napiInstance.exports['__napi_register__Fib2_struct_179']?.()
|
||||
__napiInstance.exports['__napi_register__Fib2_impl_180']?.()
|
||||
__napiInstance.exports['__napi_register__Fib2_impl_182']?.()
|
||||
__napiInstance.exports['__napi_register__Fib3_struct_183']?.()
|
||||
__napiInstance.exports['__napi_register__Fib3_impl_184']?.()
|
||||
__napiInstance.exports['__napi_register__ALIGNMENT_185']?.()
|
||||
__napiInstance.exports['__napi_register__xxh64_186']?.()
|
||||
__napiInstance.exports['__napi_register__xxh128_187']?.()
|
||||
__napiInstance.exports['__napi_register__Xxh3_struct_188']?.()
|
||||
__napiInstance.exports['__napi_register__Xxh3_impl_192']?.()
|
||||
__napiInstance.exports['__napi_register__xxh2_plus_193']?.()
|
||||
__napiInstance.exports['__napi_register__xxh3_xxh64_alias_194']?.()
|
||||
__napiInstance.exports['__napi_register__xxh64_alias_195']?.()
|
||||
__napiInstance.exports['__napi_register__get_mapping_196']?.()
|
||||
__napiInstance.exports['__napi_register__sum_mapping_197']?.()
|
||||
__napiInstance.exports['__napi_register__map_option_198']?.()
|
||||
__napiInstance.exports['__napi_register__return_null_199']?.()
|
||||
__napiInstance.exports['__napi_register__return_undefined_200']?.()
|
||||
__napiInstance.exports['__napi_register__add_201']?.()
|
||||
__napiInstance.exports['__napi_register__fibonacci_202']?.()
|
||||
__napiInstance.exports['__napi_register__list_obj_keys_203']?.()
|
||||
__napiInstance.exports['__napi_register__create_obj_204']?.()
|
||||
__napiInstance.exports['__napi_register__get_global_205']?.()
|
||||
__napiInstance.exports['__napi_register__get_undefined_206']?.()
|
||||
__napiInstance.exports['__napi_register__get_null_207']?.()
|
||||
__napiInstance.exports['__napi_register__AllOptionalObject_struct_208']?.()
|
||||
__napiInstance.exports['__napi_register__receive_all_optional_object_209']?.()
|
||||
__napiInstance.exports['__napi_register__AliasedEnum_210']?.()
|
||||
__napiInstance.exports['__napi_register__StructContainsAliasedEnum_struct_211']?.()
|
||||
__napiInstance.exports['__napi_register__fn_received_aliased_212']?.()
|
||||
__napiInstance.exports['__napi_register__StrictObject_struct_213']?.()
|
||||
__napiInstance.exports['__napi_register__receive_strict_object_214']?.()
|
||||
__napiInstance.exports['__napi_register__get_str_from_object_215']?.()
|
||||
__napiInstance.exports['__napi_register__TsTypeChanged_struct_216']?.()
|
||||
__napiInstance.exports['__napi_register__create_obj_with_property_217']?.()
|
||||
__napiInstance.exports['__napi_register__getter_from_obj_218']?.()
|
||||
__napiInstance.exports['__napi_register__ObjectOnlyFromJs_struct_219']?.()
|
||||
__napiInstance.exports['__napi_register__receive_object_only_from_js_220']?.()
|
||||
__napiInstance.exports['__napi_register__async_plus_100_221']?.()
|
||||
__napiInstance.exports['__napi_register__JsRepo_struct_222']?.()
|
||||
__napiInstance.exports['__napi_register__JsRepo_impl_225']?.()
|
||||
__napiInstance.exports['__napi_register__JsRemote_struct_226']?.()
|
||||
__napiInstance.exports['__napi_register__JsRemote_impl_228']?.()
|
||||
__napiInstance.exports['__napi_register__CSSRuleList_struct_229']?.()
|
||||
__napiInstance.exports['__napi_register__CSSRuleList_impl_233']?.()
|
||||
__napiInstance.exports['__napi_register__CSSStyleSheet_struct_234']?.()
|
||||
__napiInstance.exports['__napi_register__AnotherCSSStyleSheet_struct_235']?.()
|
||||
__napiInstance.exports['__napi_register__AnotherCSSStyleSheet_impl_237']?.()
|
||||
__napiInstance.exports['__napi_register__CSSStyleSheet_impl_241']?.()
|
||||
__napiInstance.exports['__napi_register__PackageJson_struct_242']?.()
|
||||
__napiInstance.exports['__napi_register__read_package_json_243']?.()
|
||||
__napiInstance.exports['__napi_register__get_package_json_name_244']?.()
|
||||
__napiInstance.exports['__napi_register__test_serde_roundtrip_245']?.()
|
||||
__napiInstance.exports['__napi_register__test_serde_big_number_precision_246']?.()
|
||||
__napiInstance.exports['__napi_register__return_from_shared_crate_247']?.()
|
||||
__napiInstance.exports['__napi_register__contains_248']?.()
|
||||
__napiInstance.exports['__napi_register__concat_str_249']?.()
|
||||
__napiInstance.exports['__napi_register__concat_utf16_250']?.()
|
||||
__napiInstance.exports['__napi_register__concat_latin1_251']?.()
|
||||
__napiInstance.exports['__napi_register__roundtrip_str_252']?.()
|
||||
__napiInstance.exports['__napi_register__set_symbol_in_obj_253']?.()
|
||||
__napiInstance.exports['__napi_register__create_symbol_254']?.()
|
||||
__napiInstance.exports['__napi_register__create_symbol_for_255']?.()
|
||||
__napiInstance.exports['__napi_register__DelaySum_impl_256']?.()
|
||||
__napiInstance.exports['__napi_register__without_abort_controller_257']?.()
|
||||
__napiInstance.exports['__napi_register__with_abort_controller_258']?.()
|
||||
__napiInstance.exports['__napi_register__AsyncTaskVoidReturn_impl_259']?.()
|
||||
__napiInstance.exports['__napi_register__async_task_void_return_260']?.()
|
||||
__napiInstance.exports['__napi_register__AsyncTaskOptionalReturn_impl_261']?.()
|
||||
__napiInstance.exports['__napi_register__async_task_optional_return_262']?.()
|
||||
__napiInstance.exports['__napi_register__call_threadsafe_function_263']?.()
|
||||
__napiInstance.exports['__napi_register__call_long_threadsafe_function_264']?.()
|
||||
__napiInstance.exports['__napi_register__threadsafe_function_throw_error_265']?.()
|
||||
__napiInstance.exports['__napi_register__threadsafe_function_fatal_mode_266']?.()
|
||||
__napiInstance.exports['__napi_register__threadsafe_function_fatal_mode_error_267']?.()
|
||||
__napiInstance.exports['__napi_register__threadsafe_function_closure_capture_268']?.()
|
||||
__napiInstance.exports['__napi_register__tsfn_call_with_callback_269']?.()
|
||||
__napiInstance.exports['__napi_register__tsfn_async_call_270']?.()
|
||||
__napiInstance.exports['__napi_register__accept_threadsafe_function_271']?.()
|
||||
__napiInstance.exports['__napi_register__accept_threadsafe_function_fatal_272']?.()
|
||||
__napiInstance.exports['__napi_register__accept_threadsafe_function_tuple_args_273']?.()
|
||||
__napiInstance.exports['__napi_register__tsfn_return_promise_274']?.()
|
||||
__napiInstance.exports['__napi_register__tsfn_return_promise_timeout_275']?.()
|
||||
__napiInstance.exports['__napi_register__tsfn_throw_from_js_276']?.()
|
||||
__napiInstance.exports['__napi_register__get_buffer_277']?.()
|
||||
__napiInstance.exports['__napi_register__append_buffer_278']?.()
|
||||
__napiInstance.exports['__napi_register__get_empty_buffer_279']?.()
|
||||
__napiInstance.exports['__napi_register__convert_u32_array_280']?.()
|
||||
__napiInstance.exports['__napi_register__create_external_typed_array_281']?.()
|
||||
__napiInstance.exports['__napi_register__mutate_typed_array_282']?.()
|
||||
__napiInstance.exports['__napi_register__deref_uint8_array_283']?.()
|
||||
__napiInstance.exports['__napi_register__buffer_pass_through_284']?.()
|
||||
__napiInstance.exports['__napi_register__array_buffer_pass_through_285']?.()
|
||||
__napiInstance.exports['__napi_register__AsyncBuffer_impl_286']?.()
|
||||
__napiInstance.exports['__napi_register__async_reduce_buffer_287']?.()
|
||||
__napiInstance.exports['__napi_register__call0_175']?.()
|
||||
__napiInstance.exports['__napi_register__call1_176']?.()
|
||||
__napiInstance.exports['__napi_register__call2_177']?.()
|
||||
__napiInstance.exports['__napi_register__apply0_178']?.()
|
||||
__napiInstance.exports['__napi_register__apply1_179']?.()
|
||||
__napiInstance.exports['__napi_register__call_function_180']?.()
|
||||
__napiInstance.exports['__napi_register__call_function_with_arg_181']?.()
|
||||
__napiInstance.exports['__napi_register__create_reference_on_function_182']?.()
|
||||
__napiInstance.exports['__napi_register__call_function_with_arg_and_ctx_183']?.()
|
||||
__napiInstance.exports['__napi_register__reference_as_callback_184']?.()
|
||||
__napiInstance.exports['__napi_register__Fib_struct_185']?.()
|
||||
__napiInstance.exports['__napi_register__Fib_impl_186']?.()
|
||||
__napiInstance.exports['__napi_register__Fib_impl_188']?.()
|
||||
__napiInstance.exports['__napi_register__Fib2_struct_189']?.()
|
||||
__napiInstance.exports['__napi_register__Fib2_impl_190']?.()
|
||||
__napiInstance.exports['__napi_register__Fib2_impl_192']?.()
|
||||
__napiInstance.exports['__napi_register__Fib3_struct_193']?.()
|
||||
__napiInstance.exports['__napi_register__Fib3_impl_194']?.()
|
||||
__napiInstance.exports['__napi_register__ALIGNMENT_195']?.()
|
||||
__napiInstance.exports['__napi_register__xxh64_196']?.()
|
||||
__napiInstance.exports['__napi_register__xxh128_197']?.()
|
||||
__napiInstance.exports['__napi_register__Xxh3_struct_198']?.()
|
||||
__napiInstance.exports['__napi_register__Xxh3_impl_202']?.()
|
||||
__napiInstance.exports['__napi_register__xxh2_plus_203']?.()
|
||||
__napiInstance.exports['__napi_register__xxh3_xxh64_alias_204']?.()
|
||||
__napiInstance.exports['__napi_register__xxh64_alias_205']?.()
|
||||
__napiInstance.exports['__napi_register__get_mapping_206']?.()
|
||||
__napiInstance.exports['__napi_register__sum_mapping_207']?.()
|
||||
__napiInstance.exports['__napi_register__map_option_208']?.()
|
||||
__napiInstance.exports['__napi_register__return_null_209']?.()
|
||||
__napiInstance.exports['__napi_register__return_undefined_210']?.()
|
||||
__napiInstance.exports['__napi_register__add_211']?.()
|
||||
__napiInstance.exports['__napi_register__fibonacci_212']?.()
|
||||
__napiInstance.exports['__napi_register__list_obj_keys_213']?.()
|
||||
__napiInstance.exports['__napi_register__create_obj_214']?.()
|
||||
__napiInstance.exports['__napi_register__get_global_215']?.()
|
||||
__napiInstance.exports['__napi_register__get_undefined_216']?.()
|
||||
__napiInstance.exports['__napi_register__get_null_217']?.()
|
||||
__napiInstance.exports['__napi_register__AllOptionalObject_struct_218']?.()
|
||||
__napiInstance.exports['__napi_register__receive_all_optional_object_219']?.()
|
||||
__napiInstance.exports['__napi_register__AliasedEnum_220']?.()
|
||||
__napiInstance.exports['__napi_register__StructContainsAliasedEnum_struct_221']?.()
|
||||
__napiInstance.exports['__napi_register__fn_received_aliased_222']?.()
|
||||
__napiInstance.exports['__napi_register__StrictObject_struct_223']?.()
|
||||
__napiInstance.exports['__napi_register__receive_strict_object_224']?.()
|
||||
__napiInstance.exports['__napi_register__get_str_from_object_225']?.()
|
||||
__napiInstance.exports['__napi_register__TsTypeChanged_struct_226']?.()
|
||||
__napiInstance.exports['__napi_register__create_obj_with_property_227']?.()
|
||||
__napiInstance.exports['__napi_register__getter_from_obj_228']?.()
|
||||
__napiInstance.exports['__napi_register__ObjectOnlyFromJs_struct_229']?.()
|
||||
__napiInstance.exports['__napi_register__receive_object_only_from_js_230']?.()
|
||||
__napiInstance.exports['__napi_register__async_plus_100_231']?.()
|
||||
__napiInstance.exports['__napi_register__JsRepo_struct_232']?.()
|
||||
__napiInstance.exports['__napi_register__JsRepo_impl_235']?.()
|
||||
__napiInstance.exports['__napi_register__JsRemote_struct_236']?.()
|
||||
__napiInstance.exports['__napi_register__JsRemote_impl_238']?.()
|
||||
__napiInstance.exports['__napi_register__CSSRuleList_struct_239']?.()
|
||||
__napiInstance.exports['__napi_register__CSSRuleList_impl_243']?.()
|
||||
__napiInstance.exports['__napi_register__CSSStyleSheet_struct_244']?.()
|
||||
__napiInstance.exports['__napi_register__AnotherCSSStyleSheet_struct_245']?.()
|
||||
__napiInstance.exports['__napi_register__AnotherCSSStyleSheet_impl_247']?.()
|
||||
__napiInstance.exports['__napi_register__CSSStyleSheet_impl_251']?.()
|
||||
__napiInstance.exports['__napi_register__PackageJson_struct_252']?.()
|
||||
__napiInstance.exports['__napi_register__read_package_json_253']?.()
|
||||
__napiInstance.exports['__napi_register__get_package_json_name_254']?.()
|
||||
__napiInstance.exports['__napi_register__test_serde_roundtrip_255']?.()
|
||||
__napiInstance.exports['__napi_register__test_serde_big_number_precision_256']?.()
|
||||
__napiInstance.exports['__napi_register__return_from_shared_crate_257']?.()
|
||||
__napiInstance.exports['__napi_register__contains_258']?.()
|
||||
__napiInstance.exports['__napi_register__concat_str_259']?.()
|
||||
__napiInstance.exports['__napi_register__concat_utf16_260']?.()
|
||||
__napiInstance.exports['__napi_register__concat_latin1_261']?.()
|
||||
__napiInstance.exports['__napi_register__roundtrip_str_262']?.()
|
||||
__napiInstance.exports['__napi_register__set_symbol_in_obj_263']?.()
|
||||
__napiInstance.exports['__napi_register__create_symbol_264']?.()
|
||||
__napiInstance.exports['__napi_register__create_symbol_for_265']?.()
|
||||
__napiInstance.exports['__napi_register__DelaySum_impl_266']?.()
|
||||
__napiInstance.exports['__napi_register__without_abort_controller_267']?.()
|
||||
__napiInstance.exports['__napi_register__with_abort_controller_268']?.()
|
||||
__napiInstance.exports['__napi_register__AsyncTaskVoidReturn_impl_269']?.()
|
||||
__napiInstance.exports['__napi_register__async_task_void_return_270']?.()
|
||||
__napiInstance.exports['__napi_register__AsyncTaskOptionalReturn_impl_271']?.()
|
||||
__napiInstance.exports['__napi_register__async_task_optional_return_272']?.()
|
||||
__napiInstance.exports['__napi_register__call_threadsafe_function_273']?.()
|
||||
__napiInstance.exports['__napi_register__call_long_threadsafe_function_274']?.()
|
||||
__napiInstance.exports['__napi_register__threadsafe_function_throw_error_275']?.()
|
||||
__napiInstance.exports['__napi_register__threadsafe_function_fatal_mode_276']?.()
|
||||
__napiInstance.exports['__napi_register__threadsafe_function_fatal_mode_error_277']?.()
|
||||
__napiInstance.exports['__napi_register__threadsafe_function_closure_capture_278']?.()
|
||||
__napiInstance.exports['__napi_register__tsfn_call_with_callback_279']?.()
|
||||
__napiInstance.exports['__napi_register__tsfn_async_call_280']?.()
|
||||
__napiInstance.exports['__napi_register__accept_threadsafe_function_281']?.()
|
||||
__napiInstance.exports['__napi_register__accept_threadsafe_function_fatal_282']?.()
|
||||
__napiInstance.exports['__napi_register__accept_threadsafe_function_tuple_args_283']?.()
|
||||
__napiInstance.exports['__napi_register__tsfn_return_promise_284']?.()
|
||||
__napiInstance.exports['__napi_register__tsfn_return_promise_timeout_285']?.()
|
||||
__napiInstance.exports['__napi_register__tsfn_throw_from_js_286']?.()
|
||||
__napiInstance.exports['__napi_register__get_buffer_287']?.()
|
||||
__napiInstance.exports['__napi_register__append_buffer_288']?.()
|
||||
__napiInstance.exports['__napi_register__get_empty_buffer_289']?.()
|
||||
__napiInstance.exports['__napi_register__convert_u32_array_290']?.()
|
||||
__napiInstance.exports['__napi_register__create_external_typed_array_291']?.()
|
||||
__napiInstance.exports['__napi_register__mutate_typed_array_292']?.()
|
||||
__napiInstance.exports['__napi_register__deref_uint8_array_293']?.()
|
||||
__napiInstance.exports['__napi_register__buffer_pass_through_294']?.()
|
||||
__napiInstance.exports['__napi_register__array_buffer_pass_through_295']?.()
|
||||
__napiInstance.exports['__napi_register__AsyncBuffer_impl_296']?.()
|
||||
__napiInstance.exports['__napi_register__async_reduce_buffer_297']?.()
|
||||
}
|
||||
module.exports.Animal = __napiModule.exports.Animal
|
||||
module.exports.AnimalWithDefaultConstructor = __napiModule.exports.AnimalWithDefaultConstructor
|
||||
|
@ -344,6 +355,8 @@ module.exports.add = __napiModule.exports.add
|
|||
module.exports.ALIAS = __napiModule.exports.ALIAS
|
||||
module.exports.AliasedEnum = __napiModule.exports.AliasedEnum
|
||||
module.exports.appendBuffer = __napiModule.exports.appendBuffer
|
||||
module.exports.apply0 = __napiModule.exports.apply0
|
||||
module.exports.apply1 = __napiModule.exports.apply1
|
||||
module.exports.arrayBufferPassThrough = __napiModule.exports.arrayBufferPassThrough
|
||||
module.exports.asyncMultiTwo = __napiModule.exports.asyncMultiTwo
|
||||
module.exports.asyncPlus100 = __napiModule.exports.asyncPlus100
|
||||
|
@ -355,8 +368,14 @@ module.exports.bigintFromI128 = __napiModule.exports.bigintFromI128
|
|||
module.exports.bigintFromI64 = __napiModule.exports.bigintFromI64
|
||||
module.exports.bigintGetU64AsString = __napiModule.exports.bigintGetU64AsString
|
||||
module.exports.bufferPassThrough = __napiModule.exports.bufferPassThrough
|
||||
module.exports.call0 = __napiModule.exports.call0
|
||||
module.exports.call1 = __napiModule.exports.call1
|
||||
module.exports.call2 = __napiModule.exports.call2
|
||||
module.exports.callbackReturnPromise = __napiModule.exports.callbackReturnPromise
|
||||
module.exports.callbackReturnPromiseAndSpawn = __napiModule.exports.callbackReturnPromiseAndSpawn
|
||||
module.exports.callFunction = __napiModule.exports.callFunction
|
||||
module.exports.callFunctionWithArg = __napiModule.exports.callFunctionWithArg
|
||||
module.exports.callFunctionWithArgAndCtx = __napiModule.exports.callFunctionWithArgAndCtx
|
||||
module.exports.callLongThreadsafeFunction = __napiModule.exports.callLongThreadsafeFunction
|
||||
module.exports.callThreadsafeFunction = __napiModule.exports.callThreadsafeFunction
|
||||
module.exports.captureErrorInCallback = __napiModule.exports.captureErrorInCallback
|
||||
|
@ -377,6 +396,7 @@ module.exports.createExternalTypedArray = __napiModule.exports.createExternalTyp
|
|||
module.exports.createObj = __napiModule.exports.createObj
|
||||
module.exports.createObjectWithClassField = __napiModule.exports.createObjectWithClassField
|
||||
module.exports.createObjWithProperty = __napiModule.exports.createObjWithProperty
|
||||
module.exports.createReferenceOnFunction = __napiModule.exports.createReferenceOnFunction
|
||||
module.exports.createSymbol = __napiModule.exports.createSymbol
|
||||
module.exports.createSymbolFor = __napiModule.exports.createSymbolFor
|
||||
module.exports.CustomNumEnum = __napiModule.exports.CustomNumEnum
|
||||
|
@ -435,6 +455,7 @@ module.exports.receiveObjectOnlyFromJs = __napiModule.exports.receiveObjectOnlyF
|
|||
module.exports.receiveObjectWithClassField = __napiModule.exports.receiveObjectWithClassField
|
||||
module.exports.receiveStrictObject = __napiModule.exports.receiveStrictObject
|
||||
module.exports.receiveString = __napiModule.exports.receiveString
|
||||
module.exports.referenceAsCallback = __napiModule.exports.referenceAsCallback
|
||||
module.exports.returnEither = __napiModule.exports.returnEither
|
||||
module.exports.returnEitherClass = __napiModule.exports.returnEitherClass
|
||||
module.exports.returnFromSharedCrate = __napiModule.exports.returnFromSharedCrate
|
||||
|
|
76
examples/napi/src/function.rs
Normal file
76
examples/napi/src/function.rs
Normal file
|
@ -0,0 +1,76 @@
|
|||
use napi::{
|
||||
bindgen_prelude::{ClassInstance, Function, FunctionRef},
|
||||
Env, JsFunction, JsObject, Result,
|
||||
};
|
||||
|
||||
use crate::class::Animal;
|
||||
|
||||
#[napi]
|
||||
pub fn call0(callback: JsFunction) -> Result<u32> {
|
||||
callback.call0()
|
||||
}
|
||||
|
||||
#[napi]
|
||||
pub fn call1(callback: JsFunction, arg: u32) -> Result<u32> {
|
||||
callback.call1(arg)
|
||||
}
|
||||
|
||||
#[napi]
|
||||
pub fn call2(callback: JsFunction, arg1: u32, arg2: u32) -> Result<u32> {
|
||||
callback.call2(arg1, arg2)
|
||||
}
|
||||
|
||||
#[napi]
|
||||
pub fn apply0(ctx: ClassInstance<Animal>, callback: JsFunction) -> Result<()> {
|
||||
callback.apply0(ctx)
|
||||
}
|
||||
|
||||
#[napi]
|
||||
pub fn apply1(ctx: ClassInstance<Animal>, callback: JsFunction, name: String) -> Result<()> {
|
||||
callback.apply1(ctx, name)
|
||||
}
|
||||
|
||||
#[napi]
|
||||
pub fn call_function(cb: Function<(), u32>) -> Result<u32> {
|
||||
cb.call(())
|
||||
}
|
||||
|
||||
#[napi]
|
||||
pub fn call_function_with_arg(cb: Function<(u32, u32), u32>, arg0: u32, arg1: u32) -> Result<u32> {
|
||||
cb.call((arg0, arg1))
|
||||
}
|
||||
|
||||
#[napi]
|
||||
pub fn create_reference_on_function(env: Env, cb: Function<(), ()>) -> Result<JsObject> {
|
||||
let reference = cb.create_ref()?;
|
||||
env.execute_tokio_future(
|
||||
async {
|
||||
tokio::time::sleep(std::time::Duration::from_millis(100)).await;
|
||||
Ok(())
|
||||
},
|
||||
move |env, _| {
|
||||
let cb = reference.borrow_back(&env)?;
|
||||
cb.call(())?;
|
||||
Ok(())
|
||||
},
|
||||
)
|
||||
}
|
||||
|
||||
#[napi]
|
||||
pub fn call_function_with_arg_and_ctx(
|
||||
ctx: ClassInstance<Animal>,
|
||||
cb: Function<String, ()>,
|
||||
name: String,
|
||||
) -> Result<()> {
|
||||
cb.apply(ctx, name)
|
||||
}
|
||||
|
||||
#[napi]
|
||||
pub fn reference_as_callback(
|
||||
env: Env,
|
||||
callback: FunctionRef<(u32, u32), u32>,
|
||||
arg0: u32,
|
||||
arg1: u32,
|
||||
) -> Result<u32> {
|
||||
callback.borrow_back(&env)?.call((arg0, arg1))
|
||||
}
|
|
@ -35,6 +35,7 @@ mod error;
|
|||
mod external;
|
||||
mod fn_strict;
|
||||
mod fn_ts_override;
|
||||
mod function;
|
||||
mod generator;
|
||||
mod js_mod;
|
||||
mod map;
|
||||
|
|
Loading…
Reference in a new issue