wip: move everything over to a stack dst

This commit is contained in:
Jonathan Kelley 2021-10-29 17:12:30 -04:00
parent 12a9758c3c
commit 0e9d5fc530
36 changed files with 224 additions and 185 deletions

View file

@ -20,7 +20,7 @@ fn main() {
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 first = text.get_mut(0).unwrap();
@ -43,7 +43,7 @@ impl<'a> Drop for C1Props<'a> {
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();
cx.render(rsx! {
@ -59,7 +59,7 @@ struct C2Props<'a> {
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! {
Child3 {
text: props.text
@ -72,7 +72,7 @@ struct C3Props<'a> {
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! {
div { "{props.text}"}
})

View file

@ -116,7 +116,7 @@ struct CalculatorKeyProps<'a> {
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 {
class: "calculator-key {props.name}"
onclick: {props.onclick}

View file

@ -80,7 +80,7 @@ struct ActionButtonProps<'a> {
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"
button { class:"btn btn-primary btn-block", r#type: "button", id: "{props.id}", onclick: {props.onclick},
"{props.name}"
@ -93,7 +93,7 @@ struct RowProps {
row_id: usize,
label: Rc<str>,
}
fn Row((cx, props): Component<RowProps>) -> DomTree {
fn Row((cx, props): Component<RowProps>) -> Element {
rsx!(cx, tr {
td { class:"col-md-1", "{props.row_id}" }
td { class:"col-md-1", onclick: move |_| { /* run onselect */ }

View file

@ -4,7 +4,7 @@ fn main() {
dioxus::desktop::launch(App, |c| c);
}
fn App((cx, props): Component<()>) -> DomTree {
fn App((cx, props): Component<()>) -> Element {
cx.render(rsx! (
div { "Hello, world!" }
))

View file

@ -76,7 +76,7 @@ struct CalculatorKeyProps<'a> {
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! {
button {
class: "calculator-key {props.name}"

View file

@ -184,7 +184,7 @@ mod baller {
pub struct BallerProps {}
/// This component totally balls
pub fn Baller(_: Component<BallerProps>) -> DomTree {
pub fn Baller(_: Component<BallerProps>) -> Element {
todo!()
}
}
@ -195,7 +195,7 @@ pub struct TallerProps {
}
/// This component is taller than most :)
pub fn Taller(_: Component<TallerProps>) -> DomTree {
pub fn Taller(_: Component<TallerProps>) -> Element {
let b = true;
todo!()
}

View file

@ -21,6 +21,6 @@ static App: FC<()> = |(cx, props)| {
struct MyProps<'a> {
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
}

View file

@ -85,7 +85,7 @@ pub struct TodoEntryProps {
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 contents = use_state(cx, || String::from(""));
let todo = &props.todo;

View file

@ -45,7 +45,7 @@ struct RowProps {
row_id: usize,
label: Label,
}
fn Row((cx, props): Component<RowProps>) -> DomTree {
fn Row((cx, props): Component<RowProps>) -> Element {
let [adj, col, noun] = props.label.0;
cx.render(rsx! {
tr {

View file

@ -57,11 +57,11 @@ impl ToTokens for CallBody {
}),
// Otherwise we just build the LazyNode wrapper
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};
#inner
})
}))
}),
};
}

View file

@ -22,7 +22,9 @@ longest-increasing-subsequence = "0.1.0"
# internall used
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"
@ -40,6 +42,8 @@ serde = { version = "1", features = ["derive"], optional = true }
serde_repr = { version = "0.1.7", optional = true }
stack_dst = "0.6.1"
[dev-dependencies]
anyhow = "1.0.42"
dioxus-html = { path = "../html" }

View file

@ -34,13 +34,13 @@ fn create_rows(c: &mut Criterion) {
}
}
});
cx.render(rsx! {
rsx! {
table {
tbody {
{rows}
}
}
})
}
};
c.bench_function("create rows", |b| {
@ -57,9 +57,9 @@ struct RowProps {
row_id: usize,
label: Label,
}
fn Row((cx, props): Component<RowProps>) -> DomTree {
fn Row((cx, props): Component<RowProps>) -> Element {
let [adj, col, noun] = props.label.0;
cx.render(rsx! {
rsx! {
tr {
td { class:"col-md-1", "{props.row_id}" }
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" }
}
})
}
}
#[derive(PartialEq)]

View file

@ -9,7 +9,7 @@ fn main() {
pub static EXAMPLE: FC<()> = |(cx, _)| {
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(
"div",
None,

View file

@ -20,10 +20,10 @@ struct ListItem {
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);
cx.render(LazyNodes::new(move |_nodecx| {
Some(LazyNodes::new(move |_nodecx| {
todo!()
// builder::ElementBuilder::new(_nodecx, "div")
// .iter_child({
@ -56,8 +56,8 @@ struct ChildProps {
item_handler: Rc<dyn Fn(i32)>,
}
fn ChildItem<'a>(cx: Context<'a>, props: &'a ChildProps) -> DomTree<'a> {
cx.render(LazyNodes::new(move |__cx| todo!()))
fn ChildItem<'a>(cx: Context<'a>, props: &'a ChildProps) -> Element<'a> {
Some(LazyNodes::new(move |__cx| todo!()))
}
impl PartialEq for ChildProps {

View file

@ -2,7 +2,7 @@ use dioxus_core::prelude::*;
fn main() {}
fn app<'a>(cx: Context<'a>, props: &()) -> DomTree<'a> {
fn app<'a>(cx: Context<'a>, props: &()) -> Element<'a> {
let vak = use_suspense(
cx,
|| 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(
"div",
None,

View file

@ -15,7 +15,7 @@ fn main() {
assert!(g.edits.len() > 1);
}
fn App((cx, props): Component<()>) -> DomTree {
fn App((cx, props): Component<()>) -> Element {
let mut rng = SmallRng::from_entropy();
let rows = (0..10_000_usize).map(|f| {
let label = Label::new(&mut rng);
@ -26,13 +26,13 @@ fn App((cx, props): Component<()>) -> DomTree {
}
}
});
cx.render(rsx! {
rsx! {
table {
tbody {
{rows}
}
}
})
}
}
#[derive(PartialEq, Props)]
@ -41,11 +41,11 @@ struct RowProps {
label: Label,
}
fn Row((cx, props): Component<RowProps>) -> DomTree {
fn Row((cx, props): Component<RowProps>) -> Element {
let handler = move |evt: MouseEvent| {
let g = evt.button;
};
cx.render(rsx! {
rsx! {
tr {
td { class:"col-md-1", "{props.row_id}" }
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" }
}
})
}
}
#[derive(PartialEq)]

View file

@ -32,3 +32,8 @@ fn html_usage() {
}
};
}
static App: FC<()> = |(cx, props)| {
//
rsx!(div {})
};

View file

@ -4,7 +4,7 @@ use dioxus_core::prelude::*;
#[async_std::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);

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
//! 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
///
@ -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.
///
#[allow(non_upper_case_globals, non_snake_case)]
pub fn Fragment((cx, _): Component<()>) -> DomTree {
cx.render(LazyNodes::new(|f| f.fragment_from_iter(cx.children())))
pub fn Fragment((cx, _): Component<()>) -> Element {
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

View file

@ -137,10 +137,7 @@ impl<'src> Context<'src> {
/// cx.render(lazy_tree)
/// }
///```
pub fn render<F: FnOnce(NodeFactory<'src>) -> VNode<'src>>(
self,
lazy_nodes: LazyNodes<'src, F>,
) -> DomTree<'src> {
pub fn render(self, lazy_nodes: LazyNodes<'src>) -> Option<VNode<'src>> {
let bump = &self.scope.frames.wip_frame().bump;
Some(lazy_nodes.into_vnode(NodeFactory { bump }))
}

View file

@ -93,11 +93,11 @@ pub fn use_suspense<'src, Out, Fut, Cb>(
cx: Context<'src>,
task_initializer: impl FnOnce() -> Fut,
user_callback: Cb,
) -> DomTree<'src>
) -> Element<'src>
where
Fut: Future<Output = 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:
@ -135,12 +135,12 @@ where
None => {
let value = hook.value.clone();
cx.render(LazyNodes::new(|f| {
Some(LazyNodes::new(|f| {
let bump = f.bump();
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| {
let val = value.borrow();
@ -177,12 +177,14 @@ pub struct SuspendedContext<'a> {
}
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,
lazy_nodes: LazyNodes<'src, F>,
) -> DomTree<'src> {
lazy_nodes: LazyNodes<'src>,
) -> Element<'src> {
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 }))
}
}

View file

@ -56,12 +56,13 @@ pub(crate) mod innerlude {
pub use crate::util::*;
pub use crate::virtual_dom::*;
pub type DomTree<'a> = Option<VNode<'a>>;
pub type FC<P> = for<'a> fn(Component<'a, P>) -> DomTree<'a>;
// pub type Element<'a> = Option<VNode<'a>>;
pub type Element<'a> = Option<LazyNodes<'a>>;
pub type FC<P> = for<'a> fn(Component<'a, P>) -> Element<'a>;
}
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,
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::context::Context;
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::VirtualDom;
}

View file

@ -4,7 +4,7 @@
//! cheap and *very* fast to construct - building a full tree should be quick.
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 std::{
@ -13,6 +13,10 @@ use std::{
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.
///
/// 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
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>],
@ -306,7 +310,7 @@ pub struct VSuspended<'a> {
pub dom_id: Cell<Option<ElementId>>,
#[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.
@ -328,9 +332,10 @@ impl<'a> NodeFactory<'a> {
self.bump
}
pub fn render_directly<F>(&self, lazy_nodes: LazyNodes<'a, F>) -> DomTree<'a>
where
F: FnOnce(NodeFactory<'a>) -> VNode<'a>,
pub fn render_directly<F>(&self, lazy_nodes: LazyNodes<'a>) -> Option<VNode<'a>>
// pub fn render_directly<F>(&self, lazy_nodes: LazyNodes<'a, F>) -> Element<'a>
// where
// F: FnOnce(NodeFactory<'a>) -> VNode<'a>,
{
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 caller: &'a mut dyn for<'b> Fn(&'b Scope) -> DomTree<'b> =
bump.alloc(move |scope: &Scope| -> DomTree {
let caller: &'a mut dyn for<'b> Fn(&'b Scope) -> Element<'b> =
bump.alloc(move |scope: &Scope| -> Element {
log::debug!("calling component renderr {:?}", scope.our_arena_idx);
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) }
});
@ -691,40 +696,43 @@ impl<'a> IntoVNode<'a> for VNode<'a> {
/// ```rust
/// LazyNodes::new(|f| f.element("div", [], [], [] None))
/// ```
pub struct LazyNodes<'a, G>
where
G: FnOnce(NodeFactory<'a>) -> VNode<'a>,
{
inner: G,
_p: PhantomData<&'a ()>,
pub struct LazyNodes<'a> {
inner: LazyNodeFactory<'a>,
}
// where
// G: FnOnce(NodeFactory<'a>) -> VNode<'a>,
impl<'a, G> LazyNodes<'a, G>
where
G: FnOnce(NodeFactory<'a>) -> VNode<'a>,
impl<'a> LazyNodes<'a>
// where
// G: FnOnce(NodeFactory<'a>) -> VNode<'a>,
{
pub fn new(f: G) -> Self {
Self {
inner: f,
_p: PhantomData {},
}
pub fn new(f: impl FnOnce(NodeFactory<'a>) -> VNode<'a>) -> Self {
todo!()
// pub fn new<G: FnOnce(NodeFactory<'a>) -> VNode<'a>>(f: G) -> Self {
// let inner = LazyNodeFactory::new(f);
// Self { inner: f }
}
}
// Our blanket impl
impl<'a, G> IntoVNode<'a> for LazyNodes<'a, G>
where
G: FnOnce(NodeFactory<'a>) -> VNode<'a>,
impl<'a> IntoVNode<'a> for LazyNodes<'a>
// where
// G: FnOnce(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
impl<'a, G> IntoIterator for LazyNodes<'a, G>
where
G: FnOnce(NodeFactory<'a>) -> VNode<'a>,
impl<'a> IntoIterator for LazyNodes<'a>
// where
// 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 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 {
fn into_vnode(self, cx: NodeFactory) -> VNode {
cx.static_text(self)

View file

@ -28,7 +28,7 @@ pub struct Scope {
// Nodes
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>,
/*
@ -176,7 +176,7 @@ impl Scope {
// Scopes cannot be made anywhere else except for this file
// Therefore, their lifetimes are connected exclusively to the virtual dom
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,
parent_idx: Option<ScopeId>,
height: u32,
@ -217,7 +217,7 @@ impl Scope {
pub(crate) fn update_scope_dependencies<'creator_node>(
&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,
) {
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 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");
// 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.
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
self.frames.wip_frame_mut().head_node = unsafe { std::mem::transmute(new_head) };
self.frames.cycle_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.cycle_frame();
true
} else {
false
}
// true
// } else {
// false
// }
}
}

View file

@ -21,16 +21,16 @@ impl TestDom {
NodeFactory::new(&self.bump)
}
pub fn render_direct<'a, F>(&'a self, lazy_nodes: LazyNodes<'a, F>) -> VNode<'a>
where
F: FnOnce(NodeFactory<'a>) -> VNode<'a>,
pub fn render_direct<'a>(&'a self, lazy_nodes: Element<'a>) -> VNode<'a>
// where
// F: FnOnce(NodeFactory<'a>) -> VNode<'a>,
{
lazy_nodes.into_vnode(NodeFactory::new(&self.bump))
}
pub fn render<'a, F>(&'a self, lazy_nodes: LazyNodes<'a, F>) -> &'a VNode<'a>
where
F: FnOnce(NodeFactory<'a>) -> VNode<'a>,
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)))
@ -43,9 +43,10 @@ impl TestDom {
machine.mutations
}
pub fn create<'a, F1>(&'a self, left: LazyNodes<'a, F1>) -> Mutations<'a>
where
F1: FnOnce(NodeFactory<'a>) -> VNode<'a>,
pub fn create<'a>(&'a self, left: Element<'a>) -> Mutations<'a>
// pub fn create<'a, F1>(&'a self, left: LazyNodes<'a, F1>) -> Mutations<'a>
// where
// F1: FnOnce(NodeFactory<'a>) -> VNode<'a>,
{
let old = self.bump.alloc(self.render_direct(left));
@ -58,14 +59,16 @@ impl TestDom {
machine.mutations
}
pub fn lazy_diff<'a, F1, F2>(
pub fn lazy_diff<'a>(
&'a self,
left: LazyNodes<'a, F1>,
right: LazyNodes<'a, F2>,
left: Element<'a>,
right: Element<'a>,
// left: LazyNodes<'a, F1>,
// right: LazyNodes<'a, F2>,
) -> (Mutations<'a>, Mutations<'a>)
where
F1: FnOnce(NodeFactory<'a>) -> VNode<'a>,
F2: FnOnce(NodeFactory<'a>) -> VNode<'a>,
// where
// F1: FnOnce(NodeFactory<'a>) -> VNode<'a>,
// F2: FnOnce(NodeFactory<'a>) -> VNode<'a>,
{
let (old, new) = (self.render(left), self.render(right));

View file

@ -143,7 +143,7 @@ impl VirtualDom {
let _p = root_props.clone();
// 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();
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_caller: Box<dyn Fn(&Scope) -> DomTree> =
let root_caller: Box<dyn Fn(&Scope) -> Element> =
Box::new(move |scope: &Scope| unsafe {
let props: &'_ P = &*(props_ptr as *const P);
std::mem::transmute(root((Context { scope }, props)))
@ -368,22 +368,24 @@ impl VirtualDom {
use futures_util::StreamExt;
// Wait for any new events if we have nothing to do
futures_util::select! {
_ = self.scheduler.async_tasks.next() => {}
msg = self.scheduler.receiver.next() => {
match msg.unwrap() {
SchedulerMsg::Task(t) => {
self.scheduler.handle_task(t);
},
SchedulerMsg::Immediate(im) => {
self.scheduler.dirty_scopes.insert(im);
}
SchedulerMsg::UiEvent(evt) => {
self.scheduler.ui_events.push_back(evt);
}
}
},
}
todo!("wait for work without select macro")
// futures_util::select! {
// _ = self.scheduler.async_tasks.next() => {}
// msg = self.scheduler.receiver.next() => {
// match msg.unwrap() {
// SchedulerMsg::Task(t) => {
// self.scheduler.handle_task(t);
// },
// SchedulerMsg::Immediate(im) => {
// self.scheduler.dirty_scopes.insert(im);
// }
// 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
struct RootCaller(Rc<dyn for<'b> Fn(&'b Scope) -> DomTree<'b> + 'static>);
struct RootCaller(Rc<dyn for<'b> Fn(&'b Scope) -> Element<'b> + 'static>);

View file

@ -10,17 +10,17 @@ fn test_borrowed_state() {
let _ = VirtualDom::new(Parent);
}
fn Parent((cx, _): Component<()>) -> DomTree {
fn Parent((cx, _): Component<()>) -> Element {
let value = cx.use_hook(|_| String::new(), |f| &*f, |_| {});
cx.render(rsx! {
rsx! {
div {
Child { name: value }
Child { name: value }
Child { name: value }
Child { name: value }
}
})
}
}
#[derive(Props)]
@ -28,13 +28,13 @@ struct ChildProps<'a> {
name: &'a str,
}
fn Child<'a>((cx, props): Component<'a, ChildProps>) -> DomTree<'a> {
cx.render(rsx! {
fn Child<'a>((cx, props): Component<'a, ChildProps>) -> Element<'a> {
rsx! {
div {
h1 { "it's nested" }
Child2 { name: props.name }
}
})
}
}
#[derive(Props)]
@ -42,8 +42,8 @@ struct Grandchild<'a> {
name: &'a str,
}
fn Child2<'a>((cx, props): Component<'a, Grandchild>) -> DomTree<'a> {
cx.render(rsx! {
fn Child2<'a>((cx, props): Component<'a, Grandchild>) -> Element<'a> {
rsx! {
div { "Hello {props.name}!" }
})
}
}

View file

@ -22,13 +22,13 @@ fn new_dom<P: 'static + Send>(app: FC<P>, props: P) -> VirtualDom {
#[test]
fn test_original_diff() {
static APP: FC<()> = |(cx, props)| {
cx.render(rsx! {
rsx! {
div {
div {
"Hello, world!"
}
}
})
}
};
let mut dom = new_dom(APP, ());
@ -58,7 +58,7 @@ fn test_original_diff() {
#[test]
fn create() {
static APP: FC<()> = |(cx, props)| {
cx.render(rsx! {
rsx! {
div {
div {
"Hello, world!"
@ -72,7 +72,7 @@ fn create() {
}
}
}
})
}
};
let mut dom = new_dom(APP, ());
@ -121,11 +121,11 @@ fn create() {
#[test]
fn create_list() {
static APP: FC<()> = |(cx, props)| {
cx.render(rsx! {
rsx! {
{(0..3).map(|f| rsx!{ div {
"hello"
}})}
})
}
};
let mut dom = new_dom(APP, ());
@ -170,12 +170,12 @@ fn create_list() {
#[test]
fn create_simple() {
static APP: FC<()> = |(cx, props)| {
cx.render(rsx! {
rsx! {
div {}
div {}
div {}
div {}
})
}
};
let mut dom = new_dom(APP, ());
@ -208,19 +208,19 @@ fn create_simple() {
#[test]
fn create_components() {
static App: FC<()> = |(cx, props)| {
cx.render(rsx! {
rsx! {
Child { "abc1" }
Child { "abc2" }
Child { "abc3" }
})
}
};
static Child: FC<()> = |(cx, props)| {
cx.render(rsx! {
rsx! {
h1 {}
div { {cx.children()} }
p {}
})
}
};
let mut dom = new_dom(App, ());
@ -269,10 +269,10 @@ fn create_components() {
#[test]
fn anchors() {
static App: FC<()> = |(cx, props)| {
cx.render(rsx! {
rsx! {
{true.then(|| rsx!{ div { "hello" } })}
{false.then(|| rsx!{ div { "goodbye" } })}
})
}
};
let mut dom = new_dom(App, ());
@ -303,9 +303,9 @@ fn suspended() {
|| async {
//
},
|cx, p| cx.render(rsx! { "hi "}),
|cx, p| rsx! { "hi "},
);
cx.render(rsx! { {val} })
rsx! { {val} }
};
let mut dom = new_dom(App, ());

View file

@ -807,14 +807,14 @@ fn controlled_keyed_diffing_out_of_order_max_test() {
fn suspense() {
let dom = new_dom();
let edits = dom.create(LazyNodes::new(|f| {
let edits = dom.create(Some(LazyNodes::new(|f| {
use std::cell::{Cell, RefCell};
VNode::Suspended(f.bump().alloc(VSuspended {
task_id: 0,
callback: RefCell::new(None),
dom_id: Cell::new(None),
}))
}));
})));
assert_eq!(
edits.edits,
[CreatePlaceholder { root: 0 }, AppendChildren { many: 1 }]

View file

@ -14,7 +14,7 @@ mod test_logging;
#[test]
fn please_work() {
static App: FC<()> = |(cx, props)| {
cx.render(rsx! {
rsx! {
div {
hidden: "true"
"hello"
@ -24,13 +24,13 @@ fn please_work() {
Child {}
}
div { "hello" }
})
}
};
static Child: FC<()> = |(cx, props)| {
cx.render(rsx! {
rsx! {
div { "child" }
})
}
};
let mut dom = VirtualDom::new(App);

View file

@ -22,7 +22,7 @@ fn manual_diffing() {
static App: FC<AppProps> = |(cx, props)| {
let val = props.value.lock().unwrap();
cx.render(rsx! { div { "{val}" } })
rsx! { div { "{val}" } }
};
let value = Arc::new(Mutex::new("Hello"));

View file

@ -15,12 +15,12 @@ fn shared_state_test() {
static App: FC<()> = |(cx, props)| {
cx.provide_state(MySharedState("world!"));
rsx!(cx, Child {})
rsx!(Child {})
};
static Child: FC<()> = |(cx, props)| {
let shared = cx.consume_state::<MySharedState>()?;
rsx!(cx, "Hello, {shared.0}")
rsx!("Hello, {shared.0}")
};
let mut dom = VirtualDom::new(App);

View file

@ -19,7 +19,7 @@ use dioxus_html as dioxus_elements;
fn app_runs() {
static App: FC<()> = |(cx, props)| {
//
cx.render(rsx!( div{"hello"} ))
rsx!( div{"hello"} )
};
let mut vdom = VirtualDom::new(App);
let edits = vdom.rebuild();
@ -29,10 +29,10 @@ fn app_runs() {
#[test]
fn fragments_work() {
static App: FC<()> = |(cx, props)| {
cx.render(rsx!(
rsx!(
div{"hello"}
div{"goodbye"}
))
)
};
let mut vdom = VirtualDom::new(App);
let edits = vdom.rebuild();
@ -43,10 +43,10 @@ fn fragments_work() {
#[test]
fn lists_work() {
static App: FC<()> = |(cx, props)| {
cx.render(rsx!(
rsx!(
h1 {"hello"}
{(0..6).map(|f| rsx!(span{ "{f}" }))}
))
)
};
let mut vdom = VirtualDom::new(App);
let edits = vdom.rebuild();
@ -56,11 +56,11 @@ fn lists_work() {
#[test]
fn conditional_rendering() {
static App: FC<()> = |(cx, props)| {
cx.render(rsx!(
rsx!(
h1 {"hello"}
{true.then(|| rsx!(span{ "a" }))}
{false.then(|| rsx!(span{ "b" }))}
))
)
};
let mut vdom = VirtualDom::new(App);
@ -73,16 +73,16 @@ fn conditional_rendering() {
#[test]
fn child_components() {
static App: FC<()> = |(cx, props)| {
cx.render(rsx!(
rsx!(
{true.then(|| rsx!(Child { }))}
{false.then(|| rsx!(Child { }))}
))
)
};
static Child: FC<()> = |(cx, props)| {
cx.render(rsx!(
rsx!(
h1 {"hello"}
h1 {"goodbye"}
))
)
};
let mut vdom = VirtualDom::new(App);
let edits = vdom.rebuild();
@ -92,8 +92,8 @@ fn child_components() {
#[test]
fn suspended_works() {
static App: FC<()> = |(cx, props)| {
let title = use_suspense(cx, || async { "bob" }, |cx, f| cx.render(rsx! { "{f}"}));
cx.render(rsx!("hello" { title }))
let title = use_suspense(cx, || async { "bob" }, |cx, f| rsx! { "{f}"});
rsx!("hello" { title })
};
let mut vdom = VirtualDom::new(App);

View file

@ -136,7 +136,7 @@ pub struct TodoEntryProps {
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 = todos.read();

View file

@ -2,7 +2,7 @@ use std::cell::RefCell;
use dioxus::prelude::Component;
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;
/*
@ -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>>()?;
cx.use_hook(

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 {
"bite me"
})
}
fn render_list(cx: Context, count: usize) -> DomTree {
fn render_list(cx: Context, count: usize) -> Element {
let items = (0..count).map(|f| {
rsx! {
li { "a - {f}" }