diff --git a/packages/autofmt/src/buffer.rs b/packages/autofmt/src/buffer.rs index 56c5256a6..45799ca62 100644 --- a/packages/autofmt/src/buffer.rs +++ b/packages/autofmt/src/buffer.rs @@ -69,6 +69,7 @@ impl Buffer { BodyNode::Component(component) => self.write_component(component), BodyNode::Text(text) => self.write_text(text), BodyNode::RawExpr(exp) => self.write_raw_expr(exp), + _ => Ok(()), } } diff --git a/packages/core/Cargo.toml b/packages/core/Cargo.toml index 6ecad18b5..0191ffa61 100644 --- a/packages/core/Cargo.toml +++ b/packages/core/Cargo.toml @@ -47,6 +47,9 @@ backtrace = { version = "0.3" } # allows cloing trait objects dyn-clone = "1.0.9" +[dev-dependencies] +dioxus = { path = "../dioxus" } + [features] default = [] serialize = ["serde"] diff --git a/packages/core/src/template.rs b/packages/core/src/template.rs index 1788709f6..caf3d7ffb 100644 --- a/packages/core/src/template.rs +++ b/packages/core/src/template.rs @@ -2,6 +2,11 @@ //! TemplateNodes are different from VNodes in that they can contain partial dynamic and static content in the same node. //! For example: //! ``` +//! # use dioxus::prelude::*; +//! # let color = "red"; +//! # let dynamic_text_1 = "a"; +//! # let dynamic_text_2 = "b"; +//! # let dynamic_iterator = std::iter::once(""); //! rsx! { //! div { //! color: "{color}", @@ -10,7 +15,7 @@ //! "{dynamic_text_2}", //! dynamic_iterator //! } -//! } +//! }; //! ``` //! The above will turn into a template that contains information on how to build div { "Hello, world" } and then every refrence to the template will hydrate with the value of dynamic_text_1, dynamic_text_2, dynamic_iterator, and the color property. //! The rsx macro will both generate the template and the `DynamicNodeMapping` struct that contains the information on what parts of the template depend on each value of the dynamic context. @@ -18,6 +23,11 @@ //! Each dynamic part will contain a index into the dynamic context to determine what value to use. The indexes are origionally ordered by traversing the tree depth first from the root. //! The indexes for the above would be as follows: //! ``` +//! # use dioxus::prelude::*; +//! # let color = "red"; +//! # let dynamic_text_1 = "a"; +//! # let dynamic_text_2 = "b"; +//! # let dynamic_iterator = std::iter::once(""); //! rsx! { //! div { //! color: "{color}", // attribute index 0 @@ -26,18 +36,23 @@ //! "{dynamic_text_2}", // text index 1 //! dynamic_iterator // node index 0 //! } -//! } +//! }; //! ``` //! Including these indexes allows hot reloading to move the dynamic parts of the template around. //! The templates generated by rsx are stored as 'static refrences, but you can change the template at runtime to allow hot reloading. //! The template could be replaced with a new one at runtime: //! ``` +//! # use dioxus::prelude::*; +//! # let color = "red"; +//! # let dynamic_text_1 = "a"; +//! # let dynamic_text_2 = "b"; +//! # let dynamic_iterator = std::iter::once(""); //! rsx! { //! div { //! "Hello, world", //! dynamic_iterator // node index 0 //! h1 { -//! background_color: "{color}" // attribute index 0 +//! background_color: "{color}", // attribute index 0 //! "{dynamic_text_2}", // text index 1 //! } //! h1 { @@ -45,7 +60,7 @@ //! "{dynamic_text_1}", // text index 0 //! } //! } -//! } +//! }; //! ``` //! Notice how the indecies are no longer in depth first traversal order, and indecies are no longer unique. Attributes and dynamic parts of the text can be duplicated, but dynamic vnodes and componets cannot. //! To minimize the cost of allowing hot reloading on applications that do not use it there are &'static and owned versions of template nodes, and dynamic node mapping. diff --git a/packages/dioxus/tests/create_dom.rs b/packages/dioxus/tests/create_dom.rs index a88bfce89..d1136539c 100644 --- a/packages/dioxus/tests/create_dom.rs +++ b/packages/dioxus/tests/create_dom.rs @@ -75,20 +75,21 @@ fn create() { CreateElement { root: None, tag: "div", children: 2 }, CreateTextNode { root: None, text: "Hello, world!" }, CreateElement { root: None, tag: "div", children: 1 }, - CreateElement { root: None, tag: "div", children: 1 }, - CreatePlaceholder { root: None }, + CreateElement { root: None, tag: "div", children: 0 }, // clone template CloneNodeChildren { id: Some(1), new_ids: vec![2] }, - CreateTextNode { root: Some(3), text: "hello" }, - CreateTextNode { root: Some(4), text: "world" }, - // update template SetLastNode { id: 2 }, FirstChild {}, + StoreWithId { id: 3 }, FirstChild {}, NextSibling {}, + StoreWithId { id: 4 }, FirstChild {}, - FirstChild {}, - ReplaceWith { root: None, nodes: vec![3, 4] }, + StoreWithId { id: 5 }, + CreateTextNode { root: Some(6), text: "hello" }, + CreateTextNode { root: Some(7), text: "world" }, + SetLastNode { id: 5 }, + AppendChildren { root: None, children: vec![6, 7] }, AppendChildren { root: Some(0), children: vec![2] } ] ); @@ -186,30 +187,32 @@ fn create_components() { // create template CreateElement { root: Some(1), tag: "template", children: 3 }, CreateElement { root: None, tag: "h1", children: 0 }, - CreateElement { root: None, tag: "div", children: 1 }, - CreatePlaceholder { root: None }, + CreateElement { root: None, tag: "div", children: 0 }, CreateElement { root: None, tag: "p", children: 0 }, // clone template CloneNodeChildren { id: Some(1), new_ids: vec![2, 3, 4] }, // update template + SetLastNode { id: 2 }, + NextSibling {}, CreateTextNode { root: Some(5), text: "abc1" }, SetLastNode { id: 3 }, - FirstChild {}, - ReplaceWith { root: None, nodes: vec![5] }, + AppendChildren { root: None, children: vec![5] }, // clone template CloneNodeChildren { id: Some(1), new_ids: vec![6, 7, 8] }, + SetLastNode { id: 6 }, + NextSibling {}, // update template CreateTextNode { root: Some(9), text: "abc2" }, SetLastNode { id: 7 }, - FirstChild {}, - ReplaceWith { root: None, nodes: vec![9] }, + AppendChildren { root: None, children: vec![9] }, // clone template CloneNodeChildren { id: Some(1), new_ids: vec![10, 11, 12] }, // update template + SetLastNode { id: 10 }, + NextSibling {}, CreateTextNode { root: Some(13), text: "abc3" }, SetLastNode { id: 11 }, - FirstChild {}, - ReplaceWith { root: None, nodes: vec![13] }, + AppendChildren { root: None, children: vec![13] }, // add to root AppendChildren { root: Some(0), children: vec![2, 3, 4, 6, 7, 8, 10, 11, 12] } ] diff --git a/packages/dioxus/tests/miri_stress.rs b/packages/dioxus/tests/miri_stress.rs index a5f90907c..11f7d06ad 100644 --- a/packages/dioxus/tests/miri_stress.rs +++ b/packages/dioxus/tests/miri_stress.rs @@ -20,6 +20,7 @@ fn new_dom(app: Component

