1use std::ptr;
2
3use super::Value;
4#[cfg(feature = "napi4")]
5use crate::{
6 bindgen_runtime::JsValuesTupleIntoVec,
7 threadsafe_function::{ThreadsafeCallContext, ThreadsafeFunction},
8};
9use crate::{
10 bindgen_runtime::{FromNapiValue, ToNapiValue, TypeName, ValidateNapiValue},
11 check_pending_exception, sys, Error, JsObject, JsString, NapiRaw, NapiValue, Result, Status,
12 Unknown, ValueType,
13};
14
15#[deprecated(since = "2.17.0", note = "Please use `Function` instead")]
16pub struct JsFunction(pub(crate) Value);
17
18impl ValidateNapiValue for JsFunction {}
19
20impl TypeName for JsFunction {
21 fn type_name() -> &'static str {
22 "Function"
23 }
24
25 fn value_type() -> crate::ValueType {
26 ValueType::Function
27 }
28}
29
30impl JsFunction {
45 pub fn call<V>(&self, this: Option<&JsObject>, args: &[V]) -> Result<Unknown<'_>>
47 where
48 V: NapiRaw,
49 {
50 let raw_this = this
51 .map(|v| unsafe { v.raw() })
52 .or_else(|| unsafe { ToNapiValue::to_napi_value(self.0.env, ()) }.ok())
53 .ok_or_else(|| Error::new(Status::GenericFailure, "Get raw this failed".to_owned()))?;
54 let raw_args = args
55 .iter()
56 .map(|arg| unsafe { arg.raw() })
57 .collect::<Vec<sys::napi_value>>();
58 let mut return_value = ptr::null_mut();
59 check_pending_exception!(self.0.env, unsafe {
60 sys::napi_call_function(
61 self.0.env,
62 raw_this,
63 self.0.value,
64 args.len(),
65 raw_args.as_ptr(),
66 &mut return_value,
67 )
68 })?;
69
70 Ok(unsafe { Unknown::from_raw_unchecked(self.0.env, return_value) })
71 }
72
73 pub fn call_without_args(&self, this: Option<&JsObject>) -> Result<Unknown<'_>> {
76 let raw_this = this
77 .map(|v| unsafe { v.raw() })
78 .or_else(|| unsafe { ToNapiValue::to_napi_value(self.0.env, ()) }.ok())
79 .ok_or_else(|| Error::new(Status::GenericFailure, "Get raw this failed".to_owned()))?;
80 let mut return_value = ptr::null_mut();
81 check_pending_exception!(self.0.env, unsafe {
82 sys::napi_call_function(
83 self.0.env,
84 raw_this,
85 self.0.value,
86 0,
87 ptr::null_mut(),
88 &mut return_value,
89 )
90 })?;
91
92 Ok(unsafe { Unknown::from_raw_unchecked(self.0.env, return_value) })
93 }
94
95 pub fn new_instance<V>(&self, args: &[V]) -> Result<JsObject>
99 where
100 V: NapiRaw,
101 {
102 let mut js_instance = ptr::null_mut();
103 let length = args.len();
104 let raw_args = args
105 .iter()
106 .map(|arg| unsafe { arg.raw() })
107 .collect::<Vec<sys::napi_value>>();
108 check_pending_exception!(self.0.env, unsafe {
109 sys::napi_new_instance(
110 self.0.env,
111 self.0.value,
112 length,
113 raw_args.as_ptr(),
114 &mut js_instance,
115 )
116 })?;
117 Ok(unsafe { JsObject::from_raw_unchecked(self.0.env, js_instance) })
118 }
119
120 pub fn name(&self) -> Result<String> {
122 let mut name = ptr::null_mut();
123 check_pending_exception!(self.0.env, unsafe {
124 sys::napi_get_named_property(self.0.env, self.0.value, c"name".as_ptr().cast(), &mut name)
125 })?;
126 let name_value = unsafe { JsString::from_napi_value(self.0.env, name) }?;
127 Ok(name_value.into_utf8()?.as_str()?.to_owned())
128 }
129
130 #[cfg(feature = "napi4")]
131 pub fn create_threadsafe_function<
132 T,
133 NewArgs,
134 Return,
135 ErrorStatus,
136 F,
137 const ES: bool,
138 const Weak: bool,
139 const MaxQueueSize: usize,
140 >(
141 &self,
142 callback: F,
143 ) -> Result<ThreadsafeFunction<T, Return, NewArgs, ErrorStatus, ES, Weak, MaxQueueSize>>
144 where
145 T: 'static,
146 NewArgs: 'static + JsValuesTupleIntoVec,
147 Return: crate::bindgen_runtime::FromNapiValue,
148 F: 'static + Send + FnMut(ThreadsafeCallContext<T>) -> Result<NewArgs>,
149 ErrorStatus: AsRef<str> + From<Status>,
150 {
151 ThreadsafeFunction::<T, Return, NewArgs, ErrorStatus, ES, Weak, MaxQueueSize>::create(
152 self.0.env,
153 self.0.value,
154 callback,
155 )
156 }
157}