feat: implement ID cycling
This commit is contained in:
1 parent
0cfbfc88e2
commit
5713e13ff2
10 files changed
+213
-145
No files matched your search
@@ -1,69 +1,30 @@
|
||||
//! we should properly bubble up errors from components
|
||||
|
||||
use std::{error::Error as StdError, marker::PhantomData, string::ParseError};
|
||||
|
||||
use anyhow::{anyhow, bail};
|
||||
use dioxus::prelude::*;
|
||||
|
||||
// todo: add these to dioxus
|
||||
pub trait Reject<E: Clone>: Sized {
|
||||
fn reject_err(self, t: impl FnOnce(E) -> anyhow::Error) -> Result<Self, anyhow::Error> {
|
||||
todo!()
|
||||
}
|
||||
fn reject_because(self, t: impl Into<String>) -> Result<Self, anyhow::Error> {
|
||||
todo!()
|
||||
}
|
||||
|
||||
fn reject(self) -> Result<Self, anyhow::Error> {
|
||||
todo!()
|
||||
}
|
||||
}
|
||||
|
||||
impl<T, E: Clone> Reject<E> for &Result<T, E> {
|
||||
fn reject_err(self, t: impl FnOnce(E) -> anyhow::Error) -> Result<Self, anyhow::Error> {
|
||||
todo!()
|
||||
}
|
||||
}
|
||||
|
||||
/// Call "clone" on the underlying error so it can be propogated out
|
||||
pub trait CloneErr<T, E: ToOwned> {
|
||||
fn clone_err(&self) -> Result<&T, E::Owned>
|
||||
where
|
||||
Self: Sized;
|
||||
}
|
||||
|
||||
impl<E: ToOwned, T> CloneErr<T, E> for Result<T, E> {
|
||||
fn clone_err(&self) -> Result<&T, E::Owned>
|
||||
where
|
||||
Self: Sized,
|
||||
{
|
||||
match self {
|
||||
Ok(s) => Ok(s),
|
||||
Err(e) => Err(e.to_owned()),
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
fn app(cx: Scope) -> Element {
|
||||
// propgates error upwards, does not give a reason, lets Dioxus figure it out
|
||||
let value = cx.use_hook(|| "123123123.123".parse::<f32>()).reject()?;
|
||||
let raw = match cx.generation() % 2 {
|
||||
0 => "123.123",
|
||||
1 => "123.123.123",
|
||||
_ => unreachable!(),
|
||||
};
|
||||
|
||||
// propgates error upwards, gives a reason
|
||||
let value = cx
|
||||
.use_hook(|| "123123123.123".parse::<f32>())
|
||||
.reject_because("Parsing float failed")?;
|
||||
let value = raw.parse::<f32>()?;
|
||||
|
||||
let value = cx.use_hook(|| "123123123.123".parse::<f32>()).clone_err()?;
|
||||
cx.render(rsx! {
|
||||
div { "hello {value}" }
|
||||
})
|
||||
}
|
||||
|
||||
let value = cx
|
||||
.use_hook(|| "123123123.123".parse::<f32>())
|
||||
.as_ref()
|
||||
.map_err(Clone::clone)?;
|
||||
#[test]
|
||||
fn it_goes() {
|
||||
let mut dom = VirtualDom::new(app);
|
||||
|
||||
let value = cx
|
||||
.use_hook(|| "123123123.123".parse::<f32>())
|
||||
.as_ref()
|
||||
.map_err(|_| anyhow!("Parsing float failed"))?;
|
||||
let edits = dom.rebuild().santize();
|
||||
|
||||
todo!()
|
||||
dbg!(edits);
|
||||
|
||||
dom.mark_dirty_scope(ScopeId(0));
|
||||
|
||||
dom.render_immediate();
|
||||
}
|
||||
@@ -16,7 +16,7 @@ fn empty_fragment_creates_nothing() {
|
||||
assert_eq!(
|
||||
edits.edits,
|
||||
[
|
||||
CreatePlaceholder { id: ElementId(2) },
|
||||
CreatePlaceholder { id: ElementId(1) },
|
||||
AppendChildren { m: 1 }
|
||||
]
|
||||
);
|
||||
|
||||
@@ -34,7 +34,7 @@ fn list_renders() {
|
||||
CreateElement { name: "div" },
|
||||
// todo: since this is the only child, we should just use
|
||||
// append when modify the values (IE no need for a placeholder)
|
||||
CreatePlaceholder { id: ElementId(0) },
|
||||
CreateStaticPlaceholder,
|
||||
AppendChildren { m: 1 },
|
||||
SaveTemplate { name: "template", m: 1 },
|
||||
// Create the inner template div
|
||||
|
||||
@@ -0,0 +1,51 @@
|
||||
use dioxus::core::{ElementId, Mutation::*};
|
||||
use dioxus::prelude::*;
|
||||
|
||||
/// As we clean up old templates, the ID for the node should cycle
|
||||
#[test]
|
||||
fn cycling_elements() {
|
||||
let mut dom = VirtualDom::new(|cx| {
|
||||
cx.render(match cx.generation() % 2 {
|
||||
0 => rsx! { div { "wasd" } },
|
||||
1 => rsx! { div { "abcd" } },
|
||||
_ => unreachable!(),
|
||||
})
|
||||
});
|
||||
|
||||
let edits = dom.rebuild().santize();
|
||||
assert_eq!(
|
||||
edits.edits,
|
||||
[
|
||||
LoadTemplate { name: "template", index: 0, id: ElementId(1,) },
|
||||
AppendChildren { m: 1 },
|
||||
]
|
||||
);
|
||||
|
||||
dom.mark_dirty_scope(ScopeId(0));
|
||||
assert_eq!(
|
||||
dom.render_immediate().santize().edits,
|
||||
[
|
||||
LoadTemplate { name: "template", index: 0, id: ElementId(2,) },
|
||||
ReplaceWith { id: ElementId(1,), m: 1 },
|
||||
]
|
||||
);
|
||||
|
||||
// notice that the IDs cycle back to ElementId(1), preserving a minimal memory footprint
|
||||
dom.mark_dirty_scope(ScopeId(0));
|
||||
assert_eq!(
|
||||
dom.render_immediate().santize().edits,
|
||||
[
|
||||
LoadTemplate { name: "template", index: 0, id: ElementId(1,) },
|
||||
ReplaceWith { id: ElementId(2,), m: 1 },
|
||||
]
|
||||
);
|
||||
|
||||
dom.mark_dirty_scope(ScopeId(0));
|
||||
assert_eq!(
|
||||
dom.render_immediate().santize().edits,
|
||||
[
|
||||
LoadTemplate { name: "template", index: 0, id: ElementId(2,) },
|
||||
ReplaceWith { id: ElementId(1,), m: 1 },
|
||||
]
|
||||
);
|
||||
}
|
||||
@@ -47,14 +47,38 @@ fn element_swap() {
|
||||
vdom.rebuild();
|
||||
|
||||
vdom.mark_dirty_scope(ScopeId(0));
|
||||
dbg!(vdom.render_immediate());
|
||||
assert_eq!(
|
||||
vdom.render_immediate().santize().edits,
|
||||
[
|
||||
LoadTemplate { name: "template", index: 0, id: ElementId(2,) },
|
||||
ReplaceWith { id: ElementId(1,), m: 1 },
|
||||
]
|
||||
);
|
||||
|
||||
vdom.mark_dirty_scope(ScopeId(0));
|
||||
dbg!(vdom.render_immediate());
|
||||
assert_eq!(
|
||||
vdom.render_immediate().santize().edits,
|
||||
[
|
||||
LoadTemplate { name: "template", index: 0, id: ElementId(3,) },
|
||||
ReplaceWith { id: ElementId(2,), m: 1 },
|
||||
]
|
||||
);
|
||||
|
||||
vdom.mark_dirty_scope(ScopeId(0));
|
||||
dbg!(vdom.render_immediate());
|
||||
assert_eq!(
|
||||
vdom.render_immediate().santize().edits,
|
||||
[
|
||||
LoadTemplate { name: "template", index: 0, id: ElementId(4,) },
|
||||
ReplaceWith { id: ElementId(3,), m: 1 },
|
||||
]
|
||||
);
|
||||
|
||||
vdom.mark_dirty_scope(ScopeId(0));
|
||||
dbg!(vdom.render_immediate());
|
||||
assert_eq!(
|
||||
vdom.render_immediate().santize().edits,
|
||||
[
|
||||
LoadTemplate { name: "template", index: 0, id: ElementId(5,) },
|
||||
ReplaceWith { id: ElementId(4,), m: 1 },
|
||||
]
|
||||
);
|
||||
}
|
||||
@@ -16,7 +16,7 @@ async fn it_works() {
|
||||
[
|
||||
CreateElement { name: "div" },
|
||||
CreateStaticText { value: "Waiting for child..." },
|
||||
CreatePlaceholder { id: ElementId(0) },
|
||||
CreateStaticPlaceholder,
|
||||
AppendChildren { m: 2 },
|
||||
SaveTemplate { name: "template", m: 1 }
|
||||
]
|
||||
|
||||
Reference in new issue
Block a user