diff_stack.rs 3.1 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115
  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. }
  36. impl<'bump> DiffStack<'bump> {
  37. pub fn new() -> Self {
  38. Self {
  39. instructions: Vec::with_capacity(1000),
  40. nodes_created_stack: smallvec![],
  41. scope_stack: smallvec![],
  42. }
  43. }
  44. pub fn is_empty(&self) -> bool {
  45. self.instructions.is_empty()
  46. }
  47. pub fn pop(&mut self) -> Option<DiffInstruction<'bump>> {
  48. self.instructions.pop()
  49. }
  50. pub fn pop_off_scope(&mut self) {
  51. self.scope_stack.pop();
  52. }
  53. pub fn pop_scope(&mut self) -> Option<ScopeId> {
  54. self.scope_stack.pop()
  55. }
  56. pub fn push(&mut self, instruction: DiffInstruction<'bump>) {
  57. self.instructions.push(instruction)
  58. }
  59. pub fn create_children(&mut self, children: &'bump [VNode<'bump>], and: MountType<'bump>) {
  60. self.nodes_created_stack.push(0);
  61. self.instructions.push(DiffInstruction::Mount { and });
  62. for child in children.into_iter().rev() {
  63. self.instructions
  64. .push(DiffInstruction::Create { node: child });
  65. }
  66. }
  67. pub fn push_nodes_created(&mut self, count: usize) {
  68. self.nodes_created_stack.push(count);
  69. }
  70. pub fn create_node(&mut self, node: &'bump VNode<'bump>, and: MountType<'bump>) {
  71. self.nodes_created_stack.push(0);
  72. self.instructions.push(DiffInstruction::Mount { and });
  73. self.instructions.push(DiffInstruction::Create { node });
  74. }
  75. pub fn add_child_count(&mut self, count: usize) {
  76. *self.nodes_created_stack.last_mut().unwrap() += count;
  77. }
  78. pub fn pop_nodes_created(&mut self) -> usize {
  79. self.nodes_created_stack.pop().unwrap()
  80. }
  81. pub fn current_scope(&self) -> Option<ScopeId> {
  82. self.scope_stack.last().map(|f| f.clone())
  83. }
  84. pub fn create_component(&mut self, idx: ScopeId, node: &'bump VNode<'bump>) {
  85. // Push the new scope onto the stack
  86. self.scope_stack.push(idx);
  87. self.instructions.push(DiffInstruction::PopScope);
  88. // Run the creation algorithm with this scope on the stack
  89. // ?? I think we treat components as framgnets??
  90. self.instructions.push(DiffInstruction::Create { node });
  91. }
  92. }