feat: rip out mutations for templates
This commit is contained in:
1 parent
3b166c9edd
commit
85657d3906
33 files changed
+270
-314
No files matched your search
@@ -7,7 +7,7 @@ use crate::mutations::Mutation::*;
|
||||
use crate::nodes::VNode;
|
||||
use crate::nodes::{DynamicNode, TemplateNode};
|
||||
use crate::virtual_dom::VirtualDom;
|
||||
use crate::{AttributeValue, ElementId, ScopeId, SuspenseContext, TemplateAttribute};
|
||||
use crate::{AttributeValue, ElementId, ScopeId, SuspenseContext};
|
||||
|
||||
impl<'b> VirtualDom {
|
||||
/// Create a new template [`VNode`] and write it to the [`Mutations`] buffer.
|
||||
@@ -224,81 +224,7 @@ impl<'b> VirtualDom {
|
||||
return;
|
||||
}
|
||||
|
||||
for node in template.template.roots {
|
||||
self.create_static_node(node);
|
||||
}
|
||||
|
||||
self.mutations.template_edits.push(SaveTemplate {
|
||||
name: template.template.id,
|
||||
m: template.template.roots.len(),
|
||||
});
|
||||
}
|
||||
|
||||
// todo: we shouldn't have any of instructions for building templates - renderers should be able to work with the
|
||||
// template type directly, right?
|
||||
pub(crate) fn create_static_node(&mut self, node: &'b TemplateNode<'static>) {
|
||||
match *node {
|
||||
// Todo: create the children's template
|
||||
TemplateNode::Dynamic(_) => self
|
||||
.mutations
|
||||
.template_edits
|
||||
.push(CreateStaticPlaceholder {}),
|
||||
TemplateNode::Text(value) => self
|
||||
.mutations
|
||||
.template_edits
|
||||
.push(CreateStaticText { value }),
|
||||
|
||||
TemplateNode::DynamicText { .. } => {
|
||||
self.mutations.template_edits.push(CreateTextPlaceholder)
|
||||
}
|
||||
|
||||
TemplateNode::Element {
|
||||
attrs,
|
||||
children,
|
||||
namespace,
|
||||
tag,
|
||||
..
|
||||
} => {
|
||||
match namespace {
|
||||
Some(namespace) => self.mutations.template_edits.push(CreateElementNamespace {
|
||||
name: tag,
|
||||
namespace,
|
||||
}),
|
||||
None => self
|
||||
.mutations
|
||||
.template_edits
|
||||
.push(CreateElement { name: tag }),
|
||||
}
|
||||
|
||||
self.mutations
|
||||
.template_edits
|
||||
.extend(attrs.iter().filter_map(|attr| match attr {
|
||||
TemplateAttribute::Static {
|
||||
name,
|
||||
value,
|
||||
namespace,
|
||||
..
|
||||
} => Some(SetStaticAttribute {
|
||||
name,
|
||||
value,
|
||||
ns: *namespace,
|
||||
}),
|
||||
_ => None,
|
||||
}));
|
||||
|
||||
if children.is_empty() {
|
||||
return;
|
||||
}
|
||||
|
||||
children
|
||||
.iter()
|
||||
.for_each(|child| self.create_static_node(child));
|
||||
|
||||
self.mutations
|
||||
.template_edits
|
||||
.push(AppendChildren { m: children.len() })
|
||||
}
|
||||
}
|
||||
self.mutations.templates.push(template.template);
|
||||
}
|
||||
|
||||
pub(crate) fn create_dynamic_node(
|
||||
@@ -404,7 +330,7 @@ impl<'b> VirtualDom {
|
||||
) -> usize {
|
||||
// Keep track of how many mutations are in the buffer in case we need to split them out if a suspense boundary
|
||||
// is encountered
|
||||
let mutations_to_this_point = self.mutations.dom_edits.len();
|
||||
let mutations_to_this_point = self.mutations.edits.len();
|
||||
|
||||
// Create the component's root element
|
||||
let created = self.create_scope(scope, new);
|
||||
@@ -430,10 +356,10 @@ impl<'b> VirtualDom {
|
||||
// Note that we break off dynamic mutations only - since static mutations aren't rendered immediately
|
||||
let split_off = unsafe {
|
||||
std::mem::transmute::<Vec<Mutation>, Vec<Mutation>>(
|
||||
self.mutations.dom_edits.split_off(mutations_to_this_point),
|
||||
self.mutations.edits.split_off(mutations_to_this_point),
|
||||
)
|
||||
};
|
||||
boundary.mutations.borrow_mut().dom_edits.extend(split_off);
|
||||
boundary.mutations.borrow_mut().edits.extend(split_off);
|
||||
boundary.created_on_stack.set(created);
|
||||
boundary
|
||||
.waiting_on
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
use fxhash::FxHashSet;
|
||||
|
||||
use crate::{arena::ElementId, ScopeId};
|
||||
use crate::{arena::ElementId, ScopeId, Template};
|
||||
|
||||
/// A container for all the relevant steps to modify the Real DOM
|
||||
///
|
||||
@@ -18,11 +18,13 @@ pub struct Mutations<'a> {
|
||||
/// The list of Scopes that were diffed, created, and removed during the Diff process.
|
||||
pub dirty_scopes: FxHashSet<ScopeId>,
|
||||
|
||||
/// Any mutations required to build the templates using [`Mutations`]
|
||||
pub template_edits: Vec<Mutation<'a>>,
|
||||
/// 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 dom_edits: Vec<Mutation<'a>>,
|
||||
pub edits: Vec<Mutation<'a>>,
|
||||
}
|
||||
|
||||
impl<'a> Mutations<'a> {
|
||||
@@ -30,21 +32,22 @@ impl<'a> Mutations<'a> {
|
||||
///
|
||||
/// Used really only for testing
|
||||
pub fn santize(mut self) -> Self {
|
||||
self.template_edits
|
||||
.iter_mut()
|
||||
.chain(self.dom_edits.iter_mut())
|
||||
.for_each(|edit| match edit {
|
||||
Mutation::LoadTemplate { name, .. } => *name = "template",
|
||||
Mutation::SaveTemplate { name, .. } => *name = "template",
|
||||
_ => {}
|
||||
});
|
||||
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
|
||||
// self
|
||||
}
|
||||
|
||||
/// Push a new mutation into the dom_edits list
|
||||
pub(crate) fn push(&mut self, mutation: Mutation<'static>) {
|
||||
self.dom_edits.push(mutation)
|
||||
self.edits.push(mutation)
|
||||
}
|
||||
}
|
||||
|
||||
@@ -59,34 +62,14 @@ each subtree has its own numbering scheme
|
||||
)]
|
||||
#[derive(Debug, PartialEq, Eq)]
|
||||
pub enum Mutation<'a> {
|
||||
/// 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.
|
||||
m: usize,
|
||||
},
|
||||
|
||||
AssignId {
|
||||
path: &'static [u8],
|
||||
id: ElementId,
|
||||
},
|
||||
|
||||
CreateElement {
|
||||
name: &'a str,
|
||||
},
|
||||
CreateElementNamespace {
|
||||
name: &'a str,
|
||||
namespace: &'a str,
|
||||
},
|
||||
CreatePlaceholder {
|
||||
id: ElementId,
|
||||
},
|
||||
CreateStaticPlaceholder,
|
||||
CreateTextPlaceholder,
|
||||
CreateStaticText {
|
||||
value: &'a str,
|
||||
},
|
||||
CreateTextNode {
|
||||
value: &'a str,
|
||||
id: ElementId,
|
||||
@@ -131,15 +114,6 @@ pub enum Mutation<'a> {
|
||||
m: usize,
|
||||
},
|
||||
|
||||
/// Save the top m nodes as a placeholder
|
||||
SaveTemplate {
|
||||
/// The name of the template that we're saving
|
||||
name: &'static str,
|
||||
|
||||
/// How many nodes are being saved into this template
|
||||
m: usize,
|
||||
},
|
||||
|
||||
/// Set the value of a node's attribute.
|
||||
SetAttribute {
|
||||
/// The name of the attribute to set.
|
||||
@@ -155,19 +129,6 @@ pub enum Mutation<'a> {
|
||||
ns: Option<&'a str>,
|
||||
},
|
||||
|
||||
/// Set the value of a node's attribute.
|
||||
SetStaticAttribute {
|
||||
/// The name of the attribute to set.
|
||||
name: &'a str,
|
||||
|
||||
/// The value of the attribute.
|
||||
value: &'a str,
|
||||
|
||||
/// 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.
|
||||
|
||||
@@ -62,6 +62,7 @@ impl<'a> VNode<'a> {
|
||||
}
|
||||
}
|
||||
|
||||
#[cfg_attr(feature = "serialize", derive(serde::Serialize))]
|
||||
#[derive(Debug, Clone, Copy)]
|
||||
pub struct Template<'a> {
|
||||
pub id: &'a str,
|
||||
@@ -71,6 +72,7 @@ pub struct Template<'a> {
|
||||
}
|
||||
|
||||
#[derive(Debug, Clone, Copy)]
|
||||
#[cfg_attr(feature = "serialize", derive(serde::Serialize))]
|
||||
pub enum TemplateNode<'a> {
|
||||
Element {
|
||||
tag: &'a str,
|
||||
@@ -126,11 +128,12 @@ pub struct VText<'a> {
|
||||
}
|
||||
|
||||
#[derive(Debug)]
|
||||
#[cfg_attr(feature = "serialize", derive(serde::Serialize, serde::Deserialize))]
|
||||
pub enum TemplateAttribute<'a> {
|
||||
Static {
|
||||
name: &'static str,
|
||||
name: &'a str,
|
||||
value: &'a str,
|
||||
namespace: Option<&'static str>,
|
||||
namespace: Option<&'a str>,
|
||||
volatile: bool,
|
||||
},
|
||||
Dynamic(usize),
|
||||
|
||||
@@ -490,7 +490,7 @@ impl VirtualDom {
|
||||
// Rebuilding implies we append the created elements to the root
|
||||
RenderReturn::Sync(Ok(node)) => {
|
||||
let m = self.create_scope(ScopeId(0), node);
|
||||
self.mutations.push(Mutation::AppendChildren { m });
|
||||
// self.mutations.push(Mutation::AppendChildren { m });
|
||||
}
|
||||
// If an error occurs, we should try to render the default error component and context where the error occured
|
||||
RenderReturn::Sync(Err(e)) => panic!("Cannot catch errors during rebuild {:?}", e),
|
||||
@@ -534,12 +534,12 @@ impl VirtualDom {
|
||||
let context = scope.has_context::<SuspenseContext>().unwrap();
|
||||
|
||||
self.mutations
|
||||
.template_edits
|
||||
.extend(context.mutations.borrow_mut().template_edits.drain(..));
|
||||
.templates
|
||||
.extend(context.mutations.borrow_mut().templates.drain(..));
|
||||
|
||||
self.mutations
|
||||
.dom_edits
|
||||
.extend(context.mutations.borrow_mut().dom_edits.drain(..));
|
||||
.edits
|
||||
.extend(context.mutations.borrow_mut().edits.drain(..));
|
||||
|
||||
// TODO: count how many nodes are on the stack?
|
||||
self.mutations.push(Mutation::ReplaceWith {
|
||||
@@ -559,7 +559,7 @@ impl VirtualDom {
|
||||
}
|
||||
|
||||
// Save the current mutations length so we can split them into boundary
|
||||
let mutations_to_this_point = self.mutations.dom_edits.len();
|
||||
let mutations_to_this_point = self.mutations.edits.len();
|
||||
|
||||
// Run the scope and get the mutations
|
||||
self.run_scope(dirty.id);
|
||||
@@ -578,8 +578,8 @@ impl VirtualDom {
|
||||
boundary_mut
|
||||
.mutations
|
||||
.borrow_mut()
|
||||
.dom_edits
|
||||
.extend(self.mutations.dom_edits.split_off(mutations_to_this_point));
|
||||
.edits
|
||||
.extend(self.mutations.edits.split_off(mutations_to_this_point));
|
||||
|
||||
// Attach suspended leaves
|
||||
boundary
|
||||
|
||||
Reference in new issue
Block a user