wip: move everything over to a stack dst

This commit is contained in:
Jonathan Kelley committed 2021-10-29 17:12:30 -04:00
1 parent 12a9758c3c
commit 0e9d5fc530
36 files changed
+224 -185

No files matched your search

+4 -4
View File
@@ -20,7 +20,7 @@ fn main() {
dioxus::desktop::launch(App, |c| c); dioxus::desktop::launch(App, |c| c);
} }
fn App((cx, props): Component<()>) -> DomTree { fn App((cx, props): Component<()>) -> Element {
let text: &mut Vec<String> = cx.use_hook(|_| vec![String::from("abc=def")], |f| f, |_| {}); let text: &mut Vec<String> = cx.use_hook(|_| vec![String::from("abc=def")], |f| f, |_| {});
let first = text.get_mut(0).unwrap(); let first = text.get_mut(0).unwrap();
@@ -43,7 +43,7 @@ impl<'a> Drop for C1Props<'a> {
fn drop(&mut self) {} fn drop(&mut self) {}
} }
fn Child1<'a>((cx, props): Component<'a, C1Props>) -> DomTree<'a> { fn Child1<'a>((cx, props): Component<'a, C1Props>) -> Element<'a> {
let (left, right) = props.text.split_once("=").unwrap(); let (left, right) = props.text.split_once("=").unwrap();
cx.render(rsx! { cx.render(rsx! {
@@ -59,7 +59,7 @@ struct C2Props<'a> {
text: &'a str, text: &'a str,
} }
fn Child2<'a>((cx, props): Component<'a, C2Props>) -> DomTree<'a> { fn Child2<'a>((cx, props): Component<'a, C2Props>) -> Element<'a> {
cx.render(rsx! { cx.render(rsx! {
Child3 { Child3 {
text: props.text text: props.text
@@ -72,7 +72,7 @@ struct C3Props<'a> {
text: &'a str, text: &'a str,
} }
fn Child3<'a>((cx, props): Component<'a, C3Props>) -> DomTree<'a> { fn Child3<'a>((cx, props): Component<'a, C3Props>) -> Element<'a> {
cx.render(rsx! { cx.render(rsx! {
div { "{props.text}"} div { "{props.text}"}
}) })
+1 -1
View File
@@ -116,7 +116,7 @@ struct CalculatorKeyProps<'a> {
onclick: &'a dyn Fn(MouseEvent), onclick: &'a dyn Fn(MouseEvent),
} }
fn CalculatorKey<'a>((cx, props): Component<'a, CalculatorKeyProps>) -> DomTree<'a> { fn CalculatorKey<'a>((cx, props): Component<'a, CalculatorKeyProps>) -> Element<'a> {
rsx!(cx, button { rsx!(cx, button {
class: "calculator-key {props.name}" class: "calculator-key {props.name}"
onclick: {props.onclick} onclick: {props.onclick}
+2 -2
View File
@@ -80,7 +80,7 @@ struct ActionButtonProps<'a> {
onclick: &'a dyn Fn(MouseEvent), onclick: &'a dyn Fn(MouseEvent),
} }
fn ActionButton<'a>((cx, props): Component<'a, ActionButtonProps>) -> DomTree<'a> { fn ActionButton<'a>((cx, props): Component<'a, ActionButtonProps>) -> Element<'a> {
rsx!(cx, div { class: "col-sm-6 smallpad" rsx!(cx, div { class: "col-sm-6 smallpad"
button { class:"btn btn-primary btn-block", r#type: "button", id: "{props.id}", onclick: {props.onclick}, button { class:"btn btn-primary btn-block", r#type: "button", id: "{props.id}", onclick: {props.onclick},
"{props.name}" "{props.name}"
@@ -93,7 +93,7 @@ struct RowProps {
row_id: usize, row_id: usize,
label: Rc<str>, label: Rc<str>,
} }
fn Row((cx, props): Component<RowProps>) -> DomTree { fn Row((cx, props): Component<RowProps>) -> Element {
rsx!(cx, tr { rsx!(cx, tr {
td { class:"col-md-1", "{props.row_id}" } td { class:"col-md-1", "{props.row_id}" }
td { class:"col-md-1", onclick: move |_| { /* run onselect */ } td { class:"col-md-1", onclick: move |_| { /* run onselect */ }
+1 -1
View File
@@ -4,7 +4,7 @@ fn main() {
dioxus::desktop::launch(App, |c| c); dioxus::desktop::launch(App, |c| c);
} }
fn App((cx, props): Component<()>) -> DomTree { fn App((cx, props): Component<()>) -> Element {
cx.render(rsx! ( cx.render(rsx! (
div { "Hello, world!" } div { "Hello, world!" }
)) ))
+1 -1
View File
@@ -76,7 +76,7 @@ struct CalculatorKeyProps<'a> {
onclick: &'a dyn Fn(MouseEvent), onclick: &'a dyn Fn(MouseEvent),
} }
fn CalculatorKey<'a>((cx, props): Component<'a, CalculatorKeyProps>) -> DomTree<'a> { fn CalculatorKey<'a>((cx, props): Component<'a, CalculatorKeyProps>) -> Element<'a> {
cx.render(rsx! { cx.render(rsx! {
button { button {
class: "calculator-key {props.name}" class: "calculator-key {props.name}"
+2 -2
View File
@@ -184,7 +184,7 @@ mod baller {
pub struct BallerProps {} pub struct BallerProps {}
/// This component totally balls /// This component totally balls
pub fn Baller(_: Component<BallerProps>) -> DomTree { pub fn Baller(_: Component<BallerProps>) -> Element {
todo!() todo!()
} }
} }
@@ -195,7 +195,7 @@ pub struct TallerProps {
} }
/// This component is taller than most :) /// This component is taller than most :)
pub fn Taller(_: Component<TallerProps>) -> DomTree { pub fn Taller(_: Component<TallerProps>) -> Element {
let b = true; let b = true;
todo!() todo!()
} }
+1 -1
View File
@@ -21,6 +21,6 @@ static App: FC<()> = |(cx, props)| {
struct MyProps<'a> { struct MyProps<'a> {
text: &'a str, text: &'a str,
} }
fn App2<'a>(cx: Context<'a>, props: &'a MyProps) -> DomTree<'a> { fn App2<'a>(cx: Context<'a>, props: &'a MyProps) -> Element<'a> {
None None
} }
+1 -1
View File
@@ -85,7 +85,7 @@ pub struct TodoEntryProps {
todo: Rc<TodoItem>, todo: Rc<TodoItem>,
} }
pub fn TodoEntry((cx, props): Component<TodoEntryProps>) -> DomTree { pub fn TodoEntry((cx, props): Component<TodoEntryProps>) -> Element {
let is_editing = use_state(cx, || false); let is_editing = use_state(cx, || false);
let contents = use_state(cx, || String::from("")); let contents = use_state(cx, || String::from(""));
let todo = &props.todo; let todo = &props.todo;
+1 -1
View File
@@ -45,7 +45,7 @@ struct RowProps {
row_id: usize, row_id: usize,
label: Label, label: Label,
} }
fn Row((cx, props): Component<RowProps>) -> DomTree { fn Row((cx, props): Component<RowProps>) -> Element {
let [adj, col, noun] = props.label.0; let [adj, col, noun] = props.label.0;
cx.render(rsx! { cx.render(rsx! {
tr { tr {
+2 -2
View File
@@ -57,11 +57,11 @@ impl ToTokens for CallBody {
}), }),
// Otherwise we just build the LazyNode wrapper // Otherwise we just build the LazyNode wrapper
None => out_tokens.append_all(quote! { None => out_tokens.append_all(quote! {
dioxus::prelude::LazyNodes::new(move |__cx: NodeFactory|{ Some(dioxus::prelude::LazyNodes::new(move |__cx: NodeFactory|{
use dioxus_elements::{GlobalAttributes, SvgAttributes}; use dioxus_elements::{GlobalAttributes, SvgAttributes};
#inner #inner
}) }))
}), }),
}; };
} }
+5 -1
View File
@@ -22,7 +22,9 @@ longest-increasing-subsequence = "0.1.0"
# internall used # internall used
log = { version = "0.4", features = ["release_max_level_off"] } log = { version = "0.4", features = ["release_max_level_off"] }
futures-util = { version = "0.3.15", no_default_features = true } futures-util = { version = "0.3.15", default-features = false, features = [
"std",
] }
smallvec = "1.6.1" smallvec = "1.6.1"
@@ -40,6 +42,8 @@ serde = { version = "1", features = ["derive"], optional = true }
serde_repr = { version = "0.1.7", optional = true } serde_repr = { version = "0.1.7", optional = true }
stack_dst = "0.6.1"
[dev-dependencies] [dev-dependencies]
anyhow = "1.0.42" anyhow = "1.0.42"
dioxus-html = { path = "../html" } dioxus-html = { path = "../html" }
+5 -5
View File
@@ -34,13 +34,13 @@ fn create_rows(c: &mut Criterion) {
} }
} }
}); });
cx.render(rsx! { rsx! {
table { table {
tbody { tbody {
{rows} {rows}
} }
} }
}) }
}; };
c.bench_function("create rows", |b| { c.bench_function("create rows", |b| {
@@ -57,9 +57,9 @@ struct RowProps {
row_id: usize, row_id: usize,
label: Label, label: Label,
} }
fn Row((cx, props): Component<RowProps>) -> DomTree { fn Row((cx, props): Component<RowProps>) -> Element {
let [adj, col, noun] = props.label.0; let [adj, col, noun] = props.label.0;
cx.render(rsx! { rsx! {
tr { tr {
td { class:"col-md-1", "{props.row_id}" } td { class:"col-md-1", "{props.row_id}" }
td { class:"col-md-1", onclick: move |_| { /* run onselect */ } td { class:"col-md-1", onclick: move |_| { /* run onselect */ }
@@ -72,7 +72,7 @@ fn Row((cx, props): Component<RowProps>) -> DomTree {
} }
td { class: "col-md-6" } td { class: "col-md-6" }
} }
}) }
} }
#[derive(PartialEq)] #[derive(PartialEq)]
+1 -1
View File
@@ -9,7 +9,7 @@ fn main() {
pub static EXAMPLE: FC<()> = |(cx, _)| { pub static EXAMPLE: FC<()> = |(cx, _)| {
let list = (0..10).map(|_f| LazyNodes::new(move |_f| todo!())); let list = (0..10).map(|_f| LazyNodes::new(move |_f| todo!()));
cx.render(LazyNodes::new(move |cx| { Some(LazyNodes::new(move |cx| {
cx.raw_element( cx.raw_element(
"div", "div",
None, None,
+4 -4
View File
@@ -20,10 +20,10 @@ struct ListItem {
age: u32, age: u32,
} }
fn app<'a>(cx: Context<'a>, props: &AppProps) -> DomTree<'a> { fn app<'a>(cx: Context<'a>, props: &AppProps) -> Element<'a> {
// let (val, set_val) = use_state_classic(cx, || 0); // let (val, set_val) = use_state_classic(cx, || 0);
cx.render(LazyNodes::new(move |_nodecx| { Some(LazyNodes::new(move |_nodecx| {
todo!() todo!()
// builder::ElementBuilder::new(_nodecx, "div") // builder::ElementBuilder::new(_nodecx, "div")
// .iter_child({ // .iter_child({
@@ -56,8 +56,8 @@ struct ChildProps {
item_handler: Rc<dyn Fn(i32)>, item_handler: Rc<dyn Fn(i32)>,
} }
fn ChildItem<'a>(cx: Context<'a>, props: &'a ChildProps) -> DomTree<'a> { fn ChildItem<'a>(cx: Context<'a>, props: &'a ChildProps) -> Element<'a> {
cx.render(LazyNodes::new(move |__cx| todo!())) Some(LazyNodes::new(move |__cx| todo!()))
} }
impl PartialEq for ChildProps { impl PartialEq for ChildProps {
+2 -2
View File
@@ -2,7 +2,7 @@ use dioxus_core::prelude::*;
fn main() {} fn main() {}
fn app<'a>(cx: Context<'a>, props: &()) -> DomTree<'a> { fn app<'a>(cx: Context<'a>, props: &()) -> Element<'a> {
let vak = use_suspense( let vak = use_suspense(
cx, cx,
|| async {}, || async {},
@@ -26,7 +26,7 @@ fn app<'a>(cx: Context<'a>, props: &()) -> DomTree<'a> {
) )
})); }));
cx.render(LazyNodes::new(move |f| { Some(LazyNodes::new(move |f| {
f.raw_element( f.raw_element(
"div", "div",
None, None,
+6 -6
View File
@@ -15,7 +15,7 @@ fn main() {
assert!(g.edits.len() > 1); assert!(g.edits.len() > 1);
} }
fn App((cx, props): Component<()>) -> DomTree { fn App((cx, props): Component<()>) -> Element {
let mut rng = SmallRng::from_entropy(); let mut rng = SmallRng::from_entropy();
let rows = (0..10_000_usize).map(|f| { let rows = (0..10_000_usize).map(|f| {
let label = Label::new(&mut rng); let label = Label::new(&mut rng);
@@ -26,13 +26,13 @@ fn App((cx, props): Component<()>) -> DomTree {
} }
} }
}); });
cx.render(rsx! { rsx! {
table { table {
tbody { tbody {
{rows} {rows}
} }
} }
}) }
} }
#[derive(PartialEq, Props)] #[derive(PartialEq, Props)]
@@ -41,11 +41,11 @@ struct RowProps {
label: Label, label: Label,
} }
fn Row((cx, props): Component<RowProps>) -> DomTree { fn Row((cx, props): Component<RowProps>) -> Element {
let handler = move |evt: MouseEvent| { let handler = move |evt: MouseEvent| {
let g = evt.button; let g = evt.button;
}; };
cx.render(rsx! { rsx! {
tr { tr {
td { class:"col-md-1", "{props.row_id}" } td { class:"col-md-1", "{props.row_id}" }
td { class:"col-md-1", onclick: move |_| { /* run onselect */ } td { class:"col-md-1", onclick: move |_| { /* run onselect */ }
@@ -58,7 +58,7 @@ fn Row((cx, props): Component<RowProps>) -> DomTree {
} }
td { class: "col-md-6" } td { class: "col-md-6" }
} }
}) }
} }
#[derive(PartialEq)] #[derive(PartialEq)]
+5
View File
@@ -32,3 +32,8 @@ fn html_usage() {
} }
}; };
} }
static App: FC<()> = |(cx, props)| {
//
rsx!(div {})
};
+1 -1
View File
@@ -4,7 +4,7 @@ use dioxus_core::prelude::*;
#[async_std::main] #[async_std::main]
async fn main() { async fn main() {
static App: FC<()> = |(cx, props)| cx.render(LazyNodes::new(|f| f.text(format_args!("hello")))); static App: FC<()> = |(cx, props)| Some(LazyNodes::new(|f| f.text(format_args!("hello"))));
let mut dom = VirtualDom::new(App); let mut dom = VirtualDom::new(App);
+6 -3
View File
@@ -5,7 +5,10 @@
//! if the type supports PartialEq. The Properties trait is used by the rsx! and html! macros to generate the type-safe builder //! if the type supports PartialEq. The Properties trait is used by the rsx! and html! macros to generate the type-safe builder
//! that ensures compile-time required and optional fields on cx. //! that ensures compile-time required and optional fields on cx.
use crate::innerlude::{Context, DomTree, LazyNodes, FC}; use crate::{
innerlude::{Context, Element, LazyNodes, FC},
VNode,
};
/// A component is a wrapper around a Context and some Props that share a lifetime /// A component is a wrapper around a Context and some Props that share a lifetime
/// ///
@@ -63,8 +66,8 @@ pub type Component<'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. /// 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)] #[allow(non_upper_case_globals, non_snake_case)]
pub fn Fragment((cx, _): Component<()>) -> DomTree { pub fn Fragment((cx, _): Component<()>) -> Element {
cx.render(LazyNodes::new(|f| f.fragment_from_iter(cx.children()))) Some(LazyNodes::new(|f| f.fragment_from_iter(cx.children())))
} }
/// Every "Props" used for a component must implement the `Properties` trait. This trait gives some hints to Dioxus /// Every "Props" used for a component must implement the `Properties` trait. This trait gives some hints to Dioxus
+1 -4
View File
@@ -137,10 +137,7 @@ impl<'src> Context<'src> {
/// cx.render(lazy_tree) /// cx.render(lazy_tree)
/// } /// }
///``` ///```
pub fn render<F: FnOnce(NodeFactory<'src>) -> VNode<'src>>( pub fn render(self, lazy_nodes: LazyNodes<'src>) -> Option<VNode<'src>> {
self,
lazy_nodes: LazyNodes<'src, F>,
) -> DomTree<'src> {
let bump = &self.scope.frames.wip_frame().bump; let bump = &self.scope.frames.wip_frame().bump;
Some(lazy_nodes.into_vnode(NodeFactory { bump })) Some(lazy_nodes.into_vnode(NodeFactory { bump }))
} }
+10 -8
View File
@@ -93,11 +93,11 @@ pub fn use_suspense<'src, Out, Fut, Cb>(
cx: Context<'src>, cx: Context<'src>,
task_initializer: impl FnOnce() -> Fut, task_initializer: impl FnOnce() -> Fut,
user_callback: Cb, user_callback: Cb,
) -> DomTree<'src> ) -> Element<'src>
where where
Fut: Future<Output = Out> + 'static, Fut: Future<Output = Out> + 'static,
Out: 'static, Out: 'static,
Cb: for<'a> Fn(SuspendedContext<'a>, &Out) -> DomTree<'a> + 'static, Cb: for<'a> Fn(SuspendedContext<'a>, &Out) -> Element<'a> + 'static,
{ {
/* /*
General strategy: General strategy:
@@ -135,12 +135,12 @@ where
None => { None => {
let value = hook.value.clone(); let value = hook.value.clone();
cx.render(LazyNodes::new(|f| { Some(LazyNodes::new(|f| {
let bump = f.bump(); let bump = f.bump();
use bumpalo::boxed::Box as BumpBox; use bumpalo::boxed::Box as BumpBox;
let f: &mut dyn FnMut(SuspendedContext<'src>) -> DomTree<'src> = let f: &mut dyn FnMut(SuspendedContext<'src>) -> Element<'src> =
bump.alloc(move |sus| { bump.alloc(move |sus| {
let val = value.borrow(); let val = value.borrow();
@@ -177,12 +177,14 @@ pub struct SuspendedContext<'a> {
} }
impl<'src> SuspendedContext<'src> { impl<'src> SuspendedContext<'src> {
pub fn render<F: FnOnce(NodeFactory<'src>) -> VNode<'src>>( pub fn render(
// pub fn render<F: FnOnce(NodeFactory<'src>) -> VNode<'src>>(
self, self,
lazy_nodes: LazyNodes<'src, F>, lazy_nodes: LazyNodes<'src>,
) -> DomTree<'src> { ) -> Element<'src> {
let bump = &self.inner.scope.frames.wip_frame().bump; let bump = &self.inner.scope.frames.wip_frame().bump;
Some(lazy_nodes.into_vnode(NodeFactory { bump })) todo!("suspense")
// Some(lazy_nodes.into_vnode(NodeFactory { bump }))
} }
} }
+5 -4
View File
@@ -56,12 +56,13 @@ pub(crate) mod innerlude {
pub use crate::util::*; pub use crate::util::*;
pub use crate::virtual_dom::*; pub use crate::virtual_dom::*;
pub type DomTree<'a> = Option<VNode<'a>>; // pub type Element<'a> = Option<VNode<'a>>;
pub type FC<P> = for<'a> fn(Component<'a, P>) -> DomTree<'a>; pub type Element<'a> = Option<LazyNodes<'a>>;
pub type FC<P> = for<'a> fn(Component<'a, P>) -> Element<'a>;
} }
pub use crate::innerlude::{ pub use crate::innerlude::{
Context, DioxusElement, DomEdit, DomTree, ElementId, EventPriority, LazyNodes, MountType, Context, DioxusElement, DomEdit, Element, ElementId, EventPriority, LazyNodes, MountType,
Mutations, NodeFactory, Properties, SchedulerMsg, ScopeId, SuspendedContext, TaskHandle, Mutations, NodeFactory, Properties, SchedulerMsg, ScopeId, SuspendedContext, TaskHandle,
TestDom, ThreadsafeVirtualDom, UserEvent, VNode, VirtualDom, FC, TestDom, ThreadsafeVirtualDom, UserEvent, VNode, VirtualDom, FC,
}; };
@@ -70,7 +71,7 @@ pub mod prelude {
pub use crate::component::{fc_to_builder, Component, Fragment, Properties}; pub use crate::component::{fc_to_builder, Component, Fragment, Properties};
pub use crate::context::Context; pub use crate::context::Context;
pub use crate::hooks::*; pub use crate::hooks::*;
pub use crate::innerlude::{DioxusElement, DomTree, LazyNodes, Mutations, NodeFactory, FC}; pub use crate::innerlude::{DioxusElement, Element, LazyNodes, Mutations, NodeFactory, FC};
pub use crate::nodes::VNode; pub use crate::nodes::VNode;
pub use crate::VirtualDom; pub use crate::VirtualDom;
} }
+47 -30
View File
@@ -4,7 +4,7 @@
//! cheap and *very* fast to construct - building a full tree should be quick. //! cheap and *very* fast to construct - building a full tree should be quick.
use crate::innerlude::{ use crate::innerlude::{
empty_cell, Context, DomTree, ElementId, Properties, Scope, ScopeId, SuspendedContext, FC, empty_cell, Context, Element, ElementId, Properties, Scope, ScopeId, SuspendedContext, FC,
}; };
use bumpalo::{boxed::Box as BumpBox, Bump}; use bumpalo::{boxed::Box as BumpBox, Bump};
use std::{ use std::{
@@ -13,6 +13,10 @@ use std::{
marker::PhantomData, marker::PhantomData,
}; };
use stack_dst::Value as StackDST;
pub type LazyNodeFactory<'a> = StackDST<dyn FnOnce(NodeFactory<'a>) -> VNode<'a>>;
/// A composable "VirtualNode" to declare a User Interface in the Dioxus VirtualDOM. /// A composable "VirtualNode" to declare a User Interface in the Dioxus VirtualDOM.
/// ///
/// VNodes are designed to be lightweight and used with with a bump allocator. To create a VNode, you can use either of: /// VNodes are designed to be lightweight and used with with a bump allocator. To create a VNode, you can use either of:
@@ -287,7 +291,7 @@ pub struct VComponent<'src> {
// Function pointer to the FC that was used to generate this component // Function pointer to the FC that was used to generate this component
pub user_fc: *const (), pub user_fc: *const (),
pub(crate) caller: &'src dyn for<'b> Fn(&'b Scope) -> DomTree<'b>, pub(crate) caller: &'src dyn for<'b> Fn(&'b Scope) -> Element<'b>,
pub(crate) children: &'src [VNode<'src>], pub(crate) children: &'src [VNode<'src>],
@@ -306,7 +310,7 @@ pub struct VSuspended<'a> {
pub dom_id: Cell<Option<ElementId>>, pub dom_id: Cell<Option<ElementId>>,
#[allow(clippy::type_complexity)] #[allow(clippy::type_complexity)]
pub callback: RefCell<Option<BumpBox<'a, dyn FnMut(SuspendedContext<'a>) -> DomTree<'a>>>>, pub callback: RefCell<Option<BumpBox<'a, dyn FnMut(SuspendedContext<'a>) -> Element<'a>>>>,
} }
/// This struct provides an ergonomic API to quickly build VNodes. /// This struct provides an ergonomic API to quickly build VNodes.
@@ -328,9 +332,10 @@ impl<'a> NodeFactory<'a> {
self.bump self.bump
} }
pub fn render_directly<F>(&self, lazy_nodes: LazyNodes<'a, F>) -> DomTree<'a> pub fn render_directly<F>(&self, lazy_nodes: LazyNodes<'a>) -> Option<VNode<'a>>
where // pub fn render_directly<F>(&self, lazy_nodes: LazyNodes<'a, F>) -> Element<'a>
F: FnOnce(NodeFactory<'a>) -> VNode<'a>, // where
// F: FnOnce(NodeFactory<'a>) -> VNode<'a>,
{ {
Some(lazy_nodes.into_vnode(NodeFactory { bump: self.bump })) Some(lazy_nodes.into_vnode(NodeFactory { bump: self.bump }))
} }
@@ -526,11 +531,11 @@ impl<'a> NodeFactory<'a> {
let key = key.map(|f| self.raw_text(f).0); let key = key.map(|f| self.raw_text(f).0);
let caller: &'a mut dyn for<'b> Fn(&'b Scope) -> DomTree<'b> = let caller: &'a mut dyn for<'b> Fn(&'b Scope) -> Element<'b> =
bump.alloc(move |scope: &Scope| -> DomTree { bump.alloc(move |scope: &Scope| -> Element {
log::debug!("calling component renderr {:?}", scope.our_arena_idx); log::debug!("calling component renderr {:?}", scope.our_arena_idx);
let props: &'_ P = unsafe { &*(raw_props as *const P) }; let props: &'_ P = unsafe { &*(raw_props as *const P) };
let res = component((Context { scope }, props)); let res: Element = component((Context { scope }, props));
unsafe { std::mem::transmute(res) } unsafe { std::mem::transmute(res) }
}); });
@@ -691,40 +696,43 @@ impl<'a> IntoVNode<'a> for VNode<'a> {
/// ```rust /// ```rust
/// LazyNodes::new(|f| f.element("div", [], [], [] None)) /// LazyNodes::new(|f| f.element("div", [], [], [] None))
/// ``` /// ```
pub struct LazyNodes<'a, G> pub struct LazyNodes<'a> {
where inner: LazyNodeFactory<'a>,
G: FnOnce(NodeFactory<'a>) -> VNode<'a>,
{
inner: G,
_p: PhantomData<&'a ()>,
} }
// where
// G: FnOnce(NodeFactory<'a>) -> VNode<'a>,
impl<'a, G> LazyNodes<'a, G> impl<'a> LazyNodes<'a>
where // where
G: FnOnce(NodeFactory<'a>) -> VNode<'a>, // G: FnOnce(NodeFactory<'a>) -> VNode<'a>,
{ {
pub fn new(f: G) -> Self { pub fn new(f: impl FnOnce(NodeFactory<'a>) -> VNode<'a>) -> Self {
Self { todo!()
inner: f, // pub fn new<G: FnOnce(NodeFactory<'a>) -> VNode<'a>>(f: G) -> Self {
_p: PhantomData {}, // let inner = LazyNodeFactory::new(f);
} // Self { inner: f }
} }
} }
// Our blanket impl // Our blanket impl
impl<'a, G> IntoVNode<'a> for LazyNodes<'a, G> impl<'a> IntoVNode<'a> for LazyNodes<'a>
where // where
G: FnOnce(NodeFactory<'a>) -> VNode<'a>, // G: FnOnce(NodeFactory<'a>) -> VNode<'a>,
{ {
fn into_vnode(self, cx: NodeFactory<'a>) -> VNode<'a> { fn into_vnode(self, cx: NodeFactory<'a>) -> VNode<'a> {
(self.inner)(cx) // let f = self.inner;
todo!("manually drop here")
// (self.inner)(cx)
} }
} }
// Our blanket impl // Our blanket impl
impl<'a, G> IntoIterator for LazyNodes<'a, G> impl<'a> IntoIterator for LazyNodes<'a>
where // where
G: FnOnce(NodeFactory<'a>) -> VNode<'a>, // G: FnOnce(NodeFactory<'a>) -> VNode<'a>,
// impl<'a, G> IntoIterator for LazyNodes<'a, G>
// where
// G: FnOnce(NodeFactory<'a>) -> VNode<'a>,
{ {
type Item = Self; type Item = Self;
type IntoIter = std::iter::Once<Self::Item>; type IntoIter = std::iter::Once<Self::Item>;
@@ -756,6 +764,15 @@ impl<'a> IntoVNode<'a> for Option<VNode<'a>> {
} }
} }
impl<'a> IntoVNode<'a> for Option<LazyNodes<'a>> {
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<VNode>),
}
}
}
impl IntoVNode<'_> for &'static str { impl IntoVNode<'_> for &'static str {
fn into_vnode(self, cx: NodeFactory) -> VNode { fn into_vnode(self, cx: NodeFactory) -> VNode {
cx.static_text(self) cx.static_text(self)
+19 -14
View File
@@ -28,7 +28,7 @@ pub struct Scope {
// Nodes // Nodes
pub(crate) frames: ActiveFrame, pub(crate) frames: ActiveFrame,
pub(crate) caller: *const dyn for<'b> Fn(&'b Scope) -> DomTree<'b>, pub(crate) caller: *const dyn for<'b> Fn(&'b Scope) -> Element<'b>,
pub(crate) child_nodes: ScopeChildren<'static>, pub(crate) child_nodes: ScopeChildren<'static>,
/* /*
@@ -176,7 +176,7 @@ impl Scope {
// Scopes cannot be made anywhere else except for this file // Scopes cannot be made anywhere else except for this file
// Therefore, their lifetimes are connected exclusively to the virtual dom // Therefore, their lifetimes are connected exclusively to the virtual dom
pub(crate) fn new( pub(crate) fn new(
caller: &dyn for<'b> Fn(&'b Scope) -> DomTree<'b>, caller: &dyn for<'b> Fn(&'b Scope) -> Element<'b>,
our_arena_idx: ScopeId, our_arena_idx: ScopeId,
parent_idx: Option<ScopeId>, parent_idx: Option<ScopeId>,
height: u32, height: u32,
@@ -217,7 +217,7 @@ impl Scope {
pub(crate) fn update_scope_dependencies<'creator_node>( pub(crate) fn update_scope_dependencies<'creator_node>(
&mut self, &mut self,
caller: &'creator_node dyn for<'b> Fn(&'b Scope) -> DomTree<'b>, caller: &'creator_node dyn for<'b> Fn(&'b Scope) -> Element<'b>,
child_nodes: ScopeChildren, child_nodes: ScopeChildren,
) { ) {
log::debug!("Updating scope dependencies {:?}", self.our_arena_idx); log::debug!("Updating scope dependencies {:?}", self.our_arena_idx);
@@ -317,7 +317,7 @@ impl Scope {
let mut cb = sus.callback.borrow_mut().take().unwrap(); let mut cb = sus.callback.borrow_mut().take().unwrap();
let new_node: DomTree<'a> = (cb)(cx); let new_node: Element<'a> = (cb)(cx);
} }
} }
@@ -350,20 +350,25 @@ impl Scope {
log::debug!("Borrowed stuff is successfully cleared"); log::debug!("Borrowed stuff is successfully cleared");
// Cast the caller ptr from static to one with our own reference // Cast the caller ptr from static to one with our own reference
let render: &dyn for<'b> Fn(&'b Scope) -> DomTree<'b> = unsafe { &*self.caller }; let render: &dyn for<'b> Fn(&'b Scope) -> Element<'b> = unsafe { &*self.caller };
// Todo: see if we can add stronger guarantees around internal bookkeeping and failed component renders. // Todo: see if we can add stronger guarantees around internal bookkeeping and failed component renders.
if let Some(new_head) = render(self) { //
log::debug!("Render is successful"); todo!()
// if let Some(builder) = render(self) {
// let new_head = builder.into_vnode(NodeFactory {
// bump: &self.frames.wip_frame().bump,
// });
// log::debug!("Render is successful");
// the user's component succeeded. We can safely cycle to the next frame // // the user's component succeeded. We can safely cycle to the next frame
self.frames.wip_frame_mut().head_node = unsafe { std::mem::transmute(new_head) }; // self.frames.wip_frame_mut().head_node = unsafe { std::mem::transmute(new_head) };
self.frames.cycle_frame(); // self.frames.cycle_frame();
true // true
} else { // } else {
false // false
} // }
} }
} }
+18 -15
View File
@@ -21,16 +21,16 @@ impl TestDom {
NodeFactory::new(&self.bump) NodeFactory::new(&self.bump)
} }
pub fn render_direct<'a, F>(&'a self, lazy_nodes: LazyNodes<'a, F>) -> VNode<'a> pub fn render_direct<'a>(&'a self, lazy_nodes: Element<'a>) -> VNode<'a>
where // where
F: FnOnce(NodeFactory<'a>) -> VNode<'a>, // F: FnOnce(NodeFactory<'a>) -> VNode<'a>,
{ {
lazy_nodes.into_vnode(NodeFactory::new(&self.bump)) lazy_nodes.into_vnode(NodeFactory::new(&self.bump))
} }
pub fn render<'a, F>(&'a self, lazy_nodes: LazyNodes<'a, F>) -> &'a VNode<'a> pub fn render<'a>(&'a self, lazy_nodes: Element<'a>) -> &'a VNode<'a>
where // where
F: FnOnce(NodeFactory<'a>) -> VNode<'a>, // F: FnOnce(NodeFactory<'a>) -> VNode<'a>,
{ {
self.bump self.bump
.alloc(lazy_nodes.into_vnode(NodeFactory::new(&self.bump))) .alloc(lazy_nodes.into_vnode(NodeFactory::new(&self.bump)))
@@ -43,9 +43,10 @@ impl TestDom {
machine.mutations machine.mutations
} }
pub fn create<'a, F1>(&'a self, left: LazyNodes<'a, F1>) -> Mutations<'a> pub fn create<'a>(&'a self, left: Element<'a>) -> Mutations<'a>
where // pub fn create<'a, F1>(&'a self, left: LazyNodes<'a, F1>) -> Mutations<'a>
F1: FnOnce(NodeFactory<'a>) -> VNode<'a>, // where
// F1: FnOnce(NodeFactory<'a>) -> VNode<'a>,
{ {
let old = self.bump.alloc(self.render_direct(left)); let old = self.bump.alloc(self.render_direct(left));
@@ -58,14 +59,16 @@ impl TestDom {
machine.mutations machine.mutations
} }
pub fn lazy_diff<'a, F1, F2>( pub fn lazy_diff<'a>(
&'a self, &'a self,
left: LazyNodes<'a, F1>, left: Element<'a>,
right: LazyNodes<'a, F2>, right: Element<'a>,
// left: LazyNodes<'a, F1>,
// right: LazyNodes<'a, F2>,
) -> (Mutations<'a>, Mutations<'a>) ) -> (Mutations<'a>, Mutations<'a>)
where // where
F1: FnOnce(NodeFactory<'a>) -> VNode<'a>, // F1: FnOnce(NodeFactory<'a>) -> VNode<'a>,
F2: FnOnce(NodeFactory<'a>) -> VNode<'a>, // F2: FnOnce(NodeFactory<'a>) -> VNode<'a>,
{ {
let (old, new) = (self.render(left), self.render(right)); let (old, new) = (self.render(left), self.render(right));
+21 -19
View File
@@ -143,7 +143,7 @@ impl VirtualDom {
let _p = root_props.clone(); let _p = root_props.clone();
// Safety: this callback is only valid for the lifetime of the root props // Safety: this callback is only valid for the lifetime of the root props
let root_caller: Rc<dyn Fn(&Scope) -> DomTree> = Rc::new(move |scope: &Scope| unsafe { let root_caller: Rc<dyn Fn(&Scope) -> Element> = Rc::new(move |scope: &Scope| unsafe {
let props = _p.downcast_ref::<P>().unwrap(); let props = _p.downcast_ref::<P>().unwrap();
std::mem::transmute(root((Context { scope }, props))) std::mem::transmute(root((Context { scope }, props)))
}); });
@@ -219,7 +219,7 @@ impl VirtualDom {
let root = *self.root_fc.downcast_ref::<FC<P>>().unwrap(); let root = *self.root_fc.downcast_ref::<FC<P>>().unwrap();
let root_caller: Box<dyn Fn(&Scope) -> DomTree> = let root_caller: Box<dyn Fn(&Scope) -> Element> =
Box::new(move |scope: &Scope| unsafe { Box::new(move |scope: &Scope| unsafe {
let props: &'_ P = &*(props_ptr as *const P); let props: &'_ P = &*(props_ptr as *const P);
std::mem::transmute(root((Context { scope }, props))) std::mem::transmute(root((Context { scope }, props)))
@@ -368,22 +368,24 @@ impl VirtualDom {
use futures_util::StreamExt; use futures_util::StreamExt;
// Wait for any new events if we have nothing to do // Wait for any new events if we have nothing to do
futures_util::select! { todo!("wait for work without select macro")
_ = self.scheduler.async_tasks.next() => {}
msg = self.scheduler.receiver.next() => { // futures_util::select! {
match msg.unwrap() { // _ = self.scheduler.async_tasks.next() => {}
SchedulerMsg::Task(t) => { // msg = self.scheduler.receiver.next() => {
self.scheduler.handle_task(t); // match msg.unwrap() {
}, // SchedulerMsg::Task(t) => {
SchedulerMsg::Immediate(im) => { // self.scheduler.handle_task(t);
self.scheduler.dirty_scopes.insert(im); // },
} // SchedulerMsg::Immediate(im) => {
SchedulerMsg::UiEvent(evt) => { // self.scheduler.dirty_scopes.insert(im);
self.scheduler.ui_events.push_back(evt); // }
} // SchedulerMsg::UiEvent(evt) => {
} // self.scheduler.ui_events.push_back(evt);
}, // }
} // }
// },
// }
} }
} }
@@ -408,4 +410,4 @@ impl std::fmt::Display for VirtualDom {
} }
// we never actually use the contents of this root caller // we never actually use the contents of this root caller
struct RootCaller(Rc<dyn for<'b> Fn(&'b Scope) -> DomTree<'b> + 'static>); struct RootCaller(Rc<dyn for<'b> Fn(&'b Scope) -> Element<'b> + 'static>);
+9 -9
View File
@@ -10,17 +10,17 @@ fn test_borrowed_state() {
let _ = VirtualDom::new(Parent); let _ = VirtualDom::new(Parent);
} }
fn Parent((cx, _): Component<()>) -> DomTree { fn Parent((cx, _): Component<()>) -> Element {
let value = cx.use_hook(|_| String::new(), |f| &*f, |_| {}); let value = cx.use_hook(|_| String::new(), |f| &*f, |_| {});
cx.render(rsx! { rsx! {
div { div {
Child { name: value } Child { name: value }
Child { name: value } Child { name: value }
Child { name: value } Child { name: value }
Child { name: value } Child { name: value }
} }
}) }
} }
#[derive(Props)] #[derive(Props)]
@@ -28,13 +28,13 @@ struct ChildProps<'a> {
name: &'a str, name: &'a str,
} }
fn Child<'a>((cx, props): Component<'a, ChildProps>) -> DomTree<'a> { fn Child<'a>((cx, props): Component<'a, ChildProps>) -> Element<'a> {
cx.render(rsx! { rsx! {
div { div {
h1 { "it's nested" } h1 { "it's nested" }
Child2 { name: props.name } Child2 { name: props.name }
} }
}) }
} }
#[derive(Props)] #[derive(Props)]
@@ -42,8 +42,8 @@ struct Grandchild<'a> {
name: &'a str, name: &'a str,
} }
fn Child2<'a>((cx, props): Component<'a, Grandchild>) -> DomTree<'a> { fn Child2<'a>((cx, props): Component<'a, Grandchild>) -> Element<'a> {
cx.render(rsx! { rsx! {
div { "Hello {props.name}!" } div { "Hello {props.name}!" }
}) }
} }
+16 -16
View File
@@ -22,13 +22,13 @@ fn new_dom<P: 'static + Send>(app: FC<P>, props: P) -> VirtualDom {
#[test] #[test]
fn test_original_diff() { fn test_original_diff() {
static APP: FC<()> = |(cx, props)| { static APP: FC<()> = |(cx, props)| {
cx.render(rsx! { rsx! {
div { div {
div { div {
"Hello, world!" "Hello, world!"
} }
} }
}) }
}; };
let mut dom = new_dom(APP, ()); let mut dom = new_dom(APP, ());
@@ -58,7 +58,7 @@ fn test_original_diff() {
#[test] #[test]
fn create() { fn create() {
static APP: FC<()> = |(cx, props)| { static APP: FC<()> = |(cx, props)| {
cx.render(rsx! { rsx! {
div { div {
div { div {
"Hello, world!" "Hello, world!"
@@ -72,7 +72,7 @@ fn create() {
} }
} }
} }
}) }
}; };
let mut dom = new_dom(APP, ()); let mut dom = new_dom(APP, ());
@@ -121,11 +121,11 @@ fn create() {
#[test] #[test]
fn create_list() { fn create_list() {
static APP: FC<()> = |(cx, props)| { static APP: FC<()> = |(cx, props)| {
cx.render(rsx! { rsx! {
{(0..3).map(|f| rsx!{ div { {(0..3).map(|f| rsx!{ div {
"hello" "hello"
}})} }})}
}) }
}; };
let mut dom = new_dom(APP, ()); let mut dom = new_dom(APP, ());
@@ -170,12 +170,12 @@ fn create_list() {
#[test] #[test]
fn create_simple() { fn create_simple() {
static APP: FC<()> = |(cx, props)| { static APP: FC<()> = |(cx, props)| {
cx.render(rsx! { rsx! {
div {} div {}
div {} div {}
div {} div {}
div {} div {}
}) }
}; };
let mut dom = new_dom(APP, ()); let mut dom = new_dom(APP, ());
@@ -208,19 +208,19 @@ fn create_simple() {
#[test] #[test]
fn create_components() { fn create_components() {
static App: FC<()> = |(cx, props)| { static App: FC<()> = |(cx, props)| {
cx.render(rsx! { rsx! {
Child { "abc1" } Child { "abc1" }
Child { "abc2" } Child { "abc2" }
Child { "abc3" } Child { "abc3" }
}) }
}; };
static Child: FC<()> = |(cx, props)| { static Child: FC<()> = |(cx, props)| {
cx.render(rsx! { rsx! {
h1 {} h1 {}
div { {cx.children()} } div { {cx.children()} }
p {} p {}
}) }
}; };
let mut dom = new_dom(App, ()); let mut dom = new_dom(App, ());
@@ -269,10 +269,10 @@ fn create_components() {
#[test] #[test]
fn anchors() { fn anchors() {
static App: FC<()> = |(cx, props)| { static App: FC<()> = |(cx, props)| {
cx.render(rsx! { rsx! {
{true.then(|| rsx!{ div { "hello" } })} {true.then(|| rsx!{ div { "hello" } })}
{false.then(|| rsx!{ div { "goodbye" } })} {false.then(|| rsx!{ div { "goodbye" } })}
}) }
}; };
let mut dom = new_dom(App, ()); let mut dom = new_dom(App, ());
@@ -303,9 +303,9 @@ fn suspended() {
|| async { || async {
// //
}, },
|cx, p| cx.render(rsx! { "hi "}), |cx, p| rsx! { "hi "},
); );
cx.render(rsx! { {val} }) rsx! { {val} }
}; };
let mut dom = new_dom(App, ()); let mut dom = new_dom(App, ());
+2 -2
View File
@@ -807,14 +807,14 @@ fn controlled_keyed_diffing_out_of_order_max_test() {
fn suspense() { fn suspense() {
let dom = new_dom(); let dom = new_dom();
let edits = dom.create(LazyNodes::new(|f| { let edits = dom.create(Some(LazyNodes::new(|f| {
use std::cell::{Cell, RefCell}; use std::cell::{Cell, RefCell};
VNode::Suspended(f.bump().alloc(VSuspended { VNode::Suspended(f.bump().alloc(VSuspended {
task_id: 0, task_id: 0,
callback: RefCell::new(None), callback: RefCell::new(None),
dom_id: Cell::new(None), dom_id: Cell::new(None),
})) }))
})); })));
assert_eq!( assert_eq!(
edits.edits, edits.edits,
[CreatePlaceholder { root: 0 }, AppendChildren { many: 1 }] [CreatePlaceholder { root: 0 }, AppendChildren { many: 1 }]
+4 -4
View File
@@ -14,7 +14,7 @@ mod test_logging;
#[test] #[test]
fn please_work() { fn please_work() {
static App: FC<()> = |(cx, props)| { static App: FC<()> = |(cx, props)| {
cx.render(rsx! { rsx! {
div { div {
hidden: "true" hidden: "true"
"hello" "hello"
@@ -24,13 +24,13 @@ fn please_work() {
Child {} Child {}
} }
div { "hello" } div { "hello" }
}) }
}; };
static Child: FC<()> = |(cx, props)| { static Child: FC<()> = |(cx, props)| {
cx.render(rsx! { rsx! {
div { "child" } div { "child" }
}) }
}; };
let mut dom = VirtualDom::new(App); let mut dom = VirtualDom::new(App);
+1 -1
View File
@@ -22,7 +22,7 @@ fn manual_diffing() {
static App: FC<AppProps> = |(cx, props)| { static App: FC<AppProps> = |(cx, props)| {
let val = props.value.lock().unwrap(); let val = props.value.lock().unwrap();
cx.render(rsx! { div { "{val}" } }) rsx! { div { "{val}" } }
}; };
let value = Arc::new(Mutex::new("Hello")); let value = Arc::new(Mutex::new("Hello"));
+2 -2
View File
@@ -15,12 +15,12 @@ fn shared_state_test() {
static App: FC<()> = |(cx, props)| { static App: FC<()> = |(cx, props)| {
cx.provide_state(MySharedState("world!")); cx.provide_state(MySharedState("world!"));
rsx!(cx, Child {}) rsx!(Child {})
}; };
static Child: FC<()> = |(cx, props)| { static Child: FC<()> = |(cx, props)| {
let shared = cx.consume_state::<MySharedState>()?; let shared = cx.consume_state::<MySharedState>()?;
rsx!(cx, "Hello, {shared.0}") rsx!("Hello, {shared.0}")
}; };
let mut dom = VirtualDom::new(App); let mut dom = VirtualDom::new(App);
+13 -13
View File
@@ -19,7 +19,7 @@ use dioxus_html as dioxus_elements;
fn app_runs() { fn app_runs() {
static App: FC<()> = |(cx, props)| { static App: FC<()> = |(cx, props)| {
// //
cx.render(rsx!( div{"hello"} )) rsx!( div{"hello"} )
}; };
let mut vdom = VirtualDom::new(App); let mut vdom = VirtualDom::new(App);
let edits = vdom.rebuild(); let edits = vdom.rebuild();
@@ -29,10 +29,10 @@ fn app_runs() {
#[test] #[test]
fn fragments_work() { fn fragments_work() {
static App: FC<()> = |(cx, props)| { static App: FC<()> = |(cx, props)| {
cx.render(rsx!( rsx!(
div{"hello"} div{"hello"}
div{"goodbye"} div{"goodbye"}
)) )
}; };
let mut vdom = VirtualDom::new(App); let mut vdom = VirtualDom::new(App);
let edits = vdom.rebuild(); let edits = vdom.rebuild();
@@ -43,10 +43,10 @@ fn fragments_work() {
#[test] #[test]
fn lists_work() { fn lists_work() {
static App: FC<()> = |(cx, props)| { static App: FC<()> = |(cx, props)| {
cx.render(rsx!( rsx!(
h1 {"hello"} h1 {"hello"}
{(0..6).map(|f| rsx!(span{ "{f}" }))} {(0..6).map(|f| rsx!(span{ "{f}" }))}
)) )
}; };
let mut vdom = VirtualDom::new(App); let mut vdom = VirtualDom::new(App);
let edits = vdom.rebuild(); let edits = vdom.rebuild();
@@ -56,11 +56,11 @@ fn lists_work() {
#[test] #[test]
fn conditional_rendering() { fn conditional_rendering() {
static App: FC<()> = |(cx, props)| { static App: FC<()> = |(cx, props)| {
cx.render(rsx!( rsx!(
h1 {"hello"} h1 {"hello"}
{true.then(|| rsx!(span{ "a" }))} {true.then(|| rsx!(span{ "a" }))}
{false.then(|| rsx!(span{ "b" }))} {false.then(|| rsx!(span{ "b" }))}
)) )
}; };
let mut vdom = VirtualDom::new(App); let mut vdom = VirtualDom::new(App);
@@ -73,16 +73,16 @@ fn conditional_rendering() {
#[test] #[test]
fn child_components() { fn child_components() {
static App: FC<()> = |(cx, props)| { static App: FC<()> = |(cx, props)| {
cx.render(rsx!( rsx!(
{true.then(|| rsx!(Child { }))} {true.then(|| rsx!(Child { }))}
{false.then(|| rsx!(Child { }))} {false.then(|| rsx!(Child { }))}
)) )
}; };
static Child: FC<()> = |(cx, props)| { static Child: FC<()> = |(cx, props)| {
cx.render(rsx!( rsx!(
h1 {"hello"} h1 {"hello"}
h1 {"goodbye"} h1 {"goodbye"}
)) )
}; };
let mut vdom = VirtualDom::new(App); let mut vdom = VirtualDom::new(App);
let edits = vdom.rebuild(); let edits = vdom.rebuild();
@@ -92,8 +92,8 @@ fn child_components() {
#[test] #[test]
fn suspended_works() { fn suspended_works() {
static App: FC<()> = |(cx, props)| { static App: FC<()> = |(cx, props)| {
let title = use_suspense(cx, || async { "bob" }, |cx, f| cx.render(rsx! { "{f}"})); let title = use_suspense(cx, || async { "bob" }, |cx, f| rsx! { "{f}"});
cx.render(rsx!("hello" { title })) rsx!("hello" { title })
}; };
let mut vdom = VirtualDom::new(App); let mut vdom = VirtualDom::new(App);
+1 -1
View File
@@ -136,7 +136,7 @@ pub struct TodoEntryProps {
id: u32, id: u32,
} }
pub fn TodoEntry((cx, props): Component<TodoEntryProps>) -> DomTree { pub fn TodoEntry((cx, props): Component<TodoEntryProps>) -> Element {
let todos = use_shared_state::<Todos>(cx)?; let todos = use_shared_state::<Todos>(cx)?;
let _todos = todos.read(); let _todos = todos.read();
+2 -2
View File
@@ -2,7 +2,7 @@ use std::cell::RefCell;
use dioxus::prelude::Component; use dioxus::prelude::Component;
use dioxus_core as dioxus; use dioxus_core as dioxus;
use dioxus_core::{Context, DomTree, LazyNodes, NodeFactory, Properties}; use dioxus_core::{Context, Element, LazyNodes, NodeFactory, Properties};
use dioxus_core_macro::Props; use dioxus_core_macro::Props;
/* /*
@@ -54,7 +54,7 @@ pub struct WebviewWindowProps<'a> {
/// ///
/// ///
/// ///
pub fn WebviewWindow<'a>((cx, props): Component<'a, WebviewWindowProps>) -> DomTree<'a> { pub fn WebviewWindow<'a>((cx, props): Component<'a, WebviewWindowProps>) -> Element<'a> {
let dtcx = cx.consume_state::<RefCell<DesktopContext>>()?; let dtcx = cx.consume_state::<RefCell<DesktopContext>>()?;
cx.use_hook( cx.use_hook(
+2 -2
View File
@@ -68,13 +68,13 @@ static APP: FC<()> = |(cx, _)| {
}) })
}; };
fn render_bullets(cx: Context) -> DomTree { fn render_bullets(cx: Context) -> Element {
rsx!(cx, div { rsx!(cx, div {
"bite me" "bite me"
}) })
} }
fn render_list(cx: Context, count: usize) -> DomTree { fn render_list(cx: Context, count: usize) -> Element {
let items = (0..count).map(|f| { let items = (0..count).map(|f| {
rsx! { rsx! {
li { "a - {f}" } li { "a - {f}" }