euv_core/reactive/hook/struct.rs
1use crate::*;
2
3/// Internal storage for hook state, holding boxed `Any` values.
4///
5/// This struct is not exposed directly; use `HookContext` instead.
6/// The `arm_changed` flag tracks whether a `match` arm switch occurred;
7/// when toggled, the hook array is cleared to prevent signal leakage
8/// between different match arms.
9#[derive(CustomDebug, Data)]
10pub struct HookContextInner {
11 /// Storage for hook state values (signals, etc.).
12 #[debug(skip)]
13 #[get(pub(crate))]
14 #[set(pub(crate))]
15 pub(crate) hooks: Vec<Box<dyn Any>>,
16 /// The match arm index from the last render.
17 /// Set on each `match` arm entry; when the value differs from
18 /// the previous render, hooks are cleared.
19 #[get(pub(crate), type(copy))]
20 #[set(pub(crate))]
21 pub(crate) arm_changed: usize,
22 /// Current hook index, incremented on each hook call and reset per render.
23 #[get(pub(crate), type(copy))]
24 #[set(pub(crate))]
25 pub(crate) hook_index: usize,
26 /// Cleanup closures registered by hooks (e.g., `use_signal`) that must
27 /// be executed when the hook context is cleared due to a `match` arm
28 /// switch. Each closure typically clears signal listeners so that
29 /// stale `setInterval` closures become no-ops.
30 #[debug(skip)]
31 #[get(pub(crate))]
32 #[set(pub(crate))]
33 pub(crate) cleanups: Vec<Box<dyn FnOnce()>>,
34}
35
36/// Manages hook state across render cycles for a DynamicNode.
37///
38/// Stores boxed `Any` values keyed by hook call order, enabling `use_signal`
39/// and similar hooks to persist state between re-renders of the same
40/// dynamic node.
41///
42/// Implements `Copy` for ergonomic use; all copies share the same underlying state.
43///
44/// SAFETY: The inner pointer is allocated via `Box::leak` and lives for the
45/// entire program. This is safe in single-threaded WASM contexts where no
46/// concurrent access can occur.
47#[derive(CustomDebug, Data, Eq, PartialEq)]
48pub struct HookContext {
49 /// Raw pointer to the heap-allocated hook context inner state.
50 #[debug(skip)]
51 #[get(pub(crate))]
52 #[set(pub(crate))]
53 pub(crate) inner: *mut HookContextInner,
54}
55
56/// A `Sync` wrapper for single-threaded global `HookContextInner` access.
57///
58/// SAFETY: This type is only safe to use in single-threaded contexts
59/// (e.g., WASM). It implements `Sync` to allow usage as a `static`
60/// variable, but concurrent access from multiple threads would be
61/// undefined behavior.
62#[derive(CustomDebug)]
63pub struct HookContextCell(
64 /// Interior-mutable storage for the hook context inner state.
65 #[debug(skip)]
66 pub(crate) UnsafeCell<HookContextInner>,
67);