napi/bindgen_runtime/js_values/
function.rs

1use std::ptr;
2
3use super::{Either, FromNapiValue, ToNapiValue, TypeName, Unknown, ValidateNapiValue};
4
5#[cfg(feature = "napi4")]
6use crate::threadsafe_function::{ThreadsafeCallContext, ThreadsafeFunction};
7#[cfg(feature = "compat-mode")]
8#[allow(deprecated)]
9pub use crate::JsFunction;
10use crate::{
11  bindgen_runtime::JsObjectValue, check_pending_exception, check_status, sys, Env, JsValue, Result,
12  Status, ValueType,
13};
14
15pub trait JsValuesTupleIntoVec {
16  fn into_vec(self, env: sys::napi_env) -> Result<Vec<sys::napi_value>>;
17}
18
19impl<T> JsValuesTupleIntoVec for T
20where
21  T: ToNapiValue,
22{
23  #[allow(clippy::not_unsafe_ptr_arg_deref)]
24  fn into_vec(self, env: sys::napi_env) -> Result<Vec<sys::napi_value>> {
25    // allow call function with `()` and function's arguments should be empty array
26    if std::mem::size_of::<T>() == 0 {
27      Ok(vec![])
28    } else {
29      Ok(vec![unsafe {
30        <T as ToNapiValue>::to_napi_value(env, self)?
31      }])
32    }
33  }
34}
35pub trait TupleFromSliceValues {
36  #[allow(clippy::missing_safety_doc)]
37  unsafe fn from_slice_values(env: sys::napi_env, values: &[sys::napi_value]) -> Result<Self>
38  where
39    Self: Sized;
40}
41
42#[repr(C)]
43pub struct FnArgs<T> {
44  pub data: T,
45}
46
47impl<T> From<T> for FnArgs<T> {
48  fn from(value: T) -> Self {
49    FnArgs { data: value }
50  }
51}
52
53macro_rules! impl_tuple_conversion {
54  ($($ident:ident),*) => {
55    impl<$($ident: ToNapiValue),*> JsValuesTupleIntoVec for FnArgs<($($ident,)*)> {
56      #[allow(clippy::not_unsafe_ptr_arg_deref)]
57      fn into_vec(self, env: sys::napi_env) -> Result<Vec<sys::napi_value>> {
58        #[allow(non_snake_case)]
59        let ($($ident,)*) = self.data;
60        Ok(vec![$(unsafe { <$ident as ToNapiValue>::to_napi_value(env, $ident)? }),*])
61      }
62    }
63
64    impl<$($ident: FromNapiValue),*> TupleFromSliceValues for ($($ident,)*) {
65      unsafe fn from_slice_values(env: sys::napi_env, values: &[sys::napi_value]) -> $crate::Result<Self> {
66        #[allow(non_snake_case)]
67        let [$($ident),*] = values.try_into().map_err(|_| crate::Error::new(
68          crate::Status::InvalidArg,
69          "Invalid number of arguments",
70        ))?;
71        Ok(($(
72          unsafe { $ident::from_napi_value(env, $ident)?}
73        ,)*))
74      }
75    }
76  };
77}
78
79impl_tuple_conversion!(A);
80impl_tuple_conversion!(A, B);
81impl_tuple_conversion!(A, B, C);
82impl_tuple_conversion!(A, B, C, D);
83impl_tuple_conversion!(A, B, C, D, E);
84impl_tuple_conversion!(A, B, C, D, E, F);
85impl_tuple_conversion!(A, B, C, D, E, F, G);
86impl_tuple_conversion!(A, B, C, D, E, F, G, H);
87impl_tuple_conversion!(A, B, C, D, E, F, G, H, I);
88impl_tuple_conversion!(A, B, C, D, E, F, G, H, I, J);
89impl_tuple_conversion!(A, B, C, D, E, F, G, H, I, J, K);
90impl_tuple_conversion!(A, B, C, D, E, F, G, H, I, J, K, L);
91impl_tuple_conversion!(A, B, C, D, E, F, G, H, I, J, K, L, M);
92impl_tuple_conversion!(A, B, C, D, E, F, G, H, I, J, K, L, M, N);
93impl_tuple_conversion!(A, B, C, D, E, F, G, H, I, J, K, L, M, N, O);
94impl_tuple_conversion!(A, B, C, D, E, F, G, H, I, J, K, L, M, N, O, P);
95impl_tuple_conversion!(A, B, C, D, E, F, G, H, I, J, K, L, M, N, O, P, Q);
96impl_tuple_conversion!(A, B, C, D, E, F, G, H, I, J, K, L, M, N, O, P, Q, R);
97impl_tuple_conversion!(A, B, C, D, E, F, G, H, I, J, K, L, M, N, O, P, Q, R, S);
98impl_tuple_conversion!(A, B, C, D, E, F, G, H, I, J, K, L, M, N, O, P, Q, R, S, T);
99impl_tuple_conversion!(A, B, C, D, E, F, G, H, I, J, K, L, M, N, O, P, Q, R, S, T, U);
100impl_tuple_conversion!(A, B, C, D, E, F, G, H, I, J, K, L, M, N, O, P, Q, R, S, T, U, V);
101impl_tuple_conversion!(A, B, C, D, E, F, G, H, I, J, K, L, M, N, O, P, Q, R, S, T, U, V, W);
102impl_tuple_conversion!(A, B, C, D, E, F, G, H, I, J, K, L, M, N, O, P, Q, R, S, T, U, V, W, X);
103impl_tuple_conversion!(A, B, C, D, E, F, G, H, I, J, K, L, M, N, O, P, Q, R, S, T, U, V, W, X, Y);
104impl_tuple_conversion!(
105  A, B, C, D, E, F, G, H, I, J, K, L, M, N, O, P, Q, R, S, T, U, V, W, X, Y, Z
106);
107
108#[derive(Clone, Copy)]
109/// A JavaScript function.
110/// It can only live in the scope of a function call.
111/// If you want to use it outside the scope of a function call, you can turn it into a reference.
112/// By calling the `create_ref` method.
113pub struct Function<'scope, Args: JsValuesTupleIntoVec = Unknown<'scope>, Return = Unknown<'scope>>
114{
115  pub(crate) env: sys::napi_env,
116  pub(crate) value: sys::napi_value,
117  pub(crate) _args: std::marker::PhantomData<Args>,
118  pub(crate) _return: std::marker::PhantomData<Return>,
119  pub(crate) _scope: std::marker::PhantomData<&'scope ()>,
120}
121
122impl<Args: JsValuesTupleIntoVec, Return> TypeName for Function<'_, Args, Return> {
123  fn type_name() -> &'static str {
124    "Function"
125  }
126
127  fn value_type() -> crate::ValueType {
128    ValueType::Function
129  }
130}
131
132impl<'env, Args: JsValuesTupleIntoVec, Return> JsValue<'env> for Function<'env, Args, Return> {
133  fn value(&self) -> crate::Value {
134    crate::Value {
135      value: self.value,
136      env: self.env,
137      value_type: ValueType::Function,
138    }
139  }
140}
141
142impl<'env, Args: JsValuesTupleIntoVec, Return> JsObjectValue<'env>
143  for Function<'env, Args, Return>
144{
145}
146
147impl<Args: JsValuesTupleIntoVec, Return> FromNapiValue for Function<'_, Args, Return> {
148  unsafe fn from_napi_value(env: sys::napi_env, value: sys::napi_value) -> Result<Self> {
149    Ok(Function {
150      env,
151      value,
152      _args: std::marker::PhantomData,
153      _return: std::marker::PhantomData,
154      _scope: std::marker::PhantomData,
155    })
156  }
157}
158
159impl<Args: JsValuesTupleIntoVec, Return> ValidateNapiValue for Function<'_, Args, Return> {}
160
161impl<Args: JsValuesTupleIntoVec, Return> Function<'_, Args, Return> {
162  /// Get the name of the JavaScript function.
163  pub fn name(&self) -> Result<String> {
164    let mut name = ptr::null_mut();
165    check_status!(
166      unsafe {
167        sys::napi_get_named_property(self.env, self.value, c"name".as_ptr().cast(), &mut name)
168      },
169      "Get function name failed"
170    )?;
171    unsafe { String::from_napi_value(self.env, name) }
172  }
173
174  /// Create a reference to the JavaScript function.
175  pub fn create_ref(&self) -> Result<FunctionRef<Args, Return>> {
176    let mut reference = ptr::null_mut();
177    check_status!(
178      unsafe { sys::napi_create_reference(self.env, self.value, 1, &mut reference) },
179      "Create reference failed"
180    )?;
181    Ok(FunctionRef {
182      inner: reference,
183      env: self.env,
184      _args: std::marker::PhantomData,
185      _return: std::marker::PhantomData,
186    })
187  }
188
189  /// Create a new instance of the JavaScript Class.
190  pub fn new_instance(&self, args: Args) -> Result<Unknown<'_>> {
191    let mut raw_instance = ptr::null_mut();
192    let mut args = args.into_vec(self.env)?;
193    check_status!(
194      unsafe {
195        sys::napi_new_instance(
196          self.env,
197          self.value,
198          args.len(),
199          args.as_mut_ptr().cast(),
200          &mut raw_instance,
201        )
202      },
203      "Create new instance failed"
204    )?;
205    unsafe { Unknown::from_napi_value(self.env, raw_instance) }
206  }
207
208  #[cfg(feature = "napi4")]
209  /// Create a threadsafe function from the JavaScript function.
210  pub fn build_threadsafe_function<T: 'static>(
211    &self,
212  ) -> ThreadsafeFunctionBuilder<'_, T, Args, Return> {
213    ThreadsafeFunctionBuilder {
214      env: self.env,
215      value: self.value,
216      _args: std::marker::PhantomData,
217      _return: std::marker::PhantomData,
218    }
219  }
220}
221
222impl<Args: JsValuesTupleIntoVec, Return: FromNapiValue> Function<'_, Args, Return> {
223  /// Call the JavaScript function.
224  /// `this` in the JavaScript function will be `undefined`.
225  /// If you want to specify `this`, you can use the `apply` method.
226  pub fn call(&self, args: Args) -> Result<Return> {
227    let mut raw_this = ptr::null_mut();
228    check_status!(
229      unsafe { sys::napi_get_undefined(self.env, &mut raw_this) },
230      "Get undefined value failed"
231    )?;
232    let args_ptr = args.into_vec(self.env)?;
233    let mut raw_return = ptr::null_mut();
234    check_pending_exception!(
235      self.env,
236      unsafe {
237        sys::napi_call_function(
238          self.env,
239          raw_this,
240          self.value,
241          args_ptr.len(),
242          args_ptr.as_ptr(),
243          &mut raw_return,
244        )
245      },
246      "Call Function failed"
247    )?;
248    unsafe { Return::from_napi_value(self.env, raw_return) }
249  }
250
251  /// Call the JavaScript function.
252  /// `this` in the JavaScript function will be the provided `this`.
253  pub fn apply<Context: ToNapiValue>(&self, this: Context, args: Args) -> Result<Return> {
254    let raw_this = unsafe { Context::to_napi_value(self.env, this) }?;
255    let args_ptr = args.into_vec(self.env)?;
256    let mut raw_return = ptr::null_mut();
257    check_status!(
258      unsafe {
259        sys::napi_call_function(
260          self.env,
261          raw_this,
262          self.value,
263          args_ptr.len(),
264          args_ptr.as_ptr(),
265          &mut raw_return,
266        )
267      },
268      "Call Function failed"
269    )?;
270    unsafe { Return::from_napi_value(self.env, raw_return) }
271  }
272
273  /// Call `Function.bind`
274  pub fn bind<T: ToNapiValue>(&self, this: T) -> Result<Function<'_, Args, Return>> {
275    let raw_this = unsafe { T::to_napi_value(self.env, this) }?;
276    let mut bind_function = ptr::null_mut();
277    check_status!(
278      unsafe {
279        sys::napi_get_named_property(self.env, self.value, c"bind".as_ptr(), &mut bind_function)
280      },
281      "Get bind function failed"
282    )?;
283    let mut bound_function = ptr::null_mut();
284    check_status!(
285      unsafe {
286        sys::napi_call_function(
287          self.env,
288          self.value,
289          bind_function,
290          1,
291          [raw_this].as_ptr(),
292          &mut bound_function,
293        )
294      },
295      "Bind function failed"
296    )?;
297    Ok(Function {
298      env: self.env,
299      value: bound_function,
300      _args: std::marker::PhantomData,
301      _return: std::marker::PhantomData,
302      _scope: std::marker::PhantomData,
303    })
304  }
305}
306
307#[cfg(feature = "napi4")]
308pub struct ThreadsafeFunctionBuilder<
309  'env,
310  T: 'static,
311  Args: 'static + JsValuesTupleIntoVec,
312  Return,
313  ErrorStatus: AsRef<str> + From<Status> = Status,
314  const CalleeHandled: bool = false,
315  const Weak: bool = false,
316  const MaxQueueSize: usize = 0,
317> {
318  pub(crate) env: sys::napi_env,
319  pub(crate) value: sys::napi_value,
320  _args: std::marker::PhantomData<(T, &'env Args, ErrorStatus)>,
321  _return: std::marker::PhantomData<Return>,
322}
323
324#[cfg(feature = "napi4")]
325impl<
326    'env,
327    T: 'static,
328    Args: 'static + JsValuesTupleIntoVec,
329    Return: FromNapiValue,
330    ErrorStatus: AsRef<str> + From<Status>,
331    const CalleeHandled: bool,
332    const Weak: bool,
333    const MaxQueueSize: usize,
334  >
335  ThreadsafeFunctionBuilder<'env, T, Args, Return, ErrorStatus, CalleeHandled, Weak, MaxQueueSize>
336{
337  pub fn error_status<NewErrorStatus: AsRef<str> + From<Status>>(
338    self,
339  ) -> ThreadsafeFunctionBuilder<
340    'env,
341    T,
342    Args,
343    Return,
344    NewErrorStatus,
345    CalleeHandled,
346    Weak,
347    MaxQueueSize,
348  > {
349    ThreadsafeFunctionBuilder {
350      env: self.env,
351      value: self.value,
352      _args: std::marker::PhantomData,
353      _return: std::marker::PhantomData,
354    }
355  }
356
357  pub fn weak<const NewWeak: bool>(
358    self,
359  ) -> ThreadsafeFunctionBuilder<
360    'env,
361    T,
362    Args,
363    Return,
364    ErrorStatus,
365    CalleeHandled,
366    NewWeak,
367    MaxQueueSize,
368  > {
369    ThreadsafeFunctionBuilder {
370      env: self.env,
371      value: self.value,
372      _args: std::marker::PhantomData,
373      _return: std::marker::PhantomData,
374    }
375  }
376
377  pub fn callee_handled<const NewCalleeHandled: bool>(
378    self,
379  ) -> ThreadsafeFunctionBuilder<
380    'env,
381    T,
382    Args,
383    Return,
384    ErrorStatus,
385    NewCalleeHandled,
386    Weak,
387    MaxQueueSize,
388  > {
389    ThreadsafeFunctionBuilder {
390      env: self.env,
391      value: self.value,
392      _args: std::marker::PhantomData,
393      _return: std::marker::PhantomData,
394    }
395  }
396
397  pub fn max_queue_size<const NewMaxQueueSize: usize>(
398    self,
399  ) -> ThreadsafeFunctionBuilder<
400    'env,
401    T,
402    Args,
403    Return,
404    ErrorStatus,
405    CalleeHandled,
406    Weak,
407    NewMaxQueueSize,
408  > {
409    ThreadsafeFunctionBuilder {
410      env: self.env,
411      value: self.value,
412      _args: std::marker::PhantomData,
413      _return: std::marker::PhantomData,
414    }
415  }
416
417  pub fn build_callback<CallJsBackArgs, Callback>(
418    &self,
419    call_js_back: Callback,
420  ) -> Result<
421    ThreadsafeFunction<T, Return, CallJsBackArgs, ErrorStatus, CalleeHandled, Weak, MaxQueueSize>,
422  >
423  where
424    CallJsBackArgs: 'static + JsValuesTupleIntoVec,
425    Callback: 'static + FnMut(ThreadsafeCallContext<T>) -> Result<CallJsBackArgs>,
426    ErrorStatus: AsRef<str>,
427    ErrorStatus: From<Status>,
428  {
429    ThreadsafeFunction::<T, Return, Args, ErrorStatus, CalleeHandled, Weak, MaxQueueSize>::create(
430      self.env,
431      self.value,
432      call_js_back,
433    )
434  }
435}
436
437#[cfg(feature = "napi4")]
438impl<
439    T: 'static + JsValuesTupleIntoVec,
440    Return: FromNapiValue,
441    ErrorStatus: AsRef<str> + From<Status>,
442    const CalleeHandled: bool,
443    const Weak: bool,
444    const MaxQueueSize: usize,
445  > ThreadsafeFunctionBuilder<'_, T, T, Return, ErrorStatus, CalleeHandled, Weak, MaxQueueSize>
446{
447  pub fn build(
448    &self,
449  ) -> Result<ThreadsafeFunction<T, Return, T, ErrorStatus, CalleeHandled, Weak, MaxQueueSize>> {
450    unsafe { ThreadsafeFunction::from_napi_value(self.env, self.value) }
451  }
452}
453
454/// A reference to a JavaScript function.
455/// It can be used to outlive the scope of the function.
456pub struct FunctionRef<Args: JsValuesTupleIntoVec, Return> {
457  pub(crate) inner: sys::napi_ref,
458  pub(crate) env: sys::napi_env,
459  _args: std::marker::PhantomData<Args>,
460  _return: std::marker::PhantomData<Return>,
461}
462
463unsafe impl<Args: JsValuesTupleIntoVec, Return> Send for FunctionRef<Args, Return> {}
464unsafe impl<Args: JsValuesTupleIntoVec, Return> Sync for FunctionRef<Args, Return> {}
465
466impl<Args: JsValuesTupleIntoVec, Return> FunctionRef<Args, Return> {
467  pub fn borrow_back<'scope>(&self, env: &'scope Env) -> Result<Function<'scope, Args, Return>> {
468    let mut value = ptr::null_mut();
469    check_status!(
470      unsafe { sys::napi_get_reference_value(env.0, self.inner, &mut value) },
471      "Get reference value failed"
472    )?;
473    Ok(Function {
474      env: env.0,
475      value,
476      _args: std::marker::PhantomData,
477      _return: std::marker::PhantomData,
478      _scope: std::marker::PhantomData,
479    })
480  }
481}
482
483impl<Args: JsValuesTupleIntoVec, Return> Drop for FunctionRef<Args, Return> {
484  fn drop(&mut self) {
485    let status = unsafe { sys::napi_delete_reference(self.env, self.inner) };
486    debug_assert_eq!(status, sys::Status::napi_ok, "Drop FunctionRef failed");
487  }
488}
489
490impl<Args: JsValuesTupleIntoVec, Return> TypeName for FunctionRef<Args, Return> {
491  fn type_name() -> &'static str {
492    "Function"
493  }
494
495  fn value_type() -> crate::ValueType {
496    ValueType::Function
497  }
498}
499
500impl<Args: JsValuesTupleIntoVec, Return> FromNapiValue for FunctionRef<Args, Return> {
501  unsafe fn from_napi_value(env: sys::napi_env, value: sys::napi_value) -> Result<Self> {
502    let mut reference = ptr::null_mut();
503    check_status!(
504      unsafe { sys::napi_create_reference(env, value, 1, &mut reference) },
505      "Create reference failed"
506    )?;
507    Ok(FunctionRef {
508      inner: reference,
509      env,
510      _args: std::marker::PhantomData,
511      _return: std::marker::PhantomData,
512    })
513  }
514}
515
516impl<Args: JsValuesTupleIntoVec, Return: FromNapiValue> ValidateNapiValue
517  for FunctionRef<Args, Return>
518{
519}
520
521pub struct FunctionCallContext<'scope> {
522  pub(crate) args: &'scope [sys::napi_value],
523  pub(crate) this: sys::napi_value,
524  pub env: &'scope mut Env,
525}
526
527impl FunctionCallContext<'_> {
528  /// Get the number of arguments from the JavaScript function call.
529  pub fn length(&self) -> usize {
530    self.args.len()
531  }
532
533  pub fn get<ArgType: FromNapiValue>(&self, index: usize) -> Result<ArgType> {
534    if index >= self.length() {
535      Err(crate::Error::new(
536        crate::Status::GenericFailure,
537        "Arguments index out of range".to_owned(),
538      ))
539    } else {
540      unsafe { ArgType::from_napi_value(self.env.0, self.args[index]) }
541    }
542  }
543
544  pub fn try_get<ArgType: TypeName + FromNapiValue>(
545    &self,
546    index: usize,
547  ) -> Result<Either<ArgType, ()>> {
548    let len = self.length();
549    if index >= len {
550      Err(crate::Error::new(
551        crate::Status::GenericFailure,
552        "Arguments index out of range".to_owned(),
553      ))
554    } else if index < len {
555      unsafe { ArgType::from_napi_value(self.env.0, self.args[index]) }.map(Either::A)
556    } else {
557      Ok(Either::B(()))
558    }
559  }
560
561  /// Get the first argument from the JavaScript function call.
562  pub fn first_arg<T: FromNapiValue>(&self) -> Result<T> {
563    if self.args.is_empty() {
564      return Err(crate::Error::new(
565        crate::Status::InvalidArg,
566        "There is no arguments",
567      ));
568    }
569    unsafe { T::from_napi_value(self.env.0, self.args[0]) }
570  }
571
572  /// Get the arguments from the JavaScript function call.
573  /// The arguments will be converted to a tuple.
574  /// If the number of arguments is not equal to the number of tuple elements, an error will be returned.
575  /// example:
576  /// ```rust
577  /// let (num, string) = ctx.args::<(u32, String)>()?;
578  /// ````
579  pub fn args<Args: TupleFromSliceValues>(&self) -> Result<Args> {
580    unsafe { Args::from_slice_values(self.env.0, self.args) }
581  }
582
583  /// Get the arguments Vec from the JavaScript function call.
584  pub fn arguments<T: FromNapiValue>(&self) -> Result<Vec<T>> {
585    self
586      .args
587      .iter()
588      .map(|arg| unsafe { <T as FromNapiValue>::from_napi_value(self.env.0, *arg) })
589      .collect::<Result<Vec<T>>>()
590  }
591
592  /// Get the `this` from the JavaScript function call.
593  pub fn this<This: FromNapiValue>(&self) -> Result<This> {
594    unsafe { This::from_napi_value(self.env.0, self.this) }
595  }
596}
597
598#[cfg(feature = "compat-mode")]
599macro_rules! impl_call_apply {
600  ($fn_call_name:ident, $fn_apply_name:ident, $($ident:ident),*) => {
601    #[allow(non_snake_case, deprecated, clippy::too_many_arguments)]
602    pub fn $fn_call_name<$($ident: ToNapiValue),*, Return: FromNapiValue>(
603      &self,
604      $($ident: $ident),*
605    ) -> Result<Return> {
606      let raw_this = unsafe { ToNapiValue::to_napi_value(self.0.env, ()) }?;
607
608      let raw_args = vec![
609        $(
610          unsafe { $ident::to_napi_value(self.0.env, $ident) }?
611        ),*
612      ];
613
614      let mut return_value = ptr::null_mut();
615      check_pending_exception!(self.0.env, unsafe {
616        sys::napi_call_function(
617          self.0.env,
618          raw_this,
619          self.0.value,
620          raw_args.len(),
621          raw_args.as_ptr(),
622          &mut return_value,
623        )
624      })?;
625
626      unsafe { Return::from_napi_value(self.0.env, return_value) }
627    }
628
629    #[allow(non_snake_case, deprecated, clippy::too_many_arguments)]
630    pub fn $fn_apply_name<$($ident: ToNapiValue),*, Context: ToNapiValue, Return: FromNapiValue>(
631      &self,
632      this: Context,
633      $($ident: $ident),*
634    ) -> Result<Return> {
635      let raw_this = unsafe { Context::to_napi_value(self.0.env, this) }?;
636
637      let raw_args = vec![
638        $(
639          unsafe { $ident::to_napi_value(self.0.env, $ident) }?
640        ),*
641      ];
642
643      let mut return_value = ptr::null_mut();
644      check_pending_exception!(self.0.env, unsafe {
645        sys::napi_call_function(
646          self.0.env,
647          raw_this,
648          self.0.value,
649          raw_args.len(),
650          raw_args.as_ptr(),
651          &mut return_value,
652        )
653      })?;
654
655      unsafe { Return::from_napi_value(self.0.env, return_value) }
656    }
657  };
658}
659
660#[cfg(feature = "compat-mode")]
661#[allow(deprecated)]
662impl JsFunction {
663  pub fn apply0<Return: FromNapiValue, Context: ToNapiValue>(
664    &self,
665    this: Context,
666  ) -> Result<Return> {
667    let raw_this = unsafe { Context::to_napi_value(self.0.env, this) }?;
668
669    let mut return_value = ptr::null_mut();
670    check_pending_exception!(self.0.env, unsafe {
671      sys::napi_call_function(
672        self.0.env,
673        raw_this,
674        self.0.value,
675        0,
676        ptr::null_mut(),
677        &mut return_value,
678      )
679    })?;
680
681    unsafe { Return::from_napi_value(self.0.env, return_value) }
682  }
683
684  pub fn call0<Return: FromNapiValue>(&self) -> Result<Return> {
685    let raw_this = unsafe { ToNapiValue::to_napi_value(self.0.env, ()) }?;
686
687    let mut return_value = ptr::null_mut();
688    check_pending_exception!(self.0.env, unsafe {
689      sys::napi_call_function(
690        self.0.env,
691        raw_this,
692        self.0.value,
693        0,
694        ptr::null_mut(),
695        &mut return_value,
696      )
697    })?;
698
699    unsafe { Return::from_napi_value(self.0.env, return_value) }
700  }
701
702  impl_call_apply!(call1, apply1, Arg1);
703  impl_call_apply!(call2, apply2, Arg1, Arg2);
704  impl_call_apply!(call3, apply3, Arg1, Arg2, Arg3);
705  impl_call_apply!(call4, apply4, Arg1, Arg2, Arg3, Arg4);
706  impl_call_apply!(call5, apply5, Arg1, Arg2, Arg3, Arg4, Arg5);
707  impl_call_apply!(call6, apply6, Arg1, Arg2, Arg3, Arg4, Arg5, Arg6);
708  impl_call_apply!(call7, apply7, Arg1, Arg2, Arg3, Arg4, Arg5, Arg6, Arg7);
709  impl_call_apply!(call8, apply8, Arg1, Arg2, Arg3, Arg4, Arg5, Arg6, Arg7, Arg8);
710  impl_call_apply!(call9, apply9, Arg1, Arg2, Arg3, Arg4, Arg5, Arg6, Arg7, Arg8, Arg9);
711  impl_call_apply!(call10, apply10, Arg1, Arg2, Arg3, Arg4, Arg5, Arg6, Arg7, Arg8, Arg9, Arg10);
712}