diff_stack.rs 3.2 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117
  1. use crate::innerlude::*;
  2. use smallvec::{smallvec, SmallVec};
  3. /// The stack instructions we use to diff and create new nodes.
  4. #[derive(Debug)]
  5. pub(crate) enum DiffInstruction<'a> {
  6. Diff {
  7. old: &'a VNode<'a>,
  8. new: &'a VNode<'a>,
  9. },
  10. Create {
  11. node: &'a VNode<'a>,
  12. },
  13. /// pushes the node elements onto the stack for use in mount
  14. PrepareMove {
  15. node: &'a VNode<'a>,
  16. },
  17. Mount {
  18. and: MountType<'a>,
  19. },
  20. PopScope,
  21. }
  22. #[derive(Debug, Clone, Copy)]
  23. pub enum MountType<'a> {
  24. Absorb,
  25. Append,
  26. Replace { old: &'a VNode<'a> },
  27. ReplaceByElementId { el: Option<ElementId> },
  28. InsertAfter { other_node: &'a VNode<'a> },
  29. InsertBefore { other_node: &'a VNode<'a> },
  30. }
  31. pub(crate) struct DiffStack<'bump> {
  32. instructions: Vec<DiffInstruction<'bump>>,
  33. nodes_created_stack: SmallVec<[usize; 10]>,
  34. pub scope_stack: SmallVec<[ScopeId; 5]>,
  35. pub element_id_stack: SmallVec<[ElementId; 5]>,
  36. }
  37. impl<'bump> DiffStack<'bump> {
  38. pub fn new() -> Self {
  39. Self {
  40. instructions: Vec::with_capacity(1000),
  41. nodes_created_stack: smallvec![],
  42. scope_stack: smallvec![],
  43. element_id_stack: smallvec![],
  44. }
  45. }
  46. pub fn is_empty(&self) -> bool {
  47. self.instructions.is_empty()
  48. }
  49. pub fn pop(&mut self) -> Option<DiffInstruction<'bump>> {
  50. self.instructions.pop()
  51. }
  52. pub fn pop_off_scope(&mut self) {
  53. self.scope_stack.pop();
  54. }
  55. pub fn push(&mut self, instruction: DiffInstruction<'bump>) {
  56. self.instructions.push(instruction)
  57. }
  58. pub fn create_children(&mut self, children: &'bump [VNode<'bump>], and: MountType<'bump>) {
  59. self.nodes_created_stack.push(0);
  60. self.instructions.push(DiffInstruction::Mount { and });
  61. for child in children.into_iter().rev() {
  62. self.instructions
  63. .push(DiffInstruction::Create { node: child });
  64. }
  65. }
  66. pub fn push_nodes_created(&mut self, count: usize) {
  67. self.nodes_created_stack.push(count);
  68. }
  69. pub fn push_element_id(&mut self, id: ElementId) {
  70. self.element_id_stack.push(id);
  71. }
  72. pub fn create_node(&mut self, node: &'bump VNode<'bump>, and: MountType<'bump>) {
  73. self.nodes_created_stack.push(0);
  74. self.instructions.push(DiffInstruction::Mount { and });
  75. self.instructions.push(DiffInstruction::Create { node });
  76. }
  77. pub fn add_child_count(&mut self, count: usize) {
  78. *self.nodes_created_stack.last_mut().unwrap() += count;
  79. }
  80. pub fn pop_nodes_created(&mut self) -> usize {
  81. self.nodes_created_stack.pop().unwrap()
  82. }
  83. pub fn current_scope(&self) -> Option<ScopeId> {
  84. self.scope_stack.last().map(|f| f.clone())
  85. }
  86. pub fn create_component(&mut self, idx: ScopeId, node: &'bump VNode<'bump>) {
  87. // Push the new scope onto the stack
  88. self.scope_stack.push(idx);
  89. self.instructions.push(DiffInstruction::PopScope);
  90. // Run the creation algorithm with this scope on the stack
  91. // ?? I think we treat components as framgnets??
  92. self.instructions.push(DiffInstruction::Create { node });
  93. }
  94. }