real_dom.rs 18 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458
  1. use dioxus_core::{ElementId, Mutations, TemplateNode};
  2. use rustc_hash::{FxHashMap, FxHashSet};
  3. use std::fmt::Debug;
  4. use std::ops::{Deref, DerefMut, Index, IndexMut};
  5. use crate::node::{Node, NodeType, OwnedAttributeDiscription, OwnedAttributeValue};
  6. use crate::node_ref::{AttributeMask, NodeMask};
  7. use crate::passes::DirtyNodeStates;
  8. use crate::state::State;
  9. use crate::tree::{NodeId, Tree, TreeLike, TreeView};
  10. use crate::{FxDashSet, RealNodeId, SendAnyMap};
  11. fn mark_dirty(
  12. node_id: NodeId,
  13. mask: NodeMask,
  14. nodes_updated: &mut FxHashMap<RealNodeId, NodeMask>,
  15. ) {
  16. if let Some(node) = nodes_updated.get_mut(&node_id) {
  17. *node = node.union(&mask);
  18. } else {
  19. nodes_updated.insert(node_id, mask);
  20. }
  21. }
  22. /// A Dom that can sync with the VirtualDom mutations intended for use in lazy renderers.
  23. /// The render state passes from parent to children and or accumulates state from children to parents.
  24. /// To get started implement [crate::state::ParentDepState], [crate::state::NodeDepState], or [crate::state::ChildDepState] and call [RealDom::apply_mutations] to update the dom and [RealDom::update_state] to update the state of the nodes.
  25. #[derive(Debug)]
  26. pub struct RealDom<S: State> {
  27. pub tree: Tree<Node<S>>,
  28. /// a map from element id to real node id
  29. node_id_mapping: Vec<Option<RealNodeId>>,
  30. nodes_listening: FxHashMap<String, FxHashSet<RealNodeId>>,
  31. stack: Vec<RealNodeId>,
  32. templates: FxHashMap<String, Vec<RealNodeId>>,
  33. root_initialized: bool,
  34. }
  35. impl<S: State> Default for RealDom<S> {
  36. fn default() -> Self {
  37. Self::new()
  38. }
  39. }
  40. impl<S: State> RealDom<S> {
  41. pub fn new() -> RealDom<S> {
  42. let mut root = Node::new(NodeType::Element {
  43. tag: "Root".to_string(),
  44. namespace: Some("Root".to_string()),
  45. attributes: FxHashMap::default(),
  46. listeners: FxHashSet::default(),
  47. });
  48. root.node_data.element_id = Some(ElementId(0));
  49. let mut tree = Tree::new(root);
  50. let root_id = tree.root();
  51. tree.get_mut(root_id).unwrap().node_data.node_id = root_id;
  52. RealDom {
  53. tree,
  54. node_id_mapping: vec![Some(root_id)],
  55. nodes_listening: FxHashMap::default(),
  56. stack: vec![root_id],
  57. templates: FxHashMap::default(),
  58. root_initialized: false,
  59. }
  60. }
  61. pub fn element_to_node_id(&self, element_id: ElementId) -> RealNodeId {
  62. self.node_id_mapping.get(element_id.0).unwrap().unwrap()
  63. }
  64. fn set_element_id(&mut self, node_id: NodeId, element_id: ElementId) {
  65. let node = self.tree.get_mut(node_id).unwrap();
  66. let node_id = node.node_data.node_id;
  67. node.node_data.element_id = Some(element_id);
  68. if self.node_id_mapping.len() <= element_id.0 {
  69. self.node_id_mapping.resize(element_id.0 + 1, None);
  70. }
  71. if let Some(Some(old_id)) = self.node_id_mapping.get(element_id.0) {
  72. // free the memory associated with the old node
  73. self.tree.remove(*old_id);
  74. }
  75. self.node_id_mapping[element_id.0] = Some(node_id);
  76. }
  77. fn load_child(&self, path: &[u8]) -> RealNodeId {
  78. let mut current = *self.stack.last().unwrap();
  79. for i in path {
  80. current = self.tree.children_ids(current).unwrap()[*i as usize];
  81. }
  82. current
  83. }
  84. fn create_node(&mut self, node: Node<S>) -> RealNodeId {
  85. let node_id = self.tree.create_node(node);
  86. let node = self.tree.get_mut(node_id).unwrap();
  87. node.node_data.node_id = node_id;
  88. node_id
  89. }
  90. fn add_child(&mut self, node_id: RealNodeId, child_id: RealNodeId) {
  91. self.tree.add_child(node_id, child_id);
  92. }
  93. fn create_template_node(&mut self, node: &TemplateNode) -> RealNodeId {
  94. match node {
  95. TemplateNode::Element {
  96. tag,
  97. namespace,
  98. attrs,
  99. children,
  100. } => {
  101. let node = Node::new(NodeType::Element {
  102. tag: tag.to_string(),
  103. namespace: namespace.map(|s| s.to_string()),
  104. attributes: attrs
  105. .iter()
  106. .filter_map(|attr| match attr {
  107. dioxus_core::TemplateAttribute::Static {
  108. name,
  109. value,
  110. namespace,
  111. } => Some((
  112. OwnedAttributeDiscription {
  113. namespace: namespace.map(|s| s.to_string()),
  114. name: name.to_string(),
  115. volatile: false,
  116. },
  117. OwnedAttributeValue::Text(value.to_string()),
  118. )),
  119. dioxus_core::TemplateAttribute::Dynamic { .. } => None,
  120. })
  121. .collect(),
  122. listeners: FxHashSet::default(),
  123. });
  124. let node_id = self.create_node(node);
  125. for child in *children {
  126. let child_id = self.create_template_node(child);
  127. self.add_child(node_id, child_id);
  128. }
  129. node_id
  130. }
  131. TemplateNode::Text { text } => self.create_node(Node::new(NodeType::Text {
  132. text: text.to_string(),
  133. })),
  134. TemplateNode::Dynamic { .. } => self.create_node(Node::new(NodeType::Placeholder)),
  135. TemplateNode::DynamicText { .. } => self.create_node(Node::new(NodeType::Text {
  136. text: String::new(),
  137. })),
  138. }
  139. }
  140. /// Updates the dom with some mutations and return a set of nodes that were updated. Pass the dirty nodes to update_state.
  141. pub fn apply_mutations(
  142. &mut self,
  143. mutations: Mutations,
  144. ) -> (DirtyNodeStates, FxHashMap<RealNodeId, NodeMask>) {
  145. let mut nodes_updated: FxHashMap<RealNodeId, NodeMask> = FxHashMap::default();
  146. for template in mutations.templates {
  147. let mut template_root_ids = Vec::new();
  148. for root in template.roots {
  149. let id = self.create_template_node(root);
  150. template_root_ids.push(id);
  151. }
  152. self.templates
  153. .insert(template.name.to_string(), template_root_ids);
  154. }
  155. if !self.root_initialized {
  156. self.root_initialized = true;
  157. let root_id = self.tree.root();
  158. nodes_updated.insert(root_id, NodeMask::ALL);
  159. }
  160. for e in mutations.edits {
  161. use dioxus_core::Mutation::*;
  162. match e {
  163. AppendChildren { id, m } => {
  164. let children = self.stack.split_off(m);
  165. let parent = self.element_to_node_id(id);
  166. for child in children {
  167. self.add_child(parent, child);
  168. mark_dirty(child, NodeMask::ALL, &mut nodes_updated);
  169. }
  170. }
  171. AssignId { path, id } => {
  172. self.set_element_id(self.load_child(path), id);
  173. }
  174. CreatePlaceholder { id } => {
  175. let node = Node::new(NodeType::Placeholder);
  176. let node_id = self.create_node(node);
  177. self.set_element_id(node_id, id);
  178. self.stack.push(node_id);
  179. mark_dirty(node_id, NodeMask::ALL, &mut nodes_updated);
  180. }
  181. CreateTextNode { value, id } => {
  182. let node = Node::new(NodeType::Text {
  183. text: value.to_string(),
  184. });
  185. let node_id = self.create_node(node);
  186. let node = self.tree.get_mut(node_id).unwrap();
  187. node.node_data.element_id = Some(id);
  188. self.stack.push(node_id);
  189. mark_dirty(node_id, NodeMask::new().with_text(), &mut nodes_updated);
  190. }
  191. HydrateText { path, value, id } => {
  192. let node_id = self.load_child(path);
  193. self.set_element_id(node_id, id);
  194. let node = self.tree.get_mut(node_id).unwrap();
  195. if let NodeType::Text { text } = &mut node.node_data.node_type {
  196. *text = value.to_string();
  197. } else {
  198. node.node_data.node_type = NodeType::Text {
  199. text: value.to_string(),
  200. };
  201. }
  202. mark_dirty(node_id, NodeMask::new().with_text(), &mut nodes_updated);
  203. }
  204. LoadTemplate { name, index, id } => {
  205. let template_id = self.templates[name][index];
  206. let clone_id = self.clone_node(template_id, &mut nodes_updated);
  207. self.set_element_id(clone_id, id);
  208. self.stack.push(clone_id);
  209. }
  210. ReplaceWith { id, m } => {
  211. let new_nodes = self.stack.split_off(m);
  212. let old_node_id = self.element_to_node_id(id);
  213. for new in new_nodes {
  214. self.tree.insert_after(old_node_id, new);
  215. mark_dirty(new, NodeMask::ALL, &mut nodes_updated);
  216. }
  217. self.tree.remove(old_node_id);
  218. }
  219. ReplacePlaceholder { path, m } => {
  220. let new_nodes = self.stack.split_off(self.stack.len() - m);
  221. let old_node_id = self.load_child(path);
  222. for new in new_nodes {
  223. self.tree.insert_after(old_node_id, new);
  224. mark_dirty(new, NodeMask::ALL, &mut nodes_updated);
  225. }
  226. self.tree.remove(old_node_id);
  227. }
  228. InsertAfter { id, m } => {
  229. let new_nodes = self.stack.split_off(m);
  230. let old_node_id = self.element_to_node_id(id);
  231. for new in new_nodes {
  232. self.tree.insert_after(old_node_id, new);
  233. mark_dirty(new, NodeMask::ALL, &mut nodes_updated);
  234. }
  235. }
  236. InsertBefore { id, m } => {
  237. let new_nodes = self.stack.split_off(m);
  238. let old_node_id = self.element_to_node_id(id);
  239. for new in new_nodes {
  240. self.tree.insert_before(old_node_id, new);
  241. mark_dirty(new, NodeMask::ALL, &mut nodes_updated);
  242. }
  243. }
  244. SetAttribute {
  245. name,
  246. value,
  247. id,
  248. ns,
  249. } => {
  250. let node_id = self.element_to_node_id(id);
  251. let node = self.tree.get_mut(node_id).unwrap();
  252. if let NodeType::Element { attributes, .. } = &mut node.node_data.node_type {
  253. attributes.insert(
  254. OwnedAttributeDiscription {
  255. name: name.to_string(),
  256. namespace: ns.map(|s| s.to_string()),
  257. volatile: false,
  258. },
  259. crate::node::OwnedAttributeValue::Text(value.to_string()),
  260. );
  261. mark_dirty(
  262. node_id,
  263. NodeMask::new_with_attrs(AttributeMask::single(name)),
  264. &mut nodes_updated,
  265. );
  266. }
  267. }
  268. SetBoolAttribute { name, value, id } => {
  269. let node_id = self.element_to_node_id(id);
  270. let node = self.tree.get_mut(node_id).unwrap();
  271. if let NodeType::Element { attributes, .. } = &mut node.node_data.node_type {
  272. attributes.insert(
  273. OwnedAttributeDiscription {
  274. name: name.to_string(),
  275. namespace: None,
  276. volatile: false,
  277. },
  278. crate::node::OwnedAttributeValue::Bool(value),
  279. );
  280. mark_dirty(
  281. node_id,
  282. NodeMask::new_with_attrs(AttributeMask::single(name)),
  283. &mut nodes_updated,
  284. );
  285. }
  286. }
  287. SetText { value, id } => {
  288. let node_id = self.element_to_node_id(id);
  289. let node = self.tree.get_mut(node_id).unwrap();
  290. if let NodeType::Text { text } = &mut node.node_data.node_type {
  291. *text = value.to_string();
  292. }
  293. mark_dirty(node_id, NodeMask::new().with_text(), &mut nodes_updated);
  294. }
  295. NewEventListener { name, id } => {
  296. let node_id = self.element_to_node_id(id);
  297. let node = self.tree.get_mut(node_id).unwrap();
  298. if let NodeType::Element { listeners, .. } = &mut node.node_data.node_type {
  299. match self.nodes_listening.get_mut(name) {
  300. Some(hs) => {
  301. hs.insert(node_id);
  302. }
  303. None => {
  304. let mut hs = FxHashSet::default();
  305. hs.insert(node_id);
  306. self.nodes_listening.insert(name.to_string(), hs);
  307. }
  308. }
  309. listeners.insert(name.to_string());
  310. }
  311. }
  312. RemoveEventListener { id, name } => {
  313. let node_id = self.element_to_node_id(id);
  314. let node = self.tree.get_mut(node_id).unwrap();
  315. if let NodeType::Element { listeners, .. } = &mut node.node_data.node_type {
  316. listeners.remove(name);
  317. }
  318. self.nodes_listening.get_mut(name).unwrap().remove(&node_id);
  319. }
  320. Remove { id } => {
  321. let node_id = self.element_to_node_id(id);
  322. self.tree.remove(node_id);
  323. }
  324. PushRoot { id } => {
  325. let node_id = self.element_to_node_id(id);
  326. self.stack.push(node_id);
  327. }
  328. }
  329. }
  330. let dirty_nodes = DirtyNodeStates::default();
  331. for (&n, mask) in &nodes_updated {
  332. // remove any nodes that were created and then removed in the same mutations from the dirty nodes list
  333. if self.tree.contains(n) {
  334. for (m, p) in S::MASKS.iter().zip(S::PASSES.iter()) {
  335. if mask.overlaps(m) {
  336. dirty_nodes.insert(p.pass_id(), n);
  337. }
  338. }
  339. }
  340. }
  341. (dirty_nodes, nodes_updated)
  342. }
  343. /// Update the state of the dom, after appling some mutations. This will keep the nodes in the dom up to date with their VNode counterparts.
  344. pub fn update_state(
  345. &mut self,
  346. nodes_updated: DirtyNodeStates,
  347. ctx: SendAnyMap,
  348. ) -> FxDashSet<RealNodeId> {
  349. S::update(nodes_updated, &mut self.tree, ctx)
  350. }
  351. /// Find all nodes that are listening for an event, sorted by there height in the dom progressing starting at the bottom and progressing up.
  352. /// This can be useful to avoid creating duplicate events.
  353. pub fn get_listening_sorted(&self, event: &'static str) -> Vec<&Node<S>> {
  354. if let Some(nodes) = self.nodes_listening.get(event) {
  355. let mut listening: Vec<_> = nodes.iter().map(|id| &self[*id]).collect();
  356. listening.sort_by(|n1, n2| {
  357. (self.tree.height(n1.node_data.node_id))
  358. .cmp(&self.tree.height(n2.node_data.node_id))
  359. .reverse()
  360. });
  361. listening
  362. } else {
  363. Vec::new()
  364. }
  365. }
  366. /// Return the number of nodes in the dom.
  367. pub fn size(&self) -> usize {
  368. // The dom has a root node, ignore it.
  369. self.tree.size() - 1
  370. }
  371. /// Returns the id of the root node.
  372. pub fn root_id(&self) -> NodeId {
  373. self.tree.root()
  374. }
  375. fn clone_node(
  376. &mut self,
  377. node_id: NodeId,
  378. nodes_updated: &mut FxHashMap<RealNodeId, NodeMask>,
  379. ) -> RealNodeId {
  380. let node = self.tree.get(node_id).unwrap();
  381. let new_node = node.clone();
  382. let new_id = self.create_node(new_node);
  383. mark_dirty(new_id, NodeMask::ALL, nodes_updated);
  384. let self_ptr = self as *mut Self;
  385. for child in self.tree.children_ids(node_id).unwrap() {
  386. unsafe {
  387. // this is safe because no node has itself as a child
  388. let self_mut = &mut *self_ptr;
  389. let child_id = self_mut.clone_node(*child, nodes_updated);
  390. self_mut.add_child(new_id, child_id);
  391. }
  392. }
  393. new_id
  394. }
  395. }
  396. impl<S: State> Deref for RealDom<S> {
  397. type Target = Tree<Node<S>>;
  398. fn deref(&self) -> &Self::Target {
  399. &self.tree
  400. }
  401. }
  402. impl<S: State> DerefMut for RealDom<S> {
  403. fn deref_mut(&mut self) -> &mut Self::Target {
  404. &mut self.tree
  405. }
  406. }
  407. impl<S: State> Index<ElementId> for RealDom<S> {
  408. type Output = Node<S>;
  409. fn index(&self, id: ElementId) -> &Self::Output {
  410. self.tree.get(self.element_to_node_id(id)).unwrap()
  411. }
  412. }
  413. impl<S: State> Index<RealNodeId> for RealDom<S> {
  414. type Output = Node<S>;
  415. fn index(&self, idx: RealNodeId) -> &Self::Output {
  416. self.tree.get(idx).unwrap()
  417. }
  418. }
  419. impl<S: State> IndexMut<ElementId> for RealDom<S> {
  420. fn index_mut(&mut self, id: ElementId) -> &mut Self::Output {
  421. self.tree.get_mut(self.element_to_node_id(id)).unwrap()
  422. }
  423. }
  424. impl<S: State> IndexMut<RealNodeId> for RealDom<S> {
  425. fn index_mut(&mut self, idx: RealNodeId) -> &mut Self::Output {
  426. self.tree.get_mut(idx).unwrap()
  427. }
  428. }