diff.rs 23 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598
  1. use std::any::Any;
  2. use crate::innerlude::Renderer;
  3. use crate::virtual_dom::VirtualDom;
  4. use crate::{Attribute, AttributeValue, TemplateNode};
  5. use crate::any_props::VComponentProps;
  6. use crate::component::Component;
  7. use crate::mutations::Mutation;
  8. use crate::nodes::{DynamicNode, Template, TemplateId};
  9. use crate::scopes::Scope;
  10. use crate::{
  11. any_props::AnyProps,
  12. arena::ElementId,
  13. bump_frame::BumpFrame,
  14. nodes::VNode,
  15. scopes::{ScopeId, ScopeState},
  16. };
  17. use fxhash::{FxHashMap, FxHashSet};
  18. use slab::Slab;
  19. pub struct DirtyScope {
  20. height: usize,
  21. id: ScopeId,
  22. }
  23. impl<'b> VirtualDom {
  24. pub fn diff_scope(&mut self, mutations: &mut Renderer<'b>, scope: ScopeId) {
  25. let scope_state = &mut self.scopes[scope.0];
  26. }
  27. pub fn diff_node(
  28. &mut self,
  29. muts: &mut Renderer<'b>,
  30. left_template: &'b VNode<'b>,
  31. right_template: &'b VNode<'b>,
  32. ) {
  33. if left_template.template.id != right_template.template.id {
  34. // do a light diff of the roots nodes.
  35. return;
  36. }
  37. for (_idx, (left_attr, right_attr)) in left_template
  38. .dynamic_attrs
  39. .iter()
  40. .zip(right_template.dynamic_attrs.iter())
  41. .enumerate()
  42. {
  43. debug_assert!(left_attr.name == right_attr.name);
  44. debug_assert!(left_attr.value == right_attr.value);
  45. // Move over the ID from the old to the new
  46. right_attr
  47. .mounted_element
  48. .set(left_attr.mounted_element.get());
  49. if left_attr.value != right_attr.value {
  50. let value = "todo!()";
  51. muts.push(Mutation::SetAttribute {
  52. id: left_attr.mounted_element.get(),
  53. name: left_attr.name,
  54. value,
  55. });
  56. }
  57. }
  58. for (idx, (left_node, right_node)) in left_template
  59. .dynamic_nodes
  60. .iter()
  61. .zip(right_template.dynamic_nodes.iter())
  62. .enumerate()
  63. {
  64. #[rustfmt::skip]
  65. match (left_node, right_node) {
  66. (DynamicNode::Component { props: lprops, .. }, DynamicNode::Component { static_props: is_static , props: rprops, .. }) => {
  67. let left_props = unsafe { &mut *lprops.get()};
  68. let right_props = unsafe { &mut *rprops.get()};
  69. // Ensure these two props are of the same component type
  70. match left_props.as_ptr() == right_props.as_ptr() {
  71. true => {
  72. //
  73. if *is_static {
  74. let props_are_same = unsafe { left_props.memoize(right_props) };
  75. if props_are_same{
  76. //
  77. } else {
  78. //
  79. }
  80. } else {
  81. }
  82. },
  83. false => todo!(),
  84. }
  85. //
  86. },
  87. // Make sure to drop the component properly
  88. (DynamicNode::Component { .. }, right) => {
  89. // remove all the component roots except for the first
  90. // replace the first with the new node
  91. let m = self.create_dynamic_node(muts, right_template, right, idx);
  92. todo!()
  93. },
  94. (DynamicNode::Text { id: lid, value: lvalue }, DynamicNode::Text { id: rid, value: rvalue }) => {
  95. rid.set(lid.get());
  96. if lvalue != rvalue {
  97. muts.push(Mutation::SetText {
  98. id: lid.get(),
  99. value: rvalue,
  100. });
  101. }
  102. },
  103. (DynamicNode::Text { id: lid, .. }, right) => {
  104. let m = self.create_dynamic_node(muts, right_template, right, idx);
  105. muts.push(Mutation::Replace { id: lid.get(), m });
  106. }
  107. (DynamicNode::Placeholder(_), DynamicNode::Placeholder(_)) => todo!(),
  108. (DynamicNode::Placeholder(_), _) => todo!(),
  109. (DynamicNode::Fragment (l), DynamicNode::Fragment (r)) => {
  110. // match (old, new) {
  111. // ([], []) => rp.set(lp.get()),
  112. // ([], _) => {
  113. // //
  114. // todo!()
  115. // },
  116. // (_, []) => {
  117. // todo!()
  118. // },
  119. // _ => {
  120. // let new_is_keyed = new[0].key.is_some();
  121. // let old_is_keyed = old[0].key.is_some();
  122. // debug_assert!(
  123. // new.iter().all(|n| n.key.is_some() == new_is_keyed),
  124. // "all siblings must be keyed or all siblings must be non-keyed"
  125. // );
  126. // debug_assert!(
  127. // old.iter().all(|o| o.key.is_some() == old_is_keyed),
  128. // "all siblings must be keyed or all siblings must be non-keyed"
  129. // );
  130. // if new_is_keyed && old_is_keyed {
  131. // self.diff_keyed_children(muts, old, new);
  132. // } else {
  133. // self.diff_non_keyed_children(muts, old, new);
  134. // }
  135. // }
  136. // }
  137. },
  138. // Make sure to drop all the fragment children properly
  139. (DynamicNode::Fragment { .. }, right) => todo!(),
  140. };
  141. }
  142. }
  143. // Diff children that are not keyed.
  144. //
  145. // The parent must be on the top of the change list stack when entering this
  146. // function:
  147. //
  148. // [... parent]
  149. //
  150. // the change list stack is in the same state when this function returns.
  151. fn diff_non_keyed_children(
  152. &mut self,
  153. muts: &mut Renderer<'b>,
  154. old: &'b [VNode<'b>],
  155. new: &'b [VNode<'b>],
  156. ) {
  157. use std::cmp::Ordering;
  158. // Handled these cases in `diff_children` before calling this function.
  159. debug_assert!(!new.is_empty());
  160. debug_assert!(!old.is_empty());
  161. match old.len().cmp(&new.len()) {
  162. Ordering::Greater => self.remove_nodes(muts, &old[new.len()..]),
  163. Ordering::Less => todo!(),
  164. // Ordering::Less => self.create_and_insert_after(&new[old.len()..], old.last().unwrap()),
  165. Ordering::Equal => {}
  166. }
  167. for (new, old) in new.iter().zip(old.iter()) {
  168. self.diff_node(muts, old, new);
  169. }
  170. }
  171. // Diffing "keyed" children.
  172. //
  173. // With keyed children, we care about whether we delete, move, or create nodes
  174. // versus mutate existing nodes in place. Presumably there is some sort of CSS
  175. // transition animation that makes the virtual DOM diffing algorithm
  176. // observable. By specifying keys for nodes, we know which virtual DOM nodes
  177. // must reuse (or not reuse) the same physical DOM nodes.
  178. //
  179. // This is loosely based on Inferno's keyed patching implementation. However, we
  180. // have to modify the algorithm since we are compiling the diff down into change
  181. // list instructions that will be executed later, rather than applying the
  182. // changes to the DOM directly as we compare virtual DOMs.
  183. //
  184. // https://github.com/infernojs/inferno/blob/36fd96/packages/inferno/src/DOM/patching.ts#L530-L739
  185. //
  186. // The stack is empty upon entry.
  187. fn diff_keyed_children(
  188. &mut self,
  189. muts: &mut Renderer<'b>,
  190. old: &'b [VNode<'b>],
  191. new: &'b [VNode<'b>],
  192. ) {
  193. // if cfg!(debug_assertions) {
  194. // let mut keys = fxhash::FxHashSet::default();
  195. // let mut assert_unique_keys = |children: &'b [VNode<'b>]| {
  196. // keys.clear();
  197. // for child in children {
  198. // let key = child.key;
  199. // debug_assert!(
  200. // key.is_some(),
  201. // "if any sibling is keyed, all siblings must be keyed"
  202. // );
  203. // keys.insert(key);
  204. // }
  205. // debug_assert_eq!(
  206. // children.len(),
  207. // keys.len(),
  208. // "keyed siblings must each have a unique key"
  209. // );
  210. // };
  211. // assert_unique_keys(old);
  212. // assert_unique_keys(new);
  213. // }
  214. // // First up, we diff all the nodes with the same key at the beginning of the
  215. // // children.
  216. // //
  217. // // `shared_prefix_count` is the count of how many nodes at the start of
  218. // // `new` and `old` share the same keys.
  219. // let (left_offset, right_offset) = match self.diff_keyed_ends(muts, old, new) {
  220. // Some(count) => count,
  221. // None => return,
  222. // };
  223. // // Ok, we now hopefully have a smaller range of children in the middle
  224. // // within which to re-order nodes with the same keys, remove old nodes with
  225. // // now-unused keys, and create new nodes with fresh keys.
  226. // let old_middle = &old[left_offset..(old.len() - right_offset)];
  227. // let new_middle = &new[left_offset..(new.len() - right_offset)];
  228. // debug_assert!(
  229. // !((old_middle.len() == new_middle.len()) && old_middle.is_empty()),
  230. // "keyed children must have the same number of children"
  231. // );
  232. // if new_middle.is_empty() {
  233. // // remove the old elements
  234. // self.remove_nodes(muts, old_middle);
  235. // } else if old_middle.is_empty() {
  236. // // there were no old elements, so just create the new elements
  237. // // we need to find the right "foothold" though - we shouldn't use the "append" at all
  238. // if left_offset == 0 {
  239. // // insert at the beginning of the old list
  240. // let foothold = &old[old.len() - right_offset];
  241. // self.create_and_insert_before(new_middle, foothold);
  242. // } else if right_offset == 0 {
  243. // // insert at the end the old list
  244. // let foothold = old.last().unwrap();
  245. // self.create_and_insert_after(new_middle, foothold);
  246. // } else {
  247. // // inserting in the middle
  248. // let foothold = &old[left_offset - 1];
  249. // self.create_and_insert_after(new_middle, foothold);
  250. // }
  251. // } else {
  252. // self.diff_keyed_middle(muts, old_middle, new_middle);
  253. // }
  254. }
  255. // /// Diff both ends of the children that share keys.
  256. // ///
  257. // /// Returns a left offset and right offset of that indicates a smaller section to pass onto the middle diffing.
  258. // ///
  259. // /// If there is no offset, then this function returns None and the diffing is complete.
  260. // fn diff_keyed_ends(
  261. // &mut self,
  262. // muts: &mut Renderer<'b>,
  263. // old: &'b [VNode<'b>],
  264. // new: &'b [VNode<'b>],
  265. // ) -> Option<(usize, usize)> {
  266. // let mut left_offset = 0;
  267. // for (old, new) in old.iter().zip(new.iter()) {
  268. // // abort early if we finally run into nodes with different keys
  269. // if old.key != new.key {
  270. // break;
  271. // }
  272. // self.diff_node(muts, old, new);
  273. // left_offset += 1;
  274. // }
  275. // // If that was all of the old children, then create and append the remaining
  276. // // new children and we're finished.
  277. // if left_offset == old.len() {
  278. // self.create_and_insert_after(&new[left_offset..], old.last().unwrap());
  279. // return None;
  280. // }
  281. // // And if that was all of the new children, then remove all of the remaining
  282. // // old children and we're finished.
  283. // if left_offset == new.len() {
  284. // self.remove_nodes(muts, &old[left_offset..]);
  285. // return None;
  286. // }
  287. // // if the shared prefix is less than either length, then we need to walk backwards
  288. // let mut right_offset = 0;
  289. // for (old, new) in old.iter().rev().zip(new.iter().rev()) {
  290. // // abort early if we finally run into nodes with different keys
  291. // if old.key != new.key {
  292. // break;
  293. // }
  294. // self.diff_node(muts, old, new);
  295. // right_offset += 1;
  296. // }
  297. // Some((left_offset, right_offset))
  298. // }
  299. // // The most-general, expensive code path for keyed children diffing.
  300. // //
  301. // // We find the longest subsequence within `old` of children that are relatively
  302. // // ordered the same way in `new` (via finding a longest-increasing-subsequence
  303. // // of the old child's index within `new`). The children that are elements of
  304. // // this subsequence will remain in place, minimizing the number of DOM moves we
  305. // // will have to do.
  306. // //
  307. // // Upon entry to this function, the change list stack must be empty.
  308. // //
  309. // // This function will load the appropriate nodes onto the stack and do diffing in place.
  310. // //
  311. // // Upon exit from this function, it will be restored to that same self.
  312. // #[allow(clippy::too_many_lines)]
  313. // fn diff_keyed_middle(
  314. // &mut self,
  315. // muts: &mut Renderer<'b>,
  316. // old: &'b [VNode<'b>],
  317. // new: &'b [VNode<'b>],
  318. // ) {
  319. // /*
  320. // 1. Map the old keys into a numerical ordering based on indices.
  321. // 2. Create a map of old key to its index
  322. // 3. Map each new key to the old key, carrying over the old index.
  323. // - IE if we have ABCD becomes BACD, our sequence would be 1,0,2,3
  324. // - if we have ABCD to ABDE, our sequence would be 0,1,3,MAX because E doesn't exist
  325. // now, we should have a list of integers that indicates where in the old list the new items map to.
  326. // 4. Compute the LIS of this list
  327. // - this indicates the longest list of new children that won't need to be moved.
  328. // 5. Identify which nodes need to be removed
  329. // 6. Identify which nodes will need to be diffed
  330. // 7. Going along each item in the new list, create it and insert it before the next closest item in the LIS.
  331. // - if the item already existed, just move it to the right place.
  332. // 8. Finally, generate instructions to remove any old children.
  333. // 9. Generate instructions to finally diff children that are the same between both
  334. // */
  335. // // 0. Debug sanity checks
  336. // // Should have already diffed the shared-key prefixes and suffixes.
  337. // debug_assert_ne!(new.first().map(|i| i.key), old.first().map(|i| i.key));
  338. // debug_assert_ne!(new.last().map(|i| i.key), old.last().map(|i| i.key));
  339. // // 1. Map the old keys into a numerical ordering based on indices.
  340. // // 2. Create a map of old key to its index
  341. // // IE if the keys were A B C, then we would have (A, 1) (B, 2) (C, 3).
  342. // let old_key_to_old_index = old
  343. // .iter()
  344. // .enumerate()
  345. // .map(|(i, o)| (o.key.unwrap(), i))
  346. // .collect::<FxHashMap<_, _>>();
  347. // let mut shared_keys = FxHashSet::default();
  348. // // 3. Map each new key to the old key, carrying over the old index.
  349. // let new_index_to_old_index = new
  350. // .iter()
  351. // .map(|node| {
  352. // let key = node.key.unwrap();
  353. // if let Some(&index) = old_key_to_old_index.get(&key) {
  354. // shared_keys.insert(key);
  355. // index
  356. // } else {
  357. // u32::MAX as usize
  358. // }
  359. // })
  360. // .collect::<Vec<_>>();
  361. // // If none of the old keys are reused by the new children, then we remove all the remaining old children and
  362. // // create the new children afresh.
  363. // if shared_keys.is_empty() {
  364. // if let Some(first_old) = old.get(0) {
  365. // self.remove_nodes(muts, &old[1..]);
  366. // let nodes_created = self.create_children(new);
  367. // self.replace_inner(first_old, nodes_created);
  368. // } else {
  369. // // I think this is wrong - why are we appending?
  370. // // only valid of the if there are no trailing elements
  371. // self.create_and_append_children(new);
  372. // }
  373. // return;
  374. // }
  375. // // remove any old children that are not shared
  376. // // todo: make this an iterator
  377. // for child in old {
  378. // let key = child.key.unwrap();
  379. // if !shared_keys.contains(&key) {
  380. // todo!("remove node");
  381. // // self.remove_nodes(muts, [child]);
  382. // }
  383. // }
  384. // // 4. Compute the LIS of this list
  385. // let mut lis_sequence = Vec::default();
  386. // lis_sequence.reserve(new_index_to_old_index.len());
  387. // let mut predecessors = vec![0; new_index_to_old_index.len()];
  388. // let mut starts = vec![0; new_index_to_old_index.len()];
  389. // longest_increasing_subsequence::lis_with(
  390. // &new_index_to_old_index,
  391. // &mut lis_sequence,
  392. // |a, b| a < b,
  393. // &mut predecessors,
  394. // &mut starts,
  395. // );
  396. // // the lis comes out backwards, I think. can't quite tell.
  397. // lis_sequence.sort_unstable();
  398. // // if a new node gets u32 max and is at the end, then it might be part of our LIS (because u32 max is a valid LIS)
  399. // if lis_sequence.last().map(|f| new_index_to_old_index[*f]) == Some(u32::MAX as usize) {
  400. // lis_sequence.pop();
  401. // }
  402. // for idx in &lis_sequence {
  403. // self.diff_node(muts, &old[new_index_to_old_index[*idx]], &new[*idx]);
  404. // }
  405. // let mut nodes_created = 0;
  406. // // add mount instruction for the first items not covered by the lis
  407. // let last = *lis_sequence.last().unwrap();
  408. // if last < (new.len() - 1) {
  409. // for (idx, new_node) in new[(last + 1)..].iter().enumerate() {
  410. // let new_idx = idx + last + 1;
  411. // let old_index = new_index_to_old_index[new_idx];
  412. // if old_index == u32::MAX as usize {
  413. // nodes_created += self.create(muts, new_node);
  414. // } else {
  415. // self.diff_node(muts, &old[old_index], new_node);
  416. // nodes_created += self.push_all_real_nodes(new_node);
  417. // }
  418. // }
  419. // self.mutations.insert_after(
  420. // self.find_last_element(&new[last]).unwrap(),
  421. // nodes_created as u32,
  422. // );
  423. // nodes_created = 0;
  424. // }
  425. // // for each spacing, generate a mount instruction
  426. // let mut lis_iter = lis_sequence.iter().rev();
  427. // let mut last = *lis_iter.next().unwrap();
  428. // for next in lis_iter {
  429. // if last - next > 1 {
  430. // for (idx, new_node) in new[(next + 1)..last].iter().enumerate() {
  431. // let new_idx = idx + next + 1;
  432. // let old_index = new_index_to_old_index[new_idx];
  433. // if old_index == u32::MAX as usize {
  434. // nodes_created += self.create(muts, new_node);
  435. // } else {
  436. // self.diff_node(muts, &old[old_index], new_node);
  437. // nodes_created += self.push_all_real_nodes(new_node);
  438. // }
  439. // }
  440. // self.mutations.insert_before(
  441. // self.find_first_element(&new[last]).unwrap(),
  442. // nodes_created as u32,
  443. // );
  444. // nodes_created = 0;
  445. // }
  446. // last = *next;
  447. // }
  448. // // add mount instruction for the last items not covered by the lis
  449. // let first_lis = *lis_sequence.first().unwrap();
  450. // if first_lis > 0 {
  451. // for (idx, new_node) in new[..first_lis].iter().enumerate() {
  452. // let old_index = new_index_to_old_index[idx];
  453. // if old_index == u32::MAX as usize {
  454. // nodes_created += self.create_node(new_node);
  455. // } else {
  456. // self.diff_node(muts, &old[old_index], new_node);
  457. // nodes_created += self.push_all_real_nodes(new_node);
  458. // }
  459. // }
  460. // self.mutations.insert_before(
  461. // self.find_first_element(&new[first_lis]).unwrap(),
  462. // nodes_created as u32,
  463. // );
  464. // }
  465. // }
  466. /// Remove these nodes from the dom
  467. /// Wont generate mutations for the inner nodes
  468. fn remove_nodes(&mut self, muts: &mut Renderer<'b>, nodes: &'b [VNode<'b>]) {
  469. //
  470. }
  471. }
  472. // /// Lightly diff the two templates and apply their edits to the dom
  473. // fn light_diff_template_roots(
  474. // &'a mut self,
  475. // mutations: &mut Vec<Mutation<'a>>,
  476. // left: &VNode,
  477. // right: &VNode,
  478. // ) {
  479. // match right.template.roots.len().cmp(&left.template.roots.len()) {
  480. // std::cmp::Ordering::Less => {
  481. // // remove the old nodes at the end
  482. // }
  483. // std::cmp::Ordering::Greater => {
  484. // // add the extra nodes.
  485. // }
  486. // std::cmp::Ordering::Equal => {}
  487. // }
  488. // for (left_node, right_node) in left.template.roots.iter().zip(right.template.roots.iter()) {
  489. // if let (TemplateNode::Dynamic(lidx), TemplateNode::Dynamic(ridx)) =
  490. // (left_node, right_node)
  491. // {
  492. // let left_node = &left.dynamic_nodes[*lidx];
  493. // let right_node = &right.dynamic_nodes[*ridx];
  494. // // match (left_node, right_node) {
  495. // // (
  496. // // DynamicNode::Component {
  497. // // name,
  498. // // can_memoize,
  499. // // props,
  500. // // },
  501. // // DynamicNode::Component {
  502. // // name,
  503. // // can_memoize,
  504. // // props,
  505. // // },
  506. // // ) => todo!(),
  507. // // (
  508. // // DynamicNode::Component {
  509. // // name,
  510. // // can_memoize,
  511. // // props,
  512. // // },
  513. // // DynamicNode::Fragment { children },
  514. // // ) => todo!(),
  515. // // (
  516. // // DynamicNode::Fragment { children },
  517. // // DynamicNode::Component {
  518. // // name,
  519. // // can_memoize,
  520. // // props,
  521. // // },
  522. // // ) => todo!(),
  523. // // _ => {}
  524. // // }
  525. // }
  526. // }
  527. // }