use std::ops::{Deref, DerefMut};
use crate::{
any_props::AnyProps,
innerlude::{ElementRef, MountId, ScopeOrder, VComponent, WriteMutations},
nodes::RenderReturn,
nodes::VNode,
scopes::ScopeId,
virtual_dom::VirtualDom,
};
impl VirtualDom {
pub(crate) fn diff_scope(
&mut self,
to: &mut impl WriteMutations,
scope: ScopeId,
new_nodes: RenderReturn,
) {
self.runtime.scope_stack.borrow_mut().push(scope);
let scope_state = &mut self.scopes[scope.0];
let new = &new_nodes;
let old = scope_state.last_rendered_node.take().unwrap();
old.diff_node(new, self, to);
let scope_state = &mut self.scopes[scope.0];
scope_state.last_rendered_node = Some(new_nodes);
self.runtime.scope_stack.borrow_mut().pop();
}
pub(crate) fn create_scope(
&mut self,
to: &mut impl WriteMutations,
scope: ScopeId,
new_node: RenderReturn,
parent: Option<ElementRef>,
) -> usize {
self.runtime.scope_stack.borrow_mut().push(scope);
let nodes = new_node.create(self, to, parent);
self.scopes[scope.0].last_rendered_node = Some(new_node);
self.runtime.scope_stack.borrow_mut().pop();
nodes
}
}
impl VNode {
pub(crate) fn diff_vcomponent(
&self,
mount: MountId,
idx: usize,
new: &VComponent,
old: &VComponent,
scope_id: ScopeId,
parent: Option<ElementRef>,
dom: &mut VirtualDom,
to: &mut impl WriteMutations,
) {
if old.render_fn != new.render_fn {
return self.replace_vcomponent(mount, idx, new, parent, dom, to);
}
let old_scope = &mut dom.scopes[scope_id.0];
let old_props: &mut dyn AnyProps = old_scope.props.deref_mut();
let new_props: &dyn AnyProps = new.props.deref();
if old_props.memoize(new_props.props()) {
tracing::trace!("Memoized props for component {:#?}", scope_id,);
return;
}
let new = dom.run_scope(scope_id);
dom.diff_scope(to, scope_id, new);
let height = dom.runtime.get_state(scope_id).unwrap().height;
dom.dirty_scopes.remove(&ScopeOrder::new(height, scope_id));
}
fn replace_vcomponent(
&self,
mount: MountId,
idx: usize,
new: &VComponent,
parent: Option<ElementRef>,
dom: &mut VirtualDom,
to: &mut impl WriteMutations,
) {
let scope = ScopeId(dom.mounts[mount.0].mounted_dynamic_nodes[idx]);
let m = self.create_component_node(mount, idx, new, parent, dom, to);
dom.remove_component_node(to, scope, Some(m), true);
}
pub(super) fn create_component_node(
&self,
mount: MountId,
idx: usize,
component: &VComponent,
parent: Option<ElementRef>,
dom: &mut VirtualDom,
to: &mut impl WriteMutations,
) -> usize {
let scope = dom
.new_scope(component.props.duplicate(), component.name)
.state()
.id;
dom.mounts[mount.0].mounted_dynamic_nodes[idx] = scope.0;
let new = dom.run_scope(scope);
dom.create_scope(to, scope, new, parent)
}
}