186 lines
4.8 KiB
Rust
186 lines
4.8 KiB
Rust
use fxhash::FxHashSet;
|
|
|
|
use crate::{arena::ElementId, ScopeId, Template};
|
|
|
|
/// A container for all the relevant steps to modify the Real DOM
|
|
///
|
|
/// This method returns "mutations" - IE the necessary changes to get the RealDOM to match the VirtualDOM. It also
|
|
/// includes a list of NodeRefs that need to be applied and effects that need to be triggered after the RealDOM has
|
|
/// applied the edits.
|
|
///
|
|
/// Mutations are the only link between the RealDOM and the VirtualDOM.
|
|
#[derive(Debug, Default)]
|
|
#[must_use = "not handling edits can lead to visual inconsistencies in UI"]
|
|
pub struct Mutations<'a> {
|
|
/// The ID of the subtree that these edits are targetting
|
|
pub subtree: usize,
|
|
|
|
/// The list of Scopes that were diffed, created, and removed during the Diff process.
|
|
pub dirty_scopes: FxHashSet<ScopeId>,
|
|
|
|
/// Any templates encountered while diffing the DOM.
|
|
///
|
|
/// These must be loaded into a cache before applying the edits
|
|
pub templates: Vec<Template<'a>>,
|
|
|
|
/// Any mutations required to patch the renderer to match the layout of the VirtualDom
|
|
pub edits: Vec<Mutation<'a>>,
|
|
}
|
|
|
|
impl<'a> Mutations<'a> {
|
|
/// Rewrites IDs to just be "template", so you can compare the mutations
|
|
///
|
|
/// Used really only for testing
|
|
pub fn santize(mut self) -> Self {
|
|
todo!()
|
|
// self.templates
|
|
// .iter_mut()
|
|
// .chain(self.dom_edits.iter_mut())
|
|
// .for_each(|edit| match edit {
|
|
// Mutation::LoadTemplate { name, .. } => *name = "template",
|
|
// Mutation::SaveTemplate { name, .. } => *name = "template",
|
|
// _ => {}
|
|
// });
|
|
|
|
// self
|
|
}
|
|
|
|
/// Push a new mutation into the dom_edits list
|
|
pub(crate) fn push(&mut self, mutation: Mutation<'static>) {
|
|
self.edits.push(mutation)
|
|
}
|
|
}
|
|
|
|
/*
|
|
each subtree has its own numbering scheme
|
|
*/
|
|
|
|
#[cfg_attr(
|
|
feature = "serialize",
|
|
derive(serde::Serialize, serde::Deserialize),
|
|
serde(tag = "type")
|
|
)]
|
|
#[derive(Debug, PartialEq, Eq)]
|
|
pub enum Mutation<'a> {
|
|
AssignId {
|
|
path: &'static [u8],
|
|
id: ElementId,
|
|
},
|
|
|
|
CreatePlaceholder {
|
|
id: ElementId,
|
|
},
|
|
CreateTextNode {
|
|
value: &'a str,
|
|
id: ElementId,
|
|
},
|
|
HydrateText {
|
|
path: &'static [u8],
|
|
value: &'a str,
|
|
id: ElementId,
|
|
},
|
|
LoadTemplate {
|
|
name: &'static str,
|
|
index: usize,
|
|
id: ElementId,
|
|
},
|
|
|
|
// Take the current element and replace it with the element with the given id.
|
|
ReplaceWith {
|
|
id: ElementId,
|
|
m: usize,
|
|
},
|
|
|
|
ReplacePlaceholder {
|
|
path: &'static [u8],
|
|
m: usize,
|
|
},
|
|
|
|
/// Insert a number of nodes after a given node.
|
|
InsertAfter {
|
|
/// The ID of the node to insert after.
|
|
id: ElementId,
|
|
|
|
/// The ids of the nodes to insert after the target node.
|
|
m: usize,
|
|
},
|
|
|
|
/// Insert a number of nodes before a given node.
|
|
InsertBefore {
|
|
/// The ID of the node to insert before.
|
|
id: ElementId,
|
|
|
|
/// The ids of the nodes to insert before the target node.
|
|
m: usize,
|
|
},
|
|
|
|
/// Set the value of a node's attribute.
|
|
SetAttribute {
|
|
/// The name of the attribute to set.
|
|
name: &'a str,
|
|
/// The value of the attribute.
|
|
value: &'a str,
|
|
|
|
/// The ID of the node to set the attribute of.
|
|
id: ElementId,
|
|
|
|
/// The (optional) namespace of the attribute.
|
|
/// For instance, "style" is in the "style" namespace.
|
|
ns: Option<&'a str>,
|
|
},
|
|
|
|
/// Set the value of a node's attribute.
|
|
SetBoolAttribute {
|
|
/// The name of the attribute to set.
|
|
name: &'a str,
|
|
|
|
/// The value of the attribute.
|
|
value: bool,
|
|
|
|
/// The ID of the node to set the attribute of.
|
|
id: ElementId,
|
|
},
|
|
|
|
/// Set the textcontent of a node.
|
|
SetText {
|
|
/// The textcontent of the node
|
|
value: &'a str,
|
|
|
|
/// The ID of the node to set the textcontent of.
|
|
id: ElementId,
|
|
},
|
|
|
|
/// Create a new Event Listener.
|
|
NewEventListener {
|
|
/// The name of the event to listen for.
|
|
name: &'a str,
|
|
|
|
/// The ID of the node to attach the listener to.
|
|
scope: ScopeId,
|
|
|
|
/// The ID of the node to attach the listener to.
|
|
id: ElementId,
|
|
},
|
|
|
|
/// Remove an existing Event Listener.
|
|
RemoveEventListener {
|
|
/// The name of the event to remove.
|
|
name: &'a str,
|
|
|
|
/// The ID of the node to remove.
|
|
id: ElementId,
|
|
},
|
|
|
|
/// Remove a particular node from the DOM
|
|
Remove {
|
|
/// The ID of the node to remove.
|
|
id: ElementId,
|
|
},
|
|
|
|
/// Push the given root node onto our stack.
|
|
PushRoot {
|
|
/// The ID of the root node to push.
|
|
id: ElementId,
|
|
},
|
|
}
|