Skip to main content

euv_core/vdom/node/
struct.rs

1use crate::*;
2
3/// Inner storage for a dynamic node render closure.
4///
5/// Boxes a `dyn FnMut() -> VirtualNode` so it can be stored behind `Rc<UnsafeCell<>>`.
6#[derive(CustomDebug, Data, New)]
7pub(crate) struct RenderFnInner {
8    /// The boxed render closure.
9    #[debug(skip)]
10    #[get(pub(crate))]
11    #[get_mut(pub(crate))]
12    #[set(pub(crate))]
13    pub(crate) render_fn: Box<dyn FnMut() -> VirtualNode>,
14}
15
16/// Represents a text node in the virtual DOM.
17///
18/// Text nodes may optionally be bound to a reactive signal for automatic updates.
19#[derive(Clone, CustomDebug, Data, New)]
20pub struct TextNode {
21    /// The text content.
22    #[get(pub(crate))]
23    #[get_mut(pub(crate))]
24    #[set(pub(crate))]
25    pub(crate) content: String,
26    /// An optional signal that drives reactive text updates.
27    #[debug(skip)]
28    #[get(pub(crate))]
29    #[get_mut(pub(crate))]
30    #[set(pub(crate))]
31    pub(crate) signal: Option<Signal<String>>,
32}
33
34/// A closure-based dynamic node that re-renders when its dependency signals change.
35///
36/// Holds a shared reference to a heap-allocated render closure that produces a fresh
37/// `VirtualNode` on each evaluation. The renderer subscribes to the closure's
38/// signals and patches the DOM automatically.
39/// Contains a `HookContext` that persists hook state (like `use_signal`) across
40/// re-renders, ensuring that signal values are not reset when the render function
41/// is called again.
42///
43/// Uses `Rc<UnsafeCell<>>` instead of `Rc<RefCell<>>` to avoid runtime borrow
44/// checking overhead. Safety is guaranteed by the single-threaded WASM context.
45/// The `Rc` provides automatic memory management — the render closure is freed
46/// when the last reference (either in the VirtualNode tree or the signal update
47/// callback) is dropped.
48#[derive(Clone, CustomDebug, Data, New)]
49pub struct DynamicNode {
50    /// Shared reference to the heap-allocated render closure inner state.
51    /// `Rc` ensures automatic deallocation; `UnsafeCell` allows mutable access
52    /// without RefCell overhead.
53    #[debug(skip)]
54    #[get(pub(crate))]
55    #[get_mut(pub(crate))]
56    #[set(pub(crate))]
57    pub(crate) render_fn: Rc<UnsafeCell<RenderFnInner>>,
58    /// Persistent hook context for this dynamic node, storing signal
59    /// state and other hook values across render cycles.
60    #[get(pub(crate))]
61    #[get_mut(pub(crate))]
62    #[set(pub(crate))]
63    pub(crate) hook_context: HookContext,
64}