rspack_napi/js_values/
one_shot_instance_ref.rs

1#![allow(clippy::not_unsafe_ptr_arg_deref)]
2
3use std::{
4  ops::{Deref, DerefMut},
5  ptr,
6};
7
8use napi::{
9  Env, Result,
10  bindgen_prelude::{
11    ClassInstance, JavaScriptClassExt, ToNapiValue, TypeName, ValidateNapiValue, check_status,
12  },
13  sys::{self, napi_env},
14};
15
16use crate::OneShotRef;
17
18// A RAII (Resource Acquisition Is Initialization) style wrapper around `Ref` that ensures the
19// reference is unreferenced when it goes out of scope. This struct maintains a single reference
20// count and automatically cleans up when it is dropped.
21pub struct OneShotInstanceRef<T: 'static> {
22  one_shot_ref: OneShotRef,
23  inner: *mut T,
24}
25
26impl<T: JavaScriptClassExt + 'static> OneShotInstanceRef<T> {
27  pub fn new(env: napi_env, val: T) -> Result<Self> {
28    let env_wrapper = Env::from_raw(env);
29    let instance = val.into_instance(&env_wrapper)?;
30    Self::from_instance(env, instance)
31  }
32
33  pub fn from_instance(env: napi_env, mut instance: ClassInstance<T>) -> Result<Self> {
34    let mut napi_ref = ptr::null_mut();
35    check_status!(unsafe { sys::napi_create_reference(env, instance.value, 1, &mut napi_ref) })?;
36
37    Ok(Self {
38      one_shot_ref: OneShotRef::from_napi_ref(env, napi_ref)?,
39      inner: &mut *instance,
40    })
41  }
42}
43
44impl<T: TypeName> TypeName for OneShotInstanceRef<T> {
45  fn type_name() -> &'static str {
46    T::type_name()
47  }
48  fn value_type() -> napi::ValueType {
49    T::value_type()
50  }
51}
52
53impl<T: ValidateNapiValue> ValidateNapiValue for OneShotInstanceRef<T> {
54  unsafe fn validate(env: sys::napi_env, napi_val: sys::napi_value) -> Result<sys::napi_value> {
55    unsafe { T::validate(env, napi_val) }
56  }
57}
58
59impl<T: ToNapiValue> ToNapiValue for OneShotInstanceRef<T> {
60  unsafe fn to_napi_value(env: sys::napi_env, val: Self) -> Result<sys::napi_value> {
61    unsafe { ToNapiValue::to_napi_value(env, &val.one_shot_ref) }
62  }
63}
64
65impl<T: ToNapiValue> ToNapiValue for &OneShotInstanceRef<T> {
66  unsafe fn to_napi_value(env: sys::napi_env, val: Self) -> Result<sys::napi_value> {
67    unsafe { ToNapiValue::to_napi_value(env, &val.one_shot_ref) }
68  }
69}
70
71impl<T: ToNapiValue> ToNapiValue for &mut OneShotInstanceRef<T> {
72  unsafe fn to_napi_value(env: sys::napi_env, val: Self) -> Result<sys::napi_value> {
73    unsafe { ToNapiValue::to_napi_value(env, &val.one_shot_ref) }
74  }
75}
76
77impl<T> Deref for OneShotInstanceRef<T> {
78  type Target = T;
79
80  fn deref(&self) -> &Self::Target {
81    unsafe { &*self.inner }
82  }
83}
84
85impl<T> DerefMut for OneShotInstanceRef<T> {
86  fn deref_mut(&mut self) -> &mut T {
87    unsafe { &mut *self.inner }
88  }
89}
90
91impl<T> AsRef<T> for OneShotInstanceRef<T> {
92  fn as_ref(&self) -> &T {
93    unsafe { &*self.inner }
94  }
95}