Phase 3.1-3.3: ReactiveTracker with ElementId assignment during parsing, dependency scanning, variable change notification in app.rs
This commit is contained in:
@@ -1,5 +1,6 @@
|
||||
|
||||
pub mod opcodes;
|
||||
pub mod reactive;
|
||||
pub mod reader;
|
||||
pub mod rhei;
|
||||
pub mod style;
|
||||
@@ -9,6 +10,7 @@ use std::borrow::Cow;
|
||||
pub use rhei::RheiContext;
|
||||
use style::StyleSheet as SS;
|
||||
pub use types::{ComponentDef, Document, Element, Interner, InterpError};
|
||||
pub use reactive::{ElementId, ReactiveTracker};
|
||||
|
||||
use compact_str::CompactString;
|
||||
use opcodes::*;
|
||||
@@ -31,6 +33,7 @@ impl Interpreter {
|
||||
let mut components = HashMap::new();
|
||||
let mut rhei_scripts: Vec<String> = Vec::new();
|
||||
let mut stylesheet = SS::new();
|
||||
let mut tracker = ReactiveTracker::new();
|
||||
|
||||
let roots = Self::parse_block_elements(
|
||||
&mut r,
|
||||
@@ -38,13 +41,14 @@ impl Interpreter {
|
||||
&mut components,
|
||||
&mut rhei_scripts,
|
||||
&mut stylesheet,
|
||||
&mut tracker,
|
||||
true,
|
||||
)?;
|
||||
|
||||
//let rhei_ctx = RheiContext::new(&rhei_scripts);
|
||||
//rhei_ctx.initialize(&mut variables);
|
||||
|
||||
Ok(Document { roots, components, variables, rhei_scripts, stylesheet, interner: Interner::new() })
|
||||
Ok(Document { roots, components, variables, rhei_scripts, stylesheet, interner: Interner::new(), tracker })
|
||||
}
|
||||
|
||||
fn parse_block_elements<'a>(
|
||||
@@ -53,6 +57,7 @@ impl Interpreter {
|
||||
components: &mut HashMap<String, ComponentDef<'a>>,
|
||||
rhei_scripts: &mut Vec<String>,
|
||||
stylesheet: &mut SS,
|
||||
tracker: &mut ReactiveTracker,
|
||||
is_root: bool,
|
||||
) -> Result<Vec<Element<'a>>, InterpError> {
|
||||
let mut roots: Vec<Element> = Vec::new();
|
||||
@@ -63,8 +68,12 @@ impl Interpreter {
|
||||
if !is_root && op == OP_END_BLOCK { break; }
|
||||
|
||||
match op {
|
||||
OP_ELEM_PUSH => stack.push(Element::new(r.read_str_ref()?)),
|
||||
|
||||
OP_ELEM_PUSH => {
|
||||
let elem_id = tracker.alloc_id();
|
||||
let mut el = Element::new(r.read_str_ref()?);
|
||||
el.element_id = elem_id;
|
||||
stack.push(el);
|
||||
}
|
||||
OP_ELEM_POP => {
|
||||
let finished = stack.pop().ok_or(InterpError::UnexpectedPop)?;
|
||||
Self::attach(&mut stack, &mut roots, finished);
|
||||
@@ -96,10 +105,12 @@ impl Interpreter {
|
||||
val.push_str(RHEI_PREFIX);
|
||||
val.push_str(expr_ref);
|
||||
if let Some(el) = stack.last_mut() {
|
||||
tracker.scan_value(el.element_id, &val);
|
||||
el.push_prop("text".to_string(), val);
|
||||
}
|
||||
} else if let Some(value) = r.read_value_as_string(vop)? {
|
||||
if let Some(el) = stack.last_mut() {
|
||||
tracker.scan_value(el.element_id, &value);
|
||||
el.push_prop("text".to_string(), value);
|
||||
}
|
||||
}
|
||||
@@ -108,7 +119,10 @@ impl Interpreter {
|
||||
OP_PROP_STR => {
|
||||
let key = r.read_str_ref()?;
|
||||
let val = r.read_str_ref()?;
|
||||
if let Some(el) = stack.last_mut() { el.push_prop(key, val); }
|
||||
if let Some(el) = stack.last_mut() {
|
||||
tracker.scan_value(el.element_id, val);
|
||||
el.push_prop(key, val);
|
||||
}
|
||||
}
|
||||
OP_PROP_VAR => {
|
||||
let key = r.read_str_ref()?;
|
||||
@@ -116,22 +130,31 @@ impl Interpreter {
|
||||
let mut val = String::with_capacity(val_ref.len() + 1);
|
||||
val.push('$');
|
||||
val.push_str(val_ref);
|
||||
if let Some(el) = stack.last_mut() { el.push_prop(key, val); }
|
||||
if let Some(el) = stack.last_mut() {
|
||||
tracker.scan_value(el.element_id, &val);
|
||||
el.push_prop(key, val);
|
||||
}
|
||||
}
|
||||
OP_PROP_INT => {
|
||||
let key = r.read_str_ref()?;
|
||||
let val = r.read_i64()?.to_string();
|
||||
if let Some(el) = stack.last_mut() { el.push_prop(key, val); }
|
||||
if let Some(el) = stack.last_mut() {
|
||||
el.push_prop(key, val);
|
||||
}
|
||||
}
|
||||
OP_PROP_FLOAT => {
|
||||
let key = r.read_str_ref()?;
|
||||
let val = r.read_f64()?.to_string();
|
||||
if let Some(el) = stack.last_mut() { el.push_prop(key, val); }
|
||||
if let Some(el) = stack.last_mut() {
|
||||
el.push_prop(key, val);
|
||||
}
|
||||
}
|
||||
OP_PROP_BOOL => {
|
||||
let key = r.read_str_ref()?;
|
||||
let val = (r.read_byte()? != 0).to_string();
|
||||
if let Some(el) = stack.last_mut() { el.push_prop(key, val); }
|
||||
if let Some(el) = stack.last_mut() {
|
||||
el.push_prop(key, val);
|
||||
}
|
||||
}
|
||||
OP_PROP_RHEI => {
|
||||
let key = r.read_str_ref()?;
|
||||
@@ -140,13 +163,16 @@ impl Interpreter {
|
||||
val.push_str(RHEI_PREFIX);
|
||||
val.push_str(expr_ref);
|
||||
if let Some(el) = stack.last_mut() {
|
||||
tracker.scan_value(el.element_id, &val);
|
||||
el.push_prop(key, val);
|
||||
}
|
||||
}
|
||||
OP_PROP_UNIT | OP_PROP_CALL | OP_PROP_IDENT | OP_PROP_FSPATH | OP_PROP_COLOR => {
|
||||
let key = r.read_str_ref()?;
|
||||
if let Some(val) = r.read_value_as_string(op)? {
|
||||
if let Some(el) = stack.last_mut() { el.push_prop(key, val); }
|
||||
if let Some(el) = stack.last_mut() {
|
||||
el.push_prop(key, val);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -156,10 +182,10 @@ impl Interpreter {
|
||||
rhei_scripts.push(script);
|
||||
} else {
|
||||
let mut text_el = Element::new("#text");
|
||||
text_el.push_prop(
|
||||
"text".to_string(),
|
||||
format!("{RHEI_PREFIX}{script}"),
|
||||
);
|
||||
text_el.element_id = tracker.alloc_id();
|
||||
let full_val = format!("{RHEI_PREFIX}{script}");
|
||||
tracker.scan_value(text_el.element_id, &full_val);
|
||||
text_el.push_prop("text".to_string(), full_val);
|
||||
Self::attach(&mut stack, &mut roots, text_el);
|
||||
}
|
||||
}
|
||||
@@ -171,7 +197,7 @@ impl Interpreter {
|
||||
.map(|_| Ok((r.read_string()?, r.read_string()?)))
|
||||
.collect::<Result<Vec<_>, InterpError>>()?;
|
||||
let children = Self::parse_block_elements(
|
||||
r, variables, components, rhei_scripts, stylesheet, false,
|
||||
r, variables, components, rhei_scripts, stylesheet, tracker, false,
|
||||
)?;
|
||||
components.insert(name.clone(), ComponentDef { name, params, children });
|
||||
}
|
||||
@@ -186,23 +212,26 @@ impl Interpreter {
|
||||
};
|
||||
|
||||
let true_children = Self::parse_block_elements(
|
||||
r, variables, components, rhei_scripts, stylesheet, false,
|
||||
r, variables, components, rhei_scripts, stylesheet, tracker, false,
|
||||
)?;
|
||||
let has_else = r.read_byte()? == 1;
|
||||
let false_children = if has_else {
|
||||
Self::parse_block_elements(
|
||||
r, variables, components, rhei_scripts, stylesheet, false,
|
||||
r, variables, components, rhei_scripts, stylesheet, tracker, false,
|
||||
)?
|
||||
} else {
|
||||
Vec::new()
|
||||
};
|
||||
|
||||
let mut if_el = Element::new("@if");
|
||||
if_el.element_id = tracker.alloc_id();
|
||||
tracker.scan_value(if_el.element_id, &cond_val);
|
||||
if_el.push_prop("condition", cond_val);
|
||||
if_el.children = true_children;
|
||||
|
||||
if !false_children.is_empty() {
|
||||
let mut else_el = Element::new("@else");
|
||||
else_el.element_id = tracker.alloc_id();
|
||||
else_el.children = false_children;
|
||||
if_el.children.push(else_el);
|
||||
}
|
||||
@@ -221,10 +250,12 @@ impl Interpreter {
|
||||
};
|
||||
|
||||
let block_children = Self::parse_block_elements(
|
||||
r, variables, components, rhei_scripts, stylesheet, false,
|
||||
r, variables, components, rhei_scripts, stylesheet, tracker, false,
|
||||
)?;
|
||||
|
||||
let mut each_el = Element::new("@each");
|
||||
each_el.element_id = tracker.alloc_id();
|
||||
tracker.scan_value(each_el.element_id, &source_val);
|
||||
each_el.push_prop("var_name".to_string(), var_name);
|
||||
each_el.push_prop("source".to_string(), source_val);
|
||||
each_el.children = block_children;
|
||||
|
||||
Reference in New Issue
Block a user