Refactor Mutations and simplify Templates (#578)
* update mutations to be path based rather than renderer integrated
This commit is contained in:
1 parent
020c4bf0f8
commit
3b7b503333
44 files changed
+2643
-3134
No files matched your search
+102
-213
@@ -44,57 +44,53 @@ impl Debug for Mutations<'_> {
|
||||
serde(tag = "type")
|
||||
)]
|
||||
pub enum DomEdit<'bump> {
|
||||
/// Push the given root node onto our stack.
|
||||
PushRoot {
|
||||
/// The ID of the root node to push.
|
||||
root: u64,
|
||||
},
|
||||
|
||||
/// Pop the topmost node from our stack and append them to the node
|
||||
/// at the top of the stack.
|
||||
AppendChildren {
|
||||
/// How many nodes should be popped from the stack.
|
||||
/// The node remaining on the stack will be the target for the append.
|
||||
many: u32,
|
||||
/// The parent to append nodes to.
|
||||
root: Option<u64>,
|
||||
|
||||
/// The ids of the children to append.
|
||||
children: Vec<u64>,
|
||||
},
|
||||
|
||||
/// Replace a given (single) node with a handful of nodes currently on the stack.
|
||||
ReplaceWith {
|
||||
/// The ID of the node to be replaced.
|
||||
root: u64,
|
||||
root: Option<u64>,
|
||||
|
||||
/// How many nodes should be popped from the stack to replace the target node.
|
||||
m: u32,
|
||||
/// The ids of the nodes to replace the root with.
|
||||
nodes: Vec<u64>,
|
||||
},
|
||||
|
||||
/// Insert a number of nodes after a given node.
|
||||
InsertAfter {
|
||||
/// The ID of the node to insert after.
|
||||
root: u64,
|
||||
root: Option<u64>,
|
||||
|
||||
/// How many nodes should be popped from the stack to insert after the target node.
|
||||
n: u32,
|
||||
/// The ids of the nodes to insert after the target node.
|
||||
nodes: Vec<u64>,
|
||||
},
|
||||
|
||||
/// Insert a number of nodes before a given node.
|
||||
InsertBefore {
|
||||
/// The ID of the node to insert before.
|
||||
root: u64,
|
||||
root: Option<u64>,
|
||||
|
||||
/// How many nodes should be popped from the stack to insert before the target node.
|
||||
n: u32,
|
||||
/// The ids of the nodes to insert before the target node.
|
||||
nodes: Vec<u64>,
|
||||
},
|
||||
|
||||
/// Remove a particular node from the DOM
|
||||
Remove {
|
||||
/// The ID of the node to remove.
|
||||
root: u64,
|
||||
root: Option<u64>,
|
||||
},
|
||||
|
||||
/// Create a new purely-text node
|
||||
CreateTextNode {
|
||||
/// The ID the new node should have.
|
||||
root: u64,
|
||||
root: Option<u64>,
|
||||
|
||||
/// The textcontent of the node
|
||||
text: &'bump str,
|
||||
@@ -103,82 +99,35 @@ pub enum DomEdit<'bump> {
|
||||
/// Create a new purely-element node
|
||||
CreateElement {
|
||||
/// The ID the new node should have.
|
||||
root: u64,
|
||||
root: Option<u64>,
|
||||
|
||||
/// The tagname of the node
|
||||
tag: &'bump str,
|
||||
|
||||
/// The number of children nodes that will follow this message.
|
||||
children: u32,
|
||||
},
|
||||
|
||||
/// Create a new purely-comment node with a given namespace
|
||||
CreateElementNs {
|
||||
/// The ID the new node should have.
|
||||
root: u64,
|
||||
root: Option<u64>,
|
||||
|
||||
/// The namespace of the node
|
||||
tag: &'bump str,
|
||||
|
||||
/// The namespace of the node (like `SVG`)
|
||||
ns: &'static str,
|
||||
|
||||
/// The number of children nodes that will follow this message.
|
||||
children: u32,
|
||||
},
|
||||
|
||||
/// Create a new placeholder node.
|
||||
/// In most implementations, this will either be a hidden div or a comment node.
|
||||
CreatePlaceholder {
|
||||
/// The ID the new node should have.
|
||||
root: u64,
|
||||
},
|
||||
|
||||
/// Create a new purely-text node in a template
|
||||
CreateTextNodeTemplate {
|
||||
/// The ID the new node should have.
|
||||
root: u64,
|
||||
|
||||
/// The textcontent of the noden
|
||||
text: &'bump str,
|
||||
|
||||
/// If the id of the node must be kept in the refrences
|
||||
locally_static: bool,
|
||||
},
|
||||
|
||||
/// Create a new purely-element node in a template
|
||||
CreateElementTemplate {
|
||||
/// The ID the new node should have.
|
||||
root: u64,
|
||||
|
||||
/// The tagname of the node
|
||||
tag: &'bump str,
|
||||
|
||||
/// If the id of the node must be kept in the refrences
|
||||
locally_static: bool,
|
||||
|
||||
/// If any children of this node must be kept in the references
|
||||
fully_static: bool,
|
||||
},
|
||||
|
||||
/// Create a new purely-comment node with a given namespace in a template
|
||||
CreateElementNsTemplate {
|
||||
/// The ID the new node should have.
|
||||
root: u64,
|
||||
|
||||
/// The namespace of the node
|
||||
tag: &'bump str,
|
||||
|
||||
/// The namespace of the node (like `SVG`)
|
||||
ns: &'static str,
|
||||
|
||||
/// If the id of the node must be kept in the refrences
|
||||
locally_static: bool,
|
||||
|
||||
/// If any children of this node must be kept in the references
|
||||
fully_static: bool,
|
||||
},
|
||||
|
||||
/// Create a new placeholder node.
|
||||
/// In most implementations, this will either be a hidden div or a comment node. in a template
|
||||
/// Always both locally and fully static
|
||||
CreatePlaceholderTemplate {
|
||||
/// The ID the new node should have.
|
||||
root: u64,
|
||||
root: Option<u64>,
|
||||
},
|
||||
|
||||
/// Create a new Event Listener.
|
||||
@@ -190,13 +139,13 @@ pub enum DomEdit<'bump> {
|
||||
scope: ScopeId,
|
||||
|
||||
/// The ID of the node to attach the listener to.
|
||||
root: u64,
|
||||
root: Option<u64>,
|
||||
},
|
||||
|
||||
/// Remove an existing Event Listener.
|
||||
RemoveEventListener {
|
||||
/// The ID of the node to remove.
|
||||
root: u64,
|
||||
root: Option<u64>,
|
||||
|
||||
/// The name of the event to remove.
|
||||
event: &'static str,
|
||||
@@ -205,7 +154,7 @@ pub enum DomEdit<'bump> {
|
||||
/// Set the textcontent of a node.
|
||||
SetText {
|
||||
/// The ID of the node to set the textcontent of.
|
||||
root: u64,
|
||||
root: Option<u64>,
|
||||
|
||||
/// The textcontent of the node
|
||||
text: &'bump str,
|
||||
@@ -214,7 +163,7 @@ pub enum DomEdit<'bump> {
|
||||
/// Set the value of a node's attribute.
|
||||
SetAttribute {
|
||||
/// The ID of the node to set the attribute of.
|
||||
root: u64,
|
||||
root: Option<u64>,
|
||||
|
||||
/// The name of the attribute to set.
|
||||
field: &'static str,
|
||||
@@ -231,7 +180,7 @@ pub enum DomEdit<'bump> {
|
||||
/// Remove an attribute from a node.
|
||||
RemoveAttribute {
|
||||
/// The ID of the node to remove.
|
||||
root: u64,
|
||||
root: Option<u64>,
|
||||
|
||||
/// The name of the attribute to remove.
|
||||
name: &'static str,
|
||||
@@ -240,45 +189,50 @@ pub enum DomEdit<'bump> {
|
||||
ns: Option<&'bump str>,
|
||||
},
|
||||
|
||||
/// Manually pop a root node from the stack.
|
||||
PopRoot {},
|
||||
/// Clones a node.
|
||||
CloneNode {
|
||||
/// The ID of the node to clone.
|
||||
id: Option<u64>,
|
||||
|
||||
/// Enter a TemplateRef tree
|
||||
EnterTemplateRef {
|
||||
/// The ID of the node to enter.
|
||||
root: u64,
|
||||
/// The ID of the new node.
|
||||
new_id: u64,
|
||||
},
|
||||
|
||||
/// Exit a TemplateRef tree
|
||||
ExitTemplateRef {},
|
||||
/// Clones the children of a node. (allows cloning fragments)
|
||||
CloneNodeChildren {
|
||||
/// The ID of the node to clone.
|
||||
id: Option<u64>,
|
||||
|
||||
/// Create a refrence to a template node.
|
||||
CreateTemplateRef {
|
||||
/// The ID of the new template refrence.
|
||||
id: u64,
|
||||
|
||||
/// The ID of the template the node is refrencing.
|
||||
template_id: u64,
|
||||
/// The ID of the new node.
|
||||
new_ids: Vec<u64>,
|
||||
},
|
||||
|
||||
/// Create a new templete.
|
||||
/// IMPORTANT: When adding nodes to a templete, id's will reset to zero, so they must be allocated on a different stack.
|
||||
/// It is recommended to use Cow<NativeNode>.
|
||||
CreateTemplate {
|
||||
/// The ID of the new template.
|
||||
/// Navigates to the last node to the first child of the current node.
|
||||
FirstChild {},
|
||||
|
||||
/// Navigates to the last node to the last child of the current node.
|
||||
NextSibling {},
|
||||
|
||||
/// Navigates to the last node to the parent of the current node.
|
||||
ParentNode {},
|
||||
|
||||
/// Stores the last node with a new id.
|
||||
StoreWithId {
|
||||
/// The ID of the node to store.
|
||||
id: u64,
|
||||
},
|
||||
|
||||
/// Finish a templete
|
||||
FinishTemplate {
|
||||
/// The number of root nodes in the template
|
||||
len: u32,
|
||||
/// Manually set the last node.
|
||||
SetLastNode {
|
||||
/// The ID to set the last node to.
|
||||
id: u64,
|
||||
},
|
||||
}
|
||||
|
||||
use rustc_hash::FxHashSet;
|
||||
use DomEdit::*;
|
||||
|
||||
#[allow(unused)]
|
||||
impl<'a> Mutations<'a> {
|
||||
pub(crate) fn new() -> Self {
|
||||
Self {
|
||||
@@ -288,44 +242,29 @@ impl<'a> Mutations<'a> {
|
||||
}
|
||||
}
|
||||
|
||||
// Navigation
|
||||
pub(crate) fn push_root(&mut self, root: impl Into<u64>) {
|
||||
let id = root.into();
|
||||
self.edits.push(PushRoot { root: id });
|
||||
pub(crate) fn replace_with(&mut self, root: Option<u64>, nodes: Vec<u64>) {
|
||||
self.edits.push(ReplaceWith { nodes, root });
|
||||
}
|
||||
|
||||
// Navigation
|
||||
pub(crate) fn pop_root(&mut self) {
|
||||
self.edits.push(PopRoot {});
|
||||
pub(crate) fn insert_after(&mut self, root: Option<u64>, nodes: Vec<u64>) {
|
||||
self.edits.push(InsertAfter { nodes, root });
|
||||
}
|
||||
|
||||
pub(crate) fn replace_with(&mut self, root: impl Into<u64>, m: u32) {
|
||||
let root = root.into();
|
||||
self.edits.push(ReplaceWith { m, root });
|
||||
pub(crate) fn insert_before(&mut self, root: Option<u64>, nodes: Vec<u64>) {
|
||||
self.edits.push(InsertBefore { nodes, root });
|
||||
}
|
||||
|
||||
pub(crate) fn insert_after(&mut self, root: impl Into<u64>, n: u32) {
|
||||
let root = root.into();
|
||||
self.edits.push(InsertAfter { n, root });
|
||||
}
|
||||
|
||||
pub(crate) fn insert_before(&mut self, root: impl Into<u64>, n: u32) {
|
||||
let root = root.into();
|
||||
self.edits.push(InsertBefore { n, root });
|
||||
}
|
||||
|
||||
pub(crate) fn append_children(&mut self, n: u32) {
|
||||
self.edits.push(AppendChildren { many: n });
|
||||
pub(crate) fn append_children(&mut self, root: Option<u64>, children: Vec<u64>) {
|
||||
self.edits.push(AppendChildren { root, children });
|
||||
}
|
||||
|
||||
// Remove Nodes from the dom
|
||||
pub(crate) fn remove(&mut self, id: impl Into<u64>) {
|
||||
self.edits.push(Remove { root: id.into() });
|
||||
pub(crate) fn remove(&mut self, id: Option<u64>) {
|
||||
self.edits.push(Remove { root: id });
|
||||
}
|
||||
|
||||
// Create
|
||||
pub(crate) fn create_text_node(&mut self, text: &'a str, id: impl Into<u64>) {
|
||||
let id = id.into();
|
||||
pub(crate) fn create_text_node(&mut self, text: &'a str, id: Option<u64>) {
|
||||
self.edits.push(CreateTextNode { text, root: id });
|
||||
}
|
||||
|
||||
@@ -333,66 +272,27 @@ impl<'a> Mutations<'a> {
|
||||
&mut self,
|
||||
tag: &'static str,
|
||||
ns: Option<&'static str>,
|
||||
id: impl Into<u64>,
|
||||
id: Option<u64>,
|
||||
children: u32,
|
||||
) {
|
||||
let id = id.into();
|
||||
match ns {
|
||||
Some(ns) => self.edits.push(CreateElementNs { root: id, ns, tag }),
|
||||
None => self.edits.push(CreateElement { root: id, tag }),
|
||||
}
|
||||
}
|
||||
|
||||
// placeholders are nodes that don't get rendered but still exist as an "anchor" in the real dom
|
||||
pub(crate) fn create_placeholder(&mut self, id: impl Into<u64>) {
|
||||
let id = id.into();
|
||||
self.edits.push(CreatePlaceholder { root: id });
|
||||
}
|
||||
|
||||
// Create
|
||||
pub(crate) fn create_text_node_template(
|
||||
&mut self,
|
||||
text: &'a str,
|
||||
id: impl Into<u64>,
|
||||
locally_static: bool,
|
||||
) {
|
||||
let id = id.into();
|
||||
self.edits.push(CreateTextNodeTemplate {
|
||||
text,
|
||||
root: id,
|
||||
locally_static,
|
||||
});
|
||||
}
|
||||
|
||||
pub(crate) fn create_element_template(
|
||||
&mut self,
|
||||
tag: &'static str,
|
||||
ns: Option<&'static str>,
|
||||
id: impl Into<u64>,
|
||||
locally_static: bool,
|
||||
fully_static: bool,
|
||||
) {
|
||||
let id = id.into();
|
||||
match ns {
|
||||
Some(ns) => self.edits.push(CreateElementNsTemplate {
|
||||
Some(ns) => self.edits.push(CreateElementNs {
|
||||
root: id,
|
||||
ns,
|
||||
tag,
|
||||
locally_static,
|
||||
fully_static,
|
||||
children,
|
||||
}),
|
||||
None => self.edits.push(CreateElementTemplate {
|
||||
None => self.edits.push(CreateElement {
|
||||
root: id,
|
||||
tag,
|
||||
locally_static,
|
||||
fully_static,
|
||||
children,
|
||||
}),
|
||||
}
|
||||
}
|
||||
|
||||
// placeholders are nodes that don't get rendered but still exist as an "anchor" in the real dom
|
||||
pub(crate) fn create_placeholder_template(&mut self, id: impl Into<u64>) {
|
||||
let id = id.into();
|
||||
self.edits.push(CreatePlaceholderTemplate { root: id });
|
||||
pub(crate) fn create_placeholder(&mut self, id: Option<u64>) {
|
||||
self.edits.push(CreatePlaceholder { root: id });
|
||||
}
|
||||
|
||||
// events
|
||||
@@ -403,13 +303,7 @@ impl<'a> Mutations<'a> {
|
||||
..
|
||||
} = listener;
|
||||
|
||||
let element_id = match mounted_node.get().unwrap() {
|
||||
GlobalNodeId::TemplateId {
|
||||
template_ref_id: _,
|
||||
template_node_id,
|
||||
} => template_node_id.into(),
|
||||
GlobalNodeId::VNodeId(id) => id.into(),
|
||||
};
|
||||
let element_id = Some(mounted_node.get().unwrap().into());
|
||||
|
||||
self.edits.push(NewEventListener {
|
||||
scope,
|
||||
@@ -418,21 +312,16 @@ impl<'a> Mutations<'a> {
|
||||
});
|
||||
}
|
||||
|
||||
pub(crate) fn remove_event_listener(&mut self, event: &'static str, root: impl Into<u64>) {
|
||||
self.edits.push(RemoveEventListener {
|
||||
event,
|
||||
root: root.into(),
|
||||
});
|
||||
pub(crate) fn remove_event_listener(&mut self, event: &'static str, root: Option<u64>) {
|
||||
self.edits.push(RemoveEventListener { event, root });
|
||||
}
|
||||
|
||||
// modify
|
||||
pub(crate) fn set_text(&mut self, text: &'a str, root: impl Into<u64>) {
|
||||
let root = root.into();
|
||||
pub(crate) fn set_text(&mut self, text: &'a str, root: Option<u64>) {
|
||||
self.edits.push(SetText { text, root });
|
||||
}
|
||||
|
||||
pub(crate) fn set_attribute(&mut self, attribute: &'a Attribute<'a>, root: impl Into<u64>) {
|
||||
let root = root.into();
|
||||
pub(crate) fn set_attribute(&mut self, attribute: &'a Attribute<'a>, root: Option<u64>) {
|
||||
let Attribute {
|
||||
value, attribute, ..
|
||||
} = attribute;
|
||||
@@ -445,8 +334,7 @@ impl<'a> Mutations<'a> {
|
||||
});
|
||||
}
|
||||
|
||||
pub(crate) fn remove_attribute(&mut self, attribute: &Attribute, root: impl Into<u64>) {
|
||||
let root = root.into();
|
||||
pub(crate) fn remove_attribute(&mut self, attribute: &Attribute, root: Option<u64>) {
|
||||
let Attribute { attribute, .. } = attribute;
|
||||
|
||||
self.edits.push(RemoveAttribute {
|
||||
@@ -460,31 +348,32 @@ impl<'a> Mutations<'a> {
|
||||
self.dirty_scopes.insert(scope);
|
||||
}
|
||||
|
||||
pub(crate) fn create_templete(&mut self, id: impl Into<u64>) {
|
||||
self.edits.push(CreateTemplate { id: id.into() });
|
||||
pub(crate) fn clone_node(&mut self, id: Option<u64>, new_id: u64) {
|
||||
self.edits.push(CloneNode { id, new_id });
|
||||
}
|
||||
|
||||
pub(crate) fn finish_templete(&mut self, len: u32) {
|
||||
self.edits.push(FinishTemplate { len });
|
||||
pub(crate) fn clone_node_children(&mut self, id: Option<u64>, new_ids: Vec<u64>) {
|
||||
self.edits.push(CloneNodeChildren { id, new_ids });
|
||||
}
|
||||
|
||||
pub(crate) fn create_template_ref(&mut self, id: impl Into<u64>, template_id: u64) {
|
||||
self.edits.push(CreateTemplateRef {
|
||||
id: id.into(),
|
||||
template_id,
|
||||
})
|
||||
pub(crate) fn first_child(&mut self) {
|
||||
self.edits.push(FirstChild {});
|
||||
}
|
||||
|
||||
pub(crate) fn enter_template_ref(&mut self, id: impl Into<u64>) {
|
||||
self.edits.push(EnterTemplateRef { root: id.into() });
|
||||
pub(crate) fn next_sibling(&mut self) {
|
||||
self.edits.push(NextSibling {});
|
||||
}
|
||||
|
||||
pub(crate) fn exit_template_ref(&mut self) {
|
||||
if let Some(&DomEdit::EnterTemplateRef { .. }) = self.edits.last() {
|
||||
self.edits.pop();
|
||||
} else {
|
||||
self.edits.push(ExitTemplateRef {});
|
||||
}
|
||||
pub(crate) fn parent_node(&mut self) {
|
||||
self.edits.push(ParentNode {});
|
||||
}
|
||||
|
||||
pub(crate) fn store_with_id(&mut self, id: u64) {
|
||||
self.edits.push(StoreWithId { id });
|
||||
}
|
||||
|
||||
pub(crate) fn set_last_node(&mut self, id: u64) {
|
||||
self.edits.push(SetLastNode { id });
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
Reference in new issue
Block a user