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 a raw pointer.
6/// Allocated via `Box::leak` and lives for the remainder of the program.
7pub(crate) struct RenderFnInner {
8 /// The boxed render closure.
9 pub(crate) render_fn: Box<dyn FnMut() -> VirtualNode>,
10}
11
12/// Represents a text node in the virtual DOM.
13///
14/// Text nodes may optionally be bound to a reactive signal for automatic updates.
15#[derive(Clone, Data, Debug, New)]
16pub struct TextNode {
17 /// The text content.
18 #[get(pub(crate))]
19 #[set(pub(crate))]
20 pub(crate) content: String,
21 /// An optional signal that drives reactive text updates.
22 #[get(pub(crate))]
23 #[set(pub(crate))]
24 pub(crate) signal: Option<Signal<String>>,
25}
26
27/// A closure-based dynamic node that re-renders when its dependency signals change.
28///
29/// Holds a raw pointer to a heap-allocated render closure that produces a fresh
30/// `VirtualNode` on each evaluation. The renderer subscribes to the closure's
31/// signals and patches the DOM automatically.
32/// Contains a `HookContext` that persists hook state (like `use_signal`) across
33/// re-renders, ensuring that signal values are not reset when the render function
34/// is called again.
35///
36/// Implements `Copy` for ergonomic use; all copies share the same underlying state.
37///
38/// SAFETY: The inner pointer is allocated via `Box::leak` and lives for the
39/// entire program. This is safe in single-threaded WASM contexts where no
40/// concurrent access can occur.
41#[derive(CustomDebug)]
42pub struct DynamicNode {
43 /// Raw pointer to the heap-allocated render closure inner state.
44 ///
45 /// SAFETY: Allocated via `Box::leak`, valid for the program lifetime.
46 #[debug(skip)]
47 pub(crate) render_fn: *mut RenderFnInner,
48 /// Persistent hook context for this dynamic node, storing signal
49 /// state and other hook values across render cycles.
50 ///
51 /// Implements `Copy`; all copies share the same underlying state.
52 /// When the `arm_changed` flag inside is toggled (by `match` arm switching),
53 /// the hooks array is cleared to prevent signal leakage between arms.
54 pub(crate) hook_context: HookContext,
55}