yuuang_test_napi/js_values/
function.rs

1use std::ptr;
2
3use super::Value;
4use crate::check_status;
5use crate::{sys, Env, Error, JsObject, JsUnknown, NapiRaw, NapiValue, Result, Status};
6
7pub struct JsFunction(pub(crate) Value);
8
9/// See [Working with JavaScript Functions](https://nodejs.org/api/n-api.html#n_api_working_with_javascript_functions).
10///
11/// Example:
12/// ```
13/// use napi::{JsFunction, CallContext, JsNull, Result};
14///
15/// #[js_function(1)]
16/// pub fn call_function(ctx: CallContext) -> Result<JsNull> {
17///     let js_func = ctx.get::<JsFunction>(0)?;
18///     let js_string = ctx.env.create_string("hello".as_ref())?.into_unknown()?;
19///     js_func.call(None, &[js_string])?;
20///     Ok(ctx.env.get_null()?)
21/// }
22/// ```
23impl JsFunction {
24  /// [napi_call_function](https://nodejs.org/api/n-api.html#n_api_napi_call_function)
25  #[inline]
26  pub fn call<V>(&self, this: Option<&JsObject>, args: &[V]) -> Result<JsUnknown>
27  where
28    V: NapiRaw,
29  {
30    let raw_this = this
31      .map(|v| unsafe { v.raw() })
32      .or_else(|| {
33        unsafe { Env::from_raw(self.0.env) }
34          .get_undefined()
35          .ok()
36          .map(|u| unsafe { u.raw() })
37      })
38      .ok_or_else(|| Error::new(Status::GenericFailure, "Get raw this failed".to_owned()))?;
39    let raw_args = args
40      .iter()
41      .map(|arg| unsafe { arg.raw() })
42      .collect::<Vec<sys::napi_value>>();
43    let mut return_value = ptr::null_mut();
44    check_status!(unsafe {
45      sys::napi_call_function(
46        self.0.env,
47        raw_this,
48        self.0.value,
49        args.len(),
50        raw_args.as_ptr(),
51        &mut return_value,
52      )
53    })?;
54
55    unsafe { JsUnknown::from_raw(self.0.env, return_value) }
56  }
57
58  /// [napi_call_function](https://nodejs.org/api/n-api.html#n_api_napi_call_function)
59  /// The same with `call`, but without arguments
60  #[inline]
61  pub fn call_without_args(&self, this: Option<&JsObject>) -> Result<JsUnknown> {
62    let raw_this = this
63      .map(|v| unsafe { v.raw() })
64      .or_else(|| {
65        unsafe { Env::from_raw(self.0.env) }
66          .get_undefined()
67          .ok()
68          .map(|u| unsafe { u.raw() })
69      })
70      .ok_or_else(|| Error::new(Status::GenericFailure, "Get raw this failed".to_owned()))?;
71    let mut return_value = ptr::null_mut();
72    check_status!(unsafe {
73      sys::napi_call_function(
74        self.0.env,
75        raw_this,
76        self.0.value,
77        0,
78        ptr::null_mut(),
79        &mut return_value,
80      )
81    })?;
82
83    unsafe { JsUnknown::from_raw(self.0.env, return_value) }
84  }
85
86  /// https://nodejs.org/api/n-api.html#n_api_napi_new_instance
87  ///
88  /// This method is used to instantiate a new `JavaScript` value using a given `JsFunction` that represents the constructor for the object.
89  #[allow(clippy::new_ret_no_self)]
90  #[inline]
91  pub fn new<V>(&self, args: &[V]) -> Result<JsObject>
92  where
93    V: NapiRaw,
94  {
95    let mut js_instance = ptr::null_mut();
96    let length = args.len();
97    let raw_args = args
98      .iter()
99      .map(|arg| unsafe { arg.raw() })
100      .collect::<Vec<sys::napi_value>>();
101    check_status!(unsafe {
102      sys::napi_new_instance(
103        self.0.env,
104        self.0.value,
105        length,
106        raw_args.as_ptr(),
107        &mut js_instance,
108      )
109    })?;
110    Ok(unsafe { JsObject::from_raw_unchecked(self.0.env, js_instance) })
111  }
112}