mutations.rs 4.8 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185
  1. use fxhash::FxHashSet;
  2. use crate::{arena::ElementId, ScopeId, Template};
  3. /// A container for all the relevant steps to modify the Real DOM
  4. ///
  5. /// This method returns "mutations" - IE the necessary changes to get the RealDOM to match the VirtualDOM. It also
  6. /// includes a list of NodeRefs that need to be applied and effects that need to be triggered after the RealDOM has
  7. /// applied the edits.
  8. ///
  9. /// Mutations are the only link between the RealDOM and the VirtualDOM.
  10. #[derive(Debug, Default)]
  11. #[must_use = "not handling edits can lead to visual inconsistencies in UI"]
  12. pub struct Mutations<'a> {
  13. /// The ID of the subtree that these edits are targetting
  14. pub subtree: usize,
  15. /// The list of Scopes that were diffed, created, and removed during the Diff process.
  16. pub dirty_scopes: FxHashSet<ScopeId>,
  17. /// Any templates encountered while diffing the DOM.
  18. ///
  19. /// These must be loaded into a cache before applying the edits
  20. pub templates: Vec<Template<'a>>,
  21. /// Any mutations required to patch the renderer to match the layout of the VirtualDom
  22. pub edits: Vec<Mutation<'a>>,
  23. }
  24. impl<'a> Mutations<'a> {
  25. /// Rewrites IDs to just be "template", so you can compare the mutations
  26. ///
  27. /// Used really only for testing
  28. pub fn santize(mut self) -> Self {
  29. todo!()
  30. // self.templates
  31. // .iter_mut()
  32. // .chain(self.dom_edits.iter_mut())
  33. // .for_each(|edit| match edit {
  34. // Mutation::LoadTemplate { name, .. } => *name = "template",
  35. // Mutation::SaveTemplate { name, .. } => *name = "template",
  36. // _ => {}
  37. // });
  38. // self
  39. }
  40. /// Push a new mutation into the dom_edits list
  41. pub(crate) fn push(&mut self, mutation: Mutation<'static>) {
  42. self.edits.push(mutation)
  43. }
  44. }
  45. /*
  46. each subtree has its own numbering scheme
  47. */
  48. #[cfg_attr(
  49. feature = "serialize",
  50. derive(serde::Serialize, serde::Deserialize),
  51. serde(tag = "type")
  52. )]
  53. #[derive(Debug, PartialEq, Eq)]
  54. pub enum Mutation<'a> {
  55. AssignId {
  56. path: &'static [u8],
  57. id: ElementId,
  58. },
  59. CreatePlaceholder {
  60. id: ElementId,
  61. },
  62. CreateTextNode {
  63. value: &'a str,
  64. id: ElementId,
  65. },
  66. HydrateText {
  67. path: &'static [u8],
  68. value: &'a str,
  69. id: ElementId,
  70. },
  71. LoadTemplate {
  72. name: &'static str,
  73. index: usize,
  74. id: ElementId,
  75. },
  76. // Take the current element and replace it with the element with the given id.
  77. ReplaceWith {
  78. id: ElementId,
  79. m: usize,
  80. },
  81. ReplacePlaceholder {
  82. path: &'static [u8],
  83. m: usize,
  84. },
  85. /// Insert a number of nodes after a given node.
  86. InsertAfter {
  87. /// The ID of the node to insert after.
  88. id: ElementId,
  89. /// The ids of the nodes to insert after the target node.
  90. m: usize,
  91. },
  92. /// Insert a number of nodes before a given node.
  93. InsertBefore {
  94. /// The ID of the node to insert before.
  95. id: ElementId,
  96. /// The ids of the nodes to insert before the target node.
  97. m: usize,
  98. },
  99. /// Set the value of a node's attribute.
  100. SetAttribute {
  101. /// The name of the attribute to set.
  102. name: &'a str,
  103. /// The value of the attribute.
  104. value: &'a str,
  105. /// The ID of the node to set the attribute of.
  106. id: ElementId,
  107. /// The (optional) namespace of the attribute.
  108. /// For instance, "style" is in the "style" namespace.
  109. ns: Option<&'a str>,
  110. },
  111. /// Set the value of a node's attribute.
  112. SetBoolAttribute {
  113. /// The name of the attribute to set.
  114. name: &'a str,
  115. /// The value of the attribute.
  116. value: bool,
  117. /// The ID of the node to set the attribute of.
  118. id: ElementId,
  119. },
  120. /// Set the textcontent of a node.
  121. SetText {
  122. /// The textcontent of the node
  123. value: &'a str,
  124. /// The ID of the node to set the textcontent of.
  125. id: ElementId,
  126. },
  127. /// Create a new Event Listener.
  128. NewEventListener {
  129. /// The name of the event to listen for.
  130. name: &'a str,
  131. /// The ID of the node to attach the listener to.
  132. scope: ScopeId,
  133. /// The ID of the node to attach the listener to.
  134. id: ElementId,
  135. },
  136. /// Remove an existing Event Listener.
  137. RemoveEventListener {
  138. /// The name of the event to remove.
  139. name: &'a str,
  140. /// The ID of the node to remove.
  141. id: ElementId,
  142. },
  143. /// Remove a particular node from the DOM
  144. Remove {
  145. /// The ID of the node to remove.
  146. id: ElementId,
  147. },
  148. /// Push the given root node onto our stack.
  149. PushRoot {
  150. /// The ID of the root node to push.
  151. id: ElementId,
  152. },
  153. }