#[allow(unused_imports)]
use napi::bindgen_prelude::{JsObjectValue, ToNapiValue, Unknown, Object};
#[allow(unused_imports)]
use napi::JsValue;
fn nodecontext_to_js_object<'e>(
env: &'e napi::Env,
ctx: &{{ context_type_path }},
) -> napi::Result<napi::bindgen_prelude::Object<'e>> {
let mut obj = napi::bindgen_prelude::Object::new(env)?;
{{ context_field_lines }}
Ok(obj)
}
pub struct {{ struct_name }} {
env: napi::sys::napi_env,
obj_ref: Option<napi::bindgen_prelude::ObjectRef<false>>,
}
impl std::fmt::Debug for {{ struct_name }} {
fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
write!(f, "{{ struct_name }}")
}
}
impl {{ struct_name }} {
pub fn new(js_obj: napi::bindgen_prelude::Object<'_>) -> napi::Result<Self> {
// SAFETY: Object<'_> is laid out as 3 pointer-sized words: [napi_env, napi_value, is_ref].
// We extract the raw napi_env pointer so we can reconstruct an Env inside visitor
// callbacks. The pointer is stable for the lifetime of the Node process.
let env = unsafe {
let raw: [*mut std::ffi::c_void; 3] = std::mem::transmute_copy(&js_obj);
raw[0] as napi::sys::napi_env
};
// Create a persistent napi reference so the JS object survives across the
// synchronous convert() call, regardless of HandleScope movement.
let obj_ref = js_obj.create_ref::<false>()?;
Ok(Self { env, obj_ref: Some(obj_ref) })
}
}
impl Drop for {{ struct_name }} {
fn drop(&mut self) {
// Release the persistent reference so the JS object can be GC'd. unref takes
// ownership; the Option lets us move out from &mut self in drop.
if let Some(obj_ref) = self.obj_ref.take() {
// self.env was captured from the napi_env that owns obj_ref.
let env = napi::Env::from_raw(self.env);
let _ = obj_ref.unref(&env);
}
}
}
// SAFETY: The visitor bridge stores an napi_ref (via ObjectRef), which is valid across
// threads as long as all napi:: operations using it happen on the original event loop
// thread where the reference was created. The Arc<Mutex<>> wrapper around the bridge
// ensures synchronous, single-threaded access during the convert() call.
unsafe impl Send for {{ struct_name }} {}
// SAFETY: see Send impl above.
unsafe impl Sync for {{ struct_name }} {}
impl {{ trait_path }} for {{ struct_name }} {
{{ method_impls }}
}