feat: keys
This commit is contained in:
1 parent
dddbcfd5e2
commit
584504feb7
10 files changed
+113
-94
No files matched your search
+18
-14
@@ -1,7 +1,7 @@
|
|||||||
use crate::mutations::Mutation;
|
use crate::mutations::Mutation;
|
||||||
use crate::mutations::Mutation::*;
|
use crate::mutations::Mutation::*;
|
||||||
use crate::nodes::VNode;
|
use crate::nodes::VNode;
|
||||||
use crate::nodes::{DynamicNode, DynamicNodeKind, TemplateNode};
|
use crate::nodes::{DynamicNode, TemplateNode};
|
||||||
use crate::virtualdom::VirtualDom;
|
use crate::virtualdom::VirtualDom;
|
||||||
use crate::{AttributeValue, TemplateAttribute};
|
use crate::{AttributeValue, TemplateAttribute};
|
||||||
|
|
||||||
@@ -30,8 +30,8 @@ impl VirtualDom {
|
|||||||
|
|
||||||
// Walk the roots backwards, creating nodes and assigning IDs
|
// Walk the roots backwards, creating nodes and assigning IDs
|
||||||
// todo: adjust dynamic nodes to be in the order of roots and then leaves (ie BFS)
|
// todo: adjust dynamic nodes to be in the order of roots and then leaves (ie BFS)
|
||||||
let mut dynamic_attrs = template.dynamic_attrs.iter().peekable();
|
let mut dynamic_attrs = template.template.attr_paths.iter().enumerate().peekable();
|
||||||
let mut dynamic_nodes = template.dynamic_nodes.iter().peekable();
|
let mut dynamic_nodes = template.template.node_paths.iter().enumerate().peekable();
|
||||||
|
|
||||||
let mut on_stack = 0;
|
let mut on_stack = 0;
|
||||||
for (root_idx, root) in template.template.roots.iter().enumerate() {
|
for (root_idx, root) in template.template.roots.iter().enumerate() {
|
||||||
@@ -46,7 +46,7 @@ impl VirtualDom {
|
|||||||
}
|
}
|
||||||
|
|
||||||
TemplateNode::Dynamic(id) => {
|
TemplateNode::Dynamic(id) => {
|
||||||
self.create_dynamic_node(mutations, template, &template.dynamic_nodes[*id])
|
self.create_dynamic_node(mutations, template, &template.dynamic_nodes[*id], *id)
|
||||||
}
|
}
|
||||||
|
|
||||||
TemplateNode::DynamicText { .. } => 1,
|
TemplateNode::DynamicText { .. } => 1,
|
||||||
@@ -56,9 +56,11 @@ impl VirtualDom {
|
|||||||
|
|
||||||
// we're on top of a node that has a dynamic attribute for a descendant
|
// we're on top of a node that has a dynamic attribute for a descendant
|
||||||
// Set that attribute now before the stack gets in a weird state
|
// Set that attribute now before the stack gets in a weird state
|
||||||
while let Some(attr) = dynamic_attrs.next_if(|a| a.path[0] == root_idx as u8) {
|
while let Some((idx, path)) = dynamic_attrs.next_if(|(_, p)| p[0] == root_idx as u8) {
|
||||||
|
let attr = &template.dynamic_attrs[idx];
|
||||||
|
|
||||||
if cur_route.is_none() {
|
if cur_route.is_none() {
|
||||||
cur_route = Some((self.next_element(template), &attr.path[1..]));
|
cur_route = Some((self.next_element(template), &path[1..]));
|
||||||
}
|
}
|
||||||
|
|
||||||
// Attach all the elementIDs to the nodes with dynamic content
|
// Attach all the elementIDs to the nodes with dynamic content
|
||||||
@@ -91,11 +93,12 @@ impl VirtualDom {
|
|||||||
}
|
}
|
||||||
|
|
||||||
// We're on top of a node that has a dynamic child for a descendant
|
// We're on top of a node that has a dynamic child for a descendant
|
||||||
while let Some(node) = dynamic_nodes.next_if(|f| f.path[0] == root_idx as u8) {
|
while let Some((idx, path)) = dynamic_nodes.next_if(|(_, p)| p[0] == root_idx as u8) {
|
||||||
let m = self.create_dynamic_node(mutations, template, node);
|
let node = &template.dynamic_nodes[idx];
|
||||||
|
let m = self.create_dynamic_node(mutations, template, node, idx);
|
||||||
mutations.push(ReplacePlaceholder {
|
mutations.push(ReplacePlaceholder {
|
||||||
m,
|
m,
|
||||||
path: &node.path[1..],
|
path: &path[1..],
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -151,21 +154,22 @@ impl VirtualDom {
|
|||||||
mutations: &mut Vec<Mutation<'a>>,
|
mutations: &mut Vec<Mutation<'a>>,
|
||||||
template: &'a VNode<'a>,
|
template: &'a VNode<'a>,
|
||||||
node: &'a DynamicNode<'a>,
|
node: &'a DynamicNode<'a>,
|
||||||
|
idx: usize,
|
||||||
) -> usize {
|
) -> usize {
|
||||||
match &node.kind {
|
match &node {
|
||||||
DynamicNodeKind::Text { id, value } => {
|
DynamicNode::Text { id, value } => {
|
||||||
let new_id = self.next_element(template);
|
let new_id = self.next_element(template);
|
||||||
id.set(new_id);
|
id.set(new_id);
|
||||||
mutations.push(HydrateText {
|
mutations.push(HydrateText {
|
||||||
id: new_id,
|
id: new_id,
|
||||||
path: &node.path[1..],
|
path: &template.template.node_paths[idx][1..],
|
||||||
value,
|
value,
|
||||||
});
|
});
|
||||||
|
|
||||||
1
|
1
|
||||||
}
|
}
|
||||||
|
|
||||||
DynamicNodeKind::Component { props, .. } => {
|
DynamicNode::Component { props, .. } => {
|
||||||
let id = self.new_scope(*props);
|
let id = self.new_scope(*props);
|
||||||
|
|
||||||
let template = self.run_scope(id);
|
let template = self.run_scope(id);
|
||||||
@@ -180,7 +184,7 @@ impl VirtualDom {
|
|||||||
created
|
created
|
||||||
}
|
}
|
||||||
|
|
||||||
DynamicNodeKind::Fragment { children } => {
|
DynamicNode::Fragment { children } => {
|
||||||
//
|
//
|
||||||
children
|
children
|
||||||
.iter()
|
.iter()
|
||||||
|
|||||||
@@ -115,14 +115,16 @@ impl VirtualDom {
|
|||||||
|
|
||||||
while let Some((raw_parent, dyn_index)) = index {
|
while let Some((raw_parent, dyn_index)) = index {
|
||||||
let parent = unsafe { &mut *raw_parent };
|
let parent = unsafe { &mut *raw_parent };
|
||||||
let path = parent.dynamic_nodes[dyn_index].path;
|
let path = parent.template.node_paths[dyn_index];
|
||||||
|
|
||||||
listeners.extend(
|
listeners.extend(
|
||||||
parent
|
parent
|
||||||
.dynamic_attrs
|
.dynamic_attrs
|
||||||
.iter()
|
.iter()
|
||||||
.filter(|attr| is_path_ascendant(attr.path, path))
|
.enumerate()
|
||||||
.filter(|attr| attr.name == event.name),
|
.filter(|(idx, attr)| is_path_ascendant(parent.template.node_paths[*idx], path))
|
||||||
|
.filter(|(idx, attr)| attr.name == event.name)
|
||||||
|
.map(|(_, attr)| attr),
|
||||||
);
|
);
|
||||||
|
|
||||||
index = parent.parent;
|
index = parent.parent;
|
||||||
|
|||||||
@@ -5,25 +5,24 @@ use bumpalo::Bump;
|
|||||||
use crate::{
|
use crate::{
|
||||||
any_props::{AnyProps, VComponentProps},
|
any_props::{AnyProps, VComponentProps},
|
||||||
arena::ElementId,
|
arena::ElementId,
|
||||||
innerlude::{DynamicNode, DynamicNodeKind},
|
innerlude::DynamicNode,
|
||||||
Attribute, AttributeValue, Element, LazyNodes, Properties, Scope, ScopeState, VNode,
|
Attribute, AttributeValue, Element, LazyNodes, Properties, Scope, ScopeState, VNode,
|
||||||
};
|
};
|
||||||
|
|
||||||
impl ScopeState {
|
impl ScopeState {
|
||||||
/// Create some text that's allocated along with the other vnodes
|
/// Create some text that's allocated along with the other vnodes
|
||||||
///
|
|
||||||
pub fn text<'a>(&'a self, args: Arguments) -> DynamicNode<'a> {
|
pub fn text<'a>(&'a self, args: Arguments) -> DynamicNode<'a> {
|
||||||
let (text, _) = self.raw_text(args);
|
let (text, _) = self.raw_text(args);
|
||||||
|
DynamicNode::Text {
|
||||||
DynamicNode {
|
id: Cell::new(ElementId(0)),
|
||||||
kind: DynamicNodeKind::Text {
|
value: text,
|
||||||
id: Cell::new(ElementId(0)),
|
|
||||||
value: text,
|
|
||||||
},
|
|
||||||
path: &[0],
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
pub fn raw_text_inline<'a>(&'a self, args: Arguments) -> &'a str {
|
||||||
|
self.raw_text(args).0
|
||||||
|
}
|
||||||
|
|
||||||
pub fn raw_text<'a>(&'a self, args: Arguments) -> (&'a str, bool) {
|
pub fn raw_text<'a>(&'a self, args: Arguments) -> (&'a str, bool) {
|
||||||
match args.as_str() {
|
match args.as_str() {
|
||||||
Some(static_str) => (static_str, true),
|
Some(static_str) => (static_str, true),
|
||||||
@@ -46,11 +45,8 @@ impl ScopeState {
|
|||||||
bump_vec.push(item.into_dynamic_node(self));
|
bump_vec.push(item.into_dynamic_node(self));
|
||||||
}
|
}
|
||||||
|
|
||||||
DynamicNode {
|
DynamicNode::Fragment {
|
||||||
path: &[0, 0],
|
children: bump_vec.into_bump_slice(),
|
||||||
kind: crate::innerlude::DynamicNodeKind::Fragment {
|
|
||||||
children: bump_vec.into_bump_slice(),
|
|
||||||
},
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -60,14 +56,14 @@ impl ScopeState {
|
|||||||
name: &'static str,
|
name: &'static str,
|
||||||
val: impl IntoAttributeValue<'a>,
|
val: impl IntoAttributeValue<'a>,
|
||||||
namespace: Option<&'static str>,
|
namespace: Option<&'static str>,
|
||||||
is_volatile: bool,
|
volatile: bool,
|
||||||
) -> Attribute<'a> {
|
) -> Attribute<'a> {
|
||||||
Attribute {
|
Attribute {
|
||||||
name,
|
name,
|
||||||
namespace,
|
namespace,
|
||||||
mounted_element: Cell::new(ElementId(0)),
|
volatile,
|
||||||
path: &[0],
|
|
||||||
value: val.into_value(self.bump()),
|
value: val.into_value(self.bump()),
|
||||||
|
mounted_element: Cell::new(ElementId(0)),
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -94,13 +90,10 @@ impl ScopeState {
|
|||||||
// self.scope.items.borrow_mut().borrowed_props.push(vcomp);
|
// self.scope.items.borrow_mut().borrowed_props.push(vcomp);
|
||||||
// }
|
// }
|
||||||
|
|
||||||
DynamicNode {
|
DynamicNode::Component {
|
||||||
path: &[0],
|
name: fn_name,
|
||||||
kind: DynamicNodeKind::Component {
|
can_memoize: P::IS_STATIC,
|
||||||
name: fn_name,
|
props: detached_dyn,
|
||||||
can_memoize: P::IS_STATIC,
|
|
||||||
props: detached_dyn,
|
|
||||||
},
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -116,17 +109,19 @@ impl<'a, 'b> IntoVnode<'a> for LazyNodes<'a, 'b> {
|
|||||||
}
|
}
|
||||||
|
|
||||||
impl<'a, 'b> IntoVnode<'a> for VNode<'a> {
|
impl<'a, 'b> IntoVnode<'a> for VNode<'a> {
|
||||||
fn into_dynamic_node(self, cx: &'a ScopeState) -> VNode<'a> {
|
fn into_dynamic_node(self, _cx: &'a ScopeState) -> VNode<'a> {
|
||||||
self
|
self
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
impl<'a, 'b> IntoVnode<'a> for &'a VNode<'a> {
|
impl<'a, 'b> IntoVnode<'a> for &'a VNode<'a> {
|
||||||
fn into_dynamic_node(self, cx: &'a ScopeState) -> VNode<'a> {
|
fn into_dynamic_node(self, _cx: &'a ScopeState) -> VNode<'a> {
|
||||||
VNode {
|
VNode {
|
||||||
node_id: self.node_id.clone(),
|
node_id: self.node_id.clone(),
|
||||||
parent: self.parent,
|
parent: self.parent,
|
||||||
template: self.template,
|
template: self.template,
|
||||||
root_ids: self.root_ids,
|
root_ids: self.root_ids,
|
||||||
|
key: self.key,
|
||||||
dynamic_nodes: self.dynamic_nodes,
|
dynamic_nodes: self.dynamic_nodes,
|
||||||
dynamic_attrs: self.dynamic_attrs,
|
dynamic_attrs: self.dynamic_attrs,
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -1,8 +1,4 @@
|
|||||||
use crate::{
|
use crate::{nodes::VNode, scopes::ScopeId, virtualdom::VirtualDom, DynamicNode};
|
||||||
nodes::{DynamicNodeKind, VNode},
|
|
||||||
scopes::ScopeId,
|
|
||||||
virtualdom::VirtualDom,
|
|
||||||
};
|
|
||||||
|
|
||||||
impl VirtualDom {
|
impl VirtualDom {
|
||||||
pub fn drop_scope(&mut self, id: ScopeId) {
|
pub fn drop_scope(&mut self, id: ScopeId) {
|
||||||
@@ -16,14 +12,14 @@ impl VirtualDom {
|
|||||||
|
|
||||||
pub fn drop_template<'a>(&'a mut self, template: &'a VNode<'a>) {
|
pub fn drop_template<'a>(&'a mut self, template: &'a VNode<'a>) {
|
||||||
for node in template.dynamic_nodes.iter() {
|
for node in template.dynamic_nodes.iter() {
|
||||||
match &node.kind {
|
match node {
|
||||||
DynamicNodeKind::Text { id, .. } => {}
|
DynamicNode::Text { id, .. } => {}
|
||||||
|
|
||||||
DynamicNodeKind::Component { .. } => {
|
DynamicNode::Component { .. } => {
|
||||||
todo!()
|
todo!()
|
||||||
}
|
}
|
||||||
|
|
||||||
DynamicNodeKind::Fragment { children } => {}
|
DynamicNode::Fragment { children } => {}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -72,7 +72,6 @@ pub use crate::innerlude::{
|
|||||||
Attribute,
|
Attribute,
|
||||||
AttributeValue,
|
AttributeValue,
|
||||||
DynamicNode,
|
DynamicNode,
|
||||||
DynamicNodeKind,
|
|
||||||
Element,
|
Element,
|
||||||
EventPriority,
|
EventPriority,
|
||||||
LazyNodes,
|
LazyNodes,
|
||||||
@@ -98,9 +97,9 @@ pub use crate::innerlude::{
|
|||||||
/// This includes types like [`Scope`], [`Element`], and [`Component`].
|
/// This includes types like [`Scope`], [`Element`], and [`Component`].
|
||||||
pub mod prelude {
|
pub mod prelude {
|
||||||
pub use crate::innerlude::{
|
pub use crate::innerlude::{
|
||||||
fc_to_builder, Attribute, DynamicNode, DynamicNodeKind, Element, EventPriority, LazyNodes,
|
fc_to_builder, Attribute, DynamicNode, Element, EventPriority, LazyNodes, NodeFactory,
|
||||||
NodeFactory, Properties, Scope, ScopeId, ScopeState, TaskId, Template, TemplateAttribute,
|
Properties, Scope, ScopeId, ScopeState, TaskId, Template, TemplateAttribute, TemplateNode,
|
||||||
TemplateNode, UiEvent, VNode, VirtualDom,
|
UiEvent, VNode, VirtualDom,
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -12,6 +12,8 @@ pub struct VNode<'a> {
|
|||||||
// The ID assigned for the root of this template
|
// The ID assigned for the root of this template
|
||||||
pub node_id: Cell<ElementId>,
|
pub node_id: Cell<ElementId>,
|
||||||
|
|
||||||
|
pub key: Option<&'a str>,
|
||||||
|
|
||||||
// When rendered, this template will be linked to its parent manually
|
// When rendered, this template will be linked to its parent manually
|
||||||
pub parent: Option<(*mut VNode<'static>, usize)>,
|
pub parent: Option<(*mut VNode<'static>, usize)>,
|
||||||
|
|
||||||
@@ -28,6 +30,8 @@ pub struct VNode<'a> {
|
|||||||
pub struct Template<'a> {
|
pub struct Template<'a> {
|
||||||
pub id: &'a str,
|
pub id: &'a str,
|
||||||
pub roots: &'a [TemplateNode<'a>],
|
pub roots: &'a [TemplateNode<'a>],
|
||||||
|
pub node_paths: &'a [&'a [u8]],
|
||||||
|
pub attr_paths: &'a [&'a [u8]],
|
||||||
}
|
}
|
||||||
|
|
||||||
impl<'a> std::hash::Hash for Template<'a> {
|
impl<'a> std::hash::Hash for Template<'a> {
|
||||||
@@ -68,12 +72,7 @@ pub enum TemplateNode<'a> {
|
|||||||
DynamicText(usize),
|
DynamicText(usize),
|
||||||
}
|
}
|
||||||
|
|
||||||
pub struct DynamicNode<'a> {
|
pub enum DynamicNode<'a> {
|
||||||
pub path: &'static [u8],
|
|
||||||
pub kind: DynamicNodeKind<'a>,
|
|
||||||
}
|
|
||||||
|
|
||||||
pub enum DynamicNodeKind<'a> {
|
|
||||||
// Anything declared in component form
|
// Anything declared in component form
|
||||||
// IE in caps or with underscores
|
// IE in caps or with underscores
|
||||||
Component {
|
Component {
|
||||||
@@ -102,10 +101,7 @@ pub enum TemplateAttribute<'a> {
|
|||||||
namespace: Option<&'static str>,
|
namespace: Option<&'static str>,
|
||||||
volatile: bool,
|
volatile: bool,
|
||||||
},
|
},
|
||||||
Dynamic {
|
Dynamic(usize),
|
||||||
name: &'static str,
|
|
||||||
index: usize,
|
|
||||||
},
|
|
||||||
}
|
}
|
||||||
|
|
||||||
pub struct Attribute<'a> {
|
pub struct Attribute<'a> {
|
||||||
@@ -113,7 +109,7 @@ pub struct Attribute<'a> {
|
|||||||
pub value: AttributeValue<'a>,
|
pub value: AttributeValue<'a>,
|
||||||
pub namespace: Option<&'static str>,
|
pub namespace: Option<&'static str>,
|
||||||
pub mounted_element: Cell<ElementId>,
|
pub mounted_element: Cell<ElementId>,
|
||||||
pub path: &'static [u8],
|
pub volatile: bool,
|
||||||
}
|
}
|
||||||
|
|
||||||
pub enum AttributeValue<'a> {
|
pub enum AttributeValue<'a> {
|
||||||
|
|||||||
@@ -5,11 +5,10 @@ fn basic_syntax_is_a_template(cx: Scope) -> Element {
|
|||||||
let var = 123;
|
let var = 123;
|
||||||
|
|
||||||
cx.render(rsx! {
|
cx.render(rsx! {
|
||||||
div {
|
div { key: "12345",
|
||||||
class: "asd",
|
class: "asd",
|
||||||
class: "{asd}",
|
class: "{asd}",
|
||||||
onclick: move |_| {},
|
onclick: move |_| {},
|
||||||
|
|
||||||
div { "{var}" }
|
div { "{var}" }
|
||||||
div {
|
div {
|
||||||
h1 { "var" }
|
h1 { "var" }
|
||||||
@@ -25,8 +24,9 @@ fn basic_syntax_is_a_template(cx: Scope) -> Element {
|
|||||||
}
|
}
|
||||||
|
|
||||||
fn basic_template(cx: Scope) -> Element {
|
fn basic_template(cx: Scope) -> Element {
|
||||||
|
let val = 123;
|
||||||
cx.render(rsx! {
|
cx.render(rsx! {
|
||||||
div {
|
div { class: "{val}", class: "{val}", class: "{val}", class: "{val}",
|
||||||
(0..2).map(|i| rsx! { div { "asd {i}" } })
|
(0..2).map(|i| rsx! { div { "asd {i}" } })
|
||||||
basic_child { }
|
basic_child { }
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -55,6 +55,18 @@ impl Component {
|
|||||||
|
|
||||||
Ok(())
|
Ok(())
|
||||||
}
|
}
|
||||||
|
|
||||||
|
pub fn key(&self) -> Option<&IfmtInput> {
|
||||||
|
match self
|
||||||
|
.fields
|
||||||
|
.iter()
|
||||||
|
.find(|f| f.name.to_string() == "key")
|
||||||
|
.map(|f| &f.content)
|
||||||
|
{
|
||||||
|
Some(ContentField::Formatted(fmt)) => Some(fmt),
|
||||||
|
_ => None,
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
impl Parse for Component {
|
impl Parse for Component {
|
||||||
|
|||||||
+33
-15
@@ -99,6 +99,18 @@ impl<'a> ToTokens for TemplateRenderer<'a> {
|
|||||||
dynamic_nodes: vec![],
|
dynamic_nodes: vec![],
|
||||||
dynamic_attributes: vec![],
|
dynamic_attributes: vec![],
|
||||||
current_path: vec![],
|
current_path: vec![],
|
||||||
|
attr_paths: vec![],
|
||||||
|
node_paths: vec![],
|
||||||
|
};
|
||||||
|
|
||||||
|
let key = match self.roots.get(0) {
|
||||||
|
Some(BodyNode::Element(el)) if self.roots.len() == 1 => el.key.clone(),
|
||||||
|
Some(BodyNode::Component(comp)) if self.roots.len() == 1 => comp.key().cloned(),
|
||||||
|
_ => None,
|
||||||
|
};
|
||||||
|
let key_tokens = match key {
|
||||||
|
Some(tok) => quote! { Some( __cx.raw_text_inline(#tok) ) },
|
||||||
|
None => quote! { None },
|
||||||
};
|
};
|
||||||
|
|
||||||
let root_printer = self.roots.iter().enumerate().map(|(idx, root)| {
|
let root_printer = self.roots.iter().enumerate().map(|(idx, root)| {
|
||||||
@@ -112,15 +124,27 @@ impl<'a> ToTokens for TemplateRenderer<'a> {
|
|||||||
let roots = quote! { #( #root_printer ),* };
|
let roots = quote! { #( #root_printer ),* };
|
||||||
let node_printer = &context.dynamic_nodes;
|
let node_printer = &context.dynamic_nodes;
|
||||||
let dyn_attr_printer = &context.dynamic_attributes;
|
let dyn_attr_printer = &context.dynamic_attributes;
|
||||||
|
let node_paths = context
|
||||||
|
.node_paths
|
||||||
|
.iter()
|
||||||
|
.map(|items| quote!(&[#(#items),*]));
|
||||||
|
|
||||||
|
let attr_paths = context
|
||||||
|
.attr_paths
|
||||||
|
.iter()
|
||||||
|
.map(|items| quote!(&[#(#items),*]));
|
||||||
|
|
||||||
out_tokens.append_all(quote! {
|
out_tokens.append_all(quote! {
|
||||||
static TEMPLATE: ::dioxus::core::Template = ::dioxus::core::Template {
|
static TEMPLATE: ::dioxus::core::Template = ::dioxus::core::Template {
|
||||||
id: ::dioxus::core::get_line_num!(),
|
id: ::dioxus::core::get_line_num!(),
|
||||||
roots: &[ #roots ]
|
roots: &[ #roots ],
|
||||||
|
node_paths: &[ #(#node_paths),* ],
|
||||||
|
attr_paths: &[ #(#attr_paths),* ],
|
||||||
};
|
};
|
||||||
::dioxus::core::VNode {
|
::dioxus::core::VNode {
|
||||||
node_id: Default::default(),
|
node_id: Default::default(),
|
||||||
parent: None,
|
parent: None,
|
||||||
|
key: #key_tokens,
|
||||||
template: TEMPLATE,
|
template: TEMPLATE,
|
||||||
root_ids: __cx.bump().alloc([]),
|
root_ids: __cx.bump().alloc([]),
|
||||||
dynamic_nodes: __cx.bump().alloc([ #( #node_printer ),* ]),
|
dynamic_nodes: __cx.bump().alloc([ #( #node_printer ),* ]),
|
||||||
@@ -135,6 +159,9 @@ pub struct DynamicContext<'a> {
|
|||||||
dynamic_nodes: Vec<&'a BodyNode>,
|
dynamic_nodes: Vec<&'a BodyNode>,
|
||||||
dynamic_attributes: Vec<&'a ElementAttrNamed>,
|
dynamic_attributes: Vec<&'a ElementAttrNamed>,
|
||||||
current_path: Vec<u8>,
|
current_path: Vec<u8>,
|
||||||
|
|
||||||
|
node_paths: Vec<Vec<u8>>,
|
||||||
|
attr_paths: Vec<Vec<u8>>,
|
||||||
}
|
}
|
||||||
|
|
||||||
impl<'a> DynamicContext<'a> {
|
impl<'a> DynamicContext<'a> {
|
||||||
@@ -180,22 +207,12 @@ impl<'a> DynamicContext<'a> {
|
|||||||
ElementAttr::AttrExpression { .. }
|
ElementAttr::AttrExpression { .. }
|
||||||
| ElementAttr::AttrText { .. }
|
| ElementAttr::AttrText { .. }
|
||||||
| ElementAttr::CustomAttrText { .. }
|
| ElementAttr::CustomAttrText { .. }
|
||||||
| ElementAttr::CustomAttrExpression { .. } => {
|
| ElementAttr::CustomAttrExpression { .. }
|
||||||
|
| ElementAttr::EventTokens { .. } => {
|
||||||
let ct = self.dynamic_attributes.len();
|
let ct = self.dynamic_attributes.len();
|
||||||
self.dynamic_attributes.push(attr);
|
self.dynamic_attributes.push(attr);
|
||||||
Some(quote! { ::dioxus::core::TemplateAttribute::Dynamic {
|
self.attr_paths.push(self.current_path.clone());
|
||||||
name: "asd",
|
Some(quote! { ::dioxus::core::TemplateAttribute::Dynamic(#ct) })
|
||||||
index: #ct
|
|
||||||
} })
|
|
||||||
}
|
|
||||||
|
|
||||||
ElementAttr::EventTokens { .. } => {
|
|
||||||
let ct = self.dynamic_attributes.len();
|
|
||||||
self.dynamic_attributes.push(attr);
|
|
||||||
Some(quote! { ::dioxus::core::TemplateAttribute::Dynamic {
|
|
||||||
name: "asd",
|
|
||||||
index: #ct
|
|
||||||
} })
|
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
|
|
||||||
@@ -228,6 +245,7 @@ impl<'a> DynamicContext<'a> {
|
|||||||
BodyNode::RawExpr(_) | BodyNode::Text(_) | BodyNode::Component(_) => {
|
BodyNode::RawExpr(_) | BodyNode::Text(_) | BodyNode::Component(_) => {
|
||||||
let ct = self.dynamic_nodes.len();
|
let ct = self.dynamic_nodes.len();
|
||||||
self.dynamic_nodes.push(root);
|
self.dynamic_nodes.push(root);
|
||||||
|
self.node_paths.push(self.current_path.clone());
|
||||||
quote! { ::dioxus::core::TemplateNode::Dynamic(#ct) }
|
quote! { ::dioxus::core::TemplateNode::Dynamic(#ct) }
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -72,7 +72,7 @@ impl StringCache {
|
|||||||
TemplateAttribute::Static { name, value, .. } => {
|
TemplateAttribute::Static { name, value, .. } => {
|
||||||
write!(chain, " {}=\"{}\"", name, value)?;
|
write!(chain, " {}=\"{}\"", name, value)?;
|
||||||
}
|
}
|
||||||
TemplateAttribute::Dynamic { index, .. } => {
|
TemplateAttribute::Dynamic(index) => {
|
||||||
chain.segments.push(Segment::Attr(*index))
|
chain.segments.push(Segment::Attr(*index))
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -126,18 +126,18 @@ impl SsrRender {
|
|||||||
_ => {}
|
_ => {}
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
Segment::Node(idx) => match &template.dynamic_nodes[*idx].kind {
|
Segment::Node(idx) => match &template.dynamic_nodes[*idx] {
|
||||||
DynamicNodeKind::Text { value, .. } => {
|
DynamicNode::Text { value, .. } => {
|
||||||
// todo: escape the text
|
// todo: escape the text
|
||||||
write!(buf, "{}", value)?
|
write!(buf, "{}", value)?
|
||||||
}
|
}
|
||||||
DynamicNodeKind::Fragment { children } => {
|
DynamicNode::Fragment { children } => {
|
||||||
for child in *children {
|
for child in *children {
|
||||||
self.render_template(buf, child)?;
|
self.render_template(buf, child)?;
|
||||||
}
|
}
|
||||||
//
|
//
|
||||||
}
|
}
|
||||||
DynamicNodeKind::Component { .. } => {
|
DynamicNode::Component { .. } => {
|
||||||
//
|
//
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
@@ -194,10 +194,7 @@ fn children_processes_properly() {
|
|||||||
render! {
|
render! {
|
||||||
div {
|
div {
|
||||||
ChildWithChildren {
|
ChildWithChildren {
|
||||||
p {
|
p { "{d}" "hii" }
|
||||||
"{d}"
|
|
||||||
"hii"
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
Reference in new issue
Block a user