diff --git a/packages/core/Cargo.toml b/packages/core/Cargo.toml index 9e7dcb279..ea0ae505d 100644 --- a/packages/core/Cargo.toml +++ b/packages/core/Cargo.toml @@ -49,8 +49,8 @@ fern = { version = "0.6.0", features = ["colored"] } rand = { version = "0.8.4", features = ["small_rng"] } simple_logger = "1.13.0" dioxus-core-macro = { path = "../core-macro", version = "0.1.2" } -async-std = { version = "1.9.0", features = ["attributes"] } -criterion = "0.3.5" +# async-std = { version = "1.9.0", features = ["attributes"] } +# criterion = "0.3.5" [features] default = [] diff --git a/packages/core/examples/syntax2.rs b/packages/core/examples/syntax2.rs index be1a82a4a..d3af16013 100644 --- a/packages/core/examples/syntax2.rs +++ b/packages/core/examples/syntax2.rs @@ -1,8 +1,10 @@ +use std::borrow::BorrowMut; +use std::cell::{Cell, RefCell}; use std::marker::PhantomData; use dioxus::component::Scope; use dioxus::events::on::MouseEvent; -use dioxus::nodes::{annotate_lazy, IntoVNode}; +use dioxus::nodes::{annotate_lazy, IntoVNode, VComponent, VFragment, VText}; use dioxus_core as dioxus; use dioxus_core::prelude::*; use dioxus_core_macro::*; @@ -29,191 +31,190 @@ fn t() { }; } -#[derive(PartialEq, Props)] -struct OurProps { - foo: String, -} +// #[derive(PartialEq, Props)] +// struct OurProps { +// foo: String, +// } -fn App<'a>((cx, props): Scope<'a, OurProps>) -> Element<'a> { - let a = rsx! { - div { - "asd" - "{props.foo}" - } - }; +// fn App<'a>((cx, props): Scope<'a, OurProps>) -> Element<'a> { +// let a = rsx! { +// div { +// "asd" +// "{props.foo}" +// } +// }; - let p = (0..10).map(|f| { - rsx! { - div { +// let p = (0..10).map(|f| { +// rsx! { +// div { - } - } - }); +// } +// } +// }); - let g = match "text" { - "a" => { - rsx!("asd") - } - _ => { - rsx!("asd") - } - }; +// let g = match "text" { +// "a" => { +// rsx!("asd") +// } +// _ => { +// rsx!("asd") +// } +// }; - let items = ["bob", "bill", "jack"]; +// let items = ["bob", "bill", "jack"]; - let f = items - .iter() - .filter(|f| f.starts_with('b')) - .map(|f| rsx!("hello {f}")); +// let f = items +// .iter() +// .filter(|f| f.starts_with('b')) +// .map(|f| rsx!("hello {f}")); - // use dioxus_hooks; - // let g = use_state(|| "hello".to_string()); +// // use dioxus_hooks; +// // let g = use_state(|| "hello".to_string()); - let s: &'a mut String = cx.use_hook(|_| String::new(), |f| f, |_| {}); +// let s: &'a mut String = cx.use_hook(|_| String::new(), |f| f, |_| {}); - /* - the final closure is allowed to borrow anything provided it - */ +// /* +// the final closure is allowed to borrow anything provided it +// */ +// // cx.render({ +// // let p: Option _>> = Some(Box::new(move |__cx: NodeFactory| { +// // use dioxus_elements::{GlobalAttributes, SvgAttributes}; - // cx.render({ - // let p: Option _>> = Some(Box::new(move |__cx: NodeFactory| { - // use dioxus_elements::{GlobalAttributes, SvgAttributes}; +// // let props = Child2Props { foo: s }; +// // let ch: VNode = __cx.component(Child2, props, None, []); +// // __cx.element( +// // dioxus_elements::div, +// // [], +// // [], +// // [ch], +// // // [__cx.component(Child2, fc_to_builder(Child2).foo(s).build(), None, [])], +// // None, +// // ) +// // })); +// // p +// // // let ___p: Box VNode> = Box::new(move |__cx| { +// // // use dioxus_elements::{GlobalAttributes, SvgAttributes}; - // let props = Child2Props { foo: s }; - // let ch: VNode = __cx.component(Child2, props, None, []); - // __cx.element( - // dioxus_elements::div, - // [], - // [], - // [ch], - // // [__cx.component(Child2, fc_to_builder(Child2).foo(s).build(), None, [])], - // None, - // ) - // })); - // p - // // let ___p: Box VNode> = Box::new(move |__cx| { - // // use dioxus_elements::{GlobalAttributes, SvgAttributes}; +// // // let props = Child2Props { foo: s }; +// // // let ch: VNode = __cx.component(Child2, props, None, []); +// // // __cx.element( +// // // dioxus_elements::div, +// // // [], +// // // [], +// // // [ch], +// // // // [__cx.component(Child2, fc_to_builder(Child2).foo(s).build(), None, [])], +// // // None, +// // // ) +// // // }); +// // // Some(___p) +// // }) - // // let props = Child2Props { foo: s }; - // // let ch: VNode = __cx.component(Child2, props, None, []); - // // __cx.element( - // // dioxus_elements::div, - // // [], - // // [], - // // [ch], - // // // [__cx.component(Child2, fc_to_builder(Child2).foo(s).build(), None, [])], - // // None, - // // ) - // // }); - // // Some(___p) - // }) +// let a = annotate_lazy(move |f| { +// // +// todo!() +// }); +// let b = annotate_lazy(move |f| { +// // +// f.text(format_args!("{}", props.foo)) +// }); - let a = annotate_lazy(move |f| { - // - todo!() - }); - let b = annotate_lazy(move |f| { - // - f.text(format_args!("{}", props.foo)) - }); +// let c = annotate_lazy(move |f| { +// // +// f.component( +// Child, +// OurProps { +// // +// foo: "hello".to_string(), +// }, +// None, +// [], +// ) +// }); - let c = annotate_lazy(move |f| { - // - f.component( - Child, - OurProps { - // - foo: "hello".to_string(), - }, - None, - [], - ) - }); +// let st: &'a String = cx.use_hook(|_| "hello".to_string(), |f| f, |_| {}); - let st: &'a String = cx.use_hook(|_| "hello".to_string(), |f| f, |_| {}); +// let d = annotate_lazy(move |f| { +// // +// f.component( +// Child2, +// Child2Props { +// // +// foo: st, +// }, +// None, +// [], +// ) +// }); - let d = annotate_lazy(move |f| { - // - f.component( - Child2, - Child2Props { - // - foo: st, - }, - None, - [], - ) - }); +// let e = match "asd" { +// b => { +// // - let e = match "asd" { - b => { - // +// annotate_lazy(move |f| { +// // +// f.text(format_args!("{}", props.foo)) +// }) +// } +// a => { +// // - annotate_lazy(move |f| { - // - f.text(format_args!("{}", props.foo)) - }) - } - a => { - // +// annotate_lazy(move |f| { +// // +// f.text(format_args!("{}", props.foo)) +// }) +// } +// }; - annotate_lazy(move |f| { - // - f.text(format_args!("{}", props.foo)) - }) - } - }; +// cx.render(annotate_lazy(move |f| { +// // - cx.render(annotate_lazy(move |f| { - // +// f.raw_element( +// "div", +// None, +// [], +// [], +// [ +// // +// f.fragment_from_iter(a), +// f.fragment_from_iter(b), +// f.fragment_from_iter(c), +// f.fragment_from_iter(e), +// ], +// None, +// ) +// // todo!() +// })) +// // cx.render(rsx! { +// // div { +// // div { +// // {a} +// // // {p} +// // // {g} +// // // {f} +// // } +// // // div { +// // // "asd" +// // // div { +// // // "asd" +// // // } +// // // } +// // // Child { +// // // foo: "asd".to_string(), +// // // } +// // Child2 { +// // foo: s, +// // } +// // } +// // }) +// } - f.raw_element( - "div", - None, - [], - [], - [ - // - f.fragment_from_iter(a), - f.fragment_from_iter(b), - f.fragment_from_iter(c), - f.fragment_from_iter(e), - ], - None, - ) - // todo!() - })) - // cx.render(rsx! { - // div { - // div { - // {a} - // // {p} - // // {g} - // // {f} - // } - // // div { - // // "asd" - // // div { - // // "asd" - // // } - // // } - // // Child { - // // foo: "asd".to_string(), - // // } - // Child2 { - // foo: s, - // } - // } - // }) -} - -fn Child((cx, props): Scope) -> Element { - cx.render(rsx! { - div { - div {} - } - }) -} +// fn Child((cx, props): Scope) -> Element { +// cx.render(rsx! { +// div { +// div {} +// } +// }) +// } #[derive(Props)] struct Child2Props<'a> { @@ -221,9 +222,114 @@ struct Child2Props<'a> { } fn Child2<'a>((cx, props): Scope<'a, Child2Props>) -> Element<'a> { + let node = cx + .render(rsx! { + div { + + } + }) + .unwrap(); + + let b = cx.bump(); + let node: &'a VNode<'a> = b.alloc(node); + + let children = ChildList { pthru: node }; + + // let c = VComponent { + // key: todo!(), + // associated_scope: todo!(), + // is_static: todo!(), + // user_fc: todo!(), + // caller: todo!(), + // children: todo!(), + // comparator: todo!(), + // drop_props: todo!(), + // can_memoize: todo!(), + // raw_props: todo!(), + // }; + + // Vcomp + // - borrowed + // - memoized + + cx.render({ + NodeFactory::annotate_lazy(move |__cx: NodeFactory| -> VNode { + use dioxus_elements::{GlobalAttributes, SvgAttributes}; + __cx.element( + dioxus_elements::div, + [], + [], + [], + // [__cx.component( + // ChildrenComp, + // { + // let mut __manual_props = ChildrenTest { node: children }; + // __manual_props + // }, + // None, + // [], + // )], + None, + ) + }) + }) + // cx.render(rsx! { + // div { + // // div {} + + // ChildrenComp { + // // node: children + // ..ChildrenTest { + // node: children, + // } + // } + // } + // }) +} + +#[derive(Props)] +struct ChildrenTest<'a> { + node: ChildList<'a>, +} + +struct ChildList<'a> { + pthru: &'a VNode<'a>, +} + +impl<'a> Clone for ChildList<'a> { + fn clone(&self) -> Self { + Self { pthru: self.pthru } + } +} +impl<'a> Copy for ChildList<'a> {} + +impl<'a> IntoVNode<'a> for ChildList<'a> { + fn into_vnode(self, _: NodeFactory<'a>) -> VNode<'a> { + match self.pthru { + VNode::Text(f) => VNode::Text(*f), + VNode::Element(e) => VNode::Element(*e), + VNode::Component(c) => VNode::Component(*c), + VNode::Suspended(s) => VNode::Suspended(*s), + VNode::Anchor(a) => VNode::Anchor(a), + VNode::Fragment(f) => VNode::Fragment(VFragment { + children: f.children, + is_static: f.is_static, + key: f.key, + }), + } + } +} + +fn ChildrenComp<'a>((cx, props): Scope<'a, ChildrenTest<'a>>) -> Element<'a> { cx.render(rsx! { div { - // div {} + div { + + // if the node's id is already assigned, then it's being passed in as a child + // in these instances, we don't worry about re-checking the node? + + {Some(props.node)} + } } }) } diff --git a/packages/core/src/bumpframe.rs b/packages/core/src/bumpframe.rs index a696d82b5..ac1c66189 100644 --- a/packages/core/src/bumpframe.rs +++ b/packages/core/src/bumpframe.rs @@ -21,16 +21,27 @@ pub(crate) struct BumpFrame { impl ActiveFrame { pub fn new() -> Self { + let b1 = Bump::new(); + let b2 = Bump::new(); + let frame_a = BumpFrame { - bump: Bump::new(), - head_node: NodeFactory::unstable_place_holder(), + head_node: VNode::Fragment(VFragment { + key: None, + children: &[], + is_static: false, + }), + bump: b1, #[cfg(test)] _name: "wip", }; let frame_b = BumpFrame { - bump: Bump::new(), - head_node: NodeFactory::unstable_place_holder(), + head_node: VNode::Fragment(VFragment { + key: None, + children: &[], + is_static: false, + }), + bump: b2, #[cfg(test)] _name: "fin", diff --git a/packages/core/src/context.rs b/packages/core/src/context.rs index ccbcfc92a..58ec04680 100644 --- a/packages/core/src/context.rs +++ b/packages/core/src/context.rs @@ -4,6 +4,8 @@ //! //! We unsafely implement `send` for the VirtualDom, but those guarantees can only be +use bumpalo::Bump; + use crate::innerlude::*; use std::{any::TypeId, ops::Deref, rc::Rc}; @@ -122,6 +124,11 @@ impl<'src> Context<'src> { self.scope.our_arena_idx } + pub fn bump(&self) -> &'src Bump { + let bump = &self.scope.frames.wip_frame().bump; + bump + } + /// Take a lazy VNode structure and actually build it with the context of the VDom's efficient VNode allocator. /// /// This function consumes the context and absorb the lifetime, so these VNodes *must* be returned. diff --git a/packages/core/src/diff.rs b/packages/core/src/diff.rs index 9788a75c1..c52f54284 100644 --- a/packages/core/src/diff.rs +++ b/packages/core/src/diff.rs @@ -421,6 +421,10 @@ impl<'bump> DiffMachine<'bump> { ) => self .stack .create_node(new_node, MountType::Replace { old: old_node }), + + (Placeholder, _) | (_, Placeholder) => { + unreachable!("placeholder should never be diffed"); + } } } @@ -1125,6 +1129,7 @@ impl<'bump> DiffMachine<'bump> { self.remove_nodes(e.children, false); } + VNode::Fragment(f) => { self.remove_nodes(f.children, gen_muts); } diff --git a/packages/core/src/nodes.rs b/packages/core/src/nodes.rs index fbfa93d65..fb250f1c4 100644 --- a/packages/core/src/nodes.rs +++ b/packages/core/src/nodes.rs @@ -10,7 +10,6 @@ use bumpalo::{boxed::Box as BumpBox, Bump}; use std::{ cell::{Cell, RefCell}, fmt::{Arguments, Debug, Formatter}, - marker::PhantomData, }; /// A composable "VirtualNode" to declare a User Interface in the Dioxus VirtualDOM. @@ -33,7 +32,7 @@ pub enum VNode<'src> { /// assert_eq!(vtext.is_static, true); /// } /// ``` - Text(VText<'src>), + Text(&'src VText<'src>), /// Element VNodes are VNodes that may contain attributes, listeners, a key, a tag, and children. /// @@ -116,7 +115,7 @@ pub enum VNode<'src> { /// assert_eq!(root, VNode::Anchor); /// } /// ``` - Anchor(VAnchor), + Anchor(&'src VAnchor), } impl<'src> VNode<'src> { @@ -328,21 +327,21 @@ impl<'a> NodeFactory<'a> { self.bump } - pub fn unstable_place_holder() -> VNode<'static> { - VNode::Text(VText { + pub(crate) fn unstable_place_holder(&self) -> VNode { + VNode::Text(self.bump.alloc(VText { text: "", dom_id: empty_cell(), is_static: true, - }) + })) } /// Directly pass in text blocks without the need to use the format_args macro. pub fn static_text(&self, text: &'static str) -> VNode<'a> { - VNode::Text(VText { + VNode::Text(self.bump.alloc(VText { dom_id: empty_cell(), text, is_static: true, - }) + })) } /// Parses a lazy text Arguments and returns a string and a flag indicating if the text is 'static @@ -365,11 +364,11 @@ impl<'a> NodeFactory<'a> { pub fn text(&self, args: Arguments) -> VNode<'a> { let (text, is_static) = self.raw_text(args); - VNode::Text(VText { + VNode::Text(self.bump.alloc(VText { text, is_static, dom_id: empty_cell(), - }) + })) } pub fn element( @@ -556,9 +555,9 @@ impl<'a> NodeFactory<'a> { } if nodes.is_empty() { - nodes.push(VNode::Anchor(VAnchor { + nodes.push(VNode::Anchor(bump.alloc(VAnchor { dom_id: empty_cell(), - })); + }))); } let children = nodes.into_bump_slice();