diff --git a/packages/core-macro/src/rsx/body.rs b/packages/core-macro/src/rsx/body.rs index b5b487459..a9a86daef 100644 --- a/packages/core-macro/src/rsx/body.rs +++ b/packages/core-macro/src/rsx/body.rs @@ -57,11 +57,21 @@ impl ToTokens for CallBody { }), // Otherwise we just build the LazyNode wrapper None => out_tokens.append_all(quote! { - dioxus::prelude::LazyNodes::new(move |__cx: NodeFactory|{ - use dioxus_elements::{GlobalAttributes, SvgAttributes}; - #inner - }) + { + + let ___p: Box VNode + '_> = Box::new(move |__cx: NodeFactory|{ + use dioxus_elements::{GlobalAttributes, SvgAttributes}; + + #inner + }); + Some(___p) + } + // dioxus::prelude::LazyNodes::new(move |__cx: NodeFactory|{ + // use dioxus_elements::{GlobalAttributes, SvgAttributes}; + + // #inner + // }) }), }; } diff --git a/packages/core/examples/jsframework.rs b/packages/core/examples/jsframework.rs index c0c7af057..207f6e84e 100644 --- a/packages/core/examples/jsframework.rs +++ b/packages/core/examples/jsframework.rs @@ -41,22 +41,22 @@ struct RowProps { label: Label, } -fn Row((cx, props): Scope) -> Element { +fn Row<'a>((cx, props): Scope<'a, RowProps>) -> Element<'a> { let handler = move |evt: MouseEvent| { let g = evt.button; }; cx.render(rsx! { tr { - td { class:"col-md-1", "{props.row_id}" } - td { class:"col-md-1", onclick: move |_| { /* run onselect */ } - a { class: "lbl", "{props.label}" } - } - td { class: "col-md-1" - a { class: "remove", onclick: {handler} - span { class: "glyphicon glyphicon-remove remove" aria_hidden: "true" } - } - } - td { class: "col-md-6" } + // td { class:"col-md-1", "{props.row_id}" } + // td { class:"col-md-1", onclick: move |_| { /* run onselect */ } + // a { class: "lbl", "{props.label}" } + // } + // td { class: "col-md-1" + // a { class: "remove", onclick: {handler} + // span { class: "glyphicon glyphicon-remove remove" aria_hidden: "true" } + // } + // } + // td { class: "col-md-6" } } }) } diff --git a/packages/core/examples/syntax.rs b/packages/core/examples/syntax.rs index e4bc82fa3..2e8447949 100644 --- a/packages/core/examples/syntax.rs +++ b/packages/core/examples/syntax.rs @@ -57,10 +57,11 @@ fn App3((cx, props): Scope<()>) -> Element { bame: 10, } }; - cx.render(rsx!(Child { - bame: 102, - ..ChildProps { bame: 10 } - })) + todo!() + // cx.render(rsx!(Child { + // bame: 102, + // ..ChildProps { bame: 10 } + // })) } #[derive(Props, PartialEq, Debug)] @@ -97,11 +98,11 @@ impl<'a> Children<'a> { } } } -impl<'a> IntoVNodeList<'a> for &Children<'a> { - fn into_vnode_list(self, cx: NodeFactory<'a>) -> &'a [VNode<'a>] { - todo!() - } -} +// impl<'a> IntoVNodeList<'a> for &Children<'a> { +// fn into_vnode_list(self, cx: NodeFactory<'a>) -> &'a [VNode<'a>] { +// todo!() +// } +// } static Bapp: FC<()> = |(cx, props)| { let name = cx.use_state(|| 0); @@ -117,3 +118,36 @@ static Bapp: FC<()> = |(cx, props)| { } )) }; + +static Match: FC<()> = |(cx, props)| { + // + let b: Box VNode> = Box::new(|f| todo!()); + + let b = match "ag" { + "a" => { + let __b: Box VNode> = Box::new(|f: NodeFactory| todo!()); + __b + } + _ => { + let __b: Box VNode> = Box::new(|f: NodeFactory| todo!()); + __b + } + }; + + // let b: Box VNode> = match "alph" { + // "beta" => Box::new(|f: NodeFactory| { + // // + // todo!() + // }), + // _ => Box::new(|f: NodeFactory| { + // // + // todo!() + // }), + // }; + + cx.render(rsx! { + div { + + } + }) +}; diff --git a/packages/core/examples/syntax2.rs b/packages/core/examples/syntax2.rs new file mode 100644 index 000000000..fd5e1eb26 --- /dev/null +++ b/packages/core/examples/syntax2.rs @@ -0,0 +1,71 @@ +use std::marker::PhantomData; + +use dioxus::component::Scope; +use dioxus::events::on::MouseEvent; +use dioxus::nodes::{IntoVNode, IntoVNodeList}; +use dioxus_core as dioxus; +use dioxus_core::prelude::*; +use dioxus_core_macro::*; +use dioxus_html as dioxus_elements; + +fn main() {} + +fn t() { + let g = rsx! { + div { + div { + + } + } + }; + + let g = { + let ___p: Box VNode> = Box::new(|__cx: NodeFactory| { + use dioxus_elements::{GlobalAttributes, SvgAttributes}; + __cx.element(dioxus_elements::div, [], [], [], None) + }); + // let __z = ___p as ; + // __z + }; +} + +fn App((cx, props): Scope<()>) -> Element { + let a = rsx! { + div { + "asd" + } + }; + + let p = (0..10).map(|f| { + rsx! { + div { + + } + } + }); + + let g = match "text" { + "a" => rsx!("asd"), + b => rsx!("asd"), + }; + + let items = ["bob", "bill", "jack"]; + + let f = items + .iter() + .filter(|f| f.starts_with('b')) + .map(|f| rsx!("hello {f}")); + + cx.render(rsx! { + div { + div { + {a} + {p} + {g} + {f} + } + } + }) +} + +// std::boxed::Box std::ops::FnOnce(dioxus_core::NodeFactory<'r>) -> dioxus_core::VNode<'_>> diff --git a/packages/core/src/component.rs b/packages/core/src/component.rs index a81a4078d..0738999dc 100644 --- a/packages/core/src/component.rs +++ b/packages/core/src/component.rs @@ -7,7 +7,7 @@ use crate::{ innerlude::{Context, Element, LazyNodes, FC}, - VNode, + NodeFactory, VNode, }; /// A component is a wrapper around a Context and some Props that share a lifetime @@ -66,8 +66,11 @@ pub type Scope<'a, T> = (Context<'a>, &'a T); /// You want to use this free-function when your fragment needs a key and simply returning multiple nodes from rsx! won't cut it. /// #[allow(non_upper_case_globals, non_snake_case)] -pub fn Fragment((cx, _): Scope<()>) -> Element { - cx.render(LazyNodes::new(move |f| f.fragment_from_iter(cx.children()))) +pub fn Fragment<'a>((cx, _): Scope<'a, ()>) -> Element<'a> { + todo!() + // let p: Box) -> VNode<'a> + '_> = + // Box::new(|f: NodeFactory| f.fragment_from_iter(cx.children())); + // cx.render(p) } /// Every "Props" used for a component must implement the `Properties` trait. This trait gives some hints to Dioxus diff --git a/packages/core/src/context.rs b/packages/core/src/context.rs index 5d52a6e4e..33822ffde 100644 --- a/packages/core/src/context.rs +++ b/packages/core/src/context.rs @@ -137,12 +137,30 @@ impl<'src> Context<'src> { /// cx.render(lazy_tree) /// } ///``` - pub fn render) -> VNode<'src>>( + pub fn render( self, - lazy_nodes: LazyNodes<'src, F>, + lazy_nodes: Option>, + // lazy_nodes: Box) -> VNode<'src> + '_>, ) -> Option> { + // pub fn render) -> VNode<'src>>( + // self, + // lazy_nodes: LazyNodes<'src, F>, + // ) -> Option> { let bump = &self.scope.frames.wip_frame().bump; - Some(lazy_nodes.into_vnode(NodeFactory { bump })) + // Some(lazy_nodes.into_vnode(NodeFactory { bump })) + + let factory = NodeFactory { bump }; + // let vnode = lazy_nodes(factory); + + match lazy_nodes { + Some(f) => Some(f(factory)), + None => None, + } + + // match lazy_nodes { + // None => todo!(), + // } + // Some(lazy_nodes) } /// `submit_task` will submit the future to be polled. diff --git a/packages/core/src/hooks.rs b/packages/core/src/hooks.rs index c1de46bfb..8940671f4 100644 --- a/packages/core/src/hooks.rs +++ b/packages/core/src/hooks.rs @@ -181,9 +181,11 @@ pub struct SuspendedContext<'a> { impl<'src> SuspendedContext<'src> { // pub fn render( - pub fn render) -> VNode<'src>>( + pub fn render( + // pub fn render) -> VNode<'src>>( self, - lazy_nodes: LazyNodes<'src, F>, + lazy_nodes: LazyNodes<'_>, + // lazy_nodes: LazyNodes<'src, '_>, ) -> Element<'src> { let bump = &self.inner.scope.frames.wip_frame().bump; todo!("suspense") diff --git a/packages/core/src/lazynodes.rs b/packages/core/src/lazynodes.rs index f10cd2134..e069ac372 100644 --- a/packages/core/src/lazynodes.rs +++ b/packages/core/src/lazynodes.rs @@ -26,12 +26,13 @@ use crate::innerlude::{IntoVNode, NodeFactory, VNode}; /// ```rust /// LazyNodes::new(|f| f.element("div", [], [], [] None)) /// ``` -pub struct LazyNodes<'a, F: FnOnce(NodeFactory<'a>) -> VNode<'a>> { - inner: Box, - _p: PhantomData<&'a ()>, - // inner: StackNodeStorage<'a>, - // inner: StackNodeStorage<'a>, -} +// pub struct LazyNodes<'a, F: FnOnce(NodeFactory<'a>) -> VNode<'a>> { +// inner: Box, +// _p: PhantomData<&'a ()>, +// // inner: StackNodeStorage<'a>, +// // inner: StackNodeStorage<'a>, +// } +pub type LazyNodes<'b> = Box FnOnce(NodeFactory<'a>) -> VNode<'a> + 'b>; type StackHeapSize = [usize; 12]; @@ -44,70 +45,74 @@ enum StackNodeStorage<'a> { Heap(Box) -> VNode<'a>>), } -impl<'a, F: FnOnce(NodeFactory<'a>) -> VNode<'a>> LazyNodes<'a, F> { - pub fn new(f: F) -> Self { - // let width = std::mem?::size_of::(); - // let b: Box) -> VNode<'a>> = Box::new(f); +// impl<'a, F: FnOnce(NodeFactory<'a>) -> VNode<'a>> LazyNodes<'a, F> { +// pub fn new(f: F) -> Self { +// // let width = std::mem?::size_of::(); +// // let b: Box) -> VNode<'a>> = Box::new(f); - todo!() - // Self { inner: b } - // todo!() +// todo!() +// // Self { inner: b } +// // todo!() - // if width > std::mem::size_of::() { - // let g: Box FnOnce(NodeFactory<'b>) -> VNode<'b> + 'g> = Box::new(f); - // LazyNodes { - // inner: StackNodeStorage::Heap(g), - // } - // } else { - // let mut buf = [0; 12]; - // let mut next_ofs = 0; - // next_ofs += 1; - // LazyNodes { - // inner: StackNodeStorage::Stack { - // next_ofs, - // buf, - // width, - // }, - // } - // } - } -} +// // if width > std::mem::size_of::() { +// // let g: Box FnOnce(NodeFactory<'b>) -> VNode<'b> + 'g> = Box::new(f); +// // LazyNodes { +// // inner: StackNodeStorage::Heap(g), +// // } +// // } else { +// // let mut buf = [0; 12]; +// // let mut next_ofs = 0; +// // next_ofs += 1; +// // LazyNodes { +// // inner: StackNodeStorage::Stack { +// // next_ofs, +// // buf, +// // width, +// // }, +// // } +// // } +// } +// } -// Our blanket impl -impl<'a, F> IntoIterator for LazyNodes<'a, F> -where - F: FnOnce(NodeFactory<'a>) -> VNode<'a>, -{ - type Item = Self; - type IntoIter = std::iter::Once; - fn into_iter(self) -> Self::IntoIter { - std::iter::once(self) - } -} +// // Our blanket impl +// impl<'a> IntoIterator for LazyNodes<'a> +// // where +// // F: FnOnce(NodeFactory<'a>) -> VNode<'a>, +// // impl<'a, F> IntoIterator for LazyNodes<'a, F> +// // where +// // F: FnOnce(NodeFactory<'a>) -> VNode<'a>, +// { +// type Item = Self; +// type IntoIter = std::iter::Once; +// fn into_iter(self) -> Self::IntoIter { +// std::iter::once(self) +// } +// } -// Our blanket impl -impl<'a, F: FnOnce(NodeFactory<'a>) -> VNode<'a>> IntoVNode<'a> for LazyNodes<'a, F> { - fn into_vnode(self, cx: NodeFactory<'a>) -> VNode<'a> { - todo!() - // match self.inner { - // StackNodeStorage::Stack { - // buf, - // next_ofs, - // width, - // } => { - // // get the start of the allocation - // let r = &buf[0]; +// // Our blanket impl +// impl IntoVNode for LazyNodes<'_> { +// // impl<'a, F: FnOnce(NodeFactory<'a>) -> VNode<'a>> IntoVNode<'a> for LazyNodes<'a, F> { +// fn into_vnode<'a>(self, cx: NodeFactory<'a>) -> VNode<'a> { +// todo!() +// // match self.inner { +// // StackNodeStorage::Stack { +// // buf, +// // next_ofs, +// // width, +// // } => { +// // // get the start of the allocation +// // let r = &buf[0]; - // // recast the allocation as dyn FnOnce +// // // recast the allocation as dyn FnOnce - // // pretend the FnOnce is box - // let g: Box) -> VNode<'a>> = todo!(); - // // Box::from_raw(r as *const usize as *mut dyn FnOnce(NodeFactory<'a>)); +// // // pretend the FnOnce is box +// // let g: Box) -> VNode<'a>> = todo!(); +// // // Box::from_raw(r as *const usize as *mut dyn FnOnce(NodeFactory<'a>)); - // // use Box's ability to act as FnOnce - // g(cx) - // } - // StackNodeStorage::Heap(b) => b(cx), - // } - } -} +// // // use Box's ability to act as FnOnce +// // g(cx) +// // } +// // StackNodeStorage::Heap(b) => b(cx), +// // } +// } +// } diff --git a/packages/core/src/nodes.rs b/packages/core/src/nodes.rs index 10f4d25f9..964cdb42a 100644 --- a/packages/core/src/nodes.rs +++ b/packages/core/src/nodes.rs @@ -329,12 +329,19 @@ impl<'a> NodeFactory<'a> { self.bump } - pub fn render_directly(&self, lazy_nodes: LazyNodes<'a, F>) -> Element<'a> - where - F: FnOnce(NodeFactory<'a>) -> VNode<'a>, + pub fn render_directly(&self, lazy_nodes: LazyNodes<'_>) -> Element<'a> +// pub fn render_directly(&self, lazy_nodes: LazyNodes<'a, '_>) -> Element<'a> +// where + // F: FnOnce(NodeFactory<'a>) -> VNode<'a>, { + // pub fn render_directly(&self, lazy_nodes: LazyNodes<'a, F>) -> Element<'a> + // where + // F: FnOnce(NodeFactory<'a>) -> VNode<'a>, + // { // pub fn render_directly(&self, lazy_nodes: LazyNodes<'a>) -> Option> { - Some(lazy_nodes.into_vnode(NodeFactory { bump: self.bump })) + // Some(lazy_nodes.into_vnode(NodeFactory { bump: self.bump })) + + todo!() } pub fn unstable_place_holder() -> VNode<'static> { @@ -552,7 +559,7 @@ impl<'a> NodeFactory<'a> { })) } - pub fn fragment_from_iter(self, node_iter: impl IntoVNodeList<'a>) -> VNode<'a> { + pub fn fragment_from_iter(self, node_iter: impl IntoVNodeList) -> VNode<'a> { let children = node_iter.into_vnode_list(self); // TODO @@ -597,20 +604,20 @@ impl<'a> NodeFactory<'a> { /// /// As such, all node creation must go through the factory, which is only available in the component context. /// These strict requirements make it possible to manage lifetimes and state. -pub trait IntoVNode<'a> { - fn into_vnode(self, cx: NodeFactory<'a>) -> VNode<'a>; +pub trait IntoVNode { + fn into_vnode<'a>(self, cx: NodeFactory<'a>) -> VNode<'a>; } -pub trait IntoVNodeList<'a> { - fn into_vnode_list(self, cx: NodeFactory<'a>) -> &'a [VNode<'a>]; +pub trait IntoVNodeList { + fn into_vnode_list<'a>(self, cx: NodeFactory<'a>) -> &'a [VNode<'a>]; } -impl<'a, T, V> IntoVNodeList<'a> for T +impl IntoVNodeList for T where T: IntoIterator, - V: IntoVNode<'a>, + V: IntoVNode, { - fn into_vnode_list(self, cx: NodeFactory<'a>) -> &'a [VNode<'a>] { + fn into_vnode_list<'a>(self, cx: NodeFactory<'a>) -> &'a [VNode<'a>] { let mut nodes = bumpalo::collections::Vec::new_in(cx.bump()); for node in self.into_iter() { @@ -662,11 +669,11 @@ impl ScopeChildren<'_> { } } -impl<'a> IntoVNodeList<'a> for ScopeChildren<'a> { - fn into_vnode_list(self, _: NodeFactory<'a>) -> &'a [VNode<'a>] { - self.0 - } -} +// impl IntoVNodeList for ScopeChildren<'_> { +// fn into_vnode_list<'a>(self, _: NodeFactory<'a>) -> &'a [VNode<'a>] { +// self.0 +// } +// } // For the case where a rendered VNode is passed into the rsx! macro through curly braces impl<'a> IntoIterator for VNode<'a> { @@ -677,51 +684,74 @@ impl<'a> IntoIterator for VNode<'a> { } } -// For the case where a rendered VNode is passed into the rsx! macro through curly braces -impl<'a> IntoVNode<'a> for VNode<'a> { - fn into_vnode(self, _: NodeFactory<'a>) -> VNode<'a> { - self - } -} +// // For the case where a rendered VNode is passed into the rsx! macro through curly braces +// impl IntoVNode for VNode<'_> { +// fn into_vnode<'a>(self, _: NodeFactory<'a>) -> VNode<'a> { +// self +// } +// } // Conveniently, we also support "null" (nothing) passed in -impl IntoVNode<'_> for () { - fn into_vnode(self, cx: NodeFactory) -> VNode { - cx.fragment_from_iter(None as Option) - } -} +// impl IntoVNode for () { +// fn into_vnode(self, cx: NodeFactory) -> VNode { +// cx.fragment_from_iter(None as Option) +// } +// } -// Conveniently, we also support "None" -impl IntoVNode<'_> for Option<()> { - fn into_vnode(self, cx: NodeFactory) -> VNode { - cx.fragment_from_iter(None as Option) - } -} +// // Conveniently, we also support "None" +// impl IntoVNode for Option<()> { +// fn into_vnode(self, cx: NodeFactory) -> VNode { +// cx.fragment_from_iter(None as Option) +// } +// } -impl<'a> IntoVNode<'a> for Option> { - fn into_vnode(self, cx: NodeFactory<'a>) -> VNode<'a> { +// impl IntoVNode for Option> { +// fn into_vnode<'a>(self, cx: NodeFactory<'a>) -> VNode<'a> { +// match self { +// Some(n) => n, +// None => cx.fragment_from_iter(None as Option), +// } +// } +// } + +impl IntoVNode for Option FnOnce(NodeFactory<'r>) -> VNode<'_> + '_>> { + fn into_vnode<'a>(self, cx: NodeFactory<'a>) -> VNode<'a> { match self { - Some(n) => n, - None => cx.fragment_from_iter(None as Option), + Some(n) => { + // + // n.into_vnode(cx) + n(cx) + } + None => VNode::Fragment(VFragment { + children: &[], + is_static: false, + key: None, + }), } } } -impl<'a, F: FnOnce(NodeFactory<'a>) -> VNode<'a>> IntoVNode<'a> for Option> { - fn into_vnode(self, cx: NodeFactory<'a>) -> VNode<'a> { - match self { - Some(n) => n.into_vnode(cx), - None => cx.fragment_from_iter(None as Option), - } +impl IntoVNode for Box FnOnce(NodeFactory<'r>) -> VNode<'_> + '_> { + fn into_vnode<'a>(self, cx: NodeFactory<'a>) -> VNode<'a> { + self(cx) } } -impl IntoVNode<'_> for &'static str { +// impl<'a, F: FnOnce(NodeFactory<'a>) -> VNode<'a>> IntoVNode<'a> for Option> { +// fn into_vnode(self, cx: NodeFactory<'a>) -> VNode<'a> { +// match self { +// Some(n) => n.into_vnode(cx), +// None => cx.fragment_from_iter(None as Option), +// } +// } +// } + +impl IntoVNode for &'static str { fn into_vnode(self, cx: NodeFactory) -> VNode { cx.static_text(self) } } -impl IntoVNode<'_> for Arguments<'_> { +impl IntoVNode for Arguments<'_> { fn into_vnode(self, cx: NodeFactory) -> VNode { cx.text(self) } diff --git a/packages/core/src/test_dom.rs b/packages/core/src/test_dom.rs index 2f7977269..a11bea50e 100644 --- a/packages/core/src/test_dom.rs +++ b/packages/core/src/test_dom.rs @@ -25,15 +25,17 @@ impl TestDom { // where // F: FnOnce(NodeFactory<'a>) -> VNode<'a>, { - lazy_nodes.into_vnode(NodeFactory::new(&self.bump)) + todo!() + // lazy_nodes.into_vnode(NodeFactory::new(&self.bump)) } pub fn render<'a>(&'a self, lazy_nodes: Element<'a>) -> &'a VNode<'a> // where // F: FnOnce(NodeFactory<'a>) -> VNode<'a>, { - self.bump - .alloc(lazy_nodes.into_vnode(NodeFactory::new(&self.bump))) + todo!() + // self.bump + // .alloc(lazy_nodes.into_vnode(NodeFactory::new(&self.bump))) } pub fn diff<'a>(&'a self, old: &'a VNode<'a>, new: &'a VNode<'a>) -> Mutations<'a> {