euv_core/noderef/struct.rs
1use super::*;
2
3/// A reactive handle to a mounted DOM element.
4///
5/// `NodeRef` is created via [`App::use_node_ref`] (which routes through the
6/// current [`HookContext`]) and is populated by the renderer after the
7/// corresponding virtual node is mounted into the real DOM. Before
8/// the first mount the inner value is `None`; after unmount it is reset
9/// to `None` again, so consumers can rely on `get()` returning `None`
10/// to detect the unmounted state.
11///
12/// The type parameter `T` is purely a phantom marker that names the
13/// expected element type (e.g. `NodeRef<HtmlInputElement>`). The runtime
14/// stores the element as a raw `JsValue`; calling [`get_cloned`] performs
15/// the `dyn_into` cast on demand. This avoids pulling in `web_sys` types
16/// in the core hot path and keeps the type zero-cost when the consumer
17/// only needs the raw `JsValue`.
18///
19/// `NodeRef` is `Clone` and cheap to copy (it is an `Rc` clone). All clones
20/// share the same underlying cell, so setting the value through one clone
21/// is visible through every other clone.
22///
23/// [`get_cloned`]: NodeRef::get_cloned
24pub struct NodeRef<T: ?Sized> {
25 /// Shared interior mutability cell holding the (optional) raw DOM
26 /// element as a `JsValue`.
27 pub(crate) inner: Rc<UnsafeCell<Option<JsValue>>>,
28 /// Phantom marker for the expected element type. Not used at runtime
29 /// — `get_cloned` only inspects the `T: Into<JsValue>` bound.
30 pub(crate) _marker: PhantomData<fn() -> T>,
31}
32
33// `Debug` is implemented manually as well: we want to skip the
34// non-`Debug` `JsValue` payload but still expose the phantom marker
35// type, which is useful for assertions in tests.