make the macro compile
This commit is contained in:
1 parent
53094a7bbd
commit
29a61b1855
8 files changed
+1092
-1112
No files matched your search
@@ -148,16 +148,12 @@ fn impl_derive_macro(ast: &syn::DeriveInput) -> TokenStream {
|
|||||||
let strct = Struct::new(type_name.clone(), &fields);
|
let strct = Struct::new(type_name.clone(), &fields);
|
||||||
match StateStruct::parse(&fields, &strct) {
|
match StateStruct::parse(&fields, &strct) {
|
||||||
Ok(state_strct) => {
|
Ok(state_strct) => {
|
||||||
let members: Vec<_> = state_strct
|
let member_types1 = state_strct.state_members.iter().map(|m| &m.mem.ty);
|
||||||
.state_members
|
let member_types2 = state_strct.state_members.iter().map(|m| &m.mem.ty);
|
||||||
.iter()
|
|
||||||
.map(|m| &m.mem.ident)
|
|
||||||
.collect();
|
|
||||||
let member_types = state_strct.state_members.iter().map(|m| &m.mem.ty);
|
|
||||||
let impl_members = state_strct
|
let impl_members = state_strct
|
||||||
.state_members
|
.state_members
|
||||||
.iter()
|
.iter()
|
||||||
.map(|m| state_strct.impl_pass(m));
|
.map(|m| m.impl_pass(state_strct.ty));
|
||||||
|
|
||||||
// let child_types = state_strct.child_states.iter().map(|s| &s.ty);
|
// let child_types = state_strct.child_states.iter().map(|s| &s.ty);
|
||||||
// let child_members = state_strct.child_states.iter().map(|s| &s.ident);
|
// let child_members = state_strct.child_states.iter().map(|s| &s.ident);
|
||||||
@@ -165,10 +161,10 @@ fn impl_derive_macro(ast: &syn::DeriveInput) -> TokenStream {
|
|||||||
let gen = quote! {
|
let gen = quote! {
|
||||||
#(#impl_members)*
|
#(#impl_members)*
|
||||||
impl State for #type_name {
|
impl State for #type_name {
|
||||||
const PASSES: &'static [AnyPass<Node<Self>>] = &[
|
const PASSES: &'static [dioxus_native_core::AnyPass<dioxus_native_core::node::Node<Self>>] = &[
|
||||||
AnyPass(#(&#member_types),*)
|
#(dioxus_native_core::AnyPass(&#member_types1)),*
|
||||||
];
|
];
|
||||||
const MASKS: &'static [NodeMask] = &[#(#member_types::NODE_MASK),*];
|
const MASKS: &'static [dioxus_native_core::NodeMask] = &[#(#member_types2::NODE_MASK),*];
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
gen.into()
|
gen.into()
|
||||||
@@ -177,12 +173,6 @@ fn impl_derive_macro(ast: &syn::DeriveInput) -> TokenStream {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
struct Depenadants<'a> {
|
|
||||||
node: Vec<&'a Member>,
|
|
||||||
child: Vec<&'a Member>,
|
|
||||||
parent: Vec<&'a Member>,
|
|
||||||
}
|
|
||||||
|
|
||||||
struct Struct {
|
struct Struct {
|
||||||
name: Ident,
|
name: Ident,
|
||||||
members: Vec<Member>,
|
members: Vec<Member>,
|
||||||
@@ -201,7 +191,9 @@ impl Struct {
|
|||||||
|
|
||||||
struct StateStruct<'a> {
|
struct StateStruct<'a> {
|
||||||
state_members: Vec<StateMember<'a>>,
|
state_members: Vec<StateMember<'a>>,
|
||||||
|
#[allow(unused)]
|
||||||
child_states: Vec<&'a Member>,
|
child_states: Vec<&'a Member>,
|
||||||
|
ty: &'a Ident,
|
||||||
}
|
}
|
||||||
|
|
||||||
impl<'a> StateStruct<'a> {
|
impl<'a> StateStruct<'a> {
|
||||||
@@ -222,7 +214,7 @@ impl<'a> StateStruct<'a> {
|
|||||||
.collect();
|
.collect();
|
||||||
parse_err?;
|
parse_err?;
|
||||||
for i in 0..state_members.len() {
|
for i in 0..state_members.len() {
|
||||||
let deps = state_members[i].dep_mems.clone();
|
let deps: Vec<_> = state_members[i].dep_mems.iter().map(|m| m.id).collect();
|
||||||
for dep in deps {
|
for dep in deps {
|
||||||
state_members[dep as usize].dependant_mems.push(i as u64);
|
state_members[dep as usize].dependant_mems.push(i as u64);
|
||||||
}
|
}
|
||||||
@@ -244,30 +236,11 @@ impl<'a> StateStruct<'a> {
|
|||||||
|
|
||||||
// members need to be sorted so that members are updated after the members they depend on
|
// members need to be sorted so that members are updated after the members they depend on
|
||||||
Ok(Self {
|
Ok(Self {
|
||||||
|
ty: &strct.name,
|
||||||
state_members,
|
state_members,
|
||||||
child_states: child_states.collect(),
|
child_states: child_states.collect(),
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
|
|
||||||
fn get_depenadants(&self, mem: &Member) -> Depenadants {
|
|
||||||
let mut dependants = Depenadants {
|
|
||||||
node: Vec::new(),
|
|
||||||
child: Vec::new(),
|
|
||||||
parent: Vec::new(),
|
|
||||||
};
|
|
||||||
for member in &self.state_members {
|
|
||||||
for (dep, _) in &member.dep_mems {
|
|
||||||
if *dep == mem {
|
|
||||||
match member.dep_kind {
|
|
||||||
DependencyKind::Node => dependants.node.push(member.mem),
|
|
||||||
DependencyKind::Child => dependants.child.push(member.mem),
|
|
||||||
DependencyKind::Parent => dependants.parent.push(member.mem),
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
dependants
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
fn try_parenthesized(input: ParseStream) -> Result<ParseBuffer> {
|
fn try_parenthesized(input: ParseStream) -> Result<ParseBuffer> {
|
||||||
@@ -331,7 +304,7 @@ struct StateMember<'a> {
|
|||||||
// the kind of dependncies this state has
|
// the kind of dependncies this state has
|
||||||
dep_kind: DependencyKind,
|
dep_kind: DependencyKind,
|
||||||
// the depenancy and if it is satified
|
// the depenancy and if it is satified
|
||||||
dep_mems: Vec<u64>,
|
dep_mems: Vec<&'a Member>,
|
||||||
// any members that depend on this member
|
// any members that depend on this member
|
||||||
dependant_mems: Vec<u64>,
|
dependant_mems: Vec<u64>,
|
||||||
// the context this state requires
|
// the context this state requires
|
||||||
@@ -362,7 +335,7 @@ impl<'a> StateMember<'a> {
|
|||||||
.iter()
|
.iter()
|
||||||
.filter_map(|name| {
|
.filter_map(|name| {
|
||||||
if let Some(found) = parent.members.iter().find(|m| &m.ident == name) {
|
if let Some(found) = parent.members.iter().find(|m| &m.ident == name) {
|
||||||
Some((found.id, false))
|
Some(found)
|
||||||
} else {
|
} else {
|
||||||
err = Err(Error::new(
|
err = Err(Error::new(
|
||||||
name.span(),
|
name.span(),
|
||||||
@@ -391,9 +364,8 @@ impl<'a> StateMember<'a> {
|
|||||||
}
|
}
|
||||||
|
|
||||||
/// generate code to call the resolve function for the state. This does not handle checking if resolving the state is necessary, or marking the states that depend on this state as dirty.
|
/// generate code to call the resolve function for the state. This does not handle checking if resolving the state is necessary, or marking the states that depend on this state as dirty.
|
||||||
fn impl_pass(&self, parent_type: Type) -> quote::__private::TokenStream {
|
fn impl_pass(&self, parent_type: &Ident) -> quote::__private::TokenStream {
|
||||||
let ident = &self.mem.ident;
|
let ident = &self.mem.ident;
|
||||||
let ty = &self.mem.ty;
|
|
||||||
let get_ctx = if let Some(ctx_ty) = &self.ctx_ty {
|
let get_ctx = if let Some(ctx_ty) = &self.ctx_ty {
|
||||||
if ctx_ty == &parse_quote!(()) {
|
if ctx_ty == &parse_quote!(()) {
|
||||||
quote! {&()}
|
quote! {&()}
|
||||||
@@ -407,7 +379,7 @@ impl<'a> StateMember<'a> {
|
|||||||
|
|
||||||
let ty = &self.mem.ty;
|
let ty = &self.mem.ty;
|
||||||
let node_view = quote!(dioxus_native_core::node_ref::NodeView::new(unsafe{&*{&node.node_data as *const _}}, #ty::NODE_MASK));
|
let node_view = quote!(dioxus_native_core::node_ref::NodeView::new(unsafe{&*{&node.node_data as *const _}}, #ty::NODE_MASK));
|
||||||
let dep_idents = self.dep_mems.iter().map(|m| &m.0.ident);
|
let dep_idents = self.dep_mems.iter().map(|m| &m.ident);
|
||||||
let impl_specific = match self.dep_kind {
|
let impl_specific = match self.dep_kind {
|
||||||
DependencyKind::Node => {
|
DependencyKind::Node => {
|
||||||
quote! {
|
quote! {
|
||||||
@@ -419,7 +391,7 @@ impl<'a> StateMember<'a> {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
DependencyKind::Child => {
|
DependencyKind::Child => {
|
||||||
let update = if self.dep_mems.iter().any(|id| id == self.mem.id) {
|
let update = if self.dep_mems.iter().any(|m| m.id == self.mem.id) {
|
||||||
quote! {
|
quote! {
|
||||||
if update {
|
if update {
|
||||||
PassReturn{
|
PassReturn{
|
||||||
@@ -463,7 +435,7 @@ impl<'a> StateMember<'a> {
|
|||||||
)
|
)
|
||||||
}
|
}
|
||||||
DependencyKind::Parent => {
|
DependencyKind::Parent => {
|
||||||
let update = if self.dep_mems.iter().any(|id| id == self.mem.id) {
|
let update = if self.dep_mems.iter().any(|m| m.id == self.mem.id) {
|
||||||
quote! {
|
quote! {
|
||||||
if update {
|
if update {
|
||||||
PassReturn{
|
PassReturn{
|
||||||
@@ -503,12 +475,12 @@ impl<'a> StateMember<'a> {
|
|||||||
}
|
}
|
||||||
};
|
};
|
||||||
let pass_id = self.mem.id;
|
let pass_id = self.mem.id;
|
||||||
let depenancies = &self.dep_mems;
|
let depenancies = self.dep_mems.iter().map(|m| m.id);
|
||||||
let dependants = &self.dependant_mems;
|
let dependants = &self.dependant_mems;
|
||||||
let mask = self
|
let mask = self
|
||||||
.dep_mems
|
.dep_mems
|
||||||
.iter()
|
.iter()
|
||||||
.map(|m| m.0.id)
|
.map(|m| m.id)
|
||||||
.fold(self.mem.id, |a, b| a | b);
|
.fold(self.mem.id, |a, b| a | b);
|
||||||
quote! {
|
quote! {
|
||||||
#impl_specific
|
#impl_specific
|
||||||
|
|||||||
@@ -1,255 +1,246 @@
|
|||||||
use anymap::AnyMap;
|
// use anymap::AnyMap;
|
||||||
use dioxus::prelude::*;
|
// use dioxus::prelude::*;
|
||||||
use dioxus_native_core::node_ref::*;
|
// use dioxus_native_core::node_ref::*;
|
||||||
use dioxus_native_core::real_dom::*;
|
// use dioxus_native_core::real_dom::*;
|
||||||
use dioxus_native_core::state::{ChildDepState, NodeDepState, ParentDepState, State};
|
// use dioxus_native_core::state::{ChildDepState, NodeDepState, ParentDepState, State};
|
||||||
use dioxus_native_core_macro::State;
|
// use dioxus_native_core_macro::State;
|
||||||
|
|
||||||
macro_rules! dep {
|
// macro_rules! dep {
|
||||||
( child( $name:ty, $dep:ty ) ) => {
|
// ( child( $name:ty, $dep:ty ) ) => {
|
||||||
impl ChildDepState for $name {
|
// impl ChildDepState for $name {
|
||||||
type Ctx = ();
|
// type Ctx = ();
|
||||||
type DepState = $dep;
|
// type DepState = $dep;
|
||||||
const NODE_MASK: NodeMask = NodeMask::ALL;
|
// const NODE_MASK: NodeMask = NodeMask::ALL;
|
||||||
fn reduce<'a>(
|
// fn reduce<'a>(
|
||||||
&mut self,
|
// &mut self,
|
||||||
_: NodeView,
|
// _: NodeView,
|
||||||
_: impl Iterator<Item = &'a Self::DepState>,
|
// _: impl Iterator<Item = &'a Self::DepState>,
|
||||||
_: &Self::Ctx,
|
// _: &Self::Ctx,
|
||||||
) -> bool
|
// ) -> bool
|
||||||
where
|
// where
|
||||||
Self::DepState: 'a,
|
// Self::DepState: 'a,
|
||||||
{
|
// {
|
||||||
self.0 += 1;
|
// self.0 += 1;
|
||||||
true
|
// true
|
||||||
}
|
// }
|
||||||
}
|
// }
|
||||||
};
|
// };
|
||||||
|
|
||||||
( parent( $name:ty, $dep:ty ) ) => {
|
// ( parent( $name:ty, $dep:ty ) ) => {
|
||||||
impl ParentDepState for $name {
|
// impl ParentDepState for $name {
|
||||||
type Ctx = ();
|
// type Ctx = ();
|
||||||
type DepState = $dep;
|
// type DepState = $dep;
|
||||||
const NODE_MASK: NodeMask = NodeMask::ALL;
|
// const NODE_MASK: NodeMask = NodeMask::ALL;
|
||||||
fn reduce(
|
// fn reduce(&mut self, _: NodeView, _: Option<&Self::DepState>, _: &Self::Ctx) -> bool {
|
||||||
&mut self,
|
// self.0 += 1;
|
||||||
_: NodeView,
|
// true
|
||||||
_: Option<&Self::DepState>,
|
// }
|
||||||
_: &Self::Ctx,
|
// }
|
||||||
) -> bool {
|
// };
|
||||||
self.0 += 1;
|
|
||||||
true
|
|
||||||
}
|
|
||||||
}
|
|
||||||
};
|
|
||||||
|
|
||||||
( node( $name:ty, ($($l:lifetime),*), $dep:ty ) ) => {
|
// ( node( $name:ty, $dep:ty ) ) => {
|
||||||
impl<$($l),*> NodeDepState<$dep> for $name {
|
// impl NodeDepState for $name {
|
||||||
type Ctx = ();
|
// type Ctx = ();
|
||||||
const NODE_MASK: NodeMask = NodeMask::ALL;
|
// type DepState<'a> = $dep;
|
||||||
fn reduce(
|
// const NODE_MASK: NodeMask = NodeMask::ALL;
|
||||||
&mut self,
|
// fn reduce(&mut self, _: NodeView, _: $dep, _: &Self::Ctx) -> bool {
|
||||||
_: NodeView,
|
// self.0 += 1;
|
||||||
_: $dep,
|
// true
|
||||||
_: &Self::Ctx,
|
// }
|
||||||
) -> bool {
|
// }
|
||||||
self.0 += 1;
|
// };
|
||||||
true
|
// }
|
||||||
}
|
|
||||||
}
|
|
||||||
};
|
|
||||||
}
|
|
||||||
|
|
||||||
macro_rules! test_state{
|
// macro_rules! test_state{
|
||||||
( $s:ty, child: ( $( $child:ident ),* ), node: ( $( $node:ident ),* ), parent: ( $( $parent:ident ),* ) ) => {
|
// ( $s:ty, child: ( $( $child:ident ),* ), node: ( $( $node:ident ),* ), parent: ( $( $parent:ident ),* ) ) => {
|
||||||
#[test]
|
// #[test]
|
||||||
fn state_reduce_initally_called_minimally() {
|
// fn state_reduce_initally_called_minimally() {
|
||||||
#[allow(non_snake_case)]
|
// #[allow(non_snake_case)]
|
||||||
fn Base(cx: Scope) -> Element {
|
// fn Base(cx: Scope) -> Element {
|
||||||
render!(div {
|
// render!(div {
|
||||||
div{
|
// div{
|
||||||
div{
|
// div{
|
||||||
p{}
|
// p{}
|
||||||
}
|
// }
|
||||||
p{
|
// p{
|
||||||
"hello"
|
// "hello"
|
||||||
}
|
// }
|
||||||
div{
|
// div{
|
||||||
h1{}
|
// h1{}
|
||||||
}
|
// }
|
||||||
p{
|
// p{
|
||||||
"world"
|
// "world"
|
||||||
}
|
// }
|
||||||
}
|
// }
|
||||||
})
|
// })
|
||||||
}
|
// }
|
||||||
|
|
||||||
let vdom = VirtualDom::new(Base);
|
// let vdom = VirtualDom::new(Base);
|
||||||
|
|
||||||
let mutations = vdom.create_vnodes(rsx! {
|
// let mutations = vdom.create_vnodes(rsx! {
|
||||||
div {
|
// div {
|
||||||
div{
|
// div{
|
||||||
div{
|
// div{
|
||||||
p{}
|
// p{}
|
||||||
}
|
// }
|
||||||
p{
|
// p{
|
||||||
"hello"
|
// "hello"
|
||||||
}
|
// }
|
||||||
div{
|
// div{
|
||||||
h1{}
|
// h1{}
|
||||||
}
|
// }
|
||||||
p{
|
// p{
|
||||||
"world"
|
// "world"
|
||||||
}
|
// }
|
||||||
}
|
// }
|
||||||
}
|
// }
|
||||||
});
|
// });
|
||||||
|
|
||||||
let mut dom: RealDom<$s> = RealDom::new();
|
// let mut dom: RealDom<$s> = RealDom::new();
|
||||||
|
|
||||||
let nodes_updated = dom.apply_mutations(vec![mutations]);
|
// let nodes_updated = dom.apply_mutations(vec![mutations]);
|
||||||
let _to_rerender = dom.update_state(nodes_updated, AnyMap::new());
|
// let _to_rerender = dom.update_state(nodes_updated, AnyMap::new());
|
||||||
|
|
||||||
dom.traverse_depth_first(|n| {
|
// dom.traverse_depth_first(|n| {
|
||||||
$(
|
// $(
|
||||||
assert_eq!(n.state.$child.0, 1);
|
// assert_eq!(n.state.$child.0, 1);
|
||||||
)*
|
// )*
|
||||||
$(
|
// $(
|
||||||
assert_eq!(n.state.$node.0, 1);
|
// assert_eq!(n.state.$node.0, 1);
|
||||||
)*
|
// )*
|
||||||
$(
|
// $(
|
||||||
assert_eq!(n.state.$parent.0, 1);
|
// assert_eq!(n.state.$parent.0, 1);
|
||||||
)*
|
// )*
|
||||||
});
|
// });
|
||||||
}
|
// }
|
||||||
}
|
// }
|
||||||
}
|
// }
|
||||||
|
|
||||||
mod node_depends_on_child_and_parent {
|
// mod node_depends_on_child_and_parent {
|
||||||
use super::*;
|
// use super::*;
|
||||||
#[derive(Debug, Clone, Default, PartialEq)]
|
// #[derive(Debug, Clone, Default, PartialEq)]
|
||||||
struct Node(i32);
|
// struct Node(i32);
|
||||||
dep!(node(Node, ('a, 'b), (&'a Child, &'b Parent)));
|
// dep!(node(Node, (&'a Child, &'a Parent)));
|
||||||
|
|
||||||
#[derive(Debug, Clone, Default, PartialEq)]
|
// #[derive(Debug, Clone, Default, PartialEq)]
|
||||||
struct Child(i32);
|
// struct Child(i32);
|
||||||
dep!(child(Child, Child));
|
// dep!(child(Child, Child));
|
||||||
|
|
||||||
#[derive(Debug, Clone, Default, PartialEq)]
|
// #[derive(Debug, Clone, Default, PartialEq)]
|
||||||
struct Parent(i32);
|
// struct Parent(i32);
|
||||||
dep!(parent(Parent, Parent));
|
// dep!(parent(Parent, Parent));
|
||||||
|
|
||||||
#[derive(Debug, Clone, Default, State)]
|
// #[derive(Debug, Clone, Default, State)]
|
||||||
struct StateTester {
|
// struct StateTester {
|
||||||
#[node_dep_state((child, parent))]
|
// #[node_dep_state((child, parent))]
|
||||||
node: Node,
|
// node: Node,
|
||||||
#[child_dep_state(child)]
|
// #[child_dep_state(child)]
|
||||||
child: Child,
|
// child: Child,
|
||||||
#[parent_dep_state(parent)]
|
// #[parent_dep_state(parent)]
|
||||||
parent: Parent,
|
// parent: Parent,
|
||||||
}
|
// }
|
||||||
|
|
||||||
test_state!(StateTester, child: (child), node: (node), parent: (parent));
|
// test_state!(StateTester, child: (child), node: (node), parent: (parent));
|
||||||
}
|
// }
|
||||||
|
|
||||||
mod child_depends_on_node_that_depends_on_parent {
|
// mod child_depends_on_node_that_depends_on_parent {
|
||||||
use super::*;
|
// use super::*;
|
||||||
#[derive(Debug, Clone, Default, PartialEq)]
|
// #[derive(Debug, Clone, Default, PartialEq)]
|
||||||
struct Node(i32);
|
// struct Node(i32);
|
||||||
dep!(node(Node, ('a), (&'a Parent,)));
|
// dep!(node(Node, (&'a Parent,)));
|
||||||
|
|
||||||
#[derive(Debug, Clone, Default, PartialEq)]
|
// #[derive(Debug, Clone, Default, PartialEq)]
|
||||||
struct Child(i32);
|
// struct Child(i32);
|
||||||
dep!(child(Child, Node));
|
// dep!(child(Child, Node));
|
||||||
|
|
||||||
#[derive(Debug, Clone, Default, PartialEq)]
|
// #[derive(Debug, Clone, Default, PartialEq)]
|
||||||
struct Parent(i32);
|
// struct Parent(i32);
|
||||||
dep!(parent(Parent, Parent));
|
// dep!(parent(Parent, Parent));
|
||||||
|
|
||||||
#[derive(Debug, Clone, Default, State)]
|
// #[derive(Debug, Clone, Default, State)]
|
||||||
struct StateTester {
|
// struct StateTester {
|
||||||
#[node_dep_state(parent)]
|
// #[node_dep_state(parent)]
|
||||||
node: Node,
|
// node: Node,
|
||||||
#[child_dep_state(node)]
|
// #[child_dep_state(node)]
|
||||||
child: Child,
|
// child: Child,
|
||||||
#[parent_dep_state(parent)]
|
// #[parent_dep_state(parent)]
|
||||||
parent: Parent,
|
// parent: Parent,
|
||||||
}
|
// }
|
||||||
|
|
||||||
test_state!(StateTester, child: (child), node: (node), parent: (parent));
|
// test_state!(StateTester, child: (child), node: (node), parent: (parent));
|
||||||
}
|
// }
|
||||||
|
|
||||||
mod parent_depends_on_node_that_depends_on_child {
|
// mod parent_depends_on_node_that_depends_on_child {
|
||||||
use super::*;
|
// use super::*;
|
||||||
#[derive(Debug, Clone, Default, PartialEq)]
|
// #[derive(Debug, Clone, Default, PartialEq)]
|
||||||
struct Node(i32);
|
// struct Node(i32);
|
||||||
dep!(node(Node, ('a), (&'a Child,)));
|
// dep!(node(Node, (&'a Child,)));
|
||||||
|
|
||||||
#[derive(Debug, Clone, Default, PartialEq)]
|
// #[derive(Debug, Clone, Default, PartialEq)]
|
||||||
struct Child(i32);
|
// struct Child(i32);
|
||||||
dep!(child(Child, Child));
|
// dep!(child(Child, Child));
|
||||||
|
|
||||||
#[derive(Debug, Clone, Default, PartialEq)]
|
// #[derive(Debug, Clone, Default, PartialEq)]
|
||||||
struct Parent(i32);
|
// struct Parent(i32);
|
||||||
dep!(parent(Parent, Node));
|
// dep!(parent(Parent, Node));
|
||||||
|
|
||||||
#[derive(Debug, Clone, Default, State)]
|
// #[derive(Debug, Clone, Default, State)]
|
||||||
struct StateTester {
|
// struct StateTester {
|
||||||
#[node_dep_state(child)]
|
// #[node_dep_state(child)]
|
||||||
node: Node,
|
// node: Node,
|
||||||
#[child_dep_state(child)]
|
// #[child_dep_state(child)]
|
||||||
child: Child,
|
// child: Child,
|
||||||
#[parent_dep_state(node)]
|
// #[parent_dep_state(node)]
|
||||||
parent: Parent,
|
// parent: Parent,
|
||||||
}
|
// }
|
||||||
|
|
||||||
test_state!(StateTester, child: (child), node: (node), parent: (parent));
|
// test_state!(StateTester, child: (child), node: (node), parent: (parent));
|
||||||
}
|
// }
|
||||||
|
|
||||||
mod node_depends_on_other_node_state {
|
// mod node_depends_on_other_node_state {
|
||||||
use super::*;
|
// use super::*;
|
||||||
#[derive(Debug, Clone, Default, PartialEq)]
|
// #[derive(Debug, Clone, Default, PartialEq)]
|
||||||
struct Node1(i32);
|
// struct Node1(i32);
|
||||||
dep!(node(Node1, ('a), (&'a Node2,)));
|
// dep!(node(Node1, (&'a Node2,)));
|
||||||
|
|
||||||
#[derive(Debug, Clone, Default, PartialEq)]
|
// #[derive(Debug, Clone, Default, PartialEq)]
|
||||||
struct Node2(i32);
|
// struct Node2(i32);
|
||||||
dep!(node(Node2, (), ()));
|
// dep!(node(Node2, ()));
|
||||||
|
|
||||||
#[derive(Debug, Clone, Default, State)]
|
// #[derive(Debug, Clone, Default, State)]
|
||||||
struct StateTester {
|
// struct StateTester {
|
||||||
#[node_dep_state((node2))]
|
// #[node_dep_state((node2))]
|
||||||
node1: Node1,
|
// node1: Node1,
|
||||||
#[node_dep_state()]
|
// #[node_dep_state()]
|
||||||
node2: Node2,
|
// node2: Node2,
|
||||||
}
|
// }
|
||||||
|
|
||||||
test_state!(StateTester, child: (), node: (node1, node2), parent: ());
|
// test_state!(StateTester, child: (), node: (node1, node2), parent: ());
|
||||||
}
|
// }
|
||||||
|
|
||||||
mod node_child_and_parent_state_depends_on_self {
|
// mod node_child_and_parent_state_depends_on_self {
|
||||||
use super::*;
|
// use super::*;
|
||||||
#[derive(Debug, Clone, Default, PartialEq)]
|
// #[derive(Debug, Clone, Default, PartialEq)]
|
||||||
struct Node(i32);
|
// struct Node(i32);
|
||||||
dep!(node(Node, (), ()));
|
// dep!(node(Node, ()));
|
||||||
|
|
||||||
#[derive(Debug, Clone, Default, PartialEq)]
|
// #[derive(Debug, Clone, Default, PartialEq)]
|
||||||
struct Child(i32);
|
// struct Child(i32);
|
||||||
dep!(child(Child, Child));
|
// dep!(child(Child, Child));
|
||||||
|
|
||||||
#[derive(Debug, Clone, Default, PartialEq)]
|
// #[derive(Debug, Clone, Default, PartialEq)]
|
||||||
struct Parent(i32);
|
// struct Parent(i32);
|
||||||
dep!(parent(Parent, Parent));
|
// dep!(parent(Parent, Parent));
|
||||||
|
|
||||||
#[derive(Debug, Clone, Default, State)]
|
// #[derive(Debug, Clone, Default, State)]
|
||||||
struct StateTester {
|
// struct StateTester {
|
||||||
#[node_dep_state()]
|
// #[node_dep_state()]
|
||||||
node: Node,
|
// node: Node,
|
||||||
#[child_dep_state(child)]
|
// #[child_dep_state(child)]
|
||||||
child: Child,
|
// child: Child,
|
||||||
#[parent_dep_state(parent)]
|
// #[parent_dep_state(parent)]
|
||||||
parent: Parent,
|
// parent: Parent,
|
||||||
}
|
// }
|
||||||
|
|
||||||
test_state!(StateTester, child: (child), node: (node), parent: (parent));
|
// test_state!(StateTester, child: (child), node: (node), parent: (parent));
|
||||||
}
|
// }
|
||||||
@@ -2,7 +2,8 @@ use dioxus::core::ElementId;
|
|||||||
use dioxus::prelude::*;
|
use dioxus::prelude::*;
|
||||||
use dioxus_native_core::real_dom::RealDom;
|
use dioxus_native_core::real_dom::RealDom;
|
||||||
use dioxus_native_core::state::State;
|
use dioxus_native_core::state::State;
|
||||||
use dioxus_native_core::RealNodeId;
|
use dioxus_native_core::tree::*;
|
||||||
|
use dioxus_native_core::NodeId;
|
||||||
use dioxus_native_core_macro::State;
|
use dioxus_native_core_macro::State;
|
||||||
|
|
||||||
#[derive(State, Default, Clone)]
|
#[derive(State, Default, Clone)]
|
||||||
@@ -34,13 +35,13 @@ fn remove_node() {
|
|||||||
|
|
||||||
let _to_update = dom.apply_mutations(vec![create]);
|
let _to_update = dom.apply_mutations(vec![create]);
|
||||||
|
|
||||||
assert_eq!(dom[RealNodeId::ElementId(ElementId(0))].node_data.height, 0);
|
assert_eq!(dom.tree.height(NodeId(0)), Some(0));
|
||||||
assert_eq!(dom[RealNodeId::UnaccessableId(0)].node_data.height, 1);
|
assert_eq!(dom.tree.height(NodeId(1)), Some(1));
|
||||||
|
|
||||||
dom.apply_mutations(vec![edit]);
|
dom.apply_mutations(vec![edit]);
|
||||||
|
|
||||||
assert_eq!(dom.size(), 3);
|
assert_eq!(dom.size(), 3);
|
||||||
assert_eq!(dom[RealNodeId::ElementId(ElementId(0))].node_data.height, 0);
|
assert_eq!(dom.tree.height(NodeId(0)), Some(0));
|
||||||
}
|
}
|
||||||
|
|
||||||
#[test]
|
#[test]
|
||||||
@@ -68,11 +69,11 @@ fn add_node() {
|
|||||||
let _to_update = dom.apply_mutations(vec![create]);
|
let _to_update = dom.apply_mutations(vec![create]);
|
||||||
|
|
||||||
assert_eq!(dom.size(), 2);
|
assert_eq!(dom.size(), 2);
|
||||||
assert_eq!(dom[RealNodeId::ElementId(ElementId(2))].node_data.height, 1);
|
assert_eq!(dom.tree.height(NodeId(2)), Some(1));
|
||||||
|
|
||||||
dom.apply_mutations(vec![update]);
|
dom.apply_mutations(vec![update]);
|
||||||
|
|
||||||
assert_eq!(dom.size(), 3);
|
assert_eq!(dom.size(), 3);
|
||||||
assert_eq!(dom[RealNodeId::ElementId(ElementId(3))].node_data.height, 0);
|
assert_eq!(dom.tree.height(NodeId(3)), Some(0));
|
||||||
assert_eq!(dom[RealNodeId::UnaccessableId(0)].node_data.height, 1);
|
assert_eq!(dom.tree.height(NodeId(0)), Some(1));
|
||||||
}
|
}
|
||||||
@@ -1,63 +1,63 @@
|
|||||||
use dioxus::core::ElementId;
|
// use dioxus::core::ElementId;
|
||||||
use dioxus::prelude::*;
|
// use dioxus::prelude::*;
|
||||||
use dioxus_native_core::real_dom::RealDom;
|
// use dioxus_native_core::real_dom::RealDom;
|
||||||
use dioxus_native_core::state::State;
|
// use dioxus_native_core::state::State;
|
||||||
use dioxus_native_core::RealNodeId;
|
// use dioxus_native_core::RealNodeId;
|
||||||
use dioxus_native_core_macro::State;
|
// use dioxus_native_core_macro::State;
|
||||||
|
|
||||||
#[derive(Default, Clone, State)]
|
// #[derive(Default, Clone, State)]
|
||||||
struct Empty {}
|
// struct Empty {}
|
||||||
|
|
||||||
#[test]
|
// #[test]
|
||||||
fn initial_build_simple() {
|
// fn initial_build_simple() {
|
||||||
#[allow(non_snake_case)]
|
// #[allow(non_snake_case)]
|
||||||
fn Base(cx: Scope) -> Element {
|
// fn Base(cx: Scope) -> Element {
|
||||||
render!(div {})
|
// render!(div {})
|
||||||
}
|
// }
|
||||||
|
|
||||||
let vdom = VirtualDom::new(Base);
|
// let vdom = VirtualDom::new(Base);
|
||||||
|
|
||||||
let mutations = vdom.create_vnodes(rsx! {
|
// let mutations = vdom.create_vnodes(rsx! {
|
||||||
div{}
|
// div{}
|
||||||
});
|
// });
|
||||||
|
|
||||||
let mut dom: RealDom<Empty> = RealDom::new();
|
// let mut dom: RealDom<Empty> = RealDom::new();
|
||||||
|
|
||||||
let _to_update = dom.apply_mutations(vec![mutations]);
|
// let _to_update = dom.apply_mutations(vec![mutations]);
|
||||||
|
|
||||||
assert_eq!(dom.size(), 2);
|
// assert_eq!(dom.size(), 2);
|
||||||
assert_eq!(dom[RealNodeId::ElementId(ElementId(2))].node_data.height, 1);
|
// assert_eq!(dom[RealNodeId::ElementId(ElementId(2))].node_data.height, 1);
|
||||||
}
|
// }
|
||||||
|
|
||||||
#[test]
|
// #[test]
|
||||||
fn initial_build_with_children() {
|
// fn initial_build_with_children() {
|
||||||
#[allow(non_snake_case)]
|
// #[allow(non_snake_case)]
|
||||||
fn Base(cx: Scope) -> Element {
|
// fn Base(cx: Scope) -> Element {
|
||||||
render!(div {})
|
// render!(div {})
|
||||||
}
|
// }
|
||||||
|
|
||||||
let vdom = VirtualDom::new(Base);
|
// let vdom = VirtualDom::new(Base);
|
||||||
|
|
||||||
let mutations = vdom.create_vnodes(rsx! {
|
// let mutations = vdom.create_vnodes(rsx! {
|
||||||
div{
|
// div{
|
||||||
div{
|
// div{
|
||||||
"hello"
|
// "hello"
|
||||||
p{
|
// p{
|
||||||
"world"
|
// "world"
|
||||||
}
|
// }
|
||||||
"hello world"
|
// "hello world"
|
||||||
}
|
// }
|
||||||
}
|
// }
|
||||||
});
|
// });
|
||||||
|
|
||||||
let mut dom: RealDom<Empty> = RealDom::new();
|
// let mut dom: RealDom<Empty> = RealDom::new();
|
||||||
|
|
||||||
let _to_update = dom.apply_mutations(vec![mutations]);
|
// let _to_update = dom.apply_mutations(vec![mutations]);
|
||||||
assert_eq!(dom.size(), 2);
|
// assert_eq!(dom.size(), 2);
|
||||||
assert_eq!(dom[RealNodeId::ElementId(ElementId(2))].node_data.height, 1);
|
// assert_eq!(dom[RealNodeId::ElementId(ElementId(2))].node_data.height, 1);
|
||||||
assert_eq!(dom[RealNodeId::UnaccessableId(6)].node_data.height, 2);
|
// assert_eq!(dom[RealNodeId::UnaccessableId(6)].node_data.height, 2);
|
||||||
assert_eq!(dom[RealNodeId::UnaccessableId(5)].node_data.height, 3);
|
// assert_eq!(dom[RealNodeId::UnaccessableId(5)].node_data.height, 3);
|
||||||
assert_eq!(dom[RealNodeId::UnaccessableId(8)].node_data.height, 3);
|
// assert_eq!(dom[RealNodeId::UnaccessableId(8)].node_data.height, 3);
|
||||||
assert_eq!(dom[RealNodeId::UnaccessableId(10)].node_data.height, 3);
|
// assert_eq!(dom[RealNodeId::UnaccessableId(10)].node_data.height, 3);
|
||||||
assert_eq!(dom[RealNodeId::UnaccessableId(9)].node_data.height, 4);
|
// assert_eq!(dom[RealNodeId::UnaccessableId(9)].node_data.height, 4);
|
||||||
}
|
// }
|
||||||
@@ -1,333 +1,333 @@
|
|||||||
use dioxus::core_macro::rsx_without_templates;
|
// use dioxus::core_macro::rsx_without_templates;
|
||||||
use dioxus::prelude::*;
|
// use dioxus::prelude::*;
|
||||||
use dioxus_native_core::{
|
// use dioxus_native_core::{
|
||||||
real_dom::{NodeType, RealDom},
|
// real_dom::{NodeType, RealDom},
|
||||||
state::State,
|
// state::State,
|
||||||
utils::PersistantElementIter,
|
// utils::PersistantElementIter,
|
||||||
};
|
// };
|
||||||
use dioxus_native_core_macro::State;
|
// use dioxus_native_core_macro::State;
|
||||||
|
|
||||||
#[derive(State, Default, Clone)]
|
// #[derive(State, Default, Clone)]
|
||||||
struct Empty {}
|
// struct Empty {}
|
||||||
|
|
||||||
#[test]
|
// #[test]
|
||||||
#[allow(unused_variables)]
|
// #[allow(unused_variables)]
|
||||||
fn traverse() {
|
// fn traverse() {
|
||||||
#[allow(non_snake_case)]
|
// #[allow(non_snake_case)]
|
||||||
fn Base(cx: Scope) -> Element {
|
// fn Base(cx: Scope) -> Element {
|
||||||
render!(div {})
|
// render!(div {})
|
||||||
}
|
// }
|
||||||
let vdom = VirtualDom::new(Base);
|
// let vdom = VirtualDom::new(Base);
|
||||||
let mutations = vdom.create_vnodes(rsx! {
|
// let mutations = vdom.create_vnodes(rsx! {
|
||||||
div{
|
// div{
|
||||||
div{
|
// div{
|
||||||
"hello"
|
// "hello"
|
||||||
p{
|
// p{
|
||||||
"world"
|
// "world"
|
||||||
}
|
// }
|
||||||
"hello world"
|
// "hello world"
|
||||||
}
|
// }
|
||||||
}
|
// }
|
||||||
});
|
// });
|
||||||
|
|
||||||
let mut rdom: RealDom<Empty> = RealDom::new();
|
// let mut rdom: RealDom<Empty> = RealDom::new();
|
||||||
|
|
||||||
let _to_update = rdom.apply_mutations(vec![mutations]);
|
// let _to_update = rdom.apply_mutations(vec![mutations]);
|
||||||
|
|
||||||
let mut iter = PersistantElementIter::new();
|
// let mut iter = PersistantElementIter::new();
|
||||||
let div_tag = "div".to_string();
|
// let div_tag = "div".to_string();
|
||||||
assert!(matches!(
|
// assert!(matches!(
|
||||||
&rdom[iter.next(&rdom).id()].node_data.node_type,
|
// &rdom[iter.next(&rdom).id()].node_data.node_type,
|
||||||
NodeType::Element { tag: div_tag, .. }
|
// NodeType::Element { tag: div_tag, .. }
|
||||||
));
|
// ));
|
||||||
assert!(matches!(
|
// assert!(matches!(
|
||||||
&rdom[iter.next(&rdom).id()].node_data.node_type,
|
// &rdom[iter.next(&rdom).id()].node_data.node_type,
|
||||||
NodeType::Element { tag: div_tag, .. }
|
// NodeType::Element { tag: div_tag, .. }
|
||||||
));
|
// ));
|
||||||
let text1 = "hello".to_string();
|
// let text1 = "hello".to_string();
|
||||||
assert!(matches!(
|
// assert!(matches!(
|
||||||
&rdom[iter.next(&rdom).id()].node_data.node_type,
|
// &rdom[iter.next(&rdom).id()].node_data.node_type,
|
||||||
NodeType::Text { text: text1, .. }
|
// NodeType::Text { text: text1, .. }
|
||||||
));
|
// ));
|
||||||
let p_tag = "p".to_string();
|
// let p_tag = "p".to_string();
|
||||||
assert!(matches!(
|
// assert!(matches!(
|
||||||
&rdom[iter.next(&rdom).id()].node_data.node_type,
|
// &rdom[iter.next(&rdom).id()].node_data.node_type,
|
||||||
NodeType::Element { tag: p_tag, .. }
|
// NodeType::Element { tag: p_tag, .. }
|
||||||
));
|
// ));
|
||||||
let text2 = "world".to_string();
|
// let text2 = "world".to_string();
|
||||||
assert!(matches!(
|
// assert!(matches!(
|
||||||
&rdom[iter.next(&rdom).id()].node_data.node_type,
|
// &rdom[iter.next(&rdom).id()].node_data.node_type,
|
||||||
NodeType::Text { text: text2, .. }
|
// NodeType::Text { text: text2, .. }
|
||||||
));
|
// ));
|
||||||
let text3 = "hello world".to_string();
|
// let text3 = "hello world".to_string();
|
||||||
assert!(matches!(
|
// assert!(matches!(
|
||||||
&rdom[iter.next(&rdom).id()].node_data.node_type,
|
// &rdom[iter.next(&rdom).id()].node_data.node_type,
|
||||||
NodeType::Text { text: text3, .. }
|
// NodeType::Text { text: text3, .. }
|
||||||
));
|
// ));
|
||||||
assert!(matches!(
|
// assert!(matches!(
|
||||||
&rdom[iter.next(&rdom).id()].node_data.node_type,
|
// &rdom[iter.next(&rdom).id()].node_data.node_type,
|
||||||
NodeType::Element { tag: div_tag, .. }
|
// NodeType::Element { tag: div_tag, .. }
|
||||||
));
|
// ));
|
||||||
|
|
||||||
assert!(matches!(
|
// assert!(matches!(
|
||||||
&rdom[iter.prev(&rdom).id()].node_data.node_type,
|
// &rdom[iter.prev(&rdom).id()].node_data.node_type,
|
||||||
NodeType::Text { text: text3, .. }
|
// NodeType::Text { text: text3, .. }
|
||||||
));
|
// ));
|
||||||
assert!(matches!(
|
// assert!(matches!(
|
||||||
&rdom[iter.prev(&rdom).id()].node_data.node_type,
|
// &rdom[iter.prev(&rdom).id()].node_data.node_type,
|
||||||
NodeType::Text { text: text2, .. }
|
// NodeType::Text { text: text2, .. }
|
||||||
));
|
// ));
|
||||||
assert!(matches!(
|
// assert!(matches!(
|
||||||
&rdom[iter.prev(&rdom).id()].node_data.node_type,
|
// &rdom[iter.prev(&rdom).id()].node_data.node_type,
|
||||||
NodeType::Element { tag: p_tag, .. }
|
// NodeType::Element { tag: p_tag, .. }
|
||||||
));
|
// ));
|
||||||
assert!(matches!(
|
// assert!(matches!(
|
||||||
&rdom[iter.prev(&rdom).id()].node_data.node_type,
|
// &rdom[iter.prev(&rdom).id()].node_data.node_type,
|
||||||
NodeType::Text { text: text1, .. }
|
// NodeType::Text { text: text1, .. }
|
||||||
));
|
// ));
|
||||||
assert!(matches!(
|
// assert!(matches!(
|
||||||
&rdom[iter.prev(&rdom).id()].node_data.node_type,
|
// &rdom[iter.prev(&rdom).id()].node_data.node_type,
|
||||||
NodeType::Element { tag: div_tag, .. }
|
// NodeType::Element { tag: div_tag, .. }
|
||||||
));
|
// ));
|
||||||
assert!(matches!(
|
// assert!(matches!(
|
||||||
&rdom[iter.prev(&rdom).id()].node_data.node_type,
|
// &rdom[iter.prev(&rdom).id()].node_data.node_type,
|
||||||
NodeType::Element { tag: div_tag, .. }
|
// NodeType::Element { tag: div_tag, .. }
|
||||||
));
|
// ));
|
||||||
assert!(matches!(
|
// assert!(matches!(
|
||||||
&rdom[iter.prev(&rdom).id()].node_data.node_type,
|
// &rdom[iter.prev(&rdom).id()].node_data.node_type,
|
||||||
NodeType::Element { tag: div_tag, .. }
|
// NodeType::Element { tag: div_tag, .. }
|
||||||
));
|
// ));
|
||||||
assert!(matches!(
|
// assert!(matches!(
|
||||||
&rdom[iter.prev(&rdom).id()].node_data.node_type,
|
// &rdom[iter.prev(&rdom).id()].node_data.node_type,
|
||||||
NodeType::Text { text: text3, .. }
|
// NodeType::Text { text: text3, .. }
|
||||||
));
|
// ));
|
||||||
}
|
// }
|
||||||
|
|
||||||
#[test]
|
// #[test]
|
||||||
#[allow(unused_variables)]
|
// #[allow(unused_variables)]
|
||||||
fn persist_removes() {
|
// fn persist_removes() {
|
||||||
#[allow(non_snake_case)]
|
// #[allow(non_snake_case)]
|
||||||
fn Base(cx: Scope) -> Element {
|
// fn Base(cx: Scope) -> Element {
|
||||||
render!(div {})
|
// render!(div {})
|
||||||
}
|
// }
|
||||||
let vdom = VirtualDom::new(Base);
|
// let vdom = VirtualDom::new(Base);
|
||||||
let (build, update) = vdom.diff_lazynodes(
|
// let (build, update) = vdom.diff_lazynodes(
|
||||||
rsx_without_templates! {
|
// rsx_without_templates! {
|
||||||
div{
|
// div{
|
||||||
p{
|
// p{
|
||||||
key: "1",
|
// key: "1",
|
||||||
"hello"
|
// "hello"
|
||||||
}
|
// }
|
||||||
p{
|
// p{
|
||||||
key: "2",
|
// key: "2",
|
||||||
"world"
|
// "world"
|
||||||
}
|
// }
|
||||||
p{
|
// p{
|
||||||
key: "3",
|
// key: "3",
|
||||||
"hello world"
|
// "hello world"
|
||||||
}
|
// }
|
||||||
}
|
// }
|
||||||
},
|
// },
|
||||||
rsx_without_templates! {
|
// rsx_without_templates! {
|
||||||
div{
|
// div{
|
||||||
p{
|
// p{
|
||||||
key: "1",
|
// key: "1",
|
||||||
"hello"
|
// "hello"
|
||||||
}
|
// }
|
||||||
p{
|
// p{
|
||||||
key: "3",
|
// key: "3",
|
||||||
"hello world"
|
// "hello world"
|
||||||
}
|
// }
|
||||||
}
|
// }
|
||||||
},
|
// },
|
||||||
);
|
// );
|
||||||
|
|
||||||
let mut rdom: RealDom<Empty> = RealDom::new();
|
// let mut rdom: RealDom<Empty> = RealDom::new();
|
||||||
|
|
||||||
let _to_update = rdom.apply_mutations(vec![build]);
|
// let _to_update = rdom.apply_mutations(vec![build]);
|
||||||
|
|
||||||
// this will end on the node that is removed
|
// // this will end on the node that is removed
|
||||||
let mut iter1 = PersistantElementIter::new();
|
// let mut iter1 = PersistantElementIter::new();
|
||||||
// this will end on the after node that is removed
|
// // this will end on the after node that is removed
|
||||||
let mut iter2 = PersistantElementIter::new();
|
// let mut iter2 = PersistantElementIter::new();
|
||||||
// div
|
// // div
|
||||||
iter1.next(&rdom).id();
|
// iter1.next(&rdom).id();
|
||||||
iter2.next(&rdom).id();
|
// iter2.next(&rdom).id();
|
||||||
// p
|
// // p
|
||||||
iter1.next(&rdom).id();
|
// iter1.next(&rdom).id();
|
||||||
iter2.next(&rdom).id();
|
// iter2.next(&rdom).id();
|
||||||
// "hello"
|
// // "hello"
|
||||||
iter1.next(&rdom).id();
|
// iter1.next(&rdom).id();
|
||||||
iter2.next(&rdom).id();
|
// iter2.next(&rdom).id();
|
||||||
// p
|
// // p
|
||||||
iter1.next(&rdom).id();
|
// iter1.next(&rdom).id();
|
||||||
iter2.next(&rdom).id();
|
// iter2.next(&rdom).id();
|
||||||
// "world"
|
// // "world"
|
||||||
iter1.next(&rdom).id();
|
// iter1.next(&rdom).id();
|
||||||
iter2.next(&rdom).id();
|
// iter2.next(&rdom).id();
|
||||||
// p
|
// // p
|
||||||
iter2.next(&rdom).id();
|
// iter2.next(&rdom).id();
|
||||||
// "hello world"
|
// // "hello world"
|
||||||
iter2.next(&rdom).id();
|
// iter2.next(&rdom).id();
|
||||||
|
|
||||||
iter1.prune(&update, &rdom);
|
// iter1.prune(&update, &rdom);
|
||||||
iter2.prune(&update, &rdom);
|
// iter2.prune(&update, &rdom);
|
||||||
let _to_update = rdom.apply_mutations(vec![update]);
|
// let _to_update = rdom.apply_mutations(vec![update]);
|
||||||
|
|
||||||
let p_tag = "p".to_string();
|
// let p_tag = "p".to_string();
|
||||||
let idx = iter1.next(&rdom).id();
|
// let idx = iter1.next(&rdom).id();
|
||||||
assert!(matches!(
|
// assert!(matches!(
|
||||||
&rdom[idx].node_data.node_type,
|
// &rdom[idx].node_data.node_type,
|
||||||
NodeType::Element { tag: p_tag, .. }
|
// NodeType::Element { tag: p_tag, .. }
|
||||||
));
|
// ));
|
||||||
let text = "hello world".to_string();
|
// let text = "hello world".to_string();
|
||||||
let idx = iter1.next(&rdom).id();
|
// let idx = iter1.next(&rdom).id();
|
||||||
assert!(matches!(
|
// assert!(matches!(
|
||||||
&rdom[idx].node_data.node_type,
|
// &rdom[idx].node_data.node_type,
|
||||||
NodeType::Text { text, .. }
|
// NodeType::Text { text, .. }
|
||||||
));
|
// ));
|
||||||
let div_tag = "div".to_string();
|
// let div_tag = "div".to_string();
|
||||||
let idx = iter2.next(&rdom).id();
|
// let idx = iter2.next(&rdom).id();
|
||||||
assert!(matches!(
|
// assert!(matches!(
|
||||||
&rdom[idx].node_data.node_type,
|
// &rdom[idx].node_data.node_type,
|
||||||
NodeType::Element { tag: div_tag, .. }
|
// NodeType::Element { tag: div_tag, .. }
|
||||||
));
|
// ));
|
||||||
}
|
// }
|
||||||
|
|
||||||
#[test]
|
// #[test]
|
||||||
#[allow(unused_variables)]
|
// #[allow(unused_variables)]
|
||||||
fn persist_instertions_before() {
|
// fn persist_instertions_before() {
|
||||||
#[allow(non_snake_case)]
|
// #[allow(non_snake_case)]
|
||||||
fn Base(cx: Scope) -> Element {
|
// fn Base(cx: Scope) -> Element {
|
||||||
render!(div {})
|
// render!(div {})
|
||||||
}
|
// }
|
||||||
let vdom = VirtualDom::new(Base);
|
// let vdom = VirtualDom::new(Base);
|
||||||
let (build, update) = vdom.diff_lazynodes(
|
// let (build, update) = vdom.diff_lazynodes(
|
||||||
rsx_without_templates! {
|
// rsx_without_templates! {
|
||||||
div{
|
// div{
|
||||||
p{
|
// p{
|
||||||
key: "1",
|
// key: "1",
|
||||||
"hello"
|
// "hello"
|
||||||
}
|
// }
|
||||||
p{
|
// p{
|
||||||
key: "3",
|
// key: "3",
|
||||||
"hello world"
|
// "hello world"
|
||||||
}
|
// }
|
||||||
}
|
// }
|
||||||
},
|
// },
|
||||||
rsx_without_templates! {
|
// rsx_without_templates! {
|
||||||
div{
|
// div{
|
||||||
p{
|
// p{
|
||||||
key: "1",
|
// key: "1",
|
||||||
"hello"
|
// "hello"
|
||||||
}
|
// }
|
||||||
p{
|
// p{
|
||||||
key: "2",
|
// key: "2",
|
||||||
"world"
|
// "world"
|
||||||
}
|
// }
|
||||||
p{
|
// p{
|
||||||
key: "3",
|
// key: "3",
|
||||||
"hello world"
|
// "hello world"
|
||||||
}
|
// }
|
||||||
}
|
// }
|
||||||
},
|
// },
|
||||||
);
|
// );
|
||||||
|
|
||||||
let mut rdom: RealDom<Empty> = RealDom::new();
|
// let mut rdom: RealDom<Empty> = RealDom::new();
|
||||||
|
|
||||||
let _to_update = rdom.apply_mutations(vec![build]);
|
// let _to_update = rdom.apply_mutations(vec![build]);
|
||||||
|
|
||||||
let mut iter = PersistantElementIter::new();
|
// let mut iter = PersistantElementIter::new();
|
||||||
// div
|
// // div
|
||||||
iter.next(&rdom).id();
|
// iter.next(&rdom).id();
|
||||||
// p
|
// // p
|
||||||
iter.next(&rdom).id();
|
// iter.next(&rdom).id();
|
||||||
// "hello"
|
// // "hello"
|
||||||
iter.next(&rdom).id();
|
// iter.next(&rdom).id();
|
||||||
// p
|
// // p
|
||||||
iter.next(&rdom).id();
|
// iter.next(&rdom).id();
|
||||||
// "hello world"
|
// // "hello world"
|
||||||
iter.next(&rdom).id();
|
// iter.next(&rdom).id();
|
||||||
|
|
||||||
iter.prune(&update, &rdom);
|
// iter.prune(&update, &rdom);
|
||||||
let _to_update = rdom.apply_mutations(vec![update]);
|
// let _to_update = rdom.apply_mutations(vec![update]);
|
||||||
|
|
||||||
let p_tag = "div".to_string();
|
// let p_tag = "div".to_string();
|
||||||
let idx = iter.next(&rdom).id();
|
// let idx = iter.next(&rdom).id();
|
||||||
assert!(matches!(
|
// assert!(matches!(
|
||||||
&rdom[idx].node_data.node_type,
|
// &rdom[idx].node_data.node_type,
|
||||||
NodeType::Element { tag: p_tag, .. }
|
// NodeType::Element { tag: p_tag, .. }
|
||||||
));
|
// ));
|
||||||
}
|
// }
|
||||||
|
|
||||||
#[test]
|
// #[test]
|
||||||
#[allow(unused_variables)]
|
// #[allow(unused_variables)]
|
||||||
fn persist_instertions_after() {
|
// fn persist_instertions_after() {
|
||||||
#[allow(non_snake_case)]
|
// #[allow(non_snake_case)]
|
||||||
fn Base(cx: Scope) -> Element {
|
// fn Base(cx: Scope) -> Element {
|
||||||
render!(div {})
|
// render!(div {})
|
||||||
}
|
// }
|
||||||
let vdom = VirtualDom::new(Base);
|
// let vdom = VirtualDom::new(Base);
|
||||||
let (build, update) = vdom.diff_lazynodes(
|
// let (build, update) = vdom.diff_lazynodes(
|
||||||
rsx_without_templates! {
|
// rsx_without_templates! {
|
||||||
div{
|
// div{
|
||||||
p{
|
// p{
|
||||||
key: "1",
|
// key: "1",
|
||||||
"hello"
|
// "hello"
|
||||||
}
|
// }
|
||||||
p{
|
// p{
|
||||||
key: "2",
|
// key: "2",
|
||||||
"world"
|
// "world"
|
||||||
}
|
// }
|
||||||
}
|
// }
|
||||||
},
|
// },
|
||||||
rsx_without_templates! {
|
// rsx_without_templates! {
|
||||||
div{
|
// div{
|
||||||
p{
|
// p{
|
||||||
key: "1",
|
// key: "1",
|
||||||
"hello"
|
// "hello"
|
||||||
}
|
// }
|
||||||
p{
|
// p{
|
||||||
key: "2",
|
// key: "2",
|
||||||
"world"
|
// "world"
|
||||||
}
|
// }
|
||||||
p{
|
// p{
|
||||||
key: "3",
|
// key: "3",
|
||||||
"hello world"
|
// "hello world"
|
||||||
}
|
// }
|
||||||
}
|
// }
|
||||||
},
|
// },
|
||||||
);
|
// );
|
||||||
|
|
||||||
let mut rdom: RealDom<Empty> = RealDom::new();
|
// let mut rdom: RealDom<Empty> = RealDom::new();
|
||||||
|
|
||||||
let _to_update = rdom.apply_mutations(vec![build]);
|
// let _to_update = rdom.apply_mutations(vec![build]);
|
||||||
|
|
||||||
let mut iter = PersistantElementIter::new();
|
// let mut iter = PersistantElementIter::new();
|
||||||
// div
|
// // div
|
||||||
iter.next(&rdom).id();
|
// iter.next(&rdom).id();
|
||||||
// p
|
// // p
|
||||||
iter.next(&rdom).id();
|
// iter.next(&rdom).id();
|
||||||
// "hello"
|
// // "hello"
|
||||||
iter.next(&rdom).id();
|
// iter.next(&rdom).id();
|
||||||
// p
|
// // p
|
||||||
iter.next(&rdom).id();
|
// iter.next(&rdom).id();
|
||||||
// "world"
|
// // "world"
|
||||||
iter.next(&rdom).id();
|
// iter.next(&rdom).id();
|
||||||
|
|
||||||
iter.prune(&update, &rdom);
|
// iter.prune(&update, &rdom);
|
||||||
let _to_update = rdom.apply_mutations(vec![update]);
|
// let _to_update = rdom.apply_mutations(vec![update]);
|
||||||
|
|
||||||
let p_tag = "p".to_string();
|
// let p_tag = "p".to_string();
|
||||||
let idx = iter.next(&rdom).id();
|
// let idx = iter.next(&rdom).id();
|
||||||
assert!(matches!(
|
// assert!(matches!(
|
||||||
&rdom[idx].node_data.node_type,
|
// &rdom[idx].node_data.node_type,
|
||||||
NodeType::Element { tag: p_tag, .. }
|
// NodeType::Element { tag: p_tag, .. }
|
||||||
));
|
// ));
|
||||||
let text = "hello world".to_string();
|
// let text = "hello world".to_string();
|
||||||
let idx = iter.next(&rdom).id();
|
// let idx = iter.next(&rdom).id();
|
||||||
assert!(matches!(
|
// assert!(matches!(
|
||||||
&rdom[idx].node_data.node_type,
|
// &rdom[idx].node_data.node_type,
|
||||||
NodeType::Text { text, .. }
|
// NodeType::Text { text, .. }
|
||||||
));
|
// ));
|
||||||
}
|
// }
|
||||||
@@ -1,516 +1,516 @@
|
|||||||
use anymap::AnyMap;
|
// use anymap::AnyMap;
|
||||||
use dioxus::core::ElementId;
|
// use dioxus::core::ElementId;
|
||||||
use dioxus::core::{AttributeValue, DomEdit, Mutations};
|
// use dioxus::core::{AttributeValue, DomEdit, Mutations};
|
||||||
use dioxus::core_macro::rsx_without_templates;
|
// use dioxus::core_macro::rsx_without_templates;
|
||||||
use dioxus::prelude::*;
|
// use dioxus::prelude::*;
|
||||||
use dioxus_native_core::real_dom::*;
|
// use dioxus_native_core::real_dom::*;
|
||||||
use dioxus_native_core::state::{ChildDepState, NodeDepState, ParentDepState, State};
|
// use dioxus_native_core::state::{ChildDepState, NodeDepState, ParentDepState, State};
|
||||||
use dioxus_native_core::{node_ref::*, RealNodeId};
|
// use dioxus_native_core::{node_ref::*, RealNodeId};
|
||||||
use dioxus_native_core_macro::State;
|
// use dioxus_native_core_macro::State;
|
||||||
|
|
||||||
#[derive(Debug, Clone, Default, State)]
|
// #[derive(Debug, Clone, Default, State)]
|
||||||
struct CallCounterStatePart1 {
|
// struct CallCounterStatePart1 {
|
||||||
#[child_dep_state(child_counter)]
|
// #[child_dep_state(child_counter)]
|
||||||
child_counter: ChildDepCallCounter,
|
// child_counter: ChildDepCallCounter,
|
||||||
}
|
// }
|
||||||
|
|
||||||
#[derive(Debug, Clone, Default, State)]
|
// #[derive(Debug, Clone, Default, State)]
|
||||||
struct CallCounterStatePart2 {
|
// struct CallCounterStatePart2 {
|
||||||
#[parent_dep_state(parent_counter)]
|
// #[parent_dep_state(parent_counter)]
|
||||||
parent_counter: ParentDepCallCounter,
|
// parent_counter: ParentDepCallCounter,
|
||||||
}
|
// }
|
||||||
|
|
||||||
#[derive(Debug, Clone, Default, State)]
|
// #[derive(Debug, Clone, Default, State)]
|
||||||
struct CallCounterStatePart3 {
|
// struct CallCounterStatePart3 {
|
||||||
#[node_dep_state()]
|
// #[node_dep_state()]
|
||||||
node_counter: NodeDepCallCounter,
|
// node_counter: NodeDepCallCounter,
|
||||||
}
|
// }
|
||||||
|
|
||||||
#[derive(Debug, Clone, Default, State)]
|
// #[derive(Debug, Clone, Default, State)]
|
||||||
struct CallCounterState {
|
// struct CallCounterState {
|
||||||
#[child_dep_state(child_counter)]
|
// #[child_dep_state(child_counter)]
|
||||||
child_counter: ChildDepCallCounter,
|
// child_counter: ChildDepCallCounter,
|
||||||
#[state]
|
// #[state]
|
||||||
part2: CallCounterStatePart2,
|
// part2: CallCounterStatePart2,
|
||||||
#[parent_dep_state(parent_counter)]
|
// #[parent_dep_state(parent_counter)]
|
||||||
parent_counter: ParentDepCallCounter,
|
// parent_counter: ParentDepCallCounter,
|
||||||
#[state]
|
// #[state]
|
||||||
part1: CallCounterStatePart1,
|
// part1: CallCounterStatePart1,
|
||||||
#[state]
|
// #[state]
|
||||||
part3: CallCounterStatePart3,
|
// part3: CallCounterStatePart3,
|
||||||
#[node_dep_state()]
|
// #[node_dep_state()]
|
||||||
node_counter: NodeDepCallCounter,
|
// node_counter: NodeDepCallCounter,
|
||||||
}
|
// }
|
||||||
|
|
||||||
#[derive(Debug, Clone, Default)]
|
// #[derive(Debug, Clone, Default)]
|
||||||
struct ChildDepCallCounter(u32);
|
// struct ChildDepCallCounter(u32);
|
||||||
impl ChildDepState for ChildDepCallCounter {
|
// impl ChildDepState for ChildDepCallCounter {
|
||||||
type Ctx = ();
|
// type Ctx = ();
|
||||||
type DepState = Self;
|
// type DepState = Self;
|
||||||
const NODE_MASK: NodeMask = NodeMask::ALL;
|
// const NODE_MASK: NodeMask = NodeMask::ALL;
|
||||||
fn reduce<'a>(
|
// fn reduce<'a>(
|
||||||
&mut self,
|
// &mut self,
|
||||||
_: NodeView,
|
// _: NodeView,
|
||||||
_: impl Iterator<Item = &'a Self::DepState>,
|
// _: impl Iterator<Item = &'a Self::DepState>,
|
||||||
_: &Self::Ctx,
|
// _: &Self::Ctx,
|
||||||
) -> bool
|
// ) -> bool
|
||||||
where
|
// where
|
||||||
Self::DepState: 'a,
|
// Self::DepState: 'a,
|
||||||
{
|
// {
|
||||||
self.0 += 1;
|
// self.0 += 1;
|
||||||
true
|
// true
|
||||||
}
|
// }
|
||||||
}
|
// }
|
||||||
|
|
||||||
#[derive(Debug, Clone, Default)]
|
// #[derive(Debug, Clone, Default)]
|
||||||
struct ParentDepCallCounter(u32);
|
// struct ParentDepCallCounter(u32);
|
||||||
impl ParentDepState for ParentDepCallCounter {
|
// impl ParentDepState for ParentDepCallCounter {
|
||||||
type Ctx = ();
|
// type Ctx = ();
|
||||||
type DepState = Self;
|
// type DepState = Self;
|
||||||
const NODE_MASK: NodeMask = NodeMask::ALL;
|
// const NODE_MASK: NodeMask = NodeMask::ALL;
|
||||||
fn reduce(
|
// fn reduce(
|
||||||
&mut self,
|
// &mut self,
|
||||||
_node: NodeView,
|
// _node: NodeView,
|
||||||
_parent: Option<&Self::DepState>,
|
// _parent: Option<&Self::DepState>,
|
||||||
_ctx: &Self::Ctx,
|
// _ctx: &Self::Ctx,
|
||||||
) -> bool {
|
// ) -> bool {
|
||||||
self.0 += 1;
|
// self.0 += 1;
|
||||||
true
|
// true
|
||||||
}
|
// }
|
||||||
}
|
// }
|
||||||
|
|
||||||
#[derive(Debug, Clone, Default)]
|
// #[derive(Debug, Clone, Default)]
|
||||||
struct NodeDepCallCounter(u32);
|
// struct NodeDepCallCounter(u32);
|
||||||
impl NodeDepState<()> for NodeDepCallCounter {
|
// impl NodeDepState<()> for NodeDepCallCounter {
|
||||||
type Ctx = ();
|
// type Ctx = ();
|
||||||
const NODE_MASK: NodeMask = NodeMask::ALL;
|
// const NODE_MASK: NodeMask = NodeMask::ALL;
|
||||||
fn reduce(&mut self, _node: NodeView, _sibling: (), _ctx: &Self::Ctx) -> bool {
|
// fn reduce(&mut self, _node: NodeView, _sibling: (), _ctx: &Self::Ctx) -> bool {
|
||||||
self.0 += 1;
|
// self.0 += 1;
|
||||||
true
|
// true
|
||||||
}
|
// }
|
||||||
}
|
// }
|
||||||
|
|
||||||
#[allow(clippy::vec_box)]
|
// #[allow(clippy::vec_box)]
|
||||||
#[derive(Debug, Clone, PartialEq, Default)]
|
// #[derive(Debug, Clone, PartialEq, Default)]
|
||||||
struct BubbledUpStateTester(Option<String>, Vec<Box<BubbledUpStateTester>>);
|
// struct BubbledUpStateTester(Option<String>, Vec<Box<BubbledUpStateTester>>);
|
||||||
impl ChildDepState for BubbledUpStateTester {
|
// impl ChildDepState for BubbledUpStateTester {
|
||||||
type Ctx = u32;
|
// type Ctx = u32;
|
||||||
type DepState = Self;
|
// type DepState = Self;
|
||||||
const NODE_MASK: NodeMask = NodeMask::new().with_tag();
|
// const NODE_MASK: NodeMask = NodeMask::new().with_tag();
|
||||||
fn reduce<'a>(
|
// fn reduce<'a>(
|
||||||
&mut self,
|
// &mut self,
|
||||||
node: NodeView,
|
// node: NodeView,
|
||||||
children: impl Iterator<Item = &'a Self::DepState>,
|
// children: impl Iterator<Item = &'a Self::DepState>,
|
||||||
ctx: &Self::Ctx,
|
// ctx: &Self::Ctx,
|
||||||
) -> bool
|
// ) -> bool
|
||||||
where
|
// where
|
||||||
Self::DepState: 'a,
|
// Self::DepState: 'a,
|
||||||
{
|
// {
|
||||||
assert_eq!(*ctx, 42);
|
// assert_eq!(*ctx, 42);
|
||||||
*self = BubbledUpStateTester(
|
// *self = BubbledUpStateTester(
|
||||||
node.tag().map(|s| s.to_string()),
|
// node.tag().map(|s| s.to_string()),
|
||||||
children.into_iter().map(|c| Box::new(c.clone())).collect(),
|
// children.into_iter().map(|c| Box::new(c.clone())).collect(),
|
||||||
);
|
// );
|
||||||
true
|
// true
|
||||||
}
|
// }
|
||||||
}
|
// }
|
||||||
|
|
||||||
#[derive(Debug, Clone, PartialEq, Default)]
|
// #[derive(Debug, Clone, PartialEq, Default)]
|
||||||
struct PushedDownStateTester(Option<String>, Option<Box<PushedDownStateTester>>);
|
// struct PushedDownStateTester(Option<String>, Option<Box<PushedDownStateTester>>);
|
||||||
impl ParentDepState for PushedDownStateTester {
|
// impl ParentDepState for PushedDownStateTester {
|
||||||
type Ctx = u32;
|
// type Ctx = u32;
|
||||||
type DepState = Self;
|
// type DepState = Self;
|
||||||
const NODE_MASK: NodeMask = NodeMask::new().with_tag();
|
// const NODE_MASK: NodeMask = NodeMask::new().with_tag();
|
||||||
fn reduce(&mut self, node: NodeView, parent: Option<&Self::DepState>, ctx: &Self::Ctx) -> bool {
|
// fn reduce(&mut self, node: NodeView, parent: Option<&Self::DepState>, ctx: &Self::Ctx) -> bool {
|
||||||
assert_eq!(*ctx, 42);
|
// assert_eq!(*ctx, 42);
|
||||||
*self = PushedDownStateTester(
|
// *self = PushedDownStateTester(
|
||||||
node.tag().map(|s| s.to_string()),
|
// node.tag().map(|s| s.to_string()),
|
||||||
parent.map(|c| Box::new(c.clone())),
|
// parent.map(|c| Box::new(c.clone())),
|
||||||
);
|
// );
|
||||||
true
|
// true
|
||||||
}
|
// }
|
||||||
}
|
// }
|
||||||
|
|
||||||
#[derive(Debug, Clone, PartialEq, Default)]
|
// #[derive(Debug, Clone, PartialEq, Default)]
|
||||||
struct NodeStateTester(Option<String>, Vec<(String, String)>);
|
// struct NodeStateTester(Option<String>, Vec<(String, String)>);
|
||||||
impl NodeDepState<()> for NodeStateTester {
|
// impl NodeDepState<()> for NodeStateTester {
|
||||||
type Ctx = u32;
|
// type Ctx = u32;
|
||||||
const NODE_MASK: NodeMask = NodeMask::new_with_attrs(AttributeMask::All).with_tag();
|
// const NODE_MASK: NodeMask = NodeMask::new_with_attrs(AttributeMask::All).with_tag();
|
||||||
fn reduce(&mut self, node: NodeView, _sibling: (), ctx: &Self::Ctx) -> bool {
|
// fn reduce(&mut self, node: NodeView, _sibling: (), ctx: &Self::Ctx) -> bool {
|
||||||
assert_eq!(*ctx, 42);
|
// assert_eq!(*ctx, 42);
|
||||||
*self = NodeStateTester(
|
// *self = NodeStateTester(
|
||||||
node.tag().map(|s| s.to_string()),
|
// node.tag().map(|s| s.to_string()),
|
||||||
node.attributes()
|
// node.attributes()
|
||||||
.map(|iter| {
|
// .map(|iter| {
|
||||||
iter.map(|a| {
|
// iter.map(|a| {
|
||||||
(
|
// (
|
||||||
a.attribute.name.to_string(),
|
// a.attribute.name.to_string(),
|
||||||
a.value.as_text().unwrap().to_string(),
|
// a.value.as_text().unwrap().to_string(),
|
||||||
)
|
// )
|
||||||
})
|
// })
|
||||||
.collect()
|
// .collect()
|
||||||
})
|
// })
|
||||||
.unwrap_or_default(),
|
// .unwrap_or_default(),
|
||||||
);
|
// );
|
||||||
true
|
// true
|
||||||
}
|
// }
|
||||||
}
|
// }
|
||||||
|
|
||||||
#[derive(State, Clone, Default, Debug)]
|
// #[derive(State, Clone, Default, Debug)]
|
||||||
struct StateTester {
|
// struct StateTester {
|
||||||
#[child_dep_state(bubbled, u32)]
|
// #[child_dep_state(bubbled, u32)]
|
||||||
bubbled: BubbledUpStateTester,
|
// bubbled: BubbledUpStateTester,
|
||||||
#[parent_dep_state(pushed, u32)]
|
// #[parent_dep_state(pushed, u32)]
|
||||||
pushed: PushedDownStateTester,
|
// pushed: PushedDownStateTester,
|
||||||
#[node_dep_state(NONE, u32)]
|
// #[node_dep_state(NONE, u32)]
|
||||||
node: NodeStateTester,
|
// node: NodeStateTester,
|
||||||
}
|
// }
|
||||||
|
|
||||||
#[test]
|
// #[test]
|
||||||
fn state_initial() {
|
// fn state_initial() {
|
||||||
#[allow(non_snake_case)]
|
// #[allow(non_snake_case)]
|
||||||
fn Base(cx: Scope) -> Element {
|
// fn Base(cx: Scope) -> Element {
|
||||||
render!(div {
|
// render!(div {
|
||||||
p{}
|
// p{}
|
||||||
h1{}
|
// h1{}
|
||||||
})
|
// })
|
||||||
}
|
// }
|
||||||
|
|
||||||
let vdom = VirtualDom::new(Base);
|
// let vdom = VirtualDom::new(Base);
|
||||||
|
|
||||||
let mutations = vdom.create_vnodes(rsx! {
|
// let mutations = vdom.create_vnodes(rsx! {
|
||||||
div {
|
// div {
|
||||||
p{
|
// p{
|
||||||
color: "red"
|
// color: "red"
|
||||||
}
|
// }
|
||||||
h1{}
|
// h1{}
|
||||||
}
|
// }
|
||||||
});
|
// });
|
||||||
|
|
||||||
let mut dom: RealDom<StateTester> = RealDom::new();
|
// let mut dom: RealDom<StateTester> = RealDom::new();
|
||||||
|
|
||||||
let nodes_updated = dom.apply_mutations(vec![mutations]);
|
// let nodes_updated = dom.apply_mutations(vec![mutations]);
|
||||||
let mut ctx = AnyMap::new();
|
// let mut ctx = AnyMap::new();
|
||||||
ctx.insert(42u32);
|
// ctx.insert(42u32);
|
||||||
let _to_rerender = dom.update_state(nodes_updated, ctx);
|
// let _to_rerender = dom.update_state(nodes_updated, ctx);
|
||||||
|
|
||||||
let root_div = &dom[RealNodeId::ElementId(ElementId(2))];
|
// let root_div = &dom[RealNodeId::ElementId(ElementId(2))];
|
||||||
assert_eq!(root_div.state.bubbled.0, Some("div".to_string()));
|
// assert_eq!(root_div.state.bubbled.0, Some("div".to_string()));
|
||||||
assert_eq!(
|
// assert_eq!(
|
||||||
root_div.state.bubbled.1,
|
// root_div.state.bubbled.1,
|
||||||
vec![
|
// vec![
|
||||||
Box::new(BubbledUpStateTester(Some("p".to_string()), Vec::new())),
|
// Box::new(BubbledUpStateTester(Some("p".to_string()), Vec::new())),
|
||||||
Box::new(BubbledUpStateTester(Some("h1".to_string()), Vec::new()))
|
// Box::new(BubbledUpStateTester(Some("h1".to_string()), Vec::new()))
|
||||||
]
|
// ]
|
||||||
);
|
// );
|
||||||
assert_eq!(root_div.state.pushed.0, Some("div".to_string()));
|
// assert_eq!(root_div.state.pushed.0, Some("div".to_string()));
|
||||||
assert_eq!(
|
// assert_eq!(
|
||||||
root_div.state.pushed.1,
|
// root_div.state.pushed.1,
|
||||||
Some(Box::new(PushedDownStateTester(
|
// Some(Box::new(PushedDownStateTester(
|
||||||
Some("Root".to_string()),
|
// Some("Root".to_string()),
|
||||||
None
|
// None
|
||||||
)))
|
// )))
|
||||||
);
|
// );
|
||||||
assert_eq!(root_div.state.node.0, Some("div".to_string()));
|
// assert_eq!(root_div.state.node.0, Some("div".to_string()));
|
||||||
assert_eq!(root_div.state.node.1, vec![]);
|
// assert_eq!(root_div.state.node.1, vec![]);
|
||||||
|
|
||||||
let child_p = &dom[RealNodeId::UnaccessableId(3)];
|
// let child_p = &dom[RealNodeId::UnaccessableId(3)];
|
||||||
assert_eq!(child_p.state.bubbled.0, Some("p".to_string()));
|
// assert_eq!(child_p.state.bubbled.0, Some("p".to_string()));
|
||||||
assert_eq!(child_p.state.bubbled.1, Vec::new());
|
// assert_eq!(child_p.state.bubbled.1, Vec::new());
|
||||||
assert_eq!(child_p.state.pushed.0, Some("p".to_string()));
|
// assert_eq!(child_p.state.pushed.0, Some("p".to_string()));
|
||||||
assert_eq!(
|
// assert_eq!(
|
||||||
child_p.state.pushed.1,
|
// child_p.state.pushed.1,
|
||||||
Some(Box::new(PushedDownStateTester(
|
// Some(Box::new(PushedDownStateTester(
|
||||||
Some("div".to_string()),
|
// Some("div".to_string()),
|
||||||
Some(Box::new(PushedDownStateTester(
|
// Some(Box::new(PushedDownStateTester(
|
||||||
Some("Root".to_string()),
|
// Some("Root".to_string()),
|
||||||
None
|
// None
|
||||||
)))
|
// )))
|
||||||
)))
|
// )))
|
||||||
);
|
// );
|
||||||
assert_eq!(child_p.state.node.0, Some("p".to_string()));
|
// assert_eq!(child_p.state.node.0, Some("p".to_string()));
|
||||||
assert_eq!(
|
// assert_eq!(
|
||||||
child_p.state.node.1,
|
// child_p.state.node.1,
|
||||||
vec![("color".to_string(), "red".to_string())]
|
// vec![("color".to_string(), "red".to_string())]
|
||||||
);
|
// );
|
||||||
|
|
||||||
let child_h1 = &dom[RealNodeId::UnaccessableId(4)];
|
// let child_h1 = &dom[RealNodeId::UnaccessableId(4)];
|
||||||
assert_eq!(child_h1.state.bubbled.0, Some("h1".to_string()));
|
// assert_eq!(child_h1.state.bubbled.0, Some("h1".to_string()));
|
||||||
assert_eq!(child_h1.state.bubbled.1, Vec::new());
|
// assert_eq!(child_h1.state.bubbled.1, Vec::new());
|
||||||
assert_eq!(child_h1.state.pushed.0, Some("h1".to_string()));
|
// assert_eq!(child_h1.state.pushed.0, Some("h1".to_string()));
|
||||||
assert_eq!(
|
// assert_eq!(
|
||||||
child_h1.state.pushed.1,
|
// child_h1.state.pushed.1,
|
||||||
Some(Box::new(PushedDownStateTester(
|
// Some(Box::new(PushedDownStateTester(
|
||||||
Some("div".to_string()),
|
// Some("div".to_string()),
|
||||||
Some(Box::new(PushedDownStateTester(
|
// Some(Box::new(PushedDownStateTester(
|
||||||
Some("Root".to_string()),
|
// Some("Root".to_string()),
|
||||||
None
|
// None
|
||||||
)))
|
// )))
|
||||||
)))
|
// )))
|
||||||
);
|
// );
|
||||||
assert_eq!(child_h1.state.node.0, Some("h1".to_string()));
|
// assert_eq!(child_h1.state.node.0, Some("h1".to_string()));
|
||||||
assert_eq!(child_h1.state.node.1, vec![]);
|
// assert_eq!(child_h1.state.node.1, vec![]);
|
||||||
}
|
// }
|
||||||
|
|
||||||
#[test]
|
// #[test]
|
||||||
fn state_reduce_parent_called_minimally_on_update() {
|
// fn state_reduce_parent_called_minimally_on_update() {
|
||||||
#[allow(non_snake_case)]
|
// #[allow(non_snake_case)]
|
||||||
fn Base(cx: Scope) -> Element {
|
// fn Base(cx: Scope) -> Element {
|
||||||
render!(div {
|
// render!(div {
|
||||||
width: "100%",
|
// width: "100%",
|
||||||
div{
|
// div{
|
||||||
div{
|
// div{
|
||||||
p{}
|
// p{}
|
||||||
}
|
// }
|
||||||
p{
|
// p{
|
||||||
"hello"
|
// "hello"
|
||||||
}
|
// }
|
||||||
div{
|
// div{
|
||||||
h1{}
|
// h1{}
|
||||||
}
|
// }
|
||||||
p{
|
// p{
|
||||||
"world"
|
// "world"
|
||||||
}
|
// }
|
||||||
}
|
// }
|
||||||
})
|
// })
|
||||||
}
|
// }
|
||||||
|
|
||||||
let vdom = VirtualDom::new(Base);
|
// let vdom = VirtualDom::new(Base);
|
||||||
|
|
||||||
let mutations = vdom.create_vnodes(rsx_without_templates! {
|
// let mutations = vdom.create_vnodes(rsx_without_templates! {
|
||||||
div {
|
// div {
|
||||||
width: "100%",
|
// width: "100%",
|
||||||
div{
|
// div{
|
||||||
div{
|
// div{
|
||||||
p{}
|
// p{}
|
||||||
}
|
// }
|
||||||
p{
|
// p{
|
||||||
"hello"
|
// "hello"
|
||||||
}
|
// }
|
||||||
div{
|
// div{
|
||||||
h1{}
|
// h1{}
|
||||||
}
|
// }
|
||||||
p{
|
// p{
|
||||||
"world"
|
// "world"
|
||||||
}
|
// }
|
||||||
}
|
// }
|
||||||
}
|
// }
|
||||||
});
|
// });
|
||||||
|
|
||||||
let mut dom: RealDom<CallCounterState> = RealDom::new();
|
// let mut dom: RealDom<CallCounterState> = RealDom::new();
|
||||||
|
|
||||||
let nodes_updated = dom.apply_mutations(vec![mutations]);
|
// let nodes_updated = dom.apply_mutations(vec![mutations]);
|
||||||
let _to_rerender = dom.update_state(nodes_updated, AnyMap::new());
|
// let _to_rerender = dom.update_state(nodes_updated, AnyMap::new());
|
||||||
let nodes_updated = dom.apply_mutations(vec![Mutations {
|
// let nodes_updated = dom.apply_mutations(vec![Mutations {
|
||||||
edits: vec![DomEdit::SetAttribute {
|
// edits: vec![DomEdit::SetAttribute {
|
||||||
root: Some(1),
|
// root: Some(1),
|
||||||
field: "width",
|
// field: "width",
|
||||||
value: AttributeValue::Text("99%"),
|
// value: AttributeValue::Text("99%"),
|
||||||
ns: Some("style"),
|
// ns: Some("style"),
|
||||||
}],
|
// }],
|
||||||
dirty_scopes: rustc_hash::FxHashSet::default(),
|
// dirty_scopes: rustc_hash::FxHashSet::default(),
|
||||||
refs: Vec::new(),
|
// refs: Vec::new(),
|
||||||
}]);
|
// }]);
|
||||||
let _to_rerender = dom.update_state(nodes_updated, AnyMap::new());
|
// let _to_rerender = dom.update_state(nodes_updated, AnyMap::new());
|
||||||
|
|
||||||
dom.traverse_depth_first(|n| {
|
// dom.traverse_depth_first(|n| {
|
||||||
assert_eq!(n.state.part2.parent_counter.0, 2);
|
// assert_eq!(n.state.part2.parent_counter.0, 2);
|
||||||
assert_eq!(n.state.parent_counter.0, 2);
|
// assert_eq!(n.state.parent_counter.0, 2);
|
||||||
});
|
// });
|
||||||
}
|
// }
|
||||||
|
|
||||||
#[test]
|
// #[test]
|
||||||
fn state_reduce_child_called_minimally_on_update() {
|
// fn state_reduce_child_called_minimally_on_update() {
|
||||||
#[allow(non_snake_case)]
|
// #[allow(non_snake_case)]
|
||||||
fn Base(cx: Scope) -> Element {
|
// fn Base(cx: Scope) -> Element {
|
||||||
cx.render(rsx_without_templates!(div {
|
// cx.render(rsx_without_templates!(div {
|
||||||
div{
|
// div{
|
||||||
div{
|
// div{
|
||||||
p{
|
// p{
|
||||||
width: "100%",
|
// width: "100%",
|
||||||
}
|
// }
|
||||||
}
|
// }
|
||||||
p{
|
// p{
|
||||||
"hello"
|
// "hello"
|
||||||
}
|
// }
|
||||||
div{
|
// div{
|
||||||
h1{}
|
// h1{}
|
||||||
}
|
// }
|
||||||
p{
|
// p{
|
||||||
"world"
|
// "world"
|
||||||
}
|
// }
|
||||||
}
|
// }
|
||||||
}))
|
// }))
|
||||||
}
|
// }
|
||||||
|
|
||||||
let vdom = VirtualDom::new(Base);
|
// let vdom = VirtualDom::new(Base);
|
||||||
|
|
||||||
let mutations = vdom.create_vnodes(rsx_without_templates! {
|
// let mutations = vdom.create_vnodes(rsx_without_templates! {
|
||||||
div {
|
// div {
|
||||||
div{
|
// div{
|
||||||
div{
|
// div{
|
||||||
p{
|
// p{
|
||||||
width: "100%",
|
// width: "100%",
|
||||||
}
|
// }
|
||||||
}
|
// }
|
||||||
p{
|
// p{
|
||||||
"hello"
|
// "hello"
|
||||||
}
|
// }
|
||||||
div{
|
// div{
|
||||||
h1{}
|
// h1{}
|
||||||
}
|
// }
|
||||||
p{
|
// p{
|
||||||
"world"
|
// "world"
|
||||||
}
|
// }
|
||||||
}
|
// }
|
||||||
}
|
// }
|
||||||
});
|
// });
|
||||||
|
|
||||||
let mut dom: RealDom<CallCounterState> = RealDom::new();
|
// let mut dom: RealDom<CallCounterState> = RealDom::new();
|
||||||
|
|
||||||
let nodes_updated = dom.apply_mutations(vec![mutations]);
|
// let nodes_updated = dom.apply_mutations(vec![mutations]);
|
||||||
let _to_rerender = dom.update_state(nodes_updated, AnyMap::new());
|
// let _to_rerender = dom.update_state(nodes_updated, AnyMap::new());
|
||||||
let nodes_updated = dom.apply_mutations(vec![Mutations {
|
// let nodes_updated = dom.apply_mutations(vec![Mutations {
|
||||||
edits: vec![DomEdit::SetAttribute {
|
// edits: vec![DomEdit::SetAttribute {
|
||||||
root: Some(4),
|
// root: Some(4),
|
||||||
field: "width",
|
// field: "width",
|
||||||
value: AttributeValue::Text("99%"),
|
// value: AttributeValue::Text("99%"),
|
||||||
ns: Some("style"),
|
// ns: Some("style"),
|
||||||
}],
|
// }],
|
||||||
dirty_scopes: rustc_hash::FxHashSet::default(),
|
// dirty_scopes: rustc_hash::FxHashSet::default(),
|
||||||
refs: Vec::new(),
|
// refs: Vec::new(),
|
||||||
}]);
|
// }]);
|
||||||
let _to_rerender = dom.update_state(nodes_updated, AnyMap::new());
|
// let _to_rerender = dom.update_state(nodes_updated, AnyMap::new());
|
||||||
|
|
||||||
dom.traverse_depth_first(|n| {
|
// dom.traverse_depth_first(|n| {
|
||||||
assert_eq!(
|
// assert_eq!(
|
||||||
n.state.part1.child_counter.0,
|
// n.state.part1.child_counter.0,
|
||||||
if let Some(RealNodeId::ElementId(ElementId(id))) = n.node_data.id {
|
// if let Some(RealNodeId::ElementId(ElementId(id))) = n.node_data.id {
|
||||||
if id > 4 {
|
// if id > 4 {
|
||||||
1
|
// 1
|
||||||
} else {
|
// } else {
|
||||||
2
|
// 2
|
||||||
}
|
// }
|
||||||
} else {
|
// } else {
|
||||||
panic!()
|
// panic!()
|
||||||
}
|
// }
|
||||||
);
|
// );
|
||||||
assert_eq!(
|
// assert_eq!(
|
||||||
n.state.child_counter.0,
|
// n.state.child_counter.0,
|
||||||
if let Some(RealNodeId::ElementId(ElementId(id))) = n.node_data.id {
|
// if let Some(RealNodeId::ElementId(ElementId(id))) = n.node_data.id {
|
||||||
if id > 4 {
|
// if id > 4 {
|
||||||
1
|
// 1
|
||||||
} else {
|
// } else {
|
||||||
2
|
// 2
|
||||||
}
|
// }
|
||||||
} else {
|
// } else {
|
||||||
panic!()
|
// panic!()
|
||||||
}
|
// }
|
||||||
);
|
// );
|
||||||
});
|
// });
|
||||||
}
|
// }
|
||||||
|
|
||||||
#[derive(Debug, Clone, Default, State)]
|
// #[derive(Debug, Clone, Default, State)]
|
||||||
struct UnorderedDependanciesState {
|
// struct UnorderedDependanciesState {
|
||||||
#[node_dep_state(c)]
|
// #[node_dep_state(c)]
|
||||||
b: BDepCallCounter,
|
// b: BDepCallCounter,
|
||||||
#[node_dep_state()]
|
// #[node_dep_state()]
|
||||||
c: CDepCallCounter,
|
// c: CDepCallCounter,
|
||||||
#[node_dep_state(b)]
|
// #[node_dep_state(b)]
|
||||||
a: ADepCallCounter,
|
// a: ADepCallCounter,
|
||||||
}
|
// }
|
||||||
|
|
||||||
#[derive(Debug, Clone, Default, PartialEq)]
|
// #[derive(Debug, Clone, Default, PartialEq)]
|
||||||
struct ADepCallCounter(usize, BDepCallCounter);
|
// struct ADepCallCounter(usize, BDepCallCounter);
|
||||||
impl<'a> NodeDepState<(&'a BDepCallCounter,)> for ADepCallCounter {
|
// impl<'a> NodeDepState<(&'a BDepCallCounter,)> for ADepCallCounter {
|
||||||
type Ctx = ();
|
// type Ctx = ();
|
||||||
const NODE_MASK: NodeMask = NodeMask::NONE;
|
// const NODE_MASK: NodeMask = NodeMask::NONE;
|
||||||
fn reduce(
|
// fn reduce(
|
||||||
&mut self,
|
// &mut self,
|
||||||
_node: NodeView,
|
// _node: NodeView,
|
||||||
(sibling,): (&'a BDepCallCounter,),
|
// (sibling,): (&'a BDepCallCounter,),
|
||||||
_ctx: &Self::Ctx,
|
// _ctx: &Self::Ctx,
|
||||||
) -> bool {
|
// ) -> bool {
|
||||||
self.0 += 1;
|
// self.0 += 1;
|
||||||
self.1 = sibling.clone();
|
// self.1 = sibling.clone();
|
||||||
true
|
// true
|
||||||
}
|
// }
|
||||||
}
|
// }
|
||||||
|
|
||||||
#[derive(Debug, Clone, Default, PartialEq)]
|
// #[derive(Debug, Clone, Default, PartialEq)]
|
||||||
struct BDepCallCounter(usize, CDepCallCounter);
|
// struct BDepCallCounter(usize, CDepCallCounter);
|
||||||
impl<'a> NodeDepState<(&'a CDepCallCounter,)> for BDepCallCounter {
|
// impl<'a> NodeDepState<(&'a CDepCallCounter,)> for BDepCallCounter {
|
||||||
type Ctx = ();
|
// type Ctx = ();
|
||||||
const NODE_MASK: NodeMask = NodeMask::NONE;
|
// const NODE_MASK: NodeMask = NodeMask::NONE;
|
||||||
fn reduce(
|
// fn reduce(
|
||||||
&mut self,
|
// &mut self,
|
||||||
_node: NodeView,
|
// _node: NodeView,
|
||||||
(sibling,): (&'a CDepCallCounter,),
|
// (sibling,): (&'a CDepCallCounter,),
|
||||||
_ctx: &Self::Ctx,
|
// _ctx: &Self::Ctx,
|
||||||
) -> bool {
|
// ) -> bool {
|
||||||
self.0 += 1;
|
// self.0 += 1;
|
||||||
self.1 = sibling.clone();
|
// self.1 = sibling.clone();
|
||||||
true
|
// true
|
||||||
}
|
// }
|
||||||
}
|
// }
|
||||||
|
|
||||||
#[derive(Debug, Clone, Default, PartialEq)]
|
// #[derive(Debug, Clone, Default, PartialEq)]
|
||||||
struct CDepCallCounter(usize);
|
// struct CDepCallCounter(usize);
|
||||||
impl NodeDepState<()> for CDepCallCounter {
|
// impl NodeDepState<()> for CDepCallCounter {
|
||||||
type Ctx = ();
|
// type Ctx = ();
|
||||||
const NODE_MASK: NodeMask = NodeMask::ALL;
|
// const NODE_MASK: NodeMask = NodeMask::ALL;
|
||||||
fn reduce(&mut self, _node: NodeView, _sibling: (), _ctx: &Self::Ctx) -> bool {
|
// fn reduce(&mut self, _node: NodeView, _sibling: (), _ctx: &Self::Ctx) -> bool {
|
||||||
self.0 += 1;
|
// self.0 += 1;
|
||||||
true
|
// true
|
||||||
}
|
// }
|
||||||
}
|
// }
|
||||||
|
|
||||||
#[test]
|
// #[test]
|
||||||
fn dependancies_order_independant() {
|
// fn dependancies_order_independant() {
|
||||||
#[allow(non_snake_case)]
|
// #[allow(non_snake_case)]
|
||||||
fn Base(cx: Scope) -> Element {
|
// fn Base(cx: Scope) -> Element {
|
||||||
render!(div {
|
// render!(div {
|
||||||
width: "100%",
|
// width: "100%",
|
||||||
p{
|
// p{
|
||||||
"hello"
|
// "hello"
|
||||||
}
|
// }
|
||||||
})
|
// })
|
||||||
}
|
// }
|
||||||
|
|
||||||
let vdom = VirtualDom::new(Base);
|
// let vdom = VirtualDom::new(Base);
|
||||||
|
|
||||||
let mutations = vdom.create_vnodes(rsx! {
|
// let mutations = vdom.create_vnodes(rsx! {
|
||||||
div {
|
// div {
|
||||||
width: "100%",
|
// width: "100%",
|
||||||
p{
|
// p{
|
||||||
"hello"
|
// "hello"
|
||||||
}
|
// }
|
||||||
}
|
// }
|
||||||
});
|
// });
|
||||||
|
|
||||||
let mut dom: RealDom<UnorderedDependanciesState> = RealDom::new();
|
// let mut dom: RealDom<UnorderedDependanciesState> = RealDom::new();
|
||||||
|
|
||||||
let nodes_updated = dom.apply_mutations(vec![mutations]);
|
// let nodes_updated = dom.apply_mutations(vec![mutations]);
|
||||||
let _to_rerender = dom.update_state(nodes_updated, AnyMap::new());
|
// let _to_rerender = dom.update_state(nodes_updated, AnyMap::new());
|
||||||
|
|
||||||
let c = CDepCallCounter(1);
|
// let c = CDepCallCounter(1);
|
||||||
let b = BDepCallCounter(1, c.clone());
|
// let b = BDepCallCounter(1, c.clone());
|
||||||
let a = ADepCallCounter(1, b.clone());
|
// let a = ADepCallCounter(1, b.clone());
|
||||||
dom.traverse_depth_first(|n| {
|
// dom.traverse_depth_first(|n| {
|
||||||
assert_eq!(&n.state.a, &a);
|
// assert_eq!(&n.state.a, &a);
|
||||||
assert_eq!(&n.state.b, &b);
|
// assert_eq!(&n.state.b, &b);
|
||||||
assert_eq!(&n.state.c, &c);
|
// assert_eq!(&n.state.c, &c);
|
||||||
});
|
// });
|
||||||
}
|
// }
|
||||||
|
|
||||||
#[derive(Clone, Default, State)]
|
// #[derive(Clone, Default, State)]
|
||||||
struct DependanciesStateTest {
|
// struct DependanciesStateTest {
|
||||||
#[node_dep_state(c)]
|
// #[node_dep_state(c)]
|
||||||
b: BDepCallCounter,
|
// b: BDepCallCounter,
|
||||||
#[node_dep_state()]
|
// #[node_dep_state()]
|
||||||
c: CDepCallCounter,
|
// c: CDepCallCounter,
|
||||||
#[node_dep_state(b)]
|
// #[node_dep_state(b)]
|
||||||
a: ADepCallCounter,
|
// a: ADepCallCounter,
|
||||||
#[state]
|
// #[state]
|
||||||
child: UnorderedDependanciesState,
|
// child: UnorderedDependanciesState,
|
||||||
}
|
// }
|
||||||
@@ -1,7 +1,9 @@
|
|||||||
use std::hash::BuildHasherDefault;
|
use std::hash::BuildHasherDefault;
|
||||||
|
|
||||||
|
pub use node_ref::NodeMask;
|
||||||
|
pub use passes::AnyPass;
|
||||||
use rustc_hash::FxHasher;
|
use rustc_hash::FxHasher;
|
||||||
use tree::NodeId;
|
pub use tree::NodeId;
|
||||||
|
|
||||||
pub mod layout_attributes;
|
pub mod layout_attributes;
|
||||||
pub mod node;
|
pub mod node;
|
||||||
|
|||||||
@@ -1,6 +1,6 @@
|
|||||||
use dioxus_core::{ElementId, Mutations, TemplateNode};
|
use dioxus_core::{ElementId, Mutations, TemplateNode};
|
||||||
use rustc_hash::{FxHashMap, FxHashSet};
|
use rustc_hash::{FxHashMap, FxHashSet};
|
||||||
use std::ops::{Index, IndexMut};
|
use std::ops::{Deref, DerefMut, Index, IndexMut};
|
||||||
|
|
||||||
use crate::node::{Node, NodeType, OwnedAttributeDiscription, OwnedAttributeValue};
|
use crate::node::{Node, NodeType, OwnedAttributeDiscription, OwnedAttributeValue};
|
||||||
use crate::node_ref::{AttributeMask, NodeMask};
|
use crate::node_ref::{AttributeMask, NodeMask};
|
||||||
@@ -26,7 +26,7 @@ fn mark_dirty(
|
|||||||
/// To get started implement [crate::state::ParentDepState], [crate::state::NodeDepState], or [crate::state::ChildDepState] and call [RealDom::apply_mutations] to update the dom and [RealDom::update_state] to update the state of the nodes.
|
/// To get started implement [crate::state::ParentDepState], [crate::state::NodeDepState], or [crate::state::ChildDepState] and call [RealDom::apply_mutations] to update the dom and [RealDom::update_state] to update the state of the nodes.
|
||||||
#[derive(Debug)]
|
#[derive(Debug)]
|
||||||
pub struct RealDom<S: State> {
|
pub struct RealDom<S: State> {
|
||||||
tree: Tree<Node<S>>,
|
pub tree: Tree<Node<S>>,
|
||||||
/// a map from element id to real node id
|
/// a map from element id to real node id
|
||||||
node_id_mapping: Vec<Option<RealNodeId>>,
|
node_id_mapping: Vec<Option<RealNodeId>>,
|
||||||
nodes_listening: FxHashMap<String, FxHashSet<RealNodeId>>,
|
nodes_listening: FxHashMap<String, FxHashSet<RealNodeId>>,
|
||||||
@@ -401,6 +401,20 @@ impl<S: State> RealDom<S> {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
impl<S: State> Deref for RealDom<S> {
|
||||||
|
type Target = Tree<Node<S>>;
|
||||||
|
|
||||||
|
fn deref(&self) -> &Self::Target {
|
||||||
|
&self.tree
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
impl<S: State> DerefMut for RealDom<S> {
|
||||||
|
fn deref_mut(&mut self) -> &mut Self::Target {
|
||||||
|
&mut self.tree
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
impl<S: State> Index<ElementId> for RealDom<S> {
|
impl<S: State> Index<ElementId> for RealDom<S> {
|
||||||
type Output = Node<S>;
|
type Output = Node<S>;
|
||||||
|
|
||||||
|
|||||||
Reference in new issue
Block a user