Files
Glint-Runtime/docs/en/modules/03-reactive.md

2.7 KiB

Reactivity Module: src/interpreter/reactive.rs

Dependency tracking system between variables and VDOM elements. Allows recalculation of only changed elements (Phase 3).


ElementId(u32)

Unique element identifier in the VDOM tree. Assigned by ReactiveTracker::alloc_id() during template loading.

#[derive(Debug, Clone, Copy, PartialEq, Eq, Hash)]
pub struct ElementId(pub u32);

Used as:

  • Key in dirty_set: HashSet<ElementId>
  • Key in dependencies: HashMap<ElementId, HashSet<String>>
  • Field in Element::element_id (VDOM → tracker link)
  • Source for iced::widget::Id (Phase 9.2: format!("ti:{}", id.0))
  • Source for scrollable_id (el.element_id.0 as u64)

ReactiveTracker

Dependency graph: variable → list of elements that reference it.

pub struct ReactiveTracker {
    subscribers: HashMap<String, HashSet<ElementId>>,
    dependencies: HashMap<ElementId, HashSet<String>>,
    dirty_set: HashSet<ElementId>,
    next_id: u32,
}

Fields:

  • subscribers — for each variable: which ElementIds depend on it
  • dependencies — for each element: which variables it depends on (reverse mapping)
  • dirty_set — elements to recalculate in the next frame
  • next_id — counter for alloc_id()

Methods

Method Description
new() Empty tracker
alloc_id() -> ElementId Allocate a new ID, increment counter
add_dependency(element, var_name) Register a dependency
scan_value(element, value) Scan a string for $var and add dependencies
on_variable_changed(name) Mark all dependent elements as dirty
take_dirty_set() -> HashSet<ElementId> Take dirty_set and clear it
is_dirty(id) -> bool Check if an element is marked dirty
reset() Clear all data

scan_value()

Parses a string for $var_name patterns:

"Hello $name, you are $age years old"
// → add_dependency(element, "name")
// → add_dependency(element, "age")

Used during template loading for each properties string containing $. As a result, each element knows which variables it depends on.

Update cycle

Event → update() → on_variable_changed("var")
  → dirty_set = {element_A, element_B, ...}
  → take_dirty_set() → evaluate_vdom_incr(roots, &dirty_set)
    → for dirty_set elements: recalculate
    → for others: return as-is

Tests

Test What it checks
test_basic_dependency_tracking Two elements, two variables, correct dirty_set
test_scan_value Parse $var from a string
test_scan_no_vars String without $ creates no dependencies
test_take_dirty_set take_dirty_set() clears the internal set
test_reset reset() clears everything