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> Sync for FunctionRef<Args, Return> {}
464
465impl<Args: JsValuesTupleIntoVec, Return> FunctionRef<Args, Return> {
466  pub fn borrow_back<'scope>(&self, env: &'scope Env) -> Result<Function<'scope, Args, Return>> {
467    let mut value = ptr::null_mut();
468    check_status!(
469      unsafe { sys::napi_get_reference_value(env.0, self.inner, &mut value) },
470      "Get reference value failed"
471    )?;
472    Ok(Function {
473      env: env.0,
474      value,
475      _args: std::marker::PhantomData,
476      _return: std::marker::PhantomData,
477      _scope: std::marker::PhantomData,
478    })
479  }
480}
481
482impl<Args: JsValuesTupleIntoVec, Return> Drop for FunctionRef<Args, Return> {
483  fn drop(&mut self) {
484    let status = unsafe { sys::napi_delete_reference(self.env, self.inner) };
485    debug_assert_eq!(status, sys::Status::napi_ok, "Drop FunctionRef failed");
486  }
487}
488
489impl<Args: JsValuesTupleIntoVec, Return> TypeName for FunctionRef<Args, Return> {
490  fn type_name() -> &'static str {
491    "Function"
492  }
493
494  fn value_type() -> crate::ValueType {
495    ValueType::Function
496  }
497}
498
499impl<Args: JsValuesTupleIntoVec, Return> FromNapiValue for FunctionRef<Args, Return> {
500  unsafe fn from_napi_value(env: sys::napi_env, value: sys::napi_value) -> Result<Self> {
501    let mut reference = ptr::null_mut();
502    check_status!(
503      unsafe { sys::napi_create_reference(env, value, 1, &mut reference) },
504      "Create reference failed"
505    )?;
506    Ok(FunctionRef {
507      inner: reference,
508      env,
509      _args: std::marker::PhantomData,
510      _return: std::marker::PhantomData,
511    })
512  }
513}
514
515impl<Args: JsValuesTupleIntoVec, Return: FromNapiValue> ValidateNapiValue
516  for FunctionRef<Args, Return>
517{
518}
519
520pub struct FunctionCallContext<'scope> {
521  pub(crate) args: &'scope [sys::napi_value],
522  pub(crate) this: sys::napi_value,
523  pub env: &'scope mut Env,
524}
525
526impl FunctionCallContext<'_> {
527  /// Get the number of arguments from the JavaScript function call.
528  pub fn length(&self) -> usize {
529    self.args.len()
530  }
531
532  pub fn get<ArgType: FromNapiValue>(&self, index: usize) -> Result<ArgType> {
533    if index >= self.length() {
534      Err(crate::Error::new(
535        crate::Status::GenericFailure,
536        "Arguments index out of range".to_owned(),
537      ))
538    } else {
539      unsafe { ArgType::from_napi_value(self.env.0, self.args[index]) }
540    }
541  }
542
543  pub fn try_get<ArgType: TypeName + FromNapiValue>(
544    &self,
545    index: usize,
546  ) -> Result<Either<ArgType, ()>> {
547    let len = self.length();
548    if index >= len {
549      Err(crate::Error::new(
550        crate::Status::GenericFailure,
551        "Arguments index out of range".to_owned(),
552      ))
553    } else if index < len {
554      unsafe { ArgType::from_napi_value(self.env.0, self.args[index]) }.map(Either::A)
555    } else {
556      Ok(Either::B(()))
557    }
558  }
559
560  /// Get the first argument from the JavaScript function call.
561  pub fn first_arg<T: FromNapiValue>(&self) -> Result<T> {
562    if self.args.is_empty() {
563      return Err(crate::Error::new(
564        crate::Status::InvalidArg,
565        "There is no arguments",
566      ));
567    }
568    unsafe { T::from_napi_value(self.env.0, self.args[0]) }
569  }
570
571  /// Get the arguments from the JavaScript function call.
572  /// The arguments will be converted to a tuple.
573  /// If the number of arguments is not equal to the number of tuple elements, an error will be returned.
574  /// example:
575  /// ```rust
576  /// let (num, string) = ctx.args::<(u32, String)>()?;
577  /// ````
578  pub fn args<Args: TupleFromSliceValues>(&self) -> Result<Args> {
579    unsafe { Args::from_slice_values(self.env.0, self.args) }
580  }
581
582  /// Get the arguments Vec from the JavaScript function call.
583  pub fn arguments<T: FromNapiValue>(&self) -> Result<Vec<T>> {
584    self
585      .args
586      .iter()
587      .map(|arg| unsafe { <T as FromNapiValue>::from_napi_value(self.env.0, *arg) })
588      .collect::<Result<Vec<T>>>()
589  }
590
591  /// Get the `this` from the JavaScript function call.
592  pub fn this<This: FromNapiValue>(&self) -> Result<This> {
593    unsafe { This::from_napi_value(self.env.0, self.this) }
594  }
595}
596
597#[cfg(feature = "compat-mode")]
598macro_rules! impl_call_apply {
599  ($fn_call_name:ident, $fn_apply_name:ident, $($ident:ident),*) => {
600    #[allow(non_snake_case, deprecated, clippy::too_many_arguments)]
601    pub fn $fn_call_name<$($ident: ToNapiValue),*, Return: FromNapiValue>(
602      &self,
603      $($ident: $ident),*
604    ) -> Result<Return> {
605      let raw_this = unsafe { ToNapiValue::to_napi_value(self.0.env, ()) }?;
606
607      let raw_args = vec![
608        $(
609          unsafe { $ident::to_napi_value(self.0.env, $ident) }?
610        ),*
611      ];
612
613      let mut return_value = ptr::null_mut();
614      check_pending_exception!(self.0.env, unsafe {
615        sys::napi_call_function(
616          self.0.env,
617          raw_this,
618          self.0.value,
619          raw_args.len(),
620          raw_args.as_ptr(),
621          &mut return_value,
622        )
623      })?;
624
625      unsafe { Return::from_napi_value(self.0.env, return_value) }
626    }
627
628    #[allow(non_snake_case, deprecated, clippy::too_many_arguments)]
629    pub fn $fn_apply_name<$($ident: ToNapiValue),*, Context: ToNapiValue, Return: FromNapiValue>(
630      &self,
631      this: Context,
632      $($ident: $ident),*
633    ) -> Result<Return> {
634      let raw_this = unsafe { Context::to_napi_value(self.0.env, this) }?;
635
636      let raw_args = vec![
637        $(
638          unsafe { $ident::to_napi_value(self.0.env, $ident) }?
639        ),*
640      ];
641
642      let mut return_value = ptr::null_mut();
643      check_pending_exception!(self.0.env, unsafe {
644        sys::napi_call_function(
645          self.0.env,
646          raw_this,
647          self.0.value,
648          raw_args.len(),
649          raw_args.as_ptr(),
650          &mut return_value,
651        )
652      })?;
653
654      unsafe { Return::from_napi_value(self.0.env, return_value) }
655    }
656  };
657}
658
659#[cfg(feature = "compat-mode")]
660#[allow(deprecated)]
661impl JsFunction {
662  pub fn apply0<Return: FromNapiValue, Context: ToNapiValue>(
663    &self,
664    this: Context,
665  ) -> Result<Return> {
666    let raw_this = unsafe { Context::to_napi_value(self.0.env, this) }?;
667
668    let mut return_value = ptr::null_mut();
669    check_pending_exception!(self.0.env, unsafe {
670      sys::napi_call_function(
671        self.0.env,
672        raw_this,
673        self.0.value,
674        0,
675        ptr::null_mut(),
676        &mut return_value,
677      )
678    })?;
679
680    unsafe { Return::from_napi_value(self.0.env, return_value) }
681  }
682
683  pub fn call0<Return: FromNapiValue>(&self) -> Result<Return> {
684    let raw_this = unsafe { ToNapiValue::to_napi_value(self.0.env, ()) }?;
685
686    let mut return_value = ptr::null_mut();
687    check_pending_exception!(self.0.env, unsafe {
688      sys::napi_call_function(
689        self.0.env,
690        raw_this,
691        self.0.value,
692        0,
693        ptr::null_mut(),
694        &mut return_value,
695      )
696    })?;
697
698    unsafe { Return::from_napi_value(self.0.env, return_value) }
699  }
700
701  impl_call_apply!(call1, apply1, Arg1);
702  impl_call_apply!(call2, apply2, Arg1, Arg2);
703  impl_call_apply!(call3, apply3, Arg1, Arg2, Arg3);
704  impl_call_apply!(call4, apply4, Arg1, Arg2, Arg3, Arg4);
705  impl_call_apply!(call5, apply5, Arg1, Arg2, Arg3, Arg4, Arg5);
706  impl_call_apply!(call6, apply6, Arg1, Arg2, Arg3, Arg4, Arg5, Arg6);
707  impl_call_apply!(call7, apply7, Arg1, Arg2, Arg3, Arg4, Arg5, Arg6, Arg7);
708  impl_call_apply!(call8, apply8, Arg1, Arg2, Arg3, Arg4, Arg5, Arg6, Arg7, Arg8);
709  impl_call_apply!(call9, apply9, Arg1, Arg2, Arg3, Arg4, Arg5, Arg6, Arg7, Arg8, Arg9);
710  impl_call_apply!(call10, apply10, Arg1, Arg2, Arg3, Arg4, Arg5, Arg6, Arg7, Arg8, Arg9, Arg10);
711}