chore: dynamic attributes cleanup
This commit is contained in:
1 parent
bffb2644a3
commit
399169800d
6 files changed
+130
-61
No files matched your search
@@ -1,4 +1,4 @@
|
|||||||
use crate::{nodes::VNode, virtual_dom::VirtualDom};
|
use crate::{nodes::VNode, virtual_dom::VirtualDom, Mutations, ScopeId};
|
||||||
|
|
||||||
#[cfg_attr(feature = "serialize", derive(serde::Serialize, serde::Deserialize))]
|
#[cfg_attr(feature = "serialize", derive(serde::Serialize, serde::Deserialize))]
|
||||||
#[derive(Clone, Copy, Debug, PartialEq, Eq, PartialOrd, Ord, Hash, Default)]
|
#[derive(Clone, Copy, Debug, PartialEq, Eq, PartialOrd, Ord, Hash, Default)]
|
||||||
@@ -21,7 +21,7 @@ impl ElementRef {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
impl VirtualDom {
|
impl<'b> VirtualDom {
|
||||||
pub fn next_element(&mut self, template: &VNode, path: &'static [u8]) -> ElementId {
|
pub fn next_element(&mut self, template: &VNode, path: &'static [u8]) -> ElementId {
|
||||||
let entry = self.elements.vacant_entry();
|
let entry = self.elements.vacant_entry();
|
||||||
let id = entry.key();
|
let id = entry.key();
|
||||||
@@ -39,11 +39,40 @@ impl VirtualDom {
|
|||||||
pub fn cleanup_element(&mut self, id: ElementId) {
|
pub fn cleanup_element(&mut self, id: ElementId) {
|
||||||
self.elements.remove(id.0);
|
self.elements.remove(id.0);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
pub fn drop_scope(&mut self, id: ScopeId) {
|
||||||
|
// let scope = self.scopes.get(id.0).unwrap();
|
||||||
|
|
||||||
|
// let root = scope.root_node();
|
||||||
|
// let root = unsafe { std::mem::transmute(root) };
|
||||||
|
|
||||||
|
// self.drop_template(root, false);
|
||||||
|
todo!()
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn reclaim(&mut self, el: ElementId) {
|
||||||
|
assert_ne!(el, ElementId(0));
|
||||||
|
self.elements.remove(el.0);
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn drop_template(
|
||||||
|
&mut self,
|
||||||
|
mutations: &mut Mutations,
|
||||||
|
template: &'b VNode<'b>,
|
||||||
|
gen_roots: bool,
|
||||||
|
) {
|
||||||
|
// for node in template.dynamic_nodes.iter() {
|
||||||
|
// match node {
|
||||||
|
// DynamicNode::Text { id, .. } => {}
|
||||||
|
|
||||||
|
// DynamicNode::Component { .. } => {
|
||||||
|
// todo!()
|
||||||
|
// }
|
||||||
|
|
||||||
|
// DynamicNode::Fragment { inner, nodes } => {}
|
||||||
|
// DynamicNode::Placeholder(_) => todo!(),
|
||||||
|
// _ => todo!(),
|
||||||
|
// }
|
||||||
|
// }
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/*
|
|
||||||
now......
|
|
||||||
|
|
||||||
an ID is mostly a pointer to a node in the real dom.
|
|
||||||
We need to
|
|
||||||
*/
|
|
||||||
@@ -80,7 +80,15 @@ impl<'b: 'static> VirtualDom {
|
|||||||
// Else, it's deep in the template and we should create a new id for it
|
// Else, it's deep in the template and we should create a new id for it
|
||||||
let id = match path.len() {
|
let id = match path.len() {
|
||||||
1 => this_id,
|
1 => this_id,
|
||||||
_ => self.next_element(template, template.template.attr_paths[attr_id]),
|
_ => {
|
||||||
|
let id = self
|
||||||
|
.next_element(template, template.template.attr_paths[attr_id]);
|
||||||
|
self.mutations.push(Mutation::AssignId {
|
||||||
|
path: &path[1..],
|
||||||
|
id,
|
||||||
|
});
|
||||||
|
id
|
||||||
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
loop {
|
loop {
|
||||||
|
|||||||
@@ -301,14 +301,24 @@ impl<'b: 'static> VirtualDom {
|
|||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
// we also need to clean up dynamic attribute roots
|
// we clean up nodes with dynamic attributes, provided the node is unique and not a root node
|
||||||
// let last_node = None;
|
let mut id = None;
|
||||||
// for attr in node.dynamic_attrs {
|
for (idx, attr) in node.dynamic_attrs.into_iter().enumerate() {
|
||||||
// match last_node {
|
// We'll clean up the root nodes either way, so don't worry
|
||||||
// Some(node) => todo!(),
|
if node.template.attr_paths[idx].len() == 1 {
|
||||||
// None => todo!(),
|
continue;
|
||||||
// }
|
}
|
||||||
// }
|
|
||||||
|
let next_id = attr.mounted_element.get();
|
||||||
|
|
||||||
|
if id == Some(next_id) {
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
|
||||||
|
id = Some(next_id);
|
||||||
|
|
||||||
|
self.reclaim(next_id);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
fn remove_root_node(&mut self, node: &'b VNode<'b>, idx: usize) {
|
fn remove_root_node(&mut self, node: &'b VNode<'b>, idx: usize) {
|
||||||
|
|||||||
@@ -1,42 +0,0 @@
|
|||||||
use crate::{
|
|
||||||
nodes::VNode, scopes::ScopeId, virtual_dom::VirtualDom, DynamicNode, ElementId, Mutations,
|
|
||||||
};
|
|
||||||
|
|
||||||
impl<'b> VirtualDom {
|
|
||||||
pub fn drop_scope(&mut self, id: ScopeId) {
|
|
||||||
// let scope = self.scopes.get(id.0).unwrap();
|
|
||||||
|
|
||||||
// let root = scope.root_node();
|
|
||||||
// let root = unsafe { std::mem::transmute(root) };
|
|
||||||
|
|
||||||
// self.drop_template(root, false);
|
|
||||||
todo!()
|
|
||||||
}
|
|
||||||
|
|
||||||
pub fn reclaim(&mut self, el: ElementId) {
|
|
||||||
assert_ne!(el, ElementId(0));
|
|
||||||
println!("reclaiming {}", el.0);
|
|
||||||
self.elements.remove(el.0);
|
|
||||||
}
|
|
||||||
|
|
||||||
pub fn drop_template(
|
|
||||||
&mut self,
|
|
||||||
mutations: &mut Mutations,
|
|
||||||
template: &'b VNode<'b>,
|
|
||||||
gen_roots: bool,
|
|
||||||
) {
|
|
||||||
// for node in template.dynamic_nodes.iter() {
|
|
||||||
// match node {
|
|
||||||
// DynamicNode::Text { id, .. } => {}
|
|
||||||
|
|
||||||
// DynamicNode::Component { .. } => {
|
|
||||||
// todo!()
|
|
||||||
// }
|
|
||||||
|
|
||||||
// DynamicNode::Fragment { inner, nodes } => {}
|
|
||||||
// DynamicNode::Placeholder(_) => todo!(),
|
|
||||||
// _ => todo!(),
|
|
||||||
// }
|
|
||||||
// }
|
|
||||||
}
|
|
||||||
}
|
|
||||||
@@ -8,7 +8,6 @@ mod error_boundary;
|
|||||||
mod events;
|
mod events;
|
||||||
mod factory;
|
mod factory;
|
||||||
mod fragment;
|
mod fragment;
|
||||||
mod garbage;
|
|
||||||
mod lazynodes;
|
mod lazynodes;
|
||||||
mod mutations;
|
mod mutations;
|
||||||
mod nodes;
|
mod nodes;
|
||||||
|
|||||||
@@ -0,0 +1,65 @@
|
|||||||
|
//! dynamic attributes in dioxus necessitate an allocated node ID.
|
||||||
|
//!
|
||||||
|
//! This tests to ensure we clean it up
|
||||||
|
|
||||||
|
use dioxus::core::{ElementId, Mutation::*};
|
||||||
|
use dioxus::prelude::*;
|
||||||
|
|
||||||
|
#[test]
|
||||||
|
fn attrs_cycle() {
|
||||||
|
let mut dom = VirtualDom::new(|cx| {
|
||||||
|
let id = cx.generation();
|
||||||
|
match cx.generation() % 2 {
|
||||||
|
0 => cx.render(rsx! {
|
||||||
|
div {}
|
||||||
|
}),
|
||||||
|
1 => cx.render(rsx! {
|
||||||
|
div {
|
||||||
|
h1 { class: "{id}", id: "{id}" }
|
||||||
|
}
|
||||||
|
}),
|
||||||
|
_ => unreachable!(),
|
||||||
|
}
|
||||||
|
});
|
||||||
|
|
||||||
|
assert_eq!(
|
||||||
|
dom.rebuild().santize().edits,
|
||||||
|
[
|
||||||
|
LoadTemplate { name: "template", index: 0, id: ElementId(1,) },
|
||||||
|
AppendChildren { m: 1 },
|
||||||
|
]
|
||||||
|
);
|
||||||
|
|
||||||
|
dom.mark_dirty_scope(ScopeId(0));
|
||||||
|
assert_eq!(
|
||||||
|
dom.render_immediate().santize().edits,
|
||||||
|
[
|
||||||
|
LoadTemplate { name: "template", index: 0, id: ElementId(2,) },
|
||||||
|
AssignId { path: &[0,], id: ElementId(3,) },
|
||||||
|
SetAttribute { name: "class", value: "1", id: ElementId(3,), ns: None },
|
||||||
|
SetAttribute { name: "id", value: "1", id: ElementId(3,), ns: None },
|
||||||
|
ReplaceWith { id: ElementId(1,), m: 1 },
|
||||||
|
]
|
||||||
|
);
|
||||||
|
|
||||||
|
dom.mark_dirty_scope(ScopeId(0));
|
||||||
|
dbg!(
|
||||||
|
dom.render_immediate().santize(),
|
||||||
|
[
|
||||||
|
LoadTemplate { name: "template", index: 0, id: ElementId(1,) },
|
||||||
|
ReplaceWith { id: ElementId(2,), m: 1 },
|
||||||
|
]
|
||||||
|
);
|
||||||
|
|
||||||
|
dom.mark_dirty_scope(ScopeId(0));
|
||||||
|
assert_eq!(
|
||||||
|
dom.render_immediate().santize().edits,
|
||||||
|
[
|
||||||
|
LoadTemplate { name: "template", index: 0, id: ElementId(2) },
|
||||||
|
AssignId { path: &[0], id: ElementId(1) },
|
||||||
|
SetAttribute { name: "class", value: "3", id: ElementId(1), ns: None },
|
||||||
|
SetAttribute { name: "id", value: "3", id: ElementId(1), ns: None },
|
||||||
|
ReplaceWith { id: ElementId(3), m: 1 }
|
||||||
|
]
|
||||||
|
);
|
||||||
|
}
|
||||||
Reference in new issue
Block a user