napi_async_runtime/js_callback.rs
1//! Generic JavaScript-callback alias used by the host protocol exports.
2
3use std::{ptr, sync::Arc};
4
5use napi::{
6 Either, Status, ValueType,
7 bindgen_prelude::{FromNapiValue, TypeName, ValidateNapiValue},
8 sys,
9 threadsafe_function::ThreadsafeFunction,
10};
11
12/// Used as the fallback branch in `Either<Ret, InvalidReturnValue>` to catch
13/// type mismatches from JS function options. Always passes NAPI validation so
14/// that when `Ret` validation fails, the error is handled in Rust with a clear
15/// message instead of becoming an uncatchable `napi_fatal_exception`.
16pub struct InvalidReturnValue {
17 pub value_type: ValueType,
18}
19
20impl TypeName for InvalidReturnValue {
21 fn type_name() -> &'static str {
22 "InvalidReturnValue"
23 }
24
25 fn value_type() -> ValueType {
26 ValueType::Unknown
27 }
28}
29
30impl ValidateNapiValue for InvalidReturnValue {
31 unsafe fn validate(
32 _env: sys::napi_env,
33 _napi_val: sys::napi_value,
34 ) -> napi::Result<sys::napi_value> {
35 Ok(ptr::null_mut())
36 }
37}
38
39impl FromNapiValue for InvalidReturnValue {
40 unsafe fn from_napi_value(env: sys::napi_env, napi_val: sys::napi_value) -> napi::Result<Self> {
41 let value_type = napi::type_of!(env, napi_val)?;
42 Ok(InvalidReturnValue { value_type })
43 }
44}
45
46/// `JsCallback` is a type alias for a weak, caller-handled
47/// [`ThreadsafeFunction`] whose return value is validated in Rust: it
48/// represents a JavaScript function passed to the Rust side.
49///
50/// - Rust: `JsCallback<FnArgs<(u32, f64)>, Promise<()>>`
51/// - JS: `(id: number, ms: number) => Promise<void>`
52///
53/// The `Weak = true` parameter means the callback does not keep its owning
54/// event loop alive, which is exactly what the host protocol needs: a worker
55/// that registered a timer or task host may exit at any time, and the runtime
56/// detects that through the threadsafe function's `aborted` flag instead of
57/// pinning the worker.
58pub type JsCallback<Args = (), Ret = ()> =
59 Arc<ThreadsafeFunction<Args, Either<Ret, InvalidReturnValue>, Args, Status, false, true>>;