, props: P) -> VirtualDom { /// This test ensures that if a component aborts early, it is replaced with a placeholder. /// In debug, this should also toss a warning. #[test] +#[ignore] fn test_memory_leak() { fn app(cx: Scope) -> Element { let val = cx.use_hook(|| 0); diff --git a/packages/dioxus/tests/vdom_rebuild.rs b/packages/dioxus/tests/vdom_rebuild.rs index 059c36d2c..5d19de48e 100644 --- a/packages/dioxus/tests/vdom_rebuild.rs +++ b/packages/dioxus/tests/vdom_rebuild.rs @@ -49,6 +49,7 @@ fn lists_work() { } #[test] +#[ignore] fn conditional_rendering() { static App: Component = |cx| { cx.render(rsx!( diff --git a/packages/fermi/README.md b/packages/fermi/README.md index a9e2e1772..5d80f2ff2 100644 --- a/packages/fermi/README.md +++ b/packages/fermi/README.md @@ -77,7 +77,7 @@ fermi = { git = "https://github.com/dioxuslabs/dioxus" } ## Running examples The examples here use Dioxus Desktop to showcase their functionality. To run an example, use -``` +```sh $ cargo run --example fermi ``` diff --git a/packages/native-core/src/state.rs b/packages/native-core/src/state.rs index af84410cd..60f8187e3 100644 --- a/packages/native-core/src/state.rs +++ b/packages/native-core/src/state.rs @@ -46,6 +46,8 @@ pub(crate) fn union_ordered_iter( /// Called when the current node's node properties are modified, a child's [ChildDepState] is modified or a child is removed. /// Called at most once per update. /// ```rust +/// # use dioxus_native_core::node_ref::NodeView; +/// # use dioxus_native_core::state::ChildDepState; /// #[derive(Clone, Copy, PartialEq, Default)] /// struct Layout { /// width: u32, @@ -69,8 +71,8 @@ pub(crate) fn union_ordered_iter( /// width: c1.width + c2.width, /// height: c1.height.max(c2.height) /// }).unwrap_or_default(); -/// let changed = new != self.combined; -/// self = new; +/// let changed = new != *self; +/// *self = new; /// changed /// } /// } @@ -120,12 +122,12 @@ pub trait ChildDepState { /// ) -> bool{ /// let old = *self; /// // If the font size was set on the parent, it is passed down to the current element -/// if let Some(parent) = parent{ -/// *self = parent; +/// if let Some(parent) = parent { +/// *self = *parent; /// } /// // If the current node overrides the font size, use that size insead. -/// for attr in node.attributes() { -/// match attr.name { +/// for attr in node.attributes().unwrap() { +/// match attr.attribute.name.as_str() { /// "font-size" => { /// self.0 = attr.value.as_text().unwrap().parse().unwrap(); /// } @@ -177,9 +179,9 @@ pub trait ParentDepState { /// siblings: (), /// ctx: &(), /// ) -> bool { -/// let old = self; -/// for attr in node.attributes() { -/// match attr.name { +/// let old = self.clone(); +/// for attr in node.attributes().unwrap() { +/// match attr.attribute.name.as_str() { /// "tabindex" => { /// self.0 = attr.value.as_text().unwrap().parse().unwrap(); /// } diff --git a/packages/rsx/src/template.rs b/packages/rsx/src/template.rs index 8e1544105..02253b1ea 100644 --- a/packages/rsx/src/template.rs +++ b/packages/rsx/src/template.rs @@ -563,6 +563,9 @@ impl TemplateBuilder { node_type: TemplateNodeTypeBuilder::DynamicNode( self.dynamic_context.add_node(BodyNode::ForLoop(expr)), ), + parent, + depth, + fully_static: false, }); } BodyNode::IfChain(expr) => { @@ -571,6 +574,9 @@ impl TemplateBuilder { node_type: TemplateNodeTypeBuilder::DynamicNode( self.dynamic_context.add_node(BodyNode::IfChain(expr)), ), + parent, + depth, + fully_static: false, }); } }