1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
use *;
/// Global auto-incrementing ID counter for DOM elements.
pub static NEXT_EUV_ID: AtomicUsize = new;
/// Global auto-incrementing ID counter for DynamicNode placeholder elements.
pub static NEXT_EUV_DYNAMIC_ID: AtomicUsize = new;
/// Whether `dispatch_updates` is currently executing.
pub static SIGNAL_UPDATE_DISPATCHING: AtomicBool = new;
/// Set of dynamic node IDs marked dirty since the last dispatch drain.
///
/// OPT 6: the dispatcher's hot path used to scan the entire signal
/// update registry (`HashMap<usize, SignalUpdateEntry>`) on every
/// tick to find slots whose `dirty` flag was set. For a SPA with N
/// dynamic nodes and only a handful of changed signals per tick, this
/// was an `O(N)` scan with a `*const SignalUpdateSlot` pointer
/// dereference + branch per entry. The dirty-set replaces it with a
/// single `HashSet::drain()` over the IDs that were actually marked
/// dirty — a `O(脏节点数)` operation that does no per-slot pointer
/// traversal until the matching slot is found.
///
/// Populated by `Registry::mark_dirty` and drained by
/// `Scheduler::dispatch_updates`. A redundant `dirty = true` set is a
/// no-op thanks to `HashSet` semantics. The set survives the dispatch
/// itself (the dirty flag is reset inside the loop); only the
/// `mark_dirty` path inserts into it.
pub static mut DIRTY_UPDATE_IDS: =
new;
/// Global handler registry, mapping (element_id, event_name) to HandlerEntry.
pub static mut HANDLER_REGISTRY: =
new;
/// Global set of event names that have already been delegated at the window level.
pub static mut DELEGATED_EVENTS: =
new;
/// Global signal update callback registry, mapping keys to SignalUpdateEntry.
pub static mut SIGNAL_UPDATE_REGISTRY: =
new;
/// Global auto-incrementing ID counter for window event handler entries.
pub static NEXT_WINDOW_HANDLER_ID: AtomicUsize = new;
/// Global window event proxy registry, mapping event names to handler lists.
pub static mut WINDOW_EVENT_REGISTRY: =
new;
/// Global `NodeRef` registry used to clear `NodeRef` handles when the
/// DOM element they point to is unmounted.
///
/// NP-3: each time a `ref:` attribute fires, the mount path registers
/// the `NodeRef`'s shared interior cell into this map under the
/// element's `euv_id`. `cleanup_subtree` then drains the entries for
/// that id and calls `NodeRef::clear` so `get()` / `get_cloned()` return
/// `None` after the underlying DOM subtree is gone.
pub static mut NODEREF_REGISTRY: =
new;
/// Global typed-attribute-bridge registry, mapping bridge signal addresses
/// to the `AttributeBridge` that the bridge signal's listener mutates on
/// every set.
///
/// Populated by `Registry::register_attribute_bridge` (called from the
/// per-`{sig}` mount paths in `Renderer::create_dom_with_doc`) and drained
/// by `Registry::cleanup_attribute_bridge` (called from
/// `Signal::<String>::clear_listeners`).
///
/// Replaces the older bridge-signal + `BridgeRefsCell::track` chain that
/// allocated a `HashSet<usize>` per bridge (the source-dependency set).
/// With this registry the bridge struct is freed at exactly the same time
/// as the bridge signal, and no per-source-signal `HashSet` is needed.
pub static mut ATTRIBUTE_BRIDGES: =
new